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, const DOM::DOMString &)
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 ) {
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 ( QValueListIterator<QGuardedPtr<KHTMLPart> > i = d->m_suppressedPopupOriginParts.begin();
01880           i != d->m_suppressedPopupOriginParts.end(); ++i ) {
01881        
01882       if (KHTMLPart* part = *i) {
01883         KJS::Window *w = KJS::Window::retrieveWindow( part );
01884         if (w)
01885           w->forgetSuppressedWindows();
01886       }
01887     }
01888   }
01889 
01890   clear();
01891   d->m_bCleared = false;
01892   d->m_cacheId = 0;
01893   d->m_bComplete = false;
01894   d->m_bLoadEventEmitted = false;
01895 
01896   if(url.isValid()) {
01897       QString urlString = url.url();
01898       KHTMLFactory::vLinks()->insert( urlString );
01899       QString urlString2 = url.prettyURL();
01900       if ( urlString != urlString2 ) {
01901           KHTMLFactory::vLinks()->insert( urlString2 );
01902       }
01903   }
01904 
01905 
01906   // ###
01907   //stopParser();
01908 
01909   KParts::URLArgs args( d->m_extension->urlArgs() );
01910   args.xOffset = xOffset;
01911   args.yOffset = yOffset;
01912   d->m_extension->setURLArgs( args );
01913 
01914   d->m_pageReferrer = QString::null;
01915 
01916   KURL ref(url);
01917   d->m_referrer = ref.protocol().startsWith("http") ? ref.url() : "";
01918 
01919   m_url = url;
01920 
01921   bool servedAsXHTML = args.serviceType == "application/xhtml+xml";
01922   bool servedAsXML = KMimeType::mimeType(args.serviceType)->is( "text/xml" );
01923   // ### not sure if XHTML documents served as text/xml should use DocumentImpl or HTMLDocumentImpl
01924   if ( servedAsXML && !servedAsXHTML ) { // any XML derivative, except XHTML
01925     d->m_doc = DOMImplementationImpl::instance()->createDocument( d->m_view );
01926   } else {
01927     d->m_doc = DOMImplementationImpl::instance()->createHTMLDocument( d->m_view );
01928     // HTML or XHTML? (#86446)
01929     static_cast<HTMLDocumentImpl *>(d->m_doc)->setHTMLRequested( !servedAsXHTML );
01930   }
01931 #ifndef KHTML_NO_CARET
01932 //  d->m_view->initCaret();
01933 #endif
01934 
01935   d->m_doc->ref();
01936   d->m_doc->setURL( m_url.url() );
01937   if (!d->m_doc->attached())
01938     d->m_doc->attach( );
01939   d->m_doc->setBaseURL( KURL() );
01940   d->m_doc->docLoader()->setShowAnimations( KHTMLFactory::defaultHTMLSettings()->showAnimations() );
01941   emit docCreated();
01942 
01943   d->m_paUseStylesheet->setItems(QStringList());
01944   d->m_paUseStylesheet->setEnabled( false );
01945 
01946   setAutoloadImages( KHTMLFactory::defaultHTMLSettings()->autoLoadImages() );
01947   QString userStyleSheet = KHTMLFactory::defaultHTMLSettings()->userStyleSheet();
01948   if ( !userStyleSheet.isEmpty() )
01949     setUserStyleSheet( KURL( userStyleSheet ) );
01950 
01951   d->m_doc->setRestoreState(args.docState);
01952   d->m_doc->open();
01953   connect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
01954 
01955   emit d->m_extension->enableAction( "print", true );
01956 
01957   d->m_doc->setParsing(true);
01958 }
01959 
01960 void KHTMLPart::write( const char *str, int len )
01961 {
01962   if ( !d->m_decoder )
01963     d->m_decoder = createDecoder();
01964 
01965   if ( len == -1 )
01966     len = strlen( str );
01967 
01968   if ( len == 0 )
01969     return;
01970 
01971   QString decoded = d->m_decoder->decode( str, len );
01972 
01973   if(decoded.isEmpty()) return;
01974 
01975   if(d->m_bFirstData) {
01976       // determine the parse mode
01977       d->m_doc->determineParseMode( decoded );
01978       d->m_bFirstData = false;
01979 
01980   //kdDebug(6050) << "KHTMLPart::write haveEnc = " << d->m_haveEncoding << endl;
01981       // ### this is still quite hacky, but should work a lot better than the old solution
01982       if(d->m_decoder->visuallyOrdered()) d->m_doc->setVisuallyOrdered();
01983       d->m_doc->setDecoderCodec(d->m_decoder->codec());
01984       d->m_doc->recalcStyle( NodeImpl::Force );
01985   }
01986 
01987   khtml::Tokenizer* t = d->m_doc->tokenizer();
01988   if(t)
01989     t->write( decoded, true );
01990 }
01991 
01992 void KHTMLPart::write( const QString &str )
01993 {
01994   if ( str.isNull() )
01995     return;
01996 
01997   if(d->m_bFirstData) {
01998       // determine the parse mode
01999       d->m_doc->setParseMode( DocumentImpl::Strict );
02000       d->m_bFirstData = false;
02001   }
02002   khtml::Tokenizer* t = d->m_doc->tokenizer();
02003   if(t)
02004     t->write( str, true );
02005 }
02006 
02007 void KHTMLPart::end()
02008 {
02009     // make sure nothing's left in there...
02010     if(d->m_decoder)
02011         write(d->m_decoder->flush());
02012     if (d->m_doc)
02013         d->m_doc->finishParsing();
02014 }
02015 
02016 bool KHTMLPart::doOpenStream( const QString& mimeType )
02017 {
02018     KMimeType::Ptr mime = KMimeType::mimeType(mimeType);
02019     if ( mime->is( "text/html" ) || mime->is( "text/xml" ) )
02020     {
02021         begin( url() );
02022         return true;
02023     }
02024     return false;
02025 }
02026 
02027 bool KHTMLPart::doWriteStream( const QByteArray& data )
02028 {
02029     write( data.data(), data.size() );
02030     return true;
02031 }
02032 
02033 bool KHTMLPart::doCloseStream()
02034 {
02035     end();
02036     return true;
02037 }
02038 
02039 
02040 void KHTMLPart::paint(QPainter *p, const QRect &rc, int yOff, bool *more)
02041 {
02042     if (!d->m_view) return;
02043     d->m_view->paint(p, rc, yOff, more);
02044 }
02045 
02046 void KHTMLPart::stopAnimations()
02047 {
02048   if ( d->m_doc )
02049     d->m_doc->docLoader()->setShowAnimations( KHTMLSettings::KAnimationDisabled );
02050 
02051   ConstFrameIt it = d->m_frames.begin();
02052   const ConstFrameIt end = d->m_frames.end();
02053   for (; it != end; ++it )
02054     if ( !(*it)->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
02055       KParts::ReadOnlyPart* const p = ( *it )->m_part;
02056       static_cast<KHTMLPart*>( p )->stopAnimations();
02057     }
02058 }
02059 
02060 void KHTMLPart::resetFromScript()
02061 {
02062     closeURL();
02063     d->m_bComplete = false;
02064     d->m_bLoadEventEmitted = false;
02065     disconnect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
02066     connect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
02067     d->m_doc->setParsing(true);
02068 
02069     emit started( 0L );
02070 }
02071 
02072 void KHTMLPart::slotFinishedParsing()
02073 {
02074   d->m_doc->setParsing(false);
02075   checkEmitLoadEvent();
02076   disconnect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
02077 
02078   if (!d->m_view)
02079     return; // We are probably being destructed.
02080 
02081   checkCompleted();
02082 }
02083 
02084 void KHTMLPart::slotLoaderRequestStarted( khtml::DocLoader* dl, khtml::CachedObject *obj )
02085 {
02086   if ( obj && obj->type() == khtml::CachedObject::Image && d->m_doc && d->m_doc->docLoader() == dl ) {
02087     KHTMLPart* p = this;
02088     while ( p ) {
02089       KHTMLPart* const op = p;
02090       ++(p->d->m_totalObjectCount);
02091       p = p->parentPart();
02092       if ( !p && op->d->m_loadedObjects <= op->d->m_totalObjectCount
02093         && !op->d->m_progressUpdateTimer.isActive())
02094     op->d->m_progressUpdateTimer.start( 200, true );
02095     }
02096   }
02097 }
02098 
02099 void KHTMLPart::slotLoaderRequestDone( khtml::DocLoader* dl, khtml::CachedObject *obj )
02100 {
02101   if ( obj && obj->type() == khtml::CachedObject::Image && d->m_doc && d->m_doc->docLoader() == dl ) {
02102     KHTMLPart* p = this;
02103     while ( p ) {
02104       KHTMLPart* const op = p;
02105       ++(p->d->m_loadedObjects);
02106       p = p->parentPart();
02107       if ( !p && op->d->m_loadedObjects <= op->d->m_totalObjectCount && op->d->m_jobPercent <= 100
02108         && !op->d->m_progressUpdateTimer.isActive())
02109     op->d->m_progressUpdateTimer.start( 200, true );
02110     }
02111   }
02112 
02113   checkCompleted();
02114 }
02115 
02116 void KHTMLPart::slotProgressUpdate()
02117 {
02118   int percent;
02119   if ( d->m_loadedObjects < d->m_totalObjectCount )
02120     percent = d->m_jobPercent / 4 + ( d->m_loadedObjects*300 ) / ( 4*d->m_totalObjectCount );
02121   else
02122     percent = d->m_jobPercent;
02123 
02124   if( d->m_bComplete )
02125     percent = 100;
02126 
02127   if (d->m_statusMessagesEnabled) {
02128     if( d->m_bComplete )
02129       emit d->m_extension->infoMessage( i18n( "Page loaded." ));
02130     else if ( d->m_loadedObjects < d->m_totalObjectCount && percent >= 75 )
02131       emit d->m_extension->infoMessage( i18n( "%n Image of %1 loaded.", "%n Images of %1 loaded.", d->m_loadedObjects).arg(d->m_totalObjectCount) );
02132   }
02133 
02134   emit d->m_extension->loadingProgress( percent );
02135 }
02136 
02137 void KHTMLPart::slotJobSpeed( KIO::Job* /*job*/, unsigned long speed )
02138 {
02139   d->m_jobspeed = speed;
02140   if (!parentPart())
02141     setStatusBarText(jsStatusBarText(), BarOverrideText);
02142 }
02143 
02144 void KHTMLPart::slotJobPercent( KIO::Job* /*job*/, unsigned long percent )
02145 {
02146   d->m_jobPercent = percent;
02147 
02148   if ( !parentPart() )
02149     d->m_progressUpdateTimer.start( 0, true );
02150 }
02151 
02152 void KHTMLPart::slotJobDone( KIO::Job* /*job*/ )
02153 {
02154   d->m_jobPercent = 100;
02155 
02156   if ( !parentPart() )
02157     d->m_progressUpdateTimer.start( 0, true );
02158 }
02159 
02160 void KHTMLPart::slotUserSheetStatDone( KIO::Job *_job )
02161 {
02162   using namespace KIO;
02163 
02164   if ( _job->error() ) {
02165     showError( _job );
02166     return;
02167   }
02168 
02169   const UDSEntry entry = dynamic_cast<KIO::StatJob *>( _job )->statResult();
02170   UDSEntry::ConstIterator it = entry.begin();
02171   const UDSEntry::ConstIterator end = entry.end();
02172   for ( ; it != end; ++it ) {
02173     if ( ( *it ).m_uds == UDS_MODIFICATION_TIME ) {
02174      break;
02175     }
02176   }
02177 
02178   // If the filesystem supports modification times, only reload the
02179   // user-defined stylesheet if necessary - otherwise always reload.
02180   if ( it != end ) {
02181     const time_t lastModified = static_cast<time_t>( ( *it ).m_long );
02182     if ( d->m_userStyleSheetLastModified >= lastModified ) {
02183       return;
02184     }
02185     d->m_userStyleSheetLastModified = lastModified;
02186   }
02187 
02188   setUserStyleSheet( KURL( settings()->userStyleSheet() ) );
02189 }
02190 
02191 void KHTMLPart::checkCompleted()
02192 {
02193 //   kdDebug( 6050 ) << "KHTMLPart::checkCompleted() " << this << " " << name() << endl;
02194 //   kdDebug( 6050 ) << "                           parsing: " << (d->m_doc && d->m_doc->parsing()) << endl;
02195 //   kdDebug( 6050 ) << "                           complete: " << d->m_bComplete << endl;
02196 
02197   // restore the cursor position
02198   if (d->m_doc && !d->m_doc->parsing() && !d->m_focusNodeRestored)
02199   {
02200       if (d->m_focusNodeNumber >= 0)
02201           d->m_doc->setFocusNode(d->m_doc->nodeWithAbsIndex(d->m_focusNodeNumber));
02202 
02203       d->m_focusNodeRestored = true;
02204   }
02205 
02206   bool bPendingChildRedirection = false;
02207   // Any frame that hasn't completed yet ?
02208   ConstFrameIt it = d->m_frames.begin();
02209   const ConstFrameIt end = d->m_frames.end();
02210   for (; it != end; ++it ) {
02211     if ( !(*it)->m_bCompleted )
02212     {
02213       //kdDebug( 6050 ) << this << " is waiting for " << (*it)->m_part << endl;
02214       return;
02215     }
02216     // Check for frames with pending redirections
02217     if ( (*it)->m_bPendingRedirection )
02218       bPendingChildRedirection = true;
02219   }
02220 
02221   // Any object that hasn't completed yet ?
02222   {
02223     ConstFrameIt oi = d->m_objects.begin();
02224     const ConstFrameIt oiEnd = d->m_objects.end();
02225 
02226     for (; oi != oiEnd; ++oi )
02227       if ( !(*oi)->m_bCompleted )
02228         return;
02229   }
02230   // Are we still parsing - or have we done the completed stuff already ?
02231   if ( d->m_bComplete || (d->m_doc && d->m_doc->parsing()) )
02232     return;
02233 
02234   // Still waiting for images/scripts from the loader ?
02235   int requests = 0;
02236   if ( d->m_doc && d->m_doc->docLoader() )
02237     requests = khtml::Cache::loader()->numRequests( d->m_doc->docLoader() );
02238 
02239   if ( requests > 0 )
02240   {
02241     //kdDebug(6050) << "still waiting for images/scripts from the loader - requests:" << requests << endl;
02242     return;
02243   }
02244 
02245   // OK, completed.
02246   // Now do what should be done when we are really completed.
02247   d->m_bComplete = true;
02248   d->m_cachePolicy = KProtocolManager::cacheControl(); // reset cache policy
02249   d->m_totalObjectCount = 0;
02250   d->m_loadedObjects = 0;
02251 
02252   KHTMLPart* p = this;
02253   while ( p ) {
02254     KHTMLPart* op = p;
02255     p = p->parentPart();
02256     if ( !p && !op->d->m_progressUpdateTimer.isActive())
02257       op->d->m_progressUpdateTimer.start( 0, true );
02258   }
02259 
02260   checkEmitLoadEvent(); // if we didn't do it before
02261 
02262   bool pendingAction = false;
02263 
02264   if ( !d->m_redirectURL.isEmpty() )
02265   {
02266     // DA: Do not start redirection for frames here! That action is
02267     // deferred until the parent emits a completed signal.
02268     if ( parentPart() == 0 ) {
02269       //kdDebug(6050) << this << " starting redirection timer" << endl;
02270       d->m_redirectionTimer.start( 1000 * d->m_delayRedirect, true );
02271     } else {
02272       //kdDebug(6050) << this << " not toplevel -> not starting redirection timer. Waiting for slotParentCompleted." << endl;
02273     }
02274 
02275     pendingAction = true;
02276   }
02277   else if ( bPendingChildRedirection )
02278   {
02279     pendingAction = true;
02280   }
02281 
02282   // the view will emit completed on our behalf,
02283   // either now or at next repaint if one is pending
02284 
02285   //kdDebug(6050) << this << " asks the view to emit completed. pendingAction=" << pendingAction << endl;
02286   d->m_view->complete( pendingAction );
02287 
02288   // find the alternate stylesheets
02289   QStringList sheets;
02290   if (d->m_doc)
02291      sheets = d->m_doc->availableStyleSheets();
02292   sheets.prepend( i18n( "Automatic Detection" ) );
02293   d->m_paUseStylesheet->setItems( sheets );
02294 
02295   d->m_paUseStylesheet->setEnabled( sheets.count() > 2);
02296   if (sheets.count() > 2)
02297   {
02298     d->m_paUseStylesheet->setCurrentItem(kMax(sheets.findIndex(d->m_sheetUsed), 0));
02299     slotUseStylesheet();
02300   }
02301 
02302   setJSDefaultStatusBarText(QString::null);
02303 
02304 #ifdef SPEED_DEBUG
02305   kdDebug(6050) << "DONE: " <<d->m_parsetime.elapsed() << endl;
02306 #endif
02307 }
02308 
02309 void KHTMLPart::checkEmitLoadEvent()
02310 {
02311   if ( d->m_bLoadEventEmitted || !d->m_doc || d->m_doc->parsing() ) return;
02312 
02313   ConstFrameIt it = d->m_frames.begin();
02314   const ConstFrameIt end = d->m_frames.end();
02315   for (; it != end; ++it )
02316     if ( !(*it)->m_bCompleted ) // still got a frame running -> too early
02317       return;
02318 
02319   ConstFrameIt oi = d->m_objects.begin();
02320   const ConstFrameIt oiEnd = d->m_objects.end();
02321 
02322   for (; oi != oiEnd; ++oi )
02323     if ( !(*oi)->m_bCompleted ) // still got a object running -> too early
02324       return;
02325 
02326   // Still waiting for images/scripts from the loader ?
02327   // (onload must happen afterwards, #45607)
02328   // ## This makes this method very similar to checkCompleted. A brave soul should try merging them.
02329   int requests = 0;
02330   if ( d->m_doc && d->m_doc->docLoader() )
02331     requests = khtml::Cache::loader()->numRequests( d->m_doc->docLoader() );
02332 
02333   if ( requests > 0 )
02334     return;
02335 
02336   d->m_bLoadEventEmitted = true;
02337   if (d->m_doc)
02338     d->m_doc->close();
02339 }
02340 
02341 const KHTMLSettings *KHTMLPart::settings() const
02342 {
02343   return d->m_settings;
02344 }
02345 
02346 #ifndef KDE_NO_COMPAT
02347 KURL KHTMLPart::baseURL() const
02348 {
02349   if ( !d->m_doc ) return KURL();
02350 
02351   return d->m_doc->baseURL();
02352 }
02353 
02354 QString KHTMLPart::baseTarget() const
02355 {
02356   if ( !d->m_doc ) return QString::null;
02357 
02358   return d->m_doc->baseTarget();
02359 }
02360 #endif
02361 
02362 KURL KHTMLPart::completeURL( const QString &url )
02363 {
02364   if ( !d->m_doc ) return KURL( url );
02365 
02366   if (d->m_decoder)
02367     return KURL(d->m_doc->completeURL(url), d->m_decoder->codec()->mibEnum());
02368 
02369   return KURL( d->m_doc->completeURL( url ) );
02370 }
02371 
02372 // Called by ecma/kjs_window in case of redirections from Javascript,
02373 // and by xml/dom_docimpl.cpp in case of http-equiv meta refresh.
02374 void KHTMLPart::scheduleRedirection( int delay, const QString &url, bool doLockHistory )
02375 {
02376   kdDebug(6050) << "KHTMLPart::scheduleRedirection delay=" << delay << " url=" << url << endl;
02377   kdDebug(6050) << "current redirectURL=" << d->m_redirectURL << " with delay " << d->m_delayRedirect <<  endl;
02378   if( delay < 24*60*60 &&
02379       ( d->m_redirectURL.isEmpty() || delay <= d->m_delayRedirect) ) {
02380     d->m_delayRedirect = delay;
02381     d->m_redirectURL = url;
02382     d->m_redirectLockHistory = doLockHistory;
02383     kdDebug(6050) << " d->m_bComplete=" << d->m_bComplete << endl;
02384     if ( d->m_bComplete ) {
02385       d->m_redirectionTimer.stop();
02386       d->m_redirectionTimer.start( kMax(0, 1000 * d->m_delayRedirect), true );
02387     }
02388   }
02389 }
02390 
02391 void KHTMLPart::slotRedirect()
02392 {
02393   kdDebug(6050) << this << " slotRedirect()" << endl;
02394   QString u = d->m_redirectURL;
02395   d->m_delayRedirect = 0;
02396   d->m_redirectURL = QString::null;
02397 
02398   // SYNC check with ecma/kjs_window.cpp::goURL !
02399   if ( u.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
02400   {
02401     QString script = KURL::decode_string( u.right( u.length() - 11 ) );
02402     kdDebug( 6050 ) << "KHTMLPart::slotRedirect script=" << script << endl;
02403     QVariant res = executeScript( DOM::Node(), script );
02404     if ( res.type() == QVariant::String ) {
02405       begin( url() );
02406       write( res.asString() );
02407       end();
02408     }
02409     emit completed();
02410     return;
02411   }
02412   KParts::URLArgs args;
02413   KURL cUrl( m_url );
02414   KURL url( u );
02415 
02416   // handle windows opened by JS
02417   if ( openedByJS() && d->m_opener )
02418       cUrl = d->m_opener->url();
02419 
02420   if (!kapp || !kapp->authorizeURLAction("redirect", cUrl, url))
02421   {
02422     kdWarning(6050) << "KHTMLPart::scheduleRedirection: Redirection from " << cUrl << " to " << url << " REJECTED!" << endl;
02423     emit completed();
02424     return;
02425   }
02426 
02427   if ( urlcmp( u, m_url.url(), true, true ) )
02428   {
02429     args.metaData().insert("referrer", d->m_pageReferrer);
02430   }
02431 
02432   // For javascript and META-tag based redirections:
02433   //   - We don't take cross-domain-ness in consideration if we are the
02434   //   toplevel frame because the new URL may be in a different domain as the current URL
02435   //   but that's ok.
02436   //   - If we are not the toplevel frame then we check against the toplevelURL()
02437   if (parentPart())
02438       args.metaData().insert("cross-domain", toplevelURL().url());
02439 
02440   args.setLockHistory( d->m_redirectLockHistory );
02441   // _self: make sure we don't use any <base target=>'s
02442 
02443   d->m_urlSelectedOpenedURL = true; // In case overriden, default to success
02444   urlSelected( u, 0, 0, "_self", args );
02445 
02446   if ( !d->m_urlSelectedOpenedURL ) // urlSelected didn't open a url, so emit completed ourselves
02447     emit completed();
02448 }
02449 
02450 void KHTMLPart::slotRedirection(KIO::Job*, const KURL& url)
02451 {
02452   // the slave told us that we got redirected
02453   //kdDebug( 6050 ) << "redirection by KIO to " << url.url() << endl;
02454   emit d->m_extension->setLocationBarURL( url.prettyURL() );
02455   d->m_workingURL = url;
02456 }
02457 
02458 bool KHTMLPart::setEncoding( const QString &name, bool override )
02459 {
02460     d->m_encoding = name;
02461     d->m_haveEncoding = override;
02462 
02463     if( !m_url.isEmpty() ) {
02464         // reload document
02465         closeURL();
02466         KURL url = m_url;
02467         m_url = 0;
02468         d->m_restored = true;
02469         openURL(url);
02470         d->m_restored = false;
02471     }
02472 
02473     return true;
02474 }
02475 
02476 QString KHTMLPart::encoding() const
02477 {
02478     if(d->m_haveEncoding && !d->m_encoding.isEmpty())
02479         return d->m_encoding;
02480 
02481     if(d->m_decoder && d->m_decoder->encoding())
02482         return QString(d->m_decoder->encoding());
02483 
02484     return defaultEncoding();
02485 }
02486 
02487 QString KHTMLPart::defaultEncoding() const
02488 {
02489   QString encoding = settings()->encoding();
02490   if ( !encoding.isEmpty() )
02491     return encoding;
02492   // HTTP requires the default encoding to be latin1, when neither
02493   // the user nor the page requested a particular encoding.
02494   if ( url().protocol().startsWith( "http" ) )
02495     return "iso-8859-1";
02496   else
02497     return KGlobal::locale()->encoding();
02498 }
02499 
02500 void KHTMLPart::setUserStyleSheet(const KURL &url)
02501 {
02502   if ( d->m_doc && d->m_doc->docLoader() )
02503     (void) new khtml::PartStyleSheetLoader(this, url.url(), d->m_doc->docLoader());
02504 }
02505 
02506 void KHTMLPart::setUserStyleSheet(const QString &styleSheet)
02507 {
02508   if ( d->m_doc )
02509     d->m_doc->setUserStyleSheet( styleSheet );
02510 }
02511 
02512 bool KHTMLPart::gotoAnchor( const QString &name )
02513 {
02514   if (!d->m_doc)
02515     return false;
02516 
02517   HTMLCollectionImpl *anchors =
02518       new HTMLCollectionImpl( d->m_doc, HTMLCollectionImpl::DOC_ANCHORS);
02519   anchors->ref();
02520   NodeImpl *n = anchors->namedItem(name);
02521   anchors->deref();
02522 
02523   if(!n) {
02524       n = d->m_doc->getElementById( name );
02525   }
02526 
02527   d->m_doc->setCSSTarget(n); // Setting to null will clear the current target.
02528 
02529   // Implement the rule that "" and "top" both mean top of page as in other browsers.
02530   bool quirkyName = !n && !d->m_doc->inStrictMode() && (name.isEmpty() || name.lower() == "top");
02531 
02532   if (quirkyName) {
02533       d->m_view->setContentsPos(0, 0);
02534       return true;
02535   } else if (!n) {
02536       kdDebug(6050) << "KHTMLPart::gotoAnchor node '" << name << "' not found" << endl;
02537       return false;
02538   }
02539 
02540   int x = 0, y = 0;
02541   int gox, dummy;
02542   HTMLElementImpl *a = static_cast<HTMLElementImpl *>(n);
02543 
02544   a->getUpperLeftCorner(x, y);
02545   if (x <= d->m_view->contentsX())
02546     gox = x - 10;
02547   else {
02548     gox = d->m_view->contentsX();
02549     if ( x + 10 > d->m_view->contentsX()+d->m_view->visibleWidth()) {
02550       a->getLowerRightCorner(x, dummy);
02551       gox = x - d->m_view->visibleWidth() + 10;
02552     }
02553   }
02554 
02555   d->m_view->setContentsPos(gox, y);
02556 
02557   return true;
02558 }
02559 
02560 bool KHTMLPart::nextAnchor()
02561 {
02562   if (!d->m_doc)
02563     return false;
02564   d->m_view->focusNextPrevNode ( true );
02565 
02566   return true;
02567 }
02568 
02569 bool KHTMLPart::prevAnchor()
02570 {
02571   if (!d->m_doc)
02572     return false;
02573   d->m_view->focusNextPrevNode ( false );
02574 
02575   return true;
02576 }
02577 
02578 void KHTMLPart::setStandardFont( const QString &name )
02579 {
02580     d->m_settings->setStdFontName(name);
02581 }
02582 
02583 void KHTMLPart::setFixedFont( const QString &name )
02584 {
02585     d->m_settings->setFixedFontName(name);
02586 }
02587 
02588 void KHTMLPart::setURLCursor( const QCursor &c )
02589 {
02590   d->m_linkCursor = c;
02591 }
02592 
02593 QCursor KHTMLPart::urlCursor() const
02594 {
02595   return d->m_linkCursor;
02596 }
02597 
02598 bool KHTMLPart::onlyLocalReferences() const
02599 {
02600   return d->m_onlyLocalReferences;
02601 }
02602 
02603 void KHTMLPart::setOnlyLocalReferences(bool enable)
02604 {
02605   d->m_onlyLocalReferences = enable;
02606 }
02607 
02608 void KHTMLPartPrivate::setFlagRecursively(
02609     bool KHTMLPartPrivate::*flag, bool value)
02610 {
02611   // first set it on the current one
02612   this->*flag = value;
02613 
02614   // descend into child frames recursively
02615   {
02616     QValueList<khtml::ChildFrame*>::Iterator it = m_frames.begin();
02617     const QValueList<khtml::ChildFrame*>::Iterator itEnd = m_frames.end();
02618     for (; it != itEnd; ++it) {
02619       KHTMLPart* const part = static_cast<KHTMLPart *>((KParts::ReadOnlyPart *)(*it)->m_part);
02620       if (part->inherits("KHTMLPart"))
02621         part->d->setFlagRecursively(flag, value);
02622     }/*next it*/
02623   }
02624   // do the same again for objects
02625   {
02626     QValueList<khtml::ChildFrame*>::Iterator it = m_objects.begin();
02627     const QValueList<khtml::ChildFrame*>::Iterator itEnd = m_objects.end();
02628     for (; it != itEnd; ++it) {
02629       KHTMLPart* const part = static_cast<KHTMLPart *>((KParts::ReadOnlyPart *)(*it)->m_part);
02630       if (part->inherits("KHTMLPart"))
02631         part->d->setFlagRecursively(flag, value);
02632     }/*next it*/
02633   }
02634 }
02635 
02636 void KHTMLPart::setCaretMode(bool enable)
02637 {
02638 #ifndef KHTML_NO_CARET
02639   kdDebug(6200) << "setCaretMode(" << enable << ")" << endl;
02640   if (isCaretMode() == enable) return;
02641   d->setFlagRecursively(&KHTMLPartPrivate::m_caretMode, enable);
02642   // FIXME: this won't work on frames as expected
02643   if (!isEditable()) {
02644     if (enable) {
02645       view()->initCaret(true);
02646       view()->ensureCaretVisible();
02647     } else
02648       view()->caretOff();
02649   }/*end if*/
02650 #endif // KHTML_NO_CARET
02651 }
02652 
02653 bool KHTMLPart::isCaretMode() const
02654 {
02655   return d->m_caretMode;
02656 }
02657 
02658 void KHTMLPart::setEditable(bool enable)
02659 {
02660 #ifndef KHTML_NO_CARET
02661   if (isEditable() == enable) return;
02662   d->setFlagRecursively(&KHTMLPartPrivate::m_designMode, enable);
02663   // FIXME: this won't work on frames as expected
02664   if (!isCaretMode()) {
02665     if (enable) {
02666       view()->initCaret(true);
02667       view()->ensureCaretVisible();
02668     } else
02669       view()->caretOff();
02670   }/*end if*/
02671 #endif // KHTML_NO_CARET
02672 }
02673 
02674 bool KHTMLPart::isEditable() const
02675 {
02676   return d->m_designMode;
02677 }
02678 
02679 void KHTMLPart::setCaretPosition(DOM::Node node, long offset, bool extendSelection)
02680 {
02681 #ifndef KHTML_NO_CARET
02682 #if 0
02683   kdDebug(6200) << k_funcinfo << "node: " << node.handle() << " nodeName: "
02684     << node.nodeName().string() << " offset: " << offset
02685     << " extendSelection " << extendSelection << endl;
02686 #endif
02687   if (view()->moveCaretTo(node.handle(), offset, !extendSelection))
02688     emitSelectionChanged();
02689   view()->ensureCaretVisible();
02690 #endif // KHTML_NO_CARET
02691 }
02692 
02693 KHTMLPart::CaretDisplayPolicy KHTMLPart::caretDisplayPolicyNonFocused() const
02694 {
02695 #ifndef KHTML_NO_CARET
02696   return (CaretDisplayPolicy)view()->caretDisplayPolicyNonFocused();
02697 #else // KHTML_NO_CARET
02698   return CaretInvisible;
02699 #endif // KHTML_NO_CARET
02700 }
02701 
02702 void KHTMLPart::setCaretDisplayPolicyNonFocused(CaretDisplayPolicy policy)
02703 {
02704 #ifndef KHTML_NO_CARET
02705   view()->setCaretDisplayPolicyNonFocused(policy);
02706 #endif // KHTML_NO_CARET
02707 }
02708 
02709 void KHTMLPart::setCaretVisible(bool show)
02710 {
02711 #ifndef KHTML_NO_CARET
02712   if (show) {
02713 
02714     NodeImpl *caretNode = xmlDocImpl()->focusNode();
02715     if (isCaretMode() || isEditable()
02716     || (caretNode && caretNode->contentEditable())) {
02717       view()->caretOn();
02718     }/*end if*/
02719 
02720   } else {
02721 
02722     view()->caretOff();
02723 
02724   }/*end if*/
02725 #endif // KHTML_NO_CARET
02726 }
02727 
02728 void KHTMLPart::findTextBegin()
02729 {
02730   d->m_findPos = -1;
02731   d->m_findNode = 0;
02732   d->m_findPosEnd = -1;
02733   d->m_findNodeEnd= 0;
02734   d->m_findPosStart = -1;
02735   d->m_findNodeStart = 0;
02736   d->m_findNodePrevious = 0;
02737   delete d->m_find;
02738   d->m_find = 0L;
02739 }
02740 
02741 bool KHTMLPart::initFindNode( bool selection, bool reverse, bool fromCursor )
02742 {
02743     if ( !d->m_doc )
02744         return false;
02745 
02746     DOM::NodeImpl* firstNode = 0L;
02747     if (d->m_doc->isHTMLDocument())
02748       firstNode = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
02749     else
02750       firstNode = d->m_doc;
02751 
02752     if ( !firstNode )
02753     {
02754       //kdDebug(6050) << k_funcinfo << "no first node (body or doc) -> return false" << endl;
02755       return false;
02756     }
02757     if ( firstNode->id() == ID_FRAMESET )
02758     {
02759       //kdDebug(6050) << k_funcinfo << "FRAMESET -> return false" << endl;
02760       return false;
02761     }
02762 
02763     if ( selection && hasSelection() )
02764     {
02765       //kdDebug(6050) << k_funcinfo << "using selection" << endl;
02766       if ( !fromCursor )
02767       {
02768         d->m_findNode = reverse ? d->m_selectionEnd.handle() : d->m_selectionStart.handle();
02769         d->m_findPos = reverse ? d->m_endOffset : d->m_startOffset;
02770       }
02771       d->m_findNodeEnd = reverse ? d->m_selectionStart.handle() : d->m_selectionEnd.handle();
02772       d->m_findPosEnd = reverse ? d->m_startOffset : d->m_endOffset;
02773       d->m_findNodeStart = !reverse ? d->m_selectionStart.handle() : d->m_selectionEnd.handle();
02774       d->m_findPosStart = !reverse ? d->m_startOffset : d->m_endOffset;
02775       d->m_findNodePrevious = d->m_findNodeStart;
02776     }
02777     else // whole document
02778     {
02779       //kdDebug(6050) << k_funcinfo << "whole doc" << endl;
02780       if ( !fromCursor )
02781       {
02782         d->m_findNode = firstNode;
02783         d->m_findPos = reverse ? -1 : 0;
02784       }
02785       d->m_findNodeEnd = reverse ? firstNode : 0;
02786       d->m_findPosEnd = reverse ? 0 : -1;
02787       d->m_findNodeStart = !reverse ? firstNode : 0;
02788       d->m_findPosStart = !reverse ? 0 : -1;
02789       d->m_findNodePrevious = d->m_findNodeStart;
02790       if ( reverse )
02791       {
02792         // Need to find out the really last object, to start from it
02793         khtml::RenderObject* obj = d->m_findNode ? d->m_findNode->renderer() : 0;
02794         if ( obj )
02795         {
02796           // find the last object in the render tree
02797           while ( obj->lastChild() )
02798           {
02799               obj = obj->lastChild();
02800           }
02801           // now get the last object with a NodeImpl associated
02802           while ( !obj->element() && obj->objectAbove() )
02803           {
02804              obj = obj->objectAbove();
02805           }
02806           d->m_findNode = obj->element();
02807         }
02808       }
02809     }
02810     return true;
02811 }
02812 
02813 // Old method (its API limits the available features - remove in KDE-4)
02814 bool KHTMLPart::findTextNext( const QString &str, bool forward, bool caseSensitive, bool isRegExp )
02815 {
02816     if ( !initFindNode( false, !forward, d->m_findNode ) )
02817       return false;
02818     while(1)
02819     {
02820         if( (d->m_findNode->nodeType() == Node::TEXT_NODE || d->m_findNode->nodeType() == Node::CDATA_SECTION_NODE) && d->m_findNode->renderer() )
02821         {
02822             DOMString nodeText = d->m_findNode->nodeValue();
02823             DOMStringImpl *t = nodeText.implementation();
02824             QConstString s(t->s, t->l);
02825 
02826             int matchLen = 0;
02827             if ( isRegExp ) {
02828               QRegExp matcher( str );
02829               matcher.setCaseSensitive( caseSensitive );
02830               d->m_findPos = matcher.search(s.string(), d->m_findPos+1);
02831               if ( d->m_findPos != -1 )
02832                 matchLen = matcher.matchedLength();
02833             }
02834             else {
02835               d->m_findPos = s.string().find(str, d->m_findPos+1, caseSensitive);
02836               matchLen = str.length();
02837             }
02838 
02839             if(d->m_findPos != -1)
02840             {
02841                 int x = 0, y = 0;
02842                 if(static_cast<khtml::RenderText *>(d->m_findNode->renderer())
02843                   ->posOfChar(d->m_findPos, x, y))
02844                     d->m_view->setContentsPos(x-50, y-50);
02845 
02846                 d->m_selectionStart = d->m_findNode;
02847                 d->m_startOffset = d->m_findPos;
02848                 d->m_selectionEnd = d->m_findNode;
02849                 d->m_endOffset = d->m_findPos + matchLen;
02850                 d->m_startBeforeEnd = true;
02851 
02852                 d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
02853                                         d->m_selectionEnd.handle(), d->m_endOffset );
02854                 emitSelectionChanged();
02855                 return true;
02856             }
02857         }
02858         d->m_findPos = -1;
02859 
02860         NodeImpl *next;
02861 
02862         if ( forward )
02863         {
02864           next = d->m_findNode->firstChild();
02865 
02866           if(!next) next = d->m_findNode->nextSibling();
02867           while(d->m_findNode && !next) {
02868               d->m_findNode = d->m_findNode->parentNode();
02869               if( d->m_findNode ) {
02870                   next = d->m_findNode->nextSibling();
02871               }
02872           }
02873         }
02874         else
02875         {
02876           next = d->m_findNode->lastChild();
02877 
02878           if (!next ) next = d->m_findNode->previousSibling();
02879           while ( d->m_findNode && !next )
02880           {
02881             d->m_findNode = d->m_findNode->parentNode();
02882             if( d->m_findNode )
02883             {
02884               next = d->m_findNode->previousSibling();
02885             }
02886           }
02887         }
02888 
02889         d->m_findNode = next;
02890         if(!d->m_findNode) return false;
02891     }
02892 }
02893 
02894 
02895 void KHTMLPart::slotFind()
02896 {
02897   KParts::ReadOnlyPart *part = currentFrame();
02898   if (!part)
02899     return;
02900   if (!part->inherits("KHTMLPart") )
02901   {
02902       kdError(6000) << "slotFind: part is a " << part->className() << ", can't do a search into it" << endl;
02903       return;
02904   }
02905   static_cast<KHTMLPart *>( part )->findText();
02906 }
02907 
02908 void KHTMLPart::slotFindNext()
02909 {
02910   KParts::ReadOnlyPart *part = currentFrame();
02911   if (!part)
02912     return;
02913   if (!part->inherits("KHTMLPart") )
02914   {
02915       kdError(6000) << "slotFindNext: part is a " << part->className() << ", can't do a search into it" << endl;
02916       return;
02917   }
02918   static_cast<KHTMLPart *>( part )->findTextNext();
02919 }
02920 
02921 void KHTMLPart::slotFindPrev()
02922 {
02923   KParts::ReadOnlyPart *part = currentFrame();
02924   if (!part)
02925     return;
02926   if (!part->inherits("KHTMLPart") )
02927   {
02928       kdError(6000) << "slotFindNext: part is a " << part->className() << ", can't do a search into it" << endl;
02929       return;
02930   }
02931   static_cast<KHTMLPart *>( part )->findTextNext( true ); // reverse
02932 }
02933 
02934 void KHTMLPart::slotFindDone()
02935 {
02936   // ### remove me
02937 }
02938 
02939 void KHTMLPart::slotFindAheadText()
02940 {
02941 #ifndef KHTML_NO_TYPE_AHEAD_FIND
02942   KParts::ReadOnlyPart *part = currentFrame();
02943   if (!part)
02944     return;
02945   if (!part->inherits("KHTMLPart") )
02946   {
02947       kdError(6000) << "slotFindNext: part is a " << part->className() << ", can't do a search into it" << endl;
02948       return;
02949   }
02950   static_cast<KHTMLPart *>( part )->view()->startFindAhead( false );
02951 #endif // KHTML_NO_TYPE_AHEAD_FIND
02952 }
02953 
02954 void KHTMLPart::slotFindAheadLink()
02955 {
02956 #ifndef KHTML_NO_TYPE_AHEAD_FIND
02957   KParts::ReadOnlyPart *part = currentFrame();
02958   if (!part)
02959     return;
02960   if (!part->inherits("KHTMLPart") )
02961   {
02962       kdError(6000) << "slotFindNext: part is a " << part->className() << ", can't do a search into it" << endl;
02963       return;
02964   }
02965   static_cast<KHTMLPart *>( part )->view()->startFindAhead( true );
02966 #endif // KHTML_NO_TYPE_AHEAD_FIND
02967 }
02968 
02969 void KHTMLPart::enableFindAheadActions( bool enable )
02970 {
02971   // only the topmost one has shortcuts
02972   KHTMLPart* p = this;
02973   while( p->parentPart())
02974     p = p->parentPart();
02975   p->d->m_paFindAheadText->setEnabled( enable );
02976   p->d->m_paFindAheadLinks->setEnabled( enable );
02977 }
02978 
02979 void KHTMLPart::slotFindDialogDestroyed()
02980 {
02981   d->m_lastFindState.options = d->m_findDialog->options();
02982   d->m_lastFindState.history = d->m_findDialog->findHistory();
02983   d->m_findDialog->deleteLater();
02984   d->m_findDialog = 0L;
02985 }
02986 
02987 void KHTMLPart::findText()
02988 {
02989   // First do some init to make sure we can search in this frame
02990   if ( !d->m_doc )
02991     return;
02992 
02993   // Raise if already opened
02994   if ( d->m_findDialog )
02995   {
02996     KWin::activateWindow( d->m_findDialog->winId() );
02997     return;
02998   }
02999 
03000   // The lineedit of the dialog would make khtml lose its selection, otherwise
03001 #ifndef QT_NO_CLIPBOARD
03002   disconnect( kapp->clipboard(), SIGNAL(selectionChanged()), this, SLOT(slotClearSelection()) );
03003 #endif
03004 
03005   // Now show the dialog in which the user can choose options.
03006   d->m_findDialog = new KFindDialog( false /*non-modal*/, widget(), "khtmlfind" );
03007   d->m_findDialog->setHasSelection( hasSelection() );
03008   d->m_findDialog->setHasCursor( d->m_findNode != 0 );
03009   if ( d->m_findNode ) // has a cursor -> default to 'FromCursor'
03010     d->m_lastFindState.options |= KFindDialog::FromCursor;
03011 
03012   // TODO? optionsDialog.setPattern( d->m_lastFindState.text );
03013   d->m_findDialog->setFindHistory( d->m_lastFindState.history );
03014   d->m_findDialog->setOptions( d->m_lastFindState.options );
03015 
03016   d->m_lastFindState.options = -1; // force update in findTextNext
03017   d->m_lastFindState.last_dir = -1;
03018 
03019   d->m_findDialog->show();
03020   connect( d->m_findDialog, SIGNAL(okClicked()), this, SLOT(slotFindNext()) );
03021   connect( d->m_findDialog, SIGNAL(finished()), this, SLOT(slotFindDialogDestroyed()) );
03022 
03023   findText( d->m_findDialog->pattern(), 0 /*options*/, widget(), d->m_findDialog );
03024 }
03025 
03026 void KHTMLPart::findText( const QString &str, long options, QWidget *parent, KFindDialog *findDialog )
03027 {
03028   // First do some init to make sure we can search in this frame
03029   if ( !d->m_doc )
03030     return;
03031 
03032 #ifndef QT_NO_CLIPBOARD
03033   connect( kapp->clipboard(), SIGNAL(selectionChanged()), SLOT(slotClearSelection()) );
03034 #endif
03035 
03036   // Create the KFind object
03037   delete d->m_find;
03038   d->m_find = new KFind( str, options, parent, findDialog );
03039   d->m_find->closeFindNextDialog(); // we use KFindDialog non-modal, so we don't want other dlg popping up
03040   connect( d->m_find, SIGNAL( highlight( const QString &, int, int ) ),
03041            this, SLOT( slotHighlight( const QString &, int, int ) ) );
03042   //connect(d->m_find, SIGNAL( findNext() ),
03043   //        this, SLOT( slotFindNext() ) );
03044 
03045   if ( !findDialog )
03046   {
03047     d->m_lastFindState.options = options;
03048     initFindNode( options & KFindDialog::SelectedText,
03049                   options & KFindDialog::FindBackwards,
03050                   options & KFindDialog::FromCursor );
03051   }
03052 }
03053 
03054 bool KHTMLPart::findTextNext()
03055 {
03056   return findTextNext( false );
03057 }
03058 
03059 // New method
03060 bool KHTMLPart::findTextNext( bool reverse )
03061 {
03062   if (!d->m_find)
03063   {
03064     // We didn't show the find dialog yet, let's do it then (#49442)
03065     findText();
03066     return false;
03067   }
03068 
03069   view()->updateFindAheadTimeout();
03070   long options = 0;
03071   if ( d->m_findDialog ) // 0 when we close the dialog
03072   {
03073     if ( d->m_find->pattern() != d->m_findDialog->pattern() ) {
03074       d->m_find->setPattern( d->m_findDialog->pattern() );
03075       d->m_find->resetCounts();
03076     }
03077     options = d->m_findDialog->options();
03078     if ( d->m_lastFindState.options != options )
03079     {
03080       d->m_find->setOptions( options );
03081 
03082       if ( options & KFindDialog::SelectedText )
03083         Q_ASSERT( hasSelection() );
03084 
03085       long difference = d->m_lastFindState.options ^ options;
03086       if ( difference & (KFindDialog::SelectedText | KFindDialog::FromCursor ) )
03087       {
03088           // Important options changed -> reset search range
03089         (void) initFindNode( options & KFindDialog::SelectedText,
03090                              options & KFindDialog::FindBackwards,
03091                              options & KFindDialog::FromCursor );
03092       }
03093       d->m_lastFindState.options = options;
03094     }
03095   } else
03096     options = d->m_lastFindState.options;
03097   if( reverse )
03098     options = options ^ KFindDialog::FindBackwards;
03099   if( d->m_find->options() != options )
03100     d->m_find->setOptions( options );
03101 
03102   // Changing find direction. Start and end nodes must be switched.
03103   // Additionally since d->m_findNode points after the last node
03104   // that was searched, it needs to be "after" it in the opposite direction.
03105   if( d->m_lastFindState.last_dir != -1
03106       && bool( d->m_lastFindState.last_dir ) != bool( options & KFindDialog::FindBackwards ))
03107   {
03108     qSwap( d->m_findNodeEnd, d->m_findNodeStart );
03109     qSwap( d->m_findPosEnd, d->m_findPosStart );
03110     qSwap( d->m_findNode, d->m_findNodePrevious );
03111     // d->m_findNode now point at the end of the last searched line - advance one node
03112     khtml::RenderObject* obj = d->m_findNode ? d->m_findNode->renderer() : 0;
03113     khtml::RenderObject* end = d->m_findNodeEnd ? d->m_findNodeEnd->renderer() : 0;
03114     if ( obj == end )
03115       obj = 0L;
03116     else
03117     {
03118       do {
03119         obj = (options & KFindDialog::FindBackwards) ? obj->objectAbove() : obj->objectBelow();
03120       } while ( obj && ( !obj->element() || obj->isInlineContinuation() ) );
03121     }
03122     if ( obj )
03123       d->m_findNode = obj->element();
03124     else
03125       d->m_findNode = 0;
03126   }
03127   d->m_lastFindState.last_dir = ( options & KFindDialog::FindBackwards ) ? 1 : 0;
03128 
03129   KFind::Result res = KFind::NoMatch;
03130   khtml::RenderObject* obj = d->m_findNode ? d->m_findNode->renderer() : 0;
03131   khtml::RenderObject* end = d->m_findNodeEnd ? d->m_findNodeEnd->renderer() : 0;
03132   khtml::RenderTextArea *tmpTextArea=0L;
03133   //kdDebug(6050) << k_funcinfo << "obj=" << obj << " end=" << end << endl;
03134   while( res == KFind::NoMatch )
03135   {
03136     if ( d->m_find->needData() )
03137     {
03138       if ( !obj ) {
03139         //kdDebug(6050) << k_funcinfo << "obj=0 -> done" << endl;
03140         break; // we're done
03141       }
03142       //kdDebug(6050) << k_funcinfo << " gathering data" << endl;
03143       // First make up the QString for the current 'line' (i.e. up to \n)
03144       // We also want to remember the DOMNode for every portion of the string.
03145       // We store this in an index->node list.
03146 
03147       d->m_stringPortions.clear();
03148       bool newLine = false;
03149       QString str;
03150       DOM::NodeImpl* lastNode = d->m_findNode;
03151       while ( obj && !newLine )
03152       {
03153         // Grab text from render object
03154         QString s;
03155         bool renderAreaText = obj->parent() && (QCString(obj->parent()->renderName())== "RenderTextArea");
03156         bool renderLineText = (QCString(obj->renderName())== "RenderLineEdit");
03157         if ( renderAreaText )
03158         {
03159           khtml::RenderTextArea *parent= static_cast<khtml::RenderTextArea *>(obj->parent());
03160           s = parent->text();
03161           s = s.replace(0xa0, ' ');
03162           tmpTextArea = parent;
03163         }
03164         else if ( renderLineText )
03165         {
03166           khtml::RenderLineEdit *parentLine= static_cast<khtml::RenderLineEdit *>(obj);
03167           if (parentLine->widget()->echoMode() == QLineEdit::Normal)
03168             s = parentLine->widget()->text();
03169           s = s.replace(0xa0, ' ');
03170         }
03171         else if ( obj->isText() )
03172         {
03173           bool isLink = false;
03174 
03175           // checks whether the node has a <A> parent
03176           if ( options & FindLinksOnly )
03177           {
03178             DOM::NodeImpl *parent = obj->element();
03179             while ( parent )
03180             {
03181               if ( parent->nodeType() == Node::ELEMENT_NODE && parent->id() == ID_A )
03182               {
03183                 isLink = true;
03184                 break;
03185               }
03186               parent = parent->parentNode();
03187             }
03188           }
03189           else
03190           {
03191             isLink = true;
03192           }
03193 
03194           if ( isLink && obj->parent()!=tmpTextArea )
03195           {
03196             s = static_cast<khtml::RenderText *>(obj)->data().string();
03197             s = s.replace(0xa0, ' ');
03198           }
03199         }
03200         else if ( obj->isBR() )
03201           s = '\n';
03202         else if ( !obj->isInline() && !str.isEmpty() )
03203           s = '\n';
03204 
03205         if ( lastNode == d->m_findNodeEnd )
03206           s.truncate( d->m_findPosEnd );
03207         if ( !s.isEmpty() )
03208         {
03209           newLine = s.find( '\n' ) != -1; // did we just get a newline?
03210           if( !( options & KFindDialog::FindBackwards ))
03211           {
03212             //kdDebug(6050) << "StringPortion: " << index << "-" << index+s.length()-1 << " -> " << lastNode << endl;
03213             d->m_stringPortions.append( KHTMLPartPrivate::StringPortion( str.length(), lastNode ) );
03214             str += s;
03215           }
03216           else // KFind itself can search backwards, so str must not be built backwards
03217           {
03218             for( QValueList<KHTMLPartPrivate::StringPortion>::Iterator it = d->m_stringPortions.begin();
03219                  it != d->m_stringPortions.end();
03220                  ++it )
03221                 (*it).index += s.length();
03222             d->m_stringPortions.prepend( KHTMLPartPrivate::StringPortion( 0, lastNode ) );
03223             str.prepend( s );
03224           }
03225         }
03226         // Compare obj and end _after_ we processed the 'end' node itself
03227         if ( obj == end )
03228           obj = 0L;
03229         else
03230         {
03231           // Move on to next object (note: if we found a \n already, then obj (and lastNode)
03232           // will point to the _next_ object, i.e. they are in advance.
03233           do {
03234             // We advance until the next RenderObject that has a NodeImpl as its element().
03235             // Otherwise (if we keep the 'last node', and it has a '\n') we might be stuck
03236             // on that object forever...
03237             obj = (options & KFindDialog::FindBackwards) ? obj->objectAbove() : obj->objectBelow();
03238           } while ( obj && ( !obj->element() || obj->isInlineContinuation() ) );
03239         }
03240         if ( obj )
03241           lastNode = obj->element();
03242         else
03243           lastNode = 0;
03244       } // end while
03245       //kdDebug()<<" str : "<<str<<endl;
03246       if ( !str.isEmpty() )
03247       {
03248         d->m_find->setData( str, d->m_findPos );
03249       }
03250 
03251       d->m_findPos = -1; // not used during the findnext loops. Only during init.
03252       d->m_findNodePrevious = d->m_findNode;
03253       d->m_findNode = lastNode;
03254     }
03255     if ( !d->m_find->needData() ) // happens if str was empty
03256     {
03257       // Let KFind inspect the text fragment, and emit highlighted if a match is found
03258       res = d->m_find->find();
03259     }
03260   } // end while
03261 
03262   if ( res == KFind::NoMatch ) // i.e. we're done
03263   {
03264     kdDebug() << "No more matches." << endl;
03265     if ( !(options & FindNoPopups) && d->m_find->shouldRestart() )
03266     {
03267       //kdDebug(6050) << "Restarting" << endl;
03268       initFindNode( false, options & KFindDialog::FindBackwards, false );
03269       findTextNext( reverse );
03270     }
03271     else // really done
03272     {
03273       //kdDebug(6050) << "Finishing" << endl;
03274       //delete d->m_find;
03275       //d->m_find = 0L;
03276       initFindNode( false, options & KFindDialog::FindBackwards, false );
03277       d->m_find->resetCounts();
03278       slotClearSelection();
03279     }
03280     kdDebug() << "Dialog closed." << endl;
03281   }
03282 
03283   return res == KFind::Match;
03284 }
03285 
03286 void KHTMLPart::slotHighlight( const QString& /*text*/, int index, int length )
03287 {
03288   //kdDebug(6050) << "slotHighlight index=" << index << " length=" << length << endl;
03289   QValueList<KHTMLPartPrivate::StringPortion>::Iterator it = d->m_stringPortions.begin();
03290   const QValueList<KHTMLPartPrivate::StringPortion>::Iterator itEnd = d->m_stringPortions.end();
03291   QValueList<KHTMLPartPrivate::StringPortion>::Iterator prev = it;
03292   // We stop at the first portion whose index is 'greater than', and then use the previous one
03293   while ( it != itEnd && (*it).index <= index )
03294   {
03295     prev = it;
03296     ++it;
03297   }
03298   Q_ASSERT ( prev != itEnd );
03299   DOM::NodeImpl* node = (*prev).node;
03300   Q_ASSERT( node );
03301 
03302   d->m_selectionStart = node;
03303   d->m_startOffset = index - (*prev).index;
03304 
03305   khtml::RenderObject* obj = node->renderer();
03306   khtml::RenderTextArea *parent = 0L;
03307   khtml::RenderLineEdit *parentLine = 0L;
03308   bool renderLineText =false;
03309 
03310   QRect highlightedRect;
03311   bool renderAreaText =false;
03312   Q_ASSERT( obj );
03313   if ( obj )
03314   {
03315     int x = 0, y = 0;
03316     renderAreaText = (QCString(obj->parent()->renderName())== "RenderTextArea");
03317     renderLineText = (QCString(obj->renderName())== "RenderLineEdit");
03318 
03319 
03320     if( renderAreaText )
03321       parent= static_cast<khtml::RenderTextArea *>(obj->parent());
03322     if ( renderLineText )
03323       parentLine= static_cast<khtml::RenderLineEdit *>(obj);
03324     if ( !renderLineText )
03325       //if (static_cast<khtml::RenderText *>(node->renderer())
03326       //    ->posOfChar(d->m_startOffset, x, y))
03327       {
03328         int dummy;
03329         static_cast<khtml::RenderText *>(node->renderer())
03330           ->caretPos( d->m_startOffset, false, x, y, dummy, dummy ); // more precise than posOfChar
03331         //kdDebug(6050) << "topleft: " << x << "," << y << endl;
03332         if ( x != -1 || y != -1 )
03333         {
03334           int gox = d->m_view->contentsX();
03335           if (x+50 > d->m_view->contentsX() + d->m_view->visibleWidth())
03336               gox = x - d->m_view->visibleWidth() + 50;
03337           if (x-10 < d->m_view->contentsX())
03338               gox = x - d->m_view->visibleWidth() - 10;
03339           if (gox < 0) gox = 0;
03340           d->m_view->setContentsPos(gox, y-50);
03341           highlightedRect.setTopLeft( d->m_view->mapToGlobal(QPoint(x, y)) );
03342         }
03343       }
03344   }
03345   // Now look for end node
03346   it = prev; // no need to start from beginning again
03347   while ( it != itEnd && (*it).index < index + length )
03348   {
03349     prev = it;
03350     ++it;
03351   }
03352   Q_ASSERT ( prev != itEnd );
03353 
03354   d->m_selectionEnd = (*prev).node;
03355   d->m_endOffset = index + length - (*prev).index;
03356   d->m_startBeforeEnd = true;
03357 
03358   // if the selection is limited to a single link, that link gets focus
03359   if(d->m_selectionStart == d->m_selectionEnd)
03360   {
03361     bool isLink = false;
03362 
03363     // checks whether the node has a <A> parent
03364     DOM::NodeImpl *parent = d->m_selectionStart.handle();
03365     while ( parent )
03366     {
03367       if ( parent->nodeType() == Node::ELEMENT_NODE && parent->id() == ID_A )
03368       {
03369         isLink = true;
03370         break;
03371       }
03372       parent = parent->parentNode();
03373     }
03374 
03375     if(isLink == true)
03376     {
03377       d->m_doc->setFocusNode( parent );
03378     }
03379   }
03380 
03381 #if 0
03382   kdDebug(6050) << "slotHighlight: " << d->m_selectionStart.handle() << "," << d->m_startOffset << " - " <<
03383     d->m_selectionEnd.handle() << "," << d->m_endOffset << endl;
03384   it = d->m_stringPortions.begin();
03385   for ( ; it != d->m_stringPortions.end() ; ++it )
03386     kdDebug(6050) << "  StringPortion: from index=" << (*it).index << " -> node=" << (*it).node << endl;
03387 #endif
03388   if( renderAreaText )
03389   {
03390     if( parent )
03391       parent->highLightWord( length, d->m_endOffset-length );
03392   }
03393   else if ( renderLineText )
03394   {
03395     if( parentLine )
03396       parentLine->highLightWord( length, d->m_endOffset-length );
03397   }
03398   else
03399   {
03400     d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
03401                             d->m_selectionEnd.handle(), d->m_endOffset );
03402     if (d->m_selectionEnd.handle()->renderer() )
03403     {
03404       int x, y, height, dummy;
03405       static_cast<khtml::RenderText *>(d->m_selectionEnd.handle()->renderer())
03406           ->caretPos( d->m_endOffset, false, x, y, dummy, height ); // more precise than posOfChar
03407       //kdDebug(6050) << "bottomright: " << x << "," << y+height << endl;
03408       if ( x != -1 || y != -1 )
03409       {
03410         // if ( static_cast<khtml::RenderText *>(d->m_selectionEnd.handle()->renderer())
03411         //  ->posOfChar(d->m_endOffset-1, x, y))
03412         highlightedRect.setBottomRight( d->m_view->mapToGlobal( QPoint(x, y+height) ) );
03413       }
03414     }
03415   }
03416   emitSelectionChanged();
03417 
03418   // make the finddialog move away from the selected area
03419   if ( d->m_findDialog && !highlightedRect.isNull() )
03420   {
03421     highlightedRect.moveBy( -d->m_view->contentsX(), -d->m_view->contentsY() );
03422     //kdDebug(6050) << "avoiding " << highlightedRect << endl;
03423     KDialog::avoidArea( d->m_findDialog, highlightedRect );
03424   }
03425 }
03426 
03427 QString KHTMLPart::selectedTextAsHTML() const
03428 {
03429   if(!hasSelection()) {
03430     kdDebug() << "selectedTextAsHTML(): selection is not valid.  Returning empty selection" << endl;
03431     return QString::null;
03432   }
03433   if(d->m_startOffset < 0 || d->m_endOffset <0) {
03434     kdDebug() << "invalid values for end/startOffset " << d->m_startOffset << " " << d->m_endOffset << endl;
03435     return QString::null;
03436   }
03437   DOM::Range r = selection();
03438   if(r.isNull() || r.isDetached())
03439     return QString::null;
03440   int exceptioncode = 0; //ignore the result
03441   return r.handle()->toHTML(exceptioncode).string();
03442 }
03443 
03444 QString KHTMLPart::selectedText() const
03445 {
03446   bool hasNewLine = true;
03447   bool seenTDTag = false;
03448   QString text;
03449   DOM::Node n = d->m_selectionStart;
03450   while(!n.isNull()) {
03451       if(n.nodeType() == DOM::Node::TEXT_NODE && n.handle()->renderer()) {
03452         DOM::DOMStringImpl *dstr = static_cast<DOM::TextImpl*>(n.handle())->renderString();
03453         QString str(dstr->s, dstr->l);
03454     if(!str.isEmpty()) {
03455           if(seenTDTag) {
03456         text += "  ";
03457         seenTDTag = false;
03458       }
03459           hasNewLine = false;
03460           if(n == d->m_selectionStart && n == d->m_selectionEnd)
03461             text = str.mid(d->m_startOffset, d->m_endOffset - d->m_startOffset);
03462           else if(n == d->m_selectionStart)
03463             text = str.mid(d->m_startOffset);
03464           else if(n == d->m_selectionEnd)
03465             text += str.left(d->m_endOffset);
03466           else
03467             text += str;
03468     }
03469       }
03470       else {
03471         // This is our simple HTML -> ASCII transformation:
03472         unsigned short id = n.elementId();
03473         switch(id) {
03474       case ID_TEXTAREA:
03475         text += static_cast<HTMLTextAreaElementImpl*>(n.handle())->value().string();
03476         break;
03477       case ID_INPUT:
03478             if (static_cast<HTMLInputElementImpl*>(n.handle())->inputType() != HTMLInputElementImpl::PASSWORD)
03479           text += static_cast<HTMLInputElementImpl*>(n.handle())->value().string();
03480         break;
03481       case ID_SELECT:
03482         text += static_cast<HTMLSelectElementImpl*>(n.handle())->value().string();
03483         break;
03484           case ID_BR:
03485             text += "\n";
03486             hasNewLine = true;
03487             break;
03488           case ID_IMG:
03489         text += static_cast<HTMLImageElementImpl*>(n.handle())->altText().string();
03490         break;
03491           case ID_TD:
03492         break;
03493           case ID_TH:
03494           case ID_HR:
03495           case ID_OL:
03496           case ID_UL:
03497           case ID_LI:
03498           case ID_DD:
03499           case ID_DL:
03500           case ID_DT:
03501           case ID_PRE:
03502           case ID_BLOCKQUOTE:
03503           case ID_DIV:
03504             if (!hasNewLine)
03505                text += "\n";
03506             hasNewLine = true;
03507             break;
03508           case ID_P:
03509           case ID_TR:
03510           case ID_H1:
03511           case ID_H2:
03512           case ID_H3:
03513           case ID_H4:
03514           case ID_H5:
03515           case ID_H6:
03516             if (!hasNewLine)
03517                text += "\n";
03518 //            text += "\n";
03519             hasNewLine = true;
03520             break;
03521         }
03522       }
03523       if(n == d->m_selectionEnd) break;
03524       DOM::Node next = n.firstChild();
03525       if(next.isNull()) next = n.nextSibling();
03526       while( next.isNull() && !n.parentNode().isNull() ) {
03527         n = n.parentNode();
03528         next = n.nextSibling();
03529         unsigned short id = n.elementId();
03530         switch(id) {
03531           case ID_TD:
03532         seenTDTag = true; //Add two spaces after a td if then followed by text.
03533         break;
03534           case ID_TH:
03535           case ID_HR:
03536           case ID_OL:
03537           case ID_UL:
03538           case ID_LI:
03539           case ID_DD:
03540           case ID_DL:
03541           case ID_DT:
03542           case ID_PRE:
03543           case ID_BLOCKQUOTE:
03544           case ID_DIV:
03545         seenTDTag = false;
03546             if (!hasNewLine)
03547                text += "\n";
03548             hasNewLine = true;
03549             break;
03550           case ID_P:
03551           case ID_TR:
03552           case ID_H1:
03553           case ID_H2:
03554           case ID_H3:
03555           case ID_H4:
03556           case ID_H5:
03557           case ID_H6:
03558             if (!hasNewLine)
03559                text += "\n";
03560 //            text += "\n";
03561             hasNewLine = true;
03562             break;
03563         }
03564       }
03565 
03566       n = next;
03567     }
03568 
03569     if(text.isEmpty())
03570         return QString::null;
03571 
03572     int start = 0;
03573     int end = text.length();
03574 
03575     // Strip leading LFs
03576     while ((start < end) && (text[start] == '\n'))
03577        ++start;
03578 
03579     // Strip excessive trailing LFs
03580     while ((start < (end-1)) && (text[end-1] == '\n') && (text[end-2] == '\n'))
03581        --end;
03582 
03583     return text.mid(start, end-start);
03584 }
03585 
03586 bool KHTMLPart::hasSelection() const
03587 {
03588   if ( d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() )
03589       return false;
03590   if ( d->m_selectionStart == d->m_selectionEnd &&
03591        d->m_startOffset == d->m_endOffset )
03592       return false; // empty
03593   return true;
03594 }
03595 
03596 DOM::Range KHTMLPart::selection() const
03597 {
03598     if( d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() )
03599         return DOM::Range();
03600     DOM::Range r = document().createRange();
03601     RangeImpl *rng = r.handle();
03602     int exception = 0;
03603     NodeImpl *n = d->m_selectionStart.handle();
03604     if(!n->parentNode() ||
03605        !n->renderer() ||
03606        (!n->renderer()->isReplaced() && !n->renderer()->isBR())) {
03607         rng->setStart( n, d->m_startOffset, exception );
03608     if(exception) {
03609         kdDebug(6000) << "1 -selection() threw the exception " << exception << ".  Returning empty range." << endl;
03610         return DOM::Range();
03611     }
03612     } else {
03613         int o_start = 0;
03614         while ((n = n->previousSibling()))
03615             o_start++;
03616     rng->setStart( d->m_selectionStart.parentNode().handle(), o_start + d->m_startOffset, exception );
03617     if(exception) {
03618         kdDebug(6000) << "2 - selection() threw the exception " << exception << ".  Returning empty range." << endl;
03619         return DOM::Range();
03620     }
03621 
03622     }
03623 
03624     n = d->m_selectionEnd.handle();
03625     if(!n->parentNode() ||
03626        !n->renderer() ||
03627        (!n->renderer()->isReplaced() && !n->renderer()->isBR())) {
03628 
03629     rng->setEnd( n, d->m_endOffset, exception );
03630     if(exception) {
03631         kdDebug(6000) << "3 - selection() threw the exception " << exception << ".  Returning empty range." << endl;
03632         return DOM::Range();
03633     }
03634 
03635     } else {
03636         int o_end = 0;
03637         while ((n = n->previousSibling()))
03638             o_end++;
03639     rng->setEnd( d->m_selectionEnd.parentNode().handle(), o_end + d->m_endOffset, exception);
03640     if(exception) {
03641         kdDebug(6000) << "4 - selection() threw the exception " << exception << ".  Returning empty range." << endl;
03642         return DOM::Range();
03643     }
03644 
03645     }
03646 
03647     return r;
03648 }
03649 
03650 void KHTMLPart::selection(DOM::Node &s, long &so, DOM::Node &e, long &eo) const
03651 {
03652     s = d->m_selectionStart;
03653     so = d->m_startOffset;
03654     e = d->m_selectionEnd;
03655     eo = d->m_endOffset;
03656 }
03657 
03658 void KHTMLPart::setSelection( const DOM::Range &r )
03659 {
03660     // Quick-fix: a collapsed range shouldn't select the whole node.
03661     // The real problem is in RenderCanvas::setSelection though (when index==0 the whole node is selected).
03662     if ( r.collapsed() )
03663         slotClearSelection();
03664     else {
03665         d->m_selectionStart = r.startContainer();
03666         d->m_startOffset = r.startOffset();
03667         d->m_selectionEnd = r.endContainer();
03668         d->m_endOffset = r.endOffset();
03669         d->m_doc->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
03670                                d->m_selectionEnd.handle(),d->m_endOffset);
03671 #ifndef KHTML_NO_CARET
03672         bool v = d->m_view->placeCaret();
03673         emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
03674 #endif
03675     }
03676 }
03677 
03678 void KHTMLPart::slotClearSelection()
03679 {
03680     bool hadSelection = hasSelection();
03681 #ifndef KHTML_NO_CARET
03682     //kdDebug(6000) << "d->m_selectionStart " << d->m_selectionStart.handle()
03683     //      << " d->m_selectionEnd " << d->m_selectionEnd.handle() << endl;
03684     // nothing, leave selection parameters as is
03685 #else
03686     d->m_selectionStart = 0;
03687     d->m_startOffset = 0;
03688     d->m_selectionEnd = 0;
03689     d->m_endOffset = 0;
03690 #endif
03691     if ( d->m_doc ) d->m_doc->clearSelection();
03692     if ( hadSelection )
03693       emitSelectionChanged();
03694 #ifndef KHTML_NO_CARET
03695     bool v = d->m_view->placeCaret();
03696     emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
03697 #endif
03698 }
03699 
03700 void KHTMLPart::resetHoverText()
03701 {
03702    if( !d->m_overURL.isEmpty() ) // Only if we were showing a link
03703    {
03704      d->m_overURL = d->m_overURLTarget = QString::null;
03705      emit onURL( QString::null );
03706      // revert to default statusbar text
03707      setStatusBarText(QString::null, BarHoverText);
03708      emit d->m_extension->mouseOverInfo(0);
03709   }
03710 }
03711 
03712 void KHTMLPart::overURL( const QString &url, const QString &target, bool /*shiftPressed*/ )
03713 {
03714   KURL u = completeURL(url);
03715 
03716   // special case for <a href="">
03717   if ( url.isEmpty() )
03718     u.setFileName( url );
03719 
03720   emit onURL( url );
03721 
03722   if ( url.isEmpty() ) {
03723     setStatusBarText(u.htmlURL(), BarHoverText);
03724     return;
03725   }
03726 
03727   if (url.find( QString::fromLatin1( "javascript:" ),0, false ) == 0 ) {
03728     QString jscode = KURL::decode_string( url.mid( url.find( "javascript:", 0, false ) ) );
03729     jscode = KStringHandler::rsqueeze( jscode, 80 ); // truncate if too long
03730     if (url.startsWith("javascript:window.open"))
03731       jscode += i18n(" (In new window)");
03732     setStatusBarText( QStyleSheet::escape( jscode ), BarHoverText );
03733     return;
03734   }
03735 
03736   KFileItem item(u, QString::null, KFileItem::Unknown);
03737   emit d->m_extension->mouseOverInfo(&item);
03738 
03739   QString com;
03740 
03741   KMimeType::Ptr typ = KMimeType::findByURL( u );
03742 
03743   if ( typ )
03744     com = typ->comment( u, false );
03745 
03746   if ( !u.isValid() ) {
03747     setStatusBarText(u.htmlURL(), BarHoverText);
03748     return;
03749   }
03750 
03751   if ( u.isLocalFile() )
03752   {
03753     // TODO : use KIO::stat() and create a KFileItem out of its result,
03754     // to use KFileItem::statusBarText()
03755     QCString path = QFile::encodeName( u.path() );
03756 
03757     struct stat buff;
03758     bool ok = !stat( path.data(), &buff );
03759 
03760     struct stat lbuff;
03761     if (ok) ok = !lstat( path.data(), &lbuff );
03762 
03763     QString text = u.htmlURL();
03764     QString text2 = text;
03765 
03766     if (ok && S_ISLNK( lbuff.st_mode ) )
03767     {
03768       QString tmp;
03769       if ( com.isNull() )
03770         tmp = i18n( "Symbolic Link");
03771       else
03772         tmp = i18n("%1 (Link)").arg(com);
03773       char buff_two[1024];
03774       text += " -> ";
03775       int n = readlink ( path.data(), buff_two, 1022);
03776       if (n == -1)
03777       {
03778         text2 += "  ";
03779         text2 += tmp;
03780         setStatusBarText(text2, BarHoverText);
03781         return;
03782       }
03783       buff_two[n] = 0;
03784 
03785       text += buff_two;
03786       text += "  ";
03787       text += tmp;
03788     }
03789     else if ( ok && S_ISREG( buff.st_mode ) )
03790     {
03791       if (buff.st_size < 1024)
03792         text = i18n("%2 (%1 bytes)").arg((long) buff.st_size).arg(text2); // always put the URL last, in case it contains '%'
03793       else
03794       {
03795         float d = (float) buff.st_size/1024.0;
03796         text = i18n("%2 (%1 K)").arg(KGlobal::locale()->formatNumber(d, 2)).arg(text2); // was %.2f
03797       }
03798       text += "  ";
03799       text += com;
03800     }
03801     else if ( ok && S_ISDIR( buff.st_mode ) )
03802     {
03803       text += "  ";
03804       text += com;
03805     }
03806     else
03807     {
03808       text += "  ";
03809       text += com;
03810     }
03811     setStatusBarText(text, BarHoverText);
03812   }
03813   else
03814   {
03815     QString extra;
03816     if (target.lower() == "_blank")
03817     {
03818       extra = i18n(" (In new window)");
03819     }
03820     else if (!target.isEmpty() &&
03821              (target.lower() != "_top") &&
03822              (target.lower() != "_self") &&
03823              (target.lower() != "_parent"))
03824     {
03825       KHTMLPart *p = this;
03826       while (p->parentPart())
03827           p = p->parentPart();
03828       if (!p->frameExists(target))
03829         extra = i18n(" (In new window)");
03830       else
03831         extra = i18n(" (In other frame)");
03832     }
03833 
03834     if (u.protocol() == QString::fromLatin1("mailto")) {
03835       QString mailtoMsg /* = QString::fromLatin1("<img src=%1>").arg(locate("icon", QString::fromLatin1("locolor/16x16/actions/mail_send.png")))*/;
03836       mailtoMsg += i18n("Email to: ") + KURL::decode_string(u.path());
03837       QStringList queries = QStringList::split('&', u.query().mid(1));
03838       QStringList::Iterator it = queries.begin();
03839       const QStringList::Iterator itEnd = queries.end();
03840       for (; it != itEnd; ++it)
03841         if ((*it).startsWith(QString::fromLatin1("subject=")))
03842           mailtoMsg += i18n(" - Subject: ") + KURL::decode_string((*it).mid(8));
03843         else if ((*it).startsWith(QString::fromLatin1("cc=")))
03844           mailtoMsg += i18n(" - CC: ") + KURL::decode_string((*it).mid(3));
03845         else if ((*it).startsWith(QString::fromLatin1("bcc=")))
03846           mailtoMsg += i18n(" - BCC: ") + KURL::decode_string((*it).mid(4));
03847       mailtoMsg = QStyleSheet::escape(mailtoMsg);
03848       mailtoMsg.replace(QRegExp("([\n\r\t]|[ ]{10})"), QString::null);
03849       setStatusBarText("<qt>"+mailtoMsg, BarHoverText);
03850       return;
03851     }
03852    // Is this check necessary at all? (Frerich)
03853 #if 0
03854     else if (u.protocol() == QString::fromLatin1("http")) {
03855         DOM::Node hrefNode = nodeUnderMouse().parentNode();
03856         while (hrefNode.nodeName().string() != QString::fromLatin1("A") && !hrefNode.isNull())
03857           hrefNode = hrefNode.parentNode();
03858 
03859         if (!hrefNode.isNull()) {
03860           DOM::Node hreflangNode = hrefNode.attributes().getNamedItem("HREFLANG");
03861           if (!hreflangNode.isNull()) {
03862             QString countryCode = hreflangNode.nodeValue().string().lower();
03863             // Map the language code to an appropriate country code.
03864             if (countryCode == QString::fromLatin1("en"))
03865               countryCode = QString::fromLatin1("gb");
03866             QString flagImg = QString::fromLatin1("<img src=%1>").arg(
03867                 locate("locale", QString::fromLatin1("l10n/")
03868                 + countryCode
03869                 + QString::fromLatin1("/flag.png")));
03870             emit setStatusBarText(flagImg + u.prettyURL() + extra);
03871           }
03872         }
03873       }
03874 #endif
03875     setStatusBarText(u.htmlURL() + extra, BarHoverText);
03876   }
03877 }
03878 
03879 //
03880 // This executes in the active part on a click or other url selection action in
03881 // that active part.
03882 //
03883 void KHTMLPart::urlSelected( const QString &url, int button, int state, const QString &_target, KParts::URLArgs args )
03884 {
03885   // The member var is so that slotRedirection still calls the virtual urlSelected
03886   // but is able to know if is opened a url. KDE4: just make urlSelected return a bool
03887   // and move the urlSelectedIntern code back here.
03888   d->m_urlSelectedOpenedURL = urlSelectedIntern( url, button, state, _target, args );
03889 }
03890 
03891 // Return value: true if an url was opened, false if not (e.g. error, or jumping to anchor)
03892 bool KHTMLPart::urlSelectedIntern( const QString &url, int button, int state, const QString &_target, KParts::URLArgs args )
03893 {
03894   bool hasTarget = false;
03895 
03896   QString target = _target;
03897   if ( target.isEmpty() && d->m_doc )
03898     target = d->m_doc->baseTarget();
03899   if ( !target.isEmpty() )
03900       hasTarget = true;
03901 
03902   if ( url.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
03903   {
03904     crossFrameExecuteScript( target, KURL::decode_string( url.mid( 11 ) ) );
03905     return false;
03906   }
03907 
03908   KURL cURL = completeURL(url);
03909   // special case for <a href="">  (IE removes filename, mozilla doesn't)
03910   if ( url.isEmpty() )
03911     cURL.setFileName( url ); // removes filename
03912 
03913   if ( !cURL.isValid() )
03914     // ### ERROR HANDLING
03915     return false;
03916 
03917   kdDebug(6050) << this << " urlSelected: complete URL:" << cURL.url() << " target=" << target << endl;
03918 
03919   if ( state & ControlButton )
03920   {
03921     args.setNewTab(true);
03922     emit d->m_extension->createNewWindow( cURL, args );
03923     return true;
03924   }
03925 
03926   if ( button == LeftButton && ( state & ShiftButton ) )
03927   {
03928     KIO::MetaData metaData;
03929     metaData["referrer"] = d->m_referrer;
03930     KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), cURL, metaData );
03931     return false;
03932   }
03933 
03934   if (!checkLinkSecurity(cURL,
03935              i18n( "<qt>This untrusted page links to<BR><B>%1</B>.<BR>Do you want to follow the link?" ),
03936              i18n( "Follow" )))
03937     return false;
03938 
03939   args.frameName = target;
03940 
03941   args.metaData().insert("main_frame_request",
03942                          parentPart() == 0 ? "TRUE":"FALSE");
03943   args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
03944   args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
03945   args.metaData().insert("PropagateHttpHeader", "true");
03946   args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
03947   args.metaData().insert("ssl_activate_warnings", "TRUE");
03948 
03949   if ( hasTarget && target != "_self" && target != "_top" && target != "_blank" && target != "_parent" )
03950   {
03951     // unknown frame names should open in a new window.
03952     khtml::ChildFrame *frame = recursiveFrameRequest( this, cURL, args, false );
03953     if ( frame )
03954     {
03955       args.metaData()["referrer"] = d->m_referrer;
03956       requestObject( frame, cURL, args );
03957       return true;
03958     }
03959   }
03960 
03961   if (!d->m_referrer.isEmpty() && !args.metaData().contains("referrer"))
03962     args.metaData()["referrer"] = d->m_referrer;
03963 
03964 
03965   if ( button == NoButton && (state & ShiftButton) && (state & ControlButton) )
03966   {
03967     emit d->m_extension->createNewWindow( cURL, args );
03968     return true;
03969   }
03970 
03971   if ( state & ShiftButton)
03972   {
03973     KParts::WindowArgs winArgs;
03974     winArgs.lowerWindow = true;
03975     KParts::ReadOnlyPart *newPart = 0;
03976     emit d->m_extension->createNewWindow( cURL, args, winArgs, newPart );
03977     return true;
03978   }
03979 
03980   //If we're asked to open up an anchor in the current URL, in current window,
03981   //merely gotoanchor, and do not reload the new page. Note that this does
03982   //not apply if the URL is the same page, but without a ref
03983   if (cURL.hasRef() && (!hasTarget || target == "_self"))
03984   {
03985     KURL curUrl = this->url();
03986     if (urlcmp(cURL.url(), curUrl.url(),
03987               false,  // ignore trailing / diff, IE does, even if FFox doesn't
03988               true))  // don't care if the ref changes!
03989     {
03990       m_url = cURL;
03991       emit d->m_extension->openURLNotify();
03992       if ( !gotoAnchor( m_url.encodedHtmlRef()) )
03993         gotoAnchor( m_url.htmlRef() );
03994       emit d->m_extension->setLocationBarURL( m_url.prettyURL() );
03995       return false; // we jumped, but we didn't open a URL
03996     }
03997   }
03998 
03999   if ( !d->m_bComplete && !hasTarget )
04000     closeURL();
04001 
04002   view()->viewport()->unsetCursor();
04003   emit d->m_extension->openURLRequest( cURL, args );
04004   return true;
04005 }
04006 
04007 void KHTMLPart::slotViewDocumentSource()
04008 {
04009   KURL url(m_url);
04010   bool isTempFile = false;
04011   if (!(url.isLocalFile()) && KHTMLPageCache::self()->isComplete(d->m_cacheId))
04012   {
04013      KTempFile sourceFile(QString::null, defaultExtension());
04014      if (sourceFile.status() == 0)
04015      {
04016         KHTMLPageCache::self()->saveData(d->m_cacheId, sourceFile.dataStream());
04017         url = KURL();
04018         url.setPath(sourceFile.name());
04019         isTempFile = true;
04020      }
04021   }
04022 
04023   (void) KRun::runURL( url, QString::fromLatin1("text/plain"), isTempFile );
04024 }
04025 
04026 void KHTMLPart::slotViewPageInfo()
04027 {
04028   KHTMLInfoDlg *dlg = new KHTMLInfoDlg(NULL, "KHTML Page Info Dialog", false, WDestructiveClose);
04029   dlg->_close->setGuiItem(KStdGuiItem::close());
04030 
04031   if (d->m_doc)
04032      dlg->_title->setText(d->m_doc->title().string());
04033 
04034   // If it's a frame, set the caption to "Frame Information"
04035   if ( parentPart() && d->m_doc && d->m_doc->isHTMLDocument() ) {
04036      dlg->setCaption(i18n("Frame Information"));
04037   }
04038 
04039   QString editStr = QString::null;
04040 
04041   if (!d->m_pageServices.isEmpty())
04042     editStr = i18n("   <a href=\"%1\">[Properties]</a>").arg(d->m_pageServices);
04043 
04044   QString squeezedURL = KStringHandler::csqueeze( url().prettyURL(), 80 );
04045   dlg->_url->setText("<a href=\"" + url().url() + "\">" + squeezedURL + "</a>" + editStr);
04046   if (lastModified().isEmpty())
04047   {
04048     dlg->_lastModified->hide();
04049     dlg->_lmLabel->hide();
04050   }
04051   else
04052     dlg->_lastModified->setText(lastModified());
04053 
04054   const QString& enc = encoding();
04055   if (enc.isEmpty()) {
04056     dlg->_eLabel->hide();
04057     dlg->_encoding->hide();
04058   } else {
04059     dlg->_encoding->setText(enc);
04060   }
04061   /* populate the list view now */
04062   const QStringList headers = QStringList::split("\n", d->m_httpHeaders);
04063 
04064   QStringList::ConstIterator it = headers.begin();
04065   const QStringList::ConstIterator itEnd = headers.end();
04066 
04067   for (; it != itEnd; ++it) {
04068     const QStringList header = QStringList::split(QRegExp(":[ ]+"), *it);
04069     if (header.count() != 2)
04070        continue;
04071     new QListViewItem(dlg->_headers, header[0], header[1]);
04072   }
04073 
04074   dlg->show();
04075   /* put no code here */
04076 }
04077 
04078 
04079 void KHTMLPart::slotViewFrameSource()
04080 {
04081   KParts::ReadOnlyPart *frame = currentFrame();
04082   if ( !frame )
04083     return;
04084 
04085   KURL url = frame->url();
04086   bool isTempFile = false;
04087   if (!(url.isLocalFile()) && frame->inherits("KHTMLPart"))
04088   {
04089        long cacheId = static_cast<KHTMLPart *>(frame)->d->m_cacheId;
04090 
04091        if (KHTMLPageCache::self()->isComplete(cacheId))
04092        {
04093            KTempFile sourceFile(QString::null, defaultExtension());
04094            if (sourceFile.status() == 0)
04095            {
04096                KHTMLPageCache::self()->saveData(cacheId, sourceFile.dataStream());
04097                url = KURL();
04098                url.setPath(sourceFile.name());
04099                isTempFile = true;
04100            }
04101      }
04102   }
04103 
04104   (void) KRun::runURL( url, QString::fromLatin1("text/plain"), isTempFile );
04105 }
04106 
04107 KURL KHTMLPart::backgroundURL() const
04108 {
04109   // ### what about XML documents? get from CSS?
04110   if (!d->m_doc || !d->m_doc->isHTMLDocument())
04111     return KURL();
04112 
04113   QString relURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
04114 
04115   return KURL( m_url, relURL );
04116 }
04117 
04118 void KHTMLPart::slotSaveBackground()
04119 {
04120   KIO::MetaData metaData;
04121   metaData["referrer"] = d->m_referrer;
04122   KHTMLPopupGUIClient::saveURL( d->m_view, i18n("Save Background Image As"), backgroundURL(), metaData );
04123 }
04124 
04125 void KHTMLPart::slotSaveDocument()
04126 {
04127   KURL srcURL( m_url );
04128 
04129   if ( srcURL.fileName(false).isEmpty() )
04130     srcURL.setFileName( "index" + defaultExtension() );
04131 
04132   KIO::MetaData metaData;
04133   // Referre unknown?
04134   KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), srcURL, metaData, "text/html", d->m_cacheId );
04135 }
04136 
04137 void KHTMLPart::slotSecurity()
04138 {
04139 //   kdDebug( 6050 ) << "Meta Data:" << endl
04140 //                   << d->m_ssl_peer_cert_subject
04141 //                   << endl
04142 //                   << d->m_ssl_peer_cert_issuer
04143 //                   << endl
04144 //                   << d->m_ssl_cipher
04145 //                   << endl
04146 //                   << d->m_ssl_cipher_desc
04147 //                   << endl
04148 //                   << d->m_ssl_cipher_version
04149 //                   << endl
04150 //                   << d->m_ssl_good_from
04151 //                   << endl
04152 //                   << d->m_ssl_good_until
04153 //                   << endl
04154 //                   << d->m_ssl_cert_state
04155 //                   << endl;
04156 
04157   KSSLInfoDlg *kid = new KSSLInfoDlg(d->m_ssl_in_use, widget(), "kssl_info_dlg", true );
04158 
04159   if (d->m_bSecurityInQuestion)
04160       kid->setSecurityInQuestion(true);
04161 
04162   if (d->m_ssl_in_use) {
04163     KSSLCertificate *x = KSSLCertificate::fromString(d->m_ssl_peer_certificate.local8Bit());
04164     if (x) {
04165        // Set the chain back onto the certificate
04166        const QStringList cl = QStringList::split(QString("\n"), d->m_ssl_peer_chain);
04167        QPtrList<KSSLCertificate> ncl;
04168 
04169        ncl.setAutoDelete(true);
04170        QStringList::ConstIterator it = cl.begin();
04171        const QStringList::ConstIterator itEnd = cl.end();
04172        for (; it != itEnd; ++it) {
04173           KSSLCertificate* const y = KSSLCertificate::fromString((*it).local8Bit());
04174           if (y) ncl.append(y);
04175        }
04176 
04177        if (ncl.count() > 0)
04178           x->chain().setChain(ncl);
04179 
04180        kid->setup(x,
04181                   d->m_ssl_peer_ip,
04182                   m_url.url(),
04183                   d->m_ssl_cipher,
04184                   d->m_ssl_cipher_desc,
04185                   d->m_ssl_cipher_version,
04186                   d->m_ssl_cipher_used_bits.toInt(),
04187                   d->m_ssl_cipher_bits.toInt(),
04188                   (KSSLCertificate::KSSLValidation) d->m_ssl_cert_state.toInt()
04189                   );
04190         kid->exec();
04191         delete x;
04192      } else kid->exec();
04193   } else kid->exec();
04194 }
04195 
04196 void KHTMLPart::slotSaveFrame()
04197 {
04198     KParts::ReadOnlyPart *frame = currentFrame();
04199     if ( !frame )
04200         return;
04201 
04202     KURL srcURL( frame->url() );
04203 
04204     if ( srcURL.fileName(false).isEmpty() )
04205         srcURL.setFileName( "index" + defaultExtension() );
04206 
04207     KIO::MetaData metaData;
04208     // Referrer unknown?
04209     KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save Frame As" ), srcURL, metaData, "text/html" );
04210 }
04211 
04212 void KHTMLPart::slotSetEncoding()
04213 {
04214   d->m_automaticDetection->setItemChecked( int( d->m_autoDetectLanguage ), false );
04215   d->m_paSetEncoding->popupMenu()->setItemChecked( 0, false );
04216   d->m_paSetEncoding->popupMenu()->setItemChecked( d->m_paSetEncoding->popupMenu()->idAt( 2 ), true );
04217 
04218   QString enc = KGlobal::charsets()->encodingForName( d->m_manualDetection->currentText() );
04219   setEncoding( enc, true );
04220 }
04221 
04222 void KHTMLPart::slotUseStylesheet()
04223 {
04224   if (d->m_doc)
04225   {
04226     bool autoselect = (d->m_paUseStylesheet->currentItem() == 0);
04227     d->m_sheetUsed = autoselect ? QString() : d->m_paUseStylesheet->currentText();
04228     d->m_doc->updateStyleSelector();
04229   }
04230 }
04231 
04232 void KHTMLPart::updateActions()
04233 {
04234   bool frames = false;
04235 
04236   QValueList<khtml::ChildFrame*>::ConstIterator it = d->m_frames.begin();
04237   const QValueList<khtml::ChildFrame*>::ConstIterator end = d->m_frames.end();
04238   for (; it != end; ++it )
04239       if ( (*it)->m_type == khtml::ChildFrame::Frame )
04240       {
04241           frames = true;
04242           break;
04243       }
04244 
04245   d->m_paViewFrame->setEnabled( frames );
04246   d->m_paSaveFrame->setEnabled( frames );
04247 
04248   if ( frames )
04249     d->m_paFind->setText( i18n( "&Find in Frame..." ) );
04250   else
04251     d->m_paFind->setText( i18n( "&Find..." ) );
04252 
04253   KParts::Part *frame = 0;
04254 
04255   if ( frames )
04256     frame = currentFrame();
04257 
04258   bool enableFindAndSelectAll = true;
04259 
04260   if ( frame )
04261     enableFindAndSelectAll = frame->inherits( "KHTMLPart" );
04262 
04263   d->m_paFind->setEnabled( enableFindAndSelectAll );
04264   d->m_paSelectAll->setEnabled( enableFindAndSelectAll );
04265 
04266   bool enablePrintFrame = false;
04267 
04268   if ( frame )
04269   {
04270     QObject *ext = KParts::BrowserExtension::childObject( frame );
04271     if ( ext )
04272       enablePrintFrame = ext->metaObject()->slotNames().contains( "print()" );
04273   }
04274 
04275   d->m_paPrintFrame->setEnabled( enablePrintFrame );
04276 
04277   QString bgURL;
04278 
04279   // ### frames
04280   if ( d->m_doc && d->m_doc->isHTMLDocument() && static_cast<HTMLDocumentImpl*>(d->m_doc)->body() && !d->m_bClearing )
04281     bgURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
04282 
04283   d->m_paSaveBackground->setEnabled( !bgURL.isEmpty() );
04284 
04285   if ( d->m_paDebugScript )
04286     d->m_paDebugScript->setEnabled( d->m_frame ? d->m_frame->m_jscript : 0L );
04287 }
04288 
04289 KParts::LiveConnectExtension *KHTMLPart::liveConnectExtension( const khtml::RenderPart *frame) const {
04290     const ConstFrameIt end = d->m_objects.end();
04291     for(ConstFrameIt it = d->m_objects.begin(); it != end; ++it )
04292         if ((*it)->m_frame == frame)
04293             return (*it)->m_liveconnect;
04294     return 0L;
04295 }
04296 
04297 bool KHTMLPart::requestFrame( khtml::RenderPart *frame, const QString &url, const QString &frameName,
04298                               const QStringList &params, bool isIFrame )
04299 {
04300   //kdDebug( 6050 ) << this << " requestFrame( ..., " << url << ", " << frameName << " )" << endl;
04301   FrameIt it = d->m_frames.find( frameName );
04302   if ( it == d->m_frames.end() )
04303   {
04304     khtml::ChildFrame * child = new khtml::ChildFrame;
04305     //kdDebug( 6050 ) << "inserting new frame into frame map " << frameName << endl;
04306     child->m_name = frameName;
04307     it = d->m_frames.append( child );
04308   }
04309 
04310   (*it)->m_type = isIFrame ? khtml::ChildFrame::IFrame : khtml::ChildFrame::Frame;
04311   (*it)->m_frame = frame;
04312   (*it)->m_params = params;
04313 
04314   // Support for <frame src="javascript:string">
04315   if ( url.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
04316   {
04317       QVariant res = executeScript( DOM::Node(frame->element()), KURL::decode_string( url.right( url.length() - 11) ) );
04318       KURL myurl;
04319       myurl.setProtocol("javascript");
04320       if ( res.type() == QVariant::String )
04321     myurl.setPath(res.asString());
04322       return processObjectRequest(*it, myurl, QString("text/html") );
04323   }
04324   KURL u = url.isEmpty() ? KURL() : completeURL( url );
04325   return requestObject( *it, u );
04326 }
04327 
04328 QString KHTMLPart::requestFrameName()
04329 {
04330    return QString::fromLatin1("<!--frame %1-->").arg(d->m_frameNameId++);
04331 }
04332 
04333 bool KHTMLPart::requestObject( khtml::RenderPart *frame, const QString &url, const QString &serviceType,
04334                                const QStringList &params )
04335 {
04336   //kdDebug( 6005 ) << "KHTMLPart::requestObject " << this << " frame=" << frame << endl;
04337   khtml::ChildFrame *child = new khtml::ChildFrame;
04338   FrameIt it = d->m_objects.append( child );
04339   (*it)->m_frame = frame;
04340   (*it)->m_type = khtml::ChildFrame::Object;
04341   (*it)->m_params = params;
04342 
04343   KParts::URLArgs args;
04344   args.serviceType = serviceType;
04345   if (!requestObject( *it, completeURL( url ), args ) && !(*it)->m_run) {
04346       (*it)->m_bCompleted = true;
04347       return false;
04348   }
04349   return true;
04350 }
04351 
04352 bool KHTMLPart::requestObject( khtml::ChildFrame *child, const KURL &url, const KParts::URLArgs &_args )
04353 {
04354   if (!checkLinkSecurity(url))
04355   {
04356     kdDebug(6005) << this << " KHTMLPart::requestObject checkLinkSecurity refused" << endl;
04357     return false;
04358   }
04359   if ( child->m_bPreloaded )
04360   {
04361     kdDebug(6005) << "KHTMLPart::requestObject preload" << endl;
04362     if ( child->m_frame && child->m_part )
04363       child->m_frame->setWidget( child->m_part->widget() );
04364 
04365     child->m_bPreloaded = false;
04366     return true;
04367   }
04368 
04369   //kdDebug(6005) << "KHTMLPart::requestObject child=" << child << " child->m_part=" << child->m_part << endl;
04370 
04371   KParts::URLArgs args( _args );
04372 
04373   if ( child->m_run )
04374     child->m_run->abort();
04375 
04376   if ( child->m_part && !args.reload && urlcmp( child->m_part->url().url(), url.url(), true, true ) )
04377     args.serviceType = child->m_serviceType;
04378 
04379   child->m_args = args;
04380   child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload);
04381   child->m_serviceName = QString::null;
04382   if (!d->m_referrer.isEmpty() && !child->m_args.metaData().contains( "referrer" ))
04383     child->m_args.metaData()["referrer"] = d->m_referrer;
04384 
04385   child->m_args.metaData().insert("PropagateHttpHeader", "true");
04386   child->m_args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
04387   child->m_args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
04388   child->m_args.metaData().insert("main_frame_request",
04389                                   parentPart() == 0 ? "TRUE":"FALSE");
04390   child->m_args.metaData().insert("ssl_was_in_use",
04391                                   d->m_ssl_in_use ? "TRUE":"FALSE");
04392   child->m_args.metaData().insert("ssl_activate_warnings", "TRUE");
04393   child->m_args.metaData().insert("cross-domain", toplevelURL().url());
04394 
04395   // We want a KHTMLPart if the HTML says <frame src=""> or <frame src="about:blank">
04396   if ((url.isEmpty() || url.url() == "about:blank") && args.serviceType.isEmpty())
04397     args.serviceType = QString::fromLatin1( "text/html" );
04398 
04399   if ( args.serviceType.isEmpty() ) {
04400     kdDebug(6050) << "Running new KHTMLRun for " << this << " and child=" << child << endl;
04401     child->m_run = new KHTMLRun( this, child, url, child->m_args, true );
04402     d->m_bComplete = false; // ensures we stop it in checkCompleted...
04403     return false;
04404   } else {
04405     return processObjectRequest( child, url, args.serviceType );
04406   }
04407 }
04408 
04409 bool KHTMLPart::processObjectRequest( khtml::ChildFrame *child, const KURL &_url, const QString &mimetype )
04410 {
04411   //kdDebug( 6050 ) << "KHTMLPart::processObjectRequest trying to create part for " << mimetype << endl;
04412 
04413   // IMPORTANT: create a copy of the url here, because it is just a reference, which was likely to be given
04414   // by an emitting frame part (emit openURLRequest( blahurl, ... ) . A few lines below we delete the part
04415   // though -> the reference becomes invalid -> crash is likely
04416   KURL url( _url );
04417 
04418   // khtmlrun called us this way to indicate a loading error
04419   if ( d->m_onlyLocalReferences || ( url.isEmpty() && mimetype.isEmpty() ) )
04420   {
04421       child->m_bCompleted = true;
04422       checkCompleted();
04423       return true;
04424   }
04425 
04426   if (child->m_bNotify)
04427   {
04428       child->m_bNotify = false;
04429       if ( !child->m_args.lockHistory() )
04430           emit d->m_extension->openURLNotify();
04431   }
04432 
04433   if ( child->m_serviceType != mimetype || !child->m_part )
04434   {
04435     // Before attempting to load a part, check if the user wants that.
04436     // Many don't like getting ZIP files embedded.
04437     // However we don't want to ask for flash and other plugin things..
04438     if ( child->m_type != khtml::ChildFrame::Object )
04439     {
04440       QString suggestedFilename;
04441       if ( child->m_run )
04442         suggestedFilename = child->m_run->suggestedFilename();
04443 
04444       KParts::BrowserRun::AskSaveResult res = KParts::BrowserRun::askEmbedOrSave(
04445         url, mimetype, suggestedFilename  );
04446       switch( res ) {
04447       case KParts::BrowserRun::Save:
04448         KHTMLPopupGUIClient::saveURL( widget(), i18n( "Save As" ), url, child->m_args.metaData(), QString::null, 0, suggestedFilename);
04449         // fall-through
04450       case KParts::BrowserRun::Cancel:
04451         child->m_bCompleted = true;
04452         checkCompleted();
04453         return true; // done
04454       default: // Open
04455         break;
04456       }
04457     }
04458 
04459     QStringList dummy; // the list of servicetypes handled by the part is now unused.
04460     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 );
04461 
04462     if ( !part )
04463     {
04464         if ( child->m_frame )
04465           if (child->m_frame->partLoadingErrorNotify( child, url, mimetype ))
04466             return true; // we succeeded after all (a fallback was used)
04467 
04468         checkEmitLoadEvent();
04469         return false;
04470     }
04471 
04472     //CRITICAL STUFF
04473     if ( child->m_part )
04474     {
04475       if (!::qt_cast<KHTMLPart*>(child->m_part) && child->m_jscript)
04476           child->m_jscript->clear();
04477       partManager()->removePart( (KParts::ReadOnlyPart *)child->m_part );
04478       delete (KParts::ReadOnlyPart *)child->m_part;
04479       if (child->m_liveconnect) {
04480         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 &)));
04481         child->m_liveconnect = 0L;
04482       }
04483     }
04484 
04485     child->m_serviceType = mimetype;
04486     if ( child->m_frame  && part->widget() )
04487       child->m_frame->setWidget( part->widget() );
04488 
04489     if ( child->m_type != khtml::ChildFrame::Object )
04490       partManager()->addPart( part, false );
04491 //  else
04492 //      kdDebug(6005) << "AH! NO FRAME!!!!!" << endl;
04493 
04494     child->m_part = part;
04495 
04496     if (::qt_cast<KHTMLPart*>(part)) {
04497       static_cast<KHTMLPart*>(part)->d->m_frame = child;
04498     } else if (child->m_frame) {
04499       child->m_liveconnect = KParts::LiveConnectExtension::childObject(part);
04500       if (child->m_liveconnect)
04501         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 &)));
04502     }
04503     KParts::StatusBarExtension *sb = KParts::StatusBarExtension::childObject(part);
04504     if (sb)
04505       sb->setStatusBar( d->m_statusBarExtension->statusBar() );
04506 
04507     connect( part, SIGNAL( started( KIO::Job *) ),
04508              this, SLOT( slotChildStarted( KIO::Job *) ) );
04509     connect( part, SIGNAL( completed() ),
04510              this, SLOT( slotChildCompleted() ) );
04511     connect( part, SIGNAL( completed(bool) ),
04512              this, SLOT( slotChildCompleted(bool) ) );
04513     connect( part, SIGNAL( setStatusBarText( const QString & ) ),
04514                 this, SIGNAL( setStatusBarText( const QString & ) ) );
04515     if ( part->inherits( "KHTMLPart" ) )
04516     {
04517       connect( this, SIGNAL( completed() ),
04518                part, SLOT( slotParentCompleted() ) );
04519       connect( this, SIGNAL( completed(bool) ),
04520                part, SLOT( slotParentCompleted() ) );
04521       // As soon as the child's document is created, we need to set its domain
04522       // (but we do so only once, so it can't be simply done in the child)
04523       connect( part, SIGNAL( docCreated() ),
04524                this, SLOT( slotChildDocCreated() ) );
04525     }
04526 
04527     child->m_extension = KParts::BrowserExtension::childObject( part );
04528 
04529     if ( child->m_extension )
04530     {
04531       connect( child->m_extension, SIGNAL( openURLNotify() ),
04532                d->m_extension, SIGNAL( openURLNotify() ) );
04533 
04534       connect( child->m_extension, SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ),
04535                this, SLOT( slotChildURLRequest( const KURL &, const KParts::URLArgs & ) ) );
04536 
04537       connect( child->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ),
04538                d->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ) );
04539       connect( child->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs &, const KParts::WindowArgs &, KParts::ReadOnlyPart *& ) ),
04540                d->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & , const KParts::WindowArgs &, KParts::ReadOnlyPart *&) ) );
04541 
04542       connect( child->m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ),
04543                d->m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ) );
04544       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ),
04545                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ) );
04546       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ),
04547                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ) );
04548       connect( child->m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ),
04549                d->m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ) );
04550       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ),
04551                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ) );
04552       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ),
04553                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ) );
04554 
04555       connect( child->m_extension, SIGNAL( infoMessage( const QString & ) ),
04556                d->m_extension, SIGNAL( infoMessage( const QString & ) ) );
04557 
04558       connect( child->m_extension, SIGNAL( requestFocus( KParts::ReadOnlyPart * ) ),
04559                this, SLOT( slotRequestFocus( KParts::ReadOnlyPart * ) ) );
04560 
04561       child->m_extension->setBrowserInterface( d->m_extension->browserInterface() );
04562     }
04563   }
04564   else if ( child->m_frame && child->m_part &&
04565             child->m_frame->widget() != child->m_part->widget() )
04566     child->m_frame->setWidget( child->m_part->widget() );
04567 
04568   checkEmitLoadEvent();
04569   // Some JS code in the load event may have destroyed the part
04570   // In that case, abort
04571   if ( !child->m_part )
04572     return false;
04573 
04574   if ( child->m_bPreloaded )
04575   {
04576     if ( child->m_frame && child->m_part )
04577       child->m_frame->setWidget( child->m_part->widget() );
04578 
04579     child->m_bPreloaded = false;
04580     return true;
04581   }
04582 
04583   child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload);
04584 
04585   // make sure the part has a way to find out about the mimetype.
04586   // we actually set it in child->m_args in requestObject already,
04587   // but it's useless if we had to use a KHTMLRun instance, as the
04588   // point the run object is to find out exactly the mimetype.
04589   child->m_args.serviceType = mimetype;
04590 
04591   // if not a frame set child as completed
04592   child->m_bCompleted = child->m_type == khtml::ChildFrame::Object;
04593 
04594   if ( child->m_extension )
04595     child->m_extension->setURLArgs( child->m_args );
04596 
04597   if(url.protocol() == "javascript" || url.url() == "about:blank") {
04598       if (!child->m_part->inherits("KHTMLPart"))
04599           return false;
04600 
04601       KHTMLPart* p = static_cast<KHTMLPart*>(static_cast<KParts::ReadOnlyPart *>(child->m_part));
04602 
04603       p->begin();
04604       if (d->m_doc && p->d->m_doc)
04605         p->d->m_doc->setBaseURL(d->m_doc->baseURL());
04606       if (!url.url().startsWith("about:")) {
04607         p->write(url.path());
04608       } else {
04609     p->m_url = url;
04610         // we need a body element. testcase: <iframe id="a"></iframe><script>alert(a.document.body);</script>
04611         p->write("<HTML><TITLE></TITLE><BODY></BODY></HTML>");
04612       }
04613       p->end();
04614       return true;
04615   }
04616   else if ( !url.isEmpty() )
04617   {
04618       //kdDebug( 6050 ) << "opening " << url.url() << " in frame " << child->m_part << endl;
04619       bool b = child->m_part->openURL( url );
04620       if (child->m_bCompleted)
04621           checkCompleted();
04622       return b;
04623   }
04624   else
04625   {
04626       child->m_bCompleted = true;
04627       checkCompleted();
04628       return true;
04629   }
04630 }
04631 
04632 KParts::ReadOnlyPart *KHTMLPart::createPart( QWidget *parentWidget, const char *widgetName,
04633                                              QObject *parent, const char *name, const QString &mimetype,
04634                                              QString &serviceName, QStringList &serviceTypes,
04635                                              const QStringList &params )
04636 {
04637   QString constr;
04638   if ( !serviceName.isEmpty() )
04639     constr.append( QString::fromLatin1( "Name == '%1'" ).arg( serviceName ) );
04640 
04641   KTrader::OfferList offers = KTrader::self()->query( mimetype, "KParts/ReadOnlyPart", constr, QString::null );
04642 
04643   if ( offers.isEmpty() ) {
04644     int pos = mimetype.find( "-plugin" );
04645     if (pos < 0)
04646         return 0L;
04647     QString stripped_mime = mimetype.left( pos );
04648     offers = KTrader::self()->query( stripped_mime, "KParts/ReadOnlyPart", constr, QString::null );
04649     if ( offers.isEmpty() )
04650         return 0L;
04651   }
04652 
04653   KTrader::OfferList::ConstIterator it = offers.begin();
04654   const KTrader::OfferList::ConstIterator itEnd = offers.end();
04655   for ( ; it != itEnd; ++it )
04656   {
04657     KService::Ptr service = (*it);
04658 
04659     KLibFactory* const factory = KLibLoader::self()->factory( QFile::encodeName(service->library()) );
04660     if ( factory ) {
04661       KParts::ReadOnlyPart *res = 0L;
04662 
04663       const char *className = "KParts::ReadOnlyPart";
04664       if ( service->serviceTypes().contains( "Browser/View" ) )
04665         className = "Browser/View";
04666 
04667       if ( factory->inherits( "KParts::Factory" ) )
04668         res = static_cast<KParts::ReadOnlyPart *>(static_cast<KParts::Factory *>( factory )->createPart( parentWidget, widgetName, parent, name, className, params ));
04669       else
04670         res = static_cast<KParts::ReadOnlyPart *>(factory->create( parentWidget, widgetName, className ));
04671 
04672       if ( res ) {
04673         serviceTypes = service->serviceTypes();
04674         serviceName = service->name();
04675         return res;
04676       }
04677     } else {
04678       // TODO KMessageBox::error and i18n, like in KonqFactory::createView?
04679       kdWarning() << QString("There was an error loading the module %1.\nThe diagnostics is:\n%2")
04680                       .arg(service->name()).arg(KLibLoader::self()->lastErrorMessage()) << endl;
04681     }
04682   }
04683   return 0;
04684 }
04685 
04686 KParts::PartManager *KHTMLPart::partManager()
04687 {
04688   if ( !d->m_manager && d->m_view )
04689   {
04690     d->m_manager = new KParts::PartManager( d->m_view->topLevelWidget(), this, "khtml part manager" );
04691     d->m_manager->setAllowNestedParts( true );
04692     connect( d->m_manager, SIGNAL( activePartChanged( KParts::Part * ) ),
04693              this, SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
04694     connect( d->m_manager, SIGNAL( partRemoved( KParts::Part * ) ),
04695              this, SLOT( slotPartRemoved( KParts::Part * ) ) );
04696   }
04697 
04698   return d->m_manager;
04699 }
04700 
04701 void KHTMLPart::submitFormAgain()
04702 {
04703   disconnect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
04704   if( d->m_doc && !d->m_doc->parsing() && d->m_submitForm)
04705     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 );
04706 
04707   delete d->m_submitForm;
04708   d->m_submitForm = 0;
04709 }
04710 
04711 void KHTMLPart::submitFormProxy( const char *action, const QString &url, const QByteArray &formData, const QString &_target, const QString& contentType, const QString& boundary )
04712 {
04713   submitForm(action, url, formData, _target, contentType, boundary);
04714 }
04715 
04716 void KHTMLPart::submitForm( const char *action, const QString &url, const QByteArray &formData, const QString &_target, const QString& contentType, const QString& boundary )
04717 {
04718   kdDebug(6000) << this << ": KHTMLPart::submitForm target=" << _target << " url=" << url << endl;
04719   if (d->m_formNotification == KHTMLPart::Only) {
04720     emit formSubmitNotification(action, url, formData, _target, contentType, boundary);
04721     return;
04722   } else if (d->m_formNotification == KHTMLPart::Before) {
04723     emit formSubmitNotification(action, url, formData, _target, contentType, boundary);
04724   }
04725 
04726   KURL u = completeURL( url );
04727 
04728   if ( !u.isValid() )
04729   {
04730     // ### ERROR HANDLING!
04731     return;
04732   }
04733 
04734   // Form security checks
04735   //
04736   /*
04737    * If these form security checks are still in this place in a month or two
04738    * I'm going to simply delete them.
04739    */
04740 
04741   /* This is separate for a reason.  It has to be _before_ all script, etc,
04742    * AND I don't want to break anything that uses checkLinkSecurity() in
04743    * other places.
04744    */
04745 
04746   if (!d->m_submitForm) {
04747     if (u.protocol() != "https" && u.protocol() != "mailto") {
04748       if (d->m_ssl_in_use) {    // Going from SSL -> nonSSL
04749         int rc = KMessageBox::warningContinueCancel(NULL, i18n("Warning:  This is a secure form but it is attempting to send your data back unencrypted."
04750                                                                "\nA third party may be able to intercept and view this information."
04751                                                                "\nAre you sure you wish to continue?"),
04752                                                     i18n("Network Transmission"),KGuiItem(i18n("&Send Unencrypted")));
04753         if (rc == KMessageBox::Cancel)
04754           return;
04755       } else {                  // Going from nonSSL -> nonSSL
04756         KSSLSettings kss(true);
04757         if (kss.warnOnUnencrypted()) {
04758           int rc = KMessageBox::warningContinueCancel(NULL,
04759                                                       i18n("Warning: Your data is about to be transmitted across the network unencrypted."
04760                                                            "\nAre you sure you wish to continue?"),
04761                                                       i18n("Network Transmission"),
04762                                                       KGuiItem(i18n("&Send Unencrypted")),
04763                                                       "WarnOnUnencryptedForm");
04764           // Move this setting into KSSL instead
04765           KConfig *config = kapp->config();
04766           QString grpNotifMsgs = QString::fromLatin1("Notification Messages");
04767           KConfigGroupSaver saver( config, grpNotifMsgs );
04768 
04769           if (!config->readBoolEntry("WarnOnUnencryptedForm", true)) {
04770             config->deleteEntry("WarnOnUnencryptedForm");
04771             config->sync();
04772             kss.setWarnOnUnencrypted(false);
04773             kss.save();
04774           }
04775           if (rc == KMessageBox::Cancel)
04776             return;
04777         }
04778       }
04779     }
04780 
04781     if (u.protocol() == "mailto") {
04782       int rc = KMessageBox::warningContinueCancel(NULL,
04783                                                   i18n("This site is attempting to submit form data via email.\n"
04784                                                        "Do you want to continue?"),
04785                                                   i18n("Network Transmission"),
04786                                                   KGuiItem(i18n("&Send Email")),
04787                                                   "WarnTriedEmailSubmit");
04788 
04789       if (rc == KMessageBox::Cancel) {
04790         return;
04791       }
04792     }
04793   }
04794 
04795   // End form security checks
04796   //
04797 
04798   QString urlstring = u.url();
04799 
04800   if ( urlstring.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
04801     urlstring = KURL::decode_string(urlstring);
04802     crossFrameExecuteScript( _target, urlstring.right( urlstring.length() - 11) );
04803     return;
04804   }
04805 
04806   if (!checkLinkSecurity(u,
04807              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?" ),
04808              i18n( "Submit" )))
04809     return;
04810 
04811   KParts::URLArgs args;
04812 
04813   if (!d->m_referrer.isEmpty())
04814      args.metaData()["referrer"] = d->m_referrer;
04815 
04816   args.metaData().insert("PropagateHttpHeader", "true");
04817   args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
04818   args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
04819   args.metaData().insert("main_frame_request",
04820                          parentPart() == 0 ? "TRUE":"FALSE");
04821   args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
04822   args.metaData().insert("ssl_activate_warnings", "TRUE");
04823 //WABA: When we post a form we should treat it as the main url
04824 //the request should never be considered cross-domain
04825 //args.metaData().insert("cross-domain", toplevelURL().url());
04826   args.frameName = _target.isEmpty() ? d->m_doc->baseTarget() : _target ;
04827 
04828   // Handle mailto: forms
04829   if (u.protocol() == "mailto") {
04830       // 1)  Check for attach= and strip it
04831       QString q = u.query().mid(1);
04832       QStringList nvps = QStringList::split("&", q);
04833       bool triedToAttach = false;
04834 
04835       QStringList::Iterator nvp = nvps.begin();
04836       const QStringList::Iterator nvpEnd = nvps.end();
04837 
04838 // cannot be a for loop as if something is removed we don't want to do ++nvp, as
04839 // remove returns an iterator pointing to the next item
04840 
04841       while (nvp != nvpEnd) {
04842          const QStringList pair = QStringList::split("=", *nvp);
04843          if (pair.count() >= 2) {
04844             if (pair.first().lower() == "attach") {
04845                nvp = nvps.remove(nvp);
04846                triedToAttach = true;
04847             } else {
04848                ++nvp;
04849             }
04850          } else {
04851             ++nvp;
04852          }
04853       }
04854 
04855       if (triedToAttach)
04856          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");
04857 
04858       // 2)  Append body=
04859       QString bodyEnc;
04860       if (contentType.lower() == "multipart/form-data") {
04861          // FIXME: is this correct?  I suspect not
04862          bodyEnc = KURL::encode_string(QString::fromLatin1(formData.data(),
04863                                                            formData.size()));
04864       } else if (contentType.lower() == "text/plain") {
04865          // Convention seems to be to decode, and s/&/\n/
04866          QString tmpbody = QString::fromLatin1(formData.data(),
04867                                                formData.size());
04868          tmpbody.replace(QRegExp("[&]"), "\n");
04869          tmpbody.replace(QRegExp("[+]"), " ");
04870          tmpbody = KURL::decode_string(tmpbody);  // Decode the rest of it
04871          bodyEnc = KURL::encode_string(tmpbody);  // Recode for the URL
04872       } else {
04873          bodyEnc = KURL::encode_string(QString::fromLatin1(formData.data(),
04874                                                            formData.size()));
04875       }
04876 
04877       nvps.append(QString("body=%1").arg(bodyEnc));
04878       q = nvps.join("&");
04879       u.setQuery(q);
04880   }
04881 
04882   if ( strcmp( action, "get" ) == 0 ) {
04883     if (u.protocol() != "mailto")
04884        u.setQuery( QString::fromLatin1( formData.data(), formData.size() ) );
04885     args.setDoPost( false );
04886   }
04887   else {
04888     args.postData = formData;
04889     args.setDoPost( true );
04890 
04891     // construct some user headers if necessary
04892     if (contentType.isNull() || contentType == "application/x-www-form-urlencoded")
04893       args.setContentType( "Content-Type: application/x-www-form-urlencoded" );
04894     else // contentType must be "multipart/form-data"
04895       args.setContentType( "Content-Type: " + contentType + "; boundary=" + boundary );
04896   }
04897 
04898   if ( d->m_doc->parsing() || d->m_runningScripts > 0 ) {
04899     if( d->m_submitForm ) {
04900       kdDebug(6000) << "KHTMLPart::submitForm ABORTING!" << endl;
04901       return;
04902     }
04903     d->m_submitForm = new KHTMLPartPrivate::SubmitForm;
04904     d->m_submitForm->submitAction = action;
04905     d->m_submitForm->submitUrl = url;
04906     d->m_submitForm->submitFormData = formData;
04907     d->m_submitForm->target = _target;
04908     d->m_submitForm->submitContentType = contentType;
04909     d->m_submitForm->submitBoundary = boundary;
04910     connect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
04911   }
04912   else
04913   {
04914     emit d->m_extension->openURLRequest( u, args );
04915   }
04916 }
04917 
04918 void KHTMLPart::popupMenu( const QString &linkUrl )
04919 {
04920   KURL popupURL;
04921   KURL linkKURL;
04922   KParts::URLArgs args;
04923   QString referrer;
04924   KParts::BrowserExtension::PopupFlags itemflags=KParts::BrowserExtension::ShowBookmark | KParts::BrowserExtension::ShowReload;
04925 
04926   if ( linkUrl.isEmpty() ) { // click on background
04927     KHTMLPart* khtmlPart = this;
04928     while ( khtmlPart->parentPart() )
04929     {
04930       khtmlPart=khtmlPart->parentPart();
04931     }
04932     popupURL = khtmlPart->url();
04933     referrer = khtmlPart->pageReferrer();
04934     if (hasSelection())
04935       itemflags = KParts::BrowserExtension::ShowTextSelectionItems;
04936     else
04937       itemflags |= KParts::BrowserExtension::ShowNavigationItems;
04938   } else {               // click on link
04939     popupURL = completeURL( linkUrl );
04940     linkKURL = popupURL;
04941     referrer = this->referrer();
04942 
04943     if (!(d->m_strSelectedURLTarget).isEmpty() &&
04944            (d->m_strSelectedURLTarget.lower() != "_top") &&
04945            (d->m_strSelectedURLTarget.lower() != "_self") &&
04946        (d->m_strSelectedURLTarget.lower() != "_parent")) {
04947       if (d->m_strSelectedURLTarget.lower() == "_blank")
04948         args.setForcesNewWindow(true);
04949       else {
04950     KHTMLPart *p = this;
04951     while (p->parentPart())
04952       p = p->parentPart();
04953     if (!p->frameExists(d->m_strSelectedURLTarget))
04954           args.setForcesNewWindow(true);
04955       }
04956     }
04957   }
04958 
04959   // Danger, Will Robinson. The Popup might stay around for a much
04960   // longer time than KHTMLPart. Deal with it.
04961   KHTMLPopupGUIClient* client = new KHTMLPopupGUIClient( this, d->m_popupMenuXML, linkKURL );
04962   QGuardedPtr<QObject> guard( client );
04963 
04964   QString mimetype = QString::fromLatin1( "text/html" );
04965   args.metaData()["referrer"] = referrer;
04966 
04967   if (!linkUrl.isEmpty())               // over a link
04968   {
04969     if (popupURL.isLocalFile())             // safe to do this
04970     {
04971       mimetype = KMimeType::findByURL(popupURL,0,true,false)->name();
04972     }
04973     else                        // look at "extension" of link
04974     {
04975       const QString fname(popupURL.fileName(false));
04976       if (!fname.isEmpty() && !popupURL.hasRef() && popupURL.query().isEmpty())
04977       {
04978         KMimeType::Ptr pmt = KMimeType::findByPath(fname,0,true);
04979 
04980         // Further check for mime types guessed from the extension which,
04981         // on a web page, are more likely to be a script delivering content
04982         // of undecidable type. If the mime type from the extension is one
04983         // of these, don't use it.  Retain the original type 'text/html'.
04984         if (pmt->name() != KMimeType::defaultMimeType() &&
04985             !pmt->is("application/x-perl") &&
04986             !pmt->is("application/x-perl-module") &&
04987             !pmt->is("application/x-php") &&
04988             !pmt->is("application/x-python-bytecode") &&
04989             !pmt->is("application/x-python") &&
04990             !pmt->is("application/x-shellscript"))
04991           mimetype = pmt->name();
04992       }
04993     }
04994   }
04995 
04996   args.serviceType = mimetype;
04997 
04998   emit d->m_extension->popupMenu( client, QCursor::pos(), popupURL, args, itemflags, S_IFREG /*always a file*/);
04999 
05000   if ( !guard.isNull() ) {
05001      delete client;
05002      emit popupMenu(linkUrl, QCursor::pos());
05003      d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
05004   }
05005 }
05006 
05007 void KHTMLPart::slotParentCompleted()
05008 {
05009   //kdDebug(6050) << this << " slotParentCompleted()" << endl;
05010   if ( !d->m_redirectURL.isEmpty() && !d->m_redirectionTimer.isActive() )
05011   {
05012     //kdDebug(6050) << this << ": starting timer for child redirection -> " << d->m_redirectURL << endl;
05013     d->m_redirectionTimer.start( 1000 * d->m_delayRedirect, true );
05014   }
05015 }
05016 
05017 void KHTMLPart::slotChildStarted( KIO::Job *job )
05018 {
05019   khtml::ChildFrame *child = frame( sender() );
05020 
05021   assert( child );
05022 
05023   child->m_bCompleted = false;
05024 
05025   if ( d->m_bComplete )
05026   {
05027 #if 0
05028     // WABA: Looks like this belongs somewhere else
05029     if ( !parentPart() ) // "toplevel" html document? if yes, then notify the hosting browser about the document (url) changes
05030     {
05031       emit d->m_extension->openURLNotify();
05032     }
05033 #endif
05034     d->m_bComplete = false;
05035     emit started( job );
05036   }
05037 }
05038 
05039 void KHTMLPart::slotChildCompleted()
05040 {
05041   slotChildCompleted( false );
05042 }
05043 
05044 void KHTMLPart::slotChildCompleted( bool pendingAction )
05045 {
05046   khtml::ChildFrame *child = frame( sender() );
05047 
05048   if ( child ) {
05049     kdDebug(6050) << this << " slotChildCompleted child=" << child << " m_frame=" << child->m_frame << endl;
05050     child->m_bCompleted = true;
05051     child->m_bPendingRedirection = pendingAction;
05052     child->m_args = KParts::URLArgs();
05053   }
05054   checkCompleted();
05055 }
05056 
05057 void KHTMLPart::slotChildDocCreated()
05058 {
05059   const KHTMLPart* htmlFrame = static_cast<const KHTMLPart *>(sender());
05060   // Set domain to the frameset's domain
05061   // This must only be done when loading the frameset initially (#22039),
05062   // not when following a link in a frame (#44162).
05063   if ( d->m_doc && d->m_doc->isHTMLDocument() )
05064   {
05065     if ( sender()->inherits("KHTMLPart") )
05066     {
05067       DOMString domain = static_cast<HTMLDocumentImpl*>(d->m_doc)->domain();
05068       if (htmlFrame->d->m_doc && htmlFrame->d->m_doc->isHTMLDocument() )
05069         //kdDebug(6050) << "KHTMLPart::slotChildDocCreated: url: " << htmlFrame->m_url.url() << endl;
05070         static_cast<HTMLDocumentImpl*>(htmlFrame->d->m_doc)->setDomain( domain );
05071     }
05072   }
05073   // So it only happens once
05074   disconnect( htmlFrame, SIGNAL( docCreated() ), this, SLOT( slotChildDocCreated() ) );
05075 }
05076 
05077 void KHTMLPart::slotChildURLRequest( const KURL &url, const KParts::URLArgs &args )
05078 {
05079   khtml::ChildFrame *child = frame( sender()->parent() );
05080   KHTMLPart *callingHtmlPart = const_cast<KHTMLPart *>(dynamic_cast<const KHTMLPart *>(sender()->parent()));
05081 
05082   // TODO: handle child target correctly! currently the script are always executed fur the parent
05083   QString urlStr = url.url();
05084   if ( urlStr.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
05085       QString script = KURL::decode_string( urlStr.right( urlStr.length() - 11 ) );
05086       executeScript( DOM::Node(), script );
05087       return;
05088   }
05089 
05090   QString frameName = args.frameName.lower();
05091   if ( !frameName.isEmpty() ) {
05092     if ( frameName == QString::fromLatin1( "_top" ) )
05093     {
05094       emit d->m_extension->openURLRequest( url, args );
05095       return;
05096     }
05097     else if ( frameName == QString::fromLatin1( "_blank" ) )
05098     {
05099       emit d->m_extension->createNewWindow( url, args );
05100       return;
05101     }
05102     else if ( frameName == QString::fromLatin1( "_parent" ) )
05103     {
05104       KParts::URLArgs newArgs( args );
05105       newArgs.frameName = QString::null;
05106 
05107       emit d->m_extension->openURLRequest( url, newArgs );
05108       return;
05109     }
05110     else if ( frameName != QString::fromLatin1( "_self" ) )
05111     {
05112       khtml::ChildFrame *_frame = recursiveFrameRequest( callingHtmlPart, url, args );
05113 
05114       if ( !_frame )
05115       {
05116         emit d->m_extension->openURLRequest( url, args );
05117         return;
05118       }
05119 
05120       child = _frame;
05121     }
05122   }
05123 
05124   if ( child && child->m_type != khtml::ChildFrame::Object ) {
05125       // Inform someone that we are about to show something else.
05126       child->m_bNotify = true;
05127       requestObject( child, url, args );
05128   }  else if ( frameName== "_self" ) // this is for embedded objects (via <object>) which want to replace the current document
05129   {
05130       KParts::URLArgs newArgs( args );
05131       newArgs.frameName = QString::null;
05132       emit d->m_extension->openURLRequest( url, newArgs );
05133   }
05134 }
05135 
05136 void KHTMLPart::slotRequestFocus( KParts::ReadOnlyPart * )
05137 {
05138   emit d->m_extension->requestFocus(this);
05139 }
05140 
05141 khtml::ChildFrame *KHTMLPart::frame( const QObject *obj )
05142 {
05143     assert( obj->inherits( "KParts::ReadOnlyPart" ) );
05144     const KParts::ReadOnlyPart* const part = static_cast<const KParts::ReadOnlyPart *>( obj );
05145 
05146     FrameIt it = d->m_frames.begin();
05147     const FrameIt end = d->m_frames.end();
05148     for (; it != end; ++it )
05149       if ( (KParts::ReadOnlyPart *)(*it)->m_part == part )
05150         return *it;
05151 
05152     FrameIt oi = d->m_objects.begin();
05153     const FrameIt oiEnd = d->m_objects.end();
05154     for (; oi != oiEnd; ++oi )
05155       if ( (KParts::ReadOnlyPart *)(*oi)->m_part == part )
05156         return *oi;
05157 
05158     return 0L;
05159 }
05160 
05161 //#define DEBUG_FINDFRAME
05162 
05163 bool KHTMLPart::checkFrameAccess(KHTMLPart *callingHtmlPart)
05164 {
05165   if (callingHtmlPart == this)
05166     return true; // trivial
05167 
05168   if (htmlDocument().isNull()) {
05169 #ifdef DEBUG_FINDFRAME
05170     kdDebug(6050) << "KHTMLPart::checkFrameAccess: Empty part " << this << " URL = " << m_url << endl;
05171 #endif
05172     return false; // we are empty?
05173   }
05174 
05175   // now compare the domains
05176   if (callingHtmlPart && !callingHtmlPart->htmlDocument().isNull() &&
05177       !htmlDocument().isNull())  {
05178     DOM::DOMString actDomain = callingHtmlPart->htmlDocument().domain();
05179     DOM::DOMString destDomain = htmlDocument().domain();
05180 
05181 #ifdef DEBUG_FINDFRAME
05182     kdDebug(6050) << "KHTMLPart::checkFrameAccess: actDomain = '" << actDomain.string() << "' destDomain = '" << destDomain.string() << "'" << endl;
05183 #endif
05184 
05185     if (actDomain == destDomain)
05186       return true;
05187   }
05188 #ifdef DEBUG_FINDFRAME
05189   else
05190   {
05191     kdDebug(6050) << "KHTMLPart::checkFrameAccess: Unknown part/domain " << callingHtmlPart << " tries to access part " << this << endl;
05192   }
05193 #endif
05194   return false;
05195 }
05196 
05197 KHTMLPart *
05198 KHTMLPart::findFrameParent( KParts::ReadOnlyPart *callingPart, const QString &f, khtml::ChildFrame **childFrame )
05199 {
05200 #ifdef DEBUG_FINDFRAME
05201   kdDebug(6050) << "KHTMLPart::findFrameParent: this = " << this << " URL = " << m_url << " name = " << name() << " findFrameParent( " << f << " )" << endl;
05202 #endif
05203   // Check access
05204   KHTMLPart* const callingHtmlPart = dynamic_cast<KHTMLPart *>(callingPart);
05205 
05206   if (!checkFrameAccess(callingHtmlPart))
05207      return 0;
05208 
05209   if (!childFrame && !parentPart() && (name() == f))
05210      return this;
05211 
05212   FrameIt it = d->m_frames.find( f );
05213   const FrameIt end = d->m_frames.end();
05214   if ( it != end )
05215   {
05216 #ifdef DEBUG_FINDFRAME
05217      kdDebug(6050) << "KHTMLPart::findFrameParent: FOUND!" << endl;
05218 #endif
05219      if (childFrame)
05220         *childFrame = *it;
05221      return this;
05222   }
05223 
05224   it = d->m_frames.begin();
05225   for (; it != end; ++it )
05226   {
05227     KParts::ReadOnlyPart* const p = (*it)->m_part;
05228     if ( p && p->inherits( "KHTMLPart" ))
05229     {
05230       KHTMLPart* const frameParent = static_cast<KHTMLPart*>(p)->findFrameParent(callingPart, f, childFrame);
05231       if (frameParent)
05232          return frameParent;
05233     }
05234   }
05235   return 0;
05236 }
05237 
05238 
05239 KHTMLPart *KHTMLPart::findFrame( const QString &f )
05240 {
05241   khtml::ChildFrame *childFrame;
05242   KHTMLPart *parentFrame = findFrameParent(this, f, &childFrame);
05243   if (parentFrame)
05244   {
05245      KParts::ReadOnlyPart *p = childFrame->m_part;
05246      if ( p && p->inherits( "KHTMLPart" ))
05247         return static_cast<KHTMLPart *>(p);
05248   }
05249   return 0;
05250 }
05251 
05252 KParts::ReadOnlyPart *KHTMLPart::findFramePart(const QString &f)
05253 {
05254   khtml::ChildFrame *childFrame;
05255   return findFrameParent(this, f, &childFrame) ? static_cast<KParts::ReadOnlyPart *>(childFrame->m_part) : 0L;
05256 }
05257 
05258 KParts::ReadOnlyPart *KHTMLPart::currentFrame() const
05259 {
05260   KParts::ReadOnlyPart* part = (KParts::ReadOnlyPart*)(this);
05261   // Find active part in our frame manager, in case we are a frameset
05262   // and keep doing that (in case of nested framesets).
05263   // Just realized we could also do this recursively, calling part->currentFrame()...
05264   while ( part && part->inherits("KHTMLPart") &&
05265           static_cast<KHTMLPart *>(part)->d->m_frames.count() > 0 ) {
05266     KHTMLPart* frameset = static_cast<KHTMLPart *>(part);
05267     part = static_cast<KParts::ReadOnlyPart *>(frameset->partManager()->activePart());
05268     if ( !part ) return frameset;
05269   }
05270   return part;
05271 }
05272 
05273 bool KHTMLPart::frameExists( const QString &frameName )
05274 {
05275   ConstFrameIt it = d->m_frames.find( frameName );
05276   if ( it == d->m_frames.end() )
05277     return false;
05278 
05279   // WABA: We only return true if the child actually has a frame
05280   // set. Otherwise we might find our preloaded-selve.
05281   // This happens when we restore the frameset.
05282   return (!(*it)->m_frame.isNull());
05283 }
05284 
05285 KJSProxy *KHTMLPart::framejScript(KParts::ReadOnlyPart *framePart)
05286 {
05287   KHTMLPart* const kp = ::qt_cast<KHTMLPart*>(framePart);
05288   if (kp)
05289     return kp->jScript();
05290 
05291   FrameIt it = d->m_frames.begin();
05292   const FrameIt itEnd = d->m_frames.end();
05293 
05294   for (; it != itEnd; ++it)
05295     if (framePart == (*it)->m_part) {
05296       if (!(*it)->m_jscript)
05297         createJScript(*it);
05298       return (*it)->m_jscript;
05299     }
05300   return 0L;
05301 }
05302 
05303 KHTMLPart *KHTMLPart::parentPart()
05304 {
05305   return ::qt_cast<KHTMLPart *>( parent() );
05306 }
05307 
05308 khtml::ChildFrame *KHTMLPart::recursiveFrameRequest( KHTMLPart *callingHtmlPart, const KURL &url,
05309                                                      const KParts::URLArgs &args, bool callParent )
05310 {
05311 #ifdef DEBUG_FINDFRAME
05312   kdDebug( 6050 ) << "KHTMLPart::recursiveFrameRequest this = " << this << ", frame = " << args.frameName << ", url = " << url << endl;
05313 #endif
05314   khtml::ChildFrame *childFrame;
05315   KHTMLPart *childPart = findFrameParent(callingHtmlPart, args.frameName, &childFrame);
05316   if (childPart)
05317   {
05318      if (childPart == this)
05319         return childFrame;
05320 
05321      childPart->requestObject( childFrame, url, args );
05322      return 0;
05323   }
05324 
05325   if ( parentPart() && callParent )
05326   {
05327      khtml::ChildFrame *res = parentPart()->recursiveFrameRequest( callingHtmlPart, url, args, callParent );
05328 
05329      if ( res )
05330        parentPart()->requestObject( res, url, args );
05331   }
05332 
05333   return 0L;
05334 }
05335 
05336 #ifndef NDEBUG
05337 static int s_saveStateIndentLevel = 0;
05338 #endif
05339 
05340 void KHTMLPart::saveState( QDataStream &stream )
05341 {
05342 #ifndef NDEBUG
05343   QString indent = QString().leftJustify( s_saveStateIndentLevel * 4, ' ' );
05344   const int indentLevel = s_saveStateIndentLevel++;
05345   kdDebug( 6050 ) << indent << "saveState this=" << this << " '" << name() << "' saving URL " << m_url.url() << endl;
05346 #endif
05347 
05348   stream << m_url << (Q_INT32)d->m_view->contentsX() << (Q_INT32)d->m_view->contentsY()
05349          << (Q_INT32) d->m_view->contentsWidth() << (Q_INT32) d->m_view->contentsHeight() << (Q_INT32) d->m_view->marginWidth() << (Q_INT32) d->m_view->marginHeight();
05350 
05351   // save link cursor position
05352   int focusNodeNumber;
05353   if (!d->m_focusNodeRestored)
05354       focusNodeNumber = d->m_focusNodeNumber;
05355   else if (d->m_doc && d->m_doc->focusNode())
05356       focusNodeNumber = d->m_doc->nodeAbsIndex(d->m_doc->focusNode());
05357   else
05358       focusNodeNumber = -1;
05359   stream << focusNodeNumber;
05360 
05361   // Save the doc's cache id.
05362   stream << d->m_cacheId;
05363 
05364   // Save the state of the document (Most notably the state of any forms)
05365   QStringList docState;
05366   if (d->m_doc)
05367   {
05368      docState = d->m_doc->docState();
05369   }
05370   stream << d->m_encoding << d->m_sheetUsed << docState;
05371 
05372   stream << d->m_zoomFactor;
05373 
05374   stream << d->m_httpHeaders;
05375   stream << d->m_pageServices;
05376   stream << d->m_pageReferrer;
05377 
05378   // Save ssl data
05379   stream << d->m_ssl_in_use
05380          << d->m_ssl_peer_certificate
05381          << d->m_ssl_peer_chain
05382          << d->m_ssl_peer_ip
05383          << d->m_ssl_cipher
05384          << d->m_ssl_cipher_desc
05385          << d->m_ssl_cipher_version
05386          << d->m_ssl_cipher_used_bits
05387          << d->m_ssl_cipher_bits
05388          << d->m_ssl_cert_state
05389          << d->m_ssl_parent_ip
05390          << d->m_ssl_parent_cert;
05391 
05392 
05393   QStringList frameNameLst, frameServiceTypeLst, frameServiceNameLst;
05394   KURL::List frameURLLst;
05395   QValueList<QByteArray> frameStateBufferLst;
05396 
05397   ConstFrameIt it = d->m_frames.begin();
05398   const ConstFrameIt end = d->m_frames.end();
05399   for (; it != end; ++it )
05400   {
05401     if ( !(*it)->m_part )
05402        continue;
05403 
05404     frameNameLst << (*it)->m_name;
05405     frameServiceTypeLst << (*it)->m_serviceType;
05406     frameServiceNameLst << (*it)->m_serviceName;
05407     frameURLLst << (*it)->m_part->url();
05408 
05409     QByteArray state;
05410     QDataStream frameStream( state, IO_WriteOnly );
05411 
05412     if ( (*it)->m_extension )
05413       (*it)->m_extension->saveState( frameStream );
05414 
05415     frameStateBufferLst << state;
05416   }
05417 
05418   // Save frame data
05419   stream << (Q_UINT32) frameNameLst.count();
05420   stream << frameNameLst << frameServiceTypeLst << frameServiceNameLst << frameURLLst << frameStateBufferLst;
05421 #ifndef NDEBUG
05422   s_saveStateIndentLevel = indentLevel;
05423 #endif
05424 }
05425 
05426 void KHTMLPart::restoreState( QDataStream &stream )
05427 {
05428   KURL u;
05429   Q_INT32 xOffset, yOffset, wContents, hContents, mWidth, mHeight;
05430   Q_UINT32 frameCount;
05431   QStringList frameNames, frameServiceTypes, docState, frameServiceNames;
05432   KURL::List frameURLs;
05433   QValueList<QByteArray> frameStateBuffers;
05434   QValueList<int> fSizes;
05435   QString encoding, sheetUsed;
05436   long old_cacheId = d->m_cacheId;
05437 
05438   stream >> u >> xOffset >> yOffset >> wContents >> hContents >> mWidth >> mHeight;
05439 
05440   d->m_view->setMarginWidth( mWidth );
05441   d->m_view->setMarginHeight( mHeight );
05442 
05443   // restore link cursor position
05444   // nth node is active. value is set in checkCompleted()
05445   stream >> d->m_focusNodeNumber;
05446   d->m_focusNodeRestored = false;
05447 
05448   stream >> d->m_cacheId;
05449 
05450   stream >> encoding >> sheetUsed >> docState;
05451 
05452   d->m_encoding = encoding;
05453   d->m_sheetUsed = sheetUsed;
05454 
05455   int zoomFactor;
05456   stream >> zoomFactor;
05457   setZoomFactor(zoomFactor);
05458 
05459   stream >> d->m_httpHeaders;
05460   stream >> d->m_pageServices;
05461   stream >> d->m_pageReferrer;
05462 
05463   // Restore ssl data
05464   stream >> d->m_ssl_in_use
05465          >> d->m_ssl_peer_certificate
05466          >> d->m_ssl_peer_chain
05467          >> d->m_ssl_peer_ip
05468          >> d->m_ssl_cipher
05469          >> d->m_ssl_cipher_desc
05470          >> d->m_ssl_cipher_version
05471          >> d->m_ssl_cipher_used_bits
05472          >> d->m_ssl_cipher_bits
05473          >> d->m_ssl_cert_state
05474          >> d->m_ssl_parent_ip
05475          >> d->m_ssl_parent_cert;
05476 
05477   setPageSecurity( d->m_ssl_in_use ? Encrypted : NotCrypted );
05478 
05479   stream >> frameCount >> frameNames >> frameServiceTypes >> frameServiceNames
05480          >> frameURLs >> frameStateBuffers;
05481 
05482   d->m_bComplete = false;
05483   d->m_bLoadEventEmitted = false;
05484 
05485 //   kdDebug( 6050 ) << "restoreState() docState.count() = " << docState.count() << endl;
05486 //   kdDebug( 6050 ) << "m_url " << m_url.url() << " <-> " << u.url() << endl;
05487 //   kdDebug( 6050 ) << "m_frames.count() " << d->m_frames.count() << " <-> " << frameCount << endl;
05488 
05489   if (d->m_cacheId == old_cacheId)
05490   {
05491     // Partial restore
05492     d->m_redirectionTimer.stop();
05493 
05494     FrameIt fIt = d->m_frames.begin();
05495     const FrameIt fEnd = d->m_frames.end();
05496 
05497     for (; fIt != fEnd; ++fIt )
05498         (*fIt)->m_bCompleted = false;
05499 
05500     fIt = d->m_frames.begin();
05501 
05502     QStringList::ConstIterator fNameIt = frameNames.begin();
05503     QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
05504     QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
05505     KURL::List::ConstIterator fURLIt = frameURLs.begin();
05506     QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
05507 
05508     for (; fIt != fEnd; ++fIt, ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
05509     {
05510       khtml::ChildFrame* const child = *fIt;
05511 
05512 //      kdDebug( 6050 ) <<  *fNameIt  << " ---- " <<  *fServiceTypeIt << endl;
05513 
05514       if ( child->m_name != *fNameIt || child->m_serviceType != *fServiceTypeIt )
05515       {
05516         child->m_bPreloaded = true;
05517         child->m_name = *fNameIt;
05518         child->m_serviceName = *fServiceNameIt;
05519         processObjectRequest( child, *fURLIt, *fServiceTypeIt );
05520       }
05521       if ( child->m_part )
05522       {
05523         child->m_bCompleted = false;
05524         if ( child->m_extension && !(*fBufferIt).isEmpty() )
05525         {
05526           QDataStream frameStream( *fBufferIt, IO_ReadOnly );
05527           child->m_extension->restoreState( frameStream );
05528         }
05529         else
05530           child->m_part->openURL( *fURLIt );
05531       }
05532     }
05533 
05534     KParts::URLArgs args( d->m_extension->urlArgs() );
05535     args.xOffset = xOffset;
05536     args.yOffset = yOffset;
05537     args.docState = docState;
05538     d->m_extension->setURLArgs( args );
05539 
05540     d->m_view->resizeContents( wContents,  hContents);
05541     d->m_view->setContentsPos( xOffset, yOffset );
05542 
05543     m_url = u;
05544   }
05545   else
05546   {
05547     // Full restore.
05548     closeURL();
05549     // We must force a clear because we want to be sure to delete all
05550     // frames.
05551     d->m_bCleared = false;
05552     clear();
05553     d->m_encoding = encoding;
05554     d->m_sheetUsed = sheetUsed;
05555 
05556     QStringList::ConstIterator fNameIt = frameNames.begin();
05557     const QStringList::ConstIterator fNameEnd = frameNames.end();
05558 
05559     QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
05560     QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
05561     KURL::List::ConstIterator fURLIt = frameURLs.begin();
05562     QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
05563 
05564     for (; fNameIt != fNameEnd; ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
05565     {
05566       khtml::ChildFrame* const newChild = new khtml::ChildFrame;
05567       newChild->m_bPreloaded = true;
05568       newChild->m_name = *fNameIt;
05569       newChild->m_serviceName = *fServiceNameIt;
05570 
05571 //      kdDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt << endl;
05572 
05573       const FrameIt childFrame = d->m_frames.append( newChild );
05574 
05575       processObjectRequest( *childFrame, *fURLIt, *fServiceTypeIt );
05576 
05577       (*childFrame)->m_bPreloaded = true;
05578 
05579       if ( (*childFrame)->m_part )
05580       {
05581         if ( (*childFrame)->m_extension )
05582         if ( (*childFrame)->m_extension && !(*fBufferIt).isEmpty() )
05583         {
05584           QDataStream frameStream( *fBufferIt, IO_ReadOnly );
05585           (*childFrame)->m_extension->restoreState( frameStream );
05586         }
05587         else
05588           (*childFrame)->m_part->openURL( *fURLIt );
05589       }
05590     }
05591 
05592     KParts::URLArgs args( d->m_extension->urlArgs() );
05593     args.xOffset = xOffset;
05594     args.yOffset = yOffset;
05595     args.docState = docState;
05596 
05597     d->m_extension->setURLArgs( args );
05598     if (!KHTMLPageCache::self()->isComplete(d->m_cacheId))
05599     {
05600        d->m_restored = true;
05601        openURL( u );
05602        d->m_restored = false;
05603     }
05604     else
05605     {
05606        restoreURL( u );
05607     }
05608   }
05609 
05610 }
05611 
05612 void KHTMLPart::show()
05613 {
05614   if ( d->m_view )
05615     d->m_view->show();
05616 }
05617 
05618 void KHTMLPart::hide()
05619 {
05620   if ( d->m_view )
05621     d->m_view->hide();
05622 }
05623 
05624 DOM::Node KHTMLPart::nodeUnderMouse() const
05625 {
05626     return d->m_view->nodeUnderMouse();
05627 }
05628 
05629 DOM::Node KHTMLPart::nonSharedNodeUnderMouse() const
05630 {
05631     return d->m_view->nonSharedNodeUnderMouse();
05632 }
05633 
05634 void KHTMLPart::emitSelectionChanged()
05635 {
05636   emit d->m_extension->enableAction( "copy", hasSelection() );
05637   if ( d->m_findDialog )
05638        d->m_findDialog->setHasSelection( hasSelection() );
05639 
05640   emit d->m_extension->selectionInfo( selectedText() );
05641   emit selectionChanged();
05642 }
05643 
05644 int KHTMLPart::zoomFactor() const
05645 {
05646   return d->m_zoomFactor;
05647 }
05648 
05649 // ### make the list configurable ?
05650 static const int zoomSizes[] = { 20, 40, 60, 80, 90, 95, 100, 105, 110, 120, 140, 160, 180, 200, 250, 300 };
05651 static const int zoomSizeCount = (sizeof(zoomSizes) / sizeof(int));
05652 static const int minZoom = 20;
05653 static const int maxZoom = 300;
05654 
05655 // My idea of useful stepping ;-) (LS)
05656 extern const int KDE_NO_EXPORT fastZoomSizes[] = { 20, 50, 75, 90, 100, 120, 150, 200, 300 };
05657 extern const int KDE_NO_EXPORT fastZoomSizeCount = sizeof fastZoomSizes / sizeof fastZoomSizes[0];
05658 
05659 void KHTMLPart::slotIncZoom()
05660 {
05661   zoomIn(zoomSizes, zoomSizeCount);
05662 }
05663 
05664 void KHTMLPart::slotDecZoom()
05665 {
05666   zoomOut(zoomSizes, zoomSizeCount);
05667 }
05668 
05669 void KHTMLPart::slotIncZoomFast()
05670 {
05671   zoomIn(fastZoomSizes, fastZoomSizeCount);
05672 }
05673 
05674 void KHTMLPart::slotDecZoomFast()
05675 {
05676   zoomOut(fastZoomSizes, fastZoomSizeCount);
05677 }
05678 
05679 void KHTMLPart::zoomIn(const int stepping[], int count)
05680 {
05681   int zoomFactor = d->m_zoomFactor;
05682 
05683   if (zoomFactor < maxZoom) {
05684     // find the entry nearest to the given zoomsizes
05685     for (int i = 0; i < count; ++i)
05686       if (stepping[i] > zoomFactor) {
05687         zoomFactor = stepping[i];
05688         break;
05689       }
05690     setZoomFactor(zoomFactor);
05691   }
05692 }
05693 
05694 void KHTMLPart::zoomOut(const int stepping[], int count)
05695 {
05696     int zoomFactor = d->m_zoomFactor;
05697     if (zoomFactor > minZoom) {
05698       // find the entry nearest to the given zoomsizes
05699       for (int i = count-1; i >= 0; --i)
05700         if (stepping[i] < zoomFactor) {
05701           zoomFactor = stepping[i];
05702           break;
05703         }
05704       setZoomFactor(zoomFactor);
05705     }
05706 }
05707 
05708 void KHTMLPart::setZoomFactor (int percent)
05709 {
05710   if (percent < minZoom) percent = minZoom;
05711   if (percent > maxZoom) percent = maxZoom;
05712   if (d->m_zoomFactor == percent) return;
05713   d->m_zoomFactor = percent;
05714 
05715   if(d->m_doc) {
05716       QApplication::setOverrideCursor( waitCursor );
05717     if (d->m_doc->styleSelector())
05718       d->m_doc->styleSelector()->computeFontSizes(d->m_doc->paintDeviceMetrics(), d->m_zoomFactor);
05719     d->m_doc->recalcStyle( NodeImpl::Force );
05720     QApplication::restoreOverrideCursor();
05721   }
05722 
05723   ConstFrameIt it = d->m_frames.begin();
05724   const ConstFrameIt end = d->m_frames.end();
05725   for (; it != end; ++it )
05726     if ( !( *it )->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
05727       KParts::ReadOnlyPart* const p = ( *it )->m_part;
05728       static_cast<KHTMLPart*>( p )->setZoomFactor(d->m_zoomFactor);
05729     }
05730 
05731   if ( d->m_guiProfile == BrowserViewGUI ) {
05732       d->m_paDecZoomFactor->setEnabled( d->m_zoomFactor > minZoom );
05733       d->m_paIncZoomFactor->setEnabled( d->m_zoomFactor < maxZoom );
05734   }
05735 }
05736 
05737 void KHTMLPart::slotZoomView( int delta )
05738 {
05739   if ( delta < 0 )
05740     slotIncZoom();
05741   else
05742     slotDecZoom();
05743 }
05744 
05745 void KHTMLPart::setStatusBarText( const QString& text, StatusBarPriority p)
05746 {
05747   if (!d->m_statusMessagesEnabled)
05748     return;
05749 
05750   d->m_statusBarText[p] = text;
05751 
05752   // shift handling ?
05753   QString tobe = d->m_statusBarText[BarHoverText];
05754   if (tobe.isEmpty())
05755     tobe = d->m_statusBarText[BarOverrideText];
05756   if (tobe.isEmpty()) {
05757     tobe = d->m_statusBarText[BarDefaultText];
05758     if (!tobe.isEmpty() && d->m_jobspeed)
05759       tobe += " ";
05760     if (d->m_jobspeed)
05761       tobe += i18n( "(%1/s)" ).arg( KIO::convertSize( d->m_jobspeed ) );
05762   }
05763   tobe = "<qt>"+tobe;
05764 
05765   emit ReadOnlyPart::setStatusBarText(tobe);
05766 }
05767 
05768 
05769 void KHTMLPart::setJSStatusBarText( const QString &text )
05770 {
05771   setStatusBarText(text, BarOverrideText);
05772 }
05773 
05774 void KHTMLPart::setJSDefaultStatusBarText( const QString &text )
05775 {
05776   setStatusBarText(text, BarDefaultText);
05777 }
05778 
05779 QString KHTMLPart::jsStatusBarText() const
05780 {
05781     return d->m_statusBarText[BarOverrideText];
05782 }
05783 
05784 QString KHTMLPart::jsDefaultStatusBarText() const
05785 {
05786    return d->m_statusBarText[BarDefaultText];
05787 }
05788 
05789 QString KHTMLPart::referrer() const
05790 {
05791    return d->m_referrer;
05792 }
05793 
05794 QString KHTMLPart::pageReferrer() const
05795 {
05796    KURL referrerURL = KURL( d->m_pageReferrer );
05797    if (referrerURL.isValid())
05798    {
05799       QString protocol = referrerURL.protocol();
05800 
05801       if ((protocol == "http") ||
05802          ((protocol == "https") && (m_url.protocol() == "https")))
05803       {
05804           referrerURL.setRef(QString::null);
05805           referrerURL.setUser(QString::null);
05806           referrerURL.setPass(QString::null);
05807           return referrerURL.url();
05808       }
05809    }
05810 
05811    return QString::null;
05812 }
05813 
05814 
05815 QString KHTMLPart::lastModified() const
05816 {
05817   if ( d->m_lastModified.isEmpty() && m_url.isLocalFile() ) {
05818     // Local file: set last-modified from the file's mtime.
05819     // Done on demand to save time when this isn't needed - but can lead
05820     // to slightly wrong results if updating the file on disk w/o reloading.
05821     QDateTime lastModif = QFileInfo( m_url.path() ).lastModified();
05822     d->m_lastModified = lastModif.toString( Qt::LocalDate );
05823   }
05824   //kdDebug(6050) << "KHTMLPart::lastModified: " << d->m_lastModified << endl;
05825   return d->m_lastModified;
05826 }
05827 
05828 void KHTMLPart::slotLoadImages()
05829 {
05830   if (d->m_doc )
05831     d->m_doc->docLoader()->setAutoloadImages( !d->m_doc->docLoader()->autoloadImages() );
05832 
05833   ConstFrameIt it = d->m_frames.begin();
05834   const ConstFrameIt end = d->m_frames.end();
05835   for (; it != end; ++it )
05836     if ( !( *it )->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
05837       KParts::ReadOnlyPart* const p = ( *it )->m_part;
05838       static_cast<KHTMLPart*>( p )->slotLoadImages();
05839     }
05840 }
05841 
05842 void KHTMLPart::reparseConfiguration()
05843 {
05844   KHTMLSettings *settings = KHTMLFactory::defaultHTMLSettings();
05845   settings->init();
05846 
05847   setAutoloadImages( settings->autoLoadImages() );
05848   if (d->m_doc)
05849      d->m_doc->docLoader()->setShowAnimations( settings->showAnimations() );
05850 
05851   d->m_bOpenMiddleClick = settings->isOpenMiddleClickEnabled();
05852   d->m_bBackRightClick = settings->isBackRightClickEnabled();
05853   d->m_bJScriptEnabled = settings->isJavaScriptEnabled(m_url.host());
05854   setDebugScript( settings->isJavaScriptDebugEnabled() );
05855   d->m_bJavaEnabled = settings->isJavaEnabled(m_url.host());
05856   d->m_bPluginsEnabled = settings->isPluginsEnabled(m_url.host());
05857   d->m_metaRefreshEnabled = settings->isAutoDelayedActionsEnabled ();
05858 
05859   delete d->m_settings;
05860   d->m_settings = new KHTMLSettings(*KHTMLFactory::defaultHTMLSettings());
05861 
05862   QApplication::setOverrideCursor( waitCursor );
05863   khtml::CSSStyleSelector::reparseConfiguration();
05864   if(d->m_doc) d->m_doc->updateStyleSelector();
05865   QApplication::restoreOverrideCursor();
05866 
05867   if (KHTMLFactory::defaultHTMLSettings()->isAdFilterEnabled())
05868      runAdFilter();
05869 }
05870 
05871 QStringList KHTMLPart::frameNames() const
05872 {
05873   QStringList res;
05874 
05875   ConstFrameIt it = d->m_frames.begin();
05876   const ConstFrameIt end = d->m_frames.end();
05877   for (; it != end; ++it )
05878     if (!(*it)->m_bPreloaded)
05879       res += (*it)->m_name;
05880 
05881   return res;
05882 }
05883 
05884 QPtrList<KParts::ReadOnlyPart> KHTMLPart::frames() const
05885 {
05886   QPtrList<KParts::ReadOnlyPart> res;
05887 
05888   ConstFrameIt it = d->m_frames.begin();
05889   const ConstFrameIt end = d->m_frames.end();
05890   for (; it != end; ++it )
05891     if (!(*it)->m_bPreloaded)
05892       res.append( (*it)->m_part );
05893 
05894   return res;
05895 }
05896 
05897 bool KHTMLPart::openURLInFrame( const KURL &url, const KParts::URLArgs &urlArgs )
05898 {
05899     kdDebug( 6050 ) << this << "KHTMLPart::openURLInFrame " << url << endl;
05900   FrameIt it = d->m_frames.find( urlArgs.frameName );
05901 
05902   if ( it == d->m_frames.end() )
05903     return false;
05904 
05905   // Inform someone that we are about to show something else.
05906   if ( !urlArgs.lockHistory() )
05907       emit d->m_extension->openURLNotify();
05908 
05909   requestObject( *it, url, urlArgs );
05910 
05911   return true;
05912 }
05913 
05914 void KHTMLPart::setDNDEnabled( bool b )
05915 {
05916   d->m_bDnd = b;
05917 }
05918 
05919 bool KHTMLPart::dndEnabled() const
05920 {
05921   return d->m_bDnd;
05922 }
05923 
05924 void KHTMLPart::customEvent( QCustomEvent *event )
05925 {
05926   if ( khtml::MousePressEvent::test( event ) )
05927   {
05928     khtmlMousePressEvent( static_cast<khtml::MousePressEvent *>( event ) );
05929     return;
05930   }
05931 
05932   if ( khtml::MouseDoubleClickEvent::test( event ) )
05933   {
05934     khtmlMouseDoubleClickEvent( static_cast<khtml::MouseDoubleClickEvent *>( event ) );
05935     return;
05936   }
05937 
05938   if ( khtml::MouseMoveEvent::test( event ) )
05939   {
05940     khtmlMouseMoveEvent( static_cast<khtml::MouseMoveEvent *>( event ) );
05941     return;
05942   }
05943 
05944   if ( khtml::MouseReleaseEvent::test( event ) )
05945   {
05946     khtmlMouseReleaseEvent( static_cast<khtml::MouseReleaseEvent *>( event ) );
05947     return;
05948   }
05949 
05950   if ( khtml::DrawContentsEvent::test( event ) )
05951   {
05952     khtmlDrawContentsEvent( static_cast<khtml::DrawContentsEvent *>( event ) );
05953     return;
05954   }
05955 
05956   KParts::ReadOnlyPart::customEvent( event );
05957 }
05958 
05964 static bool firstRunAt(khtml::RenderObject *renderNode, int y, NodeImpl *&startNode, long &startOffset)
05965 {
05966     for (khtml::RenderObject *n = renderNode; n; n = n->nextSibling()) {
05967         if (n->isText()) {
05968             khtml::RenderText* const textRenderer = static_cast<khtml::RenderText *>(n);
05969             const khtml::InlineTextBoxArray &runs = textRenderer->inlineTextBoxes();
05970             const unsigned lim = runs.count();
05971             for (unsigned i = 0; i != lim; ++i) {
05972                 if (runs[i]->m_y == y && textRenderer->element()) {
05973                     startNode = textRenderer->element();
05974                     startOffset = runs[i]->m_start;
05975                     return true;
05976                 }
05977             }
05978         }
05979 
05980         if (firstRunAt(n->firstChild(), y, startNode, startOffset)) {
05981             return true;
05982         }
05983     }
05984 
05985     return false;
05986 }
05987 
05993 static bool lastRunAt(khtml::RenderObject *renderNode, int y, NodeImpl *&endNode, long &endOffset)
05994 {
05995     khtml::RenderObject *n = renderNode;
05996     if (!n) {
05997         return false;
05998     }
05999     khtml::RenderObject *next;
06000     while ((next = n->nextSibling())) {
06001         n = next;
06002     }
06003 
06004     while (1) {
06005         if (lastRunAt(n->firstChild(), y, endNode, endOffset)) {
06006             return true;
06007         }
06008 
06009         if (n->isText()) {
06010             khtml::RenderText* const textRenderer =  static_cast<khtml::RenderText *>(n);
06011             const khtml::InlineTextBoxArray &runs = textRenderer->inlineTextBoxes();
06012             for (int i = (int)runs.count()-1; i >= 0; --i) {
06013                 if (runs[i]->m_y == y && textRenderer->element()) {
06014                     endNode = textRenderer->element();
06015                     endOffset = runs[i]->m_start + runs[i]->m_len;
06016                     return true;
06017                 }
06018             }
06019         }
06020 
06021         if (n == renderNode) {
06022             return false;
06023         }
06024 
06025         n = n->previousSibling();
06026     }
06027 }
06028 
06029 void KHTMLPart::khtmlMousePressEvent( khtml::MousePressEvent *event )
06030 {
06031   DOM::DOMString url = event->url();
06032   QMouseEvent *_mouse = event->qmouseEvent();
06033   DOM::Node innerNode = event->innerNode();
06034   d->m_mousePressNode = innerNode;
06035 
06036    d->m_dragStartPos = _mouse->pos();
06037 
06038    if ( !event->url().isNull() ) {
06039      d->m_strSelectedURL = event->url().string();
06040      d->m_strSelectedURLTarget = event->target().string();
06041    }
06042    else
06043      d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
06044 
06045   if ( _mouse->button() == LeftButton ||
06046        _mouse->button() == MidButton )
06047   {
06048     d->m_bMousePressed = true;
06049 
06050 #ifndef KHTML_NO_SELECTION
06051     if ( _mouse->button() == LeftButton )
06052     {
06053       if ( (!d->m_strSelectedURL.isNull() && !isEditable())
06054             || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) )
06055       return;
06056       if ( !innerNode.isNull()  && innerNode.handle()->renderer()) {
06057           int offset = 0;
06058           DOM::NodeImpl* node = 0;
06059           khtml::RenderObject::SelPointState state;
06060           innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(),
06061                                                                event->absX()-innerNode.handle()->renderer()->xPos(),
06062                                                                event->absY()-innerNode.handle()->renderer()->yPos(), node, offset, state );
06063           d->m_extendMode = d->ExtendByChar;
06064 #ifdef KHTML_NO_CARET
06065           d->m_selectionStart = node;
06066           d->m_startOffset = offset;
06067           //if ( node )
06068           //  kdDebug(6005) << "KHTMLPart::khtmlMousePressEvent selectionStart=" << d->m_selectionStart.handle()->renderer()
06069           //                << " offset=" << d->m_startOffset << endl;
06070           //else
06071           //  kdDebug(6005) << "KHTML::khtmlMousePressEvent selectionStart=(nil)" << endl;
06072           d->m_selectionEnd = d->m_selectionStart;
06073           d->m_endOffset = d->m_startOffset;
06074           d->m_doc->clearSelection();
06075 #else // KHTML_NO_CARET
06076       d->m_view->moveCaretTo(node, offset, (_mouse->state() & ShiftButton) == 0);
06077 #endif // KHTML_NO_CARET
06078       d->m_initialNode = d->m_selectionStart;
06079       d->m_initialOffset = d->m_startOffset;
06080 //           kdDebug(6000) << "press: initOfs " << d->m_initialOffset << endl;
06081       }
06082       else
06083       {
06084 #ifndef KHTML_NO_CARET
06085         // simply leave it. Is this a good idea?
06086 #else
06087         d->m_selectionStart = DOM::Node();
06088         d->m_selectionEnd = DOM::Node();
06089 #endif
06090       }
06091       emitSelectionChanged();
06092       startAutoScroll();
06093     }
06094 #else
06095     d->m_dragLastPos = _mouse->globalPos();
06096 #endif
06097   }
06098 
06099   if ( _mouse->button() == RightButton && parentPart() != 0 && d->m_bBackRightClick )
06100   {
06101     d->m_bRightMousePressed = true;
06102   } else if ( _mouse->button() == RightButton )
06103   {
06104     popupMenu( d->m_strSelectedURL );
06105     // might be deleted, don't touch "this"
06106   }
06107 }
06108 
06109 void KHTMLPart::khtmlMouseDoubleClickEvent( khtml::MouseDoubleClickEvent *event )
06110 {
06111   QMouseEvent *_mouse = event->qmouseEvent();
06112   if ( _mouse->button() == LeftButton )
06113   {
06114     d->m_bMousePressed = true;
06115     DOM::Node innerNode = event->innerNode();
06116     // Find selectionStart again, khtmlMouseReleaseEvent lost it
06117     if ( !innerNode.isNull() && innerNode.handle()->renderer()) {
06118       int offset = 0;
06119       DOM::NodeImpl* node = 0;
06120       khtml::RenderObject::SelPointState state;
06121       innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(),
06122                                                            event->absX()-innerNode.handle()->renderer()->xPos(),
06123                                                            event->absY()-innerNode.handle()->renderer()->yPos(), node, offset, state);
06124 
06125       //kdDebug() << k_funcinfo << "checkSelectionPoint returned node=" << node << " offset=" << offset << endl;
06126 
06127       if ( node && node->renderer() )
06128       {
06129         // Extend selection to a complete word (double-click) or line (triple-click)
06130         bool selectLine = (event->clickCount() == 3);
06131         d->m_extendMode = selectLine ? d->ExtendByLine : d->ExtendByWord;
06132 
06133     // Extend existing selection if Shift was pressed
06134     if (_mouse->state() & ShiftButton) {
06135           d->caretNode() = node;
06136       d->caretOffset() = offset;
06137           d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
06138                 d->m_selectionStart.handle(), d->m_startOffset,
06139             d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
06140           d->m_initialNode = d->m_extendAtEnd ? d->m_selectionStart : d->m_selectionEnd;
06141           d->m_initialOffset = d->m_extendAtEnd ? d->m_startOffset : d->m_endOffset;
06142     } else {
06143       d->m_selectionStart = d->m_selectionEnd = node;
06144       d->m_startOffset = d->m_endOffset = offset;
06145           d->m_startBeforeEnd = true;
06146           d->m_initialNode = node;
06147           d->m_initialOffset = offset;
06148     }
06149 //         kdDebug(6000) << "dblclk: initOfs " << d->m_initialOffset << endl;
06150 
06151         // Extend the start
06152         extendSelection( d->m_selectionStart.handle(), d->m_startOffset, d->m_selectionStart, d->m_startOffset, !d->m_startBeforeEnd, selectLine );
06153         // Extend the end
06154         extendSelection( d->m_selectionEnd.handle(), d->m_endOffset, d->m_selectionEnd, d->m_endOffset, d->m_startBeforeEnd, selectLine );
06155 
06156         //kdDebug() << d->m_selectionStart.handle() << " " << d->m_startOffset << "  -  " <<
06157         //  d->m_selectionEnd.handle() << " " << d->m_endOffset << endl;
06158 
06159         emitSelectionChanged();
06160         d->m_doc
06161           ->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
06162                          d->m_selectionEnd.handle(),d->m_endOffset);
06163 #ifndef KHTML_NO_CARET
06164         bool v = d->m_view->placeCaret();
06165         emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
06166 #endif
06167         startAutoScroll();
06168       }
06169     }
06170   }
06171 }
06172 
06173 void KHTMLPart::extendSelection( DOM::NodeImpl* node, long offset, DOM::Node& selectionNode, long& selectionOffset, bool right, bool selectLines )
06174 {
06175   khtml::RenderObject* obj = node->renderer();
06176 
06177   if (obj->isText() && selectLines) {
06178     int pos;
06179     khtml::RenderText *renderer = static_cast<khtml::RenderText *>(obj);
06180     khtml::InlineTextBox *run = renderer->findInlineTextBox( offset, pos );
06181     DOMString t = node->nodeValue();
06182     DOM::NodeImpl* selNode = 0;
06183     long selOfs = 0;
06184 
06185     if (!run)
06186       return;
06187 
06188     int selectionPointY = run->m_y;
06189 
06190     // Go up to first non-inline element.
06191     khtml::RenderObject *renderNode = renderer;
06192     while (renderNode && renderNode->isInline())
06193       renderNode = renderNode->parent();
06194 
06195     renderNode = renderNode->firstChild();
06196 
06197     if (right) {
06198       // Look for all the last child in the block that is on the same line
06199       // as the selection point.
06200       if (!lastRunAt (renderNode, selectionPointY, selNode, selOfs))
06201         return;
06202     } else {
06203       // Look for all the first child in the block that is on the same line
06204       // as the selection point.
06205       if (!firstRunAt (renderNode, selectionPointY, selNode, selOfs))
06206         return;
06207     }
06208 
06209     selectionNode = selNode;
06210     selectionOffset = selOfs;
06211     return;
06212   }
06213 
06214   QString str;
06215   int len = 0;
06216   if ( obj->isText() ) { // can be false e.g. when double-clicking on a disabled submit button
06217     str = static_cast<khtml::RenderText *>(obj)->data().string();
06218     len = str.length();
06219   }
06220   //kdDebug() << "extendSelection right=" << right << " offset=" << offset << " len=" << len << " Starting at obj=" << obj << endl;
06221   QChar ch;
06222   do {
06223     // Last char was ok, point to it
06224     if ( node ) {
06225       selectionNode = node;
06226       selectionOffset = offset;
06227     }
06228 
06229     // Get another char
06230     while ( obj && ( (right && offset >= len-1) || (!right && offset <= 0) ) )
06231     {
06232       obj = right ? obj->objectBelow() : obj->objectAbove();
06233       //kdDebug() << "obj=" << obj << endl;
06234       if ( obj ) {
06235         //kdDebug() << "isText=" << obj->isText() << endl;
06236         str = QString::null;
06237         if ( obj->isText() )
06238           str = static_cast<khtml::RenderText *>(obj)->data().string();
06239         else if ( obj->isBR() )
06240           str = '\n';
06241         else if ( !obj->isInline() ) {
06242           obj = 0L; // parag limit -> done
06243           break;
06244         }
06245         len = str.length();
06246         //kdDebug() << "str=" << str << " length=" << len << endl;
06247         // set offset - note that the first thing will be a ++ or -- on it.
06248         if ( right )
06249           offset = -1;
06250         else
06251           offset = len;
06252       }
06253     }
06254     if ( !obj ) // end of parag or document
06255       break;
06256     node = obj->element();
06257     if ( right )
06258     {
06259       Q_ASSERT( offset < len-1 );
06260       ++offset;
06261     }
06262     else
06263     {
06264       Q_ASSERT( offset > 0 );
06265       --offset;
06266     }
06267 
06268     // Test that char
06269     ch = str[ (int)offset ];
06270     //kdDebug() << " offset=" << offset << " ch=" << QString(ch) << endl;
06271   } while ( !ch.isSpace() && !ch.isPunct() );
06272 
06273   // make offset point after last char
06274   if (right) ++selectionOffset;
06275 }
06276 
06277 #ifndef KHTML_NO_SELECTION
06278 void KHTMLPart::extendSelectionTo(int x, int y, int absX, int absY, const DOM::Node &innerNode)
06279 {
06280       int offset;
06281       //kdDebug(6000) << "KHTMLPart::khtmlMouseMoveEvent x=" << event->x() << " y=" << event->y() << endl;
06282       DOM::NodeImpl* node=0;
06283       khtml::RenderObject::SelPointState state;
06284       innerNode.handle()->renderer()->checkSelectionPoint( x, y,
06285                                                            absX-innerNode.handle()->renderer()->xPos(),
06286                                                            absY-innerNode.handle()->renderer()->yPos(), node, offset, state);
06287       if (!node || !node->renderer()) return;
06288 
06289       // Words at the beginning/end of line cannot be deselected in
06290       // ExtendByWord mode. Therefore, do not enforce it if the selection
06291       // point does not match the node under the mouse cursor.
06292       bool withinNode = innerNode == node;
06293 
06294       // we have to get to know if end is before start or not...
06295       // shouldn't be null but it can happen with dynamic updating of nodes
06296       if (d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() ||
06297           d->m_initialNode.isNull() ||
06298           !d->m_selectionStart.handle()->renderer() ||
06299           !d->m_selectionEnd.handle()->renderer()) return;
06300 
06301       if (d->m_extendMode != d->ExtendByChar) {
06302         // check whether we should extend at the front, or at the back
06303         bool caretBeforeInit = RangeImpl::compareBoundaryPoints(
06304                 d->caretNode().handle(), d->caretOffset(),
06305             d->m_initialNode.handle(), d->m_initialOffset) <= 0;
06306         bool nodeBeforeInit = RangeImpl::compareBoundaryPoints(node, offset,
06307             d->m_initialNode.handle(), d->m_initialOffset) <= 0;
06308         // have to fix up start to point to the original end
06309         if (caretBeforeInit != nodeBeforeInit) {
06310 //         kdDebug(6000) << "extto cbi: " << caretBeforeInit << " startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << " initOfs " << d->m_initialOffset << endl;
06311           extendSelection(d->m_initialNode.handle(), d->m_initialOffset,
06312         d->m_extendAtEnd ? d->m_selectionStart : d->m_selectionEnd,
06313         d->m_extendAtEnd ? d->m_startOffset : d->m_endOffset,
06314         nodeBeforeInit, d->m_extendMode == d->ExtendByLine);
06315     }
06316       }
06317 
06318       d->caretNode() = node;
06319       d->caretOffset() = offset;
06320       //kdDebug( 6000 ) << "setting end of selection to " << d->m_selectionEnd.handle() << "/" << d->m_endOffset << endl;
06321 
06322       d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
06323                 d->m_selectionStart.handle(), d->m_startOffset,
06324             d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
06325 
06326       if ( !d->m_selectionStart.isNull() && !d->m_selectionEnd.isNull() )
06327       {
06328 //         kdDebug(6000) << "extto: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << " initOfs " << d->m_initialOffset << endl;
06329         if (d->m_extendMode != d->ExtendByChar && withinNode)
06330           extendSelection( node, offset, d->caretNode(), d->caretOffset(), d->m_startBeforeEnd ^ !d->m_extendAtEnd, d->m_extendMode == d->ExtendByLine );
06331 
06332         if (d->m_selectionEnd == d->m_selectionStart && d->m_endOffset < d->m_startOffset)
06333           d->m_doc
06334             ->setSelection(d->m_selectionStart.handle(),d->m_endOffset,
06335                            d->m_selectionEnd.handle(),d->m_startOffset);
06336         else if (d->m_startBeforeEnd)
06337           d->m_doc
06338             ->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
06339                            d->m_selectionEnd.handle(),d->m_endOffset);
06340         else
06341           d->m_doc
06342             ->setSelection(d->m_selectionEnd.handle(),d->m_endOffset,
06343                            d->m_selectionStart.handle(),d->m_startOffset);
06344       }
06345 #ifndef KHTML_NO_CARET
06346       d->m_view->placeCaret();
06347 #endif
06348 }
06349 
06350 bool KHTMLPart::isExtendingSelection() const
06351 {
06352   // This is it, the whole detection. khtmlMousePressEvent only sets this
06353   // on LMB or MMB, but never on RMB. As text selection doesn't work for MMB,
06354   // it's sufficient to only rely on this flag to detect selection extension.
06355   return d->m_bMousePressed;
06356 }
06357 #endif // KHTML_NO_SELECTION
06358 
06359 void KHTMLPart::khtmlMouseMoveEvent( khtml::MouseMoveEvent *event )
06360 {
06361   QMouseEvent *_mouse = event->qmouseEvent();
06362 
06363   if( d->m_bRightMousePressed && parentPart() != 0 && d->m_bBackRightClick )
06364   {
06365     popupMenu( d->m_strSelectedURL );
06366     d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
06367     d->m_bRightMousePressed = false;
06368   }
06369 
06370   DOM::DOMString url = event->url();
06371   DOM::DOMString target = event->target();
06372   DOM::Node innerNode = event->innerNode();
06373 
06374 #ifndef QT_NO_DRAGANDDROP
06375   if( d->m_bDnd && d->m_bMousePressed &&
06376       ( (!d->m_strSelectedURL.isEmpty() && !isEditable())
06377         || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) ) ) {
06378     if ( ( d->m_dragStartPos - _mouse->pos() ).manhattanLength() <= KGlobalSettings::dndEventDelay() )
06379       return;
06380 
06381     QPixmap pix;
06382     HTMLImageElementImpl *img = 0L;
06383     QDragObject *drag = 0;
06384     KURL u;
06385 
06386     // qDebug("****************** Event URL: %s", url.string().latin1());
06387     // qDebug("****************** Event Target: %s", target.string().latin1());
06388 
06389     // Normal image...
06390     if ( url.length() == 0 && innerNode.handle() && innerNode.handle()->id() == ID_IMG )
06391     {
06392       img = static_cast<HTMLImageElementImpl *>(innerNode.handle());
06393       u = KURL( completeURL( khtml::parseURL(img->getAttribute(ATTR_SRC)).string() ) );
06394       pix = KMimeType::mimeType("image/png")->pixmap(KIcon::Desktop);
06395     }
06396     else
06397     {
06398       // Text or image link...
06399       u = completeURL( d->m_strSelectedURL );
06400       pix = KMimeType::pixmapForURL(u, 0, KIcon::Desktop, KIcon::SizeMedium);
06401     }
06402 
06403     u.setPass(QString::null);
06404 
06405     KURLDrag* urlDrag = new KURLDrag( u, img ? 0 : d->m_view->viewport() );
06406     if ( !d->m_referrer.isEmpty() )
06407       urlDrag->metaData()["referrer"] = d->m_referrer;
06408 
06409     if( img && img->complete()) {
06410       KMultipleDrag *mdrag = new KMultipleDrag( d->m_view->viewport() );
06411       mdrag->addDragObject( new QImageDrag( img->currentImage(), 0L ) );
06412       mdrag->addDragObject( urlDrag );
06413       drag = mdrag;
06414     }
06415     else
06416       drag = urlDrag;
06417 
06418     if ( !pix.isNull() )
06419       drag->setPixmap( pix );
06420 
06421     stopAutoScroll();
06422     if(drag)
06423       drag->drag();
06424 
06425     // when we finish our drag, we need to undo our mouse press
06426     d->m_bMousePressed = false;
06427     d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
06428     return;
06429   }
06430 #endif
06431 
06432   // Not clicked -> mouse over stuff
06433   if ( !d->m_bMousePressed )
06434   {
06435     // The mouse is over something
06436     if ( url.length() )
06437     {
06438       bool shiftPressed = ( _mouse->state() & ShiftButton );
06439 
06440       // Image map
06441       if ( !innerNode.isNull() && innerNode.elementId() == ID_IMG )
06442       {
06443         HTMLImageElementImpl *i = static_cast<HTMLImageElementImpl *>(innerNode.handle());
06444         if ( i && i->isServerMap() )
06445         {
06446           khtml::RenderObject *r = i->renderer();
06447           if(r)
06448           {
06449             int absx, absy, vx, vy;
06450             r->absolutePosition(absx, absy);
06451             view()->contentsToViewport( absx, absy, vx, vy );
06452 
06453             int x(_mouse->x() - vx), y(_mouse->y() - vy);
06454 
06455             d->m_overURL = url.string() + QString("?%1,%2").arg(x).arg(y);
06456             d->m_overURLTarget = target.string();
06457             overURL( d->m_overURL, target.string(), shiftPressed );
06458             return;
06459           }
06460         }
06461       }
06462 
06463       // normal link
06464       if ( d->m_overURL.isEmpty() || d->m_overURL != url || d->m_overURLTarget != target )
06465       {
06466         d->m_overURL = url.string();
06467         d->m_overURLTarget = target.string();
06468         overURL( d->m_overURL, target.string(), shiftPressed );
06469       }
06470     }
06471     else  // Not over a link...
06472     {
06473       // reset to "default statusbar text"
06474       resetHoverText();
06475     }
06476   }
06477   else {
06478 #ifndef KHTML_NO_SELECTION
06479     // selection stuff
06480     if( d->m_bMousePressed && innerNode.handle() && innerNode.handle()->renderer() &&
06481         ( (_mouse->state() & LeftButton) != 0 )) {
06482       extendSelectionTo(event->x(), event->y(),
06483                         event->absX(), event->absY(), innerNode);
06484 #else
06485       if ( d->m_doc && d->m_view ) {
06486         QPoint diff( _mouse->globalPos() - d->m_dragLastPos );
06487 
06488         if ( abs( diff.x() ) > 64 || abs( diff.y() ) > 64 ) {
06489           d->m_view->scrollBy( -diff.x(), -diff.y() );
06490           d->m_dragLastPos = _mouse->globalPos();
06491         }
06492 #endif
06493     }
06494   }
06495 
06496 }
06497 
06498 void KHTMLPart::khtmlMouseReleaseEvent( khtml::MouseReleaseEvent *event )
06499 {
06500   DOM::Node innerNode = event->innerNode();
06501   d->m_mousePressNode = DOM::Node();
06502 
06503   if ( d->m_bMousePressed ) {
06504     setStatusBarText(QString::null, BarHoverText);
06505     stopAutoScroll();
06506   }
06507 
06508   // Used to prevent mouseMoveEvent from initiating a drag before
06509   // the mouse is pressed again.
06510   d->m_bMousePressed = false;
06511 
06512   QMouseEvent *_mouse = event->qmouseEvent();
06513   if ( _mouse->button() == RightButton && parentPart() != 0 && d->m_bBackRightClick )
06514   {
06515     d->m_bRightMousePressed = false;
06516     KParts::BrowserInterface *tmp_iface = d->m_extension->browserInterface();
06517     if( tmp_iface ) {
06518       tmp_iface->callMethod( "goHistory(int)", -1 );
06519     }
06520   }
06521 #ifndef QT_NO_CLIPBOARD
06522   if ((d->m_guiProfile == BrowserViewGUI) && (_mouse->button() == MidButton) && (event->url().isNull())) {
06523     kdDebug( 6050 ) << "KHTMLPart::khtmlMouseReleaseEvent() MMB shouldOpen="
06524                     << d->m_bOpenMiddleClick << endl;
06525 
06526     if (d->m_bOpenMiddleClick) {
06527     KHTMLPart *p = this;
06528     while (p->parentPart()) p = p->parentPart();
06529     p->d->m_extension->pasteRequest();
06530   }
06531   }
06532 #endif
06533 
06534 #ifndef KHTML_NO_SELECTION
06535   // delete selection in case start and end position are at the same point
06536   if(d->m_selectionStart == d->m_selectionEnd && d->m_startOffset == d->m_endOffset) {
06537 #ifndef KHTML_NO_CARET
06538     d->m_extendAtEnd = true;
06539 #else
06540     d->m_selectionStart = 0;
06541     d->m_selectionEnd = 0;
06542     d->m_startOffset = 0;
06543     d->m_endOffset = 0;
06544 #endif
06545     emitSelectionChanged();
06546   } else {
06547     // we have to get to know if end is before start or not...
06548 //     kdDebug(6000) << "rel: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << endl;
06549     DOM::Node n = d->m_selectionStart;
06550     d->m_startBeforeEnd = false;
06551     if( d->m_selectionStart == d->m_selectionEnd ) {
06552       if( d->m_startOffset < d->m_endOffset )
06553         d->m_startBeforeEnd = true;
06554     } else {
06555 #if 0
06556       while(!n.isNull()) {
06557         if(n == d->m_selectionEnd) {
06558           d->m_startBeforeEnd = true;
06559           break;
06560         }
06561         DOM::Node next = n.firstChild();
06562         if(next.isNull()) next = n.nextSibling();
06563         while( next.isNull() && !n.parentNode().isNull() ) {
06564           n = n.parentNode();
06565           next = n.nextSibling();
06566         }
06567         n = next;
06568       }
06569 #else
06570       // shouldn't be null but it can happen with dynamic updating of nodes
06571       if (d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() ||
06572           !d->m_selectionStart.handle()->renderer() ||
06573           !d->m_selectionEnd.handle()->renderer()) return;
06574       d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
06575                 d->m_selectionStart.handle(), d->m_startOffset,
06576             d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
06577 #endif
06578     }
06579     if(!d->m_startBeforeEnd)
06580     {
06581       DOM::Node tmpNode = d->m_selectionStart;
06582       int tmpOffset = d->m_startOffset;
06583       d->m_selectionStart = d->m_selectionEnd;
06584       d->m_startOffset = d->m_endOffset;
06585       d->m_selectionEnd = tmpNode;
06586       d->m_endOffset = tmpOffset;
06587       d->m_startBeforeEnd = true;
06588       d->m_extendAtEnd = !d->m_extendAtEnd;
06589     }
06590 #ifndef KHTML_NO_CARET
06591     bool v = d->m_view->placeCaret();
06592     emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
06593 #endif
06594     // get selected text and paste to the clipboard
06595 #ifndef QT_NO_CLIPBOARD
06596     QString text = selectedText();
06597     text.replace(QChar(0xa0), ' ');
06598     disconnect( kapp->clipboard(), SIGNAL( selectionChanged()), this, SLOT( slotClearSelection()));
06599     kapp->clipboard()->setText(text,QClipboard::Selection);
06600     connect( kapp->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection()));
06601 #endif
06602     //kdDebug( 6000 ) << "selectedText = " << text << endl;
06603     emitSelectionChanged();
06604 //kdDebug(6000) << "rel2: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << "), caretOfs " << d->caretOffset() << endl;
06605   }
06606 #endif
06607   d->m_initialNode = 0;     // don't hold nodes longer than necessary
06608   d->m_initialOffset = 0;
06609 
06610 }
06611 
06612 void KHTMLPart::khtmlDrawContentsEvent( khtml::DrawContentsEvent * )
06613 {
06614 }
06615 
06616 void KHTMLPart::guiActivateEvent( KParts::GUIActivateEvent *event )
06617 {
06618   if ( event->activated() )
06619   {
06620     emitSelectionChanged();
06621     emit d->m_extension->enableAction( "print", d->m_doc != 0 );
06622 
06623     if ( !d->m_settings->autoLoadImages() && d->m_paLoadImages )
06624     {
06625         QPtrList<KAction> lst;
06626         lst.append( d->m_paLoadImages );
06627         plugActionList( "loadImages", lst );
06628     }
06629   }
06630 }
06631 
06632 void KHTMLPart::slotPrintFrame()
06633 {
06634   if ( d->m_frames.count() == 0 )
06635     return;
06636 
06637   KParts::ReadOnlyPart *frame = currentFrame();
06638   if (!frame)
06639     return;
06640 
06641   KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject( frame );
06642 
06643   if ( !ext )
06644     return;
06645 
06646   QMetaObject *mo = ext->metaObject();
06647 
06648   int idx = mo->findSlot( "print()", true );
06649   if ( idx >= 0 ) {
06650     QUObject o[ 1 ];
06651     ext->qt_invoke( idx, o );
06652   }
06653 }
06654 
06655 void KHTMLPart::slotSelectAll()
06656 {
06657   KParts::ReadOnlyPart *part = currentFrame();
06658   if (part && part->inherits("KHTMLPart"))
06659     static_cast<KHTMLPart *>(part)->selectAll();
06660 }
06661 
06662 void KHTMLPart::startAutoScroll()
06663 {
06664    connect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
06665    d->m_scrollTimer.start(100, false);
06666 }
06667 
06668 void KHTMLPart::stopAutoScroll()
06669 {
06670    disconnect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
06671    if (d->m_scrollTimer.isActive())
06672        d->m_scrollTimer.stop();
06673 }
06674 
06675 
06676 void KHTMLPart::slotAutoScroll()
06677 {
06678     if (d->m_view)
06679       d->m_view->doAutoScroll();
06680     else
06681       stopAutoScroll(); // Safety
06682 }
06683 
06684 void KHTMLPart::runAdFilter()
06685 {
06686     if ( parentPart() )
06687         parentPart()->runAdFilter();
06688 
06689     if ( !d->m_doc )
06690         return;
06691 
06692     QPtrDictIterator<khtml::CachedObject> it( d->m_doc->docLoader()->m_docObjects );
06693     for ( ; it.current(); ++it )
06694         if ( it.current()->type() == khtml::CachedObject::Image ) {
06695             khtml::CachedImage *image = static_cast<khtml::CachedImage *>(it.current());
06696             bool wasBlocked = image->m_wasBlocked;
06697             image->m_wasBlocked = KHTMLFactory::defaultHTMLSettings()->isAdFiltered( d->m_doc->completeURL( (*it).url().string() ) );
06698             if ( image->m_wasBlocked != wasBlocked )
06699                 image->do_notify(image->pixmap(), image->valid_rect());
06700         }
06701 
06702     if ( KHTMLFactory::defaultHTMLSettings()->isHideAdsEnabled() ) {
06703         for ( NodeImpl *nextNode, *node = d->m_doc; node; node = nextNode ) {
06704 
06705             // We might be deleting 'node' shortly.
06706             nextNode = node->traverseNextNode();
06707 
06708             if ( node->id() == ID_IMG ||
06709                  node->id() == ID_IFRAME ||
06710                  (node->id() == ID_INPUT && static_cast<HTMLInputElementImpl *>(node)->inputType() == HTMLInputElementImpl::IMAGE ))
06711             {
06712                 if ( KHTMLFactory::defaultHTMLSettings()->isAdFiltered( d->m_doc->completeURL( static_cast<ElementImpl *>(node)->getAttribute(ATTR_SRC).string() ) ) )
06713                 {
06714                     // We found an IMG, IFRAME or INPUT (of type IMAGE) matching a filter.
06715                     node->ref();
06716                     NodeImpl *parent = node->parent();
06717                     if( parent )
06718                     {
06719                         int exception = 0;
06720                         parent->removeChild(node, exception);
06721                     }
06722                     node->deref();
06723                 }
06724             }
06725         }
06726     }
06727 }
06728 
06729 void KHTMLPart::selectAll()
06730 {
06731   if (!d->m_doc) return;
06732 
06733   NodeImpl *first;
06734   if (d->m_doc->isHTMLDocument())
06735     first = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
06736   else
06737     first = d->m_doc;
06738   NodeImpl *next;
06739 
06740   // Look for first text/cdata node that has a renderer,
06741   // or first childless replaced element
06742   while ( first && !(first->renderer()
06743     && ((first->nodeType() == Node::TEXT_NODE || first->nodeType() == Node::CDATA_SECTION_NODE)
06744         || (first->renderer()->isReplaced() && !first->renderer()->firstChild()))))
06745   {
06746     next = first->firstChild();
06747     if ( !next ) next = first->nextSibling();
06748     while( first && !next )
06749     {
06750       first = first->parentNode();
06751       if ( first )
06752         next = first->nextSibling();
06753     }
06754     first = next;
06755   }
06756 
06757   NodeImpl *last;
06758   if (d->m_doc->isHTMLDocument())
06759     last = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
06760   else
06761     last = d->m_doc;
06762   // Look for last text/cdata node that has a renderer,
06763   // or last childless replaced element
06764   // ### Instead of changing this loop, use findLastSelectableNode
06765   // in render_table.cpp (LS)
06766   while ( last && !(last->renderer()
06767     && ((last->nodeType() == Node::TEXT_NODE || last->nodeType() == Node::CDATA_SECTION_NODE)
06768         || (last->renderer()->isReplaced() && !last->renderer()->lastChild()))))
06769   {
06770     next = last->lastChild();
06771     if ( !next ) next = last->previousSibling();
06772     while ( last && !next )
06773     {
06774       last = last->parentNode();
06775       if ( last )
06776         next = last->previousSibling();
06777     }
06778     last = next;
06779   }
06780 
06781   if ( !first || !last )
06782     return;
06783   Q_ASSERT(first->renderer());
06784   Q_ASSERT(last->renderer());
06785   d->m_selectionStart = first;
06786   d->m_startOffset = 0;
06787   d->m_selectionEnd = last;
06788   d->m_endOffset = last->nodeValue().length();
06789   d->m_startBeforeEnd = true;
06790 
06791   d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
06792                           d->m_selectionEnd.handle(), d->m_endOffset );
06793 
06794   emitSelectionChanged();
06795 }
06796 
06797 bool KHTMLPart::checkLinkSecurity(const KURL &linkURL,const QString &message, const QString &button)
06798 {
06799   bool linkAllowed = true;
06800 
06801   if ( d->m_doc )
06802     linkAllowed = kapp && kapp->authorizeURLAction("redirect", url(), linkURL);
06803 
06804   if ( !linkAllowed ) {
06805     khtml::Tokenizer *tokenizer = d->m_doc->tokenizer();
06806     if (tokenizer)
06807       tokenizer->setOnHold(true);
06808 
06809     int response = KMessageBox::Cancel;
06810     if (!message.isEmpty())
06811     {
06812         response = KMessageBox::warningContinueCancel( 0,
06813                                message.arg(linkURL.htmlURL()),
06814                                i18n( "Security Warning" ),
06815                                button);
06816     }
06817     else
06818     {
06819         KMessageBox::error( 0,
06820                 i18n( "<qt>Access by untrusted page to<BR><B>%1</B><BR> denied.").arg(linkURL.htmlURL()),
06821                 i18n( "Security Alert" ));
06822     }
06823 
06824     if (tokenizer)
06825        tokenizer->setOnHold(false);
06826     return (response==KMessageBox::Continue);
06827   }
06828   return true;
06829 }
06830 
06831 void KHTMLPart::slotPartRemoved( KParts::Part *part )
06832 {
06833 //    kdDebug(6050) << "KHTMLPart::slotPartRemoved " << part << endl;
06834     if ( part == d->m_activeFrame )
06835     {
06836         d->m_activeFrame = 0L;
06837         if ( !part->inherits( "KHTMLPart" ) )
06838         {
06839             if (factory()) {
06840                 factory()->removeClient( part );
06841             }
06842             if (childClients()->containsRef(part)) {
06843                 removeChildClient( part );
06844             }
06845         }
06846     }
06847 }
06848 
06849 void KHTMLPart::slotActiveFrameChanged( KParts::Part *part )
06850 {
06851 //    kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged this=" << this << "part=" << part << endl;
06852     if ( part == this )
06853     {
06854         kdError(6050) << "strange error! we activated ourselves" << endl;
06855         assert( false );
06856         return;
06857     }
06858 //    kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged d->m_activeFrame=" << d->m_activeFrame << endl;
06859     if ( d->m_activeFrame && d->m_activeFrame->widget() && d->m_activeFrame->widget()->inherits( "QFrame" ) )
06860     {
06861         QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() );
06862         if (frame->frameStyle() != QFrame::NoFrame)
06863         {
06864            frame->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken);
06865            frame->repaint();
06866         }
06867     }
06868 
06869     if( d->m_activeFrame && !d->m_activeFrame->inherits( "KHTMLPart" ) )
06870     {
06871         if (factory()) {
06872             factory()->removeClient( d->m_activeFrame );
06873         }
06874         removeChildClient( d->m_activeFrame );
06875     }
06876     if( part && !part->inherits( "KHTMLPart" ) )
06877     {
06878         if (factory()) {
06879             factory()->addClient( part );
06880         }
06881         insertChildClient( part );
06882     }
06883 
06884 
06885     d->m_activeFrame = part;
06886 
06887     if ( d->m_activeFrame && d->m_activeFrame->widget()->inherits( "QFrame" ) )
06888     {
06889         QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() );
06890         if (frame->frameStyle() != QFrame::NoFrame)
06891         {
06892            frame->setFrameStyle( QFrame::StyledPanel | QFrame::Plain);
06893            frame->repaint();
06894         }
06895         kdDebug(6050) << "new active frame " << d->m_activeFrame << endl;
06896     }
06897 
06898     updateActions();
06899 
06900     // (note: childObject returns 0 if the argument is 0)
06901     d->m_extension->setExtensionProxy( KParts::BrowserExtension::childObject( d->m_activeFrame ) );
06902 }
06903 
06904 void KHTMLPart::setActiveNode(const DOM::Node &node)
06905 {
06906     if (!d->m_doc || !d->m_view)
06907         return;
06908 
06909     // Set the document's active node
06910     d->m_doc->setFocusNode(node.handle());
06911 
06912     // Scroll the view if necessary to ensure that the new focus node is visible
06913     QRect rect  = node.handle()->getRect();
06914     d->m_view->ensureVisible(rect.right(), rect.bottom());
06915     d->m_view->ensureVisible(rect.left(), rect.top());
06916 }
06917 
06918 DOM::Node KHTMLPart::activeNode() const
06919 {
06920     return DOM::Node(d->m_doc?d->m_doc->focusNode():0);
06921 }
06922 
06923 DOM::EventListener *KHTMLPart::createHTMLEventListener( QString code, QString name, NodeImpl* node )
06924 {
06925   KJSProxy *proxy = jScript();
06926 
06927   if (!proxy)
06928     return 0;
06929 
06930   return proxy->createHTMLEventHandler( m_url.url(), name, code, node );
06931 }
06932 
06933 KHTMLPart *KHTMLPart::opener()
06934 {
06935     return d->m_opener;
06936 }
06937 
06938 void KHTMLPart::setOpener(KHTMLPart *_opener)
06939 {
06940     d->m_opener = _opener;
06941 }
06942 
06943 bool KHTMLPart::openedByJS()
06944 {
06945     return d->m_openedByJS;
06946 }
06947 
06948 void KHTMLPart::setOpenedByJS(bool _openedByJS)
06949 {
06950     d->m_openedByJS = _openedByJS;
06951 }
06952 
06953 void KHTMLPart::preloadStyleSheet(const QString &url, const QString &stylesheet)
06954 {
06955     khtml::Cache::preloadStyleSheet(url, stylesheet);
06956 }
06957 
06958 void KHTMLPart::preloadScript(const QString &url, const QString &script)
06959 {
06960     khtml::Cache::preloadScript(url, script);
06961 }
06962 
06963 QCString KHTMLPart::dcopObjectId() const
06964 {
06965   QCString id;
06966   id.sprintf("html-widget%d", d->m_dcop_counter);
06967   return id;
06968 }
06969 
06970 long KHTMLPart::cacheId() const
06971 {
06972   return d->m_cacheId;
06973 }
06974 
06975 bool KHTMLPart::restored() const
06976 {
06977   return d->m_restored;
06978 }
06979 
06980 bool KHTMLPart::pluginPageQuestionAsked(const QString& mimetype) const
06981 {
06982   // parentPart() should be const!
06983   KHTMLPart* parent = const_cast<KHTMLPart *>(this)->parentPart();
06984   if ( parent )
06985     return parent->pluginPageQuestionAsked(mimetype);
06986 
06987   return d->m_pluginPageQuestionAsked.contains(mimetype);
06988 }
06989 
06990 void KHTMLPart::setPluginPageQuestionAsked(const QString& mimetype)
06991 {
06992   if ( parentPart() )
06993     parentPart()->setPluginPageQuestionAsked(mimetype);
06994 
06995   d->m_pluginPageQuestionAsked.append(mimetype);
06996 }
06997 
06998 void KHTMLPart::slotAutomaticDetectionLanguage( int _id )
06999 {
07000   d->m_automaticDetection->setItemChecked( _id, true );
07001 
07002   switch ( _id ) {
07003     case 0 :
07004       d->m_autoDetectLanguage = khtml::Decoder::SemiautomaticDetection;
07005       break;
07006     case 1 :
07007       d->m_autoDetectLanguage = khtml::Decoder::Arabic;
07008       break;
07009     case 2 :
07010       d->m_autoDetectLanguage = khtml::Decoder::Baltic;
07011       break;
07012     case 3 :
07013       d->m_autoDetectLanguage = khtml::Decoder::CentralEuropean;
07014       break;
07015     case 4 :
07016       d->m_autoDetectLanguage = khtml::Decoder::Chinese;
07017       break;
07018     case 5 :
07019       d->m_autoDetectLanguage = khtml::Decoder::Greek;
07020       break;
07021     case 6 :
07022       d->m_autoDetectLanguage = khtml::Decoder::Hebrew;
07023       break;
07024     case 7 :
07025       d->m_autoDetectLanguage = khtml::Decoder::Japanese;
07026       break;
07027     case 8 :
07028       d->m_autoDetectLanguage = khtml::Decoder::Korean;
07029       break;
07030     case 9 :
07031       d->m_autoDetectLanguage = khtml::Decoder::Russian;
07032       break;
07033     case 10 :
07034       d->m_autoDetectLanguage = khtml::Decoder::Thai;
07035       break;
07036     case 11 :
07037       d->m_autoDetectLanguage = khtml::Decoder::Turkish;
07038       break;
07039     case 12 :
07040       d->m_autoDetectLanguage = khtml::Decoder::Ukrainian;
07041       break;
07042     case 13 :
07043       d->m_autoDetectLanguage = khtml::Decoder::Unicode;
07044       break;
07045     case 14 :
07046       d->m_autoDetectLanguage = khtml::Decoder::WesternEuropean;
07047       break;
07048     default :
07049       d->m_autoDetectLanguage = khtml::Decoder::SemiautomaticDetection;
07050       break;
07051   }
07052 
07053   for ( int i = 0; i <= 14; ++i ) {
07054     if ( i != _id )
07055       d->m_automaticDetection->setItemChecked( i, false );
07056   }
07057 
07058   d->m_paSetEncoding->popupMenu()->setItemChecked( 0, true );
07059 
07060   setEncoding( QString::null, false );
07061 
07062   if( d->m_manualDetection )
07063     d->m_manualDetection->setCurrentItem( -1 );
07064   d->m_paSetEncoding->popupMenu()->setItemChecked( d->m_paSetEncoding->popupMenu()->idAt( 2 ), false );
07065 }
07066 
07067 khtml::Decoder *KHTMLPart::createDecoder()
07068 {
07069     khtml::Decoder *dec = new khtml::Decoder();
07070     if( !d->m_encoding.isNull() )
07071         dec->setEncoding( d->m_encoding.latin1(),
07072             d->m_haveEncoding ? khtml::Decoder::UserChosenEncoding : khtml::Decoder::EncodingFromHTTPHeader);
07073     else {
07074         // Inherit the default encoding from the parent frame if there is one.
07075         const char *defaultEncoding = (parentPart() && parentPart()->d->m_decoder)
07076             ? parentPart()->d->m_decoder->encoding() : settings()->encoding().latin1();
07077         dec->setEncoding(defaultEncoding, khtml::Decoder::DefaultEncoding);
07078     }
07079 #ifdef APPLE_CHANGES
07080     if (d->m_doc)
07081         d->m_doc->setDecoder(d->m_decoder);
07082 #endif
07083     dec->setAutoDetectLanguage( d->m_autoDetectLanguage );
07084     return dec;
07085 }
07086 
07087 void KHTMLPart::emitCaretPositionChanged(const DOM::Node &node, long offset) {
07088   emit caretPositionChanged(node, offset);
07089 }
07090 
07091 void KHTMLPart::restoreScrollPosition()
07092 {
07093   KParts::URLArgs args = d->m_extension->urlArgs();
07094 
07095   if ( m_url.hasRef() && !d->m_restoreScrollPosition && !args.reload) {
07096     if ( !d->m_doc || !d->m_doc->parsing() )
07097       disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
07098     if ( !gotoAnchor(m_url.encodedHtmlRef()) )
07099       gotoAnchor(m_url.htmlRef());
07100     return;
07101   }
07102 
07103   // Check whether the viewport has become large enough to encompass the stored
07104   // offsets. If the document has been fully loaded, force the new coordinates,
07105   // even if the canvas is too short (can happen when user resizes the window
07106   // during loading).
07107   if (d->m_view->contentsHeight() - d->m_view->visibleHeight() >= args.yOffset
07108       || d->m_bComplete) {
07109     d->m_view->setContentsPos(args.xOffset, args.yOffset);
07110     disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
07111   }
07112 }
07113 
07114 
07115 void KHTMLPart::openWallet(DOM::HTMLFormElementImpl *form)
07116 {
07117 #ifndef KHTML_NO_WALLET
07118   KHTMLPart *p;
07119 
07120   for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
07121   }
07122 
07123   if (p) {
07124     p->openWallet(form);
07125     return;
07126   }
07127 
07128   if (onlyLocalReferences()) { // avoid triggering on local apps, thumbnails
07129     return;
07130   }
07131 
07132   if (d->m_wallet) {
07133     if (d->m_bWalletOpened) {
07134       if (d->m_wallet->isOpen()) {
07135         form->walletOpened(d->m_wallet);
07136         return;
07137       }
07138       d->m_wallet->deleteLater();
07139       d->m_wallet = 0L;
07140       d->m_bWalletOpened = false;
07141     }
07142   }
07143 
07144   if (!d->m_wq) {
07145     KWallet::Wallet *wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0, KWallet::Wallet::Asynchronous);
07146     d->m_wq = new KHTMLWalletQueue(this);
07147     d->m_wq->wallet = wallet;
07148     connect(wallet, SIGNAL(walletOpened(bool)), d->m_wq, SLOT(walletOpened(bool)));
07149     connect(d->m_wq, SIGNAL(walletOpened(KWallet::Wallet*)), this, SLOT(walletOpened(KWallet::Wallet*)));
07150   }
07151   assert(form);
07152   d->m_wq->callers.append(KHTMLWalletQueue::Caller(form, form->getDocument()));
07153 #endif // KHTML_NO_WALLET
07154 }
07155 
07156 
07157 void KHTMLPart::saveToWallet(const QString& key, const QMap<QString,QString>& data)
07158 {
07159 #ifndef KHTML_NO_WALLET
07160   KHTMLPart *p;
07161 
07162   for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
07163   }
07164 
07165   if (p) {
07166     p->saveToWallet(key, data);
07167     return;
07168   }
07169 
07170   if (d->m_wallet) {
07171     if (d->m_bWalletOpened) {
07172       if (d->m_wallet->isOpen()) {
07173         if (!d->m_wallet->hasFolder(KWallet::Wallet::FormDataFolder())) {
07174           d->m_wallet->createFolder(KWallet::Wallet::FormDataFolder());
07175         }
07176         d->m_wallet->setFolder(KWallet::Wallet::FormDataFolder());
07177         d->m_wallet->writeMap(key, data);
07178         return;
07179       }
07180       d->m_wallet->deleteLater();
07181       d->m_wallet = 0L;
07182       d->m_bWalletOpened = false;
07183     }
07184   }
07185 
07186   if (!d->m_wq) {
07187     KWallet::Wallet *wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0, KWallet::Wallet::Asynchronous);
07188     d->m_wq = new KHTMLWalletQueue(this);
07189     d->m_wq->wallet = wallet;
07190     connect(wallet, SIGNAL(walletOpened(bool)), d->m_wq, SLOT(walletOpened(bool)));
07191     connect(d->m_wq, SIGNAL(walletOpened(KWallet::Wallet*)), this, SLOT(walletOpened(KWallet::Wallet*)));
07192   }
07193   d->m_wq->savers.append(qMakePair(key, data));
07194 #endif // KHTML_NO_WALLET
07195 }
07196 
07197 
07198 void KHTMLPart::dequeueWallet(DOM::HTMLFormElementImpl *form) {
07199 #ifndef KHTML_NO_WALLET
07200   KHTMLPart *p;
07201 
07202   for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
07203   }
07204 
07205   if (p) {
07206     p->dequeueWallet(form);
07207     return;
07208   }
07209 
07210   if (d->m_wq) {
07211     d->m_wq->callers.remove(KHTMLWalletQueue::Caller(form, form->getDocument()));
07212   }
07213 #endif // KHTML_NO_WALLET
07214 }
07215 
07216 
07217 void KHTMLPart::walletOpened(KWallet::Wallet *wallet) {
07218 #ifndef KHTML_NO_WALLET
07219   assert(!d->m_wallet);
07220   assert(d->m_wq);
07221 
07222   d->m_wq->deleteLater(); // safe?
07223   d->m_wq = 0L;
07224 
07225   if (!wallet) {
07226     d->m_bWalletOpened = false;
07227     return;
07228   }
07229 
07230   d->m_wallet = wallet;
07231   d->m_bWalletOpened = true;
07232   connect(d->m_wallet, SIGNAL(walletClosed()), SLOT(slotWalletClosed()));
07233 
07234   if (!d->m_statusBarWalletLabel) {
07235     d->m_statusBarWalletLabel = new KURLLabel(d->m_statusBarExtension->statusBar());
07236     d->m_statusBarWalletLabel->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small));
07237     d->m_statusBarWalletLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
07238     d->m_statusBarWalletLabel->setUseCursor(false);
07239     d->m_statusBarExtension->addStatusBarItem(d->m_statusBarWalletLabel, 0, false);
07240     d->m_statusBarWalletLabel->setPixmap(SmallIcon("wallet_open", instance()));
07241     connect(d->m_statusBarWalletLabel, SIGNAL(leftClickedURL()), SLOT(launchWalletManager()));
07242     connect(d->m_statusBarWalletLabel, SIGNAL(rightClickedURL()), SLOT(walletMenu()));
07243   } else {
07244     QToolTip::remove(d->m_statusBarWalletLabel);
07245   }
07246   QToolTip::add(d->m_statusBarWalletLabel, i18n("The wallet '%1' is open and being used for form data and passwords.").arg(KWallet::Wallet::NetworkWallet()));
07247 #endif // KHTML_NO_WALLET
07248 }
07249 
07250 
07251 KWallet::Wallet *KHTMLPart::wallet()
07252 {
07253 #ifndef KHTML_NO_WALLET
07254   KHTMLPart *p;
07255 
07256   for (p = parentPart(); p && p->parentPart(); p = p->parentPart())
07257     ;
07258 
07259   if (p)
07260     return p->wallet();
07261 
07262 #endif // KHTML_NO_WALLET
07263   return d->m_wallet;
07264 }
07265 
07266 
07267 void KHTMLPart::slotWalletClosed()
07268 {
07269 #ifndef KHTML_NO_WALLET
07270   if (d->m_wallet) {
07271     d->m_wallet->deleteLater();
07272     d->m_wallet = 0L;
07273   }
07274   d->m_bWalletOpened = false;
07275   if (d->m_statusBarWalletLabel) {
07276     d->m_statusBarExtension->removeStatusBarItem(d->m_statusBarWalletLabel);
07277     delete d->m_statusBarWalletLabel;
07278     d->m_statusBarWalletLabel = 0L;
07279   }
07280 #endif // KHTML_NO_WALLET
07281 }
07282 
07283 void KHTMLPart::launchWalletManager()
07284 {
07285 #ifndef KHTML_NO_WALLET
07286   if (!DCOPClient::mainClient()->isApplicationRegistered("kwalletmanager")) {
07287     KApplication::startServiceByDesktopName("kwalletmanager_show");
07288   } else {
07289     DCOPRef r("kwalletmanager", "kwalletmanager-mainwindow#1");
07290     r.send("show");
07291     r.send("raise");
07292   }
07293 #endif // KHTML_NO_WALLET
07294 }
07295 
07296 void KHTMLPart::walletMenu()
07297 {
07298 #ifndef KHTML_NO_WALLET
07299   KPopupMenu *m = new KPopupMenu(0L);
07300   m->insertItem(i18n("&Close Wallet"), this, SLOT(slotWalletClosed()));
07301   m->popup(QCursor::pos());
07302 #endif // KHTML_NO_WALLET
07303 }
07304 
07305 void KHTMLPart::slotToggleCaretMode()
07306 {
07307   setCaretMode(d->m_paToggleCaretMode->isChecked());
07308 }
07309 
07310 void KHTMLPart::setFormNotification(KHTMLPart::FormNotification fn) {
07311   d->m_formNotification = fn;
07312 }
07313 
07314 KHTMLPart::FormNotification KHTMLPart::formNotification() const {
07315   return d->m_formNotification;
07316 }
07317 
07318 KURL KHTMLPart::toplevelURL()
07319 {
07320   KHTMLPart* part = this;
07321   while (part->parentPart())
07322     part = part->parentPart();
07323 
07324   if (!part)
07325     return KURL();
07326 
07327   return part->url();
07328 }
07329 
07330 bool KHTMLPart::isModified() const
07331 {
07332   if ( !d->m_doc )
07333     return false;
07334 
07335   return d->m_doc->unsubmittedFormChanges();
07336 }
07337 
07338 void KHTMLPart::setDebugScript( bool enable )
07339 {
07340   unplugActionList( "debugScriptList" );
07341   if ( enable ) {
07342     if (!d->m_paDebugScript) {
07343       d->m_paDebugScript = new KAction( i18n( "JavaScript &Debugger" ), 0, this, SLOT( slotDebugScript() ), actionCollection(), "debugScript" );
07344     }
07345     d->m_paDebugScript->setEnabled( d->m_frame ? d->m_frame->m_jscript : 0L );
07346     QPtrList<KAction> lst;
07347     lst.append( d->m_paDebugScript );
07348     plugActionList( "debugScriptList", lst );
07349   }
07350   d->m_bJScriptDebugEnabled = enable;
07351 }
07352 
07353 void KHTMLPart::setSuppressedPopupIndicator( bool enable )
07354 {
07355     setSuppressedPopupIndicator( enable, 0 );
07356 }
07357 
07358 void KHTMLPart::setSuppressedPopupIndicator( bool enable, KHTMLPart *originPart )
07359 {
07360     if ( parentPart() ) {
07361         parentPart()->setSuppressedPopupIndicator( enable, originPart );
07362         return;
07363     }
07364 
07365     if ( enable && originPart ) {
07366         d->m_openableSuppressedPopups++;
07367         if ( d->m_suppressedPopupOriginParts.findIndex( originPart ) == -1 )
07368             d->m_suppressedPopupOriginParts.append( originPart );
07369     }
07370 
07371     if ( enable && !d->m_statusBarPopupLabel ) {
07372         d->m_statusBarPopupLabel = new KURLLabel( d->m_statusBarExtension->statusBar() );
07373         d->m_statusBarPopupLabel->setFixedHeight( instance()->iconLoader()->currentSize( KIcon::Small) );
07374         d->m_statusBarPopupLabel->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ));
07375         d->m_statusBarPopupLabel->setUseCursor( false );
07376         d->m_statusBarExtension->addStatusBarItem( d->m_statusBarPopupLabel, 0, false );
07377         d->m_statusBarPopupLabel->setPixmap( SmallIcon( "window_suppressed", instance() ) );
07378         QToolTip::add( d->m_statusBarPopupLabel, i18n("This page was prevented from opening a new window via JavaScript." ) );
07379 
07380         connect(d->m_statusBarPopupLabel, SIGNAL(leftClickedURL()), SLOT(suppressedPopupMenu()));
07381         if (d->m_settings->jsPopupBlockerPassivePopup()) {
07382             QPixmap px;
07383             px = MainBarIcon( "window_suppressed" );
07384             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);
07385         }
07386     } else if ( !enable && d->m_statusBarPopupLabel ) {
07387         QToolTip::remove( d->m_statusBarPopupLabel );
07388         d->m_statusBarExtension->removeStatusBarItem( d->m_statusBarPopupLabel );
07389         delete d->m_statusBarPopupLabel;
07390         d->m_statusBarPopupLabel = 0L;
07391     }
07392 }
07393 
07394 void KHTMLPart::suppressedPopupMenu() {
07395   KPopupMenu *m = new KPopupMenu(0L);
07396   m->setCheckable(true);
07397   if ( d->m_openableSuppressedPopups )
07398       m->insertItem(i18n("&Show Blocked Popup Window","Show %n Blocked Popup Windows", d->m_openableSuppressedPopups), this, SLOT(showSuppressedPopups()));
07399   m->insertItem(i18n("Show Blocked Window Passive Popup &Notification"), this, SLOT(togglePopupPassivePopup()),0,57);
07400   m->setItemChecked(57,d->m_settings->jsPopupBlockerPassivePopup());
07401   m->insertItem(i18n("&Configure JavaScript New Window Policies..."), this, SLOT(launchJSConfigDialog()));
07402   m->popup(QCursor::pos());
07403 }
07404 
07405 void KHTMLPart::togglePopupPassivePopup() {
07406   // Same hack as in disableJSErrorExtension()
07407   d->m_settings->setJSPopupBlockerPassivePopup( !d->m_settings->jsPopupBlockerPassivePopup() );
07408   DCOPClient::mainClient()->send("konqueror*", "KonquerorIface", "reparseConfiguration()", QByteArray());
07409 }
07410 
07411 void KHTMLPart::showSuppressedPopups() {
07412     for ( QValueListIterator<QGuardedPtr<KHTMLPart> > i = d->m_suppressedPopupOriginParts.begin();
07413           i != d->m_suppressedPopupOriginParts.end(); ++i ) {
07414       if (KHTMLPart* part = *i) {
07415         KJS::Window *w = KJS::Window::retrieveWindow( part );
07416         if (w) {
07417             w->showSuppressedWindows();
07418             w->forgetSuppressedWindows();
07419         }
07420       }
07421     }
07422     setSuppressedPopupIndicator( false );
07423     d->m_openableSuppressedPopups = 0;
07424     d->m_suppressedPopupOriginParts.clear();
07425 }
07426 
07427 // Extension to use for "view document source", "save as" etc.
07428 // Using the right extension can help the viewer get into the right mode (#40496)
07429 QString KHTMLPart::defaultExtension() const
07430 {
07431     if ( !d->m_doc )
07432         return ".html";
07433     if ( !d->m_doc->isHTMLDocument() )
07434         return ".xml";
07435     return d->m_doc->htmlMode() == DOM::DocumentImpl::XHtml ? ".xhtml" : ".html";
07436 }
07437 
07438 bool KHTMLPart::inProgress() const
07439 {
07440     if (d->m_runningScripts || (d->m_doc && d->m_doc->parsing()))
07441         return true;
07442 
07443     // Any frame that hasn't completed yet ?
07444     ConstFrameIt it = d->m_frames.begin();
07445     const ConstFrameIt end = d->m_frames.end();
07446     for (; it != end; ++it ) {
07447         if ((*it)->m_run || !(*it)->m_bCompleted)
07448         return true;
07449     }
07450 
07451     return d->m_submitForm || !d->m_redirectURL.isEmpty() || d->m_redirectionTimer.isActive() || d->m_job;
07452 }
07453 
07454 using namespace KParts;
07455 #include "khtml_part.moc"
07456 #include "khtmlpart_p.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys