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