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