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

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
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
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