• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KHTML

khtml_part.cpp

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

KHTML

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal