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