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-2003 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 "html/html_objectimpl.h"
00041 #include "rendering/render_text.h"
00042 #include "rendering/render_frames.h"
00043 #include "rendering/render_layer.h"
00044 #include "misc/htmlhashes.h"
00045 #include "misc/loader.h"
00046 #include "xml/dom2_eventsimpl.h"
00047 #include "xml/dom2_rangeimpl.h"
00048 #include "xml/xml_tokenizer.h"
00049 #include "css/cssstyleselector.h"
00050 #include "css/csshelper.h"
00051 using namespace DOM;
00052 
00053 #include "khtmlview.h"
00054 #include <kparts/partmanager.h>
00055 #include "ecma/kjs_proxy.h"
00056 #include "khtml_settings.h"
00057 #include "kjserrordlg.h"
00058 
00059 #include <kjs/function.h>
00060 #include <kjs/interpreter.h>
00061 
00062 #include "htmlpageinfo.h"
00063 
00064 #include <sys/types.h>
00065 #include <assert.h>
00066 #include <unistd.h>
00067 
00068 #include <config.h>
00069 
00070 #include <dcopclient.h>
00071 #include <dcopref.h>
00072 #include <kstandarddirs.h>
00073 #include <kstringhandler.h>
00074 #include <kio/job.h>
00075 #include <kio/global.h>
00076 #include <kprotocolmanager.h>
00077 #include <kdebug.h>
00078 #include <kiconloader.h>
00079 #include <klocale.h>
00080 #include <kcharsets.h>
00081 #include <kmessagebox.h>
00082 #include <kstdaction.h>
00083 #include <kfiledialog.h>
00084 #include <ktrader.h>
00085 #include <kdatastream.h>
00086 #include <ktempfile.h>
00087 #include <kglobalsettings.h>
00088 #include <kurldrag.h>
00089 #include <kapplication.h>
00090 #include <kparts/browserinterface.h>
00091 #if !defined(QT_NO_DRAGANDDROP)
00092 #include <kmultipledrag.h>
00093 #endif
00094 #include "../kutils/kfinddialog.h"
00095 #include "../kutils/kfind.h"
00096 
00097 #include <ksslcertchain.h>
00098 #include <ksslinfodlg.h>
00099 
00100 #include <kfileitem.h>
00101 #include <kurifilter.h>
00102 #include <kstatusbar.h>
00103 #include <kurllabel.h>
00104 
00105 #include <qclipboard.h>
00106 #include <qfile.h>
00107 #include <qtooltip.h>
00108 #include <qmetaobject.h>
00109 #include <private/qucomextra_p.h>
00110 
00111 #include "khtmlpart_p.h"
00112 #include "kpopupmenu.h"
00113 #include "rendering/render_form.h"
00114 #include <kwin.h>
00115 
00116 #define HINT_UTF8   106
00117 
00118 namespace khtml {
00119     class PartStyleSheetLoader : public CachedObjectClient
00120     {
00121     public:
00122         PartStyleSheetLoader(KHTMLPart *part, DOM::DOMString url, DocLoader* dl)
00123         {
00124             m_part = part;
00125             m_cachedSheet = dl->requestStyleSheet(url, QString::null, "text/css",
00126                                                   true /* "user sheet" */);
00127             if (m_cachedSheet)
00128         m_cachedSheet->ref( this );
00129         }
00130         virtual ~PartStyleSheetLoader()
00131         {
00132             if ( m_cachedSheet ) m_cachedSheet->deref(this);
00133         }
00134         virtual void setStyleSheet(const DOM::DOMString&, const DOM::DOMString &sheet)
00135         {
00136           if ( m_part )
00137             m_part->setUserStyleSheet( sheet.string() );
00138 
00139             delete this;
00140         }
00141         virtual void error( int, const QString& ) {
00142           delete this;
00143         }
00144         QGuardedPtr<KHTMLPart> m_part;
00145         khtml::CachedCSSStyleSheet *m_cachedSheet;
00146     };
00147 }
00148 
00149 
00150 KHTMLFrameList::Iterator KHTMLFrameList::find( const QString &name )
00151 {
00152     Iterator it = begin();
00153     Iterator e = end();
00154 
00155     for (; it!=e; ++it )
00156         if ( (*it).m_name==name )
00157             break;
00158 
00159     return it;
00160 }
00161 
00162 KHTMLPart::KHTMLPart( QWidget *parentWidget, const char *widgetname, QObject *parent, const char *name, GUIProfile prof )
00163 : KParts::ReadOnlyPart( parent, name )
00164 {
00165     d = 0;
00166     KHTMLFactory::registerPart( this );
00167     setInstance( KHTMLFactory::instance(), prof == BrowserViewGUI && !parentPart() );
00168     init( new KHTMLView( this, parentWidget, widgetname ), prof );
00169 }
00170 
00171 KHTMLPart::KHTMLPart( KHTMLView *view, QObject *parent, const char *name, GUIProfile prof )
00172 : KParts::ReadOnlyPart( parent, name )
00173 {
00174     d = 0;
00175     KHTMLFactory::registerPart( this );
00176     setInstance( KHTMLFactory::instance(), prof == BrowserViewGUI && !parentPart() );
00177     assert( view );
00178     init( view, prof );
00179 }
00180 
00181 void KHTMLPart::init( KHTMLView *view, GUIProfile prof )
00182 {
00183   if ( prof == DefaultGUI )
00184     setXMLFile( "khtml.rc" );
00185   else if ( prof == BrowserViewGUI )
00186     setXMLFile( "khtml_browser.rc" );
00187 
00188   d = new KHTMLPartPrivate(parent());
00189 
00190   d->m_view = view;
00191   setWidget( d->m_view );
00192 
00193   d->m_guiProfile = prof;
00194   d->m_extension = new KHTMLPartBrowserExtension( this );
00195   d->m_hostExtension = new KHTMLPartBrowserHostExtension( this );
00196   d->m_statusBarExtension = new KParts::StatusBarExtension( this );
00197   d->m_statusBarIconLabel = 0L;
00198 
00199   d->m_bSecurityInQuestion = false;
00200   d->m_paLoadImages = 0;
00201   d->m_paDebugScript = 0;
00202   d->m_bMousePressed = false;
00203   d->m_bRightMousePressed = false;
00204   d->m_paViewDocument = new KAction( i18n( "View Do&cument Source" ), CTRL + Key_U, this, SLOT( slotViewDocumentSource() ), actionCollection(), "viewDocumentSource" );
00205   d->m_paViewFrame = new KAction( i18n( "View Frame Source" ), 0, this, SLOT( slotViewFrameSource() ), actionCollection(), "viewFrameSource" );
00206   d->m_paViewInfo = new KAction( i18n( "View Document Information" ), CTRL+Key_I, this, SLOT( slotViewPageInfo() ), actionCollection(), "viewPageInfo" );
00207   d->m_paSaveBackground = new KAction( i18n( "Save &Background Image As..." ), 0, this, SLOT( slotSaveBackground() ), actionCollection(), "saveBackground" );
00208   d->m_paSaveDocument = KStdAction::saveAs( this, SLOT( slotSaveDocument() ), actionCollection(), "saveDocument" );
00209   if ( parentPart() )
00210       d->m_paSaveDocument->setShortcut( KShortcut() ); // avoid clashes
00211   d->m_paSaveFrame = new KAction( i18n( "Save &Frame As..." ), 0, this, SLOT( slotSaveFrame() ), actionCollection(), "saveFrame" );
00212   d->m_paSecurity = new KAction( i18n( "Security..." ), "decrypted", 0, this, SLOT( slotSecurity() ), actionCollection(), "security" );
00213   d->m_paSecurity->setWhatsThis( i18n( "Security Settings<p>"
00214                                        "Shows the certificate of the displayed page. Only "
00215                        "pages that have been transmitted using a secure, encrypted connection have a "
00216                        "certificate.<p> "
00217                        "Hint: If the image shows a closed lock, the page has been transmitted over a "
00218                        "secure connection.") );
00219   d->m_paDebugRenderTree = new KAction( i18n( "Print Rendering Tree to STDOUT" ), 0, this, SLOT( slotDebugRenderTree() ), actionCollection(), "debugRenderTree" );
00220   d->m_paDebugDOMTree = new KAction( i18n( "Print DOM Tree to STDOUT" ), 0, this, SLOT( slotDebugDOMTree() ), actionCollection(), "debugDOMTree" );
00221   d->m_paStopAnimations = new KAction( i18n( "Stop Animated Images" ), 0, this, SLOT( slotStopAnimations() ), actionCollection(), "stopAnimations" );
00222 
00223   d->m_paSetEncoding = new KActionMenu( i18n( "Set &Encoding" ), "charset", actionCollection(), "setEncoding" );
00224   d->m_paSetEncoding->setDelayed( false );
00225 
00226   d->m_automaticDetection = new KPopupMenu( 0L );
00227 
00228   d->m_automaticDetection->insertItem( i18n( "Semi-Automatic" ), 0 );
00229   d->m_automaticDetection->insertItem( i18n( "Arabic" ), 1 );
00230   d->m_automaticDetection->insertItem( i18n( "Baltic" ), 2 );
00231   d->m_automaticDetection->insertItem( i18n( "Central European" ), 3 );
00232   //d->m_automaticDetection->insertItem( i18n( "Chinese" ), 4 );
00233   d->m_automaticDetection->insertItem( i18n( "Greek" ), 5 );
00234   d->m_automaticDetection->insertItem( i18n( "Hebrew" ), 6 );
00235   d->m_automaticDetection->insertItem( i18n( "Japanese" ), 7 );
00236   //d->m_automaticDetection->insertItem( i18n( "Korean" ), 8 );
00237   d->m_automaticDetection->insertItem( i18n( "Russian" ), 9 );
00238   //d->m_automaticDetection->insertItem( i18n( "Thai" ), 10 );
00239   d->m_automaticDetection->insertItem( i18n( "Turkish" ), 11 );
00240   d->m_automaticDetection->insertItem( i18n( "Ukrainian" ), 12 );
00241   //d->m_automaticDetection->insertItem( i18n( "Unicode" ), 13 );
00242   d->m_automaticDetection->insertItem( i18n( "Western European" ), 14 );
00243 
00244   connect( d->m_automaticDetection, SIGNAL( activated( int ) ), this, SLOT( slotAutomaticDetectionLanguage( int ) ) );
00245 
00246   d->m_paSetEncoding->popupMenu()->insertItem( i18n( "Automatic Detection" ), d->m_automaticDetection, 0 );
00247 
00248   d->m_paSetEncoding->insert( new KActionSeparator( actionCollection() ) );
00249 
00250 
00251   d->m_manualDetection = new KSelectAction( i18n( "short for Manual Detection", "Manual" ), 0, this, SLOT( slotSetEncoding() ), actionCollection(), "manualDetection" );
00252   QStringList encodings = KGlobal::charsets()->descriptiveEncodingNames();
00253   d->m_manualDetection->setItems( encodings );
00254   d->m_manualDetection->setCurrentItem( -1 );
00255   d->m_paSetEncoding->insert( d->m_manualDetection );
00256 
00257 
00258   KConfig *config = KGlobal::config();
00259   if ( config->hasGroup( "HTML Settings" ) ) {
00260     config->setGroup( "HTML Settings" );
00261     khtml::Decoder::AutoDetectLanguage language;
00262     QCString name = QTextCodec::codecForLocale()->name();
00263     name = name.lower();
00264 
00265     if ( name == "cp1256" || name == "iso-8859-6" ) {
00266       language = khtml::Decoder::Arabic;
00267     }
00268     else if ( name == "cp1257" || name == "iso-8859-13" || name == "iso-8859-4" ) {
00269       language = khtml::Decoder::Baltic;
00270     }
00271     else if ( name == "cp1250" || name == "ibm852" || name == "iso-8859-2" || name == "iso-8859-3" ) {
00272       language = khtml::Decoder::CentralEuropean;
00273     }
00274     else if ( name == "cp1251" || name == "koi8-r" || name == "iso-8859-5" ) {
00275       language = khtml::Decoder::Russian;
00276     }
00277     else if ( name == "koi8-u" ) {
00278       language = khtml::Decoder::Ukrainian;
00279     }
00280     else if ( name == "cp1253" || name == "iso-8859-7" ) {
00281       language = khtml::Decoder::Greek;
00282     }
00283     else if ( name == "cp1255" || name == "iso-8859-8" || name == "iso-8859-8-i" ) {
00284       language = khtml::Decoder::Hebrew;
00285     }
00286     else if ( name == "jis7" || name == "eucjp" || name == "sjis"  ) {
00287       language = khtml::Decoder::Japanese;
00288     }
00289     else if ( name == "cp1254" || name == "iso-8859-9" ) {
00290       language = khtml::Decoder::Turkish;
00291     }
00292     else if ( name == "cp1252" || name == "iso-8859-1" || name == "iso-8859-15" ) {
00293       language = khtml::Decoder::WesternEuropean;
00294     }
00295     else
00296       language = khtml::Decoder::SemiautomaticDetection;
00297 
00298     int _id = config->readNumEntry( "AutomaticDetectionLanguage", language );
00299     d->m_automaticDetection->setItemChecked( _id, true );
00300     d->m_paSetEncoding->popupMenu()->setItemChecked( 0, true );
00301 
00302     d->m_autoDetectLanguage = static_cast< khtml::Decoder::AutoDetectLanguage >( _id );
00303   }
00304 
00305 
00306   d->m_paUseStylesheet = new KSelectAction( i18n( "Use S&tylesheet"), 0, this, SLOT( slotUseStylesheet() ), actionCollection(), "useStylesheet" );
00307 
00308   if ( prof == BrowserViewGUI ) {
00309       d->m_paIncZoomFactor = new KHTMLZoomFactorAction( this, true, i18n(
00310                   "Increase Font Sizes" ), "viewmag+", "CTRL++;CTRL+=", this,
00311               SLOT( slotIncZoomFast() ), actionCollection(), "incFontSizes" );
00312       d->m_paIncZoomFactor->setWhatsThis( i18n( "Increase Font Size<p>"
00313                                                 "Make the font in this window bigger. "
00314                             "Click and hold down the mouse button for a menu with all available font sizes." ) );
00315       d->m_paDecZoomFactor = new KHTMLZoomFactorAction( this, false, i18n(
00316                   "Decrease Font Sizes" ), "viewmag-", CTRL + Key_Minus, this,
00317               SLOT( slotDecZoomFast() ), actionCollection(), "decFontSizes" );
00318       d->m_paDecZoomFactor->setWhatsThis( i18n( "Decrease Font Size<p>"
00319                                                 "Make the font in this window smaller. "
00320                             "Click and hold down the mouse button for a menu with all available font sizes." ) );
00321   }
00322 
00323   d->m_paFind = KStdAction::find( this, SLOT( slotFind() ), actionCollection(), "find" );
00324   d->m_paFind->setWhatsThis( i18n( "Find text<p>"
00325                    "Shows a dialog that allows you to find text on the displayed page." ) );
00326 
00327   d->m_paFindNext = KStdAction::findNext( this, SLOT( slotFindNext() ), actionCollection(), "findNext" );
00328   d->m_paFindNext->setWhatsThis( i18n( "Find next<p>"
00329                        "Find the next occurrence of the text that you "
00330                        "have found using the <b>Find Text</b> function" ) );
00331   if ( parentPart() )
00332   {
00333       d->m_paFind->setShortcut( KShortcut() ); // avoid clashes
00334       d->m_paFindNext->setShortcut( KShortcut() ); // avoid clashes
00335   }
00336 
00337   d->m_paPrintFrame = new KAction( i18n( "Print Frame..." ), "frameprint", 0, this, SLOT( slotPrintFrame() ), actionCollection(), "printFrame" );
00338   d->m_paPrintFrame->setWhatsThis( i18n( "Print Frame<p>"
00339                      "Some pages have several frames. To print only a single frame, click "
00340                      "on it and then use this function." ) );
00341 
00342   d->m_paSelectAll = KStdAction::selectAll( this, SLOT( slotSelectAll() ), actionCollection(), "selectAll" );
00343   if ( parentPart() )
00344       d->m_paSelectAll->setShortcut( KShortcut() ); // avoid clashes
00345 
00346   d->m_paToggleCaretMode = new KToggleAction(i18n("Toggle Caret Mode"),
00347                 Key_F7, this, SLOT(slotToggleCaretMode()),
00348                                 actionCollection(), "caretMode");
00349   d->m_paToggleCaretMode->setChecked(isCaretMode());
00350   if (parentPart())
00351       d->m_paToggleCaretMode->setShortcut(KShortcut()); // avoid clashes
00352 
00353   // set the default java(script) flags according to the current host.
00354   d->m_bOpenMiddleClick = d->m_settings->isOpenMiddleClickEnabled();
00355   d->m_bBackRightClick = d->m_settings->isBackRightClickEnabled();
00356   d->m_bJScriptEnabled = d->m_settings->isJavaScriptEnabled();
00357   setDebugScript( d->m_settings->isJavaScriptDebugEnabled() );
00358   d->m_bJavaEnabled = d->m_settings->isJavaEnabled();
00359   d->m_bPluginsEnabled = d->m_settings->isPluginsEnabled();
00360 
00361   // Set the meta-refresh flag...
00362   d->m_metaRefreshEnabled = d->m_settings->isAutoDelayedActionsEnabled ();
00363 
00364   connect( view, SIGNAL( zoomView( int ) ), SLOT( slotZoomView( int ) ) );
00365 
00366   connect( this, SIGNAL( completed() ),
00367            this, SLOT( updateActions() ) );
00368   connect( this, SIGNAL( completed( bool ) ),
00369            this, SLOT( updateActions() ) );
00370   connect( this, SIGNAL( started( KIO::Job * ) ),
00371            this, SLOT( updateActions() ) );
00372 
00373   d->m_popupMenuXML = KXMLGUIFactory::readConfigFile( locate( "data", "khtml/khtml_popupmenu.rc", KHTMLFactory::instance() ) );
00374 
00375   connect( khtml::Cache::loader(), SIGNAL( requestStarted( khtml::DocLoader*, khtml::CachedObject* ) ),
00376            this, SLOT( slotLoaderRequestStarted( khtml::DocLoader*, khtml::CachedObject* ) ) );
00377   connect( khtml::Cache::loader(), SIGNAL( requestDone( khtml::DocLoader*, khtml::CachedObject *) ),
00378            this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
00379   connect( khtml::Cache::loader(), SIGNAL( requestFailed( khtml::DocLoader*, khtml::CachedObject *) ),
00380            this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
00381 
00382   connect ( &d->m_progressUpdateTimer, SIGNAL( timeout() ), this, SLOT( slotProgressUpdate() ) );
00383 
00384   findTextBegin(); //reset find variables
00385 
00386   connect( &d->m_redirectionTimer, SIGNAL( timeout() ),
00387            this, SLOT( slotRedirect() ) );
00388 
00389   d->m_dcopobject = new KHTMLPartIface(this);
00390 
00391   // "khtml" catalog does not exist, our translations are in kdelibs.
00392   // removing this catalog from KGlobal::locale() prevents problems
00393   // with changing the language in applications at runtime -Thomas Reitelbach
00394   KGlobal::locale()->removeCatalogue("khtml");
00395 }
00396 
00397 KHTMLPart::~KHTMLPart()
00398 {
00399   //kdDebug(6050) << "KHTMLPart::~KHTMLPart " << this << endl;
00400 
00401   KConfig *config = KGlobal::config();
00402   config->setGroup( "HTML Settings" );
00403   config->writeEntry( "AutomaticDetectionLanguage", d->m_autoDetectLanguage );
00404 
00405   delete d->m_automaticDetection;
00406   delete d->m_manualDetection;
00407 
00408   slotWalletClosed();
00409   if (!parentPart()) { // only delete it if the top khtml_part closes
00410     removeJSErrorExtension();
00411   }
00412 
00413   d->m_find = 0; // deleted by its parent, the view.
00414 
00415   if ( d->m_manager )
00416   {
00417     d->m_manager->setActivePart( 0 );
00418     // We specify "this" as parent qobject for d->manager, so no need to delete it.
00419   }
00420 
00421   stopAutoScroll();
00422   d->m_redirectionTimer.stop();
00423 
00424   if (!d->m_bComplete)
00425     closeURL();
00426 
00427   disconnect( khtml::Cache::loader(), SIGNAL( requestStarted( khtml::DocLoader*, khtml::CachedObject* ) ),
00428            this, SLOT( slotLoaderRequestStarted( khtml::DocLoader*, khtml::CachedObject* ) ) );
00429   disconnect( khtml::Cache::loader(), SIGNAL( requestDone( khtml::DocLoader*, khtml::CachedObject *) ),
00430            this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
00431   disconnect( khtml::Cache::loader(), SIGNAL( requestFailed( khtml::DocLoader*, khtml::CachedObject *) ),
00432            this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
00433 
00434   clear();
00435 
00436   if ( d->m_view )
00437   {
00438     d->m_view->hide();
00439     d->m_view->viewport()->hide();
00440     d->m_view->m_part = 0;
00441   }
00442 
00443   // Have to delete this here since we forward declare it in khtmlpart_p and
00444   // at least some compilers won't call the destructor in this case.
00445   delete d->m_jsedlg;
00446   d->m_jsedlg = 0;
00447 
00448   delete d; d = 0;
00449   KHTMLFactory::deregisterPart( this );
00450 }
00451 
00452 bool KHTMLPart::restoreURL( const KURL &url )
00453 {
00454   kdDebug( 6050 ) << "KHTMLPart::restoreURL " << url.url() << endl;
00455 
00456   d->m_redirectionTimer.stop();
00457 
00458   /*
00459    * That's not a good idea as it will call closeURL() on all
00460    * child frames, preventing them from further loading. This
00461    * method gets called from restoreState() in case of a full frameset
00462    * restoral, and restoreState() calls closeURL() before restoring
00463    * anyway.
00464   kdDebug( 6050 ) << "closing old URL" << endl;
00465   closeURL();
00466   */
00467 
00468   d->m_bComplete = false;
00469   d->m_bLoadEventEmitted = false;
00470   d->m_workingURL = url;
00471 
00472   // set the java(script) flags according to the current host.
00473   d->m_bJScriptEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptEnabled(url.host());
00474   setDebugScript( KHTMLFactory::defaultHTMLSettings()->isJavaScriptDebugEnabled() );
00475   d->m_bJavaEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaEnabled(url.host());
00476   d->m_bPluginsEnabled = KHTMLFactory::defaultHTMLSettings()->isPluginsEnabled(url.host());
00477 
00478   m_url = url;
00479 
00480   KHTMLPageCache::self()->fetchData( d->m_cacheId, this, SLOT(slotRestoreData(const QByteArray &)));
00481 
00482   emit started( 0L );
00483 
00484   return true;
00485 }
00486 
00487 
00488 bool KHTMLPart::openURL( const KURL &url )
00489 {
00490   kdDebug( 6050 ) << "KHTMLPart(" << this << ")::openURL " << url.url() << endl;
00491 
00492   d->m_redirectionTimer.stop();
00493 
00494   // check to see if this is an "error://" URL. This is caused when an error
00495   // occurs before this part was loaded (e.g. KonqRun), and is passed to
00496   // khtmlpart so that it can display the error.
00497   if ( url.protocol() == "error" && url.hasSubURL() ) {
00498     closeURL();
00499 
00500     if(  d->m_bJScriptEnabled )
00501       d->m_statusBarText[BarOverrideText] = d->m_statusBarText[BarDefaultText] = QString::null;
00502 
00508     KURL::List urls = KURL::split( url );
00509     //kdDebug(6050) << "Handling error URL. URL count:" << urls.count() << endl;
00510 
00511     if ( urls.count() > 1 ) {
00512       KURL mainURL = urls.first();
00513       int error = mainURL.queryItem( "error" ).toInt();
00514       // error=0 isn't a valid error code, so 0 means it's missing from the URL
00515       if ( error == 0 ) error = KIO::ERR_UNKNOWN;
00516       QString errorText = mainURL.queryItem( "errText", HINT_UTF8 );
00517       urls.pop_front();
00518       d->m_workingURL = KURL::join( urls );
00519       //kdDebug(6050) << "Emitting fixed URL " << d->m_workingURL.prettyURL() << endl;
00520       emit d->m_extension->setLocationBarURL( d->m_workingURL.prettyURL() );
00521       htmlError( error, errorText, d->m_workingURL );
00522       return true;
00523     }
00524   }
00525 
00526   KParts::URLArgs args( d->m_extension->urlArgs() );
00527   // in case we have a) no frameset (don't test m_frames.count(), iframes get in there)
00528   // b) the url is identical with the currently
00529   // displayed one (except for the htmlref!) , c) the url request is not a POST
00530   // operation and d) the caller did not request to reload the page we try to
00531   // be smart and instead of reloading the whole document we just jump to the
00532   // request html anchor
00533   bool isFrameSet = false;
00534   if ( d->m_doc && d->m_doc->isHTMLDocument() ) {
00535       HTMLDocumentImpl* htmlDoc = static_cast<HTMLDocumentImpl*>(d->m_doc);
00536       isFrameSet = htmlDoc->body() && (htmlDoc->body()->id() == ID_FRAMESET);
00537   }
00538   
00539   if ( url.hasRef() && !isFrameSet )
00540   {
00541 
00542     //if new url == old url, jump to anchor straight away
00543     //no need to reload unless explicitly asked
00544     bool noReloadForced = !args.reload && !args.redirectedRequest() && !args.doPost();
00545     if (urlcmp( url.url(), m_url.url(), true, true ) && noReloadForced)
00546     {
00547         kdDebug( 6050 ) << "KHTMLPart::openURL, jumping to anchor. m_url = " << url.url() << endl;
00548         m_url = url;
00549         emit started( 0L );
00550         
00551         if ( !gotoAnchor( url.encodedHtmlRef()) )
00552           gotoAnchor( url.htmlRef() );
00553         
00554         d->m_bComplete = true;
00555         if (d->m_doc)
00556         d->m_doc->setParsing(false);
00557         
00558         kdDebug( 6050 ) << "completed..." << endl;
00559         emit completed();
00560         return true;
00561     }
00562     //jump to the anchor AFTER layouting is done, otherwise the position of the
00563     //anchor is not known and we have no clue to which coordinates to jump
00564     else
00565     {
00566         disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(gotoAnchor()));
00567         if ( !url.encodedHtmlRef().isEmpty() )
00568           connect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(gotoAnchor()));
00569     }
00570   }
00571 
00572   // Save offset of viewport when page is reloaded to be compliant
00573   // to every other capable browser out there.
00574   if (args.reload) {
00575     args.xOffset = d->m_view->contentsX();
00576     args.yOffset = d->m_view->contentsY();
00577     d->m_extension->setURLArgs(args);
00578     disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(gotoAnchor()));
00579     connect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
00580   }
00581 
00582   if (!d->m_restored)
00583     closeURL();
00584 
00585   // 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
00586   // data arrives) (Simon)
00587   m_url = url;
00588   if(m_url.protocol().startsWith( "http" ) && !m_url.host().isEmpty() &&
00589      m_url.path().isEmpty()) {
00590     m_url.setPath("/");
00591     emit d->m_extension->setLocationBarURL( m_url.prettyURL() );
00592   }
00593   // copy to m_workingURL after fixing m_url above
00594   d->m_workingURL = m_url;
00595 
00596   args.metaData().insert("main_frame_request", parentPart() == 0 ? "TRUE" : "FALSE" );
00597   args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
00598   args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
00599   args.metaData().insert("PropagateHttpHeader", "true");
00600   args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE" : "FALSE" );
00601   args.metaData().insert("ssl_activate_warnings", "TRUE" );
00602   args.metaData().insert("cross-domain", toplevelURL().url());
00603 
00604   if (d->m_restored)
00605   {
00606      args.metaData().insert("referrer", d->m_pageReferrer);
00607      d->m_cachePolicy = KIO::CC_Cache;
00608   }
00609   else if (args.reload)
00610      d->m_cachePolicy = KIO::CC_Reload;
00611   else
00612      d->m_cachePolicy = KProtocolManager::cacheControl();
00613 
00614   if ( args.doPost() && (m_url.protocol().startsWith("http")) )
00615   {
00616       d->m_job = KIO::http_post( m_url, args.postData, false );
00617       d->m_job->addMetaData("content-type", args.contentType() );
00618   }
00619   else
00620   {
00621       d->m_job = KIO::get( m_url, false, false );
00622       d->m_job->addMetaData("cache", KIO::getCacheControlString(d->m_cachePolicy));
00623   }
00624 
00625   if (widget())
00626      d->m_job->setWindow(widget()->topLevelWidget());
00627   d->m_job->addMetaData(args.metaData());
00628 
00629   connect( d->m_job, SIGNAL( result( KIO::Job* ) ),
00630            SLOT( slotFinished( KIO::Job* ) ) );
00631   connect( d->m_job, SIGNAL( data( KIO::Job*, const QByteArray& ) ),
00632            SLOT( slotData( KIO::Job*, const QByteArray& ) ) );
00633   connect ( d->m_job, SIGNAL( infoMessage( KIO::Job*, const QString& ) ),
00634            SLOT( slotInfoMessage(KIO::Job*, const QString& ) ) );
00635   connect( d->m_job, SIGNAL(redirection(KIO::Job*, const KURL& ) ),
00636            SLOT( slotRedirection(KIO::Job*, const KURL&) ) );
00637 
00638   d->m_bComplete = false;
00639   d->m_bLoadEventEmitted = false;
00640 
00641   // delete old status bar msg's from kjs (if it _was_ activated on last URL)
00642   if( d->m_bJScriptEnabled )
00643     d->m_statusBarText[BarOverrideText] = d->m_statusBarText[BarDefaultText] = QString::null;
00644 
00645   // set the javascript flags according to the current url
00646   d->m_bJScriptEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptEnabled(url.host());
00647   setDebugScript( KHTMLFactory::defaultHTMLSettings()->isJavaScriptDebugEnabled() );
00648   d->m_bJavaEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaEnabled(url.host());
00649   d->m_bPluginsEnabled = KHTMLFactory::defaultHTMLSettings()->isPluginsEnabled(url.host());
00650 
00651 
00652   connect( d->m_job, SIGNAL( speed( KIO::Job*, unsigned long ) ),
00653            this, SLOT( slotJobSpeed( KIO::Job*, unsigned long ) ) );
00654 
00655   connect( d->m_job, SIGNAL( percent( KIO::Job*, unsigned long ) ),
00656            this, SLOT( slotJobPercent( KIO::Job*, unsigned long ) ) );
00657 
00658   connect( d->m_job, SIGNAL( result( KIO::Job* ) ),
00659            this, SLOT( slotJobDone( KIO::Job* ) ) );
00660 
00661   d->m_jobspeed = 0;
00662 
00663   // If this was an explicit reload and the user style sheet should be used,
00664   // do a stat to see whether the stylesheet was changed in the meanwhile.
00665   if ( args.reload && !settings()->userStyleSheet().isEmpty() ) {
00666     KURL url( settings()->userStyleSheet() );
00667     KIO::StatJob *job = KIO::stat( url, false /* don't show progress */ );
00668     connect( job, SIGNAL( result( KIO::Job * ) ),
00669              this, SLOT( slotUserSheetStatDone( KIO::Job * ) ) );
00670   }
00671   emit started( 0L );
00672 
00673   return true;
00674 }
00675 
00676 bool KHTMLPart::closeURL()
00677 {
00678   if ( d->m_job )
00679   {
00680     KHTMLPageCache::self()->cancelEntry(d->m_cacheId);
00681     d->m_job->kill();
00682     d->m_job = 0;
00683   }
00684 
00685   if ( d->m_doc && d->m_doc->isHTMLDocument() ) {
00686     HTMLDocumentImpl* hdoc = static_cast<HTMLDocumentImpl*>( d->m_doc );
00687 
00688     if ( hdoc->body() && d->m_bLoadEventEmitted ) {
00689       hdoc->body()->dispatchWindowEvent( EventImpl::UNLOAD_EVENT, false, false );
00690       if ( d->m_doc )
00691         d->m_doc->updateRendering();
00692       d->m_bLoadEventEmitted = false;
00693     }
00694   }
00695 
00696   d->m_bComplete = true; // to avoid emitting completed() in slotFinishedParsing() (David)
00697   d->m_bLoadEventEmitted = true; // don't want that one either
00698   d->m_cachePolicy = KProtocolManager::cacheControl(); // reset cache policy
00699 
00700   KHTMLPageCache::self()->cancelFetch(this);
00701   if ( d->m_doc && d->m_doc->parsing() )
00702   {
00703     kdDebug( 6050 ) << " was still parsing... calling end " << endl;
00704     slotFinishedParsing();
00705     d->m_doc->setParsing(false);
00706   }
00707 
00708   if ( !d->m_workingURL.isEmpty() )
00709   {
00710     // Aborted before starting to render
00711     kdDebug( 6050 ) << "Aborted before starting to render, reverting location bar to " << m_url.prettyURL() << endl;
00712     emit d->m_extension->setLocationBarURL( m_url.prettyURL() );
00713   }
00714 
00715   d->m_workingURL = KURL();
00716 
00717   if ( d->m_doc && d->m_doc->docLoader() )
00718     khtml::Cache::loader()->cancelRequests( d->m_doc->docLoader() );
00719 
00720   // tell all subframes to stop as well
00721   ConstFrameIt it = d->m_frames.begin();
00722   ConstFrameIt end = d->m_frames.end();
00723   for (; it != end; ++it )
00724   {
00725     if ( (*it).m_run )
00726       (*it).m_run->abort();
00727     if ( !( *it ).m_part.isNull() )
00728       ( *it ).m_part->closeURL();
00729   }
00730   // tell all objects to stop as well
00731   for (it = d->m_objects.begin(); it != d->m_objects.end(); ++it )
00732   {
00733     if ( !( *it ).m_part.isNull() )
00734       ( *it ).m_part->closeURL();
00735   }
00736 
00737   // Stop any started redirections as well!! (DA)
00738   if ( d && d->m_redirectionTimer.isActive() )
00739     d->m_redirectionTimer.stop();
00740 
00741   // null node activated.
00742   emit nodeActivated(Node());
00743 
00744   // make sure before clear() runs, we pop out of a dialog's message loop
00745   if ( d->m_view )
00746     d->m_view->closeChildDialogs();
00747 
00748   return true;
00749 }
00750 
00751 DOM::HTMLDocument KHTMLPart::htmlDocument() const
00752 {
00753   if (d->m_doc && d->m_doc->isHTMLDocument())
00754     return static_cast<HTMLDocumentImpl*>(d->m_doc);
00755   else
00756     return static_cast<HTMLDocumentImpl*>(0);
00757 }
00758 
00759 DOM::Document KHTMLPart::document() const
00760 {
00761     return d->m_doc;
00762 }
00763 
00764 KParts::BrowserExtension *KHTMLPart::browserExtension() const
00765 {
00766   return d->m_extension;
00767 }
00768 
00769 KParts::BrowserHostExtension *KHTMLPart::browserHostExtension() const
00770 {
00771   return d->m_hostExtension;
00772 }
00773 
00774 KHTMLView *KHTMLPart::view() const
00775 {
00776   return d->m_view;
00777 }
00778 
00779 void KHTMLPart::setStatusMessagesEnabled( bool enable )
00780 {
00781   d->m_statusMessagesEnabled = enable;
00782 }
00783 
00784 KJS::Interpreter *KHTMLPart::jScriptInterpreter()
00785 {
00786   KJSProxy *proxy = jScript();
00787   if (!proxy || proxy->paused())
00788     return 0;
00789 
00790   return proxy->interpreter();
00791 }
00792 
00793 bool KHTMLPart::statusMessagesEnabled() const
00794 {
00795   return d->m_statusMessagesEnabled;
00796 }
00797 
00798 void KHTMLPart::setJScriptEnabled( bool enable )
00799 {
00800   if ( !enable && jScriptEnabled() && d->m_jscript ) {
00801     d->m_jscript->clear();
00802   }
00803   d->m_bJScriptForce = enable;
00804   d->m_bJScriptOverride = true;
00805 }
00806 
00807 bool KHTMLPart::jScriptEnabled() const
00808 {
00809   if(onlyLocalReferences()) return false;
00810 
00811   if ( d->m_bJScriptOverride )
00812       return d->m_bJScriptForce;
00813   return d->m_bJScriptEnabled;
00814 }
00815 
00816 void KHTMLPart::setMetaRefreshEnabled( bool enable )
00817 {
00818   d->m_metaRefreshEnabled = enable;
00819 }
00820 
00821 bool KHTMLPart::metaRefreshEnabled() const
00822 {
00823   return d->m_metaRefreshEnabled;
00824 }
00825 
00826 // Define this to disable dlopening kjs_html, when directly linking to it.
00827 // You need to edit khtml/Makefile.am to add ./ecma/libkjs_html.la to LIBADD
00828 // and to edit khtml/ecma/Makefile.am to s/kjs_html/libkjs_html/, remove libkhtml from LIBADD,
00829 //        remove LDFLAGS line, and replace kde_module with either lib (shared) or noinst (static)
00830 //        Also, change the order of "ecma" and "." in khtml's SUBDIRS line.
00831 // OK - that's the default now, use the opposite of the above instructions to go back
00832 // to "dlopening it" - but it breaks exception catching in kjs_binding.cpp
00833 #define DIRECT_LINKAGE_TO_ECMA
00834 
00835 #ifdef DIRECT_LINKAGE_TO_ECMA
00836 extern "C" { KJSProxy *kjs_html_init(KHTMLPart *khtmlpart); }
00837 #endif
00838 
00839 KJSProxy *KHTMLPart::jScript()
00840 {
00841   if (!jScriptEnabled()) return 0;
00842 
00843   if ( !d->m_jscript )
00844   {
00845 #ifndef DIRECT_LINKAGE_TO_ECMA
00846     KLibrary *lib = KLibLoader::self()->library("kjs_html");
00847     if ( !lib ) {
00848       setJScriptEnabled( false );
00849       return 0;
00850     }
00851     // look for plain C init function
00852     void *sym = lib->symbol("kjs_html_init");
00853     if ( !sym ) {
00854       lib->unload();
00855       setJScriptEnabled( false );
00856       return 0;
00857     }
00858     typedef KJSProxy* (*initFunction)(KHTMLPart *);
00859     initFunction initSym = (initFunction) sym;
00860     d->m_jscript = (*initSym)(this);
00861     d->m_kjs_lib = lib;
00862 #else
00863     d->m_jscript = kjs_html_init(this);
00864     // d->m_kjs_lib remains 0L.
00865 #endif
00866     if (d->m_bJScriptDebugEnabled)
00867         d->m_jscript->setDebugEnabled(true);
00868   }
00869 
00870   return d->m_jscript;
00871 }
00872 
00873 QVariant KHTMLPart::crossFrameExecuteScript(const QString& target,  const QString& script)
00874 {
00875   KHTMLPart* destpart = this;
00876 
00877   QString trg = target.lower();
00878 
00879   if (target == "_top") {
00880     while (destpart->parentPart())
00881       destpart = destpart->parentPart();
00882   }
00883   else if (target == "_parent") {
00884     if (parentPart())
00885       destpart = parentPart();
00886   }
00887   else if (target == "_self" || target == "_blank")  {
00888     // we always allow these
00889   }
00890   else {
00891     destpart = findFrame(target);
00892     if (!destpart)
00893        destpart = this;
00894   }
00895 
00896   // easy way out?
00897   if (destpart == this)
00898     return executeScript(DOM::Node(), script);
00899 
00900   // now compare the domains
00901   if (destpart->checkFrameAccess(this))
00902     return destpart->executeScript(DOM::Node(), script);
00903 
00904   // eww, something went wrong. better execute it in our frame
00905   return executeScript(DOM::Node(), script);
00906 }
00907 
00908 //Enable this to see all JS scripts being executed
00909 //#define KJS_VERBOSE
00910 
00911 KJSErrorDlg *KHTMLPart::jsErrorExtension() {
00912   if (!d->m_settings->jsErrorsEnabled()) {
00913     return 0L;
00914   }
00915 
00916   if (parentPart()) {
00917     return parentPart()->jsErrorExtension();
00918   }
00919 
00920   if (!d->m_statusBarJSErrorLabel) {
00921     d->m_statusBarJSErrorLabel = new KURLLabel(d->m_statusBarExtension->statusBar());
00922     d->m_statusBarJSErrorLabel->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small));
00923     d->m_statusBarJSErrorLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
00924     d->m_statusBarJSErrorLabel->setUseCursor(false);
00925     d->m_statusBarExtension->addStatusBarItem(d->m_statusBarJSErrorLabel, 0, false);
00926     QToolTip::add(d->m_statusBarJSErrorLabel, i18n("This web page contains coding errors."));
00927     d->m_statusBarJSErrorLabel->setPixmap(SmallIcon("bug", instance()));
00928     connect(d->m_statusBarJSErrorLabel, SIGNAL(leftClickedURL()), SLOT(launchJSErrorDialog()));
00929     connect(d->m_statusBarJSErrorLabel, SIGNAL(rightClickedURL()), SLOT(jsErrorDialogContextMenu()));
00930   }
00931   if (!d->m_jsedlg) {
00932     d->m_jsedlg = new KJSErrorDlg;
00933     d->m_jsedlg->setURL(m_url.prettyURL());
00934     if (KGlobalSettings::showIconsOnPushButtons()) {
00935       d->m_jsedlg->_clear->setIconSet(SmallIconSet("locationbar_erase"));
00936       d->m_jsedlg->_close->setIconSet(SmallIconSet("fileclose"));
00937     }
00938   }
00939   return d->m_jsedlg;
00940 }
00941 
00942 void KHTMLPart::removeJSErrorExtension() {
00943   if (parentPart()) {
00944     parentPart()->removeJSErrorExtension();
00945     return;
00946   }
00947   if (d->m_statusBarJSErrorLabel != 0) {
00948     d->m_statusBarExtension->removeStatusBarItem( d->m_statusBarJSErrorLabel );
00949     delete d->m_statusBarJSErrorLabel;
00950     d->m_statusBarJSErrorLabel = 0;
00951   }
00952   delete d->m_jsedlg;
00953   d->m_jsedlg = 0;
00954 }
00955 
00956 void KHTMLPart::disableJSErrorExtension() {
00957   removeJSErrorExtension();
00958   // These two lines are really kind of hacky, and it sucks to do this inside
00959   // KHTML but I don't know of anything that's reasonably easy as an alternative
00960   // right now.  It makes me wonder if there should be a more clean way to
00961   // contact all running "KHTML" instance as opposed to Konqueror instances too.
00962   d->m_settings->setJSErrorsEnabled(false);
00963   DCOPClient::mainClient()->send("konqueror*", "KonquerorIface", "reparseConfiguration()", QByteArray());
00964 }
00965 
00966 void KHTMLPart::jsErrorDialogContextMenu() {
00967   KPopupMenu *m = new KPopupMenu(0L);
00968   m->insertItem(i18n("&Hide Errors"), this, SLOT(removeJSErrorExtension()));
00969   m->insertItem(i18n("&Disable Error Reporting"), this, SLOT(disableJSErrorExtension()));
00970   m->popup(QCursor::pos());
00971 }
00972 
00973 void KHTMLPart::launchJSErrorDialog() {
00974   KJSErrorDlg *dlg = jsErrorExtension();
00975   if (dlg) {
00976     dlg->show();
00977     dlg->raise();
00978   }
00979 }
00980 
00981 QVariant KHTMLPart::executeScript(const QString& filename, int baseLine, const DOM::Node& n, const QString& script)
00982 {
00983 #ifdef KJS_VERBOSE
00984   kdDebug(6070) << "executeScript: caller='" << name() << "' filename=" << filename << " baseLine=" << baseLine << " script=" << script << endl;
00985 #endif
00986   KJSProxy *proxy = jScript();
00987 
00988   if (!proxy || proxy->paused())
00989     return QVariant();
00990 
00991   KJS::Completion comp;
00992 
00993   QVariant ret = proxy->evaluate(filename, baseLine, script, n, &comp);
00994 
00995   /*
00996    *  Error handling
00997    */
00998   if (comp.complType() == KJS::Throw && !comp.value().isNull()) {
00999     KJSErrorDlg *dlg = jsErrorExtension();
01000     if (dlg) {
01001       KJS::UString msg = comp.value().toString(proxy->interpreter()->globalExec());
01002       dlg->addError(i18n("<b>Error</b>: %1: %2").arg(filename, msg.qstring()));
01003     }
01004   }
01005 
01006   return ret;
01007 }
01008 
01009 QVariant KHTMLPart::executeScript( const QString &script )
01010 {
01011     return executeScript( DOM::Node(), script );
01012 }
01013 
01014 QVariant KHTMLPart::executeScript( const DOM::Node &n, const QString &script )
01015 {
01016 #ifdef KJS_VERBOSE
01017   kdDebug(6070) << "KHTMLPart::executeScript caller='" << name() << "' node=" << n.nodeName().string().latin1() << "(" << (n.isNull() ? 0 : n.nodeType()) << ") " << script << endl;
01018 #endif
01019   KJSProxy *proxy = jScript();
01020 
01021   if (!proxy || proxy->paused())
01022     return QVariant();
01023   d->m_runningScripts++;
01024   KJS::Completion comp;
01025   QVariant ret = proxy->evaluate( QString::null, 1, script, n, &comp );
01026   d->m_runningScripts--;
01027 
01028   /*
01029    *  Error handling
01030    */
01031   if (comp.complType() == KJS::Throw && !comp.value().isNull()) {
01032     KJSErrorDlg *dlg = jsErrorExtension();
01033     if (dlg) {
01034       KJS::UString msg = comp.value().toString(proxy->interpreter()->globalExec());
01035       dlg->addError(i18n("<b>Error</b>: node %1: %2").arg(n.nodeName().string()).arg(msg.qstring()));
01036     }
01037   }
01038 
01039   if (!d->m_runningScripts && d->m_doc && !d->m_doc->parsing() && d->m_submitForm )
01040       submitFormAgain();
01041 
01042 #ifdef KJS_VERBOSE
01043   kdDebug(6070) << "KHTMLPart::executeScript - done" << endl;
01044 #endif
01045   return ret;
01046 }
01047 
01048 bool KHTMLPart::scheduleScript(const DOM::Node &n, const QString& script)
01049 {
01050     //kdDebug(6050) << "KHTMLPart::scheduleScript "<< script << endl;
01051 
01052     d->scheduledScript = script;
01053     d->scheduledScriptNode = n;
01054 
01055     return true;
01056 }
01057 
01058 QVariant KHTMLPart::executeScheduledScript()
01059 {
01060   if( d->scheduledScript.isEmpty() )
01061     return QVariant();
01062 
01063   //kdDebug(6050) << "executing delayed " << d->scheduledScript << endl;
01064 
01065   QVariant ret = executeScript( d->scheduledScriptNode, d->scheduledScript );
01066   d->scheduledScript = QString();
01067   d->scheduledScriptNode = DOM::Node();
01068 
01069   return ret;
01070 }
01071 
01072 void KHTMLPart::setJavaEnabled( bool enable )
01073 {
01074   d->m_bJavaForce = enable;
01075   d->m_bJavaOverride = true;
01076 }
01077 
01078 bool KHTMLPart::javaEnabled() const
01079 {
01080   if (onlyLocalReferences()) return false;
01081 
01082 #ifndef Q_WS_QWS
01083   if( d->m_bJavaOverride )
01084       return d->m_bJavaForce;
01085   return d->m_bJavaEnabled;
01086 #else
01087   return false;
01088 #endif
01089 }
01090 
01091 KJavaAppletContext *KHTMLPart::javaContext()
01092 {
01093   return 0;
01094 }
01095 
01096 KJavaAppletContext *KHTMLPart::createJavaContext()
01097 {
01098   return 0;
01099 }
01100 
01101 void KHTMLPart::setPluginsEnabled( bool enable )
01102 {
01103   d->m_bPluginsForce = enable;
01104   d->m_bPluginsOverride = true;
01105 }
01106 
01107 bool KHTMLPart::pluginsEnabled() const
01108 {
01109   if (onlyLocalReferences()) return false;
01110 
01111   if ( d->m_bPluginsOverride )
01112       return d->m_bPluginsForce;
01113   return d->m_bPluginsEnabled;
01114 }
01115 
01116 void KHTMLPart::slotDebugDOMTree()
01117 {
01118   if ( d->m_doc && d->m_doc->firstChild() )
01119     qDebug("%s", d->m_doc->firstChild()->toString().string().latin1());
01120 }
01121 
01122 void KHTMLPart::slotDebugScript()
01123 {
01124   if (jScript())
01125     jScript()->showDebugWindow();
01126 }
01127 
01128 void KHTMLPart::slotDebugRenderTree()
01129 {
01130 #ifndef NDEBUG
01131   if ( d->m_doc ) {
01132     d->m_doc->renderer()->printTree();
01133     // dump out the contents of the rendering & DOM trees
01134 //    QString dumps;
01135 //    QTextStream outputStream(dumps,IO_WriteOnly);
01136 //    d->m_doc->renderer()->layer()->dump( outputStream );
01137 //    kdDebug() << "dump output:" << "\n" + dumps;
01138   }
01139 #endif
01140 }
01141 
01142 void KHTMLPart::slotStopAnimations()
01143 {
01144   stopAnimations();
01145 }
01146 
01147 void KHTMLPart::setAutoloadImages( bool enable )
01148 {
01149   if ( d->m_doc && d->m_doc->docLoader()->autoloadImages() == enable )
01150     return;
01151 
01152   if ( d->m_doc )
01153     d->m_doc->docLoader()->setAutoloadImages( enable );
01154 
01155   unplugActionList( "loadImages" );
01156 
01157   if ( enable ) {
01158     delete d->m_paLoadImages;
01159     d->m_paLoadImages = 0;
01160   }
01161   else if ( !d->m_paLoadImages )
01162     d->m_paLoadImages = new KAction( i18n( "Display Images on Page" ), "images_display", 0, this, SLOT( slotLoadImages() ), actionCollection(), "loadImages" );
01163 
01164   if ( d->m_paLoadImages ) {
01165     QPtrList<KAction> lst;
01166     lst.append( d->m_paLoadImages );
01167     plugActionList( "loadImages", lst );
01168   }
01169 }
01170 
01171 bool KHTMLPart::autoloadImages() const
01172 {
01173   if ( d->m_doc )
01174     return d->m_doc->docLoader()->autoloadImages();
01175 
01176   return true;
01177 }
01178 
01179 void KHTMLPart::clear()
01180 {
01181   if ( d->m_bCleared )
01182     return;
01183 
01184   d->m_bCleared = true;
01185 
01186   d->m_bClearing = true;
01187 
01188   {
01189     ConstFrameIt it = d->m_frames.begin();
01190     ConstFrameIt end = d->m_frames.end();
01191     for(; it != end; ++it )
01192     {
01193       // Stop HTMLRun jobs for frames
01194       if ( (*it).m_run )
01195         (*it).m_run->abort();
01196     }
01197   }
01198 
01199   {
01200     QValueList<khtml::ChildFrame>::ConstIterator it = d->m_objects.begin();
01201     QValueList<khtml::ChildFrame>::ConstIterator end = d->m_objects.end();
01202     for(; it != end; ++it )
01203     {
01204       // Stop HTMLRun jobs for objects
01205       if ( (*it).m_run )
01206         (*it).m_run->abort();
01207     }
01208   }
01209 
01210 
01211   findTextBegin(); // resets d->m_findNode and d->m_findPos
01212   d->m_mousePressNode = DOM::Node();
01213 
01214 
01215   if ( d->m_doc )
01216     d->m_doc->detach();
01217 
01218   // Moving past doc so that onUnload works.
01219   if ( d->m_jscript )
01220     d->m_jscript->clear();
01221 
01222   // stopping marquees
01223   if (d->m_doc && d->m_doc->renderer() && d->m_doc->renderer()->layer())
01224       d->m_doc->renderer()->layer()->suspendMarquees();
01225 
01226   if ( d->m_view )
01227     d->m_view->clear();
01228 
01229   // do not dereference the document before the jscript and view are cleared, as some destructors
01230   // might still try to access the document.
01231   if ( d->m_doc ) {
01232     d->m_doc->deref();
01233   }
01234   d->m_doc = 0;
01235 
01236   delete d->m_decoder;
01237   d->m_decoder = 0;
01238 
01239   {
01240     ConstFrameIt it = d->m_frames.begin();
01241     ConstFrameIt end = d->m_frames.end();
01242     for(; it != end; ++it )
01243     {
01244       if ( (*it).m_part )
01245       {
01246         partManager()->removePart( (*it).m_part );
01247         delete (KParts::ReadOnlyPart *)(*it).m_part;
01248       }
01249     }
01250   }
01251 
01252   d->m_frames.clear();
01253   d->m_objects.clear();
01254 
01255   d->m_delayRedirect = 0;
01256   d->m_redirectURL = QString::null;
01257   d->m_redirectionTimer.stop();
01258   d->m_redirectLockHistory = true;
01259   d->m_bClearing = false;
01260   d->m_frameNameId = 1;
01261   d->m_bFirstData = true;
01262 
01263   d->m_bMousePressed = false;
01264 
01265   d->m_selectionStart = DOM::Node();
01266   d->m_selectionEnd = DOM::Node();
01267   d->m_startOffset = 0;
01268   d->m_endOffset = 0;
01269 #ifndef QT_NO_CLIPBOARD
01270   connect( kapp->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection()));
01271 #endif
01272 
01273   d->m_jobPercent = 0;
01274 
01275   if ( !d->m_haveEncoding )
01276     d->m_encoding = QString::null;
01277 #ifdef SPEED_DEBUG
01278   d->m_parsetime.restart();
01279 #endif
01280 }
01281 
01282 bool KHTMLPart::openFile()
01283 {
01284   return true;
01285 }
01286 
01287 DOM::HTMLDocumentImpl *KHTMLPart::docImpl() const
01288 {
01289     if ( d && d->m_doc && d->m_doc->isHTMLDocument() )
01290         return static_cast<HTMLDocumentImpl*>(d->m_doc);
01291     return 0;
01292 }
01293 
01294 DOM::DocumentImpl *KHTMLPart::xmlDocImpl() const
01295 {
01296     if ( d )
01297         return d->m_doc;
01298     return 0;
01299 }
01300 
01301 void KHTMLPart::slotInfoMessage(KIO::Job* kio_job, const QString& msg)
01302 {
01303   assert(d->m_job == kio_job);
01304 
01305   if (!parentPart())
01306     setStatusBarText(msg, BarDefaultText);
01307 }
01308 
01309 void KHTMLPart::setPageSecurity( PageSecurity sec )
01310 {
01311   if ( sec != NotCrypted && !d->m_statusBarIconLabel && !parentPart() ) {
01312     d->m_statusBarIconLabel = new KURLLabel( d->m_statusBarExtension->statusBar() );
01313     d->m_statusBarIconLabel->setFixedHeight( instance()->iconLoader()->currentSize(KIcon::Small) );
01314     d->m_statusBarIconLabel->setSizePolicy(QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ));
01315     d->m_statusBarIconLabel->setUseCursor( false );
01316     d->m_statusBarExtension->addStatusBarItem( d->m_statusBarIconLabel, 0, false );
01317     connect( d->m_statusBarIconLabel, SIGNAL( leftClickedURL() ), SLOT( slotSecurity() ) );
01318   } else if (d->m_statusBarIconLabel) {
01319     QToolTip::remove(d->m_statusBarIconLabel);
01320   }
01321 
01322   if (d->m_statusBarIconLabel) {
01323     if (d->m_ssl_in_use)
01324       QToolTip::add(d->m_statusBarIconLabel,
01325             i18n("Session is secured with %1 bit %2.").arg(d->m_ssl_cipher_used_bits).arg(d->m_ssl_cipher));
01326     else QToolTip::add(d->m_statusBarIconLabel, i18n("Session is not secured."));
01327   }
01328 
01329   QString iconName;
01330   switch (sec)  {
01331   case NotCrypted:
01332     iconName = "decrypted";
01333     if ( d->m_statusBarIconLabel )  {
01334       d->m_statusBarExtension->removeStatusBarItem( d->m_statusBarIconLabel );
01335       delete d->m_statusBarIconLabel;
01336       d->m_statusBarIconLabel = 0L;
01337     }
01338     break;
01339   case Encrypted:
01340     iconName = "encrypted";
01341     break;
01342   case Mixed:
01343     iconName = "halfencrypted";
01344     break;
01345   }
01346   d->m_paSecurity->setIcon( iconName );
01347   if ( d->m_statusBarIconLabel )
01348     d->m_statusBarIconLabel->setPixmap( SmallIcon( iconName, instance() ) );
01349 }
01350 
01351 void KHTMLPart::slotData( KIO::Job* kio_job, const QByteArray &data )
01352 {
01353   assert ( d->m_job == kio_job );
01354 
01355   //kdDebug( 6050 ) << "slotData: " << data.size() << endl;
01356   // The first data ?
01357   if ( !d->m_workingURL.isEmpty() )
01358   {
01359       //kdDebug( 6050 ) << "begin!" << endl;
01360 
01361     // We must suspend KIO while we're inside begin() because it can cause
01362     // crashes if a window (such as kjsdebugger) goes back into the event loop,
01363     // more data arrives, and begin() gets called again (re-entered).
01364     d->m_job->suspend();
01365     begin( d->m_workingURL, d->m_extension->urlArgs().xOffset, d->m_extension->urlArgs().yOffset );
01366     d->m_job->resume();
01367 
01368     if (d->m_cachePolicy == KIO::CC_Refresh)
01369       d->m_doc->docLoader()->setCachePolicy(KIO::CC_Verify);
01370     else
01371       d->m_doc->docLoader()->setCachePolicy(d->m_cachePolicy);
01372 
01373     d->m_workingURL = KURL();
01374 
01375     d->m_cacheId = KHTMLPageCache::self()->createCacheEntry();
01376 
01377     // When the first data arrives, the metadata has just been made available
01378     d->m_httpHeaders = d->m_job->queryMetaData("HTTP-Headers");
01379     time_t cacheCreationDate =  d->m_job->queryMetaData("cache-creation-date").toLong();
01380     d->m_doc->docLoader()->setCacheCreationDate(cacheCreationDate);
01381 
01382     d->m_pageServices = d->m_job->queryMetaData("PageServices");
01383     d->m_pageReferrer = d->m_job->queryMetaData("referrer");
01384 
01385     d->m_bSecurityInQuestion = false;
01386     d->m_ssl_in_use = (d->m_job->queryMetaData("ssl_in_use") == "TRUE");
01387 
01388     {
01389     KHTMLPart *p = parentPart();
01390     if (p && p->d->m_ssl_in_use != d->m_ssl_in_use) {
01391     while (p->parentPart()) p = p->parentPart();
01392 
01393         p->setPageSecurity( Mixed );
01394         p->d->m_bSecurityInQuestion = true;
01395     }
01396     }
01397 
01398     setPageSecurity( d->m_ssl_in_use ? Encrypted : NotCrypted );
01399 
01400     // Shouldn't all of this be done only if ssl_in_use == true ? (DF)
01401     d->m_ssl_parent_ip = d->m_job->queryMetaData("ssl_parent_ip");
01402     d->m_ssl_parent_cert = d->m_job->queryMetaData("ssl_parent_cert");
01403     d->m_ssl_peer_certificate = d->m_job->queryMetaData("ssl_peer_certificate");
01404     d->m_ssl_peer_chain = d->m_job->queryMetaData("ssl_peer_chain");
01405     d->m_ssl_peer_ip = d->m_job->queryMetaData("ssl_peer_ip");
01406     d->m_ssl_cipher = d->m_job->queryMetaData("ssl_cipher");
01407     d->m_ssl_cipher_desc = d->m_job->queryMetaData("ssl_cipher_desc");
01408     d->m_ssl_cipher_version = d->m_job->queryMetaData("ssl_cipher_version");
01409     d->m_ssl_cipher_used_bits = d->m_job->queryMetaData("ssl_cipher_used_bits");
01410     d->m_ssl_cipher_bits = d->m_job->queryMetaData("ssl_cipher_bits");
01411     d->m_ssl_cert_state = d->m_job->queryMetaData("ssl_cert_state");
01412 
01413     if (d->m_statusBarIconLabel) {
01414       QToolTip::remove(d->m_statusBarIconLabel);
01415       if (d->m_ssl_in_use) {
01416         QToolTip::add(d->m_statusBarIconLabel, i18n("Session is secured with %1 bit %2.").arg(d->m_ssl_cipher_used_bits).arg(d->m_ssl_cipher));
01417       } else {
01418         QToolTip::add(d->m_statusBarIconLabel, i18n("Session is not secured."));
01419       }
01420     }
01421 
01422     // Check for charset meta-data
01423     QString qData = d->m_job->queryMetaData("charset");
01424     if ( !qData.isEmpty() && !d->m_haveEncoding ) // only use information if the user didn't override the settings
01425        d->m_encoding = qData;
01426 
01427     // Support for http-refresh
01428     qData = d->m_job->queryMetaData("http-refresh");
01429     if( !qData.isEmpty())
01430       d->m_doc->processHttpEquiv("refresh", qData);
01431 
01432     // Support Content-Location per section 14.14 of RFC 2616.
01433     QString baseURL = d->m_job->queryMetaData ("content-location");
01434     if (!baseURL.isEmpty())
01435       d->m_doc->setBaseURL(KURL( d->m_doc->completeURL(baseURL) ));
01436 
01437 
01438     if ( !m_url.isLocalFile() ) {
01439         // Support for http last-modified
01440         d->m_lastModified = d->m_job->queryMetaData("modified");
01441     } else
01442         d->m_lastModified = QString::null; // done on-demand by lastModified()
01443 
01444     // Reset contents position
01445     d->m_view->setContentsPos( 0, 0 );
01446   }
01447 
01448   KHTMLPageCache::self()->addData(d->m_cacheId, data);
01449   write( data.data(), data.size() );
01450   if (d->m_jscript)
01451     d->m_jscript->dataReceived();
01452 }
01453 
01454 void KHTMLPart::slotRestoreData(const QByteArray &data )
01455 {
01456   // The first data ?
01457   if ( !d->m_workingURL.isEmpty() )
01458   {
01459      long saveCacheId = d->m_cacheId;
01460      QString savePageReferrer = d->m_pageReferrer;
01461      begin( d->m_workingURL, d->m_extension->urlArgs().xOffset, d->m_extension->urlArgs().yOffset );
01462      d->m_pageReferrer = savePageReferrer;
01463      d->m_cacheId = saveCacheId;
01464      d->m_workingURL = KURL();
01465   }
01466 
01467   //kdDebug( 6050 ) << "slotRestoreData: " << data.size() << endl;
01468   write( data.data(), data.size() );
01469 
01470   if (data.size() == 0)
01471   {
01472       //kdDebug( 6050 ) << "slotRestoreData: <<end of data>>" << endl;
01473      // End of data.
01474     if (d->m_doc && d->m_doc->parsing())
01475         end(); //will emit completed()
01476   }
01477 }
01478 
01479 void KHTMLPart::showError( KIO::Job* job )
01480 {
01481   kdDebug(6050) << "KHTMLPart::showError d->m_bParsing=" << (d->m_doc && d->m_doc->parsing()) << " d->m_bComplete=" << d->m_bComplete
01482                 << " d->m_bCleared=" << d->m_bCleared << endl;
01483 
01484   if (job->error() == KIO::ERR_NO_CONTENT)
01485     return;
01486 
01487   if ( (d->m_doc && d->m_doc->parsing()) || d->m_workingURL.isEmpty() ) // if we got any data already
01488     job->showErrorDialog( /*d->m_view*/ );
01489   else
01490   {
01491     htmlError( job->error(), job->errorText(), d->m_workingURL );
01492   }
01493 }
01494 
01495 // This is a protected method, placed here because of it's relevance to showError
01496 void KHTMLPart::htmlError( int errorCode, const QString& text, const KURL& reqUrl )
01497 {
01498   kdDebug(6050) << "KHTMLPart::htmlError errorCode=" << errorCode << " text=" << text << endl;
01499   // make sure we're not executing any embedded JS
01500   bool bJSFO = d->m_bJScriptForce;
01501   bool bJSOO = d->m_bJScriptOverride;
01502   d->m_bJScriptForce = false;
01503   d->m_bJScriptOverride = true;
01504   begin();
01505   QString errText = QString::fromLatin1( "<HTML dir=%1><HEAD><TITLE>" )
01506                            .arg(QApplication::reverseLayout() ? "rtl" : "ltr");
01507   errText += i18n( "Error while loading %1" ).arg( reqUrl.htmlURL() );
01508   errText += QString::fromLatin1( "</TITLE></HEAD><BODY><P>" );
01509   errText += i18n( "An error occurred while loading <B>%1</B>:" ).arg( reqUrl.htmlURL() );
01510   errText += QString::fromLatin1( "</P><P>" );
01511   QString kioErrString = KIO::buildErrorString( errorCode, text );
01512 
01513   kioErrString.replace('&', QString("&amp;"));
01514   kioErrString.replace('<', QString("&lt;"));
01515   kioErrString.replace('>', QString("&gt;"));
01516 
01517   // In case the error string has '\n' in it, replace with <BR/>
01518   kioErrString.replace( '\n', "<BR/>" );
01519 
01520   errText += kioErrString;
01521   errText += QString::fromLatin1( "</P></BODY></HTML>" );
01522   write(errText);
01523   end();
01524 
01525   d->m_bJScriptForce = bJSFO;
01526   d->m_bJScriptOverride = bJSOO;
01527 
01528   // make the working url the current url, so that reload works and
01529   // emit the progress signals to advance one step in the history
01530   // (so that 'back' works)
01531   m_url = reqUrl; // same as d->m_workingURL
01532   d->m_workingURL = KURL();
01533   emit started( 0 );
01534   emit completed();
01535   return;
01536   // following disabled until 3.1
01537 
01538   QString errorName, techName, description;
01539   QStringList causes, solutions;
01540 
01541   QByteArray raw = KIO::rawErrorDetail( errorCode, text, &reqUrl );
01542   QDataStream stream(raw, IO_ReadOnly);
01543 
01544   stream >> errorName >> techName >> description >> causes >> solutions;
01545 
01546   QString url, protocol, datetime;
01547   url = reqUrl.prettyURL();
01548   protocol = reqUrl.protocol();
01549   datetime = KGlobal::locale()->formatDateTime( QDateTime::currentDateTime(),
01550                                                 false );
01551 
01552   QString doc = QString::fromLatin1( "<html><head><title>" );
01553   doc += i18n( "Error: " );
01554   doc += errorName;
01555   doc += QString::fromLatin1( " - %1</title></head><body><h1>" ).arg( url );
01556   doc += i18n( "The requested operation could not be completed" );
01557   doc += QString::fromLatin1( "</h1><h2>" );
01558   doc += errorName;
01559   doc += QString::fromLatin1( "</h2>" );
01560   if ( !techName.isNull() ) {
01561     doc += QString::fromLatin1( "<h2>" );
01562     doc += i18n( "Technical Reason: " );
01563     doc += techName;
01564     doc += QString::fromLatin1( "</h2>" );
01565   }
01566   doc += QString::fromLatin1( "<h3>" );
01567   doc += i18n( "Details of the Request:" );
01568   doc += QString::fromLatin1( "</h3><ul><li>" );
01569   doc += i18n( "URL: %1" ).arg( url );
01570   doc += QString::fromLatin1( "</li><li>" );
01571   if ( !protocol.isNull() ) {
01572     // uncomment for 3.1... i18n change
01573     // doc += i18n( "Protocol: %1" ).arg( protocol ).arg( protocol );
01574     doc += QString::fromLatin1( "</li><li>" );
01575   }
01576   doc += i18n( "Date and Time: %1" ).arg( datetime );
01577   doc += QString::fromLatin1( "</li><li>" );
01578   doc += i18n( "Additional Information: %1" ).arg( text );
01579   doc += QString::fromLatin1( "</li></ul><h3>" );
01580   doc += i18n( "Description:" );
01581   doc += QString::fromLatin1( "</h3><p>" );
01582   doc += description;
01583   doc += QString::fromLatin1( "</p>" );
01584   if ( causes.count() ) {
01585     doc += QString::fromLatin1( "<h3>" );
01586     doc += i18n( "Possible Causes:" );
01587     doc += QString::fromLatin1( "</h3><ul><li>" );
01588     doc += causes.join( "</li><li>" );
01589     doc += QString::fromLatin1( "</li></ul>" );
01590   }
01591   if ( solutions.count() ) {
01592     doc += QString::fromLatin1( "<h3>" );
01593     doc += i18n( "Possible Solutions:" );
01594     doc += QString::fromLatin1( "</h3><ul><li>" );
01595     doc += solutions.join( "</li><li>" );
01596     doc += QString::fromLatin1( "</li></ul>" );
01597   }
01598   doc += QString::fromLatin1( "</body></html>" );
01599 
01600   write( doc );
01601   end();
01602 }
01603 
01604 void KHTMLPart::slotFinished( KIO::Job * job )
01605 {
01606   d->m_job = 0L;
01607   d->m_jobspeed = 0L;
01608 
01609   if (job->error())
01610   {
01611     KHTMLPageCache::self()->cancelEntry(d->m_cacheId);
01612 
01613     // The following catches errors that occur as a result of HTTP
01614     // to FTP redirections where the FTP URL is a directory. Since
01615     // KIO cannot change a redirection request from GET to LISTDIR,
01616     // we have to take care of it here once we know for sure it is
01617     // a directory...
01618     if (job->error() == KIO::ERR_IS_DIRECTORY)
01619     {
01620       KParts::URLArgs args;
01621       emit d->m_extension->openURLRequest( d->m_workingURL, args );
01622     }
01623     else
01624     {
01625       emit canceled( job->errorString() );
01626       // TODO: what else ?
01627       checkCompleted();
01628       showError( job );
01629     }
01630 
01631     return;
01632   }
01633   //kdDebug( 6050 ) << "slotFinished" << endl;
01634 
01635   KHTMLPageCache::self()->endData(d->m_cacheId);
01636   if (d->m_jscript)
01637     d->m_jscript->dataReceived();
01638 
01639   if ( d->m_doc && d->m_doc->docLoader()->expireDate() && m_url.protocol().lower().startsWith("http"))
01640       KIO::http_update_cache(m_url, false, d->m_doc->docLoader()->expireDate());
01641 
01642   d->m_workingURL = KURL();
01643 
01644   if ( d->m_doc && d->m_doc->parsing())
01645     end(); //will emit completed()
01646 }
01647 
01648 void KHTMLPart::begin( const KURL &url, int xOffset, int yOffset )
01649 {
01650   clear();
01651   d->m_bCleared = false;
01652   d->m_cacheId = 0;
01653   d->m_bComplete = false;
01654   d->m_bLoadEventEmitted = false;
01655   d->m_bWalletOpened = false;
01656 
01657   if(url.isValid()) {
01658       QString urlString = url.url();
01659       KHTMLFactory::vLinks()->insert( urlString );
01660       QString urlString2 = url.prettyURL();
01661       if ( urlString != urlString2 ) {
01662           KHTMLFactory::vLinks()->insert( urlString2 );
01663       }
01664   }
01665 
01666   // No need to show this for a new page until an error is triggered
01667   if (!parentPart()) {
01668     removeJSErrorExtension();
01669   }
01670 
01671   // ###
01672   //stopParser();
01673 
01674   KParts::URLArgs args( d->m_extension->urlArgs() );
01675   args.xOffset = xOffset;
01676   args.yOffset = yOffset;
01677   d->m_extension->setURLArgs( args );
01678 
01679   d->m_pageReferrer = QString::null;
01680 
01681   KURL ref(url);
01682   d->m_referrer = ref.protocol().startsWith("http") ? ref.url() : "";
01683 
01684   m_url = url;
01685   KURL baseurl;
01686 
01687   if ( !m_url.isEmpty() )
01688   {
01689     KURL title( baseurl );
01690     title.setRef( QString::null );
01691     title.setQuery( QString::null );
01692     emit setWindowCaption( title.prettyURL() );
01693   }
01694   else
01695     emit setWindowCaption( i18n( "[Untitled]" ) );
01696 
01697   // ### not sure if XHTML documents served as text/xml should use DocumentImpl or HTMLDocumentImpl
01698   if (args.serviceType == "text/xml")
01699     d->m_doc = DOMImplementationImpl::instance()->createDocument( d->m_view );
01700   else
01701     d->m_doc = DOMImplementationImpl::instance()->createHTMLDocument( d->m_view );
01702 #ifndef KHTML_NO_CARET
01703 //  d->m_view->initCaret();
01704 #endif
01705 
01706   d->m_doc->ref();
01707   d->m_doc->setURL( m_url.url() );
01708   if (!d->m_doc->attached())
01709     d->m_doc->attach( );
01710   // We prefer m_baseURL over m_url because m_url changes when we are
01711   // about to load a new page.
01712   d->m_doc->setBaseURL( baseurl );
01713   d->m_doc->docLoader()->setShowAnimations( KHTMLFactory::defaultHTMLSettings()->showAnimations() );
01714   emit docCreated(); // so that the parent can set the domain
01715 
01716   d->m_paUseStylesheet->setItems(QStringList());
01717   d->m_paUseStylesheet->setEnabled( false );
01718 
01719   setAutoloadImages( KHTMLFactory::defaultHTMLSettings()->autoLoadImages() );
01720   QString userStyleSheet = KHTMLFactory::defaultHTMLSettings()->userStyleSheet();
01721   if ( !userStyleSheet.isEmpty() )
01722     setUserStyleSheet( KURL( userStyleSheet ) );
01723 
01724   d->m_doc->setRestoreState(args.docState);
01725   d->m_doc->open();
01726   connect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
01727 
01728   emit d->m_extension->enableAction( "print", true );
01729 
01730   d->m_doc->setParsing(true);
01731 }
01732 
01733 void KHTMLPart::write( const char *str, int len )
01734 {
01735   if ( !d->m_decoder )
01736     d->m_decoder = createDecoder();
01737 
01738   if ( len == -1 )
01739     len = strlen( str );
01740 
01741   if ( len == 0 )
01742     return;
01743 
01744   QString decoded = d->m_decoder->decode( str, len );
01745 
01746   if(decoded.isEmpty()) return;
01747 
01748   if(d->m_bFirstData) {
01749       // determine the parse mode
01750       d->m_doc->determineParseMode( decoded );
01751       d->m_bFirstData = false;
01752 
01753   //kdDebug(6050) << "KHTMLPart::write haveEnc = " << d->m_haveEncoding << endl;
01754       // ### this is still quite hacky, but should work a lot better than the old solution
01755       if(d->m_decoder->visuallyOrdered()) d->m_doc->setVisuallyOrdered();
01756       d->m_doc->setDecoderCodec(d->m_decoder->codec());
01757       d->m_doc->recalcStyle( NodeImpl::Force );
01758   }
01759 
01760   khtml::Tokenizer* t = d->m_doc->tokenizer();
01761   if(t)
01762     t->write( decoded, true );
01763 }
01764 
01765 void KHTMLPart::write( const QString &str )
01766 {
01767   if ( str.isNull() )
01768     return;
01769 
01770   if(d->m_bFirstData) {
01771       // determine the parse mode
01772       d->m_doc->setParseMode( DocumentImpl::Strict );
01773       d->m_bFirstData = false;
01774   }
01775   khtml::Tokenizer* t = d->m_doc->tokenizer();
01776   if(t)
01777     t->write( str, true );
01778 }
01779 
01780 void KHTMLPart::end()
01781 {
01782     // make sure nothing's left in there...
01783     if(d->m_decoder)
01784         write(d->m_decoder->flush());
01785     if (d->m_doc)
01786         d->m_doc->finishParsing();
01787 }
01788 
01789 bool KHTMLPart::doOpenStream( const QString& mimeType )
01790 {
01791     if ( mimeType == "text/html" || mimeType == "text/xml" || mimeType == "application/xhtml+xml" )
01792     {
01793         begin( url() );
01794         return true;
01795     }
01796     return false;
01797 }
01798 
01799 bool KHTMLPart::doWriteStream( const QByteArray& data )
01800 {
01801     write( data.data(), data.size() );
01802     return true;
01803 }
01804 
01805 bool KHTMLPart::doCloseStream()
01806 {
01807     end();
01808     return true;
01809 }
01810 
01811 
01812 void KHTMLPart::paint(QPainter *p, const QRect &rc, int yOff, bool *more)
01813 {
01814     if (!d->m_view) return;
01815     d->m_view->paint(p, rc, yOff, more);
01816 }
01817 
01818 void KHTMLPart::stopAnimations()
01819 {
01820   if ( d->m_doc )
01821     d->m_doc->docLoader()->setShowAnimations( KHTMLSettings::KAnimationDisabled );
01822 
01823   ConstFrameIt it = d->m_frames.begin();
01824   ConstFrameIt end = d->m_frames.end();
01825   for (; it != end; ++it )
01826     if ( !( *it ).m_part.isNull() && ( *it ).m_part->inherits( "KHTMLPart" ) ) {
01827       KParts::ReadOnlyPart* p = ( *it ).m_part;
01828       static_cast<KHTMLPart*>( p )->stopAnimations();
01829     }
01830 }
01831 
01832 void KHTMLPart::slotFinishedParsing()
01833 {
01834   d->m_doc->setParsing(false);
01835   checkEmitLoadEvent();
01836   disconnect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
01837 
01838   if (!d->m_view)
01839     return; // We are probably being destructed.
01840   // check if the scrollbars are really needed for the content
01841   // if not, remove them, relayout, and repaint
01842 
01843   d->m_view->restoreScrollBar();
01844 
01845   checkCompleted();
01846 }
01847 
01848 void KHTMLPart::slotLoaderRequestStarted( khtml::DocLoader* dl, khtml::CachedObject *obj )
01849 {
01850   if ( obj && obj->type() == khtml::CachedObject::Image && d->m_doc && d->m_doc->docLoader() == dl ) {
01851     KHTMLPart* p = this;
01852     while ( p ) {
01853       KHTMLPart* op = p;
01854       p->d->m_totalObjectCount++;
01855       p = p->parentPart();
01856       if ( !p && op->d->m_loadedObjects <= op->d->m_totalObjectCount
01857         && !op->d->m_progressUpdateTimer.isActive())
01858     op->d->m_progressUpdateTimer.start( 200, true );
01859     }
01860   }
01861 }
01862 
01863 void KHTMLPart::slotLoaderRequestDone( khtml::DocLoader* dl, khtml::CachedObject *obj )
01864 {
01865   if ( obj && obj->type() == khtml::CachedObject::Image && d->m_doc && d->m_doc->docLoader() == dl ) {
01866     KHTMLPart* p = this;
01867     while ( p ) {
01868       KHTMLPart* op = p;
01869       p->d->m_loadedObjects++;
01870       p = p->parentPart();
01871       if ( !p && op->d->m_loadedObjects <= op->d->m_totalObjectCount && op->d->m_jobPercent <= 100
01872         && !op->d->m_progressUpdateTimer.isActive())
01873     op->d->m_progressUpdateTimer.start( 200, true );
01874     }
01875   }
01876 
01877   checkCompleted();
01878 }
01879 
01880 void KHTMLPart::slotProgressUpdate()
01881 {
01882   int percent;
01883   if ( d->m_loadedObjects < d->m_totalObjectCount )
01884     percent = d->m_jobPercent / 4 + ( d->m_loadedObjects*300 ) / ( 4*d->m_totalObjectCount );
01885   else
01886     percent = d->m_jobPercent;
01887 
01888   if( d->m_bComplete )
01889     percent = 100;
01890 
01891   if (d->m_statusMessagesEnabled) {
01892     if( d->m_bComplete )
01893       emit d->m_extension->infoMessage( i18n( "Page loaded." ));
01894     else if ( d->m_loadedObjects < d->m_totalObjectCount && percent >= 75 )
01895       emit d->m_extension->infoMessage( i18n( "%n Image of %1 loaded.", "%n Images of %1 loaded.", d->m_loadedObjects).arg(d->m_totalObjectCount) );
01896   }
01897 
01898   emit d->m_extension->loadingProgress( percent );
01899 }
01900 
01901 void KHTMLPart::slotJobSpeed( KIO::Job* /*job*/, unsigned long speed )
01902 {
01903   d->m_jobspeed = speed;
01904   if (!parentPart())
01905     setStatusBarText(jsStatusBarText(), BarOverrideText);
01906 }
01907 
01908 void KHTMLPart::slotJobPercent( KIO::Job* /*job*/, unsigned long percent )
01909 {
01910   d->m_jobPercent = percent;
01911 
01912   if ( !parentPart() )
01913     d->m_progressUpdateTimer.start( 0, true );
01914 }
01915 
01916 void KHTMLPart::slotJobDone( KIO::Job* /*job*/ )
01917 {
01918   d->m_jobPercent = 100;
01919 
01920   if ( !parentPart() )
01921     d->m_progressUpdateTimer.start( 0, true );
01922 }
01923 
01924 void KHTMLPart::slotUserSheetStatDone( KIO::Job *_job )
01925 {
01926   using namespace KIO;
01927 
01928   if ( _job->error() ) {
01929     showError( _job );
01930     return;
01931   }
01932 
01933   const UDSEntry entry = dynamic_cast<KIO::StatJob *>( _job )->statResult();
01934   UDSEntry::ConstIterator it = entry.begin();
01935   UDSEntry::ConstIterator end = entry.end();
01936   for ( ; it != end; ++it ) {
01937     if ( ( *it ).m_uds == UDS_MODIFICATION_TIME ) {
01938      break;
01939     }
01940   }
01941 
01942   // If the filesystem supports modification times, only reload the
01943   // user-defined stylesheet if necessary - otherwise always reload.
01944   if ( it != end ) {
01945     const time_t lastModified = static_cast<time_t>( ( *it ).m_long );
01946     if ( d->m_userStyleSheetLastModified >= lastModified ) {
01947       return;
01948     }
01949     d->m_userStyleSheetLastModified = lastModified;
01950   }
01951 
01952   setUserStyleSheet( KURL( settings()->userStyleSheet() ) );
01953 }
01954 
01955 void KHTMLPart::checkCompleted()
01956 {
01957 //   kdDebug( 6050 ) << "KHTMLPart::checkCompleted() " << this << " " << name() << endl;
01958 //   kdDebug( 6050 ) << "                           parsing: " << (d->m_doc && d->m_doc->parsing()) << endl;
01959 //   kdDebug( 6050 ) << "                           complete: " << d->m_bComplete << endl;
01960 
01961   // restore the cursor position
01962   if (d->m_doc && !d->m_doc->parsing() && !d->m_focusNodeRestored)
01963   {
01964       if (d->m_focusNodeNumber >= 0)
01965           d->m_doc->setFocusNode(d->m_doc->nodeWithAbsIndex(d->m_focusNodeNumber));
01966 
01967       d->m_focusNodeRestored = true;
01968   }
01969 
01970   bool bPendingChildRedirection = false;
01971   // Any frame that hasn't completed yet ?
01972   ConstFrameIt it = d->m_frames.begin();
01973   ConstFrameIt end = d->m_frames.end();
01974   for (; it != end; ++it ) {
01975     if ( !(*it).m_bCompleted )
01976     {
01977       //kdDebug( 6050 ) << this << " is waiting for " << ( *it ).m_part << endl;
01978       return;
01979     }
01980     // Check for frames with pending redirections
01981     if ( (*it).m_bPendingRedirection )
01982       bPendingChildRedirection = true;
01983   }
01984 
01985   // Any object that hasn't completed yet ?
01986   for (it = d->m_objects.begin(); it != d->m_objects.end(); ++it )
01987     if ( !(*it).m_bCompleted )
01988       return;
01989 
01990   // Are we still parsing - or have we done the completed stuff already ?
01991   if ( d->m_bComplete || (d->m_doc && d->m_doc->parsing()) )
01992     return;
01993 
01994   // Still waiting for images/scripts from the loader ?
01995   int requests = 0;
01996   if ( d->m_doc && d->m_doc->docLoader() )
01997     requests = khtml::Cache::loader()->numRequests( d->m_doc->docLoader() );
01998 
01999   if ( requests > 0 )
02000   {
02001     //kdDebug(6050) << "still waiting for images/scripts from the loader - requests:" << requests << endl;
02002     return;
02003   }
02004 
02005   // OK, completed.
02006   // Now do what should be done when we are really completed.
02007   d->m_bComplete = true;
02008   d->m_cachePolicy = KProtocolManager::cacheControl(); // reset cache policy
02009   d->m_totalObjectCount = 0;
02010   d->m_loadedObjects = 0;
02011 
02012   KHTMLPart* p = this;
02013   while ( p ) {
02014     KHTMLPart* op = p;
02015     p = p->parentPart();
02016     if ( !p && !op->d->m_progressUpdateTimer.isActive())
02017       op->d->m_progressUpdateTimer.start( 0, true );
02018   }
02019 
02020   checkEmitLoadEvent(); // if we didn't do it before
02021 
02022   // check that the view has not been moved by the user
02023 
02024   if ( m_url.encodedHtmlRef().isEmpty() && d->m_view->contentsY() == 0 )
02025       d->m_view->setContentsPos( d->m_extension->urlArgs().xOffset,
02026                                  d->m_extension->urlArgs().yOffset );
02027 
02028   d->m_view->complete();
02029 
02030   if ( !d->m_redirectURL.isEmpty() )
02031   {
02032     // Do not start redirection for frames here! That action is
02033     // deferred until the parent emits a completed signal.
02034     if ( parentPart() == 0 )
02035       d->m_redirectionTimer.start( 1000 * d->m_delayRedirect, true );
02036 
02037     emit completed( true );
02038   }
02039   else
02040   {
02041     if ( bPendingChildRedirection )
02042       emit completed( true );
02043     else
02044       emit completed();
02045   }
02046 
02047   // find the alternate stylesheets
02048   QStringList sheets;
02049   if (d->m_doc)
02050      sheets = d->m_doc->availableStyleSheets();
02051   sheets.prepend( i18n( "Automatic Detection" ) );
02052   d->m_paUseStylesheet->setItems( sheets );
02053 
02054   d->m_paUseStylesheet->setEnabled( sheets.count() > 2);
02055   if (sheets.count() > 2)
02056   {
02057     d->m_paUseStylesheet->setCurrentItem(kMax(sheets.findIndex(d->m_sheetUsed), 0));
02058     slotUseStylesheet();
02059   }
02060 
02061   setJSDefaultStatusBarText(QString::null);
02062 
02063 #ifdef SPEED_DEBUG
02064   kdDebug(6050) << "DONE: " <<d->m_parsetime.elapsed() << endl;
02065 #endif
02066 }
02067 
02068 void KHTMLPart::checkEmitLoadEvent()
02069 {
02070   if ( d->m_bLoadEventEmitted || !d->m_doc || d->m_doc->parsing() ) return;
02071 
02072   ConstFrameIt it = d->m_frames.begin();
02073   ConstFrameIt end = d->m_frames.end();
02074   for (; it != end; ++it )
02075     if ( !(*it).m_bCompleted ) // still got a frame running -> too early
02076       return;
02077 
02078   for (it = d->m_objects.begin(); it != d->m_objects.end(); ++it )
02079     if ( !(*it).m_bCompleted ) // still got a object running -> too early
02080       return;
02081 
02082   // Still waiting for images/scripts from the loader ?
02083   // (onload must happen afterwards, #45607)
02084   // ## This makes this method very similar to checkCompleted. A brave soul should try merging them.
02085   int requests = 0;
02086   if ( d->m_doc && d->m_doc->docLoader() )
02087     requests = khtml::Cache::loader()->numRequests( d->m_doc->docLoader() );
02088 
02089   if ( requests > 0 )
02090     return;
02091 
02092   d->m_bLoadEventEmitted = true;
02093   if (d->m_doc)
02094     d->m_doc->close();
02095 }
02096 
02097 const KHTMLSettings *KHTMLPart::settings() const
02098 {
02099   return d->m_settings;
02100 }
02101 
02102 #ifndef KDE_NO_COMPAT
02103 KURL KHTMLPart::baseURL() const
02104 {
02105   if ( !d->m_doc ) return KURL();
02106 
02107   return d->m_doc->baseURL();
02108 }
02109 
02110 QString KHTMLPart::baseTarget() const
02111 {
02112   if ( !d->m_doc ) return QString::null;
02113 
02114   return d->m_doc->baseTarget();
02115 }
02116 #endif
02117 
02118 KURL KHTMLPart::completeURL( const QString &url )
02119 {
02120   if ( !d->m_doc ) return KURL( url );
02121 
02122   if (d->m_decoder)
02123     return KURL(d->m_doc->completeURL(url), d->m_decoder->codec()->mibEnum());
02124 
02125   return KURL( d->m_doc->completeURL( url ) );
02126 }
02127 
02128 void KHTMLPart::scheduleRedirection( int delay, const QString &url, bool doLockHistory )
02129 {
02130   kdDebug(6050) << "KHTMLPart::scheduleRedirection delay=" << delay << " url=" << url << endl;
02131   kdDebug(6050) << "current redirectURL=" << d->m_redirectURL << " with delay " << d->m_delayRedirect <<  endl;
02132   if( delay < 24*60*60 &&
02133       ( d->m_redirectURL.isEmpty() || delay <= d->m_delayRedirect) ) {
02134     d->m_delayRedirect = delay;
02135     d->m_redirectURL = url;
02136     d->m_redirectLockHistory = doLockHistory;
02137     kdDebug(6050) << " d->m_bComplete=" << d->m_bComplete << endl;
02138     if ( d->m_bComplete ) {
02139       d->m_redirectionTimer.stop();
02140       d->m_redirectionTimer.start( kMax(0, 1000 * d->m_delayRedirect), true );
02141     }
02142   }
02143 }
02144 
02145 void KHTMLPart::slotRedirect()
02146 {
02147   kdDebug() << k_funcinfo << endl;
02148   QString u = d->m_redirectURL;
02149   d->m_delayRedirect = 0;
02150   d->m_redirectURL = QString::null;
02151 
02152   // SYNC check with ecma/kjs_window.cpp::goURL !
02153   if ( u.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
02154   {
02155     QString script = KURL::decode_string( u.right( u.length() - 11 ) );
02156     kdDebug( 6050 ) << "KHTMLPart::slotRedirect script=" << script << endl;
02157     QVariant res = executeScript( DOM::Node(), script );
02158     if ( res.type() == QVariant::String ) {
02159       begin( url() );
02160       write( res.asString() );
02161       end();
02162     }
02163     return;
02164   }
02165   KParts::URLArgs args;
02166   // Redirecting to the current URL leads to a reload.
02167   // But jumping to an anchor never leads to a reload.
02168   KURL cUrl( m_url );
02169   KURL url( u );
02170 
02171   // handle windows opened by JS
02172   if ( openedByJS() && d->m_opener )
02173       cUrl = d->m_opener->url();
02174 
02175   if (!kapp || !kapp->authorizeURLAction("redirect", cUrl, url))
02176   {
02177     kdWarning(6050) << "KHTMLPart::scheduleRedirection: Redirection from " << cUrl.prettyURL() << " to " << url.prettyURL() << " REJECTED!" << endl;
02178     return;
02179   }
02180 
02181   if ( urlcmp( u, m_url.url(), true, true ) )
02182   {
02183     args.metaData().insert("referrer", d->m_pageReferrer);
02184   }
02185 
02186   // Indicate that this request is due to a redirection.
02187   args.setRedirectedRequest(true);
02188 
02189   args.setLockHistory( d->m_redirectLockHistory );
02190   // _self: make sure we don't use any <base target=>'s
02191   urlSelected( u, 0, 0, "_self", args );
02192 }
02193 
02194 void KHTMLPart::slotRedirection(KIO::Job*, const KURL& url)
02195 {
02196   // the slave told us that we got redirected
02197   //kdDebug( 6050 ) << "redirection by KIO to " << url.url() << endl;
02198   emit d->m_extension->setLocationBarURL( url.prettyURL() );
02199   d->m_workingURL = url;
02200 }
02201 
02202 bool KHTMLPart::setEncoding( const QString &name, bool override )
02203 {
02204     d->m_encoding = name;
02205     d->m_haveEncoding = override;
02206 
02207     if( !m_url.isEmpty() ) {
02208         // reload document
02209         closeURL();
02210         KURL url = m_url;
02211         m_url = 0;
02212         d->m_restored = true;
02213         openURL(url);
02214         d->m_restored = false;
02215     }
02216 
02217     return true;
02218 }
02219 
02220 QString KHTMLPart::encoding() const
02221 {
02222     if(d->m_haveEncoding && !d->m_encoding.isEmpty())
02223         return d->m_encoding;
02224 
02225     if(d->m_decoder && d->m_decoder->encoding())
02226         return QString(d->m_decoder->encoding());
02227 
02228     return defaultEncoding();
02229 }
02230 
02231 QString KHTMLPart::defaultEncoding() const
02232 {
02233   QString encoding = settings()->encoding();
02234   if ( !encoding.isEmpty() )
02235     return encoding;
02236   // HTTP requires the default encoding to be latin1, when neither
02237   // the user nor the page requested a particular encoding.
02238   if ( url().protocol().startsWith( "http" ) )
02239     return "iso-8859-1";
02240   else
02241     return KGlobal::locale()->encoding();
02242 }
02243 
02244 void KHTMLPart::setUserStyleSheet(const KURL &url)
02245 {
02246   if ( d->m_doc && d->m_doc->docLoader() )
02247     (void) new khtml::PartStyleSheetLoader(this, url.url(), d->m_doc->docLoader());
02248 }
02249 
02250 void KHTMLPart::setUserStyleSheet(const QString &styleSheet)
02251 {
02252   if ( d->m_doc )
02253     d->m_doc->setUserStyleSheet( styleSheet );
02254 }
02255 
02256 void KHTMLPart::gotoAnchor()
02257 {
02258   if ( !d->m_doc || !d->m_doc->parsing() ) {
02259     disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(gotoAnchor()));
02260   }
02261 
02262   if ( !gotoAnchor(m_url.encodedHtmlRef()) )
02263       gotoAnchor(m_url.htmlRef());
02264 }
02265 
02266 bool KHTMLPart::gotoAnchor( const QString &name )
02267 {
02268   if (!d->m_doc)
02269     return false;
02270 
02271   HTMLCollectionImpl *anchors =
02272       new HTMLCollectionImpl( d->m_doc, HTMLCollectionImpl::DOC_ANCHORS);
02273   anchors->ref();
02274   NodeImpl *n = anchors->namedItem(name);
02275   anchors->deref();
02276 
02277   if(!n) {
02278       n = d->m_doc->getElementById( name );
02279   }
02280 
02281   // Implement the rule that "" and "top" both mean top of page as in other browsers.
02282   bool quirkyName = !n && !d->m_doc->inStrictMode() && (name.isEmpty() || name.lower() == "top");
02283 
02284   if (quirkyName) {
02285       d->m_view->setContentsPos(0, 0);
02286       return true;
02287   } else if (!n) {
02288       kdDebug(6050) << "KHTMLPart::gotoAnchor node '" << name << "' not found" << endl;
02289       return false;
02290   }
02291 
02292   int x = 0, y = 0;
02293   int gox, dummy;
02294   HTMLElementImpl *a = static_cast<HTMLElementImpl *>(n);
02295 
02296   a->getUpperLeftCorner(x, y);
02297   if (x <= d->m_view->contentsX())
02298     gox = x - 10;
02299   else {
02300     gox = d->m_view->contentsX();
02301     if ( x + 10 > d->m_view->contentsX()+d->m_view->visibleWidth()) {
02302       a->getLowerRightCorner(x, dummy);
02303       gox = x - d->m_view->visibleWidth() + 10;
02304     }
02305   }
02306 
02307   d->m_view->setContentsPos(gox, y-20);
02308 
02309   return true;
02310 }
02311 
02312 bool KHTMLPart::nextAnchor()
02313 {
02314   if (!d->m_doc)
02315     return false;
02316   d->m_view->focusNextPrevNode ( true );
02317 
02318   return true;
02319 }
02320 
02321 bool KHTMLPart::prevAnchor()
02322 {
02323   if (!d->m_doc)
02324     return false;
02325   d->m_view->focusNextPrevNode ( false );
02326 
02327   return true;
02328 }
02329 
02330 void KHTMLPart::setStandardFont( const QString &name )
02331 {
02332     d->m_settings->setStdFontName(name);
02333 }
02334 
02335 void KHTMLPart::setFixedFont( const QString &name )
02336 {
02337     d->m_settings->setFixedFontName(name);
02338 }
02339 
02340 void KHTMLPart::setURLCursor( const QCursor &c )
02341 {
02342   d->m_linkCursor = c;
02343 }
02344 
02345 QCursor KHTMLPart::urlCursor() const
02346 {
02347   return d->m_linkCursor;
02348 }
02349 
02350 bool KHTMLPart::onlyLocalReferences() const
02351 {
02352   return d->m_onlyLocalReferences;
02353 }
02354 
02355 void KHTMLPart::setOnlyLocalReferences(bool enable)
02356 {
02357   d->m_onlyLocalReferences = enable;
02358 }
02359 
02360 void KHTMLPartPrivate::setFlagRecursively(
02361     bool KHTMLPartPrivate::*flag, bool value)
02362 {
02363   // first set it on the current one
02364   this->*flag = value;
02365 
02366   // descend into child frames recursively
02367   QValueList<khtml::ChildFrame>::Iterator it = m_frames.begin();
02368   for (; it != m_frames.end(); ++it) {
02369     KHTMLPart *part = static_cast<KHTMLPart *>((KParts::ReadOnlyPart *)(*it).m_part);
02370     if (part->inherits("KHTMLPart"))
02371       part->d->setFlagRecursively(flag, value);
02372   }/*next it*/
02373 
02374   // do the same again for objects
02375   it = m_objects.begin();
02376   for (; it != m_objects.end(); ++it) {
02377     KHTMLPart *part = static_cast<KHTMLPart *>((KParts::ReadOnlyPart *)(*it).m_part);
02378     if (part->inherits("KHTMLPart"))
02379       part->d->setFlagRecursively(flag, value);
02380   }/*next it*/
02381 }
02382 
02383 void KHTMLPart::setCaretMode(bool enable)
02384 {
02385 #ifndef KHTML_NO_CARET
02386   kdDebug(6200) << "setCaretMode(" << enable << ")" << endl;
02387   if (isCaretMode() == enable) return;
02388   d->setFlagRecursively(&KHTMLPartPrivate::m_caretMode, enable);
02389   // FIXME: this won't work on frames as expected
02390   if (!isEditable()) {
02391     if (enable) {
02392       view()->initCaret(true);
02393       view()->ensureCaretVisible();
02394     } else
02395       view()->caretOff();
02396   }/*end if*/
02397 #endif // KHTML_NO_CARET
02398 }
02399 
02400 bool KHTMLPart::isCaretMode() const
02401 {
02402   return d->m_caretMode;
02403 }
02404 
02405 void KHTMLPart::setEditable(bool enable)
02406 {
02407 #ifndef KHTML_NO_CARET
02408   if (isEditable() == enable) return;
02409   d->setFlagRecursively(&KHTMLPartPrivate::m_designMode, enable);
02410   // FIXME: this won't work on frames as expected
02411   if (!isCaretMode()) {
02412     if (enable) {
02413       view()->initCaret(true);
02414       view()->ensureCaretVisible();
02415     } else
02416       view()->caretOff();
02417   }/*end if*/
02418 #endif // KHTML_NO_CARET
02419 }
02420 
02421 bool KHTMLPart::isEditable() const
02422 {
02423   return d->m_designMode;
02424 }
02425 
02426 void KHTMLPart::setCaretPosition(DOM::Node node, long offset, bool extendSelection)
02427 {
02428 #ifndef KHTML_NO_CARET
02429 #if 0
02430   kdDebug(6200) << k_funcinfo << "node: " << node.handle() << " nodeName: "
02431     << node.nodeName().string() << " offset: " << offset
02432     << " extendSelection " << extendSelection << endl;
02433 #endif
02434   if (view()->moveCaretTo(node.handle(), offset, !extendSelection))
02435     emitSelectionChanged();
02436   view()->ensureCaretVisible();
02437 #endif // KHTML_NO_CARET
02438 }
02439 
02440 KHTMLPart::CaretDisplayPolicy KHTMLPart::caretDisplayPolicyNonFocused() const
02441 {
02442 #ifndef KHTML_NO_CARET
02443   return (CaretDisplayPolicy)view()->caretDisplayPolicyNonFocused();
02444 #else // KHTML_NO_CARET
02445   return CaretInvisible;
02446 #endif // KHTML_NO_CARET
02447 }
02448 
02449 void KHTMLPart::setCaretDisplayPolicyNonFocused(CaretDisplayPolicy policy)
02450 {
02451 #ifndef KHTML_NO_CARET
02452   view()->setCaretDisplayPolicyNonFocused(policy);
02453 #endif // KHTML_NO_CARET
02454 }
02455 
02456 void KHTMLPart::setCaretVisible(bool show)
02457 {
02458 #ifndef KHTML_NO_CARET
02459   if (show) {
02460 
02461     NodeImpl *caretNode = xmlDocImpl()->focusNode();
02462     if (isCaretMode() || isEditable()
02463     || (caretNode && caretNode->contentEditable())) {
02464       view()->caretOn();
02465     }/*end if*/
02466 
02467   } else {
02468 
02469     view()->caretOff();
02470 
02471   }/*end if*/
02472 #endif // KHTML_NO_CARET
02473 }
02474 
02475 void KHTMLPart::findTextBegin()
02476 {
02477   d->m_findPos = -1;
02478   d->m_findNode = 0;
02479   d->m_findPosEnd = -1;
02480   d->m_findNodeEnd= 0;
02481   delete d->m_find;
02482   d->m_find = 0L;
02483 }
02484 
02485 bool KHTMLPart::initFindNode( bool selection, bool reverse, bool fromCursor )
02486 {
02487     if ( !d->m_doc )
02488         return false;
02489 
02490     DOM::NodeImpl* firstNode = 0L;
02491     if (d->m_doc->isHTMLDocument())
02492       firstNode = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
02493     else
02494       firstNode = d->m_doc;
02495 
02496     if ( !firstNode )
02497     {
02498       //kdDebug(6050) << k_funcinfo << "no first node (body or doc) -> return false" << endl;
02499       return false;
02500     }
02501     if ( firstNode->id() == ID_FRAMESET )
02502     {
02503       //kdDebug(6050) << k_funcinfo << "FRAMESET -> return false" << endl;
02504       return false;
02505     }
02506 
02507     if ( selection && hasSelection() )
02508     {
02509       //kdDebug(6050) << k_funcinfo << "using selection" << endl;
02510       if ( !fromCursor )
02511       {
02512         d->m_findNode = reverse ? d->m_selectionEnd.handle() : d->m_selectionStart.handle();
02513         d->m_findPos = reverse ? d->m_endOffset : d->m_startOffset;
02514       }
02515       d->m_findNodeEnd = reverse ? d->m_selectionStart.handle() : d->m_selectionEnd.handle();
02516       d->m_findPosEnd = reverse ? d->m_startOffset : d->m_endOffset;
02517     }
02518     else // whole document
02519     {
02520       //kdDebug(6050) << k_funcinfo << "whole doc" << endl;
02521       if ( !fromCursor )
02522       {
02523         d->m_findNode = firstNode;
02524         d->m_findPos = reverse ? -1 : 0;
02525       }
02526       d->m_findNodeEnd = reverse ? firstNode : 0;
02527       d->m_findPosEnd = reverse ? 0 : -1;
02528       if ( reverse )
02529       {
02530         // Need to find out the really last object, to start from it
02531         khtml::RenderObject* obj = d->m_findNode ? d->m_findNode->renderer() : 0;
02532         if ( obj )
02533         {
02534           // find the last object in the render tree
02535           while ( obj->lastChild() )
02536           {
02537               obj = obj->lastChild();
02538           }
02539           // now get the last object with a NodeImpl associated
02540           while ( !obj->element() && obj->objectAbove() )
02541           {
02542              obj = obj->objectAbove();
02543           }
02544           d->m_findNode = obj->element();
02545         }
02546       }
02547     }
02548     return true;
02549 }
02550 
02551 // Old method (its API limits the available features - remove in KDE-4)
02552 bool KHTMLPart::findTextNext( const QString &str, bool forward, bool caseSensitive, bool isRegExp )
02553 {
02554     if ( !initFindNode( false, !forward, false ) )
02555       return false;
02556     while(1)
02557     {
02558         if( (d->m_findNode->nodeType() == Node::TEXT_NODE || d->m_findNode->nodeType() == Node::CDATA_SECTION_NODE) && d->m_findNode->renderer() )
02559         {
02560             DOMString nodeText = d->m_findNode->nodeValue();
02561             DOMStringImpl *t = nodeText.implementation();
02562             QConstString s(t->s, t->l);
02563 
02564             int matchLen = 0;
02565             if ( isRegExp ) {
02566               QRegExp matcher( str );
02567               matcher.setCaseSensitive( caseSensitive );
02568               d->m_findPos = matcher.search(s.string(), d->m_findPos+1);
02569               if ( d->m_findPos != -1 )
02570                 matchLen = matcher.matchedLength();
02571             }
02572             else {
02573               d->m_findPos = s.string().find(str, d->m_findPos+1, caseSensitive);
02574               matchLen = str.length();
02575             }
02576 
02577             if(d->m_findPos != -1)
02578             {
02579                 int x = 0, y = 0;
02580                 if(static_cast<khtml::RenderText *>(d->m_findNode->renderer())
02581                   ->posOfChar(d->m_findPos, x, y))
02582                     d->m_view->setContentsPos(x-50, y-50);
02583 
02584                 d->m_selectionStart = d->m_findNode;
02585                 d->m_startOffset = d->m_findPos;
02586                 d->m_selectionEnd = d->m_findNode;
02587                 d->m_endOffset = d->m_findPos + matchLen;
02588                 d->m_startBeforeEnd = true;
02589 
02590                 d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
02591                                         d->m_selectionEnd.handle(), d->m_endOffset );
02592                 emitSelectionChanged();
02593                 return true;
02594             }
02595         }
02596         d->m_findPos = -1;
02597 
02598         NodeImpl *next;
02599 
02600         if ( forward )
02601         {
02602           next = d->m_findNode->firstChild();
02603 
02604           if(!next) next = d->m_findNode->nextSibling();
02605           while(d->m_findNode && !next) {
02606               d->m_findNode = d->m_findNode->parentNode();
02607               if( d->m_findNode ) {
02608                   next = d->m_findNode->nextSibling();
02609               }
02610           }
02611         }
02612         else
02613         {
02614           next = d->m_findNode->lastChild();
02615 
02616           if (!next ) next = d->m_findNode->previousSibling();
02617           while ( d->m_findNode && !next )
02618           {
02619             d->m_findNode = d->m_findNode->parentNode();
02620             if( d->m_findNode )
02621             {
02622               next = d->m_findNode->previousSibling();
02623             }
02624           }
02625         }
02626 
02627         d->m_findNode = next;
02628         if(!d->m_findNode) return false;
02629     }
02630 }
02631 
02632 
02633 void KHTMLPart::slotFind()
02634 {
02635   KParts::ReadOnlyPart *part = currentFrame();
02636   if (!part)
02637     return;
02638   if (!part->inherits("KHTMLPart") )
02639   {
02640       kdError(6000) << "slotFind: part is a " << part->className() << ", can't do a search into it" << endl;
02641       return;
02642   }
02643   static_cast<KHTMLPart *>( part )->findText();
02644 }
02645 
02646 void KHTMLPart::slotFindNext()
02647 {
02648   KParts::ReadOnlyPart *part = currentFrame();
02649   if (!part)
02650     return;
02651   if (!part->inherits("KHTMLPart") )
02652   {
02653       kdError(6000) << "slotFindNext: part is a " << part->className() << ", can't do a search into it" << endl;
02654       return;
02655   }
02656   static_cast<KHTMLPart *>( part )->findTextNext();
02657 }
02658 
02659 void KHTMLPart::slotFindDone()
02660 {
02661   // ### remove me
02662 }
02663 
02664 void KHTMLPart::slotFindDialogDestroyed()
02665 {
02666   d->m_lastFindState.options = d->m_findDialog->options();
02667   d->m_lastFindState.history = d->m_findDialog->findHistory();
02668   d->m_findDialog->deleteLater();
02669   d->m_findDialog = 0L;
02670 }
02671 
02672 void KHTMLPart::findText()
02673 {
02674   // First do some init to make sure we can search in this frame
02675   if ( !d->m_doc )
02676     return;
02677 
02678   // Raise if already opened
02679   if ( d->m_findDialog )
02680   {
02681     KWin::activateWindow( d->m_findDialog->winId() );
02682     return;
02683   }
02684 
02685   // The lineedit of the dialog would make khtml lose its selection, otherwise
02686 #ifndef QT_NO_CLIPBOARD
02687   disconnect( kapp->clipboard(), SIGNAL(selectionChanged()), this, SLOT(slotClearSelection()) );
02688 #endif
02689 
02690   // Now show the dialog in which the user can choose options.
02691   d->m_findDialog = new KFindDialog( false /*non-modal*/, widget(), "khtmlfind" );
02692   d->m_findDialog->setHasSelection( hasSelection() );
02693   d->m_findDialog->setHasCursor( d->m_findNode != 0 );
02694   if ( d->m_findNode ) // has a cursor -> default to 'FromCursor'
02695     d->m_lastFindState.options |= KFindDialog::FromCursor;
02696 
02697   // TODO? optionsDialog.setPattern( d->m_lastFindState.text );
02698   d->m_findDialog->setFindHistory( d->m_lastFindState.history );
02699   d->m_findDialog->setOptions( d->m_lastFindState.options );
02700 
02701   d->m_lastFindState.options = -1; // force update in findTextNext
02702 
02703   d->m_findDialog->show();
02704   connect( d->m_findDialog, SIGNAL(okClicked()), this, SLOT(slotFindNext()) );
02705   connect( d->m_findDialog, SIGNAL(finished()), this, SLOT(slotFindDialogDestroyed()) );
02706 
02707   findText( d->m_findDialog->pattern(), 0 /*options*/, widget(), d->m_findDialog );
02708 }
02709 
02710 void KHTMLPart::findText( const QString &str, long options, QWidget *parent, KFindDialog *findDialog )
02711 {
02712   // First do some init to make sure we can search in this frame
02713   if ( !d->m_doc )
02714     return;
02715 
02716 #ifndef QT_NO_CLIPBOARD
02717   connect( kapp->clipboard(), SIGNAL(selectionChanged()), SLOT(slotClearSelection()) );
02718 #endif
02719 
02720   // Create the KFind object
02721   delete d->m_find;
02722   d->m_find = new KFind( str, options, parent, findDialog );
02723   d->m_find->closeFindNextDialog(); // we use KFindDialog non-modal, so we don't want other dlg popping up
02724   connect( d->m_find, SIGNAL( highlight( const QString &, int, int ) ),
02725            this, SLOT( slotHighlight( const QString &, int, int ) ) );
02726   //connect(d->m_find, SIGNAL( findNext() ),
02727   //        this, SLOT( slotFindNext() ) );
02728 
02729   if ( !findDialog )
02730   {
02731     d->m_lastFindState.options = options;
02732     initFindNode( options & KFindDialog::SelectedText,
02733                   options & KFindDialog::FindBackwards,
02734                   options & KFindDialog::FromCursor );
02735   }
02736 }
02737 
02738 // New method
02739 bool KHTMLPart::findTextNext()
02740 {
02741   if (!d->m_find)
02742   {
02743     // We didn't show the find dialog yet, let's do it then (#49442)
02744     findText();
02745     return false;
02746   }
02747 
02748   long options = 0;
02749   if ( d->m_findDialog ) // 0 when we close the dialog
02750   {
02751     if ( d->m_find->pattern() != d->m_findDialog->pattern() ) {
02752       d->m_find->setPattern( d->m_findDialog->pattern() );
02753       d->m_find->resetCounts();
02754     }
02755     options = d->m_findDialog->options();
02756     if ( d->m_lastFindState.options != options )
02757     {
02758       d->m_find->setOptions( options );
02759 
02760       if ( options & KFindDialog::SelectedText )
02761         Q_ASSERT( hasSelection() );
02762 
02763       long difference = d->m_lastFindState.options ^ options;
02764       if ( difference & (KFindDialog::SelectedText | KFindDialog::FromCursor ) )
02765       {
02766           // Important options changed -> reset search range
02767         (void) initFindNode( options & KFindDialog::SelectedText,
02768                              options & KFindDialog::FindBackwards,
02769                              options & KFindDialog::FromCursor );
02770       }
02771       d->m_lastFindState.options = options;
02772     }
02773   } else
02774     options = d->m_lastFindState.options;
02775 
02776   KFind::Result res = KFind::NoMatch;
02777   khtml::RenderObject* obj = d->m_findNode ? d->m_findNode->renderer() : 0;
02778   khtml::RenderObject* end = d->m_findNodeEnd ? d->m_findNodeEnd->renderer() : 0;
02779   khtml::RenderTextArea *tmpTextArea=0L;
02780   //kdDebug(6050) << k_funcinfo << "obj=" << obj << " end=" << end << endl;
02781   while( res == KFind::NoMatch )
02782   {
02783     if ( d->m_find->needData() )
02784     {
02785       if ( !obj ) {
02786         //kdDebug(6050) << k_funcinfo << "obj=0 -> done" << endl;
02787         break; // we're done
02788       }
02789       //kdDebug(6050) << k_funcinfo << " gathering data" << endl;
02790       // First make up the QString for the current 'line' (i.e. up to \n)
02791       // We also want to remember the DOMNode for every portion of the string.
02792       // We store this in an index->node list.
02793 
02794       d->m_stringPortions.clear();
02795       int newLinePos = -1;
02796       QString str;
02797       DOM::NodeImpl* lastNode = d->m_findNode;
02798       while ( obj && newLinePos == -1 )
02799       {
02800         // Grab text from render object
02801         QString s;
02802         bool renderAreaText = obj->parent() && (QCString(obj->parent()->renderName())== "RenderTextArea");
02803         bool renderLineText = (QCString(obj->renderName())== "RenderLineEdit");
02804         if ( renderAreaText )
02805         {
02806           khtml::RenderTextArea *parent= static_cast<khtml::RenderTextArea *>(obj->parent());
02807           s = parent->text();
02808           s = s.replace(0xa0, ' ');
02809           tmpTextArea = parent;
02810         }
02811         else if ( renderLineText )
02812         {
02813           khtml::RenderLineEdit *parentLine= static_cast<khtml::RenderLineEdit *>(obj);
02814           s = parentLine->widget()->text();
02815           s = s.replace(0xa0, ' ');
02816         }
02817         else if ( obj->isText() )
02818         {
02819           bool isLink = false;
02820 
02821           // checks whether the node has a <A> parent
02822           if ( options & FindLinksOnly )
02823           {
02824             DOM::NodeImpl *parent = obj->element();
02825             while ( parent )
02826             {
02827               if ( parent->nodeType() == Node::ELEMENT_NODE && parent->id() == ID_A )
02828               {
02829                 isLink = true;
02830                 break;
02831               }
02832               parent = parent->parentNode();
02833             }
02834           }
02835           else
02836           {
02837             isLink = true;
02838           }
02839 
02840           if ( isLink && obj->parent()!=tmpTextArea )
02841           {
02842             s = static_cast<khtml::RenderText *>(obj)->data().string();
02843             s = s.replace(0xa0, ' ');
02844           }
02845         }
02846         else if ( obj->isBR() )
02847           s = '\n';
02848         else if ( !obj->isInline() && !str.isEmpty() )
02849           s = '\n';
02850 
02851         if ( lastNode == d->m_findNodeEnd )
02852           s.truncate( d->m_findPosEnd );
02853         if ( !s.isEmpty() )
02854         {
02855           newLinePos = s.find( '\n' ); // did we just get a newline?
02856           int index = str.length();
02857           if ( newLinePos != -1 )
02858             newLinePos += index;
02859           str += s;
02860           //kdDebug(6050) << "StringPortion: " << index << "-" << index+s.length()-1 << " -> " << lastNode << endl;
02861           d->m_stringPortions.append( KHTMLPartPrivate::StringPortion( index, lastNode ) );
02862         }
02863         // Compare obj and end _after_ we processed the 'end' node itself
02864         if ( obj == end )
02865           obj = 0L;
02866         else
02867         {
02868           // Move on to next object (note: if we found a \n already, then obj (and lastNode)
02869           // will point to the _next_ object, i.e. they are in advance.
02870           do {
02871             // We advance until the next RenderObject that has a NodeImpl as its element().
02872             // Otherwise (if we keep the 'last node', and it has a '\n') we might be stuck
02873             // on that object forever...
02874             obj = (options & KFindDialog::FindBackwards) ? obj->objectAbove() : obj->objectBelow();
02875           } while ( obj && !obj->element() );
02876         }
02877         if ( obj )
02878           lastNode = obj->element();
02879         else
02880           lastNode = 0;
02881       } // end while
02882       //kdDebug()<<" str : "<<str<<endl;
02883       if ( !str.isEmpty() )
02884       {
02885         d->m_find->setData( str, d->m_findPos );
02886       }
02887 
02888       d->m_findPos = -1; // not used during the findnext loops. Only during init.
02889       d->m_findNode = lastNode;
02890     }
02891     if ( !d->m_find->needData() ) // happens if str was empty
02892     {
02893       // Let KFind inspect the text fragment, and emit highlighted if a match is found
02894       res = d->m_find->find();
02895     }
02896   } // end while
02897 
02898   if ( res == KFind::NoMatch ) // i.e. we're done
02899   {
02900     kdDebug() << "No more matches." << endl;
02901     if ( !(options & FindNoPopups) && d->m_find->shouldRestart() )
02902     {
02903       //kdDebug(6050) << "Restarting" << endl;
02904       initFindNode( false, options & KFindDialog::FindBackwards, false );
02905       findTextNext();
02906     }
02907     else // really done
02908     {
02909       //kdDebug(6050) << "Finishing" << endl;
02910       //delete d->m_find;
02911       //d->m_find = 0L;
02912       initFindNode( false, options & KFindDialog::FindBackwards, false );
02913       d->m_find->resetCounts();
02914       slotClearSelection();
02915     }
02916     kdDebug() << "Dialog closed." << endl;
02917   }
02918 
02919   return res == KFind::Match;
02920 }
02921 
02922 void KHTMLPart::slotHighlight( const QString& /*text*/, int index, int length )
02923 {
02924   //kdDebug(6050) << "slotHighlight index=" << index << " length=" << length << endl;
02925   QValueList<KHTMLPartPrivate::StringPortion>::Iterator it = d->m_stringPortions.begin();
02926   QValueList<KHTMLPartPrivate::StringPortion>::Iterator prev = it;
02927   // We stop at the first portion whose index is 'greater than', and then use the previous one
02928   while ( it != d->m_stringPortions.end() && (*it).index <= index )
02929   {
02930     prev = it;
02931     ++it;
02932   }
02933   Q_ASSERT ( prev != d->m_stringPortions.end() );
02934   DOM::NodeImpl* node = (*prev).node;
02935   Q_ASSERT( node );
02936 
02937   d->m_selectionStart = node;
02938   d->m_startOffset = index - (*prev).index;
02939 
02940   khtml::RenderObject* obj = node->renderer();
02941   khtml::RenderTextArea *parent = 0L;
02942   khtml::RenderLineEdit *parentLine = 0L;
02943   bool renderLineText =false;
02944 
02945   QRect highlightedRect;
02946   bool renderAreaText =false;
02947   Q_ASSERT( obj );
02948   if ( obj )
02949   {
02950     int x = 0, y = 0;
02951     renderAreaText = (QCString(obj->parent()->renderName())== "RenderTextArea");
02952     renderLineText = (QCString(obj->renderName())== "RenderLineEdit");
02953 
02954 
02955     if( renderAreaText )
02956       parent= static_cast<khtml::RenderTextArea *>(obj->parent());
02957     if ( renderLineText )
02958       parentLine= static_cast<khtml::RenderLineEdit *>(obj);
02959     if ( !renderLineText )
02960       //if (static_cast<khtml::RenderText *>(node->renderer())
02961       //    ->posOfChar(d->m_startOffset, x, y))
02962       {
02963         int dummy;
02964         static_cast<khtml::RenderText *>(node->renderer())
02965           ->caretPos( d->m_startOffset, false, x, y, dummy, dummy ); // more precise than posOfChar
02966         //kdDebug(6050) << "topleft: " << x << "," << y << endl;
02967         if ( x != -1 || y != -1 )
02968         {
02969           d->m_view->setContentsPos(x-50, y-50);
02970           highlightedRect.setTopLeft( d->m_view->mapToGlobal(QPoint(x, y)) );
02971         }
02972       }
02973   }
02974   // Now look for end node
02975   it = prev; // no need to start from beginning again
02976   while ( it != d->m_stringPortions.end() && (*it).index < index + length )
02977   {
02978     prev = it;
02979     ++it;
02980   }
02981   Q_ASSERT ( prev != d->m_stringPortions.end() );
02982 
02983   d->m_selectionEnd = (*prev).node;
02984   d->m_endOffset = index + length - (*prev).index;
02985   d->m_startBeforeEnd = true;
02986 
02987   // if the selection is limited to a single link, that link gets focus
02988   if(d->m_selectionStart == d->m_selectionEnd)
02989   {
02990     bool isLink = false;
02991 
02992     // checks whether the node has a <A> parent
02993     DOM::NodeImpl *parent = d->m_selectionStart.handle();
02994     while ( parent )
02995     {
02996       if ( parent->nodeType() == Node::ELEMENT_NODE && parent->id() == ID_A )
02997       {
02998         isLink = true;
02999         break;
03000       }
03001       parent = parent->parentNode();
03002     }
03003 
03004     if(isLink == true)
03005     {
03006       d->m_doc->setFocusNode( parent );
03007     }
03008   }
03009 
03010 #if 0
03011   kdDebug(6050) << "slotHighlight: " << d->m_selectionStart.handle() << "," << d->m_startOffset << " - " <<
03012     d->m_selectionEnd.handle() << "," << d->m_endOffset << endl;
03013   it = d->m_stringPortions.begin();
03014   for ( ; it != d->m_stringPortions.end() ; ++it )
03015     kdDebug(6050) << "  StringPortion: from index=" << (*it).index << " -> node=" << (*it).node << endl;
03016 #endif
03017   if( renderAreaText )
03018   {
03019     if( parent )
03020       parent->highLightWord( length, d->m_endOffset-length );
03021   }
03022   else if ( renderLineText )
03023   {
03024     if( parentLine )
03025       parentLine->highLightWord( length, d->m_endOffset-length );
03026   }
03027   else
03028   {
03029     d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
03030                             d->m_selectionEnd.handle(), d->m_endOffset );
03031     if (d->m_selectionEnd.handle()->renderer() )
03032     {
03033       int x, y, height, dummy;
03034       static_cast<khtml::RenderText *>(d->m_selectionEnd.handle()->renderer())
03035           ->caretPos( d->m_endOffset, false, x, y, dummy, height ); // more precise than posOfChar
03036       //kdDebug(6050) << "bottomright: " << x << "," << y+height << endl;
03037       if ( x != -1 || y != -1 )
03038       {
03039         // if ( static_cast<khtml::RenderText *>(d->m_selectionEnd.handle()->renderer())
03040         //  ->posOfChar(d->m_endOffset-1, x, y))
03041         highlightedRect.setBottomRight( d->m_view->mapToGlobal( QPoint(x, y+height) ) );
03042       }
03043     }
03044   }
03045   emitSelectionChanged();
03046 
03047   // make the finddialog move away from the selected area
03048   if ( d->m_findDialog && !highlightedRect.isNull() )
03049   {
03050     highlightedRect.moveBy( -d->m_view->contentsX(), -d->m_view->contentsY() );
03051     //kdDebug(6050) << "avoiding " << highlightedRect << endl;
03052     KDialog::avoidArea( d->m_findDialog, highlightedRect );
03053   }
03054 }
03055 
03056 QString KHTMLPart::selectedText() const
03057 {
03058   bool hasNewLine = true;
03059   QString text;
03060   DOM::Node n = d->m_selectionStart;
03061   while(!n.isNull()) {
03062       if(n.nodeType() == DOM::Node::TEXT_NODE && n.handle()->renderer()) {
03063         QString str = n.nodeValue().string();
03064         hasNewLine = false;
03065         if(n == d->m_selectionStart && n == d->m_selectionEnd)
03066           text = str.mid(d->m_startOffset, d->m_endOffset - d->m_startOffset);
03067         else if(n == d->m_selectionStart)
03068           text = str.mid(d->m_startOffset);
03069         else if(n == d->m_selectionEnd)
03070           text += str.left(d->m_endOffset);
03071         else
03072           text += str;
03073       }
03074       else {
03075         // This is our simple HTML -> ASCII transformation:
03076         unsigned short id = n.elementId();
03077         switch(id) {
03078           case ID_BR:
03079             text += "\n";
03080             hasNewLine = true;
03081             break;
03082 
03083           case ID_TD:
03084           case ID_TH:
03085           case ID_HR:
03086           case ID_OL:
03087           case ID_UL:
03088           case ID_LI:
03089           case ID_DD:
03090           case ID_DL:
03091           case ID_DT:
03092           case ID_PRE:
03093           case ID_BLOCKQUOTE:
03094           case ID_DIV:
03095             if (!hasNewLine)
03096                text += "\n";
03097             hasNewLine = true;
03098             break;
03099           case ID_P:
03100           case ID_TR:
03101           case ID_H1:
03102           case ID_H2:
03103           case ID_H3:
03104           case ID_H4:
03105           case ID_H5:
03106           case ID_H6:
03107             if (!hasNewLine)
03108                text += "\n";
03109             text += "\n";
03110             hasNewLine = true;
03111             break;
03112         }
03113       }
03114       if(n == d->m_selectionEnd) break;
03115       DOM::Node next = n.firstChild();
03116       if(next.isNull()) next = n.nextSibling();
03117       while( next.isNull() && !n.parentNode().isNull() ) {
03118         n = n.parentNode();
03119         next = n.nextSibling();
03120         unsigned short id = n.elementId();
03121         switch(id) {
03122           case ID_TD:
03123           case ID_TH:
03124           case ID_HR:
03125           case ID_OL:
03126           case ID_UL:
03127           case ID_LI:
03128           case ID_DD:
03129           case ID_DL:
03130           case ID_DT:
03131           case ID_PRE:
03132           case ID_BLOCKQUOTE:
03133           case ID_DIV:
03134             if (!hasNewLine)
03135                text += "\n";
03136             hasNewLine = true;
03137             break;
03138           case ID_P:
03139           case ID_TR:
03140           case ID_H1:
03141           case ID_H2:
03142           case ID_H3:
03143           case ID_H4:
03144           case ID_H5:
03145           case ID_H6:
03146             if (!hasNewLine)
03147                text += "\n";
03148             text += "\n";
03149             hasNewLine = true;
03150             break;
03151         }
03152       }
03153 
03154       n = next;
03155     }
03156 
03157     if(text.isEmpty())
03158         return QString::null;
03159 
03160     int start = 0;
03161     int end = text.length();
03162 
03163     // Strip leading LFs
03164     while ((start < end) && (text[start] == '\n'))
03165        start++;
03166 
03167     // Strip excessive trailing LFs
03168     while ((start < (end-1)) && (text[end-1] == '\n') && (text[end-2] == '\n'))
03169        end--;
03170 
03171     return text.mid(start, end-start);
03172 }
03173 
03174 bool KHTMLPart::hasSelection() const
03175 {
03176   if ( d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() )
03177       return false;
03178   if ( d->m_selectionStart == d->m_selectionEnd &&
03179        d->m_startOffset == d->m_endOffset )
03180       return false; // empty
03181   return true;
03182 }
03183 
03184 DOM::Range KHTMLPart::selection() const
03185 {
03186     DOM::Range r = document().createRange();DOM::Range();
03187     r.setStart( d->m_selectionStart, d->m_startOffset );
03188     r.setEnd( d->m_selectionEnd, d->m_endOffset );
03189     return r;
03190 }
03191 
03192 void KHTMLPart::selection(DOM::Node &s, long &so, DOM::Node &e, long &eo) const
03193 {
03194     s = d->m_selectionStart;
03195     so = d->m_startOffset;
03196     e = d->m_selectionEnd;
03197     eo = d->m_endOffset;
03198 }
03199 
03200 void KHTMLPart::setSelection( const DOM::Range &r )
03201 {
03202     d->m_selectionStart = r.startContainer();
03203     d->m_startOffset = r.startOffset();
03204     d->m_selectionEnd = r.endContainer();
03205     d->m_endOffset = r.endOffset();
03206     d->m_doc->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
03207                            d->m_selectionEnd.handle(),d->m_endOffset);
03208 #ifndef KHTML_NO_CARET
03209     bool v = d->m_view->placeCaret();
03210     emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
03211 #endif
03212 }
03213 
03214 void KHTMLPart::slotClearSelection()
03215 {
03216     bool hadSelection = hasSelection();
03217 #ifndef KHTML_NO_CARET
03218     //kdDebug(6000) << "d->m_selectionStart " << d->m_selectionStart.handle()
03219     //      << " d->m_selectionEnd " << d->m_selectionEnd.handle() << endl;
03220     // nothing, leave selection parameters as is
03221 #else
03222     d->m_selectionStart = 0;
03223     d->m_startOffset = 0;
03224     d->m_selectionEnd = 0;
03225     d->m_endOffset = 0;
03226 #endif
03227     if ( d->m_doc ) d->m_doc->clearSelection();
03228     if ( hadSelection )
03229       emitSelectionChanged();
03230 #ifndef KHTML_NO_CARET
03231     bool v = d->m_view->placeCaret();
03232     emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
03233 #endif
03234 }
03235 
03236 void KHTMLPart::overURL( const QString &url, const QString &target, bool /*shiftPressed*/ )
03237 {
03238   KURL u = completeURL(url);
03239 
03240   // special case for <a href="">
03241   if ( url.isEmpty() )
03242     u.setFileName( url );
03243 
03244   emit onURL( url );
03245 
03246   if ( url.isEmpty() ) {
03247     setStatusBarText(u.htmlURL(), BarHoverText);
03248     return;
03249   }
03250 
03251   if (url.find( QString::fromLatin1( "javascript:" ),0, false ) == 0 ) {
03252     QString jscode = KURL::decode_string( url.mid( url.find( "javascript:", 0, false ) ) );
03253     jscode = KStringHandler::rsqueeze( jscode, 80 ); // truncate if too long
03254     setStatusBarText( QStyleSheet::escape( jscode ), BarHoverText );
03255     return;
03256   }
03257 
03258   KFileItem item(u, QString::null, KFileItem::Unknown);
03259   emit d->m_extension->mouseOverInfo(&item);
03260 
03261   QString com;
03262 
03263   KMimeType::Ptr typ = KMimeType::findByURL( u );
03264 
03265   if ( typ )
03266     com = typ->comment( u, false );
03267 
03268   if ( !u.isValid() ) {
03269     setStatusBarText(u.htmlURL(), BarHoverText);
03270     return;
03271   }
03272 
03273   if ( u.isLocalFile() )
03274   {
03275     // TODO : use KIO::stat() and create a KFileItem out of its result,
03276     // to use KFileItem::statusBarText()
03277     QCString path = QFile::encodeName( u.path() );
03278 
03279     struct stat buff;
03280     bool ok = !stat( path.data(), &buff );
03281 
03282     struct stat lbuff;
03283     if (ok) ok = !lstat( path.data(), &lbuff );
03284 
03285     QString text = u.htmlURL();
03286     QString text2 = text;
03287 
03288     if (ok && S_ISLNK( lbuff.st_mode ) )
03289     {
03290       QString tmp;
03291       if ( com.isNull() )
03292         tmp = i18n( "Symbolic Link");
03293       else
03294         tmp = i18n("%1 (Link)").arg(com);
03295       char buff_two[1024];
03296       text += " -> ";
03297       int n = readlink ( path.data(), buff_two, 1022);
03298       if (n == -1)
03299       {
03300         text2 += "  ";
03301         text2 += tmp;
03302         setStatusBarText(text2, BarHoverText);
03303         return;
03304       }
03305       buff_two[n] = 0;
03306 
03307       text += buff_two;
03308       text += "  ";
03309       text += tmp;
03310     }
03311     else if ( ok && S_ISREG( buff.st_mode ) )
03312     {
03313       if (buff.st_size < 1024)
03314         text = i18n("%2 (%1 bytes)").arg((long) buff.st_size).arg(text2); // always put the URL last, in case it contains '%'
03315       else
03316       {
03317         float d = (float) buff.st_size/1024.0;
03318         text = i18n("%2 (%1 K)").arg(KGlobal::locale()->formatNumber(d, 2)).arg(text2); // was %.2f
03319       }
03320       text += "  ";
03321       text += com;
03322     }
03323     else if ( ok && S_ISDIR( buff.st_mode ) )
03324     {
03325       text += "  ";
03326       text += com;
03327     }
03328     else
03329     {
03330       text += "  ";
03331       text += com;
03332     }
03333     setStatusBarText(text, BarHoverText);
03334   }
03335   else
03336   {
03337     QString extra;
03338     if (target.lower() == "_blank")
03339     {
03340       extra = i18n(" (In new window)");
03341     }
03342     else if (!target.isEmpty() &&
03343              (target.lower() != "_top") &&
03344              (target.lower() != "_self") &&
03345              (target.lower() != "_parent"))
03346     {
03347       extra = i18n(" (In other frame)");
03348     }
03349 
03350     if (u.protocol() == QString::fromLatin1("mailto")) {
03351       QString mailtoMsg /* = QString::fromLatin1("<img src=%1>").arg(locate("icon", QString::fromLatin1("locolor/16x16/actions/mail_send.png")))*/;
03352       mailtoMsg += i18n("Email to: ") + KURL::decode_string(u.path());
03353       QStringList queries = QStringList::split('&', u.query().mid(1));
03354       for (QStringList::Iterator it = queries.begin(); it != queries.end(); ++it)
03355         if ((*it).startsWith(QString::fromLatin1("subject=")))
03356           mailtoMsg += i18n(" - Subject: ") + KURL::decode_string((*it).mid(8));
03357         else if ((*it).startsWith(QString::fromLatin1("cc=")))
03358           mailtoMsg += i18n(" - CC: ") + KURL::decode_string((*it).mid(3));
03359         else if ((*it).startsWith(QString::fromLatin1("bcc=")))
03360           mailtoMsg += i18n(" - BCC: ") + KURL::decode_string((*it).mid(4));
03361       mailtoMsg.replace(QString::fromLatin1("&"), QString("&amp;"));
03362       mailtoMsg.replace(QString::fromLatin1("<"), QString("&lt;"));
03363       mailtoMsg.replace(QString::fromLatin1(">"), QString("&gt;"));
03364       mailtoMsg.replace(QRegExp("([\n\r\t]|[ ]{10})"), QString::null);
03365       setStatusBarText("<qt>"+mailtoMsg, BarHoverText);
03366       return;
03367     }
03368    // Is this check necessary at all? (Frerich)
03369 #if 0
03370     else if (u.protocol() == QString::fromLatin1("http")) {
03371         DOM::Node hrefNode = nodeUnderMouse().parentNode();
03372         while (hrefNode.nodeName().string() != QString::fromLatin1("A") && !hrefNode.isNull())
03373           hrefNode = hrefNode.parentNode();
03374 
03375         if (!hrefNode.isNull()) {
03376           DOM::Node hreflangNode = hrefNode.attributes().getNamedItem("HREFLANG");
03377           if (!hreflangNode.isNull()) {
03378             QString countryCode = hreflangNode.nodeValue().string().lower();
03379             // Map the language code to an appropriate country code.
03380             if (countryCode == QString::fromLatin1("en"))
03381               countryCode = QString::fromLatin1("gb");
03382             QString flagImg = QString::fromLatin1("<img src=%1>").arg(
03383                 locate("locale", QString::fromLatin1("l10n/")
03384                 + countryCode
03385                 + QString::fromLatin1("/flag.png")));
03386             emit setStatusBarText(flagImg + u.prettyURL() + extra);
03387           }
03388         }
03389       }
03390 #endif
03391     setStatusBarText(u.htmlURL() + extra, BarHoverText);
03392   }
03393 }
03394 
03395 //
03396 // This executes in the active part on a click or other url selection action in
03397 // that active part.
03398 //
03399 void KHTMLPart::urlSelected( const QString &url, int button, int state, const QString &_target, KParts::URLArgs args )
03400 {
03401   kdDebug() << k_funcinfo << url << endl;
03402   bool hasTarget = false;
03403 
03404   QString target = _target;
03405   if ( target.isEmpty() && d->m_doc )
03406     target = d->m_doc->baseTarget();
03407   if ( !target.isEmpty() )
03408       hasTarget = true;
03409 
03410   if ( url.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
03411   {
03412     crossFrameExecuteScript( target, KURL::decode_string( url.mid( 11 ) ) );
03413     return;
03414   }
03415 
03416   KURL cURL = completeURL(url);
03417   // special case for <a href="">  (IE removes filename, mozilla doesn't)
03418   if ( url.isEmpty() )
03419     cURL.setFileName( url ); // removes filename
03420 
03421   if ( !cURL.isValid() )
03422     // ### ERROR HANDLING
03423     return;
03424 
03425   kdDebug( 6000 ) << "urlSelected: complete URL:" << cURL.url() << " target = " << target << endl;
03426 
03427   if ( state & ControlButton )
03428   {
03429     args.setNewTab(true);
03430     emit d->m_extension->createNewWindow( cURL, args );
03431     return;
03432   }
03433 
03434   if ( button == LeftButton && ( state & ShiftButton ) )
03435   {
03436     KIO::MetaData metaData;
03437     metaData["referrer"] = d->m_referrer;
03438     KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), cURL, metaData );
03439     return;
03440   }
03441 
03442   if (!checkLinkSecurity(cURL,
03443              i18n( "<qt>This untrusted page links to<BR><B>%1</B>.<BR>Do you want to follow the link?" ),
03444              i18n( "Follow" )))
03445     return;
03446 
03447   args.frameName = target;
03448 
03449   args.metaData().insert("main_frame_request",
03450                          parentPart() == 0 ? "TRUE":"FALSE");
03451   args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
03452   args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
03453   args.metaData().insert("PropagateHttpHeader", "true");
03454   args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
03455   args.metaData().insert("ssl_activate_warnings", "TRUE");
03456   // WABA: When we select the link explicitly we should treat this new URL as the
03457   // toplevel url and it should never be considered cross-domain.
03458   // However this function is also called for javascript and META-tag based
03459   // redirections:
03460   //   - In such case, we don't take cross-domain-ness in consideration if we are the
03461   //   toplevel frame because the new URL may be in a different domain as the current URL
03462   //   but that's ok.
03463   //   - If we are not the toplevel frame then we check against the toplevelURL()
03464   if (args.redirectedRequest() && parentPart())
03465       args.metaData().insert("cross-domain", toplevelURL().url());
03466 
03467   if ( hasTarget )
03468   {
03469     // unknown frame names should open in a new window.
03470     khtml::ChildFrame *frame = recursiveFrameRequest( this, cURL, args, false );
03471     if ( frame )
03472     {
03473       args.metaData()["referrer"] = d->m_referrer;
03474       requestObject( frame, cURL, args );
03475       return;
03476     }
03477   }
03478 
03479   if ( !d->m_bComplete && !hasTarget )
03480     closeURL();
03481 
03482   if (!d->m_referrer.isEmpty() && !args.metaData().contains("referrer"))
03483     args.metaData()["referrer"] = d->m_referrer;
03484 
03485   if ( button == NoButton && (state & ShiftButton) && (state & ControlButton) )
03486   {
03487     emit d->m_extension->createNewWindow( cURL, args );
03488     return;
03489   }
03490 
03491   if ( state & ShiftButton)
03492   {
03493     KParts::WindowArgs winArgs;
03494     winArgs.lowerWindow = true;
03495     KParts::ReadOnlyPart *newPart = 0;
03496     emit d->m_extension->createNewWindow( cURL, args, winArgs, newPart );
03497     return;
03498   }
03499 
03500   view()->viewport()->unsetCursor();
03501   emit d->m_extension->openURLRequest( cURL, args );
03502 }
03503 
03504 void KHTMLPart::slotViewDocumentSource()
03505 {
03506   KURL url(m_url);
03507   bool isTempFile = false;
03508   if (!(url.isLocalFile()) && KHTMLPageCache::self()->isComplete(d->m_cacheId))
03509   {
03510      KTempFile sourceFile(QString::null, QString::fromLatin1(".html"));
03511      if (sourceFile.status() == 0)
03512      {
03513         KHTMLPageCache::self()->saveData(d->m_cacheId, sourceFile.dataStream());
03514         url = KURL();
03515         url.setPath(sourceFile.name());
03516         isTempFile = true;
03517      }
03518   }
03519 
03520   (void) KRun::runURL( url, QString::fromLatin1("text/plain"), isTempFile );
03521 }
03522 
03523 void KHTMLPart::slotViewPageInfo()
03524 {
03525   KHTMLInfoDlg *dlg = new KHTMLInfoDlg(NULL, "KHTML Page Info Dialog", false, WDestructiveClose);
03526   dlg->_close->setGuiItem(KStdGuiItem::close());
03527   
03528   if (d->m_doc)
03529      dlg->_title->setText(d->m_doc->title().string());
03530 
03531   // If it's a frame, set the caption to "Frame Information"
03532   if ( parentPart() && d->m_doc && d->m_doc->isHTMLDocument() ) {
03533      dlg->setCaption(i18n("Frame Information"));
03534   }
03535 
03536   QString editStr = QString::null;
03537 
03538   if (!d->m_pageServices.isEmpty())
03539     editStr = i18n("   <a href=\"%1\">[Properties]</a>").arg(d->m_pageServices);
03540 
03541   QString squeezedURL = KStringHandler::csqueeze( url().prettyURL(), 80 );
03542   dlg->_url->setText("<a href=\"" + url().url() + "\">" + squeezedURL + "</a>" + editStr);
03543   if (lastModified().isEmpty())
03544   {
03545     dlg->_lastModified->hide();
03546     dlg->_lmLabel->hide();
03547   }
03548   else
03549     dlg->_lastModified->setText(lastModified());
03550 
03551   /* populate the list view now */
03552   QStringList headers = QStringList::split("\n", d->m_httpHeaders);
03553 
03554   for (QStringList::Iterator it = headers.begin(); it != headers.end(); ++it) {
03555     QStringList header = QStringList::split(QRegExp(":[ ]+"), *it);
03556     if (header.count() != 2)
03557        continue;
03558     new QListViewItem(dlg->_headers, header[0], header[1]);
03559   }
03560 
03561   dlg->show();
03562   /* put no code here */
03563 }
03564 
03565 
03566 void KHTMLPart::slotViewFrameSource()
03567 {
03568   KParts::ReadOnlyPart *frame = currentFrame();
03569   if ( !frame )
03570     return;
03571 
03572   KURL url = frame->url();
03573   bool isTempFile = false;
03574   if (!(url.isLocalFile()) && frame->inherits("KHTMLPart"))
03575   {
03576        long cacheId = static_cast<KHTMLPart *>(frame)->d->m_cacheId;
03577 
03578        if (KHTMLPageCache::self()->isComplete(cacheId))
03579        {
03580            KTempFile sourceFile(QString::null, QString::fromLatin1(".html"));
03581            if (sourceFile.status() == 0)
03582            {
03583                KHTMLPageCache::self()->saveData(cacheId, sourceFile.dataStream());
03584                url = KURL();
03585                url.setPath(sourceFile.name());
03586                isTempFile = true;
03587            }
03588      }
03589   }
03590 
03591   (void) KRun::runURL( url, QString::fromLatin1("text/plain"), isTempFile );
03592 }
03593 
03594 KURL KHTMLPart::backgroundURL() const
03595 {
03596   // ### what about XML documents? get from CSS?
03597   if (!d->m_doc || !d->m_doc->isHTMLDocument())
03598     return KURL();
03599 
03600   QString relURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
03601 
03602   return KURL( m_url, relURL );
03603 }
03604 
03605 void KHTMLPart::slotSaveBackground()
03606 {
03607   KIO::MetaData metaData;
03608   metaData["referrer"] = d->m_referrer;
03609   KHTMLPopupGUIClient::saveURL( d->m_view, i18n("Save Background Image As"), backgroundURL(), metaData );
03610 }
03611 
03612 void KHTMLPart::slotSaveDocument()
03613 {
03614   KURL srcURL( m_url );
03615 
03616   if ( srcURL.fileName(false).isEmpty() )
03617     srcURL.setFileName( "index.html" );
03618 
03619   KIO::MetaData metaData;
03620   // Referre unknown?
03621   KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), srcURL, metaData, "text/html", d->m_cacheId );
03622 }
03623 
03624 void KHTMLPart::slotSecurity()
03625 {
03626 //   kdDebug( 6050 ) << "Meta Data:" << endl
03627 //                   << d->m_ssl_peer_cert_subject
03628 //                   << endl
03629 //                   << d->m_ssl_peer_cert_issuer
03630 //                   << endl
03631 //                   << d->m_ssl_cipher
03632 //                   << endl
03633 //                   << d->m_ssl_cipher_desc
03634 //                   << endl
03635 //                   << d->m_ssl_cipher_version
03636 //                   << endl
03637 //                   << d->m_ssl_good_from
03638 //                   << endl
03639 //                   << d->m_ssl_good_until
03640 //                   << endl
03641 //                   << d->m_ssl_cert_state
03642 //                   << endl;
03643 
03644   KSSLInfoDlg *kid = new KSSLInfoDlg(d->m_ssl_in_use, widget(), "kssl_info_dlg", true );
03645 
03646   if (d->m_bSecurityInQuestion)
03647       kid->setSecurityInQuestion(true);
03648 
03649   if (d->m_ssl_in_use) {
03650     KSSLCertificate *x = KSSLCertificate::fromString(d->m_ssl_peer_certificate.local8Bit());
03651     if (x) {
03652        // Set the chain back onto the certificate
03653        QStringList cl = QStringList::split(QString("\n"), d->m_ssl_peer_chain);
03654        QPtrList<KSSLCertificate> ncl;
03655 
03656        ncl.setAutoDelete(true);
03657        for (QStringList::Iterator it = cl.begin(); it != cl.end(); ++it) {
03658           KSSLCertificate *y = KSSLCertificate::fromString((*it).local8Bit());
03659           if (y) ncl.append(y);
03660        }
03661 
03662        if (ncl.count() > 0)
03663           x->chain().setChain(ncl);
03664 
03665        kid->setup(x,
03666                   d->m_ssl_peer_ip,
03667                   m_url.url(),
03668                   d->m_ssl_cipher,
03669                   d->m_ssl_cipher_desc,
03670                   d->m_ssl_cipher_version,
03671                   d->m_ssl_cipher_used_bits.toInt(),
03672                   d->m_ssl_cipher_bits.toInt(),
03673                   (KSSLCertificate::KSSLValidation) d->m_ssl_cert_state.toInt()
03674                   );
03675         kid->exec();
03676         delete x;
03677      } else kid->exec();
03678   } else kid->exec();
03679 }
03680 
03681 void KHTMLPart::slotSaveFrame()
03682 {
03683     if ( !d->m_activeFrame )
03684         return; // should never be the case, but one never knows :-)
03685 
03686     KURL srcURL( static_cast<KParts::ReadOnlyPart *>( d->m_activeFrame )->url() );
03687 
03688     if ( srcURL.fileName(false).isEmpty() )
03689         srcURL.setFileName( "index.html" );
03690 
03691     KIO::MetaData metaData;
03692     // Referrer unknown?
03693     KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), srcURL, metaData, "text/html" );
03694 }
03695 
03696 void KHTMLPart::slotSetEncoding()
03697 {
03698   d->m_automaticDetection->setItemChecked( int( d->m_autoDetectLanguage ), false );
03699   d->m_paSetEncoding->popupMenu()->setItemChecked( 0, false );
03700   d->m_paSetEncoding->popupMenu()->setItemChecked( d->m_paSetEncoding->popupMenu()->idAt( 2 ), true );
03701 
03702   QString enc = KGlobal::charsets()->encodingForName( d->m_manualDetection->currentText() );
03703   setEncoding( enc, true );
03704 }
03705 
03706 void KHTMLPart::slotUseStylesheet()
03707 {
03708   if (d->m_doc)
03709   {
03710     bool autoselect = (d->m_paUseStylesheet->currentItem() == 0);
03711     d->m_sheetUsed = autoselect ? QString() : d->m_paUseStylesheet->currentText();
03712     d->m_doc->updateStyleSelector();
03713   }
03714 }
03715 
03716 void KHTMLPart::updateActions()
03717 {
03718   bool frames = false;
03719 
03720   QValueList<khtml::ChildFrame>::ConstIterator it = d->m_frames.begin();
03721   QValueList<khtml::ChildFrame>::ConstIterator end = d->m_frames.end();
03722   for (; it != end; ++it )
03723       if ( (*it).m_type == khtml::ChildFrame::Frame )
03724       {
03725           frames = true;
03726           break;
03727       }
03728 
03729   d->m_paViewFrame->setEnabled( frames );
03730   d->m_paSaveFrame->setEnabled( frames );
03731 
03732   if ( frames )
03733     d->m_paFind->setText( i18n( "&Find in Frame..." ) );
03734   else
03735     d->m_paFind->setText( i18n( "&Find..." ) );
03736 
03737   KParts::Part *frame = 0;
03738 
03739   if ( frames )
03740     frame = currentFrame();
03741 
03742   bool enableFindAndSelectAll = true;
03743 
03744   if ( frame )
03745     enableFindAndSelectAll = frame->inherits( "KHTMLPart" );
03746 
03747   d->m_paFind->setEnabled( enableFindAndSelectAll );
03748   d->m_paSelectAll->setEnabled( enableFindAndSelectAll );
03749 
03750   bool enablePrintFrame = false;
03751 
03752   if ( frame )
03753   {
03754     QObject *ext = KParts::BrowserExtension::childObject( frame );
03755     if ( ext )
03756       enablePrintFrame = ext->metaObject()->slotNames().contains( "print()" );
03757   }
03758 
03759   d->m_paPrintFrame->setEnabled( enablePrintFrame );
03760 
03761   QString bgURL;
03762 
03763   // ### frames
03764   if ( d->m_doc && d->m_doc->isHTMLDocument() && static_cast<HTMLDocumentImpl*>(d->m_doc)->body() && !d->m_bClearing )
03765     bgURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
03766 
03767   d->m_paSaveBackground->setEnabled( !bgURL.isEmpty() );
03768 
03769   if ( d->m_paDebugScript )
03770     d->m_paDebugScript->setEnabled( d->m_jscript );
03771 }
03772 
03773 KParts::LiveConnectExtension *KHTMLPart::liveConnectExtension( const khtml::RenderPart *frame) const {
03774     QValueList<khtml::ChildFrame>::ConstIterator it = d->m_objects.begin();
03775     QValueList<khtml::ChildFrame>::ConstIterator end = d->m_objects.end();
03776     for(; it != end; ++it )
03777         if ((*it).m_frame == frame)
03778             return (*it).m_liveconnect;
03779     return 0L;
03780 }
03781 
03782 bool KHTMLPart::requestFrame( khtml::RenderPart *frame, const QString &url, const QString &frameName,
03783                               const QStringList &params, bool isIFrame )
03784 {
03785   //kdDebug( 6050 ) << this << " requestFrame( ..., " << url << ", " << frameName << " )" << endl;
03786   FrameIt it = d->m_frames.find( frameName );
03787   if ( it == d->m_frames.end() )
03788   {
03789     khtml::ChildFrame child;
03790     //kdDebug( 6050 ) << "inserting new frame into frame map " << frameName << endl;
03791     child.m_name = frameName;
03792     it = d->m_frames.append( child );
03793   }
03794 
03795   (*it).m_type = isIFrame ? khtml::ChildFrame::IFrame : khtml::ChildFrame::Frame;
03796   (*it).m_frame = frame;
03797   (*it).m_params = params;
03798 
03799   // Support for <frame src="javascript:string">
03800   if ( url.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
03801   {
03802       QVariant res = executeScript( DOM::Node(frame->element()), KURL::decode_string( url.right( url.length() - 11) ) );
03803       KURL myurl;
03804       myurl.setProtocol("javascript");
03805       if ( res.type() == QVariant::String )
03806     myurl.setPath(res.asString());
03807       return processObjectRequest(&(*it), myurl, QString("text/html") );
03808   }
03809   KURL u = url.isEmpty() ? KURL() : completeURL( url );
03810   return requestObject( &(*it), u );
03811 }
03812 
03813 QString KHTMLPart::requestFrameName()
03814 {
03815    return QString::fromLatin1("<!--frame %1-->").arg(d->m_frameNameId++);
03816 }
03817 
03818 bool KHTMLPart::requestObject( khtml::RenderPart *frame, const QString &url, const QString &serviceType,
03819                                const QStringList &params )
03820 {
03821     kdDebug( 6005 ) << "KHTMLPart::requestObject " << this << " frame=" << frame << endl;
03822   khtml::ChildFrame child;
03823   QValueList<khtml::ChildFrame>::Iterator it = d->m_objects.append( child );
03824   (*it).m_frame = frame;
03825   (*it).m_type = khtml::ChildFrame::Object;
03826   (*it).m_params = params;
03827 
03828   KParts::URLArgs args;
03829   args.serviceType = serviceType;
03830   if (!requestObject( &(*it), completeURL( url ), args ) && !(*it).m_run) {
03831       (*it).m_bCompleted = true;
03832       return false;
03833   }
03834   return true;
03835 }
03836 
03837 bool KHTMLPart::requestObject( khtml::ChildFrame *child, const KURL &url, const KParts::URLArgs &_args )
03838 {
03839   if (!checkLinkSecurity(url))
03840   {
03841     kdDebug(6005) << this << " KHTMLPart::requestObject checkLinkSecurity refused" << endl;
03842     return false;
03843   }
03844   if ( child->m_bPreloaded )
03845   {
03846     kdDebug(6005) << "KHTMLPart::requestObject preload" << endl;
03847     if ( child->m_frame && child->m_part )
03848       child->m_frame->setWidget( child->m_part->widget() );
03849 
03850     child->m_bPreloaded = false;
03851     return true;
03852   }
03853 
03854   KParts::URLArgs args( _args );
03855 
03856   if ( child->m_run )
03857     child->m_run->abort();
03858 
03859   if ( child->m_part && !args.reload && urlcmp( child->m_part->url().url(), url.url(), true, true ) )
03860     args.serviceType = child->m_serviceType;
03861 
03862   child->m_args = args;
03863   child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload);
03864   child->m_serviceName = QString::null;
03865   if (!d->m_referrer.isEmpty() && !child->m_args.metaData().contains( "referrer" ))
03866     child->m_args.metaData()["referrer"] = d->m_referrer;
03867 
03868   child->m_args.metaData().insert("PropagateHttpHeader", "true");
03869   child->m_args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
03870   child->m_args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
03871   child->m_args.metaData().insert("main_frame_request",
03872                                   parentPart() == 0 ? "TRUE":"FALSE");
03873   child->m_args.metaData().insert("ssl_was_in_use",
03874                                   d->m_ssl_in_use ? "TRUE":"FALSE");
03875   child->m_args.metaData().insert("ssl_activate_warnings", "TRUE");
03876   child->m_args.metaData().insert("cross-domain", toplevelURL().url());
03877 
03878   // We want a KHTMLPart if the HTML says <frame src=""> or <frame src="about:blank">
03879   if ((url.isEmpty() || url.url() == "about:blank") && args.serviceType.isEmpty())
03880     args.serviceType = QString::fromLatin1( "text/html" );
03881 
03882   if ( args.serviceType.isEmpty() ) {
03883     kdDebug(6050) << "Running new KHTMLRun for " << this << " and child=" << child << endl;
03884     child->m_run = new KHTMLRun( this, child, url, child->m_args, true );
03885     d->m_bComplete = false; // ensures we stop it in checkCompleted...
03886     return false;
03887   } else {
03888     return processObjectRequest( child, url, args.serviceType );
03889   }
03890 }
03891 
03892 bool KHTMLPart::processObjectRequest( khtml::ChildFrame *child, const KURL &_url, const QString &mimetype )
03893 {
03894   //kdDebug( 6050 ) << "KHTMLPart::processObjectRequest trying to create part for " << mimetype << endl;
03895 
03896   // IMPORTANT: create a copy of the url here, because it is just a reference, which was likely to be given
03897   // by an emitting frame part (emit openURLRequest( blahurl, ... ) . A few lines below we delete the part
03898   // though -> the reference becomes invalid -> crash is likely
03899   KURL url( _url );
03900 
03901   // khtmlrun called us this way to indicate a loading error
03902   if ( d->m_onlyLocalReferences || ( url.isEmpty() && mimetype.isEmpty() ) )
03903   {
03904       child->m_bCompleted = true;
03905       checkCompleted();
03906       return true;
03907   }
03908 
03909   if (child->m_bNotify)
03910   {
03911       child->m_bNotify = false;
03912       if ( !child->m_args.lockHistory() )
03913           emit d->m_extension->openURLNotify();
03914   }
03915 
03916   if ( child->m_serviceType != mimetype )
03917   {
03918     // Before attempting to load a part, check if the user wants that.
03919     // Many don't like getting ZIP files embedded.
03920     // However we don't want to ask for flash and other plugin things..
03921     if ( child->m_type != khtml::ChildFrame::Object )
03922     {
03923       QString suggestedFilename;
03924       if ( child->m_run )
03925         suggestedFilename = child->m_run->suggestedFilename();
03926 
03927       KParts::BrowserRun::AskSaveResult res = KParts::BrowserRun::askEmbedOrSave(
03928         url, mimetype, suggestedFilename  );
03929       switch( res ) {
03930       case KParts::BrowserRun::Save:
03931         KHTMLPopupGUIClient::saveURL( widget(), i18n( "Save As" ), url, child->m_args.metaData(), QString::null, 0, suggestedFilename);
03932         // fall-through
03933       case KParts::BrowserRun::Cancel:
03934         child->m_bCompleted = true;
03935         checkCompleted();
03936         return true; // done
03937       default: // Open
03938         break;
03939       }
03940     }
03941 
03942     QStringList dummy; // the list of servicetypes handled by the part is now unused.
03943     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 );
03944 
03945     if ( !part )
03946     {
03947         if ( child->m_frame )
03948           if (child->m_frame->partLoadingErrorNotify( child, url, mimetype ))
03949             return true; // we succeeded after all (a fallback was used)
03950 
03951         checkEmitLoadEvent();
03952         return false;
03953     } else if (child->m_frame) {
03954         child->m_liveconnect = KParts::LiveConnectExtension::childObject(part);
03955         DOM::NodeImpl* elm = child->m_frame->element();
03956         if (elm)
03957             switch (child->m_frame->element()->id()) {
03958                 case ID_APPLET:
03959                 case ID_EMBED:
03960                 case ID_OBJECT:
03961                     static_cast<HTMLObjectBaseElementImpl*>(elm)->setLiveConnect(child->m_liveconnect);
03962                 default:
03963                     break;
03964             }
03965     }
03966 
03967     //CRITICAL STUFF
03968     if ( child->m_part )
03969     {
03970       partManager()->removePart( (KParts::ReadOnlyPart *)child->m_part );
03971       delete (KParts::ReadOnlyPart *)child->m_part;
03972     }
03973 
03974     child->m_serviceType = mimetype;
03975     if ( child->m_frame )
03976       child->m_frame->setWidget( part->widget() );
03977 
03978     if ( child->m_type != khtml::ChildFrame::Object )
03979       partManager()->addPart( part, false );
03980 //  else
03981 //      kdDebug(6005) << "AH! NO FRAME!!!!!" << endl;
03982 
03983     child->m_part = part;
03984     assert( ((void*) child->m_part) != 0);
03985 
03986     connect( part, SIGNAL( started( KIO::Job *) ),
03987              this, SLOT( slotChildStarted( KIO::Job *) ) );
03988     connect( part, SIGNAL( completed() ),
03989              this, SLOT( slotChildCompleted() ) );
03990     if ( child->m_type != khtml::ChildFrame::Object )
03991     {
03992       connect( part, SIGNAL( completed(bool) ),
03993                this, SLOT( slotChildCompleted(bool) ) );
03994       connect( part, SIGNAL( setStatusBarText( const QString & ) ),
03995                this, SIGNAL( setStatusBarText( const QString & ) ) );
03996       if ( part->inherits( "KHTMLPart" ) )
03997       {
03998           connect( this, SIGNAL( completed() ),
03999                    part, SLOT( slotParentCompleted() ) );
04000           connect( this, SIGNAL( completed(bool) ),
04001                    part, SLOT( slotParentCompleted() ) );
04002           // As soon as the child's document is created, we need to set its domain
04003           // (but we do so only once, so it can't be simply done in the child)
04004           connect( part, SIGNAL( docCreated() ),
04005                    this, SLOT( slotChildDocCreated() ) );
04006       }
04007     }
04008 
04009     child->m_extension = KParts::BrowserExtension::childObject( part );
04010 
04011     if ( child->m_extension )
04012     {
04013       connect( child->m_extension, SIGNAL( openURLNotify() ),
04014                d->m_extension, SIGNAL( openURLNotify() ) );
04015 
04016       connect( child->m_extension, SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ),
04017                this, SLOT( slotChildURLRequest( const KURL &, const KParts::URLArgs & ) ) );
04018 
04019       connect( child->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ),
04020                d->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ) );
04021       connect( child->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs &, const KParts::WindowArgs &, KParts::ReadOnlyPart *& ) ),
04022                d->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & , const KParts::WindowArgs &, KParts::ReadOnlyPart *&) ) );
04023 
04024       connect( child->m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ),
04025                d->m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ) );
04026       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ),
04027                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ) );
04028       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ),
04029                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ) );
04030       connect( child->m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ),
04031                d->m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ) );
04032       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ),
04033                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ) );
04034       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ),
04035                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ) );
04036 
04037       connect( child->m_extension, SIGNAL( infoMessage( const QString & ) ),
04038                d->m_extension, SIGNAL( infoMessage( const QString & ) ) );
04039 
04040       child->m_extension->setBrowserInterface( d->m_extension->browserInterface() );
04041     }
04042   }
04043   else if ( child->m_frame && child->m_part &&
04044             child->m_frame->widget() != child->m_part->widget() )
04045     child->m_frame->setWidget( child->m_part->widget() );
04046 
04047   checkEmitLoadEvent();
04048   // Some JS code in the load event may have destroyed the part
04049   // In that case, abort
04050   if ( !child->m_part )
04051     return false;
04052 
04053   if ( child->m_bPreloaded )
04054   {
04055     if ( child->m_frame && child->m_part )
04056       child->m_frame->setWidget( child->m_part->widget() );
04057 
04058     child->m_bPreloaded = false;
04059     return true;
04060   }
04061 
04062   child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload);
04063 
04064   // make sure the part has a way to find out about the mimetype.
04065   // we actually set it in child->m_args in requestObject already,
04066   // but it's useless if we had to use a KHTMLRun instance, as the
04067   // point the run object is to find out exactly the mimetype.
04068   child->m_args.serviceType = mimetype;
04069 
04070   // if not a frame set child as completed
04071   child->m_bCompleted = child->m_type == khtml::ChildFrame::Object;
04072 
04073   if ( child->m_extension )
04074     child->m_extension->setURLArgs( child->m_args );
04075 
04076   if(url.protocol() == "javascript" || url.url() == "about:blank") {
04077       if (!child->m_part->inherits("KHTMLPart"))
04078           return false;
04079 
04080       KHTMLPart* p = static_cast<KHTMLPart*>(static_cast<KParts::ReadOnlyPart *>(child->m_part));
04081 
04082       p->begin();
04083       if (d->m_doc && p->d->m_doc)
04084         p->d->m_doc->setBaseURL(d->m_doc->baseURL());
04085       if (!url.url().startsWith("about:")) {
04086         p->write(url.path());
04087       } else {
04088     p->m_url = url;
04089         // we need a body element. testcase: <iframe id="a"></iframe><script>alert(a.document.body);</script>
04090         p->write("<HTML><TITLE></TITLE><BODY></BODY></HTML>");
04091       }
04092       p->end();
04093       return true;
04094   }
04095   else if ( !url.isEmpty() )
04096   {
04097       //kdDebug( 6050 ) << "opening " << url.url() << " in frame " << child->m_part << endl;
04098       bool b = child->m_part->openURL( url );
04099       if (child->m_bCompleted)
04100           checkCompleted();
04101       return b;
04102   }
04103   else
04104   {
04105       child->m_bCompleted = true;
04106       checkCompleted();
04107       return true;
04108   }
04109 }
04110 
04111 KParts::ReadOnlyPart *KHTMLPart::createPart( QWidget *parentWidget, const char *widgetName,
04112                                              QObject *parent, const char *name, const QString &mimetype,
04113                                              QString &serviceName, QStringList &serviceTypes,
04114                                              const QStringList &params )
04115 {
04116   QString constr;
04117   if ( !serviceName.isEmpty() )
04118     constr.append( QString::fromLatin1( "Name == '%1'" ).arg( serviceName ) );
04119 
04120   KTrader::OfferList offers = KTrader::self()->query( mimetype, "KParts/ReadOnlyPart", constr, QString::null );
04121 
04122   if ( offers.isEmpty() )
04123     return 0L;
04124 
04125   KTrader::OfferList::Iterator it = offers.begin();
04126   for (  ; it != offers.end() ; ++it )
04127   {
04128     KService::Ptr service = (*it);
04129 
04130     KLibFactory *factory = KLibLoader::self()->factory( QFile::encodeName(service->library()) );
04131     if ( factory ) {
04132       KParts::ReadOnlyPart *res = 0L;
04133 
04134       const char *className = "KParts::ReadOnlyPart";
04135       if ( service->serviceTypes().contains( "Browser/View" ) )
04136         className = "Browser/View";
04137 
04138       if ( factory->inherits( "KParts::Factory" ) )
04139         res = static_cast<KParts::ReadOnlyPart *>(static_cast<KParts::Factory *>( factory )->createPart( parentWidget, widgetName, parent, name, className, params ));
04140       else
04141         res = static_cast<KParts::ReadOnlyPart *>(factory->create( parentWidget, widgetName, className ));
04142 
04143       if ( res ) {
04144         serviceTypes = service->serviceTypes();
04145         serviceName = service->name();
04146         return res;
04147       }
04148     } else {
04149       // TODO KMessageBox::error and i18n, like in KonqFactory::createView?
04150       kdWarning() << QString("There was an error loading the module %1.\nThe diagnostics is:\n%2")
04151                       .arg(service->name()).arg(KLibLoader::self()->lastErrorMessage()) << endl;
04152     }
04153   }
04154   return 0;
04155 }
04156 
04157 KParts::PartManager *KHTMLPart::partManager()
04158 {
04159   if ( !d->m_manager )
04160   {
04161     d->m_manager = new KParts::PartManager( d->m_view->topLevelWidget(), this, "khtml part manager" );
04162     d->m_manager->setAllowNestedParts( true );
04163     connect( d->m_manager, SIGNAL( activePartChanged( KParts::Part * ) ),
04164              this, SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
04165     connect( d->m_manager, SIGNAL( partRemoved( KParts::Part * ) ),
04166              this, SLOT( slotPartRemoved( KParts::Part * ) ) );
04167   }
04168 
04169   return d->m_manager;
04170 }
04171 
04172 void KHTMLPart::submitFormAgain()
04173 {
04174   if( d->m_doc && !d->m_doc->parsing() && d->m_submitForm)
04175     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 );
04176 
04177   delete d->m_submitForm;
04178   d->m_submitForm = 0;
04179   disconnect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
04180 }
04181 
04182 void KHTMLPart::submitFormProxy( const char *action, const QString &url, const QByteArray &formData, const QString &_target, const QString& contentType, const QString& boundary )
04183 {
04184   submitForm(action, url, formData, _target, contentType, boundary);
04185 }
04186 
04187 void KHTMLPart::submitForm( const char *action, const QString &url, const QByteArray &formData, const QString &_target, const QString& contentType, const QString& boundary )
04188 {
04189   kdDebug(6000) << this << ": KHTMLPart::submitForm target=" << _target << " url=" << url << endl;
04190   if (d->m_formNotification == KHTMLPart::Only) {
04191     emit formSubmitNotification(action, url, formData, _target, contentType, boundary);
04192     return;
04193   } else if (d->m_formNotification == KHTMLPart::Before) {
04194     emit formSubmitNotification(action, url, formData, _target, contentType, boundary);
04195   }
04196 
04197   KURL u = completeURL( url );
04198 
04199   if ( !u.isValid() )
04200   {
04201     // ### ERROR HANDLING!
04202     return;
04203   }
04204 
04205   // Form security checks
04206   //
04207   /*
04208    * If these form security checks are still in this place in a month or two
04209    * I'm going to simply delete them.
04210    */
04211 
04212   /* This is separate for a reason.  It has to be _before_ all script, etc,
04213    * AND I don't want to break anything that uses checkLinkSecurity() in
04214    * other places.
04215    */
04216 
04217   if (!d->m_submitForm) {
04218     if (u.protocol() != "https" && u.protocol() != "mailto") {
04219       if (d->m_ssl_in_use) {    // Going from SSL -> nonSSL
04220         int rc = KMessageBox::warningContinueCancel(NULL, i18n("Warning:  This is a secure form but it is attempting to send your data back unencrypted."
04221                                                                "\nA third party may be able to intercept and view this information."
04222                                                                "\nAre you sure you wish to continue?"),
04223                                                     i18n("Network Transmission"),KGuiItem(i18n("&Send Unencrypted")));
04224         if (rc == KMessageBox::Cancel)
04225           return;
04226       } else {                  // Going from nonSSL -> nonSSL
04227         KSSLSettings kss(true);
04228         if (kss.warnOnUnencrypted()) {
04229           int rc = KMessageBox::warningContinueCancel(NULL,
04230                                                       i18n("Warning: Your data is about to be transmitted across the network unencrypted."
04231                                                            "\nAre you sure you wish to continue?"),
04232                                                       i18n("Network Transmission"),
04233                                                       KGuiItem(i18n("&Send Unencrypted")),
04234                                                       "WarnOnUnencryptedForm");
04235           // Move this setting into KSSL instead
04236           KConfig *config = kapp->config();
04237           QString grpNotifMsgs = QString::fromLatin1("Notification Messages");
04238           KConfigGroupSaver saver( config, grpNotifMsgs );
04239 
04240           if (!config->readBoolEntry("WarnOnUnencryptedForm", true)) {
04241             config->deleteEntry("WarnOnUnencryptedForm");
04242             config->sync();
04243             kss.setWarnOnUnencrypted(false);
04244             kss.save();
04245           }
04246           if (rc == KMessageBox::Cancel)
04247             return;
04248         }
04249       }
04250     }
04251 
04252     if (u.protocol() == "mailto") {
04253       int rc = KMessageBox::warningContinueCancel(NULL,
04254                                                   i18n("This site is attempting to submit form data via email.\n"
04255                                                        "Do you want to continue?"),
04256                                                   i18n("Network Transmission"),
04257                                                   KGuiItem(i18n("&Send Email")),
04258                                                   "WarnTriedEmailSubmit");
04259 
04260       if (rc == KMessageBox::Cancel) {
04261         return;
04262       }
04263     }
04264   }
04265 
04266   // End form security checks
04267   //
04268 
04269   QString urlstring = u.url();
04270 
04271   if ( urlstring.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
04272     urlstring = KURL::decode_string(urlstring);
04273     crossFrameExecuteScript( _target, urlstring.right( urlstring.length() - 11) );
04274     return;
04275   }
04276 
04277   if (!checkLinkSecurity(u,
04278              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?" ),
04279              i18n( "Submit" )))
04280     return;
04281 
04282   KParts::URLArgs args;
04283 
04284   if (!d->m_referrer.isEmpty())
04285      args.metaData()["referrer"] = d->m_referrer;
04286 
04287   args.metaData().insert("PropagateHttpHeader", "true");
04288   args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
04289   args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
04290   args.metaData().insert("main_frame_request",
04291                          parentPart() == 0 ? "TRUE":"FALSE");
04292   args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
04293   args.metaData().insert("ssl_activate_warnings", "TRUE");
04294 //WABA: When we post a form we should treat it as the main url
04295 //the request should never be considered cross-domain
04296 //args.metaData().insert("cross-domain", toplevelURL().url());
04297   args.frameName = _target.isEmpty() ? d->m_doc->baseTarget() : _target ;
04298 
04299   // Handle mailto: forms
04300   if (u.protocol() == "mailto") {
04301       // 1)  Check for attach= and strip it
04302       QString q = u.query().mid(1);
04303       QStringList nvps = QStringList::split("&", q);
04304       bool triedToAttach = false;
04305 
04306       for (QStringList::Iterator nvp = nvps.begin(); nvp != nvps.end(); ++nvp) {
04307          QStringList pair = QStringList::split("=", *nvp);
04308          if (pair.count() >= 2) {
04309             if (pair.first().lower() == "attach") {
04310                nvp = nvps.remove(nvp);
04311                triedToAttach = true;
04312             }
04313          }
04314       }
04315 
04316       if (triedToAttach)
04317          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");
04318 
04319       // 2)  Append body=
04320       QString bodyEnc;
04321       if (contentType.lower() == "multipart/form-data") {
04322          // FIXME: is this correct?  I suspect not
04323          bodyEnc = KURL::encode_string(QString::fromLatin1(formData.data(),
04324                                                            formData.size()));
04325       } else if (contentType.lower() == "text/plain") {
04326          // Convention seems to be to decode, and s/&/\n/
04327          QString tmpbody = QString::fromLatin1(formData.data(),
04328                                                formData.size());
04329          tmpbody.replace(QRegExp("[&]"), "\n");
04330          tmpbody.replace(QRegExp("[+]"), " ");
04331          tmpbody = KURL::decode_string(tmpbody);  // Decode the rest of it
04332          bodyEnc = KURL::encode_string(tmpbody);  // Recode for the URL
04333       } else {
04334          bodyEnc = KURL::encode_string(QString::fromLatin1(formData.data(),
04335                                                            formData.size()));
04336       }
04337 
04338       nvps.append(QString("body=%1").arg(bodyEnc));
04339       q = nvps.join("&");
04340       u.setQuery(q);
04341   }
04342 
04343   if ( strcmp( action, "get" ) == 0 ) {
04344     if (u.protocol() != "mailto")
04345        u.setQuery( QString::fromLatin1( formData.data(), formData.size() ) );
04346     args.setDoPost( false );
04347   }
04348   else {
04349     args.postData = formData;
04350     args.setDoPost( true );
04351 
04352     // construct some user headers if necessary
04353     if (contentType.isNull() || contentType == "application/x-www-form-urlencoded")
04354       args.setContentType( "Content-Type: application/x-www-form-urlencoded" );
04355     else // contentType must be "multipart/form-data"
04356       args.setContentType( "Content-Type: " + contentType + "; boundary=" + boundary );
04357   }
04358 
04359   if ( d->m_doc->parsing() || d->m_runningScripts > 0 ) {
04360     if( d->m_submitForm ) {
04361       kdDebug(6000) << "KHTMLPart::submitForm ABORTING!" << endl;
04362       return;
04363     }
04364     d->m_submitForm = new KHTMLPartPrivate::SubmitForm;
04365     d->m_submitForm->submitAction = action;
04366     d->m_submitForm->submitUrl = url;
04367     d->m_submitForm->submitFormData = formData;
04368     d->m_submitForm->target = _target;
04369     d->m_submitForm->submitContentType = contentType;
04370     d->m_submitForm->submitBoundary = boundary;
04371     connect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
04372   }
04373   else
04374   {
04375     emit d->m_extension->openURLRequest( u, args );
04376   }
04377 }
04378 
04379 void KHTMLPart::popupMenu( const QString &linkUrl )
04380 {
04381   KURL popupURL;
04382   KURL linkKURL;
04383   QString referrer;
04384   KParts::BrowserExtension::PopupFlags itemflags=KParts::BrowserExtension::ShowBookmark | KParts::BrowserExtension::ShowReload;
04385 
04386   if ( linkUrl.isEmpty() ) { // click on background
04387     KHTMLPart* khtmlPart = this;
04388     while ( khtmlPart->parentPart() )
04389     {
04390       khtmlPart=khtmlPart->parentPart();
04391     }
04392     popupURL = khtmlPart->url();
04393     referrer = khtmlPart->pageReferrer();
04394     if (hasSelection())
04395       itemflags = KParts::BrowserExtension::ShowTextSelectionItems;
04396     else
04397       itemflags |= KParts::BrowserExtension::ShowNavigationItems;
04398   } else {               // click on link
04399     popupURL = completeURL( linkUrl );
04400     linkKURL = popupURL;
04401     referrer = this->referrer();
04402   }
04403 
04404   // Danger, Will Robinson. The Popup might stay around for a much
04405   // longer time than KHTMLPart. Deal with it.
04406   KHTMLPopupGUIClient* client = new KHTMLPopupGUIClient( this, d->m_popupMenuXML, linkKURL );
04407   QGuardedPtr<QObject> guard( client );
04408 
04409   KParts::URLArgs args;
04410   args.serviceType = QString::fromLatin1( "text/html" );
04411   args.metaData()["referrer"] = referrer;
04412 
04413   emit d->m_extension->popupMenu( client, QCursor::pos(), popupURL, args, itemflags, S_IFREG /*always a file*/);
04414 
04415   if ( !guard.isNull() ) {
04416      delete client;
04417      emit popupMenu(linkUrl, QCursor::pos());
04418      d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
04419   }
04420 }
04421 
04422 void KHTMLPart::slotParentCompleted()
04423 {
04424   if ( !d->m_redirectURL.isEmpty() && !d->m_redirectionTimer.isActive() )
04425   {
04426     // kdDebug(6050) << this << ": Child redirection -> " << d->m_redirectURL << endl;
04427     d->m_redirectionTimer.start( 1000 * d->m_delayRedirect, true );
04428   }
04429 }
04430 
04431 void KHTMLPart::slotChildStarted( KIO::Job *job )
04432 {
04433   khtml::ChildFrame *child = frame( sender() );
04434 
04435   assert( child );
04436 
04437   child->m_bCompleted = false;
04438 
04439   if ( d->m_bComplete )
04440   {
04441 #if 0
04442     // WABA: Looks like this belongs somewhere else
04443     if ( !parentPart() ) // "toplevel" html document? if yes, then notify the hosting browser about the document (url) changes
04444     {
04445       emit d->m_extension->openURLNotify();
04446     }
04447 #endif
04448     d->m_bComplete = false;
04449     emit started( job );
04450   }
04451 }
04452 
04453 void KHTMLPart::slotChildCompleted()
04454 {
04455   slotChildCompleted( false );
04456 }
04457 
04458 void KHTMLPart::slotChildCompleted( bool pendingAction )
04459 {
04460   khtml::ChildFrame *child = frame( sender() );
04461 
04462   if ( child ) {
04463     kdDebug(6050) << this << " slotChildCompleted child=" << child << " m_frame=" << child->m_frame << endl;
04464     child->m_bCompleted = true;
04465     child->m_bPendingRedirection = pendingAction;
04466     child->m_args = KParts::URLArgs();
04467   }
04468   checkCompleted();
04469 }
04470 
04471 void KHTMLPart::slotChildDocCreated()
04472 {
04473   const KHTMLPart* htmlFrame = static_cast<const KHTMLPart *>(sender());
04474   // Set domain to the frameset's domain
04475   // This must only be done when loading the frameset initially (#22039),
04476   // not when following a link in a frame (#44162).
04477   if ( d->m_doc && d->m_doc->isHTMLDocument() )
04478   {
04479     if ( sender()->inherits("KHTMLPart") )
04480     {
04481       DOMString domain = static_cast<HTMLDocumentImpl*>(d->m_doc)->domain();
04482       if (htmlFrame->d->m_doc && htmlFrame->d->m_doc->isHTMLDocument() )
04483         //kdDebug(6050) << "KHTMLPart::slotChildDocCreated: url: " << htmlFrame->m_url.url() << endl;
04484         static_cast<HTMLDocumentImpl*>(htmlFrame->d->m_doc)->setDomain( domain );
04485     }
04486   }
04487   // So it only happens once
04488   disconnect( htmlFrame, SIGNAL( docCreated() ), this, SLOT( slotChildDocCreated() ) );
04489 }
04490 
04491 void KHTMLPart::slotChildURLRequest( const KURL &url, const KParts::URLArgs &args )
04492 {
04493   khtml::ChildFrame *child = frame( sender()->parent() );
04494   KHTMLPart *callingHtmlPart = const_cast<KHTMLPart *>(dynamic_cast<const KHTMLPart *>(sender()->parent()));
04495 
04496   // TODO: handle child target correctly! currently the script are always executed fur the parent
04497   QString urlStr = url.url();
04498   if ( urlStr.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
04499       QString script = KURL::decode_string( urlStr.right( urlStr.length() - 11 ) );
04500       executeScript( DOM::Node(), script );
04501       return;
04502   }
04503 
04504   QString frameName = args.frameName.lower();
04505   if ( !frameName.isEmpty() ) {
04506     if ( frameName == QString::fromLatin1( "_top" ) )
04507     {
04508       emit d->m_extension->openURLRequest( url, args );
04509       return;
04510     }
04511     else if ( frameName == QString::fromLatin1( "_blank" ) )
04512     {
04513       emit d->m_extension->createNewWindow( url, args );
04514       return;
04515     }
04516     else if ( frameName == QString::fromLatin1( "_parent" ) )
04517     {
04518       KParts::URLArgs newArgs( args );
04519       newArgs.frameName = QString::null;
04520 
04521       emit d->m_extension->openURLRequest( url, newArgs );
04522       return;
04523     }
04524     else if ( frameName != QString::fromLatin1( "_self" ) )
04525     {
04526       khtml::ChildFrame *_frame = recursiveFrameRequest( callingHtmlPart, url, args );
04527 
04528       if ( !_frame )
04529       {
04530         emit d->m_extension->openURLRequest( url, args );
04531         return;
04532       }
04533 
04534       child = _frame;
04535     }
04536   }
04537 
04538   if ( child && child->m_type != khtml::ChildFrame::Object ) {
04539       // Inform someone that we are about to show something else.
04540       child->m_bNotify = true;
04541       requestObject( child, url, args );
04542   }  else if ( frameName== "_self" ) // this is for embedded objects (via <object>) which want to replace the current document
04543   {
04544       KParts::URLArgs newArgs( args );
04545       newArgs.frameName = QString::null;
04546       emit d->m_extension->openURLRequest( url, newArgs );
04547   }
04548 }
04549 
04550 khtml::ChildFrame *KHTMLPart::frame( const QObject *obj )
04551 {
04552     assert( obj->inherits( "KParts::ReadOnlyPart" ) );
04553     const KParts::ReadOnlyPart *part = static_cast<const KParts::ReadOnlyPart *>( obj );
04554 
04555     FrameIt it = d->m_frames.begin();
04556     FrameIt end = d->m_frames.end();
04557     for (; it != end; ++it )
04558       if ( (KParts::ReadOnlyPart *)(*it).m_part == part )
04559         return &(*it);
04560 
04561     for (it = d->m_objects.begin(); it != d->m_objects.end(); ++it )
04562       if ( (KParts::ReadOnlyPart *)(*it).m_part == part )
04563         return &(*it);
04564 
04565     return 0L;
04566 }
04567 
04568 //#define DEBUG_FINDFRAME
04569 
04570 bool KHTMLPart::checkFrameAccess(KHTMLPart *callingHtmlPart)
04571 {
04572   if (callingHtmlPart == this)
04573     return true; // trivial
04574 
04575   if (htmlDocument().isNull()) {
04576 #ifdef DEBUG_FINDFRAME
04577     kdDebug(6050) << "KHTMLPart::checkFrameAccess: Empty part " << this << " URL = " << m_url << endl;
04578 #endif
04579     return false; // we are empty?
04580   }
04581 
04582   // now compare the domains
04583   if (callingHtmlPart && !callingHtmlPart->htmlDocument().isNull() &&
04584       !htmlDocument().isNull())  {
04585     DOM::DOMString actDomain = callingHtmlPart->htmlDocument().domain();
04586     DOM::DOMString destDomain = htmlDocument().domain();
04587 
04588 #ifdef DEBUG_FINDFRAME
04589     kdDebug(6050) << "KHTMLPart::checkFrameAccess: actDomain = '" << actDomain.string() << "' destDomain = '" << destDomain.string() << "'" << endl;
04590 #endif
04591 
04592     if (actDomain == destDomain)
04593       return true;
04594   }
04595 #ifdef DEBUG_FINDFRAME
04596   else
04597   {
04598     kdDebug(6050) << "KHTMLPart::checkFrameAccess: Unknown part/domain " << callingHtmlPart << " tries to access part " << this << endl;
04599   }
04600 #endif
04601   return false;
04602 }
04603 
04604 KHTMLPart *
04605 KHTMLPart::findFrameParent( KParts::ReadOnlyPart *callingPart, const QString &f, khtml::ChildFrame **childFrame )
04606 {
04607 #ifdef DEBUG_FINDFRAME
04608   kdDebug(6050) << "KHTMLPart::findFrameParent: this = " << this << " URL = " << m_url << " findFrameParent( " << f << " )" << endl;
04609 #endif
04610   // Check access
04611   KHTMLPart *callingHtmlPart = dynamic_cast<KHTMLPart *>(callingPart);
04612   
04613   if (!checkFrameAccess(callingHtmlPart))
04614      return 0;
04615 
04616   FrameIt it = d->m_frames.find( f );
04617   FrameIt end = d->m_frames.end();
04618   if ( it != end )
04619   {
04620 #ifdef DEBUG_FINDFRAME
04621      kdDebug(6050) << "KHTMLPart::findFrameParent: FOUND!" << endl;
04622 #endif
04623      if (childFrame)
04624         *childFrame = &(*it);
04625      return this;
04626   }
04627      
04628   it = d->m_frames.begin();
04629   for (; it != end; ++it )
04630   {
04631     KParts::ReadOnlyPart *p = (*it).m_part;
04632     if ( p && p->inherits( "KHTMLPart" ))
04633     {
04634       KHTMLPart *frameParent = static_cast<KHTMLPart*>(p)->findFrameParent(callingPart, f, childFrame);
04635       if (frameParent)
04636          return frameParent;
04637     }
04638   }
04639   return 0;
04640 }
04641 
04642 
04643 KHTMLPart *KHTMLPart::findFrame( const QString &f )
04644 {
04645   khtml::ChildFrame *childFrame;
04646   KHTMLPart *parentFrame = findFrameParent(this, f, &childFrame);
04647   if (parentFrame)
04648   {
04649      KParts::ReadOnlyPart *p = childFrame->m_part;
04650      if ( p && p->inherits( "KHTMLPart" ))
04651         return static_cast<KHTMLPart *>(p);
04652   }
04653   return 0;
04654 }
04655 
04656 KParts::ReadOnlyPart *KHTMLPart::currentFrame() const
04657 {
04658   KParts::ReadOnlyPart* part = (KParts::ReadOnlyPart*)(this);
04659   // Find active part in our frame manager, in case we are a frameset
04660   // and keep doing that (in case of nested framesets).
04661   // Just realized we could also do this recursively, calling part->currentFrame()...
04662   while ( part && part->inherits("KHTMLPart") &&
04663           static_cast<KHTMLPart *>(part)->d->m_frames.count() > 0 ) {
04664     KHTMLPart* frameset = static_cast<KHTMLPart *>(part);
04665     part = static_cast<KParts::ReadOnlyPart *>(frameset->partManager()->activePart());
04666     if ( !part ) return frameset;
04667   }
04668   return part;
04669 }
04670 
04671 bool KHTMLPart::frameExists( const QString &frameName )
04672 {
04673   ConstFrameIt it = d->m_frames.find( frameName );
04674   if ( it == d->m_frames.end() )
04675     return false;
04676 
04677   // WABA: We only return true if the child actually has a frame
04678   // set. Otherwise we might find our preloaded-selve.
04679   // This happens when we restore the frameset.
04680   return (!(*it).m_frame.isNull());
04681 }
04682 
04683 KHTMLPart *KHTMLPart::parentPart()
04684 {
04685   if ( !parent() || !parent()->inherits( "KHTMLPart" ) )
04686     return 0L;
04687 
04688   return (KHTMLPart *)parent();
04689 }
04690 
04691 khtml::ChildFrame *KHTMLPart::recursiveFrameRequest( KHTMLPart *callingHtmlPart, const KURL &url, 
04692                                                      const KParts::URLArgs &args, bool callParent )
04693 {
04694 #ifdef DEBUG_FINDFRAME
04695   kdDebug( 6050 ) << "KHTMLPart::recursiveFrameRequest this = " << this << ", frame = " << args.frameName << ", url = " << url << endl;
04696 #endif  
04697   khtml::ChildFrame *childFrame;
04698   KHTMLPart *childPart = findFrameParent(callingHtmlPart, args.frameName, &childFrame);
04699   if (childPart)
04700   {
04701      if (childPart == this)
04702         return childFrame;
04703      
04704      childPart->requestObject( childFrame, url, args );
04705      return 0;
04706   }
04707 
04708   if ( parentPart() && callParent )
04709   {
04710      khtml::ChildFrame *res = parentPart()->recursiveFrameRequest( callingHtmlPart, url, args, callParent );
04711 
04712      if ( res )
04713        parentPart()->requestObject( res, url, args );
04714   }
04715 
04716   return 0L;
04717 }
04718 
04719 void KHTMLPart::saveState( QDataStream &stream )
04720 {
04721   kdDebug( 6050 ) << "KHTMLPart::saveState this = " << this << " saving URL " << m_url.url() << endl;
04722 
04723   stream << m_url << (Q_INT32)d->m_view->contentsX() << (Q_INT32)d->m_view->contentsY()
04724          << (Q_INT32) d->m_view->contentsWidth() << (Q_INT32) d->m_view->contentsHeight() << (Q_INT32) d->m_view->marginWidth() << (Q_INT32) d->m_view->marginHeight();
04725 
04726   // save link cursor position
04727   int focusNodeNumber;
04728   if (!d->m_focusNodeRestored)
04729       focusNodeNumber = d->m_focusNodeNumber;
04730   else if (d->m_doc && d->m_doc->focusNode())
04731       focusNodeNumber = d->m_doc->nodeAbsIndex(d->m_doc->focusNode());
04732   else
04733       focusNodeNumber = -1;
04734   stream << focusNodeNumber;
04735 
04736   // Save the doc's cache id.
04737   stream << d->m_cacheId;
04738 
04739   // Save the state of the document (Most notably the state of any forms)
04740   QStringList docState;
04741   if (d->m_doc)
04742   {
04743      docState = d->m_doc->docState();
04744   }
04745   stream << d->m_encoding << d->m_sheetUsed << docState;
04746 
04747   stream << d->m_zoomFactor;
04748 
04749   stream << d->m_httpHeaders;
04750   stream << d->m_pageServices;
04751   stream << d->m_pageReferrer;
04752 
04753   // Save ssl data
04754   stream << d->m_ssl_in_use
04755          << d->m_ssl_peer_certificate
04756          << d->m_ssl_peer_chain
04757          << d->m_ssl_peer_ip
04758          << d->m_ssl_cipher
04759          << d->m_ssl_cipher_desc
04760          << d->m_ssl_cipher_version
04761          << d->m_ssl_cipher_used_bits
04762          << d->m_ssl_cipher_bits
04763          << d->m_ssl_cert_state
04764          << d->m_ssl_parent_ip
04765          << d->m_ssl_parent_cert;
04766 
04767 
04768   QStringList frameNameLst, frameServiceTypeLst, frameServiceNameLst;
04769   KURL::List frameURLLst;
04770   QValueList<QByteArray> frameStateBufferLst;
04771 
04772   ConstFrameIt it = d->m_frames.begin();
04773   ConstFrameIt end = d->m_frames.end();
04774   for (; it != end; ++it )
04775   {
04776     if ( !(*it).m_part )
04777        continue;
04778 
04779     frameNameLst << (*it).m_name;
04780     frameServiceTypeLst << (*it).m_serviceType;
04781     frameServiceNameLst << (*it).m_serviceName;
04782     frameURLLst << (*it).m_part->url();
04783 
04784     QByteArray state;
04785     QDataStream frameStream( state, IO_WriteOnly );
04786 
04787     if ( (*it).m_extension )
04788       (*it).m_extension->saveState( frameStream );
04789 
04790     frameStateBufferLst << state;
04791   }
04792 
04793   // Save frame data
04794   stream << (Q_UINT32) frameNameLst.count();
04795   stream << frameNameLst << frameServiceTypeLst << frameServiceNameLst << frameURLLst << frameStateBufferLst;
04796 }
04797 
04798 void KHTMLPart::restoreState( QDataStream &stream )
04799 {
04800   KURL u;
04801   Q_INT32 xOffset, yOffset, wContents, hContents, mWidth, mHeight;
04802   Q_UINT32 frameCount;
04803   QStringList frameNames, frameServiceTypes, docState, frameServiceNames;
04804   KURL::List frameURLs;
04805   QValueList<QByteArray> frameStateBuffers;
04806   QValueList<int> fSizes;
04807   QString encoding, sheetUsed;
04808   long old_cacheId = d->m_cacheId;
04809 
04810   stream >> u >> xOffset >> yOffset >> wContents >> hContents >> mWidth >> mHeight;
04811 
04812   d->m_view->setMarginWidth( mWidth );
04813   d->m_view->setMarginHeight( mHeight );
04814 
04815   // restore link cursor position
04816   // nth node is active. value is set in checkCompleted()
04817   stream >> d->m_focusNodeNumber;
04818   d->m_focusNodeRestored = false;
04819 
04820   stream >> d->m_cacheId;
04821 
04822   stream >> encoding >> sheetUsed >> docState;
04823 
04824   d->m_encoding = encoding;
04825   d->m_sheetUsed = sheetUsed;
04826 
04827   int zoomFactor;
04828   stream >> zoomFactor;
04829   setZoomFactor(zoomFactor);
04830 
04831   stream >> d->m_httpHeaders;
04832   stream >> d->m_pageServices;
04833   stream >> d->m_pageReferrer;
04834 
04835   // Restore ssl data
04836   stream >> d->m_ssl_in_use
04837          >> d->m_ssl_peer_certificate
04838          >> d->m_ssl_peer_chain
04839          >> d->m_ssl_peer_ip
04840          >> d->m_ssl_cipher
04841          >> d->m_ssl_cipher_desc
04842          >> d->m_ssl_cipher_version
04843          >> d->m_ssl_cipher_used_bits
04844          >> d->m_ssl_cipher_bits
04845          >> d->m_ssl_cert_state
04846          >> d->m_ssl_parent_ip
04847          >> d->m_ssl_parent_cert;
04848 
04849   setPageSecurity( d->m_ssl_in_use ? Encrypted : NotCrypted );
04850 
04851   stream >> frameCount >> frameNames >> frameServiceTypes >> frameServiceNames
04852          >> frameURLs >> frameStateBuffers;
04853 
04854   d->m_bComplete = false;
04855   d->m_bLoadEventEmitted = false;
04856 
04857 //   kdDebug( 6050 ) << "restoreStakte() docState.count() = " << docState.count() << endl;
04858 //   kdDebug( 6050 ) << "m_url " << m_url.url() << " <-> " << u.url() << endl;
04859 //   kdDebug( 6050 ) << "m_frames.count() " << d->m_frames.count() << " <-> " << frameCount << endl;
04860 
04861   if (d->m_cacheId == old_cacheId)
04862   {
04863     // Partial restore
04864     d->m_redirectionTimer.stop();
04865 
04866     FrameIt fIt = d->m_frames.begin();
04867     FrameIt fEnd = d->m_frames.end();
04868 
04869     for (; fIt != fEnd; ++fIt )
04870         (*fIt).m_bCompleted = false;
04871 
04872     fIt = d->m_frames.begin();
04873 
04874     QStringList::ConstIterator fNameIt = frameNames.begin();
04875     QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
04876     QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
04877     KURL::List::ConstIterator fURLIt = frameURLs.begin();
04878     QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
04879 
04880     for (; fIt != fEnd; ++fIt, ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
04881     {
04882       khtml::ChildFrame *child = &(*fIt);
04883 
04884 //      kdDebug( 6050 ) <<  *fNameIt  << " ---- " <<  *fServiceTypeIt << endl;
04885 
04886       if ( child->m_name != *fNameIt || child->m_serviceType != *fServiceTypeIt )
04887       {
04888         child->m_bPreloaded = true;
04889         child->m_name = *fNameIt;
04890         child->m_serviceName = *fServiceNameIt;
04891         processObjectRequest( child, *fURLIt, *fServiceTypeIt );
04892       }
04893 
04894       if ( child->m_part )
04895       {
04896         child->m_bCompleted = false;
04897         if ( child->m_extension && !(*fBufferIt).isEmpty() )
04898         {
04899           QDataStream frameStream( *fBufferIt, IO_ReadOnly );
04900           child->m_extension->restoreState( frameStream );
04901         }
04902         else
04903           child->m_part->openURL( *fURLIt );
04904       }
04905     }
04906 
04907     KParts::URLArgs args( d->m_extension->urlArgs() );
04908     args.xOffset = xOffset;
04909     args.yOffset = yOffset;
04910     args.docState = docState;
04911     d->m_extension->setURLArgs( args );
04912 
04913     d->m_view->resizeContents( wContents,  hContents);
04914     d->m_view->setContentsPos( xOffset, yOffset );
04915 
04916     m_url = u;
04917   }
04918   else
04919   {
04920     // Full restore.
04921     closeURL();
04922     // We must force a clear because we want to be sure to delete all
04923     // frames.
04924     d->m_bCleared = false;
04925     clear();
04926     d->m_encoding = encoding;
04927     d->m_sheetUsed = sheetUsed;
04928 
04929     QStringList::ConstIterator fNameIt = frameNames.begin();
04930     QStringList::ConstIterator fNameEnd = frameNames.end();
04931 
04932     QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
04933     QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
04934     KURL::List::ConstIterator fURLIt = frameURLs.begin();
04935     QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
04936 
04937     for (; fNameIt != fNameEnd; ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
04938     {
04939       khtml::ChildFrame newChild;
04940       newChild.m_bPreloaded = true;
04941       newChild.m_name = *fNameIt;
04942       newChild.m_serviceName = *fServiceNameIt;
04943 
04944 //      kdDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt << endl;
04945 
04946       FrameIt childFrame = d->m_frames.append( newChild );
04947 
04948       processObjectRequest( &(*childFrame), *fURLIt, *fServiceTypeIt );
04949 
04950       (*childFrame).m_bPreloaded = true;
04951 
04952       if ( (*childFrame).m_part )
04953       {
04954         if ( (*childFrame).m_extension )
04955         if ( (*childFrame).m_extension && !(*fBufferIt).isEmpty() )
04956         {
04957           QDataStream frameStream( *fBufferIt, IO_ReadOnly );
04958           (*childFrame).m_extension->restoreState( frameStream );
04959         }
04960         else
04961           (*childFrame).m_part->openURL( *fURLIt );
04962       }
04963     }
04964 
04965     KParts::URLArgs args( d->m_extension->urlArgs() );
04966     args.xOffset = xOffset;
04967     args.yOffset = yOffset;
04968     args.docState = docState;
04969 
04970     d->m_view->resizeContents( wContents,  hContents);
04971     d->m_view->setContentsPos( xOffset, yOffset );
04972 
04973     d->m_extension->setURLArgs( args );
04974     if (!KHTMLPageCache::self()->isComplete(d->m_cacheId))
04975     {
04976        d->m_restored = true;
04977        openURL( u );
04978        d->m_restored = false;
04979     }
04980     else
04981     {
04982        restoreURL( u );
04983     }
04984   }
04985 
04986 }
04987 
04988 void KHTMLPart::show()
04989 {
04990   if ( d->m_view )
04991     d->m_view->show();
04992 }
04993 
04994 void KHTMLPart::hide()
04995 {
04996   if ( d->m_view )
04997     d->m_view->hide();
04998 }
04999 
05000 DOM::Node KHTMLPart::nodeUnderMouse() const
05001 {
05002     return d->m_view->nodeUnderMouse();
05003 }
05004 
05005 DOM::Node KHTMLPart::nonSharedNodeUnderMouse() const
05006 {
05007     return d->m_view->nonSharedNodeUnderMouse();
05008 }
05009 
05010 void KHTMLPart::emitSelectionChanged()
05011 {
05012   emit d->m_extension->enableAction( "copy", hasSelection() );
05013   if ( d->m_findDialog )
05014        d->m_findDialog->setHasSelection( hasSelection() );
05015 
05016   emit d->m_extension->selectionInfo( selectedText() );
05017   emit selectionChanged();
05018 }
05019 
05020 int KHTMLPart::zoomFactor() const
05021 {
05022   return d->m_zoomFactor;
05023 }
05024 
05025 // ### make the list configurable ?
05026 static const int zoomSizes[] = { 20, 40, 60, 80, 90, 95, 100, 105, 110, 120, 140, 160, 180, 200, 250, 300 };
05027 static const int zoomSizeCount = (sizeof(zoomSizes) / sizeof(int));
05028 static const int minZoom = 20;
05029 static const int maxZoom = 300;
05030 
05031 // My idea of useful stepping ;-) (LS)
05032 extern const int KDE_NO_EXPORT fastZoomSizes[] = { 20, 50, 75, 90, 100, 120, 150, 200, 300 };
05033 extern const int KDE_NO_EXPORT fastZoomSizeCount = sizeof fastZoomSizes / sizeof fastZoomSizes[0];
05034 
05035 void KHTMLPart::slotIncZoom()
05036 {
05037   zoomIn(zoomSizes, zoomSizeCount);
05038 }
05039 
05040 void KHTMLPart::slotDecZoom()
05041 {
05042   zoomOut(zoomSizes, zoomSizeCount);
05043 }
05044 
05045 void KHTMLPart::slotIncZoomFast()
05046 {
05047   zoomIn(fastZoomSizes, fastZoomSizeCount);
05048 }
05049 
05050 void KHTMLPart::slotDecZoomFast()
05051 {
05052   zoomOut(fastZoomSizes, fastZoomSizeCount);
05053 }
05054 
05055 void KHTMLPart::zoomIn(const int stepping[], int count)
05056 {
05057   int zoomFactor = d->m_zoomFactor;
05058 
05059   if (zoomFactor < maxZoom) {
05060     // find the entry nearest to the given zoomsizes
05061     for (int i = 0; i < count; ++i)
05062       if (stepping[i] > zoomFactor) {
05063         zoomFactor = stepping[i];
05064         break;
05065       }
05066     setZoomFactor(zoomFactor);
05067   }
05068 }
05069 
05070 void KHTMLPart::zoomOut(const int stepping[], int count)
05071 {
05072     int zoomFactor = d->m_zoomFactor;
05073     if (zoomFactor > minZoom) {
05074       // find the entry nearest to the given zoomsizes
05075       for (int i = count-1; i >= 0; --i)
05076         if (stepping[i] < zoomFactor) {
05077           zoomFactor = stepping[i];
05078           break;
05079         }
05080       setZoomFactor(zoomFactor);
05081     }
05082 }
05083 
05084 void KHTMLPart::setZoomFactor (int percent)
05085 {
05086   if (percent < minZoom) percent = minZoom;
05087   if (percent > maxZoom) percent = maxZoom;
05088   if (d->m_zoomFactor == percent) return;
05089   d->m_zoomFactor = percent;
05090 
05091   if(d->m_doc) {
05092       QApplication::setOverrideCursor( waitCursor );
05093     if (d->m_doc->styleSelector())
05094       d->m_doc->styleSelector()->computeFontSizes(d->m_doc->paintDeviceMetrics(), d->m_zoomFactor);
05095     d->m_doc->recalcStyle( NodeImpl::Force );
05096     QApplication::restoreOverrideCursor();
05097   }
05098 
05099   ConstFrameIt it = d->m_frames.begin();
05100   ConstFrameIt end = d->m_frames.end();
05101   for (; it != end; ++it )
05102     if ( !( *it ).m_part.isNull() && ( *it ).m_part->inherits( "KHTMLPart" ) ) {
05103       KParts::ReadOnlyPart* p = ( *it ).m_part;
05104       static_cast<KHTMLPart*>( p )->setZoomFactor(d->m_zoomFactor);
05105     }
05106 
05107   if ( d->m_guiProfile == BrowserViewGUI ) {
05108       d->m_paDecZoomFactor->setEnabled( d->m_zoomFactor > minZoom );
05109       d->m_paIncZoomFactor->setEnabled( d->m_zoomFactor < maxZoom );
05110   }
05111 }
05112 
05113 void KHTMLPart::slotZoomView( int delta )
05114 {
05115   if ( delta < 0 )
05116     slotIncZoom();
05117   else
05118     slotDecZoom();
05119 }
05120 
05121 void KHTMLPart::setStatusBarText( const QString& text, StatusBarPriority p)
05122 {
05123   if (!d->m_statusMessagesEnabled)
05124     return;
05125 
05126   d->m_statusBarText[p] = text;
05127 
05128   // shift handling ?
05129   QString tobe = d->m_statusBarText[BarHoverText];
05130   if (tobe.isEmpty())
05131     tobe = d->m_statusBarText[BarOverrideText];
05132   if (tobe.isEmpty()) {
05133     tobe = d->m_statusBarText[BarDefaultText];
05134     if (!tobe.isEmpty() && d->m_jobspeed)
05135       tobe += " ";
05136     if (d->m_jobspeed)
05137       tobe += i18n( "(%1/s)" ).arg( KIO::convertSize( d->m_jobspeed ) );
05138   }
05139   tobe = "<qt>"+tobe;
05140 
05141   emit ReadOnlyPart::setStatusBarText(tobe);
05142 }
05143 
05144 
05145 void KHTMLPart::setJSStatusBarText( const QString &text )
05146 {
05147   setStatusBarText(text, BarOverrideText);
05148 }
05149 
05150 void KHTMLPart::setJSDefaultStatusBarText( const QString &text )
05151 {
05152   setStatusBarText(text, BarDefaultText);
05153 }
05154 
05155 QString KHTMLPart::jsStatusBarText() const
05156 {
05157     return d->m_statusBarText[BarOverrideText];
05158 }
05159 
05160 QString KHTMLPart::jsDefaultStatusBarText() const
05161 {
05162    return d->m_statusBarText[BarDefaultText];
05163 }
05164 
05165 QString KHTMLPart::referrer() const
05166 {
05167    return d->m_referrer;
05168 }
05169 
05170 QString KHTMLPart::pageReferrer() const
05171 {
05172    KURL referrerURL = KURL( d->m_pageReferrer );
05173    if (referrerURL.isValid())
05174    {
05175       QString protocol = referrerURL.protocol();
05176 
05177       if ((protocol == "http") ||
05178          ((protocol == "https") && (m_url.protocol() == "https")))
05179       {
05180           referrerURL.setRef(QString::null);
05181           referrerURL.setUser(QString::null);
05182           referrerURL.setPass(QString::null);
05183           return referrerURL.url();
05184       }
05185    }
05186 
05187    return QString::null;
05188 }
05189 
05190 
05191 QString KHTMLPart::lastModified() const
05192 {
05193   if ( d->m_lastModified.isEmpty() && m_url.isLocalFile() ) {
05194     // Local file: set last-modified from the file's mtime.
05195     // Done on demand to save time when this isn't needed - but can lead
05196     // to slightly wrong results if updating the file on disk w/o reloading.
05197     QDateTime lastModif = QFileInfo( m_url.path() ).lastModified();
05198     d->m_lastModified = lastModif.toString( Qt::LocalDate );
05199   }
05200   //kdDebug(6050) << "KHTMLPart::lastModified: " << d->m_lastModified << endl;
05201   return d->m_lastModified;
05202 }
05203 
05204 void KHTMLPart::slotLoadImages()
05205 {
05206   if (d->m_doc )
05207     d->m_doc->docLoader()->setAutoloadImages( !d->m_doc->docLoader()->autoloadImages() );
05208 
05209   ConstFrameIt it = d->m_frames.begin();
05210   ConstFrameIt end = d->m_frames.end();
05211   for (; it != end; ++it )
05212     if ( !( *it ).m_part.isNull() && ( *it ).m_part->inherits( "KHTMLPart" ) ) {
05213       KParts::ReadOnlyPart* p = ( *it ).m_part;
05214       static_cast<KHTMLPart*>( p )->slotLoadImages();
05215     }
05216 }
05217 
05218 void KHTMLPart::reparseConfiguration()
05219 {
05220   KHTMLSettings *settings = KHTMLFactory::defaultHTMLSettings();
05221   settings->init();
05222 
05223   setAutoloadImages( settings->autoLoadImages() );
05224   if (d->m_doc)
05225      d->m_doc->docLoader()->setShowAnimations( settings->showAnimations() );
05226 
05227   d->m_bOpenMiddleClick = settings->isOpenMiddleClickEnabled();
05228   d->m_bBackRightClick = settings->isBackRightClickEnabled();
05229   d->m_bJScriptEnabled = settings->isJavaScriptEnabled(m_url.host());
05230   setDebugScript( settings->isJavaScriptDebugEnabled() );
05231   d->m_bJavaEnabled = settings->isJavaEnabled(m_url.host());
05232   d->m_bPluginsEnabled = settings->isPluginsEnabled(m_url.host());
05233   d->m_metaRefreshEnabled = settings->isAutoDelayedActionsEnabled ();
05234 
05235   delete d->m_settings;
05236   d->m_settings = new KHTMLSettings(*KHTMLFactory::defaultHTMLSettings());
05237 
05238   QApplication::setOverrideCursor( waitCursor );
05239   khtml::CSSStyleSelector::reparseConfiguration();
05240   if(d->m_doc) d->m_doc->updateStyleSelector();
05241   QApplication::restoreOverrideCursor();
05242 }
05243 
05244 QStringList KHTMLPart::frameNames() const
05245 {
05246   QStringList res;
05247 
05248   ConstFrameIt it = d->m_frames.begin();
05249   ConstFrameIt end = d->m_frames.end();
05250   for (; it != end; ++it )
05251     if (!(*it).m_bPreloaded)
05252       res += (*it).m_name;
05253 
05254   return res;
05255 }
05256 
05257 QPtrList<KParts::ReadOnlyPart> KHTMLPart::frames() const
05258 {
05259   QPtrList<KParts::ReadOnlyPart> res;
05260 
05261   ConstFrameIt it = d->m_frames.begin();
05262   ConstFrameIt end = d->m_frames.end();
05263   for (; it != end; ++it )
05264     if (!(*it).m_bPreloaded)
05265       res.append( (*it).m_part );
05266 
05267   return res;
05268 }
05269 
05270 bool KHTMLPart::openURLInFrame( const KURL &url, const KParts::URLArgs &urlArgs )
05271 {
05272     kdDebug( 6050 ) << this << "KHTMLPart::openURLInFrame " << url << endl;
05273   FrameIt it = d->m_frames.find( urlArgs.frameName );
05274 
05275   if ( it == d->m_frames.end() )
05276     return false;
05277 
05278   // Inform someone that we are about to show something else.
05279   if ( !urlArgs.lockHistory() )
05280       emit d->m_extension->openURLNotify();
05281 
05282   requestObject( &(*it), url, urlArgs );
05283 
05284   return true;
05285 }
05286 
05287 void KHTMLPart::setDNDEnabled( bool b )
05288 {
05289   d->m_bDnd = b;
05290 }
05291 
05292 bool KHTMLPart::dndEnabled() const
05293 {
05294   return d->m_bDnd;
05295 }
05296 
05297 void KHTMLPart::customEvent( QCustomEvent *event )
05298 {
05299   if ( khtml::MousePressEvent::test( event ) )
05300   {
05301     khtmlMousePressEvent( static_cast<khtml::MousePressEvent *>( event ) );
05302     return;
05303   }
05304 
05305   if ( khtml::MouseDoubleClickEvent::test( event ) )
05306   {
05307     khtmlMouseDoubleClickEvent( static_cast<khtml::MouseDoubleClickEvent *>( event ) );
05308     return;
05309   }
05310 
05311   if ( khtml::MouseMoveEvent::test( event ) )
05312   {
05313     khtmlMouseMoveEvent( static_cast<khtml::MouseMoveEvent *>( event ) );
05314     return;
05315   }
05316 
05317   if ( khtml::MouseReleaseEvent::test( event ) )
05318   {
05319     khtmlMouseReleaseEvent( static_cast<khtml::MouseReleaseEvent *>( event ) );
05320     return;
05321   }
05322 
05323   if ( khtml::DrawContentsEvent::test( event ) )
05324   {
05325     khtmlDrawContentsEvent( static_cast<khtml::DrawContentsEvent *>( event ) );
05326     return;
05327   }
05328 
05329   KParts::ReadOnlyPart::customEvent( event );
05330 }
05331 
05337 static bool firstRunAt(khtml::RenderObject *renderNode, int y, NodeImpl *&startNode, long &startOffset)
05338 {
05339     for (khtml::RenderObject *n = renderNode; n; n = n->nextSibling()) {
05340         if (n->isText()) {
05341             khtml::RenderText *textRenderer = static_cast<khtml::RenderText *>(n);
05342             const khtml::InlineTextBoxArray &runs = textRenderer->inlineTextBoxes();
05343             for (unsigned i = 0; i != runs.count(); i++) {
05344                 if (runs[i]->m_y == y) {
05345                     startNode = textRenderer->element();
05346                     startOffset = runs[i]->m_start;
05347                     return true;
05348                 }
05349             }
05350         }
05351 
05352         if (firstRunAt(n->firstChild(), y, startNode, startOffset)) {
05353             return true;
05354         }
05355     }
05356 
05357     return false;
05358 }
05359 
05365 static bool lastRunAt(khtml::RenderObject *renderNode, int y, NodeImpl *&endNode, long &endOffset)
05366 {
05367     khtml::RenderObject *n = renderNode;
05368     if (!n) {
05369         return false;
05370     }
05371     khtml::RenderObject *next;
05372     while ((next = n->nextSibling())) {
05373         n = next;
05374     }
05375 
05376     while (1) {
05377         if (lastRunAt(n->firstChild(), y, endNode, endOffset)) {
05378             return true;
05379         }
05380 
05381         if (n->isText()) {
05382             khtml::RenderText *textRenderer =  static_cast<khtml::RenderText *>(n);
05383             const khtml::InlineTextBoxArray &runs = textRenderer->inlineTextBoxes();
05384             for (int i = (int)runs.count()-1; i >= 0; i--) {
05385                 if (runs[i]->m_y == y) {
05386                     endNode = textRenderer->element();
05387                     endOffset = runs[i]->m_start + runs[i]->m_len;
05388                     return true;
05389                 }
05390             }
05391         }
05392 
05393         if (n == renderNode) {
05394             return false;
05395         }
05396 
05397         n = n->previousSibling();
05398     }
05399 }
05400 
05401 void KHTMLPart::khtmlMousePressEvent( khtml::MousePressEvent *event )
05402 {
05403   DOM::DOMString url = event->url();
05404   QMouseEvent *_mouse = event->qmouseEvent();
05405   DOM::Node innerNode = event->innerNode();
05406   d->m_mousePressNode = innerNode;
05407 
05408    d->m_dragStartPos = _mouse->pos();
05409 
05410    if ( !event->url().isNull() ) {
05411      d->m_strSelectedURL = event->url().string();
05412      d->m_strSelectedURLTarget = event->target().string();
05413    }
05414    else
05415      d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
05416 
05417   if ( _mouse->button() == LeftButton ||
05418        _mouse->button() == MidButton )
05419   {
05420     d->m_bMousePressed = true;
05421 
05422 #ifndef KHTML_NO_SELECTION
05423     if ( _mouse->button() == LeftButton )
05424     {
05425       if ( (!d->m_strSelectedURL.isNull() && !isEditable())
05426             || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) )
05427       return;
05428       if ( !innerNode.isNull()  && innerNode.handle()->renderer()) {
05429           int offset = 0;
05430           DOM::NodeImpl* node = 0;
05431           khtml::RenderObject::SelPointState state;
05432           innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(),
05433                                                                event->absX()-innerNode.handle()->renderer()->xPos(),
05434                                                                event->absY()-innerNode.handle()->renderer()->yPos(), node, offset, state );
05435           d->m_extendMode = d->ExtendByChar;
05436 #ifdef KHTML_NO_CARET
05437           d->m_selectionStart = node;
05438           d->m_startOffset = offset;
05439           //if ( node )
05440           //  kdDebug(6005) << "KHTMLPart::khtmlMousePressEvent selectionStart=" << d->m_selectionStart.handle()->renderer()
05441           //                << " offset=" << d->m_startOffset << endl;
05442           //else
05443           //  kdDebug(6005) << "KHTML::khtmlMousePressEvent selectionStart=(nil)" << endl;
05444           d->m_selectionEnd = d->m_selectionStart;
05445           d->m_endOffset = d->m_startOffset;
05446           d->m_doc->clearSelection();
05447 #else // KHTML_NO_CARET
05448       d->m_view->moveCaretTo(node, offset, (_mouse->state() & ShiftButton) == 0);
05449 #endif // KHTML_NO_CARET
05450       d->m_initialNode = d->m_selectionStart;
05451       d->m_initialOffset = d->m_startOffset;
05452 //           kdDebug(6000) << "press: initOfs " << d->m_initialOffset << endl;
05453       }
05454       else
05455       {
05456 #ifndef KHTML_NO_CARET
05457         // simply leave it. Is this a good idea?
05458 #else
05459         d->m_selectionStart = DOM::Node();
05460         d->m_selectionEnd = DOM::Node();
05461 #endif
05462       }
05463       emitSelectionChanged();
05464       startAutoScroll();
05465     }
05466 #else
05467     d->m_dragLastPos = _mouse->globalPos();
05468 #endif
05469   }
05470 
05471   if ( _mouse->button() == RightButton && parentPart() != 0 && d->m_bBackRightClick )
05472   {
05473     d->m_bRightMousePressed = true;
05474   } else if ( _mouse->button() == RightButton )
05475   {
05476     popupMenu( d->m_strSelectedURL );
05477     // might be deleted, don't touch "this"
05478   }
05479 }
05480 
05481 void KHTMLPart::khtmlMouseDoubleClickEvent( khtml::MouseDoubleClickEvent *event )
05482 {
05483   QMouseEvent *_mouse = event->qmouseEvent();
05484   if ( _mouse->button() == LeftButton )
05485   {
05486     d->m_bMousePressed = true;
05487     DOM::Node innerNode = event->innerNode();
05488     // Find selectionStart again, khtmlMouseReleaseEvent lost it
05489     if ( !innerNode.isNull() && innerNode.handle()->renderer()) {
05490       int offset = 0;
05491       DOM::NodeImpl* node = 0;
05492       khtml::RenderObject::SelPointState state;
05493       innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(),
05494                                                            event->absX()-innerNode.handle()->renderer()->xPos(),
05495                                                            event->absY()-innerNode.handle()->renderer()->yPos(), node, offset, state);
05496 
05497       //kdDebug() << k_funcinfo << "checkSelectionPoint returned node=" << node << " offset=" << offset << endl;
05498 
05499       if ( node && node->renderer() )
05500       {
05501         // Extend selection to a complete word (double-click) or line (triple-click)
05502         bool selectLine = (event->clickCount() == 3);
05503         d->m_extendMode = selectLine ? d->ExtendByLine : d->ExtendByWord;
05504 
05505     // Extend existing selection if Shift was pressed
05506     if (_mouse->state() & ShiftButton) {
05507           d->caretNode() = node;
05508       d->caretOffset() = offset;
05509           d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
05510                 d->m_selectionStart.handle(), d->m_startOffset,
05511             d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
05512           d->m_initialNode = d->m_extendAtEnd ? d->m_selectionStart : d->m_selectionEnd;
05513           d->m_initialOffset = d->m_extendAtEnd ? d->m_startOffset : d->m_endOffset;
05514     } else {
05515       d->m_selectionStart = d->m_selectionEnd = node;
05516       d->m_startOffset = d->m_endOffset = offset;
05517           d->m_startBeforeEnd = true;
05518           d->m_initialNode = node;
05519           d->m_initialOffset = offset;
05520     }
05521 //         kdDebug(6000) << "dblclk: initOfs " << d->m_initialOffset << endl;
05522 
05523         // Extend the start
05524         extendSelection( d->m_selectionStart.handle(), d->m_startOffset, d->m_selectionStart, d->m_startOffset, !d->m_startBeforeEnd, selectLine );
05525         // Extend the end
05526         extendSelection( d->m_selectionEnd.handle(), d->m_endOffset, d->m_selectionEnd, d->m_endOffset, d->m_startBeforeEnd, selectLine );
05527 
05528         //kdDebug() << d->m_selectionStart.handle() << " " << d->m_startOffset << "  -  " <<
05529         //  d->m_selectionEnd.handle() << " " << d->m_endOffset << endl;
05530 
05531         emitSelectionChanged();
05532         d->m_doc
05533           ->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
05534                          d->m_selectionEnd.handle(),d->m_endOffset);
05535 #ifndef KHTML_NO_CARET
05536         bool v = d->m_view->placeCaret();
05537         emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
05538 #endif
05539         startAutoScroll();
05540       }
05541     }
05542   }
05543 }
05544 
05545 void KHTMLPart::extendSelection( DOM::NodeImpl* node, long offset, DOM::Node& selectionNode, long& selectionOffset, bool right, bool selectLines )
05546 {
05547   khtml::RenderObject* obj = node->renderer();
05548 
05549   if (obj->isText() && selectLines) {
05550     int pos;
05551     khtml::RenderText *renderer = static_cast<khtml::RenderText *>(obj);
05552     khtml::InlineTextBox *run = renderer->findInlineTextBox( offset, pos );
05553     DOMString t = node->nodeValue();
05554     DOM::NodeImpl* selNode = 0;
05555     long selOfs = 0;
05556 
05557     if (!run)
05558       return;
05559 
05560     int selectionPointY = run->m_y;
05561 
05562     // Go up to first non-inline element.
05563     khtml::RenderObject *renderNode = renderer;
05564     while (renderNode && renderNode->isInline())
05565       renderNode = renderNode->parent();
05566 
05567     renderNode = renderNode->firstChild();
05568 
05569     if (right) {
05570       // Look for all the last child in the block that is on the same line
05571       // as the selection point.
05572       if (!lastRunAt (renderNode, selectionPointY, selNode, selOfs))
05573         return;
05574     } else {
05575       // Look for all the first child in the block that is on the same line
05576       // as the selection point.
05577       if (!firstRunAt (renderNode, selectionPointY, selNode, selOfs))
05578         return;
05579     }
05580 
05581     selectionNode = selNode;
05582     selectionOffset = selOfs;
05583     return;
05584   }
05585 
05586   QString str;
05587   int len = 0;
05588   // make offset point left to current char
05589   if (right && offset > 0) offset--;
05590   if ( obj->isText() ) { // can be false e.g. when double-clicking on a disabled submit button
05591     str = static_cast<khtml::RenderText *>(obj)->data().string();
05592     len = str.length();
05593   }
05594   //kdDebug() << "extendSelection right=" << right << " offset=" << offset << " len=" << len << " Starting at obj=" << obj << endl;
05595   QChar ch;
05596   do {
05597     // Last char was ok, point to it
05598     if ( node ) {
05599       selectionNode = node;
05600       selectionOffset = offset;
05601     }
05602 
05603     // Get another char
05604     while ( obj && ( (right && offset >= len-1) || (!right && offset <= 0) ) )
05605     {
05606       obj = right ? obj->objectBelow() : obj->objectAbove();
05607       //kdDebug() << "obj=" << obj << endl;
05608       if ( obj ) {
05609         //kdDebug() << "isText=" << obj->isText() << endl;
05610         str = QString::null;
05611         if ( obj->isText() )
05612           str = static_cast<khtml::RenderText *>(obj)->data().string();
05613         else if ( obj->isBR() )
05614           str = '\n';
05615         else if ( !obj->isInline() ) {
05616           obj = 0L; // parag limit -> done
05617           break;
05618         }
05619         len = str.length();
05620         //kdDebug() << "str=" << str << " length=" << len << endl;
05621         // set offset - note that the first thing will be a ++ or -- on it.
05622         if ( right )
05623           offset = -1;
05624         else
05625           offset = len;
05626       }
05627     }
05628     if ( !obj ) // end of parag or document
05629       break;
05630     node = obj->element();
05631     if ( right )
05632     {
05633       Q_ASSERT( offset < len-1 );
05634       offset++;
05635     }
05636     else
05637     {
05638       Q_ASSERT( offset > 0 );
05639       offset--;
05640     }
05641 
05642     // Test that char
05643     ch = str[ offset ];
05644     //kdDebug() << " offset=" << offset << " ch=" << QString(ch) << endl;
05645   } while ( !ch.isSpace() && !ch.isPunct() );
05646 
05647   // make offset point after last char
05648   if (right) selectionOffset++;
05649 }
05650 
05651 #ifndef KHTML_NO_SELECTION
05652 void KHTMLPart::extendSelectionTo(int x, int y, int absX, int absY, const DOM::Node &innerNode)
05653 {
05654       int offset;
05655       //kdDebug(6000) << "KHTMLPart::khtmlMouseMoveEvent x=" << event->x() << " y=" << event->y() << endl;
05656       DOM::NodeImpl* node=0;
05657       khtml::RenderObject::SelPointState state;
05658       innerNode.handle()->renderer()->checkSelectionPoint( x, y,
05659                                                            absX-innerNode.handle()->renderer()->xPos(),
05660                                                            absY-innerNode.handle()->renderer()->yPos(), node, offset, state);
05661       if (!node || !node->renderer()) return;
05662 
05663       // Words at the beginning/end of line cannot be deselected in
05664       // ExtendByWord mode. Therefore, do not enforce it if the selection
05665       // point does not match the node under the mouse cursor.
05666       bool withinNode = innerNode == node;
05667 
05668       // we have to get to know if end is before start or not...
05669       // shouldn't be null but it can happen with dynamic updating of nodes
05670       if (d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() ||
05671           d->m_initialNode.isNull() ||
05672           !d->m_selectionStart.handle()->renderer() ||
05673           !d->m_selectionEnd.handle()->renderer()) return;
05674 
05675       if (d->m_extendMode != d->ExtendByChar) {
05676         // check whether we should extend at the front, or at the back
05677         bool caretBeforeInit = RangeImpl::compareBoundaryPoints(
05678                 d->caretNode().handle(), d->caretOffset(),
05679             d->m_initialNode.handle(), d->m_initialOffset) <= 0;
05680         bool nodeBeforeInit = RangeImpl::compareBoundaryPoints(node, offset,
05681             d->m_initialNode.handle(), d->m_initialOffset) <= 0;
05682         // have to fix up start to point to the original end
05683         if (caretBeforeInit != nodeBeforeInit) {
05684 //         kdDebug(6000) << "extto cbi: " << caretBeforeInit << " startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << " initOfs " << d->m_initialOffset << endl;
05685           extendSelection(d->m_initialNode.handle(), d->m_initialOffset,
05686         d->m_extendAtEnd ? d->m_selectionStart : d->m_selectionEnd,
05687         d->m_extendAtEnd ? d->m_startOffset : d->m_endOffset,
05688         nodeBeforeInit, d->m_extendMode == d->ExtendByLine);
05689     }
05690       }
05691 
05692       d->caretNode() = node;
05693       d->caretOffset() = offset;
05694       //kdDebug( 6000 ) << "setting end of selection to " << d->m_selectionEnd.handle() << "/" << d->m_endOffset << endl;
05695 
05696       d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
05697                 d->m_selectionStart.handle(), d->m_startOffset,
05698             d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
05699 
05700       if ( !d->m_selectionStart.isNull() && !d->m_selectionEnd.isNull() )
05701       {
05702 //         kdDebug(6000) << "extto: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << " initOfs " << d->m_initialOffset << endl;
05703         if (d->m_extendMode != d->ExtendByChar && withinNode)
05704           extendSelection( node, offset, d->caretNode(), d->caretOffset(), d->m_startBeforeEnd ^ !d->m_extendAtEnd, d->m_extendMode == d->ExtendByLine );
05705 
05706         if (d->m_selectionEnd == d->m_selectionStart && d->m_endOffset < d->m_startOffset)
05707           d->m_doc
05708             ->setSelection(d->m_selectionStart.handle(),d->m_endOffset,
05709                            d->m_selectionEnd.handle(),d->m_startOffset);
05710         else if (d->m_startBeforeEnd)
05711           d->m_doc
05712             ->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
05713                            d->m_selectionEnd.handle(),d->m_endOffset);
05714         else
05715           d->m_doc
05716             ->setSelection(d->m_selectionEnd.handle(),d->m_endOffset,
05717                            d->m_selectionStart.handle(),d->m_startOffset);
05718       }
05719 #ifndef KHTML_NO_CARET
05720       d->m_view->placeCaret();
05721 #endif
05722 }
05723 
05724 bool KHTMLPart::isExtendingSelection() const
05725 {
05726   // This is it, the whole detection. khtmlMousePressEvent only sets this
05727   // on LMB or MMB, but never on RMB. As text selection doesn't work for MMB,
05728   // it's sufficient to only rely on this flag to detect selection extension.
05729   return d->m_bMousePressed;
05730 }
05731 #endif // KHTML_NO_SELECTION
05732 
05733 void KHTMLPart::khtmlMouseMoveEvent( khtml::MouseMoveEvent *event )
05734 {
05735   QMouseEvent *_mouse = event->qmouseEvent();
05736 
05737   if( d->m_bRightMousePressed && parentPart() != 0 && d->m_bBackRightClick )
05738   {
05739     popupMenu( d->m_strSelectedURL );
05740     d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
05741     d->m_bRightMousePressed = false;
05742   }
05743 
05744   DOM::DOMString url = event->url();
05745   DOM::DOMString target = event->target();
05746   DOM::Node innerNode = event->innerNode();
05747 
05748 #ifndef QT_NO_DRAGANDDROP
05749   if( d->m_bDnd && d->m_bMousePressed &&
05750       ( (!d->m_strSelectedURL.isEmpty() && !isEditable())
05751         || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) ) ) {
05752     if ( ( d->m_dragStartPos - _mouse->pos() ).manhattanLength() <= KGlobalSettings::dndEventDelay() )
05753       return;
05754 
05755     QPixmap pix;
05756     HTMLImageElementImpl *img = 0L;
05757     QDragObject *drag = 0;
05758     KURL u;
05759 
05760     // qDebug("****************** Event URL: %s", url.string().latin1());
05761     // qDebug("****************** Event Target: %s", target.string().latin1());
05762 
05763     // Normal image...
05764     if ( url.length() == 0 && innerNode.handle() && innerNode.handle()->id() == ID_IMG )
05765     {
05766       img = static_cast<HTMLImageElementImpl *>(innerNode.handle());
05767       u = KURL( completeURL( khtml::parseURL(img->getAttribute(ATTR_SRC)).string() ) );
05768       pix = KMimeType::mimeType("image/png")->pixmap(KIcon::Desktop);
05769     }
05770     else
05771     {
05772       // Text or image link...
05773       u = completeURL( d->m_strSelectedURL );
05774       pix = KMimeType::pixmapForURL(u, 0, KIcon::Desktop, KIcon::SizeMedium);
05775     }
05776 
05777     KURLDrag* urlDrag = new KURLDrag( u, img ? 0 : d->m_view->viewport() );
05778     if ( !d->m_referrer.isEmpty() )
05779       urlDrag->metaData()["referrer"] = d->m_referrer;
05780 
05781     if( img ) {
05782       KMultipleDrag *mdrag = new KMultipleDrag( d->m_view->viewport() );
05783       mdrag->addDragObject( new QImageDrag( img->currentImage(), 0L ) );
05784       mdrag->addDragObject( urlDrag );
05785       drag = mdrag;
05786     }
05787     else
05788       drag = urlDrag;
05789 
05790     if ( !pix.isNull() )
05791       drag->setPixmap( pix );
05792 
05793     stopAutoScroll();
05794     if(drag)
05795         drag->drag();
05796 
05797     // when we finish our drag, we need to undo our mouse press
05798     d->m_bMousePressed = false;
05799     d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
05800     return;
05801   }
05802 #endif
05803 
05804   // Not clicked -> mouse over stuff
05805   if ( !d->m_bMousePressed )
05806   {
05807     // The mouse is over something
05808     if ( url.length() )
05809     {
05810       bool shiftPressed = ( _mouse->state() & ShiftButton );
05811 
05812       // Image map
05813       if ( !innerNode.isNull() && innerNode.elementId() == ID_IMG )
05814       {
05815         HTMLImageElementImpl *i = static_cast<HTMLImageElementImpl *>(innerNode.handle());
05816         if ( i && i->isServerMap() )
05817         {
05818           khtml::RenderObject *r = i->renderer();
05819           if(r)
05820           {
05821             int absx, absy, vx, vy;
05822             r->absolutePosition(absx, absy);
05823             view()->contentsToViewport( absx, absy, vx, vy );
05824 
05825             int x(_mouse->x() - vx), y(_mouse->y() - vy);
05826 
05827             d->m_overURL = url.string() + QString("?%1,%2").arg(x).arg(y);
05828             d->m_overURLTarget = target.string();
05829             overURL( d->m_overURL, target.string(), shiftPressed );
05830             return;
05831           }
05832         }
05833       }
05834 
05835       // normal link
05836       if ( d->m_overURL.isEmpty() || d->m_overURL != url || d->m_overURLTarget != target )
05837       {
05838         d->m_overURL = url.string();
05839         d->m_overURLTarget = target.string();
05840         overURL( d->m_overURL, target.string(), shiftPressed );
05841       }
05842     }
05843     else  // Not over a link...
05844     {
05845       if( !d->m_overURL.isEmpty() ) // and we were over a link  -> reset to "default statusbar text"
05846       {
05847         d->m_overURL = d->m_overURLTarget = QString::null;
05848         emit onURL( QString::null );
05849         // revert to default statusbar text
05850         setStatusBarText(QString::null, BarHoverText);
05851         emit d->m_extension->mouseOverInfo(0);
05852      }
05853     }
05854   }
05855   else {
05856 #ifndef KHTML_NO_SELECTION
05857     // selection stuff
05858     if( d->m_bMousePressed && innerNode.handle() && innerNode.handle()->renderer() &&
05859         ( (_mouse->state() & LeftButton) != 0 )) {
05860       extendSelectionTo(event->x(), event->y(),
05861                         event->absX(), event->absY(), innerNode);
05862 #else
05863       if ( d->m_doc && d->m_view ) {
05864         QPoint diff( _mouse->globalPos() - d->m_dragLastPos );
05865 
05866         if ( abs( diff.x() ) > 64 || abs( diff.y() ) > 64 ) {
05867           d->m_view->scrollBy( -diff.x(), -diff.y() );
05868           d->m_dragLastPos = _mouse->globalPos();
05869         }
05870 #endif
05871     }
05872   }
05873 
05874 }
05875 
05876 void KHTMLPart::khtmlMouseReleaseEvent( khtml::MouseReleaseEvent *event )
05877 {
05878   DOM::Node innerNode = event->innerNode();
05879   d->m_mousePressNode = DOM::Node();
05880 
05881   if ( d->m_bMousePressed ) {
05882     setStatusBarText(QString::null, BarHoverText);
05883     stopAutoScroll();
05884   }
05885 
05886   // Used to prevent mouseMoveEvent from initiating a drag before
05887   // the mouse is pressed again.
05888   d->m_bMousePressed = false;
05889 
05890   QMouseEvent *_mouse = event->qmouseEvent();
05891   if ( _mouse->button() == RightButton && parentPart() != 0 && d->m_bBackRightClick )
05892   {
05893     d->m_bRightMousePressed = false;
05894     KParts::BrowserInterface *tmp_iface = d->m_extension->browserInterface();
05895     if( tmp_iface ) {
05896       tmp_iface->callMethod( "goHistory(int)", -1 );
05897     }
05898   }
05899 #ifndef QT_NO_CLIPBOARD
05900   if ((d->m_guiProfile == BrowserViewGUI) && (_mouse->button() == MidButton) && (event->url().isNull())) {
05901     kdDebug( 6050 ) << "KHTMLPart::khtmlMouseReleaseEvent() MMB shouldOpen="
05902                     << d->m_bOpenMiddleClick << endl;
05903 
05904     if (d->m_bOpenMiddleClick) {
05905     KHTMLPart *p = this;
05906     while (p->parentPart()) p = p->parentPart();
05907     p->d->m_extension->pasteRequest();
05908   }
05909   }
05910 #endif
05911 
05912 #ifndef KHTML_NO_SELECTION
05913   // delete selection in case start and end position are at the same point
05914   if(d->m_selectionStart == d->m_selectionEnd && d->m_startOffset == d->m_endOffset) {
05915 #ifndef KHTML_NO_CARET
05916     d->m_extendAtEnd = true;
05917 #else
05918     d->m_selectionStart = 0;
05919     d->m_selectionEnd = 0;
05920     d->m_startOffset = 0;
05921     d->m_endOffset = 0;
05922 #endif
05923     emitSelectionChanged();
05924   } else {
05925     // we have to get to know if end is before start or not...
05926 //     kdDebug(6000) << "rel: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << endl;
05927     DOM::Node n = d->m_selectionStart;
05928     d->m_startBeforeEnd = false;
05929     if( d->m_selectionStart == d->m_selectionEnd ) {
05930       if( d->m_startOffset < d->m_endOffset )
05931         d->m_startBeforeEnd = true;
05932     } else {
05933 #if 0
05934       while(!n.isNull()) {
05935         if(n == d->m_selectionEnd) {
05936           d->m_startBeforeEnd = true;
05937           break;
05938         }
05939         DOM::Node next = n.firstChild();
05940         if(next.isNull()) next = n.nextSibling();
05941         while( next.isNull() && !n.parentNode().isNull() ) {
05942           n = n.parentNode();
05943           next = n.nextSibling();
05944         }
05945         n = next;
05946       }
05947 #else
05948       // shouldn't be null but it can happen with dynamic updating of nodes
05949       if (d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() ||
05950           !d->m_selectionStart.handle()->renderer() ||
05951           !d->m_selectionEnd.handle()->renderer()) return;
05952       d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
05953                 d->m_selectionStart.handle(), d->m_startOffset,
05954             d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
05955 #endif
05956     }
05957     if(!d->m_startBeforeEnd)
05958     {
05959       DOM::Node tmpNode = d->m_selectionStart;
05960       int tmpOffset = d->m_startOffset;
05961       d->m_selectionStart = d->m_selectionEnd;
05962       d->m_startOffset = d->m_endOffset;
05963       d->m_selectionEnd = tmpNode;
05964       d->m_endOffset = tmpOffset;
05965       d->m_startBeforeEnd = true;
05966       d->m_extendAtEnd = !d->m_extendAtEnd;
05967     }
05968 #ifndef KHTML_NO_CARET
05969     bool v = d->m_view->placeCaret();
05970     emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
05971 #endif
05972     // get selected text and paste to the clipboard
05973 #ifndef QT_NO_CLIPBOARD
05974     QString text = selectedText();
05975     text.replace(QChar(0xa0), ' ');
05976     disconnect( kapp->clipboard(), SIGNAL( selectionChanged()), this, SLOT( slotClearSelection()));
05977     kapp->clipboard()->setText(text,QClipboard::Selection);
05978     connect( kapp->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection()));
05979 #endif
05980     //kdDebug( 6000 ) << "selectedText = " << text << endl;
05981     emitSelectionChanged();
05982 //kdDebug(6000) << "rel2: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << "), caretOfs " << d->caretOffset() << endl;
05983   }
05984 #endif
05985   d->m_initialNode = 0;     // don't hold nodes longer than necessary
05986   d->m_initialOffset = 0;
05987 
05988 }
05989 
05990 void KHTMLPart::khtmlDrawContentsEvent( khtml::DrawContentsEvent * )
05991 {
05992 }
05993 
05994 void KHTMLPart::guiActivateEvent( KParts::GUIActivateEvent *event )
05995 {
05996   if ( event->activated() )
05997   {
05998     emitSelectionChanged();
05999     emit d->m_extension->enableAction( "print", d->m_doc != 0 );
06000 
06001     if ( !d->m_settings->autoLoadImages() && d->m_paLoadImages )
06002     {
06003         QPtrList<KAction> lst;
06004         lst.append( d->m_paLoadImages );
06005         plugActionList( "loadImages", lst );
06006     }
06007   }
06008 }
06009 
06010 void KHTMLPart::slotPrintFrame()
06011 {
06012   if ( d->m_frames.count() == 0 )
06013     return;
06014 
06015   KParts::ReadOnlyPart *frame = currentFrame();
06016   if (!frame)
06017     return;
06018 
06019   KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject( frame );
06020 
06021   if ( !ext )
06022     return;
06023 
06024   QMetaObject *mo = ext->metaObject();
06025 
06026   int idx = mo->findSlot( "print()", true );
06027   if ( idx >= 0 ) {
06028     QUObject o[ 1 ];
06029     ext->qt_invoke( idx, o );
06030   }
06031 }
06032 
06033 void KHTMLPart::slotSelectAll()
06034 {
06035   KParts::ReadOnlyPart *part = currentFrame();
06036   if (part && part->inherits("KHTMLPart"))
06037     static_cast<KHTMLPart *>(part)->selectAll();
06038 }
06039 
06040 void KHTMLPart::startAutoScroll()
06041 {
06042    connect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
06043    d->m_scrollTimer.start(100, false);
06044 }
06045 
06046 void KHTMLPart::stopAutoScroll()
06047 {
06048    disconnect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
06049    if (d->m_scrollTimer.isActive())
06050        d->m_scrollTimer.stop();
06051 }
06052 
06053 
06054 void KHTMLPart::slotAutoScroll()
06055 {
06056     if (d->m_view)
06057       d->m_view->doAutoScroll();
06058     else
06059       stopAutoScroll(); // Safety
06060 }
06061 
06062 void KHTMLPart::selectAll()
06063 {
06064   if (!d->m_doc) return;
06065 
06066   NodeImpl *first;
06067   if (d->m_doc->isHTMLDocument())
06068     first = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
06069   else
06070     first = d->m_doc;
06071   NodeImpl *next;
06072 
06073   // Look for first text/cdata node that has a renderer,
06074   // or first childless replaced element
06075   while ( first && !(first->renderer()
06076     && ((first->nodeType() == Node::TEXT_NODE || first->nodeType() == Node::CDATA_SECTION_NODE)
06077         || (first->renderer()->isReplaced() && !first->renderer()->firstChild()))))
06078   {
06079     next = first->firstChild();
06080     if ( !next ) next = first->nextSibling();
06081     while( first && !next )
06082     {
06083       first = first->parentNode();
06084       if ( first )
06085         next = first->nextSibling();
06086     }
06087     first = next;
06088   }
06089 
06090   NodeImpl *last;
06091   if (d->m_doc->isHTMLDocument())
06092     last = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
06093   else
06094     last = d->m_doc;
06095   // Look for last text/cdata node that has a renderer,
06096   // or last childless replaced element
06097   // ### Instead of changing this loop, use findLastSelectableNode
06098   // in render_table.cpp (LS)
06099   while ( last && !(last->renderer()
06100     && ((last->nodeType() == Node::TEXT_NODE || last->nodeType() == Node::CDATA_SECTION_NODE)
06101         || (last->renderer()->isReplaced() && !last->renderer()->lastChild()))))
06102   {
06103     next = last->lastChild();
06104     if ( !next ) next = last->previousSibling();
06105     while ( last && !next )
06106     {
06107       last = last->parentNode();
06108       if ( last )
06109         next = last->previousSibling();
06110     }
06111     last = next;
06112   }
06113 
06114   if ( !first || !last )
06115     return;
06116   Q_ASSERT(first->renderer());
06117   Q_ASSERT(last->renderer());
06118   d->m_selectionStart = first;
06119   d->m_startOffset = 0;
06120   d->m_selectionEnd = last;
06121   d->m_endOffset = last->nodeValue().length();
06122   d->m_startBeforeEnd = true;
06123 
06124   d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
06125                           d->m_selectionEnd.handle(), d->m_endOffset );
06126 
06127   emitSelectionChanged();
06128 }
06129 
06130 bool KHTMLPart::checkLinkSecurity(const KURL &linkURL,const QString &message, const QString &button)
06131 {
06132   bool linkAllowed = true;
06133 
06134   if ( d->m_doc )
06135     linkAllowed = kapp && kapp->authorizeURLAction("redirect", url(), linkURL);
06136 
06137   if ( !linkAllowed ) {
06138     khtml::Tokenizer *tokenizer = d->m_doc->tokenizer();
06139     if (tokenizer)
06140       tokenizer->setOnHold(true);
06141 
06142     int response = KMessageBox::Cancel;
06143     if (!message.isEmpty())
06144     {
06145         response = KMessageBox::warningContinueCancel( 0,
06146                                message.arg(linkURL.htmlURL()),
06147                                i18n( "Security Warning" ),
06148                                button);
06149     }
06150     else
06151     {
06152         KMessageBox::error( 0,
06153                 i18n( "<qt>Access by untrusted page to<BR><B>%1</B><BR> denied.").arg(linkURL.htmlURL()),
06154                 i18n( "Security Alert" ));
06155     }
06156 
06157     if (tokenizer)
06158        tokenizer->setOnHold(false);
06159     return (response==KMessageBox::Continue);
06160   }
06161   return true;
06162 }
06163 
06164 void KHTMLPart::slotPartRemoved( KParts::Part *part )
06165 {
06166 //    kdDebug(6050) << "KHTMLPart::slotPartRemoved " << part << endl;
06167     if ( part == d->m_activeFrame )
06168     {
06169         d->m_activeFrame = 0L;
06170         if ( !part->inherits( "KHTMLPart" ) )
06171         {
06172             if (factory()) {
06173                 factory()->removeClient( part );
06174             }
06175             if (childClients()->containsRef(part)) {
06176                 removeChildClient( part );
06177             }
06178         }
06179     }
06180 }
06181 
06182 void KHTMLPart::slotActiveFrameChanged( KParts::Part *part )
06183 {
06184 //    kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged part=" << part << endl;
06185     if ( part == this )
06186     {
06187         kdError(6050) << "strange error! we activated ourselves" << endl;
06188         assert( false );
06189         return;
06190     }
06191 //    kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged d->m_activeFrame=" << d->m_activeFrame << endl;
06192     if ( d->m_activeFrame && d->m_activeFrame->widget() && d->m_activeFrame->widget()->inherits( "QFrame" ) )
06193     {
06194         QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() );
06195         if (frame->frameStyle() != QFrame::NoFrame)
06196         {
06197            frame->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken);
06198            frame->repaint();
06199         }
06200     }
06201 
06202     if( d->m_activeFrame && !d->m_activeFrame->inherits( "KHTMLPart" ) )
06203     {
06204         if (factory()) {
06205             factory()->removeClient( d->m_activeFrame );
06206         }
06207         removeChildClient( d->m_activeFrame );
06208     }
06209     if( part && !part->inherits( "KHTMLPart" ) )
06210     {
06211         if (factory()) {
06212             factory()->addClient( part );
06213         }
06214         insertChildClient( part );
06215     }
06216 
06217 
06218     d->m_activeFrame = part;
06219 
06220     if ( d->m_activeFrame && d->m_activeFrame->widget()->inherits( "QFrame" ) )
06221     {
06222         QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() );
06223         if (frame->frameStyle() != QFrame::NoFrame)
06224         {
06225            frame->setFrameStyle( QFrame::StyledPanel | QFrame::Plain);
06226            frame->repaint();
06227         }
06228         kdDebug(6050) << "new active frame " << d->m_activeFrame << endl;
06229     }
06230 
06231     updateActions();
06232 
06233     // (note: childObject returns 0 if the argument is 0)
06234     d->m_extension->setExtensionProxy( KParts::BrowserExtension::childObject( d->m_activeFrame ) );
06235 }
06236 
06237 void KHTMLPart::setActiveNode(const DOM::Node &node)
06238 {
06239     if (!d->m_doc || !d->m_view)
06240         return;
06241 
06242     // Set the document's active node
06243     d->m_doc->setFocusNode(node.handle());
06244 
06245     // Scroll the view if necessary to ensure that the new focus node is visible
06246     QRect rect  = node.handle()->getRect();
06247     d->m_view->ensureVisible(rect.right(), rect.bottom());
06248     d->m_view->ensureVisible(rect.left(), rect.top());
06249 }
06250 
06251 DOM::Node KHTMLPart::activeNode() const
06252 {
06253     return DOM::Node(d->m_doc?d->m_doc->focusNode():0);
06254 }
06255 
06256 DOM::EventListener *KHTMLPart::createHTMLEventListener( QString code, QString name )
06257 {
06258   KJSProxy *proxy = jScript();
06259 
06260   if (!proxy)
06261     return 0;
06262 
06263   return proxy->createHTMLEventHandler( m_url.url(), name, code );
06264 }
06265 
06266 KHTMLPart *KHTMLPart::opener()
06267 {
06268     return d->m_opener;
06269 }
06270 
06271 void KHTMLPart::setOpener(KHTMLPart *_opener)
06272 {
06273     d->m_opener = _opener;
06274 }
06275 
06276 bool KHTMLPart::openedByJS()
06277 {
06278     return d->m_openedByJS;
06279 }
06280 
06281 void KHTMLPart::setOpenedByJS(bool _openedByJS)
06282 {
06283     d->m_openedByJS = _openedByJS;
06284 }
06285 
06286 void KHTMLPart::preloadStyleSheet(const QString &url, const QString &stylesheet)
06287 {
06288     khtml::Cache::preloadStyleSheet(url, stylesheet);
06289 }
06290 
06291 void KHTMLPart::preloadScript(const QString &url, const QString &script)
06292 {
06293     khtml::Cache::preloadScript(url, script);
06294 }
06295 
06296 QCString KHTMLPart::dcopObjectId() const
06297 {
06298   QCString id;
06299   id.sprintf("html-widget%d", d->m_dcop_counter);
06300   return id;
06301 }
06302 
06303 long KHTMLPart::cacheId() const
06304 {
06305   return d->m_cacheId;
06306 }
06307 
06308 bool KHTMLPart::restored() const
06309 {
06310   return d->m_restored;
06311 }
06312 
06313 bool KHTMLPart::pluginPageQuestionAsked(const QString& mimetype) const
06314 {
06315   // parentPart() should be const!
06316   KHTMLPart* parent = const_cast<KHTMLPart *>(this)->parentPart();
06317   if ( parent )
06318     return parent->pluginPageQuestionAsked(mimetype);
06319 
06320   return d->m_pluginPageQuestionAsked.contains(mimetype);
06321 }
06322 
06323 void KHTMLPart::setPluginPageQuestionAsked(const QString& mimetype)
06324 {
06325   if ( parentPart() )
06326     parentPart()->setPluginPageQuestionAsked(mimetype);
06327 
06328   d->m_pluginPageQuestionAsked.append(mimetype);
06329 }
06330 
06331 void KHTMLPart::slotAutomaticDetectionLanguage( int _id )
06332 {
06333   d->m_automaticDetection->setItemChecked( _id, true );
06334 
06335   switch ( _id ) {
06336     case 0 :
06337       d->m_autoDetectLanguage = khtml::Decoder::SemiautomaticDetection;
06338       break;
06339     case 1 :
06340       d->m_autoDetectLanguage = khtml::Decoder::Arabic;
06341       break;
06342     case 2 :
06343       d->m_autoDetectLanguage = khtml::Decoder::Baltic;
06344       break;
06345     case 3 :
06346       d->m_autoDetectLanguage = khtml::Decoder::CentralEuropean;
06347       break;
06348     case 4 :
06349       d->m_autoDetectLanguage = khtml::Decoder::Chinese;
06350       break;
06351     case 5 :
06352       d->m_autoDetectLanguage = khtml::Decoder::Greek;
06353       break;
06354     case 6 :
06355       d->m_autoDetectLanguage = khtml::Decoder::Hebrew;
06356       break;
06357     case 7 :
06358       d->m_autoDetectLanguage = khtml::Decoder::Japanese;
06359       break;
06360     case 8 :
06361       d->m_autoDetectLanguage = khtml::Decoder::Korean;
06362       break;
06363     case 9 :
06364       d->m_autoDetectLanguage = khtml::Decoder::Russian;
06365       break;
06366     case 10 :
06367       d->m_autoDetectLanguage = khtml::Decoder::Thai;
06368       break;
06369     case 11 :
06370       d->m_autoDetectLanguage = khtml::Decoder::Turkish;
06371       break;
06372     case 12 :
06373       d->m_autoDetectLanguage = khtml::Decoder::Ukrainian;
06374       break;
06375     case 13 :
06376       d->m_autoDetectLanguage = khtml::Decoder::Unicode;
06377       break;
06378     case 14 :
06379       d->m_autoDetectLanguage = khtml::Decoder::WesternEuropean;
06380       break;
06381     default :
06382       d->m_autoDetectLanguage = khtml::Decoder::SemiautomaticDetection;
06383       break;
06384   }
06385 
06386   for ( int i = 0; i <= 14; ++i ) {
06387     if ( i != _id )
06388       d->m_automaticDetection->setItemChecked( i, false );
06389   }
06390 
06391   d->m_paSetEncoding->popupMenu()->setItemChecked( 0, true );
06392 
06393   setEncoding( QString::null, false );
06394 
06395   if( d->m_manualDetection )
06396     d->m_manualDetection->setCurrentItem( -1 );
06397   d->m_paSetEncoding->popupMenu()->setItemChecked( d->m_paSetEncoding->popupMenu()->idAt( 2 ), false );
06398 }
06399 
06400 khtml::Decoder *KHTMLPart::createDecoder()
06401 {
06402   khtml::Decoder *dec = new khtml::Decoder();
06403   if( !d->m_encoding.isNull() )
06404     dec->setEncoding( d->m_encoding.latin1(), true );
06405   else
06406     dec->setEncoding( defaultEncoding().latin1(), d->m_haveEncoding );
06407 
06408   dec->setAutoDetectLanguage( d->m_autoDetectLanguage );
06409   return dec;
06410 }
06411 
06412 void KHTMLPart::emitCaretPositionChanged(const DOM::Node &node, long offset) {
06413   emit caretPositionChanged(node, offset);
06414 }
06415 
06416 void KHTMLPart::restoreScrollPosition()
06417 {
06418   KParts::URLArgs args = d->m_extension->urlArgs();
06419   if (!args.reload) {
06420     disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
06421     return; // should not happen
06422   }
06423 
06424   // Check whether the viewport has become large enough to encompass the stored
06425   // offsets. If the document has been fully loaded, force the new coordinates,
06426   // even if the canvas is too short (can happen when user resizes the window
06427   // during loading).
06428   if (d->m_view->contentsHeight() - d->m_view->visibleHeight() >= args.yOffset
06429       || d->m_bComplete) {
06430     d->m_view->setContentsPos(args.xOffset, args.yOffset);
06431     disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
06432   }
06433 }
06434 
06435 KWallet::Wallet* KHTMLPart::wallet()
06436 {
06437   // ### close wallet after a certain timeout period automatically
06438   //      No - KWallet already does this based on user preferences. (GS)
06439   // ### close wallet after screensaver was enabled
06440   //      No - KWalletD should do this, if anything. (GS)
06441 
06442   KHTMLPart* p;
06443 
06444   for (p = parentPart(); p && p->parentPart(); p = p->parentPart())
06445     ;
06446 
06447   if (p)
06448     return p->wallet();
06449 
06450   if (!d->m_wallet && !d->m_bWalletOpened) {
06451     d->m_wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0);
06452     d->m_bWalletOpened = true;
06453     if (d->m_wallet) {
06454       connect(d->m_wallet, SIGNAL(walletClosed()), SLOT(slotWalletClosed()));
06455       d->m_statusBarWalletLabel = new KURLLabel(d->m_statusBarExtension->statusBar());
06456       d->m_statusBarWalletLabel->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small));
06457       d->m_statusBarWalletLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
06458       d->m_statusBarWalletLabel->setUseCursor(false);
06459       d->m_statusBarExtension->addStatusBarItem(d->m_statusBarWalletLabel, 0, false);
06460       QToolTip::add(d->m_statusBarWalletLabel, i18n("The wallet '%1' is open and being used for form data and passwords.").arg(KWallet::Wallet::NetworkWallet()));
06461       d->m_statusBarWalletLabel->setPixmap(SmallIcon("wallet_open", instance()));
06462       connect(d->m_statusBarWalletLabel, SIGNAL(leftClickedURL()), SLOT(launchWalletManager()));
06463       connect(d->m_statusBarWalletLabel, SIGNAL(rightClickedURL()), SLOT(walletMenu()));
06464     } else if (d->m_statusBarWalletLabel) {
06465       d->m_statusBarExtension->removeStatusBarItem(d->m_statusBarWalletLabel);
06466       delete d->m_statusBarWalletLabel;
06467       d->m_statusBarWalletLabel = 0L;
06468     }
06469   }
06470   return d->m_wallet;
06471 }
06472 
06473 void KHTMLPart::slotWalletClosed()
06474 {
06475   if (d->m_wallet) {
06476     d->m_wallet->deleteLater();
06477     d->m_wallet = 0L;
06478   }
06479   d->m_bWalletOpened = false;
06480   if (d->m_statusBarWalletLabel) {
06481     d->m_statusBarExtension->removeStatusBarItem(d->m_statusBarWalletLabel);
06482     delete d->m_statusBarWalletLabel;
06483     d->m_statusBarWalletLabel = 0L;
06484   }
06485 }
06486 
06487 void KHTMLPart::launchWalletManager()
06488 {
06489   if (!DCOPClient::mainClient()->isApplicationRegistered("kwalletmanager")) {
06490     KApplication::startServiceByDesktopName("kwalletmanager_show");
06491   } else {
06492     DCOPRef r("kwalletmanager", "kwalletmanager-mainwindow#1");
06493     r.send("show");
06494     r.send("raise");
06495   }
06496 }
06497 
06498 void KHTMLPart::walletMenu()
06499 {
06500   KPopupMenu *m = new KPopupMenu(0L);
06501   m->insertItem(i18n("&Close Wallet"), this, SLOT(slotWalletClosed()));
06502   m->popup(QCursor::pos());
06503 }
06504 
06505 void KHTMLPart::slotToggleCaretMode()
06506 {
06507   setCaretMode(d->m_paToggleCaretMode->isChecked());
06508 }
06509 
06510 void KHTMLPart::setFormNotification(KHTMLPart::FormNotification fn) {
06511   d->m_formNotification = fn;
06512 }
06513 
06514 KHTMLPart::FormNotification KHTMLPart::formNotification() const {
06515   return d->m_formNotification;
06516 }
06517 
06518 KURL KHTMLPart::toplevelURL()
06519 {
06520   KHTMLPart* part = this;
06521   while (part->parentPart())
06522     part = part->parentPart();
06523 
06524   if (!part)
06525     return KURL();
06526 
06527   return part->url();
06528 }
06529 
06530 bool KHTMLPart::isModified() const
06531 {
06532   if ( !d->m_doc )
06533     return false;
06534 
06535   return d->m_doc->unsubmittedFormChanges();
06536 }
06537 
06538 void KHTMLPart::setDebugScript( bool enable )
06539 {
06540   unplugActionList( "debugScriptList" );
06541   if ( enable ) {
06542     if (!d->m_paDebugScript) {
06543       d->m_paDebugScript = new KAction( i18n( "JavaScript &Debugger" ), 0, this, SLOT( slotDebugScript() ), actionCollection(), "debugScript" );
06544     }
06545     d->m_paDebugScript->setEnabled( d->m_jscript );
06546     QPtrList<KAction> lst;
06547     lst.append( d->m_paDebugScript );
06548     plugActionList( "debugScriptList", lst );
06549   }
06550   d->m_bJScriptDebugEnabled = enable;
06551 }
06552 
06553 using namespace KParts;
06554 #include "khtml_part.moc"
KDE Logo
This file is part of the documentation for khtml Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Sep 23 17:13:17 2004 by doxygen 1.3.8-20040913 written by Dimitri van Heesch, © 1997-2003