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 != 0) {
01103     d->m_statusBarExtension->removeStatusBarItem( d->m_statusBarJSErrorLabel );
01104     delete d->m_statusBarJSErrorLabel;
01105     d->m_statusBarJSErrorLabel = 0;
01106   }
01107   delete d->m_jsedlg;
01108   d->m_jsedlg = 0;
01109 }
01110 
01111 void KHTMLPart::disableJSErrorExtension() {
01112   removeJSErrorExtension();
01113   // These two lines are really kind of hacky, and it sucks to do this inside
01114   // KHTML but I don't know of anything that's reasonably easy as an alternative
01115   // right now.  It makes me wonder if there should be a more clean way to
01116   // contact all running "KHTML" instance as opposed to Konqueror instances too.
01117   d->m_settings->setJSErrorsEnabled(false);
01118   DCOPClient::mainClient()->send("konqueror*", "KonquerorIface", "reparseConfiguration()", QByteArray());
01119 }
01120 
01121 void KHTMLPart::jsErrorDialogContextMenu() {
01122   KPopupMenu *m = new KPopupMenu(0L);
01123   m->insertItem(i18n("&Hide Errors"), this, SLOT(removeJSErrorExtension()));
01124   m->insertItem(i18n("&Disable Error Reporting"), this, SLOT(disableJSErrorExtension()));
01125   m->popup(QCursor::pos());
01126 }
01127 
01128 void KHTMLPart::launchJSErrorDialog() {
01129   KJSErrorDlg *dlg = jsErrorExtension();
01130   if (dlg) {
01131     dlg->show();
01132     dlg->raise();
01133   }
01134 }
01135 
01136 void KHTMLPart::launchJSConfigDialog() {
01137   QStringList args;
01138   args << "khtml_java_js";
01139   KApplication::kdeinitExec( "kcmshell", args );
01140 }
01141 
01142 QVariant KHTMLPart::executeScript(const QString& filename, int baseLine, const DOM::Node& n, const QString& script)
01143 {
01144 #ifdef KJS_VERBOSE
01145   // The script is now printed by KJS's Parser::parse
01146   kdDebug(6070) << "executeScript: caller='" << name() << "' filename=" << filename << " baseLine=" << baseLine /*<< " script=" << script*/ << endl;
01147 #endif
01148   KJSProxy *proxy = jScript();
01149 
01150   if (!proxy || proxy->paused())
01151     return QVariant();
01152 
01153   KJS::Completion comp;
01154 
01155   QVariant ret = proxy->evaluate(filename, baseLine, script, n, &comp);
01156 
01157   /*
01158    *  Error handling
01159    */
01160   if (comp.complType() == KJS::Throw && !comp.value().isNull()) {
01161     KJSErrorDlg *dlg = jsErrorExtension();
01162     if (dlg) {
01163       KJS::UString msg = comp.value().toString(proxy->interpreter()->globalExec());
01164       dlg->addError(i18n("<b>Error</b>: %1: %2").arg(filename, msg.qstring()));
01165     }
01166   }
01167 
01168   // Handle immediate redirects now (e.g. location='foo')
01169   if ( !d->m_redirectURL.isEmpty() && d->m_delayRedirect == -1 )
01170   {
01171     kdDebug(6070) << "executeScript done, handling immediate redirection NOW" << endl;
01172     // Must abort tokenizer, no further script must execute.
01173     khtml::Tokenizer* t = d->m_doc->tokenizer();
01174     if(t)
01175       t->abort();
01176     d->m_redirectionTimer.start( 0, true );
01177   }
01178 
01179   return ret;
01180 }
01181 
01182 QVariant KHTMLPart::executeScript( const QString &script )
01183 {
01184     return executeScript( DOM::Node(), script );
01185 }
01186 
01187 QVariant KHTMLPart::executeScript( const DOM::Node &n, const QString &script )
01188 {
01189 #ifdef KJS_VERBOSE
01190   kdDebug(6070) << "KHTMLPart::executeScript caller='" << name() << "' node=" << n.nodeName().string().latin1() << "(" << (n.isNull() ? 0 : n.nodeType()) << ") " /* << script */ << endl;
01191 #endif
01192   KJSProxy *proxy = jScript();
01193 
01194   if (!proxy || proxy->paused())
01195     return QVariant();
01196   ++(d->m_runningScripts);
01197   KJS::Completion comp;
01198   const QVariant ret = proxy->evaluate( QString::null, 1, script, n, &comp );
01199   --(d->m_runningScripts);
01200 
01201   /*
01202    *  Error handling
01203    */
01204   if (comp.complType() == KJS::Throw && !comp.value().isNull()) {
01205     KJSErrorDlg *dlg = jsErrorExtension();
01206     if (dlg) {
01207       KJS::UString msg = comp.value().toString(proxy->interpreter()->globalExec());
01208       dlg->addError(i18n("<b>Error</b>: node %1: %2").arg(n.nodeName().string()).arg(msg.qstring()));
01209     }
01210   }
01211 
01212   if (!d->m_runningScripts && d->m_doc && !d->m_doc->parsing() && d->m_submitForm )
01213       submitFormAgain();
01214 
01215 #ifdef KJS_VERBOSE
01216   kdDebug(6070) << "KHTMLPart::executeScript - done" << endl;
01217 #endif
01218   return ret;
01219 }
01220 
01221 bool KHTMLPart::scheduleScript(const DOM::Node &n, const QString& script)
01222 {
01223     //kdDebug(6050) << "KHTMLPart::scheduleScript "<< script << endl;
01224 
01225     d->scheduledScript = script;
01226     d->scheduledScriptNode = n;
01227 
01228     return true;
01229 }
01230 
01231 QVariant KHTMLPart::executeScheduledScript()
01232 {
01233   if( d->scheduledScript.isEmpty() )
01234     return QVariant();
01235 
01236   //kdDebug(6050) << "executing delayed " << d->scheduledScript << endl;
01237 
01238   QVariant ret = executeScript( d->scheduledScriptNode, d->scheduledScript );
01239   d->scheduledScript = QString();
01240   d->scheduledScriptNode = DOM::Node();
01241 
01242   return ret;
01243 }
01244 
01245 void KHTMLPart::setJavaEnabled( bool enable )
01246 {
01247   d->m_bJavaForce = enable;
01248   d->m_bJavaOverride = true;
01249 }
01250 
01251 bool KHTMLPart::javaEnabled() const
01252 {
01253   if (onlyLocalReferences()) return false;
01254 
01255 #ifndef Q_WS_QWS
01256   if( d->m_bJavaOverride )
01257       return d->m_bJavaForce;
01258   return d->m_bJavaEnabled;
01259 #else
01260   return false;
01261 #endif
01262 }
01263 
01264 KJavaAppletContext *KHTMLPart::javaContext()
01265 {
01266   return 0;
01267 }
01268 
01269 KJavaAppletContext *KHTMLPart::createJavaContext()
01270 {
01271   return 0;
01272 }
01273 
01274 void KHTMLPart::setPluginsEnabled( bool enable )
01275 {
01276   d->m_bPluginsForce = enable;
01277   d->m_bPluginsOverride = true;
01278 }
01279 
01280 bool KHTMLPart::pluginsEnabled() const
01281 {
01282   if (onlyLocalReferences()) return false;
01283 
01284   if ( d->m_bPluginsOverride )
01285       return d->m_bPluginsForce;
01286   return d->m_bPluginsEnabled;
01287 }
01288 
01289 static int s_DOMTreeIndentLevel = 0;
01290 
01291 void KHTMLPart::slotDebugDOMTree()
01292 {
01293   if ( d->m_doc && d->m_doc->firstChild() )
01294     qDebug("%s", d->m_doc->firstChild()->toString().string().latin1());
01295 
01296   // Now print the contents of the frames that contain HTML
01297 
01298   const int indentLevel = s_DOMTreeIndentLevel++;
01299 
01300   ConstFrameIt it = d->m_frames.begin();
01301   const ConstFrameIt end = d->m_frames.end();
01302   for (; it != end; ++it )
01303     if ( !( *it )->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
01304       KParts::ReadOnlyPart* const p = ( *it )->m_part;
01305       kdDebug(6050) << QString().leftJustify(s_DOMTreeIndentLevel*4,' ') << "FRAME " << p->name() << " " << endl;
01306       static_cast<KHTMLPart*>( p )->slotDebugDOMTree();
01307     }
01308   s_DOMTreeIndentLevel = indentLevel;
01309 }
01310 
01311 void KHTMLPart::slotDebugScript()
01312 {
01313   if (jScript())
01314     jScript()->showDebugWindow();
01315 }
01316 
01317 void KHTMLPart::slotDebugRenderTree()
01318 {
01319 #ifndef NDEBUG
01320   if ( d->m_doc ) {
01321     d->m_doc->renderer()->printTree();
01322     // dump out the contents of the rendering & DOM trees
01323 //    QString dumps;
01324 //    QTextStream outputStream(dumps,IO_WriteOnly);
01325 //    d->m_doc->renderer()->layer()->dump( outputStream );
01326 //    kdDebug() << "dump output:" << "\n" + dumps;
01327   }
01328 #endif
01329 }
01330 
01331 void KHTMLPart::slotStopAnimations()
01332 {
01333   stopAnimations();
01334 }
01335 
01336 void KHTMLPart::setAutoloadImages( bool enable )
01337 {
01338   if ( d->m_doc && d->m_doc->docLoader()->autoloadImages() == enable )
01339     return;
01340 
01341   if ( d->m_doc )
01342     d->m_doc->docLoader()->setAutoloadImages( enable );
01343 
01344   unplugActionList( "loadImages" );
01345 
01346   if ( enable ) {
01347     delete d->m_paLoadImages;
01348     d->m_paLoadImages = 0;
01349   }
01350   else if ( !d->m_paLoadImages )
01351     d->m_paLoadImages = new KAction( i18n( "Display Images on Page" ), "images_display", 0, this, SLOT( slotLoadImages() ), actionCollection(), "loadImages" );
01352 
01353   if ( d->m_paLoadImages ) {
01354     QPtrList<KAction> lst;
01355     lst.append( d->m_paLoadImages );
01356     plugActionList( "loadImages", lst );
01357   }
01358 }
01359 
01360 bool KHTMLPart::autoloadImages() const
01361 {
01362   if ( d->m_doc )
01363     return d->m_doc->docLoader()->autoloadImages();
01364 
01365   return true;
01366 }
01367 
01368 void KHTMLPart::clear()
01369 {
01370   if ( d->m_bCleared )
01371     return;
01372 
01373   d->m_bCleared = true;
01374 
01375   d->m_bClearing = true;
01376 
01377   {
01378     ConstFrameIt it = d->m_frames.begin();
01379     const ConstFrameIt end = d->m_frames.end();
01380     for(; it != end; ++it )
01381     {
01382       // Stop HTMLRun jobs for frames
01383       if ( (*it)->m_run )
01384         (*it)->m_run->abort();
01385     }
01386   }
01387 
01388   {
01389     ConstFrameIt it = d->m_objects.begin();
01390     const ConstFrameIt end = d->m_objects.end();
01391     for(; it != end; ++it )
01392     {
01393       // Stop HTMLRun jobs for objects
01394       if ( (*it)->m_run )
01395         (*it)->m_run->abort();
01396     }
01397   }
01398 
01399 
01400   findTextBegin(); // resets d->m_findNode and d->m_findPos
01401   d->m_mousePressNode = DOM::Node();
01402 
01403 
01404   if ( d->m_doc )
01405   {
01406     if (d->m_doc->attached()) //the view may have detached it already
01407     d->m_doc->detach();
01408   }
01409 
01410   // Moving past doc so that onUnload works.
01411   if ( d->m_frame && d->m_frame->m_jscript )
01412     d->m_frame->m_jscript->clear();
01413 
01414   // stopping marquees
01415   if (d->m_doc && d->m_doc->renderer() && d->m_doc->renderer()->layer())
01416       d->m_doc->renderer()->layer()->suspendMarquees();
01417 
01418   if ( d->m_view )
01419     d->m_view->clear();
01420 
01421   // do not dereference the document before the jscript and view are cleared, as some destructors
01422   // might still try to access the document.
01423   if ( d->m_doc ) {
01424     d->m_doc->deref();
01425   }
01426   d->m_doc = 0;
01427 
01428   delete d->m_decoder;
01429   d->m_decoder = 0;
01430 
01431   // We don't want to change between parts if we are going to delete all of them anyway
01432   disconnect( partManager(), SIGNAL( activePartChanged( KParts::Part * ) ),
01433                this, SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
01434 
01435   if (d->m_frames.count())
01436   {
01437     KHTMLFrameList frames = d->m_frames;
01438     d->m_frames.clear();
01439     ConstFrameIt it = frames.begin();
01440     const ConstFrameIt end = frames.end();
01441     for(; it != end; ++it )
01442     {
01443       if ( (*it)->m_part )
01444       {
01445         partManager()->removePart( (*it)->m_part );
01446         delete (KParts::ReadOnlyPart *)(*it)->m_part;
01447       }
01448       delete *it;
01449     }
01450   }
01451   d->m_suppressedPopupOriginParts.clear();
01452 
01453   if (d->m_objects.count())
01454   {
01455     KHTMLFrameList objects = d->m_objects;
01456     d->m_objects.clear();
01457     ConstFrameIt oi = objects.begin();
01458     const ConstFrameIt oiEnd = objects.end();
01459 
01460     for (; oi != oiEnd; ++oi )
01461       delete *oi;
01462   }
01463 
01464   // Listen to part changes again
01465   connect( partManager(), SIGNAL( activePartChanged( KParts::Part * ) ),
01466              this, SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
01467 
01468   d->m_delayRedirect = 0;
01469   d->m_redirectURL = QString::null;
01470   d->m_redirectionTimer.stop();
01471   d->m_redirectLockHistory = true;
01472   d->m_bClearing = false;
01473   d->m_frameNameId = 1;
01474   d->m_bFirstData = true;
01475 
01476   d->m_bMousePressed = false;
01477 
01478   d->m_selectionStart = DOM::Node();
01479   d->m_selectionEnd = DOM::Node();
01480   d->m_startOffset = 0;
01481   d->m_endOffset = 0;
01482 #ifndef QT_NO_CLIPBOARD
01483   connect( kapp->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection()));
01484 #endif
01485 
01486   d->m_jobPercent = 0;
01487 
01488   if ( !d->m_haveEncoding )
01489     d->m_encoding = QString::null;
01490 #ifdef SPEED_DEBUG
01491   d->m_parsetime.restart();
01492 #endif
01493 }
01494 
01495 bool KHTMLPart::openFile()
01496 {
01497   return true;
01498 }
01499 
01500 DOM::HTMLDocumentImpl *KHTMLPart::docImpl() const
01501 {
01502     if ( d && d->m_doc && d->m_doc->isHTMLDocument() )
01503         return static_cast<HTMLDocumentImpl*>(d->m_doc);
01504     return 0;
01505 }
01506 
01507 DOM::DocumentImpl *KHTMLPart::xmlDocImpl() const
01508 {
01509     if ( d )
01510         return d->m_doc;
01511     return 0;
01512 }
01513 
01514 void KHTMLPart::slotInfoMessage(KIO::Job* kio_job, const QString& msg)
01515 {
01516   assert(d->m_job == kio_job);
01517 
01518   if (!parentPart())
01519     setStatusBarText(msg, BarDefaultText);
01520 }
01521 
01522 void KHTMLPart::setPageSecurity( PageSecurity sec )
01523 {
01524   emit d->m_extension->setPageSecurity( sec );
01525   if ( sec != NotCrypted && !d->m_statusBarIconLabel && !parentPart() ) {
01526     d->m_statusBarIconLabel = new KURLLabel( d->m_statusBarExtension->statusBar() );
01527     d->m_statusBarIconLabel->setFixedHeight( instance()->iconLoader()->currentSize(KIcon::Small) );
01528     d->m_statusBarIconLabel->setSizePolicy(QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ));
01529     d->m_statusBarIconLabel->setUseCursor( false );
01530     d->m_statusBarExtension->addStatusBarItem( d->m_statusBarIconLabel, 0, false );
01531     connect( d->m_statusBarIconLabel, SIGNAL( leftClickedURL() ), SLOT( slotSecurity() ) );
01532   } else if (d->m_statusBarIconLabel) {
01533     QToolTip::remove(d->m_statusBarIconLabel);
01534   }
01535 
01536   if (d->m_statusBarIconLabel) {
01537     if (d->m_ssl_in_use)
01538       QToolTip::add(d->m_statusBarIconLabel,
01539             i18n("Session is secured with %1 bit %2.").arg(d->m_ssl_cipher_used_bits).arg(d->m_ssl_cipher));
01540     else QToolTip::add(d->m_statusBarIconLabel, i18n("Session is not secured."));
01541   }
01542 
01543   QString iconName;
01544   switch (sec)  {
01545   case NotCrypted:
01546     iconName = "decrypted";
01547     if ( d->m_statusBarIconLabel )  {
01548       d->m_statusBarExtension->removeStatusBarItem( d->m_statusBarIconLabel );
01549       delete d->m_statusBarIconLabel;
01550       d->m_statusBarIconLabel = 0L;
01551     }
01552     break;
01553   case Encrypted:
01554     iconName = "encrypted";
01555     break;
01556   case Mixed:
01557     iconName = "halfencrypted";
01558     break;
01559   }
01560   d->m_paSecurity->setIcon( iconName );
01561   if ( d->m_statusBarIconLabel )
01562     d->m_statusBarIconLabel->setPixmap( SmallIcon( iconName, instance() ) );
01563 }
01564 
01565 void KHTMLPart::slotData( KIO::Job* kio_job, const QByteArray &data )
01566 {
01567   assert ( d->m_job == kio_job );
01568 
01569   //kdDebug( 6050 ) << "slotData: " << data.size() << endl;
01570   // The first data ?
01571   if ( !d->m_workingURL.isEmpty() )
01572   {
01573       //kdDebug( 6050 ) << "begin!" << endl;
01574 
01575     // We must suspend KIO while we're inside begin() because it can cause
01576     // crashes if a window (such as kjsdebugger) goes back into the event loop,
01577     // more data arrives, and begin() gets called again (re-entered).
01578     d->m_job->suspend();
01579     begin( d->m_workingURL, d->m_extension->urlArgs().xOffset, d->m_extension->urlArgs().yOffset );
01580     d->m_job->resume();
01581 
01582     if (d->m_cachePolicy == KIO::CC_Refresh)
01583       d->m_doc->docLoader()->setCachePolicy(KIO::CC_Verify);
01584     else
01585       d->m_doc->docLoader()->setCachePolicy(d->m_cachePolicy);
01586 
01587     d->m_workingURL = KURL();
01588 
01589     d->m_cacheId = KHTMLPageCache::self()->createCacheEntry();
01590 
01591     // When the first data arrives, the metadata has just been made available
01592     d->m_httpHeaders = d->m_job->queryMetaData("HTTP-Headers");
01593     time_t cacheCreationDate =  d->m_job->queryMetaData("cache-creation-date").toLong();
01594     d->m_doc->docLoader()->setCacheCreationDate(cacheCreationDate);
01595 
01596     d->m_pageServices = d->m_job->queryMetaData("PageServices");
01597     d->m_pageReferrer = d->m_job->queryMetaData("referrer");
01598     d->m_bSecurityInQuestion = false;
01599     d->m_ssl_in_use = (d->m_job->queryMetaData("ssl_in_use") == "TRUE");
01600 
01601     {
01602     KHTMLPart *p = parentPart();
01603     if (p && p->d->m_ssl_in_use != d->m_ssl_in_use) {
01604     while (p->parentPart()) p = p->parentPart();
01605 
01606         p->setPageSecurity( Mixed );
01607         p->d->m_bSecurityInQuestion = true;
01608     }
01609     }
01610 
01611     setPageSecurity( d->m_ssl_in_use ? Encrypted : NotCrypted );
01612 
01613     // Shouldn't all of this be done only if ssl_in_use == true ? (DF)
01614     d->m_ssl_parent_ip = d->m_job->queryMetaData("ssl_parent_ip");
01615     d->m_ssl_parent_cert = d->m_job->queryMetaData("ssl_parent_cert");
01616     d->m_ssl_peer_certificate = d->m_job->queryMetaData("ssl_peer_certificate");
01617     d->m_ssl_peer_chain = d->m_job->queryMetaData("ssl_peer_chain");
01618     d->m_ssl_peer_ip = d->m_job->queryMetaData("ssl_peer_ip");
01619     d->m_ssl_cipher = d->m_job->queryMetaData("ssl_cipher");
01620     d->m_ssl_cipher_desc = d->m_job->queryMetaData("ssl_cipher_desc");
01621     d->m_ssl_cipher_version = d->m_job->queryMetaData("ssl_cipher_version");
01622     d->m_ssl_cipher_used_bits = d->m_job->queryMetaData("ssl_cipher_used_bits");
01623     d->m_ssl_cipher_bits = d->m_job->queryMetaData("ssl_cipher_bits");
01624     d->m_ssl_cert_state = d->m_job->queryMetaData("ssl_cert_state");
01625 
01626     if (d->m_statusBarIconLabel) {
01627       QToolTip::remove(d->m_statusBarIconLabel);
01628       if (d->m_ssl_in_use) {
01629         QToolTip::add(d->m_statusBarIconLabel, i18n("Session is secured with %1 bit %2.").arg(d->m_ssl_cipher_used_bits).arg(d->m_ssl_cipher));
01630       } else {
01631         QToolTip::add(d->m_statusBarIconLabel, i18n("Session is not secured."));
01632       }
01633     }
01634 
01635     // Check for charset meta-data
01636     QString qData = d->m_job->queryMetaData("charset");
01637     if ( !qData.isEmpty() && !d->m_haveEncoding ) // only use information if the user didn't override the settings
01638        d->m_encoding = qData;
01639 
01640 
01641     // Support for http-refresh
01642     qData = d->m_job->queryMetaData("http-refresh");
01643     if( !qData.isEmpty())
01644       d->m_doc->processHttpEquiv("refresh", qData);
01645 
01646     // DISABLED: Support Content-Location per section 14.14 of RFC 2616.
01647     // See BR# 51185,BR# 82747
01648     /*
01649     QString baseURL = d->m_job->queryMetaData ("content-location");
01650     if (!baseURL.isEmpty())
01651       d->m_doc->setBaseURL(KURL( d->m_doc->completeURL(baseURL) ));
01652     */
01653 
01654     // Support for Content-Language
01655     QString language = d->m_job->queryMetaData("content-language");
01656     if (!language.isEmpty())
01657         d->m_doc->setContentLanguage(language);
01658 
01659     if ( !m_url.isLocalFile() ) {
01660         // Support for http last-modified
01661         d->m_lastModified = d->m_job->queryMetaData("modified");
01662     } else
01663         d->m_lastModified = QString::null; // done on-demand by lastModified()
01664   }
01665 
01666   KHTMLPageCache::self()->addData(d->m_cacheId, data);
01667   write( data.data(), data.size() );
01668   if (d->m_frame && d->m_frame->m_jscript)
01669     d->m_frame->m_jscript->dataReceived();
01670 }
01671 
01672 void KHTMLPart::slotRestoreData(const QByteArray &data )
01673 {
01674   // The first data ?
01675   if ( !d->m_workingURL.isEmpty() )
01676   {
01677      long saveCacheId = d->m_cacheId;
01678      QString savePageReferrer = d->m_pageReferrer;
01679      QString saveEncoding     = d->m_encoding;
01680      begin( d->m_workingURL, d->m_extension->urlArgs().xOffset, d->m_extension->urlArgs().yOffset );
01681      d->m_encoding     = saveEncoding;
01682      d->m_pageReferrer = savePageReferrer;
01683      d->m_cacheId = saveCacheId;
01684      d->m_workingURL = KURL();
01685   }
01686 
01687   //kdDebug( 6050 ) << "slotRestoreData: " << data.size() << endl;
01688   write( data.data(), data.size() );
01689 
01690   if (data.size() == 0)
01691   {
01692       //kdDebug( 6050 ) << "slotRestoreData: <<end of data>>" << endl;
01693      // End of data.
01694     if (d->m_doc && d->m_doc->parsing())
01695         end(); //will emit completed()
01696   }
01697 }
01698 
01699 void KHTMLPart::showError( KIO::Job* job )
01700 {
01701   kdDebug(6050) << "KHTMLPart::showError d->m_bParsing=" << (d->m_doc && d->m_doc->parsing()) << " d->m_bComplete=" << d->m_bComplete
01702                 << " d->m_bCleared=" << d->m_bCleared << endl;
01703 
01704   if (job->error() == KIO::ERR_NO_CONTENT)
01705     return;
01706 
01707   if ( (d->m_doc && d->m_doc->parsing()) || d->m_workingURL.isEmpty() ) // if we got any data already
01708     job->showErrorDialog( /*d->m_view*/ );
01709   else
01710   {
01711     htmlError( job->error(), job->errorText(), d->m_workingURL );
01712   }
01713 }
01714 
01715 // This is a protected method, placed here because of it's relevance to showError
01716 void KHTMLPart::htmlError( int errorCode, const QString& text, const KURL& reqUrl )
01717 {
01718   kdDebug(6050) << "KHTMLPart::htmlError errorCode=" << errorCode << " text=" << text << endl;
01719   // make sure we're not executing any embedded JS
01720   bool bJSFO = d->m_bJScriptForce;
01721   bool bJSOO = d->m_bJScriptOverride;
01722   d->m_bJScriptForce = false;
01723   d->m_bJScriptOverride = true;
01724   begin();
01725   QString errText = QString::fromLatin1( "<HTML dir=%1><HEAD><TITLE>" )
01726                            .arg(QApplication::reverseLayout() ? "rtl" : "ltr");
01727   errText += i18n( "Error while loading %1" ).arg( reqUrl.htmlURL() );
01728   errText += QString::fromLatin1( "</TITLE></HEAD><BODY><P>" );
01729   errText += i18n( "An error occurred while loading <B>%1</B>:" ).arg( reqUrl.htmlURL() );
01730   errText += QString::fromLatin1( "</P>" );
01731   errText += QStyleSheet::convertFromPlainText( KIO::buildErrorString( errorCode, text ) );
01732   errText += QString::fromLatin1( "</BODY></HTML>" );
01733   write(errText);
01734   end();
01735 
01736   d->m_bJScriptForce = bJSFO;
01737   d->m_bJScriptOverride = bJSOO;
01738 
01739   // make the working url the current url, so that reload works and
01740   // emit the progress signals to advance one step in the history
01741   // (so that 'back' works)
01742   m_url = reqUrl; // same as d->m_workingURL
01743   d->m_workingURL = KURL();
01744   emit started( 0 );
01745   emit completed();
01746   return;
01747   // following disabled until 3.1
01748 
01749   QString errorName, techName, description;
01750   QStringList causes, solutions;
01751 
01752   QByteArray raw = KIO::rawErrorDetail( errorCode, text, &reqUrl );
01753   QDataStream stream(raw, IO_ReadOnly);
01754 
01755   stream >> errorName >> techName >> description >> causes >> solutions;
01756 
01757   QString url, protocol, datetime;
01758   url = reqUrl.prettyURL();
01759   protocol = reqUrl.protocol();
01760   datetime = KGlobal::locale()->formatDateTime( QDateTime::currentDateTime(),
01761                                                 false );
01762 
01763   QString doc = QString::fromLatin1( "<html><head><title>" );
01764   doc += i18n( "Error: " );
01765   doc += errorName;
01766   doc += QString::fromLatin1( " - %1</title></head><body><h1>" ).arg( url );
01767   doc += i18n( "The requested operation could not be completed" );
01768   doc += QString::fromLatin1( "</h1><h2>" );
01769   doc += errorName;
01770   doc += QString::fromLatin1( "</h2>" );
01771   if ( !techName.isNull() ) {
01772     doc += QString::fromLatin1( "<h2>" );
01773     doc += i18n( "Technical Reason: " );
01774     doc += techName;
01775     doc += QString::fromLatin1( "</h2>" );
01776   }
01777   doc += QString::fromLatin1( "<h3>" );
01778   doc += i18n( "Details of the Request:" );
01779   doc += QString::fromLatin1( "</h3><ul><li>" );
01780   doc += i18n( "URL: %1" ).arg( url );
01781   doc += QString::fromLatin1( "</li><li>" );
01782   if ( !protocol.isNull() ) {
01783     // uncomment for 3.1... i18n change
01784     // doc += i18n( "Protocol: %1" ).arg( protocol ).arg( protocol );
01785     doc += QString::fromLatin1( "</li><li>" );
01786   }
01787   doc += i18n( "Date and Time: %1" ).arg( datetime );
01788   doc += QString::fromLatin1( "</li><li>" );
01789   doc += i18n( "Additional Information: %1" ).arg( text );
01790   doc += QString::fromLatin1( "</li></ul><h3>" );
01791   doc += i18n( "Description:" );
01792   doc += QString::fromLatin1( "</h3><p>" );
01793   doc += description;
01794   doc += QString::fromLatin1( "</p>" );
01795   if ( causes.count() ) {
01796     doc += QString::fromLatin1( "<h3>" );
01797     doc += i18n( "Possible Causes:" );
01798     doc += QString::fromLatin1( "</h3><ul><li>" );
01799     doc += causes.join( "</li><li>" );
01800     doc += QString::fromLatin1( "</li></ul>" );
01801   }
01802   if ( solutions.count() ) {
01803     doc += QString::fromLatin1( "<h3>" );
01804     doc += i18n( "Possible Solutions:" );
01805     doc += QString::fromLatin1( "</h3><ul><li>" );
01806     doc += solutions.join( "</li><li>" );
01807     doc += QString::fromLatin1( "</li></ul>" );
01808   }
01809   doc += QString::fromLatin1( "</body></html>" );
01810 
01811   write( doc );
01812   end();
01813 }
01814 
01815 void KHTMLPart::slotFinished( KIO::Job * job )
01816 {
01817   d->m_job = 0L;
01818   d->m_jobspeed = 0L;
01819 
01820   if (job->error())
01821   {
01822     KHTMLPageCache::self()->cancelEntry(d->m_cacheId);
01823 
01824     // The following catches errors that occur as a result of HTTP
01825     // to FTP redirections where the FTP URL is a directory. Since
01826     // KIO cannot change a redirection request from GET to LISTDIR,
01827     // we have to take care of it here once we know for sure it is
01828     // a directory...
01829     if (job->error() == KIO::ERR_IS_DIRECTORY)
01830     {
01831       KParts::URLArgs args;
01832       emit d->m_extension->openURLRequest( d->m_workingURL, args );
01833     }
01834     else
01835     {
01836       emit canceled( job->errorString() );
01837       // TODO: what else ?
01838       checkCompleted();
01839       showError( job );
01840     }
01841 
01842     return;
01843   }
01844   KIO::TransferJob *tjob = ::qt_cast<KIO::TransferJob*>(job);
01845   if (tjob && tjob->isErrorPage()) {
01846     khtml::RenderPart *renderPart = d->m_frame->m_frame;
01847     if (renderPart) {
01848       HTMLObjectElementImpl* elt = static_cast<HTMLObjectElementImpl *>(renderPart->element());
01849       if (!elt)
01850         return;
01851       elt->renderAlternative();
01852       checkCompleted();
01853      }
01854      if (d->m_bComplete) return;
01855   }
01856 
01857   //kdDebug( 6050 ) << "slotFinished" << endl;
01858 
01859   KHTMLPageCache::self()->endData(d->m_cacheId);
01860   if (d->m_frame && d->m_frame->m_jscript)
01861     d->m_frame->m_jscript->dataReceived();
01862 
01863   if ( d->m_doc && d->m_doc->docLoader()->expireDate() && m_url.protocol().lower().startsWith("http"))
01864       KIO::http_update_cache(m_url, false, d->m_doc->docLoader()->expireDate());
01865 
01866   d->m_workingURL = KURL();
01867 
01868   if ( d->m_doc && d->m_doc->parsing())
01869     end(); //will emit completed()
01870 }
01871 
01872 void KHTMLPart::begin( const KURL &url, int xOffset, int yOffset )
01873 {
01874   // No need to show this for a new page until an error is triggered
01875   if (!parentPart()) {
01876     removeJSErrorExtension();
01877     setSuppressedPopupIndicator( false );
01878     d->m_openableSuppressedPopups = 0;
01879     for ( 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     if ( processObjectRequest(*it, KURL("about:blank"), QString("text/html") ) ) {
04318       KHTMLPart* p = static_cast<KHTMLPart*>(static_cast<KParts::ReadOnlyPart *>((*it)->m_part));
04319       
04320       // See if we want to replace content with javascript: output..
04321       QVariant res = p->executeScript( DOM::Node(), KURL::decode_string( url.right( url.length() - 11) ) );
04322       if ( res.type() == QVariant::String ) {
04323         p->begin();
04324         p->write( res.asString() );
04325         p->end();
04326       }
04327       return true;
04328     }
04329     return false;
04330   }
04331   KURL u = url.isEmpty() ? KURL() : completeURL( url );
04332   return requestObject( *it, u );
04333 }
04334 
04335 QString KHTMLPart::requestFrameName()
04336 {
04337    return QString::fromLatin1("<!--frame %1-->").arg(d->m_frameNameId++);
04338 }
04339 
04340 bool KHTMLPart::requestObject( khtml::RenderPart *frame, const QString &url, const QString &serviceType,
04341                                const QStringList &params )
04342 {
04343   //kdDebug( 6005 ) << "KHTMLPart::requestObject " << this << " frame=" << frame << endl;
04344   khtml::ChildFrame *child = new khtml::ChildFrame;
04345   FrameIt it = d->m_objects.append( child );
04346   (*it)->m_frame = frame;
04347   (*it)->m_type = khtml::ChildFrame::Object;
04348   (*it)->m_params = params;
04349 
04350   KParts::URLArgs args;
04351   args.serviceType = serviceType;
04352   if (!requestObject( *it, completeURL( url ), args ) && !(*it)->m_run) {
04353       (*it)->m_bCompleted = true;
04354       return false;
04355   }
04356   return true;
04357 }
04358 
04359 bool KHTMLPart::requestObject( khtml::ChildFrame *child, const KURL &url, const KParts::URLArgs &_args )
04360 {
04361   if (!checkLinkSecurity(url))
04362   {
04363     kdDebug(6005) << this << " KHTMLPart::requestObject checkLinkSecurity refused" << endl;
04364     return false;
04365   }
04366   if ( child->m_bPreloaded )
04367   {
04368     kdDebug(6005) << "KHTMLPart::requestObject preload" << endl;
04369     if ( child->m_frame && child->m_part )
04370       child->m_frame->setWidget( child->m_part->widget() );
04371 
04372     child->m_bPreloaded = false;
04373     return true;
04374   }
04375 
04376   //kdDebug(6005) << "KHTMLPart::requestObject child=" << child << " child->m_part=" << child->m_part << endl;
04377 
04378   KParts::URLArgs args( _args );
04379 
04380   if ( child->m_run )
04381     child->m_run->abort();
04382 
04383   if ( child->m_part && !args.reload && urlcmp( child->m_part->url().url(), url.url(), true, true ) )
04384     args.serviceType = child->m_serviceType;
04385 
04386   child->m_args = args;
04387   child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload);
04388   child->m_serviceName = QString::null;
04389   if (!d->m_referrer.isEmpty() && !child->m_args.metaData().contains( "referrer" ))
04390     child->m_args.metaData()["referrer"] = d->m_referrer;
04391 
04392   child->m_args.metaData().insert("PropagateHttpHeader", "true");
04393   child->m_args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
04394   child->m_args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
04395   child->m_args.metaData().insert("main_frame_request",
04396                                   parentPart() == 0 ? "TRUE":"FALSE");
04397   child->m_args.metaData().insert("ssl_was_in_use",
04398                                   d->m_ssl_in_use ? "TRUE":"FALSE");
04399   child->m_args.metaData().insert("ssl_activate_warnings", "TRUE");
04400   child->m_args.metaData().insert("cross-domain", toplevelURL().url());
04401 
04402   // We want a KHTMLPart if the HTML says <frame src=""> or <frame src="about:blank">
04403   if ((url.isEmpty() || url.url() == "about:blank") && args.serviceType.isEmpty())
04404     args.serviceType = QString::fromLatin1( "text/html" );
04405 
04406   if ( args.serviceType.isEmpty() ) {
04407     kdDebug(6050) << "Running new KHTMLRun for " << this << " and child=" << child << endl;
04408     child->m_run = new KHTMLRun( this, child, url, child->m_args, true );
04409     d->m_bComplete = false; // ensures we stop it in checkCompleted...
04410     return false;
04411   } else {
04412     return processObjectRequest( child, url, args.serviceType );
04413   }
04414 }
04415 
04416 bool KHTMLPart::processObjectRequest( khtml::ChildFrame *child, const KURL &_url, const QString &mimetype )
04417 {
04418   //kdDebug( 6050 ) << "KHTMLPart::processObjectRequest trying to create part for " << mimetype << endl;
04419 
04420   // IMPORTANT: create a copy of the url here, because it is just a reference, which was likely to be given
04421   // by an emitting frame part (emit openURLRequest( blahurl, ... ) . A few lines below we delete the part
04422   // though -> the reference becomes invalid -> crash is likely
04423   KURL url( _url );
04424 
04425   // khtmlrun called us this way to indicate a loading error
04426   if ( d->m_onlyLocalReferences || ( url.isEmpty() && mimetype.isEmpty() ) )
04427   {
04428       child->m_bCompleted = true;
04429       checkCompleted();
04430       return true;
04431   }
04432 
04433   if (child->m_bNotify)
04434   {
04435       child->m_bNotify = false;
04436       if ( !child->m_args.lockHistory() )
04437           emit d->m_extension->openURLNotify();
04438   }
04439 
04440   if ( child->m_serviceType != mimetype || !child->m_part )
04441   {
04442     // Before attempting to load a part, check if the user wants that.
04443     // Many don't like getting ZIP files embedded.
04444     // However we don't want to ask for flash and other plugin things..
04445     if ( child->m_type != khtml::ChildFrame::Object )
04446     {
04447       QString suggestedFilename;
04448       if ( child->m_run )
04449         suggestedFilename = child->m_run->suggestedFilename();
04450 
04451       KParts::BrowserRun::AskSaveResult res = KParts::BrowserRun::askEmbedOrSave(
04452         url, mimetype, suggestedFilename  );
04453       switch( res ) {
04454       case KParts::BrowserRun::Save:
04455         KHTMLPopupGUIClient::saveURL( widget(), i18n( "Save As" ), url, child->m_args.metaData(), QString::null, 0, suggestedFilename);
04456         // fall-through
04457       case KParts::BrowserRun::Cancel:
04458         child->m_bCompleted = true;
04459         checkCompleted();
04460         return true; // done
04461       default: // Open
04462         break;
04463       }
04464     }
04465 
04466     QStringList dummy; // the list of servicetypes handled by the part is now unused.
04467     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 );
04468 
04469     if ( !part )
04470     {
04471         if ( child->m_frame )
04472           if (child->m_frame->partLoadingErrorNotify( child, url, mimetype ))
04473             return true; // we succeeded after all (a fallback was used)
04474 
04475         checkEmitLoadEvent();
04476         return false;
04477     }
04478 
04479     //CRITICAL STUFF
04480     if ( child->m_part )
04481     {
04482       if (!::qt_cast<KHTMLPart*>(child->m_part) && child->m_jscript)
04483           child->m_jscript->clear();
04484       partManager()->removePart( (KParts::ReadOnlyPart *)child->m_part );
04485       delete (KParts::ReadOnlyPart *)child->m_part;
04486       if (child->m_liveconnect) {
04487         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 &)));
04488         child->m_liveconnect = 0L;
04489       }
04490     }
04491 
04492     child->m_serviceType = mimetype;
04493     if ( child->m_frame  && part->widget() )
04494       child->m_frame->setWidget( part->widget() );
04495 
04496     if ( child->m_type != khtml::ChildFrame::Object )
04497       partManager()->addPart( part, false );
04498 //  else
04499 //      kdDebug(6005) << "AH! NO FRAME!!!!!" << endl;
04500 
04501     child->m_part = part;
04502 
04503     if (::qt_cast<KHTMLPart*>(part)) {
04504       static_cast<KHTMLPart*>(part)->d->m_frame = child;
04505     } else if (child->m_frame) {
04506       child->m_liveconnect = KParts::LiveConnectExtension::childObject(part);
04507       if (child->m_liveconnect)
04508         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 &)));
04509     }
04510     KParts::StatusBarExtension *sb = KParts::StatusBarExtension::childObject(part);
04511     if (sb)
04512       sb->setStatusBar( d->m_statusBarExtension->statusBar() );
04513 
04514     connect( part, SIGNAL( started( KIO::Job *) ),
04515              this, SLOT( slotChildStarted( KIO::Job *) ) );
04516     connect( part, SIGNAL( completed() ),
04517              this, SLOT( slotChildCompleted() ) );
04518     connect( part, SIGNAL( completed(bool) ),
04519              this, SLOT( slotChildCompleted(bool) ) );
04520     connect( part, SIGNAL( setStatusBarText( const QString & ) ),
04521                 this, SIGNAL( setStatusBarText( const QString & ) ) );
04522     if ( part->inherits( "KHTMLPart" ) )
04523     {
04524       connect( this, SIGNAL( completed() ),
04525                part, SLOT( slotParentCompleted() ) );
04526       connect( this, SIGNAL( completed(bool) ),
04527                part, SLOT( slotParentCompleted() ) );
04528       // As soon as the child's document is created, we need to set its domain
04529       // (but we do so only once, so it can't be simply done in the child)
04530       connect( part, SIGNAL( docCreated() ),
04531                this, SLOT( slotChildDocCreated() ) );
04532     }
04533 
04534     child->m_extension = KParts::BrowserExtension::childObject( part );
04535 
04536     if ( child->m_extension )
04537     {
04538       connect( child->m_extension, SIGNAL( openURLNotify() ),
04539                d->m_extension, SIGNAL( openURLNotify() ) );
04540 
04541       connect( child->m_extension, SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ),
04542                this, SLOT( slotChildURLRequest( const KURL &, const KParts::URLArgs & ) ) );
04543 
04544       connect( child->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ),
04545                d->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ) );
04546       connect( child->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs &, const KParts::WindowArgs &, KParts::ReadOnlyPart *& ) ),
04547                d->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & , const KParts::WindowArgs &, KParts::ReadOnlyPart *&) ) );
04548 
04549       connect( child->m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ),
04550                d->m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ) );
04551       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ),
04552                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ) );
04553       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ),
04554                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ) );
04555       connect( child->m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ),
04556                d->m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ) );
04557       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ),
04558                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ) );
04559       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ),
04560                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ) );
04561 
04562       connect( child->m_extension, SIGNAL( infoMessage( const QString & ) ),
04563                d->m_extension, SIGNAL( infoMessage( const QString & ) ) );
04564 
04565       connect( child->m_extension, SIGNAL( requestFocus( KParts::ReadOnlyPart * ) ),
04566                this, SLOT( slotRequestFocus( KParts::ReadOnlyPart * ) ) );
04567 
04568       child->m_extension->setBrowserInterface( d->m_extension->browserInterface() );
04569     }
04570   }
04571   else if ( child->m_frame && child->m_part &&
04572             child->m_frame->widget() != child->m_part->widget() )
04573     child->m_frame->setWidget( child->m_part->widget() );
04574 
04575   checkEmitLoadEvent();
04576   // Some JS code in the load event may have destroyed the part
04577   // In that case, abort
04578   if ( !child->m_part )
04579     return false;
04580 
04581   if ( child->m_bPreloaded )
04582   {
04583     if ( child->m_frame && child->m_part )
04584       child->m_frame->setWidget( child->m_part->widget() );
04585 
04586     child->m_bPreloaded = false;
04587     return true;
04588   }
04589 
04590   child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload);
04591 
04592   // make sure the part has a way to find out about the mimetype.
04593   // we actually set it in child->m_args in requestObject already,
04594   // but it's useless if we had to use a KHTMLRun instance, as the
04595   // point the run object is to find out exactly the mimetype.
04596   child->m_args.serviceType = mimetype;
04597 
04598   // if not a frame set child as completed
04599   child->m_bCompleted = child->m_type == khtml::ChildFrame::Object;
04600 
04601   if ( child->m_extension )
04602     child->m_extension->setURLArgs( child->m_args );
04603 
04604   if(url.protocol() == "javascript" || url.url() == "about:blank") {
04605       if (!child->m_part->inherits("KHTMLPart"))
04606           return false;
04607 
04608       KHTMLPart* p = static_cast<KHTMLPart*>(static_cast<KParts::ReadOnlyPart *>(child->m_part));
04609 
04610       p->begin();
04611       if (d->m_doc && p->d->m_doc)
04612         p->d->m_doc->setBaseURL(d->m_doc->baseURL());
04613       if (!url.url().startsWith("about:")) {
04614         p->write(url.path());
04615       } else {
04616     p->m_url = url;
04617         // we need a body element. testcase: <iframe id="a"></iframe><script>alert(a.document.body);</script>
04618         p->write("<HTML><TITLE></TITLE><BODY></BODY></HTML>");
04619       }
04620       p->end();
04621       return true;
04622   }
04623   else if ( !url.isEmpty() )
04624   {
04625       //kdDebug( 6050 ) << "opening " << url.url() << " in frame " << child->m_part << endl;
04626       bool b = child->m_part->openURL( url );
04627       if (child->m_bCompleted)
04628           checkCompleted();
04629       return b;
04630   }
04631   else
04632   {
04633       child->m_bCompleted = true;
04634       checkCompleted();
04635       return true;
04636   }
04637 }
04638 
04639 KParts::ReadOnlyPart *KHTMLPart::createPart( QWidget *parentWidget, const char *widgetName,
04640                                              QObject *parent, const char *name, const QString &mimetype,
04641                                              QString &serviceName, QStringList &serviceTypes,
04642                                              const QStringList &params )
04643 {
04644   QString constr;
04645   if ( !serviceName.isEmpty() )
04646     constr.append( QString::fromLatin1( "Name == '%1'" ).arg( serviceName ) );
04647 
04648   KTrader::OfferList offers = KTrader::self()->query( mimetype, "KParts/ReadOnlyPart", constr, QString::null );
04649 
04650   if ( offers.isEmpty() ) {
04651     int pos = mimetype.find( "-plugin" );
04652     if (pos < 0)
04653         return 0L;
04654     QString stripped_mime = mimetype.left( pos );
04655     offers = KTrader::self()->query( stripped_mime, "KParts/ReadOnlyPart", constr, QString::null );
04656     if ( offers.isEmpty() )
04657         return 0L;
04658   }
04659 
04660   KTrader::OfferList::ConstIterator it = offers.begin();
04661   const KTrader::OfferList::ConstIterator itEnd = offers.end();
04662   for ( ; it != itEnd; ++it )
04663   {
04664     KService::Ptr service = (*it);
04665 
04666     KLibFactory* const factory = KLibLoader::self()->factory( QFile::encodeName(service->library()) );
04667     if ( factory ) {
04668       KParts::ReadOnlyPart *res = 0L;
04669 
04670       const char *className = "KParts::ReadOnlyPart";
04671       if ( service->serviceTypes().contains( "Browser/View" ) )
04672         className = "Browser/View";
04673 
04674       if ( factory->inherits( "KParts::Factory" ) )
04675         res = static_cast<KParts::ReadOnlyPart *>(static_cast<KParts::Factory *>( factory )->createPart( parentWidget, widgetName, parent, name, className, params ));
04676       else
04677         res = static_cast<KParts::ReadOnlyPart *>(factory->create( parentWidget, widgetName, className ));
04678 
04679       if ( res ) {
04680         serviceTypes = service->serviceTypes();
04681         serviceName = service->name();
04682         return res;
04683       }
04684     } else {
04685       // TODO KMessageBox::error and i18n, like in KonqFactory::createView?
04686       kdWarning() << QString("There was an error loading the module %1.\nThe diagnostics is:\n%2")
04687                       .arg(service->name()).arg(KLibLoader::self()->lastErrorMessage()) << endl;
04688     }
04689   }
04690   return 0;
04691 }
04692 
04693 KParts::PartManager *KHTMLPart::partManager()
04694 {
04695   if ( !d->m_manager && d->m_view )
04696   {
04697     d->m_manager = new KParts::PartManager( d->m_view->topLevelWidget(), this, "khtml part manager" );
04698     d->m_manager->setAllowNestedParts( true );
04699     connect( d->m_manager, SIGNAL( activePartChanged( KParts::Part * ) ),
04700              this, SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
04701     connect( d->m_manager, SIGNAL( partRemoved( KParts::Part * ) ),
04702              this, SLOT( slotPartRemoved( KParts::Part * ) ) );
04703   }
04704 
04705   return d->m_manager;
04706 }
04707 
04708 void KHTMLPart::submitFormAgain()
04709 {
04710   disconnect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
04711   if( d->m_doc && !d->m_doc->parsing() && d->m_submitForm)
04712     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 );
04713 
04714   delete d->m_submitForm;
04715   d->m_submitForm = 0;
04716 }
04717 
04718 void KHTMLPart::submitFormProxy( const char *action, const QString &url, const QByteArray &formData, const QString &_target, const QString& contentType, const QString& boundary )
04719 {
04720   submitForm(action, url, formData, _target, contentType, boundary);
04721 }
04722 
04723 void KHTMLPart::submitForm( const char *action, const QString &url, const QByteArray &formData, const QString &_target, const QString& contentType, const QString& boundary )
04724 {
04725   kdDebug(6000) << this << ": KHTMLPart::submitForm target=" << _target << " url=" << url << endl;
04726   if (d->m_formNotification == KHTMLPart::Only) {
04727     emit formSubmitNotification(action, url, formData, _target, contentType, boundary);
04728     return;
04729   } else if (d->m_formNotification == KHTMLPart::Before) {
04730     emit formSubmitNotification(action, url, formData, _target, contentType, boundary);
04731   }
04732 
04733   KURL u = completeURL( url );
04734 
04735   if ( !u.isValid() )
04736   {
04737     // ### ERROR HANDLING!
04738     return;
04739   }
04740 
04741   // Form security checks
04742   //
04743   /*
04744    * If these form security checks are still in this place in a month or two
04745    * I'm going to simply delete them.
04746    */
04747 
04748   /* This is separate for a reason.  It has to be _before_ all script, etc,
04749    * AND I don't want to break anything that uses checkLinkSecurity() in
04750    * other places.
04751    */
04752 
04753   if (!d->m_submitForm) {
04754     if (u.protocol() != "https" && u.protocol() != "mailto") {
04755       if (d->m_ssl_in_use) {    // Going from SSL -> nonSSL
04756         int rc = KMessageBox::warningContinueCancel(NULL, i18n("Warning:  This is a secure form but it is attempting to send your data back unencrypted."
04757                                                                "\nA third party may be able to intercept and view this information."
04758                                                                "\nAre you sure you wish to continue?"),
04759                                                     i18n("Network Transmission"),KGuiItem(i18n("&Send Unencrypted")));
04760         if (rc == KMessageBox::Cancel)
04761           return;
04762       } else {                  // Going from nonSSL -> nonSSL
04763         KSSLSettings kss(true);
04764         if (kss.warnOnUnencrypted()) {
04765           int rc = KMessageBox::warningContinueCancel(NULL,
04766                                                       i18n("Warning: Your data is about to be transmitted across the network unencrypted."
04767                                                            "\nAre you sure you wish to continue?"),
04768                                                       i18n("Network Transmission"),
04769                                                       KGuiItem(i18n("&Send Unencrypted")),
04770                                                       "WarnOnUnencryptedForm");
04771           // Move this setting into KSSL instead
04772           KConfig *config = kapp->config();
04773           QString grpNotifMsgs = QString::fromLatin1("Notification Messages");
04774           KConfigGroupSaver saver( config, grpNotifMsgs );
04775 
04776           if (!config->readBoolEntry("WarnOnUnencryptedForm", true)) {
04777             config->deleteEntry("WarnOnUnencryptedForm");
04778             config->sync();
04779             kss.setWarnOnUnencrypted(false);
04780             kss.save();
04781           }
04782           if (rc == KMessageBox::Cancel)
04783             return;
04784         }
04785       }
04786     }
04787 
04788     if (u.protocol() == "mailto") {
04789       int rc = KMessageBox::warningContinueCancel(NULL,
04790                                                   i18n("This site is attempting to submit form data via email.\n"
04791                                                        "Do you want to continue?"),
04792                                                   i18n("Network Transmission"),
04793                                                   KGuiItem(i18n("&Send Email")),
04794                                                   "WarnTriedEmailSubmit");
04795 
04796       if (rc == KMessageBox::Cancel) {
04797         return;
04798       }
04799     }
04800   }
04801 
04802   // End form security checks
04803   //
04804 
04805   QString urlstring = u.url();
04806 
04807   if ( urlstring.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
04808     urlstring = KURL::decode_string(urlstring);
04809     crossFrameExecuteScript( _target, urlstring.right( urlstring.length() - 11) );
04810     return;
04811   }
04812 
04813   if (!checkLinkSecurity(u,
04814              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?" ),
04815              i18n( "Submit" )))
04816     return;
04817 
04818   KParts::URLArgs args;
04819 
04820   if (!d->m_referrer.isEmpty())
04821      args.metaData()["referrer"] = d->m_referrer;
04822 
04823   args.metaData().insert("PropagateHttpHeader", "true");
04824   args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
04825   args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
04826   args.metaData().insert("main_frame_request",
04827                          parentPart() == 0 ? "TRUE":"FALSE");
04828   args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
04829   args.metaData().insert("ssl_activate_warnings", "TRUE");
04830 //WABA: When we post a form we should treat it as the main url
04831 //the request should never be considered cross-domain
04832 //args.metaData().insert("cross-domain", toplevelURL().url());
04833   args.frameName = _target.isEmpty() ? d->m_doc->baseTarget() : _target ;
04834 
04835   // Handle mailto: forms
04836   if (u.protocol() == "mailto") {
04837       // 1)  Check for attach= and strip it
04838       QString q = u.query().mid(1);
04839       QStringList nvps = QStringList::split("&", q);
04840       bool triedToAttach = false;
04841 
04842       QStringList::Iterator nvp = nvps.begin();
04843       const QStringList::Iterator nvpEnd = nvps.end();
04844 
04845 // cannot be a for loop as if something is removed we don't want to do ++nvp, as
04846 // remove returns an iterator pointing to the next item
04847 
04848       while (nvp != nvpEnd) {
04849          const QStringList pair = QStringList::split("=", *nvp);
04850          if (pair.count() >= 2) {
04851             if (pair.first().lower() == "attach") {
04852                nvp = nvps.remove(nvp);
04853                triedToAttach = true;
04854             } else {
04855                ++nvp;
04856             }
04857          } else {
04858             ++nvp;
04859          }
04860       }
04861 
04862       if (triedToAttach)
04863          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");
04864 
04865       // 2)  Append body=
04866       QString bodyEnc;
04867       if (contentType.lower() == "multipart/form-data") {
04868          // FIXME: is this correct?  I suspect not
04869          bodyEnc = KURL::encode_string(QString::fromLatin1(formData.data(),
04870                                                            formData.size()));
04871       } else if (contentType.lower() == "text/plain") {
04872          // Convention seems to be to decode, and s/&/\n/
04873          QString tmpbody = QString::fromLatin1(formData.data(),
04874                                                formData.size());
04875          tmpbody.replace(QRegExp("[&]"), "\n");
04876          tmpbody.replace(QRegExp("[+]"), " ");
04877          tmpbody = KURL::decode_string(tmpbody);  // Decode the rest of it
04878          bodyEnc = KURL::encode_string(tmpbody);  // Recode for the URL
04879       } else {
04880          bodyEnc = KURL::encode_string(QString::fromLatin1(formData.data(),
04881                                                            formData.size()));
04882       }
04883 
04884       nvps.append(QString("body=%1").arg(bodyEnc));
04885       q = nvps.join("&");
04886       u.setQuery(q);
04887   }
04888 
04889   if ( strcmp( action, "get" ) == 0 ) {
04890     if (u.protocol() != "mailto")
04891        u.setQuery( QString::fromLatin1( formData.data(), formData.size() ) );
04892     args.setDoPost( false );
04893   }
04894   else {
04895     args.postData = formData;
04896     args.setDoPost( true );
04897 
04898     // construct some user headers if necessary
04899     if (contentType.isNull() || contentType == "application/x-www-form-urlencoded")
04900       args.setContentType( "Content-Type: application/x-www-form-urlencoded" );
04901     else // contentType must be "multipart/form-data"
04902       args.setContentType( "Content-Type: " + contentType + "; boundary=" + boundary );
04903   }
04904 
04905   if ( d->m_doc->parsing() || d->m_runningScripts > 0 ) {
04906     if( d->m_submitForm ) {
04907       kdDebug(6000) << "KHTMLPart::submitForm ABORTING!" << endl;
04908       return;
04909     }
04910     d->m_submitForm = new KHTMLPartPrivate::SubmitForm;
04911     d->m_submitForm->submitAction = action;
04912     d->m_submitForm->submitUrl = url;
04913     d->m_submitForm->submitFormData = formData;
04914     d->m_submitForm->target = _target;
04915     d->m_submitForm->submitContentType = contentType;
04916     d->m_submitForm->submitBoundary = boundary;
04917     connect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
04918   }
04919   else
04920   {
04921     emit d->m_extension->openURLRequest( u, args );
04922   }
04923 }
04924 
04925 void KHTMLPart::popupMenu( const QString &linkUrl )
04926 {
04927   KURL popupURL;
04928   KURL linkKURL;
04929   KParts::URLArgs args;
04930   QString referrer;
04931   KParts::BrowserExtension::PopupFlags itemflags=KParts::BrowserExtension::ShowBookmark | KParts::BrowserExtension::ShowReload;
04932 
04933   if ( linkUrl.isEmpty() ) { // click on background
04934     KHTMLPart* khtmlPart = this;
04935     while ( khtmlPart->parentPart() )
04936     {
04937       khtmlPart=khtmlPart->parentPart();
04938     }
04939     popupURL = khtmlPart->url();
04940     referrer = khtmlPart->pageReferrer();
04941     if (hasSelection())
04942       itemflags = KParts::BrowserExtension::ShowTextSelectionItems;
04943     else
04944       itemflags |= KParts::BrowserExtension::ShowNavigationItems;
04945   } else {               // click on link
04946     popupURL = completeURL( linkUrl );
04947     linkKURL = popupURL;
04948     referrer = this->referrer();
04949 
04950     if (!(d->m_strSelectedURLTarget).isEmpty() &&
04951            (d->m_strSelectedURLTarget.lower() != "_top") &&
04952            (d->m_strSelectedURLTarget.lower() != "_self") &&
04953        (d->m_strSelectedURLTarget.lower() != "_parent")) {
04954       if (d->m_strSelectedURLTarget.lower() == "_blank")
04955         args.setForcesNewWindow(true);
04956       else {
04957     KHTMLPart *p = this;
04958     while (p->parentPart())
04959       p = p->parentPart();
04960     if (!p->frameExists(d->m_strSelectedURLTarget))
04961           args.setForcesNewWindow(true);
04962       }
04963     }
04964   }
04965 
04966   // Danger, Will Robinson. The Popup might stay around for a much
04967   // longer time than KHTMLPart. Deal with it.
04968   KHTMLPopupGUIClient* client = new KHTMLPopupGUIClient( this, d->m_popupMenuXML, linkKURL );
04969   QGuardedPtr<QObject> guard( client );
04970 
04971   QString mimetype = QString::fromLatin1( "text/html" );
04972   args.metaData()["referrer"] = referrer;
04973 
04974   if (!linkUrl.isEmpty())               // over a link
04975   {
04976     if (popupURL.isLocalFile())             // safe to do this
04977     {
04978       mimetype = KMimeType::findByURL(popupURL,0,true,false)->name();
04979     }
04980     else                        // look at "extension" of link
04981     {
04982       const QString fname(popupURL.fileName(false));
04983       if (!fname.isEmpty() && !popupURL.hasRef() && popupURL.query().isEmpty())
04984       {
04985         KMimeType::Ptr pmt = KMimeType::findByPath(fname,0,true);
04986 
04987         // Further check for mime types guessed from the extension which,
04988         // on a web page, are more likely to be a script delivering content
04989         // of undecidable type. If the mime type from the extension is one
04990         // of these, don't use it.  Retain the original type 'text/html'.
04991         if (pmt->name() != KMimeType::defaultMimeType() &&
04992             !pmt->is("application/x-perl") &&
04993             !pmt->is("application/x-perl-module") &&
04994             !pmt->is("application/x-php") &&
04995             !pmt->is("application/x-python-bytecode") &&
04996             !pmt->is("application/x-python") &&
04997             !pmt->is("application/x-shellscript"))
04998           mimetype = pmt->name();
04999       }
05000     }
05001   }
05002 
05003   args.serviceType = mimetype;
05004 
05005   emit d->m_extension->popupMenu( client, QCursor::pos(), popupURL, args, itemflags, S_IFREG /*always a file*/);
05006 
05007   if ( !guard.isNull() ) {
05008      delete client;
05009      emit popupMenu(linkUrl, QCursor::pos());
05010      d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
05011   }
05012 }
05013 
05014 void KHTMLPart::slotParentCompleted()
05015 {
05016   //kdDebug(6050) << this << " slotParentCompleted()" << endl;
05017   if ( !d->m_redirectURL.isEmpty() && !d->m_redirectionTimer.isActive() )
05018   {
05019     //kdDebug(6050) << this << ": starting timer for child redirection -> " << d->m_redirectURL << endl;
05020     d->m_redirectionTimer.start( 1000 * d->m_delayRedirect, true );
05021   }
05022 }
05023 
05024 void KHTMLPart::slotChildStarted( KIO::Job *job )
05025 {
05026   khtml::ChildFrame *child = frame( sender() );
05027 
05028   assert( child );
05029 
05030   child->m_bCompleted = false;
05031 
05032   if ( d->m_bComplete )
05033   {
05034 #if 0
05035     // WABA: Looks like this belongs somewhere else
05036     if ( !parentPart() ) // "toplevel" html document? if yes, then notify the hosting browser about the document (url) changes
05037     {
05038       emit d->m_extension->openURLNotify();
05039     }
05040 #endif
05041     d->m_bComplete = false;
05042     emit started( job );
05043   }
05044 }
05045 
05046 void KHTMLPart::slotChildCompleted()
05047 {
05048   slotChildCompleted( false );
05049 }
05050 
05051 void KHTMLPart::slotChildCompleted( bool pendingAction )
05052 {
05053   khtml::ChildFrame *child = frame( sender() );
05054 
05055   if ( child ) {
05056     kdDebug(6050) << this << " slotChildCompleted child=" << child << " m_frame=" << child->m_frame << endl;
05057     child->m_bCompleted = true;
05058     child->m_bPendingRedirection = pendingAction;
05059     child->m_args = KParts::URLArgs();
05060   }
05061   checkCompleted();
05062 }
05063 
05064 void KHTMLPart::slotChildDocCreated()
05065 {
05066   const KHTMLPart* htmlFrame = static_cast<const KHTMLPart *>(sender());
05067   // Set domain to the frameset's domain
05068   // This must only be done when loading the frameset initially (#22039),
05069   // not when following a link in a frame (#44162).
05070   if ( d->m_doc && d->m_doc->isHTMLDocument() )
05071   {
05072     if ( sender()->inherits("KHTMLPart") )
05073     {
05074       DOMString domain = static_cast<HTMLDocumentImpl*>(d->m_doc)->domain();
05075       if (htmlFrame->d->m_doc && htmlFrame->d->m_doc->isHTMLDocument() )
05076         //kdDebug(6050) << "KHTMLPart::slotChildDocCreated: url: " << htmlFrame->m_url.url() << endl;
05077         static_cast<HTMLDocumentImpl*>(htmlFrame->d->m_doc)->setDomain( domain );
05078     }
05079   }
05080   // So it only happens once
05081   disconnect( htmlFrame, SIGNAL( docCreated() ), this, SLOT( slotChildDocCreated() ) );
05082 }
05083 
05084 void KHTMLPart::slotChildURLRequest( const KURL &url, const KParts::URLArgs &args )
05085 {
05086   khtml::ChildFrame *child = frame( sender()->parent() );
05087   KHTMLPart *callingHtmlPart = const_cast<KHTMLPart *>(dynamic_cast<const KHTMLPart *>(sender()->parent()));
05088 
05089   // TODO: handle child target correctly! currently the script are always executed fur the parent
05090   QString urlStr = url.url();
05091   if ( urlStr.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
05092       QString script = KURL::decode_string( urlStr.right( urlStr.length() - 11 ) );
05093       executeScript( DOM::Node(), script );
05094       return;
05095   }
05096 
05097   QString frameName = args.frameName.lower();
05098   if ( !frameName.isEmpty() ) {
05099     if ( frameName == QString::fromLatin1( "_top" ) )
05100     {
05101       emit d->m_extension->openURLRequest( url, args );
05102       return;
05103     }
05104     else if ( frameName == QString::fromLatin1( "_blank" ) )
05105     {
05106       emit d->m_extension->createNewWindow( url, args );
05107       return;
05108     }
05109     else if ( frameName == QString::fromLatin1( "_parent" ) )
05110     {
05111       KParts::URLArgs newArgs( args );
05112       newArgs.frameName = QString::null;
05113 
05114       emit d->m_extension->openURLRequest( url, newArgs );
05115       return;
05116     }
05117     else if ( frameName != QString::fromLatin1( "_self" ) )
05118     {
05119       khtml::ChildFrame *_frame = recursiveFrameRequest( callingHtmlPart, url, args );
05120 
05121       if ( !_frame )
05122       {
05123         emit d->m_extension->openURLRequest( url, args );
05124         return;
05125       }
05126 
05127       child = _frame;
05128     }
05129   }
05130 
05131   if ( child && child->m_type != khtml::ChildFrame::Object ) {
05132       // Inform someone that we are about to show something else.
05133       child->m_bNotify = true;
05134       requestObject( child, url, args );
05135   }  else if ( frameName== "_self" ) // this is for embedded objects (via <object>) which want to replace the current document
05136   {
05137       KParts::URLArgs newArgs( args );
05138       newArgs.frameName = QString::null;
05139       emit d->m_extension->openURLRequest( url, newArgs );
05140   }
05141 }
05142 
05143 void KHTMLPart::slotRequestFocus( KParts::ReadOnlyPart * )
05144 {
05145   emit d->m_extension->requestFocus(this);
05146 }
05147 
05148 khtml::ChildFrame *KHTMLPart::frame( const QObject *obj )
05149 {
05150     assert( obj->inherits( "KParts::ReadOnlyPart" ) );
05151     const KParts::ReadOnlyPart* const part = static_cast<const KParts::ReadOnlyPart *>( obj );
05152 
05153     FrameIt it = d->m_frames.begin();
05154     const FrameIt end = d->m_frames.end();
05155     for (; it != end; ++it )
05156       if ( (KParts::ReadOnlyPart *)(*it)->m_part == part )
05157         return *it;
05158 
05159     FrameIt oi = d->m_objects.begin();
05160     const FrameIt oiEnd = d->m_objects.end();
05161     for (; oi != oiEnd; ++oi )
05162       if ( (KParts::ReadOnlyPart *)(*oi)->m_part == part )
05163         return *oi;
05164 
05165     return 0L;
05166 }
05167 
05168 //#define DEBUG_FINDFRAME
05169 
05170 bool KHTMLPart::checkFrameAccess(KHTMLPart *callingHtmlPart)
05171 {
05172   if (callingHtmlPart == this)
05173     return true; // trivial
05174 
05175   if (htmlDocument().isNull()) {
05176 #ifdef DEBUG_FINDFRAME
05177     kdDebug(6050) << "KHTMLPart::checkFrameAccess: Empty part " << this << " URL = " << m_url << endl;
05178 #endif
05179     return false; // we are empty?
05180   }
05181 
05182   // now compare the domains
05183   if (callingHtmlPart && !callingHtmlPart->htmlDocument().isNull() &&
05184       !htmlDocument().isNull())  {
05185     DOM::DOMString actDomain = callingHtmlPart->htmlDocument().domain();
05186     DOM::DOMString destDomain = htmlDocument().domain();
05187 
05188 #ifdef DEBUG_FINDFRAME
05189     kdDebug(6050) << "KHTMLPart::checkFrameAccess: actDomain = '" << actDomain.string() << "' destDomain = '" << destDomain.string() << "'" << endl;
05190 #endif
05191 
05192     if (actDomain == destDomain)
05193       return true;
05194   }
05195 #ifdef DEBUG_FINDFRAME
05196   else
05197   {
05198     kdDebug(6050) << "KHTMLPart::checkFrameAccess: Unknown part/domain " << callingHtmlPart << " tries to access part " << this << endl;
05199   }
05200 #endif
05201   return false;
05202 }
05203 
05204 KHTMLPart *
05205 KHTMLPart::findFrameParent( KParts::ReadOnlyPart *callingPart, const QString &f, khtml::ChildFrame **childFrame )
05206 {
05207 #ifdef DEBUG_FINDFRAME
05208   kdDebug(6050) << "KHTMLPart::findFrameParent: this = " << this << " URL = " << m_url << " name = " << name() << " findFrameParent( " << f << " )" << endl;
05209 #endif
05210   // Check access
05211   KHTMLPart* const callingHtmlPart = dynamic_cast<KHTMLPart *>(callingPart);
05212 
05213   if (!checkFrameAccess(callingHtmlPart))
05214      return 0;
05215 
05216   if (!childFrame && !parentPart() && (name() == f))
05217      return this;
05218 
05219   FrameIt it = d->m_frames.find( f );
05220   const FrameIt end = d->m_frames.end();
05221   if ( it != end )
05222   {
05223 #ifdef DEBUG_FINDFRAME
05224      kdDebug(6050) << "KHTMLPart::findFrameParent: FOUND!" << endl;
05225 #endif
05226      if (childFrame)
05227         *childFrame = *it;
05228      return this;
05229   }
05230 
05231   it = d->m_frames.begin();
05232   for (; it != end; ++it )
05233   {
05234     KParts::ReadOnlyPart* const p = (*it)->m_part;
05235     if ( p && p->inherits( "KHTMLPart" ))
05236     {
05237       KHTMLPart* const frameParent = static_cast<KHTMLPart*>(p)->findFrameParent(callingPart, f, childFrame);
05238       if (frameParent)
05239          return frameParent;
05240     }
05241   }
05242   return 0;
05243 }
05244 
05245 
05246 KHTMLPart *KHTMLPart::findFrame( const QString &f )
05247 {
05248   khtml::ChildFrame *childFrame;
05249   KHTMLPart *parentFrame = findFrameParent(this, f, &childFrame);
05250   if (parentFrame)
05251   {
05252      KParts::ReadOnlyPart *p = childFrame->m_part;
05253      if ( p && p->inherits( "KHTMLPart" ))
05254         return static_cast<KHTMLPart *>(p);
05255   }
05256   return 0;
05257 }
05258 
05259 KParts::ReadOnlyPart *KHTMLPart::findFramePart(const QString &f)
05260 {
05261   khtml::ChildFrame *childFrame;
05262   return findFrameParent(this, f, &childFrame) ? static_cast<KParts::ReadOnlyPart *>(childFrame->m_part) : 0L;
05263 }
05264 
05265 KParts::ReadOnlyPart *KHTMLPart::currentFrame() const
05266 {
05267   KParts::ReadOnlyPart* part = (KParts::ReadOnlyPart*)(this);
05268   // Find active part in our frame manager, in case we are a frameset
05269   // and keep doing that (in case of nested framesets).
05270   // Just realized we could also do this recursively, calling part->currentFrame()...
05271   while ( part && part->inherits("KHTMLPart") &&
05272           static_cast<KHTMLPart *>(part)->d->m_frames.count() > 0 ) {
05273     KHTMLPart* frameset = static_cast<KHTMLPart *>(part);
05274     part = static_cast<KParts::ReadOnlyPart *>(frameset->partManager()->activePart());
05275     if ( !part ) return frameset;
05276   }
05277   return part;
05278 }
05279 
05280 bool KHTMLPart::frameExists( const QString &frameName )
05281 {
05282   ConstFrameIt it = d->m_frames.find( frameName );
05283   if ( it == d->m_frames.end() )
05284     return false;
05285 
05286   // WABA: We only return true if the child actually has a frame
05287   // set. Otherwise we might find our preloaded-selve.
05288   // This happens when we restore the frameset.
05289   return (!(*it)->m_frame.isNull());
05290 }
05291 
05292 KJSProxy *KHTMLPart::framejScript(KParts::ReadOnlyPart *framePart)
05293 {
05294   KHTMLPart* const kp = ::qt_cast<KHTMLPart*>(framePart);
05295   if (kp)
05296     return kp->jScript();
05297 
05298   FrameIt it = d->m_frames.begin();
05299   const FrameIt itEnd = d->m_frames.end();
05300 
05301   for (; it != itEnd; ++it)
05302     if (framePart == (*it)->m_part) {
05303       if (!(*it)->m_jscript)
05304         createJScript(*it);
05305       return (*it)->m_jscript;
05306     }
05307   return 0L;
05308 }
05309 
05310 KHTMLPart *KHTMLPart::parentPart()
05311 {
05312   return ::qt_cast<KHTMLPart *>( parent() );
05313 }
05314 
05315 khtml::ChildFrame *KHTMLPart::recursiveFrameRequest( KHTMLPart *callingHtmlPart, const KURL &url,
05316                                                      const KParts::URLArgs &args, bool callParent )
05317 {
05318 #ifdef DEBUG_FINDFRAME
05319   kdDebug( 6050 ) << "KHTMLPart::recursiveFrameRequest this = " << this << ", frame = " << args.frameName << ", url = " << url << endl;
05320 #endif
05321   khtml::ChildFrame *childFrame;
05322   KHTMLPart *childPart = findFrameParent(callingHtmlPart, args.frameName, &childFrame);
05323   if (childPart)
05324   {
05325      if (childPart == this)
05326         return childFrame;
05327 
05328      childPart->requestObject( childFrame, url, args );
05329      return 0;
05330   }
05331 
05332   if ( parentPart() && callParent )
05333   {
05334      khtml::ChildFrame *res = parentPart()->recursiveFrameRequest( callingHtmlPart, url, args, callParent );
05335 
05336      if ( res )
05337        parentPart()->requestObject( res, url, args );
05338   }
05339 
05340   return 0L;
05341 }
05342 
05343 #ifndef NDEBUG
05344 static int s_saveStateIndentLevel = 0;
05345 #endif
05346 
05347 void KHTMLPart::saveState( QDataStream &stream )
05348 {
05349 #ifndef NDEBUG
05350   QString indent = QString().leftJustify( s_saveStateIndentLevel * 4, ' ' );
05351   const int indentLevel = s_saveStateIndentLevel++;
05352   kdDebug( 6050 ) << indent << "saveState this=" << this << " '" << name() << "' saving URL " << m_url.url() << endl;
05353 #endif
05354 
05355   stream << m_url << (Q_INT32)d->m_view->contentsX() << (Q_INT32)d->m_view->contentsY()
05356          << (Q_INT32) d->m_view->contentsWidth() << (Q_INT32) d->m_view->contentsHeight() << (Q_INT32) d->m_view->marginWidth() << (Q_INT32) d->m_view->marginHeight();
05357 
05358   // save link cursor position
05359   int focusNodeNumber;
05360   if (!d->m_focusNodeRestored)
05361       focusNodeNumber = d->m_focusNodeNumber;
05362   else if (d->m_doc && d->m_doc->focusNode())
05363       focusNodeNumber = d->m_doc->nodeAbsIndex(d->m_doc->focusNode());
05364   else
05365       focusNodeNumber = -1;
05366   stream << focusNodeNumber;
05367 
05368   // Save the doc's cache id.
05369   stream << d->m_cacheId;
05370 
05371   // Save the state of the document (Most notably the state of any forms)
05372   QStringList docState;
05373   if (d->m_doc)
05374   {
05375      docState = d->m_doc->docState();
05376   }
05377   stream << d->m_encoding << d->m_sheetUsed << docState;
05378 
05379   stream << d->m_zoomFactor;
05380 
05381   stream << d->m_httpHeaders;
05382   stream << d->m_pageServices;
05383   stream << d->m_pageReferrer;
05384 
05385   // Save ssl data
05386   stream << d->m_ssl_in_use
05387          << d->m_ssl_peer_certificate
05388          << d->m_ssl_peer_chain
05389          << d->m_ssl_peer_ip
05390          << d->m_ssl_cipher
05391          << d->m_ssl_cipher_desc
05392          << d->m_ssl_cipher_version
05393          << d->m_ssl_cipher_used_bits
05394          << d->m_ssl_cipher_bits
05395          << d->m_ssl_cert_state
05396          << d->m_ssl_parent_ip
05397          << d->m_ssl_parent_cert;
05398 
05399 
05400   QStringList frameNameLst, frameServiceTypeLst, frameServiceNameLst;
05401   KURL::List frameURLLst;
05402   QValueList<QByteArray> frameStateBufferLst;
05403 
05404   ConstFrameIt it = d->m_frames.begin();
05405   const ConstFrameIt end = d->m_frames.end();
05406   for (; it != end; ++it )
05407   {
05408     if ( !(*it)->m_part )
05409        continue;
05410 
05411     frameNameLst << (*it)->m_name;
05412     frameServiceTypeLst << (*it)->m_serviceType;
05413     frameServiceNameLst << (*it)->m_serviceName;
05414     frameURLLst << (*it)->m_part->url();
05415 
05416     QByteArray state;
05417     QDataStream frameStream( state, IO_WriteOnly );
05418 
05419     if ( (*it)->m_extension )
05420       (*it)->m_extension->saveState( frameStream );
05421 
05422     frameStateBufferLst << state;
05423   }
05424 
05425   // Save frame data
05426   stream << (Q_UINT32) frameNameLst.count();
05427   stream << frameNameLst << frameServiceTypeLst << frameServiceNameLst << frameURLLst << frameStateBufferLst;
05428 #ifndef NDEBUG
05429   s_saveStateIndentLevel = indentLevel;
05430 #endif
05431 }
05432 
05433 void KHTMLPart::restoreState( QDataStream &stream )
05434 {
05435   KURL u;
05436   Q_INT32 xOffset, yOffset, wContents, hContents, mWidth, mHeight;
05437   Q_UINT32 frameCount;
05438   QStringList frameNames, frameServiceTypes, docState, frameServiceNames;
05439   KURL::List frameURLs;
05440   QValueList<QByteArray> frameStateBuffers;
05441   QValueList<int> fSizes;
05442   QString encoding, sheetUsed;
05443   long old_cacheId = d->m_cacheId;
05444 
05445   stream >> u >> xOffset >> yOffset >> wContents >> hContents >> mWidth >> mHeight;
05446 
05447   d->m_view->setMarginWidth( mWidth );
05448   d->m_view->setMarginHeight( mHeight );
05449 
05450   // restore link cursor position
05451   // nth node is active. value is set in checkCompleted()
05452   stream >> d->m_focusNodeNumber;
05453   d->m_focusNodeRestored = false;
05454 
05455   stream >> d->m_cacheId;
05456 
05457   stream >> encoding >> sheetUsed >> docState;
05458 
05459   d->m_encoding = encoding;
05460   d->m_sheetUsed = sheetUsed;
05461 
05462   int zoomFactor;
05463   stream >> zoomFactor;
05464   setZoomFactor(zoomFactor);
05465 
05466   stream >> d->m_httpHeaders;
05467   stream >> d->m_pageServices;
05468   stream >> d->m_pageReferrer;
05469 
05470   // Restore ssl data
05471   stream >> d->m_ssl_in_use
05472          >> d->m_ssl_peer_certificate
05473          >> d->m_ssl_peer_chain
05474          >> d->m_ssl_peer_ip
05475          >> d->m_ssl_cipher
05476          >> d->m_ssl_cipher_desc
05477          >> d->m_ssl_cipher_version
05478          >> d->m_ssl_cipher_used_bits
05479          >> d->m_ssl_cipher_bits
05480          >> d->m_ssl_cert_state
05481          >> d->m_ssl_parent_ip
05482          >> d->m_ssl_parent_cert;
05483 
05484   setPageSecurity( d->m_ssl_in_use ? Encrypted : NotCrypted );
05485 
05486   stream >> frameCount >> frameNames >> frameServiceTypes >> frameServiceNames
05487          >> frameURLs >> frameStateBuffers;
05488 
05489   d->m_bComplete = false;
05490   d->m_bLoadEventEmitted = false;
05491 
05492 //   kdDebug( 6050 ) << "restoreState() docState.count() = " << docState.count() << endl;
05493 //   kdDebug( 6050 ) << "m_url " << m_url.url() << " <-> " << u.url() << endl;
05494 //   kdDebug( 6050 ) << "m_frames.count() " << d->m_frames.count() << " <-> " << frameCount << endl;
05495 
05496   if (d->m_cacheId == old_cacheId)
05497   {
05498     // Partial restore
05499     d->m_redirectionTimer.stop();
05500 
05501     FrameIt fIt = d->m_frames.begin();
05502     const FrameIt fEnd = d->m_frames.end();
05503 
05504     for (; fIt != fEnd; ++fIt )
05505         (*fIt)->m_bCompleted = false;
05506 
05507     fIt = d->m_frames.begin();
05508 
05509     QStringList::ConstIterator fNameIt = frameNames.begin();
05510     QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
05511     QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
05512     KURL::List::ConstIterator fURLIt = frameURLs.begin();
05513     QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
05514 
05515     for (; fIt != fEnd; ++fIt, ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
05516     {
05517       khtml::ChildFrame* const child = *fIt;
05518 
05519 //      kdDebug( 6050 ) <<  *fNameIt  << " ---- " <<  *fServiceTypeIt << endl;
05520 
05521       if ( child->m_name != *fNameIt || child->m_serviceType != *fServiceTypeIt )
05522       {
05523         child->m_bPreloaded = true;
05524         child->m_name = *fNameIt;
05525         child->m_serviceName = *fServiceNameIt;
05526         processObjectRequest( child, *fURLIt, *fServiceTypeIt );
05527       }
05528       if ( child->m_part )
05529       {
05530         child->m_bCompleted = false;
05531         if ( child->m_extension && !(*fBufferIt).isEmpty() )
05532         {
05533           QDataStream frameStream( *fBufferIt, IO_ReadOnly );
05534           child->m_extension->restoreState( frameStream );
05535         }
05536         else
05537           child->m_part->openURL( *fURLIt );
05538       }
05539     }
05540 
05541     KParts::URLArgs args( d->m_extension->urlArgs() );
05542     args.xOffset = xOffset;
05543     args.yOffset = yOffset;
05544     args.docState = docState;
05545     d->m_extension->setURLArgs( args );
05546 
05547     d->m_view->resizeContents( wContents,  hContents);
05548     d->m_view->setContentsPos( xOffset, yOffset );
05549 
05550     m_url = u;
05551   }
05552   else
05553   {
05554     // Full restore.
05555     closeURL();
05556     // We must force a clear because we want to be sure to delete all
05557     // frames.
05558     d->m_bCleared = false;
05559     clear();
05560     d->m_encoding = encoding;
05561     d->m_sheetUsed = sheetUsed;
05562 
05563     QStringList::ConstIterator fNameIt = frameNames.begin();
05564     const QStringList::ConstIterator fNameEnd = frameNames.end();
05565 
05566     QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
05567     QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
05568     KURL::List::ConstIterator fURLIt = frameURLs.begin();
05569     QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
05570 
05571     for (; fNameIt != fNameEnd; ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
05572     {
05573       khtml::ChildFrame* const newChild = new khtml::ChildFrame;
05574       newChild->m_bPreloaded = true;
05575       newChild->m_name = *fNameIt;
05576       newChild->m_serviceName = *fServiceNameIt;
05577 
05578 //      kdDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt << endl;
05579 
05580       const FrameIt childFrame = d->m_frames.append( newChild );
05581 
05582       processObjectRequest( *childFrame, *fURLIt, *fServiceTypeIt );
05583 
05584       (*childFrame)->m_bPreloaded = true;
05585 
05586       if ( (*childFrame)->m_part )
05587       {
05588         if ( (*childFrame)->m_extension )
05589         if ( (*childFrame)->m_extension && !(*fBufferIt).isEmpty() )
05590         {
05591           QDataStream frameStream( *fBufferIt, IO_ReadOnly );
05592           (*childFrame)->m_extension->restoreState( frameStream );
05593         }
05594         else
05595           (*childFrame)->m_part->openURL( *fURLIt );
05596       }
05597     }
05598 
05599     KParts::URLArgs args( d->m_extension->urlArgs() );
05600     args.xOffset = xOffset;
05601     args.yOffset = yOffset;
05602     args.docState = docState;
05603 
05604     d->m_extension->setURLArgs( args );
05605     if (!KHTMLPageCache::self()->isComplete(d->m_cacheId))
05606     {
05607        d->m_restored = true;
05608        openURL( u );
05609        d->m_restored = false;
05610     }
05611     else
05612     {
05613        restoreURL( u );
05614     }
05615   }
05616 
05617 }
05618 
05619 void KHTMLPart::show()
05620 {
05621   if ( d->m_view )
05622     d->m_view->show();
05623 }
05624 
05625 void KHTMLPart::hide()
05626 {
05627   if ( d->m_view )
05628     d->m_view->hide();
05629 }
05630 
05631 DOM::Node KHTMLPart::nodeUnderMouse() const
05632 {
05633     return d->m_view->nodeUnderMouse();
05634 }
05635 
05636 DOM::Node KHTMLPart::nonSharedNodeUnderMouse() const
05637 {
05638     return d->m_view->nonSharedNodeUnderMouse();
05639 }
05640 
05641 void KHTMLPart::emitSelectionChanged()
05642 {
05643   emit d->m_extension->enableAction( "copy", hasSelection() );
05644   if ( d->m_findDialog )
05645        d->m_findDialog->setHasSelection( hasSelection() );
05646 
05647   emit d->m_extension->selectionInfo( selectedText() );
05648   emit selectionChanged();
05649 }
05650 
05651 int KHTMLPart::zoomFactor() const
05652 {
05653   return d->m_zoomFactor;
05654 }
05655 
05656 // ### make the list configurable ?
05657 static const int zoomSizes[] = { 20, 40, 60, 80, 90, 95, 100, 105, 110, 120, 140, 160, 180, 200, 250, 300 };
05658 static const int zoomSizeCount = (sizeof(zoomSizes) / sizeof(int));
05659 static const int minZoom = 20;
05660 static const int maxZoom = 300;
05661 
05662 // My idea of useful stepping ;-) (LS)
05663 extern const int KDE_NO_EXPORT fastZoomSizes[] = { 20, 50, 75, 90, 100, 120, 150, 200, 300 };
05664 extern const int KDE_NO_EXPORT fastZoomSizeCount = sizeof fastZoomSizes / sizeof fastZoomSizes[0];
05665 
05666 void KHTMLPart::slotIncZoom()
05667 {
05668   zoomIn(zoomSizes, zoomSizeCount);
05669 }
05670 
05671 void KHTMLPart::slotDecZoom()
05672 {
05673   zoomOut(zoomSizes, zoomSizeCount);
05674 }
05675 
05676 void KHTMLPart::slotIncZoomFast()
05677 {
05678   zoomIn(fastZoomSizes, fastZoomSizeCount);
05679 }
05680 
05681 void KHTMLPart::slotDecZoomFast()
05682 {
05683   zoomOut(fastZoomSizes, fastZoomSizeCount);
05684 }
05685 
05686 void KHTMLPart::zoomIn(const int stepping[], int count)
05687 {
05688   int zoomFactor = d->m_zoomFactor;
05689 
05690   if (zoomFactor < maxZoom) {
05691     // find the entry nearest to the given zoomsizes
05692     for (int i = 0; i < count; ++i)
05693       if (stepping[i] > zoomFactor) {
05694         zoomFactor = stepping[i];
05695         break;
05696       }
05697     setZoomFactor(zoomFactor);
05698   }
05699 }
05700 
05701 void KHTMLPart::zoomOut(const int stepping[], int count)
05702 {
05703     int zoomFactor = d->m_zoomFactor;
05704     if (zoomFactor > minZoom) {
05705       // find the entry nearest to the given zoomsizes
05706       for (int i = count-1; i >= 0; --i)
05707         if (stepping[i] < zoomFactor) {
05708           zoomFactor = stepping[i];
05709           break;
05710         }
05711       setZoomFactor(zoomFactor);
05712     }
05713 }
05714 
05715 void KHTMLPart::setZoomFactor (int percent)
05716 {
05717   if (percent < minZoom) percent = minZoom;
05718   if (percent > maxZoom) percent = maxZoom;
05719   if (d->m_zoomFactor == percent) return;
05720   d->m_zoomFactor = percent;
05721 
05722   if(d->m_doc) {
05723       QApplication::setOverrideCursor( waitCursor );
05724     if (d->m_doc->styleSelector())
05725       d->m_doc->styleSelector()->computeFontSizes(d->m_doc->paintDeviceMetrics(), d->m_zoomFactor);
05726     d->m_doc->recalcStyle( NodeImpl::Force );
05727     QApplication::restoreOverrideCursor();
05728   }
05729 
05730   ConstFrameIt it = d->m_frames.begin();
05731   const ConstFrameIt end = d->m_frames.end();
05732   for (; it != end; ++it )
05733     if ( !( *it )->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
05734       KParts::ReadOnlyPart* const p = ( *it )->m_part;
05735       static_cast<KHTMLPart*>( p )->setZoomFactor(d->m_zoomFactor);
05736     }
05737 
05738   if ( d->m_guiProfile == BrowserViewGUI ) {
05739       d->m_paDecZoomFactor->setEnabled( d->m_zoomFactor > minZoom );
05740       d->m_paIncZoomFactor->setEnabled( d->m_zoomFactor < maxZoom );
05741   }
05742 }
05743 
05744 void KHTMLPart::slotZoomView( int delta )
05745 {
05746   if ( delta < 0 )
05747     slotIncZoom();
05748   else
05749     slotDecZoom();
05750 }
05751 
05752 void KHTMLPart::setStatusBarText( const QString& text, StatusBarPriority p)
05753 {
05754   if (!d->m_statusMessagesEnabled)
05755     return;
05756 
05757   d->m_statusBarText[p] = text;
05758 
05759   // shift handling ?
05760   QString tobe = d->m_statusBarText[BarHoverText];
05761   if (tobe.isEmpty())
05762     tobe = d->m_statusBarText[BarOverrideText];
05763   if (tobe.isEmpty()) {
05764     tobe = d->m_statusBarText[BarDefaultText];
05765     if (!tobe.isEmpty() && d->m_jobspeed)
05766       tobe += " ";
05767     if (d->m_jobspeed)
05768       tobe += i18n( "(%1/s)" ).arg( KIO::convertSize( d->m_jobspeed ) );
05769   }
05770   tobe = "<qt>"+tobe;
05771 
05772   emit ReadOnlyPart::setStatusBarText(tobe);
05773 }
05774 
05775 
05776 void KHTMLPart::setJSStatusBarText( const QString &text )
05777 {
05778   setStatusBarText(text, BarOverrideText);
05779 }
05780 
05781 void KHTMLPart::setJSDefaultStatusBarText( const QString &text )
05782 {
05783   setStatusBarText(text, BarDefaultText);
05784 }
05785 
05786 QString KHTMLPart::jsStatusBarText() const
05787 {
05788     return d->m_statusBarText[BarOverrideText];
05789 }
05790 
05791 QString KHTMLPart::jsDefaultStatusBarText() const
05792 {
05793    return d->m_statusBarText[BarDefaultText];
05794 }
05795 
05796 QString KHTMLPart::referrer() const
05797 {
05798    return d->m_referrer;
05799 }
05800 
05801 QString KHTMLPart::pageReferrer() const
05802 {
05803    KURL referrerURL = KURL( d->m_pageReferrer );
05804    if (referrerURL.isValid())
05805    {
05806       QString protocol = referrerURL.protocol();
05807 
05808       if ((protocol == "http") ||
05809          ((protocol == "https") && (m_url.protocol() == "https")))
05810       {
05811           referrerURL.setRef(QString::null);
05812           referrerURL.setUser(QString::null);
05813           referrerURL.setPass(QString::null);
05814           return referrerURL.url();
05815       }
05816    }
05817 
05818    return QString::null;
05819 }
05820 
05821 
05822 QString KHTMLPart::lastModified() const
05823 {
05824   if ( d->m_lastModified.isEmpty() && m_url.isLocalFile() ) {
05825     // Local file: set last-modified from the file's mtime.
05826     // Done on demand to save time when this isn't needed - but can lead
05827     // to slightly wrong results if updating the file on disk w/o reloading.
05828     QDateTime lastModif = QFileInfo( m_url.path() ).lastModified();
05829     d->m_lastModified = lastModif.toString( Qt::LocalDate );
05830   }
05831   //kdDebug(6050) << "KHTMLPart::lastModified: " << d->m_lastModified << endl;
05832   return d->m_lastModified;
05833 }
05834 
05835 void KHTMLPart::slotLoadImages()
05836 {
05837   if (d->m_doc )
05838     d->m_doc->docLoader()->setAutoloadImages( !d->m_doc->docLoader()->autoloadImages() );
05839 
05840   ConstFrameIt it = d->m_frames.begin();
05841   const ConstFrameIt end = d->m_frames.end();
05842   for (; it != end; ++it )
05843     if ( !( *it )->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
05844       KParts::ReadOnlyPart* const p = ( *it )->m_part;
05845       static_cast<KHTMLPart*>( p )->slotLoadImages();
05846     }
05847 }
05848 
05849 void KHTMLPart::reparseConfiguration()
05850 {
05851   KHTMLSettings *settings = KHTMLFactory::defaultHTMLSettings();
05852   settings->init();
05853 
05854   setAutoloadImages( settings->autoLoadImages() );
05855   if (d->m_doc)
05856      d->m_doc->docLoader()->setShowAnimations( settings->showAnimations() );
05857 
05858   d->m_bOpenMiddleClick = settings->isOpenMiddleClickEnabled();
05859   d->m_bBackRightClick = settings->isBackRightClickEnabled();
05860   d->m_bJScriptEnabled = settings->isJavaScriptEnabled(m_url.host());
05861   setDebugScript( settings->isJavaScriptDebugEnabled() );
05862   d->m_bJavaEnabled = settings->isJavaEnabled(m_url.host());
05863   d->m_bPluginsEnabled = settings->isPluginsEnabled(m_url.host());
05864   d->m_metaRefreshEnabled = settings->isAutoDelayedActionsEnabled ();
05865 
05866   delete d->m_settings;
05867   d->m_settings = new KHTMLSettings(*KHTMLFactory::defaultHTMLSettings());
05868 
05869   QApplication::setOverrideCursor( waitCursor );
05870   khtml::CSSStyleSelector::reparseConfiguration();
05871   if(d->m_doc) d->m_doc->updateStyleSelector();
05872   QApplication::restoreOverrideCursor();
05873 
05874   if (KHTMLFactory::defaultHTMLSettings()->isAdFilterEnabled())
05875      runAdFilter();
05876 }
05877 
05878 QStringList KHTMLPart::frameNames() const
05879 {
05880   QStringList res;
05881 
05882   ConstFrameIt it = d->m_frames.begin();
05883   const ConstFrameIt end = d->m_frames.end();
05884   for (; it != end; ++it )
05885     if (!(*it)->m_bPreloaded)
05886       res += (*it)->m_name;
05887 
05888   return res;
05889 }
05890 
05891 QPtrList<KParts::ReadOnlyPart> KHTMLPart::frames() const
05892 {
05893   QPtrList<KParts::ReadOnlyPart> res;
05894 
05895   ConstFrameIt it = d->m_frames.begin();
05896   const ConstFrameIt end = d->m_frames.end();
05897   for (; it != end; ++it )
05898     if (!(*it)->m_bPreloaded)
05899       res.append( (*it)->m_part );
05900 
05901   return res;
05902 }
05903 
05904 bool KHTMLPart::openURLInFrame( const KURL &url, const KParts::URLArgs &urlArgs )
05905 {
05906     kdDebug( 6050 ) << this << "KHTMLPart::openURLInFrame " << url << endl;
05907   FrameIt it = d->m_frames.find( urlArgs.frameName );
05908 
05909   if ( it == d->m_frames.end() )
05910     return false;
05911 
05912   // Inform someone that we are about to show something else.
05913   if ( !urlArgs.lockHistory() )
05914       emit d->m_extension->openURLNotify();
05915 
05916   requestObject( *it, url, urlArgs );
05917 
05918   return true;
05919 }
05920 
05921 void KHTMLPart::setDNDEnabled( bool b )
05922 {
05923   d->m_bDnd = b;
05924 }
05925 
05926 bool KHTMLPart::dndEnabled() const
05927 {
05928   return d->m_bDnd;
05929 }
05930 
05931 void KHTMLPart::customEvent( QCustomEvent *event )
05932 {
05933   if ( khtml::MousePressEvent::test( event ) )
05934   {
05935     khtmlMousePressEvent( static_cast<khtml::MousePressEvent *>( event ) );
05936     return;
05937   }
05938 
05939   if ( khtml::MouseDoubleClickEvent::test( event ) )
05940   {
05941     khtmlMouseDoubleClickEvent( static_cast<khtml::MouseDoubleClickEvent *>( event ) );
05942     return;
05943   }
05944 
05945   if ( khtml::MouseMoveEvent::test( event ) )
05946   {
05947     khtmlMouseMoveEvent( static_cast<khtml::MouseMoveEvent *>( event ) );
05948     return;
05949   }
05950 
05951   if ( khtml::MouseReleaseEvent::test( event ) )
05952   {
05953     khtmlMouseReleaseEvent( static_cast<khtml::MouseReleaseEvent *>( event ) );
05954     return;
05955   }
05956 
05957   if ( khtml::DrawContentsEvent::test( event ) )
05958   {
05959     khtmlDrawContentsEvent( static_cast<khtml::DrawContentsEvent *>( event ) );
05960     return;
05961   }
05962 
05963   KParts::ReadOnlyPart::customEvent( event );
05964 }
05965 
05971 static bool firstRunAt(khtml::RenderObject *renderNode, int y, NodeImpl *&startNode, long &startOffset)
05972 {
05973     for (khtml::RenderObject *n = renderNode; n; n = n->nextSibling()) {
05974         if (n->isText()) {
05975             khtml::RenderText* const textRenderer = static_cast<khtml::RenderText *>(n);
05976             const khtml::InlineTextBoxArray &runs = textRenderer->inlineTextBoxes();
05977             const unsigned lim = runs.count();
05978             for (unsigned i = 0; i != lim; ++i) {
05979                 if (runs[i]->m_y == y && textRenderer->element()) {
05980                     startNode = textRenderer->element();
05981                     startOffset = runs[i]->m_start;
05982                     return true;
05983                 }
05984             }
05985         }
05986 
05987         if (firstRunAt(n->firstChild(), y, startNode, startOffset)) {
05988             return true;
05989         }
05990     }
05991 
05992     return false;
05993 }
05994 
06000 static bool lastRunAt(khtml::RenderObject *renderNode, int y, NodeImpl *&endNode, long &endOffset)
06001 {
06002     khtml::RenderObject *n = renderNode;
06003     if (!n) {
06004         return false;
06005     }
06006     khtml::RenderObject *next;
06007     while ((next = n->nextSibling())) {
06008         n = next;
06009     }
06010 
06011     while (1) {
06012         if (lastRunAt(n->firstChild(), y, endNode, endOffset)) {
06013             return true;
06014         }
06015 
06016         if (n->isText()) {
06017             khtml::RenderText* const textRenderer =  static_cast<khtml::RenderText *>(n);
06018             const khtml::InlineTextBoxArray &runs = textRenderer->inlineTextBoxes();
06019             for (int i = (int)runs.count()-1; i >= 0; --i) {
06020                 if (runs[i]->m_y == y && textRenderer->element()) {
06021                     endNode = textRenderer->element();
06022                     endOffset = runs[i]->m_start + runs[i]->m_len;
06023                     return true;
06024                 }
06025             }
06026         }
06027 
06028         if (n == renderNode) {
06029             return false;
06030         }
06031 
06032         n = n->previousSibling();
06033     }
06034 }
06035 
06036 void KHTMLPart::khtmlMousePressEvent( khtml::MousePressEvent *event )
06037 {
06038   DOM::DOMString url = event->url();
06039   QMouseEvent *_mouse = event->qmouseEvent();
06040   DOM::Node innerNode = event->innerNode();
06041   d->m_mousePressNode = innerNode;
06042 
06043    d->m_dragStartPos = _mouse->pos();
06044 
06045    if ( !event->url().isNull() ) {
06046      d->m_strSelectedURL = event->url().string();
06047      d->m_strSelectedURLTarget = event->target().string();
06048    }
06049    else
06050      d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
06051 
06052   if ( _mouse->button() == LeftButton ||
06053        _mouse->button() == MidButton )
06054   {
06055     d->m_bMousePressed = true;
06056 
06057 #ifndef KHTML_NO_SELECTION
06058     if ( _mouse->button() == LeftButton )
06059     {
06060       if ( (!d->m_strSelectedURL.isNull() && !isEditable())
06061             || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) )
06062       return;
06063       if ( !innerNode.isNull()  && innerNode.handle()->renderer()) {
06064           int offset = 0;
06065           DOM::NodeImpl* node = 0;
06066           khtml::RenderObject::SelPointState state;
06067           innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(),
06068                                                                event->absX()-innerNode.handle()->renderer()->xPos(),
06069                                                                event->absY()-innerNode.handle()->renderer()->yPos(), node, offset, state );
06070           d->m_extendMode = d->ExtendByChar;
06071 #ifdef KHTML_NO_CARET
06072           d->m_selectionStart = node;
06073           d->m_startOffset = offset;
06074           //if ( node )
06075           //  kdDebug(6005) << "KHTMLPart::khtmlMousePressEvent selectionStart=" << d->m_selectionStart.handle()->renderer()
06076           //                << " offset=" << d->m_startOffset << endl;
06077           //else
06078           //  kdDebug(6005) << "KHTML::khtmlMousePressEvent selectionStart=(nil)" << endl;
06079           d->m_selectionEnd = d->m_selectionStart;
06080           d->m_endOffset = d->m_startOffset;
06081           d->m_doc->clearSelection();
06082 #else // KHTML_NO_CARET
06083       d->m_view->moveCaretTo(node, offset, (_mouse->state() & ShiftButton) == 0);
06084 #endif // KHTML_NO_CARET
06085       d->m_initialNode = d->m_selectionStart;
06086       d->m_initialOffset = d->m_startOffset;
06087 //           kdDebug(6000) << "press: initOfs " << d->m_initialOffset << endl;
06088       }
06089       else
06090       {
06091 #ifndef KHTML_NO_CARET
06092         // simply leave it. Is this a good idea?
06093 #else
06094         d->m_selectionStart = DOM::Node();
06095         d->m_selectionEnd = DOM::Node();
06096 #endif
06097       }
06098       emitSelectionChanged();
06099       startAutoScroll();
06100     }
06101 #else
06102     d->m_dragLastPos = _mouse->globalPos();
06103 #endif
06104   }
06105 
06106   if ( _mouse->button() == RightButton && parentPart() != 0 && d->m_bBackRightClick )
06107   {
06108     d->m_bRightMousePressed = true;
06109   } else if ( _mouse->button() == RightButton )
06110   {
06111     popupMenu( d->m_strSelectedURL );
06112     // might be deleted, don't touch "this"
06113   }
06114 }
06115 
06116 void KHTMLPart::khtmlMouseDoubleClickEvent( khtml::MouseDoubleClickEvent *event )
06117 {
06118   QMouseEvent *_mouse = event->qmouseEvent();
06119   if ( _mouse->button() == LeftButton )
06120   {
06121     d->m_bMousePressed = true;
06122     DOM::Node innerNode = event->innerNode();
06123     // Find selectionStart again, khtmlMouseReleaseEvent lost it
06124     if ( !innerNode.isNull() && innerNode.handle()->renderer()) {
06125       int offset = 0;
06126       DOM::NodeImpl* node = 0;
06127       khtml::RenderObject::SelPointState state;
06128       innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(),
06129                                                            event->absX()-innerNode.handle()->renderer()->xPos(),
06130                                                            event->absY()-innerNode.handle()->renderer()->yPos(), node, offset, state);
06131 
06132       //kdDebug() << k_funcinfo << "checkSelectionPoint returned node=" << node << " offset=" << offset << endl;
06133 
06134       if ( node && node->renderer() )
06135       {
06136         // Extend selection to a complete word (double-click) or line (triple-click)
06137         bool selectLine = (event->clickCount() == 3);
06138         d->m_extendMode = selectLine ? d->ExtendByLine : d->ExtendByWord;
06139 
06140     // Extend existing selection if Shift was pressed
06141     if (_mouse->state() & ShiftButton) {
06142           d->caretNode() = node;
06143       d->caretOffset() = offset;
06144           d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
06145                 d->m_selectionStart.handle(), d->m_startOffset,
06146             d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
06147           d->m_initialNode = d->m_extendAtEnd ? d->m_selectionStart : d->m_selectionEnd;
06148           d->m_initialOffset = d->m_extendAtEnd ? d->m_startOffset : d->m_endOffset;
06149     } else {
06150       d->m_selectionStart = d->m_selectionEnd = node;
06151       d->m_startOffset = d->m_endOffset = offset;
06152           d->m_startBeforeEnd = true;
06153           d->m_initialNode = node;
06154           d->m_initialOffset = offset;
06155     }
06156 //         kdDebug(6000) << "dblclk: initOfs " << d->m_initialOffset << endl;
06157 
06158         // Extend the start
06159         extendSelection( d->m_selectionStart.handle(), d->m_startOffset, d->m_selectionStart, d->m_startOffset, !d->m_startBeforeEnd, selectLine );
06160         // Extend the end
06161         extendSelection( d->m_selectionEnd.handle(), d->m_endOffset, d->m_selectionEnd, d->m_endOffset, d->m_startBeforeEnd, selectLine );
06162 
06163         //kdDebug() << d->m_selectionStart.handle() << " " << d->m_startOffset << "  -  " <<
06164         //  d->m_selectionEnd.handle() << " " << d->m_endOffset << endl;
06165 
06166         emitSelectionChanged();
06167         d->m_doc
06168           ->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
06169                          d->m_selectionEnd.handle(),d->m_endOffset);
06170 #ifndef KHTML_NO_CARET
06171         bool v = d->m_view->placeCaret();
06172         emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
06173 #endif
06174         startAutoScroll();
06175       }
06176     }
06177   }
06178 }
06179 
06180 void KHTMLPart::extendSelection( DOM::NodeImpl* node, long offset, DOM::Node& selectionNode, long& selectionOffset, bool right, bool selectLines )
06181 {
06182   khtml::RenderObject* obj = node->renderer();
06183 
06184   if (obj->isText() && selectLines) {
06185     int pos;
06186     khtml::RenderText *renderer = static_cast<khtml::RenderText *>(obj);
06187     khtml::InlineTextBox *run = renderer->findInlineTextBox( offset, pos );
06188     DOMString t = node->nodeValue();
06189     DOM::NodeImpl* selNode = 0;
06190     long selOfs = 0;
06191 
06192     if (!run)
06193       return;
06194 
06195     int selectionPointY = run->m_y;
06196 
06197     // Go up to first non-inline element.
06198     khtml::RenderObject *renderNode = renderer;
06199     while (renderNode && renderNode->isInline())
06200       renderNode = renderNode->parent();
06201 
06202     renderNode = renderNode->firstChild();
06203 
06204     if (right) {
06205       // Look for all the last child in the block that is on the same line
06206       // as the selection point.
06207       if (!lastRunAt (renderNode, selectionPointY, selNode, selOfs))
06208         return;
06209     } else {
06210       // Look for all the first child in the block that is on the same line
06211       // as the selection point.
06212       if (!firstRunAt (renderNode, selectionPointY, selNode, selOfs))
06213         return;
06214     }
06215 
06216     selectionNode = selNode;
06217     selectionOffset = selOfs;
06218     return;
06219   }
06220 
06221   QString str;
06222   int len = 0;
06223   if ( obj->isText() ) { // can be false e.g. when double-clicking on a disabled submit button
06224     str = static_cast<khtml::RenderText *>(obj)->data().string();
06225     len = str.length();
06226   }
06227   //kdDebug() << "extendSelection right=" << right << " offset=" << offset << " len=" << len << " Starting at obj=" << obj << endl;
06228   QChar ch;
06229   do {
06230     // Last char was ok, point to it
06231     if ( node ) {
06232       selectionNode = node;
06233       selectionOffset = offset;
06234     }
06235 
06236     // Get another char
06237     while ( obj && ( (right && offset >= len-1) || (!right && offset <= 0) ) )
06238     {
06239       obj = right ? obj->objectBelow() : obj->objectAbove();
06240       //kdDebug() << "obj=" << obj << endl;
06241       if ( obj ) {
06242         //kdDebug() << "isText=" << obj->isText() << endl;
06243         str = QString::null;
06244         if ( obj->isText() )
06245           str = static_cast<khtml::RenderText *>(obj)->data().string();
06246         else if ( obj->isBR() )
06247           str = '\n';
06248         else if ( !obj->isInline() ) {
06249           obj = 0L; // parag limit -> done
06250           break;
06251         }
06252         len = str.length();
06253         //kdDebug() << "str=" << str << " length=" << len << endl;
06254         // set offset - note that the first thing will be a ++ or -- on it.
06255         if ( right )
06256           offset = -1;
06257         else
06258           offset = len;
06259       }
06260     }
06261     if ( !obj ) // end of parag or document
06262       break;
06263     node = obj->element();
06264     if ( right )
06265     {
06266       Q_ASSERT( offset < len-1 );
06267       ++offset;
06268     }
06269     else
06270     {
06271       Q_ASSERT( offset > 0 );
06272       --offset;
06273     }
06274 
06275     // Test that char
06276     ch = str[ (int)offset ];
06277     //kdDebug() << " offset=" << offset << " ch=" << QString(ch) << endl;
06278   } while ( !ch.isSpace() && !ch.isPunct() );
06279 
06280   // make offset point after last char
06281   if (right) ++selectionOffset;
06282 }
06283 
06284 #ifndef KHTML_NO_SELECTION
06285 void KHTMLPart::extendSelectionTo(int x, int y, int absX, int absY, const DOM::Node &innerNode)
06286 {
06287       int offset;
06288       //kdDebug(6000) << "KHTMLPart::khtmlMouseMoveEvent x=" << event->x() << " y=" << event->y() << endl;
06289       DOM::NodeImpl* node=0;
06290       khtml::RenderObject::SelPointState state;
06291       innerNode.handle()->renderer()->checkSelectionPoint( x, y,
06292                                                            absX-innerNode.handle()->renderer()->xPos(),
06293                                                            absY-innerNode.handle()->renderer()->yPos(), node, offset, state);
06294       if (!node || !node->renderer()) return;
06295 
06296       // Words at the beginning/end of line cannot be deselected in
06297       // ExtendByWord mode. Therefore, do not enforce it if the selection
06298       // point does not match the node under the mouse cursor.
06299       bool withinNode = innerNode == node;
06300 
06301       // we have to get to know if end is before start or not...
06302       // shouldn't be null but it can happen with dynamic updating of nodes
06303       if (d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() ||
06304           d->m_initialNode.isNull() ||
06305           !d->m_selectionStart.handle()->renderer() ||
06306           !d->m_selectionEnd.handle()->renderer()) return;
06307 
06308       if (d->m_extendMode != d->ExtendByChar) {
06309         // check whether we should extend at the front, or at the back
06310         bool caretBeforeInit = RangeImpl::compareBoundaryPoints(
06311                 d->caretNode().handle(), d->caretOffset(),
06312             d->m_initialNode.handle(), d->m_initialOffset) <= 0;
06313         bool nodeBeforeInit = RangeImpl::compareBoundaryPoints(node, offset,
06314             d->m_initialNode.handle(), d->m_initialOffset) <= 0;
06315         // have to fix up start to point to the original end
06316         if (caretBeforeInit != nodeBeforeInit) {
06317 //         kdDebug(6000) << "extto cbi: " << caretBeforeInit << " startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << " initOfs " << d->m_initialOffset << endl;
06318           extendSelection(d->m_initialNode.handle(), d->m_initialOffset,
06319         d->m_extendAtEnd ? d->m_selectionStart : d->m_selectionEnd,
06320         d->m_extendAtEnd ? d->m_startOffset : d->m_endOffset,
06321         nodeBeforeInit, d->m_extendMode == d->ExtendByLine);
06322     }
06323       }
06324 
06325       d->caretNode() = node;
06326       d->caretOffset() = offset;
06327       //kdDebug( 6000 ) << "setting end of selection to " << d->m_selectionEnd.handle() << "/" << d->m_endOffset << endl;
06328 
06329       d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
06330                 d->m_selectionStart.handle(), d->m_startOffset,
06331             d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
06332 
06333       if ( !d->m_selectionStart.isNull() && !d->m_selectionEnd.isNull() )
06334       {
06335 //         kdDebug(6000) << "extto: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << " initOfs " << d->m_initialOffset << endl;
06336         if (d->m_extendMode != d->ExtendByChar && withinNode)
06337           extendSelection( node, offset, d->caretNode(), d->caretOffset(), d->m_startBeforeEnd ^ !d->m_extendAtEnd, d->m_extendMode == d->ExtendByLine );
06338 
06339         if (d->m_selectionEnd == d->m_selectionStart && d->m_endOffset < d->m_startOffset)
06340           d->m_doc
06341             ->setSelection(d->m_selectionStart.handle(),d->m_endOffset,
06342                            d->m_selectionEnd.handle(),d->m_startOffset);
06343         else if (d->m_startBeforeEnd)
06344           d->m_doc
06345             ->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
06346                            d->m_selectionEnd.handle(),d->m_endOffset);
06347         else
06348           d->m_doc
06349             ->setSelection(d->m_selectionEnd.handle(),d->m_endOffset,
06350                            d->m_selectionStart.handle(),d->m_startOffset);
06351       }
06352 #ifndef KHTML_NO_CARET
06353       d->m_view->placeCaret();
06354 #endif
06355 }
06356 
06357 bool KHTMLPart::isExtendingSelection() const
06358 {
06359   // This is it, the whole detection. khtmlMousePressEvent only sets this
06360   // on LMB or MMB, but never on RMB. As text selection doesn't work for MMB,
06361   // it's sufficient to only rely on this flag to detect selection extension.
06362   return d->m_bMousePressed;
06363 }
06364 #endif // KHTML_NO_SELECTION
06365 
06366 void KHTMLPart::khtmlMouseMoveEvent( khtml::MouseMoveEvent *event )
06367 {
06368   QMouseEvent *_mouse = event->qmouseEvent();
06369 
06370   if( d->m_bRightMousePressed && parentPart() != 0 && d->m_bBackRightClick )
06371   {
06372     popupMenu( d->m_strSelectedURL );
06373     d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
06374     d->m_bRightMousePressed = false;
06375   }
06376 
06377   DOM::DOMString url = event->url();
06378   DOM::DOMString target = event->target();
06379   DOM::Node innerNode = event->innerNode();
06380 
06381 #ifndef QT_NO_DRAGANDDROP
06382   if( d->m_bDnd && d->m_bMousePressed &&
06383       ( (!d->m_strSelectedURL.isEmpty() && !isEditable())
06384         || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) ) ) {
06385     if ( ( d->m_dragStartPos - _mouse->pos() ).manhattanLength() <= KGlobalSettings::dndEventDelay() )
06386       return;
06387 
06388     QPixmap pix;
06389     HTMLImageElementImpl *img = 0L;
06390     QDragObject *drag = 0;
06391     KURL u;
06392 
06393     // qDebug("****************** Event URL: %s", url.string().latin1());
06394     // qDebug("****************** Event Target: %s", target.string().latin1());
06395 
06396     // Normal image...
06397     if ( url.length() == 0 && innerNode.handle() && innerNode.handle()->id() == ID_IMG )
06398     {
06399       img = static_cast<HTMLImageElementImpl *>(innerNode.handle());
06400       u = KURL( completeURL( khtml::parseURL(img->getAttribute(ATTR_SRC)).string() ) );
06401       pix = KMimeType::mimeType("image/png")->pixmap(KIcon::Desktop);
06402     }
06403     else
06404     {
06405       // Text or image link...
06406       u = completeURL( d->m_strSelectedURL );
06407       pix = KMimeType::pixmapForURL(u, 0, KIcon::Desktop, KIcon::SizeMedium);
06408     }
06409 
06410     u.setPass(QString::null);
06411 
06412     KURLDrag* urlDrag = new KURLDrag( u, img ? 0 : d->m_view->viewport() );
06413     if ( !d->m_referrer.isEmpty() )
06414       urlDrag->metaData()["referrer"] = d->m_referrer;
06415 
06416     if( img && img->complete()) {
06417       KMultipleDrag *mdrag = new KMultipleDrag( d->m_view->viewport() );
06418       mdrag->addDragObject( new QImageDrag( img->currentImage(), 0L ) );
06419       mdrag->addDragObject( urlDrag );
06420       drag = mdrag;
06421     }
06422     else
06423       drag = urlDrag;
06424 
06425     if ( !pix.isNull() )
06426       drag->setPixmap( pix );
06427 
06428     stopAutoScroll();
06429     if(drag)
06430       drag->drag();
06431 
06432     // when we finish our drag, we need to undo our mouse press
06433     d->m_bMousePressed = false;
06434     d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
06435     return;
06436   }
06437 #endif
06438 
06439   // Not clicked -> mouse over stuff
06440   if ( !d->m_bMousePressed )
06441   {
06442     // The mouse is over something
06443     if ( url.length() )
06444     {
06445       bool shiftPressed = ( _mouse->state() & ShiftButton );
06446 
06447       // Image map
06448       if ( !innerNode.isNull() && innerNode.elementId() == ID_IMG )
06449       {
06450         HTMLImageElementImpl *i = static_cast<HTMLImageElementImpl *>(innerNode.handle());
06451         if ( i && i->isServerMap() )
06452         {
06453           khtml::RenderObject *r = i->renderer();
06454           if(r)
06455           {
06456             int absx, absy, vx, vy;
06457             r->absolutePosition(absx, absy);
06458             view()->contentsToViewport( absx, absy, vx, vy );
06459 
06460             int x(_mouse->x() - vx), y(_mouse->y() - vy);
06461 
06462             d->m_overURL = url.string() + QString("?%1,%2").arg(x).arg(y);
06463             d->m_overURLTarget = target.string();
06464             overURL( d->m_overURL, target.string(), shiftPressed );
06465             return;
06466           }
06467         }
06468       }
06469 
06470       // normal link
06471       if ( d->m_overURL.isEmpty() || d->m_overURL != url || d->m_overURLTarget != target )
06472       {
06473         d->m_overURL = url.string();
06474         d->m_overURLTarget = target.string();
06475         overURL( d->m_overURL, target.string(), shiftPressed );
06476       }
06477     }
06478     else  // Not over a link...
06479     {
06480       // reset to "default statusbar text"
06481       resetHoverText();
06482     }
06483   }
06484   else {
06485 #ifndef KHTML_NO_SELECTION
06486     // selection stuff
06487     if( d->m_bMousePressed && innerNode.handle() && innerNode.handle()->renderer() &&
06488         ( (_mouse->state() & LeftButton) != 0 )) {
06489       extendSelectionTo(event->x(), event->y(),
06490                         event->absX(), event->absY(), innerNode);
06491 #else
06492       if ( d->m_doc && d->m_view ) {
06493         QPoint diff( _mouse->globalPos() - d->m_dragLastPos );
06494 
06495         if ( abs( diff.x() ) > 64 || abs( diff.y() ) > 64 ) {
06496           d->m_view->scrollBy( -diff.x(), -diff.y() );
06497           d->m_dragLastPos = _mouse->globalPos();
06498         }
06499 #endif
06500     }
06501   }
06502 
06503 }
06504 
06505 void KHTMLPart::khtmlMouseReleaseEvent( khtml::MouseReleaseEvent *event )
06506 {
06507   DOM::Node innerNode = event->innerNode();
06508   d->m_mousePressNode = DOM::Node();
06509 
06510   if ( d->m_bMousePressed ) {
06511     setStatusBarText(QString::null, BarHoverText);
06512     stopAutoScroll();
06513   }
06514 
06515   // Used to prevent mouseMoveEvent from initiating a drag before
06516   // the mouse is pressed again.
06517   d->m_bMousePressed = false;
06518 
06519   QMouseEvent *_mouse = event->qmouseEvent();
06520   if ( _mouse->button() == RightButton && parentPart() != 0 && d->m_bBackRightClick )
06521   {
06522     d->m_bRightMousePressed = false;
06523     KParts::BrowserInterface *tmp_iface = d->m_extension->browserInterface();
06524     if( tmp_iface ) {
06525       tmp_iface->callMethod( "goHistory(int)", -1 );
06526     }
06527   }
06528 #ifndef QT_NO_CLIPBOARD
06529   if ((d->m_guiProfile == BrowserViewGUI) && (_mouse->button() == MidButton) && (event->url().isNull())) {
06530     kdDebug( 6050 ) << "KHTMLPart::khtmlMouseReleaseEvent() MMB shouldOpen="
06531                     << d->m_bOpenMiddleClick << endl;
06532 
06533     if (d->m_bOpenMiddleClick) {
06534     KHTMLPart *p = this;
06535     while (p->parentPart()) p = p->parentPart();
06536     p->d->m_extension->pasteRequest();
06537   }
06538   }
06539 #endif
06540 
06541 #ifndef KHTML_NO_SELECTION
06542   // delete selection in case start and end position are at the same point
06543   if(d->m_selectionStart == d->m_selectionEnd && d->m_startOffset == d->m_endOffset) {
06544 #ifndef KHTML_NO_CARET
06545     d->m_extendAtEnd = true;
06546 #else
06547     d->m_selectionStart = 0;
06548     d->m_selectionEnd = 0;
06549     d->m_startOffset = 0;
06550     d->m_endOffset = 0;
06551 #endif
06552     emitSelectionChanged();
06553   } else {
06554     // we have to get to know if end is before start or not...
06555 //     kdDebug(6000) << "rel: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << endl;
06556     DOM::Node n = d->m_selectionStart;
06557     d->m_startBeforeEnd = false;
06558     if( d->m_selectionStart == d->m_selectionEnd ) {
06559       if( d->m_startOffset < d->m_endOffset )
06560         d->m_startBeforeEnd = true;
06561     } else {
06562 #if 0
06563       while(!n.isNull()) {
06564         if(n == d->m_selectionEnd) {
06565           d->m_startBeforeEnd = true;
06566           break;
06567         }
06568         DOM::Node next = n.firstChild();
06569         if(next.isNull()) next = n.nextSibling();
06570         while( next.isNull() && !n.parentNode().isNull() ) {
06571           n = n.parentNode();
06572           next = n.nextSibling();
06573         }
06574         n = next;
06575       }
06576 #else
06577       // shouldn't be null but it can happen with dynamic updating of nodes
06578       if (d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() ||
06579           !d->m_selectionStart.handle()->renderer() ||
06580           !d->m_selectionEnd.handle()->renderer()) return;
06581       d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
06582                 d->m_selectionStart.handle(), d->m_startOffset,
06583             d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
06584 #endif
06585     }
06586     if(!d->m_startBeforeEnd)
06587     {
06588       DOM::Node tmpNode = d->m_selectionStart;
06589       int tmpOffset = d->m_startOffset;
06590       d->m_selectionStart = d->m_selectionEnd;
06591       d->m_startOffset = d->m_endOffset;
06592       d->m_selectionEnd = tmpNode;
06593       d->m_endOffset = tmpOffset;
06594       d->m_startBeforeEnd = true;
06595       d->m_extendAtEnd = !d->m_extendAtEnd;
06596     }
06597 #ifndef KHTML_NO_CARET
06598     bool v = d->m_view->placeCaret();
06599     emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
06600 #endif
06601     // get selected text and paste to the clipboard
06602 #ifndef QT_NO_CLIPBOARD
06603     QString text = selectedText();
06604     text.replace(QChar(0xa0), ' ');
06605     disconnect( kapp->clipboard(), SIGNAL( selectionChanged()), this, SLOT( slotClearSelection()));
06606     kapp->clipboard()->setText(text,QClipboard::Selection);
06607     connect( kapp->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection()));
06608 #endif
06609     //kdDebug( 6000 ) << "selectedText = " << text << endl;
06610     emitSelectionChanged();
06611 //kdDebug(6000) << "rel2: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << "), caretOfs " << d->caretOffset() << endl;
06612   }
06613 #endif
06614   d->m_initialNode = 0;     // don't hold nodes longer than necessary
06615   d->m_initialOffset = 0;
06616 
06617 }
06618 
06619 void KHTMLPart::khtmlDrawContentsEvent( khtml::DrawContentsEvent * )
06620 {
06621 }
06622 
06623 void KHTMLPart::guiActivateEvent( KParts::GUIActivateEvent *event )
06624 {
06625   if ( event->activated() )
06626   {
06627     emitSelectionChanged();
06628     emit d->m_extension->enableAction( "print", d->m_doc != 0 );
06629 
06630     if ( !d->m_settings->autoLoadImages() && d->m_paLoadImages )
06631     {
06632         QPtrList<KAction> lst;
06633         lst.append( d->m_paLoadImages );
06634         plugActionList( "loadImages", lst );
06635     }
06636   }
06637 }
06638 
06639 void KHTMLPart::slotPrintFrame()
06640 {
06641   if ( d->m_frames.count() == 0 )
06642     return;
06643 
06644   KParts::ReadOnlyPart *frame = currentFrame();
06645   if (!frame)
06646     return;
06647 
06648   KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject( frame );
06649 
06650   if ( !ext )
06651     return;
06652 
06653   QMetaObject *mo = ext->metaObject();
06654 
06655   int idx = mo->findSlot( "print()", true );
06656   if ( idx >= 0 ) {
06657     QUObject o[ 1 ];
06658     ext->qt_invoke( idx, o );
06659   }
06660 }
06661 
06662 void KHTMLPart::slotSelectAll()
06663 {
06664   KParts::ReadOnlyPart *part = currentFrame();
06665   if (part && part->inherits("KHTMLPart"))
06666     static_cast<KHTMLPart *>(part)->selectAll();
06667 }
06668 
06669 void KHTMLPart::startAutoScroll()
06670 {
06671    connect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
06672    d->m_scrollTimer.start(100, false);
06673 }
06674 
06675 void KHTMLPart::stopAutoScroll()
06676 {
06677    disconnect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
06678    if (d->m_scrollTimer.isActive())
06679        d->m_scrollTimer.stop();
06680 }
06681 
06682 
06683 void KHTMLPart::slotAutoScroll()
06684 {
06685     if (d->m_view)
06686       d->m_view->doAutoScroll();
06687     else
06688       stopAutoScroll(); // Safety
06689 }
06690 
06691 void KHTMLPart::runAdFilter()
06692 {
06693     if ( parentPart() )
06694         parentPart()->runAdFilter();
06695 
06696     if ( !d->m_doc )
06697         return;
06698 
06699     QPtrDictIterator<khtml::CachedObject> it( d->m_doc->docLoader()->m_docObjects );
06700     for ( ; it.current(); ++it )
06701         if ( it.current()->type() == khtml::CachedObject::Image ) {
06702             khtml::CachedImage *image = static_cast<khtml::CachedImage *>(it.current());
06703             bool wasBlocked = image->m_wasBlocked;
06704             image->m_wasBlocked = KHTMLFactory::defaultHTMLSettings()->isAdFiltered( d->m_doc->completeURL( (*it).url().string() ) );
06705             if ( image->m_wasBlocked != wasBlocked )
06706                 image->do_notify(image->pixmap(), image->valid_rect());
06707         }
06708 
06709     if ( KHTMLFactory::defaultHTMLSettings()->isHideAdsEnabled() ) {
06710         for ( NodeImpl *nextNode, *node = d->m_doc; node; node = nextNode ) {
06711 
06712             // We might be deleting 'node' shortly.
06713             nextNode = node->traverseNextNode();
06714 
06715             if ( node->id() == ID_IMG ||
06716                  node->id() == ID_IFRAME ||
06717                  (node->id() == ID_INPUT && static_cast<HTMLInputElementImpl *>(node)->inputType() == HTMLInputElementImpl::IMAGE ))
06718             {
06719                 if ( KHTMLFactory::defaultHTMLSettings()->isAdFiltered( d->m_doc->completeURL( static_cast<ElementImpl *>(node)->getAttribute(ATTR_SRC).string() ) ) )
06720                 {
06721                     // We found an IMG, IFRAME or INPUT (of type IMAGE) matching a filter.
06722                     node->ref();
06723                     NodeImpl *parent = node->parent();
06724                     if( parent )
06725                     {
06726                         int exception = 0;
06727                         parent->removeChild(node, exception);
06728                     }
06729                     node->deref();
06730                 }
06731             }
06732         }
06733     }
06734 }
06735 
06736 void KHTMLPart::selectAll()
06737 {
06738   if (!d->m_doc) return;
06739 
06740   NodeImpl *first;
06741   if (d->m_doc->isHTMLDocument())
06742     first = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
06743   else
06744     first = d->m_doc;
06745   NodeImpl *next;
06746 
06747   // Look for first text/cdata node that has a renderer,
06748   // or first childless replaced element
06749   while ( first && !(first->renderer()
06750     && ((first->nodeType() == Node::TEXT_NODE || first->nodeType() == Node::CDATA_SECTION_NODE)
06751         || (first->renderer()->isReplaced() && !first->renderer()->firstChild()))))
06752   {
06753     next = first->firstChild();
06754     if ( !next ) next = first->nextSibling();
06755     while( first && !next )
06756     {
06757       first = first->parentNode();
06758       if ( first )
06759         next = first->nextSibling();
06760     }
06761     first = next;
06762   }
06763 
06764   NodeImpl *last;
06765   if (d->m_doc->isHTMLDocument())
06766     last = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
06767   else
06768     last = d->m_doc;
06769   // Look for last text/cdata node that has a renderer,
06770   // or last childless replaced element
06771   // ### Instead of changing this loop, use findLastSelectableNode
06772   // in render_table.cpp (LS)
06773   while ( last && !(last->renderer()
06774     && ((last->nodeType() == Node::TEXT_NODE || last->nodeType() == Node::CDATA_SECTION_NODE)
06775         || (last->renderer()->isReplaced() && !last->renderer()->lastChild()))))
06776   {
06777     next = last->lastChild();
06778     if ( !next ) next = last->previousSibling();
06779     while ( last && !next )
06780     {
06781       last = last->parentNode();
06782       if ( last )
06783         next = last->previousSibling();
06784     }
06785     last = next;
06786   }
06787 
06788   if ( !first || !last )
06789     return;
06790   Q_ASSERT(first->renderer());
06791   Q_ASSERT(last->renderer());
06792   d->m_selectionStart = first;
06793   d->m_startOffset = 0;
06794   d->m_selectionEnd = last;
06795   d->m_endOffset = last->nodeValue().length();
06796   d->m_startBeforeEnd = true;
06797 
06798   d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
06799                           d->m_selectionEnd.handle(), d->m_endOffset );
06800 
06801   emitSelectionChanged();
06802 }
06803 
06804 bool KHTMLPart::checkLinkSecurity(const KURL &linkURL,const QString &message, const QString &button)
06805 {
06806   bool linkAllowed = true;
06807 
06808   if ( d->m_doc )
06809     linkAllowed = kapp && kapp->authorizeURLAction("redirect", url(), linkURL);
06810 
06811   if ( !linkAllowed ) {
06812     khtml::Tokenizer *tokenizer = d->m_doc->tokenizer();
06813     if (tokenizer)
06814       tokenizer->setOnHold(true);
06815 
06816     int response = KMessageBox::Cancel;
06817     if (!message.isEmpty())
06818     {
06819         response = KMessageBox::warningContinueCancel( 0,
06820                                message.arg(linkURL.htmlURL()),
06821                                i18n( "Security Warning" ),
06822                                button);
06823     }
06824     else
06825     {
06826         KMessageBox::error( 0,
06827                 i18n( "<qt>Access by untrusted page to<BR><B>%1</B><BR> denied.").arg(linkURL.htmlURL()),
06828                 i18n( "Security Alert" ));
06829     }
06830 
06831     if (tokenizer)
06832        tokenizer->setOnHold(false);
06833     return (response==KMessageBox::Continue);
06834   }
06835   return true;
06836 }
06837 
06838 void KHTMLPart::slotPartRemoved( KParts::Part *part )
06839 {
06840 //    kdDebug(6050) << "KHTMLPart::slotPartRemoved " << part << endl;
06841     if ( part == d->m_activeFrame )
06842     {
06843         d->m_activeFrame = 0L;
06844         if ( !part->inherits( "KHTMLPart" ) )
06845         {
06846             if (factory()) {
06847                 factory()->removeClient( part );
06848             }
06849             if (childClients()->containsRef(part)) {
06850                 removeChildClient( part );
06851             }
06852         }
06853     }
06854 }
06855 
06856 void KHTMLPart::slotActiveFrameChanged( KParts::Part *part )
06857 {
06858 //    kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged this=" << this << "part=" << part << endl;
06859     if ( part == this )
06860     {
06861         kdError(6050) << "strange error! we activated ourselves" << endl;
06862         assert( false );
06863         return;
06864     }
06865 //    kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged d->m_activeFrame=" << d->m_activeFrame << endl;
06866     if ( d->m_activeFrame && d->m_activeFrame->widget() && d->m_activeFrame->widget()->inherits( "QFrame" ) )
06867     {
06868         QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() );
06869         if (frame->frameStyle() != QFrame::NoFrame)
06870         {
06871            frame->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken);
06872            frame->repaint();
06873         }
06874     }
06875 
06876     if( d->m_activeFrame && !d->m_activeFrame->inherits( "KHTMLPart" ) )
06877     {
06878         if (factory()) {
06879             factory()->removeClient( d->m_activeFrame );
06880         }
06881         removeChildClient( d->m_activeFrame );
06882     }
06883     if( part && !part->inherits( "KHTMLPart" ) )
06884     {
06885         if (factory()) {
06886             factory()->addClient( part );
06887         }
06888         insertChildClient( part );
06889     }
06890 
06891 
06892     d->m_activeFrame = part;
06893 
06894     if ( d->m_activeFrame && d->m_activeFrame->widget()->inherits( "QFrame" ) )
06895     {
06896         QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() );
06897         if (frame->frameStyle() != QFrame::NoFrame)
06898         {
06899            frame->setFrameStyle( QFrame::StyledPanel | QFrame::Plain);
06900            frame->repaint();
06901         }
06902         kdDebug(6050) << "new active frame " << d->m_activeFrame << endl;
06903     }
06904 
06905     updateActions();
06906 
06907     // (note: childObject returns 0 if the argument is 0)
06908     d->m_extension->setExtensionProxy( KParts::BrowserExtension::childObject( d->m_activeFrame ) );
06909 }
06910 
06911 void KHTMLPart::setActiveNode(const DOM::Node &node)
06912 {
06913     if (!d->m_doc || !d->m_view)
06914         return;
06915 
06916     // Set the document's active node
06917     d->m_doc->setFocusNode(node.handle());
06918 
06919     // Scroll the view if necessary to ensure that the new focus node is visible
06920     QRect rect  = node.handle()->getRect();
06921     d->m_view->ensureVisible(rect.right(), rect.bottom());
06922     d->m_view->ensureVisible(rect.left(), rect.top());
06923 }
06924 
06925 DOM::Node KHTMLPart::activeNode() const
06926 {
06927     return DOM::Node(d->m_doc?d->m_doc->focusNode():0);
06928 }
06929 
06930 DOM::EventListener *KHTMLPart::createHTMLEventListener( QString code, QString name, NodeImpl* node )
06931 {
06932   KJSProxy *proxy = jScript();
06933 
06934   if (!proxy)
06935     return 0;
06936 
06937   return proxy->createHTMLEventHandler( m_url.url(), name, code, node );
06938 }
06939 
06940 KHTMLPart *KHTMLPart::opener()
06941 {
06942     return d->m_opener;
06943 }
06944 
06945 void KHTMLPart::setOpener(KHTMLPart *_opener)
06946 {
06947     d->m_opener = _opener;
06948 }
06949 
06950 bool KHTMLPart::openedByJS()
06951 {
06952     return d->m_openedByJS;
06953 }
06954 
06955 void KHTMLPart::setOpenedByJS(bool _openedByJS)
06956 {
06957     d->m_openedByJS = _openedByJS;
06958 }
06959 
06960 void KHTMLPart::preloadStyleSheet(const QString &url, const QString &stylesheet)
06961 {
06962     khtml::Cache::preloadStyleSheet(url, stylesheet);
06963 }
06964 
06965 void KHTMLPart::preloadScript(const QString &url, const QString &script)
06966 {
06967     khtml::Cache::preloadScript(url, script);
06968 }
06969 
06970 QCString KHTMLPart::dcopObjectId() const
06971 {
06972   QCString id;
06973   id.sprintf("html-widget%d", d->m_dcop_counter);
06974   return id;
06975 }
06976 
06977 long KHTMLPart::cacheId() const
06978 {
06979   return d->m_cacheId;
06980 }
06981 
06982 bool KHTMLPart::restored() const
06983 {
06984   return d->m_restored;
06985 }
06986 
06987 bool KHTMLPart::pluginPageQuestionAsked(const QString& mimetype) const
06988 {
06989   // parentPart() should be const!
06990   KHTMLPart* parent = const_cast<KHTMLPart *>(this)->parentPart();
06991   if ( parent )
06992     return parent->pluginPageQuestionAsked(mimetype);
06993 
06994   return d->m_pluginPageQuestionAsked.contains(mimetype);
06995 }
06996 
06997 void KHTMLPart::setPluginPageQuestionAsked(const QString& mimetype)
06998 {
06999   if ( parentPart() )
07000     parentPart()->setPluginPageQuestionAsked(mimetype);
07001 
07002   d->m_pluginPageQuestionAsked.append(mimetype);
07003 }
07004 
07005 void KHTMLPart::slotAutomaticDetectionLanguage( int _id )
07006 {
07007   d->m_automaticDetection->setItemChecked( _id, true );
07008 
07009   switch ( _id ) {
07010     case 0 :
07011       d->m_autoDetectLanguage = khtml::Decoder::SemiautomaticDetection;
07012       break;
07013     case 1 :
07014       d->m_autoDetectLanguage = khtml::Decoder::Arabic;
07015       break;
07016     case 2 :
07017       d->m_autoDetectLanguage = khtml::Decoder::Baltic;
07018       break;
07019     case 3 :
07020       d->m_autoDetectLanguage = khtml::Decoder::CentralEuropean;
07021       break;
07022     case 4 :
07023       d->m_autoDetectLanguage = khtml::Decoder::Chinese;
07024       break;
07025     case 5 :
07026       d->m_autoDetectLanguage = khtml::Decoder::Greek;
07027       break;
07028     case 6 :
07029       d->m_autoDetectLanguage = khtml::Decoder::Hebrew;
07030       break;
07031     case 7 :
07032       d->m_autoDetectLanguage = khtml::Decoder::Japanese;
07033       break;
07034     case 8 :
07035       d->m_autoDetectLanguage = khtml::Decoder::Korean;
07036       break;
07037     case 9 :
07038       d->m_autoDetectLanguage = khtml::Decoder::Russian;
07039       break;
07040     case 10 :
07041       d->m_autoDetectLanguage = khtml::Decoder::Thai;
07042       break;
07043     case 11 :
07044       d->m_autoDetectLanguage = khtml::Decoder::Turkish;
07045       break;
07046     case 12 :
07047       d->m_autoDetectLanguage = khtml::Decoder::Ukrainian;
07048       break;
07049     case 13 :
07050       d->m_autoDetectLanguage = khtml::Decoder::Unicode;
07051       break;
07052     case 14 :
07053       d->m_autoDetectLanguage = khtml::Decoder::WesternEuropean;
07054       break;
07055     default :
07056       d->m_autoDetectLanguage = khtml::Decoder::SemiautomaticDetection;
07057       break;
07058   }
07059 
07060   for ( int i = 0; i <= 14; ++i ) {
07061     if ( i != _id )
07062       d->m_automaticDetection->setItemChecked( i, false );
07063   }
07064 
07065   d->m_paSetEncoding->popupMenu()->setItemChecked( 0, true );
07066 
07067   setEncoding( QString::null, false );
07068 
07069   if( d->m_manualDetection )
07070     d->m_manualDetection->setCurrentItem( -1 );
07071   d->m_paSetEncoding->popupMenu()->setItemChecked( d->m_paSetEncoding->popupMenu()->idAt( 2 ), false );
07072 }
07073 
07074 khtml::Decoder *KHTMLPart::createDecoder()
07075 {
07076     khtml::Decoder *dec = new khtml::Decoder();
07077     if( !d->m_encoding.isNull() )
07078         dec->setEncoding( d->m_encoding.latin1(),
07079             d->m_haveEncoding ? khtml::Decoder::UserChosenEncoding : khtml::Decoder::EncodingFromHTTPHeader);
07080     else {
07081         // Inherit the default encoding from the parent frame if there is one.
07082         const char *defaultEncoding = (parentPart() && parentPart()->d->m_decoder)
07083             ? parentPart()->d->m_decoder->encoding() : settings()->encoding().latin1();
07084         dec->setEncoding(defaultEncoding, khtml::Decoder::DefaultEncoding);
07085     }
07086 #ifdef APPLE_CHANGES
07087     if (d->m_doc)
07088         d->m_doc->setDecoder(d->m_decoder);
07089 #endif
07090     dec->setAutoDetectLanguage( d->m_autoDetectLanguage );
07091     return dec;
07092 }
07093 
07094 void KHTMLPart::emitCaretPositionChanged(const DOM::Node &node, long offset) {
07095   emit caretPositionChanged(node, offset);
07096 }
07097 
07098 void KHTMLPart::restoreScrollPosition()
07099 {
07100   KParts::URLArgs args = d->m_extension->urlArgs();
07101 
07102   if ( m_url.hasRef() && !d->m_restoreScrollPosition && !args.reload) {
07103     if ( !d->m_doc || !d->m_doc->parsing() )
07104       disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
07105     if ( !gotoAnchor(m_url.encodedHtmlRef()) )
07106       gotoAnchor(m_url.htmlRef());
07107     return;
07108   }
07109 
07110   // Check whether the viewport has become large enough to encompass the stored
07111   // offsets. If the document has been fully loaded, force the new coordinates,
07112   // even if the canvas is too short (can happen when user resizes the window
07113   // during loading).
07114   if (d->m_view->contentsHeight() - d->m_view->visibleHeight() >= args.yOffset
07115       || d->m_bComplete) {
07116     d->m_view->setContentsPos(args.xOffset, args.yOffset);
07117     disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
07118   }
07119 }
07120 
07121 
07122 void KHTMLPart::openWallet(DOM::HTMLFormElementImpl *form)
07123 {
07124 #ifndef KHTML_NO_WALLET
07125   KHTMLPart *p;
07126 
07127   for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
07128   }
07129 
07130   if (p) {
07131     p->openWallet(form);
07132     return;
07133   }
07134 
07135   if (onlyLocalReferences()) { // avoid triggering on local apps, thumbnails
07136     return;
07137   }
07138 
07139   if (d->m_wallet) {
07140     if (d->m_bWalletOpened) {
07141       if (d->m_wallet->isOpen()) {
07142         form->walletOpened(d->m_wallet);
07143         return;
07144       }
07145       d->m_wallet->deleteLater();
07146       d->m_wallet = 0L;
07147       d->m_bWalletOpened = false;
07148     }
07149   }
07150 
07151   if (!d->m_wq) {
07152     KWallet::Wallet *wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0, KWallet::Wallet::Asynchronous);
07153     d->m_wq = new KHTMLWalletQueue(this);
07154     d->m_wq->wallet = wallet;
07155     connect(wallet, SIGNAL(walletOpened(bool)), d->m_wq, SLOT(walletOpened(bool)));
07156     connect(d->m_wq, SIGNAL(walletOpened(KWallet::Wallet*)), this, SLOT(walletOpened(KWallet::Wallet*)));
07157   }
07158   assert(form);
07159   d->m_wq->callers.append(KHTMLWalletQueue::Caller(form, form->getDocument()));
07160 #endif // KHTML_NO_WALLET
07161 }
07162 
07163 
07164 void KHTMLPart::saveToWallet(const QString& key, const QMap<QString,QString>& data)
07165 {
07166 #ifndef KHTML_NO_WALLET
07167   KHTMLPart *p;
07168 
07169   for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
07170   }
07171 
07172   if (p) {
07173     p->saveToWallet(key, data);
07174     return;
07175   }
07176 
07177   if (d->m_wallet) {
07178     if (d->m_bWalletOpened) {
07179       if (d->m_wallet->isOpen()) {
07180         if (!d->m_wallet->hasFolder(KWallet::Wallet::FormDataFolder())) {
07181           d->m_wallet->createFolder(KWallet::Wallet::FormDataFolder());
07182         }
07183         d->m_wallet->setFolder(KWallet::Wallet::FormDataFolder());
07184         d->m_wallet->writeMap(key, data);
07185         return;
07186       }
07187       d->m_wallet->deleteLater();
07188       d->m_wallet = 0L;
07189       d->m_bWalletOpened = false;
07190     }
07191   }
07192 
07193   if (!d->m_wq) {
07194     KWallet::Wallet *wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0, KWallet::Wallet::Asynchronous);
07195     d->m_wq = new KHTMLWalletQueue(this);
07196     d->m_wq->wallet = wallet;
07197     connect(wallet, SIGNAL(walletOpened(bool)), d->m_wq, SLOT(walletOpened(bool)));
07198     connect(d->m_wq, SIGNAL(walletOpened(KWallet::Wallet*)), this, SLOT(walletOpened(KWallet::Wallet*)));
07199   }
07200   d->m_wq->savers.append(qMakePair(key, data));
07201 #endif // KHTML_NO_WALLET
07202 }
07203 
07204 
07205 void KHTMLPart::dequeueWallet(DOM::HTMLFormElementImpl *form) {
07206 #ifndef KHTML_NO_WALLET
07207   KHTMLPart *p;
07208 
07209   for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
07210   }
07211 
07212   if (p) {
07213     p->dequeueWallet(form);
07214     return;
07215   }
07216 
07217   if (d->m_wq) {
07218     d->m_wq->callers.remove(KHTMLWalletQueue::Caller(form, form->getDocument()));
07219   }
07220 #endif // KHTML_NO_WALLET
07221 }
07222 
07223 
07224 void KHTMLPart::walletOpened(KWallet::Wallet *wallet) {
07225 #ifndef KHTML_NO_WALLET
07226   assert(!d->m_wallet);
07227   assert(d->m_wq);
07228 
07229   d->m_wq->deleteLater(); // safe?
07230   d->m_wq = 0L;
07231 
07232   if (!wallet) {
07233     d->m_bWalletOpened = false;
07234     return;
07235   }
07236 
07237   d->m_wallet = wallet;
07238   d->m_bWalletOpened = true;
07239   connect(d->m_wallet, SIGNAL(walletClosed()), SLOT(slotWalletClosed()));
07240 
07241   if (!d->m_statusBarWalletLabel) {
07242     d->m_statusBarWalletLabel = new KURLLabel(d->m_statusBarExtension->statusBar());
07243     d->m_statusBarWalletLabel->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small));
07244     d->m_statusBarWalletLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
07245     d->m_statusBarWalletLabel->setUseCursor(false);
07246     d->m_statusBarExtension->addStatusBarItem(d->m_statusBarWalletLabel, 0, false);
07247     d->m_statusBarWalletLabel->setPixmap(SmallIcon("wallet_open", instance()));
07248     connect(d->m_statusBarWalletLabel, SIGNAL(leftClickedURL()), SLOT(launchWalletManager()));
07249     connect(d->m_statusBarWalletLabel, SIGNAL(rightClickedURL()), SLOT(walletMenu()));
07250   } else {
07251     QToolTip::remove(d->m_statusBarWalletLabel);
07252   }
07253   QToolTip::add(d->m_statusBarWalletLabel, i18n("The wallet '%1' is open and being used for form data and passwords.").arg(KWallet::Wallet::NetworkWallet()));
07254 #endif // KHTML_NO_WALLET
07255 }
07256 
07257 
07258 KWallet::Wallet *KHTMLPart::wallet()
07259 {
07260 #ifndef KHTML_NO_WALLET
07261   KHTMLPart *p;
07262 
07263   for (p = parentPart(); p && p->parentPart(); p = p->parentPart())
07264     ;
07265 
07266   if (p)
07267     return p->wallet();
07268 
07269 #endif // KHTML_NO_WALLET
07270   return d->m_wallet;
07271 }
07272 
07273 
07274 void KHTMLPart::slotWalletClosed()
07275 {
07276 #ifndef KHTML_NO_WALLET
07277   if (d->m_wallet) {
07278     d->m_wallet->deleteLater();
07279     d->m_wallet = 0L;
07280   }
07281   d->m_bWalletOpened = false;
07282   if (d->m_statusBarWalletLabel) {
07283     d->m_statusBarExtension->removeStatusBarItem(d->m_statusBarWalletLabel);
07284     delete d->m_statusBarWalletLabel;
07285     d->m_statusBarWalletLabel = 0L;
07286   }
07287 #endif // KHTML_NO_WALLET
07288 }
07289 
07290 void KHTMLPart::launchWalletManager()
07291 {
07292 #ifndef KHTML_NO_WALLET
07293   if (!DCOPClient::mainClient()->isApplicationRegistered("kwalletmanager")) {
07294     KApplication::startServiceByDesktopName("kwalletmanager_show");
07295   } else {
07296     DCOPRef r("kwalletmanager", "kwalletmanager-mainwindow#1");
07297     r.send("show");
07298     r.send("raise");
07299   }
07300 #endif // KHTML_NO_WALLET
07301 }
07302 
07303 void KHTMLPart::walletMenu()
07304 {
07305 #ifndef KHTML_NO_WALLET
07306   KPopupMenu *m = new KPopupMenu(0L);
07307   m->insertItem(i18n("&Close Wallet"), this, SLOT(slotWalletClosed()));
07308   m->popup(QCursor::pos());
07309 #endif // KHTML_NO_WALLET
07310 }
07311 
07312 void KHTMLPart::slotToggleCaretMode()
07313 {
07314   setCaretMode(d->m_paToggleCaretMode->isChecked());
07315 }
07316 
07317 void KHTMLPart::setFormNotification(KHTMLPart::FormNotification fn) {
07318   d->m_formNotification = fn;
07319 }
07320 
07321 KHTMLPart::FormNotification KHTMLPart::formNotification() const {
07322   return d->m_formNotification;
07323 }
07324 
07325 KURL KHTMLPart::toplevelURL()
07326 {
07327   KHTMLPart* part = this;
07328   while (part->parentPart())
07329     part = part->parentPart();
07330 
07331   if (!part)
07332     return KURL();
07333 
07334   return part->url();
07335 }
07336 
07337 bool KHTMLPart::isModified() const
07338 {
07339   if ( !d->m_doc )
07340     return false;
07341 
07342   return d->m_doc->unsubmittedFormChanges();
07343 }
07344 
07345 void KHTMLPart::setDebugScript( bool enable )
07346 {
07347   unplugActionList( "debugScriptList" );
07348   if ( enable ) {
07349     if (!d->m_paDebugScript) {
07350       d->m_paDebugScript = new KAction( i18n( "JavaScript &Debugger" ), 0, this, SLOT( slotDebugScript() ), actionCollection(), "debugScript" );
07351     }
07352     d->m_paDebugScript->setEnabled( d->m_frame ? d->m_frame->m_jscript : 0L );
07353     QPtrList<KAction> lst;
07354     lst.append( d->m_paDebugScript );
07355     plugActionList( "debugScriptList", lst );
07356   }
07357   d->m_bJScriptDebugEnabled = enable;
07358 }
07359 
07360 void KHTMLPart::setSuppressedPopupIndicator( bool enable )
07361 {
07362     setSuppressedPopupIndicator( enable, 0 );
07363 }
07364 
07365 void KHTMLPart::setSuppressedPopupIndicator( bool enable, KHTMLPart *originPart )
07366 {
07367     if ( parentPart() ) {
07368         parentPart()->setSuppressedPopupIndicator( enable, originPart );
07369         return;
07370     }
07371 
07372     if ( enable && originPart ) {
07373         d->m_openableSuppressedPopups++;
07374         if ( d->m_suppressedPopupOriginParts.findIndex( originPart ) == -1 )
07375             d->m_suppressedPopupOriginParts.append( originPart );
07376     }
07377 
07378     if ( enable && !d->m_statusBarPopupLabel ) {
07379         d->m_statusBarPopupLabel = new KURLLabel( d->m_statusBarExtension->statusBar() );
07380         d->m_statusBarPopupLabel->setFixedHeight( instance()->iconLoader()->currentSize( KIcon::Small) );
07381         d->m_statusBarPopupLabel->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ));
07382         d->m_statusBarPopupLabel->setUseCursor( false );
07383         d->m_statusBarExtension->addStatusBarItem( d->m_statusBarPopupLabel, 0, false );
07384         d->m_statusBarPopupLabel->setPixmap( SmallIcon( "window_suppressed", instance() ) );
07385         QToolTip::add( d->m_statusBarPopupLabel, i18n("This page was prevented from opening a new window via JavaScript." ) );
07386 
07387         connect(d->m_statusBarPopupLabel, SIGNAL(leftClickedURL()), SLOT(suppressedPopupMenu()));
07388         if (d->m_settings->jsPopupBlockerPassivePopup()) {
07389             QPixmap px;
07390             px = MainBarIcon( "window_suppressed" );
07391             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);
07392         }
07393     } else if ( !enable && d->m_statusBarPopupLabel ) {
07394         QToolTip::remove( d->m_statusBarPopupLabel );
07395         d->m_statusBarExtension->removeStatusBarItem( d->m_statusBarPopupLabel );
07396         delete d->m_statusBarPopupLabel;
07397         d->m_statusBarPopupLabel = 0L;
07398     }
07399 }
07400 
07401 void KHTMLPart::suppressedPopupMenu() {
07402   KPopupMenu *m = new KPopupMenu(0L);
07403   m->setCheckable(true);
07404   if ( d->m_openableSuppressedPopups )
07405       m->insertItem(i18n("&Show Blocked Popup Window","Show %n Blocked Popup Windows", d->m_openableSuppressedPopups), this, SLOT(showSuppressedPopups()));
07406   m->insertItem(i18n("Show Blocked Window Passive Popup &Notification"), this, SLOT(togglePopupPassivePopup()),0,57);
07407   m->setItemChecked(57,d->m_settings->jsPopupBlockerPassivePopup());
07408   m->insertItem(i18n("&Configure JavaScript New Window Policies..."), this, SLOT(launchJSConfigDialog()));
07409   m->popup(QCursor::pos());
07410 }
07411 
07412 void KHTMLPart::togglePopupPassivePopup() {
07413   // Same hack as in disableJSErrorExtension()
07414   d->m_settings->setJSPopupBlockerPassivePopup( !d->m_settings->jsPopupBlockerPassivePopup() );
07415   DCOPClient::mainClient()->send("konqueror*", "KonquerorIface", "reparseConfiguration()", QByteArray());
07416 }
07417 
07418 void KHTMLPart::showSuppressedPopups() {
07419     for ( QValueListIterator<QGuardedPtr<KHTMLPart> > i = d->m_suppressedPopupOriginParts.begin();
07420           i != d->m_suppressedPopupOriginParts.end(); ++i ) {
07421       if (KHTMLPart* part = *i) {
07422         KJS::Window *w = KJS::Window::retrieveWindow( part );
07423         if (w) {
07424             w->showSuppressedWindows();
07425             w->forgetSuppressedWindows();
07426         }
07427       }
07428     }
07429     setSuppressedPopupIndicator( false );
07430     d->m_openableSuppressedPopups = 0;
07431     d->m_suppressedPopupOriginParts.clear();
07432 }
07433 
07434 // Extension to use for "view document source", "save as" etc.
07435 // Using the right extension can help the viewer get into the right mode (#40496)
07436 QString KHTMLPart::defaultExtension() const
07437 {
07438     if ( !d->m_doc )
07439         return ".html";
07440     if ( !d->m_doc->isHTMLDocument() )
07441         return ".xml";
07442     return d->m_doc->htmlMode() == DOM::DocumentImpl::XHtml ? ".xhtml" : ".html";
07443 }
07444 
07445 bool KHTMLPart::inProgress() const
07446 {
07447     if (d->m_runningScripts || (d->m_doc && d->m_doc->parsing()))
07448         return true;
07449 
07450     // Any frame that hasn't completed yet ?
07451     ConstFrameIt it = d->m_frames.begin();
07452     const ConstFrameIt end = d->m_frames.end();
07453     for (; it != end; ++it ) {
07454         if ((*it)->m_run || !(*it)->m_bCompleted)
07455         return true;
07456     }
07457 
07458     return d->m_submitForm || !d->m_redirectURL.isEmpty() || d->m_redirectionTimer.isActive() || d->m_job;
07459 }
07460 
07461 using namespace KParts;
07462 #include "khtml_part.moc"
07463 #include "khtmlpart_p.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys