khtml_part.cpp
// -*- c-basic-offset: 2 -*-
/* This file is part of the KDE project
*
* Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
* 1999 Lars Knoll <knoll@kde.org>
* 1999 Antti Koivisto <koivisto@kde.org>
* 2000 Simon Hausmann <hausmann@kde.org>
* 2000 Stefan Schimanski <1Stein@gmx.de>
* 2001-2003 George Staikos <staikos@kde.org>
* 2001-2003 Dirk Mueller <mueller@kde.org>
* 2000-2005 David Faure <faure@kde.org>
* 2002 Apple Computer, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
//#define SPEED_DEBUG
#include "khtml_part.h"
#include "khtml_pagecache.h"
#include "dom/dom_string.h"
#include "dom/dom_element.h"
#include "dom/dom_exception.h"
#include "html/html_documentimpl.h"
#include "html/html_baseimpl.h"
#include "html/html_objectimpl.h"
#include "html/html_miscimpl.h"
#include "html/html_imageimpl.h"
#include "html/html_objectimpl.h"
#include "rendering/render_text.h"
#include "rendering/render_frames.h"
#include "rendering/render_layer.h"
#include "misc/htmlhashes.h"
#include "misc/loader.h"
#include "xml/dom2_eventsimpl.h"
#include "xml/dom2_rangeimpl.h"
#include "xml/xml_tokenizer.h"
#include "css/cssstyleselector.h"
#include "css/csshelper.h"
using namespace DOM;
#include "khtmlview.h"
#include <kparts/partmanager.h>
#include "ecma/kjs_proxy.h"
#include "ecma/kjs_window.h"
#include "khtml_settings.h"
#include "kjserrordlg.h"
#include <kjs/function.h>
#include <kjs/interpreter.h>
#include "htmlpageinfo.h"
#include <sys/types.h>
#include <assert.h>
#include <unistd.h>
#include <config.h>
#include <dcopclient.h>
#include <dcopref.h>
#include <kstandarddirs.h>
#include <kstringhandler.h>
#include <kio/job.h>
#include <kio/global.h>
#include <kio/netaccess.h>
#include <kprotocolmanager.h>
#include <kdebug.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kcharsets.h>
#include <kmessagebox.h>
#include <kstdaction.h>
#include <kfiledialog.h>
#include <ktrader.h>
#include <kdatastream.h>
#include <ktempfile.h>
#include <kglobalsettings.h>
#include <kurldrag.h>
#include <kapplication.h>
#include <kparts/browserinterface.h>
#if !defined(QT_NO_DRAGANDDROP)
#include <kmultipledrag.h>
#endif
#include "../kutils/kfinddialog.h"
#include "../kutils/kfind.h"
#include <ksslcertchain.h>
#include <ksslinfodlg.h>
#include <kfileitem.h>
#include <kurifilter.h>
#include <kstatusbar.h>
#include <kurllabel.h>
#include <qclipboard.h>
#include <qfile.h>
#include <qtooltip.h>
#include <qmetaobject.h>
#include <private/qucomextra_p.h>
#include "khtmlpart_p.h"
#include "kpassivepopup.h"
#include "kpopupmenu.h"
#include "rendering/render_form.h"
#include <kwin.h>
#define HINT_UTF8 106
namespace khtml {
class PartStyleSheetLoader : public CachedObjectClient
{
public:
PartStyleSheetLoader(KHTMLPart *part, DOM::DOMString url, DocLoader* dl)
{
m_part = part;
m_cachedSheet = dl->requestStyleSheet(url, QString::null, "text/css",
true /* "user sheet" */);
if (m_cachedSheet)
m_cachedSheet->ref( this );
}
virtual ~PartStyleSheetLoader()
{
if ( m_cachedSheet ) m_cachedSheet->deref(this);
}
virtual void setStyleSheet(const DOM::DOMString&, const DOM::DOMString &sheet, const DOM::DOMString &)
{
if ( m_part )
m_part->setUserStyleSheet( sheet.string() );
delete this;
}
virtual void error( int, const QString& ) {
delete this;
}
QGuardedPtr<KHTMLPart> m_part;
khtml::CachedCSSStyleSheet *m_cachedSheet;
};
}
void khtml::ChildFrame::liveConnectEvent(const unsigned long, const QString & event, const KParts::LiveConnectExtension::ArgList & args)
{
if (!m_part || !m_frame || !m_liveconnect)
// hmmm
return;
QString script;
script.sprintf("%s(", event.latin1());
KParts::LiveConnectExtension::ArgList::const_iterator i = args.begin();
const KParts::LiveConnectExtension::ArgList::const_iterator argsBegin = i;
const KParts::LiveConnectExtension::ArgList::const_iterator argsEnd = args.end();
for ( ; i != argsEnd; ++i) {
if (i != argsBegin)
script += ",";
if ((*i).first == KParts::LiveConnectExtension::TypeString) {
script += "\"";
script += QString((*i).second).replace('\\', "\\\\").replace('"', "\\\"");
script += "\"";
} else
script += (*i).second;
}
script += ")";
kdDebug(6050) << "khtml::ChildFrame::liveConnectEvent " << script << endl;
KHTMLPart * part = ::qt_cast<KHTMLPart *>(m_part->parent());
if (!part)
return;
if (!m_jscript)
part->framejScript(m_part);
if (m_jscript) {
// we have a jscript => a part in an iframe
KJS::Completion cmp;
m_jscript->evaluate(QString::null, 1, script, 0L, &cmp);
} else
part->executeScript(m_frame->element(), script);
}
KHTMLFrameList::Iterator KHTMLFrameList::find( const QString &name )
{
Iterator it = begin();
const Iterator e = end();
for (; it!=e; ++it )
if ( (*it)->m_name==name )
break;
return it;
}
KHTMLPart::KHTMLPart( QWidget *parentWidget, const char *widgetname, QObject *parent, const char *name, GUIProfile prof )
: KParts::ReadOnlyPart( parent, name )
{
d = 0;
KHTMLFactory::registerPart( this );
setInstance( KHTMLFactory::instance(), prof == BrowserViewGUI && !parentPart() );
// TODO KDE4 - don't load plugins yet
//setInstance( KHTMLFactory::instance(), false );
init( new KHTMLView( this, parentWidget, widgetname ), prof );
}
KHTMLPart::KHTMLPart( KHTMLView *view, QObject *parent, const char *name, GUIProfile prof )
: KParts::ReadOnlyPart( parent, name )
{
d = 0;
KHTMLFactory::registerPart( this );
setInstance( KHTMLFactory::instance(), prof == BrowserViewGUI && !parentPart() );
// TODO KDE4 - don't load plugins yet
//setInstance( KHTMLFactory::instance(), false );
assert( view );
init( view, prof );
}
void KHTMLPart::init( KHTMLView *view, GUIProfile prof )
{
if ( prof == DefaultGUI )
setXMLFile( "khtml.rc" );
else if ( prof == BrowserViewGUI )
setXMLFile( "khtml_browser.rc" );
d = new KHTMLPartPrivate(parent());
d->m_view = view;
setWidget( d->m_view );
d->m_guiProfile = prof;
d->m_extension = new KHTMLPartBrowserExtension( this, "KHTMLBrowserExtension" );
d->m_hostExtension = new KHTMLPartBrowserHostExtension( this );
d->m_statusBarExtension = new KParts::StatusBarExtension( this );
d->m_statusBarIconLabel = 0L;
d->m_statusBarPopupLabel = 0L;
d->m_openableSuppressedPopups = 0;
d->m_bSecurityInQuestion = false;
d->m_paLoadImages = 0;
d->m_paDebugScript = 0;
d->m_bMousePressed = false;
d->m_bRightMousePressed = false;
d->m_bCleared = false;
d->m_paViewDocument = new KAction( i18n( "View Do&cument Source" ), CTRL + Key_U, this, SLOT( slotViewDocumentSource() ), actionCollection(), "viewDocumentSource" );
d->m_paViewFrame = new KAction( i18n( "View Frame Source" ), 0, this, SLOT( slotViewFrameSource() ), actionCollection(), "viewFrameSource" );
d->m_paViewInfo = new KAction( i18n( "View Document Information" ), CTRL+Key_I, this, SLOT( slotViewPageInfo() ), actionCollection(), "viewPageInfo" );
d->m_paSaveBackground = new KAction( i18n( "Save &Background Image As..." ), 0, this, SLOT( slotSaveBackground() ), actionCollection(), "saveBackground" );
d->m_paSaveDocument = KStdAction::saveAs( this, SLOT( slotSaveDocument() ), actionCollection(), "saveDocument" );
if ( parentPart() )
d->m_paSaveDocument->setShortcut( KShortcut() ); // avoid clashes
d->m_paSaveFrame = new KAction( i18n( "Save &Frame As..." ), 0, this, SLOT( slotSaveFrame() ), actionCollection(), "saveFrame" );
d->m_paSecurity = new KAction( i18n( "Security..." ), "decrypted", 0, this, SLOT( slotSecurity() ), actionCollection(), "security" );
d->m_paSecurity->setWhatsThis( i18n( "Security Settings<p>"
"Shows the certificate of the displayed page. Only "
"pages that have been transmitted using a secure, encrypted connection have a "
"certificate.<p> "
"Hint: If the image shows a closed lock, the page has been transmitted over a "
"secure connection.") );
d->m_paDebugRenderTree = new KAction( i18n( "Print Rendering Tree to STDOUT" ), ALT + CTRL + SHIFT + Key_A, this, SLOT( slotDebugRenderTree() ), actionCollection(), "debugRenderTree" );
d->m_paDebugDOMTree = new KAction( i18n( "Print DOM Tree to STDOUT" ), ALT + CTRL + SHIFT + Key_D, this, SLOT( slotDebugDOMTree() ), actionCollection(), "debugDOMTree" );
d->m_paStopAnimations = new KAction( i18n( "Stop Animated Images" ), 0, this, SLOT( slotStopAnimations() ), actionCollection(), "stopAnimations" );
d->m_paSetEncoding = new KActionMenu( i18n( "Set &Encoding" ), "charset", actionCollection(), "setEncoding" );
d->m_paSetEncoding->setDelayed( false );
d->m_automaticDetection = new KPopupMenu( 0L );
d->m_automaticDetection->insertItem( i18n( "Semi-Automatic" ), 0 );
d->m_automaticDetection->insertItem( i18n( "Arabic" ), 1 );
d->m_automaticDetection->insertItem( i18n( "Baltic" ), 2 );
d->m_automaticDetection->insertItem( i18n( "Central European" ), 3 );
//d->m_automaticDetection->insertItem( i18n( "Chinese" ), 4 );
d->m_automaticDetection->insertItem( i18n( "Greek" ), 5 );
d->m_automaticDetection->insertItem( i18n( "Hebrew" ), 6 );
d->m_automaticDetection->insertItem( i18n( "Japanese" ), 7 );
//d->m_automaticDetection->insertItem( i18n( "Korean" ), 8 );
d->m_automaticDetection->insertItem( i18n( "Russian" ), 9 );
//d->m_automaticDetection->insertItem( i18n( "Thai" ), 10 );
d->m_automaticDetection->insertItem( i18n( "Turkish" ), 11 );
d->m_automaticDetection->insertItem( i18n( "Ukrainian" ), 12 );
//d->m_automaticDetection->insertItem( i18n( "Unicode" ), 13 );
d->m_automaticDetection->insertItem( i18n( "Western European" ), 14 );
connect( d->m_automaticDetection, SIGNAL( activated( int ) ), this, SLOT( slotAutomaticDetectionLanguage( int ) ) );
d->m_paSetEncoding->popupMenu()->insertItem( i18n( "Automatic Detection" ), d->m_automaticDetection, 0 );
d->m_paSetEncoding->insert( new KActionSeparator( actionCollection() ) );
d->m_manualDetection = new KSelectAction( i18n( "short for Manual Detection", "Manual" ), 0, this, SLOT( slotSetEncoding() ), actionCollection(), "manualDetection" );
QStringList encodings = KGlobal::charsets()->descriptiveEncodingNames();
d->m_manualDetection->setItems( encodings );
d->m_manualDetection->setCurrentItem( -1 );
d->m_paSetEncoding->insert( d->m_manualDetection );
KConfig *config = KGlobal::config();
if ( config->hasGroup( "HTML Settings" ) ) {
config->setGroup( "HTML Settings" );
khtml::Decoder::AutoDetectLanguage language;
QCString name = QTextCodec::codecForLocale()->name();
name = name.lower();
if ( name == "cp1256" || name == "iso-8859-6" ) {
language = khtml::Decoder::Arabic;
}
else if ( name == "cp1257" || name == "iso-8859-13" || name == "iso-8859-4" ) {
language = khtml::Decoder::Baltic;
}
else if ( name == "cp1250" || name == "ibm852" || name == "iso-8859-2" || name == "iso-8859-3" ) {
language = khtml::Decoder::CentralEuropean;
}
else if ( name == "cp1251" || name == "koi8-r" || name == "iso-8859-5" ) {
language = khtml::Decoder::Russian;
}
else if ( name == "koi8-u" ) {
language = khtml::Decoder::Ukrainian;
}
else if ( name == "cp1253" || name == "iso-8859-7" ) {
language = khtml::Decoder::Greek;
}
else if ( name == "cp1255" || name == "iso-8859-8" || name == "iso-8859-8-i" ) {
language = khtml::Decoder::Hebrew;
}
else if ( name == "jis7" || name == "eucjp" || name == "sjis" ) {
language = khtml::Decoder::Japanese;
}
else if ( name == "cp1254" || name == "iso-8859-9" ) {
language = khtml::Decoder::Turkish;
}
else if ( name == "cp1252" || name == "iso-8859-1" || name == "iso-8859-15" ) {
language = khtml::Decoder::WesternEuropean;
}
else
language = khtml::Decoder::SemiautomaticDetection;
int _id = config->readNumEntry( "AutomaticDetectionLanguage", language );
d->m_automaticDetection->setItemChecked( _id, true );
d->m_paSetEncoding->popupMenu()->setItemChecked( 0, true );
d->m_autoDetectLanguage = static_cast< khtml::Decoder::AutoDetectLanguage >( _id );
}
d->m_paUseStylesheet = new KSelectAction( i18n( "Use S&tylesheet"), 0, this, SLOT( slotUseStylesheet() ), actionCollection(), "useStylesheet" );
if ( prof == BrowserViewGUI ) {
d->m_paIncZoomFactor = new KHTMLZoomFactorAction( this, true, i18n(
"Enlarge Font" ), "viewmag+", "CTRL++;CTRL+=", this,
SLOT( slotIncZoomFast() ), actionCollection(), "incFontSizes" );
d->m_paIncZoomFactor->setWhatsThis( i18n( "Enlarge Font<p>"
"Make the font in this window bigger. "
"Click and hold down the mouse button for a menu with all available font sizes." ) );
d->m_paDecZoomFactor = new KHTMLZoomFactorAction( this, false, i18n(
"Shrink Font" ), "viewmag-", CTRL + Key_Minus, this,
SLOT( slotDecZoomFast() ), actionCollection(), "decFontSizes" );
d->m_paDecZoomFactor->setWhatsThis( i18n( "Shrink Font<p>"
"Make the font in this window smaller. "
"Click and hold down the mouse button for a menu with all available font sizes." ) );
}
d->m_paFind = KStdAction::find( this, SLOT( slotFind() ), actionCollection(), "find" );
d->m_paFind->setWhatsThis( i18n( "Find text<p>"
"Shows a dialog that allows you to find text on the displayed page." ) );
d->m_paFindNext = KStdAction::findNext( this, SLOT( slotFindNext() ), actionCollection(), "findNext" );
d->m_paFindNext->setWhatsThis( i18n( "Find next<p>"
"Find the next occurrence of the text that you "
"have found using the <b>Find Text</b> function" ) );
d->m_paFindPrev = KStdAction::findPrev( this, SLOT( slotFindPrev() ), actionCollection(), "findPrevious" );
d->m_paFindPrev->setWhatsThis( i18n( "Find previous<p>"
"Find the previous occurrence of the text that you "
"have found using the <b>Find Text</b> function" ) );
d->m_paFindAheadText = new KAction( i18n("Find Text as You Type"), KShortcut( '/' ), this, SLOT( slotFindAheadText()),
actionCollection(), "findAheadText");
d->m_paFindAheadLinks = new KAction( i18n("Find Links as You Type"), KShortcut( '\'' ), this, SLOT( slotFindAheadLink()),
actionCollection(), "findAheadLink");
d->m_paFindAheadText->setEnabled( false );
d->m_paFindAheadLinks->setEnabled( false );
if ( parentPart() )
{
d->m_paFind->setShortcut( KShortcut() ); // avoid clashes
d->m_paFindNext->setShortcut( KShortcut() ); // avoid clashes
d->m_paFindPrev->setShortcut( KShortcut() ); // avoid clashes
d->m_paFindAheadText->setShortcut( KShortcut());
d->m_paFindAheadLinks->setShortcut( KShortcut());
}
d->m_paPrintFrame = new KAction( i18n( "Print Frame..." ), "frameprint", 0, this, SLOT( slotPrintFrame() ), actionCollection(), "printFrame" );
d->m_paPrintFrame->setWhatsThis( i18n( "Print Frame<p>"
"Some pages have several frames. To print only a single frame, click "
"on it and then use this function." ) );
d->m_paSelectAll = KStdAction::selectAll( this, SLOT( slotSelectAll() ), actionCollection(), "selectAll" );
if ( parentPart() )
d->m_paSelectAll->setShortcut( KShortcut() ); // avoid clashes
d->m_paToggleCaretMode = new KToggleAction(i18n("Toggle Caret Mode"),
Key_F7, this, SLOT(slotToggleCaretMode()),
actionCollection(), "caretMode");
d->m_paToggleCaretMode->setChecked(isCaretMode());
if (parentPart())
d->m_paToggleCaretMode->setShortcut(KShortcut()); // avoid clashes
// set the default java(script) flags according to the current host.
d->m_bOpenMiddleClick = d->m_settings->isOpenMiddleClickEnabled();
d->m_bBackRightClick = d->m_settings->isBackRightClickEnabled();
d->m_bJScriptEnabled = d->m_settings->isJavaScriptEnabled();
setDebugScript( d->m_settings->isJavaScriptDebugEnabled() );
d->m_bJavaEnabled = d->m_settings->isJavaEnabled();
d->m_bPluginsEnabled = d->m_settings->isPluginsEnabled();
// Set the meta-refresh flag...
d->m_metaRefreshEnabled = d->m_settings->isAutoDelayedActionsEnabled ();
connect( view, SIGNAL( zoomView( int ) ), SLOT( slotZoomView( int ) ) );
connect( this, SIGNAL( completed() ),
this, SLOT( updateActions() ) );
connect( this, SIGNAL( completed( bool ) ),
this, SLOT( updateActions() ) );
connect( this, SIGNAL( started( KIO::Job * ) ),
this, SLOT( updateActions() ) );
d->m_popupMenuXML = KXMLGUIFactory::readConfigFile( locate( "data", "khtml/khtml_popupmenu.rc", KHTMLFactory::instance() ) );
connect( khtml::Cache::loader(), SIGNAL( requestStarted( khtml::DocLoader*, khtml::CachedObject* ) ),
this, SLOT( slotLoaderRequestStarted( khtml::DocLoader*, khtml::CachedObject* ) ) );
connect( khtml::Cache::loader(), SIGNAL( requestDone( khtml::DocLoader*, khtml::CachedObject *) ),
this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
connect( khtml::Cache::loader(), SIGNAL( requestFailed( khtml::DocLoader*, khtml::CachedObject *) ),
this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
connect ( &d->m_progressUpdateTimer, SIGNAL( timeout() ), this, SLOT( slotProgressUpdate() ) );
findTextBegin(); //reset find variables
connect( &d->m_redirectionTimer, SIGNAL( timeout() ),
this, SLOT( slotRedirect() ) );
d->m_dcopobject = new KHTMLPartIface(this);
// TODO KDE4 - load plugins now (see also the constructors)
//if ( prof == BrowserViewGUI && !parentPart() )
// loadPlugins( partObject(), this, instance() );
// "khtml" catalog does not exist, our translations are in kdelibs.
// removing this catalog from KGlobal::locale() prevents problems
// with changing the language in applications at runtime -Thomas Reitelbach
KGlobal::locale()->removeCatalogue("khtml");
}
KHTMLPart::~KHTMLPart()
{
//kdDebug(6050) << "KHTMLPart::~KHTMLPart " << this << endl;
KConfig *config = KGlobal::config();
config->setGroup( "HTML Settings" );
config->writeEntry( "AutomaticDetectionLanguage", d->m_autoDetectLanguage );
delete d->m_automaticDetection;
delete d->m_manualDetection;
slotWalletClosed();
if (!parentPart()) { // only delete it if the top khtml_part closes
removeJSErrorExtension();
delete d->m_statusBarPopupLabel;
}
d->m_find = 0; // deleted by its parent, the view.
if ( d->m_manager )
{
d->m_manager->setActivePart( 0 );
// We specify "this" as parent qobject for d->manager, so no need to delete it.
}
stopAutoScroll();
d->m_redirectionTimer.stop();
if (!d->m_bComplete)
closeURL();
disconnect( khtml::Cache::loader(), SIGNAL( requestStarted( khtml::DocLoader*, khtml::CachedObject* ) ),
this, SLOT( slotLoaderRequestStarted( khtml::DocLoader*, khtml::CachedObject* ) ) );
disconnect( khtml::Cache::loader(), SIGNAL( requestDone( khtml::DocLoader*, khtml::CachedObject *) ),
this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
disconnect( khtml::Cache::loader(), SIGNAL( requestFailed( khtml::DocLoader*, khtml::CachedObject *) ),
this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
clear();
if ( d->m_view )
{
d->m_view->hide();
d->m_view->viewport()->hide();
d->m_view->m_part = 0;
}
// Have to delete this here since we forward declare it in khtmlpart_p and
// at least some compilers won't call the destructor in this case.
delete d->m_jsedlg;
d->m_jsedlg = 0;
if (!parentPart()) // only delete d->m_frame if the top khtml_part closes
delete d->m_frame;
delete d; d = 0;
KHTMLFactory::deregisterPart( this );
}
bool KHTMLPart::restoreURL( const KURL &url )
{
kdDebug( 6050 ) << "KHTMLPart::restoreURL " << url.url() << endl;
d->m_redirectionTimer.stop();
/*
* That's not a good idea as it will call closeURL() on all
* child frames, preventing them from further loading. This
* method gets called from restoreState() in case of a full frameset
* restoral, and restoreState() calls closeURL() before restoring
* anyway.
kdDebug( 6050 ) << "closing old URL" << endl;
closeURL();
*/
d->m_bComplete = false;
d->m_bLoadEventEmitted = false;
d->m_workingURL = url;
// set the java(script) flags according to the current host.
d->m_bJScriptEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptEnabled(url.host());
setDebugScript( KHTMLFactory::defaultHTMLSettings()->isJavaScriptDebugEnabled() );
d->m_bJavaEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaEnabled(url.host());
d->m_bPluginsEnabled = KHTMLFactory::defaultHTMLSettings()->isPluginsEnabled(url.host());
m_url = url;
d->m_restoreScrollPosition = true;
disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
connect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
KHTMLPageCache::self()->fetchData( d->m_cacheId, this, SLOT(slotRestoreData(const QByteArray &)));
emit started( 0L );
return true;
}
bool KHTMLPart::openURL( const KURL &url )
{
kdDebug( 6050 ) << "KHTMLPart(" << this << ")::openURL " << url.url() << endl;
d->m_redirectionTimer.stop();
// check to see if this is an "error://" URL. This is caused when an error
// occurs before this part was loaded (e.g. KonqRun), and is passed to
// khtmlpart so that it can display the error.
if ( url.protocol() == "error" && url.hasSubURL() ) {
closeURL();
if( d->m_bJScriptEnabled )
d->m_statusBarText[BarOverrideText] = d->m_statusBarText[BarDefaultText] = QString::null;
KURL::List urls = KURL::split( url );
//kdDebug(6050) << "Handling error URL. URL count:" << urls.count() << endl;
if ( urls.count() > 1 ) {
KURL mainURL = urls.first();
int error = mainURL.queryItem( "error" ).toInt();
// error=0 isn't a valid error code, so 0 means it's missing from the URL
if ( error == 0 ) error = KIO::ERR_UNKNOWN;
QString errorText = mainURL.queryItem( "errText", HINT_UTF8 );
urls.pop_front();
d->m_workingURL = KURL::join( urls );
//kdDebug(6050) << "Emitting fixed URL " << d->m_workingURL.prettyURL() << endl;
emit d->m_extension->setLocationBarURL( d->m_workingURL.prettyURL() );
htmlError( error, errorText, d->m_workingURL );
return true;
}
}
if (!parentPart()) { // only do it for toplevel part
QString host = url.isLocalFile() ? "localhost" : url.host();
QString userAgent = KProtocolManager::userAgentForHost(host);
if (userAgent != KProtocolManager::userAgentForHost(QString::null)) {
if (!d->m_statusBarUALabel) {
d->m_statusBarUALabel = new KURLLabel(d->m_statusBarExtension->statusBar());
d->m_statusBarUALabel->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small));
d->m_statusBarUALabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
d->m_statusBarUALabel->setUseCursor(false);
d->m_statusBarExtension->addStatusBarItem(d->m_statusBarUALabel, 0, false);
d->m_statusBarUALabel->setPixmap(SmallIcon("agent", instance()));
} else {
QToolTip::remove(d->m_statusBarUALabel);
}
QToolTip::add(d->m_statusBarUALabel, i18n("The fake user-agent '%1' is in use.").arg(userAgent));
} else if (d->m_statusBarUALabel) {
d->m_statusBarExtension->removeStatusBarItem(d->m_statusBarUALabel);
delete d->m_statusBarUALabel;
d->m_statusBarUALabel = 0L;
}
}
KParts::URLArgs args( d->m_extension->urlArgs() );
// in case
// a) we have no frameset (don't test m_frames.count(), iframes get in there)
// b) the url is identical with the currently displayed one (except for the htmlref!)
// c) the url request is not a POST operation and
// d) the caller did not request to reload the page
// e) there was no HTTP redirection meanwhile (testcase: webmin's software/tree.cgi)
// => we don't reload the whole document and
// we just jump to the requested html anchor
bool isFrameSet = false;
if ( d->m_doc && d->m_doc->isHTMLDocument() ) {
HTMLDocumentImpl* htmlDoc = static_cast<HTMLDocumentImpl*>(d->m_doc);
isFrameSet = htmlDoc->body() && (htmlDoc->body()->id() == ID_FRAMESET);
}
if ( url.hasRef() && !isFrameSet )
{
bool noReloadForced = !args.reload && !args.redirectedRequest() && !args.doPost();
if (noReloadForced && urlcmp( url.url(), m_url.url(), true, true ))
{
kdDebug( 6050 ) << "KHTMLPart::openURL, jumping to anchor. m_url = " << url.url() << endl;
m_url = url;
emit started( 0L );
if ( !gotoAnchor( url.encodedHtmlRef()) )
gotoAnchor( url.htmlRef() );
d->m_bComplete = true;
if (d->m_doc)
d->m_doc->setParsing(false);
kdDebug( 6050 ) << "completed..." << endl;
emit completed();
return true;
}
}
// Save offset of viewport when page is reloaded to be compliant
// to every other capable browser out there.
if (args.reload) {
args.xOffset = d->m_view->contentsX();
args.yOffset = d->m_view->contentsY();
d->m_extension->setURLArgs(args);
}
if (!d->m_restored)
closeURL();
d->m_restoreScrollPosition = d->m_restored;
disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
connect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
// 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
// data arrives) (Simon)
m_url = url;
if(m_url.protocol().startsWith( "http" ) && !m_url.host().isEmpty() &&
m_url.path().isEmpty()) {
m_url.setPath("/");
emit d->m_extension->setLocationBarURL( m_url.prettyURL() );
}
// copy to m_workingURL after fixing m_url above
d->m_workingURL = m_url;
args.metaData().insert("main_frame_request", parentPart() == 0 ? "TRUE" : "FALSE" );
args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
args.metaData().insert("PropagateHttpHeader", "true");
args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE" : "FALSE" );
args.metaData().insert("ssl_activate_warnings", "TRUE" );
args.metaData().insert("cross-domain", toplevelURL().url());
if (d->m_restored)
{
args.metaData().insert("referrer", d->m_pageReferrer);
d->m_cachePolicy = KIO::CC_Cache;
}
else if (args.reload)
d->m_cachePolicy = KIO::CC_Reload;
else
d->m_cachePolicy = KProtocolManager::cacheControl();
if ( args.doPost() && (m_url.protocol().startsWith("http")) )
{
d->m_job = KIO::http_post( m_url, args.postData, false );
d->m_job->addMetaData("content-type", args.contentType() );
}
else
{
d->m_job = KIO::get( m_url, false, false );
d->m_job->addMetaData("cache", KIO::getCacheControlString(d->m_cachePolicy));
}
if (widget())
d->m_job->setWindow(widget()->topLevelWidget());
d->m_job->addMetaData(args.metaData());
connect( d->m_job, SIGNAL( result( KIO::Job* ) ),
SLOT( slotFinished( KIO::Job* ) ) );
connect( d->m_job, SIGNAL( data( KIO::Job*, const QByteArray& ) ),
SLOT( slotData( KIO::Job*, const QByteArray& ) ) );
connect ( d->m_job, SIGNAL( infoMessage( KIO::Job*, const QString& ) ),
SLOT( slotInfoMessage(KIO::Job*, const QString& ) ) );
connect( d->m_job, SIGNAL(redirection(KIO::Job*, const KURL& ) ),
SLOT( slotRedirection(KIO::Job*, const KURL&) ) );
d->m_bComplete = false;
d->m_bLoadEventEmitted = false;
// delete old status bar msg's from kjs (if it _was_ activated on last URL)
if( d->m_bJScriptEnabled )
d->m_statusBarText[BarOverrideText] = d->m_statusBarText[BarDefaultText] = QString::null;
// set the javascript flags according to the current url
d->m_bJScriptEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptEnabled(url.host());
setDebugScript( KHTMLFactory::defaultHTMLSettings()->isJavaScriptDebugEnabled() );
d->m_bJavaEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaEnabled(url.host());
d->m_bPluginsEnabled = KHTMLFactory::defaultHTMLSettings()->isPluginsEnabled(url.host());
connect( d->m_job, SIGNAL( speed( KIO::Job*, unsigned long ) ),
this, SLOT( slotJobSpeed( KIO::Job*, unsigned long ) ) );
connect( d->m_job, SIGNAL( percent( KIO::Job*, unsigned long ) ),
this, SLOT( slotJobPercent( KIO::Job*, unsigned long ) ) );
connect( d->m_job, SIGNAL( result( KIO::Job* ) ),
this, SLOT( slotJobDone( KIO::Job* ) ) );
d->m_jobspeed = 0;
// If this was an explicit reload and the user style sheet should be used,
// do a stat to see whether the stylesheet was changed in the meanwhile.
if ( args.reload && !settings()->userStyleSheet().isEmpty() ) {
KURL url( settings()->userStyleSheet() );
KIO::StatJob *job = KIO::stat( url, false /* don't show progress */ );
connect( job, SIGNAL( result( KIO::Job * ) ),
this, SLOT( slotUserSheetStatDone( KIO::Job * ) ) );
}
emit started( 0L );
return true;
}
bool KHTMLPart::closeURL()
{
if ( d->m_job )
{
KHTMLPageCache::self()->cancelEntry(d->m_cacheId);
d->m_job->kill();
d->m_job = 0;
}
if ( d->m_doc && d->m_doc->isHTMLDocument() ) {
HTMLDocumentImpl* hdoc = static_cast<HTMLDocumentImpl*>( d->m_doc );
if ( hdoc->body() && d->m_bLoadEventEmitted ) {
hdoc->body()->dispatchWindowEvent( EventImpl::UNLOAD_EVENT, false, false );
if ( d->m_doc )
d->m_doc->updateRendering();
d->m_bLoadEventEmitted = false;
}
}
d->m_bComplete = true; // to avoid emitting completed() in slotFinishedParsing() (David)
d->m_bLoadEventEmitted = true; // don't want that one either
d->m_cachePolicy = KProtocolManager::cacheControl(); // reset cache policy
disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
KHTMLPageCache::self()->cancelFetch(this);
if ( d->m_doc && d->m_doc->parsing() )
{
kdDebug( 6050 ) << " was still parsing... calling end " << endl;
slotFinishedParsing();
d->m_doc->setParsing(false);
}
if ( !d->m_workingURL.isEmpty() )
{
// Aborted before starting to render
kdDebug( 6050 ) << "Aborted before starting to render, reverting location bar to " << m_url.prettyURL() << endl;
emit d->m_extension->setLocationBarURL( m_url.prettyURL() );
}
d->m_workingURL = KURL();
if ( d->m_doc && d->m_doc->docLoader() )
khtml::Cache::loader()->cancelRequests( d->m_doc->docLoader() );
// tell all subframes to stop as well
{
ConstFrameIt it = d->m_frames.begin();
const ConstFrameIt end = d->m_frames.end();
for (; it != end; ++it )
{
if ( (*it)->m_run )
(*it)->m_run->abort();
if ( !( *it )->m_part.isNull() )
( *it )->m_part->closeURL();
}
}
// tell all objects to stop as well
{
ConstFrameIt it = d->m_objects.begin();
const ConstFrameIt end = d->m_objects.end();
for (; it != end; ++it)
{
if ( !( *it )->m_part.isNull() )
( *it )->m_part->closeURL();
}
}
// Stop any started redirections as well!! (DA)
if ( d && d->m_redirectionTimer.isActive() )
d->m_redirectionTimer.stop();
// null node activated.
emit nodeActivated(Node());
// make sure before clear() runs, we pop out of a dialog's message loop
if ( d->m_view )
d->m_view->closeChildDialogs();
return true;
}
DOM::HTMLDocument KHTMLPart::htmlDocument() const
{
if (d->m_doc && d->m_doc->isHTMLDocument())
return static_cast<HTMLDocumentImpl*>(d->m_doc);
else
return static_cast<HTMLDocumentImpl*>(0);
}
DOM::Document KHTMLPart::document() const
{
return d->m_doc;
}
QString KHTMLPart::documentSource() const
{
QString sourceStr;
if ( !( m_url.isLocalFile() ) && KHTMLPageCache::self()->isComplete( d->m_cacheId ) )
{
QByteArray sourceArray;
QDataStream dataStream( sourceArray, IO_WriteOnly );
KHTMLPageCache::self()->saveData( d->m_cacheId, &dataStream );
QTextStream stream( sourceArray, IO_ReadOnly );
stream.setCodec( QTextCodec::codecForName( encoding().latin1() ) );
sourceStr = stream.read();
} else
{
QString tmpFile;
if( KIO::NetAccess::download( m_url, tmpFile, NULL ) )
{
QFile f( tmpFile );
if ( f.open( IO_ReadOnly ) )
{
QTextStream stream( &f );
stream.setCodec( QTextCodec::codecForName( encoding().latin1() ) );
sourceStr = stream.read();
f.close();
}
KIO::NetAccess::removeTempFile( tmpFile );
}
}
return sourceStr;
}
KParts::BrowserExtension *KHTMLPart::browserExtension() const
{
return d->m_extension;
}
KParts::BrowserHostExtension *KHTMLPart::browserHostExtension() const
{
return d->m_hostExtension;
}
KHTMLView *KHTMLPart::view() const
{
return d->m_view;
}
void KHTMLPart::setStatusMessagesEnabled( bool enable )
{
d->m_statusMessagesEnabled = enable;
}
KJS::Interpreter *KHTMLPart::jScriptInterpreter()
{
KJSProxy *proxy = jScript();
if (!proxy || proxy->paused())
return 0;
return proxy->interpreter();
}
bool KHTMLPart::statusMessagesEnabled() const
{
return d->m_statusMessagesEnabled;
}
void KHTMLPart::setJScriptEnabled( bool enable )
{
if ( !enable && jScriptEnabled() && d->m_frame && d->m_frame->m_jscript ) {
d->m_frame->m_jscript->clear();
}
d->m_bJScriptForce = enable;
d->m_bJScriptOverride = true;
}
bool KHTMLPart::jScriptEnabled() const
{
if(onlyLocalReferences()) return false;
if ( d->m_bJScriptOverride )
return d->m_bJScriptForce;
return d->m_bJScriptEnabled;
}
void KHTMLPart::setMetaRefreshEnabled( bool enable )
{
d->m_metaRefreshEnabled = enable;
}
bool KHTMLPart::metaRefreshEnabled() const
{
return d->m_metaRefreshEnabled;
}
// Define this to disable dlopening kjs_html, when directly linking to it.
// You need to edit khtml/Makefile.am to add ./ecma/libkjs_html.la to LIBADD
// and to edit khtml/ecma/Makefile.am to s/kjs_html/libkjs_html/, remove libkhtml from LIBADD,
// remove LDFLAGS line, and replace kde_module with either lib (shared) or noinst (static)
// Also, change the order of "ecma" and "." in khtml's SUBDIRS line.
// OK - that's the default now, use the opposite of the above instructions to go back
// to "dlopening it" - but it breaks exception catching in kjs_binding.cpp
#define DIRECT_LINKAGE_TO_ECMA
#ifdef DIRECT_LINKAGE_TO_ECMA
extern "C" { KJSProxy *kjs_html_init(khtml::ChildFrame * childframe); }
#endif
static bool createJScript(khtml::ChildFrame *frame)
{
#ifndef DIRECT_LINKAGE_TO_ECMA
KLibrary *lib = KLibLoader::self()->library("kjs_html");
if ( !lib ) {
setJScriptEnabled( false );
return false;
}
// look for plain C init function
void *sym = lib->symbol("kjs_html_init");
if ( !sym ) {
lib->unload();
setJScriptEnabled( false );
return false;
}
typedef KJSProxy* (*initFunction)(khtml::ChildFrame *);
initFunction initSym = (initFunction) sym;
frame->m_jscript = (*initSym)(d->m_frame);
frame->m_kjs_lib = lib;
#else
frame->m_jscript = kjs_html_init(frame);
// frame->m_kjs_lib remains 0L.
#endif
return true;
}
KJSProxy *KHTMLPart::jScript()
{
if (!jScriptEnabled()) return 0;
if ( !d->m_frame ) {
KHTMLPart * p = parentPart();
if (!p) {
d->m_frame = new khtml::ChildFrame;
d->m_frame->m_part = this;
} else {
ConstFrameIt it = p->d->m_frames.begin();
const ConstFrameIt end = p->d->m_frames.end();
for (; it != end; ++it)
if ((*it)->m_part.operator->() == this) {
d->m_frame = *it;
break;
}
}
if ( !d->m_frame )
return 0;
}
if ( !d->m_frame->m_jscript )
if (!createJScript(d->m_frame))
return 0;
if (d->m_bJScriptDebugEnabled)
d->m_frame->m_jscript->setDebugEnabled(true);
return d->m_frame->m_jscript;
}
QVariant KHTMLPart::crossFrameExecuteScript(const QString& target, const QString& script)
{
KHTMLPart* destpart = this;
QString trg = target.lower();
if (target == "_top") {
while (destpart->parentPart())
destpart = destpart->parentPart();
}
else if (target == "_parent") {
if (parentPart())
destpart = parentPart();
}
else if (target == "_self" || target == "_blank") {
// we always allow these
}
else {
destpart = findFrame(target);
if (!destpart)
destpart = this;
}
// easy way out?
if (destpart == this)
return executeScript(DOM::Node(), script);
// now compare the domains
if (destpart->checkFrameAccess(this))
return destpart->executeScript(DOM::Node(), script);
// eww, something went wrong. better execute it in our frame
return executeScript(DOM::Node(), script);
}
//Enable this to see all JS scripts being executed
//#define KJS_VERBOSE
KJSErrorDlg *KHTMLPart::jsErrorExtension() {
if (!d->m_settings->jsErrorsEnabled()) {
return 0L;
}
if (parentPart()) {
return parentPart()->jsErrorExtension();
}
if (!d->m_statusBarJSErrorLabel) {
d->m_statusBarJSErrorLabel = new KURLLabel(d->m_statusBarExtension->statusBar());
d->m_statusBarJSErrorLabel->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small));
d->m_statusBarJSErrorLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
d->m_statusBarJSErrorLabel->setUseCursor(false);
d->m_statusBarExtension->addStatusBarItem(d->m_statusBarJSErrorLabel, 0, false);
QToolTip::add(d->m_statusBarJSErrorLabel, i18n("This web page contains coding errors."));
d->m_statusBarJSErrorLabel->setPixmap(SmallIcon("bug", instance()));
connect(d->m_statusBarJSErrorLabel, SIGNAL(leftClickedURL()), SLOT(launchJSErrorDialog()));
connect(d->m_statusBarJSErrorLabel, SIGNAL(rightClickedURL()), SLOT(jsErrorDialogContextMenu()));
}
if (!d->m_jsedlg) {
d->m_jsedlg = new KJSErrorDlg;
d->m_jsedlg->setURL(m_url.prettyURL());
if (KGlobalSettings::showIconsOnPushButtons()) {
d->m_jsedlg->_clear->setIconSet(SmallIconSet("locationbar_erase"));
d->m_jsedlg->_close->setIconSet(SmallIconSet("fileclose"));
}
}
return d->m_jsedlg;
}
void KHTMLPart::removeJSErrorExtension() {
if (parentPart()) {
parentPart()->removeJSErrorExtension();
return;
}
if (d->m_statusBarJSErrorLabel != 0) {
d->m_statusBarExtension->removeStatusBarItem( d->m_statusBarJSErrorLabel );
delete d->m_statusBarJSErrorLabel;
d->m_statusBarJSErrorLabel = 0;
}
delete d->m_jsedlg;
d->m_jsedlg = 0;
}
void KHTMLPart::disableJSErrorExtension() {
removeJSErrorExtension();
// These two lines are really kind of hacky, and it sucks to do this inside
// KHTML but I don't know of anything that's reasonably easy as an alternative
// right now. It makes me wonder if there should be a more clean way to
// contact all running "KHTML" instance as opposed to Konqueror instances too.
d->m_settings->setJSErrorsEnabled(false);
DCOPClient::mainClient()->send("konqueror*", "KonquerorIface", "reparseConfiguration()", QByteArray());
}
void KHTMLPart::jsErrorDialogContextMenu() {
KPopupMenu *m = new KPopupMenu(0L);
m->insertItem(i18n("&Hide Errors"), this, SLOT(removeJSErrorExtension()));
m->insertItem(i18n("&Disable Error Reporting"), this, SLOT(disableJSErrorExtension()));
m->popup(QCursor::pos());
}
void KHTMLPart::launchJSErrorDialog() {
KJSErrorDlg *dlg = jsErrorExtension();
if (dlg) {
dlg->show();
dlg->raise();
}
}
void KHTMLPart::launchJSConfigDialog() {
QStringList args;
args << "khtml_java_js";
KApplication::kdeinitExec( "kcmshell", args );
}
QVariant KHTMLPart::executeScript(const QString& filename, int baseLine, const DOM::Node& n, const QString& script)
{
#ifdef KJS_VERBOSE
// The script is now printed by KJS's Parser::parse
kdDebug(6070) << "executeScript: caller='" << name() << "' filename=" << filename << " baseLine=" << baseLine /*<< " script=" << script*/ << endl;
#endif
KJSProxy *proxy = jScript();
if (!proxy || proxy->paused())
return QVariant();
KJS::Completion comp;
QVariant ret = proxy->evaluate(filename, baseLine, script, n, &comp);
/*
* Error handling
*/
if (comp.complType() == KJS::Throw && !comp.value().isNull()) {
KJSErrorDlg *dlg = jsErrorExtension();
if (dlg) {
KJS::UString msg = comp.value().toString(proxy->interpreter()->globalExec());
dlg->addError(i18n("<b>Error</b>: %1: %2").arg(filename, msg.qstring()));
}
}
// Handle immediate redirects now (e.g. location='foo')
if ( !d->m_redirectURL.isEmpty() && d->m_delayRedirect == -1 )
{
kdDebug(6070) << "executeScript done, handling immediate redirection NOW" << endl;
// Must abort tokenizer, no further script must execute.
khtml::Tokenizer* t = d->m_doc->tokenizer();
if(t)
t->abort();
d->m_redirectionTimer.start( 0, true );
}
return ret;
}
QVariant KHTMLPart::executeScript( const QString &script )
{
return executeScript( DOM::Node(), script );
}
QVariant KHTMLPart::executeScript( const DOM::Node &n, const QString &script )
{
#ifdef KJS_VERBOSE
kdDebug(6070) << "KHTMLPart::executeScript caller='" << name() << "' node=" << n.nodeName().string().latin1() << "(" << (n.isNull() ? 0 : n.nodeType()) << ") " /* << script */ << endl;
#endif
KJSProxy *proxy = jScript();
if (!proxy || proxy->paused())
return QVariant();
++(d->m_runningScripts);
KJS::Completion comp;
const QVariant ret = proxy->evaluate( QString::null, 1, script, n, &comp );
--(d->m_runningScripts);
/*
* Error handling
*/
if (comp.complType() == KJS::Throw && !comp.value().isNull()) {
KJSErrorDlg *dlg = jsErrorExtension();
if (dlg) {
KJS::UString msg = comp.value().toString(proxy->interpreter()->globalExec());
dlg->addError(i18n("<b>Error</b>: node %1: %2").arg(n.nodeName().string()).arg(msg.qstring()));
}
}
if (!d->m_runningScripts && d->m_doc && !d->m_doc->parsing() && d->m_submitForm )
submitFormAgain();
#ifdef KJS_VERBOSE
kdDebug(6070) << "KHTMLPart::executeScript - done" << endl;
#endif
return ret;
}
bool KHTMLPart::scheduleScript(const DOM::Node &n, const QString& script)
{
//kdDebug(6050) << "KHTMLPart::scheduleScript "<< script << endl;
d->scheduledScript = script;
d->scheduledScriptNode = n;
return true;
}
QVariant KHTMLPart::executeScheduledScript()
{
if( d->scheduledScript.isEmpty() )
return QVariant();
//kdDebug(6050) << "executing delayed " << d->scheduledScript << endl;
QVariant ret = executeScript( d->scheduledScriptNode, d->scheduledScript );
d->scheduledScript = QString();
d->scheduledScriptNode = DOM::Node();
return ret;
}
void KHTMLPart::setJavaEnabled( bool enable )
{
d->m_bJavaForce = enable;
d->m_bJavaOverride = true;
}
bool KHTMLPart::javaEnabled() const
{
if (onlyLocalReferences()) return false;
#ifndef Q_WS_QWS
if( d->m_bJavaOverride )
return d->m_bJavaForce;
return d->m_bJavaEnabled;
#else
return false;
#endif
}
KJavaAppletContext *KHTMLPart::javaContext()
{
return 0;
}
KJavaAppletContext *KHTMLPart::createJavaContext()
{
return 0;
}
void KHTMLPart::setPluginsEnabled( bool enable )
{
d->m_bPluginsForce = enable;
d->m_bPluginsOverride = true;
}
bool KHTMLPart::pluginsEnabled() const
{
if (onlyLocalReferences()) return false;
if ( d->m_bPluginsOverride )
return d->m_bPluginsForce;
return d->m_bPluginsEnabled;
}
static int s_DOMTreeIndentLevel = 0;
void KHTMLPart::slotDebugDOMTree()
{
if ( d->m_doc && d->m_doc->firstChild() )
qDebug("%s", d->m_doc->firstChild()->toString().string().latin1());
// Now print the contents of the frames that contain HTML
const int indentLevel = s_DOMTreeIndentLevel++;
ConstFrameIt it = d->m_frames.begin();
const ConstFrameIt end = d->m_frames.end();
for (; it != end; ++it )
if ( !( *it )->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
KParts::ReadOnlyPart* const p = ( *it )->m_part;
kdDebug(6050) << QString().leftJustify(s_DOMTreeIndentLevel*4,' ') << "FRAME " << p->name() << " " << endl;
static_cast<KHTMLPart*>( p )->slotDebugDOMTree();
}
s_DOMTreeIndentLevel = indentLevel;
}
void KHTMLPart::slotDebugScript()
{
if (jScript())
jScript()->showDebugWindow();
}
void KHTMLPart::slotDebugRenderTree()
{
#ifndef NDEBUG
if ( d->m_doc ) {
d->m_doc->renderer()->printTree();
// dump out the contents of the rendering & DOM trees
// QString dumps;
// QTextStream outputStream(dumps,IO_WriteOnly);
// d->m_doc->renderer()->layer()->dump( outputStream );
// kdDebug() << "dump output:" << "\n" + dumps;
}
#endif
}
void KHTMLPart::slotStopAnimations()
{
stopAnimations();
}
void KHTMLPart::setAutoloadImages( bool enable )
{
if ( d->m_doc && d->m_doc->docLoader()->autoloadImages() == enable )
return;
if ( d->m_doc )
d->m_doc->docLoader()->setAutoloadImages( enable );
unplugActionList( "loadImages" );
if ( enable ) {
delete d->m_paLoadImages;
d->m_paLoadImages = 0;
}
else if ( !d->m_paLoadImages )
d->m_paLoadImages = new KAction( i18n( "Display Images on Page" ), "images_display", 0, this, SLOT( slotLoadImages() ), actionCollection(), "loadImages" );
if ( d->m_paLoadImages ) {
QPtrList<KAction> lst;
lst.append( d->m_paLoadImages );
plugActionList( "loadImages", lst );
}
}
bool KHTMLPart::autoloadImages() const
{
if ( d->m_doc )
return d->m_doc->docLoader()->autoloadImages();
return true;
}
void KHTMLPart::clear()
{
if ( d->m_bCleared )
return;
d->m_bCleared = true;
d->m_bClearing = true;
{
ConstFrameIt it = d->m_frames.begin();
const ConstFrameIt end = d->m_frames.end();
for(; it != end; ++it )
{
// Stop HTMLRun jobs for frames
if ( (*it)->m_run )
(*it)->m_run->abort();
}
}
{
ConstFrameIt it = d->m_objects.begin();
const ConstFrameIt end = d->m_objects.end();
for(; it != end; ++it )
{
// Stop HTMLRun jobs for objects
if ( (*it)->m_run )
(*it)->m_run->abort();
}
}
findTextBegin(); // resets d->m_findNode and d->m_findPos
d->m_mousePressNode = DOM::Node();
if ( d->m_doc )
{
if (d->m_doc->attached()) //the view may have detached it already
d->m_doc->detach();
}
// Moving past doc so that onUnload works.
if ( d->m_frame && d->m_frame->m_jscript )
d->m_frame->m_jscript->clear();
// stopping marquees
if (d->m_doc && d->m_doc->renderer() && d->m_doc->renderer()->layer())
d->m_doc->renderer()->layer()->suspendMarquees();
if ( d->m_view )
d->m_view->clear();
// do not dereference the document before the jscript and view are cleared, as some destructors
// might still try to access the document.
if ( d->m_doc ) {
d->m_doc->deref();
}
d->m_doc = 0;
delete d->m_decoder;
d->m_decoder = 0;
// We don't want to change between parts if we are going to delete all of them anyway
disconnect( partManager(), SIGNAL( activePartChanged( KParts::Part * ) ),
this, SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
if (d->m_frames.count())
{
KHTMLFrameList frames = d->m_frames;
d->m_frames.clear();
ConstFrameIt it = frames.begin();
const ConstFrameIt end = frames.end();
for(; it != end; ++it )
{
if ( (*it)->m_part )
{
partManager()->removePart( (*it)->m_part );
delete (KParts::ReadOnlyPart *)(*it)->m_part;
}
delete *it;
}
}
d->m_suppressedPopupOriginParts.clear();
if (d->m_objects.count())
{
KHTMLFrameList objects = d->m_objects;
d->m_objects.clear();
ConstFrameIt oi = objects.begin();
const ConstFrameIt oiEnd = objects.end();
for (; oi != oiEnd; ++oi )
delete *oi;
}
// Listen to part changes again
connect( partManager(), SIGNAL( activePartChanged( KParts::Part * ) ),
this, SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
d->m_delayRedirect = 0;
d->m_redirectURL = QString::null;
d->m_redirectionTimer.stop();
d->m_redirectLockHistory = true;
d->m_bClearing = false;
d->m_frameNameId = 1;
d->m_bFirstData = true;
d->m_bMousePressed = false;
d->m_selectionStart = DOM::Node();
d->m_selectionEnd = DOM::Node();
d->m_startOffset = 0;
d->m_endOffset = 0;
#ifndef QT_NO_CLIPBOARD
connect( kapp->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection()));
#endif
d->m_jobPercent = 0;
if ( !d->m_haveEncoding )
d->m_encoding = QString::null;
#ifdef SPEED_DEBUG
d->m_parsetime.restart();
#endif
}
bool KHTMLPart::openFile()
{
return true;
}
DOM::HTMLDocumentImpl *KHTMLPart::docImpl() const
{
if ( d && d->m_doc && d->m_doc->isHTMLDocument() )
return static_cast<HTMLDocumentImpl*>(d->m_doc);
return 0;
}
DOM::DocumentImpl *KHTMLPart::xmlDocImpl() const
{
if ( d )
return d->m_doc;
return 0;
}
void KHTMLPart::slotInfoMessage(KIO::Job* kio_job, const QString& msg)
{
assert(d->m_job == kio_job);
if (!parentPart())
setStatusBarText(msg, BarDefaultText);
}
void KHTMLPart::setPageSecurity( PageSecurity sec )
{
emit d->m_extension->setPageSecurity( sec );
if ( sec != NotCrypted && !d->m_statusBarIconLabel && !parentPart() ) {
d->m_statusBarIconLabel = new KURLLabel( d->m_statusBarExtension->statusBar() );
d->m_statusBarIconLabel->setFixedHeight( instance()->iconLoader()->currentSize(KIcon::Small) );
d->m_statusBarIconLabel->setSizePolicy(QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ));
d->m_statusBarIconLabel->setUseCursor( false );
d->m_statusBarExtension->addStatusBarItem( d->m_statusBarIconLabel, 0, false );
connect( d->m_statusBarIconLabel, SIGNAL( leftClickedURL() ), SLOT( slotSecurity() ) );
} else if (d->m_statusBarIconLabel) {
QToolTip::remove(d->m_statusBarIconLabel);
}
if (d->m_statusBarIconLabel) {
if (d->m_ssl_in_use)
QToolTip::add(d->m_statusBarIconLabel,
i18n("Session is secured with %1 bit %2.").arg(d->m_ssl_cipher_used_bits).arg(d->m_ssl_cipher));
else QToolTip::add(d->m_statusBarIconLabel, i18n("Session is not secured."));
}
QString iconName;
switch (sec) {
case NotCrypted:
iconName = "decrypted";
if ( d->m_statusBarIconLabel ) {
d->m_statusBarExtension->removeStatusBarItem( d->m_statusBarIconLabel );
delete d->m_statusBarIconLabel;
d->m_statusBarIconLabel = 0L;
}
break;
case Encrypted:
iconName = "encrypted";
break;
case Mixed:
iconName = "halfencrypted";
break;
}
d->m_paSecurity->setIcon( iconName );
if ( d->m_statusBarIconLabel )
d->m_statusBarIconLabel->setPixmap( SmallIcon( iconName, instance() ) );
}
void KHTMLPart::slotData( KIO::Job* kio_job, const QByteArray &data )
{
assert ( d->m_job == kio_job );
//kdDebug( 6050 ) << "slotData: " << data.size() << endl;
// The first data ?
if ( !d->m_workingURL.isEmpty() )
{
//kdDebug( 6050 ) << "begin!" << endl;
// We must suspend KIO while we're inside begin() because it can cause
// crashes if a window (such as kjsdebugger) goes back into the event loop,
// more data arrives, and begin() gets called again (re-entered).
d->m_job->suspend();
begin( d->m_workingURL, d->m_extension->urlArgs().xOffset, d->m_extension->urlArgs().yOffset );
d->m_job->resume();
if (d->m_cachePolicy == KIO::CC_Refresh)
d->m_doc->docLoader()->setCachePolicy(KIO::CC_Verify);
else
d->m_doc->docLoader()->setCachePolicy(d->m_cachePolicy);
d->m_workingURL = KURL();
d->m_cacheId = KHTMLPageCache::self()->createCacheEntry();
// When the first data arrives, the metadata has just been made available
d->m_httpHeaders = d->m_job->queryMetaData("HTTP-Headers");
time_t cacheCreationDate = d->m_job->queryMetaData("cache-creation-date").toLong();
d->m_doc->docLoader()->setCacheCreationDate(cacheCreationDate);
d->m_pageServices = d->m_job->queryMetaData("PageServices");
d->m_pageReferrer = d->m_job->queryMetaData("referrer");
d->m_bSecurityInQuestion = false;
d->m_ssl_in_use = (d->m_job->queryMetaData("ssl_in_use") == "TRUE");
{
KHTMLPart *p = parentPart();
if (p && p->d->m_ssl_in_use != d->m_ssl_in_use) {
while (p->parentPart()) p = p->parentPart();
p->setPageSecurity( Mixed );
p->d->m_bSecurityInQuestion = true;
}
}
setPageSecurity( d->m_ssl_in_use ? Encrypted : NotCrypted );
// Shouldn't all of this be done only if ssl_in_use == true ? (DF)
d->m_ssl_parent_ip = d->m_job->queryMetaData("ssl_parent_ip");
d->m_ssl_parent_cert = d->m_job->queryMetaData("ssl_parent_cert");
d->m_ssl_peer_certificate = d->m_job->queryMetaData("ssl_peer_certificate");
d->m_ssl_peer_chain = d->m_job->queryMetaData("ssl_peer_chain");
d->m_ssl_peer_ip = d->m_job->queryMetaData("ssl_peer_ip");
d->m_ssl_cipher = d->m_job->queryMetaData("ssl_cipher");
d->m_ssl_cipher_desc = d->m_job->queryMetaData("ssl_cipher_desc");
d->m_ssl_cipher_version = d->m_job->queryMetaData("ssl_cipher_version");
d->m_ssl_cipher_used_bits = d->m_job->queryMetaData("ssl_cipher_used_bits");
d->m_ssl_cipher_bits = d->m_job->queryMetaData("ssl_cipher_bits");
d->m_ssl_cert_state = d->m_job->queryMetaData("ssl_cert_state");
if (d->m_statusBarIconLabel) {
QToolTip::remove(d->m_statusBarIconLabel);
if (d->m_ssl_in_use) {
QToolTip::add(d->m_statusBarIconLabel, i18n("Session is secured with %1 bit %2.").arg(d->m_ssl_cipher_used_bits).arg(d->m_ssl_cipher));
} else {
QToolTip::add(d->m_statusBarIconLabel, i18n("Session is not secured."));
}
}
// Check for charset meta-data
QString qData = d->m_job->queryMetaData("charset");
if ( !qData.isEmpty() && !d->m_haveEncoding ) // only use information if the user didn't override the settings
d->m_encoding = qData;
// Support for http-refresh
qData = d->m_job->queryMetaData("http-refresh");
if( !qData.isEmpty())
d->m_doc->processHttpEquiv("refresh", qData);
// DISABLED: Support Content-Location per section 14.14 of RFC 2616.
// See BR# 51185,BR# 82747
/*
QString baseURL = d->m_job->queryMetaData ("content-location");
if (!baseURL.isEmpty())
d->m_doc->setBaseURL(KURL( d->m_doc->completeURL(baseURL) ));
*/
// Support for Content-Language
QString language = d->m_job->queryMetaData("content-language");
if (!language.isEmpty())
d->m_doc->setContentLanguage(language);
if ( !m_url.isLocalFile() ) {
// Support for http last-modified
d->m_lastModified = d->m_job->queryMetaData("modified");
} else
d->m_lastModified = QString::null; // done on-demand by lastModified()
}
KHTMLPageCache::self()->addData(d->m_cacheId, data);
write( data.data(), data.size() );
if (d->m_frame && d->m_frame->m_jscript)
d->m_frame->m_jscript->dataReceived();
}
void KHTMLPart::slotRestoreData(const QByteArray &data )
{
// The first data ?
if ( !d->m_workingURL.isEmpty() )
{
long saveCacheId = d->m_cacheId;
QString savePageReferrer = d->m_pageReferrer;
QString saveEncoding = d->m_encoding;
begin( d->m_workingURL, d->m_extension->urlArgs().xOffset, d->m_extension->urlArgs().yOffset );
d->m_encoding = saveEncoding;
d->m_pageReferrer = savePageReferrer;
d->m_cacheId = saveCacheId;
d->m_workingURL = KURL();
}
//kdDebug( 6050 ) << "slotRestoreData: " << data.size() << endl;
write( data.data(), data.size() );
if (data.size() == 0)
{
//kdDebug( 6050 ) << "slotRestoreData: <<end of data>>" << endl;
// End of data.
if (d->m_doc && d->m_doc->parsing())
end(); //will emit completed()
}
}
void KHTMLPart::showError( KIO::Job* job )
{
kdDebug(6050) << "KHTMLPart::showError d->m_bParsing=" << (d->m_doc && d->m_doc->parsing()) << " d->m_bComplete=" << d->m_bComplete
<< " d->m_bCleared=" << d->m_bCleared << endl;
if (job->error() == KIO::ERR_NO_CONTENT)
return;
if ( (d->m_doc && d->m_doc->parsing()) || d->m_workingURL.isEmpty() ) // if we got any data already
job->showErrorDialog( /*d->m_view*/ );
else
{
htmlError( job->error(), job->errorText(), d->m_workingURL );
}
}
// This is a protected method, placed here because of it's relevance to showError
void KHTMLPart::htmlError( int errorCode, const QString& text, const KURL& reqUrl )
{
kdDebug(6050) << "KHTMLPart::htmlError errorCode=" << errorCode << " text=" << text << endl;
// make sure we're not executing any embedded JS
bool bJSFO = d->m_bJScriptForce;
bool bJSOO = d->m_bJScriptOverride;
d->m_bJScriptForce = false;
d->m_bJScriptOverride = true;
begin();
QString errText = QString::fromLatin1( "<HTML dir=%1><HEAD><TITLE>" )
.arg(QApplication::reverseLayout() ? "rtl" : "ltr");
errText += i18n( "Error while loading %1" ).arg( reqUrl.htmlURL() );
errText += QString::fromLatin1( "</TITLE></HEAD><BODY><P>" );
errText += i18n( "An error occurred while loading <B>%1</B>:" ).arg( reqUrl.htmlURL() );
errText += QString::fromLatin1( "</P>" );
errText += QStyleSheet::convertFromPlainText( KIO::buildErrorString( errorCode, text ) );
errText += QString::fromLatin1( "</BODY></HTML>" );
write(errText);
end();
d->m_bJScriptForce = bJSFO;
d->m_bJScriptOverride = bJSOO;
// make the working url the current url, so that reload works and
// emit the progress signals to advance one step in the history
// (so that 'back' works)
m_url = reqUrl; // same as d->m_workingURL
d->m_workingURL = KURL();
emit started( 0 );
emit completed();
return;
// following disabled until 3.1
QString errorName, techName, description;
QStringList causes, solutions;
QByteArray raw = KIO::rawErrorDetail( errorCode, text, &reqUrl );
QDataStream stream(raw, IO_ReadOnly);
stream >> errorName >> techName >> description >> causes >> solutions;
QString url, protocol, datetime;
url = reqUrl.prettyURL();
protocol = reqUrl.protocol();
datetime = KGlobal::locale()->formatDateTime( QDateTime::currentDateTime(),
false );
QString doc = QString::fromLatin1( "<html><head><title>" );
doc += i18n( "Error: " );
doc += errorName;
doc += QString::fromLatin1( " - %1</title></head><body><h1>" ).arg( url );
doc += i18n( "The requested operation could not be completed" );
doc += QString::fromLatin1( "</h1><h2>" );
doc += errorName;
doc += QString::fromLatin1( "</h2>" );
if ( !techName.isNull() ) {
doc += QString::fromLatin1( "<h2>" );
doc += i18n( "Technical Reason: " );
doc += techName;
doc += QString::fromLatin1( "</h2>" );
}
doc += QString::fromLatin1( "<h3>" );
doc += i18n( "Details of the Request:" );
doc += QString::fromLatin1( "</h3><ul><li>" );
doc += i18n( "URL: %1" ).arg( url );
doc += QString::fromLatin1( "</li><li>" );
if ( !protocol.isNull() ) {
// uncomment for 3.1... i18n change
// doc += i18n( "Protocol: %1" ).arg( protocol ).arg( protocol );
doc += QString::fromLatin1( "</li><li>" );
}
doc += i18n( "Date and Time: %1" ).arg( datetime );
doc += QString::fromLatin1( "</li><li>" );
doc += i18n( "Additional Information: %1" ).arg( text );
doc += QString::fromLatin1( "</li></ul><h3>" );
doc += i18n( "Description:" );
doc += QString::fromLatin1( "</h3><p>" );
doc += description;
doc += QString::fromLatin1( "</p>" );
if ( causes.count() ) {
doc += QString::fromLatin1( "<h3>" );
doc += i18n( "Possible Causes:" );
doc += QString::fromLatin1( "</h3><ul><li>" );
doc += causes.join( "</li><li>" );
doc += QString::fromLatin1( "</li></ul>" );
}
if ( solutions.count() ) {
doc += QString::fromLatin1( "<h3>" );
doc += i18n( "Possible Solutions:" );
doc += QString::fromLatin1( "</h3><ul><li>" );
doc += solutions.join( "</li><li>" );
doc += QString::fromLatin1( "</li></ul>" );
}
doc += QString::fromLatin1( "</body></html>" );
write( doc );
end();
}
void KHTMLPart::slotFinished( KIO::Job * job )
{
d->m_job = 0L;
d->m_jobspeed = 0L;
if (job->error())
{
KHTMLPageCache::self()->cancelEntry(d->m_cacheId);
// The following catches errors that occur as a result of HTTP
// to FTP redirections where the FTP URL is a directory. Since
// KIO cannot change a redirection request from GET to LISTDIR,
// we have to take care of it here once we know for sure it is
// a directory...
if (job->error() == KIO::ERR_IS_DIRECTORY)
{
KParts::URLArgs args;
emit d->m_extension->openURLRequest( d->m_workingURL, args );
}
else
{
emit canceled( job->errorString() );
// TODO: what else ?
checkCompleted();
showError( job );
}
return;
}
KIO::TransferJob *tjob = ::qt_cast<KIO::TransferJob*>(job);
if (tjob && tjob->isErrorPage()) {
khtml::RenderPart *renderPart = d->m_frame ? static_cast<khtml::RenderPart *>(d->m_frame->m_frame) : 0;
if (renderPart) {
HTMLObjectElementImpl* elt = static_cast<HTMLObjectElementImpl *>(renderPart->element());
if (!elt)
return;
elt->renderAlternative();
checkCompleted();
}
if (d->m_bComplete) return;
}
//kdDebug( 6050 ) << "slotFinished" << endl;
KHTMLPageCache::self()->endData(d->m_cacheId);
if (d->m_frame && d->m_frame->m_jscript)
d->m_frame->m_jscript->dataReceived();
if ( d->m_doc && d->m_doc->docLoader()->expireDate() && m_url.protocol().lower().startsWith("http"))
KIO::http_update_cache(m_url, false, d->m_doc->docLoader()->expireDate());
d->m_workingURL = KURL();
if ( d->m_doc && d->m_doc->parsing())
end(); //will emit completed()
}
void KHTMLPart::begin( const KURL &url, int xOffset, int yOffset )
{
// No need to show this for a new page until an error is triggered
if (!parentPart()) {
removeJSErrorExtension();
setSuppressedPopupIndicator( false );
d->m_openableSuppressedPopups = 0;
for ( QValueListIterator<QGuardedPtr<KHTMLPart> > i = d->m_suppressedPopupOriginParts.begin();
i != d->m_suppressedPopupOriginParts.end(); ++i ) {
if (KHTMLPart* part = *i) {
KJS::Window *w = KJS::Window::retrieveWindow( part );
if (w)
w->forgetSuppressedWindows();
}
}
}
clear();
d->m_bCleared = false;
d->m_cacheId = 0;
d->m_bComplete = false;
d->m_bLoadEventEmitted = false;
if(url.isValid()) {
QString urlString = url.url();
KHTMLFactory::vLinks()->insert( urlString );
QString urlString2 = url.prettyURL();
if ( urlString != urlString2 ) {
KHTMLFactory::vLinks()->insert( urlString2 );
}
}
// ###
//stopParser();
KParts::URLArgs args( d->m_extension->urlArgs() );
args.xOffset = xOffset;
args.yOffset = yOffset;
d->m_extension->setURLArgs( args );
d->m_pageReferrer = QString::null;
KURL ref(url);
d->m_referrer = ref.protocol().startsWith("http") ? ref.url() : "";
m_url = url;
bool servedAsXHTML = args.serviceType == "application/xhtml+xml";
bool servedAsXML = KMimeType::mimeType(args.serviceType)->is( "text/xml" );
// ### not sure if XHTML documents served as text/xml should use DocumentImpl or HTMLDocumentImpl
if ( servedAsXML && !servedAsXHTML ) { // any XML derivative, except XHTML
d->m_doc = DOMImplementationImpl::instance()->createDocument( d->m_view );
} else {
d->m_doc = DOMImplementationImpl::instance()->createHTMLDocument( d->m_view );
// HTML or XHTML? (#86446)
static_cast<HTMLDocumentImpl *>(d->m_doc)->setHTMLRequested( !servedAsXHTML );
}
#ifndef KHTML_NO_CARET
// d->m_view->initCaret();
#endif
d->m_doc->ref();
d->m_doc->setURL( m_url.url() );
if (!d->m_doc->attached())
d->m_doc->attach( );
d->m_doc->setBaseURL( KURL() );
d->m_doc->docLoader()->setShowAnimations( KHTMLFactory::defaultHTMLSettings()->showAnimations() );
emit docCreated();
d->m_paUseStylesheet->setItems(QStringList());
d->m_paUseStylesheet->setEnabled( false );
setAutoloadImages( KHTMLFactory::defaultHTMLSettings()->autoLoadImages() );
QString userStyleSheet = KHTMLFactory::defaultHTMLSettings()->userStyleSheet();
if ( !userStyleSheet.isEmpty() )
setUserStyleSheet( KURL( userStyleSheet ) );
d->m_doc->setRestoreState(args.docState);
d->m_doc->open();
connect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
emit d->m_extension->enableAction( "print", true );
d->m_doc->setParsing(true);
}
void KHTMLPart::write( const char *str, int len )
{
if ( !d->m_decoder )
d->m_decoder = createDecoder();
if ( len == -1 )
len = strlen( str );
if ( len == 0 )
return;
QString decoded = d->m_decoder->decode( str, len );
if(decoded.isEmpty()) return;
if(d->m_bFirstData) {
// determine the parse mode
d->m_doc->determineParseMode( decoded );
d->m_bFirstData = false;
//kdDebug(6050) << "KHTMLPart::write haveEnc = " << d->m_haveEncoding << endl;
// ### this is still quite hacky, but should work a lot better than the old solution
if(d->m_decoder->visuallyOrdered()) d->m_doc->setVisuallyOrdered();
d->m_doc->setDecoderCodec(d->m_decoder->codec());
d->m_doc->recalcStyle( NodeImpl::Force );
}
khtml::Tokenizer* t = d->m_doc->tokenizer();
if(t)
t->write( decoded, true );
}
void KHTMLPart::write( const QString &str )
{
if ( str.isNull() )
return;
if(d->m_bFirstData) {
// determine the parse mode
d->m_doc->setParseMode( DocumentImpl::Strict );
d->m_bFirstData = false;
}
khtml::Tokenizer* t = d->m_doc->tokenizer();
if(t)
t->write( str, true );
}
void KHTMLPart::end()
{
if (d->m_doc) {
if (d->m_decoder) {
QString decoded = d->m_decoder->flush();
if (d->m_bFirstData) {
d->m_bFirstData = false;
d->m_doc->determineParseMode(decoded);
}
write(decoded);
}
d->m_doc->finishParsing();
}
}
bool KHTMLPart::doOpenStream( const QString& mimeType )
{
KMimeType::Ptr mime = KMimeType::mimeType(mimeType);
if ( mime->is( "text/html" ) || mime->is( "text/xml" ) )
{
begin( url() );
return true;
}
return false;
}
bool KHTMLPart::doWriteStream( const QByteArray& data )
{
write( data.data(), data.size() );
return true;
}
bool KHTMLPart::doCloseStream()
{
end();
return true;
}
void KHTMLPart::paint(QPainter *p, const QRect &rc, int yOff, bool *more)
{
if (!d->m_view) return;
d->m_view->paint(p, rc, yOff, more);
}
void KHTMLPart::stopAnimations()
{
if ( d->m_doc )
d->m_doc->docLoader()->setShowAnimations( KHTMLSettings::KAnimationDisabled );
ConstFrameIt it = d->m_frames.begin();
const ConstFrameIt end = d->m_frames.end();
for (; it != end; ++it )
if ( !(*it)->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
KParts::ReadOnlyPart* const p = ( *it )->m_part;
static_cast<KHTMLPart*>( p )->stopAnimations();
}
}
void KHTMLPart::resetFromScript()
{
closeURL();
d->m_bComplete = false;
d->m_bLoadEventEmitted = false;
disconnect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
connect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
d->m_doc->setParsing(true);
emit started( 0L );
}
void KHTMLPart::slotFinishedParsing()
{
d->m_doc->setParsing(false);
checkEmitLoadEvent();
disconnect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
if (!d->m_view)
return; // We are probably being destructed.
checkCompleted();
}
void KHTMLPart::slotLoaderRequestStarted( khtml::DocLoader* dl, khtml::CachedObject *obj )
{
if ( obj && obj->type() == khtml::CachedObject::Image && d->m_doc && d->m_doc->docLoader() == dl ) {
KHTMLPart* p = this;
while ( p ) {
KHTMLPart* const op = p;
++(p->d->m_totalObjectCount);
p = p->parentPart();
if ( !p && op->d->m_loadedObjects <= op->d->m_totalObjectCount
&& !op->d->m_progressUpdateTimer.isActive())
op->d->m_progressUpdateTimer.start( 200, true );
}
}
}
void KHTMLPart::slotLoaderRequestDone( khtml::DocLoader* dl, khtml::CachedObject *obj )
{
if ( obj && obj->type() == khtml::CachedObject::Image && d->m_doc && d->m_doc->docLoader() == dl ) {
KHTMLPart* p = this;
while ( p ) {
KHTMLPart* const op = p;
++(p->d->m_loadedObjects);
p = p->parentPart();
if ( !p && op->d->m_loadedObjects <= op->d->m_totalObjectCount && op->d->m_jobPercent <= 100
&& !op->d->m_progressUpdateTimer.isActive())
op->d->m_progressUpdateTimer.start( 200, true );
}
}
checkCompleted();
}
void KHTMLPart::slotProgressUpdate()
{
int percent;
if ( d->m_loadedObjects < d->m_totalObjectCount )
percent = d->m_jobPercent / 4 + ( d->m_loadedObjects*300 ) / ( 4*d->m_totalObjectCount );
else
percent = d->m_jobPercent;
if( d->m_bComplete )
percent = 100;
if (d->m_statusMessagesEnabled) {
if( d->m_bComplete )
emit d->m_extension->infoMessage( i18n( "Page loaded." ));
else if ( d->m_loadedObjects < d->m_totalObjectCount && percent >= 75 )
emit d->m_extension->infoMessage( i18n( "%n Image of %1 loaded.", "%n Images of %1 loaded.", d->m_loadedObjects).arg(d->m_totalObjectCount) );
}
emit d->m_extension->loadingProgress( percent );
}
void KHTMLPart::slotJobSpeed( KIO::Job* /*job*/, unsigned long speed )
{
d->m_jobspeed = speed;
if (!parentPart())
setStatusBarText(jsStatusBarText(), BarOverrideText);
}
void KHTMLPart::slotJobPercent( KIO::Job* /*job*/, unsigned long percent )
{
d->m_jobPercent = percent;
if ( !parentPart() )
d->m_progressUpdateTimer.start( 0, true );
}
void KHTMLPart::slotJobDone( KIO::Job* /*job*/ )
{
d->m_jobPercent = 100;
if ( !parentPart() )
d->m_progressUpdateTimer.start( 0, true );
}
void KHTMLPart::slotUserSheetStatDone( KIO::Job *_job )
{
using namespace KIO;
if ( _job->error() ) {
showError( _job );
return;
}
const UDSEntry entry = dynamic_cast<KIO::StatJob *>( _job )->statResult();
UDSEntry::ConstIterator it = entry.begin();
const UDSEntry::ConstIterator end = entry.end();
for ( ; it != end; ++it ) {
if ( ( *it ).m_uds == UDS_MODIFICATION_TIME ) {
break;
}
}
// If the filesystem supports modification times, only reload the
// user-defined stylesheet if necessary - otherwise always reload.
if ( it != end ) {
const time_t lastModified = static_cast<time_t>( ( *it ).m_long );
if ( d->m_userStyleSheetLastModified >= lastModified ) {
return;
}
d->m_userStyleSheetLastModified = lastModified;
}
setUserStyleSheet( KURL( settings()->userStyleSheet() ) );
}
void KHTMLPart::checkCompleted()
{
// kdDebug( 6050 ) << "KHTMLPart::checkCompleted() " << this << " " << name() << endl;
// kdDebug( 6050 ) << " parsing: " << (d->m_doc && d->m_doc->parsing()) << endl;
// kdDebug( 6050 ) << " complete: " << d->m_bComplete << endl;
// restore the cursor position
if (d->m_doc && !d->m_doc->parsing() && !d->m_focusNodeRestored)
{
if (d->m_focusNodeNumber >= 0)
d->m_doc->setFocusNode(d->m_doc->nodeWithAbsIndex(d->m_focusNodeNumber));
d->m_focusNodeRestored = true;
}
bool bPendingChildRedirection = false;
// Any frame that hasn't completed yet ?
ConstFrameIt it = d->m_frames.begin();
const ConstFrameIt end = d->m_frames.end();
for (; it != end; ++it ) {
if ( !(*it)->m_bCompleted )
{
//kdDebug( 6050 ) << this << " is waiting for " << (*it)->m_part << endl;
return;
}
// Check for frames with pending redirections
if ( (*it)->m_bPendingRedirection )
bPendingChildRedirection = true;
}
// Any object that hasn't completed yet ?
{
ConstFrameIt oi = d->m_objects.begin();
const ConstFrameIt oiEnd = d->m_objects.end();
for (; oi != oiEnd; ++oi )
if ( !(*oi)->m_bCompleted )
return;
}
// Are we still parsing - or have we done the completed stuff already ?
if ( d->m_bComplete || (d->m_doc && d->m_doc->parsing()) )
return;
// Still waiting for images/scripts from the loader ?
int requests = 0;
if ( d->m_doc && d->m_doc->docLoader() )
requests = khtml::Cache::loader()->numRequests( d->m_doc->docLoader() );
if ( requests > 0 )
{
//kdDebug(6050) << "still waiting for images/scripts from the loader - requests:" << requests << endl;
return;
}
// OK, completed.
// Now do what should be done when we are really completed.
d->m_bComplete = true;
d->m_cachePolicy = KProtocolManager::cacheControl(); // reset cache policy
d->m_totalObjectCount = 0;
d->m_loadedObjects = 0;
KHTMLPart* p = this;
while ( p ) {
KHTMLPart* op = p;
p = p->parentPart();
if ( !p && !op->d->m_progressUpdateTimer.isActive())
op->d->m_progressUpdateTimer.start( 0, true );
}
checkEmitLoadEvent(); // if we didn't do it before
bool pendingAction = false;
if ( !d->m_redirectURL.isEmpty() )
{
// DA: Do not start redirection for frames here! That action is
// deferred until the parent emits a completed signal.
if ( parentPart() == 0 ) {
//kdDebug(6050) << this << " starting redirection timer" << endl;
d->m_redirectionTimer.start( 1000 * d->m_delayRedirect, true );
} else {
//kdDebug(6050) << this << " not toplevel -> not starting redirection timer. Waiting for slotParentCompleted." << endl;
}
pendingAction = true;
}
else if ( bPendingChildRedirection )
{
pendingAction = true;
}
// the view will emit completed on our behalf,
// either now or at next repaint if one is pending
//kdDebug(6050) << this << " asks the view to emit completed. pendingAction=" << pendingAction << endl;
d->m_view->complete( pendingAction );
// find the alternate stylesheets
QStringList sheets;
if (d->m_doc)
sheets = d->m_doc->availableStyleSheets();
sheets.prepend( i18n( "Automatic Detection" ) );
d->m_paUseStylesheet->setItems( sheets );
d->m_paUseStylesheet->setEnabled( sheets.count() > 2);
if (sheets.count() > 2)
{
d->m_paUseStylesheet->setCurrentItem(kMax(sheets.findIndex(d->m_sheetUsed), 0));
slotUseStylesheet();
}
setJSDefaultStatusBarText(QString::null);
#ifdef SPEED_DEBUG
kdDebug(6050) << "DONE: " <<d->m_parsetime.elapsed() << endl;
#endif
}
void KHTMLPart::checkEmitLoadEvent()
{
if ( d->m_bLoadEventEmitted || !d->m_doc || d->m_doc->parsing() ) return;
ConstFrameIt it = d->m_frames.begin();
const ConstFrameIt end = d->m_frames.end();
for (; it != end; ++it )
if ( !(*it)->m_bCompleted ) // still got a frame running -> too early
return;
ConstFrameIt oi = d->m_objects.begin();
const ConstFrameIt oiEnd = d->m_objects.end();
for (; oi != oiEnd; ++oi )
if ( !(*oi)->m_bCompleted ) // still got a object running -> too early
return;
// Still waiting for images/scripts from the loader ?
// (onload must happen afterwards, #45607)
// ## This makes this method very similar to checkCompleted. A brave soul should try merging them.
int requests = 0;
if ( d->m_doc && d->m_doc->docLoader() )
requests = khtml::Cache::loader()->numRequests( d->m_doc->docLoader() );
if ( requests > 0 )
return;
d->m_bLoadEventEmitted = true;
if (d->m_doc)
d->m_doc->close();
}
const KHTMLSettings *KHTMLPart::settings() const
{
return d->m_settings;
}
#ifndef KDE_NO_COMPAT
KURL KHTMLPart::baseURL() const
{
if ( !d->m_doc ) return KURL();
return d->m_doc->baseURL();
}
QString KHTMLPart::baseTarget() const
{
if ( !d->m_doc ) return QString::null;
return d->m_doc->baseTarget();
}
#endif
KURL KHTMLPart::completeURL( const QString &url )
{
if ( !d->m_doc ) return KURL( url );
if (d->m_decoder)
return KURL(d->m_doc->completeURL(url), d->m_decoder->codec()->mibEnum());
return KURL( d->m_doc->completeURL( url ) );
}
// Called by ecma/kjs_window in case of redirections from Javascript,
// and by xml/dom_docimpl.cpp in case of http-equiv meta refresh.
void KHTMLPart::scheduleRedirection( int delay, const QString &url, bool doLockHistory )
{
kdDebug(6050) << "KHTMLPart::scheduleRedirection delay=" << delay << " url=" << url << endl;
kdDebug(6050) << "current redirectURL=" << d->m_redirectURL << " with delay " << d->m_delayRedirect << endl;
if( delay < 24*60*60 &&
( d->m_redirectURL.isEmpty() || delay <= d->m_delayRedirect) ) {
d->m_delayRedirect = delay;
d->m_redirectURL = url;
d->m_redirectLockHistory = doLockHistory;
kdDebug(6050) << " d->m_bComplete=" << d->m_bComplete << endl;
if ( d->m_bComplete ) {
d->m_redirectionTimer.stop();
d->m_redirectionTimer.start( kMax(0, 1000 * d->m_delayRedirect), true );
}
}
}
void KHTMLPart::slotRedirect()
{
kdDebug(6050) << this << " slotRedirect()" << endl;
QString u = d->m_redirectURL;
d->m_delayRedirect = 0;
d->m_redirectURL = QString::null;
// SYNC check with ecma/kjs_window.cpp::goURL !
if ( u.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
{
QString script = KURL::decode_string( u.right( u.length() - 11 ) );
kdDebug( 6050 ) << "KHTMLPart::slotRedirect script=" << script << endl;
QVariant res = executeScript( DOM::Node(), script );
if ( res.type() == QVariant::String ) {
begin( url() );
write( res.asString() );
end();
}
emit completed();
return;
}
KParts::URLArgs args;
KURL cUrl( m_url );
KURL url( u );
// handle windows opened by JS
if ( openedByJS() && d->m_opener )
cUrl = d->m_opener->url();
if (!kapp || !kapp->authorizeURLAction("redirect", cUrl, url))
{
kdWarning(6050) << "KHTMLPart::scheduleRedirection: Redirection from " << cUrl << " to " << url << " REJECTED!" << endl;
emit completed();
return;
}
if ( urlcmp( u, m_url.url(), true, true ) )
{
args.metaData().insert("referrer", d->m_pageReferrer);
}
// For javascript and META-tag based redirections:
// - We don't take cross-domain-ness in consideration if we are the
// toplevel frame because the new URL may be in a different domain as the current URL
// but that's ok.
// - If we are not the toplevel frame then we check against the toplevelURL()
if (parentPart())
args.metaData().insert("cross-domain", toplevelURL().url());
args.setLockHistory( d->m_redirectLockHistory );
// _self: make sure we don't use any <base target=>'s
d->m_urlSelectedOpenedURL = true; // In case overriden, default to success
urlSelected( u, 0, 0, "_self", args );
if ( !d->m_urlSelectedOpenedURL ) // urlSelected didn't open a url, so emit completed ourselves
emit completed();
}
void KHTMLPart::slotRedirection(KIO::Job*, const KURL& url)
{
// the slave told us that we got redirected
//kdDebug( 6050 ) << "redirection by KIO to " << url.url() << endl;
emit d->m_extension->setLocationBarURL( url.prettyURL() );
d->m_workingURL = url;
}
bool KHTMLPart::setEncoding( const QString &name, bool override )
{
d->m_encoding = name;
d->m_haveEncoding = override;
if( !m_url.isEmpty() ) {
// reload document
closeURL();
KURL url = m_url;
m_url = 0;
d->m_restored = true;
openURL(url);
d->m_restored = false;
}
return true;
}
QString KHTMLPart::encoding() const
{
if(d->m_haveEncoding && !d->m_encoding.isEmpty())
return d->m_encoding;
if(d->m_decoder && d->m_decoder->encoding())
return QString(d->m_decoder->encoding());
return defaultEncoding();
}
QString KHTMLPart::defaultEncoding() const
{
QString encoding = settings()->encoding();
if ( !encoding.isEmpty() )
return encoding;
// HTTP requires the default encoding to be latin1, when neither
// the user nor the page requested a particular encoding.
if ( url().protocol().startsWith( "http" ) )
return "iso-8859-1";
else
return KGlobal::locale()->encoding();
}
void KHTMLPart::setUserStyleSheet(const KURL &url)
{
if ( d->m_doc && d->m_doc->docLoader() )
(void) new khtml::PartStyleSheetLoader(this, url.url(), d->m_doc->docLoader());
}
void KHTMLPart::setUserStyleSheet(const QString &styleSheet)
{
if ( d->m_doc )
d->m_doc->setUserStyleSheet( styleSheet );
}
bool KHTMLPart::gotoAnchor( const QString &name )
{
if (!d->m_doc)
return false;
HTMLCollectionImpl *anchors =
new HTMLCollectionImpl( d->m_doc, HTMLCollectionImpl::DOC_ANCHORS);
anchors->ref();
NodeImpl *n = anchors->namedItem(name);
anchors->deref();
if(!n) {
n = d->m_doc->getElementById( name );
}
d->m_doc->setCSSTarget(n); // Setting to null will clear the current target.
// Implement the rule that "" and "top" both mean top of page as in other browsers.
bool quirkyName = !n && !d->m_doc->inStrictMode() && (name.isEmpty() || name.lower() == "top");
if (quirkyName) {
d->m_view->setContentsPos(0, 0);
return true;
} else if (!n) {
kdDebug(6050) << "KHTMLPart::gotoAnchor node '" << name << "' not found" << endl;
return false;
}
int x = 0, y = 0;
int gox, dummy;
HTMLElementImpl *a = static_cast<HTMLElementImpl *>(n);
a->getUpperLeftCorner(x, y);
if (x <= d->m_view->contentsX())
gox = x - 10;
else {
gox = d->m_view->contentsX();
if ( x + 10 > d->m_view->contentsX()+d->m_view->visibleWidth()) {
a->getLowerRightCorner(x, dummy);
gox = x - d->m_view->visibleWidth() + 10;
}
}
d->m_view->setContentsPos(gox, y);
return true;
}
bool KHTMLPart::nextAnchor()
{
if (!d->m_doc)
return false;
d->m_view->focusNextPrevNode ( true );
return true;
}
bool KHTMLPart::prevAnchor()
{
if (!d->m_doc)
return false;
d->m_view->focusNextPrevNode ( false );
return true;
}
void KHTMLPart::setStandardFont( const QString &name )
{
d->m_settings->setStdFontName(name);
}
void KHTMLPart::setFixedFont( const QString &name )
{
d->m_settings->setFixedFontName(name);
}
void KHTMLPart::setURLCursor( const QCursor &c )
{
d->m_linkCursor = c;
}
QCursor KHTMLPart::urlCursor() const
{
return d->m_linkCursor;
}
bool KHTMLPart::onlyLocalReferences() const
{
return d->m_onlyLocalReferences;
}
void KHTMLPart::setOnlyLocalReferences(bool enable)
{
d->m_onlyLocalReferences = enable;
}
void KHTMLPartPrivate::setFlagRecursively(
bool KHTMLPartPrivate::*flag, bool value)
{
// first set it on the current one
this->*flag = value;
// descend into child frames recursively
{
QValueList<khtml::ChildFrame*>::Iterator it = m_frames.begin();
const QValueList<khtml::ChildFrame*>::Iterator itEnd = m_frames.end();
for (; it != itEnd; ++it) {
KHTMLPart* const part = static_cast<KHTMLPart *>((KParts::ReadOnlyPart *)(*it)->m_part);
if (part->inherits("KHTMLPart"))
part->d->setFlagRecursively(flag, value);
}/*next it*/
}
// do the same again for objects
{
QValueList<khtml::ChildFrame*>::Iterator it = m_objects.begin();
const QValueList<khtml::ChildFrame*>::Iterator itEnd = m_objects.end();
for (; it != itEnd; ++it) {
KHTMLPart* const part = static_cast<KHTMLPart *>((KParts::ReadOnlyPart *)(*it)->m_part);
if (part->inherits("KHTMLPart"))
part->d->setFlagRecursively(flag, value);
}/*next it*/
}
}
void KHTMLPart::setCaretMode(bool enable)
{
#ifndef KHTML_NO_CARET
kdDebug(6200) << "setCaretMode(" << enable << ")" << endl;
if (isCaretMode() == enable) return;
d->setFlagRecursively(&KHTMLPartPrivate::m_caretMode, enable);
// FIXME: this won't work on frames as expected
if (!isEditable()) {
if (enable) {
view()->initCaret(true);
view()->ensureCaretVisible();
} else
view()->caretOff();
}/*end if*/
#endif // KHTML_NO_CARET
}
bool KHTMLPart::isCaretMode() const
{
return d->m_caretMode;
}
void KHTMLPart::setEditable(bool enable)
{
#ifndef KHTML_NO_CARET
if (isEditable() == enable) return;
d->setFlagRecursively(&KHTMLPartPrivate::m_designMode, enable);
// FIXME: this won't work on frames as expected
if (!isCaretMode()) {
if (enable) {
view()->initCaret(true);
view()->ensureCaretVisible();
} else
view()->caretOff();
}/*end if*/
#endif // KHTML_NO_CARET
}
bool KHTMLPart::isEditable() const
{
return d->m_designMode;
}
void KHTMLPart::setCaretPosition(DOM::Node node, long offset, bool extendSelection)
{
#ifndef KHTML_NO_CARET
#if 0
kdDebug(6200) << k_funcinfo << "node: " << node.handle() << " nodeName: "
<< node.nodeName().string() << " offset: " << offset
<< " extendSelection " << extendSelection << endl;
#endif
if (view()->moveCaretTo(node.handle(), offset, !extendSelection))
emitSelectionChanged();
view()->ensureCaretVisible();
#endif // KHTML_NO_CARET
}
KHTMLPart::CaretDisplayPolicy KHTMLPart::caretDisplayPolicyNonFocused() const
{
#ifndef KHTML_NO_CARET
return (CaretDisplayPolicy)view()->caretDisplayPolicyNonFocused();
#else // KHTML_NO_CARET
return CaretInvisible;
#endif // KHTML_NO_CARET
}
void KHTMLPart::setCaretDisplayPolicyNonFocused(CaretDisplayPolicy policy)
{
#ifndef KHTML_NO_CARET
view()->setCaretDisplayPolicyNonFocused(policy);
#endif // KHTML_NO_CARET
}
void KHTMLPart::setCaretVisible(bool show)
{
#ifndef KHTML_NO_CARET
if (show) {
NodeImpl *caretNode = xmlDocImpl()->focusNode();
if (isCaretMode() || isEditable()
|| (caretNode && caretNode->contentEditable())) {
view()->caretOn();
}/*end if*/
} else {
view()->caretOff();
}/*end if*/
#endif // KHTML_NO_CARET
}
void KHTMLPart::findTextBegin()
{
d->m_findPos = -1;
d->m_findNode = 0;
d->m_findPosEnd = -1;
d->m_findNodeEnd= 0;
d->m_findPosStart = -1;
d->m_findNodeStart = 0;
d->m_findNodePrevious = 0;
delete d->m_find;
d->m_find = 0L;
}
bool KHTMLPart::initFindNode( bool selection, bool reverse, bool fromCursor )
{
if ( !d->m_doc )
return false;
DOM::NodeImpl* firstNode = 0L;
if (d->m_doc->isHTMLDocument())
firstNode = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
else
firstNode = d->m_doc;
if ( !firstNode )
{
//kdDebug(6050) << k_funcinfo << "no first node (body or doc) -> return false" << endl;
return false;
}
if ( firstNode->id() == ID_FRAMESET )
{
//kdDebug(6050) << k_funcinfo << "FRAMESET -> return false" << endl;
return false;
}
if ( selection && hasSelection() )
{
//kdDebug(6050) << k_funcinfo << "using selection" << endl;
if ( !fromCursor )
{
d->m_findNode = reverse ? d->m_selectionEnd.handle() : d->m_selectionStart.handle();
d->m_findPos = reverse ? d->m_endOffset : d->m_startOffset;
}
d->m_findNodeEnd = reverse ? d->m_selectionStart.handle() : d->m_selectionEnd.handle();
d->m_findPosEnd = reverse ? d->m_startOffset : d->m_endOffset;
d->m_findNodeStart = !reverse ? d->m_selectionStart.handle() : d->m_selectionEnd.handle();
d->m_findPosStart = !reverse ? d->m_startOffset : d->m_endOffset;
d->m_findNodePrevious = d->m_findNodeStart;
}
else // whole document
{
//kdDebug(6050) << k_funcinfo << "whole doc" << endl;
if ( !fromCursor )
{
d->m_findNode = firstNode;
d->m_findPos = reverse ? -1 : 0;
}
d->m_findNodeEnd = reverse ? firstNode : 0;
d->m_findPosEnd = reverse ? 0 : -1;
d->m_findNodeStart = !reverse ? firstNode : 0;
d->m_findPosStart = !reverse ? 0 : -1;
d->m_findNodePrevious = d->m_findNodeStart;
if ( reverse )
{
// Need to find out the really last object, to start from it
khtml::RenderObject* obj = d->m_findNode ? d->m_findNode->renderer() : 0;
if ( obj )
{
// find the last object in the render tree
while ( obj->lastChild() )
{
obj = obj->lastChild();
}
// now get the last object with a NodeImpl associated
while ( !obj->element() && obj->objectAbove() )
{
obj = obj->objectAbove();
}
d->m_findNode = obj->element();
}
}
}
return true;
}
// Old method (its API limits the available features - remove in KDE-4)
bool KHTMLPart::findTextNext( const QString &str, bool forward, bool caseSensitive, bool isRegExp )
{
if ( !initFindNode( false, !forward, d->m_findNode ) )
return false;
while(1)
{
if( (d->m_findNode->nodeType() == Node::TEXT_NODE || d->m_findNode->nodeType() == Node::CDATA_SECTION_NODE) && d->m_findNode->renderer() )
{
DOMString nodeText = d->m_findNode->nodeValue();
DOMStringImpl *t = nodeText.implementation();
QConstString s(t->s, t->l);
int matchLen = 0;
if ( isRegExp ) {
QRegExp matcher( str );
matcher.setCaseSensitive( caseSensitive );
d->m_findPos = matcher.search(s.string(), d->m_findPos+1);
if ( d->m_findPos != -1 )
matchLen = matcher.matchedLength();
}
else {
d->m_findPos = s.string().find(str, d->m_findPos+1, caseSensitive);
matchLen = str.length();
}
if(d->m_findPos != -1)
{
int x = 0, y = 0;
if(static_cast<khtml::RenderText *>(d->m_findNode->renderer())
->posOfChar(d->m_findPos, x, y))
d->m_view->setContentsPos(x-50, y-50);
d->m_selectionStart = d->m_findNode;
d->m_startOffset = d->m_findPos;
d->m_selectionEnd = d->m_findNode;
d->m_endOffset = d->m_findPos + matchLen;
d->m_startBeforeEnd = true;
d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
d->m_selectionEnd.handle(), d->m_endOffset );
emitSelectionChanged();
return true;
}
}
d->m_findPos = -1;
NodeImpl *next;
if ( forward )
{
next = d->m_findNode->firstChild();
if(!next) next = d->m_findNode->nextSibling();
while(d->m_findNode && !next) {
d->m_findNode = d->m_findNode->parentNode();
if( d->m_findNode ) {
next = d->m_findNode->nextSibling();
}
}
}
else
{
next = d->m_findNode->lastChild();
if (!next ) next = d->m_findNode->previousSibling();
while ( d->m_findNode && !next )
{
d->m_findNode = d->m_findNode->parentNode();
if( d->m_findNode )
{
next = d->m_findNode->previousSibling();
}
}
}
d->m_findNode = next;
if(!d->m_findNode) return false;
}
}
void KHTMLPart::slotFind()
{
KParts::ReadOnlyPart *part = currentFrame();
if (!part)
return;
if (!part->inherits("KHTMLPart") )
{
kdError(6000) << "slotFind: part is a " << part->className() << ", can't do a search into it" << endl;
return;
}
static_cast<KHTMLPart *>( part )->findText();
}
void KHTMLPart::slotFindNext()
{
KParts::ReadOnlyPart *part = currentFrame();
if (!part)
return;
if (!part->inherits("KHTMLPart") )
{
kdError(6000) << "slotFindNext: part is a " << part->className() << ", can't do a search into it" << endl;
return;
}
static_cast<KHTMLPart *>( part )->findTextNext();
}
void KHTMLPart::slotFindPrev()
{
KParts::ReadOnlyPart *part = currentFrame();
if (!part)
return;
if (!part->inherits("KHTMLPart") )
{
kdError(6000) << "slotFindNext: part is a " << part->className() << ", can't do a search into it" << endl;
return;
}
static_cast<KHTMLPart *>( part )->findTextNext( true ); // reverse
}
void KHTMLPart::slotFindDone()
{
// ### remove me
}
void KHTMLPart::slotFindAheadText()
{
#ifndef KHTML_NO_TYPE_AHEAD_FIND
KParts::ReadOnlyPart *part = currentFrame();
if (!part)
return;
if (!part->inherits("KHTMLPart") )
{
kdError(6000) << "slotFindNext: part is a " << part->className() << ", can't do a search into it" << endl;
return;
}
static_cast<KHTMLPart *>( part )->view()->startFindAhead( false );
#endif // KHTML_NO_TYPE_AHEAD_FIND
}
void KHTMLPart::slotFindAheadLink()
{
#ifndef KHTML_NO_TYPE_AHEAD_FIND
KParts::ReadOnlyPart *part = currentFrame();
if (!part)
return;
if (!part->inherits("KHTMLPart") )
{
kdError(6000) << "slotFindNext: part is a " << part->className() << ", can't do a search into it" << endl;
return;
}
static_cast<KHTMLPart *>( part )->view()->startFindAhead( true );
#endif // KHTML_NO_TYPE_AHEAD_FIND
}
void KHTMLPart::enableFindAheadActions( bool enable )
{
// only the topmost one has shortcuts
KHTMLPart* p = this;
while( p->parentPart())
p = p->parentPart();
p->d->m_paFindAheadText->setEnabled( enable );
p->d->m_paFindAheadLinks->setEnabled( enable );
}
void KHTMLPart::slotFindDialogDestroyed()
{
d->m_lastFindState.options = d->m_findDialog->options();
d->m_lastFindState.history = d->m_findDialog->findHistory();
d->m_findDialog->deleteLater();
d->m_findDialog = 0L;
}
void KHTMLPart::findText()
{
// First do some init to make sure we can search in this frame
if ( !d->m_doc )
return;
// Raise if already opened
if ( d->m_findDialog )
{
KWin::activateWindow( d->m_findDialog->winId() );
return;
}
// The lineedit of the dialog would make khtml lose its selection, otherwise
#ifndef QT_NO_CLIPBOARD
disconnect( kapp->clipboard(), SIGNAL(selectionChanged()), this, SLOT(slotClearSelection()) );
#endif
// Now show the dialog in which the user can choose options.
d->m_findDialog = new KFindDialog( false /*non-modal*/, widget(), "khtmlfind" );
d->m_findDialog->setHasSelection( hasSelection() );
d->m_findDialog->setHasCursor( d->m_findNode != 0 );
if ( d->m_findNode ) // has a cursor -> default to 'FromCursor'
d->m_lastFindState.options |= KFindDialog::FromCursor;
// TODO? optionsDialog.setPattern( d->m_lastFindState.text );
d->m_findDialog->setFindHistory( d->m_lastFindState.history );
d->m_findDialog->setOptions( d->m_lastFindState.options );
d->m_lastFindState.options = -1; // force update in findTextNext
d->m_lastFindState.last_dir = -1;
d->m_findDialog->show();
connect( d->m_findDialog, SIGNAL(okClicked()), this, SLOT(slotFindNext()) );
connect( d->m_findDialog, SIGNAL(finished()), this, SLOT(slotFindDialogDestroyed()) );
findText( d->m_findDialog->pattern(), 0 /*options*/, widget(), d->m_findDialog );
}
void KHTMLPart::findText( const QString &str, long options, QWidget *parent, KFindDialog *findDialog )
{
// First do some init to make sure we can search in this frame
if ( !d->m_doc )
return;
#ifndef QT_NO_CLIPBOARD
connect( kapp->clipboard(), SIGNAL(selectionChanged()), SLOT(slotClearSelection()) );
#endif
// Create the KFind object
delete d->m_find;
d->m_find = new KFind( str, options, parent, findDialog );
d->m_find->closeFindNextDialog(); // we use KFindDialog non-modal, so we don't want other dlg popping up
connect( d->m_find, SIGNAL( highlight( const QString &, int, int ) ),
this, SLOT( slotHighlight( const QString &, int, int ) ) );
//connect(d->m_find, SIGNAL( findNext() ),
// this, SLOT( slotFindNext() ) );
if ( !findDialog )
{
d->m_lastFindState.options = options;
initFindNode( options & KFindDialog::SelectedText,
options & KFindDialog::FindBackwards,
options & KFindDialog::FromCursor );
}
}
bool KHTMLPart::findTextNext()
{
return findTextNext( false );
}
// New method
bool KHTMLPart::findTextNext( bool reverse )
{
if (!d->m_find)
{
// We didn't show the find dialog yet, let's do it then (#49442)
findText();
return false;
}
view()->updateFindAheadTimeout();
long options = 0;
if ( d->m_findDialog ) // 0 when we close the dialog
{
if ( d->m_find->pattern() != d->m_findDialog->pattern() ) {
d->m_find->setPattern( d->m_findDialog->pattern() );
d->m_find->resetCounts();
}
options = d->m_findDialog->options();
if ( d->m_lastFindState.options != options )
{
d->m_find->setOptions( options );
if ( options & KFindDialog::SelectedText )
Q_ASSERT( hasSelection() );
long difference = d->m_lastFindState.options ^ options;
if ( difference & (KFindDialog::SelectedText | KFindDialog::FromCursor ) )
{
// Important options changed -> reset search range
(void) initFindNode( options & KFindDialog::SelectedText,
options & KFindDialog::FindBackwards,
options & KFindDialog::FromCursor );
}
d->m_lastFindState.options = options;
}
} else
options = d->m_lastFindState.options;
if( reverse )
options = options ^ KFindDialog::FindBackwards;
if( d->m_find->options() != options )
d->m_find->setOptions( options );
// Changing find direction. Start and end nodes must be switched.
// Additionally since d->m_findNode points after the last node
// that was searched, it needs to be "after" it in the opposite direction.
if( d->m_lastFindState.last_dir != -1
&& bool( d->m_lastFindState.last_dir ) != bool( options & KFindDialog::FindBackwards ))
{
qSwap( d->m_findNodeEnd, d->m_findNodeStart );
qSwap( d->m_findPosEnd, d->m_findPosStart );
qSwap( d->m_findNode, d->m_findNodePrevious );
// d->m_findNode now point at the end of the last searched line - advance one node
khtml::RenderObject* obj = d->m_findNode ? d->m_findNode->renderer() : 0;
khtml::RenderObject* end = d->m_findNodeEnd ? d->m_findNodeEnd->renderer() : 0;
if ( obj == end )
obj = 0L;
else if ( obj )
{
do {
obj = (options & KFindDialog::FindBackwards) ? obj->objectAbove() : obj->objectBelow();
} while ( obj && ( !obj->element() || obj->isInlineContinuation() ) );
}
if ( obj )
d->m_findNode = obj->element();
else
d->m_findNode = 0;
}
d->m_lastFindState.last_dir = ( options & KFindDialog::FindBackwards ) ? 1 : 0;
KFind::Result res = KFind::NoMatch;
khtml::RenderObject* obj = d->m_findNode ? d->m_findNode->renderer() : 0;
khtml::RenderObject* end = d->m_findNodeEnd ? d->m_findNodeEnd->renderer() : 0;
khtml::RenderTextArea *tmpTextArea=0L;
//kdDebug(6050) << k_funcinfo << "obj=" << obj << " end=" << end << endl;
while( res == KFind::NoMatch )
{
if ( d->m_find->needData() )
{
if ( !obj ) {
//kdDebug(6050) << k_funcinfo << "obj=0 -> done" << endl;
break; // we're done
}
//kdDebug(6050) << k_funcinfo << " gathering data" << endl;
// First make up the QString for the current 'line' (i.e. up to \n)
// We also want to remember the DOMNode for every portion of the string.
// We store this in an index->node list.
d->m_stringPortions.clear();
bool newLine = false;
QString str;
DOM::NodeImpl* lastNode = d->m_findNode;
while ( obj && !newLine )
{
// Grab text from render object
QString s;
bool renderAreaText = obj->parent() && (QCString(obj->parent()->renderName())== "RenderTextArea");
bool renderLineText = (QCString(obj->renderName())== "RenderLineEdit");
if ( renderAreaText )
{
khtml::RenderTextArea *parent= static_cast<khtml::RenderTextArea *>(obj->parent());
s = parent->text();
s = s.replace(0xa0, ' ');
tmpTextArea = parent;
}
else if ( renderLineText )
{
khtml::RenderLineEdit *parentLine= static_cast<khtml::RenderLineEdit *>(obj);
if (parentLine->widget()->echoMode() == QLineEdit::Normal)
s = parentLine->widget()->text();
s = s.replace(0xa0, ' ');
}
else if ( obj->isText() )
{
bool isLink = false;
// checks whether the node has a <A> parent
if ( options & FindLinksOnly )
{
DOM::NodeImpl *parent = obj->element();
while ( parent )
{
if ( parent->nodeType() == Node::ELEMENT_NODE && parent->id() == ID_A )
{
isLink = true;
break;
}
parent = parent->parentNode();
}
}
else
{
isLink = true;
}
if ( isLink && obj->parent()!=tmpTextArea )
{
s = static_cast<khtml::RenderText *>(obj)->data().string();
s = s.replace(0xa0, ' ');
}
}
else if ( obj->isBR() )
s = '\n';
else if ( !obj->isInline() && !str.isEmpty() )
s = '\n';
if ( lastNode == d->m_findNodeEnd )
s.truncate( d->m_findPosEnd );
if ( !s.isEmpty() )
{
newLine = s.find( '\n' ) != -1; // did we just get a newline?
if( !( options & KFindDialog::FindBackwards ))
{
//kdDebug(6050) << "StringPortion: " << index << "-" << index+s.length()-1 << " -> " << lastNode << endl;
d->m_stringPortions.append( KHTMLPartPrivate::StringPortion( str.length(), lastNode ) );
str += s;
}
else // KFind itself can search backwards, so str must not be built backwards
{
for( QValueList<KHTMLPartPrivate::StringPortion>::Iterator it = d->m_stringPortions.begin();
it != d->m_stringPortions.end();
++it )
(*it).index += s.length();
d->m_stringPortions.prepend( KHTMLPartPrivate::StringPortion( 0, lastNode ) );
str.prepend( s );
}
}
// Compare obj and end _after_ we processed the 'end' node itself
if ( obj == end )
obj = 0L;
else
{
// Move on to next object (note: if we found a \n already, then obj (and lastNode)
// will point to the _next_ object, i.e. they are in advance.
do {
// We advance until the next RenderObject that has a NodeImpl as its element().
// Otherwise (if we keep the 'last node', and it has a '\n') we might be stuck
// on that object forever...
obj = (options & KFindDialog::FindBackwards) ? obj->objectAbove() : obj->objectBelow();
} while ( obj && ( !obj->element() || obj->isInlineContinuation() ) );
}
if ( obj )
lastNode = obj->element();
else
lastNode = 0;
} // end while
//kdDebug()<<" str : "<<str<<endl;
if ( !str.isEmpty() )
{
d->m_find->setData( str, d->m_findPos );
}
d->m_findPos = -1; // not used during the findnext loops. Only during init.
d->m_findNodePrevious = d->m_findNode;
d->m_findNode = lastNode;
}
if ( !d->m_find->needData() ) // happens if str was empty
{
// Let KFind inspect the text fragment, and emit highlighted if a match is found
res = d->m_find->find();
}
} // end while
if ( res == KFind::NoMatch ) // i.e. we're done
{
kdDebug() << "No more matches." << endl;
if ( !(options & FindNoPopups) && d->m_find->shouldRestart() )
{
//kdDebug(6050) << "Restarting" << endl;
initFindNode( false, options & KFindDialog::FindBackwards, false );
d->m_find->resetCounts();
findTextNext( reverse );
}
else // really done
{
//kdDebug(6050) << "Finishing" << endl;
//delete d->m_find;
//d->m_find = 0L;
initFindNode( false, options & KFindDialog::FindBackwards, false );
d->m_find->resetCounts();
slotClearSelection();
}
kdDebug() << "Dialog closed." << endl;
}
return res == KFind::Match;
}
void KHTMLPart::slotHighlight( const QString& /*text*/, int index, int length )
{
//kdDebug(6050) << "slotHighlight index=" << index << " length=" << length << endl;
QValueList<KHTMLPartPrivate::StringPortion>::Iterator it = d->m_stringPortions.begin();
const QValueList<KHTMLPartPrivate::StringPortion>::Iterator itEnd = d->m_stringPortions.end();
QValueList<KHTMLPartPrivate::StringPortion>::Iterator prev = it;
// We stop at the first portion whose index is 'greater than', and then use the previous one
while ( it != itEnd && (*it).index <= index )
{
prev = it;
++it;
}
Q_ASSERT ( prev != itEnd );
DOM::NodeImpl* node = (*prev).node;
Q_ASSERT( node );
d->m_selectionStart = node;
d->m_startOffset = index - (*prev).index;
khtml::RenderObject* obj = node->renderer();
khtml::RenderTextArea *parent = 0L;
khtml::RenderLineEdit *parentLine = 0L;
bool renderLineText =false;
QRect highlightedRect;
bool renderAreaText =false;
Q_ASSERT( obj );
if ( obj )
{
int x = 0, y = 0;
renderAreaText = (QCString(obj->parent()->renderName())== "RenderTextArea");
renderLineText = (QCString(obj->renderName())== "RenderLineEdit");
if( renderAreaText )
parent= static_cast<khtml::RenderTextArea *>(obj->parent());
if ( renderLineText )
parentLine= static_cast<khtml::RenderLineEdit *>(obj);
if ( !renderLineText )
//if (static_cast<khtml::RenderText *>(node->renderer())
// ->posOfChar(d->m_startOffset, x, y))
{
int dummy;
static_cast<khtml::RenderText *>(node->renderer())
->caretPos( d->m_startOffset, false, x, y, dummy, dummy ); // more precise than posOfChar
//kdDebug(6050) << "topleft: " << x << "," << y << endl;
if ( x != -1 || y != -1 )
{
int gox = d->m_view->contentsX();
if (x+50 > d->m_view->contentsX() + d->m_view->visibleWidth())
gox = x - d->m_view->visibleWidth() + 50;
if (x-10 < d->m_view->contentsX())
gox = x - d->m_view->visibleWidth() - 10;
if (gox < 0) gox = 0;
d->m_view->setContentsPos(gox, y-50);
highlightedRect.setTopLeft( d->m_view->mapToGlobal(QPoint(x, y)) );
}
}
}
// Now look for end node
it = prev; // no need to start from beginning again
while ( it != itEnd && (*it).index < index + length )
{
prev = it;
++it;
}
Q_ASSERT ( prev != itEnd );
d->m_selectionEnd = (*prev).node;
d->m_endOffset = index + length - (*prev).index;
d->m_startBeforeEnd = true;
// if the selection is limited to a single link, that link gets focus
if(d->m_selectionStart == d->m_selectionEnd)
{
bool isLink = false;
// checks whether the node has a <A> parent
DOM::NodeImpl *parent = d->m_selectionStart.handle();
while ( parent )
{
if ( parent->nodeType() == Node::ELEMENT_NODE && parent->id() == ID_A )
{
isLink = true;
break;
}
parent = parent->parentNode();
}
if(isLink == true)
{
d->m_doc->setFocusNode( parent );
}
}
#if 0
kdDebug(6050) << "slotHighlight: " << d->m_selectionStart.handle() << "," << d->m_startOffset << " - " <<
d->m_selectionEnd.handle() << "," << d->m_endOffset << endl;
it = d->m_stringPortions.begin();
for ( ; it != d->m_stringPortions.end() ; ++it )
kdDebug(6050) << " StringPortion: from index=" << (*it).index << " -> node=" << (*it).node << endl;
#endif
if( renderAreaText )
{
if( parent )
parent->highLightWord( length, d->m_endOffset-length );
}
else if ( renderLineText )
{
if( parentLine )
parentLine->highLightWord( length, d->m_endOffset-length );
}
else
{
d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
d->m_selectionEnd.handle(), d->m_endOffset );
if (d->m_selectionEnd.handle()->renderer() )
{
int x, y, height, dummy;
static_cast<khtml::RenderText *>(d->m_selectionEnd.handle()->renderer())
->caretPos( d->m_endOffset, false, x, y, dummy, height ); // more precise than posOfChar
//kdDebug(6050) << "bottomright: " << x << "," << y+height << endl;
if ( x != -1 || y != -1 )
{
// if ( static_cast<khtml::RenderText *>(d->m_selectionEnd.handle()->renderer())
// ->posOfChar(d->m_endOffset-1, x, y))
highlightedRect.setBottomRight( d->m_view->mapToGlobal( QPoint(x, y+height) ) );
}
}
}
emitSelectionChanged();
// make the finddialog move away from the selected area
if ( d->m_findDialog && !highlightedRect.isNull() )
{
highlightedRect.moveBy( -d->m_view->contentsX(), -d->m_view->contentsY() );
//kdDebug(6050) << "avoiding " << highlightedRect << endl;
KDialog::avoidArea( d->m_findDialog, highlightedRect );
}
}
QString KHTMLPart::selectedTextAsHTML() const
{
if(!hasSelection()) {
kdDebug() << "selectedTextAsHTML(): selection is not valid. Returning empty selection" << endl;
return QString::null;
}
if(d->m_startOffset < 0 || d->m_endOffset <0) {
kdDebug() << "invalid values for end/startOffset " << d->m_startOffset << " " << d->m_endOffset << endl;
return QString::null;
}
DOM::Range r = selection();
if(r.isNull() || r.isDetached())
return QString::null;
int exceptioncode = 0; //ignore the result
return r.handle()->toHTML(exceptioncode).string();
}
QString KHTMLPart::selectedText() const
{
bool hasNewLine = true;
bool seenTDTag = false;
QString text;
DOM::Node n = d->m_selectionStart;
while(!n.isNull()) {
if(n.nodeType() == DOM::Node::TEXT_NODE && n.handle()->renderer()) {
DOM::DOMStringImpl *dstr = static_cast<DOM::TextImpl*>(n.handle())->renderString();
QString str(dstr->s, dstr->l);
if(!str.isEmpty()) {
if(seenTDTag) {
text += " ";
seenTDTag = false;
}
hasNewLine = false;
if(n == d->m_selectionStart && n == d->m_selectionEnd)
text = str.mid(d->m_startOffset, d->m_endOffset - d->m_startOffset);
else if(n == d->m_selectionStart)
text = str.mid(d->m_startOffset);
else if(n == d->m_selectionEnd)
text += str.left(d->m_endOffset);
else
text += str;
}
}
else {
// This is our simple HTML -> ASCII transformation:
unsigned short id = n.elementId();
switch(id) {
case ID_TEXTAREA:
text += static_cast<HTMLTextAreaElementImpl*>(n.handle())->value().string();
break;
case ID_INPUT:
if (static_cast<HTMLInputElementImpl*>(n.handle())->inputType() != HTMLInputElementImpl::PASSWORD)
text += static_cast<HTMLInputElementImpl*>(n.handle())->value().string();
break;
case ID_SELECT:
text += static_cast<HTMLSelectElementImpl*>(n.handle())->value().string();
break;
case ID_BR:
text += "\n";
hasNewLine = true;
break;
case ID_IMG:
text += static_cast<HTMLImageElementImpl*>(n.handle())->altText().string();
break;
case ID_TD:
break;
case ID_TH:
case ID_HR:
case ID_OL:
case ID_UL:
case ID_LI:
case ID_DD:
case ID_DL:
case ID_DT:
case ID_PRE:
case ID_BLOCKQUOTE:
case ID_DIV:
if (!hasNewLine)
text += "\n";
hasNewLine = true;
break;
case ID_P:
case ID_TR:
case ID_H1:
case ID_H2:
case ID_H3:
case ID_H4:
case ID_H5:
case ID_H6:
if (!hasNewLine)
text += "\n";
// text += "\n";
hasNewLine = true;
break;
}
}
if(n == d->m_selectionEnd) break;
DOM::Node next = n.firstChild();
if(next.isNull()) next = n.nextSibling();
while( next.isNull() && !n.parentNode().isNull() ) {
n = n.parentNode();
next = n.nextSibling();
unsigned short id = n.elementId();
switch(id) {
case ID_TD:
seenTDTag = true; //Add two spaces after a td if then followed by text.
break;
case ID_TH:
case ID_HR:
case ID_OL:
case ID_UL:
case ID_LI:
case ID_DD:
case ID_DL:
case ID_DT:
case ID_PRE:
case ID_BLOCKQUOTE:
case ID_DIV:
seenTDTag = false;
if (!hasNewLine)
text += "\n";
hasNewLine = true;
break;
case ID_P:
case ID_TR:
case ID_H1:
case ID_H2:
case ID_H3:
case ID_H4:
case ID_H5:
case ID_H6:
if (!hasNewLine)
text += "\n";
// text += "\n";
hasNewLine = true;
break;
}
}
n = next;
}
if(text.isEmpty())
return QString::null;
int start = 0;
int end = text.length();
// Strip leading LFs
while ((start < end) && (text[start] == '\n'))
++start;
// Strip excessive trailing LFs
while ((start < (end-1)) && (text[end-1] == '\n') && (text[end-2] == '\n'))
--end;
return text.mid(start, end-start);
}
bool KHTMLPart::hasSelection() const
{
if ( d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() )
return false;
if ( d->m_selectionStart == d->m_selectionEnd &&
d->m_startOffset == d->m_endOffset )
return false; // empty
return true;
}
DOM::Range KHTMLPart::selection() const
{
if( d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() )
return DOM::Range();
DOM::Range r = document().createRange();
RangeImpl *rng = r.handle();
int exception = 0;
NodeImpl *n = d->m_selectionStart.handle();
if(!n->parentNode() ||
!n->renderer() ||
(!n->renderer()->isReplaced() && !n->renderer()->isBR())) {
rng->setStart( n, d->m_startOffset, exception );
if(exception) {
kdDebug(6000) << "1 -selection() threw the exception " << exception << ". Returning empty range." << endl;
return DOM::Range();
}
} else {
int o_start = 0;
while ((n = n->previousSibling()))
o_start++;
rng->setStart( d->m_selectionStart.parentNode().handle(), o_start + d->m_startOffset, exception );
if(exception) {
kdDebug(6000) << "2 - selection() threw the exception " << exception << ". Returning empty range." << endl;
return DOM::Range();
}
}
n = d->m_selectionEnd.handle();
if(!n->parentNode() ||
!n->renderer() ||
(!n->renderer()->isReplaced() && !n->renderer()->isBR())) {
rng->setEnd( n, d->m_endOffset, exception );
if(exception) {
kdDebug(6000) << "3 - selection() threw the exception " << exception << ". Returning empty range." << endl;
return DOM::Range();
}
} else {
int o_end = 0;
while ((n = n->previousSibling()))
o_end++;
rng->setEnd( d->m_selectionEnd.parentNode().handle(), o_end + d->m_endOffset, exception);
if(exception) {
kdDebug(6000) << "4 - selection() threw the exception " << exception << ". Returning empty range." << endl;
return DOM::Range();
}
}
return r;
}
void KHTMLPart::selection(DOM::Node &s, long &so, DOM::Node &e, long &eo) const
{
s = d->m_selectionStart;
so = d->m_startOffset;
e = d->m_selectionEnd;
eo = d->m_endOffset;
}
void KHTMLPart::setSelection( const DOM::Range &r )
{
// Quick-fix: a collapsed range shouldn't select the whole node.
// The real problem is in RenderCanvas::setSelection though (when index==0 the whole node is selected).
if ( r.collapsed() )
slotClearSelection();
else {
d->m_selectionStart = r.startContainer();
d->m_startOffset = r.startOffset();
d->m_selectionEnd = r.endContainer();
d->m_endOffset = r.endOffset();
d->m_doc->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
d->m_selectionEnd.handle(),d->m_endOffset);
#ifndef KHTML_NO_CARET
bool v = d->m_view->placeCaret();
emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
#endif
}
}
void KHTMLPart::slotClearSelection()
{
bool hadSelection = hasSelection();
#ifndef KHTML_NO_CARET
//kdDebug(6000) << "d->m_selectionStart " << d->m_selectionStart.handle()
// << " d->m_selectionEnd " << d->m_selectionEnd.handle() << endl;
// nothing, leave selection parameters as is
#else
d->m_selectionStart = 0;
d->m_startOffset = 0;
d->m_selectionEnd = 0;
d->m_endOffset = 0;
#endif
if ( d->m_doc ) d->m_doc->clearSelection();
if ( hadSelection )
emitSelectionChanged();
#ifndef KHTML_NO_CARET
bool v = d->m_view->placeCaret();
emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
#endif
}
void KHTMLPart::resetHoverText()
{
if( !d->m_overURL.isEmpty() ) // Only if we were showing a link
{
d->m_overURL = d->m_overURLTarget = QString::null;
emit onURL( QString::null );
// revert to default statusbar text
setStatusBarText(QString::null, BarHoverText);
emit d->m_extension->mouseOverInfo(0);
}
}
void KHTMLPart::overURL( const QString &url, const QString &target, bool /*shiftPressed*/ )
{
KURL u = completeURL(url);
// special case for <a href="">
if ( url.isEmpty() )
u.setFileName( url );
emit onURL( url );
if ( url.isEmpty() ) {
setStatusBarText(u.htmlURL(), BarHoverText);
return;
}
if (url.find( QString::fromLatin1( "javascript:" ),0, false ) == 0 ) {
QString jscode = KURL::decode_string( url.mid( url.find( "javascript:", 0, false ) ) );
jscode = KStringHandler::rsqueeze( jscode, 80 ); // truncate if too long
if (url.startsWith("javascript:window.open"))
jscode += i18n(" (In new window)");
setStatusBarText( QStyleSheet::escape( jscode ), BarHoverText );
return;
}
KFileItem item(u, QString::null, KFileItem::Unknown);
emit d->m_extension->mouseOverInfo(&item);
QString com;
KMimeType::Ptr typ = KMimeType::findByURL( u );
if ( typ )
com = typ->comment( u, false );
if ( !u.isValid() ) {
setStatusBarText(u.htmlURL(), BarHoverText);
return;
}
if ( u.isLocalFile() )
{
// TODO : use KIO::stat() and create a KFileItem out of its result,
// to use KFileItem::statusBarText()
QCString path = QFile::encodeName( u.path() );
struct stat buff;
bool ok = !stat( path.data(), &buff );
struct stat lbuff;
if (ok) ok = !lstat( path.data(), &lbuff );
QString text = u.htmlURL();
QString text2 = text;
if (ok && S_ISLNK( lbuff.st_mode ) )
{
QString tmp;
if ( com.isNull() )
tmp = i18n( "Symbolic Link");
else
tmp = i18n("%1 (Link)").arg(com);
char buff_two[1024];
text += " -> ";
int n = readlink ( path.data(), buff_two, 1022);
if (n == -1)
{
text2 += " ";
text2 += tmp;
setStatusBarText(text2, BarHoverText);
return;
}
buff_two[n] = 0;
text += buff_two;
text += " ";
text += tmp;
}
else if ( ok && S_ISREG( buff.st_mode ) )
{
if (buff.st_size < 1024)
text = i18n("%2 (%1 bytes)").arg((long) buff.st_size).arg(text2); // always put the URL last, in case it contains '%'
else
{
float d = (float) buff.st_size/1024.0;
text = i18n("%2 (%1 K)").arg(KGlobal::locale()->formatNumber(d, 2)).arg(text2); // was %.2f
}
text += " ";
text += com;
}
else if ( ok && S_ISDIR( buff.st_mode ) )
{
text += " ";
text += com;
}
else
{
text += " ";
text += com;
}
setStatusBarText(text, BarHoverText);
}
else
{
QString extra;
if (target.lower() == "_blank")
{
extra = i18n(" (In new window)");
}
else if (!target.isEmpty() &&
(target.lower() != "_top") &&
(target.lower() != "_self") &&
(target.lower() != "_parent"))
{
KHTMLPart *p = this;
while (p->parentPart())
p = p->parentPart();
if (!p->frameExists(target))
extra = i18n(" (In new window)");
else
extra = i18n(" (In other frame)");
}
if (u.protocol() == QString::fromLatin1("mailto")) {
QString mailtoMsg /* = QString::fromLatin1("<img src=%1>").arg(locate("icon", QString::fromLatin1("locolor/16x16/actions/mail_send.png")))*/;
mailtoMsg += i18n("Email to: ") + KURL::decode_string(u.path());
QStringList queries = QStringList::split('&', u.query().mid(1));
QStringList::Iterator it = queries.begin();
const QStringList::Iterator itEnd = queries.end();
for (; it != itEnd; ++it)
if ((*it).startsWith(QString::fromLatin1("subject=")))
mailtoMsg += i18n(" - Subject: ") + KURL::decode_string((*it).mid(8));
else if ((*it).startsWith(QString::fromLatin1("cc=")))
mailtoMsg += i18n(" - CC: ") + KURL::decode_string((*it).mid(3));
else if ((*it).startsWith(QString::fromLatin1("bcc=")))
mailtoMsg += i18n(" - BCC: ") + KURL::decode_string((*it).mid(4));
mailtoMsg = QStyleSheet::escape(mailtoMsg);
mailtoMsg.replace(QRegExp("([\n\r\t]|[ ]{10})"), QString::null);
setStatusBarText("<qt>"+mailtoMsg, BarHoverText);
return;
}
// Is this check necessary at all? (Frerich)
#if 0
else if (u.protocol() == QString::fromLatin1("http")) {
DOM::Node hrefNode = nodeUnderMouse().parentNode();
while (hrefNode.nodeName().string() != QString::fromLatin1("A") && !hrefNode.isNull())
hrefNode = hrefNode.parentNode();
if (!hrefNode.isNull()) {
DOM::Node hreflangNode = hrefNode.attributes().getNamedItem("HREFLANG");
if (!hreflangNode.isNull()) {
QString countryCode = hreflangNode.nodeValue().string().lower();
// Map the language code to an appropriate country code.
if (countryCode == QString::fromLatin1("en"))
countryCode = QString::fromLatin1("gb");
QString flagImg = QString::fromLatin1("<img src=%1>").arg(
locate("locale", QString::fromLatin1("l10n/")
+ countryCode
+ QString::fromLatin1("/flag.png")));
emit setStatusBarText(flagImg + u.prettyURL() + extra);
}
}
}
#endif
setStatusBarText(u.htmlURL() + extra, BarHoverText);
}
}
//
// This executes in the active part on a click or other url selection action in
// that active part.
//
void KHTMLPart::urlSelected( const QString &url, int button, int state, const QString &_target, KParts::URLArgs args )
{
// The member var is so that slotRedirection still calls the virtual urlSelected
// but is able to know if is opened a url. KDE4: just make urlSelected return a bool
// and move the urlSelectedIntern code back here.
d->m_urlSelectedOpenedURL = urlSelectedIntern( url, button, state, _target, args );
}
// Return value: true if an url was opened, false if not (e.g. error, or jumping to anchor)
bool KHTMLPart::urlSelectedIntern( const QString &url, int button, int state, const QString &_target, KParts::URLArgs args )
{
bool hasTarget = false;
QString target = _target;
if ( target.isEmpty() && d->m_doc )
target = d->m_doc->baseTarget();
if ( !target.isEmpty() )
hasTarget = true;
if ( url.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
{
crossFrameExecuteScript( target, KURL::decode_string( url.mid( 11 ) ) );
return false;
}
KURL cURL = completeURL(url);
// special case for <a href=""> (IE removes filename, mozilla doesn't)
if ( url.isEmpty() )
cURL.setFileName( url ); // removes filename
if ( !cURL.isValid() )
// ### ERROR HANDLING
return false;
kdDebug(6050) << this << " urlSelected: complete URL:" << cURL.url() << " target=" << target << endl;
if ( state & ControlButton )
{
args.setNewTab(true);
emit d->m_extension->createNewWindow( cURL, args );
return true;
}
if ( button == LeftButton && ( state & ShiftButton ) )
{
KIO::MetaData metaData;
metaData["referrer"] = d->m_referrer;
KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), cURL, metaData );
return false;
}
if (!checkLinkSecurity(cURL,
i18n( "<qt>This untrusted page links to<BR><B>%1</B>.<BR>Do you want to follow the link?" ),
i18n( "Follow" )))
return false;
args.frameName = target;
args.metaData().insert("main_frame_request",
parentPart() == 0 ? "TRUE":"FALSE");
args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
args.metaData().insert("PropagateHttpHeader", "true");
args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
args.metaData().insert("ssl_activate_warnings", "TRUE");
if ( hasTarget && target != "_self" && target != "_top" && target != "_blank" && target != "_parent" )
{
// unknown frame names should open in a new window.
khtml::ChildFrame *frame = recursiveFrameRequest( this, cURL, args, false );
if ( frame )
{
args.metaData()["referrer"] = d->m_referrer;
requestObject( frame, cURL, args );
return true;
}
}
if (!d->m_referrer.isEmpty() && !args.metaData().contains("referrer"))
args.metaData()["referrer"] = d->m_referrer;
if ( button == NoButton && (state & ShiftButton) && (state & ControlButton) )
{
emit d->m_extension->createNewWindow( cURL, args );
return true;
}
if ( state & ShiftButton)
{
KParts::WindowArgs winArgs;
winArgs.lowerWindow = true;
KParts::ReadOnlyPart *newPart = 0;
emit d->m_extension->createNewWindow( cURL, args, winArgs, newPart );
return true;
}
//If we're asked to open up an anchor in the current URL, in current window,
//merely gotoanchor, and do not reload the new page. Note that this does
//not apply if the URL is the same page, but without a ref
if (cURL.hasRef() && (!hasTarget || target == "_self"))
{
KURL curUrl = this->url();
if (urlcmp(cURL.url(), curUrl.url(),
false, // ignore trailing / diff, IE does, even if FFox doesn't
true)) // don't care if the ref changes!
{
m_url = cURL;
emit d->m_extension->openURLNotify();
if ( !gotoAnchor( m_url.encodedHtmlRef()) )
gotoAnchor( m_url.htmlRef() );
emit d->m_extension->setLocationBarURL( m_url.prettyURL() );
return false; // we jumped, but we didn't open a URL
}
}
if ( !d->m_bComplete && !hasTarget )
closeURL();
view()->viewport()->unsetCursor();
emit d->m_extension->openURLRequest( cURL, args );
return true;
}
void KHTMLPart::slotViewDocumentSource()
{
KURL url(m_url);
bool isTempFile = false;
if (!(url.isLocalFile()) && KHTMLPageCache::self()->isComplete(d->m_cacheId))
{
KTempFile sourceFile(QString::null, defaultExtension());
if (sourceFile.status() == 0)
{
KHTMLPageCache::self()->saveData(d->m_cacheId, sourceFile.dataStream());
url = KURL();
url.setPath(sourceFile.name());
isTempFile = true;
}
}
(void) KRun::runURL( url, QString::fromLatin1("text/plain"), isTempFile );
}
void KHTMLPart::slotViewPageInfo()
{
KHTMLInfoDlg *dlg = new KHTMLInfoDlg(NULL, "KHTML Page Info Dialog", false, WDestructiveClose);
dlg->_close->setGuiItem(KStdGuiItem::close());
if (d->m_doc)
dlg->_title->setText(d->m_doc->title().string());
// If it's a frame, set the caption to "Frame Information"
if ( parentPart() && d->m_doc && d->m_doc->isHTMLDocument() ) {
dlg->setCaption(i18n("Frame Information"));
}
QString editStr = QString::null;
if (!d->m_pageServices.isEmpty())
editStr = i18n(" <a href=\"%1\">[Properties]</a>").arg(d->m_pageServices);
QString squeezedURL = KStringHandler::csqueeze( url().prettyURL(), 80 );
dlg->_url->setText("<a href=\"" + url().url() + "\">" + squeezedURL + "</a>" + editStr);
if (lastModified().isEmpty())
{
dlg->_lastModified->hide();
dlg->_lmLabel->hide();
}
else
dlg->_lastModified->setText(lastModified());
const QString& enc = encoding();
if (enc.isEmpty()) {
dlg->_eLabel->hide();
dlg->_encoding->hide();
} else {
dlg->_encoding->setText(enc);
}
/* populate the list view now */
const QStringList headers = QStringList::split("\n", d->m_httpHeaders);
QStringList::ConstIterator it = headers.begin();
const QStringList::ConstIterator itEnd = headers.end();
for (; it != itEnd; ++it) {
const QStringList header = QStringList::split(QRegExp(":[ ]+"), *it);
if (header.count() != 2)
continue;
new QListViewItem(dlg->_headers, header[0], header[1]);
}
dlg->show();
/* put no code here */
}
void KHTMLPart::slotViewFrameSource()
{
KParts::ReadOnlyPart *frame = currentFrame();
if ( !frame )
return;
KURL url = frame->url();
bool isTempFile = false;
if (!(url.isLocalFile()) && frame->inherits("KHTMLPart"))
{
long cacheId = static_cast<KHTMLPart *>(frame)->d->m_cacheId;
if (KHTMLPageCache::self()->isComplete(cacheId))
{
KTempFile sourceFile(QString::null, defaultExtension());
if (sourceFile.status() == 0)
{
KHTMLPageCache::self()->saveData(cacheId, sourceFile.dataStream());
url = KURL();
url.setPath(sourceFile.name());
isTempFile = true;
}
}
}
(void) KRun::runURL( url, QString::fromLatin1("text/plain"), isTempFile );
}
KURL KHTMLPart::backgroundURL() const
{
// ### what about XML documents? get from CSS?
if (!d->m_doc || !d->m_doc->isHTMLDocument())
return KURL();
QString relURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
return KURL( m_url, relURL );
}
void KHTMLPart::slotSaveBackground()
{
KIO::MetaData metaData;
metaData["referrer"] = d->m_referrer;
KHTMLPopupGUIClient::saveURL( d->m_view, i18n("Save Background Image As"), backgroundURL(), metaData );
}
void KHTMLPart::slotSaveDocument()
{
KURL srcURL( m_url );
if ( srcURL.fileName(false).isEmpty() )
srcURL.setFileName( "index" + defaultExtension() );
KIO::MetaData metaData;
// Referre unknown?
KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), srcURL, metaData, "text/html", d->m_cacheId );
}
void KHTMLPart::slotSecurity()
{
// kdDebug( 6050 ) << "Meta Data:" << endl
// << d->m_ssl_peer_cert_subject
// << endl
// << d->m_ssl_peer_cert_issuer
// << endl
// << d->m_ssl_cipher
// << endl
// << d->m_ssl_cipher_desc
// << endl
// << d->m_ssl_cipher_version
// << endl
// << d->m_ssl_good_from
// << endl
// << d->m_ssl_good_until
// << endl
// << d->m_ssl_cert_state
// << endl;
KSSLInfoDlg *kid = new KSSLInfoDlg(d->m_ssl_in_use, widget(), "kssl_info_dlg", true );
if (d->m_bSecurityInQuestion)
kid->setSecurityInQuestion(true);
if (d->m_ssl_in_use) {
KSSLCertificate *x = KSSLCertificate::fromString(d->m_ssl_peer_certificate.local8Bit());
if (x) {
// Set the chain back onto the certificate
const QStringList cl = QStringList::split(QString("\n"), d->m_ssl_peer_chain);
QPtrList<KSSLCertificate> ncl;
ncl.setAutoDelete(true);
QStringList::ConstIterator it = cl.begin();
const QStringList::ConstIterator itEnd = cl.end();
for (; it != itEnd; ++it) {
KSSLCertificate* const y = KSSLCertificate::fromString((*it).local8Bit());
if (y) ncl.append(y);
}
if (ncl.count() > 0)
x->chain().setChain(ncl);
kid->setup(x,
d->m_ssl_peer_ip,
m_url.url(),
d->m_ssl_cipher,
d->m_ssl_cipher_desc,
d->m_ssl_cipher_version,
d->m_ssl_cipher_used_bits.toInt(),
d->m_ssl_cipher_bits.toInt(),
(KSSLCertificate::KSSLValidation) d->m_ssl_cert_state.toInt()
);
kid->exec();
delete x;
} else kid->exec();
} else kid->exec();
}
void KHTMLPart::slotSaveFrame()
{
KParts::ReadOnlyPart *frame = currentFrame();
if ( !frame )
return;
KURL srcURL( frame->url() );
if ( srcURL.fileName(false).isEmpty() )
srcURL.setFileName( "index" + defaultExtension() );
KIO::MetaData metaData;
// Referrer unknown?
KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save Frame As" ), srcURL, metaData, "text/html" );
}
void KHTMLPart::slotSetEncoding()
{
d->m_automaticDetection->setItemChecked( int( d->m_autoDetectLanguage ), false );
d->m_paSetEncoding->popupMenu()->setItemChecked( 0, false );
d->m_paSetEncoding->popupMenu()->setItemChecked( d->m_paSetEncoding->popupMenu()->idAt( 2 ), true );
QString enc = KGlobal::charsets()->encodingForName( d->m_manualDetection->currentText() );
setEncoding( enc, true );
}
void KHTMLPart::slotUseStylesheet()
{
if (d->m_doc)
{
bool autoselect = (d->m_paUseStylesheet->currentItem() == 0);
d->m_sheetUsed = autoselect ? QString() : d->m_paUseStylesheet->currentText();
d->m_doc->updateStyleSelector();
}
}
void KHTMLPart::updateActions()
{
bool frames = false;
QValueList<khtml::ChildFrame*>::ConstIterator it = d->m_frames.begin();
const QValueList<khtml::ChildFrame*>::ConstIterator end = d->m_frames.end();
for (; it != end; ++it )
if ( (*it)->m_type == khtml::ChildFrame::Frame )
{
frames = true;
break;
}
d->m_paViewFrame->setEnabled( frames );
d->m_paSaveFrame->setEnabled( frames );
if ( frames )
d->m_paFind->setText( i18n( "&Find in Frame..." ) );
else
d->m_paFind->setText( i18n( "&Find..." ) );
KParts::Part *frame = 0;
if ( frames )
frame = currentFrame();
bool enableFindAndSelectAll = true;
if ( frame )
enableFindAndSelectAll = frame->inherits( "KHTMLPart" );
d->m_paFind->setEnabled( enableFindAndSelectAll );
d->m_paSelectAll->setEnabled( enableFindAndSelectAll );
bool enablePrintFrame = false;
if ( frame )
{
QObject *ext = KParts::BrowserExtension::childObject( frame );
if ( ext )
enablePrintFrame = ext->metaObject()->slotNames().contains( "print()" );
}
d->m_paPrintFrame->setEnabled( enablePrintFrame );
QString bgURL;
// ### frames
if ( d->m_doc && d->m_doc->isHTMLDocument() && static_cast<HTMLDocumentImpl*>(d->m_doc)->body() && !d->m_bClearing )
bgURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
d->m_paSaveBackground->setEnabled( !bgURL.isEmpty() );
if ( d->m_paDebugScript )
d->m_paDebugScript->setEnabled( d->m_frame ? d->m_frame->m_jscript : 0L );
}
KParts::LiveConnectExtension *KHTMLPart::liveConnectExtension( const khtml::RenderPart *frame) const {
const ConstFrameIt end = d->m_objects.end();
for(ConstFrameIt it = d->m_objects.begin(); it != end; ++it )
if ((*it)->m_frame == frame)
return (*it)->m_liveconnect;
return 0L;
}
bool KHTMLPart::requestFrame( khtml::RenderPart *frame, const QString &url, const QString &frameName,
const QStringList &params, bool isIFrame )
{
//kdDebug( 6050 ) << this << " requestFrame( ..., " << url << ", " << frameName << " )" << endl;
FrameIt it = d->m_frames.find( frameName );
if ( it == d->m_frames.end() )
{
khtml::ChildFrame * child = new khtml::ChildFrame;
//kdDebug( 6050 ) << "inserting new frame into frame map " << frameName << endl;
child->m_name = frameName;
it = d->m_frames.append( child );
}
(*it)->m_type = isIFrame ? khtml::ChildFrame::IFrame : khtml::ChildFrame::Frame;
(*it)->m_frame = frame;
(*it)->m_params = params;
// Support for <frame src="javascript:string">
if ( url.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
{
if ( processObjectRequest(*it, KURL("about:blank"), QString("text/html") ) ) {
KHTMLPart* p = static_cast<KHTMLPart*>(static_cast<KParts::ReadOnlyPart *>((*it)->m_part));
// See if we want to replace content with javascript: output..
QVariant res = p->executeScript( DOM::Node(), KURL::decode_string( url.right( url.length() - 11) ) );
if ( res.type() == QVariant::String ) {
p->begin();
p->write( res.asString() );
p->end();
}
return true;
}
return false;
}
KURL u = url.isEmpty() ? KURL() : completeURL( url );
return requestObject( *it, u );
}
QString KHTMLPart::requestFrameName()
{
return QString::fromLatin1("<!--frame %1-->").arg(d->m_frameNameId++);
}
bool KHTMLPart::requestObject( khtml::RenderPart *frame, const QString &url, const QString &serviceType,
const QStringList &params )
{
//kdDebug( 6005 ) << "KHTMLPart::requestObject " << this << " frame=" << frame << endl;
khtml::ChildFrame *child = new khtml::ChildFrame;
FrameIt it = d->m_objects.append( child );
(*it)->m_frame = frame;
(*it)->m_type = khtml::ChildFrame::Object;
(*it)->m_params = params;
KParts::URLArgs args;
args.serviceType = serviceType;
if (!requestObject( *it, completeURL( url ), args ) && !(*it)->m_run) {
(*it)->m_bCompleted = true;
return false;
}
return true;
}
bool KHTMLPart::requestObject( khtml::ChildFrame *child, const KURL &url, const KParts::URLArgs &_args )
{
if (!checkLinkSecurity(url))
{
kdDebug(6005) << this << " KHTMLPart::requestObject checkLinkSecurity refused" << endl;
return false;
}
if ( child->m_bPreloaded )
{
kdDebug(6005) << "KHTMLPart::requestObject preload" << endl;
if ( child->m_frame && child->m_part )
child->m_frame->setWidget( child->m_part->widget() );
child->m_bPreloaded = false;
return true;
}
//kdDebug(6005) << "KHTMLPart::requestObject child=" << child << " child->m_part=" << child->m_part << endl;
KParts::URLArgs args( _args );
if ( child->m_run )
child->m_run->abort();
if ( child->m_part && !args.reload && urlcmp( child->m_part->url().url(), url.url(), true, true ) )
args.serviceType = child->m_serviceType;
child->m_args = args;
child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload);
child->m_serviceName = QString::null;
if (!d->m_referrer.isEmpty() && !child->m_args.metaData().contains( "referrer" ))
child->m_args.metaData()["referrer"] = d->m_referrer;
child->m_args.metaData().insert("PropagateHttpHeader", "true");
child->m_args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
child->m_args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
child->m_args.metaData().insert("main_frame_request",
parentPart() == 0 ? "TRUE":"FALSE");
child->m_args.metaData().insert("ssl_was_in_use",
d->m_ssl_in_use ? "TRUE":"FALSE");
child->m_args.metaData().insert("ssl_activate_warnings", "TRUE");
child->m_args.metaData().insert("cross-domain", toplevelURL().url());
// We want a KHTMLPart if the HTML says <frame src=""> or <frame src="about:blank">
if ((url.isEmpty() || url.url() == "about:blank") && args.serviceType.isEmpty())
args.serviceType = QString::fromLatin1( "text/html" );
if ( args.serviceType.isEmpty() ) {
kdDebug(6050) << "Running new KHTMLRun for " << this << " and child=" << child << endl;
child->m_run = new KHTMLRun( this, child, url, child->m_args, true );
d->m_bComplete = false; // ensures we stop it in checkCompleted...
return false;
} else {
return processObjectRequest( child, url, args.serviceType );
}
}
bool KHTMLPart::processObjectRequest( khtml::ChildFrame *child, const KURL &_url, const QString &mimetype )
{
//kdDebug( 6050 ) << "KHTMLPart::processObjectRequest trying to create part for " << mimetype << endl;
// IMPORTANT: create a copy of the url here, because it is just a reference, which was likely to be given
// by an emitting frame part (emit openURLRequest( blahurl, ... ) . A few lines below we delete the part
// though -> the reference becomes invalid -> crash is likely
KURL url( _url );
// khtmlrun called us this way to indicate a loading error
if ( d->m_onlyLocalReferences || ( url.isEmpty() && mimetype.isEmpty() ) )
{
child->m_bCompleted = true;
checkCompleted();
return true;
}
if (child->m_bNotify)
{
child->m_bNotify = false;
if ( !child->m_args.lockHistory() )
emit d->m_extension->openURLNotify();
}
if ( child->m_serviceType != mimetype || !child->m_part )
{
// Before attempting to load a part, check if the user wants that.
// Many don't like getting ZIP files embedded.
// However we don't want to ask for flash and other plugin things..
if ( child->m_type != khtml::ChildFrame::Object )
{
QString suggestedFilename;
if ( child->m_run )
suggestedFilename = child->m_run->suggestedFilename();
KParts::BrowserRun::AskSaveResult res = KParts::BrowserRun::askEmbedOrSave(
url, mimetype, suggestedFilename );
switch( res ) {
case KParts::BrowserRun::Save:
KHTMLPopupGUIClient::saveURL( widget(), i18n( "Save As" ), url, child->m_args.metaData(), QString::null, 0, suggestedFilename);
// fall-through
case KParts::BrowserRun::Cancel:
child->m_bCompleted = true;
checkCompleted();
return true; // done
default: // Open
break;
}
}
QStringList dummy; // the list of servicetypes handled by the part is now unused.
KParts::ReadOnlyPart *part = createPart( d->m_view->viewport(), child->m_name.ascii(), this, child->m_name.ascii(), mimetype, child->m_serviceName, dummy, child->m_params );
if ( !part )
{
if ( child->m_frame )
if (child->m_frame->partLoadingErrorNotify( child, url, mimetype ))
return true; // we succeeded after all (a fallback was used)
checkEmitLoadEvent();
return false;
}
//CRITICAL STUFF
if ( child->m_part )
{
if (!::qt_cast<KHTMLPart*>(child->m_part) && child->m_jscript)
child->m_jscript->clear();
partManager()->removePart( (KParts::ReadOnlyPart *)child->m_part );
delete (KParts::ReadOnlyPart *)child->m_part;
if (child->m_liveconnect) {
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 &)));
child->m_liveconnect = 0L;
}
}
child->m_serviceType = mimetype;
if ( child->m_frame && part->widget() )
child->m_frame->setWidget( part->widget() );
if ( child->m_type != khtml::ChildFrame::Object )
partManager()->addPart( part, false );
// else
// kdDebug(6005) << "AH! NO FRAME!!!!!" << endl;
child->m_part = part;
if (::qt_cast<KHTMLPart*>(part)) {
static_cast<KHTMLPart*>(part)->d->m_frame = child;
} else if (child->m_frame) {
child->m_liveconnect = KParts::LiveConnectExtension::childObject(part);
if (child->m_liveconnect)
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 &)));
}
KParts::StatusBarExtension *sb = KParts::StatusBarExtension::childObject(part);
if (sb)
sb->setStatusBar( d->m_statusBarExtension->statusBar() );
connect( part, SIGNAL( started( KIO::Job *) ),
this, SLOT( slotChildStarted( KIO::Job *) ) );
connect( part, SIGNAL( completed() ),
this, SLOT( slotChildCompleted() ) );
connect( part, SIGNAL( completed(bool) ),
this, SLOT( slotChildCompleted(bool) ) );
connect( part, SIGNAL( setStatusBarText( const QString & ) ),
this, SIGNAL( setStatusBarText( const QString & ) ) );
if ( part->inherits( "KHTMLPart" ) )
{
connect( this, SIGNAL( completed() ),
part, SLOT( slotParentCompleted() ) );
connect( this, SIGNAL( completed(bool) ),
part, SLOT( slotParentCompleted() ) );
// As soon as the child's document is created, we need to set its domain
// (but we do so only once, so it can't be simply done in the child)
connect( part, SIGNAL( docCreated() ),
this, SLOT( slotChildDocCreated() ) );
}
child->m_extension = KParts::BrowserExtension::childObject( part );
if ( child->m_extension )
{
connect( child->m_extension, SIGNAL( openURLNotify() ),
d->m_extension, SIGNAL( openURLNotify() ) );
connect( child->m_extension, SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ),
this, SLOT( slotChildURLRequest( const KURL &, const KParts::URLArgs & ) ) );
connect( child->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ),
d->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ) );
connect( child->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs &, const KParts::WindowArgs &, KParts::ReadOnlyPart *& ) ),
d->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & , const KParts::WindowArgs &, KParts::ReadOnlyPart *&) ) );
connect( child->m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ),
d->m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ) );
connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ),
d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ) );
connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ),
d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ) );
connect( child->m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ),
d->m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ) );
connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ),
d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ) );
connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ),
d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ) );
connect( child->m_extension, SIGNAL( infoMessage( const QString & ) ),
d->m_extension, SIGNAL( infoMessage( const QString & ) ) );
connect( child->m_extension, SIGNAL( requestFocus( KParts::ReadOnlyPart * ) ),
this, SLOT( slotRequestFocus( KParts::ReadOnlyPart * ) ) );
child->m_extension->setBrowserInterface( d->m_extension->browserInterface() );
}
}
else if ( child->m_frame && child->m_part &&
child->m_frame->widget() != child->m_part->widget() )
child->m_frame->setWidget( child->m_part->widget() );
checkEmitLoadEvent();
// Some JS code in the load event may have destroyed the part
// In that case, abort
if ( !child->m_part )
return false;
if ( child->m_bPreloaded )
{
if ( child->m_frame && child->m_part )
child->m_frame->setWidget( child->m_part->widget() );
child->m_bPreloaded = false;
return true;
}
child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload);
// make sure the part has a way to find out about the mimetype.
// we actually set it in child->m_args in requestObject already,
// but it's useless if we had to use a KHTMLRun instance, as the
// point the run object is to find out exactly the mimetype.
child->m_args.serviceType = mimetype;
// if not a frame set child as completed
child->m_bCompleted = child->m_type == khtml::ChildFrame::Object;
if ( child->m_extension )
child->m_extension->setURLArgs( child->m_args );
if(url.protocol() == "javascript" || url.url() == "about:blank") {
if (!child->m_part->inherits("KHTMLPart"))
return false;
KHTMLPart* p = static_cast<KHTMLPart*>(static_cast<KParts::ReadOnlyPart *>(child->m_part));
p->begin();
if (d->m_doc && p->d->m_doc)
p->d->m_doc->setBaseURL(d->m_doc->baseURL());
if (!url.url().startsWith("about:")) {
p->write(url.path());
} else {
p->m_url = url;
// we need a body element. testcase: <iframe id="a"></iframe><script>alert(a.document.body);</script>
p->write("<HTML><TITLE></TITLE><BODY></BODY></HTML>");
}
p->end();
return true;
}
else if ( !url.isEmpty() )
{
//kdDebug( 6050 ) << "opening " << url.url() << " in frame " << child->m_part << endl;
bool b = child->m_part->openURL( url );
if (child->m_bCompleted)
checkCompleted();
return b;
}
else
{
child->m_bCompleted = true;
checkCompleted();
return true;
}
}
KParts::ReadOnlyPart *KHTMLPart::createPart( QWidget *parentWidget, const char *widgetName,
QObject *parent, const char *name, const QString &mimetype,
QString &serviceName, QStringList &serviceTypes,
const QStringList &params )
{
QString constr;
if ( !serviceName.isEmpty() )
constr.append( QString::fromLatin1( "Name == '%1'" ).arg( serviceName ) );
KTrader::OfferList offers = KTrader::self()->query( mimetype, "KParts/ReadOnlyPart", constr, QString::null );
if ( offers.isEmpty() ) {
int pos = mimetype.find( "-plugin" );
if (pos < 0)
return 0L;
QString stripped_mime = mimetype.left( pos );
offers = KTrader::self()->query( stripped_mime, "KParts/ReadOnlyPart", constr, QString::null );
if ( offers.isEmpty() )
return 0L;
}
KTrader::OfferList::ConstIterator it = offers.begin();
const KTrader::OfferList::ConstIterator itEnd = offers.end();
for ( ; it != itEnd; ++it )
{
KService::Ptr service = (*it);
KLibFactory* const factory = KLibLoader::self()->factory( QFile::encodeName(service->library()) );
if ( factory ) {
KParts::ReadOnlyPart *res = 0L;
const char *className = "KParts::ReadOnlyPart";
if ( service->serviceTypes().contains( "Browser/View" ) )
className = "Browser/View";
if ( factory->inherits( "KParts::Factory" ) )
res = static_cast<KParts::ReadOnlyPart *>(static_cast<KParts::Factory *>( factory )->createPart( parentWidget, widgetName, parent, name, className, params ));
else
res = static_cast<KParts::ReadOnlyPart *>(factory->create( parentWidget, widgetName, className ));
if ( res ) {
serviceTypes = service->serviceTypes();
serviceName = service->name();
return res;
}
} else {
// TODO KMessageBox::error and i18n, like in KonqFactory::createView?
kdWarning() << QString("There was an error loading the module %1.\nThe diagnostics is:\n%2")
.arg(service->name()).arg(KLibLoader::self()->lastErrorMessage()) << endl;
}
}
return 0;
}
KParts::PartManager *KHTMLPart::partManager()
{
if ( !d->m_manager && d->m_view )
{
d->m_manager = new KParts::PartManager( d->m_view->topLevelWidget(), this, "khtml part manager" );
d->m_manager->setAllowNestedParts( true );
connect( d->m_manager, SIGNAL( activePartChanged( KParts::Part * ) ),
this, SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
connect( d->m_manager, SIGNAL( partRemoved( KParts::Part * ) ),
this, SLOT( slotPartRemoved( KParts::Part * ) ) );
}
return d->m_manager;
}
void KHTMLPart::submitFormAgain()
{
disconnect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
if( d->m_doc && !d->m_doc->parsing() && d->m_submitForm)
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 );
delete d->m_submitForm;
d->m_submitForm = 0;
}
void KHTMLPart::submitFormProxy( const char *action, const QString &url, const QByteArray &formData, const QString &_target, const QString& contentType, const QString& boundary )
{
submitForm(action, url, formData, _target, contentType, boundary);
}
void KHTMLPart::submitForm( const char *action, const QString &url, const QByteArray &formData, const QString &_target, const QString& contentType, const QString& boundary )
{
kdDebug(6000) << this << ": KHTMLPart::submitForm target=" << _target << " url=" << url << endl;
if (d->m_formNotification == KHTMLPart::Only) {
emit formSubmitNotification(action, url, formData, _target, contentType, boundary);
return;
} else if (d->m_formNotification == KHTMLPart::Before) {
emit formSubmitNotification(action, url, formData, _target, contentType, boundary);
}
KURL u = completeURL( url );
if ( !u.isValid() )
{
// ### ERROR HANDLING!
return;
}
// Form security checks
//
/*
* If these form security checks are still in this place in a month or two
* I'm going to simply delete them.
*/
/* This is separate for a reason. It has to be _before_ all script, etc,
* AND I don't want to break anything that uses checkLinkSecurity() in
* other places.
*/
if (!d->m_submitForm) {
if (u.protocol() != "https" && u.protocol() != "mailto") {
if (d->m_ssl_in_use) { // Going from SSL -> nonSSL
int rc = KMessageBox::warningContinueCancel(NULL, i18n("Warning: This is a secure form but it is attempting to send your data back unencrypted."
"\nA third party may be able to intercept and view this information."
"\nAre you sure you wish to continue?"),
i18n("Network Transmission"),KGuiItem(i18n("&Send Unencrypted")));
if (rc == KMessageBox::Cancel)
return;
} else { // Going from nonSSL -> nonSSL
KSSLSettings kss(true);
if (kss.warnOnUnencrypted()) {
int rc = KMessageBox::warningContinueCancel(NULL,
i18n("Warning: Your data is about to be transmitted across the network unencrypted."
"\nAre you sure you wish to continue?"),
i18n("Network Transmission"),
KGuiItem(i18n("&Send Unencrypted")),
"WarnOnUnencryptedForm");
// Move this setting into KSSL instead
KConfig *config = kapp->config();
QString grpNotifMsgs = QString::fromLatin1("Notification Messages");
KConfigGroupSaver saver( config, grpNotifMsgs );
if (!config->readBoolEntry("WarnOnUnencryptedForm", true)) {
config->deleteEntry("WarnOnUnencryptedForm");
config->sync();
kss.setWarnOnUnencrypted(false);
kss.save();
}
if (rc == KMessageBox::Cancel)
return;
}
}
}
if (u.protocol() == "mailto") {
int rc = KMessageBox::warningContinueCancel(NULL,
i18n("This site is attempting to submit form data via email.\n"
"Do you want to continue?"),
i18n("Network Transmission"),
KGuiItem(i18n("&Send Email")),
"WarnTriedEmailSubmit");
if (rc == KMessageBox::Cancel) {
return;
}
}
}
// End form security checks
//
QString urlstring = u.url();
if ( urlstring.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
urlstring = KURL::decode_string(urlstring);
crossFrameExecuteScript( _target, urlstring.right( urlstring.length() - 11) );
return;
}
if (!checkLinkSecurity(u,
i18n( "<qt>The form will be submitted to <BR><B>%1</B><BR>on your local filesystem.<BR>Do you want to submit the form?" ),
i18n( "Submit" )))
return;
KParts::URLArgs args;
if (!d->m_referrer.isEmpty())
args.metaData()["referrer"] = d->m_referrer;
args.metaData().insert("PropagateHttpHeader", "true");
args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
args.metaData().insert("main_frame_request",
parentPart() == 0 ? "TRUE":"FALSE");
args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
args.metaData().insert("ssl_activate_warnings", "TRUE");
//WABA: When we post a form we should treat it as the main url
//the request should never be considered cross-domain
//args.metaData().insert("cross-domain", toplevelURL().url());
args.frameName = _target.isEmpty() ? d->m_doc->baseTarget() : _target ;
// Handle mailto: forms
if (u.protocol() == "mailto") {
// 1) Check for attach= and strip it
QString q = u.query().mid(1);
QStringList nvps = QStringList::split("&", q);
bool triedToAttach = false;
QStringList::Iterator nvp = nvps.begin();
const QStringList::Iterator nvpEnd = nvps.end();
// cannot be a for loop as if something is removed we don't want to do ++nvp, as
// remove returns an iterator pointing to the next item
while (nvp != nvpEnd) {
const QStringList pair = QStringList::split("=", *nvp);
if (pair.count() >= 2) {
if (pair.first().lower() == "attach") {
nvp = nvps.remove(nvp);
triedToAttach = true;
} else {
++nvp;
}
} else {
++nvp;
}
}
if (triedToAttach)
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");
// 2) Append body=
QString bodyEnc;
if (contentType.lower() == "multipart/form-data") {
// FIXME: is this correct? I suspect not
bodyEnc = KURL::encode_string(QString::fromLatin1(formData.data(),
formData.size()));
} else if (contentType.lower() == "text/plain") {
// Convention seems to be to decode, and s/&/\n/
QString tmpbody = QString::fromLatin1(formData.data(),
formData.size());
tmpbody.replace(QRegExp("[&]"), "\n");
tmpbody.replace(QRegExp("[+]"), " ");
tmpbody = KURL::decode_string(tmpbody); // Decode the rest of it
bodyEnc = KURL::encode_string(tmpbody); // Recode for the URL
} else {
bodyEnc = KURL::encode_string(QString::fromLatin1(formData.data(),
formData.size()));
}
nvps.append(QString("body=%1").arg(bodyEnc));
q = nvps.join("&");
u.setQuery(q);
}
if ( strcmp( action, "get" ) == 0 ) {
if (u.protocol() != "mailto")
u.setQuery( QString::fromLatin1( formData.data(), formData.size() ) );
args.setDoPost( false );
}
else {
args.postData = formData;
args.setDoPost( true );
// construct some user headers if necessary
if (contentType.isNull() || contentType == "application/x-www-form-urlencoded")
args.setContentType( "Content-Type: application/x-www-form-urlencoded" );
else // contentType must be "multipart/form-data"
args.setContentType( "Content-Type: " + contentType + "; boundary=" + boundary );
}
if ( d->m_doc->parsing() || d->m_runningScripts > 0 ) {
if( d->m_submitForm ) {
kdDebug(6000) << "KHTMLPart::submitForm ABORTING!" << endl;
return;
}
d->m_submitForm = new KHTMLPartPrivate::SubmitForm;
d->m_submitForm->submitAction = action;
d->m_submitForm->submitUrl = url;
d->m_submitForm->submitFormData = formData;
d->m_submitForm->target = _target;
d->m_submitForm->submitContentType = contentType;
d->m_submitForm->submitBoundary = boundary;
connect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
}
else
{
emit d->m_extension->openURLRequest( u, args );
}
}
void KHTMLPart::popupMenu( const QString &linkUrl )
{
KURL popupURL;
KURL linkKURL;
KParts::URLArgs args;
QString referrer;
KParts::BrowserExtension::PopupFlags itemflags=KParts::BrowserExtension::ShowBookmark | KParts::BrowserExtension::ShowReload;
if ( linkUrl.isEmpty() ) { // click on background
KHTMLPart* khtmlPart = this;
while ( khtmlPart->parentPart() )
{
khtmlPart=khtmlPart->parentPart();
}
popupURL = khtmlPart->url();
referrer = khtmlPart->pageReferrer();
if (hasSelection())
itemflags = KParts::BrowserExtension::ShowTextSelectionItems;
else
itemflags |= KParts::BrowserExtension::ShowNavigationItems;
} else { // click on link
popupURL = completeURL( linkUrl );
linkKURL = popupURL;
referrer = this->referrer();
if (!(d->m_strSelectedURLTarget).isEmpty() &&
(d->m_strSelectedURLTarget.lower() != "_top") &&
(d->m_strSelectedURLTarget.lower() != "_self") &&
(d->m_strSelectedURLTarget.lower() != "_parent")) {
if (d->m_strSelectedURLTarget.lower() == "_blank")
args.setForcesNewWindow(true);
else {
KHTMLPart *p = this;
while (p->parentPart())
p = p->parentPart();
if (!p->frameExists(d->m_strSelectedURLTarget))
args.setForcesNewWindow(true);
}
}
}
// Danger, Will Robinson. The Popup might stay around for a much
// longer time than KHTMLPart. Deal with it.
KHTMLPopupGUIClient* client = new KHTMLPopupGUIClient( this, d->m_popupMenuXML, linkKURL );
QGuardedPtr<QObject> guard( client );
QString mimetype = QString::fromLatin1( "text/html" );
args.metaData()["referrer"] = referrer;
if (!linkUrl.isEmpty()) // over a link
{
if (popupURL.isLocalFile()) // safe to do this
{
mimetype = KMimeType::findByURL(popupURL,0,true,false)->name();
}
else // look at "extension" of link
{
const QString fname(popupURL.fileName(false));
if (!fname.isEmpty() && !popupURL.hasRef() && popupURL.query().isEmpty())
{
KMimeType::Ptr pmt = KMimeType::findByPath(fname,0,true);
// Further check for mime types guessed from the extension which,
// on a web page, are more likely to be a script delivering content
// of undecidable type. If the mime type from the extension is one
// of these, don't use it. Retain the original type 'text/html'.
if (pmt->name() != KMimeType::defaultMimeType() &&
!pmt->is("application/x-perl") &&
!pmt->is("application/x-perl-module") &&
!pmt->is("application/x-php") &&
!pmt->is("application/x-python-bytecode") &&
!pmt->is("application/x-python") &&
!pmt->is("application/x-shellscript"))
mimetype = pmt->name();
}
}
}
args.serviceType = mimetype;
emit d->m_extension->popupMenu( client, QCursor::pos(), popupURL, args, itemflags, S_IFREG /*always a file*/);
if ( !guard.isNull() ) {
delete client;
emit popupMenu(linkUrl, QCursor::pos());
d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
}
}
void KHTMLPart::slotParentCompleted()
{
//kdDebug(6050) << this << " slotParentCompleted()" << endl;
if ( !d->m_redirectURL.isEmpty() && !d->m_redirectionTimer.isActive() )
{
//kdDebug(6050) << this << ": starting timer for child redirection -> " << d->m_redirectURL << endl;
d->m_redirectionTimer.start( 1000 * d->m_delayRedirect, true );
}
}
void KHTMLPart::slotChildStarted( KIO::Job *job )
{
khtml::ChildFrame *child = frame( sender() );
assert( child );
child->m_bCompleted = false;
if ( d->m_bComplete )
{
#if 0
// WABA: Looks like this belongs somewhere else
if ( !parentPart() ) // "toplevel" html document? if yes, then notify the hosting browser about the document (url) changes
{
emit d->m_extension->openURLNotify();
}
#endif
d->m_bComplete = false;
emit started( job );
}
}
void KHTMLPart::slotChildCompleted()
{
slotChildCompleted( false );
}
void KHTMLPart::slotChildCompleted( bool pendingAction )
{
khtml::ChildFrame *child = frame( sender() );
if ( child ) {
kdDebug(6050) << this << " slotChildCompleted child=" << child << " m_frame=" << child->m_frame << endl;
child->m_bCompleted = true;
child->m_bPendingRedirection = pendingAction;
child->m_args = KParts::URLArgs();
}
checkCompleted();
}
void KHTMLPart::slotChildDocCreated()
{
const KHTMLPart* htmlFrame = static_cast<const KHTMLPart *>(sender());
// Set domain to the frameset's domain
// This must only be done when loading the frameset initially (#22039),
// not when following a link in a frame (#44162).
if ( d->m_doc && d->m_doc->isHTMLDocument() )
{
if ( sender()->inherits("KHTMLPart") )
{
DOMString domain = static_cast<HTMLDocumentImpl*>(d->m_doc)->domain();
if (htmlFrame->d->m_doc && htmlFrame->d->m_doc->isHTMLDocument() )
//kdDebug(6050) << "KHTMLPart::slotChildDocCreated: url: " << htmlFrame->m_url.url() << endl;
static_cast<HTMLDocumentImpl*>(htmlFrame->d->m_doc)->setDomain( domain );
}
}
// So it only happens once
disconnect( htmlFrame, SIGNAL( docCreated() ), this, SLOT( slotChildDocCreated() ) );
}
void KHTMLPart::slotChildURLRequest( const KURL &url, const KParts::URLArgs &args )
{
khtml::ChildFrame *child = frame( sender()->parent() );
KHTMLPart *callingHtmlPart = const_cast<KHTMLPart *>(dynamic_cast<const KHTMLPart *>(sender()->parent()));
// TODO: handle child target correctly! currently the script are always executed fur the parent
QString urlStr = url.url();
if ( urlStr.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
QString script = KURL::decode_string( urlStr.right( urlStr.length() - 11 ) );
executeScript( DOM::Node(), script );
return;
}
QString frameName = args.frameName.lower();
if ( !frameName.isEmpty() ) {
if ( frameName == QString::fromLatin1( "_top" ) )
{
emit d->m_extension->openURLRequest( url, args );
return;
}
else if ( frameName == QString::fromLatin1( "_blank" ) )
{
emit d->m_extension->createNewWindow( url, args );
return;
}
else if ( frameName == QString::fromLatin1( "_parent" ) )
{
KParts::URLArgs newArgs( args );
newArgs.frameName = QString::null;
emit d->m_extension->openURLRequest( url, newArgs );
return;
}
else if ( frameName != QString::fromLatin1( "_self" ) )
{
khtml::ChildFrame *_frame = recursiveFrameRequest( callingHtmlPart, url, args );
if ( !_frame )
{
emit d->m_extension->openURLRequest( url, args );
return;
}
child = _frame;
}
}
if ( child && child->m_type != khtml::ChildFrame::Object ) {
// Inform someone that we are about to show something else.
child->m_bNotify = true;
requestObject( child, url, args );
} else if ( frameName== "_self" ) // this is for embedded objects (via <object>) which want to replace the current document
{
KParts::URLArgs newArgs( args );
newArgs.frameName = QString::null;
emit d->m_extension->openURLRequest( url, newArgs );
}
}
void KHTMLPart::slotRequestFocus( KParts::ReadOnlyPart * )
{
emit d->m_extension->requestFocus(this);
}
khtml::ChildFrame *KHTMLPart::frame( const QObject *obj )
{
assert( obj->inherits( "KParts::ReadOnlyPart" ) );
const KParts::ReadOnlyPart* const part = static_cast<const KParts::ReadOnlyPart *>( obj );
FrameIt it = d->m_frames.begin();
const FrameIt end = d->m_frames.end();
for (; it != end; ++it )
if ( (KParts::ReadOnlyPart *)(*it)->m_part == part )
return *it;
FrameIt oi = d->m_objects.begin();
const FrameIt oiEnd = d->m_objects.end();
for (; oi != oiEnd; ++oi )
if ( (KParts::ReadOnlyPart *)(*oi)->m_part == part )
return *oi;
return 0L;
}
//#define DEBUG_FINDFRAME
bool KHTMLPart::checkFrameAccess(KHTMLPart *callingHtmlPart)
{
if (callingHtmlPart == this)
return true; // trivial
if (htmlDocument().isNull()) {
#ifdef DEBUG_FINDFRAME
kdDebug(6050) << "KHTMLPart::checkFrameAccess: Empty part " << this << " URL = " << m_url << endl;
#endif
return false; // we are empty?
}
// now compare the domains
if (callingHtmlPart && !callingHtmlPart->htmlDocument().isNull() &&
!htmlDocument().isNull()) {
DOM::DOMString actDomain = callingHtmlPart->htmlDocument().domain();
DOM::DOMString destDomain = htmlDocument().domain();
#ifdef DEBUG_FINDFRAME
kdDebug(6050) << "KHTMLPart::checkFrameAccess: actDomain = '" << actDomain.string() << "' destDomain = '" << destDomain.string() << "'" << endl;
#endif
if (actDomain == destDomain)
return true;
}
#ifdef DEBUG_FINDFRAME
else
{
kdDebug(6050) << "KHTMLPart::checkFrameAccess: Unknown part/domain " << callingHtmlPart << " tries to access part " << this << endl;
}
#endif
return false;
}
KHTMLPart *
KHTMLPart::findFrameParent( KParts::ReadOnlyPart *callingPart, const QString &f, khtml::ChildFrame **childFrame )
{
#ifdef DEBUG_FINDFRAME
kdDebug(6050) << "KHTMLPart::findFrameParent: this = " << this << " URL = " << m_url << " name = " << name() << " findFrameParent( " << f << " )" << endl;
#endif
// Check access
KHTMLPart* const callingHtmlPart = dynamic_cast<KHTMLPart *>(callingPart);
if (!checkFrameAccess(callingHtmlPart))
return 0;
// match encoding used in KonqView::setViewName()
if (!childFrame && !parentPart() && (QString::fromLocal8Bit(name()) == f))
return this;
FrameIt it = d->m_frames.find( f );
const FrameIt end = d->m_frames.end();
if ( it != end )
{
#ifdef DEBUG_FINDFRAME
kdDebug(6050) << "KHTMLPart::findFrameParent: FOUND!" << endl;
#endif
if (childFrame)
*childFrame = *it;
return this;
}
it = d->m_frames.begin();
for (; it != end; ++it )
{
KParts::ReadOnlyPart* const p = (*it)->m_part;
if ( p && p->inherits( "KHTMLPart" ))
{
KHTMLPart* const frameParent = static_cast<KHTMLPart*>(p)->findFrameParent(callingPart, f, childFrame);
if (frameParent)
return frameParent;
}
}
return 0;
}
KHTMLPart *KHTMLPart::findFrame( const QString &f )
{
khtml::ChildFrame *childFrame;
KHTMLPart *parentFrame = findFrameParent(this, f, &childFrame);
if (parentFrame)
{
KParts::ReadOnlyPart *p = childFrame->m_part;
if ( p && p->inherits( "KHTMLPart" ))
return static_cast<KHTMLPart *>(p);
}
return 0;
}
KParts::ReadOnlyPart *KHTMLPart::findFramePart(const QString &f)
{
khtml::ChildFrame *childFrame;
return findFrameParent(this, f, &childFrame) ? static_cast<KParts::ReadOnlyPart *>(childFrame->m_part) : 0L;
}
KParts::ReadOnlyPart *KHTMLPart::currentFrame() const
{
KParts::ReadOnlyPart* part = (KParts::ReadOnlyPart*)(this);
// Find active part in our frame manager, in case we are a frameset
// and keep doing that (in case of nested framesets).
// Just realized we could also do this recursively, calling part->currentFrame()...
while ( part && part->inherits("KHTMLPart") &&
static_cast<KHTMLPart *>(part)->d->m_frames.count() > 0 ) {
KHTMLPart* frameset = static_cast<KHTMLPart *>(part);
part = static_cast<KParts::ReadOnlyPart *>(frameset->partManager()->activePart());
if ( !part ) return frameset;
}
return part;
}
bool KHTMLPart::frameExists( const QString &frameName )
{
ConstFrameIt it = d->m_frames.find( frameName );
if ( it == d->m_frames.end() )
return false;
// WABA: We only return true if the child actually has a frame
// set. Otherwise we might find our preloaded-selve.
// This happens when we restore the frameset.
return (!(*it)->m_frame.isNull());
}
KJSProxy *KHTMLPart::framejScript(KParts::ReadOnlyPart *framePart)
{
KHTMLPart* const kp = ::qt_cast<KHTMLPart*>(framePart);
if (kp)
return kp->jScript();
FrameIt it = d->m_frames.begin();
const FrameIt itEnd = d->m_frames.end();
for (; it != itEnd; ++it)
if (framePart == (*it)->m_part) {
if (!(*it)->m_jscript)
createJScript(*it);
return (*it)->m_jscript;
}
return 0L;
}
KHTMLPart *KHTMLPart::parentPart()
{
return ::qt_cast<KHTMLPart *>( parent() );
}
khtml::ChildFrame *KHTMLPart::recursiveFrameRequest( KHTMLPart *callingHtmlPart, const KURL &url,
const KParts::URLArgs &args, bool callParent )
{
#ifdef DEBUG_FINDFRAME
kdDebug( 6050 ) << "KHTMLPart::recursiveFrameRequest this = " << this << ", frame = " << args.frameName << ", url = " << url << endl;
#endif
khtml::ChildFrame *childFrame;
KHTMLPart *childPart = findFrameParent(callingHtmlPart, args.frameName, &childFrame);
if (childPart)
{
if (childPart == this)
return childFrame;
childPart->requestObject( childFrame, url, args );
return 0;
}
if ( parentPart() && callParent )
{
khtml::ChildFrame *res = parentPart()->recursiveFrameRequest( callingHtmlPart, url, args, callParent );
if ( res )
parentPart()->requestObject( res, url, args );
}
return 0L;
}
#ifndef NDEBUG
static int s_saveStateIndentLevel = 0;
#endif
void KHTMLPart::saveState( QDataStream &stream )
{
#ifndef NDEBUG
QString indent = QString().leftJustify( s_saveStateIndentLevel * 4, ' ' );
const int indentLevel = s_saveStateIndentLevel++;
kdDebug( 6050 ) << indent << "saveState this=" << this << " '" << name() << "' saving URL " << m_url.url() << endl;
#endif
stream << m_url << (Q_INT32)d->m_view->contentsX() << (Q_INT32)d->m_view->contentsY()
<< (Q_INT32) d->m_view->contentsWidth() << (Q_INT32) d->m_view->contentsHeight() << (Q_INT32) d->m_view->marginWidth() << (Q_INT32) d->m_view->marginHeight();
// save link cursor position
int focusNodeNumber;
if (!d->m_focusNodeRestored)
focusNodeNumber = d->m_focusNodeNumber;
else if (d->m_doc && d->m_doc->focusNode())
focusNodeNumber = d->m_doc->nodeAbsIndex(d->m_doc->focusNode());
else
focusNodeNumber = -1;
stream << focusNodeNumber;
// Save the doc's cache id.
stream << d->m_cacheId;
// Save the state of the document (Most notably the state of any forms)
QStringList docState;
if (d->m_doc)
{
docState = d->m_doc->docState();
}
stream << d->m_encoding << d->m_sheetUsed << docState;
stream << d->m_zoomFactor;
stream << d->m_httpHeaders;
stream << d->m_pageServices;
stream << d->m_pageReferrer;
// Save ssl data
stream << d->m_ssl_in_use
<< d->m_ssl_peer_certificate
<< d->m_ssl_peer_chain
<< d->m_ssl_peer_ip
<< d->m_ssl_cipher
<< d->m_ssl_cipher_desc
<< d->m_ssl_cipher_version
<< d->m_ssl_cipher_used_bits
<< d->m_ssl_cipher_bits
<< d->m_ssl_cert_state
<< d->m_ssl_parent_ip
<< d->m_ssl_parent_cert;
QStringList frameNameLst, frameServiceTypeLst, frameServiceNameLst;
KURL::List frameURLLst;
QValueList<QByteArray> frameStateBufferLst;
ConstFrameIt it = d->m_frames.begin();
const ConstFrameIt end = d->m_frames.end();
for (; it != end; ++it )
{
if ( !(*it)->m_part )
continue;
frameNameLst << (*it)->m_name;
frameServiceTypeLst << (*it)->m_serviceType;
frameServiceNameLst << (*it)->m_serviceName;
frameURLLst << (*it)->m_part->url();
QByteArray state;
QDataStream frameStream( state, IO_WriteOnly );
if ( (*it)->m_extension )
(*it)->m_extension->saveState( frameStream );
frameStateBufferLst << state;
}
// Save frame data
stream << (Q_UINT32) frameNameLst.count();
stream << frameNameLst << frameServiceTypeLst << frameServiceNameLst << frameURLLst << frameStateBufferLst;
#ifndef NDEBUG
s_saveStateIndentLevel = indentLevel;
#endif
}
void KHTMLPart::restoreState( QDataStream &stream )
{
KURL u;
Q_INT32 xOffset, yOffset, wContents, hContents, mWidth, mHeight;
Q_UINT32 frameCount;
QStringList frameNames, frameServiceTypes, docState, frameServiceNames;
KURL::List frameURLs;
QValueList<QByteArray> frameStateBuffers;
QValueList<int> fSizes;
QString encoding, sheetUsed;
long old_cacheId = d->m_cacheId;
stream >> u >> xOffset >> yOffset >> wContents >> hContents >> mWidth >> mHeight;
d->m_view->setMarginWidth( mWidth );
d->m_view->setMarginHeight( mHeight );
// restore link cursor position
// nth node is active. value is set in checkCompleted()
stream >> d->m_focusNodeNumber;
d->m_focusNodeRestored = false;
stream >> d->m_cacheId;
stream >> encoding >> sheetUsed >> docState;
d->m_encoding = encoding;
d->m_sheetUsed = sheetUsed;
int zoomFactor;
stream >> zoomFactor;
setZoomFactor(zoomFactor);
stream >> d->m_httpHeaders;
stream >> d->m_pageServices;
stream >> d->m_pageReferrer;
// Restore ssl data
stream >> d->m_ssl_in_use
>> d->m_ssl_peer_certificate
>> d->m_ssl_peer_chain
>> d->m_ssl_peer_ip
>> d->m_ssl_cipher
>> d->m_ssl_cipher_desc
>> d->m_ssl_cipher_version
>> d->m_ssl_cipher_used_bits
>> d->m_ssl_cipher_bits
>> d->m_ssl_cert_state
>> d->m_ssl_parent_ip
>> d->m_ssl_parent_cert;
setPageSecurity( d->m_ssl_in_use ? Encrypted : NotCrypted );
stream >> frameCount >> frameNames >> frameServiceTypes >> frameServiceNames
>> frameURLs >> frameStateBuffers;
d->m_bComplete = false;
d->m_bLoadEventEmitted = false;
// kdDebug( 6050 ) << "restoreState() docState.count() = " << docState.count() << endl;
// kdDebug( 6050 ) << "m_url " << m_url.url() << " <-> " << u.url() << endl;
// kdDebug( 6050 ) << "m_frames.count() " << d->m_frames.count() << " <-> " << frameCount << endl;
if (d->m_cacheId == old_cacheId)
{
// Partial restore
d->m_redirectionTimer.stop();
FrameIt fIt = d->m_frames.begin();
const FrameIt fEnd = d->m_frames.end();
for (; fIt != fEnd; ++fIt )
(*fIt)->m_bCompleted = false;
fIt = d->m_frames.begin();
QStringList::ConstIterator fNameIt = frameNames.begin();
QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
KURL::List::ConstIterator fURLIt = frameURLs.begin();
QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
for (; fIt != fEnd; ++fIt, ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
{
khtml::ChildFrame* const child = *fIt;
// kdDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt << endl;
if ( child->m_name != *fNameIt || child->m_serviceType != *fServiceTypeIt )
{
child->m_bPreloaded = true;
child->m_name = *fNameIt;
child->m_serviceName = *fServiceNameIt;
processObjectRequest( child, *fURLIt, *fServiceTypeIt );
}
if ( child->m_part )
{
child->m_bCompleted = false;
if ( child->m_extension && !(*fBufferIt).isEmpty() )
{
QDataStream frameStream( *fBufferIt, IO_ReadOnly );
child->m_extension->restoreState( frameStream );
}
else
child->m_part->openURL( *fURLIt );
}
}
KParts::URLArgs args( d->m_extension->urlArgs() );
args.xOffset = xOffset;
args.yOffset = yOffset;
args.docState = docState;
d->m_extension->setURLArgs( args );
d->m_view->resizeContents( wContents, hContents);
d->m_view->setContentsPos( xOffset, yOffset );
m_url = u;
}
else
{
// Full restore.
closeURL();
// We must force a clear because we want to be sure to delete all
// frames.
d->m_bCleared = false;
clear();
d->m_encoding = encoding;
d->m_sheetUsed = sheetUsed;
QStringList::ConstIterator fNameIt = frameNames.begin();
const QStringList::ConstIterator fNameEnd = frameNames.end();
QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
KURL::List::ConstIterator fURLIt = frameURLs.begin();
QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
for (; fNameIt != fNameEnd; ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
{
khtml::ChildFrame* const newChild = new khtml::ChildFrame;
newChild->m_bPreloaded = true;
newChild->m_name = *fNameIt;
newChild->m_serviceName = *fServiceNameIt;
// kdDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt << endl;
const FrameIt childFrame = d->m_frames.append( newChild );
processObjectRequest( *childFrame, *fURLIt, *fServiceTypeIt );
(*childFrame)->m_bPreloaded = true;
if ( (*childFrame)->m_part )
{
if ( (*childFrame)->m_extension )
if ( (*childFrame)->m_extension && !(*fBufferIt).isEmpty() )
{
QDataStream frameStream( *fBufferIt, IO_ReadOnly );
(*childFrame)->m_extension->restoreState( frameStream );
}
else
(*childFrame)->m_part->openURL( *fURLIt );
}
}
KParts::URLArgs args( d->m_extension->urlArgs() );
args.xOffset = xOffset;
args.yOffset = yOffset;
args.docState = docState;
d->m_extension->setURLArgs( args );
if (!KHTMLPageCache::self()->isComplete(d->m_cacheId))
{
d->m_restored = true;
openURL( u );
d->m_restored = false;
}
else
{
restoreURL( u );
}
}
}
void KHTMLPart::show()
{
if ( d->m_view )
d->m_view->show();
}
void KHTMLPart::hide()
{
if ( d->m_view )
d->m_view->hide();
}
DOM::Node KHTMLPart::nodeUnderMouse() const
{
return d->m_view->nodeUnderMouse();
}
DOM::Node KHTMLPart::nonSharedNodeUnderMouse() const
{
return d->m_view->nonSharedNodeUnderMouse();
}
void KHTMLPart::emitSelectionChanged()
{
emit d->m_extension->enableAction( "copy", hasSelection() );
if ( d->m_findDialog )
d->m_findDialog->setHasSelection( hasSelection() );
emit d->m_extension->selectionInfo( selectedText() );
emit selectionChanged();
}
int KHTMLPart::zoomFactor() const
{
return d->m_zoomFactor;
}
// ### make the list configurable ?
static const int zoomSizes[] = { 20, 40, 60, 80, 90, 95, 100, 105, 110, 120, 140, 160, 180, 200, 250, 300 };
static const int zoomSizeCount = (sizeof(zoomSizes) / sizeof(int));
static const int minZoom = 20;
static const int maxZoom = 300;
// My idea of useful stepping ;-) (LS)
extern const int KDE_NO_EXPORT fastZoomSizes[] = { 20, 50, 75, 90, 100, 120, 150, 200, 300 };
extern const int KDE_NO_EXPORT fastZoomSizeCount = sizeof fastZoomSizes / sizeof fastZoomSizes[0];
void KHTMLPart::slotIncZoom()
{
zoomIn(zoomSizes, zoomSizeCount);
}
void KHTMLPart::slotDecZoom()
{
zoomOut(zoomSizes, zoomSizeCount);
}
void KHTMLPart::slotIncZoomFast()
{
zoomIn(fastZoomSizes, fastZoomSizeCount);
}
void KHTMLPart::slotDecZoomFast()
{
zoomOut(fastZoomSizes, fastZoomSizeCount);
}
void KHTMLPart::zoomIn(const int stepping[], int count)
{
int zoomFactor = d->m_zoomFactor;
if (zoomFactor < maxZoom) {
// find the entry nearest to the given zoomsizes
for (int i = 0; i < count; ++i)
if (stepping[i] > zoomFactor) {
zoomFactor = stepping[i];
break;
}
setZoomFactor(zoomFactor);
}
}
void KHTMLPart::zoomOut(const int stepping[], int count)
{
int zoomFactor = d->m_zoomFactor;
if (zoomFactor > minZoom) {
// find the entry nearest to the given zoomsizes
for (int i = count-1; i >= 0; --i)
if (stepping[i] < zoomFactor) {
zoomFactor = stepping[i];
break;
}
setZoomFactor(zoomFactor);
}
}
void KHTMLPart::setZoomFactor (int percent)
{
if (percent < minZoom) percent = minZoom;
if (percent > maxZoom) percent = maxZoom;
if (d->m_zoomFactor == percent) return;
d->m_zoomFactor = percent;
if(d->m_doc) {
QApplication::setOverrideCursor( waitCursor );
if (d->m_doc->styleSelector())
d->m_doc->styleSelector()->computeFontSizes(d->m_doc->paintDeviceMetrics(), d->m_zoomFactor);
d->m_doc->recalcStyle( NodeImpl::Force );
QApplication::restoreOverrideCursor();
}
ConstFrameIt it = d->m_frames.begin();
const ConstFrameIt end = d->m_frames.end();
for (; it != end; ++it )
if ( !( *it )->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
KParts::ReadOnlyPart* const p = ( *it )->m_part;
static_cast<KHTMLPart*>( p )->setZoomFactor(d->m_zoomFactor);
}
if ( d->m_guiProfile == BrowserViewGUI ) {
d->m_paDecZoomFactor->setEnabled( d->m_zoomFactor > minZoom );
d->m_paIncZoomFactor->setEnabled( d->m_zoomFactor < maxZoom );
}
}
void KHTMLPart::slotZoomView( int delta )
{
if ( delta < 0 )
slotIncZoom();
else
slotDecZoom();
}
void KHTMLPart::setStatusBarText( const QString& text, StatusBarPriority p)
{
if (!d->m_statusMessagesEnabled)
return;
d->m_statusBarText[p] = text;
// shift handling ?
QString tobe = d->m_statusBarText[BarHoverText];
if (tobe.isEmpty())
tobe = d->m_statusBarText[BarOverrideText];
if (tobe.isEmpty()) {
tobe = d->m_statusBarText[BarDefaultText];
if (!tobe.isEmpty() && d->m_jobspeed)
tobe += " ";
if (d->m_jobspeed)
tobe += i18n( "(%1/s)" ).arg( KIO::convertSize( d->m_jobspeed ) );
}
tobe = "<qt>"+tobe;
emit ReadOnlyPart::setStatusBarText(tobe);
}
void KHTMLPart::setJSStatusBarText( const QString &text )
{
setStatusBarText(text, BarOverrideText);
}
void KHTMLPart::setJSDefaultStatusBarText( const QString &text )
{
setStatusBarText(text, BarDefaultText);
}
QString KHTMLPart::jsStatusBarText() const
{
return d->m_statusBarText[BarOverrideText];
}
QString KHTMLPart::jsDefaultStatusBarText() const
{
return d->m_statusBarText[BarDefaultText];
}
QString KHTMLPart::referrer() const
{
return d->m_referrer;
}
QString KHTMLPart::pageReferrer() const
{
KURL referrerURL = KURL( d->m_pageReferrer );
if (referrerURL.isValid())
{
QString protocol = referrerURL.protocol();
if ((protocol == "http") ||
((protocol == "https") && (m_url.protocol() == "https")))
{
referrerURL.setRef(QString::null);
referrerURL.setUser(QString::null);
referrerURL.setPass(QString::null);
return referrerURL.url();
}
}
return QString::null;
}
QString KHTMLPart::lastModified() const
{
if ( d->m_lastModified.isEmpty() && m_url.isLocalFile() ) {
// Local file: set last-modified from the file's mtime.
// Done on demand to save time when this isn't needed - but can lead
// to slightly wrong results if updating the file on disk w/o reloading.
QDateTime lastModif = QFileInfo( m_url.path() ).lastModified();
d->m_lastModified = lastModif.toString( Qt::LocalDate );
}
//kdDebug(6050) << "KHTMLPart::lastModified: " << d->m_lastModified << endl;
return d->m_lastModified;
}
void KHTMLPart::slotLoadImages()
{
if (d->m_doc )
d->m_doc->docLoader()->setAutoloadImages( !d->m_doc->docLoader()->autoloadImages() );
ConstFrameIt it = d->m_frames.begin();
const ConstFrameIt end = d->m_frames.end();
for (; it != end; ++it )
if ( !( *it )->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
KParts::ReadOnlyPart* const p = ( *it )->m_part;
static_cast<KHTMLPart*>( p )->slotLoadImages();
}
}
void KHTMLPart::reparseConfiguration()
{
KHTMLSettings *settings = KHTMLFactory::defaultHTMLSettings();
settings->init();
setAutoloadImages( settings->autoLoadImages() );
if (d->m_doc)
d->m_doc->docLoader()->setShowAnimations( settings->showAnimations() );
d->m_bOpenMiddleClick = settings->isOpenMiddleClickEnabled();
d->m_bBackRightClick = settings->isBackRightClickEnabled();
d->m_bJScriptEnabled = settings->isJavaScriptEnabled(m_url.host());
setDebugScript( settings->isJavaScriptDebugEnabled() );
d->m_bJavaEnabled = settings->isJavaEnabled(m_url.host());
d->m_bPluginsEnabled = settings->isPluginsEnabled(m_url.host());
d->m_metaRefreshEnabled = settings->isAutoDelayedActionsEnabled ();
delete d->m_settings;
d->m_settings = new KHTMLSettings(*KHTMLFactory::defaultHTMLSettings());
QApplication::setOverrideCursor( waitCursor );
khtml::CSSStyleSelector::reparseConfiguration();
if(d->m_doc) d->m_doc->updateStyleSelector();
QApplication::restoreOverrideCursor();
if (KHTMLFactory::defaultHTMLSettings()->isAdFilterEnabled())
runAdFilter();
}
QStringList KHTMLPart::frameNames() const
{
QStringList res;
ConstFrameIt it = d->m_frames.begin();
const ConstFrameIt end = d->m_frames.end();
for (; it != end; ++it )
if (!(*it)->m_bPreloaded)
res += (*it)->m_name;
return res;
}
QPtrList<KParts::ReadOnlyPart> KHTMLPart::frames() const
{
QPtrList<KParts::ReadOnlyPart> res;
ConstFrameIt it = d->m_frames.begin();
const ConstFrameIt end = d->m_frames.end();
for (; it != end; ++it )
if (!(*it)->m_bPreloaded)
res.append( (*it)->m_part );
return res;
}
bool KHTMLPart::openURLInFrame( const KURL &url, const KParts::URLArgs &urlArgs )
{
kdDebug( 6050 ) << this << "KHTMLPart::openURLInFrame " << url << endl;
FrameIt it = d->m_frames.find( urlArgs.frameName );
if ( it == d->m_frames.end() )
return false;
// Inform someone that we are about to show something else.
if ( !urlArgs.lockHistory() )
emit d->m_extension->openURLNotify();
requestObject( *it, url, urlArgs );
return true;
}
void KHTMLPart::setDNDEnabled( bool b )
{
d->m_bDnd = b;
}
bool KHTMLPart::dndEnabled() const
{
return d->m_bDnd;
}
void KHTMLPart::customEvent( QCustomEvent *event )
{
if ( khtml::MousePressEvent::test( event ) )
{
khtmlMousePressEvent( static_cast<khtml::MousePressEvent *>( event ) );
return;
}
if ( khtml::MouseDoubleClickEvent::test( event ) )
{
khtmlMouseDoubleClickEvent( static_cast<khtml::MouseDoubleClickEvent *>( event ) );
return;
}
if ( khtml::MouseMoveEvent::test( event ) )
{
khtmlMouseMoveEvent( static_cast<khtml::MouseMoveEvent *>( event ) );
return;
}
if ( khtml::MouseReleaseEvent::test( event ) )
{
khtmlMouseReleaseEvent( static_cast<khtml::MouseReleaseEvent *>( event ) );
return;
}
if ( khtml::DrawContentsEvent::test( event ) )
{
khtmlDrawContentsEvent( static_cast<khtml::DrawContentsEvent *>( event ) );
return;
}
KParts::ReadOnlyPart::customEvent( event );
}
static bool firstRunAt(khtml::RenderObject *renderNode, int y, NodeImpl *&startNode, long &startOffset)
{
for (khtml::RenderObject *n = renderNode; n; n = n->nextSibling()) {
if (n->isText()) {
khtml::RenderText* const textRenderer = static_cast<khtml::RenderText *>(n);
const khtml::InlineTextBoxArray &runs = textRenderer->inlineTextBoxes();
const unsigned lim = runs.count();
for (unsigned i = 0; i != lim; ++i) {
if (runs[i]->m_y == y && textRenderer->element()) {
startNode = textRenderer->element();
startOffset = runs[i]->m_start;
return true;
}
}
}
if (firstRunAt(n->firstChild(), y, startNode, startOffset)) {
return true;
}
}
return false;
}
static bool lastRunAt(khtml::RenderObject *renderNode, int y, NodeImpl *&endNode, long &endOffset)
{
khtml::RenderObject *n = renderNode;
if (!n) {
return false;
}
khtml::RenderObject *next;
while ((next = n->nextSibling())) {
n = next;
}
while (1) {
if (lastRunAt(n->firstChild(), y, endNode, endOffset)) {
return true;
}
if (n->isText()) {
khtml::RenderText* const textRenderer = static_cast<khtml::RenderText *>(n);
const khtml::InlineTextBoxArray &runs = textRenderer->inlineTextBoxes();
for (int i = (int)runs.count()-1; i >= 0; --i) {
if (runs[i]->m_y == y && textRenderer->element()) {
endNode = textRenderer->element();
endOffset = runs[i]->m_start + runs[i]->m_len;
return true;
}
}
}
if (n == renderNode) {
return false;
}
n = n->previousSibling();
}
}
void KHTMLPart::khtmlMousePressEvent( khtml::MousePressEvent *event )
{
DOM::DOMString url = event->url();
QMouseEvent *_mouse = event->qmouseEvent();
DOM::Node innerNode = event->innerNode();
d->m_mousePressNode = innerNode;
d->m_dragStartPos = _mouse->pos();
if ( !event->url().isNull() ) {
d->m_strSelectedURL = event->url().string();
d->m_strSelectedURLTarget = event->target().string();
}
else
d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
if ( _mouse->button() == LeftButton ||
_mouse->button() == MidButton )
{
d->m_bMousePressed = true;
#ifndef KHTML_NO_SELECTION
if ( _mouse->button() == LeftButton )
{
if ( (!d->m_strSelectedURL.isNull() && !isEditable())
|| (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) )
return;
if ( !innerNode.isNull() && innerNode.handle()->renderer()) {
int offset = 0;
DOM::NodeImpl* node = 0;
khtml::RenderObject::SelPointState state;
innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(),
event->absX()-innerNode.handle()->renderer()->xPos(),
event->absY()-innerNode.handle()->renderer()->yPos(), node, offset, state );
d->m_extendMode = d->ExtendByChar;
#ifdef KHTML_NO_CARET
d->m_selectionStart = node;
d->m_startOffset = offset;
//if ( node )
// kdDebug(6005) << "KHTMLPart::khtmlMousePressEvent selectionStart=" << d->m_selectionStart.handle()->renderer()
// << " offset=" << d->m_startOffset << endl;
//else
// kdDebug(6005) << "KHTML::khtmlMousePressEvent selectionStart=(nil)" << endl;
d->m_selectionEnd = d->m_selectionStart;
d->m_endOffset = d->m_startOffset;
d->m_doc->clearSelection();
#else // KHTML_NO_CARET
d->m_view->moveCaretTo(node, offset, (_mouse->state() & ShiftButton) == 0);
#endif // KHTML_NO_CARET
d->m_initialNode = d->m_selectionStart;
d->m_initialOffset = d->m_startOffset;
// kdDebug(6000) << "press: initOfs " << d->m_initialOffset << endl;
}
else
{
#ifndef KHTML_NO_CARET
// simply leave it. Is this a good idea?
#else
d->m_selectionStart = DOM::Node();
d->m_selectionEnd = DOM::Node();
#endif
}
emitSelectionChanged();
startAutoScroll();
}
#else
d->m_dragLastPos = _mouse->globalPos();
#endif
}
if ( _mouse->button() == RightButton && parentPart() != 0 && d->m_bBackRightClick )
{
d->m_bRightMousePressed = true;
} else if ( _mouse->button() == RightButton )
{
popupMenu( d->m_strSelectedURL );
// might be deleted, don't touch "this"
}
}
void KHTMLPart::khtmlMouseDoubleClickEvent( khtml::MouseDoubleClickEvent *event )
{
QMouseEvent *_mouse = event->qmouseEvent();
if ( _mouse->button() == LeftButton )
{
d->m_bMousePressed = true;
DOM::Node innerNode = event->innerNode();
// Find selectionStart again, khtmlMouseReleaseEvent lost it
if ( !innerNode.isNull() && innerNode.handle()->renderer()) {
int offset = 0;
DOM::NodeImpl* node = 0;
khtml::RenderObject::SelPointState state;
innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(),
event->absX()-innerNode.handle()->renderer()->xPos(),
event->absY()-innerNode.handle()->renderer()->yPos(), node, offset, state);
//kdDebug() << k_funcinfo << "checkSelectionPoint returned node=" << node << " offset=" << offset << endl;
if ( node && node->renderer() )
{
// Extend selection to a complete word (double-click) or line (triple-click)
bool selectLine = (event->clickCount() == 3);
d->m_extendMode = selectLine ? d->ExtendByLine : d->ExtendByWord;
// Extend existing selection if Shift was pressed
if (_mouse->state() & ShiftButton) {
d->caretNode() = node;
d->caretOffset() = offset;
d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
d->m_selectionStart.handle(), d->m_startOffset,
d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
d->m_initialNode = d->m_extendAtEnd ? d->m_selectionStart : d->m_selectionEnd;
d->m_initialOffset = d->m_extendAtEnd ? d->m_startOffset : d->m_endOffset;
} else {
d->m_selectionStart = d->m_selectionEnd = node;
d->m_startOffset = d->m_endOffset = offset;
d->m_startBeforeEnd = true;
d->m_initialNode = node;
d->m_initialOffset = offset;
}
// kdDebug(6000) << "dblclk: initOfs " << d->m_initialOffset << endl;
// Extend the start
extendSelection( d->m_selectionStart.handle(), d->m_startOffset, d->m_selectionStart, d->m_startOffset, !d->m_startBeforeEnd, selectLine );
// Extend the end
extendSelection( d->m_selectionEnd.handle(), d->m_endOffset, d->m_selectionEnd, d->m_endOffset, d->m_startBeforeEnd, selectLine );
//kdDebug() << d->m_selectionStart.handle() << " " << d->m_startOffset << " - " <<
// d->m_selectionEnd.handle() << " " << d->m_endOffset << endl;
emitSelectionChanged();
d->m_doc
->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
d->m_selectionEnd.handle(),d->m_endOffset);
#ifndef KHTML_NO_CARET
bool v = d->m_view->placeCaret();
emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
#endif
startAutoScroll();
}
}
}
}
void KHTMLPart::extendSelection( DOM::NodeImpl* node, long offset, DOM::Node& selectionNode, long& selectionOffset, bool right, bool selectLines )
{
khtml::RenderObject* obj = node->renderer();
if (obj->isText() && selectLines) {
int pos;
khtml::RenderText *renderer = static_cast<khtml::RenderText *>(obj);
khtml::InlineTextBox *run = renderer->findInlineTextBox( offset, pos );
DOMString t = node->nodeValue();
DOM::NodeImpl* selNode = 0;
long selOfs = 0;
if (!run)
return;
int selectionPointY = run->m_y;
// Go up to first non-inline element.
khtml::RenderObject *renderNode = renderer;
while (renderNode && renderNode->isInline())
renderNode = renderNode->parent();
renderNode = renderNode->firstChild();
if (right) {
// Look for all the last child in the block that is on the same line
// as the selection point.
if (!lastRunAt (renderNode, selectionPointY, selNode, selOfs))
return;
} else {
// Look for all the first child in the block that is on the same line
// as the selection point.
if (!firstRunAt (renderNode, selectionPointY, selNode, selOfs))
return;
}
selectionNode = selNode;
selectionOffset = selOfs;
return;
}
QString str;
int len = 0;
if ( obj->isText() ) { // can be false e.g. when double-clicking on a disabled submit button
str = static_cast<khtml::RenderText *>(obj)->data().string();
len = str.length();
}
//kdDebug() << "extendSelection right=" << right << " offset=" << offset << " len=" << len << " Starting at obj=" << obj << endl;
QChar ch;
do {
// Last char was ok, point to it
if ( node ) {
selectionNode = node;
selectionOffset = offset;
}
// Get another char
while ( obj && ( (right && offset >= len-1) || (!right && offset <= 0) ) )
{
obj = right ? obj->objectBelow() : obj->objectAbove();
//kdDebug() << "obj=" << obj << endl;
if ( obj ) {
//kdDebug() << "isText=" << obj->isText() << endl;
str = QString::null;
if ( obj->isText() )
str = static_cast<khtml::RenderText *>(obj)->data().string();
else if ( obj->isBR() )
str = '\n';
else if ( !obj->isInline() ) {
obj = 0L; // parag limit -> done
break;
}
len = str.length();
//kdDebug() << "str=" << str << " length=" << len << endl;
// set offset - note that the first thing will be a ++ or -- on it.
if ( right )
offset = -1;
else
offset = len;
}
}
if ( !obj ) // end of parag or document
break;
node = obj->element();
if ( right )
{
Q_ASSERT( offset < len-1 );
++offset;
}
else
{
Q_ASSERT( offset > 0 );
--offset;
}
// Test that char
ch = str[ (int)offset ];
//kdDebug() << " offset=" << offset << " ch=" << QString(ch) << endl;
} while ( !ch.isSpace() && !ch.isPunct() );
// make offset point after last char
if (right) ++selectionOffset;
}
#ifndef KHTML_NO_SELECTION
void KHTMLPart::extendSelectionTo(int x, int y, int absX, int absY, const DOM::Node &innerNode)
{
int offset;
//kdDebug(6000) << "KHTMLPart::khtmlMouseMoveEvent x=" << event->x() << " y=" << event->y() << endl;
DOM::NodeImpl* node=0;
khtml::RenderObject::SelPointState state;
innerNode.handle()->renderer()->checkSelectionPoint( x, y,
absX-innerNode.handle()->renderer()->xPos(),
absY-innerNode.handle()->renderer()->yPos(), node, offset, state);
if (!node || !node->renderer()) return;
// Words at the beginning/end of line cannot be deselected in
// ExtendByWord mode. Therefore, do not enforce it if the selection
// point does not match the node under the mouse cursor.
bool withinNode = innerNode == node;
// we have to get to know if end is before start or not...
// shouldn't be null but it can happen with dynamic updating of nodes
if (d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() ||
d->m_initialNode.isNull() ||
!d->m_selectionStart.handle()->renderer() ||
!d->m_selectionEnd.handle()->renderer()) return;
if (d->m_extendMode != d->ExtendByChar) {
// check whether we should extend at the front, or at the back
bool caretBeforeInit = RangeImpl::compareBoundaryPoints(
d->caretNode().handle(), d->caretOffset(),
d->m_initialNode.handle(), d->m_initialOffset) <= 0;
bool nodeBeforeInit = RangeImpl::compareBoundaryPoints(node, offset,
d->m_initialNode.handle(), d->m_initialOffset) <= 0;
// have to fix up start to point to the original end
if (caretBeforeInit != nodeBeforeInit) {
// kdDebug(6000) << "extto cbi: " << caretBeforeInit << " startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << " initOfs " << d->m_initialOffset << endl;
extendSelection(d->m_initialNode.handle(), d->m_initialOffset,
d->m_extendAtEnd ? d->m_selectionStart : d->m_selectionEnd,
d->m_extendAtEnd ? d->m_startOffset : d->m_endOffset,
nodeBeforeInit, d->m_extendMode == d->ExtendByLine);
}
}
d->caretNode() = node;
d->caretOffset() = offset;
//kdDebug( 6000 ) << "setting end of selection to " << d->m_selectionEnd.handle() << "/" << d->m_endOffset << endl;
d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
d->m_selectionStart.handle(), d->m_startOffset,
d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
if ( !d->m_selectionStart.isNull() && !d->m_selectionEnd.isNull() )
{
// kdDebug(6000) << "extto: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << " initOfs " << d->m_initialOffset << endl;
if (d->m_extendMode != d->ExtendByChar && withinNode)
extendSelection( node, offset, d->caretNode(), d->caretOffset(), d->m_startBeforeEnd ^ !d->m_extendAtEnd, d->m_extendMode == d->ExtendByLine );
if (d->m_selectionEnd == d->m_selectionStart && d->m_endOffset < d->m_startOffset)
d->m_doc
->setSelection(d->m_selectionStart.handle(),d->m_endOffset,
d->m_selectionEnd.handle(),d->m_startOffset);
else if (d->m_startBeforeEnd)
d->m_doc
->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
d->m_selectionEnd.handle(),d->m_endOffset);
else
d->m_doc
->setSelection(d->m_selectionEnd.handle(),d->m_endOffset,
d->m_selectionStart.handle(),d->m_startOffset);
}
#ifndef KHTML_NO_CARET
d->m_view->placeCaret();
#endif
}
bool KHTMLPart::isExtendingSelection() const
{
// This is it, the whole detection. khtmlMousePressEvent only sets this
// on LMB or MMB, but never on RMB. As text selection doesn't work for MMB,
// it's sufficient to only rely on this flag to detect selection extension.
return d->m_bMousePressed;
}
#endif // KHTML_NO_SELECTION
void KHTMLPart::khtmlMouseMoveEvent( khtml::MouseMoveEvent *event )
{
QMouseEvent *_mouse = event->qmouseEvent();
if( d->m_bRightMousePressed && parentPart() != 0 && d->m_bBackRightClick )
{
popupMenu( d->m_strSelectedURL );
d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
d->m_bRightMousePressed = false;
}
DOM::DOMString url = event->url();
DOM::DOMString target = event->target();
DOM::Node innerNode = event->innerNode();
#ifndef QT_NO_DRAGANDDROP
if( d->m_bDnd && d->m_bMousePressed &&
( (!d->m_strSelectedURL.isEmpty() && !isEditable())
|| (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) ) ) {
if ( ( d->m_dragStartPos - _mouse->pos() ).manhattanLength() <= KGlobalSettings::dndEventDelay() )
return;
QPixmap pix;
HTMLImageElementImpl *img = 0L;
QDragObject *drag = 0;
KURL u;
// qDebug("****************** Event URL: %s", url.string().latin1());
// qDebug("****************** Event Target: %s", target.string().latin1());
// Normal image...
if ( url.length() == 0 && innerNode.handle() && innerNode.handle()->id() == ID_IMG )
{
img = static_cast<HTMLImageElementImpl *>(innerNode.handle());
u = KURL( completeURL( khtml::parseURL(img->getAttribute(ATTR_SRC)).string() ) );
pix = KMimeType::mimeType("image/png")->pixmap(KIcon::Desktop);
}
else
{
// Text or image link...
u = completeURL( d->m_strSelectedURL );
pix = KMimeType::pixmapForURL(u, 0, KIcon::Desktop, KIcon::SizeMedium);
}
u.setPass(QString::null);
KURLDrag* urlDrag = new KURLDrag( u, img ? 0 : d->m_view->viewport() );
if ( !d->m_referrer.isEmpty() )
urlDrag->metaData()["referrer"] = d->m_referrer;
if( img && img->complete()) {
KMultipleDrag *mdrag = new KMultipleDrag( d->m_view->viewport() );
mdrag->addDragObject( new QImageDrag( img->currentImage(), 0L ) );
mdrag->addDragObject( urlDrag );
drag = mdrag;
}
else
drag = urlDrag;
if ( !pix.isNull() )
drag->setPixmap( pix );
stopAutoScroll();
if(drag)
drag->drag();
// when we finish our drag, we need to undo our mouse press
d->m_bMousePressed = false;
d->m_strSelectedURL = d->m_strSelectedURLTarget = QString::null;
return;
}
#endif
// Not clicked -> mouse over stuff
if ( !d->m_bMousePressed )
{
// The mouse is over something
if ( url.length() )
{
bool shiftPressed = ( _mouse->state() & ShiftButton );
// Image map
if ( !innerNode.isNull() && innerNode.elementId() == ID_IMG )
{
HTMLImageElementImpl *i = static_cast<HTMLImageElementImpl *>(innerNode.handle());
if ( i && i->isServerMap() )
{
khtml::RenderObject *r = i->renderer();
if(r)
{
int absx, absy, vx, vy;
r->absolutePosition(absx, absy);
view()->contentsToViewport( absx, absy, vx, vy );
int x(_mouse->x() - vx), y(_mouse->y() - vy);
d->m_overURL = url.string() + QString("?%1,%2").arg(x).arg(y);
d->m_overURLTarget = target.string();
overURL( d->m_overURL, target.string(), shiftPressed );
return;
}
}
}
// normal link
if ( d->m_overURL.isEmpty() || d->m_overURL != url || d->m_overURLTarget != target )
{
d->m_overURL = url.string();
d->m_overURLTarget = target.string();
overURL( d->m_overURL, target.string(), shiftPressed );
}
}
else // Not over a link...
{
// reset to "default statusbar text"
resetHoverText();
}
}
else {
#ifndef KHTML_NO_SELECTION
// selection stuff
if( d->m_bMousePressed && innerNode.handle() && innerNode.handle()->renderer() &&
( (_mouse->state() & LeftButton) != 0 )) {
extendSelectionTo(event->x(), event->y(),
event->absX(), event->absY(), innerNode);
#else
if ( d->m_doc && d->m_view ) {
QPoint diff( _mouse->globalPos() - d->m_dragLastPos );
if ( abs( diff.x() ) > 64 || abs( diff.y() ) > 64 ) {
d->m_view->scrollBy( -diff.x(), -diff.y() );
d->m_dragLastPos = _mouse->globalPos();
}
#endif
}
}
}
void KHTMLPart::khtmlMouseReleaseEvent( khtml::MouseReleaseEvent *event )
{
DOM::Node innerNode = event->innerNode();
d->m_mousePressNode = DOM::Node();
if ( d->m_bMousePressed ) {
setStatusBarText(QString::null, BarHoverText);
stopAutoScroll();
}
// Used to prevent mouseMoveEvent from initiating a drag before
// the mouse is pressed again.
d->m_bMousePressed = false;
QMouseEvent *_mouse = event->qmouseEvent();
if ( _mouse->button() == RightButton && parentPart() != 0 && d->m_bBackRightClick )
{
d->m_bRightMousePressed = false;
KParts::BrowserInterface *tmp_iface = d->m_extension->browserInterface();
if( tmp_iface ) {
tmp_iface->callMethod( "goHistory(int)", -1 );
}
}
#ifndef QT_NO_CLIPBOARD
if ((d->m_guiProfile == BrowserViewGUI) && (_mouse->button() == MidButton) && (event->url().isNull())) {
kdDebug( 6050 ) << "KHTMLPart::khtmlMouseReleaseEvent() MMB shouldOpen="
<< d->m_bOpenMiddleClick << endl;
if (d->m_bOpenMiddleClick) {
KHTMLPart *p = this;
while (p->parentPart()) p = p->parentPart();
p->d->m_extension->pasteRequest();
}
}
#endif
#ifndef KHTML_NO_SELECTION
// delete selection in case start and end position are at the same point
if(d->m_selectionStart == d->m_selectionEnd && d->m_startOffset == d->m_endOffset) {
#ifndef KHTML_NO_CARET
d->m_extendAtEnd = true;
#else
d->m_selectionStart = 0;
d->m_selectionEnd = 0;
d->m_startOffset = 0;
d->m_endOffset = 0;
#endif
emitSelectionChanged();
} else {
// we have to get to know if end is before start or not...
// kdDebug(6000) << "rel: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << endl;
DOM::Node n = d->m_selectionStart;
d->m_startBeforeEnd = false;
if( d->m_selectionStart == d->m_selectionEnd ) {
if( d->m_startOffset < d->m_endOffset )
d->m_startBeforeEnd = true;
} else {
#if 0
while(!n.isNull()) {
if(n == d->m_selectionEnd) {
d->m_startBeforeEnd = true;
break;
}
DOM::Node next = n.firstChild();
if(next.isNull()) next = n.nextSibling();
while( next.isNull() && !n.parentNode().isNull() ) {
n = n.parentNode();
next = n.nextSibling();
}
n = next;
}
#else
// shouldn't be null but it can happen with dynamic updating of nodes
if (d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() ||
!d->m_selectionStart.handle()->renderer() ||
!d->m_selectionEnd.handle()->renderer()) return;
d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
d->m_selectionStart.handle(), d->m_startOffset,
d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
#endif
}
if(!d->m_startBeforeEnd)
{
DOM::Node tmpNode = d->m_selectionStart;
int tmpOffset = d->m_startOffset;
d->m_selectionStart = d->m_selectionEnd;
d->m_startOffset = d->m_endOffset;
d->m_selectionEnd = tmpNode;
d->m_endOffset = tmpOffset;
d->m_startBeforeEnd = true;
d->m_extendAtEnd = !d->m_extendAtEnd;
}
#ifndef KHTML_NO_CARET
bool v = d->m_view->placeCaret();
emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
#endif
// get selected text and paste to the clipboard
#ifndef QT_NO_CLIPBOARD
QString text = selectedText();
text.replace(QChar(0xa0), ' ');
disconnect( kapp->clipboard(), SIGNAL( selectionChanged()), this, SLOT( slotClearSelection()));
kapp->clipboard()->setText(text,QClipboard::Selection);
connect( kapp->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection()));
#endif
//kdDebug( 6000 ) << "selectedText = " << text << endl;
emitSelectionChanged();
//kdDebug(6000) << "rel2: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << "), caretOfs " << d->caretOffset() << endl;
}
#endif
d->m_initialNode = 0; // don't hold nodes longer than necessary
d->m_initialOffset = 0;
}
void KHTMLPart::khtmlDrawContentsEvent( khtml::DrawContentsEvent * )
{
}
void KHTMLPart::guiActivateEvent( KParts::GUIActivateEvent *event )
{
if ( event->activated() )
{
emitSelectionChanged();
emit d->m_extension->enableAction( "print", d->m_doc != 0 );
if ( !d->m_settings->autoLoadImages() && d->m_paLoadImages )
{
QPtrList<KAction> lst;
lst.append( d->m_paLoadImages );
plugActionList( "loadImages", lst );
}
}
}
void KHTMLPart::slotPrintFrame()
{
if ( d->m_frames.count() == 0 )
return;
KParts::ReadOnlyPart *frame = currentFrame();
if (!frame)
return;
KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject( frame );
if ( !ext )
return;
QMetaObject *mo = ext->metaObject();
int idx = mo->findSlot( "print()", true );
if ( idx >= 0 ) {
QUObject o[ 1 ];
ext->qt_invoke( idx, o );
}
}
void KHTMLPart::slotSelectAll()
{
KParts::ReadOnlyPart *part = currentFrame();
if (part && part->inherits("KHTMLPart"))
static_cast<KHTMLPart *>(part)->selectAll();
}
void KHTMLPart::startAutoScroll()
{
connect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
d->m_scrollTimer.start(100, false);
}
void KHTMLPart::stopAutoScroll()
{
disconnect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
if (d->m_scrollTimer.isActive())
d->m_scrollTimer.stop();
}
void KHTMLPart::slotAutoScroll()
{
if (d->m_view)
d->m_view->doAutoScroll();
else
stopAutoScroll(); // Safety
}
void KHTMLPart::runAdFilter()
{
if ( parentPart() )
parentPart()->runAdFilter();
if ( !d->m_doc )
return;
QPtrDictIterator<khtml::CachedObject> it( d->m_doc->docLoader()->m_docObjects );
for ( ; it.current(); ++it )
if ( it.current()->type() == khtml::CachedObject::Image ) {
khtml::CachedImage *image = static_cast<khtml::CachedImage *>(it.current());
bool wasBlocked = image->m_wasBlocked;
image->m_wasBlocked = KHTMLFactory::defaultHTMLSettings()->isAdFiltered( d->m_doc->completeURL( (*it).url().string() ) );
if ( image->m_wasBlocked != wasBlocked )
image->do_notify(image->pixmap(), image->valid_rect());
}
if ( KHTMLFactory::defaultHTMLSettings()->isHideAdsEnabled() ) {
for ( NodeImpl *nextNode, *node = d->m_doc; node; node = nextNode ) {
// We might be deleting 'node' shortly.
nextNode = node->traverseNextNode();
if ( node->id() == ID_IMG ||
node->id() == ID_IFRAME ||
(node->id() == ID_INPUT && static_cast<HTMLInputElementImpl *>(node)->inputType() == HTMLInputElementImpl::IMAGE ))
{
if ( KHTMLFactory::defaultHTMLSettings()->isAdFiltered( d->m_doc->completeURL( static_cast<ElementImpl *>(node)->getAttribute(ATTR_SRC).string() ) ) )
{
// We found an IMG, IFRAME or INPUT (of type IMAGE) matching a filter.
node->ref();
NodeImpl *parent = node->parent();
if( parent )
{
int exception = 0;
parent->removeChild(node, exception);
}
node->deref();
}
}
}
}
}
void KHTMLPart::selectAll()
{
if (!d->m_doc) return;
NodeImpl *first;
if (d->m_doc->isHTMLDocument())
first = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
else
first = d->m_doc;
NodeImpl *next;
// Look for first text/cdata node that has a renderer,
// or first childless replaced element
while ( first && !(first->renderer()
&& ((first->nodeType() == Node::TEXT_NODE || first->nodeType() == Node::CDATA_SECTION_NODE)
|| (first->renderer()->isReplaced() && !first->renderer()->firstChild()))))
{
next = first->firstChild();
if ( !next ) next = first->nextSibling();
while( first && !next )
{
first = first->parentNode();
if ( first )
next = first->nextSibling();
}
first = next;
}
NodeImpl *last;
if (d->m_doc->isHTMLDocument())
last = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
else
last = d->m_doc;
// Look for last text/cdata node that has a renderer,
// or last childless replaced element
// ### Instead of changing this loop, use findLastSelectableNode
// in render_table.cpp (LS)
while ( last && !(last->renderer()
&& ((last->nodeType() == Node::TEXT_NODE || last->nodeType() == Node::CDATA_SECTION_NODE)
|| (last->renderer()->isReplaced() && !last->renderer()->lastChild()))))
{
next = last->lastChild();
if ( !next ) next = last->previousSibling();
while ( last && !next )
{
last = last->parentNode();
if ( last )
next = last->previousSibling();
}
last = next;
}
if ( !first || !last )
return;
Q_ASSERT(first->renderer());
Q_ASSERT(last->renderer());
d->m_selectionStart = first;
d->m_startOffset = 0;
d->m_selectionEnd = last;
d->m_endOffset = last->nodeValue().length();
d->m_startBeforeEnd = true;
d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
d->m_selectionEnd.handle(), d->m_endOffset );
emitSelectionChanged();
}
bool KHTMLPart::checkLinkSecurity(const KURL &linkURL,const QString &message, const QString &button)
{
bool linkAllowed = true;
if ( d->m_doc )
linkAllowed = kapp && kapp->authorizeURLAction("redirect", url(), linkURL);
if ( !linkAllowed ) {
khtml::Tokenizer *tokenizer = d->m_doc->tokenizer();
if (tokenizer)
tokenizer->setOnHold(true);
int response = KMessageBox::Cancel;
if (!message.isEmpty())
{
response = KMessageBox::warningContinueCancel( 0,
message.arg(linkURL.htmlURL()),
i18n( "Security Warning" ),
button);
}
else
{
KMessageBox::error( 0,
i18n( "<qt>Access by untrusted page to<BR><B>%1</B><BR> denied.").arg(linkURL.htmlURL()),
i18n( "Security Alert" ));
}
if (tokenizer)
tokenizer->setOnHold(false);
return (response==KMessageBox::Continue);
}
return true;
}
void KHTMLPart::slotPartRemoved( KParts::Part *part )
{
// kdDebug(6050) << "KHTMLPart::slotPartRemoved " << part << endl;
if ( part == d->m_activeFrame )
{
d->m_activeFrame = 0L;
if ( !part->inherits( "KHTMLPart" ) )
{
if (factory()) {
factory()->removeClient( part );
}
if (childClients()->containsRef(part)) {
removeChildClient( part );
}
}
}
}
void KHTMLPart::slotActiveFrameChanged( KParts::Part *part )
{
// kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged this=" << this << "part=" << part << endl;
if ( part == this )
{
kdError(6050) << "strange error! we activated ourselves" << endl;
assert( false );
return;
}
// kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged d->m_activeFrame=" << d->m_activeFrame << endl;
if ( d->m_activeFrame && d->m_activeFrame->widget() && d->m_activeFrame->widget()->inherits( "QFrame" ) )
{
QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() );
if (frame->frameStyle() != QFrame::NoFrame)
{
frame->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken);
frame->repaint();
}
}
if( d->m_activeFrame && !d->m_activeFrame->inherits( "KHTMLPart" ) )
{
if (factory()) {
factory()->removeClient( d->m_activeFrame );
}
removeChildClient( d->m_activeFrame );
}
if( part && !part->inherits( "KHTMLPart" ) )
{
if (factory()) {
factory()->addClient( part );
}
insertChildClient( part );
}
d->m_activeFrame = part;
if ( d->m_activeFrame && d->m_activeFrame->widget()->inherits( "QFrame" ) )
{
QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() );
if (frame->frameStyle() != QFrame::NoFrame)
{
frame->setFrameStyle( QFrame::StyledPanel | QFrame::Plain);
frame->repaint();
}
kdDebug(6050) << "new active frame " << d->m_activeFrame << endl;
}
updateActions();
// (note: childObject returns 0 if the argument is 0)
d->m_extension->setExtensionProxy( KParts::BrowserExtension::childObject( d->m_activeFrame ) );
}
void KHTMLPart::setActiveNode(const DOM::Node &node)
{
if (!d->m_doc || !d->m_view)
return;
// Set the document's active node
d->m_doc->setFocusNode(node.handle());
// Scroll the view if necessary to ensure that the new focus node is visible
QRect rect = node.handle()->getRect();
d->m_view->ensureVisible(rect.right(), rect.bottom());
d->m_view->ensureVisible(rect.left(), rect.top());
}
DOM::Node KHTMLPart::activeNode() const
{
return DOM::Node(d->m_doc?d->m_doc->focusNode():0);
}
DOM::EventListener *KHTMLPart::createHTMLEventListener( QString code, QString name, NodeImpl* node )
{
KJSProxy *proxy = jScript();
if (!proxy)
return 0;
return proxy->createHTMLEventHandler( m_url.url(), name, code, node );
}
KHTMLPart *KHTMLPart::opener()
{
return d->m_opener;
}
void KHTMLPart::setOpener(KHTMLPart *_opener)
{
d->m_opener = _opener;
}
bool KHTMLPart::openedByJS()
{
return d->m_openedByJS;
}
void KHTMLPart::setOpenedByJS(bool _openedByJS)
{
d->m_openedByJS = _openedByJS;
}
void KHTMLPart::preloadStyleSheet(const QString &url, const QString &stylesheet)
{
khtml::Cache::preloadStyleSheet(url, stylesheet);
}
void KHTMLPart::preloadScript(const QString &url, const QString &script)
{
khtml::Cache::preloadScript(url, script);
}
QCString KHTMLPart::dcopObjectId() const
{
QCString id;
id.sprintf("html-widget%d", d->m_dcop_counter);
return id;
}
long KHTMLPart::cacheId() const
{
return d->m_cacheId;
}
bool KHTMLPart::restored() const
{
return d->m_restored;
}
bool KHTMLPart::pluginPageQuestionAsked(const QString& mimetype) const
{
// parentPart() should be const!
KHTMLPart* parent = const_cast<KHTMLPart *>(this)->parentPart();
if ( parent )
return parent->pluginPageQuestionAsked(mimetype);
return d->m_pluginPageQuestionAsked.contains(mimetype);
}
void KHTMLPart::setPluginPageQuestionAsked(const QString& mimetype)
{
if ( parentPart() )
parentPart()->setPluginPageQuestionAsked(mimetype);
d->m_pluginPageQuestionAsked.append(mimetype);
}
void KHTMLPart::slotAutomaticDetectionLanguage( int _id )
{
d->m_automaticDetection->setItemChecked( _id, true );
switch ( _id ) {
case 0 :
d->m_autoDetectLanguage = khtml::Decoder::SemiautomaticDetection;
break;
case 1 :
d->m_autoDetectLanguage = khtml::Decoder::Arabic;
break;
case 2 :
d->m_autoDetectLanguage = khtml::Decoder::Baltic;
break;
case 3 :
d->m_autoDetectLanguage = khtml::Decoder::CentralEuropean;
break;
case 4 :
d->m_autoDetectLanguage = khtml::Decoder::Chinese;
break;
case 5 :
d->m_autoDetectLanguage = khtml::Decoder::Greek;
break;
case 6 :
d->m_autoDetectLanguage = khtml::Decoder::Hebrew;
break;
case 7 :
d->m_autoDetectLanguage = khtml::Decoder::Japanese;
break;
case 8 :
d->m_autoDetectLanguage = khtml::Decoder::Korean;
break;
case 9 :
d->m_autoDetectLanguage = khtml::Decoder::Russian;
break;
case 10 :
d->m_autoDetectLanguage = khtml::Decoder::Thai;
break;
case 11 :
d->m_autoDetectLanguage = khtml::Decoder::Turkish;
break;
case 12 :
d->m_autoDetectLanguage = khtml::Decoder::Ukrainian;
break;
case 13 :
d->m_autoDetectLanguage = khtml::Decoder::Unicode;
break;
case 14 :
d->m_autoDetectLanguage = khtml::Decoder::WesternEuropean;
break;
default :
d->m_autoDetectLanguage = khtml::Decoder::SemiautomaticDetection;
break;
}
for ( int i = 0; i <= 14; ++i ) {
if ( i != _id )
d->m_automaticDetection->setItemChecked( i, false );
}
d->m_paSetEncoding->popupMenu()->setItemChecked( 0, true );
setEncoding( QString::null, false );
if( d->m_manualDetection )
d->m_manualDetection->setCurrentItem( -1 );
d->m_paSetEncoding->popupMenu()->setItemChecked( d->m_paSetEncoding->popupMenu()->idAt( 2 ), false );
}
khtml::Decoder *KHTMLPart::createDecoder()
{
khtml::Decoder *dec = new khtml::Decoder();
if( !d->m_encoding.isNull() )
dec->setEncoding( d->m_encoding.latin1(),
d->m_haveEncoding ? khtml::Decoder::UserChosenEncoding : khtml::Decoder::EncodingFromHTTPHeader);
else {
// Inherit the default encoding from the parent frame if there is one.
const char *defaultEncoding = (parentPart() && parentPart()->d->m_decoder)
? parentPart()->d->m_decoder->encoding() : settings()->encoding().latin1();
dec->setEncoding(defaultEncoding, khtml::Decoder::DefaultEncoding);
}
#ifdef APPLE_CHANGES
if (d->m_doc)
d->m_doc->setDecoder(d->m_decoder);
#endif
dec->setAutoDetectLanguage( d->m_autoDetectLanguage );
return dec;
}
void KHTMLPart::emitCaretPositionChanged(const DOM::Node &node, long offset) {
emit caretPositionChanged(node, offset);
}
void KHTMLPart::restoreScrollPosition()
{
KParts::URLArgs args = d->m_extension->urlArgs();
if ( m_url.hasRef() && !d->m_restoreScrollPosition && !args.reload) {
if ( !d->m_doc || !d->m_doc->parsing() )
disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
if ( !gotoAnchor(m_url.encodedHtmlRef()) )
gotoAnchor(m_url.htmlRef());
return;
}
// Check whether the viewport has become large enough to encompass the stored
// offsets. If the document has been fully loaded, force the new coordinates,
// even if the canvas is too short (can happen when user resizes the window
// during loading).
if (d->m_view->contentsHeight() - d->m_view->visibleHeight() >= args.yOffset
|| d->m_bComplete) {
d->m_view->setContentsPos(args.xOffset, args.yOffset);
disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
}
}
void KHTMLPart::openWallet(DOM::HTMLFormElementImpl *form)
{
#ifndef KHTML_NO_WALLET
KHTMLPart *p;
for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
}
if (p) {
p->openWallet(form);
return;
}
if (onlyLocalReferences()) { // avoid triggering on local apps, thumbnails
return;
}
if (d->m_wallet) {
if (d->m_bWalletOpened) {
if (d->m_wallet->isOpen()) {
form->walletOpened(d->m_wallet);
return;
}
d->m_wallet->deleteLater();
d->m_wallet = 0L;
d->m_bWalletOpened = false;
}
}
if (!d->m_wq) {
KWallet::Wallet *wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0, KWallet::Wallet::Asynchronous);
d->m_wq = new KHTMLWalletQueue(this);
d->m_wq->wallet = wallet;
connect(wallet, SIGNAL(walletOpened(bool)), d->m_wq, SLOT(walletOpened(bool)));
connect(d->m_wq, SIGNAL(walletOpened(KWallet::Wallet*)), this, SLOT(walletOpened(KWallet::Wallet*)));
}
assert(form);
d->m_wq->callers.append(KHTMLWalletQueue::Caller(form, form->getDocument()));
#endif // KHTML_NO_WALLET
}
void KHTMLPart::saveToWallet(const QString& key, const QMap<QString,QString>& data)
{
#ifndef KHTML_NO_WALLET
KHTMLPart *p;
for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
}
if (p) {
p->saveToWallet(key, data);
return;
}
if (d->m_wallet) {
if (d->m_bWalletOpened) {
if (d->m_wallet->isOpen()) {
if (!d->m_wallet->hasFolder(KWallet::Wallet::FormDataFolder())) {
d->m_wallet->createFolder(KWallet::Wallet::FormDataFolder());
}
d->m_wallet->setFolder(KWallet::Wallet::FormDataFolder());
d->m_wallet->writeMap(key, data);
return;
}
d->m_wallet->deleteLater();
d->m_wallet = 0L;
d->m_bWalletOpened = false;
}
}
if (!d->m_wq) {
KWallet::Wallet *wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0, KWallet::Wallet::Asynchronous);
d->m_wq = new KHTMLWalletQueue(this);
d->m_wq->wallet = wallet;
connect(wallet, SIGNAL(walletOpened(bool)), d->m_wq, SLOT(walletOpened(bool)));
connect(d->m_wq, SIGNAL(walletOpened(KWallet::Wallet*)), this, SLOT(walletOpened(KWallet::Wallet*)));
}
d->m_wq->savers.append(qMakePair(key, data));
#endif // KHTML_NO_WALLET
}
void KHTMLPart::dequeueWallet(DOM::HTMLFormElementImpl *form) {
#ifndef KHTML_NO_WALLET
KHTMLPart *p;
for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
}
if (p) {
p->dequeueWallet(form);
return;
}
if (d->m_wq) {
d->m_wq->callers.remove(KHTMLWalletQueue::Caller(form, form->getDocument()));
}
#endif // KHTML_NO_WALLET
}
void KHTMLPart::walletOpened(KWallet::Wallet *wallet) {
#ifndef KHTML_NO_WALLET
assert(!d->m_wallet);
assert(d->m_wq);
d->m_wq->deleteLater(); // safe?
d->m_wq = 0L;
if (!wallet) {
d->m_bWalletOpened = false;
return;
}
d->m_wallet = wallet;
d->m_bWalletOpened = true;
connect(d->m_wallet, SIGNAL(walletClosed()), SLOT(slotWalletClosed()));
if (!d->m_statusBarWalletLabel) {
d->m_statusBarWalletLabel = new KURLLabel(d->m_statusBarExtension->statusBar());
d->m_statusBarWalletLabel->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small));
d->m_statusBarWalletLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
d->m_statusBarWalletLabel->setUseCursor(false);
d->m_statusBarExtension->addStatusBarItem(d->m_statusBarWalletLabel, 0, false);
d->m_statusBarWalletLabel->setPixmap(SmallIcon("wallet_open", instance()));
connect(d->m_statusBarWalletLabel, SIGNAL(leftClickedURL()), SLOT(launchWalletManager()));
connect(d->m_statusBarWalletLabel, SIGNAL(rightClickedURL()), SLOT(walletMenu()));
} else {
QToolTip::remove(d->m_statusBarWalletLabel);
}
QToolTip::add(d->m_statusBarWalletLabel, i18n("The wallet '%1' is open and being used for form data and passwords.").arg(KWallet::Wallet::NetworkWallet()));
#endif // KHTML_NO_WALLET
}
KWallet::Wallet *KHTMLPart::wallet()
{
#ifndef KHTML_NO_WALLET
KHTMLPart *p;
for (p = parentPart(); p && p->parentPart(); p = p->parentPart())
;
if (p)
return p->wallet();
#endif // KHTML_NO_WALLET
return d->m_wallet;
}
void KHTMLPart::slotWalletClosed()
{
#ifndef KHTML_NO_WALLET
if (d->m_wallet) {
d->m_wallet->deleteLater();
d->m_wallet = 0L;
}
d->m_bWalletOpened = false;
if (d->m_statusBarWalletLabel) {
d->m_statusBarExtension->removeStatusBarItem(d->m_statusBarWalletLabel);
delete d->m_statusBarWalletLabel;
d->m_statusBarWalletLabel = 0L;
}
#endif // KHTML_NO_WALLET
}
void KHTMLPart::launchWalletManager()
{
#ifndef KHTML_NO_WALLET
if (!DCOPClient::mainClient()->isApplicationRegistered("kwalletmanager")) {
KApplication::startServiceByDesktopName("kwalletmanager_show");
} else {
DCOPRef r("kwalletmanager", "kwalletmanager-mainwindow#1");
r.send("show");
r.send("raise");
}
#endif // KHTML_NO_WALLET
}
void KHTMLPart::walletMenu()
{
#ifndef KHTML_NO_WALLET
KPopupMenu *m = new KPopupMenu(0L);
m->insertItem(i18n("&Close Wallet"), this, SLOT(slotWalletClosed()));
m->popup(QCursor::pos());
#endif // KHTML_NO_WALLET
}
void KHTMLPart::slotToggleCaretMode()
{
setCaretMode(d->m_paToggleCaretMode->isChecked());
}
void KHTMLPart::setFormNotification(KHTMLPart::FormNotification fn) {
d->m_formNotification = fn;
}
KHTMLPart::FormNotification KHTMLPart::formNotification() const {
return d->m_formNotification;
}
KURL KHTMLPart::toplevelURL()
{
KHTMLPart* part = this;
while (part->parentPart())
part = part->parentPart();
if (!part)
return KURL();
return part->url();
}
bool KHTMLPart::isModified() const
{
if ( !d->m_doc )
return false;
return d->m_doc->unsubmittedFormChanges();
}
void KHTMLPart::setDebugScript( bool enable )
{
unplugActionList( "debugScriptList" );
if ( enable ) {
if (!d->m_paDebugScript) {
d->m_paDebugScript = new KAction( i18n( "JavaScript &Debugger" ), 0, this, SLOT( slotDebugScript() ), actionCollection(), "debugScript" );
}
d->m_paDebugScript->setEnabled( d->m_frame ? d->m_frame->m_jscript : 0L );
QPtrList<KAction> lst;
lst.append( d->m_paDebugScript );
plugActionList( "debugScriptList", lst );
}
d->m_bJScriptDebugEnabled = enable;
}
void KHTMLPart::setSuppressedPopupIndicator( bool enable )
{
setSuppressedPopupIndicator( enable, 0 );
}
void KHTMLPart::setSuppressedPopupIndicator( bool enable, KHTMLPart *originPart )
{
if ( parentPart() ) {
parentPart()->setSuppressedPopupIndicator( enable, originPart );
return;
}
if ( enable && originPart ) {
d->m_openableSuppressedPopups++;
if ( d->m_suppressedPopupOriginParts.findIndex( originPart ) == -1 )
d->m_suppressedPopupOriginParts.append( originPart );
}
if ( enable && !d->m_statusBarPopupLabel ) {
d->m_statusBarPopupLabel = new KURLLabel( d->m_statusBarExtension->statusBar() );
d->m_statusBarPopupLabel->setFixedHeight( instance()->iconLoader()->currentSize( KIcon::Small) );
d->m_statusBarPopupLabel->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ));
d->m_statusBarPopupLabel->setUseCursor( false );
d->m_statusBarExtension->addStatusBarItem( d->m_statusBarPopupLabel, 0, false );
d->m_statusBarPopupLabel->setPixmap( SmallIcon( "window_suppressed", instance() ) );
QToolTip::add( d->m_statusBarPopupLabel, i18n("This page was prevented from opening a new window via JavaScript." ) );
connect(d->m_statusBarPopupLabel, SIGNAL(leftClickedURL()), SLOT(suppressedPopupMenu()));
if (d->m_settings->jsPopupBlockerPassivePopup()) {
QPixmap px;
px = MainBarIcon( "window_suppressed" );
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);
}
} else if ( !enable && d->m_statusBarPopupLabel ) {
QToolTip::remove( d->m_statusBarPopupLabel );
d->m_statusBarExtension->removeStatusBarItem( d->m_statusBarPopupLabel );
delete d->m_statusBarPopupLabel;
d->m_statusBarPopupLabel = 0L;
}
}
void KHTMLPart::suppressedPopupMenu() {
KPopupMenu *m = new KPopupMenu(0L);
m->setCheckable(true);
if ( d->m_openableSuppressedPopups )
m->insertItem(i18n("&Show Blocked Popup Window","Show %n Blocked Popup Windows", d->m_openableSuppressedPopups), this, SLOT(showSuppressedPopups()));
m->insertItem(i18n("Show Blocked Window Passive Popup &Notification"), this, SLOT(togglePopupPassivePopup()),0,57);
m->setItemChecked(57,d->m_settings->jsPopupBlockerPassivePopup());
m->insertItem(i18n("&Configure JavaScript New Window Policies..."), this, SLOT(launchJSConfigDialog()));
m->popup(QCursor::pos());
}
void KHTMLPart::togglePopupPassivePopup() {
// Same hack as in disableJSErrorExtension()
d->m_settings->setJSPopupBlockerPassivePopup( !d->m_settings->jsPopupBlockerPassivePopup() );
DCOPClient::mainClient()->send("konqueror*", "KonquerorIface", "reparseConfiguration()", QByteArray());
}
void KHTMLPart::showSuppressedPopups() {
for ( QValueListIterator<QGuardedPtr<KHTMLPart> > i = d->m_suppressedPopupOriginParts.begin();
i != d->m_suppressedPopupOriginParts.end(); ++i ) {
if (KHTMLPart* part = *i) {
KJS::Window *w = KJS::Window::retrieveWindow( part );
if (w) {
w->showSuppressedWindows();
w->forgetSuppressedWindows();
}
}
}
setSuppressedPopupIndicator( false );
d->m_openableSuppressedPopups = 0;
d->m_suppressedPopupOriginParts.clear();
}
// Extension to use for "view document source", "save as" etc.
// Using the right extension can help the viewer get into the right mode (#40496)
QString KHTMLPart::defaultExtension() const
{
if ( !d->m_doc )
return ".html";
if ( !d->m_doc->isHTMLDocument() )
return ".xml";
return d->m_doc->htmlMode() == DOM::DocumentImpl::XHtml ? ".xhtml" : ".html";
}
bool KHTMLPart::inProgress() const
{
if (d->m_runningScripts || (d->m_doc && d->m_doc->parsing()))
return true;
// Any frame that hasn't completed yet ?
ConstFrameIt it = d->m_frames.begin();
const ConstFrameIt end = d->m_frames.end();
for (; it != end; ++it ) {
if ((*it)->m_run || !(*it)->m_bCompleted)
return true;
}
return d->m_submitForm || !d->m_redirectURL.isEmpty() || d->m_redirectionTimer.isActive() || d->m_job;
}
using namespace KParts;
#include "khtml_part.moc"
#include "khtmlpart_p.moc"
KHTMLPart::findTextBegin
void findTextBegin()
Initiates a text search.
Definition: khtml_part.cpp:2734
KHTMLPart::findFramePart
KParts::ReadOnlyPart * findFramePart(const QString &f)
Finds a frame by name.
Definition: khtml_part.cpp:5267
KHTMLSettings
Settings for the HTML view.
Definition: khtml_settings.h:38
KStdAccel::next
const KShortcut & next()
KParts::BrowserExtension
KHTMLPart::khtmlDrawContentsEvent
virtual void khtmlDrawContentsEvent(khtml::DrawContentsEvent *)
Eventhandler for the khtml::DrawContentsEvent.
Definition: khtml_part.cpp:6627
KHTMLPart::hide
void hide()
Convenience method to hide the document's view.
Definition: khtml_part.cpp:5633
KStdAction::saveAs
KAction * saveAs(const QObject *recvr, const char *slot, KActionCollection *parent, const char *name=0)
KHTMLPart::metaRefreshEnabled
bool metaRefreshEnabled() const
Returns true if automatic forwarding is enabled.
Definition: khtml_part.cpp:954
KHTMLPart::setSelection
void setSelection(const DOM::Range &)
Sets the current selection.
Definition: khtml_part.cpp:3665
KURL
KHTMLPart::documentSource
QString documentSource() const
Returns the content of the source document.
Definition: khtml_part.cpp:865
KParts::URLArgs::frameName
QString frameName
KHTMLPart::begin
virtual void begin(const KURL &url=KURL(), int xOffset=0, int yOffset=0)
Clears the widget and prepares it for new content.
Definition: khtml_part.cpp:1872
KHTMLPart::nextAnchor
bool nextAnchor()
Go to the next anchor.
Definition: khtml_part.cpp:2566
KHTMLPart::referrer
QString referrer() const
Referrer used for links in this page.
Definition: khtml_part.cpp:5804
KApplication::kdeinitExec
static int kdeinitExec(const QString &name, const QStringList &args, QString *error, int *pid, const QCString &startup_id)
KParts::BrowserRun::askEmbedOrSave
static AskSaveResult askEmbedOrSave(const KURL &url, const QString &mimeType, const QString &suggestedFilename=QString::null, int flags=0)
locate
QString locate(const char *type, const QString &filename, const KInstance *instance=KGlobal::instance())
KLibFactory
KHTMLPageCache::fetchData
void fetchData(long id, QObject *recvObj, const char *recvSlot)
Fetch data for cache entry id and send it to slot recvSlot in the object recvObj. ...
Definition: khtml_pagecache.cpp:200
KURL::hasRef
bool hasRef() const
KURL::hasSubURL
bool hasSubURL() const
KHTMLPartIface
DCOP interface for KHTML.
Definition: khtml_iface.h:32
KParts::URLArgs::setContentType
void setContentType(const QString &contentType)
KParts::ReadOnlyPart::m_url
KURL m_url
KHTMLPart::urlCursor
QCursor urlCursor() const
Returns the cursor which is used when the cursor is on a link.
Definition: khtml_part.cpp:2599
KParts::WindowArgs
KGlobal::locale
static KLocale * locale()
DOM::Node
The Node interface is the primary datatype for the entire Document Object Model.
Definition: dom_node.h:274
KURL::setPass
void setPass(const QString &_txt)
DOM::Node::nodeName
DOMString nodeName() const
The name of this node, depending on its type; see the table above.
Definition: dom_node.cpp:176
KHTMLPart::autoloadImages
bool autoloadImages() const
Returns whether images contained in the document are loaded automatically or not. ...
KHTMLPart::createJavaContext
KJavaAppletContext * createJavaContext()
Returns the java context of the applets.
Definition: khtml_part.cpp:1269
KHTMLPart::doOpenStream
virtual bool doOpenStream(const QString &mimeType)
Implements the streaming API of KParts::ReadOnlyPart.
Definition: khtml_part.cpp:2022
KXMLGUIClient
DOM::HTMLDocument
An HTMLDocument is the root of the HTML hierarchy and holds the entire content.
Definition: html_document.h:73
KHTMLPageCache::self
static KHTMLPageCache * self()
static "constructor".
Definition: khtml_pagecache.cpp:121
KHTMLPart::lastModified
QString lastModified() const
Last-modified date (in raw string format), if received in the [HTTP] headers.
Definition: khtml_part.cpp:5830
KHTMLPart::restoreState
virtual void restoreState(QDataStream &stream)
Restores the KHTMLPart's previously saved state (including child frame objects) from the provided QDa...
Definition: khtml_part.cpp:5441
KURLLabel
KURL::prettyURL
QString prettyURL(int _trailing=0) const
KURL::query
QString query() const
KHTMLPart::pluginsEnabled
bool pluginsEnabled() const
Returns true if plugins are enabled/disabled.
KHTMLPart::javaContext
KJavaAppletContext * javaContext()
Returns the java context of the applets.
Definition: khtml_part.cpp:1264
KParts::BrowserInterface
KStdAction::selectAll
KAction * selectAll(const QObject *recvr, const char *slot, KActionCollection *parent, const char *name=0)
KGlobal::charsets
static KCharsets * charsets()
KHTMLPart::setJSStatusBarText
void setJSStatusBarText(const QString &text)
Called by KJS.
Definition: khtml_part.cpp:5784
KHTMLPart::onlyLocalReferences
bool onlyLocalReferences() const
Returns whether only file:/ or data:/ references are allowed to be loaded ( default false )...
Definition: khtml_part.cpp:2604
KIcon::Small
KParts::URLArgs::metaData
QMap< QString, QString > & metaData()
KParts::ReadOnlyPart::completed
void completed()
KURL::setQuery
void setQuery(const QString &_txt, int encoding_hint=0)
KMultipleDrag::addDragObject
void addDragObject(QDragObject *dragObject)
kdError
kdbgstream kdError(int area=0)
KHTMLPart::toplevelURL
KURL toplevelURL()
Returns the toplevel (origin) URL of this document, even if this part is a frame or an iframe...
Definition: khtml_part.cpp:7333
KHTMLPart::frameExists
bool frameExists(const QString &frameName)
Returns whether a frame with the specified name is exists or not.
Definition: khtml_part.cpp:5288
KParts::PartManager::removePart
virtual void removePart(Part *part)
KStringHandler::rsqueeze
static QString rsqueeze(const QString &str, uint maxlen=40)
KURL::url
QString url(int _trailing=0, int encoding_hint=0) const
KHTMLPart
This class is khtml's main class.
Definition: khtml_part.h:184
KHTMLPart::setPluginsEnabled
void setPluginsEnabled(bool enable)
Enables or disables plugins, default is enabled.
Definition: khtml_part.cpp:1274
KURL::encode_string
static QString encode_string(const QString &str, int encoding_hint=0)
KConfig::hasGroup
bool hasGroup(const QString &group) const
KHTMLPart::openURL
virtual bool openURL(const KURL &url)
Opens the specified URL url.
Definition: khtml_part.cpp:566
KHTMLPart::saveState
virtual void saveState(QDataStream &stream)
Saves the KHTMLPart's complete state (including child frame objects) to the provided QDataStream...
Definition: khtml_part.cpp:5355
KHTMLPart::showError
virtual void showError(KIO::Job *job)
Called when a certain error situation (i.e.
Definition: khtml_part.cpp:1699
KHTMLView
Renders and displays HTML in a QScrollView.
Definition: khtmlview.h:78
KParts::Part::widget
virtual QWidget * widget()
KLibLoader::lastErrorMessage
QString lastErrorMessage() const
DOM::Node::attributes
NamedNodeMap attributes() const
A NamedNodeMap containing the attributes of this node (if it is an Element ) or null otherwise...
Definition: dom_node.cpp:241
KHTMLPart::activeNode
DOM::Node activeNode() const
Returns the node that has the keyboard focus.
Definition: khtml_part.cpp:6933
KHTMLPart::selection
DOM::Range selection() const
Returns the selected part of the HTML.
Definition: khtml_part.cpp:3603
kdDebug
kdbgstream kdDebug(int area=0)
KLocale::removeCatalogue
void removeCatalogue(const QString &catalog)
KParts::Part
KURL::host
QString host() const
KParts::URLArgs::setDoPost
void setDoPost(bool enable)
KConfig::sync
virtual void sync()
klocale.h
DOM::Document::createRange
Range createRange()
Introduced in DOM Level 2 This method is from the DocumentRange interface.
Definition: dom_doc.cpp:352
KHTMLPart::setCaretMode
void setCaretMode(bool enable)
Enables/disables caret mode.
Definition: khtml_part.cpp:2642
KURL::isEmpty
bool isEmpty() const
KParts::ReadOnlyPart::started
void started(KIO::Job *)
KHTMLPart::selectionChanged
void selectionChanged()
This signal is emitted when the selection changes.
KHTMLPart::setEncoding
bool setEncoding(const QString &name, bool override=false)
Sets the encoding the page uses.
Definition: khtml_part.cpp:2464
KHTMLPart::khtmlMouseReleaseEvent
virtual void khtmlMouseReleaseEvent(khtml::MouseReleaseEvent *event)
Eventhandler for the khtml::MouseMouseReleaseEvent.
Definition: khtml_part.cpp:6513
KHTMLPart::nodeUnderMouse
DOM::Node nodeUnderMouse() const
Returns the Node currently under the mouse.
Definition: khtml_part.cpp:5639
KHTMLPart::setOnlyLocalReferences
void setOnlyLocalReferences(bool enable)
Security option.
Definition: khtml_part.cpp:2609
KHTMLPageCache::isComplete
bool isComplete(long id)
Definition: khtml_pagecache.cpp:191
KCharsets::encodingForName
QString encodingForName(const QString &descriptiveName)
KHTMLPart::formNotification
FormNotification formNotification() const
Determine if signal should be emitted before, instead or never when a submitForm() happens...
Definition: khtml_part.cpp:7329
KShortcut
KHTMLPart::formSubmitNotification
void formSubmitNotification(const char *action, const QString &url, const QByteArray &formData, const QString &target, const QString &contentType, const QString &boundary)
If form notification is on, this will be emitted either for a form submit or before the form submit a...
KHTMLPart::onURL
void onURL(const QString &url)
Emitted if the cursor is moved over an URL.
KSelectAction
KHTMLPart::view
KHTMLView * view() const
Returns a pointer to the HTML document's view.
Definition: khtml_part.cpp:907
KStringHandler::csqueeze
static QString csqueeze(const QString &str, uint maxlen=40)
KURL::htmlURL
QString htmlURL() const
KHTMLPart::statusMessagesEnabled
bool statusMessagesEnabled() const
Returns true if status messages are enabled.
Definition: khtml_part.cpp:926
KURL::protocol
QString protocol() const
KHTMLPart::completeURL
KURL completeURL(const QString &url)
returns a KURL object for the given url.
Definition: khtml_part.cpp:2368
KIcon::Desktop
KHTMLPart::setCaretVisible
void setCaretVisible(bool show)
Sets the visibility of the caret.
Definition: khtml_part.cpp:2715
KHTMLPart::setMetaRefreshEnabled
void setMetaRefreshEnabled(bool enable)
Enable/disable automatic forwarding by
Definition: khtml_part.cpp:949
KHTMLPart::closeURL
virtual bool closeURL()
Stops loading the document and kills all data requests (for images, etc.)
Definition: khtml_part.cpp:770
KHTMLPart::paint
void paint(QPainter *, const QRect &, int=0, bool *=0)
Paints the HTML page to a QPainter.
Definition: khtml_part.cpp:2046
KHTMLPart::htmlError
void htmlError(int errorCode, const QString &text, const KURL &reqUrl)
presents a detailed error message to the user.
Definition: khtml_part.cpp:1716
KHTMLPart::framejScript
KJSProxy * framejScript(KParts::ReadOnlyPart *framePart)
Returns child frame framePart its script interpreter.
Definition: khtml_part.cpp:5300
KIcon::SizeMedium
DOM::Node::parentNode
Node parentNode() const
The parent of this node.
Definition: dom_node.cpp:205
KHTMLPart::khtmlMousePressEvent
virtual void khtmlMousePressEvent(khtml::MousePressEvent *event)
Eventhandler of the khtml::MousePressEvent.
Definition: khtml_part.cpp:6044
KParts::ReadOnlyPart::canceled
void canceled(const QString &errMsg)
KParts::LiveConnectExtension
KHTMLPart::setURLCursor
void setURLCursor(const QCursor &c)
Sets the cursor to use when the cursor is on a link.
Definition: khtml_part.cpp:2594
KHTMLPart::jsDefaultStatusBarText
QString jsDefaultStatusBarText() const
Called by KJS.
Definition: khtml_part.cpp:5799
KGuiItem
KParts::URLArgs::setForcesNewWindow
void setForcesNewWindow(bool forcesNewWindow)
KHTMLPart::setCaretPosition
void setCaretPosition(DOM::Node node, long offset, bool extendSelection=false)
Sets the caret to the given position.
Definition: khtml_part.cpp:2685
KLibrary::unload
void unload() const
KHTMLPart::browserExtension
KParts::BrowserExtension * browserExtension() const
Returns a pointer to the KParts::BrowserExtension.
Definition: khtml_part.cpp:897
KParts::BrowserExtension::childObject
static BrowserExtension * childObject(QObject *obj)
KHTMLPart::pageReferrer
QString pageReferrer() const
Referrer used to obtain this page.
Definition: khtml_part.cpp:5809
KURL::isLocalFile
bool isLocalFile() const
KParts::URLArgs::setLockHistory
void setLockHistory(bool lock)
KHTMLPart::~KHTMLPart
virtual ~KHTMLPart()
Destructor.
Definition: khtml_part.cpp:468
KHTMLPart::preloadScript
void preloadScript(const QString &url, const QString &script)
Loads a script into the script cache.
Definition: khtml_part.cpp:6973
kdWarning
kdbgstream kdWarning(int area=0)
KParts::ReadOnlyPart::url
KURL url() const
KLocale::formatDateTime
QString formatDateTime(const QDateTime &pDateTime, bool shortFormat=true, bool includeSecs=false) const
KLibrary
KHTMLPageCache::cancelFetch
void cancelFetch(QObject *recvObj)
Cancel sending data to recvObj.
Definition: khtml_pagecache.cpp:218
DOM::Node::isNull
bool isNull() const
tests if this Node is 0.
Definition: dom_node.h:892
DOM::DOMString
This class implements the basic string we use in the DOM.
Definition: dom_string.h:43
KCharsets::descriptiveEncodingNames
QStringList descriptiveEncodingNames()
KHTMLPart::gotoAnchor
bool gotoAnchor(const QString &name)
Finds the anchor named name.
Definition: khtml_part.cpp:2518
KHTMLPart::selectedTextAsHTML
QString selectedTextAsHTML() const
Return the text the user has marked.
Definition: khtml_part.cpp:3434
DOM::Node::nodeValue
DOMString nodeValue() const
The value of this node, depending on its type; see the table above.
Definition: dom_node.cpp:182
KHTMLPart::setJavaEnabled
void setJavaEnabled(bool enable)
Enables/disables Java applet support.
Definition: khtml_part.cpp:1245
KHTMLPart::partManager
KParts::PartManager * partManager()
Returns a reference to the partmanager instance which manages html frame objects. ...
Definition: khtml_part.cpp:4700
DOM::Document
The Document interface represents the entire HTML or XML document.
Definition: dom_doc.h:245
KHTMLPart::doWriteStream
virtual bool doWriteStream(const QByteArray &data)
Implements the streaming API of KParts::ReadOnlyPart.
Definition: khtml_part.cpp:2033
KMessageBox::error
static void error(QWidget *parent, const QString &text, const QString &caption=QString::null, int options=Notify)
KHTMLPart::findFrame
KHTMLPart * findFrame(const QString &f)
Finds a frame by name.
Definition: khtml_part.cpp:5254
KHTMLPart::setFixedFont
void setFixedFont(const QString &name)
Sets the fixed font style.
Definition: khtml_part.cpp:2589
KHTMLPart::khtmlMouseMoveEvent
virtual void khtmlMouseMoveEvent(khtml::MouseMoveEvent *event)
Eventhandler for the khtml::MouseMouseMoveEvent.
Definition: khtml_part.cpp:6374
KParts::URLArgs::reload
bool reload
KConfigGroupSaver
KParts::BrowserInterface::callMethod
void callMethod(const char *name, const QVariant &argument)
KMessageBox::warningContinueCancel
static int warningContinueCancel(QWidget *parent, const QString &text, const QString &caption=QString::null, const KGuiItem &buttonContinue=KStdGuiItem::cont(), const QString &dontAskAgainName=QString::null, int options=Notify)
KHTMLPart::openFile
virtual bool openFile()
Internal empty reimplementation of KParts::ReadOnlyPart::openFile .
Definition: khtml_part.cpp:1495
KHTMLPart::write
virtual void write(const char *str, int len=-1)
Writes another part of the HTML code to the widget.
Definition: khtml_part.cpp:1960
KHTMLPart::scheduleRedirection
void scheduleRedirection(int delay, const QString &url, bool lockHistory=true)
Schedules a redirection after delay seconds.
Definition: khtml_part.cpp:2380
KHTMLPageCache::cancelEntry
void cancelEntry(long id)
Cancel the entry.
Definition: khtml_pagecache.cpp:174
KHTMLPart::setActiveNode
void setActiveNode(const DOM::Node &node)
Sets the focused node of the document to the specified node.
Definition: khtml_part.cpp:6919
KParts::GUIActivateEvent
KURL::fileName
QString fileName(bool _ignore_trailing_slash_in_path=true) const
KHTMLPart::guiActivateEvent
virtual void guiActivateEvent(KParts::GUIActivateEvent *event)
Internal reimplementation of KParts::Part::guiActivateEvent .
Definition: khtml_part.cpp:6631
KParts::PartManager::activePart
virtual Part * activePart() const
KHTMLPart::prevAnchor
bool prevAnchor()
Go to previous anchor.
Definition: khtml_part.cpp:2575
KHTMLPart::setUserStyleSheet
void setUserStyleSheet(const KURL &url)
Sets a user defined style sheet to be used on top of the HTML 4 default style sheet.
Definition: khtml_part.cpp:2506
KURL::encodedHtmlRef
QString encodedHtmlRef() const
KMessageBox::information
static void information(QWidget *parent, const QString &text, const QString &caption=QString::null, const QString &dontShowAgainName=QString::null, int options=Notify)
KURLDrag::metaData
QMap< QString, QString > & metaData()
KHTMLPart::KHTMLPart
KHTMLPart(QWidget *parentWidget=0, const char *widgetname=0, QObject *parent=0, const char *name=0, GUIProfile prof=DefaultGUI)
Constructs a new KHTMLPart.
Definition: khtml_part.cpp:206
KParts::StatusBarExtension
KHTMLPart::setFormNotification
void setFormNotification(FormNotification fn)
Determine if signal should be emitted before, instead or never when a submitForm() happens...
Definition: khtml_part.cpp:7325
KGlobalSettings::showIconsOnPushButtons
static bool showIconsOnPushButtons()
KURL::setPath
void setPath(const QString &path)
KParts::BrowserHostExtension
KHTMLPart::setStatusMessagesEnabled
void setStatusMessagesEnabled(bool enable)
Enable/disable statusbar messages.
Definition: khtml_part.cpp:912
KHTMLPart::setStandardFont
void setStandardFont(const QString &name)
Sets the standard font style.
Definition: khtml_part.cpp:2584
KLibLoader::library
virtual KLibrary * library(const char *libname)
KParts::URLArgs
KHTMLPart::backgroundURL
KURL backgroundURL() const
Returns the URL for the background Image (used by save background)
Definition: khtml_part.cpp:4114
DOM::Node::firstChild
Node firstChild() const
The first child of this node.
Definition: dom_node.cpp:217
KTempFile
KConfig::deleteEntry
void deleteEntry(const QString &pKey, bool bNLS=false, bool bGlobal=false)
KHTMLPart::jsStatusBarText
QString jsStatusBarText() const
Called by KJS.
Definition: khtml_part.cpp:5794
KApplication::startServiceByDesktopName
static int startServiceByDesktopName(const QString &_name, const QString &URL, QString *error=0, QCString *dcopService=0, int *pid=0, const QCString &startup_id="", bool noWait=false)
KHTMLPart::findFrameParent
KHTMLPart * findFrameParent(KParts::ReadOnlyPart *callingPart, const QString &f, khtml::ChildFrame **childFrame=0)
Recursively finds the part containing the frame with name f and checks if it is accessible by calling...
Definition: khtml_part.cpp:5212
KHTMLPart::caretPositionChanged
void caretPositionChanged(const DOM::Node &node, long offset)
This signal is emitted whenever the caret position has been changed.
KParts::Part::setWidget
virtual void setWidget(QWidget *widget)
KParts::PartManager::addPart
virtual void addPart(Part *part, bool setActive=true)
KParts::URLArgs::setNewTab
void setNewTab(bool newTab)
KHTMLPart::preloadStyleSheet
void preloadStyleSheet(const QString &url, const QString &stylesheet)
Loads a style sheet into the stylesheet cache.
Definition: khtml_part.cpp:6968
DOM::EventListener
Introduced in DOM Level 2.
Definition: dom2_events.h:64
KParts::URLArgs::serviceType
QString serviceType
KURL::decode_string
static QString decode_string(const QString &str, int encoding_hint=0)
KParts::URLArgs::docState
QStringList docState
KLibLoader::self
static KLibLoader * self()
KHTMLPart::caretDisplayPolicyNonFocused
CaretDisplayPolicy caretDisplayPolicyNonFocused() const
Returns the current caret policy when the view is not focused.
Definition: khtml_part.cpp:2699
KConfig
KHTMLPart::setJScriptEnabled
void setJScriptEnabled(bool enable)
Enable/disable Javascript support.
Definition: khtml_part.cpp:931
KHTMLPart::setDNDEnabled
void setDNDEnabled(bool b)
Enables or disables Drag'n'Drop support.
Definition: khtml_part.cpp:5929
KWin::activateWindow
static void activateWindow(WId win, long time=0)
KParts::URLArgs::xOffset
int xOffset
KMultipleDrag
KURL::path
QString path() const
KHTMLPart::khtmlMouseDoubleClickEvent
virtual void khtmlMouseDoubleClickEvent(khtml::MouseDoubleClickEvent *)
Eventhandler for the khtml::MouseDoubleClickEvent.
Definition: khtml_part.cpp:6124
KHTMLPart::nonSharedNodeUnderMouse
DOM::Node nonSharedNodeUnderMouse() const
Returns the Node currently under the mouse that is not shared.
Definition: khtml_part.cpp:5644
KHTMLPart::setCaretDisplayPolicyNonFocused
void setCaretDisplayPolicyNonFocused(CaretDisplayPolicy policy)
Sets the caret display policy when the view is not focused.
Definition: khtml_part.cpp:2708
KURL::split
static List split(const QString &_url)
KHTMLPart::findText
void findText()
Starts a new search by popping up a dialog asking the user what he wants to search for...
Definition: khtml_part.cpp:2993
KURL::queryItem
QString queryItem(const QString &item) const
KHTMLPart::dndEnabled
bool dndEnabled() const
Returns whether Dragn'n'Drop support is enabled or not.
DOM::NamedNodeMap::getNamedItem
Node getNamedItem(const DOMString &name) const
Retrieves a node specified by name.
Definition: dom_node.cpp:66
KStdAction::find
KAction * find(const QObject *recvr, const char *slot, KActionCollection *parent, const char *name=0)
KHTMLPart::isEditable
bool isEditable() const
Returns true if the document is editable, false otherwise.
Definition: khtml_part.cpp:2680
KStdAction::findPrev
KAction * findPrev(const QObject *recvr, const char *slot, KActionCollection *parent, const char *name=0)
KHTMLPart::frameNames
QStringList frameNames() const
Returns a list of names of all frame (including iframe) objects of the current document.
Definition: khtml_part.cpp:5886
KHTMLPageCache::createCacheEntry
long createCacheEntry()
Create a new cache entry.
Definition: khtml_pagecache.cpp:143
KURL::setRef
void setRef(const QString &_txt)
KHTMLPart::end
virtual void end()
Call this after your last call to write().
Definition: khtml_part.cpp:2007
KAction
KLibLoader::factory
KLibFactory * factory(const char *libname)
KURLLabel::setSizePolicy
virtual void setSizePolicy(QSizePolicy)
KHTMLPart::executeScript
QVariant executeScript(const DOM::Node &n, const QString &script)
Same as executeScript( const QString & ) except with the Node parameter specifying the 'this' value...
Definition: khtml_part.cpp:1187
KParts::PartManager::setAllowNestedParts
void setAllowNestedParts(bool allow)
KHTMLPart::zoomFactor
int zoomFactor() const
Returns the current zoom factor.
Definition: khtml_part.cpp:5659
KHTMLPart::setSuppressedPopupIndicator
void setSuppressedPopupIndicator(bool enable)
Shows or hides the suppressed popup indicator.
Definition: khtml_part.cpp:7368
KHTMLPart::isCaretMode
bool isCaretMode() const
Returns whether caret mode is on/off.
Definition: khtml_part.cpp:2659
KHTMLPartBrowserExtension
This is the BrowserExtension for a KHTMLPart document.
Definition: khtml_ext.h:41
KParts::StatusBarExtension::childObject
static StatusBarExtension * childObject(QObject *obj)
KConfig::readBoolEntry
bool readBoolEntry(const QString &pKey, bool bDefault=false) const
KHTMLPart::createPart
virtual KParts::ReadOnlyPart * createPart(QWidget *parentWidget, const char *widgetName, QObject *parent, const char *name, const QString &mimetype, QString &serviceName, QStringList &serviceTypes, const QStringList &params)
This method is called when a new embedded object (include html frames) is to be created.
Definition: khtml_part.cpp:4646
KHTMLPart::setEditable
void setEditable(bool enable)
Makes the document editable.
Definition: khtml_part.cpp:2664
KHTMLPart::javaEnabled
bool javaEnabled() const
Return true if Java applet support is enabled, false if disabled.
KParts::PartManager
KHTMLPart::selectedText
virtual QString selectedText() const
Returns the text the user has marked.
Definition: khtml_part.cpp:3451
KHTMLPart::htmlDocument
DOM::HTMLDocument htmlDocument() const
Returns a reference to the DOM HTML document (for non-HTML documents, returns null) ...
Definition: khtml_part.cpp:852
KHTMLPart::setZoomFactor
void setZoomFactor(int percent)
Sets the Zoom factor.
Definition: khtml_part.cpp:5723
KHTMLPart::setAutoloadImages
void setAutoloadImages(bool enable)
Specifies whether images contained in the document should be loaded automatically or not...
Definition: khtml_part.cpp:1336
KURL::setUser
void setUser(const QString &_txt)
KToggleAction
KHTMLPart::show
void show()
Convenience method to show the document's view.
Definition: khtml_part.cpp:5627
KHTMLPageCache::saveData
void saveData(long id, QDataStream *str)
Save the data of cache entry id to the datastream str.
Definition: khtml_pagecache.cpp:272
KHTMLSettings::init
void init()
Called by constructor and reparseConfiguration.
Definition: khtml_settings.cc:290
KHTMLPart::jScriptInterpreter
KJS::Interpreter * jScriptInterpreter()
Returns the JavaScript interpreter the part is using.
Definition: khtml_part.cpp:917
KHTMLPart::document
DOM::Document document() const
Returns a reference to the DOM document.
Definition: khtml_part.cpp:860
KHTMLPart::jScriptEnabled
bool jScriptEnabled() const
Returns true if Javascript support is enabled or false otherwise.
Definition: khtml_part.cpp:940
KLibrary::symbol
void * symbol(const char *name) const
KNotifyClient::instance
KInstance * instance()
KHTMLPart::currentFrame
KParts::ReadOnlyPart * currentFrame() const
Return the current frame (the one that has focus) Not necessarily a direct child of ours...
Definition: khtml_part.cpp:5273
KHTMLPart::popupMenu
void popupMenu(const QString &url, const QPoint &point)
Emitted when the user clicks the right mouse button on the document.
KParts::URLArgs::postData
QByteArray postData
KHTMLPart::stopAnimations
void stopAnimations()
Stops all animated images on the current and child pages.
Definition: khtml_part.cpp:2052
endl
kndbgstream & endl(kndbgstream &s)
KHTMLPart::selectAll
void selectAll()
Marks all text in the document as selected.
Definition: khtml_part.cpp:6744
KParts::URLArgs::yOffset
int yOffset
KHTMLPart::nodeActivated
void nodeActivated(const DOM::Node &)
This signal is emitted when an element retrieves the keyboard focus.
KHTMLPart::CaretDisplayPolicy
CaretDisplayPolicy
Enumeration for displaying the caret.
Definition: khtml_part.h:496
KHTMLPart::doCloseStream
virtual bool doCloseStream()
Implements the streaming API of KParts::ReadOnlyPart.
Definition: khtml_part.cpp:2039
KPassivePopup::message
static KPassivePopup * message(const QString &text, QWidget *parent, const char *name=0)
KConfig::setGroup
void setGroup(const QString &group)
KHTMLPart::findTextNext
bool findTextNext()
Finds the next occurence of a string set by findText()
Definition: khtml_part.cpp:3060
KURL::List
KHTMLPageCache::addData
void addData(long id, const QByteArray &data)
Add data to the cache entry with id id.
Definition: khtml_pagecache.cpp:158
KConfig::writeEntry
void writeEntry(const QString &pKey, const QString &pValue, bool bPersistent=true, bool bGlobal=false, bool bNLS=false)
KGlobalSettings::dndEventDelay
static int dndEventDelay()
KURLDrag
KURL::join
static KURL join(const List &_list)
KHTMLPart::hasSelection
bool hasSelection() const
Has the user selected anything?
Definition: khtml_part.cpp:3593
KHTMLPart::setJSDefaultStatusBarText
void setJSDefaultStatusBarText(const QString &text)
Called by KJS.
Definition: khtml_part.cpp:5789
KHTMLPart::encoding
QString encoding() const
Returns the encoding the page currently uses.
Definition: khtml_part.cpp:2482
KStdAccel::end
const KShortcut & end()
KStdAction::findNext
KAction * findNext(const QObject *recvr, const char *slot, KActionCollection *parent, const char *name=0)
KURL::isValid
bool isValid() const
KGlobal::config
static KConfig * config()
DOM::Node::nextSibling
Node nextSibling() const
The node immediately following this node.
Definition: dom_node.cpp:235
KURL::setFileName
void setFileName(const QString &_txt)
KParts::StatusBarExtension::setStatusBar
void setStatusBar(KStatusBar *status)
KHTMLPageCache::endData
void endData(long id)
Signal end of data for the cache entry with id id.
Definition: khtml_pagecache.cpp:166
KConfig::readNumEntry
int readNumEntry(const QString &pKey, int nDefault=0) const
KHTMLPart::parentPart
KHTMLPart * parentPart()
Returns a pointer to the parent KHTMLPart if the part is a frame in an HTML frameset.
Definition: khtml_part.cpp:5318
KLocale::encoding
const char * encoding() const
KURL::htmlRef
QString htmlRef() const
DOM::HTMLDocument::domain
DOMString domain() const
The domain name of the server that served the document, or a null string if the server cannot be iden...
Definition: html_document.cpp:109
KHTMLPart::isModified
bool isModified() const
Checks whether the page contains unsubmitted form changes.
Definition: khtml_part.cpp:7345
KParts::ReadOnlyPart
DOM::Node::nodeType
unsigned short nodeType() const
A code representing the type of the underlying object, as defined above.
Definition: dom_node.cpp:199

KDE Home | KDE Accessibility Home | Description of Access Keys