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 = new KAction( i18n( "&Save As..." ), CTRL+Key_S, 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 
00738 KParts::BrowserExtension *KHTMLPart::browserExtension() const
00739 {
00740   return d->m_extension;
00741 }
00742 
00743 KHTMLView *KHTMLPart::view() const
00744 {
00745   return d->m_view;
00746 }
00747 
00748 void KHTMLPart::setStatusMessagesEnabled( bool enable )
00749 {
00750   d->m_statusMessagesEnabled = enable;
00751 }
00752 
00753 KJS::Interpreter *KHTMLPart::jScriptInterpreter()
00754 {
00755   KJSProxy *proxy = jScript();
00756   if (!proxy || proxy->paused())
00757     return 0;
00758 
00759   return proxy->interpreter();
00760 }
00761 
00762 bool KHTMLPart::statusMessagesEnabled() const
00763 {
00764   return d->m_statusMessagesEnabled;
00765 }
00766 
00767 void KHTMLPart::setJScriptEnabled( bool enable )
00768 {
00769   if ( !enable && jScriptEnabled() && d->m_jscript ) {
00770     d->m_jscript->clear();
00771   }
00772   d->m_bJScriptForce = enable;
00773   d->m_bJScriptOverride = true;
00774 }
00775 
00776 bool KHTMLPart::jScriptEnabled() const
00777 {
00778   if ( d->m_bJScriptOverride )
00779       return d->m_bJScriptForce;
00780   return d->m_bJScriptEnabled;
00781 }
00782 
00783 void KHTMLPart::setMetaRefreshEnabled( bool enable )
00784 {
00785   d->m_metaRefreshEnabled = enable;
00786 }
00787 
00788 bool KHTMLPart::metaRefreshEnabled() const
00789 {
00790   return d->m_metaRefreshEnabled;
00791 }
00792 
00793 // Define this to disable dlopening kjs_html, when directly linking to it.
00794 // You need to edit khtml/Makefile.am to add ./ecma/libkjs_html.la to LIBADD
00795 // and to edit khtml/ecma/Makefile.am to s/kjs_html/libkjs_html/, remove libkhtml from LIBADD,
00796 //        remove LDFLAGS line, and replace kde_module with either lib (shared) or noinst (static)
00797 //        Also, change the order of "ecma" and "." in khtml's SUBDIRS line.
00798 // OK - that's the default now, use the opposite of the above instructions to go back
00799 // to "dlopening it" - but it breaks exception catching in kjs_binding.cpp
00800 #define DIRECT_LINKAGE_TO_ECMA
00801 
00802 #ifdef DIRECT_LINKAGE_TO_ECMA
00803 extern "C" { KJSProxy *kjs_html_init(KHTMLPart *khtmlpart); }
00804 #endif
00805 
00806 KJSProxy *KHTMLPart::jScript()
00807 {
00808   if (!jScriptEnabled()) return 0;
00809 
00810   if ( !d->m_jscript )
00811   {
00812 #ifndef DIRECT_LINKAGE_TO_ECMA
00813     KLibrary *lib = KLibLoader::self()->library("kjs_html");
00814     if ( !lib ) {
00815       setJScriptEnabled( false );
00816       return 0;
00817     }
00818     // look for plain C init function
00819     void *sym = lib->symbol("kjs_html_init");
00820     if ( !sym ) {
00821       lib->unload();
00822       setJScriptEnabled( false );
00823       return 0;
00824     }
00825     typedef KJSProxy* (*initFunction)(KHTMLPart *);
00826     initFunction initSym = (initFunction) sym;
00827     d->m_jscript = (*initSym)(this);
00828     d->m_kjs_lib = lib;
00829 #else
00830     d->m_jscript = kjs_html_init(this);
00831     // d->m_kjs_lib remains 0L.
00832 #endif
00833     if (d->m_bJScriptDebugEnabled)
00834         d->m_jscript->setDebugEnabled(true);
00835   }
00836 
00837   return d->m_jscript;
00838 }
00839 
00840 QVariant KHTMLPart::crossFrameExecuteScript(const QString& target,  const QString& script)
00841 {
00842   KHTMLPart* destpart = this;
00843 
00844   QString trg = target.lower();
00845 
00846   if (target == "_top") {
00847     while (destpart->parentPart())
00848       destpart = destpart->parentPart();
00849   }
00850   else if (target == "_parent") {
00851     if (parentPart())
00852       destpart = parentPart();
00853   }
00854   else if (target == "_self" || target == "_blank")  {
00855     // we always allow these
00856   }
00857   else {
00858     while (destpart->parentPart())
00859       destpart = destpart->parentPart();
00860     destpart = destpart->findFrame(target);
00861 
00862     if (!destpart)
00863       destpart = this; // ### doesn't make sense, does it?
00864   }
00865 
00866   // easy way out?
00867   if (destpart == this)
00868     return executeScript(DOM::Node(), script);
00869 
00870 
00871   // now compare the domains
00872   if (!destpart->htmlDocument().isNull() &&
00873       !htmlDocument().isNull())  {
00874     DOM::DOMString actDomain = htmlDocument().domain();
00875     DOM::DOMString destDomain = destpart->htmlDocument().domain();
00876 
00877     if (actDomain == destDomain)
00878       return destpart->executeScript(DOM::Node(), script);
00879   }
00880 
00881 
00882   // eww, something went wrong. better execute it in our frame
00883   return executeScript(DOM::Node(), script);
00884 }
00885 
00886 //Enable this to see all JS scripts being executed
00887 //#define KJS_VERBOSE
00888 
00889 KJSErrorDlg *KHTMLPart::jsErrorExtension() {
00890   if (!d->m_settings->jsErrorsEnabled()) {
00891     return 0L;
00892   }
00893 
00894   if (parentPart()) {
00895     return parentPart()->jsErrorExtension();
00896   }
00897 
00898   if (!d->m_statusBarJSErrorLabel) {
00899     d->m_statusBarJSErrorLabel = new KURLLabel(d->m_statusBarExtension->statusBar());
00900     d->m_statusBarJSErrorLabel->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small));
00901     d->m_statusBarJSErrorLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
00902     d->m_statusBarJSErrorLabel->setUseCursor(false);
00903     d->m_statusBarExtension->addStatusBarItem(d->m_statusBarJSErrorLabel, 0, false);
00904     QToolTip::add(d->m_statusBarJSErrorLabel, i18n("This web page contains coding errors."));
00905     d->m_statusBarJSErrorLabel->setPixmap(SmallIcon("bug", instance()));
00906     connect(d->m_statusBarJSErrorLabel, SIGNAL(leftClickedURL()), SLOT(launchJSErrorDialog()));
00907     connect(d->m_statusBarJSErrorLabel, SIGNAL(rightClickedURL()), SLOT(jsErrorDialogContextMenu()));
00908   }
00909   if (!d->m_jsedlg) {
00910     d->m_jsedlg = new KJSErrorDlg;
00911     d->m_jsedlg->setURL(m_url.prettyURL());
00912   }
00913   return d->m_jsedlg;
00914 }
00915 
00916 void KHTMLPart::removeJSErrorExtension() {
00917   if (parentPart()) {
00918     parentPart()->removeJSErrorExtension();
00919     return;
00920   }
00921   if (d->m_statusBarJSErrorLabel != 0) {
00922     d->m_statusBarExtension->removeStatusBarItem( d->m_statusBarJSErrorLabel );
00923     delete d->m_statusBarJSErrorLabel;
00924     d->m_statusBarJSErrorLabel = 0;
00925   }
00926   delete d->m_jsedlg;
00927   d->m_jsedlg = 0;
00928 }
00929 
00930 void KHTMLPart::disableJSErrorExtension() {
00931   removeJSErrorExtension();
00932   // These two lines are really kind of hacky, and it sucks to do this inside
00933   // KHTML but I don't know of anything that's reasonably easy as an alternative
00934   // right now.  It makes me wonder if there should be a more clean way to
00935   // contact all running "KHTML" instance as opposed to Konqueror instances too.
00936   d->m_settings->setJSErrorsEnabled(false);
00937   DCOPClient::mainClient()->send("konqueror*", "KonquerorIface", "reparseConfiguration()", QByteArray());
00938 }
00939 
00940 void KHTMLPart::jsErrorDialogContextMenu() {
00941   KPopupMenu *m = new KPopupMenu(0L);
00942   m->insertItem(i18n("&Hide Errors"), this, SLOT(removeJSErrorExtension()));
00943   m->insertItem(i18n("&Disable Error Reporting"), this, SLOT(disableJSErrorExtension()));
00944   m->popup(QCursor::pos());
00945 }
00946 
00947 void KHTMLPart::launchJSErrorDialog() {
00948   KJSErrorDlg *dlg = jsErrorExtension();
00949   if (dlg) {
00950     dlg->show();
00951     dlg->raise();
00952   }
00953 }
00954 
00955 QVariant KHTMLPart::executeScript(const QString& filename, int baseLine, const DOM::Node& n, const QString& script)
00956 {
00957 #ifdef KJS_VERBOSE
00958   kdDebug(6070) << "executeScript: caller='" << name() << "' filename=" << filename << " baseLine=" << baseLine << " script=" << script << endl;
00959 #endif
00960   KJSProxy *proxy = jScript();
00961 
00962   if (!proxy || proxy->paused())
00963     return QVariant();
00964 
00965   KJS::Completion comp;
00966 
00967   QVariant ret = proxy->evaluate(filename, baseLine, script, n, &comp);
00968 
00969   /*
00970    *  Error handling
00971    */
00972   if (comp.complType() == KJS::Throw && !comp.value().isNull()) {
00973     KJSErrorDlg *dlg = jsErrorExtension();
00974     if (dlg) {
00975       KJS::UString msg = comp.value().toString(proxy->interpreter()->globalExec());
00976       dlg->addError(i18n("<b>Error</b>: %1: %2").arg(filename, msg.qstring()));
00977     }
00978   }
00979 
00980   return ret;
00981 }
00982 
00983 QVariant KHTMLPart::executeScript( const QString &script )
00984 {
00985     return executeScript( DOM::Node(), script );
00986 }
00987 
00988 QVariant KHTMLPart::executeScript( const DOM::Node &n, const QString &script )
00989 {
00990 #ifdef KJS_VERBOSE
00991   kdDebug(6070) << "KHTMLPart::executeScript caller='" << name() << "' node=" << n.nodeName().string().latin1() << "(" << (n.isNull() ? 0 : n.nodeType()) << ") " << script << endl;
00992 #endif
00993   KJSProxy *proxy = jScript();
00994 
00995   if (!proxy || proxy->paused())
00996     return QVariant();
00997   d->m_runningScripts++;
00998   KJS::Completion comp;
00999   QVariant ret = proxy->evaluate( QString::null, 1, script, n, &comp );
01000   d->m_runningScripts--;
01001 
01002   /*
01003    *  Error handling
01004    */
01005   if (comp.complType() == KJS::Throw && !comp.value().isNull()) {
01006     KJSErrorDlg *dlg = jsErrorExtension();
01007     if (dlg) {
01008       KJS::UString msg = comp.value().toString(proxy->interpreter()->globalExec());
01009       dlg->addError(i18n("<b>Error</b>: node %1: %2").arg(n.nodeName().string()).arg(msg.qstring()));
01010     }
01011   }
01012 
01013   if (!d->m_runningScripts && d->m_doc && !d->m_doc->parsing() && d->m_submitForm )
01014       submitFormAgain();
01015 
01016 #ifdef KJS_VERBOSE
01017   kdDebug(6070) << "KHTMLPart::executeScript - done" << endl;
01018 #endif
01019   return ret;
01020 }
01021 
01022 bool KHTMLPart::scheduleScript(const DOM::Node &n, const QString& script)
01023 {
01024     //kdDebug(6050) << "KHTMLPart::scheduleScript "<< script << endl;
01025 
01026     d->scheduledScript = script;
01027     d->scheduledScriptNode = n;
01028 
01029     return true;
01030 }
01031 
01032 QVariant KHTMLPart::executeScheduledScript()
01033 {
01034   if( d->scheduledScript.isEmpty() )
01035     return QVariant();
01036 
01037   //kdDebug(6050) << "executing delayed " << d->scheduledScript << endl;
01038 
01039   QVariant ret = executeScript( d->scheduledScriptNode, d->scheduledScript );
01040   d->scheduledScript = QString();
01041   d->scheduledScriptNode = DOM::Node();
01042 
01043   return ret;
01044 }
01045 
01046 void KHTMLPart::setJavaEnabled( bool enable )
01047 {
01048   d->m_bJavaForce = enable;
01049   d->m_bJavaOverride = true;
01050 }
01051 
01052 bool KHTMLPart::javaEnabled() const
01053 {
01054 #ifndef Q_WS_QWS
01055   if( d->m_bJavaOverride )
01056       return d->m_bJavaForce;
01057   return d->m_bJavaEnabled;
01058 #else
01059   return false;
01060 #endif
01061 }
01062 
01063 KJavaAppletContext *KHTMLPart::javaContext()
01064 {
01065   return 0;
01066 }
01067 
01068 KJavaAppletContext *KHTMLPart::createJavaContext()
01069 {
01070   return 0;
01071 }
01072 
01073 void KHTMLPart::setPluginsEnabled( bool enable )
01074 {
01075   d->m_bPluginsForce = enable;
01076   d->m_bPluginsOverride = true;
01077 }
01078 
01079 bool KHTMLPart::pluginsEnabled() const
01080 {
01081   if ( d->m_bPluginsOverride )
01082       return d->m_bPluginsForce;
01083   return d->m_bPluginsEnabled;
01084 }
01085 
01086 void KHTMLPart::slotDebugDOMTree()
01087 {
01088   if ( d->m_doc && d->m_doc->firstChild() )
01089     qDebug("%s", d->m_doc->firstChild()->toHTML().latin1());
01090 }
01091 
01092 void KHTMLPart::slotDebugScript()
01093 {
01094   if (jScript())
01095     jScript()->showDebugWindow();
01096 }
01097 
01098 void KHTMLPart::slotDebugRenderTree()
01099 {
01100 #ifndef NDEBUG
01101   if ( d->m_doc ) {
01102     d->m_doc->renderer()->printTree();
01103     // dump out the contents of the rendering & DOM trees
01104 //    QString dumps;
01105 //    QTextStream outputStream(dumps,IO_WriteOnly);
01106 //    d->m_doc->renderer()->layer()->dump( outputStream );
01107 //    kdDebug() << "dump output:" << "\n" + dumps;
01108   }
01109 #endif
01110 }
01111 
01112 void KHTMLPart::slotStopAnimations()
01113 {
01114   stopAnimations();
01115 }
01116 
01117 void KHTMLPart::setAutoloadImages( bool enable )
01118 {
01119   if ( d->m_doc && d->m_doc->docLoader()->autoloadImages() == enable )
01120     return;
01121 
01122   if ( d->m_doc )
01123     d->m_doc->docLoader()->setAutoloadImages( enable );
01124 
01125   unplugActionList( "loadImages" );
01126 
01127   if ( enable ) {
01128     delete d->m_paLoadImages;
01129     d->m_paLoadImages = 0;
01130   }
01131   else if ( !d->m_paLoadImages )
01132     d->m_paLoadImages = new KAction( i18n( "Display Images on Page" ), "images_display", 0, this, SLOT( slotLoadImages() ), actionCollection(), "loadImages" );
01133 
01134   if ( d->m_paLoadImages ) {
01135     QPtrList<KAction> lst;
01136     lst.append( d->m_paLoadImages );
01137     plugActionList( "loadImages", lst );
01138   }
01139 }
01140 
01141 bool KHTMLPart::autoloadImages() const
01142 {
01143   if ( d->m_doc )
01144     return d->m_doc->docLoader()->autoloadImages();
01145 
01146   return true;
01147 }
01148 
01149 void KHTMLPart::clear()
01150 {
01151   if ( d->m_bCleared )
01152     return;
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 == 0 )
01698     return;
01699 
01700   if ( len == -1 )
01701     len = strlen( str );
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     long 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 = (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 ( button == LeftButton && ( state & ShiftButton ) )
03285   {
03286     KIO::MetaData metaData;
03287     metaData["referrer"] = d->m_referrer;
03288     KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), cURL, metaData );
03289     return;
03290   }
03291 
03292   if (!checkLinkSecurity(cURL,
03293              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?" ),
03294              i18n( "Follow" )))
03295     return;
03296 
03297   args.frameName = target;
03298 
03299   args.metaData().insert("main_frame_request",
03300                          parentPart() == 0 ? "TRUE":"FALSE");
03301   args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
03302   args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
03303   args.metaData().insert("PropagateHttpHeader", "true");
03304   args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
03305   args.metaData().insert("ssl_activate_warnings", "TRUE");
03306   // WABA: When we select the link explicitly we should treat this new URL as the
03307   // toplevel url and it should never be considered cross-domain.
03308   // However this function is also called for javascript and META-tag based
03309   // redirections:
03310   //   - In such case, we don't take cross-domain-ness in consideration if we are the
03311   //   toplevel frame because the new URL may be in a different domain as the current URL
03312   //   but that's ok.
03313   //   - If we are not the toplevel frame then we check against the toplevelURL()
03314   if (args.redirectedRequest() && parentPart())
03315       args.metaData().insert("cross-domain", toplevelURL().url());
03316 
03317   if ( hasTarget )
03318   {
03319     // unknown frame names should open in a new window.
03320     khtml::ChildFrame *frame = recursiveFrameRequest( cURL, args, false );
03321     if ( frame )
03322     {
03323       args.metaData()["referrer"] = d->m_referrer;
03324       requestObject( frame, cURL, args );
03325       return;
03326     }
03327   }
03328 
03329   if ( !d->m_bComplete && !hasTarget )
03330     closeURL();
03331 
03332   if (!d->m_referrer.isEmpty() && !args.metaData().contains("referrer"))
03333     args.metaData()["referrer"] = d->m_referrer;
03334 
03335   if ( button == 0 && (state & ShiftButton) && (state & ControlButton) )
03336   {
03337     emit d->m_extension->createNewWindow( cURL, args );
03338     return;
03339   }
03340 
03341   if ( state & ShiftButton)
03342   {
03343     KParts::WindowArgs winArgs;
03344     winArgs.lowerWindow = true;
03345     KParts::ReadOnlyPart *newPart = 0;
03346     emit d->m_extension->createNewWindow( cURL, args, winArgs, newPart );
03347     return;
03348   }
03349 
03350   if ( state & ControlButton )
03351   {
03352     args.setNewTab(true);
03353     emit d->m_extension->createNewWindow( cURL, args );
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       KParts::BrowserRun::AskSaveResult res = KParts::BrowserRun::askEmbedOrSave(
03780         url, mimetype/*, suggestedFilename */ );
03781       switch( res ) {
03782       case KParts::BrowserRun::Save:
03783         KHTMLPopupGUIClient::saveURL( widget(), i18n( "Save As" ), url, child->m_args.metaData(), QString::null, 0 /*, suggestedFilename */ );
03784         // fall-through
03785       case KParts::BrowserRun::Cancel:
03786         child->m_bCompleted = true;
03787         checkCompleted();
03788         return true; // done
03789       default: // Open
03790         break;
03791       }
03792     }
03793 
03794     QStringList dummy; // the list of servicetypes handled by the part is now unused.
03795     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 );
03796 
03797     if ( !part )
03798     {
03799         if ( child->m_frame )
03800           if (child->m_frame->partLoadingErrorNotify( child, url, mimetype ))
03801             return true; // we succeeded after all (a fallback was used)
03802 
03803         checkEmitLoadEvent();
03804         return false;
03805     }
03806 
03807     //CRITICAL STUFF
03808     if ( child->m_part )
03809     {
03810       partManager()->removePart( (KParts::ReadOnlyPart *)child->m_part );
03811       delete (KParts::ReadOnlyPart *)child->m_part;
03812     }
03813 
03814     child->m_serviceType = mimetype;
03815     if ( child->m_frame )
03816       child->m_frame->setWidget( part->widget() );
03817 
03818     if ( child->m_type != khtml::ChildFrame::Object )
03819       partManager()->addPart( part, false );
03820 //  else
03821 //      kdDebug(6005) << "AH! NO FRAME!!!!!" << endl;
03822 
03823     child->m_part = part;
03824     assert( ((void*) child->m_part) != 0);
03825 
03826     connect( part, SIGNAL( started( KIO::Job *) ),
03827              this, SLOT( slotChildStarted( KIO::Job *) ) );
03828     connect( part, SIGNAL( completed() ),
03829              this, SLOT( slotChildCompleted() ) );
03830     if ( child->m_type != khtml::ChildFrame::Object )
03831     {
03832       connect( part, SIGNAL( completed(bool) ),
03833                this, SLOT( slotChildCompleted(bool) ) );
03834       connect( part, SIGNAL( setStatusBarText( const QString & ) ),
03835                this, SIGNAL( setStatusBarText( const QString & ) ) );
03836       if ( part->inherits( "KHTMLPart" ) )
03837       {
03838           connect( this, SIGNAL( completed() ),
03839                    part, SLOT( slotParentCompleted() ) );
03840           connect( this, SIGNAL( completed(bool) ),
03841                    part, SLOT( slotParentCompleted() ) );
03842           // As soon as the child's document is created, we need to set its domain
03843           // (but we do so only once, so it can't be simply done in the child)
03844           connect( part, SIGNAL( docCreated() ),
03845                    this, SLOT( slotChildDocCreated() ) );
03846       }
03847     }
03848 
03849     child->m_extension = KParts::BrowserExtension::childObject( part );
03850 
03851     if ( child->m_extension )
03852     {
03853       connect( child->m_extension, SIGNAL( openURLNotify() ),
03854                d->m_extension, SIGNAL( openURLNotify() ) );
03855 
03856       connect( child->m_extension, SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ),
03857                this, SLOT( slotChildURLRequest( const KURL &, const KParts::URLArgs & ) ) );
03858 
03859       connect( child->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ),
03860                d->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ) );
03861       connect( child->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs &, const KParts::WindowArgs &, KParts::ReadOnlyPart *& ) ),
03862                d->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & , const KParts::WindowArgs &, KParts::ReadOnlyPart *&) ) );
03863 
03864       connect( child->m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ),
03865                d->m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ) );
03866       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ),
03867                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ) );
03868       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ),
03869                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ) );
03870       connect( child->m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ),
03871                d->m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ) );
03872       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ),
03873                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ) );
03874       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ),
03875                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ) );
03876 
03877       connect( child->m_extension, SIGNAL( infoMessage( const QString & ) ),
03878                d->m_extension, SIGNAL( infoMessage( const QString & ) ) );
03879 
03880       child->m_extension->setBrowserInterface( d->m_extension->browserInterface() );
03881     }
03882     child->m_liveconnect = KParts::LiveConnectExtension::childObject( part );
03883   }
03884 
03885   checkEmitLoadEvent();
03886   // Some JS code in the load event may have destroyed the part
03887   // In that case, abort
03888   if ( !child->m_part )
03889     return false;
03890 
03891   if ( child->m_bPreloaded )
03892   {
03893     if ( child->m_frame && child->m_part )
03894       child->m_frame->setWidget( child->m_part->widget() );
03895 
03896     child->m_bPreloaded = false;
03897     return true;
03898   }
03899 
03900   child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload) || (d->m_cachePolicy == KIO::CC_Refresh);
03901 
03902   // make sure the part has a way to find out about the mimetype.
03903   // we actually set it in child->m_args in requestObject already,
03904   // but it's useless if we had to use a KHTMLRun instance, as the
03905   // point the run object is to find out exactly the mimetype.
03906   child->m_args.serviceType = mimetype;
03907 
03908   // if not a frame set child as completed
03909   child->m_bCompleted = child->m_type == khtml::ChildFrame::Object;
03910 
03911   if ( child->m_extension )
03912     child->m_extension->setURLArgs( child->m_args );
03913 
03914   if(url.protocol() == "javascript" || url.url() == "about:blank") {
03915       if (!child->m_part->inherits("KHTMLPart"))
03916           return false;
03917 
03918       KHTMLPart* p = static_cast<KHTMLPart*>(static_cast<KParts::ReadOnlyPart *>(child->m_part));
03919 
03920       p->begin();
03921       if (d->m_doc && p->d->m_doc)
03922         p->d->m_doc->setBaseURL(d->m_doc->baseURL());
03923       if (!url.url().startsWith("about:")) {
03924         p->write(url.path());
03925       } else {
03926     p->m_url = url;
03927         // we need a body element. testcase: <iframe id="a"></iframe><script>alert(a.document.body);</script>
03928         p->write("<HTML><BODY></BODY></HTML>");
03929       }
03930       p->end();
03931       return true;
03932   }
03933   else if ( !url.isEmpty() )
03934   {
03935       //kdDebug( 6050 ) << "opening " << url.url() << " in frame " << child->m_part << endl;
03936       bool b = child->m_part->openURL( url );
03937       if (child->m_bCompleted)
03938           checkCompleted();
03939       return b;
03940   }
03941   else
03942   {
03943       child->m_bCompleted = true;
03944       checkCompleted();
03945       return true;
03946   }
03947 }
03948 
03949 KParts::ReadOnlyPart *KHTMLPart::createPart( QWidget *parentWidget, const char *widgetName,
03950                                              QObject *parent, const char *name, const QString &mimetype,
03951                                              QString &serviceName, QStringList &serviceTypes,
03952                                              const QStringList &params )
03953 {
03954   QString constr;
03955   if ( !serviceName.isEmpty() )
03956     constr.append( QString::fromLatin1( "Name == '%1'" ).arg( serviceName ) );
03957 
03958   KTrader::OfferList offers = KTrader::self()->query( mimetype, "KParts/ReadOnlyPart", constr, QString::null );
03959 
03960   if ( offers.isEmpty() )
03961     return 0L;
03962 
03963   KTrader::OfferList::Iterator it = offers.begin();
03964   for (  ; it != offers.end() ; ++it )
03965   {
03966     KService::Ptr service = (*it);
03967 
03968     KLibFactory *factory = KLibLoader::self()->factory( QFile::encodeName(service->library()) );
03969     if ( factory ) {
03970       KParts::ReadOnlyPart *res = 0L;
03971 
03972       const char *className = "KParts::ReadOnlyPart";
03973       if ( service->serviceTypes().contains( "Browser/View" ) )
03974         className = "Browser/View";
03975 
03976       if ( factory->inherits( "KParts::Factory" ) )
03977         res = static_cast<KParts::ReadOnlyPart *>(static_cast<KParts::Factory *>( factory )->createPart( parentWidget, widgetName, parent, name, className, params ));
03978       else
03979         res = static_cast<KParts::ReadOnlyPart *>(factory->create( parentWidget, widgetName, className ));
03980 
03981       if ( res ) {
03982         serviceTypes = service->serviceTypes();
03983         serviceName = service->name();
03984         return res;
03985       }
03986     } else {
03987       // TODO KMessageBox::error and i18n, like in KonqFactory::createView?
03988       kdWarning() << QString("There was an error loading the module %1.\nThe diagnostics is:\n%2")
03989                       .arg(service->name()).arg(KLibLoader::self()->lastErrorMessage()) << endl;
03990     }
03991   }
03992   return 0;
03993 }
03994 
03995 KParts::PartManager *KHTMLPart::partManager()
03996 {
03997   if ( !d->m_manager )
03998   {
03999     d->m_manager = new KParts::PartManager( d->m_view->topLevelWidget(), this, "khtml part manager" );
04000     d->m_manager->setAllowNestedParts( true );
04001     connect( d->m_manager, SIGNAL( activePartChanged( KParts::Part * ) ),
04002              this, SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
04003     connect( d->m_manager, SIGNAL( partRemoved( KParts::Part * ) ),
04004              this, SLOT( slotPartRemoved( KParts::Part * ) ) );
04005   }
04006 
04007   return d->m_manager;
04008 }
04009 
04010 void KHTMLPart::submitFormAgain()
04011 {
04012   if( d->m_doc && !d->m_doc->parsing() && d->m_submitForm)
04013     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 );
04014 
04015   delete d->m_submitForm;
04016   d->m_submitForm = 0;
04017   disconnect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
04018 }
04019 
04020 void KHTMLPart::submitFormProxy( const char *action, const QString &url, const QByteArray &formData, const QString &_target, const QString& contentType, const QString& boundary )
04021 {
04022   submitForm(action, url, formData, _target, contentType, boundary);
04023 }
04024 
04025 void KHTMLPart::submitForm( const char *action, const QString &url, const QByteArray &formData, const QString &_target, const QString& contentType, const QString& boundary )
04026 {
04027   kdDebug(6000) << this << ": KHTMLPart::submitForm target=" << _target << " url=" << url << endl;
04028   if (d->m_formNotification == KHTMLPart::Only) {
04029     emit formSubmitNotification(action, url, formData, _target, contentType, boundary);
04030     return;
04031   } else if (d->m_formNotification == KHTMLPart::Before) {
04032     emit formSubmitNotification(action, url, formData, _target, contentType, boundary);
04033   }
04034 
04035   KURL u = completeURL( url );
04036 
04037   if ( !u.isValid() )
04038   {
04039     // ### ERROR HANDLING!
04040     return;
04041   }
04042 
04043   // Form security checks
04044   //
04045   /*
04046    * If these form security checks are still in this place in a month or two
04047    * I'm going to simply delete them.
04048    */
04049 
04050   /* This is separate for a reason.  It has to be _before_ all script, etc,
04051    * AND I don't want to break anything that uses checkLinkSecurity() in
04052    * other places.
04053    */
04054 
04055   if (!d->m_submitForm) {
04056     if (u.protocol() != "https" && u.protocol() != "mailto") {
04057       if (d->m_ssl_in_use) {    // Going from SSL -> nonSSL
04058         int rc = KMessageBox::warningContinueCancel(NULL, i18n("Warning:  This is a secure form but it is attempting to send your data back unencrypted."
04059                                                                "\nA third party may be able to intercept and view this information."
04060                                                                "\nAre you sure you wish to continue?"),
04061                                                     i18n("SSL"));
04062         if (rc == KMessageBox::Cancel)
04063           return;
04064       } else {                  // Going from nonSSL -> nonSSL
04065         KSSLSettings kss(true);
04066         if (kss.warnOnUnencrypted()) {
04067           int rc = KMessageBox::warningContinueCancel(NULL,
04068                                                       i18n("Warning: Your data is about to be transmitted across the network unencrypted."
04069                                                            "\nAre you sure you wish to continue?"),
04070                                                       i18n("KDE"),
04071                                                       QString::null,
04072                                                       "WarnOnUnencryptedForm");
04073           // Move this setting into KSSL instead
04074           KConfig *config = kapp->config();
04075           QString grpNotifMsgs = QString::fromLatin1("Notification Messages");
04076           KConfigGroupSaver saver( config, grpNotifMsgs );
04077 
04078           if (!config->readBoolEntry("WarnOnUnencryptedForm", true)) {
04079             config->deleteEntry("WarnOnUnencryptedForm");
04080             config->sync();
04081             kss.setWarnOnUnencrypted(false);
04082             kss.save();
04083           }
04084           if (rc == KMessageBox::Cancel)
04085             return;
04086         }
04087       }
04088     }
04089 
04090     if (u.protocol() == "mailto") {
04091       int rc = KMessageBox::warningContinueCancel(NULL,
04092                                                   i18n("This site is attempting to submit form data via email.\n"
04093                                                        "Do you want to continue?"),
04094                                                   i18n("KDE"),
04095                                                   QString::null,
04096                                                   "WarnTriedEmailSubmit");
04097 
04098       if (rc == KMessageBox::Cancel) {
04099         return;
04100       }
04101     }
04102   }
04103 
04104   // End form security checks
04105   //
04106 
04107   QString urlstring = u.url();
04108 
04109   if ( urlstring.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
04110     urlstring = KURL::decode_string(urlstring);
04111     crossFrameExecuteScript( _target, urlstring.right( urlstring.length() - 11) );
04112     return;
04113   }
04114 
04115   if (!checkLinkSecurity(u,
04116              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?" ),
04117              i18n( "Submit" )))
04118     return;
04119 
04120   KParts::URLArgs args;
04121 
04122   if (!d->m_referrer.isEmpty())
04123      args.metaData()["referrer"] = d->m_referrer;
04124 
04125   args.metaData().insert("PropagateHttpHeader", "true");
04126   args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
04127   args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
04128   args.metaData().insert("main_frame_request",
04129                          parentPart() == 0 ? "TRUE":"FALSE");
04130   args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
04131   args.metaData().insert("ssl_activate_warnings", "TRUE");
04132 //WABA: When we post a form we should treat it as the main url
04133 //the request should never be considered cross-domain
04134 //args.metaData().insert("cross-domain", toplevelURL().url());
04135   args.frameName = _target.isEmpty() ? d->m_doc->baseTarget() : _target ;
04136 
04137   // Handle mailto: forms
04138   if (u.protocol() == "mailto") {
04139       // 1)  Check for attach= and strip it
04140       QString q = u.query().mid(1);
04141       QStringList nvps = QStringList::split("&", q);
04142       bool triedToAttach = false;
04143 
04144       for (QStringList::Iterator nvp = nvps.begin(); nvp != nvps.end(); ++nvp) {
04145          QStringList pair = QStringList::split("=", *nvp);
04146          if (pair.count() >= 2) {
04147             if (pair.first().lower() == "attach") {
04148                nvp = nvps.remove(nvp);
04149                triedToAttach = true;
04150             }
04151          }
04152       }
04153 
04154       if (triedToAttach)
04155          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");
04156 
04157       // 2)  Append body=
04158       QString bodyEnc;
04159       if (contentType.lower() == "multipart/form-data") {
04160          // FIXME: is this correct?  I suspect not
04161          bodyEnc = KURL::encode_string(QString::fromLatin1(formData.data(),
04162                                                            formData.size()));
04163       } else if (contentType.lower() == "text/plain") {
04164          // Convention seems to be to decode, and s/&/\n/
04165          QString tmpbody = QString::fromLatin1(formData.data(),
04166                                                formData.size());
04167          tmpbody.replace(QRegExp("[&]"), "\n");
04168          tmpbody.replace(QRegExp("[+]"), " ");
04169          tmpbody = KURL::decode_string(tmpbody);  // Decode the rest of it
04170          bodyEnc = KURL::encode_string(tmpbody);  // Recode for the URL
04171       } else {
04172          bodyEnc = KURL::encode_string(QString::fromLatin1(formData.data(),
04173                                                            formData.size()));
04174       }
04175 
04176       nvps.append(QString("body=%1").arg(bodyEnc));
04177       q = nvps.join("&");
04178       u.setQuery(q);
04179   }
04180 
04181   if ( strcmp( action, "get" ) == 0 ) {
04182     if (u.protocol() != "mailto")
04183        u.setQuery( QString::fromLatin1( formData.data(), formData.size() ) );
04184     args.setDoPost( false );
04185   }
04186   else {
04187     args.postData = formData;
04188     args.setDoPost( true );
04189 
04190     // construct some user headers if necessary
04191     if (contentType.isNull() || contentType == "application/x-www-form-urlencoded")
04192       args.setContentType( "Content-Type: application/x-www-form-urlencoded" );
04193     else // contentType must be "multipart/form-data"
04194       args.setContentType( "Content-Type: " + contentType + "; boundary=" + boundary );
04195   }
04196 
04197   if ( d->m_doc->parsing() || d->m_runningScripts > 0 ) {
04198     if( d->m_submitForm ) {
04199       kdDebug(6000) << "KHTMLPart::submitForm ABORTING!" << endl;
04200       return;
04201     }
04202     d->m_submitForm = new KHTMLPartPrivate::SubmitForm;
04203     d->m_submitForm->submitAction = action;
04204     d->m_submitForm->submitUrl = url;
04205     d->m_submitForm->submitFormData = formData;
04206     d->m_submitForm->target = _target;
04207     d->m_submitForm->submitContentType = contentType;
04208     d->m_submitForm->submitBoundary = boundary;
04209     connect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
04210   }
04211   else
04212   {
04213     emit d->m_extension->openURLRequest( u, args );
04214   }
04215 }
04216 
04217 void KHTMLPart::popupMenu( const QString &linkUrl )
04218 {
04219   KURL popupURL;
04220   KURL linkKURL;
04221   QString referrer;
04222   KParts::BrowserExtension::PopupFlags itemflags=KParts::BrowserExtension::ShowBookmark | KParts::BrowserExtension::ShowReload;
04223 
04224   if ( linkUrl.isEmpty() ) { // click on background
04225     KHTMLPart* khtmlPart = this;
04226     while ( khtmlPart->parentPart() )
04227     {
04228       khtmlPart=khtmlPart->parentPart();
04229     }
04230     popupURL = khtmlPart->url();
04231     referrer = khtmlPart->pageReferrer();
04232     itemflags |= KParts::BrowserExtension::ShowNavigationItems;
04233   } else {               // click on link
04234     popupURL = completeURL( linkUrl );
04235     linkKURL = popupURL;
04236     referrer = this->referrer();
04237   }
04238 
04239   // Danger, Will Robinson. The Popup might stay around for a much
04240   // longer time than KHTMLPart. Deal with it.
04241   KHTMLPopupGUIClient* client = new KHTMLPopupGUIClient( this, d->m_popupMenuXML, linkKURL );
04242   QGuardedPtr<QObject> guard( client );
04243 
04244   KParts::URLArgs args;
04245   args.serviceType = QString::fromLatin1( "text/html" );
04246   args.metaData()["referrer"] = referrer;
04247 
04248   emit d->m_extension->popupMenu( client, QCursor::pos(), popupURL, args, itemflags, S_IFREG /*always a file*/);
04249 
04250   if ( !guard.isNull() ) {
04251      delete client;
04252      emit popupMenu(linkUrl, QCursor::pos());
04253      d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
04254   }
04255 }
04256 
04257 void KHTMLPart::slotParentCompleted()
04258 {
04259   if ( !d->m_redirectURL.isEmpty() && !d->m_redirectionTimer.isActive() )
04260   {
04261     // kdDebug(6050) << this << ": Child redirection -> " << d->m_redirectURL << endl;
04262     d->m_redirectionTimer.start( 1000 * d->m_delayRedirect, true );
04263   }
04264 }
04265 
04266 void KHTMLPart::slotChildStarted( KIO::Job *job )
04267 {
04268   khtml::ChildFrame *child = frame( sender() );
04269 
04270   assert( child );
04271 
04272   child->m_bCompleted = false;
04273 
04274   if ( d->m_bComplete )
04275   {
04276 #if 0
04277     // WABA: Looks like this belongs somewhere else
04278     if ( !parentPart() ) // "toplevel" html document? if yes, then notify the hosting browser about the document (url) changes
04279     {
04280       emit d->m_extension->openURLNotify();
04281     }
04282 #endif
04283     d->m_bComplete = false;
04284     emit started( job );
04285   }
04286 }
04287 
04288 void KHTMLPart::slotChildCompleted()
04289 {
04290   slotChildCompleted( false );
04291 }
04292 
04293 void KHTMLPart::slotChildCompleted( bool pendingAction )
04294 {
04295   khtml::ChildFrame *child = frame( sender() );
04296 
04297   if ( child ) {
04298     kdDebug(6050) << this << " slotChildCompleted child=" << child << " m_frame=" << child->m_frame << endl;
04299     child->m_bCompleted = true;
04300     child->m_bPendingRedirection = pendingAction;
04301     child->m_args = KParts::URLArgs();
04302   }
04303   checkCompleted();
04304 }
04305 
04306 void KHTMLPart::slotChildDocCreated()
04307 {
04308   const KHTMLPart* htmlFrame = static_cast<const KHTMLPart *>(sender());
04309   // Set domain to the frameset's domain
04310   // This must only be done when loading the frameset initially (#22039),
04311   // not when following a link in a frame (#44162).
04312   if ( d->m_doc && d->m_doc->isHTMLDocument() )
04313   {
04314     if ( sender()->inherits("KHTMLPart") )
04315     {
04316       DOMString domain = static_cast<HTMLDocumentImpl*>(d->m_doc)->domain();
04317       if (htmlFrame->d->m_doc && htmlFrame->d->m_doc->isHTMLDocument() )
04318         //kdDebug(6050) << "KHTMLPart::slotChildDocCreated: url: " << htmlFrame->m_url.url() << endl;
04319         static_cast<HTMLDocumentImpl*>(htmlFrame->d->m_doc)->setDomain( domain );
04320     }
04321   }
04322   // So it only happens once
04323   disconnect( htmlFrame, SIGNAL( docCreated() ), this, SLOT( slotChildDocCreated() ) );
04324 }
04325 
04326 void KHTMLPart::slotChildURLRequest( const KURL &url, const KParts::URLArgs &args )
04327 {
04328   khtml::ChildFrame *child = frame( sender()->parent() );
04329 
04330   // TODO: handle child target correctly! currently the script are always executed fur the parent
04331   QString urlStr = url.url();
04332   if ( urlStr.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
04333       QString script = KURL::decode_string( urlStr.right( urlStr.length() - 11 ) );
04334       executeScript( DOM::Node(), script );
04335       return;
04336   }
04337 
04338   QString frameName = args.frameName.lower();
04339   if ( !frameName.isEmpty() ) {
04340     if ( frameName == QString::fromLatin1( "_top" ) )
04341     {
04342       emit d->m_extension->openURLRequest( url, args );
04343       return;
04344     }
04345     else if ( frameName == QString::fromLatin1( "_blank" ) )
04346     {
04347       emit d->m_extension->createNewWindow( url, args );
04348       return;
04349     }
04350     else if ( frameName == QString::fromLatin1( "_parent" ) )
04351     {
04352       KParts::URLArgs newArgs( args );
04353       newArgs.frameName = QString::null;
04354 
04355       emit d->m_extension->openURLRequest( url, newArgs );
04356       return;
04357     }
04358     else if ( frameName != QString::fromLatin1( "_self" ) )
04359     {
04360       khtml::ChildFrame *_frame = recursiveFrameRequest( url, args );
04361 
04362       if ( !_frame )
04363       {
04364         emit d->m_extension->openURLRequest( url, args );
04365         return;
04366       }
04367 
04368       child = _frame;
04369     }
04370   }
04371 
04372   if ( child && child->m_type != khtml::ChildFrame::Object ) {
04373       // Inform someone that we are about to show something else.
04374       child->m_bNotify = true;
04375       requestObject( child, url, args );
04376   }  else if ( frameName== "_self" ) // this is for embedded objects (via <object>) which want to replace the current document
04377   {
04378       KParts::URLArgs newArgs( args );
04379       newArgs.frameName = QString::null;
04380       emit d->m_extension->openURLRequest( url, newArgs );
04381   }
04382 }
04383 
04384 khtml::ChildFrame *KHTMLPart::frame( const QObject *obj )
04385 {
04386     assert( obj->inherits( "KParts::ReadOnlyPart" ) );
04387     const KParts::ReadOnlyPart *part = static_cast<const KParts::ReadOnlyPart *>( obj );
04388 
04389     FrameIt it = d->m_frames.begin();
04390     FrameIt end = d->m_frames.end();
04391     for (; it != end; ++it )
04392       if ( (KParts::ReadOnlyPart *)(*it).m_part == part )
04393         return &(*it);
04394 
04395     for (it = d->m_objects.begin(); it != d->m_objects.end(); ++it )
04396       if ( (KParts::ReadOnlyPart *)(*it).m_part == part )
04397         return &(*it);
04398 
04399     return 0L;
04400 }
04401 
04402 //#define DEBUG_FINDFRAME
04403 
04404 KHTMLPart *KHTMLPart::findFrame( const QString &f )
04405 {
04406 #ifdef DEBUG_FINDFRAME
04407   kdDebug(6050) << "KHTMLPart::findFrame '" << f << "'" << endl;
04408   FrameIt it2 = d->m_frames.begin();
04409   FrameIt end = d->m_frames.end();
04410   for (; it2 != end; ++it2 )
04411       kdDebug(6050) << "  - having frame '" << (*it2).m_name << "'" << endl;
04412 #endif
04413   // ### http://www.w3.org/TR/html4/appendix/notes.html#notes-frames
04414   ConstFrameIt it = d->m_frames.find( f );
04415   if ( it == d->m_frames.end() )
04416   {
04417 #ifdef DEBUG_FINDFRAME
04418     kdDebug(6050) << "KHTMLPart::findFrame frame " << f << " not found" << endl;
04419 #endif
04420     return 0L;
04421   }
04422   else {
04423     KParts::ReadOnlyPart *p = (*it).m_part;
04424     if ( p && p->inherits( "KHTMLPart" ))
04425     {
04426 #ifdef DEBUG_FINDFRAME
04427       kdDebug(6050) << "KHTMLPart::findFrame frame " << f << " is a KHTMLPart, ok" << endl;
04428 #endif
04429       return (KHTMLPart*)p;
04430     }
04431     else
04432     {
04433 #ifdef DEBUG_FINDFRAME
04434       if (p)
04435         kdWarning() << "KHTMLPart::findFrame frame " << f << " found but isn't a KHTMLPart ! " << p->className() << endl;
04436       else
04437         kdWarning() << "KHTMLPart::findFrame frame " << f << " found but m_part=0L" << endl;
04438 #endif
04439       return 0L;
04440     }
04441   }
04442 }
04443 
04444 KParts::ReadOnlyPart *KHTMLPart::currentFrame() const
04445 {
04446   KParts::ReadOnlyPart* part = (KParts::ReadOnlyPart*)(this);
04447   // Find active part in our frame manager, in case we are a frameset
04448   // and keep doing that (in case of nested framesets).
04449   // Just realized we could also do this recursively, calling part->currentFrame()...
04450   while ( part && part->inherits("KHTMLPart") &&
04451           static_cast<KHTMLPart *>(part)->d->m_frames.count() > 0 ) {
04452     KHTMLPart* frameset = static_cast<KHTMLPart *>(part);
04453     part = static_cast<KParts::ReadOnlyPart *>(frameset->partManager()->activePart());
04454     if ( !part ) return frameset;
04455   }
04456   return part;
04457 }
04458 
04459 bool KHTMLPart::frameExists( const QString &frameName )
04460 {
04461   ConstFrameIt it = d->m_frames.find( frameName );
04462   if ( it == d->m_frames.end() )
04463     return false;
04464 
04465   // WABA: We only return true if the child actually has a frame
04466   // set. Otherwise we might find our preloaded-selve.
04467   // This happens when we restore the frameset.
04468   return (!(*it).m_frame.isNull());
04469 }
04470 
04471 KHTMLPart *KHTMLPart::parentPart()
04472 {
04473   if ( !parent() || !parent()->inherits( "KHTMLPart" ) )
04474     return 0L;
04475 
04476   return (KHTMLPart *)parent();
04477 }
04478 
04479 khtml::ChildFrame *KHTMLPart::recursiveFrameRequest( const KURL &url, const KParts::URLArgs &args,
04480                                                      bool callParent )
04481 {
04482   FrameIt it = d->m_frames.find( args.frameName );
04483 
04484   if ( it != d->m_frames.end() )
04485     return &(*it);
04486 
04487   it = d->m_frames.begin();
04488   FrameIt end = d->m_frames.end();
04489   for (; it != end; ++it )
04490     if ( (*it).m_part && (*it).m_part->inherits( "KHTMLPart" ) )
04491     {
04492       KHTMLPart *childPart = (KHTMLPart *)(KParts::ReadOnlyPart *)(*it).m_part;
04493 
04494       khtml::ChildFrame *res = childPart->recursiveFrameRequest( url, args, false );
04495       if ( !res )
04496         continue;
04497 
04498       childPart->requestObject( res, url, args );
04499       return 0L;
04500     }
04501 
04502   if ( parentPart() && callParent )
04503   {
04504     khtml::ChildFrame *res = parentPart()->recursiveFrameRequest( url, args );
04505 
04506     if ( res )
04507       parentPart()->requestObject( res, url, args );
04508 
04509     return 0L;
04510   }
04511 
04512   return 0L;
04513 }
04514 
04515 void KHTMLPart::saveState( QDataStream &stream )
04516 {
04517   kdDebug( 6050 ) << "KHTMLPart::saveState saving URL " << m_url.url() << endl;
04518 
04519   stream << m_url << (Q_INT32)d->m_view->contentsX() << (Q_INT32)d->m_view->contentsY()
04520          << (Q_INT32) d->m_view->contentsWidth() << (Q_INT32) d->m_view->contentsHeight() << (Q_INT32) d->m_view->marginWidth() << (Q_INT32) d->m_view->marginHeight();
04521 
04522   // save link cursor position
04523   int focusNodeNumber;
04524   if (!d->m_focusNodeRestored)
04525       focusNodeNumber = d->m_focusNodeNumber;
04526   else if (d->m_doc && d->m_doc->focusNode())
04527       focusNodeNumber = d->m_doc->nodeAbsIndex(d->m_doc->focusNode());
04528   else
04529       focusNodeNumber = -1;
04530   stream << focusNodeNumber;
04531 
04532   // Save the doc's cache id.
04533   stream << d->m_cacheId;
04534 
04535   // Save the state of the document (Most notably the state of any forms)
04536   QStringList docState;
04537   if (d->m_doc)
04538   {
04539      docState = d->m_doc->docState();
04540   }
04541   stream << d->m_encoding << d->m_sheetUsed << docState;
04542 
04543   stream << d->m_zoomFactor;
04544 
04545   stream << d->m_httpHeaders;
04546   stream << d->m_pageServices;
04547   stream << d->m_pageReferrer;
04548 
04549   // Save ssl data
04550   stream << d->m_ssl_in_use
04551          << d->m_ssl_peer_certificate
04552          << d->m_ssl_peer_chain
04553          << d->m_ssl_peer_ip
04554          << d->m_ssl_cipher
04555          << d->m_ssl_cipher_desc
04556          << d->m_ssl_cipher_version
04557          << d->m_ssl_cipher_used_bits
04558          << d->m_ssl_cipher_bits
04559          << d->m_ssl_cert_state
04560          << d->m_ssl_parent_ip
04561          << d->m_ssl_parent_cert;
04562 
04563 
04564   QStringList frameNameLst, frameServiceTypeLst, frameServiceNameLst;
04565   KURL::List frameURLLst;
04566   QValueList<QByteArray> frameStateBufferLst;
04567 
04568   ConstFrameIt it = d->m_frames.begin();
04569   ConstFrameIt end = d->m_frames.end();
04570   for (; it != end; ++it )
04571   {
04572     if ( !(*it).m_part )
04573        continue;
04574 
04575     frameNameLst << (*it).m_name;
04576     frameServiceTypeLst << (*it).m_serviceType;
04577     frameServiceNameLst << (*it).m_serviceName;
04578     frameURLLst << (*it).m_part->url();
04579 
04580     QByteArray state;
04581     QDataStream frameStream( state, IO_WriteOnly );
04582 
04583     if ( (*it).m_extension )
04584       (*it).m_extension->saveState( frameStream );
04585 
04586     frameStateBufferLst << state;
04587   }
04588 
04589   // Save frame data
04590   stream << (Q_UINT32) frameNameLst.count();
04591   stream << frameNameLst << frameServiceTypeLst << frameServiceNameLst << frameURLLst << frameStateBufferLst;
04592 }
04593 
04594 void KHTMLPart::restoreState( QDataStream &stream )
04595 {
04596   KURL u;
04597   Q_INT32 xOffset, yOffset, wContents, hContents, mWidth, mHeight;
04598   Q_UINT32 frameCount;
04599   QStringList frameNames, frameServiceTypes, docState, frameServiceNames;
04600   KURL::List frameURLs;
04601   QValueList<QByteArray> frameStateBuffers;
04602   QValueList<int> fSizes;
04603   QString encoding, sheetUsed;
04604   long old_cacheId = d->m_cacheId;
04605 
04606   stream >> u >> xOffset >> yOffset >> wContents >> hContents >> mWidth >> mHeight;
04607 
04608   d->m_view->setMarginWidth( mWidth );
04609   d->m_view->setMarginHeight( mHeight );
04610 
04611   // restore link cursor position
04612   // nth node is active. value is set in checkCompleted()
04613   stream >> d->m_focusNodeNumber;
04614   d->m_focusNodeRestored = false;
04615 
04616   stream >> d->m_cacheId;
04617 
04618   stream >> encoding >> sheetUsed >> docState;
04619 
04620   d->m_encoding = encoding;
04621   d->m_sheetUsed = sheetUsed;
04622 
04623   int zoomFactor;
04624   stream >> zoomFactor;
04625   setZoomFactor(zoomFactor);
04626 
04627   stream >> d->m_httpHeaders;
04628   stream >> d->m_pageServices;
04629   stream >> d->m_pageReferrer;
04630 
04631   // Restore ssl data
04632   stream >> d->m_ssl_in_use
04633          >> d->m_ssl_peer_certificate
04634          >> d->m_ssl_peer_chain
04635          >> d->m_ssl_peer_ip
04636          >> d->m_ssl_cipher
04637          >> d->m_ssl_cipher_desc
04638          >> d->m_ssl_cipher_version
04639          >> d->m_ssl_cipher_used_bits
04640          >> d->m_ssl_cipher_bits
04641          >> d->m_ssl_cert_state
04642          >> d->m_ssl_parent_ip
04643          >> d->m_ssl_parent_cert;
04644 
04645   setPageSecurity( d->m_ssl_in_use ? Encrypted : NotCrypted );
04646 
04647   stream >> frameCount >> frameNames >> frameServiceTypes >> frameServiceNames
04648          >> frameURLs >> frameStateBuffers;
04649 
04650   d->m_bComplete = false;
04651   d->m_bLoadEventEmitted = false;
04652 
04653 //   kdDebug( 6050 ) << "restoreStakte() docState.count() = " << docState.count() << endl;
04654 //   kdDebug( 6050 ) << "m_url " << m_url.url() << " <-> " << u.url() << endl;
04655 //   kdDebug( 6050 ) << "m_frames.count() " << d->m_frames.count() << " <-> " << frameCount << endl;
04656 
04657   if (d->m_cacheId == old_cacheId)
04658   {
04659     // Partial restore
04660     d->m_redirectionTimer.stop();
04661 
04662     FrameIt fIt = d->m_frames.begin();
04663     FrameIt fEnd = d->m_frames.end();
04664 
04665     for (; fIt != fEnd; ++fIt )
04666         (*fIt).m_bCompleted = false;
04667 
04668     fIt = d->m_frames.begin();
04669 
04670     QStringList::ConstIterator fNameIt = frameNames.begin();
04671     QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
04672     QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
04673     KURL::List::ConstIterator fURLIt = frameURLs.begin();
04674     QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
04675 
04676     for (; fIt != fEnd; ++fIt, ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
04677     {
04678       khtml::ChildFrame *child = &(*fIt);
04679 
04680 //      kdDebug( 6050 ) <<  *fNameIt  << " ---- " <<  *fServiceTypeIt << endl;
04681 
04682       if ( child->m_name != *fNameIt || child->m_serviceType != *fServiceTypeIt )
04683       {
04684         child->m_bPreloaded = true;
04685         child->m_name = *fNameIt;
04686         child->m_serviceName = *fServiceNameIt;
04687         processObjectRequest( child, *fURLIt, *fServiceTypeIt );
04688       }
04689 
04690       if ( child->m_part )
04691       {
04692         child->m_bCompleted = false;
04693         if ( child->m_extension && !(*fBufferIt).isEmpty() )
04694         {
04695           QDataStream frameStream( *fBufferIt, IO_ReadOnly );
04696           child->m_extension->restoreState( frameStream );
04697         }
04698         else
04699           child->m_part->openURL( *fURLIt );
04700       }
04701     }
04702 
04703     KParts::URLArgs args( d->m_extension->urlArgs() );
04704     args.xOffset = xOffset;
04705     args.yOffset = yOffset;
04706     args.docState = docState;
04707     d->m_extension->setURLArgs( args );
04708 
04709     d->m_view->resizeContents( wContents,  hContents);
04710     d->m_view->setContentsPos( xOffset, yOffset );
04711 
04712     m_url = u;
04713   }
04714   else
04715   {
04716     // Full restore.
04717     closeURL();
04718     // We must force a clear because we want to be sure to delete all
04719     // frames.
04720     d->m_bCleared = false;
04721     clear();
04722     d->m_encoding = encoding;
04723     d->m_sheetUsed = sheetUsed;
04724 
04725     QStringList::ConstIterator fNameIt = frameNames.begin();
04726     QStringList::ConstIterator fNameEnd = frameNames.end();
04727 
04728     QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
04729     QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
04730     KURL::List::ConstIterator fURLIt = frameURLs.begin();
04731     QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
04732 
04733     for (; fNameIt != fNameEnd; ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
04734     {
04735       khtml::ChildFrame newChild;
04736       newChild.m_bPreloaded = true;
04737       newChild.m_name = *fNameIt;
04738       newChild.m_serviceName = *fServiceNameIt;
04739 
04740 //      kdDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt << endl;
04741 
04742       FrameIt childFrame = d->m_frames.append( newChild );
04743 
04744       processObjectRequest( &(*childFrame), *fURLIt, *fServiceTypeIt );
04745 
04746       (*childFrame).m_bPreloaded = true;
04747 
04748       if ( (*childFrame).m_part )
04749       {
04750         if ( (*childFrame).m_extension )
04751         if ( (*childFrame).m_extension && !(*fBufferIt).isEmpty() )
04752         {
04753           QDataStream frameStream( *fBufferIt, IO_ReadOnly );
04754           (*childFrame).m_extension->restoreState( frameStream );
04755         }
04756         else
04757           (*childFrame).m_part->openURL( *fURLIt );
04758       }
04759     }
04760 
04761     KParts::URLArgs args( d->m_extension->urlArgs() );
04762     args.xOffset = xOffset;
04763     args.yOffset = yOffset;
04764     args.docState = docState;
04765 
04766     d->m_view->resizeContents( wContents,  hContents);
04767     d->m_view->setContentsPos( xOffset, yOffset );
04768 
04769     d->m_extension->setURLArgs( args );
04770     if (!KHTMLPageCache::self()->isComplete(d->m_cacheId))
04771     {
04772        d->m_restored = true;
04773        openURL( u );
04774        d->m_restored = false;
04775     }
04776     else
04777     {
04778        restoreURL( u );
04779     }
04780   }
04781 
04782 }
04783 
04784 void KHTMLPart::show()
04785 {
04786   if ( d->m_view )
04787     d->m_view->show();
04788 }
04789 
04790 void KHTMLPart::hide()
04791 {
04792   if ( d->m_view )
04793     d->m_view->hide();
04794 }
04795 
04796 DOM::Node KHTMLPart::nodeUnderMouse() const
04797 {
04798     return d->m_view->nodeUnderMouse();
04799 }
04800 
04801 void KHTMLPart::emitSelectionChanged()
04802 {
04803   emit d->m_extension->enableAction( "copy", hasSelection() );
04804   if ( d->m_findDialog )
04805        d->m_findDialog->setHasSelection( hasSelection() );
04806 
04807   emit d->m_extension->selectionInfo( selectedText() );
04808   emit selectionChanged();
04809 }
04810 
04811 int KHTMLPart::zoomFactor() const
04812 {
04813   return d->m_zoomFactor;
04814 }
04815 
04816 // ### make the list configurable ?
04817 static const int zoomSizes[] = { 20, 40, 60, 80, 90, 95, 100, 105, 110, 120, 140, 160, 180, 200, 250, 300 };
04818 static const int zoomSizeCount = (sizeof(zoomSizes) / sizeof(int));
04819 static const int minZoom = 20;
04820 static const int maxZoom = 300;
04821 
04822 void KHTMLPart::slotIncZoom()
04823 {
04824   int zoomFactor = d->m_zoomFactor;
04825 
04826   if (zoomFactor < maxZoom) {
04827     // find the entry nearest to the given zoomsizes
04828     for (int i = 0; i < zoomSizeCount; ++i)
04829       if (zoomSizes[i] > zoomFactor) {
04830         zoomFactor = zoomSizes[i];
04831         break;
04832       }
04833     setZoomFactor(zoomFactor);
04834   }
04835 }
04836 
04837 void KHTMLPart::slotDecZoom()
04838 {
04839     int zoomFactor = d->m_zoomFactor;
04840     if (zoomFactor > minZoom) {
04841       // find the entry nearest to the given zoomsizes
04842       for (int i = zoomSizeCount-1; i >= 0; --i)
04843         if (zoomSizes[i] < zoomFactor) {
04844           zoomFactor = zoomSizes[i];
04845           break;
04846         }
04847       setZoomFactor(zoomFactor);
04848     }
04849 }
04850 
04851 void KHTMLPart::setZoomFactor (int percent)
04852 {
04853   if (percent < minZoom) percent = minZoom;
04854   if (percent > maxZoom) percent = maxZoom;
04855   if (d->m_zoomFactor == percent) return;
04856   d->m_zoomFactor = percent;
04857 
04858   if(d->m_doc) {
04859       QApplication::setOverrideCursor( waitCursor );
04860     if (d->m_doc->styleSelector())
04861       d->m_doc->styleSelector()->computeFontSizes(d->m_doc->paintDeviceMetrics(), d->m_zoomFactor);
04862     d->m_doc->recalcStyle( NodeImpl::Force );
04863     QApplication::restoreOverrideCursor();
04864   }
04865 
04866   ConstFrameIt it = d->m_frames.begin();
04867   ConstFrameIt end = d->m_frames.end();
04868   for (; it != end; ++it )
04869     if ( !( *it ).m_part.isNull() && ( *it ).m_part->inherits( "KHTMLPart" ) ) {
04870       KParts::ReadOnlyPart* p = ( *it ).m_part;
04871       static_cast<KHTMLPart*>( p )->setZoomFactor(d->m_zoomFactor);
04872     }
04873 
04874   if ( d->m_guiProfile == BrowserViewGUI ) {
04875       d->m_paDecZoomFactor->setEnabled( d->m_zoomFactor > minZoom );
04876       d->m_paIncZoomFactor->setEnabled( d->m_zoomFactor < maxZoom );
04877   }
04878 }
04879 
04880 void KHTMLPart::slotZoomView( int delta )
04881 {
04882   if ( delta < 0 )
04883     slotIncZoom();
04884   else
04885     slotDecZoom();
04886 }
04887 
04888 void KHTMLPart::setStatusBarText( const QString& text, StatusBarPriority p)
04889 {
04890   if (!d->m_statusMessagesEnabled)
04891     return;
04892 
04893   d->m_statusBarText[p] = text;
04894 
04895   // shift handling ?
04896   QString tobe = d->m_statusBarText[BarHoverText];
04897   if (tobe.isEmpty())
04898     tobe = d->m_statusBarText[BarOverrideText];
04899   if (tobe.isEmpty()) {
04900     tobe = d->m_statusBarText[BarDefaultText];
04901     if (!tobe.isEmpty() && d->m_jobspeed)
04902       tobe += " ";
04903     if (d->m_jobspeed)
04904       tobe += i18n( "(%1/s)" ).arg( KIO::convertSize( d->m_jobspeed ) );
04905   }
04906   tobe = "<qt>"+tobe;
04907 
04908   emit ReadOnlyPart::setStatusBarText(tobe);
04909 }
04910 
04911 
04912 void KHTMLPart::setJSStatusBarText( const QString &text )
04913 {
04914   setStatusBarText(text, BarOverrideText);
04915 }
04916 
04917 void KHTMLPart::setJSDefaultStatusBarText( const QString &text )
04918 {
04919   setStatusBarText(text, BarDefaultText);
04920 }
04921 
04922 QString KHTMLPart::jsStatusBarText() const
04923 {
04924     return d->m_statusBarText[BarOverrideText];
04925 }
04926 
04927 QString KHTMLPart::jsDefaultStatusBarText() const
04928 {
04929    return d->m_statusBarText[BarDefaultText];
04930 }
04931 
04932 QString KHTMLPart::referrer() const
04933 {
04934    return d->m_referrer;
04935 }
04936 
04937 QString KHTMLPart::pageReferrer() const
04938 {
04939    KURL referrerURL = KURL( d->m_pageReferrer );
04940    if (referrerURL.isValid())
04941    {
04942       QString protocol = referrerURL.protocol();
04943 
04944       if ((protocol == "http") ||
04945          ((protocol == "https") && (m_url.protocol() == "https")))
04946       {
04947           referrerURL.setRef(QString::null);
04948           referrerURL.setUser(QString::null);
04949           referrerURL.setPass(QString::null);
04950           return referrerURL.url();
04951       }
04952    }
04953 
04954    return QString::null;
04955 }
04956 
04957 
04958 QString KHTMLPart::lastModified() const
04959 {
04960   if ( d->m_lastModified.isEmpty() && m_url.isLocalFile() ) {
04961     // Local file: set last-modified from the file's mtime.
04962     // Done on demand to save time when this isn't needed - but can lead
04963     // to slightly wrong results if updating the file on disk w/o reloading.
04964     QDateTime lastModif = QFileInfo( m_url.path() ).lastModified();
04965     d->m_lastModified = lastModif.toString( Qt::LocalDate );
04966   }
04967   //kdDebug(6050) << "KHTMLPart::lastModified: " << d->m_lastModified << endl;
04968   return d->m_lastModified;
04969 }
04970 
04971 void KHTMLPart::slotLoadImages()
04972 {
04973   if (d->m_doc )
04974     d->m_doc->docLoader()->setAutoloadImages( !d->m_doc->docLoader()->autoloadImages() );
04975 
04976   ConstFrameIt it = d->m_frames.begin();
04977   ConstFrameIt end = d->m_frames.end();
04978   for (; it != end; ++it )
04979     if ( !( *it ).m_part.isNull() && ( *it ).m_part->inherits( "KHTMLPart" ) ) {
04980       KParts::ReadOnlyPart* p = ( *it ).m_part;
04981       static_cast<KHTMLPart*>( p )->slotLoadImages();
04982     }
04983 }
04984 
04985 void KHTMLPart::reparseConfiguration()
04986 {
04987   KHTMLSettings *settings = KHTMLFactory::defaultHTMLSettings();
04988   settings->init();
04989 
04990   setAutoloadImages( settings->autoLoadImages() );
04991   if (d->m_doc)
04992      d->m_doc->docLoader()->setShowAnimations( settings->showAnimations() );
04993 
04994   d->m_bBackRightClick = settings->isBackRightClickEnabled();
04995   d->m_bJScriptEnabled = settings->isJavaScriptEnabled(m_url.host());
04996   setDebugScript( settings->isJavaScriptDebugEnabled() );
04997   d->m_bJavaEnabled = settings->isJavaEnabled(m_url.host());
04998   d->m_bPluginsEnabled = settings->isPluginsEnabled(m_url.host());
04999   d->m_metaRefreshEnabled = settings->isAutoDelayedActionsEnabled ();
05000 
05001   delete d->m_settings;
05002   d->m_settings = new KHTMLSettings(*KHTMLFactory::defaultHTMLSettings());
05003 
05004   QApplication::setOverrideCursor( waitCursor );
05005   khtml::CSSStyleSelector::reparseConfiguration();
05006   if(d->m_doc) d->m_doc->updateStyleSelector();
05007   QApplication::restoreOverrideCursor();
05008 }
05009 
05010 QStringList KHTMLPart::frameNames() const
05011 {
05012   QStringList res;
05013 
05014   ConstFrameIt it = d->m_frames.begin();
05015   ConstFrameIt end = d->m_frames.end();
05016   for (; it != end; ++it )
05017     if (!(*it).m_bPreloaded)
05018       res += (*it).m_name;
05019 
05020   return res;
05021 }
05022 
05023 QPtrList<KParts::ReadOnlyPart> KHTMLPart::frames() const
05024 {
05025   QPtrList<KParts::ReadOnlyPart> res;
05026 
05027   ConstFrameIt it = d->m_frames.begin();
05028   ConstFrameIt end = d->m_frames.end();
05029   for (; it != end; ++it )
05030     if (!(*it).m_bPreloaded)
05031       res.append( (*it).m_part );
05032 
05033   return res;
05034 }
05035 
05036 bool KHTMLPart::openURLInFrame( const KURL &url, const KParts::URLArgs &urlArgs )
05037 {
05038     kdDebug( 6050 ) << this << "KHTMLPart::openURLInFrame " << url << endl;
05039   FrameIt it = d->m_frames.find( urlArgs.frameName );
05040 
05041   if ( it == d->m_frames.end() )
05042     return false;
05043 
05044   // Inform someone that we are about to show something else.
05045   if ( !urlArgs.lockHistory() )
05046       emit d->m_extension->openURLNotify();
05047 
05048   requestObject( &(*it), url, urlArgs );
05049 
05050   return true;
05051 }
05052 
05053 void KHTMLPart::setDNDEnabled( bool b )
05054 {
05055   d->m_bDnd = b;
05056 }
05057 
05058 bool KHTMLPart::dndEnabled() const
05059 {
05060   return d->m_bDnd;
05061 }
05062 
05063 void KHTMLPart::customEvent( QCustomEvent *event )
05064 {
05065   if ( khtml::MousePressEvent::test( event ) )
05066   {
05067     khtmlMousePressEvent( static_cast<khtml::MousePressEvent *>( event ) );
05068     return;
05069   }
05070 
05071   if ( khtml::MouseDoubleClickEvent::test( event ) )
05072   {
05073     khtmlMouseDoubleClickEvent( static_cast<khtml::MouseDoubleClickEvent *>( event ) );
05074     return;
05075   }
05076 
05077   if ( khtml::MouseMoveEvent::test( event ) )
05078   {
05079     khtmlMouseMoveEvent( static_cast<khtml::MouseMoveEvent *>( event ) );
05080     return;
05081   }
05082 
05083   if ( khtml::MouseReleaseEvent::test( event ) )
05084   {
05085     khtmlMouseReleaseEvent( static_cast<khtml::MouseReleaseEvent *>( event ) );
05086     return;
05087   }
05088 
05089   if ( khtml::DrawContentsEvent::test( event ) )
05090   {
05091     khtmlDrawContentsEvent( static_cast<khtml::DrawContentsEvent *>( event ) );
05092     return;
05093   }
05094 
05095   KParts::ReadOnlyPart::customEvent( event );
05096 }
05097 
05098 void KHTMLPart::khtmlMousePressEvent( khtml::MousePressEvent *event )
05099 {
05100   DOM::DOMString url = event->url();
05101   QMouseEvent *_mouse = event->qmouseEvent();
05102   DOM::Node innerNode = event->innerNode();
05103   d->m_mousePressNode = innerNode;
05104 
05105    d->m_dragStartPos = _mouse->pos();
05106 
05107    if ( !event->url().isNull() ) {
05108      d->m_strSelectedURL = event->url().string();
05109      d->m_strSelectedURLTarget = event->target().string();
05110    }
05111    else
05112      d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
05113 
05114   if ( _mouse->button() == LeftButton ||
05115        _mouse->button() == MidButton )
05116   {
05117     d->m_bMousePressed = true;
05118 
05119 #ifndef KHTML_NO_SELECTION
05120     if ( _mouse->button() == LeftButton )
05121     {
05122       if ( (!d->m_strSelectedURL.isNull() && !isEditable())
05123             || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) )
05124       return;
05125       if ( !innerNode.isNull()  && innerNode.handle()->renderer()) {
05126           int offset = 0;
05127           DOM::NodeImpl* node = 0;
05128           khtml::RenderObject::SelPointState state;
05129           innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(),
05130                                                                event->absX()-innerNode.handle()->renderer()->xPos(),
05131                                                                event->absY()-innerNode.handle()->renderer()->yPos(), node, offset, state );
05132 #ifdef KHTML_NO_CARET
05133           d->m_selectionStart = node;
05134           d->m_startOffset = offset;
05135           //if ( node )
05136           //  kdDebug(6005) << "KHTMLPart::khtmlMousePressEvent selectionStart=" << d->m_selectionStart.handle()->renderer()
05137           //                << " offset=" << d->m_startOffset << endl;
05138           //else
05139           //  kdDebug(6005) << "KHTML::khtmlMousePressEvent selectionStart=(nil)" << endl;
05140           d->m_selectionEnd = d->m_selectionStart;
05141           d->m_endOffset = d->m_startOffset;
05142           d->m_doc->clearSelection();
05143 #else // KHTML_NO_CARET
05144       d->m_view->moveCaretTo(node, offset, (_mouse->state() & ShiftButton) == 0);
05145 #endif // KHTML_NO_CARET
05146       }
05147       else
05148       {
05149 #ifndef KHTML_NO_CARET
05150         // simply leave it. Is this a good idea?
05151 #else
05152         d->m_selectionStart = DOM::Node();
05153         d->m_selectionEnd = DOM::Node();
05154 #endif
05155       }
05156       emitSelectionChanged();
05157       startAutoScroll();
05158     }
05159 #else
05160     d->m_dragLastPos = _mouse->globalPos();
05161 #endif
05162   }
05163 
05164   if ( _mouse->button() == RightButton && parentPart() != 0 && d->m_bBackRightClick )
05165   {
05166     d->m_bRightMousePressed = true;
05167   } else if ( _mouse->button() == RightButton )
05168   {
05169     popupMenu( d->m_strSelectedURL );
05170     // might be deleted, don't touch "this"
05171   }
05172 }
05173 
05174 void KHTMLPart::khtmlMouseDoubleClickEvent( khtml::MouseDoubleClickEvent *event )
05175 {
05176   QMouseEvent *_mouse = event->qmouseEvent();
05177   if ( _mouse->button() == LeftButton )
05178   {
05179     d->m_bMousePressed = true;
05180     DOM::Node innerNode = event->innerNode();
05181     // Find selectionStart again, khtmlMouseReleaseEvent lost it
05182     if ( !innerNode.isNull() && innerNode.handle()->renderer()) {
05183       int offset = 0;
05184       DOM::NodeImpl* node = 0;
05185       khtml::RenderObject::SelPointState state;
05186       innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(),
05187                                                            event->absX()-innerNode.handle()->renderer()->xPos(),
05188                                                            event->absY()-innerNode.handle()->renderer()->yPos(), node, offset, state);
05189 
05190       //kdDebug() << k_funcinfo << "checkSelectionPoint returned node=" << node << " offset=" << offset << endl;
05191 
05192       if ( node && node->renderer() )
05193       {
05194         // Extend selection to a complete word (double-click) or paragraph (triple-click)
05195         bool selectParagraph = (event->clickCount() == 3);
05196 
05197         // Extend to the left
05198         extendSelection( node, offset, d->m_selectionStart, d->m_startOffset, false, selectParagraph );
05199         // Extend to the right
05200         extendSelection( node, offset, d->m_selectionEnd, d->m_endOffset, true, selectParagraph );
05201 
05202         d->m_endOffset++; // the last char must be in
05203         //kdDebug() << d->m_selectionStart.handle() << " " << d->m_startOffset << "  -  " <<
05204         //  d->m_selectionEnd.handle() << " " << d->m_endOffset << endl;
05205 
05206         d->m_startBeforeEnd = true;
05207         emitSelectionChanged();
05208         d->m_doc
05209           ->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
05210                          d->m_selectionEnd.handle(),d->m_endOffset);
05211 #ifndef KHTML_NO_CARET
05212         bool v = d->m_view->placeCaret();
05213         emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
05214 #endif
05215       }
05216     }
05217   }
05218 }
05219 
05220 void KHTMLPart::extendSelection( DOM::NodeImpl* node, long offset, DOM::Node& selectionNode, long& selectionOffset, bool right, bool selectParagraph )
05221 {
05222   khtml::RenderObject* obj = node->renderer();
05223   QString str;
05224   int len = 0;
05225   if ( obj->isText() ) { // can be false e.g. when double-clicking on a disabled submit button
05226     str = static_cast<khtml::RenderText *>(obj)->data().string();
05227     len = str.length();
05228   }
05229   //kdDebug() << "extendSelection right=" << right << " offset=" << offset << " len=" << len << " Starting at obj=" << obj << endl;
05230   QChar ch;
05231   do {
05232     // Last char was ok, point to it
05233     if ( node ) {
05234       selectionNode = node;
05235       selectionOffset = offset;
05236     }
05237 
05238     // Get another char
05239     while ( obj && ( (right && offset >= len-1) || (!right && offset <= 0) ) )
05240     {
05241       obj = right ? obj->objectBelow() : obj->objectAbove();
05242       //kdDebug() << "obj=" << obj << endl;
05243       if ( obj ) {
05244         //kdDebug() << "isText=" << obj->isText() << endl;
05245         str = QString::null;
05246         if ( obj->isText() )
05247           str = static_cast<khtml::RenderText *>(obj)->data().string();
05248         else if ( obj->isBR() )
05249           str = '\n';
05250         else if ( !obj->isInline() ) {
05251           obj = 0L; // parag limit -> done
05252           break;
05253         }
05254         len = str.length();
05255         //kdDebug() << "str=" << str << " length=" << len << endl;
05256         // set offset - note that the first thing will be a ++ or -- on it.
05257         if ( right )
05258           offset = -1;
05259         else
05260           offset = len;
05261       }
05262     }
05263     if ( !obj ) // end of parag or document
05264       break;
05265     node = obj->element();
05266     if ( right )
05267     {
05268       Q_ASSERT( offset < len-1 );
05269       offset++;
05270     }
05271     else
05272     {
05273       Q_ASSERT( offset > 0 );
05274       offset--;
05275     }
05276 
05277     // Test that char
05278     ch = str[ offset ];
05279     //kdDebug() << " offset=" << offset << " ch=" << QString(ch) << endl;
05280   } while ( selectParagraph || (!ch.isSpace() && !ch.isPunct()) );
05281 }
05282 
05283 #ifndef KHTML_NO_SELECTION
05284 void KHTMLPart::extendSelectionTo(int x, int y, int absX, int absY, const DOM::Node &innerNode)
05285 {
05286       int offset;
05287       //kdDebug(6000) << "KHTMLPart::khtmlMouseMoveEvent x=" << event->x() << " y=" << event->y() << endl;
05288       DOM::NodeImpl* node=0;
05289       khtml::RenderObject::SelPointState state;
05290       innerNode.handle()->renderer()->checkSelectionPoint( x, y,
05291                                                            absX-innerNode.handle()->renderer()->xPos(),
05292                                                            absY-innerNode.handle()->renderer()->yPos(), node, offset, state);
05293       if (!node) return;
05294 
05295       d->m_selectionEnd = node;
05296       d->m_endOffset = offset;
05297       //kdDebug( 6000 ) << "setting end of selection to " << d->m_selectionEnd.handle() << "/" << d->m_endOffset << endl;
05298 
05299       // we have to get to know if end is before start or not...
05300 #if 0
05301       DOM::Node n = d->m_selectionStart;
05302       d->m_startBeforeEnd = false;
05303       while(!n.isNull()) {
05304         if(n == d->m_selectionEnd) {
05305           d->m_startBeforeEnd = true;
05306           break;
05307         }
05308         DOM::Node next = n.firstChild();
05309         if(next.isNull()) next = n.nextSibling();
05310         while( next.isNull() && !n.parentNode().isNull() ) {
05311           n = n.parentNode();
05312           next = n.nextSibling();
05313         }
05314         n = next;
05315         //d->m_view->viewport()->repaint(false);
05316       }
05317 #else
05318       // shouldn't be null but it can happen with dynamic updating of nodes
05319       if (d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() ||
05320           !d->m_selectionStart.handle()->renderer() ||
05321           !d->m_selectionEnd.handle()->renderer()) return;
05322       d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
05323                 d->m_selectionStart.handle(), d->m_startOffset,
05324             d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
05325 #endif
05326 
05327       if ( !d->m_selectionStart.isNull() && !d->m_selectionEnd.isNull() )
05328       {
05329         if (d->m_selectionEnd == d->m_selectionStart && d->m_endOffset < d->m_startOffset)
05330           d->m_doc
05331             ->setSelection(d->m_selectionStart.handle(),d->m_endOffset,
05332                            d->m_selectionEnd.handle(),d->m_startOffset);
05333         else if (d->m_startBeforeEnd)
05334           d->m_doc
05335             ->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
05336                            d->m_selectionEnd.handle(),d->m_endOffset);
05337         else
05338           d->m_doc
05339             ->setSelection(d->m_selectionEnd.handle(),d->m_endOffset,
05340                            d->m_selectionStart.handle(),d->m_startOffset);
05341       }
05342 #ifndef KHTML_NO_CARET
05343       d->m_view->placeCaret();
05344 #endif
05345 }
05346 
05347 bool KHTMLPart::isExtendingSelection() const
05348 {
05349   // This is it, the whole detection. khtmlMousePressEvent only sets this
05350   // on LMB or MMB, but never on RMB. As text selection doesn't work for MMB,
05351   // it's sufficient to only rely on this flag to detect selection extension.
05352   return d->m_bMousePressed;
05353 }
05354 #endif // KHTML_NO_SELECTION
05355 
05356 void KHTMLPart::khtmlMouseMoveEvent( khtml::MouseMoveEvent *event )
05357 {
05358   QMouseEvent *_mouse = event->qmouseEvent();
05359 
05360   if( d->m_bRightMousePressed && parentPart() != 0 && d->m_bBackRightClick )
05361   {
05362     popupMenu( d->m_strSelectedURL );
05363     d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
05364     d->m_bRightMousePressed = false;
05365   }
05366 #ifndef QT_NO_DRAGANDDROP
05367   if( d->m_bDnd && d->m_bMousePressed &&
05368       ( (!d->m_strSelectedURL.isEmpty() && !isEditable())
05369         || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) ) ) {
05370     if ( ( d->m_dragStartPos - _mouse->pos() ).manhattanLength() <= KGlobalSettings::dndEventDelay() )
05371       return;
05372 
05373     QPixmap pix;
05374     HTMLImageElementImpl *img = 0L;
05375     QDragObject *drag = 0;
05376     KURL u;
05377     if ( d->m_mousePressNode.handle() && d->m_mousePressNode.handle()->id() == ID_IMG )
05378     {
05379       // Normal image
05380       img = static_cast<HTMLImageElementImpl *>(d->m_mousePressNode.handle());
05381       u = KURL( completeURL( khtml::parseURL(img->getAttribute(ATTR_SRC)).string() ) );
05382       pix = KMimeType::mimeType("image/png")->pixmap(KIcon::Desktop);
05383     }
05384     else if ( event->innerNode().handle() && event->innerNode().handle()->id() == ID_IMG )
05385     {
05386       // Image inside a link?
05387       img = static_cast<HTMLImageElementImpl *>(event->innerNode().handle());
05388       u = completeURL( d->m_strSelectedURL );
05389       pix = KMimeType::mimeType("image/png")->pixmap(KIcon::Desktop);
05390     }
05391     else
05392     {
05393       // Text link
05394       u = completeURL( d->m_strSelectedURL );
05395       pix = KMimeType::pixmapForURL(u, 0, KIcon::Desktop, KIcon::SizeMedium);
05396     }
05397 
05398     KURLDrag* urlDrag = new KURLDrag( u, 0 );
05399     if ( !d->m_referrer.isEmpty() )
05400       urlDrag->metaData()["referrer"] = d->m_referrer;
05401 
05402     if( img ) {
05403       KMultipleDrag *mdrag = new KMultipleDrag( d->m_view->viewport() );
05404       mdrag->addDragObject( new QImageDrag( img->currentImage(), 0L ) );
05405       mdrag->addDragObject( urlDrag );
05406       drag = mdrag;
05407     }
05408     else
05409       drag = urlDrag;
05410 
05411     if ( !pix.isNull() )
05412       drag->setPixmap( pix );
05413 
05414     stopAutoScroll();
05415     if(drag)
05416         drag->drag();
05417 
05418     // when we finish our drag, we need to undo our mouse press
05419     d->m_bMousePressed = false;
05420     d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
05421     return;
05422   }
05423 #endif
05424 
05425   DOM::DOMString url = event->url();
05426   DOM::DOMString target = event->target();
05427   DOM::Node innerNode = event->innerNode();
05428 
05429   // Not clicked -> mouse over stuff
05430   if ( !d->m_bMousePressed )
05431   {
05432     // The mouse is over something
05433     if ( url.length() )
05434     {
05435       bool shiftPressed = ( _mouse->state() & ShiftButton );
05436 
05437       // Image map
05438       if ( !innerNode.isNull() && innerNode.elementId() == ID_IMG )
05439       {
05440         HTMLImageElementImpl *i = static_cast<HTMLImageElementImpl *>(innerNode.handle());
05441         if ( i && i->isServerMap() )
05442         {
05443           khtml::RenderObject *r = i->renderer();
05444           if(r)
05445           {
05446             int absx, absy, vx, vy;
05447             r->absolutePosition(absx, absy);
05448             view()->contentsToViewport( absx, absy, vx, vy );
05449 
05450             int x(_mouse->x() - vx), y(_mouse->y() - vy);
05451 
05452             d->m_overURL = url.string() + QString("?%1,%2").arg(x).arg(y);
05453             d->m_overURLTarget = target.string();
05454             overURL( d->m_overURL, target.string(), shiftPressed );
05455             return;
05456           }
05457         }
05458       }
05459 
05460       // normal link
05461       if ( d->m_overURL.isEmpty() || d->m_overURL != url || d->m_overURLTarget != target )
05462       {
05463         d->m_overURL = url.string();
05464         d->m_overURLTarget = target.string();
05465         overURL( d->m_overURL, target.string(), shiftPressed );
05466       }
05467     }
05468     else  // Not over a link...
05469     {
05470       if( !d->m_overURL.isEmpty() ) // and we were over a link  -> reset to "default statusbar text"
05471       {
05472         d->m_overURL = d->m_overURLTarget = QString::null;
05473         emit onURL( QString::null );
05474         // revert to default statusbar text
05475         setStatusBarText(QString::null, BarHoverText);
05476         emit d->m_extension->mouseOverInfo(0);
05477      }
05478     }
05479   }
05480   else {
05481 #ifndef KHTML_NO_SELECTION
05482     // selection stuff
05483     if( d->m_bMousePressed && innerNode.handle() && innerNode.handle()->renderer() &&
05484         ( (_mouse->state() & LeftButton) != 0 )) {
05485       extendSelectionTo(event->x(), event->y(),
05486                         event->absX(), event->absY(), innerNode);
05487 #else
05488       if ( d->m_doc && d->m_view ) {
05489         QPoint diff( _mouse->globalPos() - d->m_dragLastPos );
05490 
05491         if ( abs( diff.x() ) > 64 || abs( diff.y() ) > 64 ) {
05492           d->m_view->scrollBy( -diff.x(), -diff.y() );
05493           d->m_dragLastPos = _mouse->globalPos();
05494         }
05495 #endif
05496     }
05497   }
05498 
05499 }
05500 
05501 void KHTMLPart::khtmlMouseReleaseEvent( khtml::MouseReleaseEvent *event )
05502 {
05503   DOM::Node innerNode = event->innerNode();
05504   d->m_mousePressNode = DOM::Node();
05505 
05506   if ( d->m_bMousePressed ) {
05507     setStatusBarText(QString::null, BarHoverText);
05508     stopAutoScroll();
05509   }
05510 
05511   // Used to prevent mouseMoveEvent from initiating a drag before
05512   // the mouse is pressed again.
05513   d->m_bMousePressed = false;
05514 
05515   QMouseEvent *_mouse = event->qmouseEvent();
05516   if ( _mouse->button() == RightButton && parentPart() != 0 && d->m_bBackRightClick )
05517   {
05518     d->m_bRightMousePressed = false;
05519     KParts::BrowserInterface *tmp_iface = d->m_extension->browserInterface();
05520     if( tmp_iface ) {
05521       tmp_iface->callMethod( "goHistory(int)", -1 );
05522     }
05523   }
05524 #ifndef QT_NO_CLIPBOARD
05525   if ((d->m_guiProfile == BrowserViewGUI) && (_mouse->button() == MidButton) && (event->url().isNull())) {
05526     KHTMLPart *p = this;
05527     while (p->parentPart()) p = p->parentPart();
05528     p->d->m_extension->pasteRequest();
05529   }
05530 #endif
05531 
05532 #ifndef KHTML_NO_SELECTION
05533   // delete selection in case start and end position are at the same point
05534   if(d->m_selectionStart == d->m_selectionEnd && d->m_startOffset == d->m_endOffset) {
05535 #ifndef KHTML_NO_CARET
05536     d->m_extendAtEnd = true;
05537 #else
05538     d->m_selectionStart = 0;
05539     d->m_selectionEnd = 0;
05540     d->m_startOffset = 0;
05541     d->m_endOffset = 0;
05542 #endif
05543     emitSelectionChanged();
05544   } else /*if ((_mouse->state() & ShiftButton) == 0)*/ {
05545     // we have to get to know if end is before start or not...
05546     DOM::Node n = d->m_selectionStart;
05547     d->m_startBeforeEnd = false;
05548     d->m_extendAtEnd = true;
05549     if( d->m_selectionStart == d->m_selectionEnd ) {
05550       if( d->m_startOffset < d->m_endOffset )
05551         d->m_startBeforeEnd = true;
05552     } else {
05553 #if 0
05554       while(!n.isNull()) {
05555         if(n == d->m_selectionEnd) {
05556           d->m_startBeforeEnd = true;
05557           break;
05558         }
05559         DOM::Node next = n.firstChild();
05560         if(next.isNull()) next = n.nextSibling();
05561         while( next.isNull() && !n.parentNode().isNull() ) {
05562           n = n.parentNode();
05563           next = n.nextSibling();
05564         }
05565         n = next;
05566       }
05567 #else
05568       // shouldn't be null but it can happen with dynamic updating of nodes
05569       if (d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() ||
05570           !d->m_selectionStart.handle()->renderer() ||
05571           !d->m_selectionEnd.handle()->renderer()) return;
05572       d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
05573                 d->m_selectionStart.handle(), d->m_startOffset,
05574             d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
05575 #endif
05576     }
05577     if(!d->m_startBeforeEnd)
05578     {
05579       DOM::Node tmpNode = d->m_selectionStart;
05580       int tmpOffset = d->m_startOffset;
05581       d->m_selectionStart = d->m_selectionEnd;
05582       d->m_startOffset = d->m_endOffset;
05583       d->m_selectionEnd = tmpNode;
05584       d->m_endOffset = tmpOffset;
05585       d->m_startBeforeEnd = true;
05586       d->m_extendAtEnd = false;
05587     }
05588 #ifndef KHTML_NO_CARET
05589     bool v = d->m_view->placeCaret();
05590     emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
05591 #endif
05592     // get selected text and paste to the clipboard
05593 #ifndef QT_NO_CLIPBOARD
05594     QString text = selectedText();
05595     text.replace(QChar(0xa0), ' ');
05596     disconnect( kapp->clipboard(), SIGNAL( selectionChanged()), this, SLOT( slotClearSelection()));
05597     kapp->clipboard()->setText(text,QClipboard::Selection);
05598     connect( kapp->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection()));
05599 #endif
05600     //kdDebug( 6000 ) << "selectedText = " << text << endl;
05601     emitSelectionChanged();
05602   }
05603 #endif
05604 
05605 }
05606 
05607 void KHTMLPart::khtmlDrawContentsEvent( khtml::DrawContentsEvent * )
05608 {
05609 }
05610 
05611 void KHTMLPart::guiActivateEvent( KParts::GUIActivateEvent *event )
05612 {
05613   if ( event->activated() )
05614   {
05615     emitSelectionChanged();
05616     emit d->m_extension->enableAction( "print", d->m_doc != 0 );
05617 
05618     if ( !d->m_settings->autoLoadImages() && d->m_paLoadImages )
05619     {
05620         QPtrList<KAction> lst;
05621         lst.append( d->m_paLoadImages );
05622         plugActionList( "loadImages", lst );
05623     }
05624   }
05625 }
05626 
05627 void KHTMLPart::slotPrintFrame()
05628 {
05629   if ( d->m_frames.count() == 0 )
05630     return;
05631 
05632   KParts::ReadOnlyPart *frame = currentFrame();
05633   if (!frame)
05634     return;
05635 
05636   KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject( frame );
05637 
05638   if ( !ext )
05639     return;
05640 
05641   QMetaObject *mo = ext->metaObject();
05642 
05643   int idx = mo->findSlot( "print()", true );
05644   if ( idx >= 0 ) {
05645     QUObject o[ 1 ];
05646     ext->qt_invoke( idx, o );
05647   }
05648 }
05649 
05650 void KHTMLPart::slotSelectAll()
05651 {
05652   KParts::ReadOnlyPart *part = currentFrame();
05653   if (part && part->inherits("KHTMLPart"))
05654     static_cast<KHTMLPart *>(part)->selectAll();
05655 }
05656 
05657 void KHTMLPart::startAutoScroll()
05658 {
05659    connect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
05660    d->m_scrollTimer.start(100, false);
05661 }
05662 
05663 void KHTMLPart::stopAutoScroll()
05664 {
05665    disconnect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
05666    if (d->m_scrollTimer.isActive())
05667        d->m_scrollTimer.stop();
05668 }
05669 
05670 
05671 void KHTMLPart::slotAutoScroll()
05672 {
05673     if (d->m_view)
05674       d->m_view->doAutoScroll();
05675     else
05676       stopAutoScroll(); // Safety
05677 }
05678 
05679 void KHTMLPart::selectAll()
05680 {
05681   if (!d->m_doc) return;
05682 
05683   NodeImpl *first;
05684   if (d->m_doc->isHTMLDocument())
05685     first = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
05686   else
05687     first = d->m_doc;
05688   NodeImpl *next;
05689 
05690   // Look for first text/cdata node that has a renderer,
05691   // or first childless replaced element
05692   while ( first && !(first->renderer()
05693     && ((first->nodeType() == Node::TEXT_NODE || first->nodeType() == Node::CDATA_SECTION_NODE)
05694         || (first->renderer()->isReplaced() && !first->renderer()->firstChild()))))
05695   {
05696     next = first->firstChild();
05697     if ( !next ) next = first->nextSibling();
05698     while( first && !next )
05699     {
05700       first = first->parentNode();
05701       if ( first )
05702         next = first->nextSibling();
05703     }
05704     first = next;
05705   }
05706 
05707   NodeImpl *last;
05708   if (d->m_doc->isHTMLDocument())
05709     last = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
05710   else
05711     last = d->m_doc;
05712   // Look for last text/cdata node that has a renderer,
05713   // or last childless replaced element
05714   // ### Instead of changing this loop, use findLastSelectableNode
05715   // in render_table.cpp (LS)
05716   while ( last && !(last->renderer()
05717     && ((last->nodeType() == Node::TEXT_NODE || last->nodeType() == Node::CDATA_SECTION_NODE)
05718         || (last->renderer()->isReplaced() && !last->renderer()->lastChild()))))
05719   {
05720     next = last->lastChild();
05721     if ( !next ) next = last->previousSibling();
05722     while ( last && !next )
05723     {
05724       last = last->parentNode();
05725       if ( last )
05726         next = last->previousSibling();
05727     }
05728     last = next;
05729   }
05730 
05731   if ( !first || !last )
05732     return;
05733   Q_ASSERT(first->renderer());
05734   Q_ASSERT(last->renderer());
05735   d->m_selectionStart = first;
05736   d->m_startOffset = 0;
05737   d->m_selectionEnd = last;
05738   d->m_endOffset = last->nodeValue().length();
05739   d->m_startBeforeEnd = true;
05740 
05741   d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
05742                           d->m_selectionEnd.handle(), d->m_endOffset );
05743 
05744   emitSelectionChanged();
05745 }
05746 
05747 bool KHTMLPart::checkLinkSecurity(const KURL &linkURL,const QString &message, const QString &button)
05748 {
05749   // Security check on the link.
05750   // KURL u( url ); Wrong!! Relative URL could be mis-interpreted!!! (DA)
05751   QString linkProto = linkURL.protocol().lower();
05752   QString proto = m_url.protocol().lower();
05753 
05754   if ( !linkProto.isEmpty() && !proto.isEmpty() &&
05755        ( linkProto == "cgi" || linkProto == "file" ) &&
05756        proto != "file" && proto != "cgi" && proto != "man" && proto != "about")
05757   {
05758       khtml::Tokenizer *tokenizer = d->m_doc->tokenizer();
05759     if (tokenizer)
05760       tokenizer->setOnHold(true);
05761 
05762     int response = KMessageBox::Cancel;
05763     if (!message.isEmpty())
05764     {
05765         response = KMessageBox::warningContinueCancel( 0,
05766                                message.arg(linkURL.url()),
05767                                i18n( "Security Warning" ),
05768                                button);
05769     }
05770     else
05771     {
05772         KMessageBox::error( 0,
05773                 i18n( "<qt>This untrusted page contains a link<BR><B>%1</B><BR>to your local file system.").arg(linkURL.url()),
05774                 i18n( "Security Alert" ));
05775     }
05776 
05777     if (tokenizer)
05778        tokenizer->setOnHold(false);
05779     return (response==KMessageBox::Continue);
05780   }
05781   return true;
05782 }
05783 
05784 void KHTMLPart::slotPartRemoved( KParts::Part *part )
05785 {
05786 //    kdDebug(6050) << "KHTMLPart::slotPartRemoved " << part << endl;
05787     if ( part == d->m_activeFrame )
05788     {
05789         d->m_activeFrame = 0L;
05790         if ( !part->inherits( "KHTMLPart" ) )
05791         {
05792             if (factory()) {
05793                 factory()->removeClient( part );
05794             }
05795             if (childClients()->containsRef(part)) {
05796                 removeChildClient( part );
05797             }
05798         }
05799     }
05800 }
05801 
05802 void KHTMLPart::slotActiveFrameChanged( KParts::Part *part )
05803 {
05804 //    kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged part=" << part << endl;
05805     if ( part == this )
05806     {
05807         kdError(6050) << "strange error! we activated ourselves" << endl;
05808         assert( false );
05809         return;
05810     }
05811 //    kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged d->m_activeFrame=" << d->m_activeFrame << endl;
05812     if ( d->m_activeFrame && d->m_activeFrame->widget() && d->m_activeFrame->widget()->inherits( "QFrame" ) )
05813     {
05814         QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() );
05815         if (frame->frameStyle() != QFrame::NoFrame)
05816         {
05817            frame->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken);
05818            frame->repaint();
05819         }
05820     }
05821 
05822     if( d->m_activeFrame && !d->m_activeFrame->inherits( "KHTMLPart" ) )
05823     {
05824         if (factory()) {
05825             factory()->removeClient( d->m_activeFrame );
05826         }
05827         removeChildClient( d->m_activeFrame );
05828     }
05829     if( part && !part->inherits( "KHTMLPart" ) )
05830     {
05831         if (factory()) {
05832             factory()->addClient( part );
05833         }
05834         insertChildClient( part );
05835     }
05836 
05837 
05838     d->m_activeFrame = part;
05839 
05840     if ( d->m_activeFrame && d->m_activeFrame->widget()->inherits( "QFrame" ) )
05841     {
05842         QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() );
05843         if (frame->frameStyle() != QFrame::NoFrame)
05844         {
05845            frame->setFrameStyle( QFrame::StyledPanel | QFrame::Plain);
05846            frame->repaint();
05847         }
05848         kdDebug(6050) << "new active frame " << d->m_activeFrame << endl;
05849     }
05850 
05851     updateActions();
05852 
05853     // (note: childObject returns 0 if the argument is 0)
05854     d->m_extension->setExtensionProxy( KParts::BrowserExtension::childObject( d->m_activeFrame ) );
05855 }
05856 
05857 void KHTMLPart::setActiveNode(const DOM::Node &node)
05858 {
05859     if (!d->m_doc || !d->m_view)
05860         return;
05861 
05862     // Set the document's active node
05863     d->m_doc->setFocusNode(node.handle());
05864 
05865     // Scroll the view if necessary to ensure that the new focus node is visible
05866     QRect rect  = node.handle()->getRect();
05867     d->m_view->ensureVisible(rect.right(), rect.bottom());
05868     d->m_view->ensureVisible(rect.left(), rect.top());
05869 }
05870 
05871 DOM::Node KHTMLPart::activeNode() const
05872 {
05873     return DOM::Node(d->m_doc?d->m_doc->focusNode():0);
05874 }
05875 
05876 DOM::EventListener *KHTMLPart::createHTMLEventListener( QString code, QString name )
05877 {
05878   KJSProxy *proxy = jScript();
05879 
05880   if (!proxy)
05881     return 0;
05882 
05883   return proxy->createHTMLEventHandler( m_url.url(), name, code );
05884 }
05885 
05886 KHTMLPart *KHTMLPart::opener()
05887 {
05888     return d->m_opener;
05889 }
05890 
05891 void KHTMLPart::setOpener(KHTMLPart *_opener)
05892 {
05893     d->m_opener = _opener;
05894 }
05895 
05896 bool KHTMLPart::openedByJS()
05897 {
05898     return d->m_openedByJS;
05899 }
05900 
05901 void KHTMLPart::setOpenedByJS(bool _openedByJS)
05902 {
05903     d->m_openedByJS = _openedByJS;
05904 }
05905 
05906 void KHTMLPart::preloadStyleSheet(const QString &url, const QString &stylesheet)
05907 {
05908     khtml::Cache::preloadStyleSheet(url, stylesheet);
05909 }
05910 
05911 void KHTMLPart::preloadScript(const QString &url, const QString &script)
05912 {
05913     khtml::Cache::preloadScript(url, script);
05914 }
05915 
05916 QCString KHTMLPart::dcopObjectId() const
05917 {
05918   QCString id;
05919   id.sprintf("html-widget%d", d->m_dcop_counter);
05920   return id;
05921 }
05922 
05923 long KHTMLPart::cacheId() const
05924 {
05925   return d->m_cacheId;
05926 }
05927 
05928 bool KHTMLPart::restored() const
05929 {
05930   return d->m_restored;
05931 }
05932 
05933 bool KHTMLPart::pluginPageQuestionAsked(const QString& mimetype) const
05934 {
05935   // parentPart() should be const!
05936   KHTMLPart* parent = const_cast<KHTMLPart *>(this)->parentPart();
05937   if ( parent )
05938     return parent->pluginPageQuestionAsked(mimetype);
05939 
05940   return d->m_pluginPageQuestionAsked.contains(mimetype);
05941 }
05942 
05943 void KHTMLPart::setPluginPageQuestionAsked(const QString& mimetype)
05944 {
05945   if ( parentPart() )
05946     parentPart()->setPluginPageQuestionAsked(mimetype);
05947 
05948   d->m_pluginPageQuestionAsked.append(mimetype);
05949 }
05950 
05951 void KHTMLPart::slotAutomaticDetectionLanguage( int _id )
05952 {
05953   d->m_automaticDetection->setItemChecked( _id, true );
05954 
05955   switch ( _id ) {
05956     case 0 :
05957       d->m_autoDetectLanguage = khtml::Decoder::SemiautomaticDetection;
05958       break;
05959     case 1 :
05960       d->m_autoDetectLanguage = khtml::Decoder::Arabic;
05961       break;
05962     case 2 :
05963       d->m_autoDetectLanguage = khtml::Decoder::Baltic;
05964       break;
05965     case 3 :
05966       d->m_autoDetectLanguage = khtml::Decoder::CentralEuropean;
05967       break;
05968     case 4 :
05969       d->m_autoDetectLanguage = khtml::Decoder::Chinese;
05970       break;
05971     case 5 :
05972       d->m_autoDetectLanguage = khtml::Decoder::Greek;
05973       break;
05974     case 6 :
05975       d->m_autoDetectLanguage = khtml::Decoder::Hebrew;
05976       break;
05977     case 7 :
05978       d->m_autoDetectLanguage = khtml::Decoder::Japanese;
05979       break;
05980     case 8 :
05981       d->m_autoDetectLanguage = khtml::Decoder::Korean;
05982       break;
05983     case 9 :
05984       d->m_autoDetectLanguage = khtml::Decoder::Russian;
05985       break;
05986     case 10 :
05987       d->m_autoDetectLanguage = khtml::Decoder::Thai;
05988       break;
05989     case 11 :
05990       d->m_autoDetectLanguage = khtml::Decoder::Turkish;
05991       break;
05992     case 12 :
05993       d->m_autoDetectLanguage = khtml::Decoder::Ukrainian;
05994       break;
05995     case 13 :
05996       d->m_autoDetectLanguage = khtml::Decoder::Unicode;
05997       break;
05998     case 14 :
05999       d->m_autoDetectLanguage = khtml::Decoder::WesternEuropean;
06000       break;
06001     default :
06002       d->m_autoDetectLanguage = khtml::Decoder::SemiautomaticDetection;
06003       break;
06004   }
06005 
06006   for ( int i = 0; i <= 14; ++i ) {
06007     if ( i != _id )
06008       d->m_automaticDetection->setItemChecked( i, false );
06009   }
06010 
06011   d->m_paSetEncoding->popupMenu()->setItemChecked( 0, true );
06012 
06013   setEncoding( QString::null, false );
06014 
06015   if( d->m_manualDetection )
06016     d->m_manualDetection->setCurrentItem( -1 );
06017   d->m_paSetEncoding->popupMenu()->setItemChecked( d->m_paSetEncoding->popupMenu()->idAt( 2 ), false );
06018 }
06019 
06020 khtml::Decoder *KHTMLPart::createDecoder()
06021 {
06022   khtml::Decoder *dec = new khtml::Decoder();
06023   if( !d->m_encoding.isNull() )
06024     dec->setEncoding( d->m_encoding.latin1(), true );
06025   else
06026     dec->setEncoding( settings()->encoding().latin1(), d->m_haveEncoding );
06027 
06028   dec->setAutoDetectLanguage( d->m_autoDetectLanguage );
06029   return dec;
06030 }
06031 
06032 void KHTMLPart::emitCaretPositionChanged(const DOM::Node &node, long offset) {
06033   emit caretPositionChanged(node, offset);
06034 }
06035 
06036 KWallet::Wallet* KHTMLPart::wallet()
06037 {
06038   // ### close wallet after a certain timeout period automatically
06039   //      No - KWallet already does this based on user preferences. (GS)
06040   // ### close wallet after screensaver was enabled
06041   //      No - KWalletD should do this, if anything. (GS)
06042 
06043   KHTMLPart* p;
06044 
06045   for (p = parentPart(); p && p->parentPart(); p = p->parentPart())
06046     ;
06047 
06048   if (p)
06049     return p->wallet();
06050 
06051   if (!d->m_wallet && !d->m_bWalletOpened) {
06052     d->m_wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0);
06053     d->m_bWalletOpened = true;
06054     if (d->m_wallet) {
06055       connect(d->m_wallet, SIGNAL(walletClosed()), SLOT(slotWalletClosed()));
06056       d->m_statusBarWalletLabel = new KURLLabel(d->m_statusBarExtension->statusBar());
06057       d->m_statusBarWalletLabel->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small));
06058       d->m_statusBarWalletLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
06059       d->m_statusBarWalletLabel->setUseCursor(false);
06060       d->m_statusBarExtension->addStatusBarItem(d->m_statusBarWalletLabel, 0, false);
06061       QToolTip::add(d->m_statusBarWalletLabel, i18n("The wallet '%1' is open and being used for form data and passwords.").arg(KWallet::Wallet::NetworkWallet()));
06062       d->m_statusBarWalletLabel->setPixmap(SmallIcon("wallet_open", instance()));
06063       connect(d->m_statusBarWalletLabel, SIGNAL(leftClickedURL()), SLOT(launchWalletManager()));
06064       connect(d->m_statusBarWalletLabel, SIGNAL(rightClickedURL()), SLOT(walletMenu()));
06065     } else if (d->m_statusBarWalletLabel) {
06066       d->m_statusBarExtension->removeStatusBarItem(d->m_statusBarWalletLabel);
06067       delete d->m_statusBarWalletLabel;
06068       d->m_statusBarWalletLabel = 0L;
06069     }
06070   }
06071   return d->m_wallet;
06072 }
06073 
06074 void KHTMLPart::slotWalletClosed()
06075 {
06076   if (d->m_wallet) {
06077     d->m_wallet->deleteLater();
06078     d->m_wallet = 0L;
06079   }
06080   d->m_bWalletOpened = false;
06081   if (d->m_statusBarWalletLabel) {
06082     d->m_statusBarExtension->removeStatusBarItem(d->m_statusBarWalletLabel);
06083     delete d->m_statusBarWalletLabel;
06084     d->m_statusBarWalletLabel = 0L;
06085   }
06086 }
06087 
06088 void KHTMLPart::launchWalletManager()
06089 {
06090   if (!DCOPClient::mainClient()->isApplicationRegistered("kwalletmanager")) {
06091     KApplication::startServiceByDesktopName("kwalletmanager_show");
06092   } else {
06093     DCOPRef r("kwalletmanager", "kwalletmanager-mainwindow#1");
06094     r.send("show");
06095     r.send("raise");
06096   }
06097 }
06098 
06099 void KHTMLPart::walletMenu()
06100 {
06101   KPopupMenu *m = new KPopupMenu(0L);
06102   m->insertItem(i18n("&Close Wallet"), this, SLOT(slotWalletClosed()));
06103   m->popup(QCursor::pos());
06104 }
06105 
06106 void KHTMLPart::slotToggleCaretMode()
06107 {
06108   setCaretMode(d->m_paToggleCaretMode->isChecked());
06109 }
06110 
06111 void KHTMLPart::setFormNotification(KHTMLPart::FormNotification fn) {
06112   d->m_formNotification = fn;
06113 }
06114 
06115 KHTMLPart::FormNotification KHTMLPart::formNotification() const {
06116   return d->m_formNotification;
06117 }
06118 
06119 KURL KHTMLPart::toplevelURL()
06120 {
06121   KHTMLPart* part = this;
06122   while (part->parentPart())
06123     part = part->parentPart();
06124 
06125   if (!part)
06126     return KURL();
06127 
06128   return part->url();
06129 }
06130 
06131 void KHTMLPart::setDebugScript( bool enable )
06132 {
06133   unplugActionList( "debugScriptList" );
06134   if ( enable ) {
06135     if (!d->m_paDebugScript) {
06136       d->m_paDebugScript = new KAction( i18n( "JavaScript &Debugger" ), 0, this, SLOT( slotDebugScript() ), actionCollection(), "debugScript" );
06137     }
06138     d->m_paDebugScript->setEnabled( d->m_jscript );
06139     QPtrList<KAction> lst;
06140     lst.append( d->m_paDebugScript );
06141     plugActionList( "debugScriptList", lst );
06142   }
06143   d->m_bJScriptDebugEnabled = enable;
06144 }
06145 
06146 using namespace KParts;
06147 #include "khtml_part.moc"
KDE Logo
This file is part of the documentation for khtml Library Version 3.2.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Mar 4 22:45:42 2004 by doxygen 1.3.6-20040222 written by Dimitri van Heesch, © 1997-2003