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