khtml Library API Documentation

khtml_part.cpp

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