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