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