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