| # khtml Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

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

This file is part of the documentation for khtml Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:33:14 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003