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

KDE's Doxygen guidelines are available online.

KHTML

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

kdelibs-4.8.3 API Reference

Skip menu "kdelibs-4.8.3 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • 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
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal