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 != 0) {
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::slotFinishedParsing()
01926 {
01927   d->m_doc->setParsing(false);
01928   checkEmitLoadEvent();
01929   disconnect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
01930 
01931   if (!d->m_view)
01932     return; // We are probably being destructed.
01933 
01934   checkCompleted();
01935 }
01936 
01937 void KHTMLPart::slotLoaderRequestStarted( khtml::DocLoader* dl, khtml::CachedObject *obj )
01938 {
01939   if ( obj && obj->type() == khtml::CachedObject::Image && d->m_doc && d->m_doc->docLoader() == dl ) {
01940     KHTMLPart* p = this;
01941     while ( p ) {
01942       KHTMLPart* const op = p;
01943       ++(p->d->m_totalObjectCount);
01944       p = p->parentPart();
01945       if ( !p && op->d->m_loadedObjects <= op->d->m_totalObjectCount
01946         && !op->d->m_progressUpdateTimer.isActive())
01947     op->d->m_progressUpdateTimer.start( 200, true );
01948     }
01949   }
01950 }
01951 
01952 void KHTMLPart::slotLoaderRequestDone( khtml::DocLoader* dl, khtml::CachedObject *obj )
01953 {
01954   if ( obj && obj->type() == khtml::CachedObject::Image && d->m_doc && d->m_doc->docLoader() == dl ) {
01955     KHTMLPart* p = this;
01956     while ( p ) {
01957       KHTMLPart* const op = p;
01958       ++(p->d->m_loadedObjects);
01959       p = p->parentPart();
01960       if ( !p && op->d->m_loadedObjects <= op->d->m_totalObjectCount && op->d->m_jobPercent <= 100
01961         && !op->d->m_progressUpdateTimer.isActive())
01962     op->d->m_progressUpdateTimer.start( 200, true );
01963     }
01964   }
01965 
01966   checkCompleted();
01967 }
01968 
01969 void KHTMLPart::slotProgressUpdate()
01970 {
01971   int percent;
01972   if ( d->m_loadedObjects < d->m_totalObjectCount )
01973     percent = d->m_jobPercent / 4 + ( d->m_loadedObjects*300 ) / ( 4*d->m_totalObjectCount );
01974   else
01975     percent = d->m_jobPercent;
01976 
01977   if( d->m_bComplete )
01978     percent = 100;
01979 
01980   if (d->m_statusMessagesEnabled) {
01981     if( d->m_bComplete )
01982       emit d->m_extension->infoMessage( i18n( "Page loaded." ));
01983     else if ( d->m_loadedObjects < d->m_totalObjectCount && percent >= 75 )
01984       emit d->m_extension->infoMessage( i18n( "%n Image of %1 loaded.", "%n Images of %1 loaded.", d->m_loadedObjects).arg(d->m_totalObjectCount) );
01985   }
01986 
01987   emit d->m_extension->loadingProgress( percent );
01988 }
01989 
01990 void KHTMLPart::slotJobSpeed( KIO::Job* /*job*/, unsigned long speed )
01991 {
01992   d->m_jobspeed = speed;
01993   if (!parentPart())
01994     setStatusBarText(jsStatusBarText(), BarOverrideText);
01995 }
01996 
01997 void KHTMLPart::slotJobPercent( KIO::Job* /*job*/, unsigned long percent )
01998 {
01999   d->m_jobPercent = percent;
02000 
02001   if ( !parentPart() )
02002     d->m_progressUpdateTimer.start( 0, true );
02003 }
02004 
02005 void KHTMLPart::slotJobDone( KIO::Job* /*job*/ )
02006 {
02007   d->m_jobPercent = 100;
02008 
02009   if ( !parentPart() )
02010     d->m_progressUpdateTimer.start( 0, true );
02011 }
02012 
02013 void KHTMLPart::slotUserSheetStatDone( KIO::Job *_job )
02014 {
02015   using namespace KIO;
02016 
02017   if ( _job->error() ) {
02018     showError( _job );
02019     return;
02020   }
02021 
02022   const UDSEntry entry = dynamic_cast<KIO::StatJob *>( _job )->statResult();
02023   UDSEntry::ConstIterator it = entry.begin();
02024   const UDSEntry::ConstIterator end = entry.end();
02025   for ( ; it != end; ++it ) {
02026     if ( ( *it ).m_uds == UDS_MODIFICATION_TIME ) {
02027      break;
02028     }
02029   }
02030 
02031   // If the filesystem supports modification times, only reload the
02032   // user-defined stylesheet if necessary - otherwise always reload.
02033   if ( it != end ) {
02034     const time_t lastModified = static_cast<time_t>( ( *it ).m_long );
02035     if ( d->m_userStyleSheetLastModified >= lastModified ) {
02036       return;
02037     }
02038     d->m_userStyleSheetLastModified = lastModified;
02039   }
02040 
02041   setUserStyleSheet( KURL( settings()->userStyleSheet() ) );
02042 }
02043 
02044 void KHTMLPart::checkCompleted()
02045 {
02046 //   kdDebug( 6050 ) << "KHTMLPart::checkCompleted() " << this << " " << name() << endl;
02047 //   kdDebug( 6050 ) << "                           parsing: " << (d->m_doc && d->m_doc->parsing()) << endl;
02048 //   kdDebug( 6050 ) << "                           complete: " << d->m_bComplete << endl;
02049 
02050   // restore the cursor position
02051   if (d->m_doc && !d->m_doc->parsing() && !d->m_focusNodeRestored)
02052   {
02053       if (d->m_focusNodeNumber >= 0)
02054           d->m_doc->setFocusNode(d->m_doc->nodeWithAbsIndex(d->m_focusNodeNumber));
02055 
02056       d->m_focusNodeRestored = true;
02057   }
02058 
02059   bool bPendingChildRedirection = false;
02060   // Any frame that hasn't completed yet ?
02061   ConstFrameIt it = d->m_frames.begin();
02062   const ConstFrameIt end = d->m_frames.end();
02063   for (; it != end; ++it ) {
02064     if ( !(*it)->m_bCompleted )
02065     {
02066       //kdDebug( 6050 ) << this << " is waiting for " << (*it)->m_part << endl;
02067       return;
02068     }
02069     // Check for frames with pending redirections
02070     if ( (*it)->m_bPendingRedirection )
02071       bPendingChildRedirection = true;
02072   }
02073 
02074   // Any object that hasn't completed yet ?
02075   {
02076     ConstFrameIt oi = d->m_objects.begin();
02077     const ConstFrameIt oiEnd = d->m_objects.end();
02078 
02079     for (; oi != oiEnd; ++oi )
02080       if ( !(*oi)->m_bCompleted )
02081         return;
02082   }
02083   // Are we still parsing - or have we done the completed stuff already ?
02084   if ( d->m_bComplete || (d->m_doc && d->m_doc->parsing()) )
02085     return;
02086 
02087   // Still waiting for images/scripts from the loader ?
02088   int requests = 0;
02089   if ( d->m_doc && d->m_doc->docLoader() )
02090     requests = khtml::Cache::loader()->numRequests( d->m_doc->docLoader() );
02091 
02092   if ( requests > 0 )
02093   {
02094     //kdDebug(6050) << "still waiting for images/scripts from the loader - requests:" << requests << endl;
02095     return;
02096   }
02097 
02098   // OK, completed.
02099   // Now do what should be done when we are really completed.
02100   d->m_bComplete = true;
02101   d->m_cachePolicy = KProtocolManager::cacheControl(); // reset cache policy
02102   d->m_totalObjectCount = 0;
02103   d->m_loadedObjects = 0;
02104 
02105   KHTMLPart* p = this;
02106   while ( p ) {
02107     KHTMLPart* op = p;
02108     p = p->parentPart();
02109     if ( !p && !op->d->m_progressUpdateTimer.isActive())
02110       op->d->m_progressUpdateTimer.start( 0, true );
02111   }
02112 
02113   checkEmitLoadEvent(); // if we didn't do it before
02114 
02115   bool pendingAction = false;
02116 
02117   if ( !d->m_redirectURL.isEmpty() )
02118   {
02119     // DA: Do not start redirection for frames here! That action is
02120     // deferred until the parent emits a completed signal.
02121     if ( parentPart() == 0 ) {
02122       //kdDebug(6050) << this << " starting redirection timer" << endl;
02123       d->m_redirectionTimer.start( 1000 * d->m_delayRedirect, true );
02124     } else {
02125       //kdDebug(6050) << this << " not toplevel -> not starting redirection timer. Waiting for slotParentCompleted." << endl;
02126     }
02127 
02128     pendingAction = true;
02129   }
02130   else if ( bPendingChildRedirection )
02131   {
02132     pendingAction = true;
02133   }
02134 
02135   // the view will emit completed on our behalf,
02136   // either now or at next repaint if one is pending
02137 
02138   //kdDebug(6050) << this << " asks the view to emit completed. pendingAction=" << pendingAction << endl;
02139   d->m_view->complete( pendingAction );
02140 
02141   // find the alternate stylesheets
02142   QStringList sheets;
02143   if (d->m_doc)
02144      sheets = d->m_doc->availableStyleSheets();
02145   sheets.prepend( i18n( "Automatic Detection" ) );
02146   d->m_paUseStylesheet->setItems( sheets );
02147 
02148   d->m_paUseStylesheet->setEnabled( sheets.count() > 2);
02149   if (sheets.count() > 2)
02150   {
02151     d->m_paUseStylesheet->setCurrentItem(kMax(sheets.findIndex(d->m_sheetUsed), 0));
02152     slotUseStylesheet();
02153   }
02154 
02155   setJSDefaultStatusBarText(QString::null);
02156 
02157 #ifdef SPEED_DEBUG
02158   kdDebug(6050) << "DONE: " <<d->m_parsetime.elapsed() << endl;
02159 #endif
02160 }
02161 
02162 void KHTMLPart::checkEmitLoadEvent()
02163 {
02164   if ( d->m_bLoadEventEmitted || !d->m_doc || d->m_doc->parsing() ) return;
02165 
02166   ConstFrameIt it = d->m_frames.begin();
02167   const ConstFrameIt end = d->m_frames.end();
02168   for (; it != end; ++it )
02169     if ( !(*it)->m_bCompleted ) // still got a frame running -> too early
02170       return;
02171 
02172   ConstFrameIt oi = d->m_objects.begin();
02173   const ConstFrameIt oiEnd = d->m_objects.end();
02174 
02175   for (; oi != oiEnd; ++oi )
02176     if ( !(*oi)->m_bCompleted ) // still got a object running -> too early
02177       return;
02178 
02179   // Still waiting for images/scripts from the loader ?
02180   // (onload must happen afterwards, #45607)
02181   // ## This makes this method very similar to checkCompleted. A brave soul should try merging them.
02182   int requests = 0;
02183   if ( d->m_doc && d->m_doc->docLoader() )
02184     requests = khtml::Cache::loader()->numRequests( d->m_doc->docLoader() );
02185 
02186   if ( requests > 0 )
02187     return;
02188 
02189   d->m_bLoadEventEmitted = true;
02190   if (d->m_doc)
02191     d->m_doc->close();
02192 }
02193 
02194 const KHTMLSettings *KHTMLPart::settings() const
02195 {
02196   return d->m_settings;
02197 }
02198 
02199 #ifndef KDE_NO_COMPAT
02200 KURL KHTMLPart::baseURL() const
02201 {
02202   if ( !d->m_doc ) return KURL();
02203 
02204   return d->m_doc->baseURL();
02205 }
02206 
02207 QString KHTMLPart::baseTarget() const
02208 {
02209   if ( !d->m_doc ) return QString::null;
02210 
02211   return d->m_doc->baseTarget();
02212 }
02213 #endif
02214 
02215 KURL KHTMLPart::completeURL( const QString &url )
02216 {
02217   if ( !d->m_doc ) return KURL( url );
02218 
02219   if (d->m_decoder)
02220     return KURL(d->m_doc->completeURL(url), d->m_decoder->codec()->mibEnum());
02221 
02222   return KURL( d->m_doc->completeURL( url ) );
02223 }
02224 
02225 void KHTMLPart::scheduleRedirection( int delay, const QString &url, bool doLockHistory )
02226 {
02227   kdDebug(6050) << "KHTMLPart::scheduleRedirection delay=" << delay << " url=" << url << endl;
02228   kdDebug(6050) << "current redirectURL=" << d->m_redirectURL << " with delay " << d->m_delayRedirect <<  endl;
02229   if( delay < 24*60*60 &&
02230       ( d->m_redirectURL.isEmpty() || delay <= d->m_delayRedirect) ) {
02231     d->m_delayRedirect = delay;
02232     d->m_redirectURL = url;
02233     d->m_redirectLockHistory = doLockHistory;
02234     kdDebug(6050) << " d->m_bComplete=" << d->m_bComplete << endl;
02235     if ( d->m_bComplete ) {
02236       d->m_redirectionTimer.stop();
02237       d->m_redirectionTimer.start( kMax(0, 1000 * d->m_delayRedirect), true );
02238     }
02239   }
02240 }
02241 
02242 void KHTMLPart::slotRedirect()
02243 {
02244   kdDebug(6050) << this << " slotRedirect()" << endl;
02245   QString u = d->m_redirectURL;
02246   d->m_delayRedirect = 0;
02247   d->m_redirectURL = QString::null;
02248 
02249   // SYNC check with ecma/kjs_window.cpp::goURL !
02250   if ( u.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
02251   {
02252     QString script = KURL::decode_string( u.right( u.length() - 11 ) );
02253     kdDebug( 6050 ) << "KHTMLPart::slotRedirect script=" << script << endl;
02254     QVariant res = executeScript( DOM::Node(), script );
02255     if ( res.type() == QVariant::String ) {
02256       begin( url() );
02257       write( res.asString() );
02258       end();
02259     }
02260     return;
02261   }
02262   KParts::URLArgs args;
02263   // Redirecting to the current URL leads to a reload.
02264   // But jumping to an anchor never leads to a reload.
02265   KURL cUrl( m_url );
02266   KURL url( u );
02267 
02268   // handle windows opened by JS
02269   if ( openedByJS() && d->m_opener )
02270       cUrl = d->m_opener->url();
02271 
02272   if (!kapp || !kapp->authorizeURLAction("redirect", cUrl, url))
02273   {
02274     kdWarning(6050) << "KHTMLPart::scheduleRedirection: Redirection from " << cUrl.prettyURL() << " to " << url.prettyURL() << " REJECTED!" << endl;
02275     return;
02276   }
02277 
02278   if ( urlcmp( u, m_url.url(), true, true ) )
02279   {
02280     args.metaData().insert("referrer", d->m_pageReferrer);
02281   }
02282 
02283   // Indicate that this request is due to a redirection.
02284   args.setRedirectedRequest(true);
02285 
02286   args.setLockHistory( d->m_redirectLockHistory );
02287   // _self: make sure we don't use any <base target=>'s
02288   urlSelected( u, 0, 0, "_self", args );
02289 }
02290 
02291 void KHTMLPart::slotRedirection(KIO::Job*, const KURL& url)
02292 {
02293   // the slave told us that we got redirected
02294   //kdDebug( 6050 ) << "redirection by KIO to " << url.url() << endl;
02295   emit d->m_extension->setLocationBarURL( url.prettyURL() );
02296   d->m_workingURL = url;
02297 }
02298 
02299 bool KHTMLPart::setEncoding( const QString &name, bool override )
02300 {
02301     d->m_encoding = name;
02302     d->m_haveEncoding = override;
02303 
02304     if( !m_url.isEmpty() ) {
02305         // reload document
02306         closeURL();
02307         KURL url = m_url;
02308         m_url = 0;
02309         d->m_restored = true;
02310         openURL(url);
02311         d->m_restored = false;
02312     }
02313 
02314     return true;
02315 }
02316 
02317 QString KHTMLPart::encoding() const
02318 {
02319     if(d->m_haveEncoding && !d->m_encoding.isEmpty())
02320         return d->m_encoding;
02321 
02322     if(d->m_decoder && d->m_decoder->encoding())
02323         return QString(d->m_decoder->encoding());
02324 
02325     return defaultEncoding();
02326 }
02327 
02328 QString KHTMLPart::defaultEncoding() const
02329 {
02330   QString encoding = settings()->encoding();
02331   if ( !encoding.isEmpty() )
02332     return encoding;
02333   // HTTP requires the default encoding to be latin1, when neither
02334   // the user nor the page requested a particular encoding.
02335   if ( url().protocol().startsWith( "http" ) )
02336     return "iso-8859-1";
02337   else
02338     return KGlobal::locale()->encoding();
02339 }
02340 
02341 void KHTMLPart::setUserStyleSheet(const KURL &url)
02342 {
02343   if ( d->m_doc && d->m_doc->docLoader() )
02344     (void) new khtml::PartStyleSheetLoader(this, url.url(), d->m_doc->docLoader());
02345 }
02346 
02347 void KHTMLPart::setUserStyleSheet(const QString &styleSheet)
02348 {
02349   if ( d->m_doc )
02350     d->m_doc->setUserStyleSheet( styleSheet );
02351 }
02352 
02353 bool KHTMLPart::gotoAnchor( const QString &name )
02354 {
02355   if (!d->m_doc)
02356     return false;
02357 
02358   HTMLCollectionImpl *anchors =
02359       new HTMLCollectionImpl( d->m_doc, HTMLCollectionImpl::DOC_ANCHORS);
02360   anchors->ref();
02361   NodeImpl *n = anchors->namedItem(name);
02362   anchors->deref();
02363 
02364   if(!n) {
02365       n = d->m_doc->getElementById( name );
02366   }
02367 
02368   // Implement the rule that "" and "top" both mean top of page as in other browsers.
02369   bool quirkyName = !n && !d->m_doc->inStrictMode() && (name.isEmpty() || name.lower() == "top");
02370 
02371   if (quirkyName) {
02372       d->m_view->setContentsPos(0, 0);
02373       return true;
02374   } else if (!n) {
02375       kdDebug(6050) << "KHTMLPart::gotoAnchor node '" << name << "' not found" << endl;
02376       return false;
02377   }
02378 
02379   int x = 0, y = 0;
02380   int gox, dummy;
02381   HTMLElementImpl *a = static_cast<HTMLElementImpl *>(n);
02382 
02383   a->getUpperLeftCorner(x, y);
02384   if (x <= d->m_view->contentsX())
02385     gox = x - 10;
02386   else {
02387     gox = d->m_view->contentsX();
02388     if ( x + 10 > d->m_view->contentsX()+d->m_view->visibleWidth()) {
02389       a->getLowerRightCorner(x, dummy);
02390       gox = x - d->m_view->visibleWidth() + 10;
02391     }
02392   }
02393 
02394   d->m_view->setContentsPos(gox, y-20);
02395 
02396   return true;
02397 }
02398 
02399 bool KHTMLPart::nextAnchor()
02400 {
02401   if (!d->m_doc)
02402     return false;
02403   d->m_view->focusNextPrevNode ( true );
02404 
02405   return true;
02406 }
02407 
02408 bool KHTMLPart::prevAnchor()
02409 {
02410   if (!d->m_doc)
02411     return false;
02412   d->m_view->focusNextPrevNode ( false );
02413 
02414   return true;
02415 }
02416 
02417 void KHTMLPart::setStandardFont( const QString &name )
02418 {
02419     d->m_settings->setStdFontName(name);
02420 }
02421 
02422 void KHTMLPart::setFixedFont( const QString &name )
02423 {
02424     d->m_settings->setFixedFontName(name);
02425 }
02426 
02427 void KHTMLPart::setURLCursor( const QCursor &c )
02428 {
02429   d->m_linkCursor = c;
02430 }
02431 
02432 QCursor KHTMLPart::urlCursor() const
02433 {
02434   return d->m_linkCursor;
02435 }
02436 
02437 bool KHTMLPart::onlyLocalReferences() const
02438 {
02439   return d->m_onlyLocalReferences;
02440 }
02441 
02442 void KHTMLPart::setOnlyLocalReferences(bool enable)
02443 {
02444   d->m_onlyLocalReferences = enable;
02445 }
02446 
02447 void KHTMLPartPrivate::setFlagRecursively(
02448     bool KHTMLPartPrivate::*flag, bool value)
02449 {
02450   // first set it on the current one
02451   this->*flag = value;
02452 
02453   // descend into child frames recursively
02454   {
02455     QValueList<khtml::ChildFrame*>::Iterator it = m_frames.begin();
02456     const QValueList<khtml::ChildFrame*>::Iterator itEnd = m_frames.end();
02457     for (; it != itEnd; ++it) {
02458       KHTMLPart* const part = static_cast<KHTMLPart *>((KParts::ReadOnlyPart *)(*it)->m_part);
02459       if (part->inherits("KHTMLPart"))
02460         part->d->setFlagRecursively(flag, value);
02461     }/*next it*/
02462   }
02463   // do the same again for objects
02464   {
02465     QValueList<khtml::ChildFrame*>::Iterator it = m_objects.begin();
02466     const QValueList<khtml::ChildFrame*>::Iterator itEnd = m_objects.end();
02467     for (; it != itEnd; ++it) {
02468       KHTMLPart* const part = static_cast<KHTMLPart *>((KParts::ReadOnlyPart *)(*it)->m_part);
02469       if (part->inherits("KHTMLPart"))
02470         part->d->setFlagRecursively(flag, value);
02471     }/*next it*/
02472   }
02473 }
02474 
02475 void KHTMLPart::setCaretMode(bool enable)
02476 {
02477 #ifndef KHTML_NO_CARET
02478   kdDebug(6200) << "setCaretMode(" << enable << ")" << endl;
02479   if (isCaretMode() == enable) return;
02480   d->setFlagRecursively(&KHTMLPartPrivate::m_caretMode, enable);
02481   // FIXME: this won't work on frames as expected
02482   if (!isEditable()) {
02483     if (enable) {
02484       view()->initCaret(true);
02485       view()->ensureCaretVisible();
02486     } else
02487       view()->caretOff();
02488   }/*end if*/
02489 #endif // KHTML_NO_CARET
02490 }
02491 
02492 bool KHTMLPart::isCaretMode() const
02493 {
02494   return d->m_caretMode;
02495 }
02496 
02497 void KHTMLPart::setEditable(bool enable)
02498 {
02499 #ifndef KHTML_NO_CARET
02500   if (isEditable() == enable) return;
02501   d->setFlagRecursively(&KHTMLPartPrivate::m_designMode, enable);
02502   // FIXME: this won't work on frames as expected
02503   if (!isCaretMode()) {
02504     if (enable) {
02505       view()->initCaret(true);
02506       view()->ensureCaretVisible();
02507     } else
02508       view()->caretOff();
02509   }/*end if*/
02510 #endif // KHTML_NO_CARET
02511 }
02512 
02513 bool KHTMLPart::isEditable() const
02514 {
02515   return d->m_designMode;
02516 }
02517 
02518 void KHTMLPart::setCaretPosition(DOM::Node node, long offset, bool extendSelection)
02519 {
02520 #ifndef KHTML_NO_CARET
02521 #if 0
02522   kdDebug(6200) << k_funcinfo << "node: " << node.handle() << " nodeName: "
02523     << node.nodeName().string() << " offset: " << offset
02524     << " extendSelection " << extendSelection << endl;
02525 #endif
02526   if (view()->moveCaretTo(node.handle(), offset, !extendSelection))
02527     emitSelectionChanged();
02528   view()->ensureCaretVisible();
02529 #endif // KHTML_NO_CARET
02530 }
02531 
02532 KHTMLPart::CaretDisplayPolicy KHTMLPart::caretDisplayPolicyNonFocused() const
02533 {
02534 #ifndef KHTML_NO_CARET
02535   return (CaretDisplayPolicy)view()->caretDisplayPolicyNonFocused();
02536 #else // KHTML_NO_CARET
02537   return CaretInvisible;
02538 #endif // KHTML_NO_CARET
02539 }
02540 
02541 void KHTMLPart::setCaretDisplayPolicyNonFocused(CaretDisplayPolicy policy)
02542 {
02543 #ifndef KHTML_NO_CARET
02544   view()->setCaretDisplayPolicyNonFocused(policy);
02545 #endif // KHTML_NO_CARET
02546 }
02547 
02548 void KHTMLPart::setCaretVisible(bool show)
02549 {
02550 #ifndef KHTML_NO_CARET
02551   if (show) {
02552 
02553     NodeImpl *caretNode = xmlDocImpl()->focusNode();
02554     if (isCaretMode() || isEditable()
02555     || (caretNode && caretNode->contentEditable())) {
02556       view()->caretOn();
02557     }/*end if*/
02558 
02559   } else {
02560 
02561     view()->caretOff();
02562 
02563   }/*end if*/
02564 #endif // KHTML_NO_CARET
02565 }
02566 
02567 void KHTMLPart::findTextBegin()
02568 {
02569   d->m_findPos = -1;
02570   d->m_findNode = 0;
02571   d->m_findPosEnd = -1;
02572   d->m_findNodeEnd= 0;
02573   delete d->m_find;
02574   d->m_find = 0L;
02575 }
02576 
02577 bool KHTMLPart::initFindNode( bool selection, bool reverse, bool fromCursor )
02578 {
02579     if ( !d->m_doc )
02580         return false;
02581 
02582     DOM::NodeImpl* firstNode = 0L;
02583     if (d->m_doc->isHTMLDocument())
02584       firstNode = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
02585     else
02586       firstNode = d->m_doc;
02587 
02588     if ( !firstNode )
02589     {
02590       //kdDebug(6050) << k_funcinfo << "no first node (body or doc) -> return false" << endl;
02591       return false;
02592     }
02593     if ( firstNode->id() == ID_FRAMESET )
02594     {
02595       //kdDebug(6050) << k_funcinfo << "FRAMESET -> return false" << endl;
02596       return false;
02597     }
02598 
02599     if ( selection && hasSelection() )
02600     {
02601       //kdDebug(6050) << k_funcinfo << "using selection" << endl;
02602       if ( !fromCursor )
02603       {
02604         d->m_findNode = reverse ? d->m_selectionEnd.handle() : d->m_selectionStart.handle();
02605         d->m_findPos = reverse ? d->m_endOffset : d->m_startOffset;
02606       }
02607       d->m_findNodeEnd = reverse ? d->m_selectionStart.handle() : d->m_selectionEnd.handle();
02608       d->m_findPosEnd = reverse ? d->m_startOffset : d->m_endOffset;
02609     }
02610     else // whole document
02611     {
02612       //kdDebug(6050) << k_funcinfo << "whole doc" << endl;
02613       if ( !fromCursor )
02614       {
02615         d->m_findNode = firstNode;
02616         d->m_findPos = reverse ? -1 : 0;
02617       }
02618       d->m_findNodeEnd = reverse ? firstNode : 0;
02619       d->m_findPosEnd = reverse ? 0 : -1;
02620       if ( reverse )
02621       {
02622         // Need to find out the really last object, to start from it
02623         khtml::RenderObject* obj = d->m_findNode ? d->m_findNode->renderer() : 0;
02624         if ( obj )
02625         {
02626           // find the last object in the render tree
02627           while ( obj->lastChild() )
02628           {
02629               obj = obj->lastChild();
02630           }
02631           // now get the last object with a NodeImpl associated
02632           while ( !obj->element() && obj->objectAbove() )
02633           {
02634              obj = obj->objectAbove();
02635           }
02636           d->m_findNode = obj->element();
02637         }
02638       }
02639     }
02640     return true;
02641 }
02642 
02643 // Old method (its API limits the available features - remove in KDE-4)
02644 bool KHTMLPart::findTextNext( const QString &str, bool forward, bool caseSensitive, bool isRegExp )
02645 {
02646     if ( !initFindNode( false, !forward, false ) )
02647       return false;
02648     while(1)
02649     {
02650         if( (d->m_findNode->nodeType() == Node::TEXT_NODE || d->m_findNode->nodeType() == Node::CDATA_SECTION_NODE) && d->m_findNode->renderer() )
02651         {
02652             DOMString nodeText = d->m_findNode->nodeValue();
02653             DOMStringImpl *t = nodeText.implementation();
02654             QConstString s(t->s, t->l);
02655 
02656             int matchLen = 0;
02657             if ( isRegExp ) {
02658               QRegExp matcher( str );
02659               matcher.setCaseSensitive( caseSensitive );
02660               d->m_findPos = matcher.search(s.string(), d->m_findPos+1);
02661               if ( d->m_findPos != -1 )
02662                 matchLen = matcher.matchedLength();
02663             }
02664             else {
02665               d->m_findPos = s.string().find(str, d->m_findPos+1, caseSensitive);
02666               matchLen = str.length();
02667             }
02668 
02669             if(d->m_findPos != -1)
02670             {
02671                 int x = 0, y = 0;
02672                 if(static_cast<khtml::RenderText *>(d->m_findNode->renderer())
02673                   ->posOfChar(d->m_findPos, x, y))
02674                     d->m_view->setContentsPos(x-50, y-50);
02675 
02676                 d->m_selectionStart = d->m_findNode;
02677                 d->m_startOffset = d->m_findPos;
02678                 d->m_selectionEnd = d->m_findNode;
02679                 d->m_endOffset = d->m_findPos + matchLen;
02680                 d->m_startBeforeEnd = true;
02681 
02682                 d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
02683                                         d->m_selectionEnd.handle(), d->m_endOffset );
02684                 emitSelectionChanged();
02685                 return true;
02686             }
02687         }
02688         d->m_findPos = -1;
02689 
02690         NodeImpl *next;
02691 
02692         if ( forward )
02693         {
02694           next = d->m_findNode->firstChild();
02695 
02696           if(!next) next = d->m_findNode->nextSibling();
02697           while(d->m_findNode && !next) {
02698               d->m_findNode = d->m_findNode->parentNode();
02699               if( d->m_findNode ) {
02700                   next = d->m_findNode->nextSibling();
02701               }
02702           }
02703         }
02704         else
02705         {
02706           next = d->m_findNode->lastChild();
02707 
02708           if (!next ) next = d->m_findNode->previousSibling();
02709           while ( d->m_findNode && !next )
02710           {
02711             d->m_findNode = d->m_findNode->parentNode();
02712             if( d->m_findNode )
02713             {
02714               next = d->m_findNode->previousSibling();
02715             }
02716           }
02717         }
02718 
02719         d->m_findNode = next;
02720         if(!d->m_findNode) return false;
02721     }
02722 }
02723 
02724 
02725 void KHTMLPart::slotFind()
02726 {
02727   KParts::ReadOnlyPart *part = currentFrame();
02728   if (!part)
02729     return;
02730   if (!part->inherits("KHTMLPart") )
02731   {
02732       kdError(6000) << "slotFind: part is a " << part->className() << ", can't do a search into it" << endl;
02733       return;
02734   }
02735   static_cast<KHTMLPart *>( part )->findText();
02736 }
02737 
02738 void KHTMLPart::slotFindNext()
02739 {
02740   KParts::ReadOnlyPart *part = currentFrame();
02741   if (!part)
02742     return;
02743   if (!part->inherits("KHTMLPart") )
02744   {
02745       kdError(6000) << "slotFindNext: part is a " << part->className() << ", can't do a search into it" << endl;
02746       return;
02747   }
02748   static_cast<KHTMLPart *>( part )->findTextNext();
02749 }
02750 
02751 void KHTMLPart::slotFindDone()
02752 {
02753   // ### remove me
02754 }
02755 
02756 void KHTMLPart::slotFindDialogDestroyed()
02757 {
02758   d->m_lastFindState.options = d->m_findDialog->options();
02759   d->m_lastFindState.history = d->m_findDialog->findHistory();
02760   d->m_findDialog->deleteLater();
02761   d->m_findDialog = 0L;
02762 }
02763 
02764 void KHTMLPart::findText()
02765 {
02766   // First do some init to make sure we can search in this frame
02767   if ( !d->m_doc )
02768     return;
02769 
02770   // Raise if already opened
02771   if ( d->m_findDialog )
02772   {
02773     KWin::activateWindow( d->m_findDialog->winId() );
02774     return;
02775   }
02776 
02777   // The lineedit of the dialog would make khtml lose its selection, otherwise
02778 #ifndef QT_NO_CLIPBOARD
02779   disconnect( kapp->clipboard(), SIGNAL(selectionChanged()), this, SLOT(slotClearSelection()) );
02780 #endif
02781 
02782   // Now show the dialog in which the user can choose options.
02783   d->m_findDialog = new KFindDialog( false /*non-modal*/, widget(), "khtmlfind" );
02784   d->m_findDialog->setHasSelection( hasSelection() );
02785   d->m_findDialog->setHasCursor( d->m_findNode != 0 );
02786   if ( d->m_findNode ) // has a cursor -> default to 'FromCursor'
02787     d->m_lastFindState.options |= KFindDialog::FromCursor;
02788 
02789   // TODO? optionsDialog.setPattern( d->m_lastFindState.text );
02790   d->m_findDialog->setFindHistory( d->m_lastFindState.history );
02791   d->m_findDialog->setOptions( d->m_lastFindState.options );
02792 
02793   d->m_lastFindState.options = -1; // force update in findTextNext
02794 
02795   d->m_findDialog->show();
02796   connect( d->m_findDialog, SIGNAL(okClicked()), this, SLOT(slotFindNext()) );
02797   connect( d->m_findDialog, SIGNAL(finished()), this, SLOT(slotFindDialogDestroyed()) );
02798 
02799   findText( d->m_findDialog->pattern(), 0 /*options*/, widget(), d->m_findDialog );
02800 }
02801 
02802 void KHTMLPart::findText( const QString &str, long options, QWidget *parent, KFindDialog *findDialog )
02803 {
02804   // First do some init to make sure we can search in this frame
02805   if ( !d->m_doc )
02806     return;
02807 
02808 #ifndef QT_NO_CLIPBOARD
02809   connect( kapp->clipboard(), SIGNAL(selectionChanged()), SLOT(slotClearSelection()) );
02810 #endif
02811 
02812   // Create the KFind object
02813   delete d->m_find;
02814   d->m_find = new KFind( str, options, parent, findDialog );
02815   d->m_find->closeFindNextDialog(); // we use KFindDialog non-modal, so we don't want other dlg popping up
02816   connect( d->m_find, SIGNAL( highlight( const QString &, int, int ) ),
02817            this, SLOT( slotHighlight( const QString &, int, int ) ) );
02818   //connect(d->m_find, SIGNAL( findNext() ),
02819   //        this, SLOT( slotFindNext() ) );
02820 
02821   if ( !findDialog )
02822   {
02823     d->m_lastFindState.options = options;
02824     initFindNode( options & KFindDialog::SelectedText,
02825                   options & KFindDialog::FindBackwards,
02826                   options & KFindDialog::FromCursor );
02827   }
02828 }
02829 
02830 // New method
02831 bool KHTMLPart::findTextNext()
02832 {
02833   if (!d->m_find)
02834   {
02835     // We didn't show the find dialog yet, let's do it then (#49442)
02836     findText();
02837     return false;
02838   }
02839 
02840   long options = 0;
02841   if ( d->m_findDialog ) // 0 when we close the dialog
02842   {
02843     if ( d->m_find->pattern() != d->m_findDialog->pattern() ) {
02844       d->m_find->setPattern( d->m_findDialog->pattern() );
02845       d->m_find->resetCounts();
02846     }
02847     options = d->m_findDialog->options();
02848     if ( d->m_lastFindState.options != options )
02849     {
02850       d->m_find->setOptions( options );
02851 
02852       if ( options & KFindDialog::SelectedText )
02853         Q_ASSERT( hasSelection() );
02854 
02855       long difference = d->m_lastFindState.options ^ options;
02856       if ( difference & (KFindDialog::SelectedText | KFindDialog::FromCursor ) )
02857       {
02858           // Important options changed -> reset search range
02859         (void) initFindNode( options & KFindDialog::SelectedText,
02860                              options & KFindDialog::FindBackwards,
02861                              options & KFindDialog::FromCursor );
02862       }
02863       d->m_lastFindState.options = options;
02864     }
02865   } else
02866     options = d->m_lastFindState.options;
02867 
02868   KFind::Result res = KFind::NoMatch;
02869   khtml::RenderObject* obj = d->m_findNode ? d->m_findNode->renderer() : 0;
02870   khtml::RenderObject* end = d->m_findNodeEnd ? d->m_findNodeEnd->renderer() : 0;
02871   khtml::RenderTextArea *tmpTextArea=0L;
02872   //kdDebug(6050) << k_funcinfo << "obj=" << obj << " end=" << end << endl;
02873   while( res == KFind::NoMatch )
02874   {
02875     if ( d->m_find->needData() )
02876     {
02877       if ( !obj ) {
02878         //kdDebug(6050) << k_funcinfo << "obj=0 -> done" << endl;
02879         break; // we're done
02880       }
02881       //kdDebug(6050) << k_funcinfo << " gathering data" << endl;
02882       // First make up the QString for the current 'line' (i.e. up to \n)
02883       // We also want to remember the DOMNode for every portion of the string.
02884       // We store this in an index->node list.
02885 
02886       d->m_stringPortions.clear();
02887       int newLinePos = -1;
02888       QString str;
02889       DOM::NodeImpl* lastNode = d->m_findNode;
02890       while ( obj && newLinePos == -1 )
02891       {
02892         // Grab text from render object
02893         QString s;
02894         bool renderAreaText = obj->parent() && (QCString(obj->parent()->renderName())== "RenderTextArea");
02895         bool renderLineText = (QCString(obj->renderName())== "RenderLineEdit");
02896         if ( renderAreaText )
02897         {
02898           khtml::RenderTextArea *parent= static_cast<khtml::RenderTextArea *>(obj->parent());
02899           s = parent->text();
02900           s = s.replace(0xa0, ' ');
02901           tmpTextArea = parent;
02902         }
02903         else if ( renderLineText )
02904         {
02905           khtml::RenderLineEdit *parentLine= static_cast<khtml::RenderLineEdit *>(obj);
02906           s = parentLine->widget()->text();
02907           s = s.replace(0xa0, ' ');
02908         }
02909         else if ( obj->isText() )
02910         {
02911           bool isLink = false;
02912 
02913           // checks whether the node has a <A> parent
02914           if ( options & FindLinksOnly )
02915           {
02916             DOM::NodeImpl *parent = obj->element();
02917             while ( parent )
02918             {
02919               if ( parent->nodeType() == Node::ELEMENT_NODE && parent->id() == ID_A )
02920               {
02921                 isLink = true;
02922                 break;
02923               }
02924               parent = parent->parentNode();
02925             }
02926           }
02927           else
02928           {
02929             isLink = true;
02930           }
02931 
02932           if ( isLink && obj->parent()!=tmpTextArea )
02933           {
02934             s = static_cast<khtml::RenderText *>(obj)->data().string();
02935             s = s.replace(0xa0, ' ');
02936           }
02937         }
02938         else if ( obj->isBR() )
02939           s = '\n';
02940         else if ( !obj->isInline() && !str.isEmpty() )
02941           s = '\n';
02942 
02943         if ( lastNode == d->m_findNodeEnd )
02944           s.truncate( d->m_findPosEnd );
02945         if ( !s.isEmpty() )
02946         {
02947           newLinePos = s.find( '\n' ); // did we just get a newline?
02948           int index = str.length();
02949           if ( newLinePos != -1 )
02950             newLinePos += index;
02951           str += s;
02952           //kdDebug(6050) << "StringPortion: " << index << "-" << index+s.length()-1 << " -> " << lastNode << endl;
02953           d->m_stringPortions.append( KHTMLPartPrivate::StringPortion( index, lastNode ) );
02954         }
02955         // Compare obj and end _after_ we processed the 'end' node itself
02956         if ( obj == end )
02957           obj = 0L;
02958         else
02959         {
02960           // Move on to next object (note: if we found a \n already, then obj (and lastNode)
02961           // will point to the _next_ object, i.e. they are in advance.
02962           do {
02963             // We advance until the next RenderObject that has a NodeImpl as its element().
02964             // Otherwise (if we keep the 'last node', and it has a '\n') we might be stuck
02965             // on that object forever...
02966             obj = (options & KFindDialog::FindBackwards) ? obj->objectAbove() : obj->objectBelow();
02967           } while ( obj && ( !obj->element() || obj->isInlineContinuation() ) );
02968         }
02969         if ( obj )
02970           lastNode = obj->element();
02971         else
02972           lastNode = 0;
02973       } // end while
02974       //kdDebug()<<" str : "<<str<<endl;
02975       if ( !str.isEmpty() )
02976       {
02977         d->m_find->setData( str, d->m_findPos );
02978       }
02979 
02980       d->m_findPos = -1; // not used during the findnext loops. Only during init.
02981       d->m_findNode = lastNode;
02982     }
02983     if ( !d->m_find->needData() ) // happens if str was empty
02984     {
02985       // Let KFind inspect the text fragment, and emit highlighted if a match is found
02986       res = d->m_find->find();
02987     }
02988   } // end while
02989 
02990   if ( res == KFind::NoMatch ) // i.e. we're done
02991   {
02992     kdDebug() << "No more matches." << endl;
02993     if ( !(options & FindNoPopups) && d->m_find->shouldRestart() )
02994     {
02995       //kdDebug(6050) << "Restarting" << endl;
02996       initFindNode( false, options & KFindDialog::FindBackwards, false );
02997       findTextNext();
02998     }
02999     else // really done
03000     {
03001       //kdDebug(6050) << "Finishing" << endl;
03002       //delete d->m_find;
03003       //d->m_find = 0L;
03004       initFindNode( false, options & KFindDialog::FindBackwards, false );
03005       d->m_find->resetCounts();
03006       slotClearSelection();
03007     }
03008     kdDebug() << "Dialog closed." << endl;
03009   }
03010 
03011   return res == KFind::Match;
03012 }
03013 
03014 void KHTMLPart::slotHighlight( const QString& /*text*/, int index, int length )
03015 {
03016   //kdDebug(6050) << "slotHighlight index=" << index << " length=" << length << endl;
03017   QValueList<KHTMLPartPrivate::StringPortion>::Iterator it = d->m_stringPortions.begin();
03018   const QValueList<KHTMLPartPrivate::StringPortion>::Iterator itEnd = d->m_stringPortions.end();
03019   QValueList<KHTMLPartPrivate::StringPortion>::Iterator prev = it;
03020   // We stop at the first portion whose index is 'greater than', and then use the previous one
03021   while ( it != itEnd && (*it).index <= index )
03022   {
03023     prev = it;
03024     ++it;
03025   }
03026   Q_ASSERT ( prev != itEnd );
03027   DOM::NodeImpl* node = (*prev).node;
03028   Q_ASSERT( node );
03029 
03030   d->m_selectionStart = node;
03031   d->m_startOffset = index - (*prev).index;
03032 
03033   khtml::RenderObject* obj = node->renderer();
03034   khtml::RenderTextArea *parent = 0L;
03035   khtml::RenderLineEdit *parentLine = 0L;
03036   bool renderLineText =false;
03037 
03038   QRect highlightedRect;
03039   bool renderAreaText =false;
03040   Q_ASSERT( obj );
03041   if ( obj )
03042   {
03043     int x = 0, y = 0;
03044     renderAreaText = (QCString(obj->parent()->renderName())== "RenderTextArea");
03045     renderLineText = (QCString(obj->renderName())== "RenderLineEdit");
03046 
03047 
03048     if( renderAreaText )
03049       parent= static_cast<khtml::RenderTextArea *>(obj->parent());
03050     if ( renderLineText )
03051       parentLine= static_cast<khtml::RenderLineEdit *>(obj);
03052     if ( !renderLineText )
03053       //if (static_cast<khtml::RenderText *>(node->renderer())
03054       //    ->posOfChar(d->m_startOffset, x, y))
03055       {
03056         int dummy;
03057         static_cast<khtml::RenderText *>(node->renderer())
03058           ->caretPos( d->m_startOffset, false, x, y, dummy, dummy ); // more precise than posOfChar
03059         //kdDebug(6050) << "topleft: " << x << "," << y << endl;
03060         if ( x != -1 || y != -1 )
03061         {
03062           d->m_view->setContentsPos(x-50, y-50);
03063           highlightedRect.setTopLeft( d->m_view->mapToGlobal(QPoint(x, y)) );
03064         }
03065       }
03066   }
03067   // Now look for end node
03068   it = prev; // no need to start from beginning again
03069   while ( it != itEnd && (*it).index < index + length )
03070   {
03071     prev = it;
03072     ++it;
03073   }
03074   Q_ASSERT ( prev != itEnd );
03075 
03076   d->m_selectionEnd = (*prev).node;
03077   d->m_endOffset = index + length - (*prev).index;
03078   d->m_startBeforeEnd = true;
03079 
03080   // if the selection is limited to a single link, that link gets focus
03081   if(d->m_selectionStart == d->m_selectionEnd)
03082   {
03083     bool isLink = false;
03084 
03085     // checks whether the node has a <A> parent
03086     DOM::NodeImpl *parent = d->m_selectionStart.handle();
03087     while ( parent )
03088     {
03089       if ( parent->nodeType() == Node::ELEMENT_NODE && parent->id() == ID_A )
03090       {
03091         isLink = true;
03092         break;
03093       }
03094       parent = parent->parentNode();
03095     }
03096 
03097     if(isLink == true)
03098     {
03099       d->m_doc->setFocusNode( parent );
03100     }
03101   }
03102 
03103 #if 0
03104   kdDebug(6050) << "slotHighlight: " << d->m_selectionStart.handle() << "," << d->m_startOffset << " - " <<
03105     d->m_selectionEnd.handle() << "," << d->m_endOffset << endl;
03106   it = d->m_stringPortions.begin();
03107   for ( ; it != d->m_stringPortions.end() ; ++it )
03108     kdDebug(6050) << "  StringPortion: from index=" << (*it).index << " -> node=" << (*it).node << endl;
03109 #endif
03110   if( renderAreaText )
03111   {
03112     if( parent )
03113       parent->highLightWord( length, d->m_endOffset-length );
03114   }
03115   else if ( renderLineText )
03116   {
03117     if( parentLine )
03118       parentLine->highLightWord( length, d->m_endOffset-length );
03119   }
03120   else
03121   {
03122     d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
03123                             d->m_selectionEnd.handle(), d->m_endOffset );
03124     if (d->m_selectionEnd.handle()->renderer() )
03125     {
03126       int x, y, height, dummy;
03127       static_cast<khtml::RenderText *>(d->m_selectionEnd.handle()->renderer())
03128           ->caretPos( d->m_endOffset, false, x, y, dummy, height ); // more precise than posOfChar
03129       //kdDebug(6050) << "bottomright: " << x << "," << y+height << endl;
03130       if ( x != -1 || y != -1 )
03131       {
03132         // if ( static_cast<khtml::RenderText *>(d->m_selectionEnd.handle()->renderer())
03133         //  ->posOfChar(d->m_endOffset-1, x, y))
03134         highlightedRect.setBottomRight( d->m_view->mapToGlobal( QPoint(x, y+height) ) );
03135       }
03136     }
03137   }
03138   emitSelectionChanged();
03139 
03140   // make the finddialog move away from the selected area
03141   if ( d->m_findDialog && !highlightedRect.isNull() )
03142   {
03143     highlightedRect.moveBy( -d->m_view->contentsX(), -d->m_view->contentsY() );
03144     //kdDebug(6050) << "avoiding " << highlightedRect << endl;
03145     KDialog::avoidArea( d->m_findDialog, highlightedRect );
03146   }
03147 }
03148 
03149 QString KHTMLPart::selectedText() const
03150 {
03151   bool hasNewLine = true;
03152   QString text;
03153   DOM::Node n = d->m_selectionStart;
03154   while(!n.isNull()) {
03155       if(n.nodeType() == DOM::Node::TEXT_NODE && n.handle()->renderer()) {
03156         QString str = n.nodeValue().string();
03157         hasNewLine = false;
03158         if(n == d->m_selectionStart && n == d->m_selectionEnd)
03159           text = str.mid(d->m_startOffset, d->m_endOffset - d->m_startOffset);
03160         else if(n == d->m_selectionStart)
03161           text = str.mid(d->m_startOffset);
03162         else if(n == d->m_selectionEnd)
03163           text += str.left(d->m_endOffset);
03164         else
03165           text += str;
03166       }
03167       else {
03168         // This is our simple HTML -> ASCII transformation:
03169         unsigned short id = n.elementId();
03170         switch(id) {
03171           case ID_BR:
03172             text += "\n";
03173             hasNewLine = true;
03174             break;
03175 
03176           case ID_TD:
03177           case ID_TH:
03178           case ID_HR:
03179           case ID_OL:
03180           case ID_UL:
03181           case ID_LI:
03182           case ID_DD:
03183           case ID_DL:
03184           case ID_DT:
03185           case ID_PRE:
03186           case ID_BLOCKQUOTE:
03187           case ID_DIV:
03188             if (!hasNewLine)
03189                text += "\n";
03190             hasNewLine = true;
03191             break;
03192           case ID_P:
03193           case ID_TR:
03194           case ID_H1:
03195           case ID_H2:
03196           case ID_H3:
03197           case ID_H4:
03198           case ID_H5:
03199           case ID_H6:
03200             if (!hasNewLine)
03201                text += "\n";
03202             text += "\n";
03203             hasNewLine = true;
03204             break;
03205         }
03206       }
03207       if(n == d->m_selectionEnd) break;
03208       DOM::Node next = n.firstChild();
03209       if(next.isNull()) next = n.nextSibling();
03210       while( next.isNull() && !n.parentNode().isNull() ) {
03211         n = n.parentNode();
03212         next = n.nextSibling();
03213         unsigned short id = n.elementId();
03214         switch(id) {
03215           case ID_TD:
03216           case ID_TH:
03217           case ID_HR:
03218           case ID_OL:
03219           case ID_UL:
03220           case ID_LI:
03221           case ID_DD:
03222           case ID_DL:
03223           case ID_DT:
03224           case ID_PRE:
03225           case ID_BLOCKQUOTE:
03226           case ID_DIV:
03227             if (!hasNewLine)
03228                text += "\n";
03229             hasNewLine = true;
03230             break;
03231           case ID_P:
03232           case ID_TR:
03233           case ID_H1:
03234           case ID_H2:
03235           case ID_H3:
03236           case ID_H4:
03237           case ID_H5:
03238           case ID_H6:
03239             if (!hasNewLine)
03240                text += "\n";
03241             text += "\n";
03242             hasNewLine = true;
03243             break;
03244         }
03245       }
03246 
03247       n = next;
03248     }
03249 
03250     if(text.isEmpty())
03251         return QString::null;
03252 
03253     int start = 0;
03254     int end = text.length();
03255 
03256     // Strip leading LFs
03257     while ((start < end) && (text[start] == '\n'))
03258        ++start;
03259 
03260     // Strip excessive trailing LFs
03261     while ((start < (end-1)) && (text[end-1] == '\n') && (text[end-2] == '\n'))
03262        --end;
03263 
03264     return text.mid(start, end-start);
03265 }
03266 
03267 bool KHTMLPart::hasSelection() const
03268 {
03269   if ( d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() )
03270       return false;
03271   if ( d->m_selectionStart == d->m_selectionEnd &&
03272        d->m_startOffset == d->m_endOffset )
03273       return false; // empty
03274   return true;
03275 }
03276 
03277 DOM::Range KHTMLPart::selection() const
03278 {
03279     DOM::Range r = document().createRange();
03280     r.setStart( d->m_selectionStart, d->m_startOffset );
03281     r.setEnd( d->m_selectionEnd, d->m_endOffset );
03282     return r;
03283 }
03284 
03285 void KHTMLPart::selection(DOM::Node &s, long &so, DOM::Node &e, long &eo) const
03286 {
03287     s = d->m_selectionStart;
03288     so = d->m_startOffset;
03289     e = d->m_selectionEnd;
03290     eo = d->m_endOffset;
03291 }
03292 
03293 void KHTMLPart::setSelection( const DOM::Range &r )
03294 {
03295     // Quick-fix: a collapsed range shouldn't select the whole node.
03296     // The real problem is in RenderCanvas::setSelection though (when index==0 the whole node is selected).
03297     if ( r.collapsed() )
03298         slotClearSelection();
03299     else {
03300         d->m_selectionStart = r.startContainer();
03301         d->m_startOffset = r.startOffset();
03302         d->m_selectionEnd = r.endContainer();
03303         d->m_endOffset = r.endOffset();
03304         d->m_doc->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
03305                                d->m_selectionEnd.handle(),d->m_endOffset);
03306 #ifndef KHTML_NO_CARET
03307         bool v = d->m_view->placeCaret();
03308         emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
03309 #endif
03310     }
03311 }
03312 
03313 void KHTMLPart::slotClearSelection()
03314 {
03315     bool hadSelection = hasSelection();
03316 #ifndef KHTML_NO_CARET
03317     //kdDebug(6000) << "d->m_selectionStart " << d->m_selectionStart.handle()
03318     //      << " d->m_selectionEnd " << d->m_selectionEnd.handle() << endl;
03319     // nothing, leave selection parameters as is
03320 #else
03321     d->m_selectionStart = 0;
03322     d->m_startOffset = 0;
03323     d->m_selectionEnd = 0;
03324     d->m_endOffset = 0;
03325 #endif
03326     if ( d->m_doc ) d->m_doc->clearSelection();
03327     if ( hadSelection )
03328       emitSelectionChanged();
03329 #ifndef KHTML_NO_CARET
03330     bool v = d->m_view->placeCaret();
03331     emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
03332 #endif
03333 }
03334 
03335 void KHTMLPart::overURL( const QString &url, const QString &target, bool /*shiftPressed*/ )
03336 {
03337   KURL u = completeURL(url);
03338 
03339   // special case for <a href="">
03340   if ( url.isEmpty() )
03341     u.setFileName( url );
03342 
03343   emit onURL( url );
03344 
03345   if ( url.isEmpty() ) {
03346     setStatusBarText(u.htmlURL(), BarHoverText);
03347     return;
03348   }
03349 
03350   if (url.find( QString::fromLatin1( "javascript:" ),0, false ) == 0 ) {
03351     QString jscode = KURL::decode_string( url.mid( url.find( "javascript:", 0, false ) ) );
03352     jscode = KStringHandler::rsqueeze( jscode, 80 ); // truncate if too long
03353     setStatusBarText( QStyleSheet::escape( jscode ), BarHoverText );
03354     return;
03355   }
03356 
03357   KFileItem item(u, QString::null, KFileItem::Unknown);
03358   emit d->m_extension->mouseOverInfo(&item);
03359 
03360   QString com;
03361 
03362   KMimeType::Ptr typ = KMimeType::findByURL( u );
03363 
03364   if ( typ )
03365     com = typ->comment( u, false );
03366 
03367   if ( !u.isValid() ) {
03368     setStatusBarText(u.htmlURL(), BarHoverText);
03369     return;
03370   }
03371 
03372   if ( u.isLocalFile() )
03373   {
03374     // TODO : use KIO::stat() and create a KFileItem out of its result,
03375     // to use KFileItem::statusBarText()
03376     QCString path = QFile::encodeName( u.path() );
03377 
03378     struct stat buff;
03379     bool ok = !stat( path.data(), &buff );
03380 
03381     struct stat lbuff;
03382     if (ok) ok = !lstat( path.data(), &lbuff );
03383 
03384     QString text = u.htmlURL();
03385     QString text2 = text;
03386 
03387     if (ok && S_ISLNK( lbuff.st_mode ) )
03388     {
03389       QString tmp;
03390       if ( com.isNull() )
03391         tmp = i18n( "Symbolic Link");
03392       else
03393         tmp = i18n("%1 (Link)").arg(com);
03394       char buff_two[1024];
03395       text += " -> ";
03396       int n = readlink ( path.data(), buff_two, 1022);
03397       if (n == -1)
03398       {
03399         text2 += "  ";
03400         text2 += tmp;
03401         setStatusBarText(text2, BarHoverText);
03402         return;
03403       }
03404       buff_two[n] = 0;
03405 
03406       text += buff_two;
03407       text += "  ";
03408       text += tmp;
03409     }
03410     else if ( ok && S_ISREG( buff.st_mode ) )
03411     {
03412       if (buff.st_size < 1024)
03413         text = i18n("%2 (%1 bytes)").arg((long) buff.st_size).arg(text2); // always put the URL last, in case it contains '%'
03414       else
03415       {
03416         float d = (float) buff.st_size/1024.0;
03417         text = i18n("%2 (%1 K)").arg(KGlobal::locale()->formatNumber(d, 2)).arg(text2); // was %.2f
03418       }
03419       text += "  ";
03420       text += com;
03421     }
03422     else if ( ok && S_ISDIR( buff.st_mode ) )
03423     {
03424       text += "  ";
03425       text += com;
03426     }
03427     else
03428     {
03429       text += "  ";
03430       text += com;
03431     }
03432     setStatusBarText(text, BarHoverText);
03433   }
03434   else
03435   {
03436     QString extra;
03437     if (target.lower() == "_blank")
03438     {
03439       extra = i18n(" (In new window)");
03440     }
03441     else if (!target.isEmpty() &&
03442              (target.lower() != "_top") &&
03443              (target.lower() != "_self") &&
03444              (target.lower() != "_parent"))
03445     {
03446       extra = i18n(" (In other frame)");
03447     }
03448 
03449     if (u.protocol() == QString::fromLatin1("mailto")) {
03450       QString mailtoMsg /* = QString::fromLatin1("<img src=%1>").arg(locate("icon", QString::fromLatin1("locolor/16x16/actions/mail_send.png")))*/;
03451       mailtoMsg += i18n("Email to: ") + KURL::decode_string(u.path());
03452       QStringList queries = QStringList::split('&', u.query().mid(1));
03453       QStringList::Iterator it = queries.begin();
03454       const QStringList::Iterator itEnd = queries.end();
03455       for (; it != itEnd; ++it)
03456         if ((*it).startsWith(QString::fromLatin1("subject=")))
03457           mailtoMsg += i18n(" - Subject: ") + KURL::decode_string((*it).mid(8));
03458         else if ((*it).startsWith(QString::fromLatin1("cc=")))
03459           mailtoMsg += i18n(" - CC: ") + KURL::decode_string((*it).mid(3));
03460         else if ((*it).startsWith(QString::fromLatin1("bcc=")))
03461           mailtoMsg += i18n(" - BCC: ") + KURL::decode_string((*it).mid(4));
03462       mailtoMsg.replace(QString::fromLatin1("&"), QString("&amp;"));
03463       mailtoMsg.replace(QString::fromLatin1("<"), QString("&lt;"));
03464       mailtoMsg.replace(QString::fromLatin1(">"), QString("&gt;"));
03465       mailtoMsg.replace(QRegExp("([\n\r\t]|[ ]{10})"), QString::null);
03466       setStatusBarText("<qt>"+mailtoMsg, BarHoverText);
03467       return;
03468     }
03469    // Is this check necessary at all? (Frerich)
03470 #if 0
03471     else if (u.protocol() == QString::fromLatin1("http")) {
03472         DOM::Node hrefNode = nodeUnderMouse().parentNode();
03473         while (hrefNode.nodeName().string() != QString::fromLatin1("A") && !hrefNode.isNull())
03474           hrefNode = hrefNode.parentNode();
03475 
03476         if (!hrefNode.isNull()) {
03477           DOM::Node hreflangNode = hrefNode.attributes().getNamedItem("HREFLANG");
03478           if (!hreflangNode.isNull()) {
03479             QString countryCode = hreflangNode.nodeValue().string().lower();
03480             // Map the language code to an appropriate country code.
03481             if (countryCode == QString::fromLatin1("en"))
03482               countryCode = QString::fromLatin1("gb");
03483             QString flagImg = QString::fromLatin1("<img src=%1>").arg(
03484                 locate("locale", QString::fromLatin1("l10n/")
03485                 + countryCode
03486                 + QString::fromLatin1("/flag.png")));
03487             emit setStatusBarText(flagImg + u.prettyURL() + extra);
03488           }
03489         }
03490       }
03491 #endif
03492     setStatusBarText(u.htmlURL() + extra, BarHoverText);
03493   }
03494 }
03495 
03496 //
03497 // This executes in the active part on a click or other url selection action in
03498 // that active part.
03499 //
03500 void KHTMLPart::urlSelected( const QString &url, int button, int state, const QString &_target, KParts::URLArgs args )
03501 {
03502   bool hasTarget = false;
03503 
03504   QString target = _target;
03505   if ( target.isEmpty() && d->m_doc )
03506     target = d->m_doc->baseTarget();
03507   if ( !target.isEmpty() )
03508       hasTarget = true;
03509 
03510   if ( url.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
03511   {
03512     crossFrameExecuteScript( target, KURL::decode_string( url.mid( 11 ) ) );
03513     return;
03514   }
03515 
03516   KURL cURL = completeURL(url);
03517   // special case for <a href="">  (IE removes filename, mozilla doesn't)
03518   if ( url.isEmpty() )
03519     cURL.setFileName( url ); // removes filename
03520 
03521   if ( !cURL.isValid() )
03522     // ### ERROR HANDLING
03523     return;
03524 
03525   kdDebug(6050) << this << "urlSelected: complete URL:" << cURL.url() << " target=" << target << endl;
03526 
03527   if ( state & ControlButton )
03528   {
03529     args.setNewTab(true);
03530     emit d->m_extension->createNewWindow( cURL, args );
03531     return;
03532   }
03533 
03534   if ( button == LeftButton && ( state & ShiftButton ) )
03535   {
03536     KIO::MetaData metaData;
03537     metaData["referrer"] = d->m_referrer;
03538     KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), cURL, metaData );
03539     return;
03540   }
03541 
03542   if (!checkLinkSecurity(cURL,
03543              i18n( "<qt>This untrusted page links to<BR><B>%1</B>.<BR>Do you want to follow the link?" ),
03544              i18n( "Follow" )))
03545     return;
03546 
03547   args.frameName = target;
03548 
03549   args.metaData().insert("main_frame_request",
03550                          parentPart() == 0 ? "TRUE":"FALSE");
03551   args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
03552   args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
03553   args.metaData().insert("PropagateHttpHeader", "true");
03554   args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
03555   args.metaData().insert("ssl_activate_warnings", "TRUE");
03556   // WABA: When we select the link explicitly we should treat this new URL as the
03557   // toplevel url and it should never be considered cross-domain.
03558   // However this function is also called for javascript and META-tag based
03559   // redirections:
03560   //   - In such case, we don't take cross-domain-ness in consideration if we are the
03561   //   toplevel frame because the new URL may be in a different domain as the current URL
03562   //   but that's ok.
03563   //   - If we are not the toplevel frame then we check against the toplevelURL()
03564   if (args.redirectedRequest() && parentPart())
03565       args.metaData().insert("cross-domain", toplevelURL().url());
03566 
03567   if ( hasTarget && target != "_self" && target != "_top" && target != "_blank" && target != "_parent" )
03568   {
03569     // unknown frame names should open in a new window.
03570     khtml::ChildFrame *frame = recursiveFrameRequest( this, cURL, args, false );
03571     if ( frame )
03572     {
03573       args.metaData()["referrer"] = d->m_referrer;
03574       requestObject( frame, cURL, args );
03575       return;
03576     }
03577   }
03578 
03579   if ( !d->m_bComplete && !hasTarget )
03580     closeURL();
03581 
03582   if (!d->m_referrer.isEmpty() && !args.metaData().contains("referrer"))
03583     args.metaData()["referrer"] = d->m_referrer;
03584 
03585   if ( button == NoButton && (state & ShiftButton) && (state & ControlButton) )
03586   {
03587     emit d->m_extension->createNewWindow( cURL, args );
03588     return;
03589   }
03590 
03591   if ( state & ShiftButton)
03592   {
03593     KParts::WindowArgs winArgs;
03594     winArgs.lowerWindow = true;
03595     KParts::ReadOnlyPart *newPart = 0;
03596     emit d->m_extension->createNewWindow( cURL, args, winArgs, newPart );
03597     return;
03598   }
03599 
03600   view()->viewport()->unsetCursor();
03601   emit d->m_extension->openURLRequest( cURL, args );
03602 }
03603 
03604 void KHTMLPart::slotViewDocumentSource()
03605 {
03606   KURL url(m_url);
03607   bool isTempFile = false;
03608   if (!(url.isLocalFile()) && KHTMLPageCache::self()->isComplete(d->m_cacheId))
03609   {
03610      KTempFile sourceFile(QString::null, QString::fromLatin1(".html"));
03611      if (sourceFile.status() == 0)
03612      {
03613         KHTMLPageCache::self()->saveData(d->m_cacheId, sourceFile.dataStream());
03614         url = KURL();
03615         url.setPath(sourceFile.name());
03616         isTempFile = true;
03617      }
03618   }
03619 
03620   (void) KRun::runURL( url, QString::fromLatin1("text/plain"), isTempFile );
03621 }
03622 
03623 void KHTMLPart::slotViewPageInfo()
03624 {
03625   KHTMLInfoDlg *dlg = new KHTMLInfoDlg(NULL, "KHTML Page Info Dialog", false, WDestructiveClose);
03626   dlg->_close->setGuiItem(KStdGuiItem::close());
03627 
03628   if (d->m_doc)
03629      dlg->_title->setText(d->m_doc->title().string());
03630 
03631   // If it's a frame, set the caption to "Frame Information"
03632   if ( parentPart() && d->m_doc && d->m_doc->isHTMLDocument() ) {
03633      dlg->setCaption(i18n("Frame Information"));
03634   }
03635 
03636   QString editStr = QString::null;
03637 
03638   if (!d->m_pageServices.isEmpty())
03639     editStr = i18n("   <a href=\"%1\">[Properties]</a>").arg(d->m_pageServices);
03640 
03641   QString squeezedURL = KStringHandler::csqueeze( url().prettyURL(), 80 );
03642   dlg->_url->setText("<a href=\"" + url().url() + "\">" + squeezedURL + "</a>" + editStr);
03643   if (lastModified().isEmpty())
03644   {
03645     dlg->_lastModified->hide();
03646     dlg->_lmLabel->hide();
03647   }
03648   else
03649     dlg->_lastModified->setText(lastModified());
03650 
03651   /* populate the list view now */
03652   const QStringList headers = QStringList::split("\n", d->m_httpHeaders);
03653 
03654   QStringList::ConstIterator it = headers.begin();
03655   const QStringList::ConstIterator itEnd = headers.end();
03656 
03657   for (; it != itEnd; ++it) {
03658     const QStringList header = QStringList::split(QRegExp(":[ ]+"), *it);
03659     if (header.count() != 2)
03660        continue;
03661     new QListViewItem(dlg->_headers, header[0], header[1]);
03662   }
03663 
03664   dlg->show();
03665   /* put no code here */
03666 }
03667 
03668 
03669 void KHTMLPart::slotViewFrameSource()
03670 {
03671   KParts::ReadOnlyPart *frame = currentFrame();
03672   if ( !frame )
03673     return;
03674 
03675   KURL url = frame->url();
03676   bool isTempFile = false;
03677   if (!(url.isLocalFile()) && frame->inherits("KHTMLPart"))
03678   {
03679        long cacheId = static_cast<KHTMLPart *>(frame)->d->m_cacheId;
03680 
03681        if (KHTMLPageCache::self()->isComplete(cacheId))
03682        {
03683            KTempFile sourceFile(QString::null, QString::fromLatin1(".html"));
03684            if (sourceFile.status() == 0)
03685            {
03686                KHTMLPageCache::self()->saveData(cacheId, sourceFile.dataStream());
03687                url = KURL();
03688                url.setPath(sourceFile.name());
03689                isTempFile = true;
03690            }
03691      }
03692   }
03693 
03694   (void) KRun::runURL( url, QString::fromLatin1("text/plain"), isTempFile );
03695 }
03696 
03697 KURL KHTMLPart::backgroundURL() const
03698 {
03699   // ### what about XML documents? get from CSS?
03700   if (!d->m_doc || !d->m_doc->isHTMLDocument())
03701     return KURL();
03702 
03703   QString relURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
03704 
03705   return KURL( m_url, relURL );
03706 }
03707 
03708 void KHTMLPart::slotSaveBackground()
03709 {
03710   KIO::MetaData metaData;
03711   metaData["referrer"] = d->m_referrer;
03712   KHTMLPopupGUIClient::saveURL( d->m_view, i18n("Save Background Image As"), backgroundURL(), metaData );
03713 }
03714 
03715 void KHTMLPart::slotSaveDocument()
03716 {
03717   KURL srcURL( m_url );
03718 
03719   if ( srcURL.fileName(false).isEmpty() )
03720     srcURL.setFileName( "index.html" );
03721 
03722   KIO::MetaData metaData;
03723   // Referre unknown?
03724   KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), srcURL, metaData, "text/html", d->m_cacheId );
03725 }
03726 
03727 void KHTMLPart::slotSecurity()
03728 {
03729 //   kdDebug( 6050 ) << "Meta Data:" << endl
03730 //                   << d->m_ssl_peer_cert_subject
03731 //                   << endl
03732 //                   << d->m_ssl_peer_cert_issuer
03733 //                   << endl
03734 //                   << d->m_ssl_cipher
03735 //                   << endl
03736 //                   << d->m_ssl_cipher_desc
03737 //                   << endl
03738 //                   << d->m_ssl_cipher_version
03739 //                   << endl
03740 //                   << d->m_ssl_good_from
03741 //                   << endl
03742 //                   << d->m_ssl_good_until
03743 //                   << endl
03744 //                   << d->m_ssl_cert_state
03745 //                   << endl;
03746 
03747   KSSLInfoDlg *kid = new KSSLInfoDlg(d->m_ssl_in_use, widget(), "kssl_info_dlg", true );
03748 
03749   if (d->m_bSecurityInQuestion)
03750       kid->setSecurityInQuestion(true);
03751 
03752   if (d->m_ssl_in_use) {
03753     KSSLCertificate *x = KSSLCertificate::fromString(d->m_ssl_peer_certificate.local8Bit());
03754     if (x) {
03755        // Set the chain back onto the certificate
03756        const QStringList cl = QStringList::split(QString("\n"), d->m_ssl_peer_chain);
03757        QPtrList<KSSLCertificate> ncl;
03758 
03759        ncl.setAutoDelete(true);
03760        QStringList::ConstIterator it = cl.begin();
03761        const QStringList::ConstIterator itEnd = cl.end();
03762        for (; it != itEnd; ++it) {
03763           KSSLCertificate* const y = KSSLCertificate::fromString((*it).local8Bit());
03764           if (y) ncl.append(y);
03765        }
03766 
03767        if (ncl.count() > 0)
03768           x->chain().setChain(ncl);
03769 
03770        kid->setup(x,
03771                   d->m_ssl_peer_ip,
03772                   m_url.url(),
03773                   d->m_ssl_cipher,
03774                   d->m_ssl_cipher_desc,
03775                   d->m_ssl_cipher_version,
03776                   d->m_ssl_cipher_used_bits.toInt(),
03777                   d->m_ssl_cipher_bits.toInt(),
03778                   (KSSLCertificate::KSSLValidation) d->m_ssl_cert_state.toInt()
03779                   );
03780         kid->exec();
03781         delete x;
03782      } else kid->exec();
03783   } else kid->exec();
03784 }
03785 
03786 void KHTMLPart::slotSaveFrame()
03787 {
03788     if ( !d->m_activeFrame )
03789         return; // should never be the case, but one never knows :-)
03790 
03791     KURL srcURL( static_cast<KParts::ReadOnlyPart *>( d->m_activeFrame )->url() );
03792 
03793     if ( srcURL.fileName(false).isEmpty() )
03794         srcURL.setFileName( "index.html" );
03795 
03796     KIO::MetaData metaData;
03797     // Referrer unknown?
03798     KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), srcURL, metaData, "text/html" );
03799 }
03800 
03801 void KHTMLPart::slotSetEncoding()
03802 {
03803   d->m_automaticDetection->setItemChecked( int( d->m_autoDetectLanguage ), false );
03804   d->m_paSetEncoding->popupMenu()->setItemChecked( 0, false );
03805   d->m_paSetEncoding->popupMenu()->setItemChecked( d->m_paSetEncoding->popupMenu()->idAt( 2 ), true );
03806 
03807   QString enc = KGlobal::charsets()->encodingForName( d->m_manualDetection->currentText() );
03808   setEncoding( enc, true );
03809 }
03810 
03811 void KHTMLPart::slotUseStylesheet()
03812 {
03813   if (d->m_doc)
03814   {
03815     bool autoselect = (d->m_paUseStylesheet->currentItem() == 0);
03816     d->m_sheetUsed = autoselect ? QString() : d->m_paUseStylesheet->currentText();
03817     d->m_doc->updateStyleSelector();
03818   }
03819 }
03820 
03821 void KHTMLPart::updateActions()
03822 {
03823   bool frames = false;
03824 
03825   QValueList<khtml::ChildFrame*>::ConstIterator it = d->m_frames.begin();
03826   const QValueList<khtml::ChildFrame*>::ConstIterator end = d->m_frames.end();
03827   for (; it != end; ++it )
03828       if ( (*it)->m_type == khtml::ChildFrame::Frame )
03829       {
03830           frames = true;
03831           break;
03832       }
03833 
03834   d->m_paViewFrame->setEnabled( frames );
03835   d->m_paSaveFrame->setEnabled( frames );
03836 
03837   if ( frames )
03838     d->m_paFind->setText( i18n( "&Find in Frame..." ) );
03839   else
03840     d->m_paFind->setText( i18n( "&Find..." ) );
03841 
03842   KParts::Part *frame = 0;
03843 
03844   if ( frames )
03845     frame = currentFrame();
03846 
03847   bool enableFindAndSelectAll = true;
03848 
03849   if ( frame )
03850     enableFindAndSelectAll = frame->inherits( "KHTMLPart" );
03851 
03852   d->m_paFind->setEnabled( enableFindAndSelectAll );
03853   d->m_paSelectAll->setEnabled( enableFindAndSelectAll );
03854 
03855   bool enablePrintFrame = false;
03856 
03857   if ( frame )
03858   {
03859     QObject *ext = KParts::BrowserExtension::childObject( frame );
03860     if ( ext )
03861       enablePrintFrame = ext->metaObject()->slotNames().contains( "print()" );
03862   }
03863 
03864   d->m_paPrintFrame->setEnabled( enablePrintFrame );
03865 
03866   QString bgURL;
03867 
03868   // ### frames
03869   if ( d->m_doc && d->m_doc->isHTMLDocument() && static_cast<HTMLDocumentImpl*>(d->m_doc)->body() && !d->m_bClearing )
03870     bgURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
03871 
03872   d->m_paSaveBackground->setEnabled( !bgURL.isEmpty() );
03873 
03874   if ( d->m_paDebugScript )
03875     d->m_paDebugScript->setEnabled( d->m_frame ? d->m_frame->m_jscript : 0L );
03876 }
03877 
03878 KParts::LiveConnectExtension *KHTMLPart::liveConnectExtension( const khtml::RenderPart *frame) const {
03879     const ConstFrameIt end = d->m_objects.end();
03880     for(ConstFrameIt it = d->m_objects.begin(); it != end; ++it )
03881         if ((*it)->m_frame == frame)
03882             return (*it)->m_liveconnect;
03883     return 0L;
03884 }
03885 
03886 bool KHTMLPart::requestFrame( khtml::RenderPart *frame, const QString &url, const QString &frameName,
03887                               const QStringList &params, bool isIFrame )
03888 {
03889   //kdDebug( 6050 ) << this << " requestFrame( ..., " << url << ", " << frameName << " )" << endl;
03890   FrameIt it = d->m_frames.find( frameName );
03891   if ( it == d->m_frames.end() )
03892   {
03893     khtml::ChildFrame * child = new khtml::ChildFrame;
03894     //kdDebug( 6050 ) << "inserting new frame into frame map " << frameName << endl;
03895     child->m_name = frameName;
03896     it = d->m_frames.append( child );
03897   }
03898 
03899   (*it)->m_type = isIFrame ? khtml::ChildFrame::IFrame : khtml::ChildFrame::Frame;
03900   (*it)->m_frame = frame;
03901   (*it)->m_params = params;
03902 
03903   // Support for <frame src="javascript:string">
03904   if ( url.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
03905   {
03906       QVariant res = executeScript( DOM::Node(frame->element()), KURL::decode_string( url.right( url.length() - 11) ) );
03907       KURL myurl;
03908       myurl.setProtocol("javascript");
03909       if ( res.type() == QVariant::String )
03910     myurl.setPath(res.asString());
03911       return processObjectRequest(*it, myurl, QString("text/html") );
03912   }
03913   KURL u = url.isEmpty() ? KURL() : completeURL( url );
03914   return requestObject( *it, u );
03915 }
03916 
03917 QString KHTMLPart::requestFrameName()
03918 {
03919    return QString::fromLatin1("<!--frame %1-->").arg(d->m_frameNameId++);
03920 }
03921 
03922 bool KHTMLPart::requestObject( khtml::RenderPart *frame, const QString &url, const QString &serviceType,
03923                                const QStringList &params )
03924 {
03925   //kdDebug( 6005 ) << "KHTMLPart::requestObject " << this << " frame=" << frame << endl;
03926   khtml::ChildFrame *child = new khtml::ChildFrame;
03927   FrameIt it = d->m_objects.append( child );
03928   (*it)->m_frame = frame;
03929   (*it)->m_type = khtml::ChildFrame::Object;
03930   (*it)->m_params = params;
03931 
03932   KParts::URLArgs args;
03933   args.serviceType = serviceType;
03934   if (!requestObject( *it, completeURL( url ), args ) && !(*it)->m_run) {
03935       (*it)->m_bCompleted = true;
03936       return false;
03937   }
03938   return true;
03939 }
03940 
03941 bool KHTMLPart::requestObject( khtml::ChildFrame *child, const KURL &url, const KParts::URLArgs &_args )
03942 {
03943   if (!checkLinkSecurity(url))
03944   {
03945     kdDebug(6005) << this << " KHTMLPart::requestObject checkLinkSecurity refused" << endl;
03946     return false;
03947   }
03948   if ( child->m_bPreloaded )
03949   {
03950     kdDebug(6005) << "KHTMLPart::requestObject preload" << endl;
03951     if ( child->m_frame && child->m_part )
03952       child->m_frame->setWidget( child->m_part->widget() );
03953 
03954     child->m_bPreloaded = false;
03955     return true;
03956   }
03957 
03958   //kdDebug(6005) << "KHTMLPart::requestObject child=" << child << " child->m_part=" << child->m_part << endl;
03959 
03960   KParts::URLArgs args( _args );
03961 
03962   if ( child->m_run )
03963     child->m_run->abort();
03964 
03965   if ( child->m_part && !args.reload && urlcmp( child->m_part->url().url(), url.url(), true, true ) )
03966     args.serviceType = child->m_serviceType;
03967 
03968   child->m_args = args;
03969   child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload);
03970   child->m_serviceName = QString::null;
03971   if (!d->m_referrer.isEmpty() && !child->m_args.metaData().contains( "referrer" ))
03972     child->m_args.metaData()["referrer"] = d->m_referrer;
03973 
03974   child->m_args.metaData().insert("PropagateHttpHeader", "true");
03975   child->m_args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
03976   child->m_args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
03977   child->m_args.metaData().insert("main_frame_request",
03978                                   parentPart() == 0 ? "TRUE":"FALSE");
03979   child->m_args.metaData().insert("ssl_was_in_use",
03980                                   d->m_ssl_in_use ? "TRUE":"FALSE");
03981   child->m_args.metaData().insert("ssl_activate_warnings", "TRUE");
03982   child->m_args.metaData().insert("cross-domain", toplevelURL().url());
03983 
03984   // We want a KHTMLPart if the HTML says <frame src=""> or <frame src="about:blank">
03985   if ((url.isEmpty() || url.url() == "about:blank") && args.serviceType.isEmpty())
03986     args.serviceType = QString::fromLatin1( "text/html" );
03987 
03988   if ( args.serviceType.isEmpty() ) {
03989     kdDebug(6050) << "Running new KHTMLRun for " << this << " and child=" << child << endl;
03990     child->m_run = new KHTMLRun( this, child, url, child->m_args, true );
03991     d->m_bComplete = false; // ensures we stop it in checkCompleted...
03992     return false;
03993   } else {
03994     return processObjectRequest( child, url, args.serviceType );
03995   }
03996 }
03997 
03998 bool KHTMLPart::processObjectRequest( khtml::ChildFrame *child, const KURL &_url, const QString &mimetype )
03999 {
04000   //kdDebug( 6050 ) << "KHTMLPart::processObjectRequest trying to create part for " << mimetype << endl;
04001 
04002   // IMPORTANT: create a copy of the url here, because it is just a reference, which was likely to be given
04003   // by an emitting frame part (emit openURLRequest( blahurl, ... ) . A few lines below we delete the part
04004   // though -> the reference becomes invalid -> crash is likely
04005   KURL url( _url );
04006 
04007   // khtmlrun called us this way to indicate a loading error
04008   if ( d->m_onlyLocalReferences || ( url.isEmpty() && mimetype.isEmpty() ) )
04009   {
04010       child->m_bCompleted = true;
04011       checkCompleted();
04012       return true;
04013   }
04014 
04015   if (child->m_bNotify)
04016   {
04017       child->m_bNotify = false;
04018       if ( !child->m_args.lockHistory() )
04019           emit d->m_extension->openURLNotify();
04020   }
04021 
04022   if ( child->m_serviceType != mimetype || !child->m_part )
04023   {
04024     // Before attempting to load a part, check if the user wants that.
04025     // Many don't like getting ZIP files embedded.
04026     // However we don't want to ask for flash and other plugin things..
04027     if ( child->m_type != khtml::ChildFrame::Object )
04028     {
04029       QString suggestedFilename;
04030       if ( child->m_run )
04031         suggestedFilename = child->m_run->suggestedFilename();
04032 
04033       KParts::BrowserRun::AskSaveResult res = KParts::BrowserRun::askEmbedOrSave(
04034         url, mimetype, suggestedFilename  );
04035       switch( res ) {
04036       case KParts::BrowserRun::Save:
04037         KHTMLPopupGUIClient::saveURL( widget(), i18n( "Save As" ), url, child->m_args.metaData(), QString::null, 0, suggestedFilename);
04038         // fall-through
04039       case KParts::BrowserRun::Cancel:
04040         child->m_bCompleted = true;
04041         checkCompleted();
04042         return true; // done
04043       default: // Open
04044         break;
04045       }
04046     }
04047 
04048     QStringList dummy; // the list of servicetypes handled by the part is now unused.
04049     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 );
04050 
04051     if ( !part )
04052     {
04053         if ( child->m_frame )
04054           if (child->m_frame->partLoadingErrorNotify( child, url, mimetype ))
04055             return true; // we succeeded after all (a fallback was used)
04056 
04057         checkEmitLoadEvent();
04058         return false;
04059     }
04060 
04061     //CRITICAL STUFF
04062     if ( child->m_part )
04063     {
04064       if (!::qt_cast<KHTMLPart*>(child->m_part) && child->m_jscript)
04065           child->m_jscript->clear();
04066       partManager()->removePart( (KParts::ReadOnlyPart *)child->m_part );
04067       delete (KParts::ReadOnlyPart *)child->m_part;
04068       if (child->m_liveconnect) {
04069         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 &)));
04070         child->m_liveconnect = 0L;
04071       }
04072     }
04073 
04074     child->m_serviceType = mimetype;
04075     if ( child->m_frame )
04076       child->m_frame->setWidget( part->widget() );
04077 
04078     if ( child->m_type != khtml::ChildFrame::Object )
04079       partManager()->addPart( part, false );
04080 //  else
04081 //      kdDebug(6005) << "AH! NO FRAME!!!!!" << endl;
04082 
04083     child->m_part = part;
04084 
04085     if (::qt_cast<KHTMLPart*>(part)) {
04086       static_cast<KHTMLPart*>(part)->d->m_frame = child;
04087     } else if (child->m_frame) {
04088       child->m_liveconnect = KParts::LiveConnectExtension::childObject(part);
04089       if (child->m_liveconnect)
04090         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 &)));
04091     }
04092 
04093     connect( part, SIGNAL( started( KIO::Job *) ),
04094              this, SLOT( slotChildStarted( KIO::Job *) ) );
04095     connect( part, SIGNAL( completed() ),
04096              this, SLOT( slotChildCompleted() ) );
04097     connect( part, SIGNAL( completed(bool) ),
04098              this, SLOT( slotChildCompleted(bool) ) );
04099     connect( part, SIGNAL( setStatusBarText( const QString & ) ),
04100                 this, SIGNAL( setStatusBarText( const QString & ) ) );
04101     if ( part->inherits( "KHTMLPart" ) )
04102     {
04103       connect( this, SIGNAL( completed() ),
04104                part, SLOT( slotParentCompleted() ) );
04105       connect( this, SIGNAL( completed(bool) ),
04106                part, SLOT( slotParentCompleted() ) );
04107       // As soon as the child's document is created, we need to set its domain
04108       // (but we do so only once, so it can't be simply done in the child)
04109       connect( part, SIGNAL( docCreated() ),
04110                this, SLOT( slotChildDocCreated() ) );
04111     }
04112 
04113     child->m_extension = KParts::BrowserExtension::childObject( part );
04114 
04115     if ( child->m_extension )
04116     {
04117       connect( child->m_extension, SIGNAL( openURLNotify() ),
04118                d->m_extension, SIGNAL( openURLNotify() ) );
04119 
04120       connect( child->m_extension, SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ),
04121                this, SLOT( slotChildURLRequest( const KURL &, const KParts::URLArgs & ) ) );
04122 
04123       connect( child->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ),
04124                d->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ) );
04125       connect( child->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs &, const KParts::WindowArgs &, KParts::ReadOnlyPart *& ) ),
04126                d->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & , const KParts::WindowArgs &, KParts::ReadOnlyPart *&) ) );
04127 
04128       connect( child->m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ),
04129                d->m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ) );
04130       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ),
04131                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ) );
04132       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ),
04133                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ) );
04134       connect( child->m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ),
04135                d->m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ) );
04136       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ),
04137                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ) );
04138       connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ),
04139                d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ) );
04140 
04141       connect( child->m_extension, SIGNAL( infoMessage( const QString & ) ),
04142                d->m_extension, SIGNAL( infoMessage( const QString & ) ) );
04143 
04144       connect( child->m_extension, SIGNAL( requestFocus( KParts::ReadOnlyPart * ) ),
04145                this, SLOT( slotRequestFocus( KParts::ReadOnlyPart * ) ) );
04146 
04147       child->m_extension->setBrowserInterface( d->m_extension->browserInterface() );
04148     }
04149   }
04150   else if ( child->m_frame && child->m_part &&
04151             child->m_frame->widget() != child->m_part->widget() )
04152     child->m_frame->setWidget( child->m_part->widget() );
04153 
04154   checkEmitLoadEvent();
04155   // Some JS code in the load event may have destroyed the part
04156   // In that case, abort
04157   if ( !child->m_part )
04158     return false;
04159 
04160   if ( child->m_bPreloaded )
04161   {
04162     if ( child->m_frame && child->m_part )
04163       child->m_frame->setWidget( child->m_part->widget() );
04164 
04165     child->m_bPreloaded = false;
04166     return true;
04167   }
04168 
04169   child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload);
04170 
04171   // make sure the part has a way to find out about the mimetype.
04172   // we actually set it in child->m_args in requestObject already,
04173   // but it's useless if we had to use a KHTMLRun instance, as the
04174   // point the run object is to find out exactly the mimetype.
04175   child->m_args.serviceType = mimetype;
04176 
04177   // if not a frame set child as completed
04178   child->m_bCompleted = child->m_type == khtml::ChildFrame::Object;
04179 
04180   if ( child->m_extension )
04181     child->m_extension->setURLArgs( child->m_args );
04182 
04183   if(url.protocol() == "javascript" || url.url() == "about:blank") {
04184       if (!child->m_part->inherits("KHTMLPart"))
04185           return false;
04186 
04187       KHTMLPart* p = static_cast<KHTMLPart*>(static_cast<KParts::ReadOnlyPart *>(child->m_part));
04188 
04189       p->begin();
04190       if (d->m_doc && p->d->m_doc)
04191         p->d->m_doc->setBaseURL(d->m_doc->baseURL());
04192       if (!url.url().startsWith("about:")) {
04193         p->write(url.path());
04194       } else {
04195     p->m_url = url;
04196         // we need a body element. testcase: <iframe id="a"></iframe><script>alert(a.document.body);</script>
04197         p->write("<HTML><TITLE></TITLE><BODY></BODY></HTML>");
04198       }
04199       p->end();
04200       return true;
04201   }
04202   else if ( !url.isEmpty() )
04203   {
04204       //kdDebug( 6050 ) << "opening " << url.url() << " in frame " << child->m_part << endl;
04205       bool b = child->m_part->openURL( url );
04206       if (child->m_bCompleted)
04207           checkCompleted();
04208       return b;
04209   }
04210   else
04211   {
04212       child->m_bCompleted = true;
04213       checkCompleted();
04214       return true;
04215   }
04216 }
04217 
04218 KParts::ReadOnlyPart *KHTMLPart::createPart( QWidget *parentWidget, const char *widgetName,
04219                                              QObject *parent, const char *name, const QString &mimetype,
04220                                              QString &serviceName, QStringList &serviceTypes,
04221                                              const QStringList &params )
04222 {
04223   QString constr;
04224   if ( !serviceName.isEmpty() )
04225     constr.append( QString::fromLatin1( "Name == '%1'" ).arg( serviceName ) );
04226 
04227   KTrader::OfferList offers = KTrader::self()->query( mimetype, "KParts/ReadOnlyPart", constr, QString::null );
04228 
04229   if ( offers.isEmpty() ) {
04230     int pos = mimetype.find( "-plugin" );
04231     if (pos < 0)
04232         return 0L;
04233     QString stripped_mime = mimetype.left( pos );
04234     offers = KTrader::self()->query( stripped_mime, "KParts/ReadOnlyPart", constr, QString::null );
04235     if ( offers.isEmpty() )
04236         return 0L;
04237   }
04238 
04239   KTrader::OfferList::ConstIterator it = offers.begin();
04240   const KTrader::OfferList::ConstIterator itEnd = offers.end();
04241   for ( ; it != itEnd; ++it )
04242   {
04243     KService::Ptr service = (*it);
04244 
04245     KLibFactory* const factory = KLibLoader::self()->factory( QFile::encodeName(service->library()) );
04246     if ( factory ) {
04247       KParts::ReadOnlyPart *res = 0L;
04248 
04249       const char *className = "KParts::ReadOnlyPart";
04250       if ( service->serviceTypes().contains( "Browser/View" ) )
04251         className = "Browser/View";
04252 
04253       if ( factory->inherits( "KParts::Factory" ) )
04254         res = static_cast<KParts::ReadOnlyPart *>(static_cast<KParts::Factory *>( factory )->createPart( parentWidget, widgetName, parent, name, className, params ));
04255       else
04256         res = static_cast<KParts::ReadOnlyPart *>(factory->create( parentWidget, widgetName, className ));
04257 
04258       if ( res ) {
04259         serviceTypes = service->serviceTypes();
04260         serviceName = service->name();
04261         return res;
04262       }
04263     } else {
04264       // TODO KMessageBox::error and i18n, like in KonqFactory::createView?
04265       kdWarning() << QString("There was an error loading the module %1.\nThe diagnostics is:\n%2")
04266                       .arg(service->name()).arg(KLibLoader::self()->lastErrorMessage()) << endl;
04267     }
04268   }
04269   return 0;
04270 }
04271 
04272 KParts::PartManager *KHTMLPart::partManager()
04273 {
04274   if ( !d->m_manager )
04275   {
04276     d->m_manager = new KParts::PartManager( d->m_view->topLevelWidget(), this, "khtml part manager" );
04277     d->m_manager->setAllowNestedParts( true );
04278     connect( d->m_manager, SIGNAL( activePartChanged( KParts::Part * ) ),
04279              this, SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
04280     connect( d->m_manager, SIGNAL( partRemoved( KParts::Part * ) ),
04281              this, SLOT( slotPartRemoved( KParts::Part * ) ) );
04282   }
04283 
04284   return d->m_manager;
04285 }
04286 
04287 void KHTMLPart::submitFormAgain()
04288 {
04289   if( d->m_doc && !d->m_doc->parsing() && d->m_submitForm)
04290     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 );
04291 
04292   delete d->m_submitForm;
04293   d->m_submitForm = 0;
04294   disconnect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
04295 }
04296 
04297 void KHTMLPart::submitFormProxy( const char *action, const QString &url, const QByteArray &formData, const QString &_target, const QString& contentType, const QString& boundary )
04298 {
04299   submitForm(action, url, formData, _target, contentType, boundary);
04300 }
04301 
04302 void KHTMLPart::submitForm( const char *action, const QString &url, const QByteArray &formData, const QString &_target, const QString& contentType, const QString& boundary )
04303 {
04304   kdDebug(6000) << this << ": KHTMLPart::submitForm target=" << _target << " url=" << url << endl;
04305   if (d->m_formNotification == KHTMLPart::Only) {
04306     emit formSubmitNotification(action, url, formData, _target, contentType, boundary);
04307     return;
04308   } else if (d->m_formNotification == KHTMLPart::Before) {
04309     emit formSubmitNotification(action, url, formData, _target, contentType, boundary);
04310   }
04311 
04312   KURL u = completeURL( url );
04313 
04314   if ( !u.isValid() )
04315   {
04316     // ### ERROR HANDLING!
04317     return;
04318   }
04319 
04320   // Form security checks
04321   //
04322   /*
04323    * If these form security checks are still in this place in a month or two
04324    * I'm going to simply delete them.
04325    */
04326 
04327   /* This is separate for a reason.  It has to be _before_ all script, etc,
04328    * AND I don't want to break anything that uses checkLinkSecurity() in
04329    * other places.
04330    */
04331 
04332   if (!d->m_submitForm) {
04333     if (u.protocol() != "https" && u.protocol() != "mailto") {
04334       if (d->m_ssl_in_use) {    // Going from SSL -> nonSSL
04335         int rc = KMessageBox::warningContinueCancel(NULL, i18n("Warning:  This is a secure form but it is attempting to send your data back unencrypted."
04336                                                                "\nA third party may be able to intercept and view this information."
04337                                                                "\nAre you sure you wish to continue?"),
04338                                                     i18n("Network Transmission"),KGuiItem(i18n("&Send Unencrypted")));
04339         if (rc == KMessageBox::Cancel)
04340           return;
04341       } else {                  // Going from nonSSL -> nonSSL
04342         KSSLSettings kss(true);
04343         if (kss.warnOnUnencrypted()) {
04344           int rc = KMessageBox::warningContinueCancel(NULL,
04345                                                       i18n("Warning: Your data is about to be transmitted across the network unencrypted."
04346                                                            "\nAre you sure you wish to continue?"),
04347                                                       i18n("Network Transmission"),
04348                                                       KGuiItem(i18n("&Send Unencrypted")),
04349                                                       "WarnOnUnencryptedForm");
04350           // Move this setting into KSSL instead
04351           KConfig *config = kapp->config();
04352           QString grpNotifMsgs = QString::fromLatin1("Notification Messages");
04353           KConfigGroupSaver saver( config, grpNotifMsgs );
04354 
04355           if (!config->readBoolEntry("WarnOnUnencryptedForm", true)) {
04356             config->deleteEntry("WarnOnUnencryptedForm");
04357             config->sync();
04358             kss.setWarnOnUnencrypted(false);
04359             kss.save();
04360           }
04361           if (rc == KMessageBox::Cancel)
04362             return;
04363         }
04364       }
04365     }
04366 
04367     if (u.protocol() == "mailto") {
04368       int rc = KMessageBox::warningContinueCancel(NULL,
04369                                                   i18n("This site is attempting to submit form data via email.\n"
04370                                                        "Do you want to continue?"),
04371                                                   i18n("Network Transmission"),
04372                                                   KGuiItem(i18n("&Send Email")),
04373                                                   "WarnTriedEmailSubmit");
04374 
04375       if (rc == KMessageBox::Cancel) {
04376         return;
04377       }
04378     }
04379   }
04380 
04381   // End form security checks
04382   //
04383 
04384   QString urlstring = u.url();
04385 
04386   if ( urlstring.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
04387     urlstring = KURL::decode_string(urlstring);
04388     crossFrameExecuteScript( _target, urlstring.right( urlstring.length() - 11) );
04389     return;
04390   }
04391 
04392   if (!checkLinkSecurity(u,
04393              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?" ),
04394              i18n( "Submit" )))
04395     return;
04396 
04397   KParts::URLArgs args;
04398 
04399   if (!d->m_referrer.isEmpty())
04400      args.metaData()["referrer"] = d->m_referrer;
04401 
04402   args.metaData().insert("PropagateHttpHeader", "true");
04403   args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
04404   args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
04405   args.metaData().insert("main_frame_request",
04406                          parentPart() == 0 ? "TRUE":"FALSE");
04407   args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
04408   args.metaData().insert("ssl_activate_warnings", "TRUE");
04409 //WABA: When we post a form we should treat it as the main url
04410 //the request should never be considered cross-domain
04411 //args.metaData().insert("cross-domain", toplevelURL().url());
04412   args.frameName = _target.isEmpty() ? d->m_doc->baseTarget() : _target ;
04413 
04414   // Handle mailto: forms
04415   if (u.protocol() == "mailto") {
04416       // 1)  Check for attach= and strip it
04417       QString q = u.query().mid(1);
04418       QStringList nvps = QStringList::split("&", q);
04419       bool triedToAttach = false;
04420 
04421       QStringList::Iterator nvp = nvps.begin();
04422       const QStringList::Iterator nvpEnd = nvps.end();
04423 
04424 // cannot be a for loop as if something is removed we don't want to do ++nvp, as
04425 // remove returns an iterator pointing to the next item
04426 
04427       while (nvp != nvpEnd) {
04428          const QStringList pair = QStringList::split("=", *nvp);
04429          if (pair.count() >= 2) {
04430             if (pair.first().lower() == "attach") {
04431                nvp = nvps.remove(nvp);
04432                triedToAttach = true;
04433             } else {
04434                ++nvp;
04435             }
04436          } else {
04437             ++nvp;
04438          }
04439       }
04440 
04441       if (triedToAttach)
04442          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");
04443 
04444       // 2)  Append body=
04445       QString bodyEnc;
04446       if (contentType.lower() == "multipart/form-data") {
04447          // FIXME: is this correct?  I suspect not
04448          bodyEnc = KURL::encode_string(QString::fromLatin1(formData.data(),
04449                                                            formData.size()));
04450       } else if (contentType.lower() == "text/plain") {
04451          // Convention seems to be to decode, and s/&/\n/
04452          QString tmpbody = QString::fromLatin1(formData.data(),
04453                                                formData.size());
04454          tmpbody.replace(QRegExp("[&]"), "\n");
04455          tmpbody.replace(QRegExp("[+]"), " ");
04456          tmpbody = KURL::decode_string(tmpbody);  // Decode the rest of it
04457          bodyEnc = KURL::encode_string(tmpbody);  // Recode for the URL
04458       } else {
04459          bodyEnc = KURL::encode_string(QString::fromLatin1(formData.data(),
04460                                                            formData.size()));
04461       }
04462 
04463       nvps.append(QString("body=%1").arg(bodyEnc));
04464       q = nvps.join("&");
04465       u.setQuery(q);
04466   }
04467 
04468   if ( strcmp( action, "get" ) == 0 ) {
04469     if (u.protocol() != "mailto")
04470        u.setQuery( QString::fromLatin1( formData.data(), formData.size() ) );
04471     args.setDoPost( false );
04472   }
04473   else {
04474     args.postData = formData;
04475     args.setDoPost( true );
04476 
04477     // construct some user headers if necessary
04478     if (contentType.isNull() || contentType == "application/x-www-form-urlencoded")
04479       args.setContentType( "Content-Type: application/x-www-form-urlencoded" );
04480     else // contentType must be "multipart/form-data"
04481       args.setContentType( "Content-Type: " + contentType + "; boundary=" + boundary );
04482   }
04483 
04484   if ( d->m_doc->parsing() || d->m_runningScripts > 0 ) {
04485     if( d->m_submitForm ) {
04486       kdDebug(6000) << "KHTMLPart::submitForm ABORTING!" << endl;
04487       return;
04488     }
04489     d->m_submitForm = new KHTMLPartPrivate::SubmitForm;
04490     d->m_submitForm->submitAction = action;
04491     d->m_submitForm->submitUrl = url;
04492     d->m_submitForm->submitFormData = formData;
04493     d->m_submitForm->target = _target;
04494     d->m_submitForm->submitContentType = contentType;
04495     d->m_submitForm->submitBoundary = boundary;
04496     connect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
04497   }
04498   else
04499   {
04500     emit d->m_extension->openURLRequest( u, args );
04501   }
04502 }
04503 
04504 void KHTMLPart::popupMenu( const QString &linkUrl )
04505 {
04506   KURL popupURL;
04507   KURL linkKURL;
04508   QString referrer;
04509   KParts::BrowserExtension::PopupFlags itemflags=KParts::BrowserExtension::ShowBookmark | KParts::BrowserExtension::ShowReload;
04510 
04511   if ( linkUrl.isEmpty() ) { // click on background
04512     KHTMLPart* khtmlPart = this;
04513     while ( khtmlPart->parentPart() )
04514     {
04515       khtmlPart=khtmlPart->parentPart();
04516     }
04517     popupURL = khtmlPart->url();
04518     referrer = khtmlPart->pageReferrer();
04519     if (hasSelection())
04520       itemflags = KParts::BrowserExtension::ShowTextSelectionItems;
04521     else
04522       itemflags |= KParts::BrowserExtension::ShowNavigationItems;
04523   } else {               // click on link
04524     popupURL = completeURL( linkUrl );
04525     linkKURL = popupURL;
04526     referrer = this->referrer();
04527   }
04528 
04529   // Danger, Will Robinson. The Popup might stay around for a much
04530   // longer time than KHTMLPart. Deal with it.
04531   KHTMLPopupGUIClient* client = new KHTMLPopupGUIClient( this, d->m_popupMenuXML, linkKURL );
04532   QGuardedPtr<QObject> guard( client );
04533 
04534   KParts::URLArgs args;
04535   args.serviceType = QString::fromLatin1( "text/html" );
04536   args.metaData()["referrer"] = referrer;
04537 
04538   emit d->m_extension->popupMenu( client, QCursor::pos(), popupURL, args, itemflags, S_IFREG /*always a file*/);
04539 
04540   if ( !guard.isNull() ) {
04541      delete client;
04542      emit popupMenu(linkUrl, QCursor::pos());
04543      d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
04544   }
04545 }
04546 
04547 void KHTMLPart::slotParentCompleted()
04548 {
04549   //kdDebug(6050) << this << " slotParentCompleted()" << endl;
04550   if ( !d->m_redirectURL.isEmpty() && !d->m_redirectionTimer.isActive() )
04551   {
04552     //kdDebug(6050) << this << ": starting timer for child redirection -> " << d->m_redirectURL << endl;
04553     d->m_redirectionTimer.start( 1000 * d->m_delayRedirect, true );
04554   }
04555 }
04556 
04557 void KHTMLPart::slotChildStarted( KIO::Job *job )
04558 {
04559   khtml::ChildFrame *child = frame( sender() );
04560 
04561   assert( child );
04562 
04563   child->m_bCompleted = false;
04564 
04565   if ( d->m_bComplete )
04566   {
04567 #if 0
04568     // WABA: Looks like this belongs somewhere else
04569     if ( !parentPart() ) // "toplevel" html document? if yes, then notify the hosting browser about the document (url) changes
04570     {
04571       emit d->m_extension->openURLNotify();
04572     }
04573 #endif
04574     d->m_bComplete = false;
04575     emit started( job );
04576   }
04577 }
04578 
04579 void KHTMLPart::slotChildCompleted()
04580 {
04581   slotChildCompleted( false );
04582 }
04583 
04584 void KHTMLPart::slotChildCompleted( bool pendingAction )
04585 {
04586   khtml::ChildFrame *child = frame( sender() );
04587 
04588   if ( child ) {
04589     kdDebug(6050) << this << " slotChildCompleted child=" << child << " m_frame=" << child->m_frame << endl;
04590     child->m_bCompleted = true;
04591     child->m_bPendingRedirection = pendingAction;
04592     child->m_args = KParts::URLArgs();
04593   }
04594   checkCompleted();
04595 }
04596 
04597 void KHTMLPart::slotChildDocCreated()
04598 {
04599   const KHTMLPart* htmlFrame = static_cast<const KHTMLPart *>(sender());
04600   // Set domain to the frameset's domain
04601   // This must only be done when loading the frameset initially (#22039),
04602   // not when following a link in a frame (#44162).
04603   if ( d->m_doc && d->m_doc->isHTMLDocument() )
04604   {
04605     if ( sender()->inherits("KHTMLPart") )
04606     {
04607       DOMString domain = static_cast<HTMLDocumentImpl*>(d->m_doc)->domain();
04608       if (htmlFrame->d->m_doc && htmlFrame->d->m_doc->isHTMLDocument() )
04609         //kdDebug(6050) << "KHTMLPart::slotChildDocCreated: url: " << htmlFrame->m_url.url() << endl;
04610         static_cast<HTMLDocumentImpl*>(htmlFrame->d->m_doc)->setDomain( domain );
04611     }
04612   }
04613   // So it only happens once
04614   disconnect( htmlFrame, SIGNAL( docCreated() ), this, SLOT( slotChildDocCreated() ) );
04615 }
04616 
04617 void KHTMLPart::slotChildURLRequest( const KURL &url, const KParts::URLArgs &args )
04618 {
04619   khtml::ChildFrame *child = frame( sender()->parent() );
04620   KHTMLPart *callingHtmlPart = const_cast<KHTMLPart *>(dynamic_cast<const KHTMLPart *>(sender()->parent()));
04621 
04622   // TODO: handle child target correctly! currently the script are always executed fur the parent
04623   QString urlStr = url.url();
04624   if ( urlStr.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
04625       QString script = KURL::decode_string( urlStr.right( urlStr.length() - 11 ) );
04626       executeScript( DOM::Node(), script );
04627       return;
04628   }
04629 
04630   QString frameName = args.frameName.lower();
04631   if ( !frameName.isEmpty() ) {
04632     if ( frameName == QString::fromLatin1( "_top" ) )
04633     {
04634       emit d->m_extension->openURLRequest( url, args );
04635       return;
04636     }
04637     else if ( frameName == QString::fromLatin1( "_blank" ) )
04638     {
04639       emit d->m_extension->createNewWindow( url, args );
04640       return;
04641     }
04642     else if ( frameName == QString::fromLatin1( "_parent" ) )
04643     {
04644       KParts::URLArgs newArgs( args );
04645       newArgs.frameName = QString::null;
04646 
04647       emit d->m_extension->openURLRequest( url, newArgs );
04648       return;
04649     }
04650     else if ( frameName != QString::fromLatin1( "_self" ) )
04651     {
04652       khtml::ChildFrame *_frame = recursiveFrameRequest( callingHtmlPart, url, args );
04653 
04654       if ( !_frame )
04655       {
04656         emit d->m_extension->openURLRequest( url, args );
04657         return;
04658       }
04659 
04660       child = _frame;
04661     }
04662   }
04663 
04664   if ( child && child->m_type != khtml::ChildFrame::Object ) {
04665       // Inform someone that we are about to show something else.
04666       child->m_bNotify = true;
04667       requestObject( child, url, args );
04668   }  else if ( frameName== "_self" ) // this is for embedded objects (via <object>) which want to replace the current document
04669   {
04670       KParts::URLArgs newArgs( args );
04671       newArgs.frameName = QString::null;
04672       emit d->m_extension->openURLRequest( url, newArgs );
04673   }
04674 }
04675 
04676 void KHTMLPart::slotRequestFocus( KParts::ReadOnlyPart * )
04677 {
04678   emit d->m_extension->requestFocus(this);
04679 }
04680 
04681 khtml::ChildFrame *KHTMLPart::frame( const QObject *obj )
04682 {
04683     assert( obj->inherits( "KParts::ReadOnlyPart" ) );
04684     const KParts::ReadOnlyPart* const part = static_cast<const KParts::ReadOnlyPart *>( obj );
04685 
04686     FrameIt it = d->m_frames.begin();
04687     const FrameIt end = d->m_frames.end();
04688     for (; it != end; ++it )
04689       if ( (KParts::ReadOnlyPart *)(*it)->m_part == part )
04690         return *it;
04691 
04692     FrameIt oi = d->m_objects.begin();
04693     const FrameIt oiEnd = d->m_objects.end();
04694     for (; oi != oiEnd; ++oi )
04695       if ( (KParts::ReadOnlyPart *)(*oi)->m_part == part )
04696         return *oi;
04697 
04698     return 0L;
04699 }
04700 
04701 //#define DEBUG_FINDFRAME
04702 
04703 bool KHTMLPart::checkFrameAccess(KHTMLPart *callingHtmlPart)
04704 {
04705   if (callingHtmlPart == this)
04706     return true; // trivial
04707 
04708   if (htmlDocument().isNull()) {
04709 #ifdef DEBUG_FINDFRAME
04710     kdDebug(6050) << "KHTMLPart::checkFrameAccess: Empty part " << this << " URL = " << m_url << endl;
04711 #endif
04712     return false; // we are empty?
04713   }
04714 
04715   // now compare the domains
04716   if (callingHtmlPart && !callingHtmlPart->htmlDocument().isNull() &&
04717       !htmlDocument().isNull())  {
04718     DOM::DOMString actDomain = callingHtmlPart->htmlDocument().domain();
04719     DOM::DOMString destDomain = htmlDocument().domain();
04720 
04721 #ifdef DEBUG_FINDFRAME
04722     kdDebug(6050) << "KHTMLPart::checkFrameAccess: actDomain = '" << actDomain.string() << "' destDomain = '" << destDomain.string() << "'" << endl;
04723 #endif
04724 
04725     if (actDomain == destDomain)
04726       return true;
04727   }
04728 #ifdef DEBUG_FINDFRAME
04729   else
04730   {
04731     kdDebug(6050) << "KHTMLPart::checkFrameAccess: Unknown part/domain " << callingHtmlPart << " tries to access part " << this << endl;
04732   }
04733 #endif
04734   return false;
04735 }
04736 
04737 KHTMLPart *
04738 KHTMLPart::findFrameParent( KParts::ReadOnlyPart *callingPart, const QString &f, khtml::ChildFrame **childFrame )
04739 {
04740 #ifdef DEBUG_FINDFRAME
04741   kdDebug(6050) << "KHTMLPart::findFrameParent: this = " << this << " URL = " << m_url << " name = " << name() << " findFrameParent( " << f << " )" << endl;
04742 #endif
04743   // Check access
04744   KHTMLPart* const callingHtmlPart = dynamic_cast<KHTMLPart *>(callingPart);
04745 
04746   if (!checkFrameAccess(callingHtmlPart))
04747      return 0;
04748 
04749   if (!childFrame && !parentPart() && (name() == f))
04750      return this;
04751 
04752   FrameIt it = d->m_frames.find( f );
04753   const FrameIt end = d->m_frames.end();
04754   if ( it != end )
04755   {
04756 #ifdef DEBUG_FINDFRAME
04757      kdDebug(6050) << "KHTMLPart::findFrameParent: FOUND!" << endl;
04758 #endif
04759      if (childFrame)
04760         *childFrame = *it;
04761      return this;
04762   }
04763 
04764   it = d->m_frames.begin();
04765   for (; it != end; ++it )
04766   {
04767     KParts::ReadOnlyPart* const p = (*it)->m_part;
04768     if ( p && p->inherits( "KHTMLPart" ))
04769     {
04770       KHTMLPart* const frameParent = static_cast<KHTMLPart*>(p)->findFrameParent(callingPart, f, childFrame);
04771       if (frameParent)
04772          return frameParent;
04773     }
04774   }
04775   return 0;
04776 }
04777 
04778 
04779 KHTMLPart *KHTMLPart::findFrame( const QString &f )
04780 {
04781   khtml::ChildFrame *childFrame;
04782   KHTMLPart *parentFrame = findFrameParent(this, f, &childFrame);
04783   if (parentFrame)
04784   {
04785      KParts::ReadOnlyPart *p = childFrame->m_part;
04786      if ( p && p->inherits( "KHTMLPart" ))
04787         return static_cast<KHTMLPart *>(p);
04788   }
04789   return 0;
04790 }
04791 
04792 KParts::ReadOnlyPart *KHTMLPart::findFramePart(const QString &f)
04793 {
04794   khtml::ChildFrame *childFrame;
04795   return findFrameParent(this, f, &childFrame) ? static_cast<KParts::ReadOnlyPart *>(childFrame->m_part) : 0L;
04796 }
04797 
04798 KParts::ReadOnlyPart *KHTMLPart::currentFrame() const
04799 {
04800   KParts::ReadOnlyPart* part = (KParts::ReadOnlyPart*)(this);
04801   // Find active part in our frame manager, in case we are a frameset
04802   // and keep doing that (in case of nested framesets).
04803   // Just realized we could also do this recursively, calling part->currentFrame()...
04804   while ( part && part->inherits("KHTMLPart") &&
04805           static_cast<KHTMLPart *>(part)->d->m_frames.count() > 0 ) {
04806     KHTMLPart* frameset = static_cast<KHTMLPart *>(part);
04807     part = static_cast<KParts::ReadOnlyPart *>(frameset->partManager()->activePart());
04808     if ( !part ) return frameset;
04809   }
04810   return part;
04811 }
04812 
04813 bool KHTMLPart::frameExists( const QString &frameName )
04814 {
04815   ConstFrameIt it = d->m_frames.find( frameName );
04816   if ( it == d->m_frames.end() )
04817     return false;
04818 
04819   // WABA: We only return true if the child actually has a frame
04820   // set. Otherwise we might find our preloaded-selve.
04821   // This happens when we restore the frameset.
04822   return (!(*it)->m_frame.isNull());
04823 }
04824 
04825 KJSProxy *KHTMLPart::framejScript(KParts::ReadOnlyPart *framePart)
04826 {
04827   KHTMLPart* const kp = ::qt_cast<KHTMLPart*>(framePart);
04828   if (kp)
04829     return kp->jScript();
04830 
04831   FrameIt it = d->m_frames.begin();
04832   const FrameIt itEnd = d->m_frames.end();
04833 
04834   for (; it != itEnd; ++it)
04835     if (framePart == (*it)->m_part) {
04836       if (!(*it)->m_jscript)
04837         createJScript(*it);
04838       return (*it)->m_jscript;
04839     }
04840   return 0L;
04841 }
04842 
04843 KHTMLPart *KHTMLPart::parentPart()
04844 {
04845   if ( !parent() || !parent()->inherits( "KHTMLPart" ) )
04846     return 0L;
04847 
04848   return (KHTMLPart *)parent();
04849 }
04850 
04851 khtml::ChildFrame *KHTMLPart::recursiveFrameRequest( KHTMLPart *callingHtmlPart, const KURL &url,
04852                                                      const KParts::URLArgs &args, bool callParent )
04853 {
04854 #ifdef DEBUG_FINDFRAME
04855   kdDebug( 6050 ) << "KHTMLPart::recursiveFrameRequest this = " << this << ", frame = " << args.frameName << ", url = " << url << endl;
04856 #endif
04857   khtml::ChildFrame *childFrame;
04858   KHTMLPart *childPart = findFrameParent(callingHtmlPart, args.frameName, &childFrame);
04859   if (childPart)
04860   {
04861      if (childPart == this)
04862         return childFrame;
04863 
04864      childPart->requestObject( childFrame, url, args );
04865      return 0;
04866   }
04867 
04868   if ( parentPart() && callParent )
04869   {
04870      khtml::ChildFrame *res = parentPart()->recursiveFrameRequest( callingHtmlPart, url, args, callParent );
04871 
04872      if ( res )
04873        parentPart()->requestObject( res, url, args );
04874   }
04875 
04876   return 0L;
04877 }
04878 
04879 #ifndef NDEBUG
04880 static int s_saveStateIndentLevel = 0;
04881 #endif
04882 
04883 void KHTMLPart::saveState( QDataStream &stream )
04884 {
04885 #ifndef NDEBUG
04886   QString indent = QString().leftJustify( s_saveStateIndentLevel * 4, ' ' );
04887   const int indentLevel = s_saveStateIndentLevel++;
04888   kdDebug( 6050 ) << indent << "saveState this=" << this << " '" << name() << "' saving URL " << m_url.url() << endl;
04889 #endif
04890 
04891   stream << m_url << (Q_INT32)d->m_view->contentsX() << (Q_INT32)d->m_view->contentsY()
04892          << (Q_INT32) d->m_view->contentsWidth() << (Q_INT32) d->m_view->contentsHeight() << (Q_INT32) d->m_view->marginWidth() << (Q_INT32) d->m_view->marginHeight();
04893 
04894   // save link cursor position
04895   int focusNodeNumber;
04896   if (!d->m_focusNodeRestored)
04897       focusNodeNumber = d->m_focusNodeNumber;
04898   else if (d->m_doc && d->m_doc->focusNode())
04899       focusNodeNumber = d->m_doc->nodeAbsIndex(d->m_doc->focusNode());
04900   else
04901       focusNodeNumber = -1;
04902   stream << focusNodeNumber;
04903 
04904   // Save the doc's cache id.
04905   stream << d->m_cacheId;
04906 
04907   // Save the state of the document (Most notably the state of any forms)
04908   QStringList docState;
04909   if (d->m_doc)
04910   {
04911      docState = d->m_doc->docState();
04912   }
04913   stream << d->m_encoding << d->m_sheetUsed << docState;
04914 
04915   stream << d->m_zoomFactor;
04916 
04917   stream << d->m_httpHeaders;
04918   stream << d->m_pageServices;
04919   stream << d->m_pageReferrer;
04920 
04921   // Save ssl data
04922   stream << d->m_ssl_in_use
04923          << d->m_ssl_peer_certificate
04924          << d->m_ssl_peer_chain
04925          << d->m_ssl_peer_ip
04926          << d->m_ssl_cipher
04927          << d->m_ssl_cipher_desc
04928          << d->m_ssl_cipher_version
04929          << d->m_ssl_cipher_used_bits
04930          << d->m_ssl_cipher_bits
04931          << d->m_ssl_cert_state
04932          << d->m_ssl_parent_ip
04933          << d->m_ssl_parent_cert;
04934 
04935 
04936   QStringList frameNameLst, frameServiceTypeLst, frameServiceNameLst;
04937   KURL::List frameURLLst;
04938   QValueList<QByteArray> frameStateBufferLst;
04939 
04940   ConstFrameIt it = d->m_frames.begin();
04941   const ConstFrameIt end = d->m_frames.end();
04942   for (; it != end; ++it )
04943   {
04944     if ( !(*it)->m_part )
04945        continue;
04946 
04947     frameNameLst << (*it)->m_name;
04948     frameServiceTypeLst << (*it)->m_serviceType;
04949     frameServiceNameLst << (*it)->m_serviceName;
04950     frameURLLst << (*it)->m_part->url();
04951 
04952     QByteArray state;
04953     QDataStream frameStream( state, IO_WriteOnly );
04954 
04955     if ( (*it)->m_extension )
04956       (*it)->m_extension->saveState( frameStream );
04957 
04958     frameStateBufferLst << state;
04959   }
04960 
04961   // Save frame data
04962   stream << (Q_UINT32) frameNameLst.count();
04963   stream << frameNameLst << frameServiceTypeLst << frameServiceNameLst << frameURLLst << frameStateBufferLst;
04964 #ifndef NDEBUG
04965   s_saveStateIndentLevel = indentLevel;
04966 #endif
04967 }
04968 
04969 void KHTMLPart::restoreState( QDataStream &stream )
04970 {
04971   KURL u;
04972   Q_INT32 xOffset, yOffset, wContents, hContents, mWidth, mHeight;
04973   Q_UINT32 frameCount;
04974   QStringList frameNames, frameServiceTypes, docState, frameServiceNames;
04975   KURL::List frameURLs;
04976   QValueList<QByteArray> frameStateBuffers;
04977   QValueList<int> fSizes;
04978   QString encoding, sheetUsed;
04979   long old_cacheId = d->m_cacheId;
04980 
04981   stream >> u >> xOffset >> yOffset >> wContents >> hContents >> mWidth >> mHeight;
04982 
04983   d->m_view->setMarginWidth( mWidth );
04984   d->m_view->setMarginHeight( mHeight );
04985 
04986   // restore link cursor position
04987   // nth node is active. value is set in checkCompleted()
04988   stream >> d->m_focusNodeNumber;
04989   d->m_focusNodeRestored = false;
04990 
04991   stream >> d->m_cacheId;
04992 
04993   stream >> encoding >> sheetUsed >> docState;
04994 
04995   d->m_encoding = encoding;
04996   d->m_sheetUsed = sheetUsed;
04997 
04998   int zoomFactor;
04999   stream >> zoomFactor;
05000   setZoomFactor(zoomFactor);
05001 
05002   stream >> d->m_httpHeaders;
05003   stream >> d->m_pageServices;
05004   stream >> d->m_pageReferrer;
05005 
05006   // Restore ssl data
05007   stream >> d->m_ssl_in_use
05008          >> d->m_ssl_peer_certificate
05009          >> d->m_ssl_peer_chain
05010          >> d->m_ssl_peer_ip
05011          >> d->m_ssl_cipher
05012          >> d->m_ssl_cipher_desc
05013          >> d->m_ssl_cipher_version
05014          >> d->m_ssl_cipher_used_bits
05015          >> d->m_ssl_cipher_bits
05016          >> d->m_ssl_cert_state
05017          >> d->m_ssl_parent_ip
05018          >> d->m_ssl_parent_cert;
05019 
05020   setPageSecurity( d->m_ssl_in_use ? Encrypted : NotCrypted );
05021 
05022   stream >> frameCount >> frameNames >> frameServiceTypes >> frameServiceNames
05023          >> frameURLs >> frameStateBuffers;
05024 
05025   d->m_bComplete = false;
05026   d->m_bLoadEventEmitted = false;
05027 
05028 //   kdDebug( 6050 ) << "restoreState() docState.count() = " << docState.count() << endl;
05029 //   kdDebug( 6050 ) << "m_url " << m_url.url() << " <-> " << u.url() << endl;
05030 //   kdDebug( 6050 ) << "m_frames.count() " << d->m_frames.count() << " <-> " << frameCount << endl;
05031 
05032   if (d->m_cacheId == old_cacheId)
05033   {
05034     // Partial restore
05035     d->m_redirectionTimer.stop();
05036 
05037     FrameIt fIt = d->m_frames.begin();
05038     const FrameIt fEnd = d->m_frames.end();
05039 
05040     for (; fIt != fEnd; ++fIt )
05041         (*fIt)->m_bCompleted = false;
05042 
05043     fIt = d->m_frames.begin();
05044 
05045     QStringList::ConstIterator fNameIt = frameNames.begin();
05046     QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
05047     QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
05048     KURL::List::ConstIterator fURLIt = frameURLs.begin();
05049     QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
05050 
05051     for (; fIt != fEnd; ++fIt, ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
05052     {
05053       khtml::ChildFrame* const child = *fIt;
05054 
05055 //      kdDebug( 6050 ) <<  *fNameIt  << " ---- " <<  *fServiceTypeIt << endl;
05056 
05057       if ( child->m_name != *fNameIt || child->m_serviceType != *fServiceTypeIt )
05058       {
05059         child->m_bPreloaded = true;
05060         child->m_name = *fNameIt;
05061         child->m_serviceName = *fServiceNameIt;
05062         processObjectRequest( child, *fURLIt, *fServiceTypeIt );
05063       }
05064       if ( child->m_part )
05065       {
05066         child->m_bCompleted = false;
05067         if ( child->m_extension && !(*fBufferIt).isEmpty() )
05068         {
05069           QDataStream frameStream( *fBufferIt, IO_ReadOnly );
05070           child->m_extension->restoreState( frameStream );
05071         }
05072         else
05073           child->m_part->openURL( *fURLIt );
05074       }
05075     }
05076 
05077     KParts::URLArgs args( d->m_extension->urlArgs() );
05078     args.xOffset = xOffset;
05079     args.yOffset = yOffset;
05080     args.docState = docState;
05081     d->m_extension->setURLArgs( args );
05082 
05083     d->m_view->resizeContents( wContents,  hContents);
05084     d->m_view->setContentsPos( xOffset, yOffset );
05085 
05086     m_url = u;
05087   }
05088   else
05089   {
05090     // Full restore.
05091     closeURL();
05092     // We must force a clear because we want to be sure to delete all
05093     // frames.
05094     d->m_bCleared = false;
05095     clear();
05096     d->m_encoding = encoding;
05097     d->m_sheetUsed = sheetUsed;
05098 
05099     QStringList::ConstIterator fNameIt = frameNames.begin();
05100     const QStringList::ConstIterator fNameEnd = frameNames.end();
05101 
05102     QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
05103     QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
05104     KURL::List::ConstIterator fURLIt = frameURLs.begin();
05105     QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
05106 
05107     for (; fNameIt != fNameEnd; ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
05108     {
05109       khtml::ChildFrame* const newChild = new khtml::ChildFrame;
05110       newChild->m_bPreloaded = true;
05111       newChild->m_name = *fNameIt;
05112       newChild->m_serviceName = *fServiceNameIt;
05113 
05114 //      kdDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt << endl;
05115 
05116       const FrameIt childFrame = d->m_frames.append( newChild );
05117 
05118       processObjectRequest( *childFrame, *fURLIt, *fServiceTypeIt );
05119 
05120       (*childFrame)->m_bPreloaded = true;
05121 
05122       if ( (*childFrame)->m_part )
05123       {
05124         if ( (*childFrame)->m_extension )
05125         if ( (*childFrame)->m_extension && !(*fBufferIt).isEmpty() )
05126         {
05127           QDataStream frameStream( *fBufferIt, IO_ReadOnly );
05128           (*childFrame)->m_extension->restoreState( frameStream );
05129         }
05130         else
05131           (*childFrame)->m_part->openURL( *fURLIt );
05132       }
05133     }
05134 
05135     KParts::URLArgs args( d->m_extension->urlArgs() );
05136     args.xOffset = xOffset;
05137     args.yOffset = yOffset;
05138     args.docState = docState;
05139 
05140     d->m_extension->setURLArgs( args );
05141     if (!KHTMLPageCache::self()->isComplete(d->m_cacheId))
05142     {
05143        d->m_restored = true;
05144        openURL( u );
05145        d->m_restored = false;
05146     }
05147     else
05148     {
05149        restoreURL( u );
05150     }
05151   }
05152 
05153 }
05154 
05155 void KHTMLPart::show()
05156 {
05157   if ( d->m_view )
05158     d->m_view->show();
05159 }
05160 
05161 void KHTMLPart::hide()
05162 {
05163   if ( d->m_view )
05164     d->m_view->hide();
05165 }
05166 
05167 DOM::Node KHTMLPart::nodeUnderMouse() const
05168 {
05169     return d->m_view->nodeUnderMouse();
05170 }
05171 
05172 DOM::Node KHTMLPart::nonSharedNodeUnderMouse() const
05173 {
05174     return d->m_view->nonSharedNodeUnderMouse();
05175 }
05176 
05177 void KHTMLPart::emitSelectionChanged()
05178 {
05179   emit d->m_extension->enableAction( "copy", hasSelection() );
05180   if ( d->m_findDialog )
05181        d->m_findDialog->setHasSelection( hasSelection() );
05182 
05183   emit d->m_extension->selectionInfo( selectedText() );
05184   emit selectionChanged();
05185 }
05186 
05187 int KHTMLPart::zoomFactor() const
05188 {
05189   return d->m_zoomFactor;
05190 }
05191 
05192 // ### make the list configurable ?
05193 static const int zoomSizes[] = { 20, 40, 60, 80, 90, 95, 100, 105, 110, 120, 140, 160, 180, 200, 250, 300 };
05194 static const int zoomSizeCount = (sizeof(zoomSizes) / sizeof(int));
05195 static const int minZoom = 20;
05196 static const int maxZoom = 300;
05197 
05198 // My idea of useful stepping ;-) (LS)
05199 extern const int KDE_NO_EXPORT fastZoomSizes[] = { 20, 50, 75, 90, 100, 120, 150, 200, 300 };
05200 extern const int KDE_NO_EXPORT fastZoomSizeCount = sizeof fastZoomSizes / sizeof fastZoomSizes[0];
05201 
05202 void KHTMLPart::slotIncZoom()
05203 {
05204   zoomIn(zoomSizes, zoomSizeCount);
05205 }
05206 
05207 void KHTMLPart::slotDecZoom()
05208 {
05209   zoomOut(zoomSizes, zoomSizeCount);
05210 }
05211 
05212 void KHTMLPart::slotIncZoomFast()
05213 {
05214   zoomIn(fastZoomSizes, fastZoomSizeCount);
05215 }
05216 
05217 void KHTMLPart::slotDecZoomFast()
05218 {
05219   zoomOut(fastZoomSizes, fastZoomSizeCount);
05220 }
05221 
05222 void KHTMLPart::zoomIn(const int stepping[], int count)
05223 {
05224   int zoomFactor = d->m_zoomFactor;
05225 
05226   if (zoomFactor < maxZoom) {
05227     // find the entry nearest to the given zoomsizes
05228     for (int i = 0; i < count; ++i)
05229       if (stepping[i] > zoomFactor) {
05230         zoomFactor = stepping[i];
05231         break;
05232       }
05233     setZoomFactor(zoomFactor);
05234   }
05235 }
05236 
05237 void KHTMLPart::zoomOut(const int stepping[], int count)
05238 {
05239     int zoomFactor = d->m_zoomFactor;
05240     if (zoomFactor > minZoom) {
05241       // find the entry nearest to the given zoomsizes
05242       for (int i = count-1; i >= 0; --i)
05243         if (stepping[i] < zoomFactor) {
05244           zoomFactor = stepping[i];
05245           break;
05246         }
05247       setZoomFactor(zoomFactor);
05248     }
05249 }
05250 
05251 void KHTMLPart::setZoomFactor (int percent)
05252 {
05253   if (percent < minZoom) percent = minZoom;
05254   if (percent > maxZoom) percent = maxZoom;
05255   if (d->m_zoomFactor == percent) return;
05256   d->m_zoomFactor = percent;
05257 
05258   if(d->m_doc) {
05259       QApplication::setOverrideCursor( waitCursor );
05260     if (d->m_doc->styleSelector())
05261       d->m_doc->styleSelector()->computeFontSizes(d->m_doc->paintDeviceMetrics(), d->m_zoomFactor);
05262     d->m_doc->recalcStyle( NodeImpl::Force );
05263     QApplication::restoreOverrideCursor();
05264   }
05265 
05266   ConstFrameIt it = d->m_frames.begin();
05267   const ConstFrameIt end = d->m_frames.end();
05268   for (; it != end; ++it )
05269     if ( !( *it )->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
05270       KParts::ReadOnlyPart* const p = ( *it )->m_part;
05271       static_cast<KHTMLPart*>( p )->setZoomFactor(d->m_zoomFactor);
05272     }
05273 
05274   if ( d->m_guiProfile == BrowserViewGUI ) {
05275       d->m_paDecZoomFactor->setEnabled( d->m_zoomFactor > minZoom );
05276       d->m_paIncZoomFactor->setEnabled( d->m_zoomFactor < maxZoom );
05277   }
05278 }
05279 
05280 void KHTMLPart::slotZoomView( int delta )
05281 {
05282   if ( delta < 0 )
05283     slotIncZoom();
05284   else
05285     slotDecZoom();
05286 }
05287 
05288 void KHTMLPart::setStatusBarText( const QString& text, StatusBarPriority p)
05289 {
05290   if (!d->m_statusMessagesEnabled)
05291     return;
05292 
05293   d->m_statusBarText[p] = text;
05294 
05295   // shift handling ?
05296   QString tobe = d->m_statusBarText[BarHoverText];
05297   if (tobe.isEmpty())
05298     tobe = d->m_statusBarText[BarOverrideText];
05299   if (tobe.isEmpty()) {
05300     tobe = d->m_statusBarText[BarDefaultText];
05301     if (!tobe.isEmpty() && d->m_jobspeed)
05302       tobe += " ";
05303     if (d->m_jobspeed)
05304       tobe += i18n( "(%1/s)" ).arg( KIO::convertSize( d->m_jobspeed ) );
05305   }
05306   tobe = "<qt>"+tobe;
05307 
05308   emit ReadOnlyPart::setStatusBarText(tobe);
05309 }
05310 
05311 
05312 void KHTMLPart::setJSStatusBarText( const QString &text )
05313 {
05314   setStatusBarText(text, BarOverrideText);
05315 }
05316 
05317 void KHTMLPart::setJSDefaultStatusBarText( const QString &text )
05318 {
05319   setStatusBarText(text, BarDefaultText);
05320 }
05321 
05322 QString KHTMLPart::jsStatusBarText() const
05323 {
05324     return d->m_statusBarText[BarOverrideText];
05325 }
05326 
05327 QString KHTMLPart::jsDefaultStatusBarText() const
05328 {
05329    return d->m_statusBarText[BarDefaultText];
05330 }
05331 
05332 QString KHTMLPart::referrer() const
05333 {
05334    return d->m_referrer;
05335 }
05336 
05337 QString KHTMLPart::pageReferrer() const
05338 {
05339    KURL referrerURL = KURL( d->m_pageReferrer );
05340    if (referrerURL.isValid())
05341    {
05342       QString protocol = referrerURL.protocol();
05343 
05344       if ((protocol == "http") ||
05345          ((protocol == "https") && (m_url.protocol() == "https")))
05346       {
05347           referrerURL.setRef(QString::null);
05348           referrerURL.setUser(QString::null);
05349           referrerURL.setPass(QString::null);
05350           return referrerURL.url();
05351       }
05352    }
05353 
05354    return QString::null;
05355 }
05356 
05357 
05358 QString KHTMLPart::lastModified() const
05359 {
05360   if ( d->m_lastModified.isEmpty() && m_url.isLocalFile() ) {
05361     // Local file: set last-modified from the file's mtime.
05362     // Done on demand to save time when this isn't needed - but can lead
05363     // to slightly wrong results if updating the file on disk w/o reloading.
05364     QDateTime lastModif = QFileInfo( m_url.path() ).lastModified();
05365     d->m_lastModified = lastModif.toString( Qt::LocalDate );
05366   }
05367   //kdDebug(6050) << "KHTMLPart::lastModified: " << d->m_lastModified << endl;
05368   return d->m_lastModified;
05369 }
05370 
05371 void KHTMLPart::slotLoadImages()
05372 {
05373   if (d->m_doc )
05374     d->m_doc->docLoader()->setAutoloadImages( !d->m_doc->docLoader()->autoloadImages() );
05375 
05376   ConstFrameIt it = d->m_frames.begin();
05377   const ConstFrameIt end = d->m_frames.end();
05378   for (; it != end; ++it )
05379     if ( !( *it )->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
05380       KParts::ReadOnlyPart* const p = ( *it )->m_part;
05381       static_cast<KHTMLPart*>( p )->slotLoadImages();
05382     }
05383 }
05384 
05385 void KHTMLPart::reparseConfiguration()
05386 {
05387   KHTMLSettings *settings = KHTMLFactory::defaultHTMLSettings();
05388   settings->init();
05389 
05390   setAutoloadImages( settings->autoLoadImages() );
05391   if (d->m_doc)
05392      d->m_doc->docLoader()->setShowAnimations( settings->showAnimations() );
05393 
05394   d->m_bOpenMiddleClick = settings->isOpenMiddleClickEnabled();
05395   d->m_bBackRightClick = settings->isBackRightClickEnabled();
05396   d->m_bJScriptEnabled = settings->isJavaScriptEnabled(m_url.host());
05397   setDebugScript( settings->isJavaScriptDebugEnabled() );
05398   d->m_bJavaEnabled = settings->isJavaEnabled(m_url.host());
05399   d->m_bPluginsEnabled = settings->isPluginsEnabled(m_url.host());
05400   d->m_metaRefreshEnabled = settings->isAutoDelayedActionsEnabled ();
05401 
05402   delete d->m_settings;
05403   d->m_settings = new KHTMLSettings(*KHTMLFactory::defaultHTMLSettings());
05404 
05405   QApplication::setOverrideCursor( waitCursor );
05406   khtml::CSSStyleSelector::reparseConfiguration();
05407   if(d->m_doc) d->m_doc->updateStyleSelector();
05408   QApplication::restoreOverrideCursor();
05409 }
05410 
05411 QStringList KHTMLPart::frameNames() const
05412 {
05413   QStringList res;
05414 
05415   ConstFrameIt it = d->m_frames.begin();
05416   const ConstFrameIt end = d->m_frames.end();
05417   for (; it != end; ++it )
05418     if (!(*it)->m_bPreloaded)
05419       res += (*it)->m_name;
05420 
05421   return res;
05422 }
05423 
05424 QPtrList<KParts::ReadOnlyPart> KHTMLPart::frames() const
05425 {
05426   QPtrList<KParts::ReadOnlyPart> res;
05427 
05428   ConstFrameIt it = d->m_frames.begin();
05429   const ConstFrameIt end = d->m_frames.end();
05430   for (; it != end; ++it )
05431     if (!(*it)->m_bPreloaded)
05432       res.append( (*it)->m_part );
05433 
05434   return res;
05435 }
05436 
05437 bool KHTMLPart::openURLInFrame( const KURL &url, const KParts::URLArgs &urlArgs )
05438 {
05439     kdDebug( 6050 ) << this << "KHTMLPart::openURLInFrame " << url << endl;
05440   FrameIt it = d->m_frames.find( urlArgs.frameName );
05441 
05442   if ( it == d->m_frames.end() )
05443     return false;
05444 
05445   // Inform someone that we are about to show something else.
05446   if ( !urlArgs.lockHistory() )
05447       emit d->m_extension->openURLNotify();
05448 
05449   requestObject( *it, url, urlArgs );
05450 
05451   return true;
05452 }
05453 
05454 void KHTMLPart::setDNDEnabled( bool b )
05455 {
05456   d->m_bDnd = b;
05457 }
05458 
05459 bool KHTMLPart::dndEnabled() const
05460 {
05461   return d->m_bDnd;
05462 }
05463 
05464 void KHTMLPart::customEvent( QCustomEvent *event )
05465 {
05466   if ( khtml::MousePressEvent::test( event ) )
05467   {
05468     khtmlMousePressEvent( static_cast<khtml::MousePressEvent *>( event ) );
05469     return;
05470   }
05471 
05472   if ( khtml::MouseDoubleClickEvent::test( event ) )
05473   {
05474     khtmlMouseDoubleClickEvent( static_cast<khtml::MouseDoubleClickEvent *>( event ) );
05475     return;
05476   }
05477 
05478   if ( khtml::MouseMoveEvent::test( event ) )
05479   {
05480     khtmlMouseMoveEvent( static_cast<khtml::MouseMoveEvent *>( event ) );
05481     return;
05482   }
05483 
05484   if ( khtml::MouseReleaseEvent::test( event ) )
05485   {
05486     khtmlMouseReleaseEvent( static_cast<khtml::MouseReleaseEvent *>( event ) );
05487     return;
05488   }
05489 
05490   if ( khtml::DrawContentsEvent::test( event ) )
05491   {
05492     khtmlDrawContentsEvent( static_cast<khtml::DrawContentsEvent *>( event ) );
05493     return;
05494   }
05495 
05496   KParts::ReadOnlyPart::customEvent( event );
05497 }
05498 
05504 static bool firstRunAt(khtml::RenderObject *renderNode, int y, NodeImpl *&startNode, long &startOffset)
05505 {
05506     for (khtml::RenderObject *n = renderNode; n; n = n->nextSibling()) {
05507         if (n->isText()) {
05508             khtml::RenderText* const textRenderer = static_cast<khtml::RenderText *>(n);
05509             const khtml::InlineTextBoxArray &runs = textRenderer->inlineTextBoxes();
05510         const unsigned lim = runs.count();
05511             for (unsigned i = 0; i != lim; ++i) {
05512                 if (runs[i]->m_y == y) {
05513                     startNode = textRenderer->element();
05514                     startOffset = runs[i]->m_start;
05515                     return true;
05516                 }
05517             }
05518         }
05519 
05520         if (firstRunAt(n->firstChild(), y, startNode, startOffset)) {
05521             return true;
05522         }
05523     }
05524 
05525     return false;
05526 }
05527 
05533 static bool lastRunAt(khtml::RenderObject *renderNode, int y, NodeImpl *&endNode, long &endOffset)
05534 {
05535     khtml::RenderObject *n = renderNode;
05536     if (!n) {
05537         return false;
05538     }
05539     khtml::RenderObject *next;
05540     while ((next = n->nextSibling())) {
05541         n = next;
05542     }
05543 
05544     while (1) {
05545         if (lastRunAt(n->firstChild(), y, endNode, endOffset)) {
05546             return true;
05547         }
05548 
05549         if (n->isText()) {
05550             khtml::RenderText* const textRenderer =  static_cast<khtml::RenderText *>(n);
05551             const khtml::InlineTextBoxArray &runs = textRenderer->inlineTextBoxes();
05552             for (int i = (int)runs.count()-1; i >= 0; --i) {
05553                 if (runs[i]->m_y == y) {
05554                     endNode = textRenderer->element();
05555                     endOffset = runs[i]->m_start + runs[i]->m_len;
05556                     return true;
05557                 }
05558             }
05559         }
05560 
05561         if (n == renderNode) {
05562             return false;
05563         }
05564 
05565         n = n->previousSibling();
05566     }
05567 }
05568 
05569 void KHTMLPart::khtmlMousePressEvent( khtml::MousePressEvent *event )
05570 {
05571   DOM::DOMString url = event->url();
05572   QMouseEvent *_mouse = event->qmouseEvent();
05573   DOM::Node innerNode = event->innerNode();
05574   d->m_mousePressNode = innerNode;
05575 
05576    d->m_dragStartPos = _mouse->pos();
05577 
05578    if ( !event->url().isNull() ) {
05579      d->m_strSelectedURL = event->url().string();
05580      d->m_strSelectedURLTarget = event->target().string();
05581    }
05582    else
05583      d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
05584 
05585   if ( _mouse->button() == LeftButton ||
05586        _mouse->button() == MidButton )
05587   {
05588     d->m_bMousePressed = true;
05589 
05590 #ifndef KHTML_NO_SELECTION
05591     if ( _mouse->button() == LeftButton )
05592     {
05593       if ( (!d->m_strSelectedURL.isNull() && !isEditable())
05594             || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) )
05595       return;
05596       if ( !innerNode.isNull()  && innerNode.handle()->renderer()) {
05597           int offset = 0;
05598           DOM::NodeImpl* node = 0;
05599           khtml::RenderObject::SelPointState state;
05600           innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(),
05601                                                                event->absX()-innerNode.handle()->renderer()->xPos(),
05602                                                                event->absY()-innerNode.handle()->renderer()->yPos(), node, offset, state );
05603           d->m_extendMode = d->ExtendByChar;
05604 #ifdef KHTML_NO_CARET
05605           d->m_selectionStart = node;
05606           d->m_startOffset = offset;
05607           //if ( node )
05608           //  kdDebug(6005) << "KHTMLPart::khtmlMousePressEvent selectionStart=" << d->m_selectionStart.handle()->renderer()
05609           //                << " offset=" << d->m_startOffset << endl;
05610           //else
05611           //  kdDebug(6005) << "KHTML::khtmlMousePressEvent selectionStart=(nil)" << endl;
05612           d->m_selectionEnd = d->m_selectionStart;
05613           d->m_endOffset = d->m_startOffset;
05614           d->m_doc->clearSelection();
05615 #else // KHTML_NO_CARET
05616       d->m_view->moveCaretTo(node, offset, (_mouse->state() & ShiftButton) == 0);
05617 #endif // KHTML_NO_CARET
05618       d->m_initialNode = d->m_selectionStart;
05619       d->m_initialOffset = d->m_startOffset;
05620 //           kdDebug(6000) << "press: initOfs " << d->m_initialOffset << endl;
05621       }
05622       else
05623       {
05624 #ifndef KHTML_NO_CARET
05625         // simply leave it. Is this a good idea?
05626 #else
05627         d->m_selectionStart = DOM::Node();
05628         d->m_selectionEnd = DOM::Node();
05629 #endif
05630       }
05631       emitSelectionChanged();
05632       startAutoScroll();
05633     }
05634 #else
05635     d->m_dragLastPos = _mouse->globalPos();
05636 #endif
05637   }
05638 
05639   if ( _mouse->button() == RightButton && parentPart() != 0 && d->m_bBackRightClick )
05640   {
05641     d->m_bRightMousePressed = true;
05642   } else if ( _mouse->button() == RightButton )
05643   {
05644     popupMenu( d->m_strSelectedURL );
05645     // might be deleted, don't touch "this"
05646   }
05647 }
05648 
05649 void KHTMLPart::khtmlMouseDoubleClickEvent( khtml::MouseDoubleClickEvent *event )
05650 {
05651   QMouseEvent *_mouse = event->qmouseEvent();
05652   if ( _mouse->button() == LeftButton )
05653   {
05654     d->m_bMousePressed = true;
05655     DOM::Node innerNode = event->innerNode();
05656     // Find selectionStart again, khtmlMouseReleaseEvent lost it
05657     if ( !innerNode.isNull() && innerNode.handle()->renderer()) {
05658       int offset = 0;
05659       DOM::NodeImpl* node = 0;
05660       khtml::RenderObject::SelPointState state;
05661       innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(),
05662                                                            event->absX()-innerNode.handle()->renderer()->xPos(),
05663                                                            event->absY()-innerNode.handle()->renderer()->yPos(), node, offset, state);
05664 
05665       //kdDebug() << k_funcinfo << "checkSelectionPoint returned node=" << node << " offset=" << offset << endl;
05666 
05667       if ( node && node->renderer() )
05668       {
05669         // Extend selection to a complete word (double-click) or line (triple-click)
05670         bool selectLine = (event->clickCount() == 3);
05671         d->m_extendMode = selectLine ? d->ExtendByLine : d->ExtendByWord;
05672 
05673     // Extend existing selection if Shift was pressed
05674     if (_mouse->state() & ShiftButton) {
05675           d->caretNode() = node;
05676       d->caretOffset() = offset;
05677           d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
05678                 d->m_selectionStart.handle(), d->m_startOffset,
05679             d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
05680           d->m_initialNode = d->m_extendAtEnd ? d->m_selectionStart : d->m_selectionEnd;
05681           d->m_initialOffset = d->m_extendAtEnd ? d->m_startOffset : d->m_endOffset;
05682     } else {
05683       d->m_selectionStart = d->m_selectionEnd = node;
05684       d->m_startOffset = d->m_endOffset = offset;
05685           d->m_startBeforeEnd = true;
05686           d->m_initialNode = node;
05687           d->m_initialOffset = offset;
05688     }
05689 //         kdDebug(6000) << "dblclk: initOfs " << d->m_initialOffset << endl;
05690 
05691         // Extend the start
05692         extendSelection( d->m_selectionStart.handle(), d->m_startOffset, d->m_selectionStart, d->m_startOffset, !d->m_startBeforeEnd, selectLine );
05693         // Extend the end
05694         extendSelection( d->m_selectionEnd.handle(), d->m_endOffset, d->m_selectionEnd, d->m_endOffset, d->m_startBeforeEnd, selectLine );
05695 
05696         //kdDebug() << d->m_selectionStart.handle() << " " << d->m_startOffset << "  -  " <<
05697         //  d->m_selectionEnd.handle() << " " << d->m_endOffset << endl;
05698 
05699         emitSelectionChanged();
05700         d->m_doc
05701           ->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
05702                          d->m_selectionEnd.handle(),d->m_endOffset);
05703 #ifndef KHTML_NO_CARET
05704         bool v = d->m_view->placeCaret();
05705         emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
05706 #endif
05707         startAutoScroll();
05708       }
05709     }
05710   }
05711 }
05712 
05713 void KHTMLPart::extendSelection( DOM::NodeImpl* node, long offset, DOM::Node& selectionNode, long& selectionOffset, bool right, bool selectLines )
05714 {
05715   khtml::RenderObject* obj = node->renderer();
05716 
05717   if (obj->isText() && selectLines) {
05718     int pos;
05719     khtml::RenderText *renderer = static_cast<khtml::RenderText *>(obj);
05720     khtml::InlineTextBox *run = renderer->findInlineTextBox( offset, pos );
05721     DOMString t = node->nodeValue();
05722     DOM::NodeImpl* selNode = 0;
05723     long selOfs = 0;
05724 
05725     if (!run)
05726       return;
05727 
05728     int selectionPointY = run->m_y;
05729 
05730     // Go up to first non-inline element.
05731     khtml::RenderObject *renderNode = renderer;
05732     while (renderNode && renderNode->isInline())
05733       renderNode = renderNode->parent();
05734 
05735     renderNode = renderNode->firstChild();
05736 
05737     if (right) {
05738       // Look for all the last child in the block that is on the same line
05739       // as the selection point.
05740       if (!lastRunAt (renderNode, selectionPointY, selNode, selOfs))
05741         return;
05742     } else {
05743       // Look for all the first child in the block that is on the same line
05744       // as the selection point.
05745       if (!firstRunAt (renderNode, selectionPointY, selNode, selOfs))
05746         return;
05747     }
05748 
05749     selectionNode = selNode;
05750     selectionOffset = selOfs;
05751     return;
05752   }
05753 
05754   QString str;
05755   int len = 0;
05756   if ( obj->isText() ) { // can be false e.g. when double-clicking on a disabled submit button
05757     str = static_cast<khtml::RenderText *>(obj)->data().string();
05758     len = str.length();
05759   }
05760   //kdDebug() << "extendSelection right=" << right << " offset=" << offset << " len=" << len << " Starting at obj=" << obj << endl;
05761   QChar ch;
05762   do {
05763     // Last char was ok, point to it
05764     if ( node ) {
05765       selectionNode = node;
05766       selectionOffset = offset;
05767     }
05768 
05769     // Get another char
05770     while ( obj && ( (right && offset >= len-1) || (!right && offset <= 0) ) )
05771     {
05772       obj = right ? obj->objectBelow() : obj->objectAbove();
05773       //kdDebug() << "obj=" << obj << endl;
05774       if ( obj ) {
05775         //kdDebug() << "isText=" << obj->isText() << endl;
05776         str = QString::null;
05777         if ( obj->isText() )
05778           str = static_cast<khtml::RenderText *>(obj)->data().string();
05779         else if ( obj->isBR() )
05780           str = '\n';
05781         else if ( !obj->isInline() ) {
05782           obj = 0L; // parag limit -> done
05783           break;
05784         }
05785         len = str.length();
05786         //kdDebug() << "str=" << str << " length=" << len << endl;
05787         // set offset - note that the first thing will be a ++ or -- on it.
05788         if ( right )
05789           offset = -1;
05790         else
05791           offset = len;
05792       }
05793     }
05794     if ( !obj ) // end of parag or document
05795       break;
05796     node = obj->element();
05797     if ( right )
05798     {
05799       Q_ASSERT( offset < len-1 );
05800       ++offset;
05801     }
05802     else
05803     {
05804       Q_ASSERT( offset > 0 );
05805       --offset;
05806     }
05807 
05808     // Test that char
05809     ch = str[ offset ];
05810     //kdDebug() << " offset=" << offset << " ch=" << QString(ch) << endl;
05811   } while ( !ch.isSpace() && !ch.isPunct() );
05812 
05813   // make offset point after last char
05814   if (right) ++selectionOffset;
05815 }
05816 
05817 #ifndef KHTML_NO_SELECTION
05818 void KHTMLPart::extendSelectionTo(int x, int y, int absX, int absY, const DOM::Node &innerNode)
05819 {
05820       int offset;
05821       //kdDebug(6000) << "KHTMLPart::khtmlMouseMoveEvent x=" << event->x() << " y=" << event->y() << endl;
05822       DOM::NodeImpl* node=0;
05823       khtml::RenderObject::SelPointState state;
05824       innerNode.handle()->renderer()->checkSelectionPoint( x, y,
05825                                                            absX-innerNode.handle()->renderer()->xPos(),
05826                                                            absY-innerNode.handle()->renderer()->yPos(), node, offset, state);
05827       if (!node || !node->renderer()) return;
05828 
05829       // Words at the beginning/end of line cannot be deselected in
05830       // ExtendByWord mode. Therefore, do not enforce it if the selection
05831       // point does not match the node under the mouse cursor.
05832       bool withinNode = innerNode == node;
05833 
05834       // we have to get to know if end is before start or not...
05835       // shouldn't be null but it can happen with dynamic updating of nodes
05836       if (d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() ||
05837           d->m_initialNode.isNull() ||
05838           !d->m_selectionStart.handle()->renderer() ||
05839           !d->m_selectionEnd.handle()->renderer()) return;
05840 
05841       if (d->m_extendMode != d->ExtendByChar) {
05842         // check whether we should extend at the front, or at the back
05843         bool caretBeforeInit = RangeImpl::compareBoundaryPoints(
05844                 d->caretNode().handle(), d->caretOffset(),
05845             d->m_initialNode.handle(), d->m_initialOffset) <= 0;
05846         bool nodeBeforeInit = RangeImpl::compareBoundaryPoints(node, offset,
05847             d->m_initialNode.handle(), d->m_initialOffset) <= 0;
05848         // have to fix up start to point to the original end
05849         if (caretBeforeInit != nodeBeforeInit) {
05850 //         kdDebug(6000) << "extto cbi: " << caretBeforeInit << " startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << " initOfs " << d->m_initialOffset << endl;
05851           extendSelection(d->m_initialNode.handle(), d->m_initialOffset,
05852         d->m_extendAtEnd ? d->m_selectionStart : d->m_selectionEnd,
05853         d->m_extendAtEnd ? d->m_startOffset : d->m_endOffset,
05854         nodeBeforeInit, d->m_extendMode == d->ExtendByLine);
05855     }
05856       }
05857 
05858       d->caretNode() = node;
05859       d->caretOffset() = offset;
05860       //kdDebug( 6000 ) << "setting end of selection to " << d->m_selectionEnd.handle() << "/" << d->m_endOffset << endl;
05861 
05862       d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
05863                 d->m_selectionStart.handle(), d->m_startOffset,
05864             d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
05865 
05866       if ( !d->m_selectionStart.isNull() && !d->m_selectionEnd.isNull() )
05867       {
05868 //         kdDebug(6000) << "extto: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << " initOfs " << d->m_initialOffset << endl;
05869         if (d->m_extendMode != d->ExtendByChar && withinNode)
05870           extendSelection( node, offset, d->caretNode(), d->caretOffset(), d->m_startBeforeEnd ^ !d->m_extendAtEnd, d->m_extendMode == d->ExtendByLine );
05871 
05872         if (d->m_selectionEnd == d->m_selectionStart && d->m_endOffset < d->m_startOffset)
05873           d->m_doc
05874             ->setSelection(d->m_selectionStart.handle(),d->m_endOffset,
05875                            d->m_selectionEnd.handle(),d->m_startOffset);
05876         else if (d->m_startBeforeEnd)
05877           d->m_doc
05878             ->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
05879                            d->m_selectionEnd.handle(),d->m_endOffset);
05880         else
05881           d->m_doc
05882             ->setSelection(d->m_selectionEnd.handle(),d->m_endOffset,
05883                            d->m_selectionStart.handle(),d->m_startOffset);
05884       }
05885 #ifndef KHTML_NO_CARET
05886       d->m_view->placeCaret();
05887 #endif
05888 }
05889 
05890 bool KHTMLPart::isExtendingSelection() const
05891 {
05892   // This is it, the whole detection. khtmlMousePressEvent only sets this
05893   // on LMB or MMB, but never on RMB. As text selection doesn't work for MMB,
05894   // it's sufficient to only rely on this flag to detect selection extension.
05895   return d->m_bMousePressed;
05896 }
05897 #endif // KHTML_NO_SELECTION
05898 
05899 void KHTMLPart::khtmlMouseMoveEvent( khtml::MouseMoveEvent *event )
05900 {
05901   QMouseEvent *_mouse = event->qmouseEvent();
05902 
05903   if( d->m_bRightMousePressed && parentPart() != 0 && d->m_bBackRightClick )
05904   {
05905     popupMenu( d->m_strSelectedURL );
05906     d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
05907     d->m_bRightMousePressed = false;
05908   }
05909 
05910   DOM::DOMString url = event->url();
05911   DOM::DOMString target = event->target();
05912   DOM::Node innerNode = event->innerNode();
05913 
05914 #ifndef QT_NO_DRAGANDDROP
05915   if( d->m_bDnd && d->m_bMousePressed &&
05916       ( (!d->m_strSelectedURL.isEmpty() && !isEditable())
05917         || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) ) ) {
05918     if ( ( d->m_dragStartPos - _mouse->pos() ).manhattanLength() <= KGlobalSettings::dndEventDelay() )
05919       return;
05920 
05921     QPixmap pix;
05922     HTMLImageElementImpl *img = 0L;
05923     QDragObject *drag = 0;
05924     KURL u;
05925 
05926     // qDebug("****************** Event URL: %s", url.string().latin1());
05927     // qDebug("****************** Event Target: %s", target.string().latin1());
05928 
05929     // Normal image...
05930     if ( url.length() == 0 && innerNode.handle() && innerNode.handle()->id() == ID_IMG )
05931     {
05932       img = static_cast<HTMLImageElementImpl *>(innerNode.handle());
05933       u = KURL( completeURL( khtml::parseURL(img->getAttribute(ATTR_SRC)).string() ) );
05934       pix = KMimeType::mimeType("image/png")->pixmap(KIcon::Desktop);
05935     }
05936     else
05937     {
05938       // Text or image link...
05939       u = completeURL( d->m_strSelectedURL );
05940       pix = KMimeType::pixmapForURL(u, 0, KIcon::Desktop, KIcon::SizeMedium);
05941     }
05942 
05943     u.setPass(QString::null);
05944 
05945     KURLDrag* urlDrag = new KURLDrag( u, img ? 0 : d->m_view->viewport() );
05946     if ( !d->m_referrer.isEmpty() )
05947       urlDrag->metaData()["referrer"] = d->m_referrer;
05948 
05949     if( img ) {
05950       KMultipleDrag *mdrag = new KMultipleDrag( d->m_view->viewport() );
05951       mdrag->addDragObject( new QImageDrag( img->currentImage(), 0L ) );
05952       mdrag->addDragObject( urlDrag );
05953       drag = mdrag;
05954     }
05955     else
05956       drag = urlDrag;
05957 
05958     if ( !pix.isNull() )
05959       drag->setPixmap( pix );
05960 
05961     stopAutoScroll();
05962     if(drag)
05963       drag->drag();
05964 
05965     // when we finish our drag, we need to undo our mouse press
05966     d->m_bMousePressed = false;
05967     d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
05968     return;
05969   }
05970 #endif
05971 
05972   // Not clicked -> mouse over stuff
05973   if ( !d->m_bMousePressed )
05974   {
05975     // The mouse is over something
05976     if ( url.length() )
05977     {
05978       bool shiftPressed = ( _mouse->state() & ShiftButton );
05979 
05980       // Image map
05981       if ( !innerNode.isNull() && innerNode.elementId() == ID_IMG )
05982       {
05983         HTMLImageElementImpl *i = static_cast<HTMLImageElementImpl *>(innerNode.handle());
05984         if ( i && i->isServerMap() )
05985         {
05986           khtml::RenderObject *r = i->renderer();
05987           if(r)
05988           {
05989             int absx, absy, vx, vy;
05990             r->absolutePosition(absx, absy);
05991             view()->contentsToViewport( absx, absy, vx, vy );
05992 
05993             int x(_mouse->x() - vx), y(_mouse->y() - vy);
05994 
05995             d->m_overURL = url.string() + QString("?%1,%2").arg(x).arg(y);
05996             d->m_overURLTarget = target.string();
05997             overURL( d->m_overURL, target.string(), shiftPressed );
05998             return;
05999           }
06000         }
06001       }
06002 
06003       // normal link
06004       if ( d->m_overURL.isEmpty() || d->m_overURL != url || d->m_overURLTarget != target )
06005       {
06006         d->m_overURL = url.string();
06007         d->m_overURLTarget = target.string();
06008         overURL( d->m_overURL, target.string(), shiftPressed );
06009       }
06010     }
06011     else  // Not over a link...
06012     {
06013       if( !d->m_overURL.isEmpty() ) // and we were over a link  -> reset to "default statusbar text"
06014       {
06015         d->m_overURL = d->m_overURLTarget = QString::null;
06016         emit onURL( QString::null );
06017         // revert to default statusbar text
06018         setStatusBarText(QString::null, BarHoverText);
06019         emit d->m_extension->mouseOverInfo(0);
06020      }
06021     }
06022   }
06023   else {
06024 #ifndef KHTML_NO_SELECTION
06025     // selection stuff
06026     if( d->m_bMousePressed && innerNode.handle() && innerNode.handle()->renderer() &&
06027         ( (_mouse->state() & LeftButton) != 0 )) {
06028       extendSelectionTo(event->x(), event->y(),
06029                         event->absX(), event->absY(), innerNode);
06030 #else
06031       if ( d->m_doc && d->m_view ) {
06032         QPoint diff( _mouse->globalPos() - d->m_dragLastPos );
06033 
06034         if ( abs( diff.x() ) > 64 || abs( diff.y() ) > 64 ) {
06035           d->m_view->scrollBy( -diff.x(), -diff.y() );
06036           d->m_dragLastPos = _mouse->globalPos();
06037         }
06038 #endif
06039     }
06040   }
06041 
06042 }
06043 
06044 void KHTMLPart::khtmlMouseReleaseEvent( khtml::MouseReleaseEvent *event )
06045 {
06046   DOM::Node innerNode = event->innerNode();
06047   d->m_mousePressNode = DOM::Node();
06048 
06049   if ( d->m_bMousePressed ) {
06050     setStatusBarText(QString::null, BarHoverText);
06051     stopAutoScroll();
06052   }
06053 
06054   // Used to prevent mouseMoveEvent from initiating a drag before
06055   // the mouse is pressed again.
06056   d->m_bMousePressed = false;
06057 
06058   QMouseEvent *_mouse = event->qmouseEvent();
06059   if ( _mouse->button() == RightButton && parentPart() != 0 && d->m_bBackRightClick )
06060   {
06061     d->m_bRightMousePressed = false;
06062     KParts::BrowserInterface *tmp_iface = d->m_extension->browserInterface();
06063     if( tmp_iface ) {
06064       tmp_iface->callMethod( "goHistory(int)", -1 );
06065     }
06066   }
06067 #ifndef QT_NO_CLIPBOARD
06068   if ((d->m_guiProfile == BrowserViewGUI) && (_mouse->button() == MidButton) && (event->url().isNull())) {
06069     kdDebug( 6050 ) << "KHTMLPart::khtmlMouseReleaseEvent() MMB shouldOpen="
06070                     << d->m_bOpenMiddleClick << endl;
06071 
06072     if (d->m_bOpenMiddleClick) {
06073     KHTMLPart *p = this;
06074     while (p->parentPart()) p = p->parentPart();
06075     p->d->m_extension->pasteRequest();
06076   }
06077   }
06078 #endif
06079 
06080 #ifndef KHTML_NO_SELECTION
06081   // delete selection in case start and end position are at the same point
06082   if(d->m_selectionStart == d->m_selectionEnd && d->m_startOffset == d->m_endOffset) {
06083 #ifndef KHTML_NO_CARET
06084     d->m_extendAtEnd = true;
06085 #else
06086     d->m_selectionStart = 0;
06087     d->m_selectionEnd = 0;
06088     d->m_startOffset = 0;
06089     d->m_endOffset = 0;
06090 #endif
06091     emitSelectionChanged();
06092   } else {
06093     // we have to get to know if end is before start or not...
06094 //     kdDebug(6000) << "rel: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << endl;
06095     DOM::Node n = d->m_selectionStart;
06096     d->m_startBeforeEnd = false;
06097     if( d->m_selectionStart == d->m_selectionEnd ) {
06098       if( d->m_startOffset < d->m_endOffset )
06099         d->m_startBeforeEnd = true;
06100     } else {
06101 #if 0
06102       while(!n.isNull()) {
06103         if(n == d->m_selectionEnd) {
06104           d->m_startBeforeEnd = true;
06105           break;
06106         }
06107         DOM::Node next = n.firstChild();
06108         if(next.isNull()) next = n.nextSibling();
06109         while( next.isNull() && !n.parentNode().isNull() ) {
06110           n = n.parentNode();
06111           next = n.nextSibling();
06112         }
06113         n = next;
06114       }
06115 #else
06116       // shouldn't be null but it can happen with dynamic updating of nodes
06117       if (d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() ||
06118           !d->m_selectionStart.handle()->renderer() ||
06119           !d->m_selectionEnd.handle()->renderer()) return;
06120       d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
06121                 d->m_selectionStart.handle(), d->m_startOffset,
06122             d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
06123 #endif
06124     }
06125     if(!d->m_startBeforeEnd)
06126     {
06127       DOM::Node tmpNode = d->m_selectionStart;
06128       int tmpOffset = d->m_startOffset;
06129       d->m_selectionStart = d->m_selectionEnd;
06130       d->m_startOffset = d->m_endOffset;
06131       d->m_selectionEnd = tmpNode;
06132       d->m_endOffset = tmpOffset;
06133       d->m_startBeforeEnd = true;
06134       d->m_extendAtEnd = !d->m_extendAtEnd;
06135     }
06136 #ifndef KHTML_NO_CARET
06137     bool v = d->m_view->placeCaret();
06138     emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
06139 #endif
06140     // get selected text and paste to the clipboard
06141 #ifndef QT_NO_CLIPBOARD
06142     QString text = selectedText();
06143     text.replace(QChar(0xa0), ' ');
06144     disconnect( kapp->clipboard(), SIGNAL( selectionChanged()), this, SLOT( slotClearSelection()));
06145     kapp->clipboard()->setText(text,QClipboard::Selection);
06146     connect( kapp->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection()));
06147 #endif
06148     //kdDebug( 6000 ) << "selectedText = " << text << endl;
06149     emitSelectionChanged();
06150 //kdDebug(6000) << "rel2: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << "), caretOfs " << d->caretOffset() << endl;
06151   }
06152 #endif
06153   d->m_initialNode = 0;     // don't hold nodes longer than necessary
06154   d->m_initialOffset = 0;
06155 
06156 }
06157 
06158 void KHTMLPart::khtmlDrawContentsEvent( khtml::DrawContentsEvent * )
06159 {
06160 }
06161 
06162 void KHTMLPart::guiActivateEvent( KParts::GUIActivateEvent *event )
06163 {
06164   if ( event->activated() )
06165   {
06166     emitSelectionChanged();
06167     emit d->m_extension->enableAction( "print", d->m_doc != 0 );
06168 
06169     if ( !d->m_settings->autoLoadImages() && d->m_paLoadImages )
06170     {
06171         QPtrList<KAction> lst;
06172         lst.append( d->m_paLoadImages );
06173         plugActionList( "loadImages", lst );
06174     }
06175   }
06176 }
06177 
06178 void KHTMLPart::slotPrintFrame()
06179 {
06180   if ( d->m_frames.count() == 0 )
06181     return;
06182 
06183   KParts::ReadOnlyPart *frame = currentFrame();
06184   if (!frame)
06185     return;
06186 
06187   KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject( frame );
06188 
06189   if ( !ext )
06190     return;
06191 
06192   QMetaObject *mo = ext->metaObject();
06193 
06194   int idx = mo->findSlot( "print()", true );
06195   if ( idx >= 0 ) {
06196     QUObject o[ 1 ];
06197     ext->qt_invoke( idx, o );
06198   }
06199 }
06200 
06201 void KHTMLPart::slotSelectAll()
06202 {
06203   KParts::ReadOnlyPart *part = currentFrame();
06204   if (part && part->inherits("KHTMLPart"))
06205     static_cast<KHTMLPart *>(part)->selectAll();
06206 }
06207 
06208 void KHTMLPart::startAutoScroll()
06209 {
06210    connect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
06211    d->m_scrollTimer.start(100, false);
06212 }
06213 
06214 void KHTMLPart::stopAutoScroll()
06215 {
06216    disconnect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
06217    if (d->m_scrollTimer.isActive())
06218        d->m_scrollTimer.stop();
06219 }
06220 
06221 
06222 void KHTMLPart::slotAutoScroll()
06223 {
06224     if (d->m_view)
06225       d->m_view->doAutoScroll();
06226     else
06227       stopAutoScroll(); // Safety
06228 }
06229 
06230 void KHTMLPart::selectAll()
06231 {
06232   if (!d->m_doc) return;
06233 
06234   NodeImpl *first;
06235   if (d->m_doc->isHTMLDocument())
06236     first = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
06237   else
06238     first = d->m_doc;
06239   NodeImpl *next;
06240 
06241   // Look for first text/cdata node that has a renderer,
06242   // or first childless replaced element
06243   while ( first && !(first->renderer()
06244     && ((first->nodeType() == Node::TEXT_NODE || first->nodeType() == Node::CDATA_SECTION_NODE)
06245         || (first->renderer()->isReplaced() && !first->renderer()->firstChild()))))
06246   {
06247     next = first->firstChild();
06248     if ( !next ) next = first->nextSibling();
06249     while( first && !next )
06250     {
06251       first = first->parentNode();
06252       if ( first )
06253         next = first->nextSibling();
06254     }
06255     first = next;
06256   }
06257 
06258   NodeImpl *last;
06259   if (d->m_doc->isHTMLDocument())
06260     last = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
06261   else
06262     last = d->m_doc;
06263   // Look for last text/cdata node that has a renderer,
06264   // or last childless replaced element
06265   // ### Instead of changing this loop, use findLastSelectableNode
06266   // in render_table.cpp (LS)
06267   while ( last && !(last->renderer()
06268     && ((last->nodeType() == Node::TEXT_NODE || last->nodeType() == Node::CDATA_SECTION_NODE)
06269         || (last->renderer()->isReplaced() && !last->renderer()->lastChild()))))
06270   {
06271     next = last->lastChild();
06272     if ( !next ) next = last->previousSibling();
06273     while ( last && !next )
06274     {
06275       last = last->parentNode();
06276       if ( last )
06277         next = last->previousSibling();
06278     }
06279     last = next;
06280   }
06281 
06282   if ( !first || !last )
06283     return;
06284   Q_ASSERT(first->renderer());
06285   Q_ASSERT(last->renderer());
06286   d->m_selectionStart = first;
06287   d->m_startOffset = 0;
06288   d->m_selectionEnd = last;
06289   d->m_endOffset = last->nodeValue().length();
06290   d->m_startBeforeEnd = true;
06291 
06292   d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
06293                           d->m_selectionEnd.handle(), d->m_endOffset );
06294 
06295   emitSelectionChanged();
06296 }
06297 
06298 bool KHTMLPart::checkLinkSecurity(const KURL &linkURL,const QString &message, const QString &button)
06299 {
06300   bool linkAllowed = true;
06301 
06302   if ( d->m_doc )
06303     linkAllowed = kapp && kapp->authorizeURLAction("redirect", url(), linkURL);
06304 
06305   if ( !linkAllowed ) {
06306     khtml::Tokenizer *tokenizer = d->m_doc->tokenizer();
06307     if (tokenizer)
06308       tokenizer->setOnHold(true);
06309 
06310     int response = KMessageBox::Cancel;
06311     if (!message.isEmpty())
06312     {
06313         response = KMessageBox::warningContinueCancel( 0,
06314                                message.arg(linkURL.htmlURL()),
06315                                i18n( "Security Warning" ),
06316                                button);
06317     }
06318     else
06319     {
06320         KMessageBox::error( 0,
06321                 i18n( "<qt>Access by untrusted page to<BR><B>%1</B><BR> denied.").arg(linkURL.htmlURL()),
06322                 i18n( "Security Alert" ));
06323     }
06324 
06325     if (tokenizer)
06326        tokenizer->setOnHold(false);
06327     return (response==KMessageBox::Continue);
06328   }
06329   return true;
06330 }
06331 
06332 void KHTMLPart::slotPartRemoved( KParts::Part *part )
06333 {
06334 //    kdDebug(6050) << "KHTMLPart::slotPartRemoved " << part << endl;
06335     if ( part == d->m_activeFrame )
06336     {
06337         d->m_activeFrame = 0L;
06338         if ( !part->inherits( "KHTMLPart" ) )
06339         {
06340             if (factory()) {
06341                 factory()->removeClient( part );
06342             }
06343             if (childClients()->containsRef(part)) {
06344                 removeChildClient( part );
06345             }
06346         }
06347     }
06348 }
06349 
06350 void KHTMLPart::slotActiveFrameChanged( KParts::Part *part )
06351 {
06352 //    kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged part=" << part << endl;
06353     if ( part == this )
06354     {
06355         kdError(6050) << "strange error! we activated ourselves" << endl;
06356         assert( false );
06357         return;
06358     }
06359 //    kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged d->m_activeFrame=" << d->m_activeFrame << endl;
06360     if ( d->m_activeFrame && d->m_activeFrame->widget() && d->m_activeFrame->widget()->inherits( "QFrame" ) )
06361     {
06362         QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() );
06363         if (frame->frameStyle() != QFrame::NoFrame)
06364         {
06365            frame->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken);
06366            frame->repaint();
06367         }
06368     }
06369 
06370     if( d->m_activeFrame && !d->m_activeFrame->inherits( "KHTMLPart" ) )
06371     {
06372         if (factory()) {
06373             factory()->removeClient( d->m_activeFrame );
06374         }
06375         removeChildClient( d->m_activeFrame );
06376     }
06377     if( part && !part->inherits( "KHTMLPart" ) )
06378     {
06379         if (factory()) {
06380             factory()->addClient( part );
06381         }
06382         insertChildClient( part );
06383     }
06384 
06385 
06386     d->m_activeFrame = part;
06387 
06388     if ( d->m_activeFrame && d->m_activeFrame->widget()->inherits( "QFrame" ) )
06389     {
06390         QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() );
06391         if (frame->frameStyle() != QFrame::NoFrame)
06392         {
06393            frame->setFrameStyle( QFrame::StyledPanel | QFrame::Plain);
06394            frame->repaint();
06395         }
06396         kdDebug(6050) << "new active frame " << d->m_activeFrame << endl;
06397     }
06398 
06399     updateActions();
06400 
06401     // (note: childObject returns 0 if the argument is 0)
06402     d->m_extension->setExtensionProxy( KParts::BrowserExtension::childObject( d->m_activeFrame ) );
06403 }
06404 
06405 void KHTMLPart::setActiveNode(const DOM::Node &node)
06406 {
06407     if (!d->m_doc || !d->m_view)
06408         return;
06409 
06410     // Set the document's active node
06411     d->m_doc->setFocusNode(node.handle());
06412 
06413     // Scroll the view if necessary to ensure that the new focus node is visible
06414     QRect rect  = node.handle()->getRect();
06415     d->m_view->ensureVisible(rect.right(), rect.bottom());
06416     d->m_view->ensureVisible(rect.left(), rect.top());
06417 }
06418 
06419 DOM::Node KHTMLPart::activeNode() const
06420 {
06421     return DOM::Node(d->m_doc?d->m_doc->focusNode():0);
06422 }
06423 
06424 DOM::EventListener *KHTMLPart::createHTMLEventListener( QString code, QString name )
06425 {
06426   KJSProxy *proxy = jScript();
06427 
06428   if (!proxy)
06429     return 0;
06430 
06431   return proxy->createHTMLEventHandler( m_url.url(), name, code );
06432 }
06433 
06434 KHTMLPart *KHTMLPart::opener()
06435 {
06436     return d->m_opener;
06437 }
06438 
06439 void KHTMLPart::setOpener(KHTMLPart *_opener)
06440 {
06441     d->m_opener = _opener;
06442 }
06443 
06444 bool KHTMLPart::openedByJS()
06445 {
06446     return d->m_openedByJS;
06447 }
06448 
06449 void KHTMLPart::setOpenedByJS(bool _openedByJS)
06450 {
06451     d->m_openedByJS = _openedByJS;
06452 }
06453 
06454 void KHTMLPart::preloadStyleSheet(const QString &url, const QString &stylesheet)
06455 {
06456     khtml::Cache::preloadStyleSheet(url, stylesheet);
06457 }
06458 
06459 void KHTMLPart::preloadScript(const QString &url, const QString &script)
06460 {
06461     khtml::Cache::preloadScript(url, script);
06462 }
06463 
06464 QCString KHTMLPart::dcopObjectId() const
06465 {
06466   QCString id;
06467   id.sprintf("html-widget%d", d->m_dcop_counter);
06468   return id;
06469 }
06470 
06471 long KHTMLPart::cacheId() const
06472 {
06473   return d->m_cacheId;
06474 }
06475 
06476 bool KHTMLPart::restored() const
06477 {
06478   return d->m_restored;
06479 }
06480 
06481 bool KHTMLPart::pluginPageQuestionAsked(const QString& mimetype) const
06482 {
06483   // parentPart() should be const!
06484   KHTMLPart* parent = const_cast<KHTMLPart *>(this)->parentPart();
06485   if ( parent )
06486     return parent->pluginPageQuestionAsked(mimetype);
06487 
06488   return d->m_pluginPageQuestionAsked.contains(mimetype);
06489 }
06490 
06491 void KHTMLPart::setPluginPageQuestionAsked(const QString& mimetype)
06492 {
06493   if ( parentPart() )
06494     parentPart()->setPluginPageQuestionAsked(mimetype);
06495 
06496   d->m_pluginPageQuestionAsked.append(mimetype);
06497 }
06498 
06499 void KHTMLPart::slotAutomaticDetectionLanguage( int _id )
06500 {
06501   d->m_automaticDetection->setItemChecked( _id, true );
06502 
06503   switch ( _id ) {
06504     case 0 :
06505       d->m_autoDetectLanguage = khtml::Decoder::SemiautomaticDetection;
06506       break;
06507     case 1 :
06508       d->m_autoDetectLanguage = khtml::Decoder::Arabic;
06509       break;
06510     case 2 :
06511       d->m_autoDetectLanguage = khtml::Decoder::Baltic;
06512       break;
06513     case 3 :
06514       d->m_autoDetectLanguage = khtml::Decoder::CentralEuropean;
06515       break;
06516     case 4 :
06517       d->m_autoDetectLanguage = khtml::Decoder::Chinese;
06518       break;
06519     case 5 :
06520       d->m_autoDetectLanguage = khtml::Decoder::Greek;
06521       break;
06522     case 6 :
06523       d->m_autoDetectLanguage = khtml::Decoder::Hebrew;
06524       break;
06525     case 7 :
06526       d->m_autoDetectLanguage = khtml::Decoder::Japanese;
06527       break;
06528     case 8 :
06529       d->m_autoDetectLanguage = khtml::Decoder::Korean;
06530       break;
06531     case 9 :
06532       d->m_autoDetectLanguage = khtml::Decoder::Russian;
06533       break;
06534     case 10 :
06535       d->m_autoDetectLanguage = khtml::Decoder::Thai;
06536       break;
06537     case 11 :
06538       d->m_autoDetectLanguage = khtml::Decoder::Turkish;
06539       break;
06540     case 12 :
06541       d->m_autoDetectLanguage = khtml::Decoder::Ukrainian;
06542       break;
06543     case 13 :
06544       d->m_autoDetectLanguage = khtml::Decoder::Unicode;
06545       break;
06546     case 14 :
06547       d->m_autoDetectLanguage = khtml::Decoder::WesternEuropean;
06548       break;
06549     default :
06550       d->m_autoDetectLanguage = khtml::Decoder::SemiautomaticDetection;
06551       break;
06552   }
06553 
06554   for ( int i = 0; i <= 14; ++i ) {
06555     if ( i != _id )
06556       d->m_automaticDetection->setItemChecked( i, false );
06557   }
06558 
06559   d->m_paSetEncoding->popupMenu()->setItemChecked( 0, true );
06560 
06561   setEncoding( QString::null, false );
06562 
06563   if( d->m_manualDetection )
06564     d->m_manualDetection->setCurrentItem( -1 );
06565   d->m_paSetEncoding->popupMenu()->setItemChecked( d->m_paSetEncoding->popupMenu()->idAt( 2 ), false );
06566 }
06567 
06568 khtml::Decoder *KHTMLPart::createDecoder()
06569 {
06570   khtml::Decoder *dec = new khtml::Decoder();
06571   if( !d->m_encoding.isNull() )
06572     dec->setEncoding( d->m_encoding.latin1(), true );
06573   else
06574     dec->setEncoding( defaultEncoding().latin1(), d->m_haveEncoding );
06575 
06576   dec->setAutoDetectLanguage( d->m_autoDetectLanguage );
06577   return dec;
06578 }
06579 
06580 void KHTMLPart::emitCaretPositionChanged(const DOM::Node &node, long offset) {
06581   emit caretPositionChanged(node, offset);
06582 }
06583 
06584 void KHTMLPart::restoreScrollPosition()
06585 {
06586   KParts::URLArgs args = d->m_extension->urlArgs();
06587 
06588   if ( m_url.hasRef() && !d->m_restoreScrollPosition && !args.reload) {
06589     if ( !d->m_doc || !d->m_doc->parsing() )
06590       disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
06591     if ( !gotoAnchor(m_url.encodedHtmlRef()) )
06592       gotoAnchor(m_url.htmlRef());
06593     return;
06594   }
06595   
06596   // Check whether the viewport has become large enough to encompass the stored
06597   // offsets. If the document has been fully loaded, force the new coordinates,
06598   // even if the canvas is too short (can happen when user resizes the window
06599   // during loading).
06600   if (d->m_view->contentsHeight() - d->m_view->visibleHeight() >= args.yOffset
06601       || d->m_bComplete) {
06602     d->m_view->setContentsPos(args.xOffset, args.yOffset);
06603     disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
06604   }  
06605 }
06606 
06607 
06608 void KHTMLPart::openWallet(DOM::HTMLFormElementImpl *form)
06609 {
06610   KHTMLPart *p;
06611 
06612   for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
06613   }
06614 
06615   if (p) {
06616     p->openWallet(form);
06617     return;
06618   }
06619 
06620   if (onlyLocalReferences()) { // avoid triggering on local apps, thumbnails
06621     return;
06622   }
06623 
06624   if (d->m_wallet) {
06625     if (d->m_bWalletOpened) {
06626       if (d->m_wallet->isOpen()) {
06627         form->walletOpened(d->m_wallet);
06628         return;
06629       }
06630       d->m_wallet->deleteLater();
06631       d->m_wallet = 0L;
06632       d->m_bWalletOpened = false;
06633     }
06634   }
06635 
06636   if (!d->m_wq) {
06637     KWallet::Wallet *wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0, KWallet::Wallet::Asynchronous);
06638     d->m_wq = new KHTMLWalletQueue(this);
06639     d->m_wq->wallet = wallet;
06640     connect(wallet, SIGNAL(walletOpened(bool)), d->m_wq, SLOT(walletOpened(bool)));
06641     connect(d->m_wq, SIGNAL(walletOpened(KWallet::Wallet*)), this, SLOT(walletOpened(KWallet::Wallet*)));
06642   }
06643   assert(form);
06644   d->m_wq->callers.append(KHTMLWalletQueue::Caller(form, form->getDocument()));
06645 }
06646 
06647 
06648 void KHTMLPart::saveToWallet(const QString& key, const QMap<QString,QString>& data)
06649 {
06650   KHTMLPart *p;
06651 
06652   for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
06653   }
06654 
06655   if (p) {
06656     p->saveToWallet(key, data);
06657     return;
06658   }
06659 
06660   if (d->m_wallet) {
06661     if (d->m_bWalletOpened) {
06662       if (d->m_wallet->isOpen()) {
06663         if (!d->m_wallet->hasFolder(KWallet::Wallet::FormDataFolder())) {
06664           d->m_wallet->createFolder(KWallet::Wallet::FormDataFolder());
06665         }
06666         d->m_wallet->setFolder(KWallet::Wallet::FormDataFolder());
06667         d->m_wallet->writeMap(key, data);
06668         return;
06669       }
06670       d->m_wallet->deleteLater();
06671       d->m_wallet = 0L;
06672       d->m_bWalletOpened = false;
06673     }
06674   }
06675 
06676   if (!d->m_wq) {
06677     KWallet::Wallet *wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0, KWallet::Wallet::Asynchronous);
06678     d->m_wq = new KHTMLWalletQueue(this);
06679     d->m_wq->wallet = wallet;
06680     connect(wallet, SIGNAL(walletOpened(bool)), d->m_wq, SLOT(walletOpened(bool)));
06681     connect(d->m_wq, SIGNAL(walletOpened(KWallet::Wallet*)), this, SLOT(walletOpened(KWallet::Wallet*)));
06682   }
06683   d->m_wq->savers.append(qMakePair(key, data));
06684 }
06685 
06686 
06687 void KHTMLPart::dequeueWallet(DOM::HTMLFormElementImpl *form) {
06688   KHTMLPart *p;
06689 
06690   for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
06691   }
06692 
06693   if (p) {
06694     p->dequeueWallet(form);
06695     return;
06696   }
06697 
06698   if (d->m_wq) {
06699     d->m_wq->callers.remove(KHTMLWalletQueue::Caller(form, form->getDocument()));
06700   }
06701 }
06702 
06703 
06704 void KHTMLPart::walletOpened(KWallet::Wallet *wallet) {
06705   assert(!d->m_wallet);
06706   assert(d->m_wq);
06707 
06708   d->m_wq->deleteLater(); // safe?
06709   d->m_wq = 0L;
06710 
06711   if (!wallet) {
06712     d->m_bWalletOpened = false;
06713     return;
06714   }
06715 
06716   d->m_wallet = wallet;
06717   d->m_bWalletOpened = true;
06718   connect(d->m_wallet, SIGNAL(walletClosed()), SLOT(slotWalletClosed()));
06719 
06720   if (!d->m_statusBarWalletLabel) {
06721     d->m_statusBarWalletLabel = new KURLLabel(d->m_statusBarExtension->statusBar());
06722     d->m_statusBarWalletLabel->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small));
06723     d->m_statusBarWalletLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
06724     d->m_statusBarWalletLabel->setUseCursor(false);
06725     d->m_statusBarExtension->addStatusBarItem(d->m_statusBarWalletLabel, 0, false);
06726     d->m_statusBarWalletLabel->setPixmap(SmallIcon("wallet_open", instance()));
06727     connect(d->m_statusBarWalletLabel, SIGNAL(leftClickedURL()), SLOT(launchWalletManager()));
06728     connect(d->m_statusBarWalletLabel, SIGNAL(rightClickedURL()), SLOT(walletMenu()));
06729   } else {
06730     QToolTip::remove(d->m_statusBarWalletLabel);
06731   }
06732   QToolTip::add(d->m_statusBarWalletLabel, i18n("The wallet '%1' is open and being used for form data and passwords.").arg(KWallet::Wallet::NetworkWallet()));
06733 }
06734 
06735 
06736 KWallet::Wallet *KHTMLPart::wallet()
06737 {
06738   KHTMLPart *p;
06739 
06740   for (p = parentPart(); p && p->parentPart(); p = p->parentPart())
06741     ;
06742 
06743   if (p)
06744     return p->wallet();
06745 
06746   return d->m_wallet;
06747 }
06748 
06749 
06750 void KHTMLPart::slotWalletClosed()
06751 {
06752   if (d->m_wallet) {
06753     d->m_wallet->deleteLater();
06754     d->m_wallet = 0L;
06755   }
06756   d->m_bWalletOpened = false;
06757   if (d->m_statusBarWalletLabel) {
06758     d->m_statusBarExtension->removeStatusBarItem(d->m_statusBarWalletLabel);
06759     delete d->m_statusBarWalletLabel;
06760     d->m_statusBarWalletLabel = 0L;
06761   }
06762 }
06763 
06764 void KHTMLPart::launchWalletManager()
06765 {
06766   if (!DCOPClient::mainClient()->isApplicationRegistered("kwalletmanager")) {
06767     KApplication::startServiceByDesktopName("kwalletmanager_show");
06768   } else {
06769     DCOPRef r("kwalletmanager", "kwalletmanager-mainwindow#1");
06770     r.send("show");
06771     r.send("raise");
06772   }
06773 }
06774 
06775 void KHTMLPart::walletMenu()
06776 {
06777   KPopupMenu *m = new KPopupMenu(0L);
06778   m->insertItem(i18n("&Close Wallet"), this, SLOT(slotWalletClosed()));
06779   m->popup(QCursor::pos());
06780 }
06781 
06782 void KHTMLPart::slotToggleCaretMode()
06783 {
06784   setCaretMode(d->m_paToggleCaretMode->isChecked());
06785 }
06786 
06787 void KHTMLPart::setFormNotification(KHTMLPart::FormNotification fn) {
06788   d->m_formNotification = fn;
06789 }
06790 
06791 KHTMLPart::FormNotification KHTMLPart::formNotification() const {
06792   return d->m_formNotification;
06793 }
06794 
06795 KURL KHTMLPart::toplevelURL()
06796 {
06797   KHTMLPart* part = this;
06798   while (part->parentPart())
06799     part = part->parentPart();
06800 
06801   if (!part)
06802     return KURL();
06803 
06804   return part->url();
06805 }
06806 
06807 bool KHTMLPart::isModified() const
06808 {
06809   if ( !d->m_doc )
06810     return false;
06811 
06812   return d->m_doc->unsubmittedFormChanges();
06813 }
06814 
06815 void KHTMLPart::setDebugScript( bool enable )
06816 {
06817   unplugActionList( "debugScriptList" );
06818   if ( enable ) {
06819     if (!d->m_paDebugScript) {
06820       d->m_paDebugScript = new KAction( i18n( "JavaScript &Debugger" ), 0, this, SLOT( slotDebugScript() ), actionCollection(), "debugScript" );
06821     }
06822     d->m_paDebugScript->setEnabled( d->m_frame ? d->m_frame->m_jscript : 0L );
06823     QPtrList<KAction> lst;
06824     lst.append( d->m_paDebugScript );
06825     plugActionList( "debugScriptList", lst );
06826   }
06827   d->m_bJScriptDebugEnabled = enable;
06828 }
06829 
06830 using namespace KParts;
06831 #include "khtml_part.moc"
06832 #include "khtmlpart_p.moc"
KDE Logo
This file is part of the documentation for khtml Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun Jan 15 13:34:43 2006 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003