khtml Library API Documentation

khtml_part.cpp

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