• 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   url = Qt::escape( reqUrl.prettyUrl() );
01857   protocol = reqUrl.protocol();
01858   datetime = KGlobal::locale()->formatDateTime( QDateTime::currentDateTime(),
01859                                                 KLocale::LongDate );
01860 
01861   QString filename( KStandardDirs::locate( "data", "khtml/error.html" ) );
01862   QFile file( filename );
01863   bool isOpened = file.open( QIODevice::ReadOnly );
01864   if ( !isOpened )
01865     kWarning(6050) << "Could not open error html template:" << filename;
01866 
01867   QString html = QString( QLatin1String( file.readAll() ) );
01868 
01869   html.replace( QLatin1String( "TITLE" ), i18n( "Error: %1 - %2", errorName, url ) );
01870   html.replace( QLatin1String( "DIRECTION" ), QApplication::isRightToLeft() ? "rtl" : "ltr" );
01871   html.replace( QLatin1String( "ICON_PATH" ), KIconLoader::global()->iconPath( "dialog-warning", -KIconLoader::SizeHuge ) );
01872 
01873   QString doc = QLatin1String( "<h1>" );
01874   doc += i18n( "The requested operation could not be completed" );
01875   doc += QLatin1String( "</h1><h2>" );
01876   doc += errorName;
01877   doc += QLatin1String( "</h2>" );
01878   if ( !techName.isNull() ) {
01879     doc += QLatin1String( "<h2>" );
01880     doc += i18n( "Technical Reason: " );
01881     doc += techName;
01882     doc += QLatin1String( "</h2>" );
01883   }
01884   doc += QLatin1String( "<h3>" );
01885   doc += i18n( "Details of the Request:" );
01886   doc += QLatin1String( "</h3><ul><li>" );
01887   doc += i18n( "URL: %1" ,  url );
01888   doc += QLatin1String( "</li><li>" );
01889   if ( !protocol.isNull() ) {
01890     doc += i18n( "Protocol: %1", protocol );
01891     doc += QLatin1String( "</li><li>" );
01892   }
01893   doc += i18n( "Date and Time: %1" ,  datetime );
01894   doc += QLatin1String( "</li><li>" );
01895   doc += i18n( "Additional Information: %1" ,  text );
01896   doc += QLatin1String( "</li></ul><h3>" );
01897   doc += i18n( "Description:" );
01898   doc += QLatin1String( "</h3><p>" );
01899   doc += description;
01900   doc += QLatin1String( "</p>" );
01901   if ( causes.count() ) {
01902     doc += QLatin1String( "<h3>" );
01903     doc += i18n( "Possible Causes:" );
01904     doc += QLatin1String( "</h3><ul><li>" );
01905     doc += causes.join( "</li><li>" );
01906     doc += QLatin1String( "</li></ul>" );
01907   }
01908   if ( solutions.count() ) {
01909     doc += QLatin1String( "<h3>" );
01910     doc += i18n( "Possible Solutions:" );
01911     doc += QLatin1String( "</h3><ul><li>" );
01912     doc += solutions.join( "</li><li>" );
01913     doc += QLatin1String( "</li></ul>" );
01914   }
01915 
01916   html.replace( QLatin1String("TEXT"), doc );
01917 
01918   write( html );
01919   end();
01920 
01921   d->m_bJScriptForce = bJSFO;
01922   d->m_bJScriptOverride = bJSOO;
01923 
01924   // make the working url the current url, so that reload works and
01925   // emit the progress signals to advance one step in the history
01926   // (so that 'back' works)
01927   setUrl(reqUrl); // same as d->m_workingURL
01928   d->m_workingURL = KUrl();
01929   emit started( 0 );
01930   emit completed();
01931 }
01932 
01933 void KHTMLPart::slotFinished( KJob * job )
01934 {
01935   d->m_job = 0L;
01936   d->m_jobspeed = 0L;
01937 
01938   if (job->error())
01939   {
01940     KHTMLPageCache::self()->cancelEntry(d->m_cacheId);
01941 
01942     // The following catches errors that occur as a result of HTTP
01943     // to FTP redirections where the FTP URL is a directory. Since
01944     // KIO cannot change a redirection request from GET to LISTDIR,
01945     // we have to take care of it here once we know for sure it is
01946     // a directory...
01947     if (job->error() == KIO::ERR_IS_DIRECTORY)
01948     {
01949       emit canceled( job->errorString() );
01950       emit d->m_extension->openUrlRequest( d->m_workingURL );
01951     }
01952     else
01953     {
01954       emit canceled( job->errorString() );
01955       // TODO: what else ?
01956       checkCompleted();
01957       showError( job );
01958     }
01959 
01960     return;
01961   }
01962   KIO::TransferJob *tjob = ::qobject_cast<KIO::TransferJob*>(job);
01963   if (tjob && tjob->isErrorPage()) {
01964     HTMLPartContainerElementImpl *elt = d->m_frame ?
01965         (HTMLPartContainerElementImpl*)d->m_frame->m_partContainerElement : 0;
01966 
01967     if (!elt)
01968       return;
01969 
01970     elt->partLoadingErrorNotify();
01971     checkCompleted();
01972     if (d->m_bComplete) return;
01973   }
01974 
01975   //kDebug( 6050 ) << "slotFinished";
01976 
01977   KHTMLPageCache::self()->endData(d->m_cacheId);
01978   if (d->m_frame && d->m_frame->m_jscript)
01979     d->m_frame->m_jscript->dataReceived();
01980 
01981   if ( d->m_doc && d->m_doc->docLoader()->expireDate() && url().protocol().toLower().startsWith("http"))
01982       KIO::http_update_cache(url(), false, d->m_doc->docLoader()->expireDate());
01983 
01984   d->m_workingURL = KUrl();
01985 
01986   if ( d->m_doc && d->m_doc->parsing())
01987     end(); //will emit completed()
01988 }
01989 
01990 void KHTMLPart::begin( const KUrl &url, int xOffset, int yOffset )
01991 {
01992   if ( d->m_view->underMouse() )
01993     QToolTip::hideText();  // in case a previous tooltip is still shown
01994 
01995   // No need to show this for a new page until an error is triggered
01996   if (!parentPart()) {
01997     removeJSErrorExtension();
01998     setSuppressedPopupIndicator( false );
01999     d->m_openableSuppressedPopups = 0;
02000     foreach ( KHTMLPart* part, d->m_suppressedPopupOriginParts ) {
02001       if (part) {
02002         KJS::Window *w = KJS::Window::retrieveWindow( part );
02003         if (w)
02004           w->forgetSuppressedWindows();
02005       }
02006     }
02007   }
02008 
02009   d->m_bCleared = false;
02010   d->m_cacheId = 0;
02011   d->m_bComplete = false;
02012   d->m_bLoadEventEmitted = false;
02013   clear();
02014   d->m_bCleared = false;
02015 
02016   if(url.isValid()) {
02017       QString urlString = url.url();
02018       KHTMLGlobal::vLinks()->insert( urlString );
02019       QString urlString2 = url.prettyUrl();
02020       if ( urlString != urlString2 ) {
02021           KHTMLGlobal::vLinks()->insert( urlString2 );
02022       }
02023   }
02024 
02025   // ###
02026   //stopParser();
02027 
02028   KParts::OpenUrlArguments args = arguments();
02029   args.setXOffset(xOffset);
02030   args.setYOffset(yOffset);
02031   setArguments(args);
02032 
02033   d->m_pageReferrer.clear();
02034 
02035   KUrl ref(url);
02036   d->m_referrer = ref.protocol().startsWith("http") ? ref.url() : "";
02037 
02038   setUrl(url);
02039 
02040   bool servedAsXHTML = args.mimeType() == "application/xhtml+xml";
02041   bool servedAsSVG = !servedAsXHTML && args.mimeType() == "image/svg+xml";
02042   KMimeType::Ptr mime = KMimeType::mimeType( args.mimeType(), KMimeType::ResolveAliases );
02043         // We want to make sure text/xml and application/xml are both handled right...
02044   bool servedAsXML = mime && mime->is( "text/xml" );
02045   // ### not sure if XHTML documents served as text/xml should use DocumentImpl or HTMLDocumentImpl
02046   if ( servedAsSVG ) {
02047     d->m_doc = DOMImplementationImpl::instance()->createSVGDocument( d->m_view );
02048   } else {
02049     if ( servedAsXML && !servedAsXHTML ) { // any XML derivative, except XHTML
02050       d->m_doc = DOMImplementationImpl::instance()->createXMLDocument( d->m_view );
02051     } else {
02052       d->m_doc = DOMImplementationImpl::instance()->createHTMLDocument( d->m_view );
02053       // HTML or XHTML? (#86446)
02054       static_cast<HTMLDocumentImpl *>(d->m_doc)->setHTMLRequested( !servedAsXHTML );
02055     }
02056   }
02057 
02058   d->m_doc->ref();
02059   d->m_doc->setURL( url.url() );
02060   d->m_doc->open( );
02061   if (!d->m_doc->attached())
02062     d->m_doc->attach( );
02063   d->m_doc->setBaseURL( KUrl() );
02064   d->m_doc->docLoader()->setShowAnimations( KHTMLGlobal::defaultHTMLSettings()->showAnimations() );
02065   emit docCreated();
02066 
02067   d->m_paUseStylesheet->setItems(QStringList());
02068   d->m_paUseStylesheet->setEnabled( false );
02069 
02070   setAutoloadImages( KHTMLGlobal::defaultHTMLSettings()->autoLoadImages() );
02071   QString userStyleSheet = KHTMLGlobal::defaultHTMLSettings()->userStyleSheet();
02072   if ( !userStyleSheet.isEmpty() )
02073     setUserStyleSheet( KUrl( userStyleSheet ) );
02074 
02075   d->m_doc->setRestoreState(d->m_extension->browserArguments().docState);
02076   connect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
02077 
02078   emit d->m_extension->enableAction( "print", true );
02079 
02080   d->m_doc->setParsing(true);
02081 }
02082 
02083 void KHTMLPart::write( const char *data, int len )
02084 {
02085   if ( !d->m_decoder )
02086     d->m_decoder = createDecoder();
02087 
02088   if ( len == -1 )
02089     len = strlen( data );
02090 
02091   if ( len == 0 )
02092     return;
02093 
02094   QString decoded=d->m_decoder->decodeWithBuffering(data,len);
02095 
02096   if(decoded.isEmpty())
02097       return;
02098 
02099   if(d->m_bFirstData)
02100       onFirstData();
02101 
02102   khtml::Tokenizer* t = d->m_doc->tokenizer();
02103   if(t)
02104     t->write( decoded, true );
02105 }
02106 
02107 // ### KDE5: remove
02108 void KHTMLPart::setAlwaysHonourDoctype( bool b )
02109 {
02110     d->m_bStrictModeQuirk = !b;
02111 }
02112 
02113 void KHTMLPart::write( const QString &str )
02114 {
02115     if ( str.isNull() )
02116         return;
02117 
02118     if(d->m_bFirstData) {
02119             // determine the parse mode
02120         if (d->m_bStrictModeQuirk) {
02121             d->m_doc->setParseMode( DocumentImpl::Strict );
02122             d->m_bFirstData = false;
02123         } else {
02124             onFirstData();
02125         }
02126     }
02127     khtml::Tokenizer* t = d->m_doc->tokenizer();
02128     if(t)
02129         t->write( str, true );
02130 }
02131 
02132 void KHTMLPart::end()
02133 {
02134     if (d->m_doc) {
02135         if (d->m_decoder)
02136         {
02137             QString decoded=d->m_decoder->flush();
02138             if (d->m_bFirstData)
02139                 onFirstData();
02140             if (!decoded.isEmpty())
02141                 write(decoded);
02142         }
02143         d->m_doc->finishParsing();
02144     }
02145 }
02146 
02147 void KHTMLPart::onFirstData()
02148 {
02149       assert( d->m_bFirstData );
02150 
02151       // determine the parse mode
02152       d->m_doc->determineParseMode();
02153       d->m_bFirstData = false;
02154 
02155       // ### this is still quite hacky, but should work a lot better than the old solution
02156       // Note: decoder may be null if only write(QString) is used.
02157       if (d->m_decoder && d->m_decoder->visuallyOrdered())
02158           d->m_doc->setVisuallyOrdered();
02159       d->m_doc->recalcStyle( NodeImpl::Force );
02160 }
02161 
02162 bool KHTMLPart::doOpenStream( const QString& mimeType )
02163 {
02164     KMimeType::Ptr mime = KMimeType::mimeType(mimeType, KMimeType::ResolveAliases);
02165     if ( mime && ( mime->is( "text/html" ) || mime->is( "text/xml" ) ) )
02166     {
02167         begin( url() );
02168         return true;
02169     }
02170     return false;
02171 }
02172 
02173 bool KHTMLPart::doWriteStream( const QByteArray& data )
02174 {
02175     write( data.data(), data.size() );
02176     return true;
02177 }
02178 
02179 bool KHTMLPart::doCloseStream()
02180 {
02181     end();
02182     return true;
02183 }
02184 
02185 
02186 void KHTMLPart::paint(QPainter *p, const QRect &rc, int yOff, bool *more)
02187 {
02188     if (!d->m_view) return;
02189     d->m_view->paint(p, rc, yOff, more);
02190 }
02191 
02192 void KHTMLPart::stopAnimations()
02193 {
02194   if ( d->m_doc )
02195     d->m_doc->docLoader()->setShowAnimations( KHTMLSettings::KAnimationDisabled );
02196 
02197   ConstFrameIt it = d->m_frames.constBegin();
02198   const ConstFrameIt end = d->m_frames.constEnd();
02199   for (; it != end; ++it )
02200     if ( !(*it)->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
02201       KParts::ReadOnlyPart* const p = ( *it )->m_part;
02202       static_cast<KHTMLPart*>( p )->stopAnimations();
02203     }
02204 }
02205 
02206 void KHTMLPart::resetFromScript()
02207 {
02208     closeUrl();
02209     d->m_bComplete = false;
02210     d->m_bLoadEventEmitted = false;
02211     disconnect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
02212     connect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
02213     d->m_doc->setParsing(true);
02214 
02215     emit started( 0L );
02216 }
02217 
02218 void KHTMLPart::slotFinishedParsing()
02219 {
02220   d->m_doc->setParsing(false);
02221   d->m_doc->dispatchWindowEvent(EventImpl::KHTML_CONTENTLOADED_EVENT, false, false);
02222   checkEmitLoadEvent();
02223   disconnect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
02224 
02225   if (!d->m_view)
02226     return; // We are probably being destructed.
02227 
02228   checkCompleted();
02229 }
02230 
02231 void KHTMLPart::slotLoaderRequestStarted( khtml::DocLoader* dl, khtml::CachedObject *obj )
02232 {
02233   if ( obj && obj->type() == khtml::CachedObject::Image && d->m_doc && d->m_doc->docLoader() == dl ) {
02234     KHTMLPart* p = this;
02235     while ( p ) {
02236       KHTMLPart* const op = p;
02237       ++(p->d->m_totalObjectCount);
02238       p = p->parentPart();
02239       if ( !p && op->d->m_loadedObjects <= op->d->m_totalObjectCount
02240         && !op->d->m_progressUpdateTimer.isActive()) {
02241         op->d->m_progressUpdateTimer.setSingleShot( true );
02242         op->d->m_progressUpdateTimer.start( 200 );
02243       }
02244     }
02245   }
02246 }
02247 
02248 static bool isAncestorOrSamePart(KHTMLPart* p1, KHTMLPart* p2)
02249 {
02250     KHTMLPart* p = p2;
02251     do {
02252         if (p == p1)
02253             return true;
02254     } while ((p = p->parentPart()));
02255     return false;
02256 }
02257 
02258 void KHTMLPart::slotLoaderRequestDone( khtml::DocLoader* dl, khtml::CachedObject *obj )
02259 {
02260   if ( obj && obj->type() == khtml::CachedObject::Image && d->m_doc && d->m_doc->docLoader() == dl ) {
02261     KHTMLPart* p = this;
02262     while ( p ) {
02263       KHTMLPart* const op = p;
02264       ++(p->d->m_loadedObjects);
02265       p = p->parentPart();
02266       if ( !p && op->d->m_loadedObjects <= op->d->m_totalObjectCount && op->d->m_jobPercent <= 100
02267         && !op->d->m_progressUpdateTimer.isActive()) {
02268         op->d->m_progressUpdateTimer.setSingleShot( true );
02269         op->d->m_progressUpdateTimer.start( 200 );
02270       }
02271     }
02272   }
02274   //  then our loading state can't possibly be affected : don't waste time checking for completion.
02275   if (!d->m_doc || !dl->doc()->part() || !isAncestorOrSamePart(this, dl->doc()->part()))
02276       return;
02277   checkCompleted();
02278 }
02279 
02280 void KHTMLPart::slotProgressUpdate()
02281 {
02282   int percent;
02283   if ( d->m_loadedObjects < d->m_totalObjectCount )
02284     percent = d->m_jobPercent / 4 + ( d->m_loadedObjects*300 ) / ( 4*d->m_totalObjectCount );
02285   else
02286     percent = d->m_jobPercent;
02287 
02288   if( d->m_bComplete )
02289     percent = 100;
02290 
02291   if (d->m_statusMessagesEnabled) {
02292     if( d->m_bComplete )
02293       emit d->m_extension->infoMessage( i18n( "Page loaded." ));
02294     else if ( d->m_loadedObjects < d->m_totalObjectCount && percent >= 75 )
02295       emit d->m_extension->infoMessage( i18np( "%1 Image of %2 loaded.", "%1 Images of %2 loaded.", d->m_loadedObjects, d->m_totalObjectCount) );
02296   }
02297 
02298   emit d->m_extension->loadingProgress( percent );
02299 }
02300 
02301 void KHTMLPart::slotJobSpeed( KJob* /*job*/, unsigned long speed )
02302 {
02303   d->m_jobspeed = speed;
02304   if (!parentPart())
02305     setStatusBarText(jsStatusBarText(), BarOverrideText);
02306 }
02307 
02308 void KHTMLPart::slotJobPercent( KJob* /*job*/, unsigned long percent )
02309 {
02310   d->m_jobPercent = percent;
02311 
02312   if ( !parentPart() ) {
02313     d->m_progressUpdateTimer.setSingleShot( true );
02314     d->m_progressUpdateTimer.start( 0 );
02315   }
02316 }
02317 
02318 void KHTMLPart::slotJobDone( KJob* /*job*/ )
02319 {
02320   d->m_jobPercent = 100;
02321 
02322   if ( !parentPart() ) {
02323     d->m_progressUpdateTimer.setSingleShot( true );
02324     d->m_progressUpdateTimer.start( 0 );
02325   }
02326 }
02327 
02328 void KHTMLPart::slotUserSheetStatDone( KJob *_job )
02329 {
02330   using namespace KIO;
02331 
02332   if ( _job->error() ) {
02333     showError( _job );
02334     return;
02335   }
02336 
02337   const UDSEntry entry = dynamic_cast<KIO::StatJob *>( _job )->statResult();
02338   const time_t lastModified = entry.numberValue( KIO::UDSEntry::UDS_MODIFICATION_TIME, -1 );
02339 
02340   // If the filesystem supports modification times, only reload the
02341   // user-defined stylesheet if necessary - otherwise always reload.
02342   if ( lastModified != static_cast<time_t>(-1) ) {
02343     if ( d->m_userStyleSheetLastModified >= lastModified ) {
02344       return;
02345     }
02346     d->m_userStyleSheetLastModified = lastModified;
02347   }
02348 
02349   setUserStyleSheet( KUrl( settings()->userStyleSheet() ) );
02350 }
02351 
02352 void KHTMLPart::checkCompleted()
02353 {
02354 //   kDebug( 6050 ) << this;
02355 //   kDebug( 6050 ) << "   parsing: " << (d->m_doc && d->m_doc->parsing());
02356 //   kDebug( 6050 ) << "   complete: " << d->m_bComplete;
02357 
02358   // restore the cursor position
02359   if (d->m_doc && !d->m_doc->parsing() && !d->m_focusNodeRestored)
02360   {
02361       if (d->m_focusNodeNumber >= 0)
02362           d->m_doc->setFocusNode(d->m_doc->nodeWithAbsIndex(d->m_focusNodeNumber));
02363 
02364       d->m_focusNodeRestored = true;
02365   }
02366 
02367   bool bPendingChildRedirection = false;
02368   // Any frame that hasn't completed yet ?
02369   ConstFrameIt it = d->m_frames.constBegin();
02370   const ConstFrameIt end = d->m_frames.constEnd();
02371   for (; it != end; ++it ) {
02372     if ( !(*it)->m_bCompleted )
02373     {
02374       //kDebug( 6050 ) << this << " is waiting for " << (*it)->m_part;
02375       return;
02376     }
02377     // Check for frames with pending redirections
02378     if ( (*it)->m_bPendingRedirection )
02379       bPendingChildRedirection = true;
02380   }
02381 
02382   // Any object that hasn't completed yet ?
02383   {
02384     ConstFrameIt oi = d->m_objects.constBegin();
02385     const ConstFrameIt oiEnd = d->m_objects.constEnd();
02386 
02387     for (; oi != oiEnd; ++oi )
02388       if ( !(*oi)->m_bCompleted )
02389         return;
02390   }
02391 
02392   // Are we still parsing - or have we done the completed stuff already ?
02393   if ( d->m_bComplete || (d->m_doc && d->m_doc->parsing()) )
02394     return;
02395 
02396   // Still waiting for images/scripts from the loader ?
02397   int requests = 0;
02398   if ( d->m_doc && d->m_doc->docLoader() )
02399     requests = khtml::Cache::loader()->numRequests( d->m_doc->docLoader() );
02400 
02401   if ( requests > 0 )
02402   {
02403     //kDebug(6050) << "still waiting for images/scripts from the loader - requests:" << requests;
02404     return;
02405   }
02406 
02407   // OK, completed.
02408   // Now do what should be done when we are really completed.
02409   d->m_bComplete = true;
02410   d->m_cachePolicy = KProtocolManager::cacheControl(); // reset cache policy
02411   d->m_totalObjectCount = 0;
02412   d->m_loadedObjects = 0;
02413 
02414   KHTMLPart* p = this;
02415   while ( p ) {
02416     KHTMLPart* op = p;
02417     p = p->parentPart();
02418     if ( !p && !op->d->m_progressUpdateTimer.isActive()) {
02419       op->d->m_progressUpdateTimer.setSingleShot( true );
02420       op->d->m_progressUpdateTimer.start( 0 );
02421     }
02422   }
02423 
02424   checkEmitLoadEvent(); // if we didn't do it before
02425 
02426   bool pendingAction = false;
02427 
02428   if ( !d->m_redirectURL.isEmpty() )
02429   {
02430     // DA: Do not start redirection for frames here! That action is
02431     // deferred until the parent emits a completed signal.
02432     if ( parentPart() == 0 ) {
02433       //kDebug(6050) << this << " starting redirection timer";
02434       d->m_redirectionTimer.setSingleShot( true );
02435       d->m_redirectionTimer.start( qMax(0, 1000 * d->m_delayRedirect) );
02436     } else {
02437       //kDebug(6050) << this << " not toplevel -> not starting redirection timer. Waiting for slotParentCompleted.";
02438     }
02439 
02440     pendingAction = true;
02441   }
02442   else if ( bPendingChildRedirection )
02443   {
02444     pendingAction = true;
02445   }
02446 
02447   // the view will emit completed on our behalf,
02448   // either now or at next repaint if one is pending
02449 
02450   //kDebug(6050) << this << " asks the view to emit completed. pendingAction=" << pendingAction;
02451   d->m_view->complete( pendingAction );
02452 
02453   // find the alternate stylesheets
02454   QStringList sheets;
02455   if (d->m_doc)
02456      sheets = d->m_doc->availableStyleSheets();
02457   sheets.prepend( i18n( "Automatic Detection" ) );
02458   d->m_paUseStylesheet->setItems( sheets );
02459 
02460   d->m_paUseStylesheet->setEnabled( sheets.count() > 2);
02461   if (sheets.count() > 2)
02462   {
02463     d->m_paUseStylesheet->setCurrentItem(qMax(sheets.indexOf(d->m_sheetUsed), 0));
02464     slotUseStylesheet();
02465   }
02466 
02467   setJSDefaultStatusBarText(QString());
02468 
02469 #ifdef SPEED_DEBUG
02470   kDebug(6050) << "DONE: " <<d->m_parsetime.elapsed();
02471 #endif
02472 }
02473 
02474 void KHTMLPart::checkEmitLoadEvent()
02475 {
02476   if ( d->m_bLoadEventEmitted || !d->m_doc || d->m_doc->parsing() ) return;
02477 
02478   ConstFrameIt it = d->m_frames.constBegin();
02479   const ConstFrameIt end = d->m_frames.constEnd();
02480   for (; it != end; ++it )
02481     if ( !(*it)->m_bCompleted ) // still got a frame running -> too early
02482       return;
02483 
02484   ConstFrameIt oi = d->m_objects.constBegin();
02485   const ConstFrameIt oiEnd = d->m_objects.constEnd();
02486 
02487   for (; oi != oiEnd; ++oi )
02488     if ( !(*oi)->m_bCompleted ) // still got a object running -> too early
02489       return;
02490 
02491   // Still waiting for images/scripts from the loader ?
02492   // (onload must happen afterwards, #45607)
02493   // ## This makes this method very similar to checkCompleted. A brave soul should try merging them.
02494   int requests = 0;
02495   if ( d->m_doc && d->m_doc->docLoader() )
02496     requests = khtml::Cache::loader()->numRequests( d->m_doc->docLoader() );
02497 
02498   if ( requests > 0 )
02499     return;
02500 
02501   d->m_bLoadEventEmitted = true;
02502   if (d->m_doc)
02503     d->m_doc->close();
02504 }
02505 
02506 const KHTMLSettings *KHTMLPart::settings() const
02507 {
02508   return d->m_settings;
02509 }
02510 
02511 #ifndef KDE_NO_COMPAT
02512 KUrl KHTMLPart::baseURL() const
02513 {
02514   if ( !d->m_doc ) return KUrl();
02515 
02516   return d->m_doc->baseURL();
02517 }
02518 #endif
02519 
02520 KUrl KHTMLPart::completeURL( const QString &url )
02521 {
02522   if ( !d->m_doc ) return KUrl( url );
02523 
02524 #if 0
02525   if (d->m_decoder)
02526     return KUrl(d->m_doc->completeURL(url), d->m_decoder->codec()->mibEnum());
02527 #endif
02528 
02529   return KUrl( d->m_doc->completeURL( url ) );
02530 }
02531 
02532 QString KHTMLPartPrivate::codeForJavaScriptURL(const QString &u)
02533 {
02534     return KUrl::fromPercentEncoding( u.right( u.length() - 11 ).toUtf8() );
02535 }
02536 
02537 void KHTMLPartPrivate::executeJavascriptURL(const QString &u)
02538 {
02539     QString script = codeForJavaScriptURL(u);
02540     kDebug( 6050 ) << "script=" << script;
02541     QVariant res = q->executeScript( DOM::Node(), script );
02542     if ( res.type() == QVariant::String ) {
02543       q->begin( q->url() );
02544       q->setAlwaysHonourDoctype(); // Disable public API compat; it messes with doctype
02545       q->write( res.toString() );
02546       q->end();
02547     }
02548     emit q->completed();
02549 }
02550 
02551 bool KHTMLPartPrivate::isJavaScriptURL(const QString& url)
02552 {
02553     return url.indexOf( QLatin1String( "javascript:" ), 0, Qt::CaseInsensitive ) == 0;
02554 }
02555 
02556 // Called by ecma/kjs_window in case of redirections from Javascript,
02557 // and by xml/dom_docimpl.cpp in case of http-equiv meta refresh.
02558 void KHTMLPart::scheduleRedirection( int delay, const QString &url, bool doLockHistory )
02559 {
02560   kDebug(6050) << "delay=" << delay << " url=" << url;
02561   kDebug(6050) << "current redirectURL=" << d->m_redirectURL << " with delay " << d->m_delayRedirect;
02562 
02563   // In case of JS redirections, some, such as jump to anchors, and javascript:
02564   // evaluation should actually be handled immediately, and not waiting until
02565   // the end of the script. (Besides, we don't want to abort the tokenizer for those)
02566   if ( delay == -1 && d->isInPageURL(url) ) {
02567     d->executeInPageURL(url, doLockHistory);
02568     return;
02569   }
02570 
02571   if( delay < 24*60*60 &&
02572       ( d->m_redirectURL.isEmpty() || delay <= d->m_delayRedirect) ) {
02573     d->m_delayRedirect = delay;
02574     d->m_redirectURL = url;
02575     d->m_redirectLockHistory = doLockHistory;
02576     kDebug(6050) << " d->m_bComplete=" << d->m_bComplete;
02577 
02578     if ( d->m_bComplete ) {
02579       d->m_redirectionTimer.stop();
02580       d->m_redirectionTimer.setSingleShot( true );
02581       d->m_redirectionTimer.start( qMax(0, 1000 * d->m_delayRedirect) );
02582     }
02583   }
02584 }
02585 
02586 void KHTMLPartPrivate::clearRedirection()
02587 {
02588   m_delayRedirect = 0;
02589   m_redirectURL.clear();
02590   m_redirectionTimer.stop();
02591 }
02592 
02593 void KHTMLPart::slotRedirect()
02594 {
02595   kDebug(6050) << this;
02596   QString u = d->m_redirectURL;
02597   KUrl url( u );
02598   d->clearRedirection();
02599 
02600   if ( d->isInPageURL(u) )
02601   {
02602     d->executeInPageURL(u, d->m_redirectLockHistory);
02603     return;
02604   }
02605 
02606   KParts::OpenUrlArguments args;
02607   KUrl cUrl( this->url() );
02608 
02609   // handle windows opened by JS
02610   if ( openedByJS() && d->m_opener )
02611       cUrl = d->m_opener->url();
02612 
02613   if (!KAuthorized::authorizeUrlAction("redirect", cUrl, url))
02614   {
02615     kWarning(6050) << "KHTMLPart::scheduleRedirection: Redirection from " << cUrl << " to " << url << " REJECTED!";
02616     emit completed();
02617     return;
02618   }
02619 
02620   if ( urlcmp( u, this->url().url(), KUrl::CompareWithoutTrailingSlash | KUrl::CompareWithoutFragment) )
02621   {
02622     args.metaData().insert("referrer", d->m_pageReferrer);
02623   }
02624 
02625   // For javascript and META-tag based redirections:
02626   //   - We don't take cross-domain-ness in consideration if we are the
02627   //   toplevel frame because the new URL may be in a different domain as the current URL
02628   //   but that's ok.
02629   //   - If we are not the toplevel frame then we check against the toplevelURL()
02630   if (parentPart())
02631       args.metaData().insert("cross-domain", toplevelURL().url());
02632 
02633   KParts::BrowserArguments browserArgs;
02634   browserArgs.setLockHistory( d->m_redirectLockHistory );
02635   // _self: make sure we don't use any <base target=>'s
02636 
02637   if ( !urlSelected( u, 0, 0, "_self", args, browserArgs ) ) {
02638     // urlSelected didn't open a url, so emit completed ourselves
02639     emit completed();
02640   }
02641 }
02642 
02643 void KHTMLPart::slotRedirection(KIO::Job*, const KUrl& url)
02644 {
02645   // the slave told us that we got redirected
02646   //kDebug( 6050 ) << "redirection by KIO to" << url;
02647   emit d->m_extension->setLocationBarUrl( url.prettyUrl() );
02648   d->m_workingURL = url;
02649 }
02650 
02651 bool KHTMLPart::setEncoding( const QString &name, bool override )
02652 {
02653     d->m_encoding = name;
02654     d->m_haveEncoding = override;
02655 
02656     if( !url().isEmpty() ) {
02657         // reload document
02658         closeUrl();
02659         KUrl oldUrl = url();
02660         setUrl(KUrl());
02661         d->m_restored = true;
02662         openUrl(oldUrl);
02663         d->m_restored = false;
02664     }
02665 
02666     return true;
02667 }
02668 
02669 QString KHTMLPart::encoding() const
02670 {
02671     if(d->m_haveEncoding && !d->m_encoding.isEmpty())
02672         return d->m_encoding;
02673 
02674     if(d->m_decoder && d->m_decoder->encoding())
02675         return QString(d->m_decoder->encoding());
02676 
02677     return defaultEncoding();
02678 }
02679 
02680 QString KHTMLPart::defaultEncoding() const
02681 {
02682   QString encoding = settings()->encoding();
02683   if ( !encoding.isEmpty() )
02684     return encoding;
02685   // HTTP requires the default encoding to be latin1, when neither
02686   // the user nor the page requested a particular encoding.
02687   if ( url().protocol().startsWith( "http" ) )
02688     return "iso-8859-1";
02689   else
02690     return KGlobal::locale()->encoding();
02691 }
02692 
02693 void KHTMLPart::setUserStyleSheet(const KUrl &url)
02694 {
02695   if ( d->m_doc && d->m_doc->docLoader() )
02696     (void) new khtml::PartStyleSheetLoader(this, url.url(), d->m_doc->docLoader());
02697 }
02698 
02699 void KHTMLPart::setUserStyleSheet(const QString &styleSheet)
02700 {
02701   if ( d->m_doc )
02702     d->m_doc->setUserStyleSheet( styleSheet );
02703 }
02704 
02705 bool KHTMLPart::gotoAnchor( const QString &name )
02706 {
02707   if (!d->m_doc)
02708     return false;
02709 
02710   HTMLCollectionImpl *anchors =
02711       new HTMLCollectionImpl( d->m_doc, HTMLCollectionImpl::DOC_ANCHORS);
02712   anchors->ref();
02713   NodeImpl *n = anchors->namedItem(name);
02714   anchors->deref();
02715 
02716   if(!n) {
02717       n = d->m_doc->getElementById( name );
02718   }
02719 
02720   d->m_doc->setCSSTarget(n); // Setting to null will clear the current target.
02721 
02722   // Implement the rule that "" and "top" both mean top of page as in other browsers.
02723   bool quirkyName = !n && !d->m_doc->inStrictMode() && (name.isEmpty() || name.toLower() == "top");
02724 
02725   if (quirkyName) {
02726       d->m_view->setContentsPos( d->m_view->contentsX(), 0);
02727       return true;
02728   } else if (!n) {
02729       kDebug(6050) << name << "not found";
02730       return false;
02731   }
02732 
02733   int x = 0, y = 0;
02734   int gox, dummy;
02735   HTMLElementImpl *a = static_cast<HTMLElementImpl *>(n);
02736 
02737   a->getUpperLeftCorner(x, y);
02738   if (x <= d->m_view->contentsX())
02739     gox = x - 10;
02740   else {
02741     gox = d->m_view->contentsX();
02742     if ( x + 10 > d->m_view->contentsX()+d->m_view->visibleWidth()) {
02743       a->getLowerRightCorner(x, dummy);
02744       gox = x - d->m_view->visibleWidth() + 10;
02745     }
02746   }
02747 
02748   d->m_view->setContentsPos(gox, y);
02749 
02750   return true;
02751 }
02752 
02753 bool KHTMLPart::nextAnchor()
02754 {
02755   if (!d->m_doc)
02756     return false;
02757   d->m_view->focusNextPrevNode ( true );
02758 
02759   return true;
02760 }
02761 
02762 bool KHTMLPart::prevAnchor()
02763 {
02764   if (!d->m_doc)
02765     return false;
02766   d->m_view->focusNextPrevNode ( false );
02767 
02768   return true;
02769 }
02770 
02771 void KHTMLPart::setStandardFont( const QString &name )
02772 {
02773     d->m_settings->setStdFontName(name);
02774 }
02775 
02776 void KHTMLPart::setFixedFont( const QString &name )
02777 {
02778     d->m_settings->setFixedFontName(name);
02779 }
02780 
02781 void KHTMLPart::setURLCursor( const QCursor &c )
02782 {
02783   d->m_linkCursor = c;
02784 }
02785 
02786 QCursor KHTMLPart::urlCursor() const
02787 {
02788   return d->m_linkCursor;
02789 }
02790 
02791 bool KHTMLPart::onlyLocalReferences() const
02792 {
02793   return d->m_onlyLocalReferences;
02794 }
02795 
02796 void KHTMLPart::setOnlyLocalReferences(bool enable)
02797 {
02798   d->m_onlyLocalReferences = enable;
02799 }
02800 
02801 void KHTMLPartPrivate::setFlagRecursively(
02802         bool KHTMLPartPrivate::*flag, bool value)
02803 {
02804   // first set it on the current one
02805   this->*flag = value;
02806 
02807   // descend into child frames recursively
02808   {
02809     QList<khtml::ChildFrame*>::Iterator it = m_frames.begin();
02810     const QList<khtml::ChildFrame*>::Iterator itEnd = m_frames.end();
02811     for (; it != itEnd; ++it) {
02812       KHTMLPart* const part = qobject_cast<KHTMLPart *>( (*it)->m_part );
02813       if (part)
02814         part->d->setFlagRecursively(flag, value);
02815     }/*next it*/
02816   }
02817   // do the same again for objects
02818   {
02819     QList<khtml::ChildFrame*>::Iterator it = m_objects.begin();
02820     const QList<khtml::ChildFrame*>::Iterator itEnd = m_objects.end();
02821     for (; it != itEnd; ++it) {
02822       KHTMLPart* const part = qobject_cast<KHTMLPart *>( (*it)->m_part );
02823       if (part)
02824         part->d->setFlagRecursively(flag, value);
02825     }/*next it*/
02826   }
02827 }
02828 
02829 void KHTMLPart::initCaret()
02830 {
02831   // initialize caret if not used yet
02832   if (d->editor_context.m_selection.state() == Selection::NONE) {
02833     if (d->m_doc) {
02834       NodeImpl *node;
02835       if (d->m_doc->isHTMLDocument()) {
02836         HTMLDocumentImpl* htmlDoc = static_cast<HTMLDocumentImpl*>(d->m_doc);
02837         node = htmlDoc->body();
02838       } else
02839         node = d->m_doc;
02840       if (!node) return;
02841       d->editor_context.m_selection.moveTo(Position(node, 0));
02842       d->editor_context.m_selection.setNeedsLayout();
02843       d->editor_context.m_selection.needsCaretRepaint();
02844     }
02845   }
02846 }
02847 
02848 static void setCaretInvisibleIfNeeded(KHTMLPart *part)
02849 {
02850   // On contenteditable nodes, don't hide the caret
02851   if (!khtml::KHTMLPartAccessor::caret(part).caretPos().node()->isContentEditable())
02852     part->setCaretVisible(false);
02853 }
02854 
02855 void KHTMLPart::setCaretMode(bool enable)
02856 {
02857   kDebug(6200) << enable;
02858   if (isCaretMode() == enable) return;
02859   d->setFlagRecursively(&KHTMLPartPrivate::m_caretMode, enable);
02860   // FIXME: this won't work on frames as expected
02861   if (!isEditable()) {
02862     if (enable) {
02863       initCaret();
02864       setCaretVisible(true);
02865 //       view()->ensureCaretVisible();
02866     } else {
02867       setCaretInvisibleIfNeeded(this);
02868     }
02869   }
02870 }
02871 
02872 bool KHTMLPart::isCaretMode() const
02873 {
02874   return d->m_caretMode;
02875 }
02876 
02877 void KHTMLPart::setEditable(bool enable)
02878 {
02879   if (isEditable() == enable) return;
02880   d->setFlagRecursively(&KHTMLPartPrivate::m_designMode, enable);
02881   // FIXME: this won't work on frames as expected
02882   if (!isCaretMode()) {
02883     if (enable) {
02884       initCaret();
02885       setCaretVisible(true);
02886 //       view()->ensureCaretVisible();
02887     } else
02888       setCaretInvisibleIfNeeded(this);
02889   }
02890 }
02891 
02892 bool KHTMLPart::isEditable() const
02893 {
02894   return d->m_designMode;
02895 }
02896 
02897 khtml::EditorContext *KHTMLPart::editorContext() const {
02898     return &d->editor_context;
02899 }
02900 
02901 void KHTMLPart::setCaretPosition(DOM::Node node, long offset, bool extendSelection)
02902 {
02903 #ifndef KHTML_NO_CARET
02904 #if 0
02905   kDebug(6200) << "node: " << node.handle() << " nodeName: "
02906                << node.nodeName().string() << " offset: " << offset
02907                << " extendSelection " << extendSelection;
02908   if (view()->moveCaretTo(node.handle(), offset, !extendSelection))
02909     emitSelectionChanged();
02910   view()->ensureCaretVisible();
02911 #endif
02912 #endif // KHTML_NO_CARET
02913 }
02914 
02915 KHTMLPart::CaretDisplayPolicy KHTMLPart::caretDisplayPolicyNonFocused() const
02916 {
02917 #if 0
02918 #ifndef KHTML_NO_CARET
02919   return (CaretDisplayPolicy)view()->caretDisplayPolicyNonFocused();
02920 #else // KHTML_NO_CARET
02921   return CaretInvisible;
02922 #endif // KHTML_NO_CARET
02923 #endif
02924   return CaretInvisible;
02925 }
02926 
02927 void KHTMLPart::setCaretDisplayPolicyNonFocused(CaretDisplayPolicy policy)
02928 {
02929 #if 0
02930 #ifndef KHTML_NO_CARET
02931   view()->setCaretDisplayPolicyNonFocused(policy);
02932 #endif // KHTML_NO_CARET
02933 #endif
02934 }
02935 
02936 void KHTMLPart::setCaretVisible(bool show)
02937 {
02938   if (show) {
02939     NodeImpl *caretNode = d->editor_context.m_selection.caretPos().node();
02940     if (isCaretMode() || (caretNode && caretNode->isContentEditable())) {
02941         invalidateSelection();
02942         enableFindAheadActions(false);
02943     }
02944   } else {
02945 
02946     if (d->editor_context.m_caretBlinkTimer >= 0)
02947         killTimer(d->editor_context.m_caretBlinkTimer);
02948     clearCaretRectIfNeeded();
02949 
02950   }
02951 }
02952 
02953 void KHTMLPart::findTextBegin()
02954 {
02955   d->m_find.findTextBegin();
02956 }
02957 
02958 bool KHTMLPart::initFindNode( bool selection, bool reverse, bool fromCursor )
02959 {
02960   return d->m_find.initFindNode(selection, reverse, fromCursor);
02961 }
02962 
02963 void KHTMLPart::slotFind()
02964 {
02965   KParts::ReadOnlyPart *part = currentFrame();
02966   if (!part)
02967     return;
02968   if (!part->inherits("KHTMLPart") )
02969   {
02970       kError(6000) << "part is a" << part->metaObject()->className() << ", can't do a search into it";
02971       return;
02972   }
02973   static_cast<KHTMLPart *>( part )->findText();
02974 }
02975 
02976 void KHTMLPart::slotFindNext()
02977 {
02978   KParts::ReadOnlyPart *part = currentFrame();
02979   if (!part)
02980     return;
02981   if (!part->inherits("KHTMLPart") )
02982   {
02983       kError(6000) << "part is a" << part->metaObject()->className() << ", can't do a search into it";
02984       return;
02985   }
02986   static_cast<KHTMLPart *>( part )->findTextNext();
02987 }
02988 
02989 void KHTMLPart::slotFindPrev()
02990 {
02991   KParts::ReadOnlyPart *part = currentFrame();
02992   if (!part)
02993     return;
02994   if (!part->inherits("KHTMLPart") )
02995   {
02996       kError(6000) << "part is a" << part->metaObject()->className() << ", can't do a search into it";
02997       return;
02998   }
02999   static_cast<KHTMLPart *>( part )->findTextNext( true ); // reverse
03000 }
03001 
03002 void KHTMLPart::slotFindDone()
03003 {
03004   // ### remove me
03005 }
03006 
03007 void KHTMLPart::slotFindAheadText()
03008 {
03009 #ifndef KHTML_NO_TYPE_AHEAD_FIND
03010   KParts::ReadOnlyPart *part = currentFrame();
03011   if (!part)
03012     return;
03013   if (!part->inherits("KHTMLPart") )
03014   {
03015       kError(6000) << "part is a" << part->metaObject()->className() << ", can't do a search into it";
03016       return;
03017   }
03018   static_cast<KHTMLPart *>( part )->view()->startFindAhead( false );
03019 #endif // KHTML_NO_TYPE_AHEAD_FIND
03020 }
03021 
03022 void KHTMLPart::slotFindAheadLink()
03023 {
03024 #ifndef KHTML_NO_TYPE_AHEAD_FIND
03025   KParts::ReadOnlyPart *part = currentFrame();
03026   if (!part)
03027     return;
03028   if (!part->inherits("KHTMLPart") )
03029   {
03030       kError(6000) << "part is a" << part->metaObject()->className() << ", can't do a search into it";
03031       return;
03032   }
03033   static_cast<KHTMLPart *>( part )->view()->startFindAhead( true );
03034 #endif // KHTML_NO_TYPE_AHEAD_FIND
03035 }
03036 
03037 void KHTMLPart::enableFindAheadActions( bool enable )
03038 {
03039   // only the topmost one has shortcuts
03040   KHTMLPart* p = this;
03041   while( p->parentPart())
03042     p = p->parentPart();
03043   p->d->m_paFindAheadText->setEnabled( enable );
03044   p->d->m_paFindAheadLinks->setEnabled( enable );
03045 }
03046 
03047 void KHTMLPart::slotFindDialogDestroyed()
03048 {
03049   // ### remove me
03050 }
03051 
03052 void KHTMLPart::findText()
03053 {
03054   if (parentPart())
03055       return parentPart()->findText();
03056   d->m_find.activate();
03057 }
03058 
03059 void KHTMLPart::findText( const QString &str, long options, QWidget *parent, KFindDialog *findDialog )
03060 {
03061   if (parentPart())
03062       return parentPart()->findText(str, options, parent, findDialog);
03063   d->m_find.createNewKFind(str, options, parent, findDialog );
03064 }
03065 
03066 // New method
03067 bool KHTMLPart::findTextNext( bool reverse )
03068 {
03069   if (parentPart())
03070       return parentPart()->findTextNext( reverse );
03071   return d->m_find.findTextNext( reverse );
03072 }
03073 
03074 bool KHTMLPart::pFindTextNextInThisFrame( bool reverse )
03075 {
03076   return d->m_find.findTextNext( reverse );
03077 }
03078 
03079 QString KHTMLPart::selectedTextAsHTML() const
03080 {
03081   const Selection &sel = d->editor_context.m_selection;
03082   if(!hasSelection()) {
03083     kDebug() << "Selection is not valid. Returning empty selection";
03084     return QString();
03085   }
03086   if(sel.start().offset() < 0 || sel.end().offset() < 0) {
03087     kDebug() << "invalid values for end/startOffset " << sel.start().offset() << " " << sel.end().offset();
03088     return QString();
03089   }
03090   DOM::Range r = selection();
03091   if(r.isNull() || r.isDetached())
03092     return QString();
03093   int exceptioncode = 0; //ignore the result
03094   return r.handle()->toHTML(exceptioncode).string();
03095 }
03096 
03097 QString KHTMLPart::selectedText() const
03098 {
03099   bool hasNewLine = true;
03100   bool seenTDTag = false;
03101   QString text;
03102   const Selection &sel = d->editor_context.m_selection;
03103   DOM::Node n = sel.start().node();
03104   while(!n.isNull()) {
03105       if(n.nodeType() == DOM::Node::TEXT_NODE && n.handle()->renderer()) {
03106         DOM::DOMStringImpl *dstr = static_cast<DOM::TextImpl*>(n.handle())->renderString();
03107         QString str(dstr->s, dstr->l);
03108         if(!str.isEmpty()) {
03109           if(seenTDTag) {
03110             text += "  ";
03111             seenTDTag = false;
03112           }
03113           hasNewLine = false;
03114           if(n == sel.start().node() && n == sel.end().node())
03115             text = str.mid(sel.start().offset(), sel.end().offset() - sel.start().offset());
03116           else if(n == sel.start().node())
03117             text = str.mid(sel.start().offset());
03118           else if(n == sel.end().node())
03119             text += str.left(sel.end().offset());
03120           else
03121             text += str;
03122         }
03123       }
03124       else {
03125         // This is our simple HTML -> ASCII transformation:
03126         unsigned short id = n.elementId();
03127         switch(id) {
03128           case ID_TEXTAREA:
03129             text += static_cast<HTMLTextAreaElementImpl*>(n.handle())->value().string();
03130             break;
03131           case ID_INPUT:
03132             if (static_cast<HTMLInputElementImpl*>(n.handle())->inputType() != HTMLInputElementImpl::PASSWORD)
03133                 text += static_cast<HTMLInputElementImpl*>(n.handle())->value().string();
03134             break;
03135           case ID_SELECT:
03136             text += static_cast<HTMLSelectElementImpl*>(n.handle())->value().string();
03137             break;
03138           case ID_BR:
03139             text += "\n";
03140             hasNewLine = true;
03141             break;
03142           case ID_IMG:
03143             text += static_cast<HTMLImageElementImpl*>(n.handle())->altText().string();
03144             break;
03145           case ID_TD:
03146             break;
03147           case ID_TH:
03148           case ID_HR:
03149           case ID_OL:
03150           case ID_UL:
03151           case ID_LI:
03152           case ID_DD:
03153           case ID_DL:
03154           case ID_DT:
03155           case ID_PRE:
03156           case ID_LISTING:
03157           case ID_BLOCKQUOTE:
03158           case ID_DIV:
03159             if (!hasNewLine)
03160                text += "\n";
03161             hasNewLine = true;
03162             break;
03163           case ID_P:
03164           case ID_TR:
03165           case ID_H1:
03166           case ID_H2:
03167           case ID_H3:
03168           case ID_H4:
03169           case ID_H5:
03170           case ID_H6:
03171             if (!hasNewLine)
03172                text += "\n";
03173             hasNewLine = true;
03174             break;
03175         }
03176       }
03177       if(n == sel.end().node()) break;
03178       DOM::Node next = n.firstChild();
03179       if(next.isNull()) next = n.nextSibling();
03180       while( next.isNull() && !n.parentNode().isNull() ) {
03181         n = n.parentNode();
03182         next = n.nextSibling();
03183         unsigned short id = n.elementId();
03184         switch(id) {
03185           case ID_TD:
03186             seenTDTag = true; //Add two spaces after a td if then followed by text.
03187             break;
03188           case ID_TH:
03189           case ID_HR:
03190           case ID_OL:
03191           case ID_UL:
03192           case ID_LI:
03193           case ID_DD:
03194           case ID_DL:
03195           case ID_DT:
03196           case ID_PRE:
03197           case ID_LISTING:
03198           case ID_BLOCKQUOTE:
03199           case ID_DIV:
03200             seenTDTag = false;
03201             if (!hasNewLine)
03202                text += "\n";
03203             hasNewLine = true;
03204             break;
03205           case ID_P:
03206           case ID_TR:
03207           case ID_H1:
03208           case ID_H2:
03209           case ID_H3:
03210           case ID_H4:
03211           case ID_H5:
03212           case ID_H6:
03213             if (!hasNewLine)
03214                text += "\n";
03215 //            text += "\n";
03216             hasNewLine = true;
03217             break;
03218         }
03219       }
03220 
03221       n = next;
03222     }
03223 
03224     if(text.isEmpty())
03225         return QString();
03226 
03227     int start = 0;
03228     int end = text.length();
03229 
03230     // Strip leading LFs
03231     while ((start < end) && (text[start] == '\n'))
03232        ++start;
03233 
03234     // Strip excessive trailing LFs
03235     while ((start < (end-1)) && (text[end-1] == '\n') && (text[end-2] == '\n'))
03236        --end;
03237 
03238     return text.mid(start, end-start);
03239 }
03240 
03241 QString KHTMLPart::simplifiedSelectedText() const
03242 {
03243     QString text = selectedText();
03244     text.replace(QChar(0xa0), ' ');
03245     // remove leading and trailing whitespace
03246     while (!text.isEmpty() && text[0].isSpace())
03247         text = text.mid(1);
03248     while (!text.isEmpty() && text[text.length()-1].isSpace())
03249         text.truncate(text.length()-1);
03250     return text;
03251 }
03252 
03253 bool KHTMLPart::hasSelection() const
03254 {
03255     return !d->editor_context.m_selection.isEmpty() && !d->editor_context.m_selection.isCollapsed();
03256 }
03257 
03258 DOM::Range KHTMLPart::selection() const
03259 {
03260     return d->editor_context.m_selection.toRange();
03261 }
03262 
03263 void KHTMLPart::selection(DOM::Node &s, long &so, DOM::Node &e, long &eo) const
03264 {
03265     DOM::Range r = d->editor_context.m_selection.toRange();
03266     s = r.startContainer();
03267     so = r.startOffset();
03268     e = r.endContainer();
03269     eo = r.endOffset();
03270 }
03271 
03272 void KHTMLPart::setSelection( const DOM::Range &r )
03273 {
03274     setCaret(r);
03275 }
03276 
03277 const Selection &KHTMLPart::caret() const
03278 {
03279   return d->editor_context.m_selection;
03280 }
03281 
03282 const Selection &KHTMLPart::dragCaret() const
03283 {
03284   return d->editor_context.m_dragCaret;
03285 }
03286 
03287 void KHTMLPart::setCaret(const Selection &s, bool closeTyping)
03288 {
03289   if (d->editor_context.m_selection != s) {
03290     clearCaretRectIfNeeded();
03291     setFocusNodeIfNeeded(s);
03292     d->editor_context.m_selection = s;
03293     notifySelectionChanged(closeTyping);
03294   }
03295 }
03296 
03297 void KHTMLPart::setDragCaret(const DOM::Selection &dragCaret)
03298 {
03299   if (d->editor_context.m_dragCaret != dragCaret) {
03300     d->editor_context.m_dragCaret.needsCaretRepaint();
03301     d->editor_context.m_dragCaret = dragCaret;
03302     d->editor_context.m_dragCaret.needsCaretRepaint();
03303   }
03304 }
03305 
03306 void KHTMLPart::clearSelection()
03307 {
03308   clearCaretRectIfNeeded();
03309   setFocusNodeIfNeeded(d->editor_context.m_selection);
03310 #ifdef APPLE_CHANGES
03311   d->editor_context.m_selection.clear();
03312 #else
03313   d->editor_context.m_selection.collapse();
03314 #endif
03315   notifySelectionChanged();
03316 }
03317 
03318 void KHTMLPart::invalidateSelection()
03319 {
03320   clearCaretRectIfNeeded();
03321   d->editor_context.m_selection.setNeedsLayout();
03322   selectionLayoutChanged();
03323 }
03324 
03325 void KHTMLPart::setSelectionVisible(bool flag)
03326 {
03327   if (d->editor_context.m_caretVisible == flag)
03328     return;
03329 
03330   clearCaretRectIfNeeded();
03331   setFocusNodeIfNeeded(d->editor_context.m_selection);
03332   d->editor_context.m_caretVisible = flag;
03333 //   notifySelectionChanged();
03334 }
03335 
03336 #if 1
03337 void KHTMLPart::slotClearSelection()
03338 {
03339   if (!isCaretMode()
03340        && d->editor_context.m_selection.state() != Selection::NONE
03341        && !d->editor_context.m_selection.caretPos().node()->isContentEditable())
03342     clearCaretRectIfNeeded();
03343   bool hadSelection = hasSelection();
03344 #ifdef APPLE_CHANGES
03345   d->editor_context.m_selection.clear();
03346 #else
03347   d->editor_context.m_selection.collapse();
03348 #endif
03349   if (hadSelection)
03350     notifySelectionChanged();
03351 }
03352 #endif
03353 
03354 void KHTMLPart::clearCaretRectIfNeeded()
03355 {
03356   if (d->editor_context.m_caretPaint) {
03357     d->editor_context.m_caretPaint = false;
03358     d->editor_context.m_selection.needsCaretRepaint();
03359   }
03360 }
03361 
03362 void KHTMLPart::setFocusNodeIfNeeded(const Selection &s)
03363 {
03364   if (!xmlDocImpl() || s.state() == Selection::NONE)
03365     return;
03366 
03367   NodeImpl *n = s.start().node();
03368   NodeImpl *target = (n && n->isContentEditable()) ? n : 0;
03369   if (!target) {
03370     while (n && n != s.end().node()) {
03371       if (n->isContentEditable()) {
03372         target = n;
03373         break;
03374       }
03375       n = n->traverseNextNode();
03376     }
03377   }
03378   assert(target == 0 || target->isContentEditable());
03379 
03380   if (target) {
03381     for ( ; target && !target->isFocusable(); target = target->parentNode())
03382       {}
03383     if (target && target->isMouseFocusable())
03384       xmlDocImpl()->setFocusNode(target);
03385     else if (!target || !target->focused())
03386       xmlDocImpl()->setFocusNode(0);
03387   }
03388 }
03389 
03390 void KHTMLPart::selectionLayoutChanged()
03391 {
03392   // kill any caret blink timer now running
03393   if (d->editor_context.m_caretBlinkTimer >= 0) {
03394     killTimer(d->editor_context.m_caretBlinkTimer);
03395     d->editor_context.m_caretBlinkTimer = -1;
03396   }
03397 
03398   // see if a new caret blink timer needs to be started
03399   if (d->editor_context.m_caretVisible
03400       && d->editor_context.m_selection.state() != Selection::NONE) {
03401     d->editor_context.m_caretPaint = isCaretMode()
03402         || d->editor_context.m_selection.caretPos().node()->isContentEditable();
03403     if (d->editor_context.m_caretBlinks && d->editor_context.m_caretPaint)
03404       d->editor_context.m_caretBlinkTimer = startTimer(qApp->cursorFlashTime() / 2);
03405     d->editor_context.m_selection.needsCaretRepaint();
03406   }
03407 
03408   if (d->m_doc)
03409     d->m_doc->updateSelection();
03410 
03411   // Always clear the x position used for vertical arrow navigation.
03412   // It will be restored by the vertical arrow navigation code if necessary.
03413   d->editor_context.m_xPosForVerticalArrowNavigation = d->editor_context.NoXPosForVerticalArrowNavigation;
03414 }
03415 
03416 void KHTMLPart::notifySelectionChanged(bool closeTyping)
03417 {
03418   Editor *ed = d->editor_context.m_editor;
03419   selectionLayoutChanged();
03420   if (ed) {
03421     ed->clearTypingStyle();
03422 
03423     if (closeTyping)
03424       khtml::TypingCommand::closeTyping(ed->lastEditCommand());
03425   }
03426 
03427   emitSelectionChanged();
03428 
03429 }
03430 
03431 void KHTMLPart::timerEvent(QTimerEvent *e)
03432 {
03433   if (e->timerId() == d->editor_context.m_caretBlinkTimer) {
03434     if (d->editor_context.m_caretBlinks &&
03435         d->editor_context.m_selection.state() != Selection::NONE) {
03436       d->editor_context.m_caretPaint = !d->editor_context.m_caretPaint;
03437       d->editor_context.m_selection.needsCaretRepaint();
03438     }
03439   } else if (e->timerId() == d->m_DNSPrefetchTimer) {
03440       // kDebug( 6050 ) << "will lookup " << d->m_DNSPrefetchQueue.head() << d->m_numDNSPrefetchedNames;
03441       KIO::HostInfo::prefetchHost( d->m_DNSPrefetchQueue.dequeue() );
03442       if (d->m_DNSPrefetchQueue.isEmpty()) {
03443           killTimer( d->m_DNSPrefetchTimer );
03444           d->m_DNSPrefetchTimer = -1;
03445       }
03446   } else if (e->timerId() == d->m_DNSTTLTimer) {
03447       foreach (QString name, d->m_lookedupHosts)
03448           d->m_DNSPrefetchQueue.enqueue(name);
03449       if (d->m_DNSPrefetchTimer <= 0)
03450          d->m_DNSPrefetchTimer = startTimer( sDNSPrefetchTimerDelay );
03451   }
03452 }
03453 
03454 bool KHTMLPart::mayPrefetchHostname( const QString& name )
03455 {
03456     if (d->m_bDNSPrefetch == DNSPrefetchDisabled)
03457         return false;
03458 
03459     if (d->m_numDNSPrefetchedNames >= sMaxDNSPrefetchPerPage)
03460         return false;
03461 
03462     if (d->m_bDNSPrefetch == DNSPrefetchOnlyWWWAndSLD) {
03463         int dots = name.count('.');
03464         if (dots > 2 || (dots == 2 &&  !name.startsWith("www.")))
03465             return false;
03466     }
03467 
03468     if ( d->m_lookedupHosts.contains( name ) )
03469         return false;
03470 
03471     d->m_DNSPrefetchQueue.enqueue( name );
03472     d->m_lookedupHosts.insert( name );
03473     d->m_numDNSPrefetchedNames++;
03474 
03475     if (d->m_DNSPrefetchTimer < 1)
03476         d->m_DNSPrefetchTimer = startTimer( sDNSPrefetchTimerDelay );
03477     if (d->m_DNSTTLTimer < 1)
03478         d->m_DNSTTLTimer = startTimer( sDNSTTLSeconds*1000 + 1 );
03479 
03480     return true;
03481 }
03482 
03483 void KHTMLPart::paintCaret(QPainter *p, const QRect &rect) const
03484 {
03485   if (d->editor_context.m_caretPaint)
03486     d->editor_context.m_selection.paintCaret(p, rect);
03487 }
03488 
03489 void KHTMLPart::paintDragCaret(QPainter *p, const QRect &rect) const
03490 {
03491   d->editor_context.m_dragCaret.paintCaret(p, rect);
03492 }
03493 
03494 DOM::Editor *KHTMLPart::editor() const {
03495   if (!d->editor_context.m_editor)
03496     const_cast<KHTMLPart *>(this)->d->editor_context.m_editor = new DOM::Editor(const_cast<KHTMLPart *>(this));
03497   return d->editor_context.m_editor;
03498 }
03499 
03500 void KHTMLPart::resetHoverText()
03501 {
03502    if( !d->m_overURL.isEmpty() ) // Only if we were showing a link
03503    {
03504      d->m_overURL.clear();
03505      d->m_overURLTarget.clear();
03506      emit onURL( QString() );
03507      // revert to default statusbar text
03508      setStatusBarText(QString(), BarHoverText);
03509      emit d->m_extension->mouseOverInfo(KFileItem());
03510   }
03511 }
03512 
03513 void KHTMLPart::overURL( const QString &url, const QString &target, bool /*shiftPressed*/ )
03514 {
03515   KUrl u = completeURL(url);
03516 
03517   // special case for <a href="">
03518   if ( url.isEmpty() )
03519     u.setFileName( url );
03520 
03521   emit onURL( url );
03522 
03523   if ( url.isEmpty() ) {
03524     setStatusBarText(Qt::escape(u.prettyUrl()), BarHoverText);
03525     return;
03526   }
03527 
03528   if ( d->isJavaScriptURL(url) ) {
03529     QString jscode = d->codeForJavaScriptURL( url );
03530     jscode = KStringHandler::rsqueeze( jscode, 80 ); // truncate if too long
03531     if (url.startsWith("javascript:window.open"))
03532       jscode += i18n(" (In new window)");
03533     setStatusBarText( Qt::escape( jscode ), BarHoverText );
03534     return;
03535   }
03536 
03537   KFileItem item(u, QString(), KFileItem::Unknown);
03538   emit d->m_extension->mouseOverInfo(item);
03539 
03540   QString com;
03541 
03542   KMimeType::Ptr typ = KMimeType::findByUrl( u );
03543 
03544   if ( typ )
03545     com = typ->comment( u );
03546 
03547   if ( !u.isValid() ) {
03548     setStatusBarText(Qt::escape(u.prettyUrl()), BarHoverText);
03549     return;
03550   }
03551 
03552   if ( u.isLocalFile() )
03553   {
03554     // TODO : use KIO::stat() and create a KFileItem out of its result,
03555     // to use KFileItem::statusBarText()
03556     const QString path = QFile::encodeName( u.toLocalFile() );
03557 
03558     KDE_struct_stat buff;
03559     bool ok = !KDE::stat( path, &buff );
03560 
03561     KDE_struct_stat lbuff;
03562     if (ok) ok = !KDE::lstat( path, &lbuff );
03563 
03564     QString text = Qt::escape(u.prettyUrl());
03565     QString text2 = text;
03566 
03567     if (ok && S_ISLNK( lbuff.st_mode ) )
03568     {
03569       QString tmp;
03570       if ( com.isNull() )
03571         tmp = i18n( "Symbolic Link");
03572       else
03573         tmp = i18n("%1 (Link)", com);
03574       char buff_two[1024];
03575       text += " -> ";
03576       int n = readlink ( path.toLocal8Bit().data(), buff_two, 1022);
03577       if (n == -1)
03578       {
03579         text2 += "  ";
03580         text2 += tmp;
03581         setStatusBarText(text2, BarHoverText);
03582         return;
03583       }
03584       buff_two[n] = 0;
03585 
03586       text += buff_two;
03587       text += "  ";
03588       text += tmp;
03589     }
03590     else if ( ok && S_ISREG( buff.st_mode ) )
03591     {
03592       if (buff.st_size < 1024)
03593         text = i18n("%2 (%1 bytes)", (long) buff.st_size, text2); // always put the URL last, in case it contains '%'
03594       else
03595       {
03596         float d = (float) buff.st_size/1024.0;
03597         text = i18n("%2 (%1 K)", KGlobal::locale()->formatNumber(d, 2), text2); // was %.2f
03598       }
03599       text += "  ";
03600       text += com;
03601     }
03602     else if ( ok && S_ISDIR( buff.st_mode ) )
03603     {
03604       text += "  ";
03605       text += com;
03606     }
03607     else
03608     {
03609       text += "  ";
03610       text += com;
03611     }
03612     setStatusBarText(text, BarHoverText);
03613   }
03614   else
03615   {
03616     QString extra;
03617     if (target.toLower() == "_blank")
03618     {
03619       extra = i18n(" (In new window)");
03620     }
03621     else if (!target.isEmpty() &&
03622              (target.toLower() != "_top") &&
03623              (target.toLower() != "_self") &&
03624              (target.toLower() != "_parent"))
03625     {
03626       KHTMLPart *p = this;
03627       while (p->parentPart())
03628           p = p->parentPart();
03629       if (!p->frameExists(target))
03630         extra = i18n(" (In new window)");
03631       else
03632         extra = i18n(" (In other frame)");
03633     }
03634 
03635     if (u.protocol() == QLatin1String("mailto")) {
03636       QString mailtoMsg /* = QString::fromLatin1("<img src=%1>").arg(locate("icon", QString::fromLatin1("locolor/16x16/actions/mail_send.png")))*/;
03637       mailtoMsg += i18n("Email to: ") + KUrl::fromPercentEncoding(u.path().toLatin1());
03638       const QStringList queries = u.query().mid(1).split('&');
03639       QStringList::ConstIterator it = queries.begin();
03640       const QStringList::ConstIterator itEnd = queries.end();
03641       for (; it != itEnd; ++it)
03642         if ((*it).startsWith(QLatin1String("subject=")))
03643           mailtoMsg += i18n(" - Subject: ") + KUrl::fromPercentEncoding((*it).mid(8).toLatin1());
03644         else if ((*it).startsWith(QLatin1String("cc=")))
03645           mailtoMsg += i18n(" - CC: ") + KUrl::fromPercentEncoding((*it).mid(3).toLatin1());
03646         else if ((*it).startsWith(QLatin1String("bcc=")))
03647           mailtoMsg += i18n(" - BCC: ") + KUrl::fromPercentEncoding((*it).mid(4).toLatin1());
03648       mailtoMsg = Qt::escape(mailtoMsg);
03649       mailtoMsg.replace(QRegExp("([\n\r\t]|[ ]{10})"), QString());
03650       setStatusBarText("<qt>"+mailtoMsg, BarHoverText);
03651       return;
03652     }
03653    // Is this check necessary at all? (Frerich)
03654 #if 0
03655     else if (u.protocol() == QLatin1String("http")) {
03656         DOM::Node hrefNode = nodeUnderMouse().parentNode();
03657         while (hrefNode.nodeName().string() != QLatin1String("A") && !hrefNode.isNull())
03658           hrefNode = hrefNode.parentNode();
03659 
03660         if (!hrefNode.isNull()) {
03661           DOM::Node hreflangNode = hrefNode.attributes().getNamedItem("HREFLANG");
03662           if (!hreflangNode.isNull()) {
03663             QString countryCode = hreflangNode.nodeValue().string().toLower();
03664             // Map the language code to an appropriate country code.
03665             if (countryCode == QLatin1String("en"))
03666               countryCode = QLatin1String("gb");
03667             QString flagImg = QLatin1String("<img src=%1>").arg(
03668                 locate("locale", QLatin1String("l10n/")
03669                 + countryCode
03670                 + QLatin1String("/flag.png")));
03671             emit setStatusBarText(flagImg + u.prettyUrl() + extra);
03672           }
03673         }
03674       }
03675 #endif
03676     setStatusBarText(Qt::escape(u.prettyUrl()) + extra, BarHoverText);
03677   }
03678 }
03679 
03680 //
03681 // This executes in the active part on a click or other url selection action in
03682 // that active part.
03683 //
03684 bool KHTMLPart::urlSelected( const QString &url, int button, int state, const QString &_target, const KParts::OpenUrlArguments& _args, const KParts::BrowserArguments& _browserArgs )
03685 {
03686   KParts::OpenUrlArguments args = _args;
03687   KParts::BrowserArguments browserArgs = _browserArgs;
03688   bool hasTarget = false;
03689 
03690   QString target = _target;
03691   if ( target.isEmpty() && d->m_doc )
03692     target = d->m_doc->baseTarget();
03693   if ( !target.isEmpty() )
03694       hasTarget = true;
03695 
03696   if ( d->isJavaScriptURL(url) )
03697   {
03698     crossFrameExecuteScript( target, d->codeForJavaScriptURL(url) );
03699     return false;
03700   }
03701 
03702   KUrl cURL = completeURL(url);
03703   // special case for <a href="">  (IE removes filename, mozilla doesn't)
03704   if ( url.isEmpty() )
03705     cURL.setFileName( url ); // removes filename
03706 
03707   if ( !cURL.isValid() )
03708     // ### ERROR HANDLING
03709     return false;
03710 
03711   kDebug(6050) << this << "complete URL:" << cURL.url() << "target=" << target;
03712 
03713   if ( state & Qt::ControlModifier )
03714   {
03715     browserArgs.setNewTab(true);
03716     emit d->m_extension->createNewWindow( cURL, args, browserArgs );
03717     return true;
03718   }
03719 
03720   if ( button == Qt::LeftButton && ( state & Qt::ShiftModifier ) )
03721   {
03722     KIO::MetaData metaData;
03723     metaData.insert( "referrer", d->m_referrer );
03724     KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), cURL, metaData );
03725     return false;
03726   }
03727 
03728   if (!checkLinkSecurity(cURL,
03729                          ki18n( "<qt>This untrusted page links to<br /><b>%1</b>.<br />Do you want to follow the link?</qt>" ),
03730                          i18n( "Follow" )))
03731     return false;
03732 
03733   browserArgs.frameName = target;
03734 
03735   args.metaData().insert("main_frame_request",
03736                          parentPart() == 0 ? "TRUE":"FALSE");
03737   args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
03738   args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
03739   args.metaData().insert("PropagateHttpHeader", "true");
03740   args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
03741   args.metaData().insert("ssl_activate_warnings", "TRUE");
03742 
03743   if ( hasTarget && target != "_self" && target != "_top" && target != "_blank" && target != "_parent" )
03744   {
03745     // unknown frame names should open in a new window.
03746     khtml::ChildFrame *frame = recursiveFrameRequest( this, cURL, args, browserArgs, false );
03747     if ( frame )
03748     {
03749       args.metaData()["referrer"] = d->m_referrer;
03750       requestObject( frame, cURL, args, browserArgs );
03751       return true;
03752     }
03753   }
03754 
03755   if (!d->m_referrer.isEmpty() && !args.metaData().contains("referrer"))
03756     args.metaData()["referrer"] = d->m_referrer;
03757 
03758   if ( button == Qt::NoButton && (state & Qt::ShiftModifier) && (state & Qt::ControlModifier) )
03759   {
03760     emit d->m_extension->createNewWindow( cURL, args, browserArgs );
03761     return true;
03762   }
03763 
03764   if ( state & Qt::ShiftModifier)
03765   {
03766     KParts::WindowArgs winArgs;
03767     winArgs.setLowerWindow(true);
03768     emit d->m_extension->createNewWindow( cURL, args, browserArgs, winArgs );
03769     return true;
03770   }
03771 
03772   //If we're asked to open up an anchor in the current URL, in current window,
03773   //merely gotoanchor, and do not reload the new page. Note that this does
03774   //not apply if the URL is the same page, but without a ref
03775   if (cURL.hasRef() && (!hasTarget || target == "_self"))
03776   {
03777     if (d->isLocalAnchorJump(cURL))
03778     {
03779       d->executeAnchorJump(cURL, browserArgs.lockHistory() );
03780       return false; // we jumped, but we didn't open a URL
03781     }
03782   }
03783 
03784   if ( !d->m_bComplete && !hasTarget )
03785     closeUrl();
03786 
03787   view()->viewport()->unsetCursor();
03788   emit d->m_extension->openUrlRequest( cURL, args, browserArgs );
03789   return true;
03790 }
03791 
03792 void KHTMLPart::slotViewDocumentSource()
03793 {
03794   KUrl currentUrl(this->url());
03795   bool isTempFile = false;
03796   if (!(currentUrl.isLocalFile()) && KHTMLPageCache::self()->isComplete(d->m_cacheId))
03797   {
03798      KTemporaryFile sourceFile;
03799      sourceFile.setSuffix(defaultExtension());
03800      sourceFile.setAutoRemove(false);
03801      if (sourceFile.open())
03802      {
03803         QDataStream stream ( &sourceFile );
03804         KHTMLPageCache::self()->saveData(d->m_cacheId, &stream);
03805         currentUrl = KUrl();
03806         currentUrl.setPath(sourceFile.fileName());
03807         isTempFile = true;
03808      }
03809   }
03810 
03811   (void) KRun::runUrl( currentUrl, QLatin1String("text/plain"), view(), isTempFile );
03812 }
03813 
03814 void KHTMLPart::slotViewPageInfo()
03815 {
03816   Ui_KHTMLInfoDlg ui;
03817 
03818   QDialog *dlg = new QDialog(0);
03819   dlg->setAttribute(Qt::WA_DeleteOnClose);
03820   dlg->setObjectName("KHTML Page Info Dialog");
03821   ui.setupUi(dlg);
03822 
03823   ui._close->setGuiItem(KStandardGuiItem::close());
03824 
03825   connect(ui._close, SIGNAL(clicked()), dlg, SLOT(accept()));
03826   if (d->m_doc)
03827      ui._title->setText(d->m_doc->title().string());
03828 
03829   // If it's a frame, set the caption to "Frame Information"
03830   if ( parentPart() && d->m_doc && d->m_doc->isHTMLDocument() ) {
03831      dlg->setWindowTitle(i18n("Frame Information"));
03832   }
03833 
03834   QString editStr;
03835 
03836   if (!d->m_pageServices.isEmpty())
03837     editStr = i18n("   <a href=\"%1\">[Properties]</a>", d->m_pageServices);
03838 
03839   QString squeezedURL = KStringHandler::csqueeze( url().prettyUrl(), 80 );
03840   ui._url->setText("<a href=\"" + url().url() + "\">" + squeezedURL + "</a>" + editStr);
03841   if (lastModified().isEmpty())
03842   {
03843     ui._lastModified->hide();
03844     ui._lmLabel->hide();
03845   }
03846   else
03847     ui._lastModified->setText(lastModified());
03848 
03849   const QString& enc = encoding();
03850   if (enc.isEmpty()) {
03851     ui._eLabel->hide();
03852     ui._encoding->hide();
03853   } else {
03854     ui._encoding->setText(enc);
03855   }
03856   /* populate the list view now */
03857   const QStringList headers = d->m_httpHeaders.split("\n");
03858 
03859   QStringList::ConstIterator it = headers.begin();
03860   const QStringList::ConstIterator itEnd = headers.end();
03861 
03862   for (; it != itEnd; ++it) {
03863     const QStringList header = (*it).split(QRegExp(":[ ]+"));
03864     if (header.count() != 2)
03865        continue;
03866     QTreeWidgetItem *item = new QTreeWidgetItem(ui._headers);
03867     item->setText(0, header[0]);
03868     item->setText(1, header[1]);
03869   }
03870 
03871   dlg->show();
03872   /* put no code here */
03873 }
03874 
03875 
03876 void KHTMLPart::slotViewFrameSource()
03877 {
03878   KParts::ReadOnlyPart *frame = currentFrame();
03879   if ( !frame )
03880     return;
03881 
03882   KUrl url = frame->url();
03883   bool isTempFile = false;
03884   if (!(url.isLocalFile()) && frame->inherits("KHTMLPart"))
03885   {
03886        long cacheId = static_cast<KHTMLPart *>(frame)->d->m_cacheId;
03887 
03888        if (KHTMLPageCache::self()->isComplete(cacheId))
03889        {
03890            KTemporaryFile sourceFile;
03891            sourceFile.setSuffix(defaultExtension());
03892            sourceFile.setAutoRemove(false);
03893            if (sourceFile.open())
03894            {
03895                QDataStream stream ( &sourceFile );
03896                KHTMLPageCache::self()->saveData(cacheId, &stream);
03897                url = KUrl();
03898                url.setPath(sourceFile.fileName());
03899                isTempFile = true;
03900            }
03901      }
03902   }
03903 
03904   (void) KRun::runUrl( url, QLatin1String("text/plain"), view(), isTempFile );
03905 }
03906 
03907 KUrl KHTMLPart::backgroundURL() const
03908 {
03909   // ### what about XML documents? get from CSS?
03910   if (!d->m_doc || !d->m_doc->isHTMLDocument())
03911     return KUrl();
03912 
03913   QString relURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
03914 
03915   return KUrl( url(), relURL );
03916 }
03917 
03918 void KHTMLPart::slotSaveBackground()
03919 {
03920   KIO::MetaData metaData;
03921   metaData["referrer"] = d->m_referrer;
03922   KHTMLPopupGUIClient::saveURL( d->m_view, i18n("Save Background Image As"), backgroundURL(), metaData );
03923 }
03924 
03925 void KHTMLPart::slotSaveDocument()
03926 {
03927   KUrl srcURL( url() );
03928 
03929   if ( srcURL.fileName(KUrl::ObeyTrailingSlash).isEmpty() )
03930     srcURL.setFileName( "index" + defaultExtension() );
03931 
03932   KIO::MetaData metaData;
03933   // Referre unknown?
03934   KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), srcURL, metaData, "text/html", d->m_cacheId );
03935 }
03936 
03937 void KHTMLPart::slotSecurity()
03938 {
03939 //   kDebug( 6050 ) << "Meta Data:" << endl
03940 //                   << d->m_ssl_peer_cert_subject
03941 //                   << endl
03942 //                   << d->m_ssl_peer_cert_issuer
03943 //                   << endl
03944 //                   << d->m_ssl_cipher
03945 //                   << endl
03946 //                   << d->m_ssl_cipher_desc
03947 //                   << endl
03948 //                   << d->m_ssl_cipher_version
03949 //                   << endl
03950 //                   << d->m_ssl_good_from
03951 //                   << endl
03952 //                   << d->m_ssl_good_until
03953 //                   << endl
03954 //                   << d->m_ssl_cert_state
03955 //                   << endl;
03956 
03957   //### reenable with new signature
03958 #if 0
03959   KSslInfoDialog *kid = new KSslInfoDialog(d->m_ssl_in_use, widget(), "kssl_info_dlg", true );
03960 
03961   const QStringList sl = d->m_ssl_peer_chain.split('\n', QString::SkipEmptyParts);
03962   QList<QSslCertificate> certChain;
03963   bool certChainOk = d->m_ssl_in_use;
03964   if (certChainOk) {
03965     foreach (const QString &s, sl) {
03966       certChain.append(QSslCertificate(s.toAscii())); //or is it toLocal8Bit or whatever?
03967       if (certChain.last().isNull()) {
03968         certChainOk = false;
03969         break;
03970       }
03971     }
03972   }
03973   if (certChainOk) {
03974     kid->setup(certChain,
03975                d->m_ssl_peer_ip,
03976                url().url(),
03977                d->m_ssl_cipher,
03978                d->m_ssl_cipher_desc,
03979                d->m_ssl_cipher_version,
03980                d->m_ssl_cipher_used_bits.toInt(),
03981                d->m_ssl_cipher_bits.toInt(),
03982                (KSSLCertificate::KSSLValidation) d->m_ssl_cert_state.toInt());
03983   }
03984   kid->exec();
03985   //the dialog deletes itself on close
03986 #endif
03987 
03988     KSslInfoDialog *kid = new KSslInfoDialog(0);
03989     //### This is boilerplate code and it's copied from SlaveInterface.
03990     QStringList sl = d->m_ssl_peer_chain.split('\x01', QString::SkipEmptyParts);
03991     QList<QSslCertificate> certChain;
03992     bool decodedOk = true;
03993     foreach (const QString &s, sl) {
03994         certChain.append(QSslCertificate(s.toAscii())); //or is it toLocal8Bit or whatever?
03995         if (certChain.last().isNull()) {
03996             decodedOk = false;
03997             break;
03998         }
03999     }
04000 
04001     if (decodedOk || true /*H4X*/) {
04002         kid->setSslInfo(certChain,
04003                         d->m_ssl_peer_ip,
04004                         url().host(),
04005                         d->m_ssl_protocol_version,
04006                         d->m_ssl_cipher,
04007                         d->m_ssl_cipher_used_bits.toInt(),
04008                         d->m_ssl_cipher_bits.toInt(),
04009                         KSslInfoDialog::errorsFromString(d->m_ssl_cert_errors));
04010         kDebug(7024) << "Showing SSL Info dialog";
04011         kid->exec();
04012         kDebug(7024) << "SSL Info dialog closed";
04013     } else {
04014         KMessageBox::information(0, i18n("The peer SSL certificate chain "
04015                                          "appears to be corrupt."),
04016                                  i18n("SSL"));
04017     }
04018 }
04019 
04020 void KHTMLPart::slotSaveFrame()
04021 {
04022     KParts::ReadOnlyPart *frame = currentFrame();
04023     if ( !frame )
04024         return;
04025 
04026     KUrl srcURL( frame->url() );
04027 
04028         if ( srcURL.fileName(KUrl::ObeyTrailingSlash).isEmpty() )
04029         srcURL.setFileName( "index" + defaultExtension() );
04030 
04031     KIO::MetaData metaData;
04032     // Referrer unknown?
04033     KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save Frame As" ), srcURL, metaData, "text/html" );
04034 }
04035 
04036 void KHTMLPart::slotSetEncoding(const QString &enc)
04037 {
04038     d->m_autoDetectLanguage=KEncodingDetector::None;
04039     setEncoding( enc, true);
04040 }
04041 
04042 void KHTMLPart::slotAutomaticDetectionLanguage(KEncodingDetector::AutoDetectScript scri)
04043 {
04044   d->m_autoDetectLanguage=scri;
04045   setEncoding( QString(), false );
04046 }
04047 
04048 void KHTMLPart::slotUseStylesheet()
04049 {
04050   if (d->m_doc)
04051   {
04052     bool autoselect = (d->m_paUseStylesheet->currentItem() == 0);
04053     d->m_sheetUsed = autoselect ? QString() : d->m_paUseStylesheet->currentText();
04054     d->m_doc->updateStyleSelector();
04055   }
04056 }
04057 
04058 void KHTMLPart::updateActions()
04059 {
04060   bool frames = false;
04061 
04062   QList<khtml::ChildFrame*>::ConstIterator it = d->m_frames.constBegin();
04063   const QList<khtml::ChildFrame*>::ConstIterator end = d->m_frames.constEnd();
04064   for (; it != end; ++it )
04065       if ( (*it)->m_type == khtml::ChildFrame::Frame )
04066       {
04067           frames = true;
04068           break;
04069       }
04070 
04071   if (d->m_paViewFrame)
04072     d->m_paViewFrame->setEnabled( frames );
04073   if (d->m_paSaveFrame)
04074     d->m_paSaveFrame->setEnabled( frames );
04075 
04076   if ( frames )
04077     d->m_paFind->setText( i18n( "&Find in Frame..." ) );
04078   else
04079     d->m_paFind->setText( i18n( "&Find..." ) );
04080 
04081   KParts::Part *frame = 0;
04082 
04083   if ( frames )
04084     frame = currentFrame();
04085 
04086   bool enableFindAndSelectAll = true;
04087 
04088   if ( frame )
04089     enableFindAndSelectAll = frame->inherits( "KHTMLPart" );
04090 
04091   d->m_paFind->setEnabled( enableFindAndSelectAll );
04092   d->m_paSelectAll->setEnabled( enableFindAndSelectAll );
04093 
04094   bool enablePrintFrame = false;
04095 
04096   if ( frame )
04097   {
04098     QObject *ext = KParts::BrowserExtension::childObject( frame );
04099     if ( ext )
04100       enablePrintFrame = ext->metaObject()->indexOfSlot( "print()" ) != -1;
04101   }
04102 
04103   d->m_paPrintFrame->setEnabled( enablePrintFrame );
04104 
04105   QString bgURL;
04106 
04107   // ### frames
04108   if ( d->m_doc && d->m_doc->isHTMLDocument() && static_cast<HTMLDocumentImpl*>(d->m_doc)->body() && !d->m_bClearing )
04109     bgURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
04110 
04111   if (d->m_paSaveBackground)
04112     d->m_paSaveBackground->setEnabled( !bgURL.isEmpty() );
04113 
04114   if ( d->m_paDebugScript )
04115     d->m_paDebugScript->setEnabled( d->m_frame ? d->m_frame->m_jscript : 0L );
04116 }
04117 
04118 KParts::LiveConnectExtension *KHTMLPart::liveConnectExtension( const DOM::NodeImpl *frame) {
04119     const ConstFrameIt end = d->m_objects.constEnd();
04120     for(ConstFrameIt it = d->m_objects.constBegin(); it != end; ++it )
04121         if ((*it)->m_partContainerElement == frame)
04122             return (*it)->m_liveconnect;
04123     return 0L;
04124 }
04125 
04126 bool KHTMLPart::requestFrame( DOM::HTMLPartContainerElementImpl *frame, const QString &url,
04127                               const QString &frameName, const QStringList &params, bool isIFrame )
04128 {
04129   //kDebug( 6050 ) << this << " requestFrame( ..., " << url << ", " << frameName << " )";
04130   FrameIt it = d->m_frames.find( frameName );
04131   if ( it == d->m_frames.end() )
04132   {
04133     khtml::ChildFrame * child = new khtml::ChildFrame;
04134     //kDebug( 6050 ) << "inserting new frame into frame map " << frameName;
04135     child->m_name = frameName;
04136     it = d->m_frames.insert( d->m_frames.end(), child );
04137   }
04138 
04139   (*it)->m_type = isIFrame ? khtml::ChildFrame::IFrame : khtml::ChildFrame::Frame;
04140   (*it)->m_partContainerElement = frame;
04141   (*it)->m_params = params;
04142 
04143   // Support for <frame src="javascript:string">
04144   if ( d->isJavaScriptURL(url) )
04145   {
04146     if ( processObjectRequest(*it, KUrl("about:blank"), QString("text/html") ) ) {
04147       KHTMLPart* p = static_cast<KHTMLPart*>(static_cast<KParts::ReadOnlyPart *>((*it)->m_part));
04148 
04149       // See if we want to replace content with javascript: output..
04150       QVariant res = p->executeScript( DOM::Node(),
04151                                        d->codeForJavaScriptURL(url) );
04152       if ( res.type() == QVariant::String && p->d->m_redirectURL.isEmpty() ) {
04153         p->begin();
04154         p->setAlwaysHonourDoctype(); // Disable public API compat; it messes with doctype
04155         // We recreated the document, so propagate domain again.
04156         d->propagateInitialDomainTo( p );
04157         p->write( res.toString() );
04158         p->end();
04159       }
04160       return true;
04161     }
04162     return false;
04163   }
04164   KUrl u = url.isEmpty() ? KUrl() : completeURL( url );
04165   return requestObject( *it, u );
04166 }
04167 
04168 QString KHTMLPart::requestFrameName()
04169 {
04170    return QString::fromLatin1("<!--frame %1-->").arg(d->m_frameNameId++);
04171 }
04172 
04173 bool KHTMLPart::requestObject( DOM::HTMLPartContainerElementImpl *frame, const QString &url,
04174                                const QString &serviceType, const QStringList &params )
04175 {
04176   //kDebug( 6005 ) << this << "frame=" << frame;
04177   khtml::ChildFrame *child = new khtml::ChildFrame;
04178   FrameIt it = d->m_objects.insert( d->m_objects.end(), child );
04179   (*it)->m_partContainerElement = frame;
04180   (*it)->m_type = khtml::ChildFrame::Object;
04181   (*it)->m_params = params;
04182 
04183   KParts::OpenUrlArguments args;
04184   args.setMimeType(serviceType);
04185   if (!requestObject( *it, completeURL( url ), args ) && !(*it)->m_run) {
04186       (*it)->m_bCompleted = true;
04187       return false;
04188   }
04189   return true;
04190 }
04191 
04192 bool KHTMLPart::requestObject( khtml::ChildFrame *child, const KUrl &url, const KParts::OpenUrlArguments &_args,
04193                                const KParts::BrowserArguments& browserArgs )
04194 {
04195   if (!checkLinkSecurity(url))
04196   {
04197     kDebug(6005) << this << "checkLinkSecurity refused";
04198     return false;
04199   }
04200 
04201   if (d->m_bClearing)
04202   {
04203     return false;
04204   }
04205 
04206   if ( child->m_bPreloaded )
04207   {
04208     kDebug(6005) << "preload";
04209     if ( child->m_partContainerElement && child->m_part )
04210       child->m_partContainerElement->setWidget( child->m_part->widget() );
04211 
04212     child->m_bPreloaded = false;
04213     return true;
04214   }
04215 
04216   //kDebug(6005) << "child=" << child << "child->m_part=" << child->m_part;
04217 
04218   KParts::OpenUrlArguments args( _args );
04219 
04220   if ( child->m_run )
04221     child->m_run->abort();
04222 
04223   if ( child->m_part && !args.reload() && urlcmp( child->m_part->url().url(), url.url(), KUrl::CompareWithoutTrailingSlash | KUrl::CompareWithoutFragment ) )
04224     args.setMimeType(child->m_serviceType);
04225 
04226   child->m_browserArgs = browserArgs;
04227   child->m_args = args;
04228 
04229   // reload/soft-reload arguments are always inherited from parent
04230   child->m_args.setReload( arguments().reload() );
04231   child->m_browserArgs.softReload = d->m_extension->browserArguments().softReload;
04232 
04233   child->m_serviceName.clear();
04234   if (!d->m_referrer.isEmpty() && !child->m_args.metaData().contains( "referrer" ))
04235     child->m_args.metaData()["referrer"] = d->m_referrer;
04236 
04237   child->m_args.metaData().insert("PropagateHttpHeader", "true");
04238   child->m_args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
04239   child->m_args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
04240   child->m_args.metaData().insert("main_frame_request",
04241                                   parentPart() == 0 ? "TRUE":"FALSE");
04242   child->m_args.metaData().insert("ssl_was_in_use",
04243                                   d->m_ssl_in_use ? "TRUE":"FALSE");
04244   child->m_args.metaData().insert("ssl_activate_warnings", "TRUE");
04245   child->m_args.metaData().insert("cross-domain", toplevelURL().url());
04246 
04247   // We want a KHTMLPart if the HTML says <frame src=""> or <frame src="about:blank">
04248   if ((url.isEmpty() || url.url() == "about:blank") && args.mimeType().isEmpty())
04249     args.setMimeType(QLatin1String("text/html"));
04250 
04251   if ( args.mimeType().isEmpty() ) {
04252     kDebug(6050) << "Running new KHTMLRun for" << this << "and child=" << child;
04253     child->m_run = new KHTMLRun( this, child, url, child->m_args, child->m_browserArgs, true );
04254     d->m_bComplete = false; // ensures we stop it in checkCompleted...
04255     return false;
04256   } else {
04257     return processObjectRequest( child, url, args.mimeType() );
04258   }
04259 }
04260 
04261 void KHTMLPart::childLoadFailure( khtml::ChildFrame *child )
04262 {
04263   child->m_bCompleted = true;
04264   if ( child->m_partContainerElement )
04265     child->m_partContainerElement->partLoadingErrorNotify();
04266 
04267   checkCompleted();
04268 }
04269 
04270 bool KHTMLPart::processObjectRequest( khtml::ChildFrame *child, const KUrl &_url, const QString &mimetype )
04271 {
04272   //kDebug( 6050 ) << "trying to create part for" << mimetype;
04273 
04274   // IMPORTANT: create a copy of the url here, because it is just a reference, which was likely to be given
04275   // by an emitting frame part (emit openUrlRequest( blahurl, ... ) . A few lines below we delete the part
04276   // though -> the reference becomes invalid -> crash is likely
04277   KUrl url( _url );
04278 
04279   // khtmlrun called us this way to indicate a loading error
04280   if ( d->m_onlyLocalReferences || ( url.isEmpty() && mimetype.isEmpty() ) )
04281   {
04282       childLoadFailure(child);
04283       return true;
04284   }
04285 
04286   // we also want to ignore any spurious requests due to closing when parser is being cleared. These should be
04287   // ignored entirely  --- the tail end of ::clear will clean things up.
04288   if (d->m_bClearing)
04289       return false;
04290 
04291   if (child->m_bNotify)
04292   {
04293       child->m_bNotify = false;
04294       if ( !child->m_browserArgs.lockHistory() )
04295           emit d->m_extension->openUrlNotify();
04296   }
04297 
04298   if ( child->m_serviceType != mimetype || !child->m_part || (child->m_run && child->m_run->serverSuggestsSave()))
04299   {
04300     // We often get here if we didn't know the mimetype in advance, and had to rely
04301     // on KRun to figure it out. In this case, we let the element check if it wants to
04302     // handle this mimetype itself, for e.g. images.
04303     if ( child->m_partContainerElement &&
04304          child->m_partContainerElement->mimetypeHandledInternally(mimetype) ) {
04305       child->m_bCompleted = true;
04306       checkCompleted();
04307       return true;
04308     }
04309 
04310     // Before attempting to load a part, check if the user wants that.
04311     // Many don't like getting ZIP files embedded.
04312     // However we don't want to ask for flash and other plugin things..
04313     if ( child->m_type != khtml::ChildFrame::Object && child->m_type != khtml::ChildFrame::IFrame )
04314     {
04315       QString suggestedFileName;
04316       int disposition = 0;
04317       if ( child->m_run ) {
04318         suggestedFileName = child->m_run->suggestedFileName();
04319         disposition = (child->m_run->serverSuggestsSave()) ? KParts::BrowserRun::AttachmentDisposition : KParts::BrowserRun::InlineDisposition;
04320       }
04321 
04322       KParts::BrowserRun::AskSaveResult res = KParts::BrowserRun::askEmbedOrSave(
04323         url, mimetype, suggestedFileName, disposition );
04324       switch( res ) {
04325       case KParts::BrowserRun::Save:
04326         KHTMLPopupGUIClient::saveURL( widget(), i18n( "Save As" ), url, child->m_args.metaData(), QString(), 0, suggestedFileName );
04327         // fall-through
04328       case KParts::BrowserRun::Cancel:
04329         child->m_bCompleted = true;
04330         checkCompleted();
04331         return true; // done
04332       default: // Open
04333         break;
04334       }
04335     }
04336 
04337     KMimeType::Ptr mime = KMimeType::mimeType(mimetype);
04338     if (mime) {
04339         // If KHTMLPart can handle the frame, then let's force using it, even
04340         // if the normally preferred part is another one, so that cross-frame
04341         // scripting can work.
04342         if (mime->is("text/html")
04343             || mime->is("application/xml")) { // this includes xhtml and svg
04344             child->m_serviceName = "khtml";
04345         }
04346     }
04347 
04348     QStringList dummy; // the list of servicetypes handled by the part is now unused.
04349     KParts::ReadOnlyPart *part = createPart( d->m_view->viewport(), this, mimetype, child->m_serviceName, dummy, child->m_params );
04350 
04351     if ( !part )
04352     {
04353         childLoadFailure(child);
04354         return false;
04355     }
04356 
04357     part->setObjectName( child->m_name );
04358 
04359     //CRITICAL STUFF
04360     if ( child->m_part )
04361     {
04362       if (!qobject_cast<KHTMLPart*>(child->m_part) && child->m_jscript)
04363           child->m_jscript->clear();
04364       partManager()->removePart( (KParts::ReadOnlyPart *)child->m_part );
04365       delete (KParts::ReadOnlyPart *)child->m_part;
04366       if (child->m_liveconnect) {
04367         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 &)));
04368         child->m_liveconnect = 0L;
04369       }
04370     }
04371 
04372     child->m_serviceType = mimetype;
04373     if ( child->m_partContainerElement && part->widget() )
04374       child->m_partContainerElement->setWidget( part->widget() );
04375 
04376     if ( child->m_type != khtml::ChildFrame::Object )
04377       partManager()->addPart( part, false );
04378 //  else
04379 //      kDebug(6005) << "AH! NO FRAME!!!!!";
04380 
04381     child->m_part = part;
04382 
04383     if (qobject_cast<KHTMLPart*>(part)) {
04384       static_cast<KHTMLPart*>(part)->d->m_frame = child;
04385     } else if (child->m_partContainerElement) {
04386       child->m_liveconnect = KParts::LiveConnectExtension::childObject(part);
04387       if (child->m_liveconnect)
04388         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 &)));
04389     }
04390     KParts::StatusBarExtension *sb = KParts::StatusBarExtension::childObject(part);
04391     if (sb)
04392       sb->setStatusBar( d->m_statusBarExtension->statusBar() );
04393 
04394     connect( part, SIGNAL( started( KIO::Job *) ),
04395              this, SLOT( slotChildStarted( KIO::Job *) ) );
04396     connect( part, SIGNAL( completed() ),
04397              this, SLOT( slotChildCompleted() ) );
04398     connect( part, SIGNAL( completed(bool) ),
04399              this, SLOT( slotChildCompleted(bool) ) );
04400     connect( part, SIGNAL( setStatusBarText( const QString & ) ),
04401                 this, SIGNAL( setStatusBarText( const QString & ) ) );
04402     if ( part->inherits( "KHTMLPart" ) )
04403     {
04404       connect( this, SIGNAL( completed() ),
04405                part, SLOT( slotParentCompleted() ) );
04406       connect( this, SIGNAL( completed(bool) ),
04407                part, SLOT( slotParentCompleted() ) );
04408       // As soon as the child's document is created, we need to set its domain
04409       // (but we do so only once, so it can't be simply done in the child)
04410       connect( part, SIGNAL( docCreated() ),
04411                this, SLOT( slotChildDocCreated() ) );
04412     }
04413 
04414     child->m_extension = KParts::BrowserExtension::childObject( part );
04415 
04416     if ( child->m_extension )
04417     {
04418       connect( child->m_extension, SIGNAL( openUrlNotify() ),
04419                d->m_extension, SIGNAL( openUrlNotify() ) );
04420 
04421       connect( child->m_extension, SIGNAL( openUrlRequestDelayed( const KUrl &, const KParts::OpenUrlArguments&, const KParts::BrowserArguments & ) ),
04422                this, SLOT( slotChildURLRequest( const KUrl &, const KParts::OpenUrlArguments&, const KParts::BrowserArguments & ) ) );
04423 
04424       connect( child->m_extension, SIGNAL( createNewWindow( const KUrl &, const KParts::OpenUrlArguments&, const KParts::BrowserArguments &, const KParts::WindowArgs &, KParts::ReadOnlyPart ** ) ),
04425                d->m_extension, SIGNAL( createNewWindow( const KUrl &, const KParts::OpenUrlArguments&, const KParts::BrowserArguments & , const KParts::WindowArgs &, KParts::ReadOnlyPart **) ) );
04426 
04427       connect( child->m_extension, SIGNAL(popupMenu(QPoint,KFileItemList,KParts::OpenUrlArguments,KParts::BrowserArguments,KParts::BrowserExtension::PopupFlags,KParts::BrowserExtension::ActionGroupMap)),
04428              d->m_extension, SIGNAL(popupMenu(QPoint,KFileItemList,KParts::OpenUrlArguments,KParts::BrowserArguments,KParts::BrowserExtension::PopupFlags,KParts::BrowserExtension::ActionGroupMap)) );
04429       connect( child->m_extension, SIGNAL(popupMenu(QPoint,KUrl,mode_t,KParts::OpenUrlArguments,KParts::BrowserArguments,KParts::BrowserExtension::PopupFlags,KParts::BrowserExtension::ActionGroupMap)),
04430              d->m_extension, SIGNAL(popupMenu(QPoint,KUrl,mode_t,KParts::OpenUrlArguments,KParts::BrowserArguments,KParts::BrowserExtension::PopupFlags,KParts::BrowserExtension::ActionGroupMap)) );
04431 
04432       connect( child->m_extension, SIGNAL( infoMessage( const QString & ) ),
04433                d->m_extension, SIGNAL( infoMessage( const QString & ) ) );
04434 
04435       connect( child->m_extension, SIGNAL( requestFocus( KParts::ReadOnlyPart * ) ),
04436                this, SLOT( slotRequestFocus( KParts::ReadOnlyPart * ) ) );
04437 
04438       child->m_extension->setBrowserInterface( d->m_extension->browserInterface() );
04439     }
04440   }
04441   else if ( child->m_partContainerElement && child->m_part &&
04442             child->m_partContainerElement->childWidget() != child->m_part->widget() )
04443     child->m_partContainerElement->setWidget( child->m_part->widget() );
04444 
04445   checkEmitLoadEvent();
04446   // Some JS code in the load event may have destroyed the part
04447   // In that case, abort
04448   if ( !child->m_part )
04449     return false;
04450 
04451   if ( child->m_bPreloaded )
04452   {
04453     if ( child->m_partContainerElement && child->m_part )
04454       child->m_partContainerElement->setWidget( child->m_part->widget() );
04455 
04456     child->m_bPreloaded = false;
04457     return true;
04458   }
04459 
04460   // reload/soft-reload arguments are always inherited from parent
04461   child->m_args.setReload( arguments().reload() );
04462   child->m_browserArgs.softReload = d->m_extension->browserArguments().softReload;
04463 
04464   // make sure the part has a way to find out about the mimetype.
04465   // we actually set it in child->m_args in requestObject already,
04466   // but it's useless if we had to use a KHTMLRun instance, as the
04467   // point the run object is to find out exactly the mimetype.
04468   child->m_args.setMimeType(mimetype);
04469 
04470   // if not a frame set child as completed
04471   child->m_bCompleted = child->m_type == khtml::ChildFrame::Object;
04472 
04473   if ( child->m_part ) {
04474     child->m_part->setArguments( child->m_args );
04475   }
04476   if ( child->m_extension ) {
04477     child->m_extension->setBrowserArguments( child->m_browserArgs );
04478   }
04479 
04480   if(url.protocol() == "javascript" || url.url() == "about:blank") {
04481       if (!child->m_part->inherits("KHTMLPart"))
04482           return false;
04483 
04484       KHTMLPart* p = static_cast<KHTMLPart*>(static_cast<KParts::ReadOnlyPart *>(child->m_part));
04485 
04486       p->begin();
04487       if (d->m_doc && p->d->m_doc)
04488         p->d->m_doc->setBaseURL(d->m_doc->baseURL());
04489 
04490       // We may have to re-propagate the domain here if we go here due to navigation
04491       d->propagateInitialDomainTo(p);
04492 
04493       if (!url.url().startsWith("about:")) {
04494         p->write(url.path());
04495       } else {
04496         p->setUrl(url);
04497         // we need a body element. testcase: <iframe id="a"></iframe><script>alert(a.document.body);</script>
04498         p->write("<HTML><TITLE></TITLE><BODY></BODY></HTML>");
04499       }
04500       p->end();
04501       return true;
04502   }
04503   else if ( !url.isEmpty() )
04504   {
04505       //kDebug( 6050 ) << "opening" << url << "in frame" << child->m_part;
04506       bool b = child->m_part->openUrl( url );
04507       if (child->m_bCompleted)
04508           checkCompleted();
04509       return b;
04510   }
04511   else
04512   {
04513       child->m_bCompleted = true;
04514       checkCompleted();
04515       return true;
04516   }
04517 }
04518 
04519 KParts::ReadOnlyPart *KHTMLPart::createPart( QWidget *parentWidget,
04520                                              QObject *parent, const QString &mimetype,
04521                                              QString &serviceName, QStringList &serviceTypes,
04522                                              const QStringList &params )
04523 {
04524   QString constr;
04525   if ( !serviceName.isEmpty() )
04526     constr.append( QString::fromLatin1( "DesktopEntryName == '%1'" ).arg( serviceName ) );
04527 
04528   KService::List offers = KMimeTypeTrader::self()->query( mimetype, "KParts/ReadOnlyPart", constr );
04529 
04530   if ( offers.isEmpty() ) {
04531     int pos = mimetype.indexOf( "-plugin" );
04532     if (pos < 0)
04533         return 0L;
04534     QString stripped_mime = mimetype.left( pos );
04535     offers = KMimeTypeTrader::self()->query( stripped_mime, "KParts/ReadOnlyPart", constr );
04536     if ( offers.isEmpty() )
04537         return 0L;
04538   }
04539 
04540   KService::List::ConstIterator it = offers.constBegin();
04541   const KService::List::ConstIterator itEnd = offers.constEnd();
04542   for ( ; it != itEnd; ++it )
04543   {
04544     KService::Ptr service = (*it);
04545 
04546     KPluginLoader loader( *service, KHTMLGlobal::componentData() );
04547     KPluginFactory* const factory = loader.factory();
04548     if ( factory ) {
04549       // Turn params into a QVariantList as expected by KPluginFactory
04550       QVariantList variantlist;
04551       Q_FOREACH(const QString& str, params)
04552           variantlist << QVariant(str);
04553 
04554       if ( service->serviceTypes().contains( "Browser/View" ) )
04555         variantlist << QString("Browser/View");
04556 
04557       KParts::ReadOnlyPart* part = factory->create<KParts::ReadOnlyPart>(parentWidget, parent, QString(), variantlist);
04558       if ( part ) {
04559         serviceTypes = service->serviceTypes();
04560         serviceName = service->name();
04561         return part;
04562       }
04563     } else {
04564       // TODO KMessageBox::error and i18n, like in KonqFactory::createView?
04565       kWarning() << QString("There was an error loading the module %1.\nThe diagnostics is:\n%2")
04566                       .arg(service->name()).arg(loader.errorString());
04567     }
04568   }
04569   return 0;
04570 }
04571 
04572 KParts::PartManager *KHTMLPart::partManager()
04573 {
04574   if ( !d->m_manager && d->m_view )
04575   {
04576     d->m_manager = new KParts::PartManager( d->m_view->topLevelWidget(), this );
04577     d->m_manager->setObjectName( "khtml part manager" );
04578     d->m_manager->setAllowNestedParts( true );
04579     connect( d->m_manager, SIGNAL( activePartChanged( KParts::Part * ) ),
04580              this, SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
04581     connect( d->m_manager, SIGNAL( partRemoved( KParts::Part * ) ),
04582              this, SLOT( slotPartRemoved( KParts::Part * ) ) );
04583   }
04584 
04585   return d->m_manager;
04586 }
04587 
04588 void KHTMLPart::submitFormAgain()
04589 {
04590   disconnect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
04591   if( d->m_doc && !d->m_doc->parsing() && d->m_submitForm)
04592     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 );
04593 
04594   delete d->m_submitForm;
04595   d->m_submitForm = 0;
04596 }
04597 
04598 void KHTMLPart::submitFormProxy( const char *action, const QString &url, const QByteArray &formData, const QString &_target, const QString& contentType, const QString& boundary )
04599 {
04600   submitForm(action, url, formData, _target, contentType, boundary);
04601 }
04602 
04603 void KHTMLPart::submitForm( const char *action, const QString &url, const QByteArray &formData, const QString &_target, const QString& contentType, const QString& boundary )
04604 {
04605   kDebug(6000) << this << "target=" << _target << "url=" << url;
04606   if (d->m_formNotification == KHTMLPart::Only) {
04607     emit formSubmitNotification(action, url, formData, _target, contentType, boundary);
04608     return;
04609   } else if (d->m_formNotification == KHTMLPart::Before) {
04610     emit formSubmitNotification(action, url, formData, _target, contentType, boundary);
04611   }
04612 
04613   KUrl u = completeURL( url );
04614 
04615   if ( !u.isValid() )
04616   {
04617     // ### ERROR HANDLING!
04618     return;
04619   }
04620 
04621   // Form security checks
04622   //
04623   /*
04624    * If these form security checks are still in this place in a month or two
04625    * I'm going to simply delete them.
04626    */
04627 
04628   /* This is separate for a reason.  It has to be _before_ all script, etc,
04629    * AND I don't want to break anything that uses checkLinkSecurity() in
04630    * other places.
04631    */
04632 
04633   if (!d->m_submitForm) {
04634     if (u.protocol() != "https" && u.protocol() != "mailto") {
04635       if (d->m_ssl_in_use) {    // Going from SSL -> nonSSL
04636         int rc = KMessageBox::warningContinueCancel(NULL, i18n("Warning:  This is a secure form but it is attempting to send your data back unencrypted."
04637                                                                "\nA third party may be able to intercept and view this information."
04638                                                                "\nAre you sure you wish to continue?"),
04639                                                     i18n("Network Transmission"),KGuiItem(i18n("&Send Unencrypted")));
04640         if (rc == KMessageBox::Cancel)
04641           return;
04642       } else {                  // Going from nonSSL -> nonSSL
04643         KSSLSettings kss(true);
04644         if (kss.warnOnUnencrypted()) {
04645           int rc = KMessageBox::warningContinueCancel(NULL,
04646                                                       i18n("Warning: Your data is about to be transmitted across the network unencrypted."
04647                                                            "\nAre you sure you wish to continue?"),
04648                                                       i18n("Network Transmission"),
04649                                                       KGuiItem(i18n("&Send Unencrypted")),
04650                                                       KStandardGuiItem::cancel(),
04651                                                       "WarnOnUnencryptedForm");
04652           // Move this setting into KSSL instead
04653           QString grpNotifMsgs = QLatin1String("Notification Messages");
04654           KConfigGroup cg( KGlobal::config(), grpNotifMsgs );
04655 
04656           if (!cg.readEntry("WarnOnUnencryptedForm", true)) {
04657             cg.deleteEntry("WarnOnUnencryptedForm");
04658             cg.sync();
04659             kss.setWarnOnUnencrypted(false);
04660             kss.save();
04661           }
04662           if (rc == KMessageBox::Cancel)
04663             return;
04664         }
04665       }
04666     }
04667 
04668     if (u.protocol() == "mailto") {
04669       int rc = KMessageBox::warningContinueCancel(NULL,
04670                                                   i18n("This site is attempting to submit form data via email.\n"
04671                                                        "Do you want to continue?"),
04672                                                   i18n("Network Transmission"),
04673                                                   KGuiItem(i18n("&Send Email")),
04674                                                   KStandardGuiItem::cancel(),
04675                                                   "WarnTriedEmailSubmit");
04676 
04677       if (rc == KMessageBox::Cancel) {
04678         return;
04679       }
04680     }
04681   }
04682 
04683   // End form security checks
04684   //
04685 
04686   QString urlstring = u.url();
04687 
04688   if ( d->isJavaScriptURL(urlstring) ) {
04689     crossFrameExecuteScript( _target, d->codeForJavaScriptURL(urlstring) );
04690     return;
04691   }
04692 
04693   if (!checkLinkSecurity(u,
04694                          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>" ),
04695                          i18n( "Submit" )))
04696     return;
04697 
04698   // OK. We're actually going to submit stuff. Clear any redirections,
04699   // we should win over them
04700   d->clearRedirection();
04701 
04702   KParts::OpenUrlArguments args;
04703 
04704   if (!d->m_referrer.isEmpty())
04705      args.metaData()["referrer"] = d->m_referrer;
04706 
04707   args.metaData().insert("PropagateHttpHeader", "true");
04708   args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
04709   args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
04710   args.metaData().insert("main_frame_request",
04711                          parentPart() == 0 ? "TRUE":"FALSE");
04712   args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
04713   args.metaData().insert("ssl_activate_warnings", "TRUE");
04714 //WABA: When we post a form we should treat it as the main url
04715 //the request should never be considered cross-domain
04716 //args.metaData().insert("cross-domain", toplevelURL().url());
04717   KParts::BrowserArguments browserArgs;
04718   browserArgs.frameName = _target.isEmpty() ? d->m_doc->baseTarget() : _target ;
04719 
04720   // Handle mailto: forms
04721   if (u.protocol() == "mailto") {
04722       // 1)  Check for attach= and strip it
04723       QString q = u.query().mid(1);
04724       QStringList nvps = q.split("&");
04725       bool triedToAttach = false;
04726 
04727       QStringList::Iterator nvp = nvps.begin();
04728       const QStringList::Iterator nvpEnd = nvps.end();
04729 
04730 // cannot be a for loop as if something is removed we don't want to do ++nvp, as
04731 // remove returns an iterator pointing to the next item
04732 
04733       while (nvp != nvpEnd) {
04734          const QStringList pair = (*nvp).split("=");
04735          if (pair.count() >= 2) {
04736             if (pair.first().toLower() == "attach") {
04737                nvp = nvps.erase(nvp);
04738                triedToAttach = true;
04739             } else {
04740                ++nvp;
04741             }
04742          } else {
04743             ++nvp;
04744          }
04745       }
04746 
04747       if (triedToAttach)
04748          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");
04749 
04750       // 2)  Append body=
04751       QString bodyEnc;
04752       if (contentType.toLower() == "multipart/form-data") {
04753          // FIXME: is this correct?  I suspect not
04754          bodyEnc = QLatin1String( KUrl::toPercentEncoding(QString::fromLatin1(formData.data(),
04755                                                            formData.size())));
04756       } else if (contentType.toLower() == "text/plain") {
04757          // Convention seems to be to decode, and s/&/\n/
04758          QString tmpbody = QString::fromLatin1(formData.data(),
04759                                                formData.size());
04760          tmpbody.replace(QRegExp("[&]"), "\n");
04761          tmpbody.replace(QRegExp("[+]"), " ");
04762          tmpbody = KUrl::fromPercentEncoding(tmpbody.toLatin1());  // Decode the rest of it
04763          bodyEnc = QLatin1String( KUrl::toPercentEncoding(tmpbody) );  // Recode for the URL
04764       } else {
04765          bodyEnc = QLatin1String( KUrl::toPercentEncoding(QString::fromLatin1(formData.data(),
04766                                                            formData.size())) );
04767       }
04768 
04769       nvps.append(QString("body=%1").arg(bodyEnc));
04770       q = nvps.join("&");
04771       u.setQuery(q);
04772   }
04773 
04774   if ( strcmp( action, "get" ) == 0 ) {
04775     if (u.protocol() != "mailto")
04776        u.setQuery( QString::fromLatin1( formData.data(), formData.size() ) );
04777     browserArgs.setDoPost( false );
04778   }
04779   else {
04780     browserArgs.postData = formData;
04781     browserArgs.setDoPost( true );
04782 
04783     // construct some user headers if necessary
04784     if (contentType.isNull() || contentType == "application/x-www-form-urlencoded")
04785       browserArgs.setContentType( "Content-Type: application/x-www-form-urlencoded" );
04786     else // contentType must be "multipart/form-data"
04787       browserArgs.setContentType( "Content-Type: " + contentType + "; boundary=" + boundary );
04788   }
04789 
04790   if ( d->m_doc->parsing() || d->m_runningScripts > 0 ) {
04791     if( d->m_submitForm ) {
04792       kDebug(6000) << "ABORTING!";
04793       return;
04794     }
04795     d->m_submitForm = new KHTMLPartPrivate::SubmitForm;
04796     d->m_submitForm->submitAction = action;
04797     d->m_submitForm->submitUrl = url;
04798     d->m_submitForm->submitFormData = formData;
04799     d->m_submitForm->target = _target;
04800     d->m_submitForm->submitContentType = contentType;
04801     d->m_submitForm->submitBoundary = boundary;
04802     connect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
04803   }
04804   else
04805   {
04806     emit d->m_extension->openUrlRequest( u, args, browserArgs );
04807   }
04808 }
04809 
04810 void KHTMLPart::popupMenu( const QString &linkUrl )
04811 {
04812   KUrl popupURL;
04813   KUrl linkKUrl;
04814   KParts::OpenUrlArguments args;
04815   KParts::BrowserArguments browserArgs;
04816   QString referrer;
04817   KParts::BrowserExtension::PopupFlags itemflags=KParts::BrowserExtension::ShowBookmark | KParts::BrowserExtension::ShowReload;
04818 
04819   if ( linkUrl.isEmpty() ) { // click on background
04820     KHTMLPart* khtmlPart = this;
04821     while ( khtmlPart->parentPart() )
04822     {
04823       khtmlPart=khtmlPart->parentPart();
04824     }
04825     popupURL = khtmlPart->url();
04826     referrer = khtmlPart->pageReferrer();
04827     if (hasSelection())
04828       itemflags = KParts::BrowserExtension::ShowTextSelectionItems;
04829     else
04830       itemflags |= KParts::BrowserExtension::ShowNavigationItems;
04831   } else {               // click on link
04832     popupURL = completeURL( linkUrl );
04833     linkKUrl = popupURL;
04834     referrer = this->referrer();
04835     itemflags |= KParts::BrowserExtension::IsLink;
04836 
04837     if (!(d->m_strSelectedURLTarget).isEmpty() &&
04838            (d->m_strSelectedURLTarget.toLower() != "_top") &&
04839            (d->m_strSelectedURLTarget.toLower() != "_self") &&
04840            (d->m_strSelectedURLTarget.toLower() != "_parent")) {
04841       if (d->m_strSelectedURLTarget.toLower() == "_blank")
04842         browserArgs.setForcesNewWindow(true);
04843       else {
04844         KHTMLPart *p = this;
04845         while (p->parentPart())
04846           p = p->parentPart();
04847         if (!p->frameExists(d->m_strSelectedURLTarget))
04848           browserArgs.setForcesNewWindow(true);
04849       }
04850     }
04851   }
04852 
04853   // Danger, Will Robinson. The Popup might stay around for a much
04854   // longer time than KHTMLPart. Deal with it.
04855   KHTMLPopupGUIClient* client = new KHTMLPopupGUIClient( this, linkKUrl );
04856   QPointer<QObject> guard( client );
04857 
04858   QString mimetype = QLatin1String( "text/html" );
04859   args.metaData()["referrer"] = referrer;
04860 
04861   if (!linkUrl.isEmpty())                                // over a link
04862   {
04863     if (popupURL.isLocalFile())                                // safe to do this
04864     {
04865       mimetype = KMimeType::findByUrl(popupURL,0,true,false)->name();
04866     }
04867     else                                                // look at "extension" of link
04868     {
04869       const QString fname(popupURL.fileName(KUrl::ObeyTrailingSlash));
04870       if (!fname.isEmpty() && !popupURL.hasRef() && popupURL.query().isEmpty())
04871       {
04872         KMimeType::Ptr pmt = KMimeType::findByPath(fname,0,true);
04873 
04874         // Further check for mime types guessed from the extension which,
04875         // on a web page, are more likely to be a script delivering content
04876         // of undecidable type. If the mime type from the extension is one
04877         // of these, don't use it.  Retain the original type 'text/html'.
04878         if (pmt->name() != KMimeType::defaultMimeType() &&
04879             !pmt->is("application/x-perl") &&
04880             !pmt->is("application/x-perl-module") &&
04881             !pmt->is("application/x-php") &&
04882             !pmt->is("application/x-python-bytecode") &&
04883             !pmt->is("application/x-python") &&
04884             !pmt->is("application/x-shellscript"))
04885           mimetype = pmt->name();
04886       }
04887     }
04888   }
04889 
04890   args.setMimeType(mimetype);
04891 
04892   emit d->m_extension->popupMenu( QCursor::pos(), popupURL, S_IFREG /*always a file*/,
04893                                   args, browserArgs, itemflags,
04894                                   client->actionGroups() );
04895 
04896   if ( !guard.isNull() ) {
04897      delete client;
04898      emit popupMenu(linkUrl, QCursor::pos());
04899      d->m_strSelectedURL.clear();
04900      d->m_strSelectedURLTarget.clear();
04901   }
04902 }
04903 
04904 void KHTMLPart::slotParentCompleted()
04905 {
04906   //kDebug(6050) << this;
04907   if ( !d->m_redirectURL.isEmpty() && !d->m_redirectionTimer.isActive() )
04908   {
04909     //kDebug(6050) << this << ": starting timer for child redirection -> " << d->m_redirectURL;
04910     d->m_redirectionTimer.setSingleShot( true );
04911     d->m_redirectionTimer.start( qMax(0, 1000 * d->m_delayRedirect) );
04912   }
04913 }
04914 
04915 void KHTMLPart::slotChildStarted( KIO::Job *job )
04916 {
04917   khtml::ChildFrame *child = frame( sender() );
04918 
04919   assert( child );
04920 
04921   child->m_bCompleted = false;
04922 
04923   if ( d->m_bComplete )
04924   {
04925 #if 0
04926     // WABA: Looks like this belongs somewhere else
04927     if ( !parentPart() ) // "toplevel" html document? if yes, then notify the hosting browser about the document (url) changes
04928     {
04929       emit d->m_extension->openURLNotify();
04930     }
04931 #endif
04932     d->m_bComplete = false;
04933     emit started( job );
04934   }
04935 }
04936 
04937 void KHTMLPart::slotChildCompleted()
04938 {
04939   slotChildCompleted( false );
04940 }
04941 
04942 void KHTMLPart::slotChildCompleted( bool pendingAction )
04943 {
04944   khtml::ChildFrame *child = frame( sender() );
04945 
04946   if ( child ) {
04947     kDebug(6050) << this << "child=" << child << "m_partContainerElement=" << child->m_partContainerElement;
04948     child->m_bCompleted = true;
04949     child->m_bPendingRedirection = pendingAction;
04950     child->m_args = KParts::OpenUrlArguments();
04951     child->m_browserArgs = KParts::BrowserArguments();
04952     // dispatch load event
04953     if (!qobject_cast<KHTMLPart*>(child->m_part))
04954         QTimer::singleShot(0, child->m_partContainerElement, SLOT(slotEmitLoadEvent()));
04955   }
04956   checkCompleted();
04957 }
04958 
04959 void KHTMLPart::slotChildDocCreated()
04960 {
04961   // Set domain to the frameset's domain
04962   // This must only be done when loading the frameset initially (#22039),
04963   // not when following a link in a frame (#44162).
04964   if (KHTMLPart* htmlFrame = qobject_cast<KHTMLPart*>(sender()))
04965     d->propagateInitialDomainTo( htmlFrame );
04966 
04967   // So it only happens once
04968   disconnect( sender(), SIGNAL( docCreated() ), this, SLOT( slotChildDocCreated() ) );
04969 }
04970 
04971 void KHTMLPartPrivate::propagateInitialDomainTo(KHTMLPart* kid)
04972 {
04973   // This method is used to propagate our domain information for
04974   // child frames, potentially widening to have less periods, and also
04975   // to provide a domain for about: or JavaScript: URLs altogether.
04976   // Note that DocumentImpl:;setDomain does the checking.
04977   if ( m_doc && kid->d->m_doc )
04978     kid->d->m_doc->setDomain( m_doc->domain() );
04979 }
04980 
04981 void KHTMLPart::slotChildURLRequest( const KUrl &url, const KParts::OpenUrlArguments& args, const KParts::BrowserArguments &browserArgs )
04982 {
04983   khtml::ChildFrame *child = frame( sender()->parent() );
04984   KHTMLPart *callingHtmlPart = const_cast<KHTMLPart *>(dynamic_cast<const KHTMLPart *>(sender()->parent()));
04985 
04986   // TODO: handle child target correctly! currently the script are always executed for the parent
04987   QString urlStr = url.url();
04988   if ( d->isJavaScriptURL(urlStr) ) {
04989       executeScript( DOM::Node(), d->codeForJavaScriptURL(urlStr) );
04990       return;
04991   }
04992 
04993   QString frameName = browserArgs.frameName.toLower();
04994   if ( !frameName.isEmpty() ) {
04995     if ( frameName == QLatin1String( "_top" ) )
04996     {
04997       emit d->m_extension->openUrlRequest( url, args, browserArgs );
04998       return;
04999     }
05000     else if ( frameName == QLatin1String( "_blank" ) )
05001     {
05002       emit d->m_extension->createNewWindow( url, args, browserArgs );
05003       return;
05004     }
05005     else if ( frameName == QLatin1String( "_parent" ) )
05006     {
05007       KParts::BrowserArguments newBrowserArgs( browserArgs );
05008       newBrowserArgs.frameName.clear();
05009       emit d->m_extension->openUrlRequest( url, args, newBrowserArgs );
05010       return;
05011     }
05012     else if ( frameName != QLatin1String( "_self" ) )
05013     {
05014       khtml::ChildFrame *_frame = recursiveFrameRequest( callingHtmlPart, url, args, browserArgs );
05015 
05016       if ( !_frame )
05017       {
05018         emit d->m_extension->openUrlRequest( url, args, browserArgs );
05019         return;
05020       }
05021 
05022       child = _frame;
05023     }
05024   }
05025 
05026   if ( child && child->m_type != khtml::ChildFrame::Object ) {
05027       // Inform someone that we are about to show something else.
05028       child->m_bNotify = true;
05029       requestObject( child, url, args, browserArgs );
05030   }  else if ( frameName== "_self" ) // this is for embedded objects (via <object>) which want to replace the current document
05031   {
05032       KParts::BrowserArguments newBrowserArgs( browserArgs );
05033       newBrowserArgs.frameName.clear();
05034       emit d->m_extension->openUrlRequest( url, args, newBrowserArgs );
05035   }
05036 }
05037 
05038 void KHTMLPart::slotRequestFocus( KParts::ReadOnlyPart * )
05039 {
05040   emit d->m_extension->requestFocus(this);
05041 }
05042 
05043 khtml::ChildFrame *KHTMLPart::frame( const QObject *obj )
05044 {
05045     assert( obj->inherits( "KParts::ReadOnlyPart" ) );
05046     const KParts::ReadOnlyPart* const part = static_cast<const KParts::ReadOnlyPart *>( obj );
05047 
05048     FrameIt it = d->m_frames.begin();
05049     const FrameIt end = d->m_frames.end();
05050     for (; it != end; ++it )
05051       if ( (KParts::ReadOnlyPart *)(*it)->m_part == part )
05052         return *it;
05053 
05054     FrameIt oi = d->m_objects.begin();
05055     const FrameIt oiEnd = d->m_objects.end();
05056     for (; oi != oiEnd; ++oi )
05057       if ( (KParts::ReadOnlyPart *)(*oi)->m_part == part )
05058         return *oi;
05059 
05060     return 0L;
05061 }
05062 
05063 //#define DEBUG_FINDFRAME
05064 
05065 bool KHTMLPart::checkFrameAccess(KHTMLPart *callingHtmlPart)
05066 {
05067   if (callingHtmlPart == this)
05068     return true; // trivial
05069 
05070   if (!xmlDocImpl()) {
05071 #ifdef DEBUG_FINDFRAME
05072     kDebug(6050) << "Empty part" << this << "URL = " << url();
05073 #endif
05074     return false; // we are empty?
05075   }
05076 
05077   // now compare the domains
05078   if (callingHtmlPart && callingHtmlPart->xmlDocImpl() && xmlDocImpl())  {
05079     DOM::DOMString actDomain = callingHtmlPart->xmlDocImpl()->domain();
05080     DOM::DOMString destDomain = xmlDocImpl()->domain();
05081 
05082 #ifdef DEBUG_FINDFRAME
05083     kDebug(6050) << "actDomain =" << actDomain.string() << "destDomain =" << destDomain.string();
05084 #endif
05085 
05086     if (actDomain == destDomain)
05087       return true;
05088   }
05089 #ifdef DEBUG_FINDFRAME
05090   else
05091   {
05092     kDebug(6050) << "Unknown part/domain" << callingHtmlPart << "tries to access part" << this;
05093   }
05094 #endif
05095   return false;
05096 }
05097 
05098 KHTMLPart *
05099 KHTMLPart::findFrameParent( KParts::ReadOnlyPart *callingPart, const QString &f, khtml::ChildFrame **childFrame )
05100 {
05101 #ifdef DEBUG_FINDFRAME
05102   kDebug(6050) << this << "URL =" << url() << "name =" << name() << "findFrameParent(" << f << ")";
05103 #endif
05104   // Check access
05105   KHTMLPart* const callingHtmlPart = dynamic_cast<KHTMLPart *>(callingPart);
05106 
05107   if (!checkFrameAccess(callingHtmlPart))
05108      return 0;
05109 
05110   if (!childFrame && !parentPart() && (objectName() == f))
05111      return this;
05112 
05113   FrameIt it = d->m_frames.find( f );
05114   const FrameIt end = d->m_frames.end();
05115   if ( it != end )
05116   {
05117 #ifdef DEBUG_FINDFRAME
05118      kDebug(6050) << "FOUND!";
05119 #endif
05120      if (childFrame)
05121         *childFrame = *it;
05122      return this;
05123   }
05124 
05125   it = d->m_frames.begin();
05126   for (; it != end; ++it )
05127   {
05128     KParts::ReadOnlyPart* const p = (*it)->m_part;
05129     if ( p && p->inherits( "KHTMLPart" ))
05130     {
05131       KHTMLPart* const frameParent = static_cast<KHTMLPart*>(p)->findFrameParent(callingPart, f, childFrame);
05132       if (frameParent)
05133          return frameParent;
05134     }
05135   }
05136   return 0;
05137 }
05138 
05139 
05140 KHTMLPart *KHTMLPart::findFrame( const QString &f )
05141 {
05142   khtml::ChildFrame *childFrame;
05143   KHTMLPart *parentFrame = findFrameParent(this, f, &childFrame);
05144   if (parentFrame)
05145   {
05146      KParts::ReadOnlyPart *p = childFrame->m_part;
05147      if ( p && p->inherits( "KHTMLPart" ))
05148         return static_cast<KHTMLPart *>(p);
05149   }
05150   return 0;
05151 }
05152 
05153 KParts::ReadOnlyPart *KHTMLPart::findFramePart(const QString &f)
05154 {
05155   khtml::ChildFrame *childFrame;
05156   return findFrameParent(this, f, &childFrame) ? static_cast<KParts::ReadOnlyPart *>(childFrame->m_part) : 0L;
05157 }
05158 
05159 KParts::ReadOnlyPart *KHTMLPart::currentFrame() const
05160 {
05161   KParts::ReadOnlyPart* part = (KParts::ReadOnlyPart*)(this);
05162   // Find active part in our frame manager, in case we are a frameset
05163   // and keep doing that (in case of nested framesets).
05164   // Just realized we could also do this recursively, calling part->currentFrame()...
05165   while ( part && part->inherits("KHTMLPart") &&
05166           static_cast<KHTMLPart *>(part)->d->m_frames.count() > 0 ) {
05167     KHTMLPart* frameset = static_cast<KHTMLPart *>(part);
05168     part = static_cast<KParts::ReadOnlyPart *>(frameset->partManager()->activePart());
05169     if ( !part ) return frameset;
05170   }
05171   return part;
05172 }
05173 
05174 bool KHTMLPart::frameExists( const QString &frameName )
05175 {
05176   FrameIt it = d->m_frames.find( frameName );
05177   if ( it == d->m_frames.end() )
05178     return false;
05179 
05180   // WABA: We only return true if the child actually has a frame
05181   // set. Otherwise we might find our preloaded-selve.
05182   // This happens when we restore the frameset.
05183   return (!(*it)->m_partContainerElement.isNull());
05184 }
05185 
05186 KJSProxy *KHTMLPart::framejScript(KParts::ReadOnlyPart *framePart)
05187 {
05188   KHTMLPart* const kp = qobject_cast<KHTMLPart*>(framePart);
05189   if (kp)
05190     return kp->jScript();
05191 
05192   FrameIt it = d->m_frames.begin();
05193   const FrameIt itEnd = d->m_frames.end();
05194 
05195   for (; it != itEnd; ++it)
05196     if (framePart == (*it)->m_part) {
05197       if (!(*it)->m_jscript)
05198         createJScript(*it);
05199       return (*it)->m_jscript;
05200     }
05201   return 0L;
05202 }
05203 
05204 KHTMLPart *KHTMLPart::parentPart()
05205 {
05206   return qobject_cast<KHTMLPart*>( parent() );
05207 }
05208 
05209 khtml::ChildFrame *KHTMLPart::recursiveFrameRequest( KHTMLPart *callingHtmlPart, const KUrl &url,
05210                                                      const KParts::OpenUrlArguments &args,
05211                                                      const KParts::BrowserArguments &browserArgs, bool callParent )
05212 {
05213 #ifdef DEBUG_FINDFRAME
05214   kDebug( 6050 ) << this << "frame = " << args.frameName << "url = " << url;
05215 #endif
05216   khtml::ChildFrame *childFrame;
05217   KHTMLPart *childPart = findFrameParent(callingHtmlPart, browserArgs.frameName, &childFrame);
05218   if (childPart)
05219   {
05220      if (childPart == this)
05221         return childFrame;
05222 
05223      childPart->requestObject( childFrame, url, args, browserArgs );
05224      return 0;
05225   }
05226 
05227   if ( parentPart() && callParent )
05228   {
05229      khtml::ChildFrame *res = parentPart()->recursiveFrameRequest( callingHtmlPart, url, args, browserArgs, callParent );
05230 
05231      if ( res )
05232        parentPart()->requestObject( res, url, args, browserArgs );
05233   }
05234 
05235   return 0L;
05236 }
05237 
05238 #ifdef DEBUG_SAVESTATE
05239 static int s_saveStateIndentLevel = 0;
05240 #endif
05241 
05242 void KHTMLPart::saveState( QDataStream &stream )
05243 {
05244 #ifdef DEBUG_SAVESTATE
05245   QString indent= QString().leftJustified( s_saveStateIndentLevel * 4, ' ' );
05246   const int indentLevel = s_saveStateIndentLevel++;
05247   kDebug( 6050 ) << indent << "saveState this=" << this << " '" << objectName() << "' saving URL " << url().url();
05248 #endif
05249 
05250   stream << url() << (qint32)d->m_view->contentsX() << (qint32)d->m_view->contentsY()
05251          << (qint32) d->m_view->contentsWidth() << (qint32) d->m_view->contentsHeight() << (qint32) d->m_view->marginWidth() << (qint32) d->m_view->marginHeight();
05252 
05253   // save link cursor position
05254   int focusNodeNumber;
05255   if (!d->m_focusNodeRestored)
05256       focusNodeNumber = d->m_focusNodeNumber;
05257   else if (d->m_doc && d->m_doc->focusNode())
05258       focusNodeNumber = d->m_doc->nodeAbsIndex(d->m_doc->focusNode());
05259   else
05260       focusNodeNumber = -1;
05261   stream << focusNodeNumber;
05262 
05263   // Save the doc's cache id.
05264   stream << d->m_cacheId;
05265 
05266   // Save the state of the document (Most notably the state of any forms)
05267   QStringList docState;
05268   if (d->m_doc)
05269   {
05270      docState = d->m_doc->docState();
05271   }
05272   stream << d->m_encoding << d->m_sheetUsed << docState;
05273 
05274   stream << d->m_zoomFactor;
05275   stream << d->m_fontScaleFactor;
05276 
05277   stream << d->m_httpHeaders;
05278   stream << d->m_pageServices;
05279   stream << d->m_pageReferrer;
05280 
05281   // Save ssl data
05282   stream << d->m_ssl_in_use
05283          << d->m_ssl_peer_chain
05284          << d->m_ssl_peer_ip
05285          << d->m_ssl_cipher
05286          << d->m_ssl_protocol_version
05287          << d->m_ssl_cipher_used_bits
05288          << d->m_ssl_cipher_bits
05289          << d->m_ssl_cert_errors
05290          << d->m_ssl_parent_ip
05291          << d->m_ssl_parent_cert;
05292 
05293 
05294   QStringList frameNameLst, frameServiceTypeLst, frameServiceNameLst;
05295   KUrl::List frameURLLst;
05296   QList<QByteArray> frameStateBufferLst;
05297   QList<int> frameTypeLst;
05298 
05299   ConstFrameIt it = d->m_frames.constBegin();
05300   const ConstFrameIt end = d->m_frames.constEnd();
05301   for (; it != end; ++it )
05302   {
05303     if ( !(*it)->m_part )
05304        continue;
05305 
05306     frameNameLst << (*it)->m_name;
05307     frameServiceTypeLst << (*it)->m_serviceType;
05308     frameServiceNameLst << (*it)->m_serviceName;
05309     frameURLLst << (*it)->m_part->url();
05310 
05311     QByteArray state;
05312     QDataStream frameStream( &state, QIODevice::WriteOnly );
05313 
05314     if ( (*it)->m_extension )
05315       (*it)->m_extension->saveState( frameStream );
05316 
05317     frameStateBufferLst << state;
05318 
05319     frameTypeLst << int( (*it)->m_type );
05320   }
05321 
05322   // Save frame data
05323   stream << (quint32) frameNameLst.count();
05324   stream << frameNameLst << frameServiceTypeLst << frameServiceNameLst << frameURLLst << frameStateBufferLst << frameTypeLst;
05325 #ifdef DEBUG_SAVESTATE
05326   s_saveStateIndentLevel = indentLevel;
05327 #endif
05328 }
05329 
05330 void KHTMLPart::restoreState( QDataStream &stream )
05331 {
05332   KUrl u;
05333   qint32 xOffset, yOffset, wContents, hContents, mWidth, mHeight;
05334   quint32 frameCount;
05335   QStringList frameNames, frameServiceTypes, docState, frameServiceNames;
05336   QList<int> frameTypes;
05337   KUrl::List frameURLs;
05338   QList<QByteArray> frameStateBuffers;
05339   QList<int> fSizes;
05340   QString encoding, sheetUsed;
05341   long old_cacheId = d->m_cacheId;
05342 
05343   stream >> u >> xOffset >> yOffset >> wContents >> hContents >> mWidth >> mHeight;
05344 
05345   d->m_view->setMarginWidth( mWidth );
05346   d->m_view->setMarginHeight( mHeight );
05347 
05348   // restore link cursor position
05349   // nth node is active. value is set in checkCompleted()
05350   stream >> d->m_focusNodeNumber;
05351   d->m_focusNodeRestored = false;
05352 
05353   stream >> d->m_cacheId;
05354 
05355   stream >> encoding >> sheetUsed >> docState;
05356 
05357   d->m_encoding = encoding;
05358   d->m_sheetUsed = sheetUsed;
05359 
05360   int zoomFactor;
05361   stream >> zoomFactor;
05362   setZoomFactor(zoomFactor);
05363 
05364   int fontScaleFactor;
05365   stream >> fontScaleFactor;
05366   setFontScaleFactor(fontScaleFactor);
05367 
05368   stream >> d->m_httpHeaders;
05369   stream >> d->m_pageServices;
05370   stream >> d->m_pageReferrer;
05371 
05372   // Restore ssl data
05373   stream >> d->m_ssl_in_use
05374          >> d->m_ssl_peer_chain
05375          >> d->m_ssl_peer_ip
05376          >> d->m_ssl_cipher
05377          >> d->m_ssl_protocol_version
05378          >> d->m_ssl_cipher_used_bits
05379          >> d->m_ssl_cipher_bits
05380          >> d->m_ssl_cert_errors
05381          >> d->m_ssl_parent_ip
05382          >> d->m_ssl_parent_cert;
05383 
05384   setPageSecurity( d->m_ssl_in_use ? Encrypted : NotCrypted );
05385 
05386   stream >> frameCount >> frameNames >> frameServiceTypes >> frameServiceNames
05387          >> frameURLs >> frameStateBuffers >> frameTypes;
05388 
05389   d->m_bComplete = false;
05390   d->m_bLoadEventEmitted = false;
05391 
05392 //   kDebug( 6050 ) << "docState.count() = " << docState.count();
05393 //   kDebug( 6050 ) << "m_url " << url().url() << " <-> " << u.url();
05394 //   kDebug( 6050 ) << "m_frames.count() " << d->m_frames.count() << " <-> " << frameCount;
05395 
05396   if (d->m_cacheId == old_cacheId && signed(frameCount) == d->m_frames.count())
05397   {
05398     // Partial restore
05399     d->m_redirectionTimer.stop();
05400 
05401     FrameIt fIt = d->m_frames.begin();
05402     const FrameIt fEnd = d->m_frames.end();
05403 
05404     for (; fIt != fEnd; ++fIt )
05405         (*fIt)->m_bCompleted = false;
05406 
05407     fIt = d->m_frames.begin();
05408 
05409     QStringList::ConstIterator fNameIt = frameNames.constBegin();
05410     QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.constBegin();
05411     QStringList::ConstIterator fServiceNameIt = frameServiceNames.constBegin();
05412     KUrl::List::ConstIterator fURLIt = frameURLs.constBegin();
05413     QList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.constBegin();
05414     QList<int>::ConstIterator fFrameTypeIt = frameTypes.constBegin();
05415 
05416     for (; fIt != fEnd; ++fIt, ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt, ++fFrameTypeIt )
05417     {
05418       khtml::ChildFrame* const child = *fIt;
05419 
05420 //      kDebug( 6050 ) <<  *fNameIt  << " ---- " <<  *fServiceTypeIt;
05421 
05422       if ( child->m_name != *fNameIt || child->m_serviceType != *fServiceTypeIt )
05423       {
05424         child->m_bPreloaded = true;
05425         child->m_name = *fNameIt;
05426         child->m_serviceName = *fServiceNameIt;
05427         child->m_type = static_cast<khtml::ChildFrame::Type>(*fFrameTypeIt);
05428         processObjectRequest( child, *fURLIt, *fServiceTypeIt );
05429       }
05430       if ( child->m_part )
05431       {
05432         child->m_bCompleted = false;
05433         if ( child->m_extension && !(*fBufferIt).isEmpty() )
05434         {
05435           QDataStream frameStream( *fBufferIt );
05436           child->m_extension->restoreState( frameStream );
05437         }
05438         else
05439           child->m_part->openUrl( *fURLIt );
05440       }
05441     }
05442 
05443     KParts::OpenUrlArguments args( arguments() );
05444     args.setXOffset(xOffset);
05445     args.setYOffset(yOffset);
05446     setArguments(args);
05447 
05448     KParts::BrowserArguments browserArgs( d->m_extension->browserArguments() );
05449     browserArgs.docState = docState;
05450     d->m_extension->setBrowserArguments(browserArgs);
05451 
05452     d->m_view->resizeContents( wContents, hContents );
05453     d->m_view->setContentsPos( xOffset, yOffset );
05454 
05455     setUrl(u);
05456   }
05457   else
05458   {
05459     // Full restore.
05460     closeUrl();
05461     // We must force a clear because we want to be sure to delete all
05462     // frames.
05463     d->m_bCleared = false;
05464     clear();
05465     d->m_encoding = encoding;
05466     d->m_sheetUsed = sheetUsed;
05467 
05468     QStringList::ConstIterator fNameIt = frameNames.constBegin();
05469     const QStringList::ConstIterator fNameEnd = frameNames.constEnd();
05470 
05471     QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.constBegin();
05472     QStringList::ConstIterator fServiceNameIt = frameServiceNames.constBegin();
05473     KUrl::List::ConstIterator fURLIt = frameURLs.constBegin();
05474     QList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.constBegin();
05475     QList<int>::ConstIterator fFrameTypeIt = frameTypes.constBegin();
05476 
05477     for (; fNameIt != fNameEnd; ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt, ++fFrameTypeIt )
05478     {
05479       khtml::ChildFrame* const newChild = new khtml::ChildFrame;
05480       newChild->m_bPreloaded = true;
05481       newChild->m_name = *fNameIt;
05482       newChild->m_serviceName = *fServiceNameIt;
05483       newChild->m_type = static_cast<khtml::ChildFrame::Type>(*fFrameTypeIt);
05484 
05485 //      kDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt;
05486 
05487       const FrameIt childFrame = d->m_frames.insert( d->m_frames.end(), newChild );
05488 
05489       processObjectRequest( *childFrame, *fURLIt, *fServiceTypeIt );
05490 
05491       (*childFrame)->m_bPreloaded = true;
05492 
05493       if ( (*childFrame)->m_part )
05494       {
05495         if ( (*childFrame)->m_extension && !(*fBufferIt).isEmpty() )
05496         {
05497           QDataStream frameStream( *fBufferIt );
05498           (*childFrame)->m_extension->restoreState( frameStream );
05499         }
05500         else
05501           (*childFrame)->m_part->openUrl( *fURLIt );
05502       }
05503     }
05504 
05505     KParts::OpenUrlArguments args( arguments() );
05506     args.setXOffset(xOffset);
05507     args.setYOffset(yOffset);
05508     setArguments(args);
05509 
05510     KParts::BrowserArguments browserArgs( d->m_extension->browserArguments() );
05511     browserArgs.docState = docState;
05512     d->m_extension->setBrowserArguments(browserArgs);
05513 
05514     if (!KHTMLPageCache::self()->isComplete(d->m_cacheId))
05515     {
05516        d->m_restored = true;
05517        openUrl( u );
05518        d->m_restored = false;
05519     }
05520     else
05521     {
05522        restoreURL( u );
05523     }
05524   }
05525 
05526 }
05527 
05528 void KHTMLPart::show()
05529 {
05530   if ( widget() )
05531     widget()->show();
05532 }
05533 
05534 void KHTMLPart::hide()
05535 {
05536   if ( widget() )
05537     widget()->hide();
05538 }
05539 
05540 DOM::Node KHTMLPart::nodeUnderMouse() const
05541 {
05542     return d->m_view->nodeUnderMouse();
05543 }
05544 
05545 DOM::Node KHTMLPart::nonSharedNodeUnderMouse() const
05546 {
05547     return d->m_view->nonSharedNodeUnderMouse();
05548 }
05549 
05550 void KHTMLPart::emitSelectionChanged()
05551 {
05552     // Don't emit signals about our selection if this is a frameset;
05553     // the active frame has the selection (#187403)
05554     if (!d->m_activeFrame)
05555     {
05556         emit d->m_extension->enableAction( "copy", hasSelection() );
05557         emit d->m_extension->selectionInfo( selectedText() );
05558         emit selectionChanged();
05559     }
05560 }
05561 
05562 int KHTMLPart::zoomFactor() const
05563 {
05564   return d->m_zoomFactor;
05565 }
05566 
05567 // ### make the list configurable ?
05568 static const int zoomSizes[] = { 20, 40, 60, 80, 90, 95, 100, 105, 110, 120, 140, 160, 180, 200, 250, 300 };
05569 static const int zoomSizeCount = (sizeof(zoomSizes) / sizeof(int));
05570 static const int minZoom = 20;
05571 static const int maxZoom = 300;
05572 
05573 // My idea of useful stepping ;-) (LS)
05574 extern const int KDE_NO_EXPORT fastZoomSizes[] = { 20, 50, 75, 90, 100, 120, 150, 200, 300 };
05575 extern const int KDE_NO_EXPORT fastZoomSizeCount = sizeof fastZoomSizes / sizeof fastZoomSizes[0];
05576 
05577 void KHTMLPart::slotIncZoom()
05578 {
05579   zoomIn(zoomSizes, zoomSizeCount);
05580 }
05581 
05582 void KHTMLPart::slotDecZoom()
05583 {
05584   zoomOut(zoomSizes, zoomSizeCount);
05585 }
05586 
05587 void KHTMLPart::slotIncZoomFast()
05588 {
05589   zoomIn(fastZoomSizes, fastZoomSizeCount);
05590 }
05591 
05592 void KHTMLPart::slotDecZoomFast()
05593 {
05594   zoomOut(fastZoomSizes, fastZoomSizeCount);
05595 }
05596 
05597 void KHTMLPart::zoomIn(const int stepping[], int count)
05598 {
05599   int zoomFactor = d->m_zoomFactor;
05600 
05601   if (zoomFactor < maxZoom) {
05602     // find the entry nearest to the given zoomsizes
05603     for (int i = 0; i < count; ++i)
05604       if (stepping[i] > zoomFactor) {
05605         zoomFactor = stepping[i];
05606         break;
05607       }
05608     setZoomFactor(zoomFactor);
05609   }
05610 }
05611 
05612 void KHTMLPart::zoomOut(const int stepping[], int count)
05613 {
05614     int zoomFactor = d->m_zoomFactor;
05615     if (zoomFactor > minZoom) {
05616       // find the entry nearest to the given zoomsizes
05617       for (int i = count-1; i >= 0; --i)
05618         if (stepping[i] < zoomFactor) {
05619           zoomFactor = stepping[i];
05620           break;
05621         }
05622       setZoomFactor(zoomFactor);
05623     }
05624 }
05625 
05626 void KHTMLPart::setZoomFactor (int percent)
05627 {
05628   // ### zooming under 100% is majorly botched,
05629   //     so disable that for now.
05630   if (percent < 100) percent = 100;
05631   // ### if (percent < minZoom) percent = minZoom;
05632 
05633   if (percent > maxZoom) percent = maxZoom;
05634   if (d->m_zoomFactor == percent) return;
05635   d->m_zoomFactor = percent;
05636 
05637   if(d->m_view) {
05638     QApplication::setOverrideCursor( Qt::WaitCursor );
05639     d->m_view->setZoomLevel( d->m_zoomFactor );
05640     QApplication::restoreOverrideCursor();
05641   }
05642 
05643   ConstFrameIt it = d->m_frames.constBegin();
05644   const ConstFrameIt end = d->m_frames.constEnd();
05645   for (; it != end; ++it )
05646     if ( !( *it )->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
05647       KParts::ReadOnlyPart* const p = ( *it )->m_part;
05648       static_cast<KHTMLPart*>( p )->setZoomFactor(d->m_zoomFactor);
05649     }
05650 
05651   if ( d->m_guiProfile == BrowserViewGUI ) {
05652       d->m_paDecZoomFactor->setEnabled( d->m_zoomFactor > minZoom );
05653       d->m_paIncZoomFactor->setEnabled( d->m_zoomFactor < maxZoom );
05654   }
05655 }
05656 void KHTMLPart::slotIncFontSize()
05657 {
05658   incFontSize(zoomSizes, zoomSizeCount);
05659 }
05660 
05661 void KHTMLPart::slotDecFontSize()
05662 {
05663   decFontSize(zoomSizes, zoomSizeCount);
05664 }
05665 
05666 void KHTMLPart::slotIncFontSizeFast()
05667 {
05668   incFontSize(fastZoomSizes, fastZoomSizeCount);
05669 }
05670 
05671 void KHTMLPart::slotDecFontSizeFast()
05672 {
05673   decFontSize(fastZoomSizes, fastZoomSizeCount);
05674 }
05675 
05676 void KHTMLPart::incFontSize(const int stepping[], int count)
05677 {
05678   int zoomFactor = d->m_fontScaleFactor;
05679 
05680   if (zoomFactor < maxZoom) {
05681     // find the entry nearest to the given zoomsizes
05682     for (int i = 0; i < count; ++i)
05683       if (stepping[i] > zoomFactor) {
05684         zoomFactor = stepping[i];
05685         break;
05686       }
05687     setFontScaleFactor(zoomFactor);
05688   }
05689 }
05690 
05691 void KHTMLPart::decFontSize(const int stepping[], int count)
05692 {
05693     int zoomFactor = d->m_fontScaleFactor;
05694     if (zoomFactor > minZoom) {
05695       // find the entry nearest to the given zoomsizes
05696       for (int i = count-1; i >= 0; --i)
05697         if (stepping[i] < zoomFactor) {
05698           zoomFactor = stepping[i];
05699           break;
05700         }
05701       setFontScaleFactor(zoomFactor);
05702     }
05703 }
05704 
05705 void KHTMLPart::setFontScaleFactor(int percent)
05706 {
05707   if (percent < minZoom) percent = minZoom;
05708   if (percent > maxZoom) percent = maxZoom;
05709   if (d->m_fontScaleFactor == percent) return;
05710   d->m_fontScaleFactor = percent;
05711 
05712   if (d->m_view && d->m_doc) {
05713     QApplication::setOverrideCursor( Qt::WaitCursor );
05714     if (d->m_doc->styleSelector())
05715       d->m_doc->styleSelector()->computeFontSizes(d->m_doc->logicalDpiY(), d->m_fontScaleFactor);
05716     d->m_doc->recalcStyle( NodeImpl::Force );
05717     QApplication::restoreOverrideCursor();
05718   }
05719 
05720   ConstFrameIt it = d->m_frames.constBegin();
05721   const ConstFrameIt end = d->m_frames.constEnd();
05722   for (; it != end; ++it )
05723     if ( !( *it )->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
05724       KParts::ReadOnlyPart* const p = ( *it )->m_part;
05725       static_cast<KHTMLPart*>( p )->setFontScaleFactor(d->m_fontScaleFactor);
05726     }
05727 }
05728 
05729 int KHTMLPart::fontScaleFactor() const
05730 {
05731   return d->m_fontScaleFactor;
05732 }
05733 
05734 void KHTMLPart::slotZoomView( int delta )
05735 {
05736   if ( delta < 0 )
05737     slotIncZoom();
05738   else
05739     slotDecZoom();
05740 }
05741 
05742 void KHTMLPart::setStatusBarText( const QString& text, StatusBarPriority p)
05743 {
05744   if (!d->m_statusMessagesEnabled)
05745     return;
05746 
05747   d->m_statusBarText[p] = text;
05748 
05749   // shift handling ?
05750   QString tobe = d->m_statusBarText[BarHoverText];
05751   if (tobe.isEmpty())
05752     tobe = d->m_statusBarText[BarOverrideText];
05753   if (tobe.isEmpty()) {
05754     tobe = d->m_statusBarText[BarDefaultText];
05755     if (!tobe.isEmpty() && d->m_jobspeed)
05756       tobe += " ";
05757     if (d->m_jobspeed)
05758       tobe += i18n( "(%1/s)" ,  KIO::convertSize( d->m_jobspeed ) );
05759   }
05760   tobe = "<qt>"+tobe;
05761 
05762   emit ReadOnlyPart::setStatusBarText(tobe);
05763 }
05764 
05765 
05766 void KHTMLPart::setJSStatusBarText( const QString &text )
05767 {
05768   setStatusBarText(text, BarOverrideText);
05769 }
05770 
05771 void KHTMLPart::setJSDefaultStatusBarText( const QString &text )
05772 {
05773   setStatusBarText(text, BarDefaultText);
05774 }
05775 
05776 QString KHTMLPart::jsStatusBarText() const
05777 {
05778     return d->m_statusBarText[BarOverrideText];
05779 }
05780 
05781 QString KHTMLPart::jsDefaultStatusBarText() const
05782 {
05783    return d->m_statusBarText[BarDefaultText];
05784 }
05785 
05786 QString KHTMLPart::referrer() const
05787 {
05788    return d->m_referrer;
05789 }
05790 
05791 QString KHTMLPart::pageReferrer() const
05792 {
05793    KUrl referrerURL = KUrl( d->m_pageReferrer );
05794    if (referrerURL.isValid())
05795    {
05796       QString protocol = referrerURL.protocol();
05797 
05798       if ((protocol == "http") ||
05799          ((protocol == "https") && (url().protocol() == "https")))
05800       {
05801           referrerURL.setRef(QString());
05802           referrerURL.setUser(QString());
05803           referrerURL.setPass(QString());
05804           return referrerURL.url();
05805       }
05806    }
05807 
05808    return QString();
05809 }
05810 
05811 
05812 QString KHTMLPart::lastModified() const
05813 {
05814   if ( d->m_lastModified.isEmpty() && url().isLocalFile() ) {
05815     // Local file: set last-modified from the file's mtime.
05816     // Done on demand to save time when this isn't needed - but can lead
05817     // to slightly wrong results if updating the file on disk w/o reloading.
05818     QDateTime lastModif = QFileInfo( url().toLocalFile() ).lastModified();
05819     d->m_lastModified = lastModif.toString( Qt::LocalDate );
05820   }
05821   //kDebug(6050) << d->m_lastModified;
05822   return d->m_lastModified;
05823 }
05824 
05825 void KHTMLPart::slotLoadImages()
05826 {
05827   if (d->m_doc )
05828     d->m_doc->docLoader()->setAutoloadImages( !d->m_doc->docLoader()->autoloadImages() );
05829 
05830   ConstFrameIt it = d->m_frames.constBegin();
05831   const ConstFrameIt end = d->m_frames.constEnd();
05832   for (; it != end; ++it )
05833     if ( !( *it )->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
05834       KParts::ReadOnlyPart* const p = ( *it )->m_part;
05835       static_cast<KHTMLPart*>( p )->slotLoadImages();
05836     }
05837 }
05838 
05839 void KHTMLPart::reparseConfiguration()
05840 {
05841   KHTMLSettings *settings = KHTMLGlobal::defaultHTMLSettings();
05842   settings->init();
05843 
05844   setAutoloadImages( settings->autoLoadImages() );
05845   if (d->m_doc)
05846      d->m_doc->docLoader()->setShowAnimations( settings->showAnimations() );
05847 
05848   d->m_bOpenMiddleClick = settings->isOpenMiddleClickEnabled();
05849   d->m_bBackRightClick = settings->isBackRightClickEnabled();
05850   d->m_bJScriptEnabled = settings->isJavaScriptEnabled(url().host());
05851   setDebugScript( settings->isJavaScriptDebugEnabled() );
05852   d->m_bJavaEnabled = settings->isJavaEnabled(url().host());
05853   d->m_bPluginsEnabled = settings->isPluginsEnabled(url().host());
05854   d->m_metaRefreshEnabled = settings->isAutoDelayedActionsEnabled ();
05855 
05856   delete d->m_settings;
05857   d->m_settings = new KHTMLSettings(*KHTMLGlobal::defaultHTMLSettings());
05858 
05859   QApplication::setOverrideCursor( Qt::WaitCursor );
05860   khtml::CSSStyleSelector::reparseConfiguration();
05861   if(d->m_doc) d->m_doc->updateStyleSelector();
05862   QApplication::restoreOverrideCursor();
05863 
05864   if (d->m_view) {
05865       KHTMLSettings::KSmoothScrollingMode ssm = d->m_settings->smoothScrolling();
05866       if (ssm == KHTMLSettings::KSmoothScrollingDisabled)
05867           d->m_view->setSmoothScrollingModeDefault(KHTMLView::SSMDisabled);
05868       else if (ssm == KHTMLSettings::KSmoothScrollingWhenEfficient)
05869           d->m_view->setSmoothScrollingModeDefault(KHTMLView::SSMWhenEfficient);
05870       else
05871           d->m_view->setSmoothScrollingModeDefault(KHTMLView::SSMEnabled);
05872   }
05873 
05874   if (KHTMLGlobal::defaultHTMLSettings()->isAdFilterEnabled())
05875      runAdFilter();
05876 }
05877 
05878 QStringList KHTMLPart::frameNames() const
05879 {
05880   QStringList res;
05881 
05882   ConstFrameIt it = d->m_frames.constBegin();
05883   const ConstFrameIt end = d->m_frames.constEnd();
05884   for (; it != end; ++it )
05885     if (!(*it)->m_bPreloaded && (*it)->m_part)
05886       res += (*it)->m_name;
05887 
05888   return res;
05889 }
05890 
05891 QList<KParts::ReadOnlyPart*> KHTMLPart::frames() const
05892 {
05893   QList<KParts::ReadOnlyPart*> res;
05894 
05895   ConstFrameIt it = d->m_frames.constBegin();
05896   const ConstFrameIt end = d->m_frames.constEnd();
05897   for (; it != end; ++it )
05898     if (!(*it)->m_bPreloaded && (*it)->m_part) // ### TODO: make sure that we always create an empty
05899                                                // KHTMLPart for frames so this never happens.
05900       res.append( (*it)->m_part );
05901 
05902   return res;
05903 }
05904 
05905 bool KHTMLPart::openUrlInFrame( const KUrl &url, const KParts::OpenUrlArguments& args, const KParts::BrowserArguments &browserArgs)
05906 {
05907   kDebug( 6050 ) << this << url;
05908   FrameIt it = d->m_frames.find( browserArgs.frameName );
05909 
05910   if ( it == d->m_frames.end() )
05911     return false;
05912 
05913   // Inform someone that we are about to show something else.
05914   if ( !browserArgs.lockHistory() )
05915       emit d->m_extension->openUrlNotify();
05916 
05917   requestObject( *it, url, args, browserArgs );
05918 
05919   return true;
05920 }
05921 
05922 void KHTMLPart::setDNDEnabled( bool b )
05923 {
05924   d->m_bDnd = b;
05925 }
05926 
05927 bool KHTMLPart::dndEnabled() const
05928 {
05929   return d->m_bDnd;
05930 }
05931 
05932 void KHTMLPart::customEvent( QEvent *event )
05933 {
05934   if ( khtml::MousePressEvent::test( event ) )
05935   {
05936     khtmlMousePressEvent( static_cast<khtml::MousePressEvent *>( event ) );
05937     return;
05938   }
05939 
05940   if ( khtml::MouseDoubleClickEvent::test( event ) )
05941   {
05942     khtmlMouseDoubleClickEvent( static_cast<khtml::MouseDoubleClickEvent *>( event ) );
05943     return;
05944   }
05945 
05946   if ( khtml::MouseMoveEvent::test( event ) )
05947   {
05948     khtmlMouseMoveEvent( static_cast<khtml::MouseMoveEvent *>( event ) );
05949     return;
05950   }
05951 
05952   if ( khtml::MouseReleaseEvent::test( event ) )
05953   {
05954     khtmlMouseReleaseEvent( static_cast<khtml::MouseReleaseEvent *>( event ) );
05955     return;
05956   }
05957 
05958   if ( khtml::DrawContentsEvent::test( event ) )
05959   {
05960     khtmlDrawContentsEvent( static_cast<khtml::DrawContentsEvent *>( event ) );
05961     return;
05962   }
05963 
05964   KParts::ReadOnlyPart::customEvent( event );
05965 }
05966 
05967 bool KHTMLPart::isPointInsideSelection(int x, int y)
05968 {
05969   // Treat a collapsed selection like no selection.
05970   if (d->editor_context.m_selection.state() == Selection::CARET)
05971     return false;
05972   if (!xmlDocImpl()->renderer())
05973     return false;
05974 
05975   khtml::RenderObject::NodeInfo nodeInfo(true, true);
05976   xmlDocImpl()->renderer()->layer()->nodeAtPoint(nodeInfo, x, y);
05977   NodeImpl *innerNode = nodeInfo.innerNode();
05978   if (!innerNode || !innerNode->renderer())
05979     return false;
05980 
05981   return innerNode->isPointInsideSelection(x, y, d->editor_context.m_selection);
05982 }
05983 
05989 static bool firstRunAt(khtml::RenderObject *renderNode, int y, NodeImpl *&startNode, long &startOffset)
05990 {
05991     for (khtml::RenderObject *n = renderNode; n; n = n->nextSibling()) {
05992         if (n->isText()) {
05993             khtml::RenderText* const textRenderer = static_cast<khtml::RenderText *>(n);
05994             for (khtml::InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
05995                 if (box->m_y == y && textRenderer->element()) {
05996                     startNode = textRenderer->element();
05997                     startOffset = box->m_start;
05998                     return true;
05999                 }
06000             }
06001         }
06002 
06003         if (firstRunAt(n->firstChild(), y, startNode, startOffset)) {
06004             return true;
06005         }
06006     }
06007 
06008     return false;
06009 }
06010 
06016 static bool lastRunAt(khtml::RenderObject *renderNode, int y, NodeImpl *&endNode, long &endOffset)
06017 {
06018     khtml::RenderObject *n = renderNode;
06019     if (!n) {
06020         return false;
06021     }
06022     khtml::RenderObject *next;
06023     while ((next = n->nextSibling())) {
06024         n = next;
06025     }
06026 
06027     while (1) {
06028         if (lastRunAt(n->firstChild(), y, endNode, endOffset)) {
06029             return true;
06030         }
06031 
06032         if (n->isText()) {
06033             khtml::RenderText* const textRenderer =  static_cast<khtml::RenderText *>(n);
06034             for (khtml::InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
06035                 if (box->m_y == y && textRenderer->element()) {
06036                     endNode = textRenderer->element();
06037                     endOffset = box->m_start + box->m_len;
06038                     return true;
06039                 }
06040             }
06041         }
06042 
06043         if (n == renderNode) {
06044             return false;
06045         }
06046 
06047         n = n->previousSibling();
06048     }
06049 }
06050 
06051 void KHTMLPart::handleMousePressEventDoubleClick(khtml::MouseDoubleClickEvent *event)
06052 {
06053     QMouseEvent *mouse = event->qmouseEvent();
06054     DOM::Node innerNode = event->innerNode();
06055 
06056     Selection selection;
06057 
06058     if (mouse->button() == Qt::LeftButton && !innerNode.isNull() && innerNode.handle()->renderer() &&
06059         innerNode.handle()->renderer()->shouldSelect()) {
06060         Position pos(innerNode.handle()->positionForCoordinates(event->x(), event->y()));
06061         if (pos.node() && (pos.node()->nodeType() == Node::TEXT_NODE || pos.node()->nodeType() == Node::CDATA_SECTION_NODE)) {
06062             selection.moveTo(pos);
06063             selection.expandUsingGranularity(Selection::WORD);
06064         }
06065     }
06066 
06067     if (selection.state() != Selection::CARET) {
06068         d->editor_context.beginSelectingText(Selection::WORD);
06069     }
06070 
06071     setCaret(selection);
06072     startAutoScroll();
06073 }
06074 
06075 void KHTMLPart::handleMousePressEventTripleClick(khtml::MouseDoubleClickEvent *event)
06076 {
06077     QMouseEvent *mouse = event->qmouseEvent();
06078     DOM::Node innerNode = event->innerNode();
06079 
06080     Selection selection;
06081 
06082     if (mouse->button() == Qt::LeftButton && !innerNode.isNull() && innerNode.handle()->renderer() &&
06083         innerNode.handle()->renderer()->shouldSelect()) {
06084         Position pos(innerNode.handle()->positionForCoordinates(event->x(), event->y()));
06085         if (pos.node() && (pos.node()->nodeType() == Node::TEXT_NODE || pos.node()->nodeType() == Node::CDATA_SECTION_NODE)) {
06086             selection.moveTo(pos);
06087             selection.expandUsingGranularity(Selection::LINE);
06088         }
06089     }
06090 
06091     if (selection.state() != Selection::CARET) {
06092         d->editor_context.beginSelectingText(Selection::LINE);
06093     }
06094 
06095     setCaret(selection);
06096     startAutoScroll();
06097 }
06098 
06099 void KHTMLPart::handleMousePressEventSingleClick(khtml::MousePressEvent *event)
06100 {
06101     QMouseEvent *mouse = event->qmouseEvent();
06102     DOM::Node innerNode = event->innerNode();
06103 
06104     if (mouse->button() == Qt::LeftButton) {
06105         Selection sel;
06106 
06107         if (!innerNode.isNull() && innerNode.handle()->renderer() &&
06108             innerNode.handle()->renderer()->shouldSelect()) {
06109             bool extendSelection = mouse->modifiers() & Qt::ShiftModifier;
06110 
06111             // Don't restart the selection when the mouse is pressed on an
06112             // existing selection so we can allow for text dragging.
06113             if (!extendSelection && isPointInsideSelection(event->x(), event->y())) {
06114                 return;
06115             }
06116             Position pos(innerNode.handle()->positionForCoordinates(event->x(), event->y()));
06117             if (pos.isEmpty())
06118                 pos = Position(innerNode.handle(), innerNode.handle()->caretMinOffset());
06119 
06120             sel = caret();
06121             if (extendSelection && sel.notEmpty()) {
06122                 sel.clearModifyBias();
06123                 sel.setExtent(pos);
06124                 if (d->editor_context.m_selectionGranularity != Selection::CHARACTER) {
06125                     sel.expandUsingGranularity(d->editor_context.m_selectionGranularity);
06126                 }
06127                 d->editor_context.m_beganSelectingText = true;
06128             } else {
06129                 sel = pos;
06130                 d->editor_context.m_selectionGranularity = Selection::CHARACTER;
06131             }
06132         }
06133 
06134         setCaret(sel);
06135         startAutoScroll();
06136     }
06137 }
06138 
06139 void KHTMLPart::khtmlMousePressEvent( khtml::MousePressEvent *event )
06140 {
06141   DOM::DOMString url = event->url();
06142   QMouseEvent *_mouse = event->qmouseEvent();
06143   DOM::Node innerNode = event->innerNode();
06144   d->m_mousePressNode = innerNode;
06145 
06146   d->m_dragStartPos = QPoint(event->x(), event->y());
06147 
06148   if ( !event->url().isNull() ) {
06149     d->m_strSelectedURL = event->url().string();
06150     d->m_strSelectedURLTarget = event->target().string();
06151   }
06152   else {
06153     d->m_strSelectedURL.clear();
06154     d->m_strSelectedURLTarget.clear();
06155   }
06156 
06157   if ( _mouse->button() == Qt::LeftButton ||
06158        _mouse->button() == Qt::MidButton )
06159   {
06160     d->m_bMousePressed = true;
06161 
06162 #ifdef KHTML_NO_SELECTION
06163     d->m_dragLastPos = _mouse->globalPos();
06164 #else
06165     if ( _mouse->button() == Qt::LeftButton )
06166     {
06167       if ( (!d->m_strSelectedURL.isNull() && !isEditable())
06168                 || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) )
06169           return;
06170 
06171       d->editor_context.m_beganSelectingText = false;
06172 
06173       handleMousePressEventSingleClick(event);
06174     }
06175 #endif
06176   }
06177 
06178   if ( _mouse->button() == Qt::RightButton && parentPart() != 0 && d->m_bBackRightClick )
06179   {
06180     d->m_bRightMousePressed = true;
06181   } else if ( _mouse->button() == Qt::RightButton )
06182   {
06183     popupMenu( d->m_strSelectedURL );
06184     // might be deleted, don't touch "this"
06185   }
06186 }
06187 
06188 void KHTMLPart::khtmlMouseDoubleClickEvent( khtml::MouseDoubleClickEvent *event )
06189 {
06190   QMouseEvent *_mouse = event->qmouseEvent();
06191   if ( _mouse->button() == Qt::LeftButton )
06192   {
06193     d->m_bMousePressed = true;
06194     d->editor_context.m_beganSelectingText = false;
06195 
06196     if (event->clickCount() == 2) {
06197       handleMousePressEventDoubleClick(event);
06198       return;
06199     }
06200 
06201     if (event->clickCount() >= 3) {
06202       handleMousePressEventTripleClick(event);
06203       return;
06204     }
06205   }
06206 }
06207 
06208 #ifndef KHTML_NO_SELECTION
06209 bool KHTMLPart::isExtendingSelection() const
06210  {
06211   // This is it, the whole detection. khtmlMousePressEvent only sets this
06212   // on LMB or MMB, but never on RMB. As text selection doesn't work for MMB,
06213   // it's sufficient to only rely on this flag to detect selection extension.
06214   return d->editor_context.m_beganSelectingText;
06215 }
06216 
06217 void KHTMLPart::extendSelectionTo(int x, int y, const DOM::Node &innerNode)
06218 {
06219     // handle making selection
06220     Position pos(innerNode.handle()->positionForCoordinates(x, y));
06221 
06222     // Don't modify the selection if we're not on a node.
06223     if (pos.isEmpty())
06224         return;
06225 
06226     // Restart the selection if this is the first mouse move. This work is usually
06227     // done in khtmlMousePressEvent, but not if the mouse press was on an existing selection.
06228     Selection sel = caret();
06229     sel.clearModifyBias();
06230     if (!d->editor_context.m_beganSelectingText) {
06231         // We are beginning a selection during press-drag, when the original click
06232         // wasn't appropriate for one. Make sure to set the granularity.
06233         d->editor_context.beginSelectingText(Selection::CHARACTER);
06234         sel.moveTo(pos);
06235     }
06236 
06237     sel.setExtent(pos);
06238     if (d->editor_context.m_selectionGranularity != Selection::CHARACTER) {
06239         sel.expandUsingGranularity(d->editor_context.m_selectionGranularity);
06240     }
06241     setCaret(sel);
06242 
06243 }
06244 #endif // KHTML_NO_SELECTION
06245 
06246 bool KHTMLPart::handleMouseMoveEventDrag(khtml::MouseMoveEvent *event)
06247 {
06248 #ifdef QT_NO_DRAGANDDROP
06249   return false;
06250 #else
06251   if (!dndEnabled())
06252     return false;
06253 
06254   DOM::Node innerNode = event->innerNode();
06255 
06256   if( (d->m_bMousePressed &&
06257        ( (!d->m_strSelectedURL.isEmpty() && !isEditable())
06258         || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) ) )
06259         && ( d->m_dragStartPos - QPoint(event->x(), event->y()) ).manhattanLength() > KGlobalSettings::dndEventDelay() ) {
06260 
06261     DOM::DOMString url = event->url();
06262 
06263     QPixmap pix;
06264     HTMLImageElementImpl *img = 0L;
06265     KUrl u;
06266 
06267     // qDebug("****************** Event URL: %s", url.string().toLatin1().constData());
06268     // qDebug("****************** Event Target: %s", target.string().toLatin1().constData());
06269 
06270     // Normal image...
06271     if ( url.length() == 0 && innerNode.handle() && innerNode.handle()->id() == ID_IMG )
06272     {
06273       img = static_cast<HTMLImageElementImpl *>(innerNode.handle());
06274       u = KUrl( completeURL( khtml::parseURL(img->getAttribute(ATTR_SRC)).string() ) );
06275       pix = KIconLoader::global()->loadIcon("image-x-generic", KIconLoader::Desktop);
06276     }
06277     else
06278     {
06279       // Text or image link...
06280       u = completeURL( d->m_strSelectedURL );
06281       pix = KIO::pixmapForUrl(u, 0, KIconLoader::Desktop, KIconLoader::SizeMedium);
06282     }
06283 
06284     u.setPass(QString());
06285 
06286     QDrag *drag = new QDrag( d->m_view->viewport() );
06287     QMap<QString, QString> metaDataMap;
06288     if ( !d->m_referrer.isEmpty() )
06289       metaDataMap.insert( "referrer", d->m_referrer );
06290     QMimeData* mimeData = new QMimeData();
06291     u.populateMimeData( mimeData, metaDataMap );
06292     drag->setMimeData( mimeData );
06293 
06294     if( img && img->complete() )
06295       drag->mimeData()->setImageData( img->currentImage() );
06296 
06297     if ( !pix.isNull() )
06298       drag->setPixmap( pix );
06299 
06300     stopAutoScroll();
06301     drag->start();
06302 
06303     // when we finish our drag, we need to undo our mouse press
06304     d->m_bMousePressed = false;
06305     d->m_strSelectedURL.clear();
06306     d->m_strSelectedURLTarget.clear();
06307     return true;
06308   }
06309   return false;
06310 #endif // QT_NO_DRAGANDDROP
06311 }
06312 
06313 bool KHTMLPart::handleMouseMoveEventOver(khtml::MouseMoveEvent *event)
06314 {
06315   // Mouse clicked -> do nothing
06316   if ( d->m_bMousePressed ) return false;
06317 
06318   DOM::DOMString url = event->url();
06319 
06320   // The mouse is over something
06321   if ( url.length() )
06322   {
06323     DOM::DOMString target = event->target();
06324     QMouseEvent *_mouse = event->qmouseEvent();
06325     DOM::Node innerNode = event->innerNode();
06326 
06327     bool shiftPressed = ( _mouse->modifiers() & Qt::ShiftModifier );
06328 
06329     // Image map
06330     if ( !innerNode.isNull() && innerNode.elementId() == ID_IMG )
06331     {
06332       HTMLImageElementImpl *i = static_cast<HTMLImageElementImpl *>(innerNode.handle());
06333       if ( i && i->isServerMap() )
06334       {
06335         khtml::RenderObject *r = i->renderer();
06336         if(r)
06337         {
06338           int absx, absy;
06339           r->absolutePosition(absx, absy);
06340           int x(event->x() - absx), y(event->y() - absy);
06341 
06342           d->m_overURL = url.string() + QString("?%1,%2").arg(x).arg(y);
06343           d->m_overURLTarget = target.string();
06344           overURL( d->m_overURL, target.string(), shiftPressed );
06345           return true;
06346         }
06347       }
06348     }
06349 
06350     // normal link
06351     if ( d->m_overURL.isEmpty() || d->m_overURL != url || d->m_overURLTarget != target )
06352     {
06353       d->m_overURL = url.string();
06354       d->m_overURLTarget = target.string();
06355       overURL( d->m_overURL, target.string(), shiftPressed );
06356     }
06357   }
06358   else  // Not over a link...
06359   {
06360     if( !d->m_overURL.isEmpty() ) // and we were over a link  -> reset to "default statusbar text"
06361     {
06362       // reset to "default statusbar text"
06363       resetHoverText();
06364     }
06365   }
06366   return true;
06367 }
06368 
06369 void KHTMLPart::handleMouseMoveEventSelection(khtml::MouseMoveEvent *event)
06370 {
06371     // Mouse not pressed. Do nothing.
06372     if (!d->m_bMousePressed)
06373         return;
06374 
06375 #ifdef KHTML_NO_SELECTION
06376     if (d->m_doc && d->m_view) {
06377         QPoint diff( mouse->globalPos() - d->m_dragLastPos );
06378 
06379         if (abs(diff.x()) > 64 || abs(diff.y()) > 64) {
06380             d->m_view->scrollBy(-diff.x(), -diff.y());
06381             d->m_dragLastPos = mouse->globalPos();
06382         }
06383     }
06384 #else
06385 
06386     QMouseEvent *mouse = event->qmouseEvent();
06387     DOM::Node innerNode = event->innerNode();
06388 
06389     if ( (mouse->buttons() & Qt::LeftButton) == 0 || !innerNode.handle() || !innerNode.handle()->renderer() ||
06390         !innerNode.handle()->renderer()->shouldSelect())
06391             return;
06392 
06393     // handle making selection
06394     extendSelectionTo(event->x(), event->y(), innerNode);
06395 #endif // KHTML_NO_SELECTION
06396 }
06397 
06398 void KHTMLPart::khtmlMouseMoveEvent( khtml::MouseMoveEvent *event )
06399 {
06400     if (handleMouseMoveEventDrag(event))
06401         return;
06402 
06403     if (handleMouseMoveEventOver(event))
06404         return;
06405 
06406     handleMouseMoveEventSelection(event);
06407 }
06408 
06409 void KHTMLPart::khtmlMouseReleaseEvent( khtml::MouseReleaseEvent *event )
06410 {
06411   DOM::Node innerNode = event->innerNode();
06412   d->m_mousePressNode = DOM::Node();
06413 
06414   if ( d->m_bMousePressed ) {
06415     setStatusBarText(QString(), BarHoverText);
06416     stopAutoScroll();
06417   }
06418 
06419   // Used to prevent mouseMoveEvent from initiating a drag before
06420   // the mouse is pressed again.
06421   d->m_bMousePressed = false;
06422 
06423   QMouseEvent *_mouse = event->qmouseEvent();
06424   if ( _mouse->button() == Qt::RightButton && parentPart() != 0 && d->m_bBackRightClick )
06425   {
06426     d->m_bRightMousePressed = false;
06427     KParts::BrowserInterface *tmp_iface = d->m_extension->browserInterface();
06428     if( tmp_iface ) {
06429       tmp_iface->callMethod( "goHistory", -1 );
06430     }
06431   }
06432 #ifndef QT_NO_CLIPBOARD
06433   if ((d->m_guiProfile == BrowserViewGUI) && (_mouse->button() == Qt::MidButton) && (event->url().isNull())) {
06434     kDebug( 6050 ) << "MMB shouldOpen=" << d->m_bOpenMiddleClick;
06435 
06436     if (d->m_bOpenMiddleClick) {
06437       KHTMLPart *p = this;
06438       while (p->parentPart()) p = p->parentPart();
06439       p->d->m_extension->pasteRequest();
06440     }
06441   }
06442 #endif
06443 
06444 #ifndef KHTML_NO_SELECTION
06445   {
06446 
06447     // Clear the selection if the mouse didn't move after the last mouse press.
06448     // We do this so when clicking on the selection, the selection goes away.
06449     // However, if we are editing, place the caret.
06450     if (!d->editor_context.m_beganSelectingText
06451             && d->m_dragStartPos.x() == event->x()
06452             && d->m_dragStartPos.y() == event->y()
06453             && d->editor_context.m_selection.state() == Selection::RANGE) {
06454       Selection selection;
06455 #ifdef APPLE_CHANGES
06456       if (d->editor_context.m_selection.base().node()->isContentEditable())
06457 #endif
06458         selection.moveTo(d->editor_context.m_selection.base().node()->positionForCoordinates(event->x(), event->y()));
06459       setCaret(selection);
06460     }
06461     // get selected text and paste to the clipboard
06462 #ifndef QT_NO_CLIPBOARD
06463     QString text = selectedText();
06464     text.replace(QChar(0xa0), ' ');
06465     if (!text.isEmpty()) {
06466         disconnect( qApp->clipboard(), SIGNAL( selectionChanged()), this, SLOT( slotClearSelection()));
06467         qApp->clipboard()->setText(text,QClipboard::Selection);
06468         connect( qApp->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection()));
06469     }
06470 #endif
06471     //kDebug( 6000 ) << "selectedText = " << text;
06472     emitSelectionChanged();
06473 //kDebug(6000) << "rel2: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << "), caretOfs " << d->caretOffset();
06474   }
06475 #endif
06476 }
06477 
06478 void KHTMLPart::khtmlDrawContentsEvent( khtml::DrawContentsEvent * )
06479 {
06480 }
06481 
06482 void KHTMLPart::guiActivateEvent( KParts::GUIActivateEvent *event )
06483 {
06484   if ( event->activated() )
06485   {
06486     emitSelectionChanged();
06487     emit d->m_extension->enableAction( "print", d->m_doc != 0 );
06488 
06489     if ( !d->m_settings->autoLoadImages() && d->m_paLoadImages )
06490     {
06491         QList<QAction*> lst;
06492         lst.append( d->m_paLoadImages );
06493         plugActionList( "loadImages", lst );
06494     }
06495   }
06496 }
06497 
06498 void KHTMLPart::slotPrintFrame()
06499 {
06500   if ( d->m_frames.count() == 0 )
06501     return;
06502 
06503   KParts::ReadOnlyPart *frame = currentFrame();
06504   if (!frame)
06505     return;
06506 
06507   KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject( frame );
06508 
06509   if ( !ext )
06510     return;
06511 
06512 
06513   const QMetaObject *mo = ext->metaObject();
06514 
06515 
06516   if (mo->indexOfSlot( "print()") != -1)
06517     QMetaObject::invokeMethod(ext, "print()",  Qt::DirectConnection);
06518 }
06519 
06520 void KHTMLPart::slotSelectAll()
06521 {
06522   KParts::ReadOnlyPart *part = currentFrame();
06523   if (part && part->inherits("KHTMLPart"))
06524     static_cast<KHTMLPart *>(part)->selectAll();
06525 }
06526 
06527 void KHTMLPart::startAutoScroll()
06528 {
06529    connect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
06530    d->m_scrollTimer.setSingleShot(false);
06531    d->m_scrollTimer.start(100);
06532 }
06533 
06534 void KHTMLPart::stopAutoScroll()
06535 {
06536    disconnect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
06537    if (d->m_scrollTimer.isActive())
06538        d->m_scrollTimer.stop();
06539 }
06540 
06541 
06542 void KHTMLPart::slotAutoScroll()
06543 {
06544     if (d->m_view)
06545       d->m_view->doAutoScroll();
06546     else
06547       stopAutoScroll(); // Safety
06548 }
06549 
06550 void KHTMLPart::runAdFilter()
06551 {
06552     if ( parentPart() )
06553         parentPart()->runAdFilter();
06554 
06555     if ( !d->m_doc )
06556         return;
06557 
06558     QSetIterator<khtml::CachedObject*> it( d->m_doc->docLoader()->m_docObjects );
06559     while (it.hasNext())
06560     {
06561         khtml::CachedObject* obj = it.next();
06562         if ( obj->type() == khtml::CachedObject::Image ) {
06563             khtml::CachedImage *image = static_cast<khtml::CachedImage *>(obj);
06564             bool wasBlocked = image->m_wasBlocked;
06565             image->m_wasBlocked = KHTMLGlobal::defaultHTMLSettings()->isAdFiltered( d->m_doc->completeURL( image->url().string() ) );
06566             if ( image->m_wasBlocked != wasBlocked )
06567                 image->do_notify(QRect(QPoint(0,0), image->pixmap_size()));
06568         }
06569     }
06570 
06571     if ( KHTMLGlobal::defaultHTMLSettings()->isHideAdsEnabled() ) {
06572         for ( NodeImpl *nextNode, *node = d->m_doc; node; node = nextNode ) {
06573 
06574             // We might be deleting 'node' shortly.
06575             nextNode = node->traverseNextNode();
06576 
06577             if ( node->id() == ID_IMG ||
06578                  node->id() == ID_IFRAME ||
06579                  (node->id() == ID_INPUT && static_cast<HTMLInputElementImpl *>(node)->inputType() == HTMLInputElementImpl::IMAGE ))
06580             {
06581                 if ( KHTMLGlobal::defaultHTMLSettings()->isAdFiltered( d->m_doc->completeURL( static_cast<ElementImpl *>(node)->getAttribute(ATTR_SRC).string() ) ) )
06582                 {
06583                     // Since any kids of node will be deleted, too, fastforward nextNode
06584                     // until we get outside of node.
06585                     while (nextNode && nextNode->isAncestor(node))
06586                         nextNode = nextNode->traverseNextNode();
06587 
06588                     node->ref();
06589                     NodeImpl *parent = node->parent();
06590                     if( parent )
06591                     {
06592                         int exception = 0;
06593                         parent->removeChild(node, exception);
06594                     }
06595                     node->deref();
06596                 }
06597             }
06598         }
06599     }
06600 }
06601 
06602 void KHTMLPart::selectAll()
06603 {
06604   if (!d->m_doc) return;
06605 
06606   NodeImpl *first;
06607   if (d->m_doc->isHTMLDocument())
06608     first = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
06609   else
06610     first = d->m_doc;
06611   NodeImpl *next;
06612 
06613   // Look for first text/cdata node that has a renderer,
06614   // or first childless replaced element
06615   while ( first && !(first->renderer()
06616           && ((first->nodeType() == Node::TEXT_NODE || first->nodeType() == Node::CDATA_SECTION_NODE)
06617                 || (first->renderer()->isReplaced() && !first->renderer()->firstChild()))))
06618   {
06619     next = first->firstChild();
06620     if ( !next ) next = first->nextSibling();
06621     while( first && !next )
06622     {
06623       first = first->parentNode();
06624       if ( first )
06625         next = first->nextSibling();
06626     }
06627     first = next;
06628   }
06629 
06630   NodeImpl *last;
06631   if (d->m_doc->isHTMLDocument())
06632     last = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
06633   else
06634     last = d->m_doc;
06635   // Look for last text/cdata node that has a renderer,
06636   // or last childless replaced element
06637   // ### Instead of changing this loop, use findLastSelectableNode
06638   // in render_table.cpp (LS)
06639   while ( last && !(last->renderer()
06640           && ((last->nodeType() == Node::TEXT_NODE || last->nodeType() == Node::CDATA_SECTION_NODE)
06641                 || (last->renderer()->isReplaced() && !last->renderer()->lastChild()))))
06642   {
06643     next = last->lastChild();
06644     if ( !next ) next = last->previousSibling();
06645     while ( last && !next )
06646     {
06647       last = last->parentNode();
06648       if ( last )
06649         next = last->previousSibling();
06650     }
06651     last = next;
06652   }
06653 
06654   if ( !first || !last )
06655     return;
06656   Q_ASSERT(first->renderer());
06657   Q_ASSERT(last->renderer());
06658   d->editor_context.m_selection.moveTo(Position(first, 0), Position(last, last->nodeValue().length()));
06659   d->m_doc->updateSelection();
06660 
06661   emitSelectionChanged();
06662 }
06663 
06664 bool KHTMLPart::checkLinkSecurity(const KUrl &linkURL,const KLocalizedString &message, const QString &button)
06665 {
06666   bool linkAllowed = true;
06667 
06668   if ( d->m_doc )
06669     linkAllowed = KAuthorized::authorizeUrlAction("redirect", url(), linkURL);
06670 
06671   if ( !linkAllowed ) {
06672     khtml::Tokenizer *tokenizer = d->m_doc->tokenizer();
06673     if (tokenizer)
06674       tokenizer->setOnHold(true);
06675 
06676     int response = KMessageBox::Cancel;
06677     if (!message.isEmpty())
06678     {
06679             // Dangerous flag makes the Cancel button the default
06680             response = KMessageBox::warningContinueCancel( 0,
06681                                                            message.subs(Qt::escape(linkURL.prettyUrl())).toString(),
06682                                                            i18n( "Security Warning" ),
06683                                                            KGuiItem(button),
06684                                                            KStandardGuiItem::cancel(),
06685                                                            QString(), // no don't ask again info
06686                                                            KMessageBox::Notify | KMessageBox::Dangerous );
06687     }
06688     else
06689     {
06690             KMessageBox::error( 0,
06691                                 i18n( "<qt>Access by untrusted page to<br /><b>%1</b><br /> denied.</qt>", Qt::escape(linkURL.prettyUrl())),
06692                                 i18n( "Security Alert" ));
06693     }
06694 
06695     if (tokenizer)
06696        tokenizer->setOnHold(false);
06697     return (response==KMessageBox::Continue);
06698   }
06699   return true;
06700 }
06701 
06702 void KHTMLPart::slotPartRemoved( KParts::Part *part )
06703 {
06704 //    kDebug(6050) << part;
06705     if ( part == d->m_activeFrame )
06706     {
06707         d->m_activeFrame = 0L;
06708         if ( !part->inherits( "KHTMLPart" ) )
06709         {
06710             if (factory()) {
06711                 factory()->removeClient( part );
06712             }
06713             if (childClients().contains(part)) {
06714                 removeChildClient( part );
06715             }
06716         }
06717     }
06718 }
06719 
06720 void KHTMLPart::slotActiveFrameChanged( KParts::Part *part )
06721 {
06722 //    kDebug(6050) << this << "part=" << part;
06723     if ( part == this )
06724     {
06725         kError(6050) << "strange error! we activated ourselves";
06726         assert( false );
06727         return;
06728     }
06729 //    kDebug(6050) << "d->m_activeFrame=" << d->m_activeFrame;
06730     if ( d->m_activeFrame && d->m_activeFrame->widget() && d->m_activeFrame->widget()->inherits( "QFrame" ) )
06731     {
06732         QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() );
06733         if (frame->frameStyle() != QFrame::NoFrame)
06734         {
06735            frame->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken);
06736            frame->repaint();
06737         }
06738     }
06739 
06740     if( d->m_activeFrame && !d->m_activeFrame->inherits( "KHTMLPart" ) )
06741     {
06742         if (factory()) {
06743             factory()->removeClient( d->m_activeFrame );
06744         }
06745         removeChildClient( d->m_activeFrame );
06746     }
06747     if( part && !part->inherits( "KHTMLPart" ) )
06748     {
06749         if (factory()) {
06750             factory()->addClient( part );
06751         }
06752         insertChildClient( part );
06753     }
06754 
06755 
06756     d->m_activeFrame = part;
06757 
06758     if ( d->m_activeFrame && d->m_activeFrame->widget()->inherits( "QFrame" ) )
06759     {
06760         QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() );
06761         if (frame->frameStyle() != QFrame::NoFrame)
06762         {
06763            frame->setFrameStyle( QFrame::StyledPanel | QFrame::Plain);
06764            frame->repaint();
06765         }
06766         kDebug(6050) << "new active frame " << d->m_activeFrame;
06767     }
06768 
06769     updateActions();
06770 
06771     // (note: childObject returns 0 if the argument is 0)
06772     d->m_extension->setExtensionProxy( KParts::BrowserExtension::childObject( d->m_activeFrame ) );
06773 }
06774 
06775 void KHTMLPart::setActiveNode(const DOM::Node &node)
06776 {
06777     if (!d->m_doc || !d->m_view)
06778         return;
06779 
06780     // Set the document's active node
06781     d->m_doc->setFocusNode(node.handle());
06782 
06783     // Scroll the view if necessary to ensure that the new focus node is visible
06784     QRect rect  = node.handle()->getRect();
06785     d->m_view->ensureVisible(rect.right(), rect.bottom());
06786     d->m_view->ensureVisible(rect.left(), rect.top());
06787 }
06788 
06789 DOM::Node KHTMLPart::activeNode() const
06790 {
06791     return DOM::Node(d->m_doc?d->m_doc->focusNode():0);
06792 }
06793 
06794 DOM::EventListener *KHTMLPart::createHTMLEventListener( QString code, QString name, NodeImpl* node, bool svg )
06795 {
06796   KJSProxy *proxy = jScript();
06797 
06798   if (!proxy)
06799     return 0;
06800 
06801   return proxy->createHTMLEventHandler( url().url(), name, code, node, svg );
06802 }
06803 
06804 KHTMLPart *KHTMLPart::opener()
06805 {
06806     return d->m_opener;
06807 }
06808 
06809 void KHTMLPart::setOpener(KHTMLPart *_opener)
06810 {
06811     d->m_opener = _opener;
06812 }
06813 
06814 bool KHTMLPart::openedByJS()
06815 {
06816     return d->m_openedByJS;
06817 }
06818 
06819 void KHTMLPart::setOpenedByJS(bool _openedByJS)
06820 {
06821     d->m_openedByJS = _openedByJS;
06822 }
06823 
06824 void KHTMLPart::preloadStyleSheet(const QString &url, const QString &stylesheet)
06825 {
06826     khtml::Cache::preloadStyleSheet(url, stylesheet);
06827 }
06828 
06829 void KHTMLPart::preloadScript(const QString &url, const QString &script)
06830 {
06831     khtml::Cache::preloadScript(url, script);
06832 }
06833 
06834 long KHTMLPart::cacheId() const
06835 {
06836   return d->m_cacheId;
06837 }
06838 
06839 bool KHTMLPart::restored() const
06840 {
06841   return d->m_restored;
06842 }
06843 
06844 bool KHTMLPart::pluginPageQuestionAsked(const QString& mimetype) const
06845 {
06846   // parentPart() should be const!
06847   KHTMLPart* parent = const_cast<KHTMLPart *>(this)->parentPart();
06848   if ( parent )
06849     return parent->pluginPageQuestionAsked(mimetype);
06850 
06851   return d->m_pluginPageQuestionAsked.contains(mimetype);
06852 }
06853 
06854 void KHTMLPart::setPluginPageQuestionAsked(const QString& mimetype)
06855 {
06856   if ( parentPart() )
06857     parentPart()->setPluginPageQuestionAsked(mimetype);
06858 
06859   d->m_pluginPageQuestionAsked.append(mimetype);
06860 }
06861 
06862 KEncodingDetector *KHTMLPart::createDecoder()
06863 {
06864     KEncodingDetector *dec = new KEncodingDetector();
06865     if( !d->m_encoding.isNull() )
06866         dec->setEncoding( d->m_encoding.toLatin1().constData(),
06867             d->m_haveEncoding ? KEncodingDetector::UserChosenEncoding : KEncodingDetector::EncodingFromHTTPHeader);
06868     else {
06869         // Inherit the default encoding from the parent frame if there is one.
06870         QByteArray defaultEncoding = (parentPart() && parentPart()->d->m_decoder)
06871             ? QByteArray( parentPart()->d->m_decoder->encoding() ) : settings()->encoding().toLatin1();
06872         dec->setEncoding(defaultEncoding.constData(), KEncodingDetector::DefaultEncoding);
06873     }
06874 
06875     if (d->m_doc)
06876         d->m_doc->setDecoder(dec);
06877     dec->setAutoDetectLanguage( d->m_autoDetectLanguage );
06878     return dec;
06879 }
06880 
06881 void KHTMLPart::emitCaretPositionChanged(const DOM::Position &pos) {
06882   // pos must not be already converted to range-compliant coordinates
06883   Position rng_pos = pos.equivalentRangeCompliantPosition();
06884   Node node = rng_pos.node();
06885   emit caretPositionChanged(node, rng_pos.offset());
06886 }
06887 
06888 void KHTMLPart::restoreScrollPosition()
06889 {
06890   const KParts::OpenUrlArguments args( arguments() );
06891 
06892   if ( url().hasRef() && !d->m_restoreScrollPosition && !args.reload()) {
06893     if ( !d->m_doc || !d->m_doc->parsing() )
06894       disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
06895     if ( !gotoAnchor(url().encodedHtmlRef()) )
06896       gotoAnchor(url().htmlRef());
06897     return;
06898   }
06899 
06900   // Check whether the viewport has become large enough to encompass the stored
06901   // offsets. If the document has been fully loaded, force the new coordinates,
06902   // even if the canvas is too short (can happen when user resizes the window
06903   // during loading).
06904   if (d->m_view->contentsHeight() - d->m_view->visibleHeight() >= args.yOffset()
06905       || d->m_bComplete) {
06906     d->m_view->setContentsPos(args.xOffset(), args.yOffset());
06907     disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
06908   }
06909 }
06910 
06911 
06912 void KHTMLPart::openWallet(DOM::HTMLFormElementImpl *form)
06913 {
06914 #ifndef KHTML_NO_WALLET
06915   KHTMLPart *p;
06916 
06917   for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
06918   }
06919 
06920   if (p) {
06921     p->openWallet(form);
06922     return;
06923   }
06924 
06925   if (onlyLocalReferences()) { // avoid triggering on local apps, thumbnails
06926     return;
06927   }
06928 
06929   if (d->m_wallet) {
06930     if (d->m_bWalletOpened) {
06931       if (d->m_wallet->isOpen()) {
06932         form->walletOpened(d->m_wallet);
06933         return;
06934       }
06935       d->m_wallet->deleteLater();
06936       d->m_wallet = 0L;
06937       d->m_bWalletOpened = false;
06938     }
06939   }
06940 
06941   if (!d->m_wq) {
06942     KWallet::Wallet *wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0, KWallet::Wallet::Asynchronous);
06943     d->m_wq = new KHTMLWalletQueue(this);
06944     d->m_wq->wallet = wallet;
06945     connect(wallet, SIGNAL(walletOpened(bool)), d->m_wq, SLOT(walletOpened(bool)));
06946     connect(d->m_wq, SIGNAL(walletOpened(KWallet::Wallet*)), this, SLOT(walletOpened(KWallet::Wallet*)));
06947   }
06948   assert(form);
06949   d->m_wq->callers.append(KHTMLWalletQueue::Caller(form, form->document()));
06950 #endif // KHTML_NO_WALLET
06951 }
06952 
06953 
06954 void KHTMLPart::saveToWallet(const QString& key, const QMap<QString,QString>& data)
06955 {
06956 #ifndef KHTML_NO_WALLET
06957   KHTMLPart *p;
06958 
06959   for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
06960   }
06961 
06962   if (p) {
06963     p->saveToWallet(key, data);
06964     return;
06965   }
06966 
06967   if (d->m_wallet) {
06968     if (d->m_bWalletOpened) {
06969       if (d->m_wallet->isOpen()) {
06970         if (!d->m_wallet->hasFolder(KWallet::Wallet::FormDataFolder())) {
06971           d->m_wallet->createFolder(KWallet::Wallet::FormDataFolder());
06972         }
06973         d->m_wallet->setFolder(KWallet::Wallet::FormDataFolder());
06974         d->m_wallet->writeMap(key, data);
06975         return;
06976       }
06977       d->m_wallet->deleteLater();
06978       d->m_wallet = 0L;
06979       d->m_bWalletOpened = false;
06980     }
06981   }
06982 
06983   if (!d->m_wq) {
06984     KWallet::Wallet *wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0, KWallet::Wallet::Asynchronous);
06985     d->m_wq = new KHTMLWalletQueue(this);
06986     d->m_wq->wallet = wallet;
06987     connect(wallet, SIGNAL(walletOpened(bool)), d->m_wq, SLOT(walletOpened(bool)));
06988     connect(d->m_wq, SIGNAL(walletOpened(KWallet::Wallet*)), this, SLOT(walletOpened(KWallet::Wallet*)));
06989   }
06990   d->m_wq->savers.append(qMakePair(key, data));
06991 #endif // KHTML_NO_WALLET
06992 }
06993 
06994 
06995 void KHTMLPart::dequeueWallet(DOM::HTMLFormElementImpl *form) {
06996 #ifndef KHTML_NO_WALLET
06997   KHTMLPart *p;
06998 
06999   for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
07000   }
07001 
07002   if (p) {
07003     p->dequeueWallet(form);
07004     return;
07005   }
07006 
07007   if (d->m_wq) {
07008     d->m_wq->callers.removeAll(KHTMLWalletQueue::Caller(form, form->document()));
07009   }
07010 #endif // KHTML_NO_WALLET
07011 }
07012 
07013 
07014 void KHTMLPart::walletOpened(KWallet::Wallet *wallet) {
07015 #ifndef KHTML_NO_WALLET
07016   assert(!d->m_wallet);
07017   assert(d->m_wq);
07018 
07019   d->m_wq->deleteLater(); // safe?
07020   d->m_wq = 0L;
07021 
07022   if (!wallet) {
07023     d->m_bWalletOpened = false;
07024     return;
07025   }
07026 
07027   d->m_wallet = wallet;
07028   d->m_bWalletOpened = true;
07029   connect(d->m_wallet, SIGNAL(walletClosed()), SLOT(slotWalletClosed()));
07030   d->m_walletForms.clear();
07031   if (!d->m_statusBarWalletLabel) {
07032     d->m_statusBarWalletLabel = new KUrlLabel(d->m_statusBarExtension->statusBar());
07033     d->m_statusBarWalletLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum));
07034     d->m_statusBarWalletLabel->setUseCursor(false);
07035     d->m_statusBarExtension->addStatusBarItem(d->m_statusBarWalletLabel, 0, false);
07036     d->m_statusBarWalletLabel->setPixmap(SmallIcon("wallet-open"));
07037     connect(d->m_statusBarWalletLabel, SIGNAL(leftClickedUrl()), SLOT(launchWalletManager()));
07038     connect(d->m_statusBarWalletLabel, SIGNAL(rightClickedUrl()), SLOT(walletMenu()));
07039   }
07040   d->m_statusBarWalletLabel->setToolTip(i18n("The wallet '%1' is open and being used for form data and passwords.", KWallet::Wallet::NetworkWallet()));
07041 #endif // KHTML_NO_WALLET
07042 }
07043 
07044 
07045 KWallet::Wallet *KHTMLPart::wallet()
07046 {
07047 #ifndef KHTML_NO_WALLET
07048   KHTMLPart *p;
07049 
07050   for (p = parentPart(); p && p->parentPart(); p = p->parentPart())
07051     ;
07052 
07053   if (p)
07054     return p->wallet();
07055 
07056   return d->m_wallet;
07057 #else
07058   return 0;
07059 #endif // !KHTML_NO_WALLET
07060 }
07061 
07062 
07063 void KHTMLPart::slotWalletClosed()
07064 {
07065 #ifndef KHTML_NO_WALLET
07066   if (d->m_wallet) {
07067     d->m_wallet->deleteLater();
07068     d->m_wallet = 0L;
07069   }
07070   d->m_bWalletOpened = false;
07071   if (d->m_statusBarWalletLabel) {
07072     d->m_statusBarExtension->removeStatusBarItem(d->m_statusBarWalletLabel);
07073     delete d->m_statusBarWalletLabel;
07074     d->m_statusBarWalletLabel = 0L;
07075   }
07076 #endif // KHTML_NO_WALLET
07077 }
07078 
07079 void KHTMLPart::launchWalletManager()
07080 {
07081 #ifndef KHTML_NO_WALLET
07082   QDBusInterface r("org.kde.kwalletmanager", "/kwalletmanager/MainWindow_1",
07083                       "org.kde.KMainWindow");
07084   if (!r.isValid()) {
07085     KToolInvocation::startServiceByDesktopName("kwalletmanager_show");
07086   } else {
07087     r.call(QDBus::NoBlock, "show");
07088     r.call(QDBus::NoBlock, "raise");
07089   }
07090 #endif // KHTML_NO_WALLET
07091 }
07092 
07093 void KHTMLPart::walletMenu()
07094 {
07095 #ifndef KHTML_NO_WALLET
07096   KMenu *menu = new KMenu(0L);
07097   QActionGroup *menuActionGroup = new QActionGroup(menu);
07098   connect( menuActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(removeStoredPasswordForm(QAction*)) );
07099 
07100   menu->addAction(i18n("&Close Wallet"), this, SLOT(slotWalletClosed()));
07101 
07102   if (d->m_view && d->m_view->nonPasswordStorableSite(toplevelURL().host())) {
07103     menu->addAction(i18n("&Allow storing passwords for this site"), this, SLOT(delNonPasswordStorableSite()));
07104   }
07105 
07106   // List currently removable form passwords
07107   for ( QStringList::ConstIterator it = d->m_walletForms.constBegin(); it != d->m_walletForms.constEnd(); ++it ) {
07108       QAction* action = menu->addAction( i18n("Remove password for form %1", *it) );
07109       action->setActionGroup(menuActionGroup);
07110       QVariant var(*it);
07111       action->setData(var);
07112   }
07113 
07114   KAcceleratorManager::manage(menu);
07115   menu->popup(QCursor::pos());
07116 #endif // KHTML_NO_WALLET
07117 }
07118 
07119 void KHTMLPart::removeStoredPasswordForm(QAction* action)
07120 {
07121 #ifndef KHTML_NO_WALLET
07122   assert(action);
07123   assert(d->m_wallet);
07124   QVariant var(action->data());
07125 
07126   if(var.isNull() || !var.isValid() || var.type() != QVariant::String)
07127     return;
07128 
07129   QString key = var.toString();
07130   if (KWallet::Wallet::keyDoesNotExist(KWallet::Wallet::NetworkWallet(),
07131                                       KWallet::Wallet::FormDataFolder(),
07132                                       key))
07133     return; // failed
07134 
07135 
07136   if (!d->m_wallet->hasFolder(KWallet::Wallet::FormDataFolder()))
07137     return; // failed
07138 
07139   d->m_wallet->setFolder(KWallet::Wallet::FormDataFolder());
07140   if (d->m_wallet->removeEntry(key))
07141     return; // failed
07142 
07143   d->m_walletForms.removeAll(key);
07144 #endif // KHTML_NO_WALLET
07145 }
07146 
07147 void KHTMLPart::addWalletFormKey(const QString& walletFormKey)
07148 {
07149 #ifndef KHTML_NO_WALLET
07150 
07151   if (parentPart()) {
07152     parentPart()->addWalletFormKey(walletFormKey);
07153     return;
07154   }
07155 
07156   if(!d->m_walletForms.contains(walletFormKey))
07157     d->m_walletForms.append(walletFormKey);
07158 #endif // KHTML_NO_WALLET
07159 }
07160 
07161 void KHTMLPart::delNonPasswordStorableSite()
07162 {
07163 #ifndef KHTML_NO_WALLET
07164   if (d->m_view)
07165     d->m_view->delNonPasswordStorableSite(toplevelURL().host());
07166 #endif // KHTML_NO_WALLET
07167 }
07168 void KHTMLPart::saveLoginInformation(const QString& host, const QString& key, const QMap<QString, QString>& walletMap)
07169 {
07170 #ifndef KHTML_NO_WALLET
07171   d->m_storePass.saveLoginInformation(host, key, walletMap);
07172 #endif // KHTML_NO_WALLET
07173 }
07174 
07175 void KHTMLPart::slotToggleCaretMode()
07176 {
07177   setCaretMode(d->m_paToggleCaretMode->isChecked());
07178 }
07179 
07180 void KHTMLPart::setFormNotification(KHTMLPart::FormNotification fn) {
07181   d->m_formNotification = fn;
07182 }
07183 
07184 KHTMLPart::FormNotification KHTMLPart::formNotification() const {
07185   return d->m_formNotification;
07186 }
07187 
07188 KUrl KHTMLPart::toplevelURL()
07189 {
07190   KHTMLPart* part = this;
07191   while (part->parentPart())
07192     part = part->parentPart();
07193 
07194   if (!part)
07195     return KUrl();
07196 
07197   return part->url();
07198 }
07199 
07200 bool KHTMLPart::isModified() const
07201 {
07202   if ( !d->m_doc )
07203     return false;
07204 
07205   return d->m_doc->unsubmittedFormChanges();
07206 }
07207 
07208 void KHTMLPart::setDebugScript( bool enable )
07209 {
07210   unplugActionList( "debugScriptList" );
07211   if ( enable ) {
07212     if (!d->m_paDebugScript) {
07213       d->m_paDebugScript = new KAction( i18n( "JavaScript &Debugger" ), this );
07214       actionCollection()->addAction( "debugScript", d->m_paDebugScript );
07215       connect( d->m_paDebugScript, SIGNAL( triggered( bool ) ), this, SLOT( slotDebugScript() ) );
07216     }
07217     d->m_paDebugScript->setEnabled( d->m_frame ? d->m_frame->m_jscript : 0L );
07218     QList<QAction*> lst;
07219     lst.append( d->m_paDebugScript );
07220     plugActionList( "debugScriptList", lst );
07221   }
07222   d->m_bJScriptDebugEnabled = enable;
07223 }
07224 
07225 void KHTMLPart::setSuppressedPopupIndicator( bool enable, KHTMLPart *originPart )
07226 {
07227     if ( parentPart() ) {
07228         parentPart()->setSuppressedPopupIndicator( enable, originPart );
07229         return;
07230     }
07231 
07232     if ( enable && originPart ) {
07233         d->m_openableSuppressedPopups++;
07234         if ( d->m_suppressedPopupOriginParts.indexOf( originPart ) == -1 )
07235             d->m_suppressedPopupOriginParts.append( originPart );
07236     }
07237 
07238     if ( enable && !d->m_statusBarPopupLabel ) {
07239         d->m_statusBarPopupLabel = new KUrlLabel( d->m_statusBarExtension->statusBar() );
07240         d->m_statusBarPopupLabel->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Minimum ));
07241         d->m_statusBarPopupLabel->setUseCursor( false );
07242         d->m_statusBarExtension->addStatusBarItem( d->m_statusBarPopupLabel, 0, false );
07243         d->m_statusBarPopupLabel->setPixmap( SmallIcon( "window-suppressed") );
07244 
07245                 d->m_statusBarPopupLabel->setToolTip(i18n("This page was prevented from opening a new window via JavaScript." ) );
07246 
07247         connect(d->m_statusBarPopupLabel, SIGNAL(leftClickedUrl()), SLOT(suppressedPopupMenu()));
07248         if (d->m_settings->jsPopupBlockerPassivePopup()) {
07249             QPixmap px;
07250             px = MainBarIcon( "window-suppressed" );
07251             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);
07252         }
07253     } else if ( !enable && d->m_statusBarPopupLabel ) {
07254         d->m_statusBarPopupLabel->setToolTip("" );
07255         d->m_statusBarExtension->removeStatusBarItem( d->m_statusBarPopupLabel );
07256         delete d->m_statusBarPopupLabel;
07257         d->m_statusBarPopupLabel = 0L;
07258     }
07259 }
07260 
07261 void KHTMLPart::suppressedPopupMenu() {
07262   KMenu *m = new KMenu(0L);
07263   if ( d->m_openableSuppressedPopups )
07264       m->addAction(i18np("&Show Blocked Popup Window","&Show %1 Blocked Popup Windows", d->m_openableSuppressedPopups), this, SLOT(showSuppressedPopups()));
07265   QAction *a = m->addAction(i18n("Show Blocked Window Passive Popup &Notification"), this, SLOT(togglePopupPassivePopup()));
07266   a->setChecked(d->m_settings->jsPopupBlockerPassivePopup());
07267   m->addAction(i18n("&Configure JavaScript New Window Policies..."), this, SLOT(launchJSConfigDialog()));
07268   m->popup(QCursor::pos());
07269 }
07270 
07271 void KHTMLPart::togglePopupPassivePopup() {
07272   // Same hack as in disableJSErrorExtension()
07273   d->m_settings->setJSPopupBlockerPassivePopup( !d->m_settings->jsPopupBlockerPassivePopup() );
07274   emit configurationChanged();
07275 }
07276 
07277 void KHTMLPart::showSuppressedPopups() {
07278     foreach ( KHTMLPart* part, d->m_suppressedPopupOriginParts ) {
07279       if (part) {
07280         KJS::Window *w = KJS::Window::retrieveWindow( part );
07281         if (w) {
07282           w->showSuppressedWindows();
07283           w->forgetSuppressedWindows();
07284         }
07285       }
07286     }
07287     setSuppressedPopupIndicator( false );
07288     d->m_openableSuppressedPopups = 0;
07289     d->m_suppressedPopupOriginParts.clear();
07290 }
07291 
07292 // Extension to use for "view document source", "save as" etc.
07293 // Using the right extension can help the viewer get into the right mode (#40496)
07294 QString KHTMLPart::defaultExtension() const
07295 {
07296     if ( !d->m_doc )
07297         return ".html";
07298     if ( !d->m_doc->isHTMLDocument() )
07299         return ".xml";
07300     return d->m_doc->htmlMode() == DOM::DocumentImpl::XHtml ? ".xhtml" : ".html";
07301 }
07302 
07303 bool KHTMLPart::inProgress() const
07304 {
07305     if (!d->m_bComplete || d->m_runningScripts || (d->m_doc && d->m_doc->parsing()))
07306         return true;
07307 
07308     // Any frame that hasn't completed yet ?
07309     ConstFrameIt it = d->m_frames.constBegin();
07310     const ConstFrameIt end = d->m_frames.constEnd();
07311     for (; it != end; ++it ) {
07312         if ((*it)->m_run || !(*it)->m_bCompleted)
07313             return true;
07314     }
07315 
07316     return d->m_submitForm || !d->m_redirectURL.isEmpty() || d->m_redirectionTimer.isActive() || d->m_job;
07317 }
07318 
07319 using namespace KParts;
07320 #include "khtml_part.moc"
07321 #include "khtmlpart_p.moc"
07322 #ifndef KHTML_NO_WALLET
07323 #include "khtml_wallet_p.moc"
07324 #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