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 << " name = " << name() << " 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   if (!childFrame && !parentPart() && (name() == f))
04625      return this;
04626 
04627   FrameIt it = d->m_frames.find( f );
04628   FrameIt end = d->m_frames.end();
04629   if ( it != end )
04630   {
04631 #ifdef DEBUG_FINDFRAME
04632      kdDebug(6050) << "KHTMLPart::findFrameParent: FOUND!" << endl;
04633 #endif
04634      if (childFrame)
04635         *childFrame = &(*it);
04636      return this;
04637   }
04638      
04639   it = d->m_frames.begin();
04640   for (; it != end; ++it )
04641   {
04642     KParts::ReadOnlyPart *p = (*it).m_part;
04643     if ( p && p->inherits( "KHTMLPart" ))
04644     {
04645       KHTMLPart *frameParent = static_cast<KHTMLPart*>(p)->findFrameParent(callingPart, f, childFrame);
04646       if (frameParent)
04647          return frameParent;
04648     }
04649   }
04650   return 0;
04651 }
04652 
04653 
04654 KHTMLPart *KHTMLPart::findFrame( const QString &f )
04655 {
04656   khtml::ChildFrame *childFrame;
04657   KHTMLPart *parentFrame = findFrameParent(this, f, &childFrame);
04658   if (parentFrame)
04659   {
04660      KParts::ReadOnlyPart *p = childFrame->m_part;
04661      if ( p && p->inherits( "KHTMLPart" ))
04662         return static_cast<KHTMLPart *>(p);
04663   }
04664   return 0;
04665 }
04666 
04667 KParts::ReadOnlyPart *KHTMLPart::currentFrame() const
04668 {
04669   KParts::ReadOnlyPart* part = (KParts::ReadOnlyPart*)(this);
04670   // Find active part in our frame manager, in case we are a frameset
04671   // and keep doing that (in case of nested framesets).
04672   // Just realized we could also do this recursively, calling part->currentFrame()...
04673   while ( part && part->inherits("KHTMLPart") &&
04674           static_cast<KHTMLPart *>(part)->d->m_frames.count() > 0 ) {
04675     KHTMLPart* frameset = static_cast<KHTMLPart *>(part);
04676     part = static_cast<KParts::ReadOnlyPart *>(frameset->partManager()->activePart());
04677     if ( !part ) return frameset;
04678   }
04679   return part;
04680 }
04681 
04682 bool KHTMLPart::frameExists( const QString &frameName )
04683 {
04684   ConstFrameIt it = d->m_frames.find( frameName );
04685   if ( it == d->m_frames.end() )
04686     return false;
04687 
04688   // WABA: We only return true if the child actually has a frame
04689   // set. Otherwise we might find our preloaded-selve.
04690   // This happens when we restore the frameset.
04691   return (!(*it).m_frame.isNull());
04692 }
04693 
04694 KHTMLPart *KHTMLPart::parentPart()
04695 {
04696   if ( !parent() || !parent()->inherits( "KHTMLPart" ) )
04697     return 0L;
04698 
04699   return (KHTMLPart *)parent();
04700 }
04701 
04702 khtml::ChildFrame *KHTMLPart::recursiveFrameRequest( KHTMLPart *callingHtmlPart, const KURL &url, 
04703                                                      const KParts::URLArgs &args, bool callParent )
04704 {
04705 #ifdef DEBUG_FINDFRAME
04706   kdDebug( 6050 ) << "KHTMLPart::recursiveFrameRequest this = " << this << ", frame = " << args.frameName << ", url = " << url << endl;
04707 #endif  
04708   khtml::ChildFrame *childFrame;
04709   KHTMLPart *childPart = findFrameParent(callingHtmlPart, args.frameName, &childFrame);
04710   if (childPart)
04711   {
04712      if (childPart == this)
04713         return childFrame;
04714      
04715      childPart->requestObject( childFrame, url, args );
04716      return 0;
04717   }
04718 
04719   if ( parentPart() && callParent )
04720   {
04721      khtml::ChildFrame *res = parentPart()->recursiveFrameRequest( callingHtmlPart, url, args, callParent );
04722 
04723      if ( res )
04724        parentPart()->requestObject( res, url, args );
04725   }
04726 
04727   return 0L;
04728 }
04729 
04730 void KHTMLPart::saveState( QDataStream &stream )
04731 {
04732   kdDebug( 6050 ) << "KHTMLPart::saveState this = " << this << " saving URL " << m_url.url() << endl;
04733 
04734   stream << m_url << (Q_INT32)d->m_view->contentsX() << (Q_INT32)d->m_view->contentsY()
04735          << (Q_INT32) d->m_view->contentsWidth() << (Q_INT32) d->m_view->contentsHeight() << (Q_INT32) d->m_view->marginWidth() << (Q_INT32) d->m_view->marginHeight();
04736 
04737   // save link cursor position
04738   int focusNodeNumber;
04739   if (!d->m_focusNodeRestored)
04740       focusNodeNumber = d->m_focusNodeNumber;
04741   else if (d->m_doc && d->m_doc->focusNode())
04742       focusNodeNumber = d->m_doc->nodeAbsIndex(d->m_doc->focusNode());
04743   else
04744       focusNodeNumber = -1;
04745   stream << focusNodeNumber;
04746 
04747   // Save the doc's cache id.
04748   stream << d->m_cacheId;
04749 
04750   // Save the state of the document (Most notably the state of any forms)
04751   QStringList docState;
04752   if (d->m_doc)
04753   {
04754      docState = d->m_doc->docState();
04755   }
04756   stream << d->m_encoding << d->m_sheetUsed << docState;
04757 
04758   stream << d->m_zoomFactor;
04759 
04760   stream << d->m_httpHeaders;
04761   stream << d->m_pageServices;
04762   stream << d->m_pageReferrer;
04763 
04764   // Save ssl data
04765   stream << d->m_ssl_in_use
04766          << d->m_ssl_peer_certificate
04767          << d->m_ssl_peer_chain
04768          << d->m_ssl_peer_ip
04769          << d->m_ssl_cipher
04770          << d->m_ssl_cipher_desc
04771          << d->m_ssl_cipher_version
04772          << d->m_ssl_cipher_used_bits
04773          << d->m_ssl_cipher_bits
04774          << d->m_ssl_cert_state
04775          << d->m_ssl_parent_ip
04776          << d->m_ssl_parent_cert;
04777 
04778 
04779   QStringList frameNameLst, frameServiceTypeLst, frameServiceNameLst;
04780   KURL::List frameURLLst;
04781   QValueList<QByteArray> frameStateBufferLst;
04782 
04783   ConstFrameIt it = d->m_frames.begin();
04784   ConstFrameIt end = d->m_frames.end();
04785   for (; it != end; ++it )
04786   {
04787     if ( !(*it).m_part )
04788        continue;
04789 
04790     frameNameLst << (*it).m_name;
04791     frameServiceTypeLst << (*it).m_serviceType;
04792     frameServiceNameLst << (*it).m_serviceName;
04793     frameURLLst << (*it).m_part->url();
04794 
04795     QByteArray state;
04796     QDataStream frameStream( state, IO_WriteOnly );
04797 
04798     if ( (*it).m_extension )
04799       (*it).m_extension->saveState( frameStream );
04800 
04801     frameStateBufferLst << state;
04802   }
04803 
04804   // Save frame data
04805   stream << (Q_UINT32) frameNameLst.count();
04806   stream << frameNameLst << frameServiceTypeLst << frameServiceNameLst << frameURLLst << frameStateBufferLst;
04807 }
04808 
04809 void KHTMLPart::restoreState( QDataStream &stream )
04810 {
04811   KURL u;
04812   Q_INT32 xOffset, yOffset, wContents, hContents, mWidth, mHeight;
04813   Q_UINT32 frameCount;
04814   QStringList frameNames, frameServiceTypes, docState, frameServiceNames;
04815   KURL::List frameURLs;
04816   QValueList<QByteArray> frameStateBuffers;
04817   QValueList<int> fSizes;
04818   QString encoding, sheetUsed;
04819   long old_cacheId = d->m_cacheId;
04820 
04821   stream >> u >> xOffset >> yOffset >> wContents >> hContents >> mWidth >> mHeight;
04822 
04823   d->m_view->setMarginWidth( mWidth );
04824   d->m_view->setMarginHeight( mHeight );
04825 
04826   // restore link cursor position
04827   // nth node is active. value is set in checkCompleted()
04828   stream >> d->m_focusNodeNumber;
04829   d->m_focusNodeRestored = false;
04830 
04831   stream >> d->m_cacheId;
04832 
04833   stream >> encoding >> sheetUsed >> docState;
04834 
04835   d->m_encoding = encoding;
04836   d->m_sheetUsed = sheetUsed;
04837 
04838   int zoomFactor;
04839   stream >> zoomFactor;
04840   setZoomFactor(zoomFactor);
04841 
04842   stream >> d->m_httpHeaders;
04843   stream >> d->m_pageServices;
04844   stream >> d->m_pageReferrer;
04845 
04846   // Restore ssl data
04847   stream >> d->m_ssl_in_use
04848          >> d->m_ssl_peer_certificate
04849          >> d->m_ssl_peer_chain
04850          >> d->m_ssl_peer_ip
04851          >> d->m_ssl_cipher
04852          >> d->m_ssl_cipher_desc
04853          >> d->m_ssl_cipher_version
04854          >> d->m_ssl_cipher_used_bits
04855          >> d->m_ssl_cipher_bits
04856          >> d->m_ssl_cert_state
04857          >> d->m_ssl_parent_ip
04858          >> d->m_ssl_parent_cert;
04859 
04860   setPageSecurity( d->m_ssl_in_use ? Encrypted : NotCrypted );
04861 
04862   stream >> frameCount >> frameNames >> frameServiceTypes >> frameServiceNames
04863          >> frameURLs >> frameStateBuffers;
04864 
04865   d->m_bComplete = false;
04866   d->m_bLoadEventEmitted = false;
04867 
04868 //   kdDebug( 6050 ) << "restoreStakte() docState.count() = " << docState.count() << endl;
04869 //   kdDebug( 6050 ) << "m_url " << m_url.url() << " <-> " << u.url() << endl;
04870 //   kdDebug( 6050 ) << "m_frames.count() " << d->m_frames.count() << " <-> " << frameCount << endl;
04871 
04872   if (d->m_cacheId == old_cacheId)
04873   {
04874     // Partial restore
04875     d->m_redirectionTimer.stop();
04876 
04877     FrameIt fIt = d->m_frames.begin();
04878     FrameIt fEnd = d->m_frames.end();
04879 
04880     for (; fIt != fEnd; ++fIt )
04881         (*fIt).m_bCompleted = false;
04882 
04883     fIt = d->m_frames.begin();
04884 
04885     QStringList::ConstIterator fNameIt = frameNames.begin();
04886     QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
04887     QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
04888     KURL::List::ConstIterator fURLIt = frameURLs.begin();
04889     QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
04890 
04891     for (; fIt != fEnd; ++fIt, ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
04892     {
04893       khtml::ChildFrame *child = &(*fIt);
04894 
04895 //      kdDebug( 6050 ) <<  *fNameIt  << " ---- " <<  *fServiceTypeIt << endl;
04896 
04897       if ( child->m_name != *fNameIt || child->m_serviceType != *fServiceTypeIt )
04898       {
04899         child->m_bPreloaded = true;
04900         child->m_name = *fNameIt;
04901         child->m_serviceName = *fServiceNameIt;
04902         processObjectRequest( child, *fURLIt, *fServiceTypeIt );
04903       }
04904 
04905       if ( child->m_part )
04906       {
04907         child->m_bCompleted = false;
04908         if ( child->m_extension && !(*fBufferIt).isEmpty() )
04909         {
04910           QDataStream frameStream( *fBufferIt, IO_ReadOnly );
04911           child->m_extension->restoreState( frameStream );
04912         }
04913         else
04914           child->m_part->openURL( *fURLIt );
04915       }
04916     }
04917 
04918     KParts::URLArgs args( d->m_extension->urlArgs() );
04919     args.xOffset = xOffset;
04920     args.yOffset = yOffset;
04921     args.docState = docState;
04922     d->m_extension->setURLArgs( args );
04923 
04924     d->m_view->resizeContents( wContents,  hContents);
04925     d->m_view->setContentsPos( xOffset, yOffset );
04926 
04927     m_url = u;
04928   }
04929   else
04930   {
04931     // Full restore.
04932     closeURL();
04933     // We must force a clear because we want to be sure to delete all
04934     // frames.
04935     d->m_bCleared = false;
04936     clear();
04937     d->m_encoding = encoding;
04938     d->m_sheetUsed = sheetUsed;
04939 
04940     QStringList::ConstIterator fNameIt = frameNames.begin();
04941     QStringList::ConstIterator fNameEnd = frameNames.end();
04942 
04943     QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
04944     QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
04945     KURL::List::ConstIterator fURLIt = frameURLs.begin();
04946     QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
04947 
04948     for (; fNameIt != fNameEnd; ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
04949     {
04950       khtml::ChildFrame newChild;
04951       newChild.m_bPreloaded = true;
04952       newChild.m_name = *fNameIt;
04953       newChild.m_serviceName = *fServiceNameIt;
04954 
04955 //      kdDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt << endl;
04956 
04957       FrameIt childFrame = d->m_frames.append( newChild );
04958 
04959       processObjectRequest( &(*childFrame), *fURLIt, *fServiceTypeIt );
04960 
04961       (*childFrame).m_bPreloaded = true;
04962 
04963       if ( (*childFrame).m_part )
04964       {
04965         if ( (*childFrame).m_extension )
04966         if ( (*childFrame).m_extension && !(*fBufferIt).isEmpty() )
04967         {
04968           QDataStream frameStream( *fBufferIt, IO_ReadOnly );
04969           (*childFrame).m_extension->restoreState( frameStream );
04970         }
04971         else
04972           (*childFrame).m_part->openURL( *fURLIt );
04973       }
04974     }
04975 
04976     KParts::URLArgs args( d->m_extension->urlArgs() );
04977     args.xOffset = xOffset;
04978     args.yOffset = yOffset;
04979     args.docState = docState;
04980 
04981     d->m_view->resizeContents( wContents,  hContents);
04982     d->m_view->setContentsPos( xOffset, yOffset );
04983 
04984     d->m_extension->setURLArgs( args );
04985     if (!KHTMLPageCache::self()->isComplete(d->m_cacheId))
04986     {
04987        d->m_restored = true;
04988        openURL( u );
04989        d->m_restored = false;
04990     }
04991     else
04992     {
04993        restoreURL( u );
04994     }
04995   }
04996 
04997 }
04998 
04999 void KHTMLPart::show()
05000 {
05001   if ( d->m_view )
05002     d->m_view->show();
05003 }
05004 
05005 void KHTMLPart::hide()
05006 {
05007   if ( d->m_view )
05008     d->m_view->hide();
05009 }
05010 
05011 DOM::Node KHTMLPart::nodeUnderMouse() const
05012 {
05013     return d->m_view->nodeUnderMouse();
05014 }
05015 
05016 DOM::Node KHTMLPart::nonSharedNodeUnderMouse() const
05017 {
05018     return d->m_view->nonSharedNodeUnderMouse();
05019 }
05020 
05021 void KHTMLPart::emitSelectionChanged()
05022 {
05023   emit d->m_extension->enableAction( "copy", hasSelection() );
05024   if ( d->m_findDialog )
05025        d->m_findDialog->setHasSelection( hasSelection() );
05026 
05027   emit d->m_extension->selectionInfo( selectedText() );
05028   emit selectionChanged();
05029 }
05030 
05031 int KHTMLPart::zoomFactor() const
05032 {
05033   return d->m_zoomFactor;
05034 }
05035 
05036 // ### make the list configurable ?
05037 static const int zoomSizes[] = { 20, 40, 60, 80, 90, 95, 100, 105, 110, 120, 140, 160, 180, 200, 250, 300 };
05038 static const int zoomSizeCount = (sizeof(zoomSizes) / sizeof(int));
05039 static const int minZoom = 20;
05040 static const int maxZoom = 300;
05041 
05042 // My idea of useful stepping ;-) (LS)
05043 extern const int KDE_NO_EXPORT fastZoomSizes[] = { 20, 50, 75, 90, 100, 120, 150, 200, 300 };
05044 extern const int KDE_NO_EXPORT fastZoomSizeCount = sizeof fastZoomSizes / sizeof fastZoomSizes[0];
05045 
05046 void KHTMLPart::slotIncZoom()
05047 {
05048   zoomIn(zoomSizes, zoomSizeCount);
05049 }
05050 
05051 void KHTMLPart::slotDecZoom()
05052 {
05053   zoomOut(zoomSizes, zoomSizeCount);
05054 }
05055 
05056 void KHTMLPart::slotIncZoomFast()
05057 {
05058   zoomIn(fastZoomSizes, fastZoomSizeCount);
05059 }
05060 
05061 void KHTMLPart::slotDecZoomFast()
05062 {
05063   zoomOut(fastZoomSizes, fastZoomSizeCount);
05064 }
05065 
05066 void KHTMLPart::zoomIn(const int stepping[], int count)
05067 {
05068   int zoomFactor = d->m_zoomFactor;
05069 
05070   if (zoomFactor < maxZoom) {
05071     // find the entry nearest to the given zoomsizes
05072     for (int i = 0; i < count; ++i)
05073       if (stepping[i] > zoomFactor) {
05074         zoomFactor = stepping[i];
05075         break;
05076       }
05077     setZoomFactor(zoomFactor);
05078   }
05079 }
05080 
05081 void KHTMLPart::zoomOut(const int stepping[], int count)
05082 {
05083     int zoomFactor = d->m_zoomFactor;
05084     if (zoomFactor > minZoom) {
05085       // find the entry nearest to the given zoomsizes
05086       for (int i = count-1; i >= 0; --i)
05087         if (stepping[i] < zoomFactor) {
05088           zoomFactor = stepping[i];
05089           break;
05090         }
05091       setZoomFactor(zoomFactor);
05092     }
05093 }
05094 
05095 void KHTMLPart::setZoomFactor (int percent)
05096 {
05097   if (percent < minZoom) percent = minZoom;
05098   if (percent > maxZoom) percent = maxZoom;
05099   if (d->m_zoomFactor == percent) return;
05100   d->m_zoomFactor = percent;
05101 
05102   if(d->m_doc) {
05103       QApplication::setOverrideCursor( waitCursor );
05104     if (d->m_doc->styleSelector())
05105       d->m_doc->styleSelector()->computeFontSizes(d->m_doc->paintDeviceMetrics(), d->m_zoomFactor);
05106     d->m_doc->recalcStyle( NodeImpl::Force );
05107     QApplication::restoreOverrideCursor();
05108   }
05109 
05110   ConstFrameIt it = d->m_frames.begin();
05111   ConstFrameIt end = d->m_frames.end();
05112   for (; it != end; ++it )
05113     if ( !( *it ).m_part.isNull() && ( *it ).m_part->inherits( "KHTMLPart" ) ) {
05114       KParts::ReadOnlyPart* p = ( *it ).m_part;
05115       static_cast<KHTMLPart*>( p )->setZoomFactor(d->m_zoomFactor);
05116     }
05117 
05118   if ( d->m_guiProfile == BrowserViewGUI ) {
05119       d->m_paDecZoomFactor->setEnabled( d->m_zoomFactor > minZoom );
05120       d->m_paIncZoomFactor->setEnabled( d->m_zoomFactor < maxZoom );
05121   }
05122 }
05123 
05124 void KHTMLPart::slotZoomView( int delta )
05125 {
05126   if ( delta < 0 )
05127     slotIncZoom();
05128   else
05129     slotDecZoom();
05130 }
05131 
05132 void KHTMLPart::setStatusBarText( const QString& text, StatusBarPriority p)
05133 {
05134   if (!d->m_statusMessagesEnabled)
05135     return;
05136 
05137   d->m_statusBarText[p] = text;
05138 
05139   // shift handling ?
05140   QString tobe = d->m_statusBarText[BarHoverText];
05141   if (tobe.isEmpty())
05142     tobe = d->m_statusBarText[BarOverrideText];
05143   if (tobe.isEmpty()) {
05144     tobe = d->m_statusBarText[BarDefaultText];
05145     if (!tobe.isEmpty() && d->m_jobspeed)
05146       tobe += " ";
05147     if (d->m_jobspeed)
05148       tobe += i18n( "(%1/s)" ).arg( KIO::convertSize( d->m_jobspeed ) );
05149   }
05150   tobe = "<qt>"+tobe;
05151 
05152   emit ReadOnlyPart::setStatusBarText(tobe);
05153 }
05154 
05155 
05156 void KHTMLPart::setJSStatusBarText( const QString &text )
05157 {
05158   setStatusBarText(text, BarOverrideText);
05159 }
05160 
05161 void KHTMLPart::setJSDefaultStatusBarText( const QString &text )
05162 {
05163   setStatusBarText(text, BarDefaultText);
05164 }
05165 
05166 QString KHTMLPart::jsStatusBarText() const
05167 {
05168     return d->m_statusBarText[BarOverrideText];
05169 }
05170 
05171 QString KHTMLPart::jsDefaultStatusBarText() const
05172 {
05173    return d->m_statusBarText[BarDefaultText];
05174 }
05175 
05176 QString KHTMLPart::referrer() const
05177 {
05178    return d->m_referrer;
05179 }
05180 
05181 QString KHTMLPart::pageReferrer() const
05182 {
05183    KURL referrerURL = KURL( d->m_pageReferrer );
05184    if (referrerURL.isValid())
05185    {
05186       QString protocol = referrerURL.protocol();
05187 
05188       if ((protocol == "http") ||
05189          ((protocol == "https") && (m_url.protocol() == "https")))
05190       {
05191           referrerURL.setRef(QString::null);
05192           referrerURL.setUser(QString::null);
05193           referrerURL.setPass(QString::null);
05194           return referrerURL.url();
05195       }
05196    }
05197 
05198    return QString::null;
05199 }
05200 
05201 
05202 QString KHTMLPart::lastModified() const
05203 {
05204   if ( d->m_lastModified.isEmpty() && m_url.isLocalFile() ) {
05205     // Local file: set last-modified from the file's mtime.
05206     // Done on demand to save time when this isn't needed - but can lead
05207     // to slightly wrong results if updating the file on disk w/o reloading.
05208     QDateTime lastModif = QFileInfo( m_url.path() ).lastModified();
05209     d->m_lastModified = lastModif.toString( Qt::LocalDate );
05210   }
05211   //kdDebug(6050) << "KHTMLPart::lastModified: " << d->m_lastModified << endl;
05212   return d->m_lastModified;
05213 }
05214 
05215 void KHTMLPart::slotLoadImages()
05216 {
05217   if (d->m_doc )
05218     d->m_doc->docLoader()->setAutoloadImages( !d->m_doc->docLoader()->autoloadImages() );
05219 
05220   ConstFrameIt it = d->m_frames.begin();
05221   ConstFrameIt end = d->m_frames.end();
05222   for (; it != end; ++it )
05223     if ( !( *it ).m_part.isNull() && ( *it ).m_part->inherits( "KHTMLPart" ) ) {
05224       KParts::ReadOnlyPart* p = ( *it ).m_part;
05225       static_cast<KHTMLPart*>( p )->slotLoadImages();
05226     }
05227 }
05228 
05229 void KHTMLPart::reparseConfiguration()
05230 {
05231   KHTMLSettings *settings = KHTMLFactory::defaultHTMLSettings();
05232   settings->init();
05233 
05234   setAutoloadImages( settings->autoLoadImages() );
05235   if (d->m_doc)
05236      d->m_doc->docLoader()->setShowAnimations( settings->showAnimations() );
05237 
05238   d->m_bOpenMiddleClick = settings->isOpenMiddleClickEnabled();
05239   d->m_bBackRightClick = settings->isBackRightClickEnabled();
05240   d->m_bJScriptEnabled = settings->isJavaScriptEnabled(m_url.host());
05241   setDebugScript( settings->isJavaScriptDebugEnabled() );
05242   d->m_bJavaEnabled = settings->isJavaEnabled(m_url.host());
05243   d->m_bPluginsEnabled = settings->isPluginsEnabled(m_url.host());
05244   d->m_metaRefreshEnabled = settings->isAutoDelayedActionsEnabled ();
05245 
05246   delete d->m_settings;
05247   d->m_settings = new KHTMLSettings(*KHTMLFactory::defaultHTMLSettings());
05248 
05249   QApplication::setOverrideCursor( waitCursor );
05250   khtml::CSSStyleSelector::reparseConfiguration();
05251   if(d->m_doc) d->m_doc->updateStyleSelector();
05252   QApplication::restoreOverrideCursor();
05253 }
05254 
05255 QStringList KHTMLPart::frameNames() const
05256 {
05257   QStringList res;
05258 
05259   ConstFrameIt it = d->m_frames.begin();
05260   ConstFrameIt end = d->m_frames.end();
05261   for (; it != end; ++it )
05262     if (!(*it).m_bPreloaded)
05263       res += (*it).m_name;
05264 
05265   return res;
05266 }
05267 
05268 QPtrList<KParts::ReadOnlyPart> KHTMLPart::frames() const
05269 {
05270   QPtrList<KParts::ReadOnlyPart> res;
05271 
05272   ConstFrameIt it = d->m_frames.begin();
05273   ConstFrameIt end = d->m_frames.end();
05274   for (; it != end; ++it )
05275     if (!(*it).m_bPreloaded)
05276       res.append( (*it).m_part );
05277 
05278   return res;
05279 }
05280 
05281 bool KHTMLPart::openURLInFrame( const KURL &url, const KParts::URLArgs &urlArgs )
05282 {
05283     kdDebug( 6050 ) << this << "KHTMLPart::openURLInFrame " << url << endl;
05284   FrameIt it = d->m_frames.find( urlArgs.frameName );
05285 
05286   if ( it == d->m_frames.end() )
05287     return false;
05288 
05289   // Inform someone that we are about to show something else.
05290   if ( !urlArgs.lockHistory() )
05291       emit d->m_extension->openURLNotify();
05292 
05293   requestObject( &(*it), url, urlArgs );
05294 
05295   return true;
05296 }
05297 
05298 void KHTMLPart::setDNDEnabled( bool b )
05299 {
05300   d->m_bDnd = b;
05301 }
05302 
05303 bool KHTMLPart::dndEnabled() const
05304 {
05305   return d->m_bDnd;
05306 }
05307 
05308 void KHTMLPart::customEvent( QCustomEvent *event )
05309 {
05310   if ( khtml::MousePressEvent::test( event ) )
05311   {
05312     khtmlMousePressEvent( static_cast<khtml::MousePressEvent *>( event ) );
05313     return;
05314   }
05315 
05316   if ( khtml::MouseDoubleClickEvent::test( event ) )
05317   {
05318     khtmlMouseDoubleClickEvent( static_cast<khtml::MouseDoubleClickEvent *>( event ) );
05319     return;
05320   }
05321 
05322   if ( khtml::MouseMoveEvent::test( event ) )
05323   {
05324     khtmlMouseMoveEvent( static_cast<khtml::MouseMoveEvent *>( event ) );
05325     return;
05326   }
05327 
05328   if ( khtml::MouseReleaseEvent::test( event ) )
05329   {
05330     khtmlMouseReleaseEvent( static_cast<khtml::MouseReleaseEvent *>( event ) );
05331     return;
05332   }
05333 
05334   if ( khtml::DrawContentsEvent::test( event ) )
05335   {
05336     khtmlDrawContentsEvent( static_cast<khtml::DrawContentsEvent *>( event ) );
05337     return;
05338   }
05339 
05340   KParts::ReadOnlyPart::customEvent( event );
05341 }
05342 
05348 static bool firstRunAt(khtml::RenderObject *renderNode, int y, NodeImpl *&startNode, long &startOffset)
05349 {
05350     for (khtml::RenderObject *n = renderNode; n; n = n->nextSibling()) {
05351         if (n->isText()) {
05352             khtml::RenderText *textRenderer = static_cast<khtml::RenderText *>(n);
05353             const khtml::InlineTextBoxArray &runs = textRenderer->inlineTextBoxes();
05354             for (unsigned i = 0; i != runs.count(); i++) {
05355                 if (runs[i]->m_y == y) {
05356                     startNode = textRenderer->element();
05357                     startOffset = runs[i]->m_start;
05358                     return true;
05359                 }
05360             }
05361         }
05362 
05363         if (firstRunAt(n->firstChild(), y, startNode, startOffset)) {
05364             return true;
05365         }
05366     }
05367 
05368     return false;
05369 }
05370 
05376 static bool lastRunAt(khtml::RenderObject *renderNode, int y, NodeImpl *&endNode, long &endOffset)
05377 {
05378     khtml::RenderObject *n = renderNode;
05379     if (!n) {
05380         return false;
05381     }
05382     khtml::RenderObject *next;
05383     while ((next = n->nextSibling())) {
05384         n = next;
05385     }
05386 
05387     while (1) {
05388         if (lastRunAt(n->firstChild(), y, endNode, endOffset)) {
05389             return true;
05390         }
05391 
05392         if (n->isText()) {
05393             khtml::RenderText *textRenderer =  static_cast<khtml::RenderText *>(n);
05394             const khtml::InlineTextBoxArray &runs = textRenderer->inlineTextBoxes();
05395             for (int i = (int)runs.count()-1; i >= 0; i--) {
05396                 if (runs[i]->m_y == y) {
05397                     endNode = textRenderer->element();
05398                     endOffset = runs[i]->m_start + runs[i]->m_len;
05399                     return true;
05400                 }
05401             }
05402         }
05403 
05404         if (n == renderNode) {
05405             return false;
05406         }
05407 
05408         n = n->previousSibling();
05409     }
05410 }
05411 
05412 void KHTMLPart::khtmlMousePressEvent( khtml::MousePressEvent *event )
05413 {
05414   DOM::DOMString url = event->url();
05415   QMouseEvent *_mouse = event->qmouseEvent();
05416   DOM::Node innerNode = event->innerNode();
05417   d->m_mousePressNode = innerNode;
05418 
05419    d->m_dragStartPos = _mouse->pos();
05420 
05421    if ( !event->url().isNull() ) {
05422      d->m_strSelectedURL = event->url().string();
05423      d->m_strSelectedURLTarget = event->target().string();
05424    }
05425    else
05426      d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
05427 
05428   if ( _mouse->button() == LeftButton ||
05429        _mouse->button() == MidButton )
05430   {
05431     d->m_bMousePressed = true;
05432 
05433 #ifndef KHTML_NO_SELECTION
05434     if ( _mouse->button() == LeftButton )
05435     {
05436       if ( (!d->m_strSelectedURL.isNull() && !isEditable())
05437             || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) )
05438       return;
05439       if ( !innerNode.isNull()  && innerNode.handle()->renderer()) {
05440           int offset = 0;
05441           DOM::NodeImpl* node = 0;
05442           khtml::RenderObject::SelPointState state;
05443           innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(),
05444                                                                event->absX()-innerNode.handle()->renderer()->xPos(),
05445                                                                event->absY()-innerNode.handle()->renderer()->yPos(), node, offset, state );
05446           d->m_extendMode = d->ExtendByChar;
05447 #ifdef KHTML_NO_CARET
05448           d->m_selectionStart = node;
05449           d->m_startOffset = offset;
05450           //if ( node )
05451           //  kdDebug(6005) << "KHTMLPart::khtmlMousePressEvent selectionStart=" << d->m_selectionStart.handle()->renderer()
05452           //                << " offset=" << d->m_startOffset << endl;
05453           //else
05454           //  kdDebug(6005) << "KHTML::khtmlMousePressEvent selectionStart=(nil)" << endl;
05455           d->m_selectionEnd = d->m_selectionStart;
05456           d->m_endOffset = d->m_startOffset;
05457           d->m_doc->clearSelection();
05458 #else // KHTML_NO_CARET
05459       d->m_view->moveCaretTo(node, offset, (_mouse->state() & ShiftButton) == 0);
05460 #endif // KHTML_NO_CARET
05461       d->m_initialNode = d->m_selectionStart;
05462       d->m_initialOffset = d->m_startOffset;
05463 //           kdDebug(6000) << "press: initOfs " << d->m_initialOffset << endl;
05464       }
05465       else
05466       {
05467 #ifndef KHTML_NO_CARET
05468         // simply leave it. Is this a good idea?
05469 #else
05470         d->m_selectionStart = DOM::Node();
05471         d->m_selectionEnd = DOM::Node();
05472 #endif
05473       }
05474       emitSelectionChanged();
05475       startAutoScroll();
05476     }
05477 #else
05478     d->m_dragLastPos = _mouse->globalPos();
05479 #endif
05480   }
05481 
05482   if ( _mouse->button() == RightButton && parentPart() != 0 && d->m_bBackRightClick )
05483   {
05484     d->m_bRightMousePressed = true;
05485   } else if ( _mouse->button() == RightButton )
05486   {
05487     popupMenu( d->m_strSelectedURL );
05488     // might be deleted, don't touch "this"
05489   }
05490 }
05491 
05492 void KHTMLPart::khtmlMouseDoubleClickEvent( khtml::MouseDoubleClickEvent *event )
05493 {
05494   QMouseEvent *_mouse = event->qmouseEvent();
05495   if ( _mouse->button() == LeftButton )
05496   {
05497     d->m_bMousePressed = true;
05498     DOM::Node innerNode = event->innerNode();
05499     // Find selectionStart again, khtmlMouseReleaseEvent lost it
05500     if ( !innerNode.isNull() && innerNode.handle()->renderer()) {
05501       int offset = 0;
05502       DOM::NodeImpl* node = 0;
05503       khtml::RenderObject::SelPointState state;
05504       innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(),
05505                                                            event->absX()-innerNode.handle()->renderer()->xPos(),
05506                                                            event->absY()-innerNode.handle()->renderer()->yPos(), node, offset, state);
05507 
05508       //kdDebug() << k_funcinfo << "checkSelectionPoint returned node=" << node << " offset=" << offset << endl;
05509 
05510       if ( node && node->renderer() )
05511       {
05512         // Extend selection to a complete word (double-click) or line (triple-click)
05513         bool selectLine = (event->clickCount() == 3);
05514         d->m_extendMode = selectLine ? d->ExtendByLine : d->ExtendByWord;
05515 
05516     // Extend existing selection if Shift was pressed
05517     if (_mouse->state() & ShiftButton) {
05518           d->caretNode() = node;
05519       d->caretOffset() = offset;
05520           d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
05521                 d->m_selectionStart.handle(), d->m_startOffset,
05522             d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
05523           d->m_initialNode = d->m_extendAtEnd ? d->m_selectionStart : d->m_selectionEnd;
05524           d->m_initialOffset = d->m_extendAtEnd ? d->m_startOffset : d->m_endOffset;
05525     } else {
05526       d->m_selectionStart = d->m_selectionEnd = node;
05527       d->m_startOffset = d->m_endOffset = offset;
05528           d->m_startBeforeEnd = true;
05529           d->m_initialNode = node;
05530           d->m_initialOffset = offset;
05531     }
05532 //         kdDebug(6000) << "dblclk: initOfs " << d->m_initialOffset << endl;
05533 
05534         // Extend the start
05535         extendSelection( d->m_selectionStart.handle(), d->m_startOffset, d->m_selectionStart, d->m_startOffset, !d->m_startBeforeEnd, selectLine );
05536         // Extend the end
05537         extendSelection( d->m_selectionEnd.handle(), d->m_endOffset, d->m_selectionEnd, d->m_endOffset, d->m_startBeforeEnd, selectLine );
05538 
05539         //kdDebug() << d->m_selectionStart.handle() << " " << d->m_startOffset << "  -  " <<
05540         //  d->m_selectionEnd.handle() << " " << d->m_endOffset << endl;
05541 
05542         emitSelectionChanged();
05543         d->m_doc
05544           ->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
05545                          d->m_selectionEnd.handle(),d->m_endOffset);
05546 #ifndef KHTML_NO_CARET
05547         bool v = d->m_view->placeCaret();
05548         emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
05549 #endif
05550         startAutoScroll();
05551       }
05552     }
05553   }
05554 }
05555 
05556 void KHTMLPart::extendSelection( DOM::NodeImpl* node, long offset, DOM::Node& selectionNode, long& selectionOffset, bool right, bool selectLines )
05557 {
05558   khtml::RenderObject* obj = node->renderer();
05559 
05560   if (obj->isText() && selectLines) {
05561     int pos;
05562     khtml::RenderText *renderer = static_cast<khtml::RenderText *>(obj);
05563     khtml::InlineTextBox *run = renderer->findInlineTextBox( offset, pos );
05564     DOMString t = node->nodeValue();
05565     DOM::NodeImpl* selNode = 0;
05566     long selOfs = 0;
05567 
05568     if (!run)
05569       return;
05570 
05571     int selectionPointY = run->m_y;
05572 
05573     // Go up to first non-inline element.
05574     khtml::RenderObject *renderNode = renderer;
05575     while (renderNode && renderNode->isInline())
05576       renderNode = renderNode->parent();
05577 
05578     renderNode = renderNode->firstChild();
05579 
05580     if (right) {
05581       // Look for all the last child in the block that is on the same line
05582       // as the selection point.
05583       if (!lastRunAt (renderNode, selectionPointY, selNode, selOfs))
05584         return;
05585     } else {
05586       // Look for all the first child in the block that is on the same line
05587       // as the selection point.
05588       if (!firstRunAt (renderNode, selectionPointY, selNode, selOfs))
05589         return;
05590     }
05591 
05592     selectionNode = selNode;
05593     selectionOffset = selOfs;
05594     return;
05595   }
05596 
05597   QString str;
05598   int len = 0;
05599   if ( obj->isText() ) { // can be false e.g. when double-clicking on a disabled submit button
05600     str = static_cast<khtml::RenderText *>(obj)->data().string();
05601     len = str.length();
05602   }
05603   //kdDebug() << "extendSelection right=" << right << " offset=" << offset << " len=" << len << " Starting at obj=" << obj << endl;
05604   QChar ch;
05605   do {
05606     // Last char was ok, point to it
05607     if ( node ) {
05608       selectionNode = node;
05609       selectionOffset = offset;
05610     }
05611 
05612     // Get another char
05613     while ( obj && ( (right && offset >= len-1) || (!right && offset <= 0) ) )
05614     {
05615       obj = right ? obj->objectBelow() : obj->objectAbove();
05616       //kdDebug() << "obj=" << obj << endl;
05617       if ( obj ) {
05618         //kdDebug() << "isText=" << obj->isText() << endl;
05619         str = QString::null;
05620         if ( obj->isText() )
05621           str = static_cast<khtml::RenderText *>(obj)->data().string();
05622         else if ( obj->isBR() )
05623           str = '\n';
05624         else if ( !obj->isInline() ) {
05625           obj = 0L; // parag limit -> done
05626           break;
05627         }
05628         len = str.length();
05629         //kdDebug() << "str=" << str << " length=" << len << endl;
05630         // set offset - note that the first thing will be a ++ or -- on it.
05631         if ( right )
05632           offset = -1;
05633         else
05634           offset = len;
05635       }
05636     }
05637     if ( !obj ) // end of parag or document
05638       break;
05639     node = obj->element();
05640     if ( right )
05641     {
05642       Q_ASSERT( offset < len-1 );
05643       offset++;
05644     }
05645     else
05646     {
05647       Q_ASSERT( offset > 0 );
05648       offset--;
05649     }
05650 
05651     // Test that char
05652     ch = str[ offset ];
05653     //kdDebug() << " offset=" << offset << " ch=" << QString(ch) << endl;
05654   } while ( !ch.isSpace() && !ch.isPunct() );
05655 
05656   // make offset point after last char
05657   if (right) selectionOffset++;
05658 }
05659 
05660 #ifndef KHTML_NO_SELECTION
05661 void KHTMLPart::extendSelectionTo(int x, int y, int absX, int absY, const DOM::Node &innerNode)
05662 {
05663       int offset;
05664       //kdDebug(6000) << "KHTMLPart::khtmlMouseMoveEvent x=" << event->x() << " y=" << event->y() << endl;
05665       DOM::NodeImpl* node=0;
05666       khtml::RenderObject::SelPointState state;
05667       innerNode.handle()->renderer()->checkSelectionPoint( x, y,
05668                                                            absX-innerNode.handle()->renderer()->xPos(),
05669                                                            absY-innerNode.handle()->renderer()->yPos(), node, offset, state);
05670       if (!node || !node->renderer()) return;
05671 
05672       // Words at the beginning/end of line cannot be deselected in
05673       // ExtendByWord mode. Therefore, do not enforce it if the selection
05674       // point does not match the node under the mouse cursor.
05675       bool withinNode = innerNode == node;
05676 
05677       // we have to get to know if end is before start or not...
05678       // shouldn't be null but it can happen with dynamic updating of nodes
05679       if (d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() ||
05680           d->m_initialNode.isNull() ||
05681           !d->m_selectionStart.handle()->renderer() ||
05682           !d->m_selectionEnd.handle()->renderer()) return;
05683 
05684       if (d->m_extendMode != d->ExtendByChar) {
05685         // check whether we should extend at the front, or at the back
05686         bool caretBeforeInit = RangeImpl::compareBoundaryPoints(
05687                 d->caretNode().handle(), d->caretOffset(),
05688             d->m_initialNode.handle(), d->m_initialOffset) <= 0;
05689         bool nodeBeforeInit = RangeImpl::compareBoundaryPoints(node, offset,
05690             d->m_initialNode.handle(), d->m_initialOffset) <= 0;
05691         // have to fix up start to point to the original end
05692         if (caretBeforeInit != nodeBeforeInit) {
05693 //         kdDebug(6000) << "extto cbi: " << caretBeforeInit << " startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << " initOfs " << d->m_initialOffset << endl;
05694           extendSelection(d->m_initialNode.handle(), d->m_initialOffset,
05695         d->m_extendAtEnd ? d->m_selectionStart : d->m_selectionEnd,
05696         d->m_extendAtEnd ? d->m_startOffset : d->m_endOffset,
05697         nodeBeforeInit, d->m_extendMode == d->ExtendByLine);
05698     }
05699       }
05700 
05701       d->caretNode() = node;
05702       d->caretOffset() = offset;
05703       //kdDebug( 6000 ) << "setting end of selection to " << d->m_selectionEnd.handle() << "/" << d->m_endOffset << endl;
05704 
05705       d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
05706                 d->m_selectionStart.handle(), d->m_startOffset,
05707             d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
05708 
05709       if ( !d->m_selectionStart.isNull() && !d->m_selectionEnd.isNull() )
05710       {
05711 //         kdDebug(6000) << "extto: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << " initOfs " << d->m_initialOffset << endl;
05712         if (d->m_extendMode != d->ExtendByChar && withinNode)
05713           extendSelection( node, offset, d->caretNode(), d->caretOffset(), d->m_startBeforeEnd ^ !d->m_extendAtEnd, d->m_extendMode == d->ExtendByLine );
05714 
05715         if (d->m_selectionEnd == d->m_selectionStart && d->m_endOffset < d->m_startOffset)
05716           d->m_doc
05717             ->setSelection(d->m_selectionStart.handle(),d->m_endOffset,
05718                            d->m_selectionEnd.handle(),d->m_startOffset);
05719         else if (d->m_startBeforeEnd)
05720           d->m_doc
05721             ->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
05722                            d->m_selectionEnd.handle(),d->m_endOffset);
05723         else
05724           d->m_doc
05725             ->setSelection(d->m_selectionEnd.handle(),d->m_endOffset,
05726                            d->m_selectionStart.handle(),d->m_startOffset);
05727       }
05728 #ifndef KHTML_NO_CARET
05729       d->m_view->placeCaret();
05730 #endif
05731 }
05732 
05733 bool KHTMLPart::isExtendingSelection() const
05734 {
05735   // This is it, the whole detection. khtmlMousePressEvent only sets this
05736   // on LMB or MMB, but never on RMB. As text selection doesn't work for MMB,
05737   // it's sufficient to only rely on this flag to detect selection extension.
05738   return d->m_bMousePressed;
05739 }
05740 #endif // KHTML_NO_SELECTION
05741 
05742 void KHTMLPart::khtmlMouseMoveEvent( khtml::MouseMoveEvent *event )
05743 {
05744   QMouseEvent *_mouse = event->qmouseEvent();
05745 
05746   if( d->m_bRightMousePressed && parentPart() != 0 && d->m_bBackRightClick )
05747   {
05748     popupMenu( d->m_strSelectedURL );
05749     d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
05750     d->m_bRightMousePressed = false;
05751   }
05752 
05753   DOM::DOMString url = event->url();
05754   DOM::DOMString target = event->target();
05755   DOM::Node innerNode = event->innerNode();
05756 
05757 #ifndef QT_NO_DRAGANDDROP
05758   if( d->m_bDnd && d->m_bMousePressed &&
05759       ( (!d->m_strSelectedURL.isEmpty() && !isEditable())
05760         || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) ) ) {
05761     if ( ( d->m_dragStartPos - _mouse->pos() ).manhattanLength() <= KGlobalSettings::dndEventDelay() )
05762       return;
05763 
05764     QPixmap pix;
05765     HTMLImageElementImpl *img = 0L;
05766     QDragObject *drag = 0;
05767     KURL u;
05768 
05769     // qDebug("****************** Event URL: %s", url.string().latin1());
05770     // qDebug("****************** Event Target: %s", target.string().latin1());
05771 
05772     // Normal image...
05773     if ( url.length() == 0 && innerNode.handle() && innerNode.handle()->id() == ID_IMG )
05774     {
05775       img = static_cast<HTMLImageElementImpl *>(innerNode.handle());
05776       u = KURL( completeURL( khtml::parseURL(img->getAttribute(ATTR_SRC)).string() ) );
05777       pix = KMimeType::mimeType("image/png")->pixmap(KIcon::Desktop);
05778     }
05779     else
05780     {
05781       // Text or image link...
05782       u = completeURL( d->m_strSelectedURL );
05783       pix = KMimeType::pixmapForURL(u, 0, KIcon::Desktop, KIcon::SizeMedium);
05784     }
05785 
05786     u.setPass(QString::null);
05787 
05788     KURLDrag* urlDrag = new KURLDrag( u, img ? 0 : d->m_view->viewport() );
05789     if ( !d->m_referrer.isEmpty() )
05790       urlDrag->metaData()["referrer"] = d->m_referrer;
05791 
05792     if( img ) {
05793       KMultipleDrag *mdrag = new KMultipleDrag( d->m_view->viewport() );
05794       mdrag->addDragObject( new QImageDrag( img->currentImage(), 0L ) );
05795       mdrag->addDragObject( urlDrag );
05796       drag = mdrag;
05797     }
05798     else
05799       drag = urlDrag;
05800 
05801     if ( !pix.isNull() )
05802       drag->setPixmap( pix );
05803 
05804     stopAutoScroll();
05805     if(drag)
05806       drag->drag();
05807 
05808     // when we finish our drag, we need to undo our mouse press
05809     d->m_bMousePressed = false;
05810     d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
05811     return;
05812   }
05813 #endif
05814 
05815   // Not clicked -> mouse over stuff
05816   if ( !d->m_bMousePressed )
05817   {
05818     // The mouse is over something
05819     if ( url.length() )
05820     {
05821       bool shiftPressed = ( _mouse->state() & ShiftButton );
05822 
05823       // Image map
05824       if ( !innerNode.isNull() && innerNode.elementId() == ID_IMG )
05825       {
05826         HTMLImageElementImpl *i = static_cast<HTMLImageElementImpl *>(innerNode.handle());
05827         if ( i && i->isServerMap() )
05828         {
05829           khtml::RenderObject *r = i->renderer();
05830           if(r)
05831           {
05832             int absx, absy, vx, vy;
05833             r->absolutePosition(absx, absy);
05834             view()->contentsToViewport( absx, absy, vx, vy );
05835 
05836             int x(_mouse->x() - vx), y(_mouse->y() - vy);
05837 
05838             d->m_overURL = url.string() + QString("?%1,%2").arg(x).arg(y);
05839             d->m_overURLTarget = target.string();
05840             overURL( d->m_overURL, target.string(), shiftPressed );
05841             return;
05842           }
05843         }
05844       }
05845 
05846       // normal link
05847       if ( d->m_overURL.isEmpty() || d->m_overURL != url || d->m_overURLTarget != target )
05848       {
05849         d->m_overURL = url.string();
05850         d->m_overURLTarget = target.string();
05851         overURL( d->m_overURL, target.string(), shiftPressed );
05852       }
05853     }
05854     else  // Not over a link...
05855     {
05856       if( !d->m_overURL.isEmpty() ) // and we were over a link  -> reset to "default statusbar text"
05857       {
05858         d->m_overURL = d->m_overURLTarget = QString::null;
05859         emit onURL( QString::null );
05860         // revert to default statusbar text
05861         setStatusBarText(QString::null, BarHoverText);
05862         emit d->m_extension->mouseOverInfo(0);
05863      }
05864     }
05865   }
05866   else {
05867 #ifndef KHTML_NO_SELECTION
05868     // selection stuff
05869     if( d->m_bMousePressed && innerNode.handle() && innerNode.handle()->renderer() &&
05870         ( (_mouse->state() & LeftButton) != 0 )) {
05871       extendSelectionTo(event->x(), event->y(),
05872                         event->absX(), event->absY(), innerNode);
05873 #else
05874       if ( d->m_doc && d->m_view ) {
05875         QPoint diff( _mouse->globalPos() - d->m_dragLastPos );
05876 
05877         if ( abs( diff.x() ) > 64 || abs( diff.y() ) > 64 ) {
05878           d->m_view->scrollBy( -diff.x(), -diff.y() );
05879           d->m_dragLastPos = _mouse->globalPos();
05880         }
05881 #endif
05882     }
05883   }
05884 
05885 }
05886 
05887 void KHTMLPart::khtmlMouseReleaseEvent( khtml::MouseReleaseEvent *event )
05888 {
05889   DOM::Node innerNode = event->innerNode();
05890   d->m_mousePressNode = DOM::Node();
05891 
05892   if ( d->m_bMousePressed ) {
05893     setStatusBarText(QString::null, BarHoverText);
05894     stopAutoScroll();
05895   }
05896 
05897   // Used to prevent mouseMoveEvent from initiating a drag before
05898   // the mouse is pressed again.
05899   d->m_bMousePressed = false;
05900 
05901   QMouseEvent *_mouse = event->qmouseEvent();
05902   if ( _mouse->button() == RightButton && parentPart() != 0 && d->m_bBackRightClick )
05903   {
05904     d->m_bRightMousePressed = false;
05905     KParts::BrowserInterface *tmp_iface = d->m_extension->browserInterface();
05906     if( tmp_iface ) {
05907       tmp_iface->callMethod( "goHistory(int)", -1 );
05908     }
05909   }
05910 #ifndef QT_NO_CLIPBOARD
05911   if ((d->m_guiProfile == BrowserViewGUI) && (_mouse->button() == MidButton) && (event->url().isNull())) {
05912     kdDebug( 6050 ) << "KHTMLPart::khtmlMouseReleaseEvent() MMB shouldOpen="
05913                     << d->m_bOpenMiddleClick << endl;
05914 
05915     if (d->m_bOpenMiddleClick) {
05916     KHTMLPart *p = this;
05917     while (p->parentPart()) p = p->parentPart();
05918     p->d->m_extension->pasteRequest();
05919   }
05920   }
05921 #endif
05922 
05923 #ifndef KHTML_NO_SELECTION
05924   // delete selection in case start and end position are at the same point
05925   if(d->m_selectionStart == d->m_selectionEnd && d->m_startOffset == d->m_endOffset) {
05926 #ifndef KHTML_NO_CARET
05927     d->m_extendAtEnd = true;
05928 #else
05929     d->m_selectionStart = 0;
05930     d->m_selectionEnd = 0;
05931     d->m_startOffset = 0;
05932     d->m_endOffset = 0;
05933 #endif
05934     emitSelectionChanged();
05935   } else {
05936     // we have to get to know if end is before start or not...
05937 //     kdDebug(6000) << "rel: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << endl;
05938     DOM::Node n = d->m_selectionStart;
05939     d->m_startBeforeEnd = false;
05940     if( d->m_selectionStart == d->m_selectionEnd ) {
05941       if( d->m_startOffset < d->m_endOffset )
05942         d->m_startBeforeEnd = true;
05943     } else {
05944 #if 0
05945       while(!n.isNull()) {
05946         if(n == d->m_selectionEnd) {
05947           d->m_startBeforeEnd = true;
05948           break;
05949         }
05950         DOM::Node next = n.firstChild();
05951         if(next.isNull()) next = n.nextSibling();
05952         while( next.isNull() && !n.parentNode().isNull() ) {
05953           n = n.parentNode();
05954           next = n.nextSibling();
05955         }
05956         n = next;
05957       }
05958 #else
05959       // shouldn't be null but it can happen with dynamic updating of nodes
05960       if (d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() ||
05961           !d->m_selectionStart.handle()->renderer() ||
05962           !d->m_selectionEnd.handle()->renderer()) return;
05963       d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
05964                 d->m_selectionStart.handle(), d->m_startOffset,
05965             d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
05966 #endif
05967     }
05968     if(!d->m_startBeforeEnd)
05969     {
05970       DOM::Node tmpNode = d->m_selectionStart;
05971       int tmpOffset = d->m_startOffset;
05972       d->m_selectionStart = d->m_selectionEnd;
05973       d->m_startOffset = d->m_endOffset;
05974       d->m_selectionEnd = tmpNode;
05975       d->m_endOffset = tmpOffset;
05976       d->m_startBeforeEnd = true;
05977       d->m_extendAtEnd = !d->m_extendAtEnd;
05978     }
05979 #ifndef KHTML_NO_CARET
05980     bool v = d->m_view->placeCaret();
05981     emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
05982 #endif
05983     // get selected text and paste to the clipboard
05984 #ifndef QT_NO_CLIPBOARD
05985     QString text = selectedText();
05986     text.replace(QChar(0xa0), ' ');
05987     disconnect( kapp->clipboard(), SIGNAL( selectionChanged()), this, SLOT( slotClearSelection()));
05988     kapp->clipboard()->setText(text,QClipboard::Selection);
05989     connect( kapp->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection()));
05990 #endif
05991     //kdDebug( 6000 ) << "selectedText = " << text << endl;
05992     emitSelectionChanged();
05993 //kdDebug(6000) << "rel2: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << "), caretOfs " << d->caretOffset() << endl;
05994   }
05995 #endif
05996   d->m_initialNode = 0;     // don't hold nodes longer than necessary
05997   d->m_initialOffset = 0;
05998 
05999 }
06000 
06001 void KHTMLPart::khtmlDrawContentsEvent( khtml::DrawContentsEvent * )
06002 {
06003 }
06004 
06005 void KHTMLPart::guiActivateEvent( KParts::GUIActivateEvent *event )
06006 {
06007   if ( event->activated() )
06008   {
06009     emitSelectionChanged();
06010     emit d->m_extension->enableAction( "print", d->m_doc != 0 );
06011 
06012     if ( !d->m_settings->autoLoadImages() && d->m_paLoadImages )
06013     {
06014         QPtrList<KAction> lst;
06015         lst.append( d->m_paLoadImages );
06016         plugActionList( "loadImages", lst );
06017     }
06018   }
06019 }
06020 
06021 void KHTMLPart::slotPrintFrame()
06022 {
06023   if ( d->m_frames.count() == 0 )
06024     return;
06025 
06026   KParts::ReadOnlyPart *frame = currentFrame();
06027   if (!frame)
06028     return;
06029 
06030   KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject( frame );
06031 
06032   if ( !ext )
06033     return;
06034 
06035   QMetaObject *mo = ext->metaObject();
06036 
06037   int idx = mo->findSlot( "print()", true );
06038   if ( idx >= 0 ) {
06039     QUObject o[ 1 ];
06040     ext->qt_invoke( idx, o );
06041   }
06042 }
06043 
06044 void KHTMLPart::slotSelectAll()
06045 {
06046   KParts::ReadOnlyPart *part = currentFrame();
06047   if (part && part->inherits("KHTMLPart"))
06048     static_cast<KHTMLPart *>(part)->selectAll();
06049 }
06050 
06051 void KHTMLPart::startAutoScroll()
06052 {
06053    connect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
06054    d->m_scrollTimer.start(100, false);
06055 }
06056 
06057 void KHTMLPart::stopAutoScroll()
06058 {
06059    disconnect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
06060    if (d->m_scrollTimer.isActive())
06061        d->m_scrollTimer.stop();
06062 }
06063 
06064 
06065 void KHTMLPart::slotAutoScroll()
06066 {
06067     if (d->m_view)
06068       d->m_view->doAutoScroll();
06069     else
06070       stopAutoScroll(); // Safety
06071 }
06072 
06073 void KHTMLPart::selectAll()
06074 {
06075   if (!d->m_doc) return;
06076 
06077   NodeImpl *first;
06078   if (d->m_doc->isHTMLDocument())
06079     first = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
06080   else
06081     first = d->m_doc;
06082   NodeImpl *next;
06083 
06084   // Look for first text/cdata node that has a renderer,
06085   // or first childless replaced element
06086   while ( first && !(first->renderer()
06087     && ((first->nodeType() == Node::TEXT_NODE || first->nodeType() == Node::CDATA_SECTION_NODE)
06088         || (first->renderer()->isReplaced() && !first->renderer()->firstChild()))))
06089   {
06090     next = first->firstChild();
06091     if ( !next ) next = first->nextSibling();
06092     while( first && !next )
06093     {
06094       first = first->parentNode();
06095       if ( first )
06096         next = first->nextSibling();
06097     }
06098     first = next;
06099   }
06100 
06101   NodeImpl *last;
06102   if (d->m_doc->isHTMLDocument())
06103     last = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
06104   else
06105     last = d->m_doc;
06106   // Look for last text/cdata node that has a renderer,
06107   // or last childless replaced element
06108   // ### Instead of changing this loop, use findLastSelectableNode
06109   // in render_table.cpp (LS)
06110   while ( last && !(last->renderer()
06111     && ((last->nodeType() == Node::TEXT_NODE || last->nodeType() == Node::CDATA_SECTION_NODE)
06112         || (last->renderer()->isReplaced() && !last->renderer()->lastChild()))))
06113   {
06114     next = last->lastChild();
06115     if ( !next ) next = last->previousSibling();
06116     while ( last && !next )
06117     {
06118       last = last->parentNode();
06119       if ( last )
06120         next = last->previousSibling();
06121     }
06122     last = next;
06123   }
06124 
06125   if ( !first || !last )
06126     return;
06127   Q_ASSERT(first->renderer());
06128   Q_ASSERT(last->renderer());
06129   d->m_selectionStart = first;
06130   d->m_startOffset = 0;
06131   d->m_selectionEnd = last;
06132   d->m_endOffset = last->nodeValue().length();
06133   d->m_startBeforeEnd = true;
06134 
06135   d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
06136                           d->m_selectionEnd.handle(), d->m_endOffset );
06137 
06138   emitSelectionChanged();
06139 }
06140 
06141 bool KHTMLPart::checkLinkSecurity(const KURL &linkURL,const QString &message, const QString &button)
06142 {
06143   bool linkAllowed = true;
06144 
06145   if ( d->m_doc )
06146     linkAllowed = kapp && kapp->authorizeURLAction("redirect", url(), linkURL);
06147 
06148   if ( !linkAllowed ) {
06149     khtml::Tokenizer *tokenizer = d->m_doc->tokenizer();
06150     if (tokenizer)
06151       tokenizer->setOnHold(true);
06152 
06153     int response = KMessageBox::Cancel;
06154     if (!message.isEmpty())
06155     {
06156         response = KMessageBox::warningContinueCancel( 0,
06157                                message.arg(linkURL.htmlURL()),
06158                                i18n( "Security Warning" ),
06159                                button);
06160     }
06161     else
06162     {
06163         KMessageBox::error( 0,
06164                 i18n( "<qt>Access by untrusted page to<BR><B>%1</B><BR> denied.").arg(linkURL.htmlURL()),
06165                 i18n( "Security Alert" ));
06166     }
06167 
06168     if (tokenizer)
06169        tokenizer->setOnHold(false);
06170     return (response==KMessageBox::Continue);
06171   }
06172   return true;
06173 }
06174 
06175 void KHTMLPart::slotPartRemoved( KParts::Part *part )
06176 {
06177 //    kdDebug(6050) << "KHTMLPart::slotPartRemoved " << part << endl;
06178     if ( part == d->m_activeFrame )
06179     {
06180         d->m_activeFrame = 0L;
06181         if ( !part->inherits( "KHTMLPart" ) )
06182         {
06183             if (factory()) {
06184                 factory()->removeClient( part );
06185             }
06186             if (childClients()->containsRef(part)) {
06187                 removeChildClient( part );
06188             }
06189         }
06190     }
06191 }
06192 
06193 void KHTMLPart::slotActiveFrameChanged( KParts::Part *part )
06194 {
06195 //    kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged part=" << part << endl;
06196     if ( part == this )
06197     {
06198         kdError(6050) << "strange error! we activated ourselves" << endl;
06199         assert( false );
06200         return;
06201     }
06202 //    kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged d->m_activeFrame=" << d->m_activeFrame << endl;
06203     if ( d->m_activeFrame && d->m_activeFrame->widget() && d->m_activeFrame->widget()->inherits( "QFrame" ) )
06204     {
06205         QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() );
06206         if (frame->frameStyle() != QFrame::NoFrame)
06207         {
06208            frame->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken);
06209            frame->repaint();
06210         }
06211     }
06212 
06213     if( d->m_activeFrame && !d->m_activeFrame->inherits( "KHTMLPart" ) )
06214     {
06215         if (factory()) {
06216             factory()->removeClient( d->m_activeFrame );
06217         }
06218         removeChildClient( d->m_activeFrame );
06219     }
06220     if( part && !part->inherits( "KHTMLPart" ) )
06221     {
06222         if (factory()) {
06223             factory()->addClient( part );
06224         }
06225         insertChildClient( part );
06226     }
06227 
06228 
06229     d->m_activeFrame = part;
06230 
06231     if ( d->m_activeFrame && d->m_activeFrame->widget()->inherits( "QFrame" ) )
06232     {
06233         QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() );
06234         if (frame->frameStyle() != QFrame::NoFrame)
06235         {
06236            frame->setFrameStyle( QFrame::StyledPanel | QFrame::Plain);
06237            frame->repaint();
06238         }
06239         kdDebug(6050) << "new active frame " << d->m_activeFrame << endl;
06240     }
06241 
06242     updateActions();
06243 
06244     // (note: childObject returns 0 if the argument is 0)
06245     d->m_extension->setExtensionProxy( KParts::BrowserExtension::childObject( d->m_activeFrame ) );
06246 }
06247 
06248 void KHTMLPart::setActiveNode(const DOM::Node &node)
06249 {
06250     if (!d->m_doc || !d->m_view)
06251         return;
06252 
06253     // Set the document's active node
06254     d->m_doc->setFocusNode(node.handle());
06255 
06256     // Scroll the view if necessary to ensure that the new focus node is visible
06257     QRect rect  = node.handle()->getRect();
06258     d->m_view->ensureVisible(rect.right(), rect.bottom());
06259     d->m_view->ensureVisible(rect.left(), rect.top());
06260 }
06261 
06262 DOM::Node KHTMLPart::activeNode() const
06263 {
06264     return DOM::Node(d->m_doc?d->m_doc->focusNode():0);
06265 }
06266 
06267 DOM::EventListener *KHTMLPart::createHTMLEventListener( QString code, QString name )
06268 {
06269   KJSProxy *proxy = jScript();
06270 
06271   if (!proxy)
06272     return 0;
06273 
06274   return proxy->createHTMLEventHandler( m_url.url(), name, code );
06275 }
06276 
06277 KHTMLPart *KHTMLPart::opener()
06278 {
06279     return d->m_opener;
06280 }
06281 
06282 void KHTMLPart::setOpener(KHTMLPart *_opener)
06283 {
06284     d->m_opener = _opener;
06285 }
06286 
06287 bool KHTMLPart::openedByJS()
06288 {
06289     return d->m_openedByJS;
06290 }
06291 
06292 void KHTMLPart::setOpenedByJS(bool _openedByJS)
06293 {
06294     d->m_openedByJS = _openedByJS;
06295 }
06296 
06297 void KHTMLPart::preloadStyleSheet(const QString &url, const QString &stylesheet)
06298 {
06299     khtml::Cache::preloadStyleSheet(url, stylesheet);
06300 }
06301 
06302 void KHTMLPart::preloadScript(const QString &url, const QString &script)
06303 {
06304     khtml::Cache::preloadScript(url, script);
06305 }
06306 
06307 QCString KHTMLPart::dcopObjectId() const
06308 {
06309   QCString id;
06310   id.sprintf("html-widget%d", d->m_dcop_counter);
06311   return id;
06312 }
06313 
06314 long KHTMLPart::cacheId() const
06315 {
06316   return d->m_cacheId;
06317 }
06318 
06319 bool KHTMLPart::restored() const
06320 {
06321   return d->m_restored;
06322 }
06323 
06324 bool KHTMLPart::pluginPageQuestionAsked(const QString& mimetype) const
06325 {
06326   // parentPart() should be const!
06327   KHTMLPart* parent = const_cast<KHTMLPart *>(this)->parentPart();
06328   if ( parent )
06329     return parent->pluginPageQuestionAsked(mimetype);
06330 
06331   return d->m_pluginPageQuestionAsked.contains(mimetype);
06332 }
06333 
06334 void KHTMLPart::setPluginPageQuestionAsked(const QString& mimetype)
06335 {
06336   if ( parentPart() )
06337     parentPart()->setPluginPageQuestionAsked(mimetype);
06338 
06339   d->m_pluginPageQuestionAsked.append(mimetype);
06340 }
06341 
06342 void KHTMLPart::slotAutomaticDetectionLanguage( int _id )
06343 {
06344   d->m_automaticDetection->setItemChecked( _id, true );
06345 
06346   switch ( _id ) {
06347     case 0 :
06348       d->m_autoDetectLanguage = khtml::Decoder::SemiautomaticDetection;
06349       break;
06350     case 1 :
06351       d->m_autoDetectLanguage = khtml::Decoder::Arabic;
06352       break;
06353     case 2 :
06354       d->m_autoDetectLanguage = khtml::Decoder::Baltic;
06355       break;
06356     case 3 :
06357       d->m_autoDetectLanguage = khtml::Decoder::CentralEuropean;
06358       break;
06359     case 4 :
06360       d->m_autoDetectLanguage = khtml::Decoder::Chinese;
06361       break;
06362     case 5 :
06363       d->m_autoDetectLanguage = khtml::Decoder::Greek;
06364       break;
06365     case 6 :
06366       d->m_autoDetectLanguage = khtml::Decoder::Hebrew;
06367       break;
06368     case 7 :
06369       d->m_autoDetectLanguage = khtml::Decoder::Japanese;
06370       break;
06371     case 8 :
06372       d->m_autoDetectLanguage = khtml::Decoder::Korean;
06373       break;
06374     case 9 :
06375       d->m_autoDetectLanguage = khtml::Decoder::Russian;
06376       break;
06377     case 10 :
06378       d->m_autoDetectLanguage = khtml::Decoder::Thai;
06379       break;
06380     case 11 :
06381       d->m_autoDetectLanguage = khtml::Decoder::Turkish;
06382       break;
06383     case 12 :
06384       d->m_autoDetectLanguage = khtml::Decoder::Ukrainian;
06385       break;
06386     case 13 :
06387       d->m_autoDetectLanguage = khtml::Decoder::Unicode;
06388       break;
06389     case 14 :
06390       d->m_autoDetectLanguage = khtml::Decoder::WesternEuropean;
06391       break;
06392     default :
06393       d->m_autoDetectLanguage = khtml::Decoder::SemiautomaticDetection;
06394       break;
06395   }
06396 
06397   for ( int i = 0; i <= 14; ++i ) {
06398     if ( i != _id )
06399       d->m_automaticDetection->setItemChecked( i, false );
06400   }
06401 
06402   d->m_paSetEncoding->popupMenu()->setItemChecked( 0, true );
06403 
06404   setEncoding( QString::null, false );
06405 
06406   if( d->m_manualDetection )
06407     d->m_manualDetection->setCurrentItem( -1 );
06408   d->m_paSetEncoding->popupMenu()->setItemChecked( d->m_paSetEncoding->popupMenu()->idAt( 2 ), false );
06409 }
06410 
06411 khtml::Decoder *KHTMLPart::createDecoder()
06412 {
06413   khtml::Decoder *dec = new khtml::Decoder();
06414   if( !d->m_encoding.isNull() )
06415     dec->setEncoding( d->m_encoding.latin1(), true );
06416   else
06417     dec->setEncoding( defaultEncoding().latin1(), d->m_haveEncoding );
06418 
06419   dec->setAutoDetectLanguage( d->m_autoDetectLanguage );
06420   return dec;
06421 }
06422 
06423 void KHTMLPart::emitCaretPositionChanged(const DOM::Node &node, long offset) {
06424   emit caretPositionChanged(node, offset);
06425 }
06426 
06427 void KHTMLPart::restoreScrollPosition()
06428 {
06429   KParts::URLArgs args = d->m_extension->urlArgs();
06430   if (!args.reload) {
06431     disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
06432     return; // should not happen
06433   }
06434 
06435   // Check whether the viewport has become large enough to encompass the stored
06436   // offsets. If the document has been fully loaded, force the new coordinates,
06437   // even if the canvas is too short (can happen when user resizes the window
06438   // during loading).
06439   if (d->m_view->contentsHeight() - d->m_view->visibleHeight() >= args.yOffset
06440       || d->m_bComplete) {
06441     d->m_view->setContentsPos(args.xOffset, args.yOffset);
06442     disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
06443   }
06444 }
06445 
06446 KWallet::Wallet* KHTMLPart::wallet()
06447 {
06448   // ### close wallet after a certain timeout period automatically
06449   //      No - KWallet already does this based on user preferences. (GS)
06450   // ### close wallet after screensaver was enabled
06451   //      No - KWalletD should do this, if anything. (GS)
06452 
06453   KHTMLPart* p;
06454 
06455   for (p = parentPart(); p && p->parentPart(); p = p->parentPart())
06456     ;
06457 
06458   if (p)
06459     return p->wallet();
06460 
06461   if (!d->m_wallet && !d->m_bWalletOpened) {
06462     d->m_wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0);
06463     d->m_bWalletOpened = true;
06464     if (d->m_wallet) {
06465       connect(d->m_wallet, SIGNAL(walletClosed()), SLOT(slotWalletClosed()));
06466       d->m_statusBarWalletLabel = new KURLLabel(d->m_statusBarExtension->statusBar());
06467       d->m_statusBarWalletLabel->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small));
06468       d->m_statusBarWalletLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
06469       d->m_statusBarWalletLabel->setUseCursor(false);
06470       d->m_statusBarExtension->addStatusBarItem(d->m_statusBarWalletLabel, 0, false);
06471       QToolTip::add(d->m_statusBarWalletLabel, i18n("The wallet '%1' is open and being used for form data and passwords.").arg(KWallet::Wallet::NetworkWallet()));
06472       d->m_statusBarWalletLabel->setPixmap(SmallIcon("wallet_open", instance()));
06473       connect(d->m_statusBarWalletLabel, SIGNAL(leftClickedURL()), SLOT(launchWalletManager()));
06474       connect(d->m_statusBarWalletLabel, SIGNAL(rightClickedURL()), SLOT(walletMenu()));
06475     } else if (d->m_statusBarWalletLabel) {
06476       d->m_statusBarExtension->removeStatusBarItem(d->m_statusBarWalletLabel);
06477       delete d->m_statusBarWalletLabel;
06478       d->m_statusBarWalletLabel = 0L;
06479     }
06480   }
06481   return d->m_wallet;
06482 }
06483 
06484 void KHTMLPart::slotWalletClosed()
06485 {
06486   if (d->m_wallet) {
06487     d->m_wallet->deleteLater();
06488     d->m_wallet = 0L;
06489   }
06490   d->m_bWalletOpened = false;
06491   if (d->m_statusBarWalletLabel) {
06492     d->m_statusBarExtension->removeStatusBarItem(d->m_statusBarWalletLabel);
06493     delete d->m_statusBarWalletLabel;
06494     d->m_statusBarWalletLabel = 0L;
06495   }
06496 }
06497 
06498 void KHTMLPart::launchWalletManager()
06499 {
06500   if (!DCOPClient::mainClient()->isApplicationRegistered("kwalletmanager")) {
06501     KApplication::startServiceByDesktopName("kwalletmanager_show");
06502   } else {
06503     DCOPRef r("kwalletmanager", "kwalletmanager-mainwindow#1");
06504     r.send("show");
06505     r.send("raise");
06506   }
06507 }
06508 
06509 void KHTMLPart::walletMenu()
06510 {
06511   KPopupMenu *m = new KPopupMenu(0L);
06512   m->insertItem(i18n("&Close Wallet"), this, SLOT(slotWalletClosed()));
06513   m->popup(QCursor::pos());
06514 }
06515 
06516 void KHTMLPart::slotToggleCaretMode()
06517 {
06518   setCaretMode(d->m_paToggleCaretMode->isChecked());
06519 }
06520 
06521 void KHTMLPart::setFormNotification(KHTMLPart::FormNotification fn) {
06522   d->m_formNotification = fn;
06523 }
06524 
06525 KHTMLPart::FormNotification KHTMLPart::formNotification() const {
06526   return d->m_formNotification;
06527 }
06528 
06529 KURL KHTMLPart::toplevelURL()
06530 {
06531   KHTMLPart* part = this;
06532   while (part->parentPart())
06533     part = part->parentPart();
06534 
06535   if (!part)
06536     return KURL();
06537 
06538   return part->url();
06539 }
06540 
06541 bool KHTMLPart::isModified() const
06542 {
06543   if ( !d->m_doc )
06544     return false;
06545 
06546   return d->m_doc->unsubmittedFormChanges();
06547 }
06548 
06549 void KHTMLPart::setDebugScript( bool enable )
06550 {
06551   unplugActionList( "debugScriptList" );
06552   if ( enable ) {
06553     if (!d->m_paDebugScript) {
06554       d->m_paDebugScript = new KAction( i18n( "JavaScript &Debugger" ), 0, this, SLOT( slotDebugScript() ), actionCollection(), "debugScript" );
06555     }
06556     d->m_paDebugScript->setEnabled( d->m_jscript );
06557     QPtrList<KAction> lst;
06558     lst.append( d->m_paDebugScript );
06559     plugActionList( "debugScriptList", lst );
06560   }
06561   d->m_bJScriptDebugEnabled = enable;
06562 }
06563 
06564 using namespace KParts;
06565 #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 Fri Feb 18 15:11:43 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003