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() || obj->isInlineContinuation() ) );
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 || !child->m_part )
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       connect( child->m_extension, SIGNAL( requestFocus( KParts::ReadOnlyPart * ) ),
04041                this, SLOT( slotRequestFocus( KParts::ReadOnlyPart * ) ) );
04042 
04043       child->m_extension->setBrowserInterface( d->m_extension->browserInterface() );
04044     }
04045   }
04046   else if ( child->m_frame && child->m_part &&
04047             child->m_frame->widget() != child->m_part->widget() )
04048     child->m_frame->setWidget( child->m_part->widget() );
04049 
04050   checkEmitLoadEvent();
04051   // Some JS code in the load event may have destroyed the part
04052   // In that case, abort
04053   if ( !child->m_part )
04054     return false;
04055 
04056   if ( child->m_bPreloaded )
04057   {
04058     if ( child->m_frame && child->m_part )
04059       child->m_frame->setWidget( child->m_part->widget() );
04060 
04061     child->m_bPreloaded = false;
04062     return true;
04063   }
04064 
04065   child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload);
04066 
04067   // make sure the part has a way to find out about the mimetype.
04068   // we actually set it in child->m_args in requestObject already,
04069   // but it's useless if we had to use a KHTMLRun instance, as the
04070   // point the run object is to find out exactly the mimetype.
04071   child->m_args.serviceType = mimetype;
04072 
04073   // if not a frame set child as completed
04074   child->m_bCompleted = child->m_type == khtml::ChildFrame::Object;
04075 
04076   if ( child->m_extension )
04077     child->m_extension->setURLArgs( child->m_args );
04078 
04079   if(url.protocol() == "javascript" || url.url() == "about:blank") {
04080       if (!child->m_part->inherits("KHTMLPart"))
04081           return false;
04082 
04083       KHTMLPart* p = static_cast<KHTMLPart*>(static_cast<KParts::ReadOnlyPart *>(child->m_part));
04084 
04085       p->begin();
04086       if (d->m_doc && p->d->m_doc)
04087         p->d->m_doc->setBaseURL(d->m_doc->baseURL());
04088       if (!url.url().startsWith("about:")) {
04089         p->write(url.path());
04090       } else {
04091     p->m_url = url;
04092         // we need a body element. testcase: <iframe id="a"></iframe><script>alert(a.document.body);</script>
04093         p->write("<HTML><TITLE></TITLE><BODY></BODY></HTML>");
04094       }
04095       p->end();
04096       return true;
04097   }
04098   else if ( !url.isEmpty() )
04099   {
04100       //kdDebug( 6050 ) << "opening " << url.url() << " in frame " << child->m_part << endl;
04101       bool b = child->m_part->openURL( url );
04102       if (child->m_bCompleted)
04103           checkCompleted();
04104       return b;
04105   }
04106   else
04107   {
04108       child->m_bCompleted = true;
04109       checkCompleted();
04110       return true;
04111   }
04112 }
04113 
04114 KParts::ReadOnlyPart *KHTMLPart::createPart( QWidget *parentWidget, const char *widgetName,
04115                                              QObject *parent, const char *name, const QString &mimetype,
04116                                              QString &serviceName, QStringList &serviceTypes,
04117                                              const QStringList &params )
04118 {
04119   QString constr;
04120   if ( !serviceName.isEmpty() )
04121     constr.append( QString::fromLatin1( "Name == '%1'" ).arg( serviceName ) );
04122 
04123   KTrader::OfferList offers = KTrader::self()->query( mimetype, "KParts/ReadOnlyPart", constr, QString::null );
04124 
04125   if ( offers.isEmpty() )
04126     return 0L;
04127 
04128   KTrader::OfferList::Iterator it = offers.begin();
04129   for (  ; it != offers.end() ; ++it )
04130   {
04131     KService::Ptr service = (*it);
04132 
04133     KLibFactory *factory = KLibLoader::self()->factory( QFile::encodeName(service->library()) );
04134     if ( factory ) {
04135       KParts::ReadOnlyPart *res = 0L;
04136 
04137       const char *className = "KParts::ReadOnlyPart";
04138       if ( service->serviceTypes().contains( "Browser/View" ) )
04139         className = "Browser/View";
04140 
04141       if ( factory->inherits( "KParts::Factory" ) )
04142         res = static_cast<KParts::ReadOnlyPart *>(static_cast<KParts::Factory *>( factory )->createPart( parentWidget, widgetName, parent, name, className, params ));
04143       else
04144         res = static_cast<KParts::ReadOnlyPart *>(factory->create( parentWidget, widgetName, className ));
04145 
04146       if ( res ) {
04147         serviceTypes = service->serviceTypes();
04148         serviceName = service->name();
04149         return res;
04150       }
04151     } else {
04152       // TODO KMessageBox::error and i18n, like in KonqFactory::createView?
04153       kdWarning() << QString("There was an error loading the module %1.\nThe diagnostics is:\n%2")
04154                       .arg(service->name()).arg(KLibLoader::self()->lastErrorMessage()) << endl;
04155     }
04156   }
04157   return 0;
04158 }
04159 
04160 KParts::PartManager *KHTMLPart::partManager()
04161 {
04162   if ( !d->m_manager )
04163   {
04164     d->m_manager = new KParts::PartManager( d->m_view->topLevelWidget(), this, "khtml part manager" );
04165     d->m_manager->setAllowNestedParts( true );
04166     connect( d->m_manager, SIGNAL( activePartChanged( KParts::Part * ) ),
04167              this, SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
04168     connect( d->m_manager, SIGNAL( partRemoved( KParts::Part * ) ),
04169              this, SLOT( slotPartRemoved( KParts::Part * ) ) );
04170   }
04171 
04172   return d->m_manager;
04173 }
04174 
04175 void KHTMLPart::submitFormAgain()
04176 {
04177   if( d->m_doc && !d->m_doc->parsing() && d->m_submitForm)
04178     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 );
04179 
04180   delete d->m_submitForm;
04181   d->m_submitForm = 0;
04182   disconnect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
04183 }
04184 
04185 void KHTMLPart::submitFormProxy( const char *action, const QString &url, const QByteArray &formData, const QString &_target, const QString& contentType, const QString& boundary )
04186 {
04187   submitForm(action, url, formData, _target, contentType, boundary);
04188 }
04189 
04190 void KHTMLPart::submitForm( const char *action, const QString &url, const QByteArray &formData, const QString &_target, const QString& contentType, const QString& boundary )
04191 {
04192   kdDebug(6000) << this << ": KHTMLPart::submitForm target=" << _target << " url=" << url << endl;
04193   if (d->m_formNotification == KHTMLPart::Only) {
04194     emit formSubmitNotification(action, url, formData, _target, contentType, boundary);
04195     return;
04196   } else if (d->m_formNotification == KHTMLPart::Before) {
04197     emit formSubmitNotification(action, url, formData, _target, contentType, boundary);
04198   }
04199 
04200   KURL u = completeURL( url );
04201 
04202   if ( !u.isValid() )
04203   {
04204     // ### ERROR HANDLING!
04205     return;
04206   }
04207 
04208   // Form security checks
04209   //
04210   /*
04211    * If these form security checks are still in this place in a month or two
04212    * I'm going to simply delete them.
04213    */
04214 
04215   /* This is separate for a reason.  It has to be _before_ all script, etc,
04216    * AND I don't want to break anything that uses checkLinkSecurity() in
04217    * other places.
04218    */
04219 
04220   if (!d->m_submitForm) {
04221     if (u.protocol() != "https" && u.protocol() != "mailto") {
04222       if (d->m_ssl_in_use) {    // Going from SSL -> nonSSL
04223         int rc = KMessageBox::warningContinueCancel(NULL, i18n("Warning:  This is a secure form but it is attempting to send your data back unencrypted."
04224                                                                "\nA third party may be able to intercept and view this information."
04225                                                                "\nAre you sure you wish to continue?"),
04226                                                     i18n("Network Transmission"),KGuiItem(i18n("&Send Unencrypted")));
04227         if (rc == KMessageBox::Cancel)
04228           return;
04229       } else {                  // Going from nonSSL -> nonSSL
04230         KSSLSettings kss(true);
04231         if (kss.warnOnUnencrypted()) {
04232           int rc = KMessageBox::warningContinueCancel(NULL,
04233                                                       i18n("Warning: Your data is about to be transmitted across the network unencrypted."
04234                                                            "\nAre you sure you wish to continue?"),
04235                                                       i18n("Network Transmission"),
04236                                                       KGuiItem(i18n("&Send Unencrypted")),
04237                                                       "WarnOnUnencryptedForm");
04238           // Move this setting into KSSL instead
04239           KConfig *config = kapp->config();
04240           QString grpNotifMsgs = QString::fromLatin1("Notification Messages");
04241           KConfigGroupSaver saver( config, grpNotifMsgs );
04242 
04243           if (!config->readBoolEntry("WarnOnUnencryptedForm", true)) {
04244             config->deleteEntry("WarnOnUnencryptedForm");
04245             config->sync();
04246             kss.setWarnOnUnencrypted(false);
04247             kss.save();
04248           }
04249           if (rc == KMessageBox::Cancel)
04250             return;
04251         }
04252       }
04253     }
04254 
04255     if (u.protocol() == "mailto") {
04256       int rc = KMessageBox::warningContinueCancel(NULL,
04257                                                   i18n("This site is attempting to submit form data via email.\n"
04258                                                        "Do you want to continue?"),
04259                                                   i18n("Network Transmission"),
04260                                                   KGuiItem(i18n("&Send Email")),
04261                                                   "WarnTriedEmailSubmit");
04262 
04263       if (rc == KMessageBox::Cancel) {
04264         return;
04265       }
04266     }
04267   }
04268 
04269   // End form security checks
04270   //
04271 
04272   QString urlstring = u.url();
04273 
04274   if ( urlstring.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
04275     urlstring = KURL::decode_string(urlstring);
04276     crossFrameExecuteScript( _target, urlstring.right( urlstring.length() - 11) );
04277     return;
04278   }
04279 
04280   if (!checkLinkSecurity(u,
04281              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?" ),
04282              i18n( "Submit" )))
04283     return;
04284 
04285   KParts::URLArgs args;
04286 
04287   if (!d->m_referrer.isEmpty())
04288      args.metaData()["referrer"] = d->m_referrer;
04289 
04290   args.metaData().insert("PropagateHttpHeader", "true");
04291   args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
04292   args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
04293   args.metaData().insert("main_frame_request",
04294                          parentPart() == 0 ? "TRUE":"FALSE");
04295   args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
04296   args.metaData().insert("ssl_activate_warnings", "TRUE");
04297 //WABA: When we post a form we should treat it as the main url
04298 //the request should never be considered cross-domain
04299 //args.metaData().insert("cross-domain", toplevelURL().url());
04300   args.frameName = _target.isEmpty() ? d->m_doc->baseTarget() : _target ;
04301 
04302   // Handle mailto: forms
04303   if (u.protocol() == "mailto") {
04304       // 1)  Check for attach= and strip it
04305       QString q = u.query().mid(1);
04306       QStringList nvps = QStringList::split("&", q);
04307       bool triedToAttach = false;
04308 
04309       for (QStringList::Iterator nvp = nvps.begin(); nvp != nvps.end(); ++nvp) {
04310          QStringList pair = QStringList::split("=", *nvp);
04311          if (pair.count() >= 2) {
04312             if (pair.first().lower() == "attach") {
04313                nvp = nvps.remove(nvp);
04314                triedToAttach = true;
04315             }
04316          }
04317       }
04318 
04319       if (triedToAttach)
04320          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");
04321 
04322       // 2)  Append body=
04323       QString bodyEnc;
04324       if (contentType.lower() == "multipart/form-data") {
04325          // FIXME: is this correct?  I suspect not
04326          bodyEnc = KURL::encode_string(QString::fromLatin1(formData.data(),
04327                                                            formData.size()));
04328       } else if (contentType.lower() == "text/plain") {
04329          // Convention seems to be to decode, and s/&/\n/
04330          QString tmpbody = QString::fromLatin1(formData.data(),
04331                                                formData.size());
04332          tmpbody.replace(QRegExp("[&]"), "\n");
04333          tmpbody.replace(QRegExp("[+]"), " ");
04334          tmpbody = KURL::decode_string(tmpbody);  // Decode the rest of it
04335          bodyEnc = KURL::encode_string(tmpbody);  // Recode for the URL
04336       } else {
04337          bodyEnc = KURL::encode_string(QString::fromLatin1(formData.data(),
04338                                                            formData.size()));
04339       }
04340 
04341       nvps.append(QString("body=%1").arg(bodyEnc));
04342       q = nvps.join("&");
04343       u.setQuery(q);
04344   }
04345 
04346   if ( strcmp( action, "get" ) == 0 ) {
04347     if (u.protocol() != "mailto")
04348        u.setQuery( QString::fromLatin1( formData.data(), formData.size() ) );
04349     args.setDoPost( false );
04350   }
04351   else {
04352     args.postData = formData;
04353     args.setDoPost( true );
04354 
04355     // construct some user headers if necessary
04356     if (contentType.isNull() || contentType == "application/x-www-form-urlencoded")
04357       args.setContentType( "Content-Type: application/x-www-form-urlencoded" );
04358     else // contentType must be "multipart/form-data"
04359       args.setContentType( "Content-Type: " + contentType + "; boundary=" + boundary );
04360   }
04361 
04362   if ( d->m_doc->parsing() || d->m_runningScripts > 0 ) {
04363     if( d->m_submitForm ) {
04364       kdDebug(6000) << "KHTMLPart::submitForm ABORTING!" << endl;
04365       return;
04366     }
04367     d->m_submitForm = new KHTMLPartPrivate::SubmitForm;
04368     d->m_submitForm->submitAction = action;
04369     d->m_submitForm->submitUrl = url;
04370     d->m_submitForm->submitFormData = formData;
04371     d->m_submitForm->target = _target;
04372     d->m_submitForm->submitContentType = contentType;
04373     d->m_submitForm->submitBoundary = boundary;
04374     connect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
04375   }
04376   else
04377   {
04378     emit d->m_extension->openURLRequest( u, args );
04379   }
04380 }
04381 
04382 void KHTMLPart::popupMenu( const QString &linkUrl )
04383 {
04384   KURL popupURL;
04385   KURL linkKURL;
04386   QString referrer;
04387   KParts::BrowserExtension::PopupFlags itemflags=KParts::BrowserExtension::ShowBookmark | KParts::BrowserExtension::ShowReload;
04388 
04389   if ( linkUrl.isEmpty() ) { // click on background
04390     KHTMLPart* khtmlPart = this;
04391     while ( khtmlPart->parentPart() )
04392     {
04393       khtmlPart=khtmlPart->parentPart();
04394     }
04395     popupURL = khtmlPart->url();
04396     referrer = khtmlPart->pageReferrer();
04397     if (hasSelection())
04398       itemflags = KParts::BrowserExtension::ShowTextSelectionItems;
04399     else
04400       itemflags |= KParts::BrowserExtension::ShowNavigationItems;
04401   } else {               // click on link
04402     popupURL = completeURL( linkUrl );
04403     linkKURL = popupURL;
04404     referrer = this->referrer();
04405   }
04406 
04407   // Danger, Will Robinson. The Popup might stay around for a much
04408   // longer time than KHTMLPart. Deal with it.
04409   KHTMLPopupGUIClient* client = new KHTMLPopupGUIClient( this, d->m_popupMenuXML, linkKURL );
04410   QGuardedPtr<QObject> guard( client );
04411 
04412   KParts::URLArgs args;
04413   args.serviceType = QString::fromLatin1( "text/html" );
04414   args.metaData()["referrer"] = referrer;
04415 
04416   emit d->m_extension->popupMenu( client, QCursor::pos(), popupURL, args, itemflags, S_IFREG /*always a file*/);
04417 
04418   if ( !guard.isNull() ) {
04419      delete client;
04420      emit popupMenu(linkUrl, QCursor::pos());
04421      d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
04422   }
04423 }
04424 
04425 void KHTMLPart::slotParentCompleted()
04426 {
04427   if ( !d->m_redirectURL.isEmpty() && !d->m_redirectionTimer.isActive() )
04428   {
04429     // kdDebug(6050) << this << ": Child redirection -> " << d->m_redirectURL << endl;
04430     d->m_redirectionTimer.start( 1000 * d->m_delayRedirect, true );
04431   }
04432 }
04433 
04434 void KHTMLPart::slotChildStarted( KIO::Job *job )
04435 {
04436   khtml::ChildFrame *child = frame( sender() );
04437 
04438   assert( child );
04439 
04440   child->m_bCompleted = false;
04441 
04442   if ( d->m_bComplete )
04443   {
04444 #if 0
04445     // WABA: Looks like this belongs somewhere else
04446     if ( !parentPart() ) // "toplevel" html document? if yes, then notify the hosting browser about the document (url) changes
04447     {
04448       emit d->m_extension->openURLNotify();
04449     }
04450 #endif
04451     d->m_bComplete = false;
04452     emit started( job );
04453   }
04454 }
04455 
04456 void KHTMLPart::slotChildCompleted()
04457 {
04458   slotChildCompleted( false );
04459 }
04460 
04461 void KHTMLPart::slotChildCompleted( bool pendingAction )
04462 {
04463   khtml::ChildFrame *child = frame( sender() );
04464 
04465   if ( child ) {
04466     kdDebug(6050) << this << " slotChildCompleted child=" << child << " m_frame=" << child->m_frame << endl;
04467     child->m_bCompleted = true;
04468     child->m_bPendingRedirection = pendingAction;
04469     child->m_args = KParts::URLArgs();
04470   }
04471   checkCompleted();
04472 }
04473 
04474 void KHTMLPart::slotChildDocCreated()
04475 {
04476   const KHTMLPart* htmlFrame = static_cast<const KHTMLPart *>(sender());
04477   // Set domain to the frameset's domain
04478   // This must only be done when loading the frameset initially (#22039),
04479   // not when following a link in a frame (#44162).
04480   if ( d->m_doc && d->m_doc->isHTMLDocument() )
04481   {
04482     if ( sender()->inherits("KHTMLPart") )
04483     {
04484       DOMString domain = static_cast<HTMLDocumentImpl*>(d->m_doc)->domain();
04485       if (htmlFrame->d->m_doc && htmlFrame->d->m_doc->isHTMLDocument() )
04486         //kdDebug(6050) << "KHTMLPart::slotChildDocCreated: url: " << htmlFrame->m_url.url() << endl;
04487         static_cast<HTMLDocumentImpl*>(htmlFrame->d->m_doc)->setDomain( domain );
04488     }
04489   }
04490   // So it only happens once
04491   disconnect( htmlFrame, SIGNAL( docCreated() ), this, SLOT( slotChildDocCreated() ) );
04492 }
04493 
04494 void KHTMLPart::slotChildURLRequest( const KURL &url, const KParts::URLArgs &args )
04495 {
04496   khtml::ChildFrame *child = frame( sender()->parent() );
04497   KHTMLPart *callingHtmlPart = const_cast<KHTMLPart *>(dynamic_cast<const KHTMLPart *>(sender()->parent()));
04498 
04499   // TODO: handle child target correctly! currently the script are always executed fur the parent
04500   QString urlStr = url.url();
04501   if ( urlStr.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
04502       QString script = KURL::decode_string( urlStr.right( urlStr.length() - 11 ) );
04503       executeScript( DOM::Node(), script );
04504       return;
04505   }
04506 
04507   QString frameName = args.frameName.lower();
04508   if ( !frameName.isEmpty() ) {
04509     if ( frameName == QString::fromLatin1( "_top" ) )
04510     {
04511       emit d->m_extension->openURLRequest( url, args );
04512       return;
04513     }
04514     else if ( frameName == QString::fromLatin1( "_blank" ) )
04515     {
04516       emit d->m_extension->createNewWindow( url, args );
04517       return;
04518     }
04519     else if ( frameName == QString::fromLatin1( "_parent" ) )
04520     {
04521       KParts::URLArgs newArgs( args );
04522       newArgs.frameName = QString::null;
04523 
04524       emit d->m_extension->openURLRequest( url, newArgs );
04525       return;
04526     }
04527     else if ( frameName != QString::fromLatin1( "_self" ) )
04528     {
04529       khtml::ChildFrame *_frame = recursiveFrameRequest( callingHtmlPart, url, args );
04530 
04531       if ( !_frame )
04532       {
04533         emit d->m_extension->openURLRequest( url, args );
04534         return;
04535       }
04536 
04537       child = _frame;
04538     }
04539   }
04540 
04541   if ( child && child->m_type != khtml::ChildFrame::Object ) {
04542       // Inform someone that we are about to show something else.
04543       child->m_bNotify = true;
04544       requestObject( child, url, args );
04545   }  else if ( frameName== "_self" ) // this is for embedded objects (via <object>) which want to replace the current document
04546   {
04547       KParts::URLArgs newArgs( args );
04548       newArgs.frameName = QString::null;
04549       emit d->m_extension->openURLRequest( url, newArgs );
04550   }
04551 }
04552 
04553 void KHTMLPart::slotRequestFocus( KParts::ReadOnlyPart * )
04554 {
04555   emit d->m_extension->requestFocus(this);
04556 }
04557 
04558 khtml::ChildFrame *KHTMLPart::frame( const QObject *obj )
04559 {
04560     assert( obj->inherits( "KParts::ReadOnlyPart" ) );
04561     const KParts::ReadOnlyPart *part = static_cast<const KParts::ReadOnlyPart *>( obj );
04562 
04563     FrameIt it = d->m_frames.begin();
04564     FrameIt end = d->m_frames.end();
04565     for (; it != end; ++it )
04566       if ( (KParts::ReadOnlyPart *)(*it).m_part == part )
04567         return &(*it);
04568 
04569     for (it = d->m_objects.begin(); it != d->m_objects.end(); ++it )
04570       if ( (KParts::ReadOnlyPart *)(*it).m_part == part )
04571         return &(*it);
04572 
04573     return 0L;
04574 }
04575 
04576 //#define DEBUG_FINDFRAME
04577 
04578 bool KHTMLPart::checkFrameAccess(KHTMLPart *callingHtmlPart)
04579 {
04580   if (callingHtmlPart == this)
04581     return true; // trivial
04582 
04583   if (htmlDocument().isNull()) {
04584 #ifdef DEBUG_FINDFRAME
04585     kdDebug(6050) << "KHTMLPart::checkFrameAccess: Empty part " << this << " URL = " << m_url << endl;
04586 #endif
04587     return false; // we are empty?
04588   }
04589 
04590   // now compare the domains
04591   if (callingHtmlPart && !callingHtmlPart->htmlDocument().isNull() &&
04592       !htmlDocument().isNull())  {
04593     DOM::DOMString actDomain = callingHtmlPart->htmlDocument().domain();
04594     DOM::DOMString destDomain = htmlDocument().domain();
04595 
04596 #ifdef DEBUG_FINDFRAME
04597     kdDebug(6050) << "KHTMLPart::checkFrameAccess: actDomain = '" << actDomain.string() << "' destDomain = '" << destDomain.string() << "'" << endl;
04598 #endif
04599 
04600     if (actDomain == destDomain)
04601       return true;
04602   }
04603 #ifdef DEBUG_FINDFRAME
04604   else
04605   {
04606     kdDebug(6050) << "KHTMLPart::checkFrameAccess: Unknown part/domain " << callingHtmlPart << " tries to access part " << this << endl;
04607   }
04608 #endif
04609   return false;
04610 }
04611 
04612 KHTMLPart *
04613 KHTMLPart::findFrameParent( KParts::ReadOnlyPart *callingPart, const QString &f, khtml::ChildFrame **childFrame )
04614 {
04615 #ifdef DEBUG_FINDFRAME
04616   kdDebug(6050) << "KHTMLPart::findFrameParent: this = " << this << " URL = " << m_url << " findFrameParent( " << f << " )" << endl;
04617 #endif
04618   // Check access
04619   KHTMLPart *callingHtmlPart = dynamic_cast<KHTMLPart *>(callingPart);
04620   
04621   if (!checkFrameAccess(callingHtmlPart))
04622      return 0;
04623 
04624   FrameIt it = d->m_frames.find( f );
04625   FrameIt end = d->m_frames.end();
04626   if ( it != end )
04627   {
04628 #ifdef DEBUG_FINDFRAME
04629      kdDebug(6050) << "KHTMLPart::findFrameParent: FOUND!" << endl;
04630 #endif
04631      if (childFrame)
04632         *childFrame = &(*it);
04633      return this;
04634   }
04635      
04636   it = d->m_frames.begin();
04637   for (; it != end; ++it )
04638   {
04639     KParts::ReadOnlyPart *p = (*it).m_part;
04640     if ( p && p->inherits( "KHTMLPart" ))
04641     {
04642       KHTMLPart *frameParent = static_cast<KHTMLPart*>(p)->findFrameParent(callingPart, f, childFrame);
04643       if (frameParent)
04644          return frameParent;
04645     }
04646   }
04647   return 0;
04648 }
04649 
04650 
04651 KHTMLPart *KHTMLPart::findFrame( const QString &f )
04652 {
04653   khtml::ChildFrame *childFrame;
04654   KHTMLPart *parentFrame = findFrameParent(this, f, &childFrame);
04655   if (parentFrame)
04656   {
04657      KParts::ReadOnlyPart *p = childFrame->m_part;
04658      if ( p && p->inherits( "KHTMLPart" ))
04659         return static_cast<KHTMLPart *>(p);
04660   }
04661   return 0;
04662 }
04663 
04664 KParts::ReadOnlyPart *KHTMLPart::currentFrame() const
04665 {
04666   KParts::ReadOnlyPart* part = (KParts::ReadOnlyPart*)(this);
04667   // Find active part in our frame manager, in case we are a frameset
04668   // and keep doing that (in case of nested framesets).
04669   // Just realized we could also do this recursively, calling part->currentFrame()...
04670   while ( part && part->inherits("KHTMLPart") &&
04671           static_cast<KHTMLPart *>(part)->d->m_frames.count() > 0 ) {
04672     KHTMLPart* frameset = static_cast<KHTMLPart *>(part);
04673     part = static_cast<KParts::ReadOnlyPart *>(frameset->partManager()->activePart());
04674     if ( !part ) return frameset;
04675   }
04676   return part;
04677 }
04678 
04679 bool KHTMLPart::frameExists( const QString &frameName )
04680 {
04681   ConstFrameIt it = d->m_frames.find( frameName );
04682   if ( it == d->m_frames.end() )
04683     return false;
04684 
04685   // WABA: We only return true if the child actually has a frame
04686   // set. Otherwise we might find our preloaded-selve.
04687   // This happens when we restore the frameset.
04688   return (!(*it).m_frame.isNull());
04689 }
04690 
04691 KHTMLPart *KHTMLPart::parentPart()
04692 {
04693   if ( !parent() || !parent()->inherits( "KHTMLPart" ) )
04694     return 0L;
04695 
04696   return (KHTMLPart *)parent();
04697 }
04698 
04699 khtml::ChildFrame *KHTMLPart::recursiveFrameRequest( KHTMLPart *callingHtmlPart, const KURL &url, 
04700                                                      const KParts::URLArgs &args, bool callParent )
04701 {
04702 #ifdef DEBUG_FINDFRAME
04703   kdDebug( 6050 ) << "KHTMLPart::recursiveFrameRequest this = " << this << ", frame = " << args.frameName << ", url = " << url << endl;
04704 #endif  
04705   khtml::ChildFrame *childFrame;
04706   KHTMLPart *childPart = findFrameParent(callingHtmlPart, args.frameName, &childFrame);
04707   if (childPart)
04708   {
04709      if (childPart == this)
04710         return childFrame;
04711      
04712      childPart->requestObject( childFrame, url, args );
04713      return 0;
04714   }
04715 
04716   if ( parentPart() && callParent )
04717   {
04718      khtml::ChildFrame *res = parentPart()->recursiveFrameRequest( callingHtmlPart, url, args, callParent );
04719 
04720      if ( res )
04721        parentPart()->requestObject( res, url, args );
04722   }
04723 
04724   return 0L;
04725 }
04726 
04727 void KHTMLPart::saveState( QDataStream &stream )
04728 {
04729   kdDebug( 6050 ) << "KHTMLPart::saveState this = " << this << " saving URL " << m_url.url() << endl;
04730 
04731   stream << m_url << (Q_INT32)d->m_view->contentsX() << (Q_INT32)d->m_view->contentsY()
04732          << (Q_INT32) d->m_view->contentsWidth() << (Q_INT32) d->m_view->contentsHeight() << (Q_INT32) d->m_view->marginWidth() << (Q_INT32) d->m_view->marginHeight();
04733 
04734   // save link cursor position
04735   int focusNodeNumber;
04736   if (!d->m_focusNodeRestored)
04737       focusNodeNumber = d->m_focusNodeNumber;
04738   else if (d->m_doc && d->m_doc->focusNode())
04739       focusNodeNumber = d->m_doc->nodeAbsIndex(d->m_doc->focusNode());
04740   else
04741       focusNodeNumber = -1;
04742   stream << focusNodeNumber;
04743 
04744   // Save the doc's cache id.
04745   stream << d->m_cacheId;
04746 
04747   // Save the state of the document (Most notably the state of any forms)
04748   QStringList docState;
04749   if (d->m_doc)
04750   {
04751      docState = d->m_doc->docState();
04752   }
04753   stream << d->m_encoding << d->m_sheetUsed << docState;
04754 
04755   stream << d->m_zoomFactor;
04756 
04757   stream << d->m_httpHeaders;
04758   stream << d->m_pageServices;
04759   stream << d->m_pageReferrer;
04760 
04761   // Save ssl data
04762   stream << d->m_ssl_in_use
04763          << d->m_ssl_peer_certificate
04764          << d->m_ssl_peer_chain
04765          << d->m_ssl_peer_ip
04766          << d->m_ssl_cipher
04767          << d->m_ssl_cipher_desc
04768          << d->m_ssl_cipher_version
04769          << d->m_ssl_cipher_used_bits
04770          << d->m_ssl_cipher_bits
04771          << d->m_ssl_cert_state
04772          << d->m_ssl_parent_ip
04773          << d->m_ssl_parent_cert;
04774 
04775 
04776   QStringList frameNameLst, frameServiceTypeLst, frameServiceNameLst;
04777   KURL::List frameURLLst;
04778   QValueList<QByteArray> frameStateBufferLst;
04779 
04780   ConstFrameIt it = d->m_frames.begin();
04781   ConstFrameIt end = d->m_frames.end();
04782   for (; it != end; ++it )
04783   {
04784     if ( !(*it).m_part )
04785        continue;
04786 
04787     frameNameLst << (*it).m_name;
04788     frameServiceTypeLst << (*it).m_serviceType;
04789     frameServiceNameLst << (*it).m_serviceName;
04790     frameURLLst << (*it).m_part->url();
04791 
04792     QByteArray state;
04793     QDataStream frameStream( state, IO_WriteOnly );
04794 
04795     if ( (*it).m_extension )
04796       (*it).m_extension->saveState( frameStream );
04797 
04798     frameStateBufferLst << state;
04799   }
04800 
04801   // Save frame data
04802   stream << (Q_UINT32) frameNameLst.count();
04803   stream << frameNameLst << frameServiceTypeLst << frameServiceNameLst << frameURLLst << frameStateBufferLst;
04804 }
04805 
04806 void KHTMLPart::restoreState( QDataStream &stream )
04807 {
04808   KURL u;
04809   Q_INT32 xOffset, yOffset, wContents, hContents, mWidth, mHeight;
04810   Q_UINT32 frameCount;
04811   QStringList frameNames, frameServiceTypes, docState, frameServiceNames;
04812   KURL::List frameURLs;
04813   QValueList<QByteArray> frameStateBuffers;
04814   QValueList<int> fSizes;
04815   QString encoding, sheetUsed;
04816   long old_cacheId = d->m_cacheId;
04817 
04818   stream >> u >> xOffset >> yOffset >> wContents >> hContents >> mWidth >> mHeight;
04819 
04820   d->m_view->setMarginWidth( mWidth );
04821   d->m_view->setMarginHeight( mHeight );
04822 
04823   // restore link cursor position
04824   // nth node is active. value is set in checkCompleted()
04825   stream >> d->m_focusNodeNumber;
04826   d->m_focusNodeRestored = false;
04827 
04828   stream >> d->m_cacheId;
04829 
04830   stream >> encoding >> sheetUsed >> docState;
04831 
04832   d->m_encoding = encoding;
04833   d->m_sheetUsed = sheetUsed;
04834 
04835   int zoomFactor;
04836   stream >> zoomFactor;
04837   setZoomFactor(zoomFactor);
04838 
04839   stream >> d->m_httpHeaders;
04840   stream >> d->m_pageServices;
04841   stream >> d->m_pageReferrer;
04842 
04843   // Restore ssl data
04844   stream >> d->m_ssl_in_use
04845          >> d->m_ssl_peer_certificate
04846          >> d->m_ssl_peer_chain
04847          >> d->m_ssl_peer_ip
04848          >> d->m_ssl_cipher
04849          >> d->m_ssl_cipher_desc
04850          >> d->m_ssl_cipher_version
04851          >> d->m_ssl_cipher_used_bits
04852          >> d->m_ssl_cipher_bits
04853          >> d->m_ssl_cert_state
04854          >> d->m_ssl_parent_ip
04855          >> d->m_ssl_parent_cert;
04856 
04857   setPageSecurity( d->m_ssl_in_use ? Encrypted : NotCrypted );
04858 
04859   stream >> frameCount >> frameNames >> frameServiceTypes >> frameServiceNames
04860          >> frameURLs >> frameStateBuffers;
04861 
04862   d->m_bComplete = false;
04863   d->m_bLoadEventEmitted = false;
04864 
04865 //   kdDebug( 6050 ) << "restoreStakte() docState.count() = " << docState.count() << endl;
04866 //   kdDebug( 6050 ) << "m_url " << m_url.url() << " <-> " << u.url() << endl;
04867 //   kdDebug( 6050 ) << "m_frames.count() " << d->m_frames.count() << " <-> " << frameCount << endl;
04868 
04869   if (d->m_cacheId == old_cacheId)
04870   {
04871     // Partial restore
04872     d->m_redirectionTimer.stop();
04873 
04874     FrameIt fIt = d->m_frames.begin();
04875     FrameIt fEnd = d->m_frames.end();
04876 
04877     for (; fIt != fEnd; ++fIt )
04878         (*fIt).m_bCompleted = false;
04879 
04880     fIt = d->m_frames.begin();
04881 
04882     QStringList::ConstIterator fNameIt = frameNames.begin();
04883     QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
04884     QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
04885     KURL::List::ConstIterator fURLIt = frameURLs.begin();
04886     QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
04887 
04888     for (; fIt != fEnd; ++fIt, ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
04889     {
04890       khtml::ChildFrame *child = &(*fIt);
04891 
04892 //      kdDebug( 6050 ) <<  *fNameIt  << " ---- " <<  *fServiceTypeIt << endl;
04893 
04894       if ( child->m_name != *fNameIt || child->m_serviceType != *fServiceTypeIt )
04895       {
04896         child->m_bPreloaded = true;
04897         child->m_name = *fNameIt;
04898         child->m_serviceName = *fServiceNameIt;
04899         processObjectRequest( child, *fURLIt, *fServiceTypeIt );
04900       }
04901 
04902       if ( child->m_part )
04903       {
04904         child->m_bCompleted = false;
04905         if ( child->m_extension && !(*fBufferIt).isEmpty() )
04906         {
04907           QDataStream frameStream( *fBufferIt, IO_ReadOnly );
04908           child->m_extension->restoreState( frameStream );
04909         }
04910         else
04911           child->m_part->openURL( *fURLIt );
04912       }
04913     }
04914 
04915     KParts::URLArgs args( d->m_extension->urlArgs() );
04916     args.xOffset = xOffset;
04917     args.yOffset = yOffset;
04918     args.docState = docState;
04919     d->m_extension->setURLArgs( args );
04920 
04921     d->m_view->resizeContents( wContents,  hContents);
04922     d->m_view->setContentsPos( xOffset, yOffset );
04923 
04924     m_url = u;
04925   }
04926   else
04927   {
04928     // Full restore.
04929     closeURL();
04930     // We must force a clear because we want to be sure to delete all
04931     // frames.
04932     d->m_bCleared = false;
04933     clear();
04934     d->m_encoding = encoding;
04935     d->m_sheetUsed = sheetUsed;
04936 
04937     QStringList::ConstIterator fNameIt = frameNames.begin();
04938     QStringList::ConstIterator fNameEnd = frameNames.end();
04939 
04940     QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
04941     QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
04942     KURL::List::ConstIterator fURLIt = frameURLs.begin();
04943     QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
04944 
04945     for (; fNameIt != fNameEnd; ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
04946     {
04947       khtml::ChildFrame newChild;
04948       newChild.m_bPreloaded = true;
04949       newChild.m_name = *fNameIt;
04950       newChild.m_serviceName = *fServiceNameIt;
04951 
04952 //      kdDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt << endl;
04953 
04954       FrameIt childFrame = d->m_frames.append( newChild );
04955 
04956       processObjectRequest( &(*childFrame), *fURLIt, *fServiceTypeIt );
04957 
04958       (*childFrame).m_bPreloaded = true;
04959 
04960       if ( (*childFrame).m_part )
04961       {
04962         if ( (*childFrame).m_extension )
04963         if ( (*childFrame).m_extension && !(*fBufferIt).isEmpty() )
04964         {
04965           QDataStream frameStream( *fBufferIt, IO_ReadOnly );
04966           (*childFrame).m_extension->restoreState( frameStream );
04967         }
04968         else
04969           (*childFrame).m_part->openURL( *fURLIt );
04970       }
04971     }
04972 
04973     KParts::URLArgs args( d->m_extension->urlArgs() );
04974     args.xOffset = xOffset;
04975     args.yOffset = yOffset;
04976     args.docState = docState;
04977 
04978     d->m_view->resizeContents( wContents,  hContents);
04979     d->m_view->setContentsPos( xOffset, yOffset );
04980 
04981     d->m_extension->setURLArgs( args );
04982     if (!KHTMLPageCache::self()->isComplete(d->m_cacheId))
04983     {
04984        d->m_restored = true;
04985        openURL( u );
04986        d->m_restored = false;
04987     }
04988     else
04989     {
04990        restoreURL( u );
04991     }
04992   }
04993 
04994 }
04995 
04996 void KHTMLPart::show()
04997 {
04998   if ( d->m_view )
04999     d->m_view->show();
05000 }
05001 
05002 void KHTMLPart::hide()
05003 {
05004   if ( d->m_view )
05005     d->m_view->hide();
05006 }
05007 
05008 DOM::Node KHTMLPart::nodeUnderMouse() const
05009 {
05010     return d->m_view->nodeUnderMouse();
05011 }
05012 
05013 DOM::Node KHTMLPart::nonSharedNodeUnderMouse() const
05014 {
05015     return d->m_view->nonSharedNodeUnderMouse();
05016 }
05017 
05018 void KHTMLPart::emitSelectionChanged()
05019 {
05020   emit d->m_extension->enableAction( "copy", hasSelection() );
05021   if ( d->m_findDialog )
05022        d->m_findDialog->setHasSelection( hasSelection() );
05023 
05024   emit d->m_extension->selectionInfo( selectedText() );
05025   emit selectionChanged();
05026 }
05027 
05028 int KHTMLPart::zoomFactor() const
05029 {
05030   return d->m_zoomFactor;
05031 }
05032 
05033 // ### make the list configurable ?
05034 static const int zoomSizes[] = { 20, 40, 60, 80, 90, 95, 100, 105, 110, 120, 140, 160, 180, 200, 250, 300 };
05035 static const int zoomSizeCount = (sizeof(zoomSizes) / sizeof(int));
05036 static const int minZoom = 20;
05037 static const int maxZoom = 300;
05038 
05039 // My idea of useful stepping ;-) (LS)
05040 extern const int KDE_NO_EXPORT fastZoomSizes[] = { 20, 50, 75, 90, 100, 120, 150, 200, 300 };
05041 extern const int KDE_NO_EXPORT fastZoomSizeCount = sizeof fastZoomSizes / sizeof fastZoomSizes[0];
05042 
05043 void KHTMLPart::slotIncZoom()
05044 {
05045   zoomIn(zoomSizes, zoomSizeCount);
05046 }
05047 
05048 void KHTMLPart::slotDecZoom()
05049 {
05050   zoomOut(zoomSizes, zoomSizeCount);
05051 }
05052 
05053 void KHTMLPart::slotIncZoomFast()
05054 {
05055   zoomIn(fastZoomSizes, fastZoomSizeCount);
05056 }
05057 
05058 void KHTMLPart::slotDecZoomFast()
05059 {
05060   zoomOut(fastZoomSizes, fastZoomSizeCount);
05061 }
05062 
05063 void KHTMLPart::zoomIn(const int stepping[], int count)
05064 {
05065   int zoomFactor = d->m_zoomFactor;
05066 
05067   if (zoomFactor < maxZoom) {
05068     // find the entry nearest to the given zoomsizes
05069     for (int i = 0; i < count; ++i)
05070       if (stepping[i] > zoomFactor) {
05071         zoomFactor = stepping[i];
05072         break;
05073       }
05074     setZoomFactor(zoomFactor);
05075   }
05076 }
05077 
05078 void KHTMLPart::zoomOut(const int stepping[], int count)
05079 {
05080     int zoomFactor = d->m_zoomFactor;
05081     if (zoomFactor > minZoom) {
05082       // find the entry nearest to the given zoomsizes
05083       for (int i = count-1; i >= 0; --i)
05084         if (stepping[i] < zoomFactor) {
05085           zoomFactor = stepping[i];
05086           break;
05087         }
05088       setZoomFactor(zoomFactor);
05089     }
05090 }
05091 
05092 void KHTMLPart::setZoomFactor (int percent)
05093 {
05094   if (percent < minZoom) percent = minZoom;
05095   if (percent > maxZoom) percent = maxZoom;
05096   if (d->m_zoomFactor == percent) return;
05097   d->m_zoomFactor = percent;
05098 
05099   if(d->m_doc) {
05100       QApplication::setOverrideCursor( waitCursor );
05101     if (d->m_doc->styleSelector())
05102       d->m_doc->styleSelector()->computeFontSizes(d->m_doc->paintDeviceMetrics(), d->m_zoomFactor);
05103     d->m_doc->recalcStyle( NodeImpl::Force );
05104     QApplication::restoreOverrideCursor();
05105   }
05106 
05107   ConstFrameIt it = d->m_frames.begin();
05108   ConstFrameIt end = d->m_frames.end();
05109   for (; it != end; ++it )
05110     if ( !( *it ).m_part.isNull() && ( *it ).m_part->inherits( "KHTMLPart" ) ) {
05111       KParts::ReadOnlyPart* p = ( *it ).m_part;
05112       static_cast<KHTMLPart*>( p )->setZoomFactor(d->m_zoomFactor);
05113     }
05114 
05115   if ( d->m_guiProfile == BrowserViewGUI ) {
05116       d->m_paDecZoomFactor->setEnabled( d->m_zoomFactor > minZoom );
05117       d->m_paIncZoomFactor->setEnabled( d->m_zoomFactor < maxZoom );
05118   }
05119 }
05120 
05121 void KHTMLPart::slotZoomView( int delta )
05122 {
05123   if ( delta < 0 )
05124     slotIncZoom();
05125   else
05126     slotDecZoom();
05127 }
05128 
05129 void KHTMLPart::setStatusBarText( const QString& text, StatusBarPriority p)
05130 {
05131   if (!d->m_statusMessagesEnabled)
05132     return;
05133 
05134   d->m_statusBarText[p] = text;
05135 
05136   // shift handling ?
05137   QString tobe = d->m_statusBarText[BarHoverText];
05138   if (tobe.isEmpty())
05139     tobe = d->m_statusBarText[BarOverrideText];
05140   if (tobe.isEmpty()) {
05141     tobe = d->m_statusBarText[BarDefaultText];
05142     if (!tobe.isEmpty() && d->m_jobspeed)
05143       tobe += " ";
05144     if (d->m_jobspeed)
05145       tobe += i18n( "(%1/s)" ).arg( KIO::convertSize( d->m_jobspeed ) );
05146   }
05147   tobe = "<qt>"+tobe;
05148 
05149   emit ReadOnlyPart::setStatusBarText(tobe);
05150 }
05151 
05152 
05153 void KHTMLPart::setJSStatusBarText( const QString &text )
05154 {
05155   setStatusBarText(text, BarOverrideText);
05156 }
05157 
05158 void KHTMLPart::setJSDefaultStatusBarText( const QString &text )
05159 {
05160   setStatusBarText(text, BarDefaultText);
05161 }
05162 
05163 QString KHTMLPart::jsStatusBarText() const
05164 {
05165     return d->m_statusBarText[BarOverrideText];
05166 }
05167 
05168 QString KHTMLPart::jsDefaultStatusBarText() const
05169 {
05170    return d->m_statusBarText[BarDefaultText];
05171 }
05172 
05173 QString KHTMLPart::referrer() const
05174 {
05175    return d->m_referrer;
05176 }
05177 
05178 QString KHTMLPart::pageReferrer() const
05179 {
05180    KURL referrerURL = KURL( d->m_pageReferrer );
05181    if (referrerURL.isValid())
05182    {
05183       QString protocol = referrerURL.protocol();
05184 
05185       if ((protocol == "http") ||
05186          ((protocol == "https") && (m_url.protocol() == "https")))
05187       {
05188           referrerURL.setRef(QString::null);
05189           referrerURL.setUser(QString::null);
05190           referrerURL.setPass(QString::null);
05191           return referrerURL.url();
05192       }
05193    }
05194 
05195    return QString::null;
05196 }
05197 
05198 
05199 QString KHTMLPart::lastModified() const
05200 {
05201   if ( d->m_lastModified.isEmpty() && m_url.isLocalFile() ) {
05202     // Local file: set last-modified from the file's mtime.
05203     // Done on demand to save time when this isn't needed - but can lead
05204     // to slightly wrong results if updating the file on disk w/o reloading.
05205     QDateTime lastModif = QFileInfo( m_url.path() ).lastModified();
05206     d->m_lastModified = lastModif.toString( Qt::LocalDate );
05207   }
05208   //kdDebug(6050) << "KHTMLPart::lastModified: " << d->m_lastModified << endl;
05209   return d->m_lastModified;
05210 }
05211 
05212 void KHTMLPart::slotLoadImages()
05213 {
05214   if (d->m_doc )
05215     d->m_doc->docLoader()->setAutoloadImages( !d->m_doc->docLoader()->autoloadImages() );
05216 
05217   ConstFrameIt it = d->m_frames.begin();
05218   ConstFrameIt end = d->m_frames.end();
05219   for (; it != end; ++it )
05220     if ( !( *it ).m_part.isNull() && ( *it ).m_part->inherits( "KHTMLPart" ) ) {
05221       KParts::ReadOnlyPart* p = ( *it ).m_part;
05222       static_cast<KHTMLPart*>( p )->slotLoadImages();
05223     }
05224 }
05225 
05226 void KHTMLPart::reparseConfiguration()
05227 {
05228   KHTMLSettings *settings = KHTMLFactory::defaultHTMLSettings();
05229   settings->init();
05230 
05231   setAutoloadImages( settings->autoLoadImages() );
05232   if (d->m_doc)
05233      d->m_doc->docLoader()->setShowAnimations( settings->showAnimations() );
05234 
05235   d->m_bOpenMiddleClick = settings->isOpenMiddleClickEnabled();
05236   d->m_bBackRightClick = settings->isBackRightClickEnabled();
05237   d->m_bJScriptEnabled = settings->isJavaScriptEnabled(m_url.host());
05238   setDebugScript( settings->isJavaScriptDebugEnabled() );
05239   d->m_bJavaEnabled = settings->isJavaEnabled(m_url.host());
05240   d->m_bPluginsEnabled = settings->isPluginsEnabled(m_url.host());
05241   d->m_metaRefreshEnabled = settings->isAutoDelayedActionsEnabled ();
05242 
05243   delete d->m_settings;
05244   d->m_settings = new KHTMLSettings(*KHTMLFactory::defaultHTMLSettings());
05245 
05246   QApplication::setOverrideCursor( waitCursor );
05247   khtml::CSSStyleSelector::reparseConfiguration();
05248   if(d->m_doc) d->m_doc->updateStyleSelector();
05249   QApplication::restoreOverrideCursor();
05250 }
05251 
05252 QStringList KHTMLPart::frameNames() const
05253 {
05254   QStringList res;
05255 
05256   ConstFrameIt it = d->m_frames.begin();
05257   ConstFrameIt end = d->m_frames.end();
05258   for (; it != end; ++it )
05259     if (!(*it).m_bPreloaded)
05260       res += (*it).m_name;
05261 
05262   return res;
05263 }
05264 
05265 QPtrList<KParts::ReadOnlyPart> KHTMLPart::frames() const
05266 {
05267   QPtrList<KParts::ReadOnlyPart> res;
05268 
05269   ConstFrameIt it = d->m_frames.begin();
05270   ConstFrameIt end = d->m_frames.end();
05271   for (; it != end; ++it )
05272     if (!(*it).m_bPreloaded)
05273       res.append( (*it).m_part );
05274 
05275   return res;
05276 }
05277 
05278 bool KHTMLPart::openURLInFrame( const KURL &url, const KParts::URLArgs &urlArgs )
05279 {
05280     kdDebug( 6050 ) << this << "KHTMLPart::openURLInFrame " << url << endl;
05281   FrameIt it = d->m_frames.find( urlArgs.frameName );
05282 
05283   if ( it == d->m_frames.end() )
05284     return false;
05285 
05286   // Inform someone that we are about to show something else.
05287   if ( !urlArgs.lockHistory() )
05288       emit d->m_extension->openURLNotify();
05289 
05290   requestObject( &(*it), url, urlArgs );
05291 
05292   return true;
05293 }
05294 
05295 void KHTMLPart::setDNDEnabled( bool b )
05296 {
05297   d->m_bDnd = b;
05298 }
05299 
05300 bool KHTMLPart::dndEnabled() const
05301 {
05302   return d->m_bDnd;
05303 }
05304 
05305 void KHTMLPart::customEvent( QCustomEvent *event )
05306 {
05307   if ( khtml::MousePressEvent::test( event ) )
05308   {
05309     khtmlMousePressEvent( static_cast<khtml::MousePressEvent *>( event ) );
05310     return;
05311   }
05312 
05313   if ( khtml::MouseDoubleClickEvent::test( event ) )
05314   {
05315     khtmlMouseDoubleClickEvent( static_cast<khtml::MouseDoubleClickEvent *>( event ) );
05316     return;
05317   }
05318 
05319   if ( khtml::MouseMoveEvent::test( event ) )
05320   {
05321     khtmlMouseMoveEvent( static_cast<khtml::MouseMoveEvent *>( event ) );
05322     return;
05323   }
05324 
05325   if ( khtml::MouseReleaseEvent::test( event ) )
05326   {
05327     khtmlMouseReleaseEvent( static_cast<khtml::MouseReleaseEvent *>( event ) );
05328     return;
05329   }
05330 
05331   if ( khtml::DrawContentsEvent::test( event ) )
05332   {
05333     khtmlDrawContentsEvent( static_cast<khtml::DrawContentsEvent *>( event ) );
05334     return;
05335   }
05336 
05337   KParts::ReadOnlyPart::customEvent( event );
05338 }
05339 
05345 static bool firstRunAt(khtml::RenderObject *renderNode, int y, NodeImpl *&startNode, long &startOffset)
05346 {
05347     for (khtml::RenderObject *n = renderNode; n; n = n->nextSibling()) {
05348         if (n->isText()) {
05349             khtml::RenderText *textRenderer = static_cast<khtml::RenderText *>(n);
05350             const khtml::InlineTextBoxArray &runs = textRenderer->inlineTextBoxes();
05351             for (unsigned i = 0; i != runs.count(); i++) {
05352                 if (runs[i]->m_y == y) {
05353                     startNode = textRenderer->element();
05354                     startOffset = runs[i]->m_start;
05355                     return true;
05356                 }
05357             }
05358         }
05359 
05360         if (firstRunAt(n->firstChild(), y, startNode, startOffset)) {
05361             return true;
05362         }
05363     }
05364 
05365     return false;
05366 }
05367 
05373 static bool lastRunAt(khtml::RenderObject *renderNode, int y, NodeImpl *&endNode, long &endOffset)
05374 {
05375     khtml::RenderObject *n = renderNode;
05376     if (!n) {
05377         return false;
05378     }
05379     khtml::RenderObject *next;
05380     while ((next = n->nextSibling())) {
05381         n = next;
05382     }
05383 
05384     while (1) {
05385         if (lastRunAt(n->firstChild(), y, endNode, endOffset)) {
05386             return true;
05387         }
05388 
05389         if (n->isText()) {
05390             khtml::RenderText *textRenderer =  static_cast<khtml::RenderText *>(n);
05391             const khtml::InlineTextBoxArray &runs = textRenderer->inlineTextBoxes();
05392             for (int i = (int)runs.count()-1; i >= 0; i--) {
05393                 if (runs[i]->m_y == y) {
05394                     endNode = textRenderer->element();
05395                     endOffset = runs[i]->m_start + runs[i]->m_len;
05396                     return true;
05397                 }
05398             }
05399         }
05400 
05401         if (n == renderNode) {
05402             return false;
05403         }
05404 
05405         n = n->previousSibling();
05406     }
05407 }
05408 
05409 void KHTMLPart::khtmlMousePressEvent( khtml::MousePressEvent *event )
05410 {
05411   DOM::DOMString url = event->url();
05412   QMouseEvent *_mouse = event->qmouseEvent();
05413   DOM::Node innerNode = event->innerNode();
05414   d->m_mousePressNode = innerNode;
05415 
05416    d->m_dragStartPos = _mouse->pos();
05417 
05418    if ( !event->url().isNull() ) {
05419      d->m_strSelectedURL = event->url().string();
05420      d->m_strSelectedURLTarget = event->target().string();
05421    }
05422    else
05423      d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
05424 
05425   if ( _mouse->button() == LeftButton ||
05426        _mouse->button() == MidButton )
05427   {
05428     d->m_bMousePressed = true;
05429 
05430 #ifndef KHTML_NO_SELECTION
05431     if ( _mouse->button() == LeftButton )
05432     {
05433       if ( (!d->m_strSelectedURL.isNull() && !isEditable())
05434             || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) )
05435       return;
05436       if ( !innerNode.isNull()  && innerNode.handle()->renderer()) {
05437           int offset = 0;
05438           DOM::NodeImpl* node = 0;
05439           khtml::RenderObject::SelPointState state;
05440           innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(),
05441                                                                event->absX()-innerNode.handle()->renderer()->xPos(),
05442                                                                event->absY()-innerNode.handle()->renderer()->yPos(), node, offset, state );
05443           d->m_extendMode = d->ExtendByChar;
05444 #ifdef KHTML_NO_CARET
05445           d->m_selectionStart = node;
05446           d->m_startOffset = offset;
05447           //if ( node )
05448           //  kdDebug(6005) << "KHTMLPart::khtmlMousePressEvent selectionStart=" << d->m_selectionStart.handle()->renderer()
05449           //                << " offset=" << d->m_startOffset << endl;
05450           //else
05451           //  kdDebug(6005) << "KHTML::khtmlMousePressEvent selectionStart=(nil)" << endl;
05452           d->m_selectionEnd = d->m_selectionStart;
05453           d->m_endOffset = d->m_startOffset;
05454           d->m_doc->clearSelection();
05455 #else // KHTML_NO_CARET
05456       d->m_view->moveCaretTo(node, offset, (_mouse->state() & ShiftButton) == 0);
05457 #endif // KHTML_NO_CARET
05458       d->m_initialNode = d->m_selectionStart;
05459       d->m_initialOffset = d->m_startOffset;
05460 //           kdDebug(6000) << "press: initOfs " << d->m_initialOffset << endl;
05461       }
05462       else
05463       {
05464 #ifndef KHTML_NO_CARET
05465         // simply leave it. Is this a good idea?
05466 #else
05467         d->m_selectionStart = DOM::Node();
05468         d->m_selectionEnd = DOM::Node();
05469 #endif
05470       }
05471       emitSelectionChanged();
05472       startAutoScroll();
05473     }
05474 #else
05475     d->m_dragLastPos = _mouse->globalPos();
05476 #endif
05477   }
05478 
05479   if ( _mouse->button() == RightButton && parentPart() != 0 && d->m_bBackRightClick )
05480   {
05481     d->m_bRightMousePressed = true;
05482   } else if ( _mouse->button() == RightButton )
05483   {
05484     popupMenu( d->m_strSelectedURL );
05485     // might be deleted, don't touch "this"
05486   }
05487 }
05488 
05489 void KHTMLPart::khtmlMouseDoubleClickEvent( khtml::MouseDoubleClickEvent *event )
05490 {
05491   QMouseEvent *_mouse = event->qmouseEvent();
05492   if ( _mouse->button() == LeftButton )
05493   {
05494     d->m_bMousePressed = true;
05495     DOM::Node innerNode = event->innerNode();
05496     // Find selectionStart again, khtmlMouseReleaseEvent lost it
05497     if ( !innerNode.isNull() && innerNode.handle()->renderer()) {
05498       int offset = 0;
05499       DOM::NodeImpl* node = 0;
05500       khtml::RenderObject::SelPointState state;
05501       innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(),
05502                                                            event->absX()-innerNode.handle()->renderer()->xPos(),
05503                                                            event->absY()-innerNode.handle()->renderer()->yPos(), node, offset, state);
05504 
05505       //kdDebug() << k_funcinfo << "checkSelectionPoint returned node=" << node << " offset=" << offset << endl;
05506 
05507       if ( node && node->renderer() )
05508       {
05509         // Extend selection to a complete word (double-click) or line (triple-click)
05510         bool selectLine = (event->clickCount() == 3);
05511         d->m_extendMode = selectLine ? d->ExtendByLine : d->ExtendByWord;
05512 
05513     // Extend existing selection if Shift was pressed
05514     if (_mouse->state() & ShiftButton) {
05515           d->caretNode() = node;
05516       d->caretOffset() = offset;
05517           d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
05518                 d->m_selectionStart.handle(), d->m_startOffset,
05519             d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
05520           d->m_initialNode = d->m_extendAtEnd ? d->m_selectionStart : d->m_selectionEnd;
05521           d->m_initialOffset = d->m_extendAtEnd ? d->m_startOffset : d->m_endOffset;
05522     } else {
05523       d->m_selectionStart = d->m_selectionEnd = node;
05524       d->m_startOffset = d->m_endOffset = offset;
05525           d->m_startBeforeEnd = true;
05526           d->m_initialNode = node;
05527           d->m_initialOffset = offset;
05528     }
05529 //         kdDebug(6000) << "dblclk: initOfs " << d->m_initialOffset << endl;
05530 
05531         // Extend the start
05532         extendSelection( d->m_selectionStart.handle(), d->m_startOffset, d->m_selectionStart, d->m_startOffset, !d->m_startBeforeEnd, selectLine );
05533         // Extend the end
05534         extendSelection( d->m_selectionEnd.handle(), d->m_endOffset, d->m_selectionEnd, d->m_endOffset, d->m_startBeforeEnd, selectLine );
05535 
05536         //kdDebug() << d->m_selectionStart.handle() << " " << d->m_startOffset << "  -  " <<
05537         //  d->m_selectionEnd.handle() << " " << d->m_endOffset << endl;
05538 
05539         emitSelectionChanged();
05540         d->m_doc
05541           ->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
05542                          d->m_selectionEnd.handle(),d->m_endOffset);
05543 #ifndef KHTML_NO_CARET
05544         bool v = d->m_view->placeCaret();
05545         emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
05546 #endif
05547         startAutoScroll();
05548       }
05549     }
05550   }
05551 }
05552 
05553 void KHTMLPart::extendSelection( DOM::NodeImpl* node, long offset, DOM::Node& selectionNode, long& selectionOffset, bool right, bool selectLines )
05554 {
05555   khtml::RenderObject* obj = node->renderer();
05556 
05557   if (obj->isText() && selectLines) {
05558     int pos;
05559     khtml::RenderText *renderer = static_cast<khtml::RenderText *>(obj);
05560     khtml::InlineTextBox *run = renderer->findInlineTextBox( offset, pos );
05561     DOMString t = node->nodeValue();
05562     DOM::NodeImpl* selNode = 0;
05563     long selOfs = 0;
05564 
05565     if (!run)
05566       return;
05567 
05568     int selectionPointY = run->m_y;
05569 
05570     // Go up to first non-inline element.
05571     khtml::RenderObject *renderNode = renderer;
05572     while (renderNode && renderNode->isInline())
05573       renderNode = renderNode->parent();
05574 
05575     renderNode = renderNode->firstChild();
05576 
05577     if (right) {
05578       // Look for all the last child in the block that is on the same line
05579       // as the selection point.
05580       if (!lastRunAt (renderNode, selectionPointY, selNode, selOfs))
05581         return;
05582     } else {
05583       // Look for all the first child in the block that is on the same line
05584       // as the selection point.
05585       if (!firstRunAt (renderNode, selectionPointY, selNode, selOfs))
05586         return;
05587     }
05588 
05589     selectionNode = selNode;
05590     selectionOffset = selOfs;
05591     return;
05592   }
05593 
05594   QString str;
05595   int len = 0;
05596   if ( obj->isText() ) { // can be false e.g. when double-clicking on a disabled submit button
05597     str = static_cast<khtml::RenderText *>(obj)->data().string();
05598     len = str.length();
05599   }
05600   //kdDebug() << "extendSelection right=" << right << " offset=" << offset << " len=" << len << " Starting at obj=" << obj << endl;
05601   QChar ch;
05602   do {
05603     // Last char was ok, point to it
05604     if ( node ) {
05605       selectionNode = node;
05606       selectionOffset = offset;
05607     }
05608 
05609     // Get another char
05610     while ( obj && ( (right && offset >= len-1) || (!right && offset <= 0) ) )
05611     {
05612       obj = right ? obj->objectBelow() : obj->objectAbove();
05613       //kdDebug() << "obj=" << obj << endl;
05614       if ( obj ) {
05615         //kdDebug() << "isText=" << obj->isText() << endl;
05616         str = QString::null;
05617         if ( obj->isText() )
05618           str = static_cast<khtml::RenderText *>(obj)->data().string();
05619         else if ( obj->isBR() )
05620           str = '\n';
05621         else if ( !obj->isInline() ) {
05622           obj = 0L; // parag limit -> done
05623           break;
05624         }
05625         len = str.length();
05626         //kdDebug() << "str=" << str << " length=" << len << endl;
05627         // set offset - note that the first thing will be a ++ or -- on it.
05628         if ( right )
05629           offset = -1;
05630         else
05631           offset = len;
05632       }
05633     }
05634     if ( !obj ) // end of parag or document
05635       break;
05636     node = obj->element();
05637     if ( right )
05638     {
05639       Q_ASSERT( offset < len-1 );
05640       offset++;
05641     }
05642     else
05643     {
05644       Q_ASSERT( offset > 0 );
05645       offset--;
05646     }
05647 
05648     // Test that char
05649     ch = str[ offset ];
05650     //kdDebug() << " offset=" << offset << " ch=" << QString(ch) << endl;
05651   } while ( !ch.isSpace() && !ch.isPunct() );
05652 
05653   // make offset point after last char
05654   if (right) selectionOffset++;
05655 }
05656 
05657 #ifndef KHTML_NO_SELECTION
05658 void KHTMLPart::extendSelectionTo(int x, int y, int absX, int absY, const DOM::Node &innerNode)
05659 {
05660       int offset;
05661       //kdDebug(6000) << "KHTMLPart::khtmlMouseMoveEvent x=" << event->x() << " y=" << event->y() << endl;
05662       DOM::NodeImpl* node=0;
05663       khtml::RenderObject::SelPointState state;
05664       innerNode.handle()->renderer()->checkSelectionPoint( x, y,
05665                                                            absX-innerNode.handle()->renderer()->xPos(),
05666                                                            absY-innerNode.handle()->renderer()->yPos(), node, offset, state);
05667       if (!node || !node->renderer()) return;
05668 
05669       // Words at the beginning/end of line cannot be deselected in
05670       // ExtendByWord mode. Therefore, do not enforce it if the selection
05671       // point does not match the node under the mouse cursor.
05672       bool withinNode = innerNode == node;
05673 
05674       // we have to get to know if end is before start or not...
05675       // shouldn't be null but it can happen with dynamic updating of nodes
05676       if (d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() ||
05677           d->m_initialNode.isNull() ||
05678           !d->m_selectionStart.handle()->renderer() ||
05679           !d->m_selectionEnd.handle()->renderer()) return;
05680 
05681       if (d->m_extendMode != d->ExtendByChar) {
05682         // check whether we should extend at the front, or at the back
05683         bool caretBeforeInit = RangeImpl::compareBoundaryPoints(
05684                 d->caretNode().handle(), d->caretOffset(),
05685             d->m_initialNode.handle(), d->m_initialOffset) <= 0;
05686         bool nodeBeforeInit = RangeImpl::compareBoundaryPoints(node, offset,
05687             d->m_initialNode.handle(), d->m_initialOffset) <= 0;
05688         // have to fix up start to point to the original end
05689         if (caretBeforeInit != nodeBeforeInit) {
05690 //         kdDebug(6000) << "extto cbi: " << caretBeforeInit << " startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << " initOfs " << d->m_initialOffset << endl;
05691           extendSelection(d->m_initialNode.handle(), d->m_initialOffset,
05692         d->m_extendAtEnd ? d->m_selectionStart : d->m_selectionEnd,
05693         d->m_extendAtEnd ? d->m_startOffset : d->m_endOffset,
05694         nodeBeforeInit, d->m_extendMode == d->ExtendByLine);
05695     }
05696       }
05697 
05698       d->caretNode() = node;
05699       d->caretOffset() = offset;
05700       //kdDebug( 6000 ) << "setting end of selection to " << d->m_selectionEnd.handle() << "/" << d->m_endOffset << endl;
05701 
05702       d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
05703                 d->m_selectionStart.handle(), d->m_startOffset,
05704             d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
05705 
05706       if ( !d->m_selectionStart.isNull() && !d->m_selectionEnd.isNull() )
05707       {
05708 //         kdDebug(6000) << "extto: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << " initOfs " << d->m_initialOffset << endl;
05709         if (d->m_extendMode != d->ExtendByChar && withinNode)
05710           extendSelection( node, offset, d->caretNode(), d->caretOffset(), d->m_startBeforeEnd ^ !d->m_extendAtEnd, d->m_extendMode == d->ExtendByLine );
05711 
05712         if (d->m_selectionEnd == d->m_selectionStart && d->m_endOffset < d->m_startOffset)
05713           d->m_doc
05714             ->setSelection(d->m_selectionStart.handle(),d->m_endOffset,
05715                            d->m_selectionEnd.handle(),d->m_startOffset);
05716         else if (d->m_startBeforeEnd)
05717           d->m_doc
05718             ->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
05719                            d->m_selectionEnd.handle(),d->m_endOffset);
05720         else
05721           d->m_doc
05722             ->setSelection(d->m_selectionEnd.handle(),d->m_endOffset,
05723                            d->m_selectionStart.handle(),d->m_startOffset);
05724       }
05725 #ifndef KHTML_NO_CARET
05726       d->m_view->placeCaret();
05727 #endif
05728 }
05729 
05730 bool KHTMLPart::isExtendingSelection() const
05731 {
05732   // This is it, the whole detection. khtmlMousePressEvent only sets this
05733   // on LMB or MMB, but never on RMB. As text selection doesn't work for MMB,
05734   // it's sufficient to only rely on this flag to detect selection extension.
05735   return d->m_bMousePressed;
05736 }
05737 #endif // KHTML_NO_SELECTION
05738 
05739 void KHTMLPart::khtmlMouseMoveEvent( khtml::MouseMoveEvent *event )
05740 {
05741   QMouseEvent *_mouse = event->qmouseEvent();
05742 
05743   if( d->m_bRightMousePressed && parentPart() != 0 && d->m_bBackRightClick )
05744   {
05745     popupMenu( d->m_strSelectedURL );
05746     d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
05747     d->m_bRightMousePressed = false;
05748   }
05749 
05750   DOM::DOMString url = event->url();
05751   DOM::DOMString target = event->target();
05752   DOM::Node innerNode = event->innerNode();
05753 
05754 #ifndef QT_NO_DRAGANDDROP
05755   if( d->m_bDnd && d->m_bMousePressed &&
05756       ( (!d->m_strSelectedURL.isEmpty() && !isEditable())
05757         || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) ) ) {
05758     if ( ( d->m_dragStartPos - _mouse->pos() ).manhattanLength() <= KGlobalSettings::dndEventDelay() )
05759       return;
05760 
05761     QPixmap pix;
05762     HTMLImageElementImpl *img = 0L;
05763     QDragObject *drag = 0;
05764     KURL u;
05765 
05766     // qDebug("****************** Event URL: %s", url.string().latin1());
05767     // qDebug("****************** Event Target: %s", target.string().latin1());
05768 
05769     // Normal image...
05770     if ( url.length() == 0 && innerNode.handle() && innerNode.handle()->id() == ID_IMG )
05771     {
05772       img = static_cast<HTMLImageElementImpl *>(innerNode.handle());
05773       u = KURL( completeURL( khtml::parseURL(img->getAttribute(ATTR_SRC)).string() ) );
05774       pix = KMimeType::mimeType("image/png")->pixmap(KIcon::Desktop);
05775     }
05776     else
05777     {
05778       // Text or image link...
05779       u = completeURL( d->m_strSelectedURL );
05780       pix = KMimeType::pixmapForURL(u, 0, KIcon::Desktop, KIcon::SizeMedium);
05781     }
05782 
05783     KURLDrag* urlDrag = new KURLDrag( u, img ? 0 : d->m_view->viewport() );
05784     if ( !d->m_referrer.isEmpty() )
05785       urlDrag->metaData()["referrer"] = d->m_referrer;
05786 
05787     if( img ) {
05788       KMultipleDrag *mdrag = new KMultipleDrag( d->m_view->viewport() );
05789       mdrag->addDragObject( new QImageDrag( img->currentImage(), 0L ) );
05790       mdrag->addDragObject( urlDrag );
05791       drag = mdrag;
05792     }
05793     else
05794       drag = urlDrag;
05795 
05796     if ( !pix.isNull() )
05797       drag->setPixmap( pix );
05798 
05799     stopAutoScroll();
05800     if(drag)
05801         drag->drag();
05802 
05803     // when we finish our drag, we need to undo our mouse press
05804     d->m_bMousePressed = false;
05805     d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
05806     return;
05807   }
05808 #endif
05809 
05810   // Not clicked -> mouse over stuff
05811   if ( !d->m_bMousePressed )
05812   {
05813     // The mouse is over something
05814     if ( url.length() )
05815     {
05816       bool shiftPressed = ( _mouse->state() & ShiftButton );
05817 
05818       // Image map
05819       if ( !innerNode.isNull() && innerNode.elementId() == ID_IMG )
05820       {
05821         HTMLImageElementImpl *i = static_cast<HTMLImageElementImpl *>(innerNode.handle());
05822         if ( i && i->isServerMap() )
05823         {
05824           khtml::RenderObject *r = i->renderer();
05825           if(r)
05826           {
05827             int absx, absy, vx, vy;
05828             r->absolutePosition(absx, absy);
05829             view()->contentsToViewport( absx, absy, vx, vy );
05830 
05831             int x(_mouse->x() - vx), y(_mouse->y() - vy);
05832 
05833             d->m_overURL = url.string() + QString("?%1,%2").arg(x).arg(y);
05834             d->m_overURLTarget = target.string();
05835             overURL( d->m_overURL, target.string(), shiftPressed );
05836             return;
05837           }
05838         }
05839       }
05840 
05841       // normal link
05842       if ( d->m_overURL.isEmpty() || d->m_overURL != url || d->m_overURLTarget != target )
05843       {
05844         d->m_overURL = url.string();
05845         d->m_overURLTarget = target.string();
05846         overURL( d->m_overURL, target.string(), shiftPressed );
05847       }
05848     }
05849     else  // Not over a link...
05850     {
05851       if( !d->m_overURL.isEmpty() ) // and we were over a link  -> reset to "default statusbar text"
05852       {
05853         d->m_overURL = d->m_overURLTarget = QString::null;
05854         emit onURL( QString::null );
05855         // revert to default statusbar text
05856         setStatusBarText(QString::null, BarHoverText);
05857         emit d->m_extension->mouseOverInfo(0);
05858      }
05859     }
05860   }
05861   else {
05862 #ifndef KHTML_NO_SELECTION
05863     // selection stuff
05864     if( d->m_bMousePressed && innerNode.handle() && innerNode.handle()->renderer() &&
05865         ( (_mouse->state() & LeftButton) != 0 )) {
05866       extendSelectionTo(event->x(), event->y(),
05867                         event->absX(), event->absY(), innerNode);
05868 #else
05869       if ( d->m_doc && d->m_view ) {
05870         QPoint diff( _mouse->globalPos() - d->m_dragLastPos );
05871 
05872         if ( abs( diff.x() ) > 64 || abs( diff.y() ) > 64 ) {
05873           d->m_view->scrollBy( -diff.x(), -diff.y() );
05874           d->m_dragLastPos = _mouse->globalPos();
05875         }
05876 #endif
05877     }
05878   }
05879 
05880 }
05881 
05882 void KHTMLPart::khtmlMouseReleaseEvent( khtml::MouseReleaseEvent *event )
05883 {
05884   DOM::Node innerNode = event->innerNode();
05885   d->m_mousePressNode = DOM::Node();
05886 
05887   if ( d->m_bMousePressed ) {
05888     setStatusBarText(QString::null, BarHoverText);
05889     stopAutoScroll();
05890   }
05891 
05892   // Used to prevent mouseMoveEvent from initiating a drag before
05893   // the mouse is pressed again.
05894   d->m_bMousePressed = false;
05895 
05896   QMouseEvent *_mouse = event->qmouseEvent();
05897   if ( _mouse->button() == RightButton && parentPart() != 0 && d->m_bBackRightClick )
05898   {
05899     d->m_bRightMousePressed = false;
05900     KParts::BrowserInterface *tmp_iface = d->m_extension->browserInterface();
05901     if( tmp_iface ) {
05902       tmp_iface->callMethod( "goHistory(int)", -1 );
05903     }
05904   }
05905 #ifndef QT_NO_CLIPBOARD
05906   if ((d->m_guiProfile == BrowserViewGUI) && (_mouse->button() == MidButton) && (event->url().isNull())) {
05907     kdDebug( 6050 ) << "KHTMLPart::khtmlMouseReleaseEvent() MMB shouldOpen="
05908                     << d->m_bOpenMiddleClick << endl;
05909 
05910     if (d->m_bOpenMiddleClick) {
05911     KHTMLPart *p = this;
05912     while (p->parentPart()) p = p->parentPart();
05913     p->d->m_extension->pasteRequest();
05914   }
05915   }
05916 #endif
05917 
05918 #ifndef KHTML_NO_SELECTION
05919   // delete selection in case start and end position are at the same point
05920   if(d->m_selectionStart == d->m_selectionEnd && d->m_startOffset == d->m_endOffset) {
05921 #ifndef KHTML_NO_CARET
05922     d->m_extendAtEnd = true;
05923 #else
05924     d->m_selectionStart = 0;
05925     d->m_selectionEnd = 0;
05926     d->m_startOffset = 0;
05927     d->m_endOffset = 0;
05928 #endif
05929     emitSelectionChanged();
05930   } else {
05931     // we have to get to know if end is before start or not...
05932 //     kdDebug(6000) << "rel: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << endl;
05933     DOM::Node n = d->m_selectionStart;
05934     d->m_startBeforeEnd = false;
05935     if( d->m_selectionStart == d->m_selectionEnd ) {
05936       if( d->m_startOffset < d->m_endOffset )
05937         d->m_startBeforeEnd = true;
05938     } else {
05939 #if 0
05940       while(!n.isNull()) {
05941         if(n == d->m_selectionEnd) {
05942           d->m_startBeforeEnd = true;
05943           break;
05944         }
05945         DOM::Node next = n.firstChild();
05946         if(next.isNull()) next = n.nextSibling();
05947         while( next.isNull() && !n.parentNode().isNull() ) {
05948           n = n.parentNode();
05949           next = n.nextSibling();
05950         }
05951         n = next;
05952       }
05953 #else
05954       // shouldn't be null but it can happen with dynamic updating of nodes
05955       if (d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() ||
05956           !d->m_selectionStart.handle()->renderer() ||
05957           !d->m_selectionEnd.handle()->renderer()) return;
05958       d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
05959                 d->m_selectionStart.handle(), d->m_startOffset,
05960             d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
05961 #endif
05962     }
05963     if(!d->m_startBeforeEnd)
05964     {
05965       DOM::Node tmpNode = d->m_selectionStart;
05966       int tmpOffset = d->m_startOffset;
05967       d->m_selectionStart = d->m_selectionEnd;
05968       d->m_startOffset = d->m_endOffset;
05969       d->m_selectionEnd = tmpNode;
05970       d->m_endOffset = tmpOffset;
05971       d->m_startBeforeEnd = true;
05972       d->m_extendAtEnd = !d->m_extendAtEnd;
05973     }
05974 #ifndef KHTML_NO_CARET
05975     bool v = d->m_view->placeCaret();
05976     emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
05977 #endif
05978     // get selected text and paste to the clipboard
05979 #ifndef QT_NO_CLIPBOARD
05980     QString text = selectedText();
05981     text.replace(QChar(0xa0), ' ');
05982     disconnect( kapp->clipboard(), SIGNAL( selectionChanged()), this, SLOT( slotClearSelection()));
05983     kapp->clipboard()->setText(text,QClipboard::Selection);
05984     connect( kapp->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection()));
05985 #endif
05986     //kdDebug( 6000 ) << "selectedText = " << text << endl;
05987     emitSelectionChanged();
05988 //kdDebug(6000) << "rel2: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << "), caretOfs " << d->caretOffset() << endl;
05989   }
05990 #endif
05991   d->m_initialNode = 0;     // don't hold nodes longer than necessary
05992   d->m_initialOffset = 0;
05993 
05994 }
05995 
05996 void KHTMLPart::khtmlDrawContentsEvent( khtml::DrawContentsEvent * )
05997 {
05998 }
05999 
06000 void KHTMLPart::guiActivateEvent( KParts::GUIActivateEvent *event )
06001 {
06002   if ( event->activated() )
06003   {
06004     emitSelectionChanged();
06005     emit d->m_extension->enableAction( "print", d->m_doc != 0 );
06006 
06007     if ( !d->m_settings->autoLoadImages() && d->m_paLoadImages )
06008     {
06009         QPtrList<KAction> lst;
06010         lst.append( d->m_paLoadImages );
06011         plugActionList( "loadImages", lst );
06012     }
06013   }
06014 }
06015 
06016 void KHTMLPart::slotPrintFrame()
06017 {
06018   if ( d->m_frames.count() == 0 )
06019     return;
06020 
06021   KParts::ReadOnlyPart *frame = currentFrame();
06022   if (!frame)
06023     return;
06024 
06025   KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject( frame );
06026 
06027   if ( !ext )
06028     return;
06029 
06030   QMetaObject *mo = ext->metaObject();
06031 
06032   int idx = mo->findSlot( "print()", true );
06033   if ( idx >= 0 ) {
06034     QUObject o[ 1 ];
06035     ext->qt_invoke( idx, o );
06036   }
06037 }
06038 
06039 void KHTMLPart::slotSelectAll()
06040 {
06041   KParts::ReadOnlyPart *part = currentFrame();
06042   if (part && part->inherits("KHTMLPart"))
06043     static_cast<KHTMLPart *>(part)->selectAll();
06044 }
06045 
06046 void KHTMLPart::startAutoScroll()
06047 {
06048    connect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
06049    d->m_scrollTimer.start(100, false);
06050 }
06051 
06052 void KHTMLPart::stopAutoScroll()
06053 {
06054    disconnect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
06055    if (d->m_scrollTimer.isActive())
06056        d->m_scrollTimer.stop();
06057 }
06058 
06059 
06060 void KHTMLPart::slotAutoScroll()
06061 {
06062     if (d->m_view)
06063       d->m_view->doAutoScroll();
06064     else
06065       stopAutoScroll(); // Safety
06066 }
06067 
06068 void KHTMLPart::selectAll()
06069 {
06070   if (!d->m_doc) return;
06071 
06072   NodeImpl *first;
06073   if (d->m_doc->isHTMLDocument())
06074     first = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
06075   else
06076     first = d->m_doc;
06077   NodeImpl *next;
06078 
06079   // Look for first text/cdata node that has a renderer,
06080   // or first childless replaced element
06081   while ( first && !(first->renderer()
06082     && ((first->nodeType() == Node::TEXT_NODE || first->nodeType() == Node::CDATA_SECTION_NODE)
06083         || (first->renderer()->isReplaced() && !first->renderer()->firstChild()))))
06084   {
06085     next = first->firstChild();
06086     if ( !next ) next = first->nextSibling();
06087     while( first && !next )
06088     {
06089       first = first->parentNode();
06090       if ( first )
06091         next = first->nextSibling();
06092     }
06093     first = next;
06094   }
06095 
06096   NodeImpl *last;
06097   if (d->m_doc->isHTMLDocument())
06098     last = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
06099   else
06100     last = d->m_doc;
06101   // Look for last text/cdata node that has a renderer,
06102   // or last childless replaced element
06103   // ### Instead of changing this loop, use findLastSelectableNode
06104   // in render_table.cpp (LS)
06105   while ( last && !(last->renderer()
06106     && ((last->nodeType() == Node::TEXT_NODE || last->nodeType() == Node::CDATA_SECTION_NODE)
06107         || (last->renderer()->isReplaced() && !last->renderer()->lastChild()))))
06108   {
06109     next = last->lastChild();
06110     if ( !next ) next = last->previousSibling();
06111     while ( last && !next )
06112     {
06113       last = last->parentNode();
06114       if ( last )
06115         next = last->previousSibling();
06116     }
06117     last = next;
06118   }
06119 
06120   if ( !first || !last )
06121     return;
06122   Q_ASSERT(first->renderer());
06123   Q_ASSERT(last->renderer());
06124   d->m_selectionStart = first;
06125   d->m_startOffset = 0;
06126   d->m_selectionEnd = last;
06127   d->m_endOffset = last->nodeValue().length();
06128   d->m_startBeforeEnd = true;
06129 
06130   d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
06131                           d->m_selectionEnd.handle(), d->m_endOffset );
06132 
06133   emitSelectionChanged();
06134 }
06135 
06136 bool KHTMLPart::checkLinkSecurity(const KURL &linkURL,const QString &message, const QString &button)
06137 {
06138   bool linkAllowed = true;
06139 
06140   if ( d->m_doc )
06141     linkAllowed = kapp && kapp->authorizeURLAction("redirect", url(), linkURL);
06142 
06143   if ( !linkAllowed ) {
06144     khtml::Tokenizer *tokenizer = d->m_doc->tokenizer();
06145     if (tokenizer)
06146       tokenizer->setOnHold(true);
06147 
06148     int response = KMessageBox::Cancel;
06149     if (!message.isEmpty())
06150     {
06151         response = KMessageBox::warningContinueCancel( 0,
06152                                message.arg(linkURL.htmlURL()),
06153                                i18n( "Security Warning" ),
06154                                button);
06155     }
06156     else
06157     {
06158         KMessageBox::error( 0,
06159                 i18n( "<qt>Access by untrusted page to<BR><B>%1</B><BR> denied.").arg(linkURL.htmlURL()),
06160                 i18n( "Security Alert" ));
06161     }
06162 
06163     if (tokenizer)
06164        tokenizer->setOnHold(false);
06165     return (response==KMessageBox::Continue);
06166   }
06167   return true;
06168 }
06169 
06170 void KHTMLPart::slotPartRemoved( KParts::Part *part )
06171 {
06172 //    kdDebug(6050) << "KHTMLPart::slotPartRemoved " << part << endl;
06173     if ( part == d->m_activeFrame )
06174     {
06175         d->m_activeFrame = 0L;
06176         if ( !part->inherits( "KHTMLPart" ) )
06177         {
06178             if (factory()) {
06179                 factory()->removeClient( part );
06180             }
06181             if (childClients()->containsRef(part)) {
06182                 removeChildClient( part );
06183             }
06184         }
06185     }
06186 }
06187 
06188 void KHTMLPart::slotActiveFrameChanged( KParts::Part *part )
06189 {
06190 //    kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged part=" << part << endl;
06191     if ( part == this )
06192     {
06193         kdError(6050) << "strange error! we activated ourselves" << endl;
06194         assert( false );
06195         return;
06196     }
06197 //    kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged d->m_activeFrame=" << d->m_activeFrame << endl;
06198     if ( d->m_activeFrame && d->m_activeFrame->widget() && d->m_activeFrame->widget()->inherits( "QFrame" ) )
06199     {
06200         QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() );
06201         if (frame->frameStyle() != QFrame::NoFrame)
06202         {
06203            frame->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken);
06204            frame->repaint();
06205         }
06206     }
06207 
06208     if( d->m_activeFrame && !d->m_activeFrame->inherits( "KHTMLPart" ) )
06209     {
06210         if (factory()) {
06211             factory()->removeClient( d->m_activeFrame );
06212         }
06213         removeChildClient( d->m_activeFrame );
06214     }
06215     if( part && !part->inherits( "KHTMLPart" ) )
06216     {
06217         if (factory()) {
06218             factory()->addClient( part );
06219         }
06220         insertChildClient( part );
06221     }
06222 
06223 
06224     d->m_activeFrame = part;
06225 
06226     if ( d->m_activeFrame && d->m_activeFrame->widget()->inherits( "QFrame" ) )
06227     {
06228         QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() );
06229         if (frame->frameStyle() != QFrame::NoFrame)
06230         {
06231            frame->setFrameStyle( QFrame::StyledPanel | QFrame::Plain);
06232            frame->repaint();
06233         }
06234         kdDebug(6050) << "new active frame " << d->m_activeFrame << endl;
06235     }
06236 
06237     updateActions();
06238 
06239     // (note: childObject returns 0 if the argument is 0)
06240     d->m_extension->setExtensionProxy( KParts::BrowserExtension::childObject( d->m_activeFrame ) );
06241 }
06242 
06243 void KHTMLPart::setActiveNode(const DOM::Node &node)
06244 {
06245     if (!d->m_doc || !d->m_view)
06246         return;
06247 
06248     // Set the document's active node
06249     d->m_doc->setFocusNode(node.handle());
06250 
06251     // Scroll the view if necessary to ensure that the new focus node is visible
06252     QRect rect  = node.handle()->getRect();
06253     d->m_view->ensureVisible(rect.right(), rect.bottom());
06254     d->m_view->ensureVisible(rect.left(), rect.top());
06255 }
06256 
06257 DOM::Node KHTMLPart::activeNode() const
06258 {
06259     return DOM::Node(d->m_doc?d->m_doc->focusNode():0);
06260 }
06261 
06262 DOM::EventListener *KHTMLPart::createHTMLEventListener( QString code, QString name )
06263 {
06264   KJSProxy *proxy = jScript();
06265 
06266   if (!proxy)
06267     return 0;
06268 
06269   return proxy->createHTMLEventHandler( m_url.url(), name, code );
06270 }
06271 
06272 KHTMLPart *KHTMLPart::opener()
06273 {
06274     return d->m_opener;
06275 }
06276 
06277 void KHTMLPart::setOpener(KHTMLPart *_opener)
06278 {
06279     d->m_opener = _opener;
06280 }
06281 
06282 bool KHTMLPart::openedByJS()
06283 {
06284     return d->m_openedByJS;
06285 }
06286 
06287 void KHTMLPart::setOpenedByJS(bool _openedByJS)
06288 {
06289     d->m_openedByJS = _openedByJS;
06290 }
06291 
06292 void KHTMLPart::preloadStyleSheet(const QString &url, const QString &stylesheet)
06293 {
06294     khtml::Cache::preloadStyleSheet(url, stylesheet);
06295 }
06296 
06297 void KHTMLPart::preloadScript(const QString &url, const QString &script)
06298 {
06299     khtml::Cache::preloadScript(url, script);
06300 }
06301 
06302 QCString KHTMLPart::dcopObjectId() const
06303 {
06304   QCString id;
06305   id.sprintf("html-widget%d", d->m_dcop_counter);
06306   return id;
06307 }
06308 
06309 long KHTMLPart::cacheId() const
06310 {
06311   return d->m_cacheId;
06312 }
06313 
06314 bool KHTMLPart::restored() const
06315 {
06316   return d->m_restored;
06317 }
06318 
06319 bool KHTMLPart::pluginPageQuestionAsked(const QString& mimetype) const
06320 {
06321   // parentPart() should be const!
06322   KHTMLPart* parent = const_cast<KHTMLPart *>(this)->parentPart();
06323   if ( parent )
06324     return parent->pluginPageQuestionAsked(mimetype);
06325 
06326   return d->m_pluginPageQuestionAsked.contains(mimetype);
06327 }
06328 
06329 void KHTMLPart::setPluginPageQuestionAsked(const QString& mimetype)
06330 {
06331   if ( parentPart() )
06332     parentPart()->setPluginPageQuestionAsked(mimetype);
06333 
06334   d->m_pluginPageQuestionAsked.append(mimetype);
06335 }
06336 
06337 void KHTMLPart::slotAutomaticDetectionLanguage( int _id )
06338 {
06339   d->m_automaticDetection->setItemChecked( _id, true );
06340 
06341   switch ( _id ) {
06342     case 0 :
06343       d->m_autoDetectLanguage = khtml::Decoder::SemiautomaticDetection;
06344       break;
06345     case 1 :
06346       d->m_autoDetectLanguage = khtml::Decoder::Arabic;
06347       break;
06348     case 2 :
06349       d->m_autoDetectLanguage = khtml::Decoder::Baltic;
06350       break;
06351     case 3 :
06352       d->m_autoDetectLanguage = khtml::Decoder::CentralEuropean;
06353       break;
06354     case 4 :
06355       d->m_autoDetectLanguage = khtml::Decoder::Chinese;
06356       break;
06357     case 5 :
06358       d->m_autoDetectLanguage = khtml::Decoder::Greek;
06359       break;
06360     case 6 :
06361       d->m_autoDetectLanguage = khtml::Decoder::Hebrew;
06362       break;
06363     case 7 :
06364       d->m_autoDetectLanguage = khtml::Decoder::Japanese;
06365       break;
06366     case 8 :
06367       d->m_autoDetectLanguage = khtml::Decoder::Korean;
06368       break;
06369     case 9 :
06370       d->m_autoDetectLanguage = khtml::Decoder::Russian;
06371       break;
06372     case 10 :
06373       d->m_autoDetectLanguage = khtml::Decoder::Thai;
06374       break;
06375     case 11 :
06376       d->m_autoDetectLanguage = khtml::Decoder::Turkish;
06377       break;
06378     case 12 :
06379       d->m_autoDetectLanguage = khtml::Decoder::Ukrainian;
06380       break;
06381     case 13 :
06382       d->m_autoDetectLanguage = khtml::Decoder::Unicode;
06383       break;
06384     case 14 :
06385       d->m_autoDetectLanguage = khtml::Decoder::WesternEuropean;
06386       break;
06387     default :
06388       d->m_autoDetectLanguage = khtml::Decoder::SemiautomaticDetection;
06389       break;
06390   }
06391 
06392   for ( int i = 0; i <= 14; ++i ) {
06393     if ( i != _id )
06394       d->m_automaticDetection->setItemChecked( i, false );
06395   }
06396 
06397   d->m_paSetEncoding->popupMenu()->setItemChecked( 0, true );
06398 
06399   setEncoding( QString::null, false );
06400 
06401   if( d->m_manualDetection )
06402     d->m_manualDetection->setCurrentItem( -1 );
06403   d->m_paSetEncoding->popupMenu()->setItemChecked( d->m_paSetEncoding->popupMenu()->idAt( 2 ), false );
06404 }
06405 
06406 khtml::Decoder *KHTMLPart::createDecoder()
06407 {
06408   khtml::Decoder *dec = new khtml::Decoder();
06409   if( !d->m_encoding.isNull() )
06410     dec->setEncoding( d->m_encoding.latin1(), true );
06411   else
06412     dec->setEncoding( defaultEncoding().latin1(), d->m_haveEncoding );
06413 
06414   dec->setAutoDetectLanguage( d->m_autoDetectLanguage );
06415   return dec;
06416 }
06417 
06418 void KHTMLPart::emitCaretPositionChanged(const DOM::Node &node, long offset) {
06419   emit caretPositionChanged(node, offset);
06420 }
06421 
06422 void KHTMLPart::restoreScrollPosition()
06423 {
06424   KParts::URLArgs args = d->m_extension->urlArgs();
06425   if (!args.reload) {
06426     disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
06427     return; // should not happen
06428   }
06429 
06430   // Check whether the viewport has become large enough to encompass the stored
06431   // offsets. If the document has been fully loaded, force the new coordinates,
06432   // even if the canvas is too short (can happen when user resizes the window
06433   // during loading).
06434   if (d->m_view->contentsHeight() - d->m_view->visibleHeight() >= args.yOffset
06435       || d->m_bComplete) {
06436     d->m_view->setContentsPos(args.xOffset, args.yOffset);
06437     disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
06438   }
06439 }
06440 
06441 KWallet::Wallet* KHTMLPart::wallet()
06442 {
06443   // ### close wallet after a certain timeout period automatically
06444   //      No - KWallet already does this based on user preferences. (GS)
06445   // ### close wallet after screensaver was enabled
06446   //      No - KWalletD should do this, if anything. (GS)
06447 
06448   KHTMLPart* p;
06449 
06450   for (p = parentPart(); p && p->parentPart(); p = p->parentPart())
06451     ;
06452 
06453   if (p)
06454     return p->wallet();
06455 
06456   if (!d->m_wallet && !d->m_bWalletOpened) {
06457     d->m_wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0);
06458     d->m_bWalletOpened = true;
06459     if (d->m_wallet) {
06460       connect(d->m_wallet, SIGNAL(walletClosed()), SLOT(slotWalletClosed()));
06461       d->m_statusBarWalletLabel = new KURLLabel(d->m_statusBarExtension->statusBar());
06462       d->m_statusBarWalletLabel->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small));
06463       d->m_statusBarWalletLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
06464       d->m_statusBarWalletLabel->setUseCursor(false);
06465       d->m_statusBarExtension->addStatusBarItem(d->m_statusBarWalletLabel, 0, false);
06466       QToolTip::add(d->m_statusBarWalletLabel, i18n("The wallet '%1' is open and being used for form data and passwords.").arg(KWallet::Wallet::NetworkWallet()));
06467       d->m_statusBarWalletLabel->setPixmap(SmallIcon("wallet_open", instance()));
06468       connect(d->m_statusBarWalletLabel, SIGNAL(leftClickedURL()), SLOT(launchWalletManager()));
06469       connect(d->m_statusBarWalletLabel, SIGNAL(rightClickedURL()), SLOT(walletMenu()));
06470     } else if (d->m_statusBarWalletLabel) {
06471       d->m_statusBarExtension->removeStatusBarItem(d->m_statusBarWalletLabel);
06472       delete d->m_statusBarWalletLabel;
06473       d->m_statusBarWalletLabel = 0L;
06474     }
06475   }
06476   return d->m_wallet;
06477 }
06478 
06479 void KHTMLPart::slotWalletClosed()
06480 {
06481   if (d->m_wallet) {
06482     d->m_wallet->deleteLater();
06483     d->m_wallet = 0L;
06484   }
06485   d->m_bWalletOpened = false;
06486   if (d->m_statusBarWalletLabel) {
06487     d->m_statusBarExtension->removeStatusBarItem(d->m_statusBarWalletLabel);
06488     delete d->m_statusBarWalletLabel;
06489     d->m_statusBarWalletLabel = 0L;
06490   }
06491 }
06492 
06493 void KHTMLPart::launchWalletManager()
06494 {
06495   if (!DCOPClient::mainClient()->isApplicationRegistered("kwalletmanager")) {
06496     KApplication::startServiceByDesktopName("kwalletmanager_show");
06497   } else {
06498     DCOPRef r("kwalletmanager", "kwalletmanager-mainwindow#1");
06499     r.send("show");
06500     r.send("raise");
06501   }
06502 }
06503 
06504 void KHTMLPart::walletMenu()
06505 {
06506   KPopupMenu *m = new KPopupMenu(0L);
06507   m->insertItem(i18n("&Close Wallet"), this, SLOT(slotWalletClosed()));
06508   m->popup(QCursor::pos());
06509 }
06510 
06511 void KHTMLPart::slotToggleCaretMode()
06512 {
06513   setCaretMode(d->m_paToggleCaretMode->isChecked());
06514 }
06515 
06516 void KHTMLPart::setFormNotification(KHTMLPart::FormNotification fn) {
06517   d->m_formNotification = fn;
06518 }
06519 
06520 KHTMLPart::FormNotification KHTMLPart::formNotification() const {
06521   return d->m_formNotification;
06522 }
06523 
06524 KURL KHTMLPart::toplevelURL()
06525 {
06526   KHTMLPart* part = this;
06527   while (part->parentPart())
06528     part = part->parentPart();
06529 
06530   if (!part)
06531     return KURL();
06532 
06533   return part->url();
06534 }
06535 
06536 bool KHTMLPart::isModified() const
06537 {
06538   if ( !d->m_doc )
06539     return false;
06540 
06541   return d->m_doc->unsubmittedFormChanges();
06542 }
06543 
06544 void KHTMLPart::setDebugScript( bool enable )
06545 {
06546   unplugActionList( "debugScriptList" );
06547   if ( enable ) {
06548     if (!d->m_paDebugScript) {
06549       d->m_paDebugScript = new KAction( i18n( "JavaScript &Debugger" ), 0, this, SLOT( slotDebugScript() ), actionCollection(), "debugScript" );
06550     }
06551     d->m_paDebugScript->setEnabled( d->m_jscript );
06552     QPtrList<KAction> lst;
06553     lst.append( d->m_paDebugScript );
06554     plugActionList( "debugScriptList", lst );
06555   }
06556   d->m_bJScriptDebugEnabled = enable;
06557 }
06558 
06559 using namespace KParts;
06560 #include "khtml_part.moc"
KDE Logo
This file is part of the documentation for khtml Library Version 3.3.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jan 22 16:51:59 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003