• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KHTML

khtml_part.cpp

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

KHTML

Skip menu "KHTML"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal