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