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