You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
7472 lines
240 KiB
7472 lines
240 KiB
// -*- 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 <tqclipboard.h>
|
|
#include <tqfile.h>
|
|
#include <tqtooltip.h>
|
|
#include <tqmetaobject.h>
|
|
#include <tqucomextra_p.h>
|
|
|
|
#include "khtmlpart_p.h"
|
|
#include "kpassivepopup.h"
|
|
#include "kpopupmenu.h"
|
|
#include "rendering/render_form.h"
|
|
#include <twin.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, TQString(), "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 TQString& ) {
|
|
delete this;
|
|
}
|
|
TQGuardedPtr<KHTMLPart> m_part;
|
|
khtml::CachedCSSStyleSheet *m_cachedSheet;
|
|
};
|
|
}
|
|
|
|
void khtml::ChildFrame::liveConnectEvent(const unsigned long, const TQString & event, const KParts::LiveConnectExtension::ArgList & args)
|
|
{
|
|
if (!m_part || !m_frame || !m_liveconnect)
|
|
// hmmm
|
|
return;
|
|
|
|
TQString 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 += TQString((*i).second).replace('\\', "\\\\").replace('"', "\\\"");
|
|
script += "\"";
|
|
} else
|
|
script += (*i).second;
|
|
}
|
|
script += ")";
|
|
kdDebug(6050) << "khtml::ChildFrame::liveConnectEvent " << script << endl;
|
|
|
|
KHTMLPart * part = ::tqqt_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(TQString(), 1, script, 0L, &cmp);
|
|
} else
|
|
part->executeScript(m_frame->element(), script);
|
|
}
|
|
|
|
KHTMLFrameList::Iterator KHTMLFrameList::find( const TQString &name )
|
|
{
|
|
Iterator it = begin();
|
|
const Iterator e = end();
|
|
|
|
for (; it!=e; ++it )
|
|
if ( (*it)->m_name==name )
|
|
break;
|
|
|
|
return it;
|
|
}
|
|
|
|
KHTMLPart::KHTMLPart( TQWidget *parentWidget, const char *widgetname, TQObject *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, TQObject *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, TQT_SLOT( slotViewDocumentSource() ), actionCollection(), "viewDocumentSource" );
|
|
d->m_paViewFrame = new KAction( i18n( "View Frame Source" ), 0, this, TQT_SLOT( slotViewFrameSource() ), actionCollection(), "viewFrameSource" );
|
|
d->m_paViewInfo = new KAction( i18n( "View Document Information" ), CTRL+Key_I, this, TQT_SLOT( slotViewPageInfo() ), actionCollection(), "viewPageInfo" );
|
|
d->m_paSaveBackground = new KAction( i18n( "Save &Background Image As..." ), 0, this, TQT_SLOT( slotSaveBackground() ), actionCollection(), "saveBackground" );
|
|
d->m_paSaveDocument = KStdAction::saveAs( this, TQT_SLOT( slotSaveDocument() ), actionCollection(), "saveDocument" );
|
|
if ( parentPart() )
|
|
d->m_paSaveDocument->setShortcut( KShortcut() ); // avoid clashes
|
|
d->m_paSaveFrame = new KAction( i18n( "Save &Frame As..." ), 0, this, TQT_SLOT( slotSaveFrame() ), actionCollection(), "saveFrame" );
|
|
d->m_paSecurity = new KAction( i18n( "Security..." ), "decrypted", 0, this, TQT_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, TQT_SLOT( slotDebugRenderTree() ), actionCollection(), "debugRenderTree" );
|
|
d->m_paDebugDOMTree = new KAction( i18n( "Print DOM Tree to STDOUT" ), ALT + CTRL + SHIFT + Key_D, this, TQT_SLOT( slotDebugDOMTree() ), actionCollection(), "debugDOMTree" );
|
|
d->m_paStopAnimations = new KAction( i18n( "Stop Animated Images" ), 0, this, TQT_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, TQT_SIGNAL( activated( int ) ), this, TQT_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, TQT_SLOT( slotSetEncoding() ), actionCollection(), "manualDetection" );
|
|
TQStringList 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;
|
|
TQCString name = TQTextCodec::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, TQT_SLOT( slotUseStylesheet() ), actionCollection(), "useStylesheet" );
|
|
|
|
if ( prof == BrowserViewGUI ) {
|
|
d->m_paIncZoomFactor = new KHTMLZoomFactorAction( this, true, i18n(
|
|
"Enlarge Font" ), "viewmag+", "CTRL++;CTRL+=", this,
|
|
TQT_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,
|
|
TQT_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, TQT_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, TQT_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, TQT_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, TQT_SLOT( slotFindAheadText()),
|
|
actionCollection(), "findAheadText");
|
|
d->m_paFindAheadLinks = new KAction( i18n("Find Links as You Type"), KShortcut( '\'' ), this, TQT_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, TQT_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, TQT_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, TQT_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, TQT_SIGNAL( zoomView( int ) ), TQT_SLOT( slotZoomView( int ) ) );
|
|
|
|
connect( this, TQT_SIGNAL( completed() ),
|
|
this, TQT_SLOT( updateActions() ) );
|
|
connect( this, TQT_SIGNAL( completed( bool ) ),
|
|
this, TQT_SLOT( updateActions() ) );
|
|
connect( this, TQT_SIGNAL( started( KIO::Job * ) ),
|
|
this, TQT_SLOT( updateActions() ) );
|
|
|
|
d->m_popupMenuXML = KXMLGUIFactory::readConfigFile( locate( "data", "khtml/khtml_popupmenu.rc", KHTMLFactory::instance() ) );
|
|
|
|
connect( khtml::Cache::loader(), TQT_SIGNAL( requestStarted( khtml::DocLoader*, khtml::CachedObject* ) ),
|
|
this, TQT_SLOT( slotLoaderRequestStarted( khtml::DocLoader*, khtml::CachedObject* ) ) );
|
|
connect( khtml::Cache::loader(), TQT_SIGNAL( requestDone( khtml::DocLoader*, khtml::CachedObject *) ),
|
|
this, TQT_SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
|
|
connect( khtml::Cache::loader(), TQT_SIGNAL( requestFailed( khtml::DocLoader*, khtml::CachedObject *) ),
|
|
this, TQT_SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
|
|
|
|
connect ( &d->m_progressUpdateTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( slotProgressUpdate() ) );
|
|
|
|
findTextBegin(); //reset find variables
|
|
|
|
connect( &d->m_redirectionTimer, TQT_SIGNAL( timeout() ),
|
|
this, TQT_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 tdelibs.
|
|
// 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(), TQT_SIGNAL( requestStarted( khtml::DocLoader*, khtml::CachedObject* ) ),
|
|
this, TQT_SLOT( slotLoaderRequestStarted( khtml::DocLoader*, khtml::CachedObject* ) ) );
|
|
disconnect( khtml::Cache::loader(), TQT_SIGNAL( requestDone( khtml::DocLoader*, khtml::CachedObject *) ),
|
|
this, TQT_SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
|
|
disconnect( khtml::Cache::loader(), TQT_SIGNAL( requestFailed( khtml::DocLoader*, khtml::CachedObject *) ),
|
|
this, TQT_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, TQT_SIGNAL(finishedLayout()), this, TQT_SLOT(restoreScrollPosition()));
|
|
connect(d->m_view, TQT_SIGNAL(finishedLayout()), this, TQT_SLOT(restoreScrollPosition()));
|
|
|
|
KHTMLPageCache::self()->fetchData( d->m_cacheId, this, TQT_SLOT(slotRestoreData(const TQByteArray &)));
|
|
|
|
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] = TQString();
|
|
|
|
/**
|
|
* The format of the error url is that two variables are passed in the query:
|
|
* error = int kio error code, errText = TQString error text from kio
|
|
* and the URL where the error happened is passed as a sub URL.
|
|
*/
|
|
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;
|
|
TQString 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
|
|
TQString host = url.isLocalFile() ? "localhost" : url.host();
|
|
TQString userAgent = KProtocolManager::userAgentForHost(host);
|
|
if (userAgent != KProtocolManager::userAgentForHost(TQString())) {
|
|
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(TQSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Fixed));
|
|
d->m_statusBarUALabel->setUseCursor(false);
|
|
d->m_statusBarExtension->addStatusBarItem(d->m_statusBarUALabel, 0, false);
|
|
d->m_statusBarUALabel->setPixmap(SmallIcon("agent", instance()));
|
|
} else {
|
|
TQToolTip::remove(d->m_statusBarUALabel);
|
|
}
|
|
TQToolTip::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, TQT_SIGNAL(finishedLayout()), this, TQT_SLOT(restoreScrollPosition()));
|
|
connect(d->m_view, TQT_SIGNAL(finishedLayout()), this, TQT_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, TQT_SIGNAL( result( KIO::Job* ) ),
|
|
TQT_SLOT( slotFinished( KIO::Job* ) ) );
|
|
connect( d->m_job, TQT_SIGNAL( data( KIO::Job*, const TQByteArray& ) ),
|
|
TQT_SLOT( slotData( KIO::Job*, const TQByteArray& ) ) );
|
|
connect ( d->m_job, TQT_SIGNAL( infoMessage( KIO::Job*, const TQString& ) ),
|
|
TQT_SLOT( slotInfoMessage(KIO::Job*, const TQString& ) ) );
|
|
connect( d->m_job, TQT_SIGNAL(redirection(KIO::Job*, const KURL& ) ),
|
|
TQT_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] = TQString();
|
|
|
|
// 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, TQT_SIGNAL( speed( KIO::Job*, unsigned long ) ),
|
|
this, TQT_SLOT( slotJobSpeed( KIO::Job*, unsigned long ) ) );
|
|
|
|
connect( d->m_job, TQT_SIGNAL( percent( KIO::Job*, unsigned long ) ),
|
|
this, TQT_SLOT( slotJobPercent( KIO::Job*, unsigned long ) ) );
|
|
|
|
connect( d->m_job, TQT_SIGNAL( result( KIO::Job* ) ),
|
|
this, TQT_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, TQT_SIGNAL( result( KIO::Job * ) ),
|
|
this, TQT_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, TQT_SIGNAL(finishedLayout()), this, TQT_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;
|
|
}
|
|
|
|
TQString KHTMLPart::documentSource() const
|
|
{
|
|
TQString sourceStr;
|
|
if ( !( m_url.isLocalFile() ) && KHTMLPageCache::self()->isComplete( d->m_cacheId ) )
|
|
{
|
|
TQByteArray sourceArray;
|
|
TQDataStream dataStream( sourceArray, IO_WriteOnly );
|
|
KHTMLPageCache::self()->saveData( d->m_cacheId, &dataStream );
|
|
TQTextStream stream( sourceArray, IO_ReadOnly );
|
|
stream.setCodec( TQTextCodec::codecForName( encoding().latin1() ) );
|
|
sourceStr = stream.read();
|
|
} else
|
|
{
|
|
TQString tmpFile;
|
|
if( KIO::NetAccess::download( m_url, tmpFile, NULL ) )
|
|
{
|
|
TQFile f( tmpFile );
|
|
if ( f.open( IO_ReadOnly ) )
|
|
{
|
|
TQTextStream stream( &f );
|
|
stream.setCodec( TQTextCodec::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;
|
|
}
|
|
|
|
TQVariant KHTMLPart::crossFrameExecuteScript(const TQString& target, const TQString& script)
|
|
{
|
|
KHTMLPart* destpart = this;
|
|
|
|
TQString 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(TQSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Fixed));
|
|
d->m_statusBarJSErrorLabel->setUseCursor(false);
|
|
d->m_statusBarExtension->addStatusBarItem(d->m_statusBarJSErrorLabel, 0, false);
|
|
TQToolTip::add(d->m_statusBarJSErrorLabel, i18n("This web page contains coding errors."));
|
|
d->m_statusBarJSErrorLabel->setPixmap(SmallIcon("bug", instance()));
|
|
connect(d->m_statusBarJSErrorLabel, TQT_SIGNAL(leftClickedURL()), TQT_SLOT(launchJSErrorDialog()));
|
|
connect(d->m_statusBarJSErrorLabel, TQT_SIGNAL(rightClickedURL()), TQT_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()", TQByteArray());
|
|
}
|
|
|
|
void KHTMLPart::jsErrorDialogContextMenu() {
|
|
KPopupMenu *m = new KPopupMenu(0L);
|
|
m->insertItem(i18n("&Hide Errors"), this, TQT_SLOT(removeJSErrorExtension()));
|
|
m->insertItem(i18n("&Disable Error Reporting"), this, TQT_SLOT(disableJSErrorExtension()));
|
|
m->popup(TQCursor::pos());
|
|
}
|
|
|
|
void KHTMLPart::launchJSErrorDialog() {
|
|
KJSErrorDlg *dlg = jsErrorExtension();
|
|
if (dlg) {
|
|
dlg->show();
|
|
dlg->raise();
|
|
}
|
|
}
|
|
|
|
void KHTMLPart::launchJSConfigDialog() {
|
|
TQStringList args;
|
|
args << "khtml_java_js";
|
|
KApplication::tdeinitExec( "kcmshell", args );
|
|
}
|
|
|
|
TQVariant KHTMLPart::executeScript(const TQString& filename, int baseLine, const DOM::Node& n, const TQString& 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 TQVariant();
|
|
|
|
KJS::Completion comp;
|
|
|
|
TQVariant 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;
|
|
}
|
|
|
|
TQVariant KHTMLPart::executeScript( const TQString &script )
|
|
{
|
|
return executeScript( DOM::Node(), script );
|
|
}
|
|
|
|
TQVariant KHTMLPart::executeScript( const DOM::Node &n, const TQString &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 TQVariant();
|
|
++(d->m_runningScripts);
|
|
KJS::Completion comp;
|
|
const TQVariant ret = proxy->evaluate( TQString(), 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 TQString& script)
|
|
{
|
|
//kdDebug(6050) << "KHTMLPart::scheduleScript "<< script << endl;
|
|
|
|
d->scheduledScript = script;
|
|
d->scheduledScriptNode = n;
|
|
|
|
return true;
|
|
}
|
|
|
|
TQVariant KHTMLPart::executeScheduledScript()
|
|
{
|
|
if( d->scheduledScript.isEmpty() )
|
|
return TQVariant();
|
|
|
|
//kdDebug(6050) << "executing delayed " << d->scheduledScript << endl;
|
|
|
|
TQVariant ret = executeScript( d->scheduledScriptNode, d->scheduledScript );
|
|
d->scheduledScript = TQString();
|
|
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) << TQString().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
|
|
// TQString dumps;
|
|
// TQTextStream 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, TQT_SLOT( slotLoadImages() ), actionCollection(), "loadImages" );
|
|
|
|
if ( d->m_paLoadImages ) {
|
|
TQPtrList<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(), TQT_SIGNAL( activePartChanged( KParts::Part * ) ),
|
|
this, TQT_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(), TQT_SIGNAL( activePartChanged( KParts::Part * ) ),
|
|
this, TQT_SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
|
|
|
|
d->m_delayRedirect = 0;
|
|
d->m_redirectURL = TQString();
|
|
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->tqclipboard(), TQT_SIGNAL( selectionChanged()), TQT_SLOT( slotClearSelection()));
|
|
#endif
|
|
|
|
d->m_jobPercent = 0;
|
|
|
|
if ( !d->m_haveEncoding )
|
|
d->m_encoding = TQString();
|
|
#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 TQString& 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(TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ));
|
|
d->m_statusBarIconLabel->setUseCursor( false );
|
|
d->m_statusBarExtension->addStatusBarItem( d->m_statusBarIconLabel, 0, false );
|
|
connect( d->m_statusBarIconLabel, TQT_SIGNAL( leftClickedURL() ), TQT_SLOT( slotSecurity() ) );
|
|
} else if (d->m_statusBarIconLabel) {
|
|
TQToolTip::remove(d->m_statusBarIconLabel);
|
|
}
|
|
|
|
if (d->m_statusBarIconLabel) {
|
|
if (d->m_ssl_in_use)
|
|
TQToolTip::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 TQToolTip::add(d->m_statusBarIconLabel, i18n("Session is not secured."));
|
|
}
|
|
|
|
TQString 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 TQByteArray &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) {
|
|
TQToolTip::remove(d->m_statusBarIconLabel);
|
|
if (d->m_ssl_in_use) {
|
|
TQToolTip::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 {
|
|
TQToolTip::add(d->m_statusBarIconLabel, i18n("Session is not secured."));
|
|
}
|
|
}
|
|
|
|
// Check for charset meta-data
|
|
TQString 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
|
|
/*
|
|
TQString baseURL = d->m_job->queryMetaData ("content-location");
|
|
if (!baseURL.isEmpty())
|
|
d->m_doc->setBaseURL(KURL( d->m_doc->completeURL(baseURL) ));
|
|
*/
|
|
|
|
// Support for Content-Language
|
|
TQString 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 = TQString(); // 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 TQByteArray &data )
|
|
{
|
|
// The first data ?
|
|
if ( !d->m_workingURL.isEmpty() )
|
|
{
|
|
long saveCacheId = d->m_cacheId;
|
|
TQString savePageReferrer = d->m_pageReferrer;
|
|
TQString 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 TQString& 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();
|
|
TQString errText = TQString::fromLatin1( "<HTML dir=%1><HEAD><TITLE>" )
|
|
.arg(TQApplication::reverseLayout() ? "rtl" : "ltr");
|
|
errText += i18n( "Error while loading %1" ).arg( reqUrl.htmlURL() );
|
|
errText += TQString::fromLatin1( "</TITLE></HEAD><BODY><P>" );
|
|
errText += i18n( "An error occurred while loading <B>%1</B>:" ).arg( reqUrl.htmlURL() );
|
|
errText += TQString::fromLatin1( "</P>" );
|
|
errText += TQStyleSheet::convertFromPlainText( KIO::buildErrorString( errorCode, text ) );
|
|
errText += TQString::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
|
|
|
|
TQString errorName, techName, description;
|
|
TQStringList causes, solutions;
|
|
|
|
TQByteArray raw = KIO::rawErrorDetail( errorCode, text, &reqUrl );
|
|
TQDataStream stream(raw, IO_ReadOnly);
|
|
|
|
stream >> errorName >> techName >> description >> causes >> solutions;
|
|
|
|
TQString url, protocol, datetime;
|
|
url = reqUrl.prettyURL();
|
|
protocol = reqUrl.protocol();
|
|
datetime = KGlobal::locale()->formatDateTime( TQDateTime::currentDateTime(),
|
|
false );
|
|
|
|
TQString doc = TQString::fromLatin1( "<html><head><title>" );
|
|
doc += i18n( "Error: " );
|
|
doc += errorName;
|
|
doc += TQString::fromLatin1( " - %1</title></head><body><h1>" ).arg( url );
|
|
doc += i18n( "The requested operation could not be completed" );
|
|
doc += TQString::fromLatin1( "</h1><h2>" );
|
|
doc += errorName;
|
|
doc += TQString::fromLatin1( "</h2>" );
|
|
if ( !techName.isNull() ) {
|
|
doc += TQString::fromLatin1( "<h2>" );
|
|
doc += i18n( "Technical Reason: " );
|
|
doc += techName;
|
|
doc += TQString::fromLatin1( "</h2>" );
|
|
}
|
|
doc += TQString::fromLatin1( "<h3>" );
|
|
doc += i18n( "Details of the Request:" );
|
|
doc += TQString::fromLatin1( "</h3><ul><li>" );
|
|
doc += i18n( "URL: %1" ).arg( url );
|
|
doc += TQString::fromLatin1( "</li><li>" );
|
|
if ( !protocol.isNull() ) {
|
|
// uncomment for 3.1... i18n change
|
|
// doc += i18n( "Protocol: %1" ).arg( protocol ).arg( protocol );
|
|
doc += TQString::fromLatin1( "</li><li>" );
|
|
}
|
|
doc += i18n( "Date and Time: %1" ).arg( datetime );
|
|
doc += TQString::fromLatin1( "</li><li>" );
|
|
doc += i18n( "Additional Information: %1" ).arg( text );
|
|
doc += TQString::fromLatin1( "</li></ul><h3>" );
|
|
doc += i18n( "Description:" );
|
|
doc += TQString::fromLatin1( "</h3><p>" );
|
|
doc += description;
|
|
doc += TQString::fromLatin1( "</p>" );
|
|
if ( causes.count() ) {
|
|
doc += TQString::fromLatin1( "<h3>" );
|
|
doc += i18n( "Possible Causes:" );
|
|
doc += TQString::fromLatin1( "</h3><ul><li>" );
|
|
doc += causes.join( "</li><li>" );
|
|
doc += TQString::fromLatin1( "</li></ul>" );
|
|
}
|
|
if ( solutions.count() ) {
|
|
doc += TQString::fromLatin1( "<h3>" );
|
|
doc += i18n( "Possible Solutions:" );
|
|
doc += TQString::fromLatin1( "</h3><ul><li>" );
|
|
doc += solutions.join( "</li><li>" );
|
|
doc += TQString::fromLatin1( "</li></ul>" );
|
|
}
|
|
doc += TQString::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 = ::tqqt_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 ( TQValueListIterator<TQGuardedPtr<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()) {
|
|
TQString urlString = url.url();
|
|
KHTMLFactory::vLinks()->insert( urlString );
|
|
TQString 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 = TQString();
|
|
|
|
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(TQStringList());
|
|
d->m_paUseStylesheet->setEnabled( false );
|
|
|
|
setAutoloadImages( KHTMLFactory::defaultHTMLSettings()->autoLoadImages() );
|
|
TQString userStyleSheet = KHTMLFactory::defaultHTMLSettings()->userStyleSheet();
|
|
if ( !userStyleSheet.isEmpty() )
|
|
setUserStyleSheet( KURL( userStyleSheet ) );
|
|
|
|
d->m_doc->setRestoreState(args.docState);
|
|
d->m_doc->open();
|
|
connect(d->m_doc,TQT_SIGNAL(finishedParsing()),this,TQT_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;
|
|
|
|
TQString 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 TQString &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) {
|
|
TQString 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 TQString& 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 TQByteArray& data )
|
|
{
|
|
write( data.data(), data.size() );
|
|
return true;
|
|
}
|
|
|
|
bool KHTMLPart::doCloseStream()
|
|
{
|
|
end();
|
|
return true;
|
|
}
|
|
|
|
|
|
void KHTMLPart::paint(TQPainter *p, const TQRect &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,TQT_SIGNAL(finishedParsing()),this,TQT_SLOT(slotFinishedParsing()));
|
|
connect(d->m_doc,TQT_SIGNAL(finishedParsing()),this,TQT_SLOT(slotFinishedParsing()));
|
|
d->m_doc->setParsing(true);
|
|
|
|
emit started( 0L );
|
|
}
|
|
|
|
void KHTMLPart::slotFinishedParsing()
|
|
{
|
|
d->m_doc->setParsing(false);
|
|
checkEmitLoadEvent();
|
|
disconnect(d->m_doc,TQT_SIGNAL(finishedParsing()),this,TQT_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 tqrepaint 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
|
|
TQStringList 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(TQString());
|
|
|
|
#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();
|
|
}
|
|
|
|
TQString KHTMLPart::baseTarget() const
|
|
{
|
|
if ( !d->m_doc ) return TQString();
|
|
|
|
return d->m_doc->baseTarget();
|
|
}
|
|
#endif
|
|
|
|
KURL KHTMLPart::completeURL( const TQString &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 TQString &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;
|
|
TQString u = d->m_redirectURL;
|
|
d->m_delayRedirect = 0;
|
|
d->m_redirectURL = TQString();
|
|
|
|
// SYNC check with ecma/kjs_window.cpp::goURL !
|
|
if ( u.find( TQString::fromLatin1( "javascript:" ), 0, false ) == 0 )
|
|
{
|
|
TQString script = KURL::decode_string( u.right( u.length() - 11 ) );
|
|
kdDebug( 6050 ) << "KHTMLPart::slotRedirect script=" << script << endl;
|
|
TQVariant res = executeScript( DOM::Node(), script );
|
|
if ( res.type() == TQVariant::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 TQString &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;
|
|
}
|
|
|
|
TQString KHTMLPart::encoding() const
|
|
{
|
|
if(d->m_haveEncoding && !d->m_encoding.isEmpty())
|
|
return d->m_encoding;
|
|
|
|
if(d->m_decoder && d->m_decoder->encoding())
|
|
return TQString(d->m_decoder->encoding());
|
|
|
|
return defaultEncoding();
|
|
}
|
|
|
|
TQString KHTMLPart::defaultEncoding() const
|
|
{
|
|
TQString 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 TQString &styleSheet)
|
|
{
|
|
if ( d->m_doc )
|
|
d->m_doc->setUserStyleSheet( styleSheet );
|
|
}
|
|
|
|
bool KHTMLPart::gotoAnchor( const TQString &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 TQString &name )
|
|
{
|
|
d->m_settings->setStdFontName(name);
|
|
}
|
|
|
|
void KHTMLPart::setFixedFont( const TQString &name )
|
|
{
|
|
d->m_settings->setFixedFontName(name);
|
|
}
|
|
|
|
void KHTMLPart::setURLCursor( const TQCursor &c )
|
|
{
|
|
d->m_linkCursor = c;
|
|
}
|
|
|
|
TQCursor 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
|
|
{
|
|
TQValueList<khtml::ChildFrame*>::Iterator it = m_frames.begin();
|
|
const TQValueList<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
|
|
{
|
|
TQValueList<khtml::ChildFrame*>::Iterator it = m_objects.begin();
|
|
const TQValueList<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 TQString &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();
|
|
TQConstString s(t->s, t->l);
|
|
|
|
int matchLen = 0;
|
|
if ( isRegExp ) {
|
|
TQRegExp 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->tqclipboard(), TQT_SIGNAL(selectionChanged()), this, TQT_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, TQT_SIGNAL(okClicked()), this, TQT_SLOT(slotFindNext()) );
|
|
connect( d->m_findDialog, TQT_SIGNAL(finished()), this, TQT_SLOT(slotFindDialogDestroyed()) );
|
|
|
|
findText( d->m_findDialog->pattern(), 0 /*options*/, widget(), d->m_findDialog );
|
|
}
|
|
|
|
void KHTMLPart::findText( const TQString &str, long options, TQWidget *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->tqclipboard(), TQT_SIGNAL(selectionChanged()), TQT_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, TQT_SIGNAL( highlight( const TQString &, int, int ) ),
|
|
this, TQT_SLOT( slotHighlight( const TQString &, int, int ) ) );
|
|
//connect(d->m_find, TQT_SIGNAL( findNext() ),
|
|
// this, TQT_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 ))
|
|
{
|
|
tqSwap( d->m_findNodeEnd, d->m_findNodeStart );
|
|
tqSwap( d->m_findPosEnd, d->m_findPosStart );
|
|
tqSwap( 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 TQString 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;
|
|
TQString str;
|
|
DOM::NodeImpl* lastNode = d->m_findNode;
|
|
while ( obj && !newLine )
|
|
{
|
|
// Grab text from render object
|
|
TQString s;
|
|
bool renderAreaText = obj->parent() && (TQCString(obj->parent()->renderName())== "RenderTextArea");
|
|
bool renderLineText = (TQCString(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() == TQLineEdit::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( TQValueList<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 TQString& /*text*/, int index, int length )
|
|
{
|
|
//kdDebug(6050) << "slotHighlight index=" << index << " length=" << length << endl;
|
|
TQValueList<KHTMLPartPrivate::StringPortion>::Iterator it = d->m_stringPortions.begin();
|
|
const TQValueList<KHTMLPartPrivate::StringPortion>::Iterator itEnd = d->m_stringPortions.end();
|
|
TQValueList<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;
|
|
|
|
TQRect highlightedRect;
|
|
bool renderAreaText =false;
|
|
Q_ASSERT( obj );
|
|
if ( obj )
|
|
{
|
|
int x = 0, y = 0;
|
|
renderAreaText = (TQCString(obj->parent()->renderName())== "RenderTextArea");
|
|
renderLineText = (TQCString(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(TQPoint(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( TQPoint(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 );
|
|
}
|
|
}
|
|
|
|
TQString KHTMLPart::selectedTextAsHTML() const
|
|
{
|
|
if(!hasSelection()) {
|
|
kdDebug() << "selectedTextAsHTML(): selection is not valid. Returning empty selection" << endl;
|
|
return TQString();
|
|
}
|
|
if(d->m_startOffset < 0 || d->m_endOffset <0) {
|
|
kdDebug() << "invalid values for end/startOffset " << d->m_startOffset << " " << d->m_endOffset << endl;
|
|
return TQString();
|
|
}
|
|
DOM::Range r = selection();
|
|
if(r.isNull() || r.isDetached())
|
|
return TQString();
|
|
int exceptioncode = 0; //ignore the result
|
|
return r.handle()->toHTML(exceptioncode).string();
|
|
}
|
|
|
|
TQString KHTMLPart::selectedText() const
|
|
{
|
|
bool hasNewLine = true;
|
|
bool seenTDTag = false;
|
|
TQString 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();
|
|
TQString 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 TQString();
|
|
|
|
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 = TQString();
|
|
emit onURL( TQString() );
|
|
// revert to default statusbar text
|
|
setStatusBarText(TQString(), BarHoverText);
|
|
emit d->m_extension->mouseOverInfo(0);
|
|
}
|
|
}
|
|
|
|
void KHTMLPart::overURL( const TQString &url, const TQString &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( TQString::fromLatin1( "javascript:" ),0, false ) == 0 ) {
|
|
TQString 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( TQStyleSheet::escape( jscode ), BarHoverText );
|
|
return;
|
|
}
|
|
|
|
KFileItem item(u, TQString(), KFileItem::Unknown);
|
|
emit d->m_extension->mouseOverInfo(&item);
|
|
|
|
TQString 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()
|
|
TQCString path = TQFile::encodeName( u.path() );
|
|
|
|
struct stat buff;
|
|
bool ok = !stat( path.data(), &buff );
|
|
|
|
struct stat lbuff;
|
|
if (ok) ok = !lstat( path.data(), &lbuff );
|
|
|
|
TQString text = u.htmlURL();
|
|
TQString text2 = text;
|
|
|
|
if (ok && S_ISLNK( lbuff.st_mode ) )
|
|
{
|
|
TQString 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
|
|
{
|
|
TQString 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() == TQString::fromLatin1("mailto")) {
|
|
TQString mailtoMsg /* = TQString::fromLatin1("<img src=%1>").arg(locate("icon", TQString::fromLatin1("locolor/16x16/actions/mail_send.png")))*/;
|
|
mailtoMsg += i18n("Email to: ") + KURL::decode_string(u.path());
|
|
TQStringList queries = TQStringList::split('&', u.query().mid(1));
|
|
TQStringList::Iterator it = queries.begin();
|
|
const TQStringList::Iterator itEnd = queries.end();
|
|
for (; it != itEnd; ++it)
|
|
if ((*it).startsWith(TQString::fromLatin1("subject=")))
|
|
mailtoMsg += i18n(" - Subject: ") + KURL::decode_string((*it).mid(8));
|
|
else if ((*it).startsWith(TQString::fromLatin1("cc=")))
|
|
mailtoMsg += i18n(" - CC: ") + KURL::decode_string((*it).mid(3));
|
|
else if ((*it).startsWith(TQString::fromLatin1("bcc=")))
|
|
mailtoMsg += i18n(" - BCC: ") + KURL::decode_string((*it).mid(4));
|
|
mailtoMsg = TQStyleSheet::escape(mailtoMsg);
|
|
mailtoMsg.replace(TQRegExp("([\n\r\t]|[ ]{10})"), TQString());
|
|
setStatusBarText("<qt>"+mailtoMsg, BarHoverText);
|
|
return;
|
|
}
|
|
// Is this check necessary at all? (Frerich)
|
|
#if 0
|
|
else if (u.protocol() == TQString::fromLatin1("http")) {
|
|
DOM::Node hrefNode = nodeUnderMouse().parentNode();
|
|
while (hrefNode.nodeName().string() != TQString::fromLatin1("A") && !hrefNode.isNull())
|
|
hrefNode = hrefNode.parentNode();
|
|
|
|
if (!hrefNode.isNull()) {
|
|
DOM::Node hreflangNode = hrefNode.attributes().getNamedItem("HREFLANG");
|
|
if (!hreflangNode.isNull()) {
|
|
TQString countryCode = hreflangNode.nodeValue().string().lower();
|
|
// Map the language code to an appropriate country code.
|
|
if (countryCode == TQString::fromLatin1("en"))
|
|
countryCode = TQString::fromLatin1("gb");
|
|
TQString flagImg = TQString::fromLatin1("<img src=%1>").arg(
|
|
locate("locale", TQString::fromLatin1("l10n/")
|
|
+ countryCode
|
|
+ TQString::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 TQString &url, int button, int state, const TQString &_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 TQString &url, int button, int state, const TQString &_target, KParts::URLArgs args )
|
|
{
|
|
bool hasTarget = false;
|
|
|
|
TQString target = _target;
|
|
if ( target.isEmpty() && d->m_doc )
|
|
target = d->m_doc->baseTarget();
|
|
if ( !target.isEmpty() )
|
|
hasTarget = true;
|
|
|
|
if ( url.find( TQString::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 == Qt::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 == Qt::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(TQString(), 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, TQString::fromLatin1("text/plain"), isTempFile );
|
|
}
|
|
|
|
void KHTMLPart::slotViewPageInfo()
|
|
{
|
|
KHTMLInfoDlg *dlg = new KHTMLInfoDlg(NULL, "KHTML Page Info Dialog", false, (WFlags)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"));
|
|
}
|
|
|
|
TQString editStr = TQString();
|
|
|
|
if (!d->m_pageServices.isEmpty())
|
|
editStr = i18n(" <a href=\"%1\">[Properties]</a>").arg(d->m_pageServices);
|
|
|
|
TQString 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 TQString& enc = encoding();
|
|
if (enc.isEmpty()) {
|
|
dlg->_eLabel->hide();
|
|
dlg->_encoding->hide();
|
|
} else {
|
|
dlg->_encoding->setText(enc);
|
|
}
|
|
/* populate the list view now */
|
|
const TQStringList headers = TQStringList::split("\n", d->m_httpHeaders);
|
|
|
|
TQStringList::ConstIterator it = headers.begin();
|
|
const TQStringList::ConstIterator itEnd = headers.end();
|
|
|
|
for (; it != itEnd; ++it) {
|
|
const TQStringList header = TQStringList::split(TQRegExp(":[ ]+"), *it);
|
|
if (header.count() != 2)
|
|
continue;
|
|
new TQListViewItem(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(TQString(), defaultExtension());
|
|
if (sourceFile.status() == 0)
|
|
{
|
|
KHTMLPageCache::self()->saveData(cacheId, sourceFile.dataStream());
|
|
url = KURL();
|
|
url.setPath(sourceFile.name());
|
|
isTempFile = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
(void) KRun::runURL( url, TQString::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();
|
|
|
|
TQString 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 TQStringList cl = TQStringList::split(TQString("\n"), d->m_ssl_peer_chain);
|
|
TQPtrList<KSSLCertificate> ncl;
|
|
|
|
ncl.setAutoDelete(true);
|
|
TQStringList::ConstIterator it = cl.begin();
|
|
const TQStringList::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 );
|
|
|
|
TQString 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 ? TQString() : d->m_paUseStylesheet->currentText();
|
|
d->m_doc->updateStyleSelector();
|
|
}
|
|
}
|
|
|
|
void KHTMLPart::updateActions()
|
|
{
|
|
bool frames = false;
|
|
|
|
TQValueList<khtml::ChildFrame*>::ConstIterator it = d->m_frames.begin();
|
|
const TQValueList<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 )
|
|
{
|
|
TQObject *ext = KParts::BrowserExtension::childObject( frame );
|
|
if ( ext )
|
|
enablePrintFrame = ext->metaObject()->slotNames().contains( "print()" );
|
|
}
|
|
|
|
d->m_paPrintFrame->setEnabled( enablePrintFrame );
|
|
|
|
TQString 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 TQString &url, const TQString &frameName,
|
|
const TQStringList ¶ms, 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( TQString::fromLatin1( "javascript:" ), 0, false ) == 0 )
|
|
{
|
|
if ( processObjectRequest(*it, KURL("about:blank"), TQString("text/html") ) ) {
|
|
KHTMLPart* p = static_cast<KHTMLPart*>(static_cast<KParts::ReadOnlyPart *>((*it)->m_part));
|
|
|
|
// See if we want to replace content with javascript: output..
|
|
TQVariant res = p->executeScript( DOM::Node(), KURL::decode_string( url.right( url.length() - 11) ) );
|
|
if ( res.type() == TQVariant::String ) {
|
|
p->begin();
|
|
p->write( res.asString() );
|
|
p->end();
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
KURL u = url.isEmpty() ? KURL() : completeURL( url );
|
|
return requestObject( *it, u );
|
|
}
|
|
|
|
TQString KHTMLPart::requestFrameName()
|
|
{
|
|
return TQString::fromLatin1("<!--frame %1-->").arg(d->m_frameNameId++);
|
|
}
|
|
|
|
bool KHTMLPart::requestObject( khtml::RenderPart *frame, const TQString &url, const TQString &serviceType,
|
|
const TQStringList ¶ms )
|
|
{
|
|
//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 = TQString();
|
|
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 = TQString::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 TQString &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 )
|
|
{
|
|
TQString 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(), TQString(), 0, suggestedFilename);
|
|
// fall-through
|
|
case KParts::BrowserRun::Cancel:
|
|
child->m_bCompleted = true;
|
|
checkCompleted();
|
|
return true; // done
|
|
default: // Open
|
|
break;
|
|
}
|
|
}
|
|
|
|
TQStringList 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 (!::tqqt_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, TQT_SIGNAL(partEvent(const unsigned long, const TQString &, const KParts::LiveConnectExtension::ArgList &)), child, TQT_SLOT(liveConnectEvent(const unsigned long, const TQString&, 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 (::tqqt_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, TQT_SIGNAL(partEvent(const unsigned long, const TQString &, const KParts::LiveConnectExtension::ArgList &)), child, TQT_SLOT(liveConnectEvent(const unsigned long, const TQString&, const KParts::LiveConnectExtension::ArgList &)));
|
|
}
|
|
KParts::StatusBarExtension *sb = KParts::StatusBarExtension::childObject(part);
|
|
if (sb)
|
|
sb->setStatusBar( d->m_statusBarExtension->statusBar() );
|
|
|
|
connect( part, TQT_SIGNAL( started( KIO::Job *) ),
|
|
this, TQT_SLOT( slotChildStarted( KIO::Job *) ) );
|
|
connect( part, TQT_SIGNAL( completed() ),
|
|
this, TQT_SLOT( slotChildCompleted() ) );
|
|
connect( part, TQT_SIGNAL( completed(bool) ),
|
|
this, TQT_SLOT( slotChildCompleted(bool) ) );
|
|
connect( part, TQT_SIGNAL( setStatusBarText( const TQString & ) ),
|
|
this, TQT_SIGNAL( setStatusBarText( const TQString & ) ) );
|
|
if ( part->inherits( "KHTMLPart" ) )
|
|
{
|
|
connect( this, TQT_SIGNAL( completed() ),
|
|
part, TQT_SLOT( slotParentCompleted() ) );
|
|
connect( this, TQT_SIGNAL( completed(bool) ),
|
|
part, TQT_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, TQT_SIGNAL( docCreated() ),
|
|
this, TQT_SLOT( slotChildDocCreated() ) );
|
|
}
|
|
|
|
child->m_extension = KParts::BrowserExtension::childObject( part );
|
|
|
|
if ( child->m_extension )
|
|
{
|
|
connect( child->m_extension, TQT_SIGNAL( openURLNotify() ),
|
|
d->m_extension, TQT_SIGNAL( openURLNotify() ) );
|
|
|
|
connect( child->m_extension, TQT_SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ),
|
|
this, TQT_SLOT( slotChildURLRequest( const KURL &, const KParts::URLArgs & ) ) );
|
|
|
|
connect( child->m_extension, TQT_SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ),
|
|
d->m_extension, TQT_SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ) );
|
|
connect( child->m_extension, TQT_SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs &, const KParts::WindowArgs &, KParts::ReadOnlyPart *& ) ),
|
|
d->m_extension, TQT_SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & , const KParts::WindowArgs &, KParts::ReadOnlyPart *&) ) );
|
|
|
|
connect( child->m_extension, TQT_SIGNAL( popupMenu( const TQPoint &, const KFileItemList & ) ),
|
|
d->m_extension, TQT_SIGNAL( popupMenu( const TQPoint &, const KFileItemList & ) ) );
|
|
connect( child->m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KFileItemList & ) ),
|
|
d->m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KFileItemList & ) ) );
|
|
connect( child->m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ),
|
|
d->m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ) );
|
|
connect( child->m_extension, TQT_SIGNAL( popupMenu( const TQPoint &, const KURL &, const TQString &, mode_t ) ),
|
|
d->m_extension, TQT_SIGNAL( popupMenu( const TQPoint &, const KURL &, const TQString &, mode_t ) ) );
|
|
connect( child->m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &, const TQString &, mode_t ) ),
|
|
d->m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &, const TQString &, mode_t ) ) );
|
|
connect( child->m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ),
|
|
d->m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ) );
|
|
|
|
connect( child->m_extension, TQT_SIGNAL( infoMessage( const TQString & ) ),
|
|
d->m_extension, TQT_SIGNAL( infoMessage( const TQString & ) ) );
|
|
|
|
connect( child->m_extension, TQT_SIGNAL( requestFocus( KParts::ReadOnlyPart * ) ),
|
|
this, TQT_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( TQWidget *parentWidget, const char *widgetName,
|
|
TQObject *parent, const char *name, const TQString &mimetype,
|
|
TQString &serviceName, TQStringList &serviceTypes,
|
|
const TQStringList ¶ms )
|
|
{
|
|
TQString constr;
|
|
if ( !serviceName.isEmpty() )
|
|
constr.append( TQString::fromLatin1( "Name == '%1'" ).arg( serviceName ) );
|
|
|
|
KTrader::OfferList offers = KTrader::self()->query( mimetype, "KParts/ReadOnlyPart", constr, TQString() );
|
|
|
|
if ( offers.isEmpty() ) {
|
|
int pos = mimetype.find( "-plugin" );
|
|
if (pos < 0)
|
|
return 0L;
|
|
TQString stripped_mime = mimetype.left( pos );
|
|
offers = KTrader::self()->query( stripped_mime, "KParts/ReadOnlyPart", constr, TQString() );
|
|
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( TQFile::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( TQT_TQOBJECT(parentWidget), widgetName, className ));
|
|
|
|
if ( res ) {
|
|
serviceTypes = service->serviceTypes();
|
|
serviceName = service->name();
|
|
return res;
|
|
}
|
|
} else {
|
|
// TODO KMessageBox::error and i18n, like in KonqFactory::createView?
|
|
kdWarning() << TQString(TQString("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, TQT_SIGNAL( activePartChanged( KParts::Part * ) ),
|
|
this, TQT_SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
|
|
connect( d->m_manager, TQT_SIGNAL( partRemoved( KParts::Part * ) ),
|
|
this, TQT_SLOT( slotPartRemoved( KParts::Part * ) ) );
|
|
}
|
|
|
|
return d->m_manager;
|
|
}
|
|
|
|
void KHTMLPart::submitFormAgain()
|
|
{
|
|
disconnect(this, TQT_SIGNAL(completed()), this, TQT_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 TQString &url, const TQByteArray &formData, const TQString &_target, const TQString& contentType, const TQString& boundary )
|
|
{
|
|
submitForm(action, url, formData, _target, contentType, boundary);
|
|
}
|
|
|
|
void KHTMLPart::submitForm( const char *action, const TQString &url, const TQByteArray &formData, const TQString &_target, const TQString& contentType, const TQString& 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();
|
|
TQString grpNotifMsgs = TQString::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
|
|
//
|
|
|
|
TQString urlstring = u.url();
|
|
|
|
if ( urlstring.find( TQString::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
|
|
TQString q = u.query().mid(1);
|
|
TQStringList nvps = TQStringList::split("&", q);
|
|
bool triedToAttach = false;
|
|
|
|
TQStringList::Iterator nvp = nvps.begin();
|
|
const TQStringList::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 TQStringList pair = TQStringList::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=
|
|
TQString bodyEnc;
|
|
if (contentType.lower() == "multipart/form-data") {
|
|
// FIXME: is this correct? I suspect not
|
|
bodyEnc = KURL::encode_string(TQString::fromLatin1(formData.data(),
|
|
formData.size()));
|
|
} else if (contentType.lower() == "text/plain") {
|
|
// Convention seems to be to decode, and s/&/\n/
|
|
TQString tmpbody = TQString::fromLatin1(formData.data(),
|
|
formData.size());
|
|
tmpbody.replace(TQRegExp("[&]"), "\n");
|
|
tmpbody.replace(TQRegExp("[+]"), " ");
|
|
tmpbody = KURL::decode_string(tmpbody); // Decode the rest of it
|
|
bodyEnc = KURL::encode_string(tmpbody); // Recode for the URL
|
|
} else {
|
|
bodyEnc = KURL::encode_string(TQString::fromLatin1(formData.data(),
|
|
formData.size()));
|
|
}
|
|
|
|
nvps.append(TQString("body=%1").arg(bodyEnc));
|
|
q = nvps.join("&");
|
|
u.setQuery(q);
|
|
}
|
|
|
|
if ( strcmp( action, "get" ) == 0 ) {
|
|
if (u.protocol() != "mailto")
|
|
u.setQuery( TQString::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, TQT_SIGNAL(completed()), this, TQT_SLOT(submitFormAgain()));
|
|
}
|
|
else
|
|
{
|
|
emit d->m_extension->openURLRequest( u, args );
|
|
}
|
|
}
|
|
|
|
void KHTMLPart::popupMenu( const TQString &linkUrl )
|
|
{
|
|
KURL popupURL;
|
|
KURL linkKURL;
|
|
KParts::URLArgs args;
|
|
TQString 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 );
|
|
TQGuardedPtr<TQObject> guard( client );
|
|
|
|
TQString mimetype = TQString::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 TQString 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, TQCursor::pos(), popupURL, args, itemflags, S_IFREG /*always a file*/);
|
|
|
|
if ( !guard.isNull() ) {
|
|
delete client;
|
|
emit popupMenu(linkUrl, TQCursor::pos());
|
|
d->m_strSelectedURL = d->m_strSelectedURLTarget = TQString();
|
|
}
|
|
}
|
|
|
|
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( TQT_TQOBJECT_CONST(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( TQT_TQOBJECT_CONST(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, TQT_SIGNAL( docCreated() ), this, TQT_SLOT( slotChildDocCreated() ) );
|
|
}
|
|
|
|
void KHTMLPart::slotChildURLRequest( const KURL &url, const KParts::URLArgs &args )
|
|
{
|
|
khtml::ChildFrame *child = frame( TQT_TQOBJECT_CONST(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
|
|
TQString urlStr = url.url();
|
|
if ( urlStr.find( TQString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
|
|
TQString script = KURL::decode_string( urlStr.right( urlStr.length() - 11 ) );
|
|
executeScript( DOM::Node(), script );
|
|
return;
|
|
}
|
|
|
|
TQString frameName = args.frameName.lower();
|
|
if ( !frameName.isEmpty() ) {
|
|
if ( frameName == TQString::fromLatin1( "_top" ) )
|
|
{
|
|
emit d->m_extension->openURLRequest( url, args );
|
|
return;
|
|
}
|
|
else if ( frameName == TQString::fromLatin1( "_blank" ) )
|
|
{
|
|
emit d->m_extension->createNewWindow( url, args );
|
|
return;
|
|
}
|
|
else if ( frameName == TQString::fromLatin1( "_parent" ) )
|
|
{
|
|
KParts::URLArgs newArgs( args );
|
|
newArgs.frameName = TQString();
|
|
|
|
emit d->m_extension->openURLRequest( url, newArgs );
|
|
return;
|
|
}
|
|
else if ( frameName != TQString::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 = TQString();
|
|
emit d->m_extension->openURLRequest( url, newArgs );
|
|
}
|
|
}
|
|
|
|
void KHTMLPart::slotRequestFocus( KParts::ReadOnlyPart * )
|
|
{
|
|
emit d->m_extension->requestFocus(this);
|
|
}
|
|
|
|
khtml::ChildFrame *KHTMLPart::frame( const TQObject *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 TQString &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() && (TQString::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 TQString &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 TQString &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 TQString &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 = ::tqqt_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 ::tqqt_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( TQDataStream &stream )
|
|
{
|
|
#ifndef NDEBUG
|
|
TQString indent = TQString().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 << (TQ_INT32)d->m_view->contentsX() << (TQ_INT32)d->m_view->contentsY()
|
|
<< (TQ_INT32) d->m_view->contentsWidth() << (TQ_INT32) d->m_view->contentsHeight() << (TQ_INT32) d->m_view->marginWidth() << (TQ_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)
|
|
TQStringList 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;
|
|
|
|
|
|
TQStringList frameNameLst, frameServiceTypeLst, frameServiceNameLst;
|
|
KURL::List frameURLLst;
|
|
TQValueList<TQByteArray> 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();
|
|
|
|
TQByteArray state;
|
|
TQDataStream frameStream( state, IO_WriteOnly );
|
|
|
|
if ( (*it)->m_extension )
|
|
(*it)->m_extension->saveState( frameStream );
|
|
|
|
frameStateBufferLst << state;
|
|
}
|
|
|
|
// Save frame data
|
|
stream << (TQ_UINT32) frameNameLst.count();
|
|
stream << frameNameLst << frameServiceTypeLst << frameServiceNameLst << frameURLLst << frameStateBufferLst;
|
|
#ifndef NDEBUG
|
|
s_saveStateIndentLevel = indentLevel;
|
|
#endif
|
|
}
|
|
|
|
void KHTMLPart::restoreState( TQDataStream &stream )
|
|
{
|
|
KURL u;
|
|
TQ_INT32 xOffset, yOffset, wContents, hContents, mWidth, mHeight;
|
|
TQ_UINT32 frameCount;
|
|
TQStringList frameNames, frameServiceTypes, docState, frameServiceNames;
|
|
KURL::List frameURLs;
|
|
TQValueList<TQByteArray> frameStateBuffers;
|
|
TQValueList<int> fSizes;
|
|
TQString 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();
|
|
|
|
TQStringList::ConstIterator fNameIt = frameNames.begin();
|
|
TQStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
|
|
TQStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
|
|
KURL::List::ConstIterator fURLIt = frameURLs.begin();
|
|
TQValueList<TQByteArray>::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() )
|
|
{
|
|
TQDataStream 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;
|
|
|
|
TQStringList::ConstIterator fNameIt = frameNames.begin();
|
|
const TQStringList::ConstIterator fNameEnd = frameNames.end();
|
|
|
|
TQStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
|
|
TQStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
|
|
KURL::List::ConstIterator fURLIt = frameURLs.begin();
|
|
TQValueList<TQByteArray>::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() )
|
|
{
|
|
TQDataStream 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) {
|
|
TQApplication::setOverrideCursor( tqwaitCursor );
|
|
if (d->m_doc->styleSelector())
|
|
d->m_doc->styleSelector()->computeFontSizes(d->m_doc->paintDeviceMetrics(), d->m_zoomFactor);
|
|
d->m_doc->recalcStyle( NodeImpl::Force );
|
|
TQApplication::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 TQString& text, StatusBarPriority p)
|
|
{
|
|
if (!d->m_statusMessagesEnabled)
|
|
return;
|
|
|
|
d->m_statusBarText[p] = text;
|
|
|
|
// shift handling ?
|
|
TQString 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 TQString &text )
|
|
{
|
|
setStatusBarText(text, BarOverrideText);
|
|
}
|
|
|
|
void KHTMLPart::setJSDefaultStatusBarText( const TQString &text )
|
|
{
|
|
setStatusBarText(text, BarDefaultText);
|
|
}
|
|
|
|
TQString KHTMLPart::jsStatusBarText() const
|
|
{
|
|
return d->m_statusBarText[BarOverrideText];
|
|
}
|
|
|
|
TQString KHTMLPart::jsDefaultStatusBarText() const
|
|
{
|
|
return d->m_statusBarText[BarDefaultText];
|
|
}
|
|
|
|
TQString KHTMLPart::referrer() const
|
|
{
|
|
return d->m_referrer;
|
|
}
|
|
|
|
TQString KHTMLPart::pageReferrer() const
|
|
{
|
|
KURL referrerURL = KURL( d->m_pageReferrer );
|
|
if (referrerURL.isValid())
|
|
{
|
|
TQString protocol = referrerURL.protocol();
|
|
|
|
if ((protocol == "http") ||
|
|
((protocol == "https") && (m_url.protocol() == "https")))
|
|
{
|
|
referrerURL.setRef(TQString());
|
|
referrerURL.setUser(TQString());
|
|
referrerURL.setPass(TQString());
|
|
return referrerURL.url();
|
|
}
|
|
}
|
|
|
|
return TQString();
|
|
}
|
|
|
|
|
|
TQString 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.
|
|
TQDateTime lastModif = TQFileInfo( 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());
|
|
|
|
TQApplication::setOverrideCursor( tqwaitCursor );
|
|
khtml::CSSStyleSelector::reparseConfiguration();
|
|
if(d->m_doc) d->m_doc->updateStyleSelector();
|
|
TQApplication::restoreOverrideCursor();
|
|
|
|
if (KHTMLFactory::defaultHTMLSettings()->isAdFilterEnabled())
|
|
runAdFilter();
|
|
}
|
|
|
|
TQStringList KHTMLPart::frameNames() const
|
|
{
|
|
TQStringList 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;
|
|
}
|
|
|
|
TQPtrList<KParts::ReadOnlyPart> KHTMLPart::frames() const
|
|
{
|
|
TQPtrList<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( TQCustomEvent *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 );
|
|
}
|
|
|
|
/** returns the position of the first inline text box of the line at
|
|
* coordinate y in renderNode
|
|
*
|
|
* This is a helper function for line-by-line text selection.
|
|
*/
|
|
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;
|
|
}
|
|
|
|
/** returns the position of the last inline text box of the line at
|
|
* coordinate y in renderNode
|
|
*
|
|
* This is a helper function for line-by-line text selection.
|
|
*/
|
|
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();
|
|
TQMouseEvent *_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 = TQString();
|
|
|
|
if ( _mouse->button() == Qt::LeftButton ||
|
|
_mouse->button() == Qt::MidButton )
|
|
{
|
|
d->m_bMousePressed = true;
|
|
|
|
#ifndef KHTML_NO_SELECTION
|
|
if ( _mouse->button() == Qt::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() == Qt::RightButton && parentPart() != 0 && d->m_bBackRightClick )
|
|
{
|
|
d->m_bRightMousePressed = true;
|
|
} else if ( _mouse->button() == Qt::RightButton )
|
|
{
|
|
popupMenu( d->m_strSelectedURL );
|
|
// might be deleted, don't touch "this"
|
|
}
|
|
}
|
|
|
|
void KHTMLPart::khtmlMouseDoubleClickEvent( khtml::MouseDoubleClickEvent *event )
|
|
{
|
|
TQMouseEvent *_mouse = event->qmouseEvent();
|
|
if ( _mouse->button() == Qt::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;
|
|
}
|
|
|
|
TQString 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;
|
|
TQChar 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 = TQString();
|
|
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=" << TQString(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 )
|
|
{
|
|
TQMouseEvent *_mouse = event->qmouseEvent();
|
|
|
|
if( d->m_bRightMousePressed && parentPart() != 0 && d->m_bBackRightClick )
|
|
{
|
|
popupMenu( d->m_strSelectedURL );
|
|
d->m_strSelectedURL = d->m_strSelectedURLTarget = TQString();
|
|
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;
|
|
|
|
TQPixmap pix;
|
|
HTMLImageElementImpl *img = 0L;
|
|
TQDragObject *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(TQString());
|
|
|
|
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 TQImageDrag( 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 = TQString();
|
|
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() + TQString("?%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() & Qt::LeftButton) != 0 )) {
|
|
extendSelectionTo(event->x(), event->y(),
|
|
event->absX(), event->absY(), innerNode);
|
|
#else
|
|
if ( d->m_doc && d->m_view ) {
|
|
TQPoint 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(TQString(), BarHoverText);
|
|
stopAutoScroll();
|
|
}
|
|
|
|
// Used to prevent mouseMoveEvent from initiating a drag before
|
|
// the mouse is pressed again.
|
|
d->m_bMousePressed = false;
|
|
|
|
TQMouseEvent *_mouse = event->qmouseEvent();
|
|
if ( _mouse->button() == Qt::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() == Qt::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
|
|
TQString text = selectedText();
|
|
text.replace(TQChar(0xa0), ' ');
|
|
disconnect( kapp->tqclipboard(), TQT_SIGNAL( selectionChanged()), this, TQT_SLOT( slotClearSelection()));
|
|
kapp->tqclipboard()->setText(text,TQClipboard::Selection);
|
|
connect( kapp->tqclipboard(), TQT_SIGNAL( selectionChanged()), TQT_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 )
|
|
{
|
|
TQPtrList<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;
|
|
|
|
TQMetaObject *mo = ext->metaObject();
|
|
|
|
int idx = mo->findSlot( "print()", true );
|
|
if ( idx >= 0 ) {
|
|
TQUObject 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, TQT_SIGNAL( timeout() ), this, TQT_SLOT( slotAutoScroll() ));
|
|
d->m_scrollTimer.start(100, false);
|
|
}
|
|
|
|
void KHTMLPart::stopAutoScroll()
|
|
{
|
|
disconnect(&d->m_scrollTimer, TQT_SIGNAL( timeout() ), this, TQT_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;
|
|
|
|
TQPtrDictIterator<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 TQString &message, const TQString &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( TQFRAME_OBJECT_NAME_STRING ) )
|
|
{
|
|
TQFrame *frame = static_cast<TQFrame *>( d->m_activeFrame->widget() );
|
|
if (frame->frameStyle() != TQFrame::NoFrame)
|
|
{
|
|
frame->setFrameStyle( TQFrame::StyledPanel | TQFrame::Sunken);
|
|
frame->tqrepaint();
|
|
}
|
|
}
|
|
|
|
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( TQFRAME_OBJECT_NAME_STRING ) )
|
|
{
|
|
TQFrame *frame = static_cast<TQFrame *>( d->m_activeFrame->widget() );
|
|
if (frame->frameStyle() != TQFrame::NoFrame)
|
|
{
|
|
frame->setFrameStyle( TQFrame::StyledPanel | TQFrame::Plain);
|
|
frame->tqrepaint();
|
|
}
|
|
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
|
|
TQRect 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( TQString code, TQString 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 TQString &url, const TQString &stylesheet)
|
|
{
|
|
khtml::Cache::preloadStyleSheet(url, stylesheet);
|
|
}
|
|
|
|
void KHTMLPart::preloadScript(const TQString &url, const TQString &script)
|
|
{
|
|
khtml::Cache::preloadScript(url, script);
|
|
}
|
|
|
|
TQCString KHTMLPart::dcopObjectId() const
|
|
{
|
|
TQCString 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 TQString& 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 TQString& 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( TQString(), 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, TQT_SIGNAL(finishedLayout()), this, TQT_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, TQT_SIGNAL(finishedLayout()), this, TQT_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, TQT_SIGNAL(walletOpened(bool)), d->m_wq, TQT_SLOT(walletOpened(bool)));
|
|
connect(d->m_wq, TQT_SIGNAL(walletOpened(KWallet::Wallet*)), this, TQT_SLOT(walletOpened(KWallet::Wallet*)));
|
|
}
|
|
assert(form);
|
|
d->m_wq->callers.append(KHTMLWalletQueue::Caller(form, form->getDocument()));
|
|
#endif // KHTML_NO_WALLET
|
|
}
|
|
|
|
|
|
void KHTMLPart::saveToWallet(const TQString& key, const TQMap<TQString,TQString>& 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, TQT_SIGNAL(walletOpened(bool)), d->m_wq, TQT_SLOT(walletOpened(bool)));
|
|
connect(d->m_wq, TQT_SIGNAL(walletOpened(KWallet::Wallet*)), this, TQT_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, TQT_SIGNAL(walletClosed()), TQT_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(TQSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::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, TQT_SIGNAL(leftClickedURL()), TQT_SLOT(launchWalletManager()));
|
|
connect(d->m_statusBarWalletLabel, TQT_SIGNAL(rightClickedURL()), TQT_SLOT(walletMenu()));
|
|
} else {
|
|
TQToolTip::remove(d->m_statusBarWalletLabel);
|
|
}
|
|
TQToolTip::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, TQT_SLOT(slotWalletClosed()));
|
|
m->popup(TQCursor::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, TQT_SLOT( slotDebugScript() ), actionCollection(), "debugScript" );
|
|
}
|
|
d->m_paDebugScript->setEnabled( d->m_frame ? d->m_frame->m_jscript : 0L );
|
|
TQPtrList<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( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ));
|
|
d->m_statusBarPopupLabel->setUseCursor( false );
|
|
d->m_statusBarExtension->addStatusBarItem( d->m_statusBarPopupLabel, 0, false );
|
|
d->m_statusBarPopupLabel->setPixmap( SmallIcon( "window_suppressed", instance() ) );
|
|
TQToolTip::add( d->m_statusBarPopupLabel, i18n("This page was prevented from opening a new window via JavaScript." ) );
|
|
|
|
connect(d->m_statusBarPopupLabel, TQT_SIGNAL(leftClickedURL()), TQT_SLOT(suppressedPopupMenu()));
|
|
if (d->m_settings->jsPopupBlockerPassivePopup()) {
|
|
TQPixmap 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 ) {
|
|
TQToolTip::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, TQT_SLOT(showSuppressedPopups()));
|
|
m->insertItem(i18n("Show Blocked Window Passive Popup &Notification"), this, TQT_SLOT(togglePopupPassivePopup()),0,57);
|
|
m->setItemChecked(57,d->m_settings->jsPopupBlockerPassivePopup());
|
|
m->insertItem(i18n("&Configure JavaScript New Window Policies..."), this, TQT_SLOT(launchJSConfigDialog()));
|
|
m->popup(TQCursor::pos());
|
|
}
|
|
|
|
void KHTMLPart::togglePopupPassivePopup() {
|
|
// Same hack as in disableJSErrorExtension()
|
|
d->m_settings->setJSPopupBlockerPassivePopup( !d->m_settings->jsPopupBlockerPassivePopup() );
|
|
DCOPClient::mainClient()->send("konqueror*", "KonquerorIface", "reparseConfiguration()", TQByteArray());
|
|
}
|
|
|
|
void KHTMLPart::showSuppressedPopups() {
|
|
for ( TQValueListIterator<TQGuardedPtr<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)
|
|
TQString 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"
|