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