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