• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KHTML

khtml_part.cpp

Go to the documentation of this file.
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 ? static_cast<khtml::RenderPart *>(d->m_frame->m_frame) : 0;
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       d->m_find->resetCounts();
03276       findTextNext( reverse );
03277     }
03278     else // really done
03279     {
03280       //kdDebug(6050) << "Finishing" << endl;
03281       //delete d->m_find;
03282       //d->m_find = 0L;
03283       initFindNode( false, options & KFindDialog::FindBackwards, false );
03284       d->m_find->resetCounts();
03285       slotClearSelection();
03286     }
03287     kdDebug() << "Dialog closed." << endl;
03288   }
03289 
03290   return res == KFind::Match;
03291 }
03292 
03293 void KHTMLPart::slotHighlight( const QString& /*text*/, int index, int length )
03294 {
03295   //kdDebug(6050) << "slotHighlight index=" << index << " length=" << length << endl;
03296   QValueList<KHTMLPartPrivate::StringPortion>::Iterator it = d->m_stringPortions.begin();
03297   const QValueList<KHTMLPartPrivate::StringPortion>::Iterator itEnd = d->m_stringPortions.end();
03298   QValueList<KHTMLPartPrivate::StringPortion>::Iterator prev = it;
03299   // We stop at the first portion whose index is 'greater than', and then use the previous one
03300   while ( it != itEnd && (*it).index <= index )
03301   {
03302     prev = it;
03303     ++it;
03304   }
03305   Q_ASSERT ( prev != itEnd );
03306   DOM::NodeImpl* node = (*prev).node;
03307   Q_ASSERT( node );
03308 
03309   d->m_selectionStart = node;
03310   d->m_startOffset = index - (*prev).index;
03311 
03312   khtml::RenderObject* obj = node->renderer();
03313   khtml::RenderTextArea *parent = 0L;
03314   khtml::RenderLineEdit *parentLine = 0L;
03315   bool renderLineText =false;
03316 
03317   QRect highlightedRect;
03318   bool renderAreaText =false;
03319   Q_ASSERT( obj );
03320   if ( obj )
03321   {
03322     int x = 0, y = 0;
03323     renderAreaText = (QCString(obj->parent()->renderName())== "RenderTextArea");
03324     renderLineText = (QCString(obj->renderName())== "RenderLineEdit");
03325 
03326 
03327     if( renderAreaText )
03328       parent= static_cast<khtml::RenderTextArea *>(obj->parent());
03329     if ( renderLineText )
03330       parentLine= static_cast<khtml::RenderLineEdit *>(obj);
03331     if ( !renderLineText )
03332       //if (static_cast<khtml::RenderText *>(node->renderer())
03333       //    ->posOfChar(d->m_startOffset, x, y))
03334       {
03335         int dummy;
03336         static_cast<khtml::RenderText *>(node->renderer())
03337           ->caretPos( d->m_startOffset, false, x, y, dummy, dummy ); // more precise than posOfChar
03338         //kdDebug(6050) << "topleft: " << x << "," << y << endl;
03339         if ( x != -1 || y != -1 )
03340         {
03341           int gox = d->m_view->contentsX();
03342           if (x+50 > d->m_view->contentsX() + d->m_view->visibleWidth())
03343               gox = x - d->m_view->visibleWidth() + 50;
03344           if (x-10 < d->m_view->contentsX())
03345               gox = x - d->m_view->visibleWidth() - 10;
03346           if (gox < 0) gox = 0;
03347           d->m_view->setContentsPos(gox, y-50);
03348           highlightedRect.setTopLeft( d->m_view->mapToGlobal(QPoint(x, y)) );
03349         }
03350       }
03351   }
03352   // Now look for end node
03353   it = prev; // no need to start from beginning again
03354   while ( it != itEnd && (*it).index < index + length )
03355   {
03356     prev = it;
03357     ++it;
03358   }
03359   Q_ASSERT ( prev != itEnd );
03360 
03361   d->m_selectionEnd = (*prev).node;
03362   d->m_endOffset = index + length - (*prev).index;
03363   d->m_startBeforeEnd = true;
03364 
03365   // if the selection is limited to a single link, that link gets focus
03366   if(d->m_selectionStart == d->m_selectionEnd)
03367   {
03368     bool isLink = false;
03369 
03370     // checks whether the node has a <A> parent
03371     DOM::NodeImpl *parent = d->m_selectionStart.handle();
03372     while ( parent )
03373     {
03374       if ( parent->nodeType() == Node::ELEMENT_NODE && parent->id() == ID_A )
03375       {
03376         isLink = true;
03377         break;
03378       }
03379       parent = parent->parentNode();
03380     }
03381 
03382     if(isLink == true)
03383     {
03384       d->m_doc->setFocusNode( parent );
03385     }
03386   }
03387 
03388 #if 0
03389   kdDebug(6050) << "slotHighlight: " << d->m_selectionStart.handle() << "," << d->m_startOffset << " - " <<
03390     d->m_selectionEnd.handle() << "," << d->m_endOffset << endl;
03391   it = d->m_stringPortions.begin();
03392   for ( ; it != d->m_stringPortions.end() ; ++it )
03393     kdDebug(6050) << "  StringPortion: from index=" << (*it).index << " -> node=" << (*it).node << endl;
03394 #endif
03395   if( renderAreaText )
03396   {
03397     if( parent )
03398       parent->highLightWord( length, d->m_endOffset-length );
03399   }
03400   else if ( renderLineText )
03401   {
03402     if( parentLine )
03403       parentLine->highLightWord( length, d->m_endOffset-length );
03404   }
03405   else
03406   {
03407     d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
03408                             d->m_selectionEnd.handle(), d->m_endOffset );
03409     if (d->m_selectionEnd.handle()->renderer() )
03410     {
03411       int x, y, height, dummy;
03412       static_cast<khtml::RenderText *>(d->m_selectionEnd.handle()->renderer())
03413           ->caretPos( d->m_endOffset, false, x, y, dummy, height ); // more precise than posOfChar
03414       //kdDebug(6050) << "bottomright: " << x << "," << y+height << endl;
03415       if ( x != -1 || y != -1 )
03416       {
03417         // if ( static_cast<khtml::RenderText *>(d->m_selectionEnd.handle()->renderer())
03418         //  ->posOfChar(d->m_endOffset-1, x, y))
03419         highlightedRect.setBottomRight( d->m_view->mapToGlobal( QPoint(x, y+height) ) );
03420       }
03421     }
03422   }
03423   emitSelectionChanged();
03424 
03425   // make the finddialog move away from the selected area
03426   if ( d->m_findDialog && !highlightedRect.isNull() )
03427   {
03428     highlightedRect.moveBy( -d->m_view->contentsX(), -d->m_view->contentsY() );
03429     //kdDebug(6050) << "avoiding " << highlightedRect << endl;
03430     KDialog::avoidArea( d->m_findDialog, highlightedRect );
03431   }
03432 }
03433 
03434 QString KHTMLPart::selectedTextAsHTML() const
03435 {
03436   if(!hasSelection()) {
03437     kdDebug() << "selectedTextAsHTML(): selection is not valid.  Returning empty selection" << endl;
03438     return QString::null;
03439   }
03440   if(d->m_startOffset < 0 || d->m_endOffset <0) {
03441     kdDebug() << "invalid values for end/startOffset " << d->m_startOffset << " " << d->m_endOffset << endl;
03442     return QString::null;
03443   }
03444   DOM::Range r = selection();
03445   if(r.isNull() || r.isDetached())
03446     return QString::null;
03447   int exceptioncode = 0; //ignore the result
03448   return r.handle()->toHTML(exceptioncode).string();
03449 }
03450 
03451 QString KHTMLPart::selectedText() const
03452 {
03453   bool hasNewLine = true;
03454   bool seenTDTag = false;
03455   QString text;
03456   DOM::Node n = d->m_selectionStart;
03457   while(!n.isNull()) {
03458       if(n.nodeType() == DOM::Node::TEXT_NODE && n.handle()->renderer()) {
03459         DOM::DOMStringImpl *dstr = static_cast<DOM::TextImpl*>(n.handle())->renderString();
03460         QString str(dstr->s, dstr->l);
03461     if(!str.isEmpty()) {
03462           if(seenTDTag) {
03463         text += "  ";
03464         seenTDTag = false;
03465       }
03466           hasNewLine = false;
03467           if(n == d->m_selectionStart && n == d->m_selectionEnd)
03468             text = str.mid(d->m_startOffset, d->m_endOffset - d->m_startOffset);
03469           else if(n == d->m_selectionStart)
03470             text = str.mid(d->m_startOffset);
03471           else if(n == d->m_selectionEnd)
03472             text += str.left(d->m_endOffset);
03473           else
03474             text += str;
03475     }
03476       }
03477       else {
03478         // This is our simple HTML -> ASCII transformation:
03479         unsigned short id = n.elementId();
03480         switch(id) {
03481       case ID_TEXTAREA:
03482         text += static_cast<HTMLTextAreaElementImpl*>(n.handle())->value().string();
03483         break;
03484       case ID_INPUT:
03485             if (static_cast<HTMLInputElementImpl*>(n.handle())->inputType() != HTMLInputElementImpl::PASSWORD)
03486           text += static_cast<HTMLInputElementImpl*>(n.handle())->value().string();
03487         break;
03488       case ID_SELECT:
03489         text += static_cast<HTMLSelectElementImpl*>(n.handle())->value().string();
03490         break;
03491           case ID_BR:
03492             text += "\n";
03493             hasNewLine = true;
03494             break;
03495           case ID_IMG:
03496         text += static_cast<HTMLImageElementImpl*>(n.handle())->altText().string();
03497         break;
03498           case ID_TD:
03499         break;
03500           case ID_TH:
03501           case ID_HR:
03502           case ID_OL:
03503           case ID_UL:
03504           case ID_LI:
03505           case ID_DD:
03506           case ID_DL:
03507           case ID_DT:
03508           case ID_PRE:
03509           case ID_BLOCKQUOTE:
03510           case ID_DIV:
03511             if (!hasNewLine)
03512                text += "\n";
03513             hasNewLine = true;
03514             break;
03515           case ID_P:
03516           case ID_TR:
03517           case ID_H1:
03518           case ID_H2:
03519           case ID_H3:
03520           case ID_H4:
03521           case ID_H5:
03522           case ID_H6:
03523             if (!hasNewLine)
03524                text += "\n";
03525 //            text += "\n";
03526             hasNewLine = true;
03527             break;
03528         }
03529       }
03530       if(n == d->m_selectionEnd) break;
03531       DOM::Node next = n.firstChild();
03532       if(next.isNull()) next = n.nextSibling();
03533       while( next.isNull() && !n.parentNode().isNull() ) {
03534         n = n.parentNode();
03535         next = n.nextSibling();
03536         unsigned short id = n.elementId();
03537         switch(id) {
03538           case ID_TD:
03539         seenTDTag = true; //Add two spaces after a td if then followed by text.
03540         break;
03541           case ID_TH:
03542           case ID_HR:
03543           case ID_OL:
03544           case ID_UL:
03545           case ID_LI:
03546           case ID_DD:
03547           case ID_DL:
03548           case ID_DT:
03549           case ID_PRE:
03550           case ID_BLOCKQUOTE:
03551           case ID_DIV:
03552         seenTDTag = false;
03553             if (!hasNewLine)
03554                text += "\n";
03555             hasNewLine = true;
03556             break;
03557           case ID_P:
03558           case ID_TR:
03559           case ID_H1:
03560           case ID_H2:
03561           case ID_H3:
03562           case ID_H4:
03563           case ID_H5:
03564           case ID_H6:
03565             if (!hasNewLine)
03566                text += "\n";
03567 //            text += "\n";
03568             hasNewLine = true;
03569             break;
03570         }
03571       }
03572 
03573       n = next;
03574     }
03575 
03576     if(text.isEmpty())
03577         return QString::null;
03578 
03579     int start = 0;
03580     int end = text.length();
03581 
03582     // Strip leading LFs
03583     while ((start < end) && (text[start] == '\n'))
03584        ++start;
03585 
03586     // Strip excessive trailing LFs
03587     while ((start < (end-1)) && (text[end-1] == '\n') && (text[end-2] == '\n'))
03588        --end;
03589 
03590     return text.mid(start, end-start);
03591 }
03592 
03593 bool KHTMLPart::hasSelection() const
03594 {
03595   if ( d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() )
03596       return false;
03597   if ( d->m_selectionStart == d->m_selectionEnd &&
03598        d->m_startOffset == d->m_endOffset )
03599       return false; // empty
03600   return true;
03601 }
03602 
03603 DOM::Range KHTMLPart::selection() const
03604 {
03605     if( d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() )
03606         return DOM::Range();
03607     DOM::Range r = document().createRange();
03608     RangeImpl *rng = r.handle();
03609     int exception = 0;
03610     NodeImpl *n = d->m_selectionStart.handle();
03611     if(!n->parentNode() ||
03612        !n->renderer() ||
03613        (!n->renderer()->isReplaced() && !n->renderer()->isBR())) {
03614         rng->setStart( n, d->m_startOffset, exception );
03615     if(exception) {
03616         kdDebug(6000) << "1 -selection() threw the exception " << exception << ".  Returning empty range." << endl;
03617         return DOM::Range();
03618     }
03619     } else {
03620         int o_start = 0;
03621         while ((n = n->previousSibling()))
03622             o_start++;
03623     rng->setStart( d->m_selectionStart.parentNode().handle(), o_start + d->m_startOffset, exception );
03624     if(exception) {
03625         kdDebug(6000) << "2 - selection() threw the exception " << exception << ".  Returning empty range." << endl;
03626         return DOM::Range();
03627     }
03628 
03629     }
03630 
03631     n = d->m_selectionEnd.handle();
03632     if(!n->parentNode() ||
03633        !n->renderer() ||
03634        (!n->renderer()->isReplaced() && !n->renderer()->isBR())) {
03635 
03636     rng->setEnd( n, d->m_endOffset, exception );
03637     if(exception) {
03638         kdDebug(6000) << "3 - selection() threw the exception " << exception << ".  Returning empty range." << endl;
03639         return DOM::Range();
03640     }
03641 
03642     } else {
03643         int o_end = 0;
03644         while ((n = n->previousSibling()))
03645             o_end++;
03646     rng->setEnd( d->m_selectionEnd.parentNode().handle(), o_end + d->m_endOffset, exception);
03647     if(exception) {
03648         kdDebug(6000) << "4 - selection() threw the exception " << exception << ".  Returning empty range." << endl;
03649         return DOM::Range();
03650     }
03651 
03652     }
03653 
03654     return r;
03655 }
03656 
03657 void KHTMLPart::selection(DOM::Node &s, long &so, DOM::Node &e, long &eo) const
03658 {
03659     s = d->m_selectionStart;
03660     so = d->m_startOffset;
03661     e = d->m_selectionEnd;
03662     eo = d->m_endOffset;
03663 }
03664 
03665 void KHTMLPart::setSelection( const DOM::Range &r )
03666 {
03667     // Quick-fix: a collapsed range shouldn't select the whole node.
03668     // The real problem is in RenderCanvas::setSelection though (when index==0 the whole node is selected).
03669     if ( r.collapsed() )
03670         slotClearSelection();
03671     else {
03672         d->m_selectionStart = r.startContainer();
03673         d->m_startOffset = r.startOffset();
03674         d->m_selectionEnd = r.endContainer();
03675         d->m_endOffset = r.endOffset();
03676         d->m_doc->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
03677                                d->m_selectionEnd.handle(),d->m_endOffset);
03678 #ifndef KHTML_NO_CARET
03679         bool v = d->m_view->placeCaret();
03680         emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
03681 #endif
03682     }
03683 }
03684 
03685 void KHTMLPart::slotClearSelection()
03686 {
03687     bool hadSelection = hasSelection();
03688 #ifndef KHTML_NO_CARET
03689     //kdDebug(6000) << "d->m_selectionStart " << d->m_selectionStart.handle()
03690     //      << " d->m_selectionEnd " << d->m_selectionEnd.handle() << endl;
03691     // nothing, leave selection parameters as is
03692 #else
03693     d->m_selectionStart = 0;
03694     d->m_startOffset = 0;
03695     d->m_selectionEnd = 0;
03696     d->m_endOffset = 0;
03697 #endif
03698     if ( d->m_doc ) d->m_doc->clearSelection();
03699     if ( hadSelection )
03700       emitSelectionChanged();
03701 #ifndef KHTML_NO_CARET
03702     bool v = d->m_view->placeCaret();
03703     emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
03704 #endif
03705 }
03706 
03707 void KHTMLPart::resetHoverText()
03708 {
03709    if( !d->m_overURL.isEmpty() ) // Only if we were showing a link
03710    {
03711      d->m_overURL = d->m_overURLTarget = QString::null;
03712      emit onURL( QString::null );
03713      // revert to default statusbar text
03714      setStatusBarText(QString::null, BarHoverText);
03715      emit d->m_extension->mouseOverInfo(0);
03716   }
03717 }
03718 
03719 void KHTMLPart::overURL( const QString &url, const QString &target, bool /*shiftPressed*/ )
03720 {
03721   KURL u = completeURL(url);
03722 
03723   // special case for <a href="">
03724   if ( url.isEmpty() )
03725     u.setFileName( url );
03726 
03727   emit onURL( url );
03728 
03729   if ( url.isEmpty() ) {
03730     setStatusBarText(u.htmlURL(), BarHoverText);
03731     return;
03732   }
03733 
03734   if (url.find( QString::fromLatin1( "javascript:" ),0, false ) == 0 ) {
03735     QString jscode = KURL::decode_string( url.mid( url.find( "javascript:", 0, false ) ) );
03736     jscode = KStringHandler::rsqueeze( jscode, 80 ); // truncate if too long
03737     if (url.startsWith("javascript:window.open"))
03738       jscode += i18n(" (In new window)");
03739     setStatusBarText( QStyleSheet::escape( jscode ), BarHoverText );
03740     return;
03741   }
03742 
03743   KFileItem item(u, QString::null, KFileItem::Unknown);
03744   emit d->m_extension->mouseOverInfo(&item);
03745 
03746   QString com;
03747 
03748   KMimeType::Ptr typ = KMimeType::findByURL( u );
03749 
03750   if ( typ )
03751     com = typ->comment( u, false );
03752 
03753   if ( !u.isValid() ) {
03754     setStatusBarText(u.htmlURL(), BarHoverText);
03755     return;
03756   }
03757 
03758   if ( u.isLocalFile() )
03759   {
03760     // TODO : use KIO::stat() and create a KFileItem out of its result,
03761     // to use KFileItem::statusBarText()
03762     QCString path = QFile::encodeName( u.path() );
03763 
03764     struct stat buff;
03765     bool ok = !stat( path.data(), &buff );
03766 
03767     struct stat lbuff;
03768     if (ok) ok = !lstat( path.data(), &lbuff );
03769 
03770     QString text = u.htmlURL();
03771     QString text2 = text;
03772 
03773     if (ok && S_ISLNK( lbuff.st_mode ) )
03774     {
03775       QString tmp;
03776       if ( com.isNull() )
03777         tmp = i18n( "Symbolic Link");
03778       else
03779         tmp = i18n("%1 (Link)").arg(com);
03780       char buff_two[1024];
03781       text += " -> ";
03782       int n = readlink ( path.data(), buff_two, 1022);
03783       if (n == -1)
03784       {
03785         text2 += "  ";
03786         text2 += tmp;
03787         setStatusBarText(text2, BarHoverText);
03788         return;
03789       }
03790       buff_two[n] = 0;
03791 
03792       text += buff_two;
03793       text += "  ";
03794       text += tmp;
03795     }
03796     else if ( ok && S_ISREG( buff.st_mode ) )
03797     {
03798       if (buff.st_size < 1024)
03799         text = i18n("%2 (%1 bytes)").arg((long) buff.st_size).arg(text2); // always put the URL last, in case it contains '%'
03800       else
03801       {
03802         float d = (float) buff.st_size/1024.0;
03803         text = i18n("%2 (%1 K)").arg(KGlobal::locale()->formatNumber(d, 2)).arg(text2); // was %.2f
03804       }
03805       text += "  ";
03806       text += com;
03807     }
03808     else if ( ok && S_ISDIR( buff.st_mode ) )
03809     {
03810       text += "  ";
03811       text += com;
03812     }
03813     else
03814     {
03815       text += "  ";
03816       text += com;
03817     }
03818     setStatusBarText(text, BarHoverText);
03819   }
03820   else
03821   {
03822     QString extra;
03823     if (target.lower() == "_blank")
03824     {
03825       extra = i18n(" (In new window)");
03826     }
03827     else if (!target.isEmpty() &&
03828              (target.lower() != "_top") &&
03829              (target.lower() != "_self") &&
03830              (target.lower() != "_parent"))
03831     {
03832       KHTMLPart *p = this;
03833       while (p->parentPart())
03834           p = p->parentPart();
03835       if (!p->frameExists(target))
03836         extra = i18n(" (In new window)");
03837       else
03838         extra = i18n(" (In other frame)");
03839     }
03840 
03841     if (u.protocol() == QString::fromLatin1("mailto")) {
03842       QString mailtoMsg /* = QString::fromLatin1("<img src=%1>").arg(locate("icon", QString::fromLatin1("locolor/16x16/actions/mail_send.png")))*/;
03843       mailtoMsg += i18n("Email to: ") + KURL::decode_string(u.path());
03844       QStringList queries = QStringList::split('&', u.query().mid(1));
03845       QStringList::Iterator it = queries.begin();
03846       const QStringList::Iterator itEnd = queries.end();
03847       for (; it != itEnd; ++it)
03848         if ((*it).startsWith(QString::fromLatin1("subject=")))
03849           mailtoMsg += i18n(" - Subject: ") + KURL::decode_string((*it).mid(8));
03850         else if ((*it).startsWith(QString::fromLatin1("cc=")))
03851           mailtoMsg += i18n(" - CC: ") + KURL::decode_string((*it).mid(3));
03852         else if ((*it).startsWith(QString::fromLatin1("bcc=")))
03853           mailtoMsg += i18n(" - BCC: ") + KURL::decode_string((*it).mid(4));
03854       mailtoMsg = QStyleSheet::escape(mailtoMsg);
03855       mailtoMsg.replace(QRegExp("([\n\r\t]|[ ]{10})"), QString::null);
03856       setStatusBarText("<qt>"+mailtoMsg, BarHoverText);
03857       return;
03858     }
03859    // Is this check necessary at all? (Frerich)
03860 #if 0
03861     else if (u.protocol() == QString::fromLatin1("http")) {
03862         DOM::Node hrefNode = nodeUnderMouse().parentNode();
03863         while (hrefNode.nodeName().string() != QString::fromLatin1("A") && !hrefNode.isNull())
03864           hrefNode = hrefNode.parentNode();
03865 
03866         if (!hrefNode.isNull()) {
03867           DOM::Node hreflangNode = hrefNode.attributes().getNamedItem("HREFLANG");
03868           if (!hreflangNode.isNull()) {
03869             QString countryCode = hreflangNode.nodeValue().string().lower();
03870             // Map the language code to an appropriate country code.
03871             if (countryCode == QString::fromLatin1("en"))
03872               countryCode = QString::fromLatin1("gb");
03873             QString flagImg = QString::fromLatin1("<img src=%1>").arg(
03874                 locate("locale", QString::fromLatin1("l10n/")
03875                 + countryCode
03876                 + QString::fromLatin1("/flag.png")));
03877             emit setStatusBarText(flagImg + u.prettyURL() + extra);
03878           }
03879         }
03880       }
03881 #endif
03882     setStatusBarText(u.htmlURL() + extra, BarHoverText);
03883   }
03884 }
03885 
03886 //
03887 // This executes in the active part on a click or other url selection action in
03888 // that active part.
03889 //
03890 void KHTMLPart::urlSelected( const QString &url, int button, int state, const QString &_target, KParts::URLArgs args )
03891 {
03892   // The member var is so that slotRedirection still calls the virtual urlSelected
03893   // but is able to know if is opened a url. KDE4: just make urlSelected return a bool
03894   // and move the urlSelectedIntern code back here.
03895   d->m_urlSelectedOpenedURL = urlSelectedIntern( url, button, state, _target, args );
03896 }
03897 
03898 // Return value: true if an url was opened, false if not (e.g. error, or jumping to anchor)
03899 bool KHTMLPart::urlSelectedIntern( const QString &url, int button, int state, const QString &_target, KParts::URLArgs args )
03900 {
03901   bool hasTarget = false;
03902 
03903   QString target = _target;
03904   if ( target.isEmpty() && d->m_doc )
03905     target = d->m_doc->baseTarget();
03906   if ( !target.isEmpty() )
03907       hasTarget = true;
03908 
03909   if ( url.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
03910   {
03911     crossFrameExecuteScript( target, KURL::decode_string( url.mid( 11 ) ) );
03912     return false;
03913   }
03914 
03915   KURL cURL = completeURL(url);
03916   // special case for <a href="">  (IE removes filename, mozilla doesn't)
03917   if ( url.isEmpty() )
03918     cURL.setFileName( url ); // removes filename
03919 
03920   if ( !cURL.isValid() )
03921     // ### ERROR HANDLING
03922     return false;
03923 
03924   kdDebug(6050) << this << " urlSelected: complete URL:" << cURL.url() << " target=" << target << endl;
03925 
03926   if ( state & ControlButton )
03927   {
03928     args.setNewTab(true);
03929     emit d->m_extension->createNewWindow( cURL, args );
03930     return true;
03931   }
03932 
03933   if ( button == LeftButton && ( state & ShiftButton ) )
03934   {
03935     KIO::MetaData metaData;
03936     metaData["referrer"] = d->m_referrer;
03937     KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), cURL, metaData );
03938     return false;
03939   }
03940 
03941   if (!checkLinkSecurity(cURL,
03942              i18n( "<qt>This untrusted page links to<BR><B>%1</B>.<BR>Do you want to follow the link?" ),
03943              i18n( "Follow" )))
03944     return false;
03945 
03946   args.frameName = target;
03947 
03948   args.metaData().insert("main_frame_request",
03949                          parentPart() == 0 ? "TRUE":"FALSE");
03950   args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
03951   args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
03952   args.metaData().insert("PropagateHttpHeader", "true");
03953   args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
03954   args.metaData().insert("ssl_activate_warnings", "TRUE");
03955 
03956   if ( hasTarget && target != "_self" && target != "_top" && target != "_blank" && target != "_parent" )
03957   {
03958     // unknown frame names should open in a new window.
03959     khtml::ChildFrame *frame = recursiveFrameRequest( this, cURL, args, false );
03960     if ( frame )
03961     {
03962       args.metaData()["referrer"] = d->m_referrer;
03963       requestObject( frame, cURL, args );
03964       return true;
03965     }
03966   }
03967 
03968   if (!d->m_referrer.isEmpty() && !args.metaData().contains("referrer"))
03969     args.metaData()["referrer"] = d->m_referrer;
03970 
03971 
03972   if ( button == NoButton && (state & ShiftButton) && (state & ControlButton) )
03973   {
03974     emit d->m_extension->createNewWindow( cURL, args );
03975     return true;
03976   }
03977 
03978   if ( state & ShiftButton)
03979   {
03980     KParts::WindowArgs winArgs;
03981     winArgs.lowerWindow = true;
03982     KParts::ReadOnlyPart *newPart = 0;
03983     emit d->m_extension->createNewWindow( cURL, args, winArgs, newPart );
03984     return true;
03985   }
03986 
03987   //If we're asked to open up an anchor in the current URL, in current window,
03988   //merely gotoanchor, and do not reload the new page. Note that this does
03989   //not apply if the URL is the same page, but without a ref
03990   if (cURL.hasRef() && (!hasTarget || target == "_self"))
03991   {
03992     KURL curUrl = this->url();
03993     if (urlcmp(cURL.url(), curUrl.url(),
03994               false,  // ignore trailing / diff, IE does, even if FFox doesn't
03995               true))  // don't care if the ref changes!
03996     {
03997       m_url = cURL;
03998       emit d->m_extension->openURLNotify();
03999       if ( !gotoAnchor( m_url.encodedHtmlRef()) )
04000         gotoAnchor( m_url.htmlRef() );
04001       emit d->m_extension->setLocationBarURL( m_url.prettyURL() );
04002       return false; // we jumped, but we didn't open a URL
04003     }
04004   }
04005 
04006   if ( !d->m_bComplete && !hasTarget )
04007     closeURL();
04008 
04009   view()->viewport()->unsetCursor();
04010   emit d->m_extension->openURLRequest( cURL, args );
04011   return true;
04012 }
04013 
04014 void KHTMLPart::slotViewDocumentSource()
04015 {
04016   KURL url(m_url);
04017   bool isTempFile = false;
04018   if (!(url.isLocalFile()) && KHTMLPageCache::self()->isComplete(d->m_cacheId))
04019   {
04020      KTempFile sourceFile(QString::null, defaultExtension());
04021      if (sourceFile.status() == 0)
04022      {
04023         KHTMLPageCache::self()->saveData(d->m_cacheId, sourceFile.dataStream());
04024         url = KURL();
04025         url.setPath(sourceFile.name());
04026         isTempFile = true;
04027      }
04028   }
04029 
04030   (void) KRun::runURL( url, QString::fromLatin1("text/plain"), isTempFile );
04031 }
04032 
04033 void KHTMLPart::slotViewPageInfo()
04034 {
04035   KHTMLInfoDlg *dlg = new KHTMLInfoDlg(NULL, "KHTML Page Info Dialog", false, WDestructiveClose);
04036   dlg->_close->setGuiItem(KStdGuiItem::close());
04037 
04038   if (d->m_doc)
04039      dlg->_title->setText(d->m_doc->title().string());
04040 
04041   // If it's a frame, set the caption to "Frame Information"
04042   if ( parentPart() && d->m_doc && d->m_doc->isHTMLDocument() ) {
04043      dlg->setCaption(i18n("Frame Information"));
04044   }
04045 
04046   QString editStr = QString::null;
04047 
04048   if (!d->m_pageServices.isEmpty())
04049     editStr = i18n("   <a href=\"%1\">[Properties]</a>").arg(d->m_pageServices);
04050 
04051   QString squeezedURL = KStringHandler::csqueeze( url().prettyURL(), 80 );
04052   dlg->_url->setText("<a href=\"" + url().url() + "\">" + squeezedURL + "</a>" + editStr);
04053   if (lastModified().isEmpty())
04054   {
04055     dlg->_lastModified->hide();
04056     dlg->_lmLabel->hide();
04057   }
04058   else
04059     dlg->_lastModified->setText(lastModified());
04060 
04061   const QString& enc = encoding();
04062   if (enc.isEmpty()) {
04063     dlg->_eLabel->hide();
04064     dlg->_encoding->hide();
04065   } else {
04066     dlg->_encoding->setText(enc);
04067   }
04068   /* populate the list view now */
04069   const QStringList headers = QStringList::split("\n", d->m_httpHeaders);
04070 
04071   QStringList::ConstIterator it = headers.begin();
04072   const QStringList::ConstIterator itEnd = headers.end();
04073 
04074   for (; it != itEnd; ++it) {
04075     const QStringList header = QStringList::split(QRegExp(":[ ]+"), *it);
04076     if (header.count() != 2)
04077        continue;
04078     new QListViewItem(dlg->_headers, header[0], header[1]);
04079   }
04080 
04081   dlg->show();
04082   /* put no code here */
04083 }
04084 
04085 
04086 void KHTMLPart::slotViewFrameSource()
04087 {
04088   KParts::ReadOnlyPart *frame = currentFrame();
04089   if ( !frame )
04090     return;
04091 
04092   KURL url = frame->url();
04093   bool isTempFile = false;
04094   if (!(url.isLocalFile()) && frame->inherits("KHTMLPart"))
04095   {
04096        long cacheId = static_cast<KHTMLPart *>(frame)->d->m_cacheId;
04097 
04098        if (KHTMLPageCache::self()->isComplete(cacheId))
04099        {
04100            KTempFile sourceFile(QString::null, defaultExtension());
04101            if (sourceFile.status() == 0)
04102            {
04103                KHTMLPageCache::self()->saveData(cacheId, sourceFile.dataStream());
04104                url = KURL();
04105                url.setPath(sourceFile.name());
04106                isTempFile = true;
04107            }
04108      }
04109   }
04110 
04111   (void) KRun::runURL( url, QString::fromLatin1("text/plain"), isTempFile );
04112 }
04113 
04114 KURL KHTMLPart::backgroundURL() const
04115 {
04116   // ### what about XML documents? get from CSS?
04117   if (!d->m_doc || !d->m_doc->isHTMLDocument())
04118     return KURL();
04119 
04120   QString relURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
04121 
04122   return KURL( m_url, relURL );
04123 }
04124 
04125 void KHTMLPart::slotSaveBackground()
04126 {
04127   KIO::MetaData metaData;
04128   metaData["referrer"] = d->m_referrer;
04129   KHTMLPopupGUIClient::saveURL( d->m_view, i18n("Save Background Image As"), backgroundURL(), metaData );
04130 }
04131 
04132 void KHTMLPart::slotSaveDocument()
04133 {
04134   KURL srcURL( m_url );
04135 
04136   if ( srcURL.fileName(false).isEmpty() )
04137     srcURL.setFileName( "index" + defaultExtension() );
04138 
04139   KIO::MetaData metaData;
04140   // Referre unknown?
04141   KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), srcURL, metaData, "text/html", d->m_cacheId );
04142 }
04143 
04144 void KHTMLPart::slotSecurity()
04145 {
04146 //   kdDebug( 6050 ) << "Meta Data:" << endl
04147 //                   << d->m_ssl_peer_cert_subject
04148 //                   << endl
04149 //                   << d->m_ssl_peer_cert_issuer
04150 //                   << endl
04151 //                   << d->m_ssl_cipher
04152 //                   << endl
04153 //                   << d->m_ssl_cipher_desc
04154 //                   << endl
04155 //                   << d->m_ssl_cipher_version
04156 //                   << endl
04157 //                   << d->m_ssl_good_from
04158 //                   << endl
04159 //                   << d->m_ssl_good_until
04160 //                   << endl
04161 //                   << d->m_ssl_cert_state
04162 //                   << endl;
04163 
04164   KSSLInfoDlg *kid = new KSSLInfoDlg(d->m_ssl_in_use, widget(), "kssl_info_dlg", true );
04165 
04166   if (d->m_bSecurityInQuestion)
04167       kid->setSecurityInQuestion(true);
04168 
04169   if (d->m_ssl_in_use) {
04170     KSSLCertificate *x = KSSLCertificate::fromString(d->m_ssl_peer_certificate.local8Bit());
04171     if (x) {
04172        // Set the chain back onto the certificate
04173        const QStringList cl = QStringList::split(QString("\n"), d->m_ssl_peer_chain);
04174        QPtrList<KSSLCertificate> ncl;
04175 
04176        ncl.setAutoDelete(true);
04177        QStringList::ConstIterator it = cl.begin();
04178        const QStringList::ConstIterator itEnd = cl.end();
04179        for (; it != itEnd; ++it) {
04180           KSSLCertificate* const y = KSSLCertificate::fromString((*it).local8Bit());
04181           if (y) ncl.append(y);
04182        }
04183 
04184        if (ncl.count() > 0)
04185           x->chain().setChain(ncl);
04186 
04187        kid->setup(x,
04188                   d->m_ssl_peer_ip,
04189                   m_url.url(),
04190                   d->m_ssl_cipher,
04191                   d->m_ssl_cipher_desc,
04192                   d->m_ssl_cipher_version,
04193                   d->m_ssl_cipher_used_bits.toInt(),
04194                   d->m_ssl_cipher_bits.toInt(),
04195                   (KSSLCertificate::KSSLValidation) d->m_ssl_cert_state.toInt()
04196                   );
04197         kid->exec();
04198         delete x;
04199      } else kid->exec();
04200   } else kid->exec();
04201 }
04202 
04203 void KHTMLPart::slotSaveFrame()
04204 {
04205     KParts::ReadOnlyPart *frame = currentFrame();
04206     if ( !frame )
04207         return;
04208 
04209     KURL srcURL( frame->url() );
04210 
04211     if ( srcURL.fileName(false).isEmpty() )
04212         srcURL.setFileName( "index" + defaultExtension() );
04213 
04214     KIO::MetaData metaData;
04215     // Referrer unknown?
04216     KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save Frame As" ), srcURL, metaData, "text/html" );
04217 }
04218 
04219 void KHTMLPart::slotSetEncoding()
04220 {
04221   d->m_automaticDetection->setItemChecked( int( d->m_autoDetectLanguage ), false );
04222   d->m_paSetEncoding->popupMenu()->setItemChecked( 0, false );
04223   d->m_paSetEncoding->popupMenu()->setItemChecked( d->m_paSetEncoding->popupMenu()->idAt( 2 ), true );
04224 
04225   QString enc = KGlobal::charsets()->encodingForName( d->m_manualDetection->currentText() );
04226   setEncoding( enc, true );
04227 }
04228 
04229 void KHTMLPart::slotUseStylesheet()
04230 {
04231   if (d->m_doc)
04232   {
04233     bool autoselect = (d->m_paUseStylesheet->currentItem() == 0);
04234     d->m_sheetUsed = autoselect ? QString() : d->m_paUseStylesheet->currentText();
04235     d->m_doc->updateStyleSelector();
04236   }
04237 }
04238 
04239 void KHTMLPart::updateActions()
04240 {
04241   bool frames = false;
04242 
04243   QValueList<khtml::ChildFrame*>::ConstIterator it = d->m_frames.begin();
04244   const QValueList<khtml::ChildFrame*>::ConstIterator end = d->m_frames.end();
04245   for (; it != end; ++it )
04246       if ( (*it)->m_type == khtml::ChildFrame::Frame )
04247       {
04248           frames = true;
04249           break;
04250       }
04251 
04252   d->m_paViewFrame->setEnabled( frames );
04253   d->m_paSaveFrame->setEnabled( frames );
04254 
04255   if ( frames )
04256     d->m_paFind->setText( i18n( "&Find in Frame..." ) );
04257   else
04258     d->m_paFind->setText( i18n( "&Find..." ) );
04259 
04260   KParts::Part *frame = 0;
04261 
04262   if ( frames )
04263     frame = currentFrame();
04264 
04265   bool enableFindAndSelectAll = true;
04266 
04267   if ( frame )
04268     enableFindAndSelectAll = frame->inherits( "KHTMLPart" );
04269 
04270   d->m_paFind->setEnabled( enableFindAndSelectAll );
04271   d->m_paSelectAll->setEnabled( enableFindAndSelectAll );
04272 
04273   bool enablePrintFrame = false;
04274 
04275   if ( frame )
04276   {
04277     QObject *ext = KParts::BrowserExtension::childObject( frame );
04278     if ( ext )
04279       enablePrintFrame = ext->metaObject()->slotNames().contains( "print()" );
04280   }
04281 
04282   d->m_paPrintFrame->setEnabled( enablePrintFrame );
04283 
04284   QString bgURL;
04285 
04286   // ### frames
04287   if ( d->m_doc && d->m_doc->isHTMLDocument() && static_cast<HTMLDocumentImpl*>(d->m_doc)->body() && !d->m_bClearing )
04288     bgURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
04289 
04290   d->m_paSaveBackground->setEnabled( !bgURL.isEmpty() );
04291 
04292   if ( d->m_paDebugScript )
04293     d->m_paDebugScript->setEnabled( d->m_frame ? d->m_frame->m_jscript : 0L );
04294 }
04295 
04296 KParts::LiveConnectExtension *KHTMLPart::liveConnectExtension( const khtml::RenderPart *frame) const {
04297     const ConstFrameIt end = d->m_objects.end();
04298     for(ConstFrameIt it = d->m_objects.begin(); it != end; ++it )
04299         if ((*it)->m_frame == frame)
04300             return (*it)->m_liveconnect;
04301     return 0L;
04302 }
04303 
04304 bool KHTMLPart::requestFrame( khtml::RenderPart *frame, const QString &url, const QString &frameName,
04305                               const QStringList &params, bool isIFrame )
04306 {
04307   //kdDebug( 6050 ) << this << " requestFrame( ..., " << url << ", " << frameName << " )" << endl;
04308   FrameIt it = d->m_frames.find( frameName );
04309   if ( it == d->m_frames.end() )
04310   {
04311     khtml::ChildFrame * child = new khtml::ChildFrame;
04312     //kdDebug( 6050 ) << "inserting new frame into frame map " << frameName << endl;
04313     child->m_name = frameName;
04314     it = d->m_frames.append( child );
04315   }
04316 
04317   (*it)->m_type = isIFrame ? khtml::ChildFrame::IFrame : khtml::ChildFrame::Frame;
04318   (*it)->m_frame = frame;
04319   (*it)->m_params = params;
04320 
04321   // Support for <frame src="javascript:string">
04322   if ( url.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
04323   {
04324     if ( processObjectRequest(*it, KURL("about:blank"), QString("text/html") ) ) {
04325       KHTMLPart* p = static_cast<KHTMLPart*>(static_cast<KParts::ReadOnlyPart *>((*it)->m_part));
04326 
04327       // See if we want to replace content with javascript: output..
04328       QVariant res = p->executeScript( DOM::Node(), KURL::decode_string( url.right( url.length() - 11) ) );
04329       if ( res.type() == QVariant::String ) {
04330         p->begin();
04331         p->write( res.asString() );
04332         p->end();
04333       }
04334       return true;
04335     }
04336     return false;
04337   }
04338   KURL u = url.isEmpty() ? KURL() : completeURL( url );
04339   return requestObject( *it, u );
04340 }
04341 
04342 QString KHTMLPart::requestFrameName()
04343 {
04344    return QString::fromLatin1("<!--frame %1-->").arg(d->m_frameNameId++);
04345 }
04346 
04347 bool KHTMLPart::requestObject( khtml::RenderPart *frame, const QString &url, const QString &serviceType,
04348                                const QStringList &params )
04349 {
04350   //kdDebug( 6005 ) << "KHTMLPart::requestObject " << this << " frame=" << frame << endl;
04351   khtml::ChildFrame *child = new khtml::ChildFrame;
04352   FrameIt it = d->m_objects.append( child );
04353   (*it)->m_frame = frame;
04354   (*it)->m_type = khtml::ChildFrame::Object;
04355   (*it)->m_params = params;
04356 
04357   KParts::URLArgs args;
04358   args.serviceType = serviceType;
04359   if (!requestObject( *it, completeURL( url ), args ) && !(*it)->m_run) {
04360       (*it)->m_bCompleted = true;
04361       return false;
04362   }
04363   return true;
04364 }
04365 
04366 bool KHTMLPart::requestObject( khtml::ChildFrame *child, const KURL &url, const KParts::URLArgs &_args )
04367 {
04368   if (!checkLinkSecurity(url))
04369   {
04370     kdDebug(6005) << this << " KHTMLPart::requestObject checkLinkSecurity refused" << endl;
04371     return false;
04372   }
04373   if ( child->m_bPreloaded )
04374   {
04375     kdDebug(6005) << "KHTMLPart::requestObject preload" << endl;
04376     if ( child->m_frame && child->m_part )
04377       child->m_frame->setWidget( child->m_part->widget() );
04378 
04379     child->m_bPreloaded = false;
04380     return true;
04381   }
04382 
04383   //kdDebug(6005) << "KHTMLPart::requestObject child=" << child << " child->m_part=" << child->m_part << endl;
04384 
04385   KParts::URLArgs args( _args );
04386 
04387   if ( child->m_run )
04388     child->m_run->abort();
04389 
04390   if ( child->m_part && !args.reload && urlcmp( child->m_part->url().url(), url.url(), true, true ) )
04391     args.serviceType = child->m_serviceType;
04392 
04393   child->m_args = args;
04394   child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload);
04395   child->m_serviceName = QString::null;
04396   if (!d->m_referrer.isEmpty() && !child->m_args.metaData().contains( "referrer" ))
04397     child->m_args.metaData()["referrer"] = d->m_referrer;
04398 
04399   child->m_args.metaData().insert("PropagateHttpHeader", "true");
04400   child->m_args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
04401   child->m_args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
04402   child->m_args.metaData().insert("main_frame_request",
04403                                   parentPart() == 0 ? "TRUE":"FALSE");
04404   child->m_args.metaData().insert("ssl_was_in_use",
04405                                   d->m_ssl_in_use ? "TRUE":"FALSE");
04406   child->m_args.metaData().insert("ssl_activate_warnings", "TRUE");
04407   child->m_args.metaData().insert("cross-domain", toplevelURL().url());
04408 
04409   // We want a KHTMLPart if the HTML says <frame src=""> or <frame src="about:blank">
04410   if ((url.isEmpty() || url.url() == "about:blank") && args.serviceType.isEmpty())
04411     args.serviceType = QString::fromLatin1( "text/html" );
04412 
04413   if ( args.serviceType.isEmpty() ) {
04414     kdDebug(6050) << "Running new KHTMLRun for " << this << " and child=" << child << endl;
04415     child->m_run = new KHTMLRun( this, child, url, child->m_args, true );
04416     d->m_bComplete = false; // ensures we stop it in checkCompleted...
04417     return false;
04418   } else {
04419     return processObjectRequest( child, url, args.serviceType );
04420   }
04421 }
04422 
04423 bool KHTMLPart::processObjectRequest( khtml::ChildFrame *child, const KURL &_url, const QString &mimetype )
04424 {
04425   //kdDebug( 6050 ) << "KHTMLPart::processObjectRequest trying to create part for " << mimetype << endl;
04426 
04427   // IMPORTANT: create a copy of the url here, because it is just a reference, which was likely to be given
04428   // by an emitting frame part (emit openURLRequest( blahurl, ... ) . A few lines below we delete the part
04429   // though -> the reference becomes invalid -> crash is likely
04430   KURL url( _url );
04431 
04432   // khtmlrun called us this way to indicate a loading error
04433   if ( d->m_onlyLocalReferences || ( url.isEmpty() && mimetype.isEmpty() ) )
04434   {
04435       child->m_bCompleted = true;
04436       checkCompleted();
04437       return true;
04438   }
04439 
04440   if (child->m_bNotify)
04441   {
04442       child->m_bNotify = false;
04443       if ( !child->m_args.lockHistory() )
04444           emit d->m_extension->openURLNotify();
04445   }
04446 
04447   if ( child->m_serviceType != mimetype || !child->m_part )
04448   {
04449     // Before attempting to load a part, check if the user wants that.
04450     // Many don't like getting ZIP files embedded.
04451     // However we don't want to ask for flash and other plugin things..
04452     if ( child->m_type != khtml::ChildFrame::Object )
04453     {
04454       QString suggestedFilename;
04455       if ( child->m_run )
04456         suggestedFilename = child->m_run->suggestedFilename();
04457 
04458       KParts::BrowserRun::AskSaveResult res = KParts::BrowserRun::askEmbedOrSave(
04459         url, mimetype, suggestedFilename  );
04460       switch( res ) {
04461       case KParts::BrowserRun::Save:
04462         KHTMLPopupGUIClient::saveURL( widget(), i18n( "Save As" ), url, child->m_args.metaData(), QString::null, 0, suggestedFilename);
04463         // fall-through
04464       case KParts::BrowserRun::Cancel:
04465         child->m_bCompleted = true;
04466         checkCompleted();
04467         return true; // done
04468       default: // Open
04469         break;
04470       }
04471     }
04472 
04473     QStringList dummy; // the list of servicetypes handled by the part is now unused.
04474     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 );
04475 
04476     if ( !part )
04477     {
04478         if ( child->m_frame )
04479           if (child->m_frame->partLoadingErrorNotify( child, url, mimetype ))
04480             return true; // we succeeded after all (a fallback was used)
04481 
04482         checkEmitLoadEvent();
04483         return false;
04484     }
04485 
04486     //CRITICAL STUFF
04487     if ( child->m_part )
04488     {
04489       if (!::qt_cast<KHTMLPart*>(child->m_part) && child->m_jscript)
04490           child->m_jscript->clear();
04491       partManager()->removePart( (KParts::ReadOnlyPart *)child->m_part );
04492       delete (KParts::ReadOnlyPart *)child->m_part;
04493       if (child->m_liveconnect) {
04494         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 &)));
04495         child->m_liveconnect = 0L;
04496       }
04497     }
04498 
04499     child->m_serviceType = mimetype;
04500     if ( child->m_frame  && part->widget() )
04501       child->m_frame->setWidget( part->widget() );
04502 
04503     if ( child->m_type != khtml::ChildFrame::Object )
04504       partManager()->addPart( part, false );
04505 //  else
04506 //      kdDebug(6005) << "AH! NO FRAME!!!!!" << endl;
04507 
04508     child->m_part = part;
04509 
04510     if (::qt_cast<KHTMLPart*>(part)) {
04511       static_cast<KHTMLPart*>(part)->d->m_frame = child;
04512     } else if (child->m_frame) {
04513       child->m_liveconnect = KParts::LiveConnectExtension::childObject(part);
04514       if (child->m_liveconnect)
04515         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 &)));
04516     }
04517     KParts::StatusBarExtension *sb = KParts::StatusBarExtension::childObject(part);
04518     if (sb)
04519       sb->setStatusBar( d->m_statusBarExtension->statusBar() );
04520 
04521     connect( part, SIGNAL( started( KIO::Job *) ),
04522              this, SLOT( slotChildStarted( KIO::Job *) ) );
04523     connect( part, SIGNAL( completed() ),
04524              this, SLOT( slotChildCompleted() ) );
04525     connect( part, SIGNAL( completed(bool) ),
04526              this, SLOT( slotChildCompleted(bool) ) );
04527     connect( part, SIGNAL( setStatusBarText( const QString & ) ),
04528                 this, SIGNAL( setStatusBarText( const QString & ) ) );
04529     if ( part->inherits( "KHTMLPart" ) )
04530     {
04531       connect( this, SIGNAL( completed() ),
04532                part, SLOT( slotParentCompleted() ) );
04533       connect( this, SIGNAL( completed(bool) ),
04534                part, SLOT( slotParentCompleted() ) );
04535       // As soon as the child's document is created, we need to set its domain
04536       // (but we do so only once, so it can't be simply done in the child)
04537       connect( part, SIGNAL( docCreated() ),
04538                this, SLOT( slotChildDocCreated() ) );
04539     }
04540 
04541     child->m_extension = KParts::BrowserExtension::childObject( part );
04542 
04543     if ( child->m_extension )
04544     {
04545       connect( child->m_extension, SIGNAL( openURLNotify() ),
04546                d->m_extension, SIGNAL( openURLNotify() ) );
04547 
04548       connect( child->m_extension, SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ),
04549                this, SLOT( slotChildURLRequest( const KURL &, const KParts::URLArgs & ) ) );
04550 
04551       connect( child->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ),
04552                d->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ) );
04553       connect( child->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs &, const KParts::WindowArgs &, KParts::ReadOnlyPart *& ) ),
04554                d->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & , const KParts::WindowArgs &, KParts::ReadOnlyPart *&) ) );
04555 
04556       connect( child->m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ),
04557                d->m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ) );
04558       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ),
04559                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ) );
04560       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ),
04561                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ) );
04562       connect( child->m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ),
04563                d->m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ) );
04564       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ),
04565                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ) );
04566       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ),
04567                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ) );
04568 
04569       connect( child->m_extension, SIGNAL( infoMessage( const QString & ) ),
04570                d->m_extension, SIGNAL( infoMessage( const QString & ) ) );
04571 
04572       connect( child->m_extension, SIGNAL( requestFocus( KParts::ReadOnlyPart * ) ),
04573                this, SLOT( slotRequestFocus( KParts::ReadOnlyPart * ) ) );
04574 
04575       child->m_extension->setBrowserInterface( d->m_extension->browserInterface() );
04576     }
04577   }
04578   else if ( child->m_frame && child->m_part &&
04579             child->m_frame->widget() != child->m_part->widget() )
04580     child->m_frame->setWidget( child->m_part->widget() );
04581 
04582   checkEmitLoadEvent();
04583   // Some JS code in the load event may have destroyed the part
04584   // In that case, abort
04585   if ( !child->m_part )
04586     return false;
04587 
04588   if ( child->m_bPreloaded )
04589   {
04590     if ( child->m_frame && child->m_part )
04591       child->m_frame->setWidget( child->m_part->widget() );
04592 
04593     child->m_bPreloaded = false;
04594     return true;
04595   }
04596 
04597   child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload);
04598 
04599   // make sure the part has a way to find out about the mimetype.
04600   // we actually set it in child->m_args in requestObject already,
04601   // but it's useless if we had to use a KHTMLRun instance, as the
04602   // point the run object is to find out exactly the mimetype.
04603   child->m_args.serviceType = mimetype;
04604 
04605   // if not a frame set child as completed
04606   child->m_bCompleted = child->m_type == khtml::ChildFrame::Object;
04607 
04608   if ( child->m_extension )
04609     child->m_extension->setURLArgs( child->m_args );
04610 
04611   if(url.protocol() == "javascript" || url.url() == "about:blank") {
04612       if (!child->m_part->inherits("KHTMLPart"))
04613           return false;
04614 
04615       KHTMLPart* p = static_cast<KHTMLPart*>(static_cast<KParts::ReadOnlyPart *>(child->m_part));
04616 
04617       p->begin();
04618       if (d->m_doc && p->d->m_doc)
04619         p->d->m_doc->setBaseURL(d->m_doc->baseURL());
04620       if (!url.url().startsWith("about:")) {
04621         p->write(url.path());
04622       } else {
04623     p->m_url = url;
04624         // we need a body element. testcase: <iframe id="a"></iframe><script>alert(a.document.body);</script>
04625         p->write("<HTML><TITLE></TITLE><BODY></BODY></HTML>");
04626       }
04627       p->end();
04628       return true;
04629   }
04630   else if ( !url.isEmpty() )
04631   {
04632       //kdDebug( 6050 ) << "opening " << url.url() << " in frame " << child->m_part << endl;
04633       bool b = child->m_part->openURL( url );
04634       if (child->m_bCompleted)
04635           checkCompleted();
04636       return b;
04637   }
04638   else
04639   {
04640       child->m_bCompleted = true;
04641       checkCompleted();
04642       return true;
04643   }
04644 }
04645 
04646 KParts::ReadOnlyPart *KHTMLPart::createPart( QWidget *parentWidget, const char *widgetName,
04647                                              QObject *parent, const char *name, const QString &mimetype,
04648                                              QString &serviceName, QStringList &serviceTypes,
04649                                              const QStringList &params )
04650 {
04651   QString constr;
04652   if ( !serviceName.isEmpty() )
04653     constr.append( QString::fromLatin1( "Name == '%1'" ).arg( serviceName ) );
04654 
04655   KTrader::OfferList offers = KTrader::self()->query( mimetype, "KParts/ReadOnlyPart", constr, QString::null );
04656 
04657   if ( offers.isEmpty() ) {
04658     int pos = mimetype.find( "-plugin" );
04659     if (pos < 0)
04660         return 0L;
04661     QString stripped_mime = mimetype.left( pos );
04662     offers = KTrader::self()->query( stripped_mime, "KParts/ReadOnlyPart", constr, QString::null );
04663     if ( offers.isEmpty() )
04664         return 0L;
04665   }
04666 
04667   KTrader::OfferList::ConstIterator it = offers.begin();
04668   const KTrader::OfferList::ConstIterator itEnd = offers.end();
04669   for ( ; it != itEnd; ++it )
04670   {
04671     KService::Ptr service = (*it);
04672 
04673     KLibFactory* const factory = KLibLoader::self()->factory( QFile::encodeName(service->library()) );
04674     if ( factory ) {
04675       KParts::ReadOnlyPart *res = 0L;
04676 
04677       const char *className = "KParts::ReadOnlyPart";
04678       if ( service->serviceTypes().contains( "Browser/View" ) )
04679         className = "Browser/View";
04680 
04681       if ( factory->inherits( "KParts::Factory" ) )
04682         res = static_cast<KParts::ReadOnlyPart *>(static_cast<KParts::Factory *>( factory )->createPart( parentWidget, widgetName, parent, name, className, params ));
04683       else
04684         res = static_cast<KParts::ReadOnlyPart *>(factory->create( parentWidget, widgetName, className ));
04685 
04686       if ( res ) {
04687         serviceTypes = service->serviceTypes();
04688         serviceName = service->name();
04689         return res;
04690       }
04691     } else {
04692       // TODO KMessageBox::error and i18n, like in KonqFactory::createView?
04693       kdWarning() << QString("There was an error loading the module %1.\nThe diagnostics is:\n%2")
04694                       .arg(service->name()).arg(KLibLoader::self()->lastErrorMessage()) << endl;
04695     }
04696   }
04697   return 0;
04698 }
04699 
04700 KParts::PartManager *KHTMLPart::partManager()
04701 {
04702   if ( !d->m_manager && d->m_view )
04703   {
04704     d->m_manager = new KParts::PartManager( d->m_view->topLevelWidget(), this, "khtml part manager" );
04705     d->m_manager->setAllowNestedParts( true );
04706     connect( d->m_manager, SIGNAL( activePartChanged( KParts::Part * ) ),
04707              this, SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
04708     connect( d->m_manager, SIGNAL( partRemoved( KParts::Part * ) ),
04709              this, SLOT( slotPartRemoved( KParts::Part * ) ) );
04710   }
04711 
04712   return d->m_manager;
04713 }
04714 
04715 void KHTMLPart::submitFormAgain()
04716 {
04717   disconnect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
04718   if( d->m_doc && !d->m_doc->parsing() && d->m_submitForm)
04719     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 );
04720 
04721   delete d->m_submitForm;
04722   d->m_submitForm = 0;
04723 }
04724 
04725 void KHTMLPart::submitFormProxy( const char *action, const QString &url, const QByteArray &formData, const QString &_target, const QString& contentType, const QString& boundary )
04726 {
04727   submitForm(action, url, formData, _target, contentType, boundary);
04728 }
04729 
04730 void KHTMLPart::submitForm( const char *action, const QString &url, const QByteArray &formData, const QString &_target, const QString& contentType, const QString& boundary )
04731 {
04732   kdDebug(6000) << this << ": KHTMLPart::submitForm target=" << _target << " url=" << url << endl;
04733   if (d->m_formNotification == KHTMLPart::Only) {
04734     emit formSubmitNotification(action, url, formData, _target, contentType, boundary);
04735     return;
04736   } else if (d->m_formNotification == KHTMLPart::Before) {
04737     emit formSubmitNotification(action, url, formData, _target, contentType, boundary);
04738   }
04739 
04740   KURL u = completeURL( url );
04741 
04742   if ( !u.isValid() )
04743   {
04744     // ### ERROR HANDLING!
04745     return;
04746   }
04747 
04748   // Form security checks
04749   //
04750   /*
04751    * If these form security checks are still in this place in a month or two
04752    * I'm going to simply delete them.
04753    */
04754 
04755   /* This is separate for a reason.  It has to be _before_ all script, etc,
04756    * AND I don't want to break anything that uses checkLinkSecurity() in
04757    * other places.
04758    */
04759 
04760   if (!d->m_submitForm) {
04761     if (u.protocol() != "https" && u.protocol() != "mailto") {
04762       if (d->m_ssl_in_use) {    // Going from SSL -> nonSSL
04763         int rc = KMessageBox::warningContinueCancel(NULL, i18n("Warning:  This is a secure form but it is attempting to send your data back unencrypted."
04764                                                                "\nA third party may be able to intercept and view this information."
04765                                                                "\nAre you sure you wish to continue?"),
04766                                                     i18n("Network Transmission"),KGuiItem(i18n("&Send Unencrypted")));
04767         if (rc == KMessageBox::Cancel)
04768           return;
04769       } else {                  // Going from nonSSL -> nonSSL
04770         KSSLSettings kss(true);
04771         if (kss.warnOnUnencrypted()) {
04772           int rc = KMessageBox::warningContinueCancel(NULL,
04773                                                       i18n("Warning: Your data is about to be transmitted across the network unencrypted."
04774                                                            "\nAre you sure you wish to continue?"),
04775                                                       i18n("Network Transmission"),
04776                                                       KGuiItem(i18n("&Send Unencrypted")),
04777                                                       "WarnOnUnencryptedForm");
04778           // Move this setting into KSSL instead
04779           KConfig *config = kapp->config();
04780           QString grpNotifMsgs = QString::fromLatin1("Notification Messages");
04781           KConfigGroupSaver saver( config, grpNotifMsgs );
04782 
04783           if (!config->readBoolEntry("WarnOnUnencryptedForm", true)) {
04784             config->deleteEntry("WarnOnUnencryptedForm");
04785             config->sync();
04786             kss.setWarnOnUnencrypted(false);
04787             kss.save();
04788           }
04789           if (rc == KMessageBox::Cancel)
04790             return;
04791         }
04792       }
04793     }
04794 
04795     if (u.protocol() == "mailto") {
04796       int rc = KMessageBox::warningContinueCancel(NULL,
04797                                                   i18n("This site is attempting to submit form data via email.\n"
04798                                                        "Do you want to continue?"),
04799                                                   i18n("Network Transmission"),
04800                                                   KGuiItem(i18n("&Send Email")),
04801                                                   "WarnTriedEmailSubmit");
04802 
04803       if (rc == KMessageBox::Cancel) {
04804         return;
04805       }
04806     }
04807   }
04808 
04809   // End form security checks
04810   //
04811 
04812   QString urlstring = u.url();
04813 
04814   if ( urlstring.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
04815     urlstring = KURL::decode_string(urlstring);
04816     crossFrameExecuteScript( _target, urlstring.right( urlstring.length() - 11) );
04817     return;
04818   }
04819 
04820   if (!checkLinkSecurity(u,
04821              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?" ),
04822              i18n( "Submit" )))
04823     return;
04824 
04825   KParts::URLArgs args;
04826 
04827   if (!d->m_referrer.isEmpty())
04828      args.metaData()["referrer"] = d->m_referrer;
04829 
04830   args.metaData().insert("PropagateHttpHeader", "true");
04831   args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
04832   args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
04833   args.metaData().insert("main_frame_request",
04834                          parentPart() == 0 ? "TRUE":"FALSE");
04835   args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
04836   args.metaData().insert("ssl_activate_warnings", "TRUE");
04837 //WABA: When we post a form we should treat it as the main url
04838 //the request should never be considered cross-domain
04839 //args.metaData().insert("cross-domain", toplevelURL().url());
04840   args.frameName = _target.isEmpty() ? d->m_doc->baseTarget() : _target ;
04841 
04842   // Handle mailto: forms
04843   if (u.protocol() == "mailto") {
04844       // 1)  Check for attach= and strip it
04845       QString q = u.query().mid(1);
04846       QStringList nvps = QStringList::split("&", q);
04847       bool triedToAttach = false;
04848 
04849       QStringList::Iterator nvp = nvps.begin();
04850       const QStringList::Iterator nvpEnd = nvps.end();
04851 
04852 // cannot be a for loop as if something is removed we don't want to do ++nvp, as
04853 // remove returns an iterator pointing to the next item
04854 
04855       while (nvp != nvpEnd) {
04856          const QStringList pair = QStringList::split("=", *nvp);
04857          if (pair.count() >= 2) {
04858             if (pair.first().lower() == "attach") {
04859                nvp = nvps.remove(nvp);
04860                triedToAttach = true;
04861             } else {
04862                ++nvp;
04863             }
04864          } else {
04865             ++nvp;
04866          }
04867       }
04868 
04869       if (triedToAttach)
04870          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");
04871 
04872       // 2)  Append body=
04873       QString bodyEnc;
04874       if (contentType.lower() == "multipart/form-data") {
04875          // FIXME: is this correct?  I suspect not
04876          bodyEnc = KURL::encode_string(QString::fromLatin1(formData.data(),
04877                                                            formData.size()));
04878       } else if (contentType.lower() == "text/plain") {
04879          // Convention seems to be to decode, and s/&/\n/
04880          QString tmpbody = QString::fromLatin1(formData.data(),
04881                                                formData.size());
04882          tmpbody.replace(QRegExp("[&]"), "\n");
04883          tmpbody.replace(QRegExp("[+]"), " ");
04884          tmpbody = KURL::decode_string(tmpbody);  // Decode the rest of it
04885          bodyEnc = KURL::encode_string(tmpbody);  // Recode for the URL
04886       } else {
04887          bodyEnc = KURL::encode_string(QString::fromLatin1(formData.data(),
04888                                                            formData.size()));
04889       }
04890 
04891       nvps.append(QString("body=%1").arg(bodyEnc));
04892       q = nvps.join("&");
04893       u.setQuery(q);
04894   }
04895 
04896   if ( strcmp( action, "get" ) == 0 ) {
04897     if (u.protocol() != "mailto")
04898        u.setQuery( QString::fromLatin1( formData.data(), formData.size() ) );
04899     args.setDoPost( false );
04900   }
04901   else {
04902     args.postData = formData;
04903     args.setDoPost( true );
04904 
04905     // construct some user headers if necessary
04906     if (contentType.isNull() || contentType == "application/x-www-form-urlencoded")
04907       args.setContentType( "Content-Type: application/x-www-form-urlencoded" );
04908     else // contentType must be "multipart/form-data"
04909       args.setContentType( "Content-Type: " + contentType + "; boundary=" + boundary );
04910   }
04911 
04912   if ( d->m_doc->parsing() || d->m_runningScripts > 0 ) {
04913     if( d->m_submitForm ) {
04914       kdDebug(6000) << "KHTMLPart::submitForm ABORTING!" << endl;
04915       return;
04916     }
04917     d->m_submitForm = new KHTMLPartPrivate::SubmitForm;
04918     d->m_submitForm->submitAction = action;
04919     d->m_submitForm->submitUrl = url;
04920     d->m_submitForm->submitFormData = formData;
04921     d->m_submitForm->target = _target;
04922     d->m_submitForm->submitContentType = contentType;
04923     d->m_submitForm->submitBoundary = boundary;
04924     connect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
04925   }
04926   else
04927   {
04928     emit d->m_extension->openURLRequest( u, args );
04929   }
04930 }
04931 
04932 void KHTMLPart::popupMenu( const QString &linkUrl )
04933 {
04934   KURL popupURL;
04935   KURL linkKURL;
04936   KParts::URLArgs args;
04937   QString referrer;
04938   KParts::BrowserExtension::PopupFlags itemflags=KParts::BrowserExtension::ShowBookmark | KParts::BrowserExtension::ShowReload;
04939 
04940   if ( linkUrl.isEmpty() ) { // click on background
04941     KHTMLPart* khtmlPart = this;
04942     while ( khtmlPart->parentPart() )
04943     {
04944       khtmlPart=khtmlPart->parentPart();
04945     }
04946     popupURL = khtmlPart->url();
04947     referrer = khtmlPart->pageReferrer();
04948     if (hasSelection())
04949       itemflags = KParts::BrowserExtension::ShowTextSelectionItems;
04950     else
04951       itemflags |= KParts::BrowserExtension::ShowNavigationItems;
04952   } else {               // click on link
04953     popupURL = completeURL( linkUrl );
04954     linkKURL = popupURL;
04955     referrer = this->referrer();
04956 
04957     if (!(d->m_strSelectedURLTarget).isEmpty() &&
04958            (d->m_strSelectedURLTarget.lower() != "_top") &&
04959            (d->m_strSelectedURLTarget.lower() != "_self") &&
04960        (d->m_strSelectedURLTarget.lower() != "_parent")) {
04961       if (d->m_strSelectedURLTarget.lower() == "_blank")
04962         args.setForcesNewWindow(true);
04963       else {
04964     KHTMLPart *p = this;
04965     while (p->parentPart())
04966       p = p->parentPart();
04967     if (!p->frameExists(d->m_strSelectedURLTarget))
04968           args.setForcesNewWindow(true);
04969       }
04970     }
04971   }
04972 
04973   // Danger, Will Robinson. The Popup might stay around for a much
04974   // longer time than KHTMLPart. Deal with it.
04975   KHTMLPopupGUIClient* client = new KHTMLPopupGUIClient( this, d->m_popupMenuXML, linkKURL );
04976   QGuardedPtr<QObject> guard( client );
04977 
04978   QString mimetype = QString::fromLatin1( "text/html" );
04979   args.metaData()["referrer"] = referrer;
04980 
04981   if (!linkUrl.isEmpty())               // over a link
04982   {
04983     if (popupURL.isLocalFile())             // safe to do this
04984     {
04985       mimetype = KMimeType::findByURL(popupURL,0,true,false)->name();
04986     }
04987     else                        // look at "extension" of link
04988     {
04989       const QString fname(popupURL.fileName(false));
04990       if (!fname.isEmpty() && !popupURL.hasRef() && popupURL.query().isEmpty())
04991       {
04992         KMimeType::Ptr pmt = KMimeType::findByPath(fname,0,true);
04993 
04994         // Further check for mime types guessed from the extension which,
04995         // on a web page, are more likely to be a script delivering content
04996         // of undecidable type. If the mime type from the extension is one
04997         // of these, don't use it.  Retain the original type 'text/html'.
04998         if (pmt->name() != KMimeType::defaultMimeType() &&
04999             !pmt->is("application/x-perl") &&
05000             !pmt->is("application/x-perl-module") &&
05001             !pmt->is("application/x-php") &&
05002             !pmt->is("application/x-python-bytecode") &&
05003             !pmt->is("application/x-python") &&
05004             !pmt->is("application/x-shellscript"))
05005           mimetype = pmt->name();
05006       }
05007     }
05008   }
05009 
05010   args.serviceType = mimetype;
05011 
05012   emit d->m_extension->popupMenu( client, QCursor::pos(), popupURL, args, itemflags, S_IFREG /*always a file*/);
05013 
05014   if ( !guard.isNull() ) {
05015      delete client;
05016      emit popupMenu(linkUrl, QCursor::pos());
05017      d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
05018   }
05019 }
05020 
05021 void KHTMLPart::slotParentCompleted()
05022 {
05023   //kdDebug(6050) << this << " slotParentCompleted()" << endl;
05024   if ( !d->m_redirectURL.isEmpty() && !d->m_redirectionTimer.isActive() )
05025   {
05026     //kdDebug(6050) << this << ": starting timer for child redirection -> " << d->m_redirectURL << endl;
05027     d->m_redirectionTimer.start( 1000 * d->m_delayRedirect, true );
05028   }
05029 }
05030 
05031 void KHTMLPart::slotChildStarted( KIO::Job *job )
05032 {
05033   khtml::ChildFrame *child = frame( sender() );
05034 
05035   assert( child );
05036 
05037   child->m_bCompleted = false;
05038 
05039   if ( d->m_bComplete )
05040   {
05041 #if 0
05042     // WABA: Looks like this belongs somewhere else
05043     if ( !parentPart() ) // "toplevel" html document? if yes, then notify the hosting browser about the document (url) changes
05044     {
05045       emit d->m_extension->openURLNotify();
05046     }
05047 #endif
05048     d->m_bComplete = false;
05049     emit started( job );
05050   }
05051 }
05052 
05053 void KHTMLPart::slotChildCompleted()
05054 {
05055   slotChildCompleted( false );
05056 }
05057 
05058 void KHTMLPart::slotChildCompleted( bool pendingAction )
05059 {
05060   khtml::ChildFrame *child = frame( sender() );
05061 
05062   if ( child ) {
05063     kdDebug(6050) << this << " slotChildCompleted child=" << child << " m_frame=" << child->m_frame << endl;
05064     child->m_bCompleted = true;
05065     child->m_bPendingRedirection = pendingAction;
05066     child->m_args = KParts::URLArgs();
05067   }
05068   checkCompleted();
05069 }
05070 
05071 void KHTMLPart::slotChildDocCreated()
05072 {
05073   const KHTMLPart* htmlFrame = static_cast<const KHTMLPart *>(sender());
05074   // Set domain to the frameset's domain
05075   // This must only be done when loading the frameset initially (#22039),
05076   // not when following a link in a frame (#44162).
05077   if ( d->m_doc && d->m_doc->isHTMLDocument() )
05078   {
05079     if ( sender()->inherits("KHTMLPart") )
05080     {
05081       DOMString domain = static_cast<HTMLDocumentImpl*>(d->m_doc)->domain();
05082       if (htmlFrame->d->m_doc && htmlFrame->d->m_doc->isHTMLDocument() )
05083         //kdDebug(6050) << "KHTMLPart::slotChildDocCreated: url: " << htmlFrame->m_url.url() << endl;
05084         static_cast<HTMLDocumentImpl*>(htmlFrame->d->m_doc)->setDomain( domain );
05085     }
05086   }
05087   // So it only happens once
05088   disconnect( htmlFrame, SIGNAL( docCreated() ), this, SLOT( slotChildDocCreated() ) );
05089 }
05090 
05091 void KHTMLPart::slotChildURLRequest( const KURL &url, const KParts::URLArgs &args )
05092 {
05093   khtml::ChildFrame *child = frame( sender()->parent() );
05094   KHTMLPart *callingHtmlPart = const_cast<KHTMLPart *>(dynamic_cast<const KHTMLPart *>(sender()->parent()));
05095 
05096   // TODO: handle child target correctly! currently the script are always executed fur the parent
05097   QString urlStr = url.url();
05098   if ( urlStr.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
05099       QString script = KURL::decode_string( urlStr.right( urlStr.length() - 11 ) );
05100       executeScript( DOM::Node(), script );
05101       return;
05102   }
05103 
05104   QString frameName = args.frameName.lower();
05105   if ( !frameName.isEmpty() ) {
05106     if ( frameName == QString::fromLatin1( "_top" ) )
05107     {
05108       emit d->m_extension->openURLRequest( url, args );
05109       return;
05110     }
05111     else if ( frameName == QString::fromLatin1( "_blank" ) )
05112     {
05113       emit d->m_extension->createNewWindow( url, args );
05114       return;
05115     }
05116     else if ( frameName == QString::fromLatin1( "_parent" ) )
05117     {
05118       KParts::URLArgs newArgs( args );
05119       newArgs.frameName = QString::null;
05120 
05121       emit d->m_extension->openURLRequest( url, newArgs );
05122       return;
05123     }
05124     else if ( frameName != QString::fromLatin1( "_self" ) )
05125     {
05126       khtml::ChildFrame *_frame = recursiveFrameRequest( callingHtmlPart, url, args );
05127 
05128       if ( !_frame )
05129       {
05130         emit d->m_extension->openURLRequest( url, args );
05131         return;
05132       }
05133 
05134       child = _frame;
05135     }
05136   }
05137 
05138   if ( child && child->m_type != khtml::ChildFrame::Object ) {
05139       // Inform someone that we are about to show something else.
05140       child->m_bNotify = true;
05141       requestObject( child, url, args );
05142   }  else if ( frameName== "_self" ) // this is for embedded objects (via <object>) which want to replace the current document
05143   {
05144       KParts::URLArgs newArgs( args );
05145       newArgs.frameName = QString::null;
05146       emit d->m_extension->openURLRequest( url, newArgs );
05147   }
05148 }
05149 
05150 void KHTMLPart::slotRequestFocus( KParts::ReadOnlyPart * )
05151 {
05152   emit d->m_extension->requestFocus(this);
05153 }
05154 
05155 khtml::ChildFrame *KHTMLPart::frame( const QObject *obj )
05156 {
05157     assert( obj->inherits( "KParts::ReadOnlyPart" ) );
05158     const KParts::ReadOnlyPart* const part = static_cast<const KParts::ReadOnlyPart *>( obj );
05159 
05160     FrameIt it = d->m_frames.begin();
05161     const FrameIt end = d->m_frames.end();
05162     for (; it != end; ++it )
05163       if ( (KParts::ReadOnlyPart *)(*it)->m_part == part )
05164         return *it;
05165 
05166     FrameIt oi = d->m_objects.begin();
05167     const FrameIt oiEnd = d->m_objects.end();
05168     for (; oi != oiEnd; ++oi )
05169       if ( (KParts::ReadOnlyPart *)(*oi)->m_part == part )
05170         return *oi;
05171 
05172     return 0L;
05173 }
05174 
05175 //#define DEBUG_FINDFRAME
05176 
05177 bool KHTMLPart::checkFrameAccess(KHTMLPart *callingHtmlPart)
05178 {
05179   if (callingHtmlPart == this)
05180     return true; // trivial
05181 
05182   if (htmlDocument().isNull()) {
05183 #ifdef DEBUG_FINDFRAME
05184     kdDebug(6050) << "KHTMLPart::checkFrameAccess: Empty part " << this << " URL = " << m_url << endl;
05185 #endif
05186     return false; // we are empty?
05187   }
05188 
05189   // now compare the domains
05190   if (callingHtmlPart && !callingHtmlPart->htmlDocument().isNull() &&
05191       !htmlDocument().isNull())  {
05192     DOM::DOMString actDomain = callingHtmlPart->htmlDocument().domain();
05193     DOM::DOMString destDomain = htmlDocument().domain();
05194 
05195 #ifdef DEBUG_FINDFRAME
05196     kdDebug(6050) << "KHTMLPart::checkFrameAccess: actDomain = '" << actDomain.string() << "' destDomain = '" << destDomain.string() << "'" << endl;
05197 #endif
05198 
05199     if (actDomain == destDomain)
05200       return true;
05201   }
05202 #ifdef DEBUG_FINDFRAME
05203   else
05204   {
05205     kdDebug(6050) << "KHTMLPart::checkFrameAccess: Unknown part/domain " << callingHtmlPart << " tries to access part " << this << endl;
05206   }
05207 #endif
05208   return false;
05209 }
05210 
05211 KHTMLPart *
05212 KHTMLPart::findFrameParent( KParts::ReadOnlyPart *callingPart, const QString &f, khtml::ChildFrame **childFrame )
05213 {
05214 #ifdef DEBUG_FINDFRAME
05215   kdDebug(6050) << "KHTMLPart::findFrameParent: this = " << this << " URL = " << m_url << " name = " << name() << " findFrameParent( " << f << " )" << endl;
05216 #endif
05217   // Check access
05218   KHTMLPart* const callingHtmlPart = dynamic_cast<KHTMLPart *>(callingPart);
05219 
05220   if (!checkFrameAccess(callingHtmlPart))
05221      return 0;
05222 
05223   // match encoding used in KonqView::setViewName()
05224   if (!childFrame && !parentPart() && (QString::fromLocal8Bit(name()) == f))
05225      return this;
05226 
05227   FrameIt it = d->m_frames.find( f );
05228   const FrameIt end = d->m_frames.end();
05229   if ( it != end )
05230   {
05231 #ifdef DEBUG_FINDFRAME
05232      kdDebug(6050) << "KHTMLPart::findFrameParent: FOUND!" << endl;
05233 #endif
05234      if (childFrame)
05235         *childFrame = *it;
05236      return this;
05237   }
05238 
05239   it = d->m_frames.begin();
05240   for (; it != end; ++it )
05241   {
05242     KParts::ReadOnlyPart* const p = (*it)->m_part;
05243     if ( p && p->inherits( "KHTMLPart" ))
05244     {
05245       KHTMLPart* const frameParent = static_cast<KHTMLPart*>(p)->findFrameParent(callingPart, f, childFrame);
05246       if (frameParent)
05247          return frameParent;
05248     }
05249   }
05250   return 0;
05251 }
05252 
05253 
05254 KHTMLPart *KHTMLPart::findFrame( const QString &f )
05255 {
05256   khtml::ChildFrame *childFrame;
05257   KHTMLPart *parentFrame = findFrameParent(this, f, &childFrame);
05258   if (parentFrame)
05259   {
05260      KParts::ReadOnlyPart *p = childFrame->m_part;
05261      if ( p && p->inherits( "KHTMLPart" ))
05262         return static_cast<KHTMLPart *>(p);
05263   }
05264   return 0;
05265 }
05266 
05267 KParts::ReadOnlyPart *KHTMLPart::findFramePart(const QString &f)
05268 {
05269   khtml::ChildFrame *childFrame;
05270   return findFrameParent(this, f, &childFrame) ? static_cast<KParts::ReadOnlyPart *>(childFrame->m_part) : 0L;
05271 }
05272 
05273 KParts::ReadOnlyPart *KHTMLPart::currentFrame() const
05274 {
05275   KParts::ReadOnlyPart* part = (KParts::ReadOnlyPart*)(this);
05276   // Find active part in our frame manager, in case we are a frameset
05277   // and keep doing that (in case of nested framesets).
05278   // Just realized we could also do this recursively, calling part->currentFrame()...
05279   while ( part && part->inherits("KHTMLPart") &&
05280           static_cast<KHTMLPart *>(part)->d->m_frames.count() > 0 ) {
05281     KHTMLPart* frameset = static_cast<KHTMLPart *>(part);
05282     part = static_cast<KParts::ReadOnlyPart *>(frameset->partManager()->activePart());
05283     if ( !part ) return frameset;
05284   }
05285   return part;
05286 }
05287 
05288 bool KHTMLPart::frameExists( const QString &frameName )
05289 {
05290   ConstFrameIt it = d->m_frames.find( frameName );
05291   if ( it == d->m_frames.end() )
05292     return false;
05293 
05294   // WABA: We only return true if the child actually has a frame
05295   // set. Otherwise we might find our preloaded-selve.
05296   // This happens when we restore the frameset.
05297   return (!(*it)->m_frame.isNull());
05298 }
05299 
05300 KJSProxy *KHTMLPart::framejScript(KParts::ReadOnlyPart *framePart)
05301 {
05302   KHTMLPart* const kp = ::qt_cast<KHTMLPart*>(framePart);
05303   if (kp)
05304     return kp->jScript();
05305 
05306   FrameIt it = d->m_frames.begin();
05307   const FrameIt itEnd = d->m_frames.end();
05308 
05309   for (; it != itEnd; ++it)
05310     if (framePart == (*it)->m_part) {
05311       if (!(*it)->m_jscript)
05312         createJScript(*it);
05313       return (*it)->m_jscript;
05314     }
05315   return 0L;
05316 }
05317 
05318 KHTMLPart *KHTMLPart::parentPart()
05319 {
05320   return ::qt_cast<KHTMLPart *>( parent() );
05321 }
05322 
05323 khtml::ChildFrame *KHTMLPart::recursiveFrameRequest( KHTMLPart *callingHtmlPart, const KURL &url,
05324                                                      const KParts::URLArgs &args, bool callParent )
05325 {
05326 #ifdef DEBUG_FINDFRAME
05327   kdDebug( 6050 ) << "KHTMLPart::recursiveFrameRequest this = " << this << ", frame = " << args.frameName << ", url = " << url << endl;
05328 #endif
05329   khtml::ChildFrame *childFrame;
05330   KHTMLPart *childPart = findFrameParent(callingHtmlPart, args.frameName, &childFrame);
05331   if (childPart)
05332   {
05333      if (childPart == this)
05334         return childFrame;
05335 
05336      childPart->requestObject( childFrame, url, args );
05337      return 0;
05338   }
05339 
05340   if ( parentPart() && callParent )
05341   {
05342      khtml::ChildFrame *res = parentPart()->recursiveFrameRequest( callingHtmlPart, url, args, callParent );
05343 
05344      if ( res )
05345        parentPart()->requestObject( res, url, args );
05346   }
05347 
05348   return 0L;
05349 }
05350 
05351 #ifndef NDEBUG
05352 static int s_saveStateIndentLevel = 0;
05353 #endif
05354 
05355 void KHTMLPart::saveState( QDataStream &stream )
05356 {
05357 #ifndef NDEBUG
05358   QString indent = QString().leftJustify( s_saveStateIndentLevel * 4, ' ' );
05359   const int indentLevel = s_saveStateIndentLevel++;
05360   kdDebug( 6050 ) << indent << "saveState this=" << this << " '" << name() << "' saving URL " << m_url.url() << endl;
05361 #endif
05362 
05363   stream << m_url << (Q_INT32)d->m_view->contentsX() << (Q_INT32)d->m_view->contentsY()
05364          << (Q_INT32) d->m_view->contentsWidth() << (Q_INT32) d->m_view->contentsHeight() << (Q_INT32) d->m_view->marginWidth() << (Q_INT32) d->m_view->marginHeight();
05365 
05366   // save link cursor position
05367   int focusNodeNumber;
05368   if (!d->m_focusNodeRestored)
05369       focusNodeNumber = d->m_focusNodeNumber;
05370   else if (d->m_doc && d->m_doc->focusNode())
05371       focusNodeNumber = d->m_doc->nodeAbsIndex(d->m_doc->focusNode());
05372   else
05373       focusNodeNumber = -1;
05374   stream << focusNodeNumber;
05375 
05376   // Save the doc's cache id.
05377   stream << d->m_cacheId;
05378 
05379   // Save the state of the document (Most notably the state of any forms)
05380   QStringList docState;
05381   if (d->m_doc)
05382   {
05383      docState = d->m_doc->docState();
05384   }
05385   stream << d->m_encoding << d->m_sheetUsed << docState;
05386 
05387   stream << d->m_zoomFactor;
05388 
05389   stream << d->m_httpHeaders;
05390   stream << d->m_pageServices;
05391   stream << d->m_pageReferrer;
05392 
05393   // Save ssl data
05394   stream << d->m_ssl_in_use
05395          << d->m_ssl_peer_certificate
05396          << d->m_ssl_peer_chain
05397          << d->m_ssl_peer_ip
05398          << d->m_ssl_cipher
05399          << d->m_ssl_cipher_desc
05400          << d->m_ssl_cipher_version
05401          << d->m_ssl_cipher_used_bits
05402          << d->m_ssl_cipher_bits
05403          << d->m_ssl_cert_state
05404          << d->m_ssl_parent_ip
05405          << d->m_ssl_parent_cert;
05406 
05407 
05408   QStringList frameNameLst, frameServiceTypeLst, frameServiceNameLst;
05409   KURL::List frameURLLst;
05410   QValueList<QByteArray> frameStateBufferLst;
05411 
05412   ConstFrameIt it = d->m_frames.begin();
05413   const ConstFrameIt end = d->m_frames.end();
05414   for (; it != end; ++it )
05415   {
05416     if ( !(*it)->m_part )
05417        continue;
05418 
05419     frameNameLst << (*it)->m_name;
05420     frameServiceTypeLst << (*it)->m_serviceType;
05421     frameServiceNameLst << (*it)->m_serviceName;
05422     frameURLLst << (*it)->m_part->url();
05423 
05424     QByteArray state;
05425     QDataStream frameStream( state, IO_WriteOnly );
05426 
05427     if ( (*it)->m_extension )
05428       (*it)->m_extension->saveState( frameStream );
05429 
05430     frameStateBufferLst << state;
05431   }
05432 
05433   // Save frame data
05434   stream << (Q_UINT32) frameNameLst.count();
05435   stream << frameNameLst << frameServiceTypeLst << frameServiceNameLst << frameURLLst << frameStateBufferLst;
05436 #ifndef NDEBUG
05437   s_saveStateIndentLevel = indentLevel;
05438 #endif
05439 }
05440 
05441 void KHTMLPart::restoreState( QDataStream &stream )
05442 {
05443   KURL u;
05444   Q_INT32 xOffset, yOffset, wContents, hContents, mWidth, mHeight;
05445   Q_UINT32 frameCount;
05446   QStringList frameNames, frameServiceTypes, docState, frameServiceNames;
05447   KURL::List frameURLs;
05448   QValueList<QByteArray> frameStateBuffers;
05449   QValueList<int> fSizes;
05450   QString encoding, sheetUsed;
05451   long old_cacheId = d->m_cacheId;
05452 
05453   stream >> u >> xOffset >> yOffset >> wContents >> hContents >> mWidth >> mHeight;
05454 
05455   d->m_view->setMarginWidth( mWidth );
05456   d->m_view->setMarginHeight( mHeight );
05457 
05458   // restore link cursor position
05459   // nth node is active. value is set in checkCompleted()
05460   stream >> d->m_focusNodeNumber;
05461   d->m_focusNodeRestored = false;
05462 
05463   stream >> d->m_cacheId;
05464 
05465   stream >> encoding >> sheetUsed >> docState;
05466 
05467   d->m_encoding = encoding;
05468   d->m_sheetUsed = sheetUsed;
05469 
05470   int zoomFactor;
05471   stream >> zoomFactor;
05472   setZoomFactor(zoomFactor);
05473 
05474   stream >> d->m_httpHeaders;
05475   stream >> d->m_pageServices;
05476   stream >> d->m_pageReferrer;
05477 
05478   // Restore ssl data
05479   stream >> d->m_ssl_in_use
05480          >> d->m_ssl_peer_certificate
05481          >> d->m_ssl_peer_chain
05482          >> d->m_ssl_peer_ip
05483          >> d->m_ssl_cipher
05484          >> d->m_ssl_cipher_desc
05485          >> d->m_ssl_cipher_version
05486          >> d->m_ssl_cipher_used_bits
05487          >> d->m_ssl_cipher_bits
05488          >> d->m_ssl_cert_state
05489          >> d->m_ssl_parent_ip
05490          >> d->m_ssl_parent_cert;
05491 
05492   setPageSecurity( d->m_ssl_in_use ? Encrypted : NotCrypted );
05493 
05494   stream >> frameCount >> frameNames >> frameServiceTypes >> frameServiceNames
05495          >> frameURLs >> frameStateBuffers;
05496 
05497   d->m_bComplete = false;
05498   d->m_bLoadEventEmitted = false;
05499 
05500 //   kdDebug( 6050 ) << "restoreState() docState.count() = " << docState.count() << endl;
05501 //   kdDebug( 6050 ) << "m_url " << m_url.url() << " <-> " << u.url() << endl;
05502 //   kdDebug( 6050 ) << "m_frames.count() " << d->m_frames.count() << " <-> " << frameCount << endl;
05503 
05504   if (d->m_cacheId == old_cacheId)
05505   {
05506     // Partial restore
05507     d->m_redirectionTimer.stop();
05508 
05509     FrameIt fIt = d->m_frames.begin();
05510     const FrameIt fEnd = d->m_frames.end();
05511 
05512     for (; fIt != fEnd; ++fIt )
05513         (*fIt)->m_bCompleted = false;
05514 
05515     fIt = d->m_frames.begin();
05516 
05517     QStringList::ConstIterator fNameIt = frameNames.begin();
05518     QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
05519     QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
05520     KURL::List::ConstIterator fURLIt = frameURLs.begin();
05521     QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
05522 
05523     for (; fIt != fEnd; ++fIt, ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
05524     {
05525       khtml::ChildFrame* const child = *fIt;
05526 
05527 //      kdDebug( 6050 ) <<  *fNameIt  << " ---- " <<  *fServiceTypeIt << endl;
05528 
05529       if ( child->m_name != *fNameIt || child->m_serviceType != *fServiceTypeIt )
05530       {
05531         child->m_bPreloaded = true;
05532         child->m_name = *fNameIt;
05533         child->m_serviceName = *fServiceNameIt;
05534         processObjectRequest( child, *fURLIt, *fServiceTypeIt );
05535       }
05536       if ( child->m_part )
05537       {
05538         child->m_bCompleted = false;
05539         if ( child->m_extension && !(*fBufferIt).isEmpty() )
05540         {
05541           QDataStream frameStream( *fBufferIt, IO_ReadOnly );
05542           child->m_extension->restoreState( frameStream );
05543         }
05544         else
05545           child->m_part->openURL( *fURLIt );
05546       }
05547     }
05548 
05549     KParts::URLArgs args( d->m_extension->urlArgs() );
05550     args.xOffset = xOffset;
05551     args.yOffset = yOffset;
05552     args.docState = docState;
05553     d->m_extension->setURLArgs( args );
05554 
05555     d->m_view->resizeContents( wContents,  hContents);
05556     d->m_view->setContentsPos( xOffset, yOffset );
05557 
05558     m_url = u;
05559   }
05560   else
05561   {
05562     // Full restore.
05563     closeURL();
05564     // We must force a clear because we want to be sure to delete all
05565     // frames.
05566     d->m_bCleared = false;
05567     clear();
05568     d->m_encoding = encoding;
05569     d->m_sheetUsed = sheetUsed;
05570 
05571     QStringList::ConstIterator fNameIt = frameNames.begin();
05572     const QStringList::ConstIterator fNameEnd = frameNames.end();
05573 
05574     QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
05575     QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
05576     KURL::List::ConstIterator fURLIt = frameURLs.begin();
05577     QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
05578 
05579     for (; fNameIt != fNameEnd; ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
05580     {
05581       khtml::ChildFrame* const newChild = new khtml::ChildFrame;
05582       newChild->m_bPreloaded = true;
05583       newChild->m_name = *fNameIt;
05584       newChild->m_serviceName = *fServiceNameIt;
05585 
05586 //      kdDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt << endl;
05587 
05588       const FrameIt childFrame = d->m_frames.append( newChild );
05589 
05590       processObjectRequest( *childFrame, *fURLIt, *fServiceTypeIt );
05591 
05592       (*childFrame)->m_bPreloaded = true;
05593 
05594       if ( (*childFrame)->m_part )
05595       {
05596         if ( (*childFrame)->m_extension )
05597         if ( (*childFrame)->m_extension && !(*fBufferIt).isEmpty() )
05598         {
05599           QDataStream frameStream( *fBufferIt, IO_ReadOnly );
05600           (*childFrame)->m_extension->restoreState( frameStream );
05601         }
05602         else
05603           (*childFrame)->m_part->openURL( *fURLIt );
05604       }
05605     }
05606 
05607     KParts::URLArgs args( d->m_extension->urlArgs() );
05608     args.xOffset = xOffset;
05609     args.yOffset = yOffset;
05610     args.docState = docState;
05611 
05612     d->m_extension->setURLArgs( args );
05613     if (!KHTMLPageCache::self()->isComplete(d->m_cacheId))
05614     {
05615        d->m_restored = true;
05616        openURL( u );
05617        d->m_restored = false;
05618     }
05619     else
05620     {
05621        restoreURL( u );
05622     }
05623   }
05624 
05625 }
05626 
05627 void KHTMLPart::show()
05628 {
05629   if ( d->m_view )
05630     d->m_view->show();
05631 }
05632 
05633 void KHTMLPart::hide()
05634 {
05635   if ( d->m_view )
05636     d->m_view->hide();
05637 }
05638 
05639 DOM::Node KHTMLPart::nodeUnderMouse() const
05640 {
05641     return d->m_view->nodeUnderMouse();
05642 }
05643 
05644 DOM::Node KHTMLPart::nonSharedNodeUnderMouse() const
05645 {
05646     return d->m_view->nonSharedNodeUnderMouse();
05647 }
05648 
05649 void KHTMLPart::emitSelectionChanged()
05650 {
05651   emit d->m_extension->enableAction( "copy", hasSelection() );
05652   if ( d->m_findDialog )
05653        d->m_findDialog->setHasSelection( hasSelection() );
05654 
05655   emit d->m_extension->selectionInfo( selectedText() );
05656   emit selectionChanged();
05657 }
05658 
05659 int KHTMLPart::zoomFactor() const
05660 {
05661   return d->m_zoomFactor;
05662 }
05663 
05664 // ### make the list configurable ?
05665 static const int zoomSizes[] = { 20, 40, 60, 80, 90, 95, 100, 105, 110, 120, 140, 160, 180, 200, 250, 300 };
05666 static const int zoomSizeCount = (sizeof(zoomSizes) / sizeof(int));
05667 static const int minZoom = 20;
05668 static const int maxZoom = 300;
05669 
05670 // My idea of useful stepping ;-) (LS)
05671 extern const int KDE_NO_EXPORT fastZoomSizes[] = { 20, 50, 75, 90, 100, 120, 150, 200, 300 };
05672 extern const int KDE_NO_EXPORT fastZoomSizeCount = sizeof fastZoomSizes / sizeof fastZoomSizes[0];
05673 
05674 void KHTMLPart::slotIncZoom()
05675 {
05676   zoomIn(zoomSizes, zoomSizeCount);
05677 }
05678 
05679 void KHTMLPart::slotDecZoom()
05680 {
05681   zoomOut(zoomSizes, zoomSizeCount);
05682 }
05683 
05684 void KHTMLPart::slotIncZoomFast()
05685 {
05686   zoomIn(fastZoomSizes, fastZoomSizeCount);
05687 }
05688 
05689 void KHTMLPart::slotDecZoomFast()
05690 {
05691   zoomOut(fastZoomSizes, fastZoomSizeCount);
05692 }
05693 
05694 void KHTMLPart::zoomIn(const int stepping[], int count)
05695 {
05696   int zoomFactor = d->m_zoomFactor;
05697 
05698   if (zoomFactor < maxZoom) {
05699     // find the entry nearest to the given zoomsizes
05700     for (int i = 0; i < count; ++i)
05701       if (stepping[i] > zoomFactor) {
05702         zoomFactor = stepping[i];
05703         break;
05704       }
05705     setZoomFactor(zoomFactor);
05706   }
05707 }
05708 
05709 void KHTMLPart::zoomOut(const int stepping[], int count)
05710 {
05711     int zoomFactor = d->m_zoomFactor;
05712     if (zoomFactor > minZoom) {
05713       // find the entry nearest to the given zoomsizes
05714       for (int i = count-1; i >= 0; --i)
05715         if (stepping[i] < zoomFactor) {
05716           zoomFactor = stepping[i];
05717           break;
05718         }
05719       setZoomFactor(zoomFactor);
05720     }
05721 }
05722 
05723 void KHTMLPart::setZoomFactor (int percent)
05724 {
05725   if (percent < minZoom) percent = minZoom;
05726   if (percent > maxZoom) percent = maxZoom;
05727   if (d->m_zoomFactor == percent) return;
05728   d->m_zoomFactor = percent;
05729 
05730   if(d->m_doc) {
05731       QApplication::setOverrideCursor( waitCursor );
05732     if (d->m_doc->styleSelector())
05733       d->m_doc->styleSelector()->computeFontSizes(d->m_doc->paintDeviceMetrics(), d->m_zoomFactor);
05734     d->m_doc->recalcStyle( NodeImpl::Force );
05735     QApplication::restoreOverrideCursor();
05736   }
05737 
05738   ConstFrameIt it = d->m_frames.begin();
05739   const ConstFrameIt end = d->m_frames.end();
05740   for (; it != end; ++it )
05741     if ( !( *it )->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
05742       KParts::ReadOnlyPart* const p = ( *it )->m_part;
05743       static_cast<KHTMLPart*>( p )->setZoomFactor(d->m_zoomFactor);
05744     }
05745 
05746   if ( d->m_guiProfile == BrowserViewGUI ) {
05747       d->m_paDecZoomFactor->setEnabled( d->m_zoomFactor > minZoom );
05748       d->m_paIncZoomFactor->setEnabled( d->m_zoomFactor < maxZoom );
05749   }
05750 }
05751 
05752 void KHTMLPart::slotZoomView( int delta )
05753 {
05754   if ( delta < 0 )
05755     slotIncZoom();
05756   else
05757     slotDecZoom();
05758 }
05759 
05760 void KHTMLPart::setStatusBarText( const QString& text, StatusBarPriority p)
05761 {
05762   if (!d->m_statusMessagesEnabled)
05763     return;
05764 
05765   d->m_statusBarText[p] = text;
05766 
05767   // shift handling ?
05768   QString tobe = d->m_statusBarText[BarHoverText];
05769   if (tobe.isEmpty())
05770     tobe = d->m_statusBarText[BarOverrideText];
05771   if (tobe.isEmpty()) {
05772     tobe = d->m_statusBarText[BarDefaultText];
05773     if (!tobe.isEmpty() && d->m_jobspeed)
05774       tobe += " ";
05775     if (d->m_jobspeed)
05776       tobe += i18n( "(%1/s)" ).arg( KIO::convertSize( d->m_jobspeed ) );
05777   }
05778   tobe = "<qt>"+tobe;
05779 
05780   emit ReadOnlyPart::setStatusBarText(tobe);
05781 }
05782 
05783 
05784 void KHTMLPart::setJSStatusBarText( const QString &text )
05785 {
05786   setStatusBarText(text, BarOverrideText);
05787 }
05788 
05789 void KHTMLPart::setJSDefaultStatusBarText( const QString &text )
05790 {
05791   setStatusBarText(text, BarDefaultText);
05792 }
05793 
05794 QString KHTMLPart::jsStatusBarText() const
05795 {
05796     return d->m_statusBarText[BarOverrideText];
05797 }
05798 
05799 QString KHTMLPart::jsDefaultStatusBarText() const
05800 {
05801    return d->m_statusBarText[BarDefaultText];
05802 }
05803 
05804 QString KHTMLPart::referrer() const
05805 {
05806    return d->m_referrer;
05807 }
05808 
05809 QString KHTMLPart::pageReferrer() const
05810 {
05811    KURL referrerURL = KURL( d->m_pageReferrer );
05812    if (referrerURL.isValid())
05813    {
05814       QString protocol = referrerURL.protocol();
05815 
05816       if ((protocol == "http") ||
05817          ((protocol == "https") && (m_url.protocol() == "https")))
05818       {
05819           referrerURL.setRef(QString::null);
05820           referrerURL.setUser(QString::null);
05821           referrerURL.setPass(QString::null);
05822           return referrerURL.url();
05823       }
05824    }
05825 
05826    return QString::null;
05827 }
05828 
05829 
05830 QString KHTMLPart::lastModified() const
05831 {
05832   if ( d->m_lastModified.isEmpty() && m_url.isLocalFile() ) {
05833     // Local file: set last-modified from the file's mtime.
05834     // Done on demand to save time when this isn't needed - but can lead
05835     // to slightly wrong results if updating the file on disk w/o reloading.
05836     QDateTime lastModif = QFileInfo( m_url.path() ).lastModified();
05837     d->m_lastModified = lastModif.toString( Qt::LocalDate );
05838   }
05839   //kdDebug(6050) << "KHTMLPart::lastModified: " << d->m_lastModified << endl;
05840   return d->m_lastModified;
05841 }
05842 
05843 void KHTMLPart::slotLoadImages()
05844 {
05845   if (d->m_doc )
05846     d->m_doc->docLoader()->setAutoloadImages( !d->m_doc->docLoader()->autoloadImages() );
05847 
05848   ConstFrameIt it = d->m_frames.begin();
05849   const ConstFrameIt end = d->m_frames.end();
05850   for (; it != end; ++it )
05851     if ( !( *it )->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
05852       KParts::ReadOnlyPart* const p = ( *it )->m_part;
05853       static_cast<KHTMLPart*>( p )->slotLoadImages();
05854     }
05855 }
05856 
05857 void KHTMLPart::reparseConfiguration()
05858 {
05859   KHTMLSettings *settings = KHTMLFactory::defaultHTMLSettings();
05860   settings->init();
05861 
05862   setAutoloadImages( settings->autoLoadImages() );
05863   if (d->m_doc)
05864      d->m_doc->docLoader()->setShowAnimations( settings->showAnimations() );
05865 
05866   d->m_bOpenMiddleClick = settings->isOpenMiddleClickEnabled();
05867   d->m_bBackRightClick = settings->isBackRightClickEnabled();
05868   d->m_bJScriptEnabled = settings->isJavaScriptEnabled(m_url.host());
05869   setDebugScript( settings->isJavaScriptDebugEnabled() );
05870   d->m_bJavaEnabled = settings->isJavaEnabled(m_url.host());
05871   d->m_bPluginsEnabled = settings->isPluginsEnabled(m_url.host());
05872   d->m_metaRefreshEnabled = settings->isAutoDelayedActionsEnabled ();
05873 
05874   delete d->m_settings;
05875   d->m_settings = new KHTMLSettings(*KHTMLFactory::defaultHTMLSettings());
05876 
05877   QApplication::setOverrideCursor( waitCursor );
05878   khtml::CSSStyleSelector::reparseConfiguration();
05879   if(d->m_doc) d->m_doc->updateStyleSelector();
05880   QApplication::restoreOverrideCursor();
05881 
05882   if (KHTMLFactory::defaultHTMLSettings()->isAdFilterEnabled())
05883      runAdFilter();
05884 }
05885 
05886 QStringList KHTMLPart::frameNames() const
05887 {
05888   QStringList res;
05889 
05890   ConstFrameIt it = d->m_frames.begin();
05891   const ConstFrameIt end = d->m_frames.end();
05892   for (; it != end; ++it )
05893     if (!(*it)->m_bPreloaded)
05894       res += (*it)->m_name;
05895 
05896   return res;
05897 }
05898 
05899 QPtrList<KParts::ReadOnlyPart> KHTMLPart::frames() const
05900 {
05901   QPtrList<KParts::ReadOnlyPart> res;
05902 
05903   ConstFrameIt it = d->m_frames.begin();
05904   const ConstFrameIt end = d->m_frames.end();
05905   for (; it != end; ++it )
05906     if (!(*it)->m_bPreloaded)
05907       res.append( (*it)->m_part );
05908 
05909   return res;
05910 }
05911 
05912 bool KHTMLPart::openURLInFrame( const KURL &url, const KParts::URLArgs &urlArgs )
05913 {
05914     kdDebug( 6050 ) << this << "KHTMLPart::openURLInFrame " << url << endl;
05915   FrameIt it = d->m_frames.find( urlArgs.frameName );
05916 
05917   if ( it == d->m_frames.end() )
05918     return false;
05919 
05920   // Inform someone that we are about to show something else.
05921   if ( !urlArgs.lockHistory() )
05922       emit d->m_extension->openURLNotify();
05923 
05924   requestObject( *it, url, urlArgs );
05925 
05926   return true;
05927 }
05928 
05929 void KHTMLPart::setDNDEnabled( bool b )
05930 {
05931   d->m_bDnd = b;
05932 }
05933 
05934 bool KHTMLPart::dndEnabled() const
05935 {
05936   return d->m_bDnd;
05937 }
05938 
05939 void KHTMLPart::customEvent( QCustomEvent *event )
05940 {
05941   if ( khtml::MousePressEvent::test( event ) )
05942   {
05943     khtmlMousePressEvent( static_cast<khtml::MousePressEvent *>( event ) );
05944     return;
05945   }
05946 
05947   if ( khtml::MouseDoubleClickEvent::test( event ) )
05948   {
05949     khtmlMouseDoubleClickEvent( static_cast<khtml::MouseDoubleClickEvent *>( event ) );
05950     return;
05951   }
05952 
05953   if ( khtml::MouseMoveEvent::test( event ) )
05954   {
05955     khtmlMouseMoveEvent( static_cast<khtml::MouseMoveEvent *>( event ) );
05956     return;
05957   }
05958 
05959   if ( khtml::MouseReleaseEvent::test( event ) )
05960   {
05961     khtmlMouseReleaseEvent( static_cast<khtml::MouseReleaseEvent *>( event ) );
05962     return;
05963   }
05964 
05965   if ( khtml::DrawContentsEvent::test( event ) )
05966   {
05967     khtmlDrawContentsEvent( static_cast<khtml::DrawContentsEvent *>( event ) );
05968     return;
05969   }
05970 
05971   KParts::ReadOnlyPart::customEvent( event );
05972 }
05973 
05979 static bool firstRunAt(khtml::RenderObject *renderNode, int y, NodeImpl *&startNode, long &startOffset)
05980 {
05981     for (khtml::RenderObject *n = renderNode; n; n = n->nextSibling()) {
05982         if (n->isText()) {
05983             khtml::RenderText* const textRenderer = static_cast<khtml::RenderText *>(n);
05984             const khtml::InlineTextBoxArray &runs = textRenderer->inlineTextBoxes();
05985             const unsigned lim = runs.count();
05986             for (unsigned i = 0; i != lim; ++i) {
05987                 if (runs[i]->m_y == y && textRenderer->element()) {
05988                     startNode = textRenderer->element();
05989                     startOffset = runs[i]->m_start;
05990                     return true;
05991                 }
05992             }
05993         }
05994 
05995         if (firstRunAt(n->firstChild(), y, startNode, startOffset)) {
05996             return true;
05997         }
05998     }
05999 
06000     return false;
06001 }
06002 
06008 static bool lastRunAt(khtml::RenderObject *renderNode, int y, NodeImpl *&endNode, long &endOffset)
06009 {
06010     khtml::RenderObject *n = renderNode;
06011     if (!n) {
06012         return false;
06013     }
06014     khtml::RenderObject *next;
06015     while ((next = n->nextSibling())) {
06016         n = next;
06017     }
06018 
06019     while (1) {
06020         if (lastRunAt(n->firstChild(), y, endNode, endOffset)) {
06021             return true;
06022         }
06023 
06024         if (n->isText()) {
06025             khtml::RenderText* const textRenderer =  static_cast<khtml::RenderText *>(n);
06026             const khtml::InlineTextBoxArray &runs = textRenderer->inlineTextBoxes();
06027             for (int i = (int)runs.count()-1; i >= 0; --i) {
06028                 if (runs[i]->m_y == y && textRenderer->element()) {
06029                     endNode = textRenderer->element();
06030                     endOffset = runs[i]->m_start + runs[i]->m_len;
06031                     return true;
06032                 }
06033             }
06034         }
06035 
06036         if (n == renderNode) {
06037             return false;
06038         }
06039 
06040         n = n->previousSibling();
06041     }
06042 }
06043 
06044 void KHTMLPart::khtmlMousePressEvent( khtml::MousePressEvent *event )
06045 {
06046   DOM::DOMString url = event->url();
06047   QMouseEvent *_mouse = event->qmouseEvent();
06048   DOM::Node innerNode = event->innerNode();
06049   d->m_mousePressNode = innerNode;
06050 
06051    d->m_dragStartPos = _mouse->pos();
06052 
06053    if ( !event->url().isNull() ) {
06054      d->m_strSelectedURL = event->url().string();
06055      d->m_strSelectedURLTarget = event->target().string();
06056    }
06057    else
06058      d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
06059 
06060   if ( _mouse->button() == LeftButton ||
06061        _mouse->button() == MidButton )
06062   {
06063     d->m_bMousePressed = true;
06064 
06065 #ifndef KHTML_NO_SELECTION
06066     if ( _mouse->button() == LeftButton )
06067     {
06068       if ( (!d->m_strSelectedURL.isNull() && !isEditable())
06069             || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) )
06070       return;
06071       if ( !innerNode.isNull()  && innerNode.handle()->renderer()) {
06072           int offset = 0;
06073           DOM::NodeImpl* node = 0;
06074           khtml::RenderObject::SelPointState state;
06075           innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(),
06076                                                                event->absX()-innerNode.handle()->renderer()->xPos(),
06077                                                                event->absY()-innerNode.handle()->renderer()->yPos(), node, offset, state );
06078           d->m_extendMode = d->ExtendByChar;
06079 #ifdef KHTML_NO_CARET
06080           d->m_selectionStart = node;
06081           d->m_startOffset = offset;
06082           //if ( node )
06083           //  kdDebug(6005) << "KHTMLPart::khtmlMousePressEvent selectionStart=" << d->m_selectionStart.handle()->renderer()
06084           //                << " offset=" << d->m_startOffset << endl;
06085           //else
06086           //  kdDebug(6005) << "KHTML::khtmlMousePressEvent selectionStart=(nil)" << endl;
06087           d->m_selectionEnd = d->m_selectionStart;
06088           d->m_endOffset = d->m_startOffset;
06089           d->m_doc->clearSelection();
06090 #else // KHTML_NO_CARET
06091       d->m_view->moveCaretTo(node, offset, (_mouse->state() & ShiftButton) == 0);
06092 #endif // KHTML_NO_CARET
06093       d->m_initialNode = d->m_selectionStart;
06094       d->m_initialOffset = d->m_startOffset;
06095 //           kdDebug(6000) << "press: initOfs " << d->m_initialOffset << endl;
06096       }
06097       else
06098       {
06099 #ifndef KHTML_NO_CARET
06100         // simply leave it. Is this a good idea?
06101 #else
06102         d->m_selectionStart = DOM::Node();
06103         d->m_selectionEnd = DOM::Node();
06104 #endif
06105       }
06106       emitSelectionChanged();
06107       startAutoScroll();
06108     }
06109 #else
06110     d->m_dragLastPos = _mouse->globalPos();
06111 #endif
06112   }
06113 
06114   if ( _mouse->button() == RightButton && parentPart() != 0 && d->m_bBackRightClick )
06115   {
06116     d->m_bRightMousePressed = true;
06117   } else if ( _mouse->button() == RightButton )
06118   {
06119     popupMenu( d->m_strSelectedURL );
06120     // might be deleted, don't touch "this"
06121   }
06122 }
06123 
06124 void KHTMLPart::khtmlMouseDoubleClickEvent( khtml::MouseDoubleClickEvent *event )
06125 {
06126   QMouseEvent *_mouse = event->qmouseEvent();
06127   if ( _mouse->button() == LeftButton )
06128   {
06129     d->m_bMousePressed = true;
06130     DOM::Node innerNode = event->innerNode();
06131     // Find selectionStart again, khtmlMouseReleaseEvent lost it
06132     if ( !innerNode.isNull() && innerNode.handle()->renderer()) {
06133       int offset = 0;
06134       DOM::NodeImpl* node = 0;
06135       khtml::RenderObject::SelPointState state;
06136       innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(),
06137                                                            event->absX()-innerNode.handle()->renderer()->xPos(),
06138                                                            event->absY()-innerNode.handle()->renderer()->yPos(), node, offset, state);
06139 
06140       //kdDebug() << k_funcinfo << "checkSelectionPoint returned node=" << node << " offset=" << offset << endl;
06141 
06142       if ( node && node->renderer() )
06143       {
06144         // Extend selection to a complete word (double-click) or line (triple-click)
06145         bool selectLine = (event->clickCount() == 3);
06146         d->m_extendMode = selectLine ? d->ExtendByLine : d->ExtendByWord;
06147 
06148     // Extend existing selection if Shift was pressed
06149     if (_mouse->state() & ShiftButton) {
06150           d->caretNode() = node;
06151       d->caretOffset() = offset;
06152           d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
06153                 d->m_selectionStart.handle(), d->m_startOffset,
06154             d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
06155           d->m_initialNode = d->m_extendAtEnd ? d->m_selectionStart : d->m_selectionEnd;
06156           d->m_initialOffset = d->m_extendAtEnd ? d->m_startOffset : d->m_endOffset;
06157     } else {
06158       d->m_selectionStart = d->m_selectionEnd = node;
06159       d->m_startOffset = d->m_endOffset = offset;
06160           d->m_startBeforeEnd = true;
06161           d->m_initialNode = node;
06162           d->m_initialOffset = offset;
06163     }
06164 //         kdDebug(6000) << "dblclk: initOfs " << d->m_initialOffset << endl;
06165 
06166         // Extend the start
06167         extendSelection( d->m_selectionStart.handle(), d->m_startOffset, d->m_selectionStart, d->m_startOffset, !d->m_startBeforeEnd, selectLine );
06168         // Extend the end
06169         extendSelection( d->m_selectionEnd.handle(), d->m_endOffset, d->m_selectionEnd, d->m_endOffset, d->m_startBeforeEnd, selectLine );
06170 
06171         //kdDebug() << d->m_selectionStart.handle() << " " << d->m_startOffset << "  -  " <<
06172         //  d->m_selectionEnd.handle() << " " << d->m_endOffset << endl;
06173 
06174         emitSelectionChanged();
06175         d->m_doc
06176           ->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
06177                          d->m_selectionEnd.handle(),d->m_endOffset);
06178 #ifndef KHTML_NO_CARET
06179         bool v = d->m_view->placeCaret();
06180         emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
06181 #endif
06182         startAutoScroll();
06183       }
06184     }
06185   }
06186 }
06187 
06188 void KHTMLPart::extendSelection( DOM::NodeImpl* node, long offset, DOM::Node& selectionNode, long& selectionOffset, bool right, bool selectLines )
06189 {
06190   khtml::RenderObject* obj = node->renderer();
06191 
06192   if (obj->isText() && selectLines) {
06193     int pos;
06194     khtml::RenderText *renderer = static_cast<khtml::RenderText *>(obj);
06195     khtml::InlineTextBox *run = renderer->findInlineTextBox( offset, pos );
06196     DOMString t = node->nodeValue();
06197     DOM::NodeImpl* selNode = 0;
06198     long selOfs = 0;
06199 
06200     if (!run)
06201       return;
06202 
06203     int selectionPointY = run->m_y;
06204 
06205     // Go up to first non-inline element.
06206     khtml::RenderObject *renderNode = renderer;
06207     while (renderNode && renderNode->isInline())
06208       renderNode = renderNode->parent();
06209 
06210     renderNode = renderNode->firstChild();
06211 
06212     if (right) {
06213       // Look for all the last child in the block that is on the same line
06214       // as the selection point.
06215       if (!lastRunAt (renderNode, selectionPointY, selNode, selOfs))
06216         return;
06217     } else {
06218       // Look for all the first child in the block that is on the same line
06219       // as the selection point.
06220       if (!firstRunAt (renderNode, selectionPointY, selNode, selOfs))
06221         return;
06222     }
06223 
06224     selectionNode = selNode;
06225     selectionOffset = selOfs;
06226     return;
06227   }
06228 
06229   QString str;
06230   int len = 0;
06231   if ( obj->isText() ) { // can be false e.g. when double-clicking on a disabled submit button
06232     str = static_cast<khtml::RenderText *>(obj)->data().string();
06233     len = str.length();
06234   }
06235   //kdDebug() << "extendSelection right=" << right << " offset=" << offset << " len=" << len << " Starting at obj=" << obj << endl;
06236   QChar ch;
06237   do {
06238     // Last char was ok, point to it
06239     if ( node ) {
06240       selectionNode = node;
06241       selectionOffset = offset;
06242     }
06243 
06244     // Get another char
06245     while ( obj && ( (right && offset >= len-1) || (!right && offset <= 0) ) )
06246     {
06247       obj = right ? obj->objectBelow() : obj->objectAbove();
06248       //kdDebug() << "obj=" << obj << endl;
06249       if ( obj ) {
06250         //kdDebug() << "isText=" << obj->isText() << endl;
06251         str = QString::null;
06252         if ( obj->isText() )
06253           str = static_cast<khtml::RenderText *>(obj)->data().string();
06254         else if ( obj->isBR() )
06255           str = '\n';
06256         else if ( !obj->isInline() ) {
06257           obj = 0L; // parag limit -> done
06258           break;
06259         }
06260         len = str.length();
06261         //kdDebug() << "str=" << str << " length=" << len << endl;
06262         // set offset - note that the first thing will be a ++ or -- on it.
06263         if ( right )
06264           offset = -1;
06265         else
06266           offset = len;
06267       }
06268     }
06269     if ( !obj ) // end of parag or document
06270       break;
06271     node = obj->element();
06272     if ( right )
06273     {
06274       Q_ASSERT( offset < len-1 );
06275       ++offset;
06276     }
06277     else
06278     {
06279       Q_ASSERT( offset > 0 );
06280       --offset;
06281     }
06282 
06283     // Test that char
06284     ch = str[ (int)offset ];
06285     //kdDebug() << " offset=" << offset << " ch=" << QString(ch) << endl;
06286   } while ( !ch.isSpace() && !ch.isPunct() );
06287 
06288   // make offset point after last char
06289   if (right) ++selectionOffset;
06290 }
06291 
06292 #ifndef KHTML_NO_SELECTION
06293 void KHTMLPart::extendSelectionTo(int x, int y, int absX, int absY, const DOM::Node &innerNode)
06294 {
06295       int offset;
06296       //kdDebug(6000) << "KHTMLPart::khtmlMouseMoveEvent x=" << event->x() << " y=" << event->y() << endl;
06297       DOM::NodeImpl* node=0;
06298       khtml::RenderObject::SelPointState state;
06299       innerNode.handle()->renderer()->checkSelectionPoint( x, y,
06300                                                            absX-innerNode.handle()->renderer()->xPos(),
06301                                                            absY-innerNode.handle()->renderer()->yPos(), node, offset, state);
06302       if (!node || !node->renderer()) return;
06303 
06304       // Words at the beginning/end of line cannot be deselected in
06305       // ExtendByWord mode. Therefore, do not enforce it if the selection
06306       // point does not match the node under the mouse cursor.
06307       bool withinNode = innerNode == node;
06308 
06309       // we have to get to know if end is before start or not...
06310       // shouldn't be null but it can happen with dynamic updating of nodes
06311       if (d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() ||
06312           d->m_initialNode.isNull() ||
06313           !d->m_selectionStart.handle()->renderer() ||
06314           !d->m_selectionEnd.handle()->renderer()) return;
06315 
06316       if (d->m_extendMode != d->ExtendByChar) {
06317         // check whether we should extend at the front, or at the back
06318         bool caretBeforeInit = RangeImpl::compareBoundaryPoints(
06319                 d->caretNode().handle(), d->caretOffset(),
06320             d->m_initialNode.handle(), d->m_initialOffset) <= 0;
06321         bool nodeBeforeInit = RangeImpl::compareBoundaryPoints(node, offset,
06322             d->m_initialNode.handle(), d->m_initialOffset) <= 0;
06323         // have to fix up start to point to the original end
06324         if (caretBeforeInit != nodeBeforeInit) {
06325 //         kdDebug(6000) << "extto cbi: " << caretBeforeInit << " startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << " initOfs " << d->m_initialOffset << endl;
06326           extendSelection(d->m_initialNode.handle(), d->m_initialOffset,
06327         d->m_extendAtEnd ? d->m_selectionStart : d->m_selectionEnd,
06328         d->m_extendAtEnd ? d->m_startOffset : d->m_endOffset,
06329         nodeBeforeInit, d->m_extendMode == d->ExtendByLine);
06330     }
06331       }
06332 
06333       d->caretNode() = node;
06334       d->caretOffset() = offset;
06335       //kdDebug( 6000 ) << "setting end of selection to " << d->m_selectionEnd.handle() << "/" << d->m_endOffset << endl;
06336 
06337       d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
06338                 d->m_selectionStart.handle(), d->m_startOffset,
06339             d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
06340 
06341       if ( !d->m_selectionStart.isNull() && !d->m_selectionEnd.isNull() )
06342       {
06343 //         kdDebug(6000) << "extto: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << " initOfs " << d->m_initialOffset << endl;
06344         if (d->m_extendMode != d->ExtendByChar && withinNode)
06345           extendSelection( node, offset, d->caretNode(), d->caretOffset(), d->m_startBeforeEnd ^ !d->m_extendAtEnd, d->m_extendMode == d->ExtendByLine );
06346 
06347         if (d->m_selectionEnd == d->m_selectionStart && d->m_endOffset < d->m_startOffset)
06348           d->m_doc
06349             ->setSelection(d->m_selectionStart.handle(),d->m_endOffset,
06350                            d->m_selectionEnd.handle(),d->m_startOffset);
06351         else if (d->m_startBeforeEnd)
06352           d->m_doc
06353             ->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
06354                            d->m_selectionEnd.handle(),d->m_endOffset);
06355         else
06356           d->m_doc
06357             ->setSelection(d->m_selectionEnd.handle(),d->m_endOffset,
06358                            d->m_selectionStart.handle(),d->m_startOffset);
06359       }
06360 #ifndef KHTML_NO_CARET
06361       d->m_view->placeCaret();
06362 #endif
06363 }
06364 
06365 bool KHTMLPart::isExtendingSelection() const
06366 {
06367   // This is it, the whole detection. khtmlMousePressEvent only sets this
06368   // on LMB or MMB, but never on RMB. As text selection doesn't work for MMB,
06369   // it's sufficient to only rely on this flag to detect selection extension.
06370   return d->m_bMousePressed;
06371 }
06372 #endif // KHTML_NO_SELECTION
06373 
06374 void KHTMLPart::khtmlMouseMoveEvent( khtml::MouseMoveEvent *event )
06375 {
06376   QMouseEvent *_mouse = event->qmouseEvent();
06377 
06378   if( d->m_bRightMousePressed && parentPart() != 0 && d->m_bBackRightClick )
06379   {
06380     popupMenu( d->m_strSelectedURL );
06381     d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
06382     d->m_bRightMousePressed = false;
06383   }
06384 
06385   DOM::DOMString url = event->url();
06386   DOM::DOMString target = event->target();
06387   DOM::Node innerNode = event->innerNode();
06388 
06389 #ifndef QT_NO_DRAGANDDROP
06390   if( d->m_bDnd && d->m_bMousePressed &&
06391       ( (!d->m_strSelectedURL.isEmpty() && !isEditable())
06392         || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) ) ) {
06393     if ( ( d->m_dragStartPos - _mouse->pos() ).manhattanLength() <= KGlobalSettings::dndEventDelay() )
06394       return;
06395 
06396     QPixmap pix;
06397     HTMLImageElementImpl *img = 0L;
06398     QDragObject *drag = 0;
06399     KURL u;
06400 
06401     // qDebug("****************** Event URL: %s", url.string().latin1());
06402     // qDebug("****************** Event Target: %s", target.string().latin1());
06403 
06404     // Normal image...
06405     if ( url.length() == 0 && innerNode.handle() && innerNode.handle()->id() == ID_IMG )
06406     {
06407       img = static_cast<HTMLImageElementImpl *>(innerNode.handle());
06408       u = KURL( completeURL( khtml::parseURL(img->getAttribute(ATTR_SRC)).string() ) );
06409       pix = KMimeType::mimeType("image/png")->pixmap(KIcon::Desktop);
06410     }
06411     else
06412     {
06413       // Text or image link...
06414       u = completeURL( d->m_strSelectedURL );
06415       pix = KMimeType::pixmapForURL(u, 0, KIcon::Desktop, KIcon::SizeMedium);
06416     }
06417 
06418     u.setPass(QString::null);
06419 
06420     KURLDrag* urlDrag = new KURLDrag( u, img ? 0 : d->m_view->viewport() );
06421     if ( !d->m_referrer.isEmpty() )
06422       urlDrag->metaData()["referrer"] = d->m_referrer;
06423 
06424     if( img && img->complete()) {
06425       KMultipleDrag *mdrag = new KMultipleDrag( d->m_view->viewport() );
06426       mdrag->addDragObject( new QImageDrag( img->currentImage(), 0L ) );
06427       mdrag->addDragObject( urlDrag );
06428       drag = mdrag;
06429     }
06430     else
06431       drag = urlDrag;
06432 
06433     if ( !pix.isNull() )
06434       drag->setPixmap( pix );
06435 
06436     stopAutoScroll();
06437     if(drag)
06438       drag->drag();
06439 
06440     // when we finish our drag, we need to undo our mouse press
06441     d->m_bMousePressed = false;
06442     d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
06443     return;
06444   }
06445 #endif
06446 
06447   // Not clicked -> mouse over stuff
06448   if ( !d->m_bMousePressed )
06449   {
06450     // The mouse is over something
06451     if ( url.length() )
06452     {
06453       bool shiftPressed = ( _mouse->state() & ShiftButton );
06454 
06455       // Image map
06456       if ( !innerNode.isNull() && innerNode.elementId() == ID_IMG )
06457       {
06458         HTMLImageElementImpl *i = static_cast<HTMLImageElementImpl *>(innerNode.handle());
06459         if ( i && i->isServerMap() )
06460         {
06461           khtml::RenderObject *r = i->renderer();
06462           if(r)
06463           {
06464             int absx, absy, vx, vy;
06465             r->absolutePosition(absx, absy);
06466             view()->contentsToViewport( absx, absy, vx, vy );
06467 
06468             int x(_mouse->x() - vx), y(_mouse->y() - vy);
06469 
06470             d->m_overURL = url.string() + QString("?%1,%2").arg(x).arg(y);
06471             d->m_overURLTarget = target.string();
06472             overURL( d->m_overURL, target.string(), shiftPressed );
06473             return;
06474           }
06475         }
06476       }
06477 
06478       // normal link
06479       if ( d->m_overURL.isEmpty() || d->m_overURL != url || d->m_overURLTarget != target )
06480       {
06481         d->m_overURL = url.string();
06482         d->m_overURLTarget = target.string();
06483         overURL( d->m_overURL, target.string(), shiftPressed );
06484       }
06485     }
06486     else  // Not over a link...
06487     {
06488       // reset to "default statusbar text"
06489       resetHoverText();
06490     }
06491   }
06492   else {
06493 #ifndef KHTML_NO_SELECTION
06494     // selection stuff
06495     if( d->m_bMousePressed && innerNode.handle() && innerNode.handle()->renderer() &&
06496         ( (_mouse->state() & LeftButton) != 0 )) {
06497       extendSelectionTo(event->x(), event->y(),
06498                         event->absX(), event->absY(), innerNode);
06499 #else
06500       if ( d->m_doc && d->m_view ) {
06501         QPoint diff( _mouse->globalPos() - d->m_dragLastPos );
06502 
06503         if ( abs( diff.x() ) > 64 || abs( diff.y() ) > 64 ) {
06504           d->m_view->scrollBy( -diff.x(), -diff.y() );
06505           d->m_dragLastPos = _mouse->globalPos();
06506         }
06507 #endif
06508     }
06509   }
06510 
06511 }
06512 
06513 void KHTMLPart::khtmlMouseReleaseEvent( khtml::MouseReleaseEvent *event )
06514 {
06515   DOM::Node innerNode = event->innerNode();
06516   d->m_mousePressNode = DOM::Node();
06517 
06518   if ( d->m_bMousePressed ) {
06519     setStatusBarText(QString::null, BarHoverText);
06520     stopAutoScroll();
06521   }
06522 
06523   // Used to prevent mouseMoveEvent from initiating a drag before
06524   // the mouse is pressed again.
06525   d->m_bMousePressed = false;
06526 
06527   QMouseEvent *_mouse = event->qmouseEvent();
06528   if ( _mouse->button() == RightButton && parentPart() != 0 && d->m_bBackRightClick )
06529   {
06530     d->m_bRightMousePressed = false;
06531     KParts::BrowserInterface *tmp_iface = d->m_extension->browserInterface();
06532     if( tmp_iface ) {
06533       tmp_iface->callMethod( "goHistory(int)", -1 );
06534     }
06535   }
06536 #ifndef QT_NO_CLIPBOARD
06537   if ((d->m_guiProfile == BrowserViewGUI) && (_mouse->button() == MidButton) && (event->url().isNull())) {
06538     kdDebug( 6050 ) << "KHTMLPart::khtmlMouseReleaseEvent() MMB shouldOpen="
06539                     << d->m_bOpenMiddleClick << endl;
06540 
06541     if (d->m_bOpenMiddleClick) {
06542     KHTMLPart *p = this;
06543     while (p->parentPart()) p = p->parentPart();
06544     p->d->m_extension->pasteRequest();
06545   }
06546   }
06547 #endif
06548 
06549 #ifndef KHTML_NO_SELECTION
06550   // delete selection in case start and end position are at the same point
06551   if(d->m_selectionStart == d->m_selectionEnd && d->m_startOffset == d->m_endOffset) {
06552 #ifndef KHTML_NO_CARET
06553     d->m_extendAtEnd = true;
06554 #else
06555     d->m_selectionStart = 0;
06556     d->m_selectionEnd = 0;
06557     d->m_startOffset = 0;
06558     d->m_endOffset = 0;
06559 #endif
06560     emitSelectionChanged();
06561   } else {
06562     // we have to get to know if end is before start or not...
06563 //     kdDebug(6000) << "rel: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << endl;
06564     DOM::Node n = d->m_selectionStart;
06565     d->m_startBeforeEnd = false;
06566     if( d->m_selectionStart == d->m_selectionEnd ) {
06567       if( d->m_startOffset < d->m_endOffset )
06568         d->m_startBeforeEnd = true;
06569     } else {
06570 #if 0
06571       while(!n.isNull()) {
06572         if(n == d->m_selectionEnd) {
06573           d->m_startBeforeEnd = true;
06574           break;
06575         }
06576         DOM::Node next = n.firstChild();
06577         if(next.isNull()) next = n.nextSibling();
06578         while( next.isNull() && !n.parentNode().isNull() ) {
06579           n = n.parentNode();
06580           next = n.nextSibling();
06581         }
06582         n = next;
06583       }
06584 #else
06585       // shouldn't be null but it can happen with dynamic updating of nodes
06586       if (d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() ||
06587           !d->m_selectionStart.handle()->renderer() ||
06588           !d->m_selectionEnd.handle()->renderer()) return;
06589       d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
06590                 d->m_selectionStart.handle(), d->m_startOffset,
06591             d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
06592 #endif
06593     }
06594     if(!d->m_startBeforeEnd)
06595     {
06596       DOM::Node tmpNode = d->m_selectionStart;
06597       int tmpOffset = d->m_startOffset;
06598       d->m_selectionStart = d->m_selectionEnd;
06599       d->m_startOffset = d->m_endOffset;
06600       d->m_selectionEnd = tmpNode;
06601       d->m_endOffset = tmpOffset;
06602       d->m_startBeforeEnd = true;
06603       d->m_extendAtEnd = !d->m_extendAtEnd;
06604     }
06605 #ifndef KHTML_NO_CARET
06606     bool v = d->m_view->placeCaret();
06607     emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
06608 #endif
06609     // get selected text and paste to the clipboard
06610 #ifndef QT_NO_CLIPBOARD
06611     QString text = selectedText();
06612     text.replace(QChar(0xa0), ' ');
06613     disconnect( kapp->clipboard(), SIGNAL( selectionChanged()), this, SLOT( slotClearSelection()));
06614     kapp->clipboard()->setText(text,QClipboard::Selection);
06615     connect( kapp->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection()));
06616 #endif
06617     //kdDebug( 6000 ) << "selectedText = " << text << endl;
06618     emitSelectionChanged();
06619 //kdDebug(6000) << "rel2: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << "), caretOfs " << d->caretOffset() << endl;
06620   }
06621 #endif
06622   d->m_initialNode = 0;     // don't hold nodes longer than necessary
06623   d->m_initialOffset = 0;
06624 
06625 }
06626 
06627 void KHTMLPart::khtmlDrawContentsEvent( khtml::DrawContentsEvent * )
06628 {
06629 }
06630 
06631 void KHTMLPart::guiActivateEvent( KParts::GUIActivateEvent *event )
06632 {
06633   if ( event->activated() )
06634   {
06635     emitSelectionChanged();
06636     emit d->m_extension->enableAction( "print", d->m_doc != 0 );
06637 
06638     if ( !d->m_settings->autoLoadImages() && d->m_paLoadImages )
06639     {
06640         QPtrList<KAction> lst;
06641         lst.append( d->m_paLoadImages );
06642         plugActionList( "loadImages", lst );
06643     }
06644   }
06645 }
06646 
06647 void KHTMLPart::slotPrintFrame()
06648 {
06649   if ( d->m_frames.count() == 0 )
06650     return;
06651 
06652   KParts::ReadOnlyPart *frame = currentFrame();
06653   if (!frame)
06654     return;
06655 
06656   KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject( frame );
06657 
06658   if ( !ext )
06659     return;
06660 
06661   QMetaObject *mo = ext->metaObject();
06662 
06663   int idx = mo->findSlot( "print()", true );
06664   if ( idx >= 0 ) {
06665     QUObject o[ 1 ];
06666     ext->qt_invoke( idx, o );
06667   }
06668 }
06669 
06670 void KHTMLPart::slotSelectAll()
06671 {
06672   KParts::ReadOnlyPart *part = currentFrame();
06673   if (part && part->inherits("KHTMLPart"))
06674     static_cast<KHTMLPart *>(part)->selectAll();
06675 }
06676 
06677 void KHTMLPart::startAutoScroll()
06678 {
06679    connect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
06680    d->m_scrollTimer.start(100, false);
06681 }
06682 
06683 void KHTMLPart::stopAutoScroll()
06684 {
06685    disconnect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
06686    if (d->m_scrollTimer.isActive())
06687        d->m_scrollTimer.stop();
06688 }
06689 
06690 
06691 void KHTMLPart::slotAutoScroll()
06692 {
06693     if (d->m_view)
06694       d->m_view->doAutoScroll();
06695     else
06696       stopAutoScroll(); // Safety
06697 }
06698 
06699 void KHTMLPart::runAdFilter()
06700 {
06701     if ( parentPart() )
06702         parentPart()->runAdFilter();
06703 
06704     if ( !d->m_doc )
06705         return;
06706 
06707     QPtrDictIterator<khtml::CachedObject> it( d->m_doc->docLoader()->m_docObjects );
06708     for ( ; it.current(); ++it )
06709         if ( it.current()->type() == khtml::CachedObject::Image ) {
06710             khtml::CachedImage *image = static_cast<khtml::CachedImage *>(it.current());
06711             bool wasBlocked = image->m_wasBlocked;
06712             image->m_wasBlocked = KHTMLFactory::defaultHTMLSettings()->isAdFiltered( d->m_doc->completeURL( (*it).url().string() ) );
06713             if ( image->m_wasBlocked != wasBlocked )
06714                 image->do_notify(image->pixmap(), image->valid_rect());
06715         }
06716 
06717     if ( KHTMLFactory::defaultHTMLSettings()->isHideAdsEnabled() ) {
06718         for ( NodeImpl *nextNode, *node = d->m_doc; node; node = nextNode ) {
06719 
06720             // We might be deleting 'node' shortly.
06721             nextNode = node->traverseNextNode();
06722 
06723             if ( node->id() == ID_IMG ||
06724                  node->id() == ID_IFRAME ||
06725                  (node->id() == ID_INPUT && static_cast<HTMLInputElementImpl *>(node)->inputType() == HTMLInputElementImpl::IMAGE ))
06726             {
06727                 if ( KHTMLFactory::defaultHTMLSettings()->isAdFiltered( d->m_doc->completeURL( static_cast<ElementImpl *>(node)->getAttribute(ATTR_SRC).string() ) ) )
06728                 {
06729                     // We found an IMG, IFRAME or INPUT (of type IMAGE) matching a filter.
06730                     node->ref();
06731                     NodeImpl *parent = node->parent();
06732                     if( parent )
06733                     {
06734                         int exception = 0;
06735                         parent->removeChild(node, exception);
06736                     }
06737                     node->deref();
06738                 }
06739             }
06740         }
06741     }
06742 }
06743 
06744 void KHTMLPart::selectAll()
06745 {
06746   if (!d->m_doc) return;
06747 
06748   NodeImpl *first;
06749   if (d->m_doc->isHTMLDocument())
06750     first = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
06751   else
06752     first = d->m_doc;
06753   NodeImpl *next;
06754 
06755   // Look for first text/cdata node that has a renderer,
06756   // or first childless replaced element
06757   while ( first && !(first->renderer()
06758     && ((first->nodeType() == Node::TEXT_NODE || first->nodeType() == Node::CDATA_SECTION_NODE)
06759         || (first->renderer()->isReplaced() && !first->renderer()->firstChild()))))
06760   {
06761     next = first->firstChild();
06762     if ( !next ) next = first->nextSibling();
06763     while( first && !next )
06764     {
06765       first = first->parentNode();
06766       if ( first )
06767         next = first->nextSibling();
06768     }
06769     first = next;
06770   }
06771 
06772   NodeImpl *last;
06773   if (d->m_doc->isHTMLDocument())
06774     last = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
06775   else
06776     last = d->m_doc;
06777   // Look for last text/cdata node that has a renderer,
06778   // or last childless replaced element
06779   // ### Instead of changing this loop, use findLastSelectableNode
06780   // in render_table.cpp (LS)
06781   while ( last && !(last->renderer()
06782     && ((last->nodeType() == Node::TEXT_NODE || last->nodeType() == Node::CDATA_SECTION_NODE)
06783         || (last->renderer()->isReplaced() && !last->renderer()->lastChild()))))
06784   {
06785     next = last->lastChild();
06786     if ( !next ) next = last->previousSibling();
06787     while ( last && !next )
06788     {
06789       last = last->parentNode();
06790       if ( last )
06791         next = last->previousSibling();
06792     }
06793     last = next;
06794   }
06795 
06796   if ( !first || !last )
06797     return;
06798   Q_ASSERT(first->renderer());
06799   Q_ASSERT(last->renderer());
06800   d->m_selectionStart = first;
06801   d->m_startOffset = 0;
06802   d->m_selectionEnd = last;
06803   d->m_endOffset = last->nodeValue().length();
06804   d->m_startBeforeEnd = true;
06805 
06806   d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
06807                           d->m_selectionEnd.handle(), d->m_endOffset );
06808 
06809   emitSelectionChanged();
06810 }
06811 
06812 bool KHTMLPart::checkLinkSecurity(const KURL &linkURL,const QString &message, const QString &button)
06813 {
06814   bool linkAllowed = true;
06815 
06816   if ( d->m_doc )
06817     linkAllowed = kapp && kapp->authorizeURLAction("redirect", url(), linkURL);
06818 
06819   if ( !linkAllowed ) {
06820     khtml::Tokenizer *tokenizer = d->m_doc->tokenizer();
06821     if (tokenizer)
06822       tokenizer->setOnHold(true);
06823 
06824     int response = KMessageBox::Cancel;
06825     if (!message.isEmpty())
06826     {
06827         response = KMessageBox::warningContinueCancel( 0,
06828                                message.arg(linkURL.htmlURL()),
06829                                i18n( "Security Warning" ),
06830                                button);
06831     }
06832     else
06833     {
06834         KMessageBox::error( 0,
06835                 i18n( "<qt>Access by untrusted page to<BR><B>%1</B><BR> denied.").arg(linkURL.htmlURL()),
06836                 i18n( "Security Alert" ));
06837     }
06838 
06839     if (tokenizer)
06840        tokenizer->setOnHold(false);
06841     return (response==KMessageBox::Continue);
06842   }
06843   return true;
06844 }
06845 
06846 void KHTMLPart::slotPartRemoved( KParts::Part *part )
06847 {
06848 //    kdDebug(6050) << "KHTMLPart::slotPartRemoved " << part << endl;
06849     if ( part == d->m_activeFrame )
06850     {
06851         d->m_activeFrame = 0L;
06852         if ( !part->inherits( "KHTMLPart" ) )
06853         {
06854             if (factory()) {
06855                 factory()->removeClient( part );
06856             }
06857             if (childClients()->containsRef(part)) {
06858                 removeChildClient( part );
06859             }
06860         }
06861     }
06862 }
06863 
06864 void KHTMLPart::slotActiveFrameChanged( KParts::Part *part )
06865 {
06866 //    kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged this=" << this << "part=" << part << endl;
06867     if ( part == this )
06868     {
06869         kdError(6050) << "strange error! we activated ourselves" << endl;
06870         assert( false );
06871         return;
06872     }
06873 //    kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged d->m_activeFrame=" << d->m_activeFrame << endl;
06874     if ( d->m_activeFrame && d->m_activeFrame->widget() && d->m_activeFrame->widget()->inherits( "QFrame" ) )
06875     {
06876         QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() );
06877         if (frame->frameStyle() != QFrame::NoFrame)
06878         {
06879            frame->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken);
06880            frame->repaint();
06881         }
06882     }
06883 
06884     if( d->m_activeFrame && !d->m_activeFrame->inherits( "KHTMLPart" ) )
06885     {
06886         if (factory()) {
06887             factory()->removeClient( d->m_activeFrame );
06888         }
06889         removeChildClient( d->m_activeFrame );
06890     }
06891     if( part && !part->inherits( "KHTMLPart" ) )
06892     {
06893         if (factory()) {
06894             factory()->addClient( part );
06895         }
06896         insertChildClient( part );
06897     }
06898 
06899 
06900     d->m_activeFrame = part;
06901 
06902     if ( d->m_activeFrame && d->m_activeFrame->widget()->inherits( "QFrame" ) )
06903     {
06904         QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() );
06905         if (frame->frameStyle() != QFrame::NoFrame)
06906         {
06907            frame->setFrameStyle( QFrame::StyledPanel | QFrame::Plain);
06908            frame->repaint();
06909         }
06910         kdDebug(6050) << "new active frame " << d->m_activeFrame << endl;
06911     }
06912 
06913     updateActions();
06914 
06915     // (note: childObject returns 0 if the argument is 0)
06916     d->m_extension->setExtensionProxy( KParts::BrowserExtension::childObject( d->m_activeFrame ) );
06917 }
06918 
06919 void KHTMLPart::setActiveNode(const DOM::Node &node)
06920 {
06921     if (!d->m_doc || !d->m_view)
06922         return;
06923 
06924     // Set the document's active node
06925     d->m_doc->setFocusNode(node.handle());
06926 
06927     // Scroll the view if necessary to ensure that the new focus node is visible
06928     QRect rect  = node.handle()->getRect();
06929     d->m_view->ensureVisible(rect.right(), rect.bottom());
06930     d->m_view->ensureVisible(rect.left(), rect.top());
06931 }
06932 
06933 DOM::Node KHTMLPart::activeNode() const
06934 {
06935     return DOM::Node(d->m_doc?d->m_doc->focusNode():0);
06936 }
06937 
06938 DOM::EventListener *KHTMLPart::createHTMLEventListener( QString code, QString name, NodeImpl* node )
06939 {
06940   KJSProxy *proxy = jScript();
06941 
06942   if (!proxy)
06943     return 0;
06944 
06945   return proxy->createHTMLEventHandler( m_url.url(), name, code, node );
06946 }
06947 
06948 KHTMLPart *KHTMLPart::opener()
06949 {
06950     return d->m_opener;
06951 }
06952 
06953 void KHTMLPart::setOpener(KHTMLPart *_opener)
06954 {
06955     d->m_opener = _opener;
06956 }
06957 
06958 bool KHTMLPart::openedByJS()
06959 {
06960     return d->m_openedByJS;
06961 }
06962 
06963 void KHTMLPart::setOpenedByJS(bool _openedByJS)
06964 {
06965     d->m_openedByJS = _openedByJS;
06966 }
06967 
06968 void KHTMLPart::preloadStyleSheet(const QString &url, const QString &stylesheet)
06969 {
06970     khtml::Cache::preloadStyleSheet(url, stylesheet);
06971 }
06972 
06973 void KHTMLPart::preloadScript(const QString &url, const QString &script)
06974 {
06975     khtml::Cache::preloadScript(url, script);
06976 }
06977 
06978 QCString KHTMLPart::dcopObjectId() const
06979 {
06980   QCString id;
06981   id.sprintf("html-widget%d", d->m_dcop_counter);
06982   return id;
06983 }
06984 
06985 long KHTMLPart::cacheId() const
06986 {
06987   return d->m_cacheId;
06988 }
06989 
06990 bool KHTMLPart::restored() const
06991 {
06992   return d->m_restored;
06993 }
06994 
06995 bool KHTMLPart::pluginPageQuestionAsked(const QString& mimetype) const
06996 {
06997   // parentPart() should be const!
06998   KHTMLPart* parent = const_cast<KHTMLPart *>(this)->parentPart();
06999   if ( parent )
07000     return parent->pluginPageQuestionAsked(mimetype);
07001 
07002   return d->m_pluginPageQuestionAsked.contains(mimetype);
07003 }
07004 
07005 void KHTMLPart::setPluginPageQuestionAsked(const QString& mimetype)
07006 {
07007   if ( parentPart() )
07008     parentPart()->setPluginPageQuestionAsked(mimetype);
07009 
07010   d->m_pluginPageQuestionAsked.append(mimetype);
07011 }
07012 
07013 void KHTMLPart::slotAutomaticDetectionLanguage( int _id )
07014 {
07015   d->m_automaticDetection->setItemChecked( _id, true );
07016 
07017   switch ( _id ) {
07018     case 0 :
07019       d->m_autoDetectLanguage = khtml::Decoder::SemiautomaticDetection;
07020       break;
07021     case 1 :
07022       d->m_autoDetectLanguage = khtml::Decoder::Arabic;
07023       break;
07024     case 2 :
07025       d->m_autoDetectLanguage = khtml::Decoder::Baltic;
07026       break;
07027     case 3 :
07028       d->m_autoDetectLanguage = khtml::Decoder::CentralEuropean;
07029       break;
07030     case 4 :
07031       d->m_autoDetectLanguage = khtml::Decoder::Chinese;
07032       break;
07033     case 5 :
07034       d->m_autoDetectLanguage = khtml::Decoder::Greek;
07035       break;
07036     case 6 :
07037       d->m_autoDetectLanguage = khtml::Decoder::Hebrew;
07038       break;
07039     case 7 :
07040       d->m_autoDetectLanguage = khtml::Decoder::Japanese;
07041       break;
07042     case 8 :
07043       d->m_autoDetectLanguage = khtml::Decoder::Korean;
07044       break;
07045     case 9 :
07046       d->m_autoDetectLanguage = khtml::Decoder::Russian;
07047       break;
07048     case 10 :
07049       d->m_autoDetectLanguage = khtml::Decoder::Thai;
07050       break;
07051     case 11 :
07052       d->m_autoDetectLanguage = khtml::Decoder::Turkish;
07053       break;
07054     case 12 :
07055       d->m_autoDetectLanguage = khtml::Decoder::Ukrainian;
07056       break;
07057     case 13 :
07058       d->m_autoDetectLanguage = khtml::Decoder::Unicode;
07059       break;
07060     case 14 :
07061       d->m_autoDetectLanguage = khtml::Decoder::WesternEuropean;
07062       break;
07063     default :
07064       d->m_autoDetectLanguage = khtml::Decoder::SemiautomaticDetection;
07065       break;
07066   }
07067 
07068   for ( int i = 0; i <= 14; ++i ) {
07069     if ( i != _id )
07070       d->m_automaticDetection->setItemChecked( i, false );
07071   }
07072 
07073   d->m_paSetEncoding->popupMenu()->setItemChecked( 0, true );
07074 
07075   setEncoding( QString::null, false );
07076 
07077   if( d->m_manualDetection )
07078     d->m_manualDetection->setCurrentItem( -1 );
07079   d->m_paSetEncoding->popupMenu()->setItemChecked( d->m_paSetEncoding->popupMenu()->idAt( 2 ), false );
07080 }
07081 
07082 khtml::Decoder *KHTMLPart::createDecoder()
07083 {
07084     khtml::Decoder *dec = new khtml::Decoder();
07085     if( !d->m_encoding.isNull() )
07086         dec->setEncoding( d->m_encoding.latin1(),
07087             d->m_haveEncoding ? khtml::Decoder::UserChosenEncoding : khtml::Decoder::EncodingFromHTTPHeader);
07088     else {
07089         // Inherit the default encoding from the parent frame if there is one.
07090         const char *defaultEncoding = (parentPart() && parentPart()->d->m_decoder)
07091             ? parentPart()->d->m_decoder->encoding() : settings()->encoding().latin1();
07092         dec->setEncoding(defaultEncoding, khtml::Decoder::DefaultEncoding);
07093     }
07094 #ifdef APPLE_CHANGES
07095     if (d->m_doc)
07096         d->m_doc->setDecoder(d->m_decoder);
07097 #endif
07098     dec->setAutoDetectLanguage( d->m_autoDetectLanguage );
07099     return dec;
07100 }
07101 
07102 void KHTMLPart::emitCaretPositionChanged(const DOM::Node &node, long offset) {
07103   emit caretPositionChanged(node, offset);
07104 }
07105 
07106 void KHTMLPart::restoreScrollPosition()
07107 {
07108   KParts::URLArgs args = d->m_extension->urlArgs();
07109 
07110   if ( m_url.hasRef() && !d->m_restoreScrollPosition && !args.reload) {
07111     if ( !d->m_doc || !d->m_doc->parsing() )
07112       disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
07113     if ( !gotoAnchor(m_url.encodedHtmlRef()) )
07114       gotoAnchor(m_url.htmlRef());
07115     return;
07116   }
07117 
07118   // Check whether the viewport has become large enough to encompass the stored
07119   // offsets. If the document has been fully loaded, force the new coordinates,
07120   // even if the canvas is too short (can happen when user resizes the window
07121   // during loading).
07122   if (d->m_view->contentsHeight() - d->m_view->visibleHeight() >= args.yOffset
07123       || d->m_bComplete) {
07124     d->m_view->setContentsPos(args.xOffset, args.yOffset);
07125     disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
07126   }
07127 }
07128 
07129 
07130 void KHTMLPart::openWallet(DOM::HTMLFormElementImpl *form)
07131 {
07132 #ifndef KHTML_NO_WALLET
07133   KHTMLPart *p;
07134 
07135   for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
07136   }
07137 
07138   if (p) {
07139     p->openWallet(form);
07140     return;
07141   }
07142 
07143   if (onlyLocalReferences()) { // avoid triggering on local apps, thumbnails
07144     return;
07145   }
07146 
07147   if (d->m_wallet) {
07148     if (d->m_bWalletOpened) {
07149       if (d->m_wallet->isOpen()) {
07150         form->walletOpened(d->m_wallet);
07151         return;
07152       }
07153       d->m_wallet->deleteLater();
07154       d->m_wallet = 0L;
07155       d->m_bWalletOpened = false;
07156     }
07157   }
07158 
07159   if (!d->m_wq) {
07160     KWallet::Wallet *wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0, KWallet::Wallet::Asynchronous);
07161     d->m_wq = new KHTMLWalletQueue(this);
07162     d->m_wq->wallet = wallet;
07163     connect(wallet, SIGNAL(walletOpened(bool)), d->m_wq, SLOT(walletOpened(bool)));
07164     connect(d->m_wq, SIGNAL(walletOpened(KWallet::Wallet*)), this, SLOT(walletOpened(KWallet::Wallet*)));
07165   }
07166   assert(form);
07167   d->m_wq->callers.append(KHTMLWalletQueue::Caller(form, form->getDocument()));
07168 #endif // KHTML_NO_WALLET
07169 }
07170 
07171 
07172 void KHTMLPart::saveToWallet(const QString& key, const QMap<QString,QString>& data)
07173 {
07174 #ifndef KHTML_NO_WALLET
07175   KHTMLPart *p;
07176 
07177   for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
07178   }
07179 
07180   if (p) {
07181     p->saveToWallet(key, data);
07182     return;
07183   }
07184 
07185   if (d->m_wallet) {
07186     if (d->m_bWalletOpened) {
07187       if (d->m_wallet->isOpen()) {
07188         if (!d->m_wallet->hasFolder(KWallet::Wallet::FormDataFolder())) {
07189           d->m_wallet->createFolder(KWallet::Wallet::FormDataFolder());
07190         }
07191         d->m_wallet->setFolder(KWallet::Wallet::FormDataFolder());
07192         d->m_wallet->writeMap(key, data);
07193         return;
07194       }
07195       d->m_wallet->deleteLater();
07196       d->m_wallet = 0L;
07197       d->m_bWalletOpened = false;
07198     }
07199   }
07200 
07201   if (!d->m_wq) {
07202     KWallet::Wallet *wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0, KWallet::Wallet::Asynchronous);
07203     d->m_wq = new KHTMLWalletQueue(this);
07204     d->m_wq->wallet = wallet;
07205     connect(wallet, SIGNAL(walletOpened(bool)), d->m_wq, SLOT(walletOpened(bool)));
07206     connect(d->m_wq, SIGNAL(walletOpened(KWallet::Wallet*)), this, SLOT(walletOpened(KWallet::Wallet*)));
07207   }
07208   d->m_wq->savers.append(qMakePair(key, data));
07209 #endif // KHTML_NO_WALLET
07210 }
07211 
07212 
07213 void KHTMLPart::dequeueWallet(DOM::HTMLFormElementImpl *form) {
07214 #ifndef KHTML_NO_WALLET
07215   KHTMLPart *p;
07216 
07217   for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
07218   }
07219 
07220   if (p) {
07221     p->dequeueWallet(form);
07222     return;
07223   }
07224 
07225   if (d->m_wq) {
07226     d->m_wq->callers.remove(KHTMLWalletQueue::Caller(form, form->getDocument()));
07227   }
07228 #endif // KHTML_NO_WALLET
07229 }
07230 
07231 
07232 void KHTMLPart::walletOpened(KWallet::Wallet *wallet) {
07233 #ifndef KHTML_NO_WALLET
07234   assert(!d->m_wallet);
07235   assert(d->m_wq);
07236 
07237   d->m_wq->deleteLater(); // safe?
07238   d->m_wq = 0L;
07239 
07240   if (!wallet) {
07241     d->m_bWalletOpened = false;
07242     return;
07243   }
07244 
07245   d->m_wallet = wallet;
07246   d->m_bWalletOpened = true;
07247   connect(d->m_wallet, SIGNAL(walletClosed()), SLOT(slotWalletClosed()));
07248 
07249   if (!d->m_statusBarWalletLabel) {
07250     d->m_statusBarWalletLabel = new KURLLabel(d->m_statusBarExtension->statusBar());
07251     d->m_statusBarWalletLabel->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small));
07252     d->m_statusBarWalletLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
07253     d->m_statusBarWalletLabel->setUseCursor(false);
07254     d->m_statusBarExtension->addStatusBarItem(d->m_statusBarWalletLabel, 0, false);
07255     d->m_statusBarWalletLabel->setPixmap(SmallIcon("wallet_open", instance()));
07256     connect(d->m_statusBarWalletLabel, SIGNAL(leftClickedURL()), SLOT(launchWalletManager()));
07257     connect(d->m_statusBarWalletLabel, SIGNAL(rightClickedURL()), SLOT(walletMenu()));
07258   } else {
07259     QToolTip::remove(d->m_statusBarWalletLabel);
07260   }
07261   QToolTip::add(d->m_statusBarWalletLabel, i18n("The wallet '%1' is open and being used for form data and passwords.").arg(KWallet::Wallet::NetworkWallet()));
07262 #endif // KHTML_NO_WALLET
07263 }
07264 
07265 
07266 KWallet::Wallet *KHTMLPart::wallet()
07267 {
07268 #ifndef KHTML_NO_WALLET
07269   KHTMLPart *p;
07270 
07271   for (p = parentPart(); p && p->parentPart(); p = p->parentPart())
07272     ;
07273 
07274   if (p)
07275     return p->wallet();
07276 
07277 #endif // KHTML_NO_WALLET
07278   return d->m_wallet;
07279 }
07280 
07281 
07282 void KHTMLPart::slotWalletClosed()
07283 {
07284 #ifndef KHTML_NO_WALLET
07285   if (d->m_wallet) {
07286     d->m_wallet->deleteLater();
07287     d->m_wallet = 0L;
07288   }
07289   d->m_bWalletOpened = false;
07290   if (d->m_statusBarWalletLabel) {
07291     d->m_statusBarExtension->removeStatusBarItem(d->m_statusBarWalletLabel);
07292     delete d->m_statusBarWalletLabel;
07293     d->m_statusBarWalletLabel = 0L;
07294   }
07295 #endif // KHTML_NO_WALLET
07296 }
07297 
07298 void KHTMLPart::launchWalletManager()
07299 {
07300 #ifndef KHTML_NO_WALLET
07301   if (!DCOPClient::mainClient()->isApplicationRegistered("kwalletmanager")) {
07302     KApplication::startServiceByDesktopName("kwalletmanager_show");
07303   } else {
07304     DCOPRef r("kwalletmanager", "kwalletmanager-mainwindow#1");
07305     r.send("show");
07306     r.send("raise");
07307   }
07308 #endif // KHTML_NO_WALLET
07309 }
07310 
07311 void KHTMLPart::walletMenu()
07312 {
07313 #ifndef KHTML_NO_WALLET
07314   KPopupMenu *m = new KPopupMenu(0L);
07315   m->insertItem(i18n("&Close Wallet"), this, SLOT(slotWalletClosed()));
07316   m->popup(QCursor::pos());
07317 #endif // KHTML_NO_WALLET
07318 }
07319 
07320 void KHTMLPart::slotToggleCaretMode()
07321 {
07322   setCaretMode(d->m_paToggleCaretMode->isChecked());
07323 }
07324 
07325 void KHTMLPart::setFormNotification(KHTMLPart::FormNotification fn) {
07326   d->m_formNotification = fn;
07327 }
07328 
07329 KHTMLPart::FormNotification KHTMLPart::formNotification() const {
07330   return d->m_formNotification;
07331 }
07332 
07333 KURL KHTMLPart::toplevelURL()
07334 {
07335   KHTMLPart* part = this;
07336   while (part->parentPart())
07337     part = part->parentPart();
07338 
07339   if (!part)
07340     return KURL();
07341 
07342   return part->url();
07343 }
07344 
07345 bool KHTMLPart::isModified() const
07346 {
07347   if ( !d->m_doc )
07348     return false;
07349 
07350   return d->m_doc->unsubmittedFormChanges();
07351 }
07352 
07353 void KHTMLPart::setDebugScript( bool enable )
07354 {
07355   unplugActionList( "debugScriptList" );
07356   if ( enable ) {
07357     if (!d->m_paDebugScript) {
07358       d->m_paDebugScript = new KAction( i18n( "JavaScript &Debugger" ), 0, this, SLOT( slotDebugScript() ), actionCollection(), "debugScript" );
07359     }
07360     d->m_paDebugScript->setEnabled( d->m_frame ? d->m_frame->m_jscript : 0L );
07361     QPtrList<KAction> lst;
07362     lst.append( d->m_paDebugScript );
07363     plugActionList( "debugScriptList", lst );
07364   }
07365   d->m_bJScriptDebugEnabled = enable;
07366 }
07367 
07368 void KHTMLPart::setSuppressedPopupIndicator( bool enable )
07369 {
07370     setSuppressedPopupIndicator( enable, 0 );
07371 }
07372 
07373 void KHTMLPart::setSuppressedPopupIndicator( bool enable, KHTMLPart *originPart )
07374 {
07375     if ( parentPart() ) {
07376         parentPart()->setSuppressedPopupIndicator( enable, originPart );
07377         return;
07378     }
07379 
07380     if ( enable && originPart ) {
07381         d->m_openableSuppressedPopups++;
07382         if ( d->m_suppressedPopupOriginParts.findIndex( originPart ) == -1 )
07383             d->m_suppressedPopupOriginParts.append( originPart );
07384     }
07385 
07386     if ( enable && !d->m_statusBarPopupLabel ) {
07387         d->m_statusBarPopupLabel = new KURLLabel( d->m_statusBarExtension->statusBar() );
07388         d->m_statusBarPopupLabel->setFixedHeight( instance()->iconLoader()->currentSize( KIcon::Small) );
07389         d->m_statusBarPopupLabel->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ));
07390         d->m_statusBarPopupLabel->setUseCursor( false );
07391         d->m_statusBarExtension->addStatusBarItem( d->m_statusBarPopupLabel, 0, false );
07392         d->m_statusBarPopupLabel->setPixmap( SmallIcon( "window_suppressed", instance() ) );
07393         QToolTip::add( d->m_statusBarPopupLabel, i18n("This page was prevented from opening a new window via JavaScript." ) );
07394 
07395         connect(d->m_statusBarPopupLabel, SIGNAL(leftClickedURL()), SLOT(suppressedPopupMenu()));
07396         if (d->m_settings->jsPopupBlockerPassivePopup()) {
07397             QPixmap px;
07398             px = MainBarIcon( "window_suppressed" );
07399             KPassivePopup::message(i18n("Popup Window Blocked"),i18n("This page has attempted to open a popup window but was blocked.\nYou can click on this icon in the status bar to control this behavior\nor to open the popup."),px,d->m_statusBarPopupLabel);
07400         }
07401     } else if ( !enable && d->m_statusBarPopupLabel ) {
07402         QToolTip::remove( d->m_statusBarPopupLabel );
07403         d->m_statusBarExtension->removeStatusBarItem( d->m_statusBarPopupLabel );
07404         delete d->m_statusBarPopupLabel;
07405         d->m_statusBarPopupLabel = 0L;
07406     }
07407 }
07408 
07409 void KHTMLPart::suppressedPopupMenu() {
07410   KPopupMenu *m = new KPopupMenu(0L);
07411   m->setCheckable(true);
07412   if ( d->m_openableSuppressedPopups )
07413       m->insertItem(i18n("&Show Blocked Popup Window","Show %n Blocked Popup Windows", d->m_openableSuppressedPopups), this, SLOT(showSuppressedPopups()));
07414   m->insertItem(i18n("Show Blocked Window Passive Popup &Notification"), this, SLOT(togglePopupPassivePopup()),0,57);
07415   m->setItemChecked(57,d->m_settings->jsPopupBlockerPassivePopup());
07416   m->insertItem(i18n("&Configure JavaScript New Window Policies..."), this, SLOT(launchJSConfigDialog()));
07417   m->popup(QCursor::pos());
07418 }
07419 
07420 void KHTMLPart::togglePopupPassivePopup() {
07421   // Same hack as in disableJSErrorExtension()
07422   d->m_settings->setJSPopupBlockerPassivePopup( !d->m_settings->jsPopupBlockerPassivePopup() );
07423   DCOPClient::mainClient()->send("konqueror*", "KonquerorIface", "reparseConfiguration()", QByteArray());
07424 }
07425 
07426 void KHTMLPart::showSuppressedPopups() {
07427     for ( QValueListIterator<QGuardedPtr<KHTMLPart> > i = d->m_suppressedPopupOriginParts.begin();
07428           i != d->m_suppressedPopupOriginParts.end(); ++i ) {
07429       if (KHTMLPart* part = *i) {
07430         KJS::Window *w = KJS::Window::retrieveWindow( part );
07431         if (w) {
07432             w->showSuppressedWindows();
07433             w->forgetSuppressedWindows();
07434         }
07435       }
07436     }
07437     setSuppressedPopupIndicator( false );
07438     d->m_openableSuppressedPopups = 0;
07439     d->m_suppressedPopupOriginParts.clear();
07440 }
07441 
07442 // Extension to use for "view document source", "save as" etc.
07443 // Using the right extension can help the viewer get into the right mode (#40496)
07444 QString KHTMLPart::defaultExtension() const
07445 {
07446     if ( !d->m_doc )
07447         return ".html";
07448     if ( !d->m_doc->isHTMLDocument() )
07449         return ".xml";
07450     return d->m_doc->htmlMode() == DOM::DocumentImpl::XHtml ? ".xhtml" : ".html";
07451 }
07452 
07453 bool KHTMLPart::inProgress() const
07454 {
07455     if (d->m_runningScripts || (d->m_doc && d->m_doc->parsing()))
07456         return true;
07457 
07458     // Any frame that hasn't completed yet ?
07459     ConstFrameIt it = d->m_frames.begin();
07460     const ConstFrameIt end = d->m_frames.end();
07461     for (; it != end; ++it ) {
07462         if ((*it)->m_run || !(*it)->m_bCompleted)
07463         return true;
07464     }
07465 
07466     return d->m_submitForm || !d->m_redirectURL.isEmpty() || d->m_redirectionTimer.isActive() || d->m_job;
07467 }
07468 
07469 using namespace KParts;
07470 #include "khtml_part.moc"
07471 #include "khtmlpart_p.moc"

KHTML

Skip menu "KHTML"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal