TDE core libraries
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
240KB

  1. // -*- c-basic-offset: 2 -*-
  2. /* This file is part of the KDE project
  3. *
  4. * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
  5. * 1999 Lars Knoll <knoll@kde.org>
  6. * 1999 Antti Koivisto <koivisto@kde.org>
  7. * 2000 Simon Hausmann <hausmann@kde.org>
  8. * 2000 Stefan Schimanski <1Stein@gmx.de>
  9. * 2001-2003 George Staikos <staikos@kde.org>
  10. * 2001-2003 Dirk Mueller <mueller@kde.org>
  11. * 2000-2005 David Faure <faure@kde.org>
  12. * 2002 Apple Computer, Inc.
  13. *
  14. * This library is free software; you can redistribute it and/or
  15. * modify it under the terms of the GNU Library General Public
  16. * License as published by the Free Software Foundation; either
  17. * version 2 of the License, or (at your option) any later version.
  18. *
  19. * This library is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  22. * Library General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU Library General Public License
  25. * along with this library; see the file COPYING.LIB. If not, write to
  26. * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  27. * Boston, MA 02110-1301, USA.
  28. */
  29. //#define SPEED_DEBUG
  30. #include "khtml_part.h"
  31. #include "khtml_pagecache.h"
  32. #include "dom/dom_string.h"
  33. #include "dom/dom_element.h"
  34. #include "dom/dom_exception.h"
  35. #include "html/html_documentimpl.h"
  36. #include "html/html_baseimpl.h"
  37. #include "html/html_objectimpl.h"
  38. #include "html/html_miscimpl.h"
  39. #include "html/html_imageimpl.h"
  40. #include "html/html_objectimpl.h"
  41. #include "rendering/render_text.h"
  42. #include "rendering/render_frames.h"
  43. #include "rendering/render_layer.h"
  44. #include "misc/htmlhashes.h"
  45. #include "misc/loader.h"
  46. #include "xml/dom2_eventsimpl.h"
  47. #include "xml/dom2_rangeimpl.h"
  48. #include "xml/xml_tokenizer.h"
  49. #include "css/cssstyleselector.h"
  50. #include "css/csshelper.h"
  51. using namespace DOM;
  52. #include "khtmlview.h"
  53. #include <kparts/partmanager.h>
  54. #include "ecma/kjs_proxy.h"
  55. #include "ecma/kjs_window.h"
  56. #include "khtml_settings.h"
  57. #include "kjserrordlg.h"
  58. #include <kjs/function.h>
  59. #include <kjs/interpreter.h>
  60. #include "htmlpageinfo.h"
  61. #include <sys/types.h>
  62. #include <assert.h>
  63. #include <unistd.h>
  64. #include <config.h>
  65. #include <dcopclient.h>
  66. #include <dcopref.h>
  67. #include <kstandarddirs.h>
  68. #include <kstringhandler.h>
  69. #include <kio/job.h>
  70. #include <kio/global.h>
  71. #include <kio/netaccess.h>
  72. #include <kprotocolmanager.h>
  73. #include <kdebug.h>
  74. #include <kiconloader.h>
  75. #include <klocale.h>
  76. #include <kcharsets.h>
  77. #include <kmessagebox.h>
  78. #include <kstdaction.h>
  79. #include <kfiledialog.h>
  80. #include <ktrader.h>
  81. #include <kdatastream.h>
  82. #include <ktempfile.h>
  83. #include <kglobalsettings.h>
  84. #include <kurldrag.h>
  85. #include <kapplication.h>
  86. #include <kparts/browserinterface.h>
  87. #if !defined(QT_NO_DRAGANDDROP)
  88. #include <kmultipledrag.h>
  89. #endif
  90. #include "../kutils/kfinddialog.h"
  91. #include "../kutils/kfind.h"
  92. #include <ksslcertchain.h>
  93. #include <ksslinfodlg.h>
  94. #include <kfileitem.h>
  95. #include <kurifilter.h>
  96. #include <kstatusbar.h>
  97. #include <kurllabel.h>
  98. #include <tqclipboard.h>
  99. #include <tqfile.h>
  100. #include <tqtooltip.h>
  101. #include <tqmetaobject.h>
  102. #include <tqucomextra_p.h>
  103. #include "khtmlpart_p.h"
  104. #include "kpassivepopup.h"
  105. #include "kpopupmenu.h"
  106. #include "rendering/render_form.h"
  107. #include <twin.h>
  108. #define HINT_UTF8 106
  109. namespace khtml {
  110. class PartStyleSheetLoader : public CachedObjectClient
  111. {
  112. public:
  113. PartStyleSheetLoader(KHTMLPart *part, DOM::DOMString url, DocLoader* dl)
  114. {
  115. m_part = part;
  116. m_cachedSheet = dl->requestStyleSheet(url, TQString(), "text/css",
  117. true /* "user sheet" */);
  118. if (m_cachedSheet)
  119. m_cachedSheet->ref( this );
  120. }
  121. virtual ~PartStyleSheetLoader()
  122. {
  123. if ( m_cachedSheet ) m_cachedSheet->deref(this);
  124. }
  125. virtual void setStyleSheet(const DOM::DOMString&, const DOM::DOMString &sheet, const DOM::DOMString &)
  126. {
  127. if ( m_part )
  128. m_part->setUserStyleSheet( sheet.string() );
  129. delete this;
  130. }
  131. virtual void error( int, const TQString& ) {
  132. delete this;
  133. }
  134. TQGuardedPtr<KHTMLPart> m_part;
  135. khtml::CachedCSSStyleSheet *m_cachedSheet;
  136. };
  137. }
  138. void khtml::ChildFrame::liveConnectEvent(const unsigned long, const TQString & event, const KParts::LiveConnectExtension::ArgList & args)
  139. {
  140. if (!m_part || !m_frame || !m_liveconnect)
  141. // hmmm
  142. return;
  143. TQString script;
  144. script.sprintf("%s(", event.latin1());
  145. KParts::LiveConnectExtension::ArgList::const_iterator i = args.begin();
  146. const KParts::LiveConnectExtension::ArgList::const_iterator argsBegin = i;
  147. const KParts::LiveConnectExtension::ArgList::const_iterator argsEnd = args.end();
  148. for ( ; i != argsEnd; ++i) {
  149. if (i != argsBegin)
  150. script += ",";
  151. if ((*i).first == KParts::LiveConnectExtension::TypeString) {
  152. script += "\"";
  153. script += TQString((*i).second).replace('\\', "\\\\").replace('"', "\\\"");
  154. script += "\"";
  155. } else
  156. script += (*i).second;
  157. }
  158. script += ")";
  159. kdDebug(6050) << "khtml::ChildFrame::liveConnectEvent " << script << endl;
  160. KHTMLPart * part = ::tqqt_cast<KHTMLPart *>(m_part->parent());
  161. if (!part)
  162. return;
  163. if (!m_jscript)
  164. part->framejScript(m_part);
  165. if (m_jscript) {
  166. // we have a jscript => a part in an iframe
  167. KJS::Completion cmp;
  168. m_jscript->evaluate(TQString(), 1, script, 0L, &cmp);
  169. } else
  170. part->executeScript(m_frame->element(), script);
  171. }
  172. KHTMLFrameList::Iterator KHTMLFrameList::find( const TQString &name )
  173. {
  174. Iterator it = begin();
  175. const Iterator e = end();
  176. for (; it!=e; ++it )
  177. if ( (*it)->m_name==name )
  178. break;
  179. return it;
  180. }
  181. KHTMLPart::KHTMLPart( TQWidget *parentWidget, const char *widgetname, TQObject *parent, const char *name, GUIProfile prof )
  182. : KParts::ReadOnlyPart( parent, name )
  183. {
  184. d = 0;
  185. KHTMLFactory::registerPart( this );
  186. setInstance( KHTMLFactory::instance(), prof == BrowserViewGUI && !parentPart() );
  187. // TODO KDE4 - don't load plugins yet
  188. //setInstance( KHTMLFactory::instance(), false );
  189. init( new KHTMLView( this, parentWidget, widgetname ), prof );
  190. }
  191. KHTMLPart::KHTMLPart( KHTMLView *view, TQObject *parent, const char *name, GUIProfile prof )
  192. : KParts::ReadOnlyPart( parent, name )
  193. {
  194. d = 0;
  195. KHTMLFactory::registerPart( this );
  196. setInstance( KHTMLFactory::instance(), prof == BrowserViewGUI && !parentPart() );
  197. // TODO KDE4 - don't load plugins yet
  198. //setInstance( KHTMLFactory::instance(), false );
  199. assert( view );
  200. init( view, prof );
  201. }
  202. void KHTMLPart::init( KHTMLView *view, GUIProfile prof )
  203. {
  204. if ( prof == DefaultGUI )
  205. setXMLFile( "khtml.rc" );
  206. else if ( prof == BrowserViewGUI )
  207. setXMLFile( "khtml_browser.rc" );
  208. d = new KHTMLPartPrivate(parent());
  209. d->m_view = view;
  210. setWidget( d->m_view );
  211. d->m_guiProfile = prof;
  212. d->m_extension = new KHTMLPartBrowserExtension( this, "KHTMLBrowserExtension" );
  213. d->m_hostExtension = new KHTMLPartBrowserHostExtension( this );
  214. d->m_statusBarExtension = new KParts::StatusBarExtension( this );
  215. d->m_statusBarIconLabel = 0L;
  216. d->m_statusBarPopupLabel = 0L;
  217. d->m_openableSuppressedPopups = 0;
  218. d->m_bSecurityInQuestion = false;
  219. d->m_paLoadImages = 0;
  220. d->m_paDebugScript = 0;
  221. d->m_bMousePressed = false;
  222. d->m_bRightMousePressed = false;
  223. d->m_bCleared = false;
  224. d->m_paViewDocument = new KAction( i18n( "View Do&cument Source" ), CTRL + Key_U, this, TQT_SLOT( slotViewDocumentSource() ), actionCollection(), "viewDocumentSource" );
  225. d->m_paViewFrame = new KAction( i18n( "View Frame Source" ), 0, this, TQT_SLOT( slotViewFrameSource() ), actionCollection(), "viewFrameSource" );
  226. d->m_paViewInfo = new KAction( i18n( "View Document Information" ), CTRL+Key_I, this, TQT_SLOT( slotViewPageInfo() ), actionCollection(), "viewPageInfo" );
  227. d->m_paSaveBackground = new KAction( i18n( "Save &Background Image As..." ), 0, this, TQT_SLOT( slotSaveBackground() ), actionCollection(), "saveBackground" );
  228. d->m_paSaveDocument = KStdAction::saveAs( this, TQT_SLOT( slotSaveDocument() ), actionCollection(), "saveDocument" );
  229. if ( parentPart() )
  230. d->m_paSaveDocument->setShortcut( KShortcut() ); // avoid clashes
  231. d->m_paSaveFrame = new KAction( i18n( "Save &Frame As..." ), 0, this, TQT_SLOT( slotSaveFrame() ), actionCollection(), "saveFrame" );
  232. d->m_paSecurity = new KAction( i18n( "Security..." ), "decrypted", 0, this, TQT_SLOT( slotSecurity() ), actionCollection(), "security" );
  233. d->m_paSecurity->setWhatsThis( i18n( "Security Settings<p>"
  234. "Shows the certificate of the displayed page. Only "
  235. "pages that have been transmitted using a secure, encrypted connection have a "
  236. "certificate.<p> "
  237. "Hint: If the image shows a closed lock, the page has been transmitted over a "
  238. "secure connection.") );
  239. d->m_paDebugRenderTree = new KAction( i18n( "Print Rendering Tree to STDOUT" ), ALT + CTRL + SHIFT + Key_A, this, TQT_SLOT( slotDebugRenderTree() ), actionCollection(), "debugRenderTree" );
  240. d->m_paDebugDOMTree = new KAction( i18n( "Print DOM Tree to STDOUT" ), ALT + CTRL + SHIFT + Key_D, this, TQT_SLOT( slotDebugDOMTree() ), actionCollection(), "debugDOMTree" );
  241. d->m_paStopAnimations = new KAction( i18n( "Stop Animated Images" ), 0, this, TQT_SLOT( slotStopAnimations() ), actionCollection(), "stopAnimations" );
  242. d->m_paSetEncoding = new KActionMenu( i18n( "Set &Encoding" ), "charset", actionCollection(), "setEncoding" );
  243. d->m_paSetEncoding->setDelayed( false );
  244. d->m_automaticDetection = new KPopupMenu( 0L );
  245. d->m_automaticDetection->insertItem( i18n( "Semi-Automatic" ), 0 );
  246. d->m_automaticDetection->insertItem( i18n( "Arabic" ), 1 );
  247. d->m_automaticDetection->insertItem( i18n( "Baltic" ), 2 );
  248. d->m_automaticDetection->insertItem( i18n( "Central European" ), 3 );
  249. //d->m_automaticDetection->insertItem( i18n( "Chinese" ), 4 );
  250. d->m_automaticDetection->insertItem( i18n( "Greek" ), 5 );
  251. d->m_automaticDetection->insertItem( i18n( "Hebrew" ), 6 );
  252. d->m_automaticDetection->insertItem( i18n( "Japanese" ), 7 );
  253. //d->m_automaticDetection->insertItem( i18n( "Korean" ), 8 );
  254. d->m_automaticDetection->insertItem( i18n( "Russian" ), 9 );
  255. //d->m_automaticDetection->insertItem( i18n( "Thai" ), 10 );
  256. d->m_automaticDetection->insertItem( i18n( "Turkish" ), 11 );
  257. d->m_automaticDetection->insertItem( i18n( "Ukrainian" ), 12 );
  258. //d->m_automaticDetection->insertItem( i18n( "Unicode" ), 13 );
  259. d->m_automaticDetection->insertItem( i18n( "Western European" ), 14 );
  260. connect( d->m_automaticDetection, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( slotAutomaticDetectionLanguage( int ) ) );
  261. d->m_paSetEncoding->popupMenu()->insertItem( i18n( "Automatic Detection" ), d->m_automaticDetection, 0 );
  262. d->m_paSetEncoding->insert( new KActionSeparator( actionCollection() ) );
  263. d->m_manualDetection = new KSelectAction( i18n( "short for Manual Detection", "Manual" ), 0, this, TQT_SLOT( slotSetEncoding() ), actionCollection(), "manualDetection" );
  264. TQStringList encodings = KGlobal::charsets()->descriptiveEncodingNames();
  265. d->m_manualDetection->setItems( encodings );
  266. d->m_manualDetection->setCurrentItem( -1 );
  267. d->m_paSetEncoding->insert( d->m_manualDetection );
  268. KConfig *config = KGlobal::config();
  269. if ( config->hasGroup( "HTML Settings" ) ) {
  270. config->setGroup( "HTML Settings" );
  271. khtml::Decoder::AutoDetectLanguage language;
  272. TQCString name = TQTextCodec::codecForLocale()->name();
  273. name = name.lower();
  274. if ( name == "cp1256" || name == "iso-8859-6" ) {
  275. language = khtml::Decoder::Arabic;
  276. }
  277. else if ( name == "cp1257" || name == "iso-8859-13" || name == "iso-8859-4" ) {
  278. language = khtml::Decoder::Baltic;
  279. }
  280. else if ( name == "cp1250" || name == "ibm852" || name == "iso-8859-2" || name == "iso-8859-3" ) {
  281. language = khtml::Decoder::CentralEuropean;
  282. }
  283. else if ( name == "cp1251" || name == "koi8-r" || name == "iso-8859-5" ) {
  284. language = khtml::Decoder::Russian;
  285. }
  286. else if ( name == "koi8-u" ) {
  287. language = khtml::Decoder::Ukrainian;
  288. }
  289. else if ( name == "cp1253" || name == "iso-8859-7" ) {
  290. language = khtml::Decoder::Greek;
  291. }
  292. else if ( name == "cp1255" || name == "iso-8859-8" || name == "iso-8859-8-i" ) {
  293. language = khtml::Decoder::Hebrew;
  294. }
  295. else if ( name == "jis7" || name == "eucjp" || name == "sjis" ) {
  296. language = khtml::Decoder::Japanese;
  297. }
  298. else if ( name == "cp1254" || name == "iso-8859-9" ) {
  299. language = khtml::Decoder::Turkish;
  300. }
  301. else if ( name == "cp1252" || name == "iso-8859-1" || name == "iso-8859-15" ) {
  302. language = khtml::Decoder::WesternEuropean;
  303. }
  304. else
  305. language = khtml::Decoder::SemiautomaticDetection;
  306. int _id = config->readNumEntry( "AutomaticDetectionLanguage", language );
  307. d->m_automaticDetection->setItemChecked( _id, true );
  308. d->m_paSetEncoding->popupMenu()->setItemChecked( 0, true );
  309. d->m_autoDetectLanguage = static_cast< khtml::Decoder::AutoDetectLanguage >( _id );
  310. }
  311. d->m_paUseStylesheet = new KSelectAction( i18n( "Use S&tylesheet"), 0, this, TQT_SLOT( slotUseStylesheet() ), actionCollection(), "useStylesheet" );
  312. if ( prof == BrowserViewGUI ) {
  313. d->m_paIncZoomFactor = new KHTMLZoomFactorAction( this, true, i18n(
  314. "Enlarge Font" ), "viewmag+", "CTRL++;CTRL+=", this,
  315. TQT_SLOT( slotIncZoomFast() ), actionCollection(), "incFontSizes" );
  316. d->m_paIncZoomFactor->setWhatsThis( i18n( "Enlarge Font<p>"
  317. "Make the font in this window bigger. "
  318. "Click and hold down the mouse button for a menu with all available font sizes." ) );
  319. d->m_paDecZoomFactor = new KHTMLZoomFactorAction( this, false, i18n(
  320. "Shrink Font" ), "viewmag-", CTRL + Key_Minus, this,
  321. TQT_SLOT( slotDecZoomFast() ), actionCollection(), "decFontSizes" );
  322. d->m_paDecZoomFactor->setWhatsThis( i18n( "Shrink Font<p>"
  323. "Make the font in this window smaller. "
  324. "Click and hold down the mouse button for a menu with all available font sizes." ) );
  325. }
  326. d->m_paFind = KStdAction::find( this, TQT_SLOT( slotFind() ), actionCollection(), "find" );
  327. d->m_paFind->setWhatsThis( i18n( "Find text<p>"
  328. "Shows a dialog that allows you to find text on the displayed page." ) );
  329. d->m_paFindNext = KStdAction::findNext( this, TQT_SLOT( slotFindNext() ), actionCollection(), "findNext" );
  330. d->m_paFindNext->setWhatsThis( i18n( "Find next<p>"
  331. "Find the next occurrence of the text that you "
  332. "have found using the <b>Find Text</b> function" ) );
  333. d->m_paFindPrev = KStdAction::findPrev( this, TQT_SLOT( slotFindPrev() ), actionCollection(), "findPrevious" );
  334. d->m_paFindPrev->setWhatsThis( i18n( "Find previous<p>"
  335. "Find the previous occurrence of the text that you "
  336. "have found using the <b>Find Text</b> function" ) );
  337. d->m_paFindAheadText = new KAction( i18n("Find Text as You Type"), KShortcut( '/' ), this, TQT_SLOT( slotFindAheadText()),
  338. actionCollection(), "findAheadText");
  339. d->m_paFindAheadLinks = new KAction( i18n("Find Links as You Type"), KShortcut( '\'' ), this, TQT_SLOT( slotFindAheadLink()),
  340. actionCollection(), "findAheadLink");
  341. d->m_paFindAheadText->setEnabled( false );
  342. d->m_paFindAheadLinks->setEnabled( false );
  343. if ( parentPart() )
  344. {
  345. d->m_paFind->setShortcut( KShortcut() ); // avoid clashes
  346. d->m_paFindNext->setShortcut( KShortcut() ); // avoid clashes
  347. d->m_paFindPrev->setShortcut( KShortcut() ); // avoid clashes
  348. d->m_paFindAheadText->setShortcut( KShortcut());
  349. d->m_paFindAheadLinks->setShortcut( KShortcut());
  350. }
  351. d->m_paPrintFrame = new KAction( i18n( "Print Frame..." ), "frameprint", 0, this, TQT_SLOT( slotPrintFrame() ), actionCollection(), "printFrame" );
  352. d->m_paPrintFrame->setWhatsThis( i18n( "Print Frame<p>"
  353. "Some pages have several frames. To print only a single frame, click "
  354. "on it and then use this function." ) );
  355. d->m_paSelectAll = KStdAction::selectAll( this, TQT_SLOT( slotSelectAll() ), actionCollection(), "selectAll" );
  356. if ( parentPart() )
  357. d->m_paSelectAll->setShortcut( KShortcut() ); // avoid clashes
  358. d->m_paToggleCaretMode = new KToggleAction(i18n("Toggle Caret Mode"),
  359. Key_F7, this, TQT_SLOT(slotToggleCaretMode()),
  360. actionCollection(), "caretMode");
  361. d->m_paToggleCaretMode->setChecked(isCaretMode());
  362. if (parentPart())
  363. d->m_paToggleCaretMode->setShortcut(KShortcut()); // avoid clashes
  364. // set the default java(script) flags according to the current host.
  365. d->m_bOpenMiddleClick = d->m_settings->isOpenMiddleClickEnabled();
  366. d->m_bBackRightClick = d->m_settings->isBackRightClickEnabled();
  367. d->m_bJScriptEnabled = d->m_settings->isJavaScriptEnabled();
  368. setDebugScript( d->m_settings->isJavaScriptDebugEnabled() );
  369. d->m_bJavaEnabled = d->m_settings->isJavaEnabled();
  370. d->m_bPluginsEnabled = d->m_settings->isPluginsEnabled();
  371. // Set the meta-refresh flag...
  372. d->m_metaRefreshEnabled = d->m_settings->isAutoDelayedActionsEnabled ();
  373. connect( view, TQT_SIGNAL( zoomView( int ) ), TQT_SLOT( slotZoomView( int ) ) );
  374. connect( this, TQT_SIGNAL( completed() ),
  375. this, TQT_SLOT( updateActions() ) );
  376. connect( this, TQT_SIGNAL( completed( bool ) ),
  377. this, TQT_SLOT( updateActions() ) );
  378. connect( this, TQT_SIGNAL( started( KIO::Job * ) ),
  379. this, TQT_SLOT( updateActions() ) );
  380. d->m_popupMenuXML = KXMLGUIFactory::readConfigFile( locate( "data", "khtml/khtml_popupmenu.rc", KHTMLFactory::instance() ) );
  381. connect( khtml::Cache::loader(), TQT_SIGNAL( requestStarted( khtml::DocLoader*, khtml::CachedObject* ) ),
  382. this, TQT_SLOT( slotLoaderRequestStarted( khtml::DocLoader*, khtml::CachedObject* ) ) );
  383. connect( khtml::Cache::loader(), TQT_SIGNAL( requestDone( khtml::DocLoader*, khtml::CachedObject *) ),
  384. this, TQT_SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
  385. connect( khtml::Cache::loader(), TQT_SIGNAL( requestFailed( khtml::DocLoader*, khtml::CachedObject *) ),
  386. this, TQT_SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
  387. connect ( &d->m_progressUpdateTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( slotProgressUpdate() ) );
  388. findTextBegin(); //reset find variables
  389. connect( &d->m_redirectionTimer, TQT_SIGNAL( timeout() ),
  390. this, TQT_SLOT( slotRedirect() ) );
  391. d->m_dcopobject = new KHTMLPartIface(this);
  392. // TODO KDE4 - load plugins now (see also the constructors)
  393. //if ( prof == BrowserViewGUI && !parentPart() )
  394. // loadPlugins( partObject(), this, instance() );
  395. // "khtml" catalog does not exist, our translations are in tdelibs.
  396. // removing this catalog from KGlobal::locale() prevents problems
  397. // with changing the language in applications at runtime -Thomas Reitelbach
  398. KGlobal::locale()->removeCatalogue("khtml");
  399. }
  400. KHTMLPart::~KHTMLPart()
  401. {
  402. //kdDebug(6050) << "KHTMLPart::~KHTMLPart " << this << endl;
  403. KConfig *config = KGlobal::config();
  404. config->setGroup( "HTML Settings" );
  405. config->writeEntry( "AutomaticDetectionLanguage", d->m_autoDetectLanguage );
  406. delete d->m_automaticDetection;
  407. delete d->m_manualDetection;
  408. slotWalletClosed();
  409. if (!parentPart()) { // only delete it if the top khtml_part closes
  410. removeJSErrorExtension();
  411. delete d->m_statusBarPopupLabel;
  412. }
  413. d->m_find = 0; // deleted by its parent, the view.
  414. if ( d->m_manager )
  415. {
  416. d->m_manager->setActivePart( 0 );
  417. // We specify "this" as parent qobject for d->manager, so no need to delete it.
  418. }
  419. stopAutoScroll();
  420. d->m_redirectionTimer.stop();
  421. if (!d->m_bComplete)
  422. closeURL();
  423. disconnect( khtml::Cache::loader(), TQT_SIGNAL( requestStarted( khtml::DocLoader*, khtml::CachedObject* ) ),
  424. this, TQT_SLOT( slotLoaderRequestStarted( khtml::DocLoader*, khtml::CachedObject* ) ) );
  425. disconnect( khtml::Cache::loader(), TQT_SIGNAL( requestDone( khtml::DocLoader*, khtml::CachedObject *) ),
  426. this, TQT_SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
  427. disconnect( khtml::Cache::loader(), TQT_SIGNAL( requestFailed( khtml::DocLoader*, khtml::CachedObject *) ),
  428. this, TQT_SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
  429. clear();
  430. if ( d->m_view )
  431. {
  432. d->m_view->hide();
  433. d->m_view->viewport()->hide();
  434. d->m_view->m_part = 0;
  435. }
  436. // Have to delete this here since we forward declare it in khtmlpart_p and
  437. // at least some compilers won't call the destructor in this case.
  438. delete d->m_jsedlg;
  439. d->m_jsedlg = 0;
  440. if (!parentPart()) // only delete d->m_frame if the top khtml_part closes
  441. delete d->m_frame;
  442. delete d; d = 0;
  443. KHTMLFactory::deregisterPart( this );
  444. }
  445. bool KHTMLPart::restoreURL( const KURL &url )
  446. {
  447. kdDebug( 6050 ) << "KHTMLPart::restoreURL " << url.url() << endl;
  448. d->m_redirectionTimer.stop();
  449. /*
  450. * That's not a good idea as it will call closeURL() on all
  451. * child frames, preventing them from further loading. This
  452. * method gets called from restoreState() in case of a full frameset
  453. * restoral, and restoreState() calls closeURL() before restoring
  454. * anyway.
  455. kdDebug( 6050 ) << "closing old URL" << endl;
  456. closeURL();
  457. */
  458. d->m_bComplete = false;
  459. d->m_bLoadEventEmitted = false;
  460. d->m_workingURL = url;
  461. // set the java(script) flags according to the current host.
  462. d->m_bJScriptEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptEnabled(url.host());
  463. setDebugScript( KHTMLFactory::defaultHTMLSettings()->isJavaScriptDebugEnabled() );
  464. d->m_bJavaEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaEnabled(url.host());
  465. d->m_bPluginsEnabled = KHTMLFactory::defaultHTMLSettings()->isPluginsEnabled(url.host());
  466. m_url = url;
  467. d->m_restoreScrollPosition = true;
  468. disconnect(d->m_view, TQT_SIGNAL(finishedLayout()), this, TQT_SLOT(restoreScrollPosition()));
  469. connect(d->m_view, TQT_SIGNAL(finishedLayout()), this, TQT_SLOT(restoreScrollPosition()));
  470. KHTMLPageCache::self()->fetchData( d->m_cacheId, this, TQT_SLOT(slotRestoreData(const TQByteArray &)));
  471. emit started( 0L );
  472. return true;
  473. }
  474. bool KHTMLPart::openURL( const KURL &url )
  475. {
  476. kdDebug( 6050 ) << "KHTMLPart(" << this << ")::openURL " << url.url() << endl;
  477. d->m_redirectionTimer.stop();
  478. // check to see if this is an "error://" URL. This is caused when an error
  479. // occurs before this part was loaded (e.g. KonqRun), and is passed to
  480. // khtmlpart so that it can display the error.
  481. if ( url.protocol() == "error" && url.hasSubURL() ) {
  482. closeURL();
  483. if( d->m_bJScriptEnabled )
  484. d->m_statusBarText[BarOverrideText] = d->m_statusBarText[BarDefaultText] = TQString();
  485. /**
  486. * The format of the error url is that two variables are passed in the query:
  487. * error = int kio error code, errText = TQString error text from kio
  488. * and the URL where the error happened is passed as a sub URL.
  489. */
  490. KURL::List urls = KURL::split( url );
  491. //kdDebug(6050) << "Handling error URL. URL count:" << urls.count() << endl;
  492. if ( urls.count() > 1 ) {
  493. KURL mainURL = urls.first();
  494. int error = mainURL.queryItem( "error" ).toInt();
  495. // error=0 isn't a valid error code, so 0 means it's missing from the URL
  496. if ( error == 0 ) error = KIO::ERR_UNKNOWN;
  497. TQString errorText = mainURL.queryItem( "errText", HINT_UTF8 );
  498. urls.pop_front();
  499. d->m_workingURL = KURL::join( urls );
  500. //kdDebug(6050) << "Emitting fixed URL " << d->m_workingURL.prettyURL() << endl;
  501. emit d->m_extension->setLocationBarURL( d->m_workingURL.prettyURL() );
  502. htmlError( error, errorText, d->m_workingURL );
  503. return true;
  504. }
  505. }
  506. if (!parentPart()) { // only do it for toplevel part
  507. TQString host = url.isLocalFile() ? "localhost" : url.host();
  508. TQString userAgent = KProtocolManager::userAgentForHost(host);
  509. if (userAgent != KProtocolManager::userAgentForHost(TQString())) {
  510. if (!d->m_statusBarUALabel) {
  511. d->m_statusBarUALabel = new KURLLabel(d->m_statusBarExtension->statusBar());
  512. d->m_statusBarUALabel->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small));
  513. d->m_statusBarUALabel->setSizePolicy(TQSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Fixed));
  514. d->m_statusBarUALabel->setUseCursor(false);
  515. d->m_statusBarExtension->addStatusBarItem(d->m_statusBarUALabel, 0, false);
  516. d->m_statusBarUALabel->setPixmap(SmallIcon("agent", instance()));
  517. } else {
  518. TQToolTip::remove(d->m_statusBarUALabel);
  519. }
  520. TQToolTip::add(d->m_statusBarUALabel, i18n("The fake user-agent '%1' is in use.").arg(userAgent));
  521. } else if (d->m_statusBarUALabel) {
  522. d->m_statusBarExtension->removeStatusBarItem(d->m_statusBarUALabel);
  523. delete d->m_statusBarUALabel;
  524. d->m_statusBarUALabel = 0L;
  525. }
  526. }
  527. KParts::URLArgs args( d->m_extension->urlArgs() );
  528. // in case
  529. // a) we have no frameset (don't test m_frames.count(), iframes get in there)
  530. // b) the url is identical with the currently displayed one (except for the htmlref!)
  531. // c) the url request is not a POST operation and
  532. // d) the caller did not request to reload the page
  533. // e) there was no HTTP redirection meanwhile (testcase: webmin's software/tree.cgi)
  534. // => we don't reload the whole document and
  535. // we just jump to the requested html anchor
  536. bool isFrameSet = false;
  537. if ( d->m_doc && d->m_doc->isHTMLDocument() ) {
  538. HTMLDocumentImpl* htmlDoc = static_cast<HTMLDocumentImpl*>(d->m_doc);
  539. isFrameSet = htmlDoc->body() && (htmlDoc->body()->id() == ID_FRAMESET);
  540. }
  541. if ( url.hasRef() && !isFrameSet )
  542. {
  543. bool noReloadForced = !args.reload && !args.redirectedRequest() && !args.doPost();
  544. if (noReloadForced && urlcmp( url.url(), m_url.url(), true, true ))
  545. {
  546. kdDebug( 6050 ) << "KHTMLPart::openURL, jumping to anchor. m_url = " << url.url() << endl;
  547. m_url = url;
  548. emit started( 0L );
  549. if ( !gotoAnchor( url.encodedHtmlRef()) )
  550. gotoAnchor( url.htmlRef() );
  551. d->m_bComplete = true;
  552. if (d->m_doc)
  553. d->m_doc->setParsing(false);
  554. kdDebug( 6050 ) << "completed..." << endl;
  555. emit completed();
  556. return true;
  557. }
  558. }
  559. // Save offset of viewport when page is reloaded to be compliant
  560. // to every other capable browser out there.
  561. if (args.reload) {
  562. args.xOffset = d->m_view->contentsX();
  563. args.yOffset = d->m_view->contentsY();
  564. d->m_extension->setURLArgs(args);
  565. }
  566. if (!d->m_restored)
  567. closeURL();
  568. d->m_restoreScrollPosition = d->m_restored;
  569. disconnect(d->m_view, TQT_SIGNAL(finishedLayout()), this, TQT_SLOT(restoreScrollPosition()));
  570. connect(d->m_view, TQT_SIGNAL(finishedLayout()), this, TQT_SLOT(restoreScrollPosition()));
  571. // 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
  572. // data arrives) (Simon)
  573. m_url = url;
  574. if(m_url.protocol().startsWith( "http" ) && !m_url.host().isEmpty() &&
  575. m_url.path().isEmpty()) {
  576. m_url.setPath("/");
  577. emit d->m_extension->setLocationBarURL( m_url.prettyURL() );
  578. }
  579. // copy to m_workingURL after fixing m_url above
  580. d->m_workingURL = m_url;
  581. args.metaData().insert("main_frame_request", parentPart() == 0 ? "TRUE" : "FALSE" );
  582. args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
  583. args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
  584. args.metaData().insert("PropagateHttpHeader", "true");
  585. args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE" : "FALSE" );
  586. args.metaData().insert("ssl_activate_warnings", "TRUE" );
  587. args.metaData().insert("cross-domain", toplevelURL().url());
  588. if (d->m_restored)
  589. {
  590. args.metaData().insert("referrer", d->m_pageReferrer);
  591. d->m_cachePolicy = KIO::CC_Cache;
  592. }
  593. else if (args.reload)
  594. d->m_cachePolicy = KIO::CC_Reload;
  595. else
  596. d->m_cachePolicy = KProtocolManager::cacheControl();
  597. if ( args.doPost() && (m_url.protocol().startsWith("http")) )
  598. {
  599. d->m_job = KIO::http_post( m_url, args.postData, false );
  600. d->m_job->addMetaData("content-type", args.contentType() );
  601. }
  602. else
  603. {
  604. d->m_job = KIO::get( m_url, false, false );
  605. d->m_job->addMetaData("cache", KIO::getCacheControlString(d->m_cachePolicy));
  606. }
  607. if (widget())
  608. d->m_job->setWindow(widget()->topLevelWidget());
  609. d->m_job->addMetaData(args.metaData());
  610. connect( d->m_job, TQT_SIGNAL( result( KIO::Job* ) ),
  611. TQT_SLOT( slotFinished( KIO::Job* ) ) );
  612. connect( d->m_job, TQT_SIGNAL( data( KIO::Job*, const TQByteArray& ) ),
  613. TQT_SLOT( slotData( KIO::Job*, const TQByteArray& ) ) );
  614. connect ( d->m_job, TQT_SIGNAL( infoMessage( KIO::Job*, const TQString& ) ),
  615. TQT_SLOT( slotInfoMessage(KIO::Job*, const TQString& ) ) );
  616. connect( d->m_job, TQT_SIGNAL(redirection(KIO::Job*, const KURL& ) ),
  617. TQT_SLOT( slotRedirection(KIO::Job*, const KURL&) ) );
  618. d->m_bComplete = false;
  619. d->m_bLoadEventEmitted = false;
  620. // delete old status bar msg's from kjs (if it _was_ activated on last URL)
  621. if( d->m_bJScriptEnabled )
  622. d->m_statusBarText[BarOverrideText] = d->m_statusBarText[BarDefaultText] = TQString();
  623. // set the javascript flags according to the current url
  624. d->m_bJScriptEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptEnabled(url.host());
  625. setDebugScript( KHTMLFactory::defaultHTMLSettings()->isJavaScriptDebugEnabled() );
  626. d->m_bJavaEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaEnabled(url.host());
  627. d->m_bPluginsEnabled = KHTMLFactory::defaultHTMLSettings()->isPluginsEnabled(url.host());
  628. connect( d->m_job, TQT_SIGNAL( speed( KIO::Job*, unsigned long ) ),
  629. this, TQT_SLOT( slotJobSpeed( KIO::Job*, unsigned long ) ) );
  630. connect( d->m_job, TQT_SIGNAL( percent( KIO::Job*, unsigned long ) ),
  631. this, TQT_SLOT( slotJobPercent( KIO::Job*, unsigned long ) ) );
  632. connect( d->m_job, TQT_SIGNAL( result( KIO::Job* ) ),
  633. this, TQT_SLOT( slotJobDone( KIO::Job* ) ) );
  634. d->m_jobspeed = 0;
  635. // If this was an explicit reload and the user style sheet should be used,
  636. // do a stat to see whether the stylesheet was changed in the meanwhile.
  637. if ( args.reload && !settings()->userStyleSheet().isEmpty() ) {
  638. KURL url( settings()->userStyleSheet() );
  639. KIO::StatJob *job = KIO::stat( url, false /* don't show progress */ );
  640. connect( job, TQT_SIGNAL( result( KIO::Job * ) ),
  641. this, TQT_SLOT( slotUserSheetStatDone( KIO::Job * ) ) );
  642. }
  643. emit started( 0L );
  644. return true;
  645. }
  646. bool KHTMLPart::closeURL()
  647. {
  648. if ( d->m_job )
  649. {
  650. KHTMLPageCache::self()->cancelEntry(d->m_cacheId);
  651. d->m_job->kill();
  652. d->m_job = 0;
  653. }
  654. if ( d->m_doc && d->m_doc->isHTMLDocument() ) {
  655. HTMLDocumentImpl* hdoc = static_cast<HTMLDocumentImpl*>( d->m_doc );
  656. if ( hdoc->body() && d->m_bLoadEventEmitted ) {
  657. hdoc->body()->dispatchWindowEvent( EventImpl::UNLOAD_EVENT, false, false );
  658. if ( d->m_doc )
  659. d->m_doc->updateRendering();
  660. d->m_bLoadEventEmitted = false;
  661. }
  662. }
  663. d->m_bComplete = true; // to avoid emitting completed() in slotFinishedParsing() (David)
  664. d->m_bLoadEventEmitted = true; // don't want that one either
  665. d->m_cachePolicy = KProtocolManager::cacheControl(); // reset cache policy
  666. disconnect(d->m_view, TQT_SIGNAL(finishedLayout()), this, TQT_SLOT(restoreScrollPosition()));
  667. KHTMLPageCache::self()->cancelFetch(this);
  668. if ( d->m_doc && d->m_doc->parsing() )
  669. {
  670. kdDebug( 6050 ) << " was still parsing... calling end " << endl;
  671. slotFinishedParsing();
  672. d->m_doc->setParsing(false);
  673. }
  674. if ( !d->m_workingURL.isEmpty() )
  675. {
  676. // Aborted before starting to render
  677. kdDebug( 6050 ) << "Aborted before starting to render, reverting location bar to " << m_url.prettyURL() << endl;
  678. emit d->m_extension->setLocationBarURL( m_url.prettyURL() );
  679. }
  680. d->m_workingURL = KURL();
  681. if ( d->m_doc && d->m_doc->docLoader() )
  682. khtml::Cache::loader()->cancelRequests( d->m_doc->docLoader() );
  683. // tell all subframes to stop as well
  684. {
  685. ConstFrameIt it = d->m_frames.begin();
  686. const ConstFrameIt end = d->m_frames.end();
  687. for (; it != end; ++it )
  688. {
  689. if ( (*it)->m_run )
  690. (*it)->m_run->abort();
  691. if ( !( *it )->m_part.isNull() )
  692. ( *it )->m_part->closeURL();
  693. }
  694. }
  695. // tell all objects to stop as well
  696. {
  697. ConstFrameIt it = d->m_objects.begin();
  698. const ConstFrameIt end = d->m_objects.end();
  699. for (; it != end; ++it)
  700. {
  701. if ( !( *it )->m_part.isNull() )
  702. ( *it )->m_part->closeURL();
  703. }
  704. }
  705. // Stop any started redirections as well!! (DA)
  706. if ( d && d->m_redirectionTimer.isActive() )
  707. d->m_redirectionTimer.stop();
  708. // null node activated.
  709. emit nodeActivated(Node());
  710. // make sure before clear() runs, we pop out of a dialog's message loop
  711. if ( d->m_view )
  712. d->m_view->closeChildDialogs();
  713. return true;
  714. }
  715. DOM::HTMLDocument KHTMLPart::htmlDocument() const
  716. {
  717. if (d->m_doc && d->m_doc->isHTMLDocument())
  718. return static_cast<HTMLDocumentImpl*>(d->m_doc);
  719. else
  720. return static_cast<HTMLDocumentImpl*>(0);
  721. }
  722. DOM::Document KHTMLPart::document() const
  723. {
  724. return d->m_doc;
  725. }
  726. TQString KHTMLPart::documentSource() const
  727. {
  728. TQString sourceStr;
  729. if ( !( m_url.isLocalFile() ) && KHTMLPageCache::self()->isComplete( d->m_cacheId ) )
  730. {
  731. TQByteArray sourceArray;
  732. TQDataStream dataStream( sourceArray, IO_WriteOnly );
  733. KHTMLPageCache::self()->saveData( d->m_cacheId, &dataStream );
  734. TQTextStream stream( sourceArray, IO_ReadOnly );
  735. stream.setCodec( TQTextCodec::codecForName( encoding().latin1() ) );
  736. sourceStr = stream.read();
  737. } else
  738. {
  739. TQString tmpFile;
  740. if( KIO::NetAccess::download( m_url, tmpFile, NULL ) )
  741. {
  742. TQFile f( tmpFile );
  743. if ( f.open( IO_ReadOnly ) )
  744. {
  745. TQTextStream stream( &f );
  746. stream.setCodec( TQTextCodec::codecForName( encoding().latin1() ) );
  747. sourceStr = stream.read();
  748. f.close();
  749. }
  750. KIO::NetAccess::removeTempFile( tmpFile );
  751. }
  752. }
  753. return sourceStr;
  754. }
  755. KParts::BrowserExtension *KHTMLPart::browserExtension() const
  756. {
  757. return d->m_extension;
  758. }
  759. KParts::BrowserHostExtension *KHTMLPart::browserHostExtension() const
  760. {
  761. return d->m_hostExtension;
  762. }
  763. KHTMLView *KHTMLPart::view() const
  764. {
  765. return d->m_view;
  766. }
  767. void KHTMLPart::setStatusMessagesEnabled( bool enable )
  768. {
  769. d->m_statusMessagesEnabled = enable;
  770. }
  771. KJS::Interpreter *KHTMLPart::jScriptInterpreter()
  772. {
  773. KJSProxy *proxy = jScript();
  774. if (!proxy || proxy->paused())
  775. return 0;
  776. return proxy->interpreter();
  777. }
  778. bool KHTMLPart::statusMessagesEnabled() const
  779. {
  780. return d->m_statusMessagesEnabled;
  781. }
  782. void KHTMLPart::setJScriptEnabled( bool enable )
  783. {
  784. if ( !enable && jScriptEnabled() && d->m_frame && d->m_frame->m_jscript ) {
  785. d->m_frame->m_jscript->clear();
  786. }
  787. d->m_bJScriptForce = enable;
  788. d->m_bJScriptOverride = true;
  789. }
  790. bool KHTMLPart::jScriptEnabled() const
  791. {
  792. if(onlyLocalReferences()) return false;
  793. if ( d->m_bJScriptOverride )
  794. return d->m_bJScriptForce;
  795. return d->m_bJScriptEnabled;
  796. }
  797. void KHTMLPart::setMetaRefreshEnabled( bool enable )
  798. {
  799. d->m_metaRefreshEnabled = enable;
  800. }
  801. bool KHTMLPart::metaRefreshEnabled() const
  802. {
  803. return d->m_metaRefreshEnabled;
  804. }
  805. // Define this to disable dlopening kjs_html, when directly linking to it.
  806. // You need to edit khtml/Makefile.am to add ./ecma/libkjs_html.la to LIBADD
  807. // and to edit khtml/ecma/Makefile.am to s/kjs_html/libkjs_html/, remove libkhtml from LIBADD,
  808. // remove LDFLAGS line, and replace kde_module with either lib (shared) or noinst (static)
  809. // Also, change the order of "ecma" and "." in khtml's SUBDIRS line.
  810. // OK - that's the default now, use the opposite of the above instructions to go back
  811. // to "dlopening it" - but it breaks exception catching in kjs_binding.cpp
  812. #define DIRECT_LINKAGE_TO_ECMA
  813. #ifdef DIRECT_LINKAGE_TO_ECMA
  814. extern "C" { KJSProxy *kjs_html_init(khtml::ChildFrame * childframe); }
  815. #endif
  816. static bool createJScript(khtml::ChildFrame *frame)
  817. {
  818. #ifndef DIRECT_LINKAGE_TO_ECMA
  819. KLibrary *lib = KLibLoader::self()->library("kjs_html");
  820. if ( !lib ) {
  821. setJScriptEnabled( false );
  822. return false;
  823. }
  824. // look for plain C init function
  825. void *sym = lib->symbol("kjs_html_init");
  826. if ( !sym ) {
  827. lib->unload();
  828. setJScriptEnabled( false );
  829. return false;
  830. }
  831. typedef KJSProxy* (*initFunction)(khtml::ChildFrame *);
  832. initFunction initSym = (initFunction) sym;
  833. frame->m_jscript = (*initSym)(d->m_frame);
  834. frame->m_kjs_lib = lib;
  835. #else
  836. frame->m_jscript = kjs_html_init(frame);
  837. // frame->m_kjs_lib remains 0L.
  838. #endif
  839. return true;
  840. }
  841. KJSProxy *KHTMLPart::jScript()
  842. {
  843. if (!jScriptEnabled()) return 0;
  844. if ( !d->m_frame ) {
  845. KHTMLPart * p = parentPart();
  846. if (!p) {
  847. d->m_frame = new khtml::ChildFrame;
  848. d->m_frame->m_part = this;
  849. } else {
  850. ConstFrameIt it = p->d->m_frames.begin();
  851. const ConstFrameIt end = p->d->m_frames.end();
  852. for (; it != end; ++it)
  853. if ((*it)->m_part.operator->() == this) {
  854. d->m_frame = *it;
  855. break;
  856. }
  857. }
  858. if ( !d->m_frame )
  859. return 0;
  860. }
  861. if ( !d->m_frame->m_jscript )
  862. if (!createJScript(d->m_frame))
  863. return 0;
  864. if (d->m_bJScriptDebugEnabled)
  865. d->m_frame->m_jscript->setDebugEnabled(true);
  866. return d->m_frame->m_jscript;
  867. }
  868. TQVariant KHTMLPart::crossFrameExecuteScript(const TQString& target, const TQString& script)
  869. {
  870. KHTMLPart* destpart = this;
  871. TQString trg = target.lower();
  872. if (target == "_top") {
  873. while (destpart->parentPart())
  874. destpart = destpart->parentPart();
  875. }
  876. else if (target == "_parent") {
  877. if (parentPart())
  878. destpart = parentPart();
  879. }
  880. else if (target == "_self" || target == "_blank") {
  881. // we always allow these
  882. }
  883. else {
  884. destpart = findFrame(target);
  885. if (!destpart)
  886. destpart = this;
  887. }
  888. // easy way out?
  889. if (destpart == this)
  890. return executeScript(DOM::Node(), script);
  891. // now compare the domains
  892. if (destpart->checkFrameAccess(this))
  893. return destpart->executeScript(DOM::Node(), script);
  894. // eww, something went wrong. better execute it in our frame
  895. return executeScript(DOM::Node(), script);
  896. }
  897. //Enable this to see all JS scripts being executed
  898. //#define KJS_VERBOSE
  899. KJSErrorDlg *KHTMLPart::jsErrorExtension() {
  900. if (!d->m_settings->jsErrorsEnabled()) {
  901. return 0L;
  902. }
  903. if (parentPart()) {
  904. return parentPart()->jsErrorExtension();
  905. }
  906. if (!d->m_statusBarJSErrorLabel) {
  907. d->m_statusBarJSErrorLabel = new KURLLabel(d->m_statusBarExtension->statusBar());
  908. d->m_statusBarJSErrorLabel->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small));
  909. d->m_statusBarJSErrorLabel->setSizePolicy(TQSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Fixed));
  910. d->m_statusBarJSErrorLabel->setUseCursor(false);
  911. d->m_statusBarExtension->addStatusBarItem(d->m_statusBarJSErrorLabel, 0, false);
  912. TQToolTip::add(d->m_statusBarJSErrorLabel, i18n("This web page contains coding errors."));
  913. d->m_statusBarJSErrorLabel->setPixmap(SmallIcon("bug", instance()));
  914. connect(d->m_statusBarJSErrorLabel, TQT_SIGNAL(leftClickedURL()), TQT_SLOT(launchJSErrorDialog()));
  915. connect(d->m_statusBarJSErrorLabel, TQT_SIGNAL(rightClickedURL()), TQT_SLOT(jsErrorDialogContextMenu()));
  916. }
  917. if (!d->m_jsedlg) {
  918. d->m_jsedlg = new KJSErrorDlg;
  919. d->m_jsedlg->setURL(m_url.prettyURL());
  920. if (KGlobalSettings::showIconsOnPushButtons()) {
  921. d->m_jsedlg->_clear->setIconSet(SmallIconSet("locationbar_erase"));
  922. d->m_jsedlg->_close->setIconSet(SmallIconSet("fileclose"));
  923. }
  924. }
  925. return d->m_jsedlg;
  926. }
  927. void KHTMLPart::removeJSErrorExtension() {
  928. if (parentPart()) {
  929. parentPart()->removeJSErrorExtension();
  930. return;
  931. }
  932. if (d->m_statusBarJSErrorLabel != 0) {
  933. d->m_statusBarExtension->removeStatusBarItem( d->m_statusBarJSErrorLabel );
  934. delete d->m_statusBarJSErrorLabel;
  935. d->m_statusBarJSErrorLabel = 0;
  936. }
  937. delete d->m_jsedlg;
  938. d->m_jsedlg = 0;
  939. }
  940. void KHTMLPart::disableJSErrorExtension() {
  941. removeJSErrorExtension();
  942. // These two lines are really kind of hacky, and it sucks to do this inside
  943. // KHTML but I don't know of anything that's reasonably easy as an alternative
  944. // right now. It makes me wonder if there should be a more clean way to
  945. // contact all running "KHTML" instance as opposed to Konqueror instances too.
  946. d->m_settings->setJSErrorsEnabled(false);
  947. DCOPClient::mainClient()->send("konqueror*", "KonquerorIface", "reparseConfiguration()", TQByteArray());
  948. }
  949. void KHTMLPart::jsErrorDialogContextMenu() {
  950. KPopupMenu *m = new KPopupMenu(0L);
  951. m->insertItem(i18n("&Hide Errors"), this, TQT_SLOT(removeJSErrorExtension()));
  952. m->insertItem(i18n("&Disable Error Reporting"), this, TQT_SLOT(disableJSErrorExtension()));
  953. m->popup(TQCursor::pos());
  954. }
  955. void KHTMLPart::launchJSErrorDialog() {
  956. KJSErrorDlg *dlg = jsErrorExtension();
  957. if (dlg) {
  958. dlg->show();
  959. dlg->raise();
  960. }
  961. }
  962. void KHTMLPart::launchJSConfigDialog() {
  963. TQStringList args;
  964. args << "khtml_java_js";
  965. KApplication::tdeinitExec( "kcmshell", args );
  966. }
  967. TQVariant KHTMLPart::executeScript(const TQString& filename, int baseLine, const DOM::Node& n, const TQString& script)
  968. {
  969. #ifdef KJS_VERBOSE
  970. // The script is now printed by KJS's Parser::parse
  971. kdDebug(6070) << "executeScript: caller='" << name() << "' filename=" << filename << " baseLine=" << baseLine /*<< " script=" << script*/ << endl;
  972. #endif
  973. KJSProxy *proxy = jScript();
  974. if (!proxy || proxy->paused())
  975. return TQVariant();
  976. KJS::Completion comp;
  977. TQVariant ret = proxy->evaluate(filename, baseLine, script, n, &comp);
  978. /*
  979. * Error handling
  980. */
  981. if (comp.complType() == KJS::Throw && !comp.value().isNull()) {
  982. KJSErrorDlg *dlg = jsErrorExtension();
  983. if (dlg) {
  984. KJS::UString msg = comp.value().toString(proxy->interpreter()->globalExec());
  985. dlg->addError(i18n("<b>Error</b>: %1: %2").arg(filename, msg.qstring()));
  986. }
  987. }
  988. // Handle immediate redirects now (e.g. location='foo')
  989. if ( !d->m_redirectURL.isEmpty() && d->m_delayRedirect == -1 )
  990. {
  991. kdDebug(6070) << "executeScript done, handling immediate redirection NOW" << endl;
  992. // Must abort tokenizer, no further script must execute.
  993. khtml::Tokenizer* t = d->m_doc->tokenizer();
  994. if(t)
  995. t->abort();
  996. d->m_redirectionTimer.start( 0, true );
  997. }
  998. return ret;
  999. }
  1000. TQVariant KHTMLPart::executeScript( const TQString &script )
  1001. {
  1002. return executeScript( DOM::Node(), script );
  1003. }
  1004. TQVariant KHTMLPart::executeScript( const DOM::Node &n, const TQString &script )
  1005. {
  1006. #ifdef KJS_VERBOSE
  1007. kdDebug(6070) << "KHTMLPart::executeScript caller='" << name() << "' node=" << n.nodeName().string().latin1() << "(" << (n.isNull() ? 0 : n.nodeType()) << ") " /* << script */ << endl;
  1008. #endif
  1009. KJSProxy *proxy = jScript();
  1010. if (!proxy || proxy->paused())
  1011. return TQVariant();
  1012. ++(d->m_runningScripts);
  1013. KJS::Completion comp;
  1014. const TQVariant ret = proxy->evaluate( TQString(), 1, script, n, &comp );
  1015. --(d->m_runningScripts);
  1016. /*
  1017. * Error handling
  1018. */
  1019. if (comp.complType() == KJS::Throw && !comp.value().isNull()) {
  1020. KJSErrorDlg *dlg = jsErrorExtension();
  1021. if (dlg) {
  1022. KJS::UString msg = comp.value().toString(proxy->interpreter()->globalExec());
  1023. dlg->addError(i18n("<b>Error</b>: node %1: %2").arg(n.nodeName().string()).arg(msg.qstring()));
  1024. }
  1025. }
  1026. if (!d->m_runningScripts && d->m_doc && !d->m_doc->parsing() && d->m_submitForm )
  1027. submitFormAgain();
  1028. #ifdef KJS_VERBOSE
  1029. kdDebug(6070) << "KHTMLPart::executeScript - done" << endl;
  1030. #endif
  1031. return ret;
  1032. }
  1033. bool KHTMLPart::scheduleScript(const DOM::Node &n, const TQString& script)
  1034. {
  1035. //kdDebug(6050) << "KHTMLPart::scheduleScript "<< script << endl;
  1036. d->scheduledScript = script;
  1037. d->scheduledScriptNode = n;
  1038. return true;
  1039. }
  1040. TQVariant KHTMLPart::executeScheduledScript()
  1041. {
  1042. if( d->scheduledScript.isEmpty() )
  1043. return TQVariant();
  1044. //kdDebug(6050) << "executing delayed " << d->scheduledScript << endl;
  1045. TQVariant ret = executeScript( d->scheduledScriptNode, d->scheduledScript );
  1046. d->scheduledScript = TQString();
  1047. d->scheduledScriptNode = DOM::Node();
  1048. return ret;
  1049. }
  1050. void KHTMLPart::setJavaEnabled( bool enable )
  1051. {
  1052. d->m_bJavaForce = enable;
  1053. d->m_bJavaOverride = true;
  1054. }
  1055. bool KHTMLPart::javaEnabled() const
  1056. {
  1057. if (onlyLocalReferences()) return false;
  1058. #ifndef Q_WS_QWS
  1059. if( d->m_bJavaOverride )
  1060. return d->m_bJavaForce;
  1061. return d->m_bJavaEnabled;
  1062. #else
  1063. return false;
  1064. #endif
  1065. }
  1066. KJavaAppletContext *KHTMLPart::javaContext()
  1067. {
  1068. return 0;
  1069. }
  1070. KJavaAppletContext *KHTMLPart::createJavaContext()
  1071. {
  1072. return 0;
  1073. }
  1074. void KHTMLPart::setPluginsEnabled( bool enable )
  1075. {
  1076. d->m_bPluginsForce = enable;
  1077. d->m_bPluginsOverride = true;
  1078. }
  1079. bool KHTMLPart::pluginsEnabled() const
  1080. {
  1081. if (onlyLocalReferences()) return false;
  1082. if ( d->m_bPluginsOverride )
  1083. return d->m_bPluginsForce;
  1084. return d->m_bPluginsEnabled;
  1085. }
  1086. static int s_DOMTreeIndentLevel = 0;
  1087. void KHTMLPart::slotDebugDOMTree()
  1088. {
  1089. if ( d->m_doc && d->m_doc->firstChild() )
  1090. tqDebug("%s", d->m_doc->firstChild()->toString().string().latin1());
  1091. // Now print the contents of the frames that contain HTML
  1092. const int indentLevel = s_DOMTreeIndentLevel++;
  1093. ConstFrameIt it = d->m_frames.begin();
  1094. const ConstFrameIt end = d->m_frames.end();
  1095. for (; it != end; ++it )
  1096. if ( !( *it )->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
  1097. KParts::ReadOnlyPart* const p = ( *it )->m_part;
  1098. kdDebug(6050) << TQString().leftJustify(s_DOMTreeIndentLevel*4,' ') << "FRAME " << p->name() << " " << endl;
  1099. static_cast<KHTMLPart*>( p )->slotDebugDOMTree();
  1100. }
  1101. s_DOMTreeIndentLevel = indentLevel;
  1102. }
  1103. void KHTMLPart::slotDebugScript()
  1104. {
  1105. if (jScript())
  1106. jScript()->showDebugWindow();
  1107. }
  1108. void KHTMLPart::slotDebugRenderTree()
  1109. {
  1110. #ifndef NDEBUG
  1111. if ( d->m_doc ) {
  1112. d->m_doc->renderer()->printTree();
  1113. // dump out the contents of the rendering & DOM trees
  1114. // TQString dumps;
  1115. // TQTextStream outputStream(dumps,IO_WriteOnly);
  1116. // d->m_doc->renderer()->layer()->dump( outputStream );
  1117. // kdDebug() << "dump output:" << "\n" + dumps;
  1118. }
  1119. #endif
  1120. }
  1121. void KHTMLPart::slotStopAnimations()
  1122. {
  1123. stopAnimations();
  1124. }
  1125. void KHTMLPart::setAutoloadImages( bool enable )
  1126. {
  1127. if ( d->m_doc && d->m_doc->docLoader()->autoloadImages() == enable )
  1128. return;
  1129. if ( d->m_doc )
  1130. d->m_doc->docLoader()->setAutoloadImages( enable );
  1131. unplugActionList( "loadImages" );
  1132. if ( enable ) {
  1133. delete d->m_paLoadImages;
  1134. d->m_paLoadImages = 0;
  1135. }
  1136. else if ( !d->m_paLoadImages )
  1137. d->m_paLoadImages = new KAction( i18n( "Display Images on Page" ), "images_display", 0, this, TQT_SLOT( slotLoadImages() ), actionCollection(), "loadImages" );
  1138. if ( d->m_paLoadImages ) {
  1139. TQPtrList<KAction> lst;
  1140. lst.append( d->m_paLoadImages );
  1141. plugActionList( "loadImages", lst );
  1142. }
  1143. }
  1144. bool KHTMLPart::autoloadImages() const
  1145. {
  1146. if ( d->m_doc )
  1147. return d->m_doc->docLoader()->autoloadImages();
  1148. return true;
  1149. }
  1150. void KHTMLPart::clear()
  1151. {
  1152. if ( d->m_bCleared )
  1153. return;
  1154. d->m_bCleared = true;
  1155. d->m_bClearing = true;
  1156. {
  1157. ConstFrameIt it = d->m_frames.begin();
  1158. const ConstFrameIt end = d->m_frames.end();
  1159. for(; it != end; ++it )
  1160. {
  1161. // Stop HTMLRun jobs for frames
  1162. if ( (*it)->m_run )
  1163. (*it)->m_run->abort();
  1164. }
  1165. }
  1166. {
  1167. ConstFrameIt it = d->m_objects.begin();
  1168. const ConstFrameIt end = d->m_objects.end();
  1169. for(; it != end; ++it )
  1170. {
  1171. // Stop HTMLRun jobs for objects
  1172. if ( (*it)->m_run )
  1173. (*it)->m_run->abort();
  1174. }
  1175. }
  1176. findTextBegin(); // resets d->m_findNode and d->m_findPos
  1177. d->m_mousePressNode = DOM::Node();
  1178. if ( d->m_doc )
  1179. {
  1180. if (d->m_doc->attached()) //the view may have detached it already
  1181. d->m_doc->detach();
  1182. }
  1183. // Moving past doc so that onUnload works.
  1184. if ( d->m_frame && d->m_frame->m_jscript )
  1185. d->m_frame->m_jscript->clear();
  1186. // stopping marquees
  1187. if (d->m_doc && d->m_doc->renderer() && d->m_doc->renderer()->layer())
  1188. d->m_doc->renderer()->layer()->suspendMarquees();
  1189. if ( d->m_view )
  1190. d->m_view->clear();
  1191. // do not dereference the document before the jscript and view are cleared, as some destructors
  1192. // might still try to access the document.
  1193. if ( d->m_doc ) {
  1194. d->m_doc->deref();
  1195. }
  1196. d->m_doc = 0;
  1197. delete d->m_decoder;
  1198. d->m_decoder = 0;
  1199. // We don't want to change between parts if we are going to delete all of them anyway
  1200. disconnect( partManager(), TQT_SIGNAL( activePartChanged( KParts::Part * ) ),
  1201. this, TQT_SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
  1202. if (d->m_frames.count())
  1203. {
  1204. KHTMLFrameList frames = d->m_frames;
  1205. d->m_frames.clear();
  1206. ConstFrameIt it = frames.begin();
  1207. const ConstFrameIt end = frames.end();
  1208. for(; it != end; ++it )
  1209. {
  1210. if ( (*it)->m_part )
  1211. {
  1212. partManager()->removePart( (*it)->m_part );
  1213. delete (KParts::ReadOnlyPart *)(*it)->m_part;
  1214. }
  1215. delete *it;
  1216. }
  1217. }
  1218. d->m_suppressedPopupOriginParts.clear();
  1219. if (d->m_objects.count())
  1220. {
  1221. KHTMLFrameList objects = d->m_objects;
  1222. d->m_objects.clear();
  1223. ConstFrameIt oi = objects.begin();
  1224. const ConstFrameIt oiEnd = objects.end();
  1225. for (; oi != oiEnd; ++oi )
  1226. delete *oi;
  1227. }
  1228. // Listen to part changes again
  1229. connect( partManager(), TQT_SIGNAL( activePartChanged( KParts::Part * ) ),
  1230. this, TQT_SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
  1231. d->m_delayRedirect = 0;
  1232. d->m_redirectURL = TQString();
  1233. d->m_redirectionTimer.stop();
  1234. d->m_redirectLockHistory = true;
  1235. d->m_bClearing = false;
  1236. d->m_frameNameId = 1;
  1237. d->m_bFirstData = true;
  1238. d->m_bMousePressed = false;
  1239. d->m_selectionStart = DOM::Node();
  1240. d->m_selectionEnd = DOM::Node();
  1241. d->m_startOffset = 0;
  1242. d->m_endOffset = 0;
  1243. #ifndef QT_NO_CLIPBOARD
  1244. connect( kapp->clipboard(), TQT_SIGNAL( selectionChanged()), TQT_SLOT( slotClearSelection()));
  1245. #endif
  1246. d->m_jobPercent = 0;
  1247. if ( !d->m_haveEncoding )
  1248. d->m_encoding = TQString();
  1249. #ifdef SPEED_DEBUG
  1250. d->m_parsetime.restart();
  1251. #endif
  1252. }
  1253. bool KHTMLPart::openFile()
  1254. {
  1255. return true;
  1256. }
  1257. DOM::HTMLDocumentImpl *KHTMLPart::docImpl() const
  1258. {
  1259. if ( d && d->m_doc && d->m_doc->isHTMLDocument() )
  1260. return static_cast<HTMLDocumentImpl*>(d->m_doc);
  1261. return 0;
  1262. }
  1263. DOM::DocumentImpl *KHTMLPart::xmlDocImpl() const
  1264. {
  1265. if ( d )
  1266. return d->m_doc;
  1267. return 0;
  1268. }
  1269. void KHTMLPart::slotInfoMessage(KIO::Job* kio_job, const TQString& msg)
  1270. {
  1271. assert(d->m_job == kio_job);
  1272. if (!parentPart())
  1273. setStatusBarText(msg, BarDefaultText);
  1274. }
  1275. void KHTMLPart::setPageSecurity( PageSecurity sec )
  1276. {
  1277. emit d->m_extension->setPageSecurity( sec );
  1278. if ( sec != NotCrypted && !d->m_statusBarIconLabel && !parentPart() ) {
  1279. d->m_statusBarIconLabel = new KURLLabel( d->m_statusBarExtension->statusBar() );
  1280. d->m_statusBarIconLabel->setFixedHeight( instance()->iconLoader()->currentSize(KIcon::Small) );
  1281. d->m_statusBarIconLabel->setSizePolicy(TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ));
  1282. d->m_statusBarIconLabel->setUseCursor( false );
  1283. d->m_statusBarExtension->addStatusBarItem( d->m_statusBarIconLabel, 0, false );
  1284. connect( d->m_statusBarIconLabel, TQT_SIGNAL( leftClickedURL() ), TQT_SLOT( slotSecurity() ) );
  1285. } else if (d->m_statusBarIconLabel) {
  1286. TQToolTip::remove(d->m_statusBarIconLabel);
  1287. }
  1288. if (d->m_statusBarIconLabel) {
  1289. if (d->m_ssl_in_use)
  1290. TQToolTip::add(d->m_statusBarIconLabel,
  1291. i18n("Session is secured with %1 bit %2.").arg(d->m_ssl_cipher_used_bits).arg(d->m_ssl_cipher));
  1292. else TQToolTip::add(d->m_statusBarIconLabel, i18n("Session is not secured."));
  1293. }
  1294. TQString iconName;
  1295. switch (sec) {
  1296. case NotCrypted:
  1297. iconName = "decrypted";
  1298. if ( d->m_statusBarIconLabel ) {
  1299. d->m_statusBarExtension->removeStatusBarItem( d->m_statusBarIconLabel );
  1300. delete d->m_statusBarIconLabel;
  1301. d->m_statusBarIconLabel = 0L;
  1302. }
  1303. break;
  1304. case Encrypted:
  1305. iconName = "encrypted";
  1306. break;
  1307. case Mixed:
  1308. iconName = "halfencrypted";
  1309. break;
  1310. }
  1311. d->m_paSecurity->setIcon( iconName );
  1312. if ( d->m_statusBarIconLabel )
  1313. d->m_statusBarIconLabel->setPixmap( SmallIcon( iconName, instance() ) );
  1314. }
  1315. void KHTMLPart::slotData( KIO::Job* kio_job, const TQByteArray &data )
  1316. {
  1317. assert ( d->m_job == kio_job );
  1318. //kdDebug( 6050 ) << "slotData: " << data.size() << endl;
  1319. // The first data ?
  1320. if ( !d->m_workingURL.isEmpty() )
  1321. {
  1322. //kdDebug( 6050 ) << "begin!" << endl;
  1323. // We must suspend KIO while we're inside begin() because it can cause
  1324. // crashes if a window (such as kjsdebugger) goes back into the event loop,
  1325. // more data arrives, and begin() gets called again (re-entered).
  1326. d->m_job->suspend();
  1327. begin( d->m_workingURL, d->m_extension->urlArgs().xOffset, d->m_extension->urlArgs().yOffset );
  1328. d->m_job->resume();
  1329. if (d->m_cachePolicy == KIO::CC_Refresh)
  1330. d->m_doc->docLoader()->setCachePolicy(KIO::CC_Verify);
  1331. else
  1332. d->m_doc->docLoader()->setCachePolicy(d->m_cachePolicy);
  1333. d->m_workingURL = KURL();
  1334. d->m_cacheId = KHTMLPageCache::self()->createCacheEntry();
  1335. // When the first data arrives, the metadata has just been made available
  1336. d->m_httpHeaders = d->m_job->queryMetaData("HTTP-Headers");
  1337. time_t cacheCreationDate = d->m_job->queryMetaData("cache-creation-date").toLong();
  1338. d->m_doc->docLoader()->setCacheCreationDate(cacheCreationDate);
  1339. d->m_pageServices = d->m_job->queryMetaData("PageServices");
  1340. d->m_pageReferrer = d->m_job->queryMetaData("referrer");
  1341. d->m_bSecurityInQuestion = false;
  1342. d->m_ssl_in_use = (d->m_job->queryMetaData("ssl_in_use") == "TRUE");
  1343. {
  1344. KHTMLPart *p = parentPart();
  1345. if (p && p->d->m_ssl_in_use != d->m_ssl_in_use) {
  1346. while (p->parentPart()) p = p->parentPart();
  1347. p->setPageSecurity( Mixed );
  1348. p->d->m_bSecurityInQuestion = true;
  1349. }
  1350. }
  1351. setPageSecurity( d->m_ssl_in_use ? Encrypted : NotCrypted );
  1352. // Shouldn't all of this be done only if ssl_in_use == true ? (DF)
  1353. d->m_ssl_parent_ip = d->m_job->queryMetaData("ssl_parent_ip");
  1354. d->m_ssl_parent_cert = d->m_job->queryMetaData("ssl_parent_cert");
  1355. d->m_ssl_peer_certificate = d->m_job->queryMetaData("ssl_peer_certificate");
  1356. d->m_ssl_peer_chain = d->m_job->queryMetaData("ssl_peer_chain");
  1357. d->m_ssl_peer_ip = d->m_job->queryMetaData("ssl_peer_ip");
  1358. d->m_ssl_cipher = d->m_job->queryMetaData("ssl_cipher");
  1359. d->m_ssl_cipher_desc = d->m_job->queryMetaData("ssl_cipher_desc");
  1360. d->m_ssl_cipher_version = d->m_job->queryMetaData("ssl_cipher_version");
  1361. d->m_ssl_cipher_used_bits = d->m_job->queryMetaData("ssl_cipher_used_bits");
  1362. d->m_ssl_cipher_bits = d->m_job->queryMetaData("ssl_cipher_bits");
  1363. d->m_ssl_cert_state = d->m_job->queryMetaData("ssl_cert_state");
  1364. if (d->m_statusBarIconLabel) {
  1365. TQToolTip::remove(d->m_statusBarIconLabel);
  1366. if (d->m_ssl_in_use) {
  1367. 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));
  1368. } else {
  1369. TQToolTip::add(d->m_statusBarIconLabel, i18n("Session is not secured."));
  1370. }
  1371. }
  1372. // Check for charset meta-data
  1373. TQString qData = d->m_job->queryMetaData("charset");
  1374. if ( !qData.isEmpty() && !d->m_haveEncoding ) // only use information if the user didn't override the settings
  1375. d->m_encoding = qData;
  1376. // Support for http-refresh
  1377. qData = d->m_job->queryMetaData("http-refresh");
  1378. if( !qData.isEmpty())
  1379. d->m_doc->processHttpEquiv("refresh", qData);
  1380. // DISABLED: Support Content-Location per section 14.14 of RFC 2616.
  1381. // See BR# 51185,BR# 82747
  1382. /*
  1383. TQString baseURL = d->m_job->queryMetaData ("content-location");
  1384. if (!baseURL.isEmpty())
  1385. d->m_doc->setBaseURL(KURL( d->m_doc->completeURL(baseURL) ));
  1386. */
  1387. // Support for Content-Language
  1388. TQString language = d->m_job->queryMetaData("content-language");
  1389. if (!language.isEmpty())
  1390. d->m_doc->setContentLanguage(language);
  1391. if ( !m_url.isLocalFile() ) {
  1392. // Support for http last-modified
  1393. d->m_lastModified = d->m_job->queryMetaData("modified");
  1394. } else
  1395. d->m_lastModified = TQString(); // done on-demand by lastModified()
  1396. }
  1397. KHTMLPageCache::self()->addData(d->m_cacheId, data);
  1398. write( data.data(), data.size() );
  1399. if (d->m_frame && d->m_frame->m_jscript)
  1400. d->m_frame->m_jscript->dataReceived();
  1401. }
  1402. void KHTMLPart::slotRestoreData(const TQByteArray &data )
  1403. {
  1404. // The first data ?
  1405. if ( !d->m_workingURL.isEmpty() )
  1406. {
  1407. long saveCacheId = d->m_cacheId;
  1408. TQString savePageReferrer = d->m_pageReferrer;
  1409. TQString saveEncoding = d->m_encoding;
  1410. begin( d->m_workingURL, d->m_extension->urlArgs().xOffset, d->m_extension->urlArgs().yOffset );
  1411. d->m_encoding = saveEncoding;
  1412. d->m_pageReferrer = savePageReferrer;
  1413. d->m_cacheId = saveCacheId;
  1414. d->m_workingURL = KURL();
  1415. }
  1416. //kdDebug( 6050 ) << "slotRestoreData: " << data.size() << endl;
  1417. write( data.data(), data.size() );
  1418. if (data.size() == 0)
  1419. {
  1420. //kdDebug( 6050 ) << "slotRestoreData: <<end of data>>" << endl;
  1421. // End of data.
  1422. if (d->m_doc && d->m_doc->parsing())
  1423. end(); //will emit completed()
  1424. }
  1425. }
  1426. void KHTMLPart::showError( KIO::Job* job )
  1427. {
  1428. kdDebug(6050) << "KHTMLPart::showError d->m_bParsing=" << (d->m_doc && d->m_doc->parsing()) << " d->m_bComplete=" << d->m_bComplete
  1429. << " d->m_bCleared=" << d->m_bCleared << endl;
  1430. if (job->error() == KIO::ERR_NO_CONTENT)
  1431. return;
  1432. if ( (d->m_doc && d->m_doc->parsing()) || d->m_workingURL.isEmpty() ) // if we got any data already
  1433. job->showErrorDialog( /*d->m_view*/ );
  1434. else
  1435. {
  1436. htmlError( job->error(), job->errorText(), d->m_workingURL );
  1437. }
  1438. }
  1439. // This is a protected method, placed here because of it's relevance to showError
  1440. void KHTMLPart::htmlError( int errorCode, const TQString& text, const KURL& reqUrl )
  1441. {
  1442. kdDebug(6050) << "KHTMLPart::htmlError errorCode=" << errorCode << " text=" << text << endl;
  1443. // make sure we're not executing any embedded JS
  1444. bool bJSFO = d->m_bJScriptForce;
  1445. bool bJSOO = d->m_bJScriptOverride;
  1446. d->m_bJScriptForce = false;
  1447. d->m_bJScriptOverride = true;
  1448. begin();
  1449. TQString errText = TQString::fromLatin1( "<HTML dir=%1><HEAD><TITLE>" )
  1450. .arg(TQApplication::reverseLayout() ? "rtl" : "ltr");
  1451. errText += i18n( "Error while loading %1" ).arg( reqUrl.htmlURL() );
  1452. errText += TQString::fromLatin1( "</TITLE></HEAD><BODY><P>" );
  1453. errText += i18n( "An error occurred while loading <B>%1</B>:" ).arg( reqUrl.htmlURL() );
  1454. errText += TQString::fromLatin1( "</P>" );
  1455. errText += TQStyleSheet::convertFromPlainText( KIO::buildErrorString( errorCode, text ) );
  1456. errText += TQString::fromLatin1( "</BODY></HTML>" );
  1457. write(errText);
  1458. end();
  1459. d->m_bJScriptForce = bJSFO;
  1460. d->m_bJScriptOverride = bJSOO;
  1461. // make the working url the current url, so that reload works and
  1462. // emit the progress signals to advance one step in the history
  1463. // (so that 'back' works)
  1464. m_url = reqUrl; // same as d->m_workingURL
  1465. d->m_workingURL = KURL();
  1466. emit started( 0 );
  1467. emit completed();
  1468. return;
  1469. // following disabled until 3.1
  1470. TQString errorName, techName, description;
  1471. TQStringList causes, solutions;
  1472. TQByteArray raw = KIO::rawErrorDetail( errorCode, text, &reqUrl );
  1473. TQDataStream stream(raw, IO_ReadOnly);
  1474. stream >> errorName >> techName >> description >> causes >> solutions;
  1475. TQString url, protocol, datetime;
  1476. url = reqUrl.prettyURL();
  1477. protocol = reqUrl.protocol();
  1478. datetime = KGlobal::locale()->formatDateTime( TQDateTime::currentDateTime(),
  1479. false );
  1480. TQString doc = TQString::fromLatin1( "<html><head><title>" );
  1481. doc += i18n( "Error: " );
  1482. doc += errorName;
  1483. doc += TQString::fromLatin1( " - %1</title></head><body><h1>" ).arg( url );
  1484. doc += i18n( "The requested operation could not be completed" );
  1485. doc += TQString::fromLatin1( "</h1><h2>" );
  1486. doc += errorName;
  1487. doc += TQString::fromLatin1( "</h2>" );
  1488. if ( !techName.isNull() ) {
  1489. doc += TQString::fromLatin1( "<h2>" );
  1490. doc += i18n( "Technical Reason: " );
  1491. doc += techName;
  1492. doc += TQString::fromLatin1( "</h2>" );
  1493. }
  1494. doc += TQString::fromLatin1( "<h3>" );
  1495. doc += i18n( "Details of the Request:" );
  1496. doc += TQString::fromLatin1( "</h3><ul><li>" );
  1497. doc += i18n( "URL: %1" ).arg( url );
  1498. doc += TQString::fromLatin1( "</li><li>" );
  1499. if ( !protocol.isNull() ) {
  1500. // uncomment for 3.1... i18n change
  1501. // doc += i18n( "Protocol: %1" ).arg( protocol ).arg( protocol );
  1502. doc += TQString::fromLatin1( "</li><li>" );
  1503. }
  1504. doc += i18n( "Date and Time: %1" ).arg( datetime );
  1505. doc += TQString::fromLatin1( "</li><li>" );
  1506. doc += i18n( "Additional Information: %1" ).arg( text );
  1507. doc += TQString::fromLatin1( "</li></ul><h3>" );
  1508. doc += i18n( "Description:" );
  1509. doc += TQString::fromLatin1( "</h3><p>" );
  1510. doc += description;
  1511. doc += TQString::fromLatin1( "</p>" );
  1512. if ( causes.count() ) {
  1513. doc += TQString::fromLatin1( "<h3>" );
  1514. doc += i18n( "Possible Causes:" );
  1515. doc += TQString::fromLatin1( "</h3><ul><li>" );
  1516. doc += causes.join( "</li><li>" );
  1517. doc += TQString::fromLatin1( "</li></ul>" );
  1518. }
  1519. if ( solutions.count() ) {
  1520. doc += TQString::fromLatin1( "<h3>" );
  1521. doc += i18n( "Possible Solutions:" );
  1522. doc += TQString::fromLatin1( "</h3><ul><li>" );
  1523. doc += solutions.join( "</li><li>" );
  1524. doc += TQString::fromLatin1( "</li></ul>" );
  1525. }
  1526. doc += TQString::fromLatin1( "</body></html>" );
  1527. write( doc );
  1528. end();
  1529. }
  1530. void KHTMLPart::slotFinished( KIO::Job * job )
  1531. {
  1532. d->m_job = 0L;
  1533. d->m_jobspeed = 0L;
  1534. if (job->error())
  1535. {
  1536. KHTMLPageCache::self()->cancelEntry(d->m_cacheId);
  1537. // The following catches errors that occur as a result of HTTP
  1538. // to FTP redirections where the FTP URL is a directory. Since
  1539. // KIO cannot change a redirection request from GET to LISTDIR,
  1540. // we have to take care of it here once we know for sure it is
  1541. // a directory...
  1542. if (job->error() == KIO::ERR_IS_DIRECTORY)
  1543. {
  1544. KParts::URLArgs args;
  1545. emit d->m_extension->openURLRequest( d->m_workingURL, args );
  1546. }
  1547. else
  1548. {
  1549. emit canceled( job->errorString() );
  1550. // TODO: what else ?
  1551. checkCompleted();
  1552. showError( job );
  1553. }
  1554. return;
  1555. }
  1556. KIO::TransferJob *tjob = ::tqqt_cast<KIO::TransferJob*>(job);
  1557. if (tjob && tjob->isErrorPage()) {
  1558. khtml::RenderPart *renderPart = d->m_frame ? static_cast<khtml::RenderPart *>(d->m_frame->m_frame) : 0;
  1559. if (renderPart) {
  1560. HTMLObjectElementImpl* elt = static_cast<HTMLObjectElementImpl *>(renderPart->element());
  1561. if (!elt)
  1562. return;
  1563. elt->renderAlternative();
  1564. checkCompleted();
  1565. }
  1566. if (d->m_bComplete) return;
  1567. }
  1568. //kdDebug( 6050 ) << "slotFinished" << endl;
  1569. KHTMLPageCache::self()->endData(d->m_cacheId);
  1570. if (d->m_frame && d->m_frame->m_jscript)
  1571. d->m_frame->m_jscript->dataReceived();
  1572. if ( d->m_doc && d->m_doc->docLoader()->expireDate() && m_url.protocol().lower().startsWith("http"))
  1573. KIO::http_update_cache(m_url, false, d->m_doc->docLoader()->expireDate());
  1574. d->m_workingURL = KURL();
  1575. if ( d->m_doc && d->m_doc->parsing())
  1576. end(); //will emit completed()
  1577. }
  1578. void KHTMLPart::begin( const KURL &url, int xOffset, int yOffset )
  1579. {
  1580. // No need to show this for a new page until an error is triggered
  1581. if (!parentPart()) {
  1582. removeJSErrorExtension();
  1583. setSuppressedPopupIndicator( false );
  1584. d->m_openableSuppressedPopups = 0;
  1585. for ( TQValueListIterator<TQGuardedPtr<KHTMLPart> > i = d->m_suppressedPopupOriginParts.begin();
  1586. i != d->m_suppressedPopupOriginParts.end(); ++i ) {
  1587. if (KHTMLPart* part = *i) {
  1588. KJS::Window *w = KJS::Window::retrieveWindow( part );
  1589. if (w)
  1590. w->forgetSuppressedWindows();
  1591. }
  1592. }
  1593. }
  1594. clear();
  1595. d->m_bCleared = false;
  1596. d->m_cacheId = 0;
  1597. d->m_bComplete = false;
  1598. d->m_bLoadEventEmitted = false;
  1599. if(url.isValid()) {
  1600. TQString urlString = url.url();
  1601. KHTMLFactory::vLinks()->insert( urlString );
  1602. TQString urlString2 = url.prettyURL();
  1603. if ( urlString != urlString2 ) {
  1604. KHTMLFactory::vLinks()->insert( urlString2 );
  1605. }
  1606. }
  1607. // ###
  1608. //stopParser();
  1609. KParts::URLArgs args( d->m_extension->urlArgs() );
  1610. args.xOffset = xOffset;
  1611. args.yOffset = yOffset;
  1612. d->m_extension->setURLArgs( args );
  1613. d->m_pageReferrer = TQString();
  1614. KURL ref(url);
  1615. d->m_referrer = ref.protocol().startsWith("http") ? ref.url() : "";
  1616. m_url = url;
  1617. bool servedAsXHTML = args.serviceType == "application/xhtml+xml";
  1618. bool servedAsXML = KMimeType::mimeType(args.serviceType)->is( "text/xml" );
  1619. // ### not sure if XHTML documents served as text/xml should use DocumentImpl or HTMLDocumentImpl
  1620. if ( servedAsXML && !servedAsXHTML ) { // any XML derivative, except XHTML
  1621. d->m_doc = DOMImplementationImpl::instance()->createDocument( d->m_view );
  1622. } else {
  1623. d->m_doc = DOMImplementationImpl::instance()->createHTMLDocument( d->m_view );
  1624. // HTML or XHTML? (#86446)
  1625. static_cast<HTMLDocumentImpl *>(d->m_doc)->setHTMLRequested( !servedAsXHTML );
  1626. }
  1627. #ifndef KHTML_NO_CARET
  1628. // d->m_view->initCaret();
  1629. #endif
  1630. d->m_doc->ref();
  1631. d->m_doc->setURL( m_url.url() );
  1632. if (!d->m_doc->attached())
  1633. d->m_doc->attach( );
  1634. d->m_doc->setBaseURL( KURL() );
  1635. d->m_doc->docLoader()->setShowAnimations( KHTMLFactory::defaultHTMLSettings()->showAnimations() );
  1636. emit docCreated();
  1637. d->m_paUseStylesheet->setItems(TQStringList());
  1638. d->m_paUseStylesheet->setEnabled( false );
  1639. setAutoloadImages( KHTMLFactory::defaultHTMLSettings()->autoLoadImages() );
  1640. TQString userStyleSheet = KHTMLFactory::defaultHTMLSettings()->userStyleSheet();
  1641. if ( !userStyleSheet.isEmpty() )
  1642. setUserStyleSheet( KURL( userStyleSheet ) );
  1643. d->m_doc->setRestoreState(args.docState);
  1644. d->m_doc->open();
  1645. connect(d->m_doc,TQT_SIGNAL(finishedParsing()),this,TQT_SLOT(slotFinishedParsing()));
  1646. emit d->m_extension->enableAction( "print", true );
  1647. d->m_doc->setParsing(true);
  1648. }
  1649. void KHTMLPart::write( const char *str, int len )
  1650. {
  1651. if ( !d->m_decoder )
  1652. d->m_decoder = createDecoder();
  1653. if ( len == -1 )
  1654. len = strlen( str );
  1655. if ( len == 0 )
  1656. return;
  1657. TQString decoded = d->m_decoder->decode( str, len );
  1658. if(decoded.isEmpty()) return;
  1659. if(d->m_bFirstData) {
  1660. // determine the parse mode
  1661. d->m_doc->determineParseMode( decoded );
  1662. d->m_bFirstData = false;
  1663. //kdDebug(6050) << "KHTMLPart::write haveEnc = " << d->m_haveEncoding << endl;
  1664. // ### this is still quite hacky, but should work a lot better than the old solution
  1665. if(d->m_decoder->visuallyOrdered()) d->m_doc->setVisuallyOrdered();
  1666. d->m_doc->setDecoderCodec(d->m_decoder->codec());
  1667. d->m_doc->recalcStyle( NodeImpl::Force );
  1668. }
  1669. khtml::Tokenizer* t = d->m_doc->tokenizer();
  1670. if(t)
  1671. t->write( decoded, true );
  1672. }
  1673. void KHTMLPart::write( const TQString &str )
  1674. {
  1675. if ( str.isNull() )
  1676. return;
  1677. if(d->m_bFirstData) {
  1678. // determine the parse mode
  1679. d->m_doc->setParseMode( DocumentImpl::Strict );
  1680. d->m_bFirstData = false;
  1681. }
  1682. khtml::Tokenizer* t = d->m_doc->tokenizer();
  1683. if(t)
  1684. t->write( str, true );
  1685. }
  1686. void KHTMLPart::end()
  1687. {
  1688. if (d->m_doc) {
  1689. if (d->m_decoder) {
  1690. TQString decoded = d->m_decoder->flush();
  1691. if (d->m_bFirstData) {
  1692. d->m_bFirstData = false;
  1693. d->m_doc->determineParseMode(decoded);
  1694. }
  1695. write(decoded);
  1696. }
  1697. d->m_doc->finishParsing();
  1698. }
  1699. }
  1700. bool KHTMLPart::doOpenStream( const TQString& mimeType )
  1701. {
  1702. KMimeType::Ptr mime = KMimeType::mimeType(mimeType);
  1703. if ( mime->is( "text/html" ) || mime->is( "text/xml" ) )
  1704. {
  1705. begin( url() );
  1706. return true;
  1707. }
  1708. return false;
  1709. }
  1710. bool KHTMLPart::doWriteStream( const TQByteArray& data )
  1711. {
  1712. write( data.data(), data.size() );
  1713. return true;
  1714. }
  1715. bool KHTMLPart::doCloseStream()
  1716. {
  1717. end();
  1718. return true;
  1719. }
  1720. void KHTMLPart::paint(TQPainter *p, const TQRect &rc, int yOff, bool *more)
  1721. {
  1722. if (!d->m_view) return;
  1723. d->m_view->paint(p, rc, yOff, more);
  1724. }
  1725. void KHTMLPart::stopAnimations()
  1726. {
  1727. if ( d->m_doc )
  1728. d->m_doc->docLoader()->setShowAnimations( KHTMLSettings::KAnimationDisabled );
  1729. ConstFrameIt it = d->m_frames.begin();
  1730. const ConstFrameIt end = d->m_frames.end();
  1731. for (; it != end; ++it )
  1732. if ( !(*it)->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
  1733. KParts::ReadOnlyPart* const p = ( *it )->m_part;
  1734. static_cast<KHTMLPart*>( p )->stopAnimations();
  1735. }
  1736. }
  1737. void KHTMLPart::resetFromScript()
  1738. {
  1739. closeURL();
  1740. d->m_bComplete = false;
  1741. d->m_bLoadEventEmitted = false;
  1742. disconnect(d->m_doc,TQT_SIGNAL(finishedParsing()),this,TQT_SLOT(slotFinishedParsing()));
  1743. connect(d->m_doc,TQT_SIGNAL(finishedParsing()),this,TQT_SLOT(slotFinishedParsing()));
  1744. d->m_doc->setParsing(true);
  1745. emit started( 0L );
  1746. }
  1747. void KHTMLPart::slotFinishedParsing()
  1748. {
  1749. d->m_doc->setParsing(false);
  1750. checkEmitLoadEvent();
  1751. disconnect(d->m_doc,TQT_SIGNAL(finishedParsing()),this,TQT_SLOT(slotFinishedParsing()));
  1752. if (!d->m_view)
  1753. return; // We are probably being destructed.
  1754. checkCompleted();
  1755. }
  1756. void KHTMLPart::slotLoaderRequestStarted( khtml::DocLoader* dl, khtml::CachedObject *obj )
  1757. {
  1758. if ( obj && obj->type() == khtml::CachedObject::Image && d->m_doc && d->m_doc->docLoader() == dl ) {
  1759. KHTMLPart* p = this;
  1760. while ( p ) {
  1761. KHTMLPart* const op = p;
  1762. ++(p->d->m_totalObjectCount);
  1763. p = p->parentPart();
  1764. if ( !p && op->d->m_loadedObjects <= op->d->m_totalObjectCount
  1765. && !op->d->m_progressUpdateTimer.isActive())
  1766. op->d->m_progressUpdateTimer.start( 200, true );
  1767. }
  1768. }
  1769. }
  1770. void KHTMLPart::slotLoaderRequestDone( khtml::DocLoader* dl, khtml::CachedObject *obj )
  1771. {
  1772. if ( obj && obj->type() == khtml::CachedObject::Image && d->m_doc && d->m_doc->docLoader() == dl ) {
  1773. KHTMLPart* p = this;
  1774. while ( p ) {
  1775. KHTMLPart* const op = p;
  1776. ++(p->d->m_loadedObjects);
  1777. p = p->parentPart();
  1778. if ( !p && op->d->m_loadedObjects <= op->d->m_totalObjectCount && op->d->m_jobPercent <= 100
  1779. && !op->d->m_progressUpdateTimer.isActive())
  1780. op->d->m_progressUpdateTimer.start( 200, true );
  1781. }
  1782. }
  1783. checkCompleted();
  1784. }
  1785. void KHTMLPart::slotProgressUpdate()
  1786. {
  1787. int percent;
  1788. if ( d->m_loadedObjects < d->m_totalObjectCount )
  1789. percent = d->m_jobPercent / 4 + ( d->m_loadedObjects*300 ) / ( 4*d->m_totalObjectCount );
  1790. else
  1791. percent = d->m_jobPercent;
  1792. if( d->m_bComplete )
  1793. percent = 100;
  1794. if (d->m_statusMessagesEnabled) {
  1795. if( d->m_bComplete )
  1796. emit d->m_extension->infoMessage( i18n( "Page loaded." ));
  1797. else if ( d->m_loadedObjects < d->m_totalObjectCount && percent >= 75 )
  1798. emit d->m_extension->infoMessage( i18n( "%n Image of %1 loaded.", "%n Images of %1 loaded.", d->m_loadedObjects).arg(d->m_totalObjectCount) );
  1799. }
  1800. emit d->m_extension->loadingProgress( percent );
  1801. }
  1802. void KHTMLPart::slotJobSpeed( KIO::Job* /*job*/, unsigned long speed )
  1803. {
  1804. d->m_jobspeed = speed;
  1805. if (!parentPart())
  1806. setStatusBarText(jsStatusBarText(), BarOverrideText);
  1807. }
  1808. void KHTMLPart::slotJobPercent( KIO::Job* /*job*/, unsigned long percent )
  1809. {
  1810. d->m_jobPercent = percent;
  1811. if ( !parentPart() )
  1812. d->m_progressUpdateTimer.start( 0, true );
  1813. }
  1814. void KHTMLPart::slotJobDone( KIO::Job* /*job*/ )
  1815. {
  1816. d->m_jobPercent = 100;
  1817. if ( !parentPart() )
  1818. d->m_progressUpdateTimer.start( 0, true );
  1819. }
  1820. void KHTMLPart::slotUserSheetStatDone( KIO::Job *_job )
  1821. {
  1822. using namespace KIO;
  1823. if ( _job->error() ) {
  1824. showError( _job );
  1825. return;
  1826. }
  1827. const UDSEntry entry = dynamic_cast<KIO::StatJob *>( _job )->statResult();
  1828. UDSEntry::ConstIterator it = entry.begin();
  1829. const UDSEntry::ConstIterator end = entry.end();
  1830. for ( ; it != end; ++it ) {
  1831. if ( ( *it ).m_uds == UDS_MODIFICATION_TIME ) {
  1832. break;
  1833. }
  1834. }
  1835. // If the filesystem supports modification times, only reload the
  1836. // user-defined stylesheet if necessary - otherwise always reload.
  1837. if ( it != end ) {
  1838. const time_t lastModified = static_cast<time_t>( ( *it ).m_long );
  1839. if ( d->m_userStyleSheetLastModified >= lastModified ) {
  1840. return;
  1841. }
  1842. d->m_userStyleSheetLastModified = lastModified;
  1843. }
  1844. setUserStyleSheet( KURL( settings()->userStyleSheet() ) );
  1845. }
  1846. void KHTMLPart::checkCompleted()
  1847. {
  1848. // kdDebug( 6050 ) << "KHTMLPart::checkCompleted() " << this << " " << name() << endl;
  1849. // kdDebug( 6050 ) << " parsing: " << (d->m_doc && d->m_doc->parsing()) << endl;
  1850. // kdDebug( 6050 ) << " complete: " << d->m_bComplete << endl;
  1851. // restore the cursor position
  1852. if (d->m_doc && !d->m_doc->parsing() && !d->m_focusNodeRestored)
  1853. {
  1854. if (d->m_focusNodeNumber >= 0)
  1855. d->m_doc->setFocusNode(d->m_doc->nodeWithAbsIndex(d->m_focusNodeNumber));
  1856. d->m_focusNodeRestored = true;
  1857. }
  1858. bool bPendingChildRedirection = false;
  1859. // Any frame that hasn't completed yet ?
  1860. ConstFrameIt it = d->m_frames.begin();
  1861. const ConstFrameIt end = d->m_frames.end();
  1862. for (; it != end; ++it ) {
  1863. if ( !(*it)->m_bCompleted )
  1864. {
  1865. //kdDebug( 6050 ) << this << " is waiting for " << (*it)->m_part << endl;
  1866. return;
  1867. }
  1868. // Check for frames with pending redirections
  1869. if ( (*it)->m_bPendingRedirection )
  1870. bPendingChildRedirection = true;
  1871. }
  1872. // Any object that hasn't completed yet ?
  1873. {
  1874. ConstFrameIt oi = d->m_objects.begin();
  1875. const ConstFrameIt oiEnd = d->m_objects.end();
  1876. for (; oi != oiEnd; ++oi )
  1877. if ( !(*oi)->m_bCompleted )
  1878. return;
  1879. }
  1880. // Are we still parsing - or have we done the completed stuff already ?
  1881. if ( d->m_bComplete || (d->m_doc && d->m_doc->parsing()) )
  1882. return;
  1883. // Still waiting for images/scripts from the loader ?
  1884. int requests = 0;
  1885. if ( d->m_doc && d->m_doc->docLoader() )
  1886. requests = khtml::Cache::loader()->numRequests( d->m_doc->docLoader() );
  1887. if ( requests > 0 )
  1888. {
  1889. //kdDebug(6050) << "still waiting for images/scripts from the loader - requests:" << requests << endl;
  1890. return;
  1891. }
  1892. // OK, completed.
  1893. // Now do what should be done when we are really completed.
  1894. d->m_bComplete = true;
  1895. d->m_cachePolicy = KProtocolManager::cacheControl(); // reset cache policy
  1896. d->m_totalObjectCount = 0;
  1897. d->m_loadedObjects = 0;
  1898. KHTMLPart* p = this;
  1899. while ( p ) {
  1900. KHTMLPart* op = p;
  1901. p = p->parentPart();
  1902. if ( !p && !op->d->m_progressUpdateTimer.isActive())
  1903. op->d->m_progressUpdateTimer.start( 0, true );
  1904. }
  1905. checkEmitLoadEvent(); // if we didn't do it before
  1906. bool pendingAction = false;
  1907. if ( !d->m_redirectURL.isEmpty() )
  1908. {
  1909. // DA: Do not start redirection for frames here! That action is
  1910. // deferred until the parent emits a completed signal.
  1911. if ( parentPart() == 0 ) {
  1912. //kdDebug(6050) << this << " starting redirection timer" << endl;
  1913. d->m_redirectionTimer.start( 1000 * d->m_delayRedirect, true );
  1914. } else {
  1915. //kdDebug(6050) << this << " not toplevel -> not starting redirection timer. Waiting for slotParentCompleted." << endl;
  1916. }
  1917. pendingAction = true;
  1918. }
  1919. else if ( bPendingChildRedirection )
  1920. {
  1921. pendingAction = true;
  1922. }
  1923. // the view will emit completed on our behalf,
  1924. // either now or at next repaint if one is pending
  1925. //kdDebug(6050) << this << " asks the view to emit completed. pendingAction=" << pendingAction << endl;
  1926. d->m_view->complete( pendingAction );
  1927. // find the alternate stylesheets
  1928. TQStringList sheets;
  1929. if (d->m_doc)
  1930. sheets = d->m_doc->availableStyleSheets();
  1931. sheets.prepend( i18n( "Automatic Detection" ) );
  1932. d->m_paUseStylesheet->setItems( sheets );
  1933. d->m_paUseStylesheet->setEnabled( sheets.count() > 2);
  1934. if (sheets.count() > 2)
  1935. {
  1936. d->m_paUseStylesheet->setCurrentItem(kMax(sheets.findIndex(d->m_sheetUsed), 0));
  1937. slotUseStylesheet();
  1938. }
  1939. setJSDefaultStatusBarText(TQString());
  1940. #ifdef SPEED_DEBUG
  1941. kdDebug(6050) << "DONE: " <<d->m_parsetime.elapsed() << endl;
  1942. #endif
  1943. }
  1944. void KHTMLPart::checkEmitLoadEvent()
  1945. {
  1946. if ( d->m_bLoadEventEmitted || !d->m_doc || d->m_doc->parsing() ) return;
  1947. ConstFrameIt it = d->m_frames.begin();
  1948. const ConstFrameIt end = d->m_frames.end();
  1949. for (; it != end; ++it )
  1950. if ( !(*it)->m_bCompleted ) // still got a frame running -> too early
  1951. return;
  1952. ConstFrameIt oi = d->m_objects.begin();
  1953. const ConstFrameIt oiEnd = d->m_objects.end();
  1954. for (; oi != oiEnd; ++oi )
  1955. if ( !(*oi)->m_bCompleted ) // still got a object running -> too early
  1956. return;
  1957. // Still waiting for images/scripts from the loader ?
  1958. // (onload must happen afterwards, #45607)
  1959. // ## This makes this method very similar to checkCompleted. A brave soul should try merging them.
  1960. int requests = 0;
  1961. if ( d->m_doc && d->m_doc->docLoader() )
  1962. requests = khtml::Cache::loader()->numRequests( d->m_doc->docLoader() );
  1963. if ( requests > 0 )
  1964. return;
  1965. d->m_bLoadEventEmitted = true;
  1966. if (d->m_doc)
  1967. d->m_doc->close();
  1968. }
  1969. const KHTMLSettings *KHTMLPart::settings() const
  1970. {
  1971. return d->m_settings;
  1972. }
  1973. #ifndef KDE_NO_COMPAT
  1974. KURL KHTMLPart::baseURL() const
  1975. {
  1976. if ( !d->m_doc ) return KURL();
  1977. return d->m_doc->baseURL();
  1978. }
  1979. TQString KHTMLPart::baseTarget() const
  1980. {
  1981. if ( !d->m_doc ) return TQString();
  1982. return d->m_doc->baseTarget();
  1983. }
  1984. #endif
  1985. KURL KHTMLPart::completeURL( const TQString &url )
  1986. {
  1987. if ( !d->m_doc ) return KURL( url );
  1988. if (d->m_decoder)
  1989. return KURL(d->m_doc->completeURL(url), d->m_decoder->codec()->mibEnum());
  1990. return KURL( d->m_doc->completeURL( url ) );
  1991. }
  1992. // Called by ecma/kjs_window in case of redirections from Javascript,
  1993. // and by xml/dom_docimpl.cpp in case of http-equiv meta refresh.
  1994. void KHTMLPart::scheduleRedirection( int delay, const TQString &url, bool doLockHistory )
  1995. {
  1996. kdDebug(6050) << "KHTMLPart::scheduleRedirection delay=" << delay << " url=" << url << endl;
  1997. kdDebug(6050) << "current redirectURL=" << d->m_redirectURL << " with delay " << d->m_delayRedirect << endl;
  1998. if( delay < 24*60*60 &&
  1999. ( d->m_redirectURL.isEmpty() || delay <= d->m_delayRedirect) ) {
  2000. d->m_delayRedirect = delay;
  2001. d->m_redirectURL = url;
  2002. d->m_redirectLockHistory = doLockHistory;
  2003. kdDebug(6050) << " d->m_bComplete=" << d->m_bComplete << endl;
  2004. if ( d->m_bComplete ) {
  2005. d->m_redirectionTimer.stop();
  2006. d->m_redirectionTimer.start( kMax(0, 1000 * d->m_delayRedirect), true );
  2007. }
  2008. }
  2009. }
  2010. void KHTMLPart::slotRedirect()
  2011. {
  2012. kdDebug(6050) << this << " slotRedirect()" << endl;
  2013. TQString u = d->m_redirectURL;
  2014. d->m_delayRedirect = 0;
  2015. d->m_redirectURL = TQString();
  2016. // SYNC check with ecma/kjs_window.cpp::goURL !
  2017. if ( u.find( TQString::fromLatin1( "javascript:" ), 0, false ) == 0 )
  2018. {
  2019. TQString script = KURL::decode_string( u.right( u.length() - 11 ) );
  2020. kdDebug( 6050 ) << "KHTMLPart::slotRedirect script=" << script << endl;
  2021. TQVariant res = executeScript( DOM::Node(), script );
  2022. if ( res.type() == TQVariant::String ) {
  2023. begin( url() );
  2024. write( res.asString() );
  2025. end();
  2026. }
  2027. emit completed();
  2028. return;
  2029. }
  2030. KParts::URLArgs args;
  2031. KURL cUrl( m_url );
  2032. KURL url( u );
  2033. // handle windows opened by JS
  2034. if ( openedByJS() && d->m_opener )
  2035. cUrl = d->m_opener->url();
  2036. if (!kapp || !kapp->authorizeURLAction("redirect", cUrl, url))
  2037. {
  2038. kdWarning(6050) << "KHTMLPart::scheduleRedirection: Redirection from " << cUrl << " to " << url << " REJECTED!" << endl;
  2039. emit completed();
  2040. return;
  2041. }
  2042. if ( urlcmp( u, m_url.url(), true, true ) )
  2043. {
  2044. args.metaData().insert("referrer", d->m_pageReferrer);
  2045. }
  2046. // For javascript and META-tag based redirections:
  2047. // - We don't take cross-domain-ness in consideration if we are the
  2048. // toplevel frame because the new URL may be in a different domain as the current URL
  2049. // but that's ok.
  2050. // - If we are not the toplevel frame then we check against the toplevelURL()
  2051. if (parentPart())
  2052. args.metaData().insert("cross-domain", toplevelURL().url());
  2053. args.setLockHistory( d->m_redirectLockHistory );
  2054. // _self: make sure we don't use any <base target=>'s
  2055. d->m_urlSelectedOpenedURL = true; // In case overriden, default to success
  2056. urlSelected( u, 0, 0, "_self", args );
  2057. if ( !d->m_urlSelectedOpenedURL ) // urlSelected didn't open a url, so emit completed ourselves
  2058. emit completed();
  2059. }
  2060. void KHTMLPart::slotRedirection(KIO::Job*, const KURL& url)
  2061. {
  2062. // the slave told us that we got redirected
  2063. //kdDebug( 6050 ) << "redirection by KIO to " << url.url() << endl;
  2064. emit d->m_extension->setLocationBarURL( url.prettyURL() );
  2065. d->m_workingURL = url;
  2066. }
  2067. bool KHTMLPart::setEncoding( const TQString &name, bool override )
  2068. {
  2069. d->m_encoding = name;
  2070. d->m_haveEncoding = override;
  2071. if( !m_url.isEmpty() ) {
  2072. // reload document
  2073. closeURL();
  2074. KURL url = m_url;
  2075. m_url = 0;
  2076. d->m_restored = true;
  2077. openURL(url);
  2078. d->m_restored = false;
  2079. }
  2080. return true;
  2081. }
  2082. TQString KHTMLPart::encoding() const
  2083. {
  2084. if(d->m_haveEncoding && !d->m_encoding.isEmpty())
  2085. return d->m_encoding;
  2086. if(d->m_decoder && d->m_decoder->encoding())
  2087. return TQString(d->m_decoder->encoding());
  2088. return defaultEncoding();
  2089. }
  2090. TQString KHTMLPart::defaultEncoding() const
  2091. {
  2092. TQString encoding = settings()->encoding();
  2093. if ( !encoding.isEmpty() )
  2094. return encoding;
  2095. // HTTP requires the default encoding to be latin1, when neither
  2096. // the user nor the page requested a particular encoding.
  2097. if ( url().protocol().startsWith( "http" ) )
  2098. return "iso-8859-1";
  2099. else
  2100. return KGlobal::locale()->encoding();
  2101. }
  2102. void KHTMLPart::setUserStyleSheet(const KURL &url)
  2103. {
  2104. if ( d->m_doc && d->m_doc->docLoader() )
  2105. (void) new khtml::PartStyleSheetLoader(this, url.url(), d->m_doc->docLoader());
  2106. }
  2107. void KHTMLPart::setUserStyleSheet(const TQString &styleSheet)
  2108. {
  2109. if ( d->m_doc )
  2110. d->m_doc->setUserStyleSheet( styleSheet );
  2111. }
  2112. bool KHTMLPart::gotoAnchor( const TQString &name )
  2113. {
  2114. if (!d->m_doc)
  2115. return false;
  2116. HTMLCollectionImpl *anchors =
  2117. new HTMLCollectionImpl( d->m_doc, HTMLCollectionImpl::DOC_ANCHORS);
  2118. anchors->ref();
  2119. NodeImpl *n = anchors->namedItem(name);
  2120. anchors->deref();
  2121. if(!n) {
  2122. n = d->m_doc->getElementById( name );
  2123. }
  2124. d->m_doc->setCSSTarget(n); // Setting to null will clear the current target.
  2125. // Implement the rule that "" and "top" both mean top of page as in other browsers.
  2126. bool quirkyName = !n && !d->m_doc->inStrictMode() && (name.isEmpty() || name.lower() == "top");
  2127. if (quirkyName) {
  2128. d->m_view->setContentsPos(0, 0);
  2129. return true;
  2130. } else if (!n) {
  2131. kdDebug(6050) << "KHTMLPart::gotoAnchor node '" << name << "' not found" << endl;
  2132. return false;
  2133. }
  2134. int x = 0, y = 0;
  2135. int gox, dummy;
  2136. HTMLElementImpl *a = static_cast<HTMLElementImpl *>(n);
  2137. a->getUpperLeftCorner(x, y);
  2138. if (x <= d->m_view->contentsX())
  2139. gox = x - 10;
  2140. else {
  2141. gox = d->m_view->contentsX();
  2142. if ( x + 10 > d->m_view->contentsX()+d->m_view->visibleWidth()) {
  2143. a->getLowerRightCorner(x, dummy);
  2144. gox = x - d->m_view->visibleWidth() + 10;
  2145. }
  2146. }
  2147. d->m_view->setContentsPos(gox, y);
  2148. return true;
  2149. }
  2150. bool KHTMLPart::nextAnchor()
  2151. {
  2152. if (!d->m_doc)
  2153. return false;
  2154. d->m_view->focusNextPrevNode ( true );
  2155. return true;
  2156. }
  2157. bool KHTMLPart::prevAnchor()
  2158. {
  2159. if (!d->m_doc)
  2160. return false;
  2161. d->m_view->focusNextPrevNode ( false );
  2162. return true;
  2163. }
  2164. void KHTMLPart::setStandardFont( const TQString &name )
  2165. {
  2166. d->m_settings->setStdFontName(name);
  2167. }
  2168. void KHTMLPart::setFixedFont( const TQString &name )
  2169. {
  2170. d->m_settings->setFixedFontName(name);
  2171. }
  2172. void KHTMLPart::setURLCursor( const TQCursor &c )
  2173. {
  2174. d->m_linkCursor = c;
  2175. }
  2176. TQCursor KHTMLPart::urlCursor() const
  2177. {
  2178. return d->m_linkCursor;
  2179. }
  2180. bool KHTMLPart::onlyLocalReferences() const
  2181. {
  2182. return d->m_onlyLocalReferences;
  2183. }
  2184. void KHTMLPart::setOnlyLocalReferences(bool enable)
  2185. {
  2186. d->m_onlyLocalReferences = enable;
  2187. }
  2188. void KHTMLPartPrivate::setFlagRecursively(
  2189. bool KHTMLPartPrivate::*flag, bool value)
  2190. {
  2191. // first set it on the current one
  2192. this->*flag = value;
  2193. // descend into child frames recursively
  2194. {
  2195. TQValueList<khtml::ChildFrame*>::Iterator it = m_frames.begin();
  2196. const TQValueList<khtml::ChildFrame*>::Iterator itEnd = m_frames.end();
  2197. for (; it != itEnd; ++it) {
  2198. KHTMLPart* const part = static_cast<KHTMLPart *>((KParts::ReadOnlyPart *)(*it)->m_part);
  2199. if (part->inherits("KHTMLPart"))
  2200. part->d->setFlagRecursively(flag, value);
  2201. }/*next it*/
  2202. }
  2203. // do the same again for objects
  2204. {
  2205. TQValueList<khtml::ChildFrame*>::Iterator it = m_objects.begin();
  2206. const TQValueList<khtml::ChildFrame*>::Iterator itEnd = m_objects.end();
  2207. for (; it != itEnd; ++it) {
  2208. KHTMLPart* const part = static_cast<KHTMLPart *>((KParts::ReadOnlyPart *)(*it)->m_part);
  2209. if (part->inherits("KHTMLPart"))
  2210. part->d->setFlagRecursively(flag, value);
  2211. }/*next it*/
  2212. }
  2213. }
  2214. void KHTMLPart::setCaretMode(bool enable)
  2215. {
  2216. #ifndef KHTML_NO_CARET
  2217. kdDebug(6200) << "setCaretMode(" << enable << ")" << endl;
  2218. if (isCaretMode() == enable) return;
  2219. d->setFlagRecursively(&KHTMLPartPrivate::m_caretMode, enable);
  2220. // FIXME: this won't work on frames as expected
  2221. if (!isEditable()) {
  2222. if (enable) {
  2223. view()->initCaret(true);
  2224. view()->ensureCaretVisible();
  2225. } else
  2226. view()->caretOff();
  2227. }/*end if*/
  2228. #endif // KHTML_NO_CARET
  2229. }
  2230. bool KHTMLPart::isCaretMode() const
  2231. {
  2232. return d->m_caretMode;
  2233. }
  2234. void KHTMLPart::setEditable(bool enable)
  2235. {
  2236. #ifndef KHTML_NO_CARET
  2237. if (isEditable() == enable) return;
  2238. d->setFlagRecursively(&KHTMLPartPrivate::m_designMode, enable);
  2239. // FIXME: this won't work on frames as expected
  2240. if (!isCaretMode()) {
  2241. if (enable) {
  2242. view()->initCaret(true);
  2243. view()->ensureCaretVisible();
  2244. } else
  2245. view()->caretOff();
  2246. }/*end if*/
  2247. #endif // KHTML_NO_CARET
  2248. }
  2249. bool KHTMLPart::isEditable() const
  2250. {
  2251. return d->m_designMode;
  2252. }
  2253. void KHTMLPart::setCaretPosition(DOM::Node node, long offset, bool extendSelection)
  2254. {
  2255. #ifndef KHTML_NO_CARET
  2256. #if 0
  2257. kdDebug(6200) << k_funcinfo << "node: " << node.handle() << " nodeName: "
  2258. << node.nodeName().string() << " offset: " << offset
  2259. << " extendSelection " << extendSelection << endl;
  2260. #endif
  2261. if (view()->moveCaretTo(node.handle(), offset, !extendSelection))
  2262. emitSelectionChanged();
  2263. view()->ensureCaretVisible();
  2264. #endif // KHTML_NO_CARET
  2265. }
  2266. KHTMLPart::CaretDisplayPolicy KHTMLPart::caretDisplayPolicyNonFocused() const
  2267. {
  2268. #ifndef KHTML_NO_CARET
  2269. return (CaretDisplayPolicy)view()->caretDisplayPolicyNonFocused();
  2270. #else // KHTML_NO_CARET
  2271. return CaretInvisible;
  2272. #endif // KHTML_NO_CARET
  2273. }
  2274. void KHTMLPart::setCaretDisplayPolicyNonFocused(CaretDisplayPolicy policy)
  2275. {
  2276. #ifndef KHTML_NO_CARET
  2277. view()->setCaretDisplayPolicyNonFocused(policy);
  2278. #endif // KHTML_NO_CARET
  2279. }
  2280. void KHTMLPart::setCaretVisible(bool show)
  2281. {
  2282. #ifndef KHTML_NO_CARET
  2283. if (show) {
  2284. NodeImpl *caretNode = xmlDocImpl()->focusNode();
  2285. if (isCaretMode() || isEditable()
  2286. || (caretNode && caretNode->contentEditable())) {
  2287. view()->caretOn();
  2288. }/*end if*/
  2289. } else {
  2290. view()->caretOff();
  2291. }/*end if*/
  2292. #endif // KHTML_NO_CARET
  2293. }
  2294. void KHTMLPart::findTextBegin()
  2295. {
  2296. d->m_findPos = -1;
  2297. d->m_findNode = 0;
  2298. d->m_findPosEnd = -1;
  2299. d->m_findNodeEnd= 0;
  2300. d->m_findPosStart = -1;
  2301. d->m_findNodeStart = 0;
  2302. d->m_findNodePrevious = 0;
  2303. delete d->m_find;
  2304. d->m_find = 0L;
  2305. }
  2306. bool KHTMLPart::initFindNode( bool selection, bool reverse, bool fromCursor )
  2307. {
  2308. if ( !d->m_doc )
  2309. return false;
  2310. DOM::NodeImpl* firstNode = 0L;
  2311. if (d->m_doc->isHTMLDocument())
  2312. firstNode = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
  2313. else
  2314. firstNode = d->m_doc;
  2315. if ( !firstNode )
  2316. {
  2317. //kdDebug(6050) << k_funcinfo << "no first node (body or doc) -> return false" << endl;
  2318. return false;
  2319. }
  2320. if ( firstNode->id() == ID_FRAMESET )
  2321. {
  2322. //kdDebug(6050) << k_funcinfo << "FRAMESET -> return false" << endl;
  2323. return false;
  2324. }
  2325. if ( selection && hasSelection() )
  2326. {
  2327. //kdDebug(6050) << k_funcinfo << "using selection" << endl;
  2328. if ( !fromCursor )
  2329. {
  2330. d->m_findNode = reverse ? d->m_selectionEnd.handle() : d->m_selectionStart.handle();
  2331. d->m_findPos = reverse ? d->m_endOffset : d->m_startOffset;
  2332. }
  2333. d->m_findNodeEnd = reverse ? d->m_selectionStart.handle() : d->m_selectionEnd.handle();
  2334. d->m_findPosEnd = reverse ? d->m_startOffset : d->m_endOffset;
  2335. d->m_findNodeStart = !reverse ? d->m_selectionStart.handle() : d->m_selectionEnd.handle();
  2336. d->m_findPosStart = !reverse ? d->m_startOffset : d->m_endOffset;
  2337. d->m_findNodePrevious = d->m_findNodeStart;
  2338. }
  2339. else // whole document
  2340. {
  2341. //kdDebug(6050) << k_funcinfo << "whole doc" << endl;
  2342. if ( !fromCursor )
  2343. {
  2344. d->m_findNode = firstNode;
  2345. d->m_findPos = reverse ? -1 : 0;
  2346. }
  2347. d->m_findNodeEnd = reverse ? firstNode : 0;
  2348. d->m_findPosEnd = reverse ? 0 : -1;
  2349. d->m_findNodeStart = !reverse ? firstNode : 0;
  2350. d->m_findPosStart = !reverse ? 0 : -1;
  2351. d->m_findNodePrevious = d->m_findNodeStart;
  2352. if ( reverse )
  2353. {
  2354. // Need to find out the really last object, to start from it
  2355. khtml::RenderObject* obj = d->m_findNode ? d->m_findNode->renderer() : 0;
  2356. if ( obj )
  2357. {
  2358. // find the last object in the render tree
  2359. while ( obj->lastChild() )
  2360. {
  2361. obj = obj->lastChild();
  2362. }
  2363. // now get the last object with a NodeImpl associated
  2364. while ( !obj->element() && obj->objectAbove() )
  2365. {
  2366. obj = obj->objectAbove();
  2367. }
  2368. d->m_findNode = obj->element();
  2369. }
  2370. }
  2371. }
  2372. return true;
  2373. }
  2374. // Old method (its API limits the available features - remove in KDE-4)
  2375. bool KHTMLPart::findTextNext( const TQString &str, bool forward, bool caseSensitive, bool isRegExp )
  2376. {
  2377. if ( !initFindNode( false, !forward, d->m_findNode ) )
  2378. return false;
  2379. while(1)
  2380. {
  2381. if( (d->m_findNode->nodeType() == Node::TEXT_NODE || d->m_findNode->nodeType() == Node::CDATA_SECTION_NODE) && d->m_findNode->renderer() )
  2382. {
  2383. DOMString nodeText = d->m_findNode->nodeValue();
  2384. DOMStringImpl *t = nodeText.implementation();
  2385. TQConstString s(t->s, t->l);
  2386. int matchLen = 0;
  2387. if ( isRegExp ) {
  2388. TQRegExp matcher( str );
  2389. matcher.setCaseSensitive( caseSensitive );
  2390. d->m_findPos = matcher.search(s.string(), d->m_findPos+1);
  2391. if ( d->m_findPos != -1 )
  2392. matchLen = matcher.matchedLength();
  2393. }
  2394. else {
  2395. d->m_findPos = s.string().find(str, d->m_findPos+1, caseSensitive);
  2396. matchLen = str.length();
  2397. }
  2398. if(d->m_findPos != -1)
  2399. {
  2400. int x = 0, y = 0;
  2401. if(static_cast<khtml::RenderText *>(d->m_findNode->renderer())
  2402. ->posOfChar(d->m_findPos, x, y))
  2403. d->m_view->setContentsPos(x-50, y-50);
  2404. d->m_selectionStart = d->m_findNode;
  2405. d->m_startOffset = d->m_findPos;
  2406. d->m_selectionEnd = d->m_findNode;
  2407. d->m_endOffset = d->m_findPos + matchLen;
  2408. d->m_startBeforeEnd = true;
  2409. d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
  2410. d->m_selectionEnd.handle(), d->m_endOffset );
  2411. emitSelectionChanged();
  2412. return true;
  2413. }
  2414. }
  2415. d->m_findPos = -1;
  2416. NodeImpl *next;
  2417. if ( forward )
  2418. {
  2419. next = d->m_findNode->firstChild();
  2420. if(!next) next = d->m_findNode->nextSibling();
  2421. while(d->m_findNode && !next) {
  2422. d->m_findNode = d->m_findNode->parentNode();
  2423. if( d->m_findNode ) {
  2424. next = d->m_findNode->nextSibling();
  2425. }
  2426. }
  2427. }
  2428. else
  2429. {
  2430. next = d->m_findNode->lastChild();
  2431. if (!next ) next = d->m_findNode->previousSibling();
  2432. while ( d->m_findNode && !next )
  2433. {
  2434. d->m_findNode = d->m_findNode->parentNode();
  2435. if( d->m_findNode )
  2436. {
  2437. next = d->m_findNode->previousSibling();
  2438. }
  2439. }
  2440. }
  2441. d->m_findNode = next;
  2442. if(!d->m_findNode) return false;
  2443. }
  2444. }
  2445. void KHTMLPart::slotFind()
  2446. {
  2447. KParts::ReadOnlyPart *part = currentFrame();
  2448. if (!part)
  2449. return;
  2450. if (!part->inherits("KHTMLPart") )
  2451. {
  2452. kdError(6000) << "slotFind: part is a " << part->className() << ", can't do a search into it" << endl;
  2453. return;
  2454. }
  2455. static_cast<KHTMLPart *>( part )->findText();
  2456. }
  2457. void KHTMLPart::slotFindNext()
  2458. {
  2459. KParts::ReadOnlyPart *part = currentFrame();
  2460. if (!part)
  2461. return;
  2462. if (!part->inherits("KHTMLPart") )
  2463. {
  2464. kdError(6000) << "slotFindNext: part is a " << part->className() << ", can't do a search into it" << endl;
  2465. return;
  2466. }
  2467. static_cast<KHTMLPart *>( part )->findTextNext();
  2468. }
  2469. void KHTMLPart::slotFindPrev()
  2470. {
  2471. KParts::ReadOnlyPart *part = currentFrame();
  2472. if (!part)
  2473. return;
  2474. if (!part->inherits("KHTMLPart") )
  2475. {
  2476. kdError(6000) << "slotFindNext: part is a " << part->className() << ", can't do a search into it" << endl;
  2477. return;
  2478. }
  2479. static_cast<KHTMLPart *>( part )->findTextNext( true ); // reverse
  2480. }
  2481. void KHTMLPart::slotFindDone()
  2482. {
  2483. // ### remove me
  2484. }
  2485. void KHTMLPart::slotFindAheadText()
  2486. {
  2487. #ifndef KHTML_NO_TYPE_AHEAD_FIND
  2488. KParts::ReadOnlyPart *part = currentFrame();
  2489. if (!part)
  2490. return;
  2491. if (!part->inherits("KHTMLPart") )
  2492. {
  2493. kdError(6000) << "slotFindNext: part is a " << part->className() << ", can't do a search into it" << endl;
  2494. return;
  2495. }
  2496. static_cast<KHTMLPart *>( part )->view()->startFindAhead( false );
  2497. #endif // KHTML_NO_TYPE_AHEAD_FIND
  2498. }
  2499. void KHTMLPart::slotFindAheadLink()
  2500. {
  2501. #ifndef KHTML_NO_TYPE_AHEAD_FIND
  2502. KParts::ReadOnlyPart *part = currentFrame();
  2503. if (!part)
  2504. return;
  2505. if (!part->inherits("KHTMLPart") )
  2506. {
  2507. kdError(6000) << "slotFindNext: part is a " << part->className() << ", can't do a search into it" << endl;
  2508. return;
  2509. }
  2510. static_cast<KHTMLPart *>( part )->view()->startFindAhead( true );
  2511. #endif // KHTML_NO_TYPE_AHEAD_FIND
  2512. }
  2513. void KHTMLPart::enableFindAheadActions( bool enable )
  2514. {
  2515. // only the topmost one has shortcuts
  2516. KHTMLPart* p = this;
  2517. while( p->parentPart())
  2518. p = p->parentPart();
  2519. p->d->m_paFindAheadText->setEnabled( enable );
  2520. p->d->m_paFindAheadLinks->setEnabled( enable );
  2521. }
  2522. void KHTMLPart::slotFindDialogDestroyed()
  2523. {
  2524. d->m_lastFindState.options = d->m_findDialog->options();
  2525. d->m_lastFindState.history = d->m_findDialog->findHistory();
  2526. d->m_findDialog->deleteLater();
  2527. d->m_findDialog = 0L;
  2528. }
  2529. void KHTMLPart::findText()
  2530. {
  2531. // First do some init to make sure we can search in this frame
  2532. if ( !d->m_doc )
  2533. return;
  2534. // Raise if already opened
  2535. if ( d->m_findDialog )
  2536. {
  2537. KWin::activateWindow( d->m_findDialog->winId() );
  2538. return;
  2539. }
  2540. // The lineedit of the dialog would make khtml lose its selection, otherwise
  2541. #ifndef QT_NO_CLIPBOARD
  2542. disconnect( kapp->clipboard(), TQT_SIGNAL(selectionChanged()), this, TQT_SLOT(slotClearSelection()) );
  2543. #endif
  2544. // Now show the dialog in which the user can choose options.
  2545. d->m_findDialog = new KFindDialog( false /*non-modal*/, widget(), "khtmlfind" );
  2546. d->m_findDialog->setHasSelection( hasSelection() );
  2547. d->m_findDialog->setHasCursor( d->m_findNode != 0 );
  2548. if ( d->m_findNode ) // has a cursor -> default to 'FromCursor'
  2549. d->m_lastFindState.options |= KFindDialog::FromCursor;
  2550. // TODO? optionsDialog.setPattern( d->m_lastFindState.text );
  2551. d->m_findDialog->setFindHistory( d->m_lastFindState.history );
  2552. d->m_findDialog->setOptions( d->m_lastFindState.options );
  2553. d->m_lastFindState.options = -1; // force update in findTextNext
  2554. d->m_lastFindState.last_dir = -1;
  2555. d->m_findDialog->show();
  2556. connect( d->m_findDialog, TQT_SIGNAL(okClicked()), this, TQT_SLOT(slotFindNext()) );
  2557. connect( d->m_findDialog, TQT_SIGNAL(finished()), this, TQT_SLOT(slotFindDialogDestroyed()) );
  2558. findText( d->m_findDialog->pattern(), 0 /*options*/, widget(), d->m_findDialog );
  2559. }
  2560. void KHTMLPart::findText( const TQString &str, long options, TQWidget *parent, KFindDialog *findDialog )
  2561. {
  2562. // First do some init to make sure we can search in this frame
  2563. if ( !d->m_doc )
  2564. return;
  2565. #ifndef QT_NO_CLIPBOARD
  2566. connect( kapp->clipboard(), TQT_SIGNAL(selectionChanged()), TQT_SLOT(slotClearSelection()) );
  2567. #endif
  2568. // Create the KFind object
  2569. delete d->m_find;
  2570. d->m_find = new KFind( str, options, parent, findDialog );
  2571. d->m_find->closeFindNextDialog(); // we use KFindDialog non-modal, so we don't want other dlg popping up
  2572. connect( d->m_find, TQT_SIGNAL( highlight( const TQString &, int, int ) ),
  2573. this, TQT_SLOT( slotHighlight( const TQString &, int, int ) ) );
  2574. //connect(d->m_find, TQT_SIGNAL( findNext() ),
  2575. // this, TQT_SLOT( slotFindNext() ) );
  2576. if ( !findDialog )
  2577. {
  2578. d->m_lastFindState.options = options;
  2579. initFindNode( options & KFindDialog::SelectedText,
  2580. options & KFindDialog::FindBackwards,
  2581. options & KFindDialog::FromCursor );
  2582. }
  2583. }
  2584. bool KHTMLPart::findTextNext()
  2585. {
  2586. return findTextNext( false );
  2587. }
  2588. // New method
  2589. bool KHTMLPart::findTextNext( bool reverse )
  2590. {
  2591. if (!d->m_find)
  2592. {
  2593. // We didn't show the find dialog yet, let's do it then (#49442)
  2594. findText();
  2595. return false;
  2596. }
  2597. view()->updateFindAheadTimeout();
  2598. long options = 0;
  2599. if ( d->m_findDialog ) // 0 when we close the dialog
  2600. {
  2601. if ( d->m_find->pattern() != d->m_findDialog->pattern() ) {
  2602. d->m_find->setPattern( d->m_findDialog->pattern() );
  2603. d->m_find->resetCounts();
  2604. }
  2605. options = d->m_findDialog->options();
  2606. if ( d->m_lastFindState.options != options )
  2607. {
  2608. d->m_find->setOptions( options );
  2609. if ( options & KFindDialog::SelectedText )
  2610. Q_ASSERT( hasSelection() );
  2611. long difference = d->m_lastFindState.options ^ options;
  2612. if ( difference & (KFindDialog::SelectedText | KFindDialog::FromCursor ) )
  2613. {
  2614. // Important options changed -> reset search range
  2615. (void) initFindNode( options & KFindDialog::SelectedText,
  2616. options & KFindDialog::FindBackwards,
  2617. options & KFindDialog::FromCursor );
  2618. }
  2619. d->m_lastFindState.options = options;
  2620. }
  2621. } else
  2622. options = d->m_lastFindState.options;
  2623. if( reverse )
  2624. options = options ^ KFindDialog::FindBackwards;
  2625. if( d->m_find->options() != options )
  2626. d->m_find->setOptions( options );
  2627. // Changing find direction. Start and end nodes must be switched.
  2628. // Additionally since d->m_findNode points after the last node
  2629. // that was searched, it needs to be "after" it in the opposite direction.
  2630. if( d->m_lastFindState.last_dir != -1
  2631. && bool( d->m_lastFindState.last_dir ) != bool( options & KFindDialog::FindBackwards ))
  2632. {
  2633. tqSwap( d->m_findNodeEnd, d->m_findNodeStart );
  2634. tqSwap( d->m_findPosEnd, d->m_findPosStart );
  2635. tqSwap( d->m_findNode, d->m_findNodePrevious );
  2636. // d->m_findNode now point at the end of the last searched line - advance one node
  2637. khtml::RenderObject* obj = d->m_findNode ? d->m_findNode->renderer() : 0;
  2638. khtml::RenderObject* end = d->m_findNodeEnd ? d->m_findNodeEnd->renderer() : 0;
  2639. if ( obj == end )
  2640. obj = 0L;
  2641. else if ( obj )
  2642. {
  2643. do {
  2644. obj = (options & KFindDialog::FindBackwards) ? obj->objectAbove() : obj->objectBelow();
  2645. } while ( obj && ( !obj->element() || obj->isInlineContinuation() ) );
  2646. }
  2647. if ( obj )
  2648. d->m_findNode = obj->element();
  2649. else
  2650. d->m_findNode = 0;
  2651. }
  2652. d->m_lastFindState.last_dir = ( options & KFindDialog::FindBackwards ) ? 1 : 0;
  2653. KFind::Result res = KFind::NoMatch;
  2654. khtml::RenderObject* obj = d->m_findNode ? d->m_findNode->renderer() : 0;
  2655. khtml::RenderObject* end = d->m_findNodeEnd ? d->m_findNodeEnd->renderer() : 0;
  2656. khtml::RenderTextArea *tmpTextArea=0L;
  2657. //kdDebug(6050) << k_funcinfo << "obj=" << obj << " end=" << end << endl;
  2658. while( res == KFind::NoMatch )
  2659. {
  2660. if ( d->m_find->needData() )
  2661. {
  2662. if ( !obj ) {
  2663. //kdDebug(6050) << k_funcinfo << "obj=0 -> done" << endl;
  2664. break; // we're done
  2665. }
  2666. //kdDebug(6050) << k_funcinfo << " gathering data" << endl;
  2667. // First make up the TQString for the current 'line' (i.e. up to \n)
  2668. // We also want to remember the DOMNode for every portion of the string.
  2669. // We store this in an index->node list.
  2670. d->m_stringPortions.clear();
  2671. bool newLine = false;
  2672. TQString str;
  2673. DOM::NodeImpl* lastNode = d->m_findNode;
  2674. while ( obj && !newLine )
  2675. {
  2676. // Grab text from render object
  2677. TQString s;
  2678. bool renderAreaText = obj->parent() && (TQCString(obj->parent()->renderName())== "RenderTextArea");
  2679. bool renderLineText = (TQCString(obj->renderName())== "RenderLineEdit");
  2680. if ( renderAreaText )
  2681. {
  2682. khtml::RenderTextArea *parent= static_cast<khtml::RenderTextArea *>(obj->parent());
  2683. s = parent->text();
  2684. s = s.replace(0xa0, ' ');
  2685. tmpTextArea = parent;
  2686. }
  2687. else if ( renderLineText )
  2688. {
  2689. khtml::RenderLineEdit *parentLine= static_cast<khtml::RenderLineEdit *>(obj);
  2690. if (parentLine->widget()->echoMode() == TQLineEdit::Normal)
  2691. s = parentLine->widget()->text();
  2692. s = s.replace(0xa0, ' ');
  2693. }
  2694. else if ( obj->isText() )
  2695. {
  2696. bool isLink = false;
  2697. // checks whether the node has a <A> parent
  2698. if ( options & FindLinksOnly )
  2699. {
  2700. DOM::NodeImpl *parent = obj->element();
  2701. while ( parent )
  2702. {
  2703. if ( parent->nodeType() == Node::ELEMENT_NODE && parent->id() == ID_A )
  2704. {
  2705. isLink = true;
  2706. break;
  2707. }
  2708. parent = parent->parentNode();
  2709. }
  2710. }
  2711. else
  2712. {
  2713. isLink = true;
  2714. }
  2715. if ( isLink && obj->parent()!=tmpTextArea )
  2716. {
  2717. s = static_cast<khtml::RenderText *>(obj)->data().string();
  2718. s = s.replace(0xa0, ' ');
  2719. }
  2720. }
  2721. else if ( obj->isBR() )
  2722. s = '\n';
  2723. else if ( !obj->isInline() && !str.isEmpty() )
  2724. s = '\n';
  2725. if ( lastNode == d->m_findNodeEnd )
  2726. s.truncate( d->m_findPosEnd );
  2727. if ( !s.isEmpty() )
  2728. {
  2729. newLine = s.find( '\n' ) != -1; // did we just get a newline?
  2730. if( !( options & KFindDialog::FindBackwards ))
  2731. {
  2732. //kdDebug(6050) << "StringPortion: " << index << "-" << index+s.length()-1 << " -> " << lastNode << endl;
  2733. d->m_stringPortions.append( KHTMLPartPrivate::StringPortion( str.length(), lastNode ) );
  2734. str += s;
  2735. }
  2736. else // KFind itself can search backwards, so str must not be built backwards
  2737. {
  2738. for( TQValueList<KHTMLPartPrivate::StringPortion>::Iterator it = d->m_stringPortions.begin();
  2739. it != d->m_stringPortions.end();
  2740. ++it )
  2741. (*it).index += s.length();
  2742. d->m_stringPortions.prepend( KHTMLPartPrivate::StringPortion( 0, lastNode ) );
  2743. str.prepend( s );
  2744. }
  2745. }
  2746. // Compare obj and end _after_ we processed the 'end' node itself
  2747. if ( obj == end )
  2748. obj = 0L;
  2749. else
  2750. {
  2751. // Move on to next object (note: if we found a \n already, then obj (and lastNode)
  2752. // will point to the _next_ object, i.e. they are in advance.
  2753. do {
  2754. // We advance until the next RenderObject that has a NodeImpl as its element().
  2755. // Otherwise (if we keep the 'last node', and it has a '\n') we might be stuck
  2756. // on that object forever...
  2757. obj = (options & KFindDialog::FindBackwards) ? obj->objectAbove() : obj->objectBelow();
  2758. } while ( obj && ( !obj->element() || obj->isInlineContinuation() ) );
  2759. }
  2760. if ( obj )
  2761. lastNode = obj->element();
  2762. else
  2763. lastNode = 0;
  2764. } // end while
  2765. //kdDebug()<<" str : "<<str<<endl;
  2766. if ( !str.isEmpty() )
  2767. {
  2768. d->m_find->setData( str, d->m_findPos );
  2769. }
  2770. d->m_findPos = -1; // not used during the findnext loops. Only during init.
  2771. d->m_findNodePrevious = d->m_findNode;
  2772. d->m_findNode = lastNode;
  2773. }
  2774. if ( !d->m_find->needData() ) // happens if str was empty
  2775. {
  2776. // Let KFind inspect the text fragment, and emit highlighted if a match is found
  2777. res = d->m_find->find();
  2778. }
  2779. } // end while
  2780. if ( res == KFind::NoMatch ) // i.e. we're done
  2781. {
  2782. kdDebug() << "No more matches." << endl;
  2783. if ( !(options & FindNoPopups) && d->m_find->shouldRestart() )
  2784. {
  2785. //kdDebug(6050) << "Restarting" << endl;
  2786. initFindNode( false, options & KFindDialog::FindBackwards, false );
  2787. d->m_find->resetCounts();
  2788. findTextNext( reverse );
  2789. }
  2790. else // really done
  2791. {
  2792. //kdDebug(6050) << "Finishing" << endl;
  2793. //delete d->m_find;
  2794. //d->m_find = 0L;
  2795. initFindNode( false, options & KFindDialog::FindBackwards, false );
  2796. d->m_find->resetCounts();
  2797. slotClearSelection();
  2798. }
  2799. kdDebug() << "Dialog closed." << endl;
  2800. }
  2801. return res == KFind::Match;
  2802. }
  2803. void KHTMLPart::slotHighlight( const TQString& /*text*/, int index, int length )
  2804. {
  2805. //kdDebug(6050) << "slotHighlight index=" << index << " length=" << length << endl;
  2806. TQValueList<KHTMLPartPrivate::StringPortion>::Iterator it = d->m_stringPortions.begin();
  2807. const TQValueList<KHTMLPartPrivate::StringPortion>::Iterator itEnd = d->m_stringPortions.end();
  2808. TQValueList<KHTMLPartPrivate::StringPortion>::Iterator prev = it;
  2809. // We stop at the first portion whose index is 'greater than', and then use the previous one
  2810. while ( it != itEnd && (*it).index <= index )
  2811. {
  2812. prev = it;
  2813. ++it;
  2814. }
  2815. Q_ASSERT ( prev != itEnd );
  2816. DOM::NodeImpl* node = (*prev).node;
  2817. Q_ASSERT( node );
  2818. d->m_selectionStart = node;
  2819. d->m_startOffset = index - (*prev).index;
  2820. khtml::RenderObject* obj = node->renderer();
  2821. khtml::RenderTextArea *parent = 0L;
  2822. khtml::RenderLineEdit *parentLine = 0L;
  2823. bool renderLineText =false;
  2824. TQRect highlightedRect;
  2825. bool renderAreaText =false;
  2826. Q_ASSERT( obj );
  2827. if ( obj )
  2828. {
  2829. int x = 0, y = 0;
  2830. renderAreaText = (TQCString(obj->parent()->renderName())== "RenderTextArea");
  2831. renderLineText = (TQCString(obj->renderName())== "RenderLineEdit");
  2832. if( renderAreaText )
  2833. parent= static_cast<khtml::RenderTextArea *>(obj->parent());
  2834. if ( renderLineText )
  2835. parentLine= static_cast<khtml::RenderLineEdit *>(obj);
  2836. if ( !renderLineText )
  2837. //if (static_cast<khtml::RenderText *>(node->renderer())
  2838. // ->posOfChar(d->m_startOffset, x, y))
  2839. {
  2840. int dummy;
  2841. static_cast<khtml::RenderText *>(node->renderer())
  2842. ->caretPos( d->m_startOffset, false, x, y, dummy, dummy ); // more precise than posOfChar
  2843. //kdDebug(6050) << "topleft: " << x << "," << y << endl;
  2844. if ( x != -1 || y != -1 )
  2845. {
  2846. int gox = d->m_view->contentsX();
  2847. if (x+50 > d->m_view->contentsX() + d->m_view->visibleWidth())
  2848. gox = x - d->m_view->visibleWidth() + 50;
  2849. if (x-10 < d->m_view->contentsX())
  2850. gox = x - d->m_view->visibleWidth() - 10;
  2851. if (gox < 0) gox = 0;
  2852. d->m_view->setContentsPos(gox, y-50);
  2853. highlightedRect.setTopLeft( d->m_view->mapToGlobal(TQPoint(x, y)) );
  2854. }
  2855. }
  2856. }
  2857. // Now look for end node
  2858. it = prev; // no need to start from beginning again
  2859. while ( it != itEnd && (*it).index < index + length )
  2860. {
  2861. prev = it;
  2862. ++it;
  2863. }
  2864. Q_ASSERT ( prev != itEnd );
  2865. d->m_selectionEnd = (*prev).node;
  2866. d->m_endOffset = index + length - (*prev).index;
  2867. d->m_startBeforeEnd = true;
  2868. // if the selection is limited to a single link, that link gets focus
  2869. if(d->m_selectionStart == d->m_selectionEnd)
  2870. {
  2871. bool isLink = false;
  2872. // checks whether the node has a <A> parent
  2873. DOM::NodeImpl *parent = d->m_selectionStart.handle();
  2874. while ( parent )
  2875. {
  2876. if ( parent->nodeType() == Node::ELEMENT_NODE && parent->id() == ID_A )
  2877. {
  2878. isLink = true;
  2879. break;
  2880. }
  2881. parent = parent->parentNode();
  2882. }
  2883. if(isLink == true)
  2884. {
  2885. d->m_doc->setFocusNode( parent );
  2886. }
  2887. }
  2888. #if 0
  2889. kdDebug(6050) << "slotHighlight: " << d->m_selectionStart.handle() << "," << d->m_startOffset << " - " <<
  2890. d->m_selectionEnd.handle() << "," << d->m_endOffset << endl;
  2891. it = d->m_stringPortions.begin();
  2892. for ( ; it != d->m_stringPortions.end() ; ++it )
  2893. kdDebug(6050) << " StringPortion: from index=" << (*it).index << " -> node=" << (*it).node << endl;
  2894. #endif
  2895. if( renderAreaText )
  2896. {
  2897. if( parent )
  2898. parent->highLightWord( length, d->m_endOffset-length );
  2899. }
  2900. else if ( renderLineText )
  2901. {
  2902. if( parentLine )
  2903. parentLine->highLightWord( length, d->m_endOffset-length );
  2904. }
  2905. else
  2906. {
  2907. d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
  2908. d->m_selectionEnd.handle(), d->m_endOffset );
  2909. if (d->m_selectionEnd.handle()->renderer() )
  2910. {
  2911. int x, y, height, dummy;
  2912. static_cast<khtml::RenderText *>(d->m_selectionEnd.handle()->renderer())
  2913. ->caretPos( d->m_endOffset, false, x, y, dummy, height ); // more precise than posOfChar
  2914. //kdDebug(6050) << "bottomright: " << x << "," << y+height << endl;
  2915. if ( x != -1 || y != -1 )
  2916. {
  2917. // if ( static_cast<khtml::RenderText *>(d->m_selectionEnd.handle()->renderer())
  2918. // ->posOfChar(d->m_endOffset-1, x, y))
  2919. highlightedRect.setBottomRight( d->m_view->mapToGlobal( TQPoint(x, y+height) ) );
  2920. }
  2921. }
  2922. }
  2923. emitSelectionChanged();
  2924. // make the finddialog move away from the selected area
  2925. if ( d->m_findDialog && !highlightedRect.isNull() )
  2926. {
  2927. highlightedRect.moveBy( -d->m_view->contentsX(), -d->m_view->contentsY() );
  2928. //kdDebug(6050) << "avoiding " << highlightedRect << endl;
  2929. KDialog::avoidArea( d->m_findDialog, highlightedRect );
  2930. }
  2931. }
  2932. TQString KHTMLPart::selectedTextAsHTML() const
  2933. {
  2934. if(!hasSelection()) {
  2935. kdDebug() << "selectedTextAsHTML(): selection is not valid. Returning empty selection" << endl;
  2936. return TQString();
  2937. }
  2938. if(d->m_startOffset < 0 || d->m_endOffset <0) {
  2939. kdDebug() << "invalid values for end/startOffset " << d->m_startOffset << " " << d->m_endOffset << endl;
  2940. return TQString();
  2941. }
  2942. DOM::Range r = selection();
  2943. if(r.isNull() || r.isDetached())
  2944. return TQString();
  2945. int exceptioncode = 0; //ignore the result
  2946. return r.handle()->toHTML(exceptioncode).string();
  2947. }
  2948. TQString KHTMLPart::selectedText() const
  2949. {
  2950. bool hasNewLine = true;
  2951. bool seenTDTag = false;
  2952. TQString text;
  2953. DOM::Node n = d->m_selectionStart;
  2954. while(!n.isNull()) {
  2955. if(n.nodeType() == DOM::Node::TEXT_NODE && n.handle()->renderer()) {
  2956. DOM::DOMStringImpl *dstr = static_cast<DOM::TextImpl*>(n.handle())->renderString();
  2957. TQString str(dstr->s, dstr->l);
  2958. if(!str.isEmpty()) {
  2959. if(seenTDTag) {
  2960. text += " ";
  2961. seenTDTag = false;
  2962. }
  2963. hasNewLine = false;
  2964. if(n == d->m_selectionStart && n == d->m_selectionEnd)
  2965. text = str.mid(d->m_startOffset, d->m_endOffset - d->m_startOffset);
  2966. else if(n == d->m_selectionStart)
  2967. text = str.mid(d->m_startOffset);
  2968. else if(n == d->m_selectionEnd)
  2969. text += str.left(d->m_endOffset);
  2970. else
  2971. text += str;
  2972. }
  2973. }
  2974. else {
  2975. // This is our simple HTML -> ASCII transformation:
  2976. unsigned short id = n.elementId();
  2977. switch(id) {
  2978. case ID_TEXTAREA:
  2979. text += static_cast<HTMLTextAreaElementImpl*>(n.handle())->value().string();
  2980. break;
  2981. case ID_INPUT:
  2982. if (static_cast<HTMLInputElementImpl*>(n.handle())->inputType() != HTMLInputElementImpl::PASSWORD)
  2983. text += static_cast<HTMLInputElementImpl*>(n.handle())->value().string();
  2984. break;
  2985. case ID_SELECT:
  2986. text += static_cast<HTMLSelectElementImpl*>(n.handle())->value().string();
  2987. break;
  2988. case ID_BR:
  2989. text += "\n";
  2990. hasNewLine = true;
  2991. break;
  2992. case ID_IMG:
  2993. text += static_cast<HTMLImageElementImpl*>(n.handle())->altText().string();
  2994. break;
  2995. case ID_TD:
  2996. break;
  2997. case ID_TH:
  2998. case ID_HR:
  2999. case ID_OL:
  3000. case ID_UL:
  3001. case ID_LI:
  3002. case ID_DD:
  3003. case ID_DL:
  3004. case ID_DT:
  3005. case ID_PRE:
  3006. case ID_BLOCKQUOTE:
  3007. case ID_DIV:
  3008. if (!hasNewLine)
  3009. text += "\n";
  3010. hasNewLine = true;
  3011. break;
  3012. case ID_P:
  3013. case ID_TR:
  3014. case ID_H1:
  3015. case ID_H2:
  3016. case ID_H3:
  3017. case ID_H4:
  3018. case ID_H5:
  3019. case ID_H6:
  3020. if (!hasNewLine)
  3021. text += "\n";
  3022. // text += "\n";
  3023. hasNewLine = true;
  3024. break;
  3025. }
  3026. }
  3027. if(n == d->m_selectionEnd) break;
  3028. DOM::Node next = n.firstChild();
  3029. if(next.isNull()) next = n.nextSibling();
  3030. while( next.isNull() && !n.parentNode().isNull() ) {
  3031. n = n.parentNode();
  3032. next = n.nextSibling();
  3033. unsigned short id = n.elementId();
  3034. switch(id) {
  3035. case ID_TD:
  3036. seenTDTag = true; //Add two spaces after a td if then followed by text.
  3037. break;
  3038. case ID_TH:
  3039. case ID_HR:
  3040. case ID_OL:
  3041. case ID_UL:
  3042. case ID_LI:
  3043. case ID_DD:
  3044. case ID_DL:
  3045. case ID_DT:
  3046. case ID_PRE:
  3047. case ID_BLOCKQUOTE:
  3048. case ID_DIV:
  3049. seenTDTag = false;
  3050. if (!hasNewLine)
  3051. text += "\n";
  3052. hasNewLine = true;
  3053. break;
  3054. case ID_P:
  3055. case ID_TR:
  3056. case ID_H1:
  3057. case ID_H2:
  3058. case ID_H3:
  3059. case ID_H4:
  3060. case ID_H5:
  3061. case ID_H6:
  3062. if (!hasNewLine)
  3063. text += "\n";
  3064. // text += "\n";
  3065. hasNewLine = true;
  3066. break;
  3067. }
  3068. }
  3069. n = next;
  3070. }
  3071. if(text.isEmpty())
  3072. return TQString();
  3073. int start = 0;
  3074. int end = text.length();
  3075. // Strip leading LFs
  3076. while ((start < end) && (text[start] == '\n'))
  3077. ++start;
  3078. // Strip excessive trailing LFs
  3079. while ((start < (end-1)) && (text[end-1] == '\n') && (text[end-2] == '\n'))
  3080. --end;
  3081. return text.mid(start, end-start);
  3082. }
  3083. bool KHTMLPart::hasSelection() const
  3084. {
  3085. if ( d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() )
  3086. return false;
  3087. if ( d->m_selectionStart == d->m_selectionEnd &&
  3088. d->m_startOffset == d->m_endOffset )
  3089. return false; // empty
  3090. return true;
  3091. }
  3092. DOM::Range KHTMLPart::selection() const
  3093. {
  3094. if( d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() )
  3095. return DOM::Range();
  3096. DOM::Range r = document().createRange();
  3097. RangeImpl *rng = r.handle();
  3098. int exception = 0;
  3099. NodeImpl *n = d->m_selectionStart.handle();
  3100. if(!n->parentNode() ||
  3101. !n->renderer() ||
  3102. (!n->renderer()->isReplaced() && !n->renderer()->isBR())) {
  3103. rng->setStart( n, d->m_startOffset, exception );
  3104. if(exception) {
  3105. kdDebug(6000) << "1 -selection() threw the exception " << exception << ". Returning empty range." << endl;
  3106. return DOM::Range();
  3107. }
  3108. } else {
  3109. int o_start = 0;
  3110. while ((n = n->previousSibling()))
  3111. o_start++;
  3112. rng->setStart( d->m_selectionStart.parentNode().handle(), o_start + d->m_startOffset, exception );
  3113. if(exception) {
  3114. kdDebug(6000) << "2 - selection() threw the exception " << exception << ". Returning empty range." << endl;
  3115. return DOM::Range();
  3116. }
  3117. }
  3118. n = d->m_selectionEnd.handle();
  3119. if(!n->parentNode() ||
  3120. !n->renderer() ||
  3121. (!n->renderer()->isReplaced() && !n->renderer()->isBR())) {
  3122. rng->setEnd( n, d->m_endOffset, exception );
  3123. if(exception) {
  3124. kdDebug(6000) << "3 - selection() threw the exception " << exception << ". Returning empty range." << endl;
  3125. return DOM::Range();
  3126. }
  3127. } else {
  3128. int o_end = 0;
  3129. while ((n = n->previousSibling()))
  3130. o_end++;
  3131. rng->setEnd( d->m_selectionEnd.parentNode().handle(), o_end + d->m_endOffset, exception);
  3132. if(exception) {
  3133. kdDebug(6000) << "4 - selection() threw the exception " << exception << ". Returning empty range." << endl;
  3134. return DOM::Range();
  3135. }
  3136. }
  3137. return r;
  3138. }
  3139. void KHTMLPart::selection(DOM::Node &s, long &so, DOM::Node &e, long &eo) const
  3140. {
  3141. s = d->m_selectionStart;
  3142. so = d->m_startOffset;
  3143. e = d->m_selectionEnd;
  3144. eo = d->m_endOffset;
  3145. }
  3146. void KHTMLPart::setSelection( const DOM::Range &r )
  3147. {
  3148. // Quick-fix: a collapsed range shouldn't select the whole node.
  3149. // The real problem is in RenderCanvas::setSelection though (when index==0 the whole node is selected).
  3150. if ( r.collapsed() )
  3151. slotClearSelection();
  3152. else {
  3153. d->m_selectionStart = r.startContainer();
  3154. d->m_startOffset = r.startOffset();
  3155. d->m_selectionEnd = r.endContainer();
  3156. d->m_endOffset = r.endOffset();
  3157. d->m_doc->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
  3158. d->m_selectionEnd.handle(),d->m_endOffset);
  3159. #ifndef KHTML_NO_CARET
  3160. bool v = d->m_view->placeCaret();
  3161. emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
  3162. #endif
  3163. }
  3164. }
  3165. void KHTMLPart::slotClearSelection()
  3166. {
  3167. bool hadSelection = hasSelection();
  3168. #ifndef KHTML_NO_CARET
  3169. //kdDebug(6000) << "d->m_selectionStart " << d->m_selectionStart.handle()
  3170. // << " d->m_selectionEnd " << d->m_selectionEnd.handle() << endl;
  3171. // nothing, leave selection parameters as is
  3172. #else
  3173. d->m_selectionStart = 0;
  3174. d->m_startOffset = 0;
  3175. d->m_selectionEnd = 0;
  3176. d->m_endOffset = 0;
  3177. #endif
  3178. if ( d->m_doc ) d->m_doc->clearSelection();
  3179. if ( hadSelection )
  3180. emitSelectionChanged();
  3181. #ifndef KHTML_NO_CARET
  3182. bool v = d->m_view->placeCaret();
  3183. emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
  3184. #endif
  3185. }
  3186. void KHTMLPart::resetHoverText()
  3187. {
  3188. if( !d->m_overURL.isEmpty() ) // Only if we were showing a link
  3189. {
  3190. d->m_overURL = d->m_overURLTarget = TQString();
  3191. emit onURL( TQString() );
  3192. // revert to default statusbar text
  3193. setStatusBarText(TQString(), BarHoverText);
  3194. emit d->m_extension->mouseOverInfo(0);
  3195. }
  3196. }
  3197. void KHTMLPart::overURL( const TQString &url, const TQString &target, bool /*shiftPressed*/ )
  3198. {
  3199. KURL u = completeURL(url);
  3200. // special case for <a href="">
  3201. if ( url.isEmpty() )
  3202. u.setFileName( url );
  3203. emit onURL( url );
  3204. if ( url.isEmpty() ) {
  3205. setStatusBarText(u.htmlURL(), BarHoverText);
  3206. return;
  3207. }
  3208. if (url.find( TQString::fromLatin1( "javascript:" ),0, false ) == 0 ) {
  3209. TQString jscode = KURL::decode_string( url.mid( url.find( "javascript:", 0, false ) ) );
  3210. jscode = KStringHandler::rsqueeze( jscode, 80 ); // truncate if too long
  3211. if (url.startsWith("javascript:window.open"))
  3212. jscode += i18n(" (In new window)");
  3213. setStatusBarText( TQStyleSheet::escape( jscode ), BarHoverText );
  3214. return;
  3215. }
  3216. KFileItem item(u, TQString(), KFileItem::Unknown);
  3217. emit d->m_extension->mouseOverInfo(&item);
  3218. TQString com;
  3219. KMimeType::Ptr typ = KMimeType::findByURL( u );
  3220. if ( typ )
  3221. com = typ->comment( u, false );
  3222. if ( !u.isValid() ) {
  3223. setStatusBarText(u.htmlURL(), BarHoverText);
  3224. return;
  3225. }
  3226. if ( u.isLocalFile() )
  3227. {
  3228. // TODO : use KIO::stat() and create a KFileItem out of its result,
  3229. // to use KFileItem::statusBarText()
  3230. TQCString path = TQFile::encodeName( u.path() );
  3231. struct stat buff;
  3232. bool ok = !stat( path.data(), &buff );
  3233. struct stat lbuff;
  3234. if (ok) ok = !lstat( path.data(), &lbuff );
  3235. TQString text = u.htmlURL();
  3236. TQString text2 = text;
  3237. if (ok && S_ISLNK( lbuff.st_mode ) )
  3238. {
  3239. TQString tmp;
  3240. if ( com.isNull() )
  3241. tmp = i18n( "Symbolic Link");
  3242. else
  3243. tmp = i18n("%1 (Link)").arg(com);
  3244. char buff_two[1024];
  3245. text += " -> ";
  3246. int n = readlink ( path.data(), buff_two, 1022);
  3247. if (n == -1)
  3248. {
  3249. text2 += " ";
  3250. text2 += tmp;
  3251. setStatusBarText(text2, BarHoverText);
  3252. return;
  3253. }
  3254. buff_two[n] = 0;
  3255. text += buff_two;
  3256. text += " ";
  3257. text += tmp;
  3258. }
  3259. else if ( ok && S_ISREG( buff.st_mode ) )
  3260. {
  3261. if (buff.st_size < 1024)
  3262. text = i18n("%2 (%1 bytes)").arg((long) buff.st_size).arg(text2); // always put the URL last, in case it contains '%'
  3263. else
  3264. {
  3265. float d = (float) buff.st_size/1024.0;
  3266. text = i18n("%2 (%1 K)").arg(KGlobal::locale()->formatNumber(d, 2)).arg(text2); // was %.2f
  3267. }
  3268. text += " ";
  3269. text += com;
  3270. }
  3271. else if ( ok && S_ISDIR( buff.st_mode ) )
  3272. {
  3273. text += " ";
  3274. text += com;
  3275. }
  3276. else
  3277. {
  3278. text += " ";
  3279. text += com;
  3280. }
  3281. setStatusBarText(text, BarHoverText);
  3282. }
  3283. else
  3284. {
  3285. TQString extra;
  3286. if (target.lower() == "_blank")
  3287. {
  3288. extra = i18n(" (In new window)");
  3289. }
  3290. else if (!target.isEmpty() &&
  3291. (target.lower() != "_top") &&
  3292. (target.lower() != "_self") &&
  3293. (target.lower() != "_parent"))
  3294. {
  3295. KHTMLPart *p = this;
  3296. while (p->parentPart())
  3297. p = p->parentPart();
  3298. if (!p->frameExists(target))
  3299. extra = i18n(" (In new window)");
  3300. else
  3301. extra = i18n(" (In other frame)");
  3302. }
  3303. if (u.protocol() == TQString::fromLatin1("mailto")) {
  3304. TQString mailtoMsg /* = TQString::fromLatin1("<img src=%1>").arg(locate("icon", TQString::fromLatin1("locolor/16x16/actions/mail_send.png")))*/;
  3305. mailtoMsg += i18n("Email to: ") + KURL::decode_string(u.path());
  3306. TQStringList queries = TQStringList::split('&', u.query().mid(1));
  3307. TQStringList::Iterator it = queries.begin();
  3308. const TQStringList::Iterator itEnd = queries.end();
  3309. for (; it != itEnd; ++it)
  3310. if ((*it).startsWith(TQString::fromLatin1("subject=")))
  3311. mailtoMsg += i18n(" - Subject: ") + KURL::decode_string((*it).mid(8));
  3312. else if ((*it).startsWith(TQString::fromLatin1("cc=")))
  3313. mailtoMsg += i18n(" - CC: ") + KURL::decode_string((*it).mid(3));
  3314. else if ((*it).startsWith(TQString::fromLatin1("bcc=")))
  3315. mailtoMsg += i18n(" - BCC: ") + KURL::decode_string((*it).mid(4));
  3316. mailtoMsg = TQStyleSheet::escape(mailtoMsg);
  3317. mailtoMsg.replace(TQRegExp("([\n\r\t]|[ ]{10})"), TQString());
  3318. setStatusBarText("<qt>"+mailtoMsg, BarHoverText);
  3319. return;
  3320. }
  3321. // Is this check necessary at all? (Frerich)
  3322. #if 0
  3323. else if (u.protocol() == TQString::fromLatin1("http")) {
  3324. DOM::Node hrefNode = nodeUnderMouse().parentNode();
  3325. while (hrefNode.nodeName().string() != TQString::fromLatin1("A") && !hrefNode.isNull())
  3326. hrefNode = hrefNode.parentNode();
  3327. if (!hrefNode.isNull()) {
  3328. DOM::Node hreflangNode = hrefNode.attributes().getNamedItem("HREFLANG");
  3329. if (!hreflangNode.isNull()) {
  3330. TQString countryCode = hreflangNode.nodeValue().string().lower();
  3331. // Map the language code to an appropriate country code.
  3332. if (countryCode == TQString::fromLatin1("en"))
  3333. countryCode = TQString::fromLatin1("gb");
  3334. TQString flagImg = TQString::fromLatin1("<img src=%1>").arg(
  3335. locate("locale", TQString::fromLatin1("l10n/")
  3336. + countryCode
  3337. + TQString::fromLatin1("/flag.png")));
  3338. emit setStatusBarText(flagImg + u.prettyURL() + extra);
  3339. }
  3340. }
  3341. }
  3342. #endif
  3343. setStatusBarText(u.htmlURL() + extra, BarHoverText);
  3344. }
  3345. }
  3346. //
  3347. // This executes in the active part on a click or other url selection action in
  3348. // that active part.
  3349. //
  3350. void KHTMLPart::urlSelected( const TQString &url, int button, int state, const TQString &_target, KParts::URLArgs args )
  3351. {
  3352. // The member var is so that slotRedirection still calls the virtual urlSelected
  3353. // but is able to know if is opened a url. KDE4: just make urlSelected return a bool
  3354. // and move the urlSelectedIntern code back here.
  3355. d->m_urlSelectedOpenedURL = urlSelectedIntern( url, button, state, _target, args );
  3356. }
  3357. // Return value: true if an url was opened, false if not (e.g. error, or jumping to anchor)
  3358. bool KHTMLPart::urlSelectedIntern( const TQString &url, int button, int state, const TQString &_target, KParts::URLArgs args )
  3359. {
  3360. bool hasTarget = false;
  3361. TQString target = _target;
  3362. if ( target.isEmpty() && d->m_doc )
  3363. target = d->m_doc->baseTarget();
  3364. if ( !target.isEmpty() )
  3365. hasTarget = true;
  3366. if ( url.find( TQString::fromLatin1( "javascript:" ), 0, false ) == 0 )
  3367. {
  3368. crossFrameExecuteScript( target, KURL::decode_string( url.mid( 11 ) ) );
  3369. return false;
  3370. }
  3371. KURL cURL = completeURL(url);
  3372. // special case for <a href=""> (IE removes filename, mozilla doesn't)
  3373. if ( url.isEmpty() )
  3374. cURL.setFileName( url ); // removes filename
  3375. if ( !cURL.isValid() )
  3376. // ### ERROR HANDLING
  3377. return false;
  3378. kdDebug(6050) << this << " urlSelected: complete URL:" << cURL.url() << " target=" << target << endl;
  3379. if ( state & ControlButton )
  3380. {
  3381. args.setNewTab(true);
  3382. emit d->m_extension->createNewWindow( cURL, args );
  3383. return true;
  3384. }
  3385. if ( button == Qt::LeftButton && ( state & ShiftButton ) )
  3386. {
  3387. KIO::MetaData metaData;
  3388. metaData["referrer"] = d->m_referrer;
  3389. KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), cURL, metaData );
  3390. return false;
  3391. }
  3392. if (!checkLinkSecurity(cURL,
  3393. i18n( "<qt>This untrusted page links to<BR><B>%1</B>.<BR>Do you want to follow the link?" ),
  3394. i18n( "Follow" )))
  3395. return false;
  3396. args.frameName = target;
  3397. args.metaData().insert("main_frame_request",
  3398. parentPart() == 0 ? "TRUE":"FALSE");
  3399. args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
  3400. args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
  3401. args.metaData().insert("PropagateHttpHeader", "true");
  3402. args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
  3403. args.metaData().insert("ssl_activate_warnings", "TRUE");
  3404. if ( hasTarget && target != "_self" && target != "_top" && target != "_blank" && target != "_parent" )
  3405. {
  3406. // unknown frame names should open in a new window.
  3407. khtml::ChildFrame *frame = recursiveFrameRequest( this, cURL, args, false );
  3408. if ( frame )
  3409. {
  3410. args.metaData()["referrer"] = d->m_referrer;
  3411. requestObject( frame, cURL, args );
  3412. return true;
  3413. }
  3414. }
  3415. if (!d->m_referrer.isEmpty() && !args.metaData().contains("referrer"))
  3416. args.metaData()["referrer"] = d->m_referrer;
  3417. if ( button == Qt::NoButton && (state & ShiftButton) && (state & ControlButton) )
  3418. {
  3419. emit d->m_extension->createNewWindow( cURL, args );
  3420. return true;
  3421. }
  3422. if ( state & ShiftButton)
  3423. {
  3424. KParts::WindowArgs winArgs;
  3425. winArgs.lowerWindow = true;
  3426. KParts::ReadOnlyPart *newPart = 0;
  3427. emit d->m_extension->createNewWindow( cURL, args, winArgs, newPart );
  3428. return true;
  3429. }
  3430. //If we're asked to open up an anchor in the current URL, in current window,
  3431. //merely gotoanchor, and do not reload the new page. Note that this does
  3432. //not apply if the URL is the same page, but without a ref
  3433. if (cURL.hasRef() && (!hasTarget || target == "_self"))
  3434. {
  3435. KURL curUrl = this->url();
  3436. if (urlcmp(cURL.url(), curUrl.url(),
  3437. false, // ignore trailing / diff, IE does, even if FFox doesn't
  3438. true)) // don't care if the ref changes!
  3439. {
  3440. m_url = cURL;
  3441. emit d->m_extension->openURLNotify();
  3442. if ( !gotoAnchor( m_url.encodedHtmlRef()) )
  3443. gotoAnchor( m_url.htmlRef() );
  3444. emit d->m_extension->setLocationBarURL( m_url.prettyURL() );
  3445. return false; // we jumped, but we didn't open a URL
  3446. }
  3447. }
  3448. if ( !d->m_bComplete && !hasTarget )
  3449. closeURL();
  3450. view()->viewport()->unsetCursor();
  3451. emit d->m_extension->openURLRequest( cURL, args );
  3452. return true;
  3453. }
  3454. void KHTMLPart::slotViewDocumentSource()
  3455. {
  3456. KURL url(m_url);
  3457. bool isTempFile = false;
  3458. if (!(url.isLocalFile()) && KHTMLPageCache::self()->isComplete(d->m_cacheId))
  3459. {
  3460. KTempFile sourceFile(TQString(), defaultExtension());
  3461. if (sourceFile.status() == 0)
  3462. {
  3463. KHTMLPageCache::self()->saveData(d->m_cacheId, sourceFile.dataStream());
  3464. url = KURL();
  3465. url.setPath(sourceFile.name());
  3466. isTempFile = true;
  3467. }
  3468. }
  3469. (void) KRun::runURL( url, TQString::fromLatin1("text/plain"), isTempFile );
  3470. }
  3471. void KHTMLPart::slotViewPageInfo()
  3472. {
  3473. KHTMLInfoDlg *dlg = new KHTMLInfoDlg(NULL, "KHTML Page Info Dialog", false, (WFlags)WDestructiveClose);
  3474. dlg->_close->setGuiItem(KStdGuiItem::close());
  3475. if (d->m_doc)
  3476. dlg->_title->setText(d->m_doc->title().string());
  3477. // If it's a frame, set the caption to "Frame Information"
  3478. if ( parentPart() && d->m_doc && d->m_doc->isHTMLDocument() ) {
  3479. dlg->setCaption(i18n("Frame Information"));
  3480. }
  3481. TQString editStr = TQString();
  3482. if (!d->m_pageServices.isEmpty())
  3483. editStr = i18n(" <a href=\"%1\">[Properties]</a>").arg(d->m_pageServices);
  3484. TQString squeezedURL = KStringHandler::csqueeze( url().prettyURL(), 80 );
  3485. dlg->_url->setText("<a href=\"" + url().url() + "\">" + squeezedURL + "</a>" + editStr);
  3486. if (lastModified().isEmpty())
  3487. {
  3488. dlg->_lastModified->hide();
  3489. dlg->_lmLabel->hide();
  3490. }
  3491. else
  3492. dlg->_lastModified->setText(lastModified());
  3493. const TQString& enc = encoding();
  3494. if (enc.isEmpty()) {
  3495. dlg->_eLabel->hide();
  3496. dlg->_encoding->hide();
  3497. } else {
  3498. dlg->_encoding->setText(enc);
  3499. }
  3500. /* populate the list view now */
  3501. const TQStringList headers = TQStringList::split("\n", d->m_httpHeaders);
  3502. TQStringList::ConstIterator it = headers.begin();
  3503. const TQStringList::ConstIterator itEnd = headers.end();
  3504. for (; it != itEnd; ++it) {
  3505. const TQStringList header = TQStringList::split(TQRegExp(":[ ]+"), *it);
  3506. if (header.count() != 2)
  3507. continue;
  3508. new TQListViewItem(dlg->_headers, header[0], header[1]);
  3509. }
  3510. dlg->show();
  3511. /* put no code here */
  3512. }
  3513. void KHTMLPart::slotViewFrameSource()
  3514. {
  3515. KParts::ReadOnlyPart *frame = currentFrame();
  3516. if ( !frame )
  3517. return;
  3518. KURL url = frame->url();
  3519. bool isTempFile = false;
  3520. if (!(url.isLocalFile()) && frame->inherits("KHTMLPart"))
  3521. {
  3522. long cacheId = static_cast<KHTMLPart *>(frame)->d->m_cacheId;
  3523. if (KHTMLPageCache::self()->isComplete(cacheId))
  3524. {
  3525. KTempFile sourceFile(TQString(), defaultExtension());
  3526. if (sourceFile.status() == 0)
  3527. {
  3528. KHTMLPageCache::self()->saveData(cacheId, sourceFile.dataStream());
  3529. url = KURL();
  3530. url.setPath(sourceFile.name());
  3531. isTempFile = true;
  3532. }
  3533. }
  3534. }
  3535. (void) KRun::runURL( url, TQString::fromLatin1("text/plain"), isTempFile );
  3536. }
  3537. KURL KHTMLPart::backgroundURL() const
  3538. {
  3539. // ### what about XML documents? get from CSS?
  3540. if (!d->m_doc || !d->m_doc->isHTMLDocument())
  3541. return KURL();
  3542. TQString relURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
  3543. return KURL( m_url, relURL );
  3544. }
  3545. void KHTMLPart::slotSaveBackground()
  3546. {
  3547. KIO::MetaData metaData;
  3548. metaData["referrer"] = d->m_referrer;
  3549. KHTMLPopupGUIClient::saveURL( d->m_view, i18n("Save Background Image As"), backgroundURL(), metaData );
  3550. }
  3551. void KHTMLPart::slotSaveDocument()
  3552. {
  3553. KURL srcURL( m_url );
  3554. if ( srcURL.fileName(false).isEmpty() )
  3555. srcURL.setFileName( "index" + defaultExtension() );
  3556. KIO::MetaData metaData;
  3557. // Referre unknown?
  3558. KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), srcURL, metaData, "text/html", d->m_cacheId );
  3559. }
  3560. void KHTMLPart::slotSecurity()
  3561. {
  3562. // kdDebug( 6050 ) << "Meta Data:" << endl
  3563. // << d->m_ssl_peer_cert_subject
  3564. // << endl
  3565. // << d->m_ssl_peer_cert_issuer
  3566. // << endl
  3567. // << d->m_ssl_cipher
  3568. // << endl
  3569. // << d->m_ssl_cipher_desc
  3570. // << endl
  3571. // << d->m_ssl_cipher_version
  3572. // << endl
  3573. // << d->m_ssl_good_from
  3574. // << endl
  3575. // << d->m_ssl_good_until
  3576. // << endl
  3577. // << d->m_ssl_cert_state
  3578. // << endl;
  3579. KSSLInfoDlg *kid = new KSSLInfoDlg(d->m_ssl_in_use, widget(), "kssl_info_dlg", true );
  3580. if (d->m_bSecurityInQuestion)
  3581. kid->setSecurityInQuestion(true);
  3582. if (d->m_ssl_in_use) {
  3583. KSSLCertificate *x = KSSLCertificate::fromString(d->m_ssl_peer_certificate.local8Bit());
  3584. if (x) {
  3585. // Set the chain back onto the certificate
  3586. const TQStringList cl = TQStringList::split(TQString("\n"), d->m_ssl_peer_chain);
  3587. TQPtrList<KSSLCertificate> ncl;
  3588. ncl.setAutoDelete(true);
  3589. TQStringList::ConstIterator it = cl.begin();
  3590. const TQStringList::ConstIterator itEnd = cl.end();
  3591. for (; it != itEnd; ++it) {
  3592. KSSLCertificate* const y = KSSLCertificate::fromString((*it).local8Bit());
  3593. if (y) ncl.append(y);
  3594. }
  3595. if (ncl.count() > 0)
  3596. x->chain().setChain(ncl);
  3597. kid->setup(x,
  3598. d->m_ssl_peer_ip,
  3599. m_url.url(),
  3600. d->m_ssl_cipher,
  3601. d->m_ssl_cipher_desc,
  3602. d->m_ssl_cipher_version,
  3603. d->m_ssl_cipher_used_bits.toInt(),
  3604. d->m_ssl_cipher_bits.toInt(),
  3605. (KSSLCertificate::KSSLValidation) d->m_ssl_cert_state.toInt()
  3606. );
  3607. kid->exec();
  3608. delete x;
  3609. } else kid->exec();
  3610. } else kid->exec();
  3611. }
  3612. void KHTMLPart::slotSaveFrame()
  3613. {
  3614. KParts::ReadOnlyPart *frame = currentFrame();
  3615. if ( !frame )
  3616. return;
  3617. KURL srcURL( frame->url() );
  3618. if ( srcURL.fileName(false).isEmpty() )
  3619. srcURL.setFileName( "index" + defaultExtension() );
  3620. KIO::MetaData metaData;
  3621. // Referrer unknown?
  3622. KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save Frame As" ), srcURL, metaData, "text/html" );
  3623. }
  3624. void KHTMLPart::slotSetEncoding()
  3625. {
  3626. d->m_automaticDetection->setItemChecked( int( d->m_autoDetectLanguage ), false );
  3627. d->m_paSetEncoding->popupMenu()->setItemChecked( 0, false );
  3628. d->m_paSetEncoding->popupMenu()->setItemChecked( d->m_paSetEncoding->popupMenu()->idAt( 2 ), true );
  3629. TQString enc = KGlobal::charsets()->encodingForName( d->m_manualDetection->currentText() );
  3630. setEncoding( enc, true );
  3631. }
  3632. void KHTMLPart::slotUseStylesheet()
  3633. {
  3634. if (d->m_doc)
  3635. {
  3636. bool autoselect = (d->m_paUseStylesheet->currentItem() == 0);
  3637. d->m_sheetUsed = autoselect ? TQString() : d->m_paUseStylesheet->currentText();
  3638. d->m_doc->updateStyleSelector();
  3639. }
  3640. }
  3641. void KHTMLPart::updateActions()
  3642. {
  3643. bool frames = false;
  3644. TQValueList<khtml::ChildFrame*>::ConstIterator it = d->m_frames.begin();
  3645. const TQValueList<khtml::ChildFrame*>::ConstIterator end = d->m_frames.end();
  3646. for (; it != end; ++it )
  3647. if ( (*it)->m_type == khtml::ChildFrame::Frame )
  3648. {
  3649. frames = true;
  3650. break;
  3651. }
  3652. d->m_paViewFrame->setEnabled( frames );
  3653. d->m_paSaveFrame->setEnabled( frames );
  3654. if ( frames )
  3655. d->m_paFind->setText( i18n( "&Find in Frame..." ) );
  3656. else
  3657. d->m_paFind->setText( i18n( "&Find..." ) );
  3658. KParts::Part *frame = 0;
  3659. if ( frames )
  3660. frame = currentFrame();
  3661. bool enableFindAndSelectAll = true;
  3662. if ( frame )
  3663. enableFindAndSelectAll = frame->inherits( "KHTMLPart" );
  3664. d->m_paFind->setEnabled( enableFindAndSelectAll );
  3665. d->m_paSelectAll->setEnabled( enableFindAndSelectAll );
  3666. bool enablePrintFrame = false;
  3667. if ( frame )
  3668. {
  3669. TQObject *ext = KParts::BrowserExtension::childObject( frame );
  3670. if ( ext )
  3671. enablePrintFrame = ext->metaObject()->slotNames().contains( "print()" );
  3672. }
  3673. d->m_paPrintFrame->setEnabled( enablePrintFrame );
  3674. TQString bgURL;
  3675. // ### frames
  3676. if ( d->m_doc && d->m_doc->isHTMLDocument() && static_cast<HTMLDocumentImpl*>(d->m_doc)->body() && !d->m_bClearing )
  3677. bgURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
  3678. d->m_paSaveBackground->setEnabled( !bgURL.isEmpty() );
  3679. if ( d->m_paDebugScript )
  3680. d->m_paDebugScript->setEnabled( d->m_frame ? d->m_frame->m_jscript : 0L );
  3681. }
  3682. KParts::LiveConnectExtension *KHTMLPart::liveConnectExtension( const khtml::RenderPart *frame) const {
  3683. const ConstFrameIt end = d->m_objects.end();
  3684. for(ConstFrameIt it = d->m_objects.begin(); it != end; ++it )
  3685. if ((*it)->m_frame == frame)
  3686. return (*it)->m_liveconnect;
  3687. return 0L;
  3688. }
  3689. bool KHTMLPart::requestFrame( khtml::RenderPart *frame, const TQString &url, const TQString &frameName,
  3690. const TQStringList &params, bool isIFrame )
  3691. {
  3692. //kdDebug( 6050 ) << this << " requestFrame( ..., " << url << ", " << frameName << " )" << endl;
  3693. FrameIt it = d->m_frames.find( frameName );
  3694. if ( it == d->m_frames.end() )
  3695. {
  3696. khtml::ChildFrame * child = new khtml::ChildFrame;
  3697. //kdDebug( 6050 ) << "inserting new frame into frame map " << frameName << endl;
  3698. child->m_name = frameName;
  3699. it = d->m_frames.append( child );
  3700. }
  3701. (*it)->m_type = isIFrame ? khtml::ChildFrame::IFrame : khtml::ChildFrame::Frame;
  3702. (*it)->m_frame = frame;
  3703. (*it)->m_params = params;
  3704. // Support for <frame src="javascript:string">
  3705. if ( url.find( TQString::fromLatin1( "javascript:" ), 0, false ) == 0 )
  3706. {
  3707. if ( processObjectRequest(*it, KURL("about:blank"), TQString("text/html") ) ) {
  3708. KHTMLPart* p = static_cast<KHTMLPart*>(static_cast<KParts::ReadOnlyPart *>((*it)->m_part));
  3709. // See if we want to replace content with javascript: output..
  3710. TQVariant res = p->executeScript( DOM::Node(), KURL::decode_string( url.right( url.length() - 11) ) );
  3711. if ( res.type() == TQVariant::String ) {
  3712. p->begin();
  3713. p->write( res.asString() );
  3714. p->end();
  3715. }
  3716. return true;
  3717. }
  3718. return false;
  3719. }
  3720. KURL u = url.isEmpty() ? KURL() : completeURL( url );
  3721. return requestObject( *it, u );
  3722. }
  3723. TQString KHTMLPart::requestFrameName()
  3724. {
  3725. return TQString::fromLatin1("<!--frame %1-->").arg(d->m_frameNameId++);
  3726. }
  3727. bool KHTMLPart::requestObject( khtml::RenderPart *frame, const TQString &url, const TQString &serviceType,
  3728. const TQStringList &params )
  3729. {
  3730. //kdDebug( 6005 ) << "KHTMLPart::requestObject " << this << " frame=" << frame << endl;
  3731. khtml::ChildFrame *child = new khtml::ChildFrame;
  3732. FrameIt it = d->m_objects.append( child );
  3733. (*it)->m_frame = frame;
  3734. (*it)->m_type = khtml::ChildFrame::Object;
  3735. (*it)->m_params = params;
  3736. KParts::URLArgs args;
  3737. args.serviceType = serviceType;
  3738. if (!requestObject( *it, completeURL( url ), args ) && !(*it)->m_run) {
  3739. (*it)->m_bCompleted = true;
  3740. return false;
  3741. }
  3742. return true;
  3743. }
  3744. bool KHTMLPart::requestObject( khtml::ChildFrame *child, const KURL &url, const KParts::URLArgs &_args )
  3745. {
  3746. if (!checkLinkSecurity(url))
  3747. {
  3748. kdDebug(6005) << this << " KHTMLPart::requestObject checkLinkSecurity refused" << endl;
  3749. return false;
  3750. }
  3751. if ( child->m_bPreloaded )
  3752. {
  3753. kdDebug(6005) << "KHTMLPart::requestObject preload" << endl;
  3754. if ( child->m_frame && child->m_part )
  3755. child->m_frame->setWidget( child->m_part->widget() );
  3756. child->m_bPreloaded = false;
  3757. return true;
  3758. }
  3759. //kdDebug(6005) << "KHTMLPart::requestObject child=" << child << " child->m_part=" << child->m_part << endl;
  3760. KParts::URLArgs args( _args );
  3761. if ( child->m_run )
  3762. child->m_run->abort();
  3763. if ( child->m_part && !args.reload && urlcmp( child->m_part->url().url(), url.url(), true, true ) )
  3764. args.serviceType = child->m_serviceType;
  3765. child->m_args = args;
  3766. child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload);
  3767. child->m_serviceName = TQString();
  3768. if (!d->m_referrer.isEmpty() && !child->m_args.metaData().contains( "referrer" ))
  3769. child->m_args.metaData()["referrer"] = d->m_referrer;
  3770. child->m_args.metaData().insert("PropagateHttpHeader", "true");
  3771. child->m_args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
  3772. child->m_args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
  3773. child->m_args.metaData().insert("main_frame_request",
  3774. parentPart() == 0 ? "TRUE":"FALSE");
  3775. child->m_args.metaData().insert("ssl_was_in_use",
  3776. d->m_ssl_in_use ? "TRUE":"FALSE");
  3777. child->m_args.metaData().insert("ssl_activate_warnings", "TRUE");
  3778. child->m_args.metaData().insert("cross-domain", toplevelURL().url());
  3779. // We want a KHTMLPart if the HTML says <frame src=""> or <frame src="about:blank">
  3780. if ((url.isEmpty() || url.url() == "about:blank") && args.serviceType.isEmpty())
  3781. args.serviceType = TQString::fromLatin1( "text/html" );
  3782. if ( args.serviceType.isEmpty() ) {
  3783. kdDebug(6050) << "Running new KHTMLRun for " << this << " and child=" << child << endl;
  3784. child->m_run = new KHTMLRun( this, child, url, child->m_args, true );
  3785. d->m_bComplete = false; // ensures we stop it in checkCompleted...
  3786. return false;
  3787. } else {
  3788. return processObjectRequest( child, url, args.serviceType );
  3789. }
  3790. }
  3791. bool KHTMLPart::processObjectRequest( khtml::ChildFrame *child, const KURL &_url, const TQString &mimetype )
  3792. {
  3793. //kdDebug( 6050 ) << "KHTMLPart::processObjectRequest trying to create part for " << mimetype << endl;
  3794. // IMPORTANT: create a copy of the url here, because it is just a reference, which was likely to be given
  3795. // by an emitting frame part (emit openURLRequest( blahurl, ... ) . A few lines below we delete the part
  3796. // though -> the reference becomes invalid -> crash is likely
  3797. KURL url( _url );
  3798. // khtmlrun called us this way to indicate a loading error
  3799. if ( d->m_onlyLocalReferences || ( url.isEmpty() && mimetype.isEmpty() ) )
  3800. {
  3801. child->m_bCompleted = true;
  3802. checkCompleted();
  3803. return true;
  3804. }
  3805. if (child->m_bNotify)
  3806. {
  3807. child->m_bNotify = false;
  3808. if ( !child->m_args.lockHistory() )
  3809. emit d->m_extension->openURLNotify();
  3810. }
  3811. if ( child->m_serviceType != mimetype || !child->m_part )
  3812. {
  3813. // Before attempting to load a part, check if the user wants that.
  3814. // Many don't like getting ZIP files embedded.
  3815. // However we don't want to ask for flash and other plugin things..
  3816. if ( child->m_type != khtml::ChildFrame::Object )
  3817. {
  3818. TQString suggestedFilename;
  3819. if ( child->m_run )
  3820. suggestedFilename = child->m_run->suggestedFilename();
  3821. KParts::BrowserRun::AskSaveResult res = KParts::BrowserRun::askEmbedOrSave(
  3822. url, mimetype, suggestedFilename );
  3823. switch( res ) {
  3824. case KParts::BrowserRun::Save:
  3825. KHTMLPopupGUIClient::saveURL( widget(), i18n( "Save As" ), url, child->m_args.metaData(), TQString(), 0, suggestedFilename);
  3826. // fall-through
  3827. case KParts::BrowserRun::Cancel:
  3828. child->m_bCompleted = true;
  3829. checkCompleted();
  3830. return true; // done
  3831. default: // Open
  3832. break;
  3833. }
  3834. }
  3835. TQStringList dummy; // the list of servicetypes handled by the part is now unused.
  3836. 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 );
  3837. if ( !part )
  3838. {
  3839. if ( child->m_frame )
  3840. if (child->m_frame->partLoadingErrorNotify( child, url, mimetype ))
  3841. return true; // we succeeded after all (a fallback was used)
  3842. checkEmitLoadEvent();
  3843. return false;
  3844. }
  3845. //CRITICAL STUFF
  3846. if ( child->m_part )
  3847. {
  3848. if (!::tqqt_cast<KHTMLPart*>(child->m_part) && child->m_jscript)
  3849. child->m_jscript->clear();
  3850. partManager()->removePart( (KParts::ReadOnlyPart *)child->m_part );
  3851. delete (KParts::ReadOnlyPart *)child->m_part;
  3852. if (child->m_liveconnect) {
  3853. 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 &)));
  3854. child->m_liveconnect = 0L;
  3855. }
  3856. }
  3857. child->m_serviceType = mimetype;
  3858. if ( child->m_frame && part->widget() )
  3859. child->m_frame->setWidget( part->widget() );
  3860. if ( child->m_type != khtml::ChildFrame::Object )
  3861. partManager()->addPart( part, false );
  3862. // else
  3863. // kdDebug(6005) << "AH! NO FRAME!!!!!" << endl;
  3864. child->m_part = part;
  3865. if (::tqqt_cast<KHTMLPart*>(part)) {
  3866. static_cast<KHTMLPart*>(part)->d->m_frame = child;
  3867. } else if (child->m_frame) {
  3868. child->m_liveconnect = KParts::LiveConnectExtension::childObject(part);
  3869. if (child->m_liveconnect)
  3870. 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 &)));
  3871. }
  3872. KParts::StatusBarExtension *sb = KParts::StatusBarExtension::childObject(part);
  3873. if (sb)
  3874. sb->setStatusBar( d->m_statusBarExtension->statusBar() );
  3875. connect( part, TQT_SIGNAL( started( KIO::Job *) ),
  3876. this, TQT_SLOT( slotChildStarted( KIO::Job *) ) );
  3877. connect( part, TQT_SIGNAL( completed() ),
  3878. this, TQT_SLOT( slotChildCompleted() ) );
  3879. connect( part, TQT_SIGNAL( completed(bool) ),
  3880. this, TQT_SLOT( slotChildCompleted(bool) ) );
  3881. connect( part, TQT_SIGNAL( setStatusBarText( const TQString & ) ),
  3882. this, TQT_SIGNAL( setStatusBarText( const TQString & ) ) );
  3883. if ( part->inherits( "KHTMLPart" ) )
  3884. {
  3885. connect( this, TQT_SIGNAL( completed() ),
  3886. part, TQT_SLOT( slotParentCompleted() ) );
  3887. connect( this, TQT_SIGNAL( completed(bool) ),
  3888. part, TQT_SLOT( slotParentCompleted() ) );
  3889. // As soon as the child's document is created, we need to set its domain
  3890. // (but we do so only once, so it can't be simply done in the child)
  3891. connect( part, TQT_SIGNAL( docCreated() ),
  3892. this, TQT_SLOT( slotChildDocCreated() ) );
  3893. }
  3894. child->m_extension = KParts::BrowserExtension::childObject( part );
  3895. if ( child->m_extension )
  3896. {
  3897. connect( child->m_extension, TQT_SIGNAL( openURLNotify() ),
  3898. d->m_extension, TQT_SIGNAL( openURLNotify() ) );
  3899. connect( child->m_extension, TQT_SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ),
  3900. this, TQT_SLOT( slotChildURLRequest( const KURL &, const KParts::URLArgs & ) ) );
  3901. connect( child->m_extension, TQT_SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ),
  3902. d->m_extension, TQT_SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ) );
  3903. connect( child->m_extension, TQT_SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs &, const KParts::WindowArgs &, KParts::ReadOnlyPart *& ) ),
  3904. d->m_extension, TQT_SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & , const KParts::WindowArgs &, KParts::ReadOnlyPart *&) ) );
  3905. connect( child->m_extension, TQT_SIGNAL( popupMenu( const TQPoint &, const KFileItemList & ) ),
  3906. d->m_extension, TQT_SIGNAL( popupMenu( const TQPoint &, const KFileItemList & ) ) );
  3907. connect( child->m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KFileItemList & ) ),
  3908. d->m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KFileItemList & ) ) );
  3909. connect( child->m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ),
  3910. d->m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ) );
  3911. connect( child->m_extension, TQT_SIGNAL( popupMenu( const TQPoint &, const KURL &, const TQString &, mode_t ) ),
  3912. d->m_extension, TQT_SIGNAL( popupMenu( const TQPoint &, const KURL &, const TQString &, mode_t ) ) );
  3913. connect( child->m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &, const TQString &, mode_t ) ),
  3914. d->m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &, const TQString &, mode_t ) ) );
  3915. connect( child->m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ),
  3916. d->m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ) );
  3917. connect( child->m_extension, TQT_SIGNAL( infoMessage( const TQString & ) ),
  3918. d->m_extension, TQT_SIGNAL( infoMessage( const TQString & ) ) );
  3919. connect( child->m_extension, TQT_SIGNAL( requestFocus( KParts::ReadOnlyPart * ) ),
  3920. this, TQT_SLOT( slotRequestFocus( KParts::ReadOnlyPart * ) ) );
  3921. child->m_extension->setBrowserInterface( d->m_extension->browserInterface() );
  3922. }
  3923. }
  3924. else if ( child->m_frame && child->m_part &&
  3925. child->m_frame->widget() != child->m_part->widget() )
  3926. child->m_frame->setWidget( child->m_part->widget() );
  3927. checkEmitLoadEvent();
  3928. // Some JS code in the load event may have destroyed the part
  3929. // In that case, abort
  3930. if ( !child->m_part )
  3931. return false;
  3932. if ( child->m_bPreloaded )
  3933. {
  3934. if ( child->m_frame && child->m_part )
  3935. child->m_frame->setWidget( child->m_part->widget() );
  3936. child->m_bPreloaded = false;
  3937. return true;
  3938. }
  3939. child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload);
  3940. // make sure the part has a way to find out about the mimetype.
  3941. // we actually set it in child->m_args in requestObject already,
  3942. // but it's useless if we had to use a KHTMLRun instance, as the
  3943. // point the run object is to find out exactly the mimetype.
  3944. child->m_args.serviceType = mimetype;
  3945. // if not a frame set child as completed
  3946. child->m_bCompleted = child->m_type == khtml::ChildFrame::Object;
  3947. if ( child->m_extension )
  3948. child->m_extension->setURLArgs( child->m_args );
  3949. if(url.protocol() == "javascript" || url.url() == "about:blank") {
  3950. if (!child->m_part->inherits("KHTMLPart"))
  3951. return false;
  3952. KHTMLPart* p = static_cast<KHTMLPart*>(static_cast<KParts::ReadOnlyPart *>(child->m_part));
  3953. p->begin();
  3954. if (d->m_doc && p->d->m_doc)
  3955. p->d->m_doc->setBaseURL(d->m_doc->baseURL());
  3956. if (!url.url().startsWith("about:")) {
  3957. p->write(url.path());
  3958. } else {
  3959. p->m_url = url;
  3960. // we need a body element. testcase: <iframe id="a"></iframe><script>alert(a.document.body);</script>
  3961. p->write("<HTML><TITLE></TITLE><BODY></BODY></HTML>");
  3962. }
  3963. p->end();
  3964. return true;
  3965. }
  3966. else if ( !url.isEmpty() )
  3967. {
  3968. //kdDebug( 6050 ) << "opening " << url.url() << " in frame " << child->m_part << endl;
  3969. bool b = child->m_part->openURL( url );
  3970. if (child->m_bCompleted)
  3971. checkCompleted();
  3972. return b;
  3973. }
  3974. else
  3975. {
  3976. child->m_bCompleted = true;
  3977. checkCompleted();
  3978. return true;
  3979. }
  3980. }
  3981. KParts::ReadOnlyPart *KHTMLPart::createPart( TQWidget *parentWidget, const char *widgetName,
  3982. TQObject *parent, const char *name, const TQString &mimetype,
  3983. TQString &serviceName, TQStringList &serviceTypes,
  3984. const TQStringList &params )
  3985. {
  3986. TQString constr;
  3987. if ( !serviceName.isEmpty() )
  3988. constr.append( TQString::fromLatin1( "Name == '%1'" ).arg( serviceName ) );
  3989. KTrader::OfferList offers = KTrader::self()->query( mimetype, "KParts/ReadOnlyPart", constr, TQString() );
  3990. if ( offers.isEmpty() ) {
  3991. int pos = mimetype.find( "-plugin" );
  3992. if (pos < 0)
  3993. return 0L;
  3994. TQString stripped_mime = mimetype.left( pos );
  3995. offers = KTrader::self()->query( stripped_mime, "KParts/ReadOnlyPart", constr, TQString() );
  3996. if ( offers.isEmpty() )
  3997. return 0L;
  3998. }
  3999. KTrader::OfferList::ConstIterator it = offers.begin();
  4000. const KTrader::OfferList::ConstIterator itEnd = offers.end();
  4001. for ( ; it != itEnd; ++it )
  4002. {
  4003. KService::Ptr service = (*it);
  4004. KLibFactory* const factory = KLibLoader::self()->factory( TQFile::encodeName(service->library()) );
  4005. if ( factory ) {
  4006. KParts::ReadOnlyPart *res = 0L;
  4007. const char *className = "KParts::ReadOnlyPart";
  4008. if ( service->serviceTypes().contains( "Browser/View" ) )
  4009. className = "Browser/View";
  4010. if ( factory->inherits( "KParts::Factory" ) )
  4011. res = static_cast<KParts::ReadOnlyPart *>(static_cast<KParts::Factory *>( factory )->createPart( parentWidget, widgetName, parent, name, className, params ));
  4012. else
  4013. res = static_cast<KParts::ReadOnlyPart *>(factory->create( TQT_TQOBJECT(parentWidget), widgetName, className ));
  4014. if ( res ) {
  4015. serviceTypes = service->serviceTypes();
  4016. serviceName = service->name();
  4017. return res;
  4018. }
  4019. } else {
  4020. // TODO KMessageBox::error and i18n, like in KonqFactory::createView?
  4021. kdWarning() << TQString(TQString("There was an error loading the module %1.\nThe diagnostics is:\n%2")
  4022. .arg(service->name()).arg(KLibLoader::self()->lastErrorMessage())) << endl;
  4023. }
  4024. }
  4025. return 0;
  4026. }
  4027. KParts::PartManager *KHTMLPart::partManager()
  4028. {
  4029. if ( !d->m_manager && d->m_view )
  4030. {
  4031. d->m_manager = new KParts::PartManager( d->m_view->topLevelWidget(), this, "khtml part manager" );
  4032. d->m_manager->setAllowNestedParts( true );
  4033. connect( d->m_manager, TQT_SIGNAL( activePartChanged( KParts::Part * ) ),
  4034. this, TQT_SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
  4035. connect( d->m_manager, TQT_SIGNAL( partRemoved( KParts::Part * ) ),
  4036. this, TQT_SLOT( slotPartRemoved( KParts::Part * ) ) );
  4037. }
  4038. return d->m_manager;
  4039. }
  4040. void KHTMLPart::submitFormAgain()
  4041. {
  4042. disconnect(this, TQT_SIGNAL(completed()), this, TQT_SLOT(submitFormAgain()));
  4043. if( d->m_doc && !d->m_doc->parsing() && d->m_submitForm)
  4044. 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 );
  4045. delete d->m_submitForm;
  4046. d->m_submitForm = 0;
  4047. }
  4048. void KHTMLPart::submitFormProxy( const char *action, const TQString &url, const TQByteArray &formData, const TQString &_target, const TQString& contentType, const TQString& boundary )
  4049. {
  4050. submitForm(action, url, formData, _target, contentType, boundary);
  4051. }
  4052. void KHTMLPart::submitForm( const char *action, const TQString &url, const TQByteArray &formData, const TQString &_target, const TQString& contentType, const TQString& boundary )
  4053. {
  4054. kdDebug(6000) << this << ": KHTMLPart::submitForm target=" << _target << " url=" << url << endl;
  4055. if (d->m_formNotification == KHTMLPart::Only) {
  4056. emit formSubmitNotification(action, url, formData, _target, contentType, boundary);
  4057. return;
  4058. } else if (d->m_formNotification == KHTMLPart::Before) {
  4059. emit formSubmitNotification(action, url, formData, _target, contentType, boundary);
  4060. }
  4061. KURL u = completeURL( url );
  4062. if ( !u.isValid() )
  4063. {
  4064. // ### ERROR HANDLING!
  4065. return;
  4066. }
  4067. // Form security checks
  4068. //
  4069. /*
  4070. * If these form security checks are still in this place in a month or two
  4071. * I'm going to simply delete them.
  4072. */
  4073. /* This is separate for a reason. It has to be _before_ all script, etc,
  4074. * AND I don't want to break anything that uses checkLinkSecurity() in
  4075. * other places.
  4076. */
  4077. if (!d->m_submitForm) {
  4078. if (u.protocol() != "https" && u.protocol() != "mailto") {
  4079. if (d->m_ssl_in_use) { // Going from SSL -> nonSSL
  4080. int rc = KMessageBox::warningContinueCancel(NULL, i18n("Warning: This is a secure form but it is attempting to send your data back unencrypted."
  4081. "\nA third party may be able to intercept and view this information."
  4082. "\nAre you sure you wish to continue?"),
  4083. i18n("Network Transmission"),KGuiItem(i18n("&Send Unencrypted")));
  4084. if (rc == KMessageBox::Cancel)
  4085. return;
  4086. } else { // Going from nonSSL -> nonSSL
  4087. KSSLSettings kss(true);
  4088. if (kss.warnOnUnencrypted()) {
  4089. int rc = KMessageBox::warningContinueCancel(NULL,
  4090. i18n("Warning: Your data is about to be transmitted across the network unencrypted."
  4091. "\nAre you sure you wish to continue?"),
  4092. i18n("Network Transmission"),
  4093. KGuiItem(i18n("&Send Unencrypted")),
  4094. "WarnOnUnencryptedForm");
  4095. // Move this setting into KSSL instead
  4096. KConfig *config = kapp->config();
  4097. TQString grpNotifMsgs = TQString::fromLatin1("Notification Messages");
  4098. KConfigGroupSaver saver( config, grpNotifMsgs );
  4099. if (!config->readBoolEntry("WarnOnUnencryptedForm", true)) {
  4100. config->deleteEntry("WarnOnUnencryptedForm");
  4101. config->sync();
  4102. kss.setWarnOnUnencrypted(false);
  4103. kss.save();
  4104. }
  4105. if (rc == KMessageBox::Cancel)
  4106. return;
  4107. }
  4108. }
  4109. }
  4110. if (u.protocol() == "mailto") {
  4111. int rc = KMessageBox::warningContinueCancel(NULL,
  4112. i18n("This site is attempting to submit form data via email.\n"
  4113. "Do you want to continue?"),
  4114. i18n("Network Transmission"),
  4115. KGuiItem(i18n("&Send Email")),
  4116. "WarnTriedEmailSubmit");
  4117. if (rc == KMessageBox::Cancel) {
  4118. return;
  4119. }
  4120. }
  4121. }
  4122. // End form security checks
  4123. //
  4124. TQString urlstring = u.url();
  4125. if ( urlstring.find( TQString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
  4126. urlstring = KURL::decode_string(urlstring);
  4127. crossFrameExecuteScript( _target, urlstring.right( urlstring.length() - 11) );
  4128. return;
  4129. }
  4130. if (!checkLinkSecurity(u,
  4131. 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?" ),
  4132. i18n( "Submit" )))
  4133. return;
  4134. KParts::URLArgs args;
  4135. if (!d->m_referrer.isEmpty())
  4136. args.metaData()["referrer"] = d->m_referrer;
  4137. args.metaData().insert("PropagateHttpHeader", "true");
  4138. args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
  4139. args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
  4140. args.metaData().insert("main_frame_request",
  4141. parentPart() == 0 ? "TRUE":"FALSE");
  4142. args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
  4143. args.metaData().insert("ssl_activate_warnings", "TRUE");
  4144. //WABA: When we post a form we should treat it as the main url
  4145. //the request should never be considered cross-domain
  4146. //args.metaData().insert("cross-domain", toplevelURL().url());
  4147. args.frameName = _target.isEmpty() ? d->m_doc->baseTarget() : _target ;
  4148. // Handle mailto: forms
  4149. if (u.protocol() == "mailto") {
  4150. // 1) Check for attach= and strip it
  4151. TQString q = u.query().mid(1);
  4152. TQStringList nvps = TQStringList::split("&", q);
  4153. bool triedToAttach = false;
  4154. TQStringList::Iterator nvp = nvps.begin();
  4155. const TQStringList::Iterator nvpEnd = nvps.end();
  4156. // cannot be a for loop as if something is removed we don't want to do ++nvp, as
  4157. // remove returns an iterator pointing to the next item
  4158. while (nvp != nvpEnd) {
  4159. const TQStringList pair = TQStringList::split("=", *nvp);
  4160. if (pair.count() >= 2) {
  4161. if (pair.first().lower() == "attach") {
  4162. nvp = nvps.remove(nvp);
  4163. triedToAttach = true;
  4164. } else {
  4165. ++nvp;
  4166. }
  4167. } else {
  4168. ++nvp;
  4169. }
  4170. }
  4171. if (triedToAttach)
  4172. 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("TDE"), "WarnTriedAttach");
  4173. // 2) Append body=
  4174. TQString bodyEnc;
  4175. if (contentType.lower() == "multipart/form-data") {
  4176. // FIXME: is this correct? I suspect not
  4177. bodyEnc = KURL::encode_string(TQString::fromLatin1(formData.data(),
  4178. formData.size()));
  4179. } else if (contentType.lower() == "text/plain") {
  4180. // Convention seems to be to decode, and s/&/\n/
  4181. TQString tmpbody = TQString::fromLatin1(formData.data(),
  4182. formData.size());
  4183. tmpbody.replace(TQRegExp("[&]"), "\n");
  4184. tmpbody.replace(TQRegExp("[+]"), " ");
  4185. tmpbody = KURL::decode_string(tmpbody); // Decode the rest of it
  4186. bodyEnc = KURL::encode_string(tmpbody); // Recode for the URL
  4187. } else {
  4188. bodyEnc = KURL::encode_string(TQString::fromLatin1(formData.data(),
  4189. formData.size()));
  4190. }
  4191. nvps.append(TQString("body=%1").arg(bodyEnc));
  4192. q = nvps.join("&");
  4193. u.setQuery(q);
  4194. }
  4195. if ( strcmp( action, "get" ) == 0 ) {
  4196. if (u.protocol() != "mailto")
  4197. u.setQuery( TQString::fromLatin1( formData.data(), formData.size() ) );
  4198. args.setDoPost( false );
  4199. }
  4200. else {
  4201. args.postData = formData;
  4202. args.setDoPost( true );
  4203. // construct some user headers if necessary
  4204. if (contentType.isNull() || contentType == "application/x-www-form-urlencoded")
  4205. args.setContentType( "Content-Type: application/x-www-form-urlencoded" );
  4206. else // contentType must be "multipart/form-data"
  4207. args.setContentType( "Content-Type: " + contentType + "; boundary=" + boundary );
  4208. }
  4209. if ( d->m_doc->parsing() || d->m_runningScripts > 0 ) {
  4210. if( d->m_submitForm ) {
  4211. kdDebug(6000) << "KHTMLPart::submitForm ABORTING!" << endl;
  4212. return;
  4213. }
  4214. d->m_submitForm = new KHTMLPartPrivate::SubmitForm;
  4215. d->m_submitForm->submitAction = action;
  4216. d->m_submitForm->submitUrl = url;
  4217. d->m_submitForm->submitFormData = formData;
  4218. d->m_submitForm->target = _target;
  4219. d->m_submitForm->submitContentType = contentType;
  4220. d->m_submitForm->submitBoundary = boundary;
  4221. connect(this, TQT_SIGNAL(completed()), this, TQT_SLOT(submitFormAgain()));
  4222. }
  4223. else
  4224. {
  4225. emit d->m_extension->openURLRequest( u, args );
  4226. }
  4227. }
  4228. void KHTMLPart::popupMenu( const TQString &linkUrl )
  4229. {
  4230. KURL popupURL;
  4231. KURL linkKURL;
  4232. KParts::URLArgs args;
  4233. TQString referrer;
  4234. KParts::BrowserExtension::PopupFlags itemflags=KParts::BrowserExtension::ShowBookmark | KParts::BrowserExtension::ShowReload;
  4235. if ( linkUrl.isEmpty() ) { // click on background
  4236. KHTMLPart* khtmlPart = this;
  4237. while ( khtmlPart->parentPart() )
  4238. {
  4239. khtmlPart=khtmlPart->parentPart();
  4240. }
  4241. popupURL = khtmlPart->url();
  4242. referrer = khtmlPart->pageReferrer();
  4243. if (hasSelection())
  4244. itemflags = KParts::BrowserExtension::ShowTextSelectionItems;
  4245. else
  4246. itemflags |= KParts::BrowserExtension::ShowNavigationItems;
  4247. } else { // click on link
  4248. popupURL = completeURL( linkUrl );
  4249. linkKURL = popupURL;
  4250. referrer = this->referrer();
  4251. if (!(d->m_strSelectedURLTarget).isEmpty() &&
  4252. (d->m_strSelectedURLTarget.lower() != "_top") &&
  4253. (d->m_strSelectedURLTarget.lower() != "_self") &&
  4254. (d->m_strSelectedURLTarget.lower() != "_parent")) {
  4255. if (d->m_strSelectedURLTarget.lower() == "_blank")
  4256. args.setForcesNewWindow(true);
  4257. else {
  4258. KHTMLPart *p = this;
  4259. while (p->parentPart())
  4260. p = p->parentPart();
  4261. if (!p->frameExists(d->m_strSelectedURLTarget))
  4262. args.setForcesNewWindow(true);
  4263. }
  4264. }
  4265. }
  4266. // Danger, Will Robinson. The Popup might stay around for a much
  4267. // longer time than KHTMLPart. Deal with it.
  4268. KHTMLPopupGUIClient* client = new KHTMLPopupGUIClient( this, d->m_popupMenuXML, linkKURL );
  4269. TQGuardedPtr<TQObject> guard( client );
  4270. TQString mimetype = TQString::fromLatin1( "text/html" );
  4271. args.metaData()["referrer"] = referrer;
  4272. if (!linkUrl.isEmpty()) // over a link
  4273. {
  4274. if (popupURL.isLocalFile()) // safe to do this
  4275. {
  4276. mimetype = KMimeType::findByURL(popupURL,0,true,false)->name();
  4277. }
  4278. else // look at "extension" of link
  4279. {
  4280. const TQString fname(popupURL.fileName(false));
  4281. if (!fname.isEmpty() && !popupURL.hasRef() && popupURL.query().isEmpty())
  4282. {
  4283. KMimeType::Ptr pmt = KMimeType::findByPath(fname,0,true);
  4284. // Further check for mime types guessed from the extension which,
  4285. // on a web page, are more likely to be a script delivering content
  4286. // of undecidable type. If the mime type from the extension is one
  4287. // of these, don't use it. Retain the original type 'text/html'.
  4288. if (pmt->name() != KMimeType::defaultMimeType() &&
  4289. !pmt->is("application/x-perl") &&
  4290. !pmt->is("application/x-perl-module") &&
  4291. !pmt->is("application/x-php") &&
  4292. !pmt->is("application/x-python-bytecode") &&
  4293. !pmt->is("application/x-python") &&
  4294. !pmt->is("application/x-shellscript"))
  4295. mimetype = pmt->name();
  4296. }
  4297. }
  4298. }
  4299. args.serviceType = mimetype;
  4300. emit d->m_extension->popupMenu( client, TQCursor::pos(), popupURL, args, itemflags, S_IFREG /*always a file*/);
  4301. if ( !guard.isNull() ) {
  4302. delete client;
  4303. emit popupMenu(linkUrl, TQCursor::pos());
  4304. d->m_strSelectedURL = d->m_strSelectedURLTarget = TQString();
  4305. }
  4306. }
  4307. void KHTMLPart::slotParentCompleted()
  4308. {
  4309. //kdDebug(6050) << this << " slotParentCompleted()" << endl;
  4310. if ( !d->m_redirectURL.isEmpty() && !d->m_redirectionTimer.isActive() )
  4311. {
  4312. //kdDebug(6050) << this << ": starting timer for child redirection -> " << d->m_redirectURL << endl;
  4313. d->m_redirectionTimer.start( 1000 * d->m_delayRedirect, true );
  4314. }
  4315. }
  4316. void KHTMLPart::slotChildStarted( KIO::Job *job )
  4317. {
  4318. khtml::ChildFrame *child = frame( TQT_TQOBJECT_CONST(sender()) );
  4319. assert( child );
  4320. child->m_bCompleted = false;
  4321. if ( d->m_bComplete )
  4322. {
  4323. #if 0
  4324. // WABA: Looks like this belongs somewhere else
  4325. if ( !parentPart() ) // "toplevel" html document? if yes, then notify the hosting browser about the document (url) changes
  4326. {
  4327. emit d->m_extension->openURLNotify();
  4328. }
  4329. #endif
  4330. d->m_bComplete = false;
  4331. emit started( job );
  4332. }
  4333. }
  4334. void KHTMLPart::slotChildCompleted()
  4335. {
  4336. slotChildCompleted( false );
  4337. }
  4338. void KHTMLPart::slotChildCompleted( bool pendingAction )
  4339. {
  4340. khtml::ChildFrame *child = frame( TQT_TQOBJECT_CONST(sender()) );
  4341. if ( child ) {
  4342. kdDebug(6050) << this << " slotChildCompleted child=" << child << " m_frame=" << child->m_frame << endl;
  4343. child->m_bCompleted = true;
  4344. child->m_bPendingRedirection = pendingAction;
  4345. child->m_args = KParts::URLArgs();
  4346. }
  4347. checkCompleted();
  4348. }
  4349. void KHTMLPart::slotChildDocCreated()
  4350. {
  4351. const KHTMLPart* htmlFrame = static_cast<const KHTMLPart *>(sender());
  4352. // Set domain to the frameset's domain
  4353. // This must only be done when loading the frameset initially (#22039),
  4354. // not when following a link in a frame (#44162).
  4355. if ( d->m_doc && d->m_doc->isHTMLDocument() )
  4356. {
  4357. if ( sender()->inherits("KHTMLPart") )
  4358. {
  4359. DOMString domain = static_cast<HTMLDocumentImpl*>(d->m_doc)->domain();
  4360. if (htmlFrame->d->m_doc && htmlFrame->d->m_doc->isHTMLDocument() )
  4361. //kdDebug(6050) << "KHTMLPart::slotChildDocCreated: url: " << htmlFrame->m_url.url() << endl;
  4362. static_cast<HTMLDocumentImpl*>(htmlFrame->d->m_doc)->setDomain( domain );
  4363. }
  4364. }
  4365. // So it only happens once
  4366. disconnect( htmlFrame, TQT_SIGNAL( docCreated() ), this, TQT_SLOT( slotChildDocCreated() ) );
  4367. }
  4368. void KHTMLPart::slotChildURLRequest( const KURL &url, const KParts::URLArgs &args )
  4369. {
  4370. khtml::ChildFrame *child = frame( TQT_TQOBJECT_CONST(sender())->parent() );
  4371. KHTMLPart *callingHtmlPart = const_cast<KHTMLPart *>(dynamic_cast<const KHTMLPart *>(sender()->parent()));
  4372. // TODO: handle child target correctly! currently the script are always executed fur the parent
  4373. TQString urlStr = url.url();
  4374. if ( urlStr.find( TQString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
  4375. TQString script = KURL::decode_string( urlStr.right( urlStr.length() - 11 ) );
  4376. executeScript( DOM::Node(), script );
  4377. return;
  4378. }
  4379. TQString frameName = args.frameName.lower();
  4380. if ( !frameName.isEmpty() ) {
  4381. if ( frameName == TQString::fromLatin1( "_top" ) )
  4382. {
  4383. emit d->m_extension->openURLRequest( url, args );
  4384. return;
  4385. }
  4386. else if ( frameName == TQString::fromLatin1( "_blank" ) )
  4387. {
  4388. emit d->m_extension->createNewWindow( url, args );
  4389. return;
  4390. }
  4391. else if ( frameName == TQString::fromLatin1( "_parent" ) )
  4392. {
  4393. KParts::URLArgs newArgs( args );
  4394. newArgs.frameName = TQString();
  4395. emit d->m_extension->openURLRequest( url, newArgs );
  4396. return;
  4397. }
  4398. else if ( frameName != TQString::fromLatin1( "_self" ) )
  4399. {
  4400. khtml::ChildFrame *_frame = recursiveFrameRequest( callingHtmlPart, url, args );
  4401. if ( !_frame )
  4402. {
  4403. emit d->m_extension->openURLRequest( url, args );
  4404. return;
  4405. }
  4406. child = _frame;
  4407. }
  4408. }
  4409. if ( child && child->m_type != khtml::ChildFrame::Object ) {
  4410. // Inform someone that we are about to show something else.
  4411. child->m_bNotify = true;
  4412. requestObject( child, url, args );
  4413. } else if ( frameName== "_self" ) // this is for embedded objects (via <object>) which want to replace the current document
  4414. {
  4415. KParts::URLArgs newArgs( args );
  4416. newArgs.frameName = TQString();
  4417. emit d->m_extension->openURLRequest( url, newArgs );
  4418. }
  4419. }
  4420. void KHTMLPart::slotRequestFocus( KParts::ReadOnlyPart * )
  4421. {
  4422. emit d->m_extension->requestFocus(this);
  4423. }
  4424. khtml::ChildFrame *KHTMLPart::frame( const TQObject *obj )
  4425. {
  4426. assert( obj->inherits( "KParts::ReadOnlyPart" ) );
  4427. const KParts::ReadOnlyPart* const part = static_cast<const KParts::ReadOnlyPart *>( obj );
  4428. FrameIt it = d->m_frames.begin();
  4429. const FrameIt end = d->m_frames.end();
  4430. for (; it != end; ++it )
  4431. if ( (KParts::ReadOnlyPart *)(*it)->m_part == part )
  4432. return *it;
  4433. FrameIt oi = d->m_objects.begin();
  4434. const FrameIt oiEnd = d->m_objects.end();
  4435. for (; oi != oiEnd; ++oi )
  4436. if ( (KParts::ReadOnlyPart *)(*oi)->m_part == part )
  4437. return *oi;
  4438. return 0L;
  4439. }
  4440. //#define DEBUG_FINDFRAME
  4441. bool KHTMLPart::checkFrameAccess(KHTMLPart *callingHtmlPart)
  4442. {
  4443. if (callingHtmlPart == this)
  4444. return true; // trivial
  4445. if (htmlDocument().isNull()) {
  4446. #ifdef DEBUG_FINDFRAME
  4447. kdDebug(6050) << "KHTMLPart::checkFrameAccess: Empty part " << this << " URL = " << m_url << endl;
  4448. #endif
  4449. return false; // we are empty?
  4450. }
  4451. // now compare the domains
  4452. if (callingHtmlPart && !callingHtmlPart->htmlDocument().isNull() &&
  4453. !htmlDocument().isNull()) {
  4454. DOM::DOMString actDomain = callingHtmlPart->htmlDocument().domain();
  4455. DOM::DOMString destDomain = htmlDocument().domain();
  4456. #ifdef DEBUG_FINDFRAME
  4457. kdDebug(6050) << "KHTMLPart::checkFrameAccess: actDomain = '" << actDomain.string() << "' destDomain = '" << destDomain.string() << "'" << endl;
  4458. #endif
  4459. if (actDomain == destDomain)
  4460. return true;
  4461. }
  4462. #ifdef DEBUG_FINDFRAME
  4463. else
  4464. {
  4465. kdDebug(6050) << "KHTMLPart::checkFrameAccess: Unknown part/domain " << callingHtmlPart << " tries to access part " << this << endl;
  4466. }
  4467. #endif
  4468. return false;
  4469. }
  4470. KHTMLPart *
  4471. KHTMLPart::findFrameParent( KParts::ReadOnlyPart *callingPart, const TQString &f, khtml::ChildFrame **childFrame )
  4472. {
  4473. #ifdef DEBUG_FINDFRAME
  4474. kdDebug(6050) << "KHTMLPart::findFrameParent: this = " << this << " URL = " << m_url << " name = " << name() << " findFrameParent( " << f << " )" << endl;
  4475. #endif
  4476. // Check access
  4477. KHTMLPart* const callingHtmlPart = dynamic_cast<KHTMLPart *>(callingPart);
  4478. if (!checkFrameAccess(callingHtmlPart))
  4479. return 0;
  4480. // match encoding used in KonqView::setViewName()
  4481. if (!childFrame && !parentPart() && (TQString::fromLocal8Bit(name()) == f))
  4482. return this;
  4483. FrameIt it = d->m_frames.find( f );
  4484. const FrameIt end = d->m_frames.end();
  4485. if ( it != end )
  4486. {
  4487. #ifdef DEBUG_FINDFRAME
  4488. kdDebug(6050) << "KHTMLPart::findFrameParent: FOUND!" << endl;
  4489. #endif
  4490. if (childFrame)
  4491. *childFrame = *it;
  4492. return this;
  4493. }
  4494. it = d->m_frames.begin();
  4495. for (; it != end; ++it )
  4496. {
  4497. KParts::ReadOnlyPart* const p = (*it)->m_part;
  4498. if ( p && p->inherits( "KHTMLPart" ))
  4499. {
  4500. KHTMLPart* const frameParent = static_cast<KHTMLPart*>(p)->findFrameParent(callingPart, f, childFrame);
  4501. if (frameParent)
  4502. return frameParent;
  4503. }
  4504. }
  4505. return 0;
  4506. }
  4507. KHTMLPart *KHTMLPart::findFrame( const TQString &f )
  4508. {
  4509. khtml::ChildFrame *childFrame;
  4510. KHTMLPart *parentFrame = findFrameParent(this, f, &childFrame);
  4511. if (parentFrame)
  4512. {
  4513. KParts::ReadOnlyPart *p = childFrame->m_part;
  4514. if ( p && p->inherits( "KHTMLPart" ))
  4515. return static_cast<KHTMLPart *>(p);
  4516. }
  4517. return 0;
  4518. }
  4519. KParts::ReadOnlyPart *KHTMLPart::findFramePart(const TQString &f)
  4520. {
  4521. khtml::ChildFrame *childFrame;
  4522. return findFrameParent(this, f, &childFrame) ? static_cast<KParts::ReadOnlyPart *>(childFrame->m_part) : 0L;
  4523. }
  4524. KParts::ReadOnlyPart *KHTMLPart::currentFrame() const
  4525. {
  4526. KParts::ReadOnlyPart* part = (KParts::ReadOnlyPart*)(this);
  4527. // Find active part in our frame manager, in case we are a frameset
  4528. // and keep doing that (in case of nested framesets).
  4529. // Just realized we could also do this recursively, calling part->currentFrame()...
  4530. while ( part && part->inherits("KHTMLPart") &&
  4531. static_cast<KHTMLPart *>(part)->d->m_frames.count() > 0 ) {
  4532. KHTMLPart* frameset = static_cast<KHTMLPart *>(part);
  4533. part = static_cast<KParts::ReadOnlyPart *>(frameset->partManager()->activePart());
  4534. if ( !part ) return frameset;
  4535. }
  4536. return part;
  4537. }
  4538. bool KHTMLPart::frameExists( const TQString &frameName )
  4539. {
  4540. ConstFrameIt it = d->m_frames.find( frameName );
  4541. if ( it == d->m_frames.end() )
  4542. return false;
  4543. // WABA: We only return true if the child actually has a frame
  4544. // set. Otherwise we might find our preloaded-selve.
  4545. // This happens when we restore the frameset.
  4546. return (!(*it)->m_frame.isNull());
  4547. }
  4548. KJSProxy *KHTMLPart::framejScript(KParts::ReadOnlyPart *framePart)
  4549. {
  4550. KHTMLPart* const kp = ::tqqt_cast<KHTMLPart*>(framePart);
  4551. if (kp)
  4552. return kp->jScript();
  4553. FrameIt it = d->m_frames.begin();
  4554. const FrameIt itEnd = d->m_frames.end();
  4555. for (; it != itEnd; ++it)
  4556. if (framePart == (*it)->m_part) {
  4557. if (!(*it)->m_jscript)
  4558. createJScript(*it);
  4559. return (*it)->m_jscript;
  4560. }
  4561. return 0L;
  4562. }
  4563. KHTMLPart *KHTMLPart::parentPart()
  4564. {
  4565. return ::tqqt_cast<KHTMLPart *>( parent() );
  4566. }
  4567. khtml::ChildFrame *KHTMLPart::recursiveFrameRequest( KHTMLPart *callingHtmlPart, const KURL &url,
  4568. const KParts::URLArgs &args, bool callParent )
  4569. {
  4570. #ifdef DEBUG_FINDFRAME
  4571. kdDebug( 6050 ) << "KHTMLPart::recursiveFrameRequest this = " << this << ", frame = " << args.frameName << ", url = " << url << endl;
  4572. #endif
  4573. khtml::ChildFrame *childFrame;
  4574. KHTMLPart *childPart = findFrameParent(callingHtmlPart, args.frameName, &childFrame);
  4575. if (childPart)
  4576. {
  4577. if (childPart == this)
  4578. return childFrame;
  4579. childPart->requestObject( childFrame, url, args );
  4580. return 0;
  4581. }
  4582. if ( parentPart() && callParent )
  4583. {
  4584. khtml::ChildFrame *res = parentPart()->recursiveFrameRequest( callingHtmlPart, url, args, callParent );
  4585. if ( res )
  4586. parentPart()->requestObject( res, url, args );
  4587. }
  4588. return 0L;
  4589. }
  4590. #ifndef NDEBUG
  4591. static int s_saveStateIndentLevel = 0;
  4592. #endif
  4593. void KHTMLPart::saveState( TQDataStream &stream )
  4594. {
  4595. #ifndef NDEBUG
  4596. TQString indent = TQString().leftJustify( s_saveStateIndentLevel * 4, ' ' );
  4597. const int indentLevel = s_saveStateIndentLevel++;
  4598. kdDebug( 6050 ) << indent << "saveState this=" << this << " '" << name() << "' saving URL " << m_url.url() << endl;
  4599. #endif
  4600. stream << m_url << (TQ_INT32)d->m_view->contentsX() << (TQ_INT32)d->m_view->contentsY()
  4601. << (TQ_INT32) d->m_view->contentsWidth() << (TQ_INT32) d->m_view->contentsHeight() << (TQ_INT32) d->m_view->marginWidth() << (TQ_INT32) d->m_view->marginHeight();
  4602. // save link cursor position
  4603. int focusNodeNumber;
  4604. if (!d->m_focusNodeRestored)
  4605. focusNodeNumber = d->m_focusNodeNumber;
  4606. else if (d->m_doc && d->m_doc->focusNode())
  4607. focusNodeNumber = d->m_doc->nodeAbsIndex(d->m_doc->focusNode());
  4608. else
  4609. focusNodeNumber = -1;
  4610. stream << focusNodeNumber;
  4611. // Save the doc's cache id.
  4612. stream << d->m_cacheId;
  4613. // Save the state of the document (Most notably the state of any forms)
  4614. TQStringList docState;
  4615. if (d->m_doc)
  4616. {
  4617. docState = d->m_doc->docState();
  4618. }
  4619. stream << d->m_encoding << d->m_sheetUsed << docState;
  4620. stream << d->m_zoomFactor;
  4621. stream << d->m_httpHeaders;
  4622. stream << d->m_pageServices;
  4623. stream << d->m_pageReferrer;
  4624. // Save ssl data
  4625. stream << d->m_ssl_in_use
  4626. << d->m_ssl_peer_certificate
  4627. << d->m_ssl_peer_chain
  4628. << d->m_ssl_peer_ip
  4629. << d->m_ssl_cipher
  4630. << d->m_ssl_cipher_desc
  4631. << d->m_ssl_cipher_version
  4632. << d->m_ssl_cipher_used_bits
  4633. << d->m_ssl_cipher_bits
  4634. << d->m_ssl_cert_state
  4635. << d->m_ssl_parent_ip
  4636. << d->m_ssl_parent_cert;
  4637. TQStringList frameNameLst, frameServiceTypeLst, frameServiceNameLst;
  4638. KURL::List frameURLLst;
  4639. TQValueList<TQByteArray> frameStateBufferLst;
  4640. ConstFrameIt it = d->m_frames.begin();
  4641. const ConstFrameIt end = d->m_frames.end();
  4642. for (; it != end; ++it )
  4643. {
  4644. if ( !(*it)->m_part )
  4645. continue;
  4646. frameNameLst << (*it)->m_name;
  4647. frameServiceTypeLst << (*it)->m_serviceType;
  4648. frameServiceNameLst << (*it)->m_serviceName;
  4649. frameURLLst << (*it)->m_part->url();
  4650. TQByteArray state;
  4651. TQDataStream frameStream( state, IO_WriteOnly );
  4652. if ( (*it)->m_extension )
  4653. (*it)->m_extension->saveState( frameStream );
  4654. frameStateBufferLst << state;
  4655. }
  4656. // Save frame data
  4657. stream << (TQ_UINT32) frameNameLst.count();
  4658. stream << frameNameLst << frameServiceTypeLst << frameServiceNameLst << frameURLLst << frameStateBufferLst;
  4659. #ifndef NDEBUG
  4660. s_saveStateIndentLevel = indentLevel;
  4661. #endif
  4662. }
  4663. void KHTMLPart::restoreState( TQDataStream &stream )
  4664. {
  4665. KURL u;
  4666. TQ_INT32 xOffset, yOffset, wContents, hContents, mWidth, mHeight;
  4667. TQ_UINT32 frameCount;
  4668. TQStringList frameNames, frameServiceTypes, docState, frameServiceNames;
  4669. KURL::List frameURLs;
  4670. TQValueList<TQByteArray> frameStateBuffers;
  4671. TQValueList<int> fSizes;
  4672. TQString encoding, sheetUsed;
  4673. long old_cacheId = d->m_cacheId;
  4674. stream >> u >> xOffset >> yOffset >> wContents >> hContents >> mWidth >> mHeight;
  4675. d->m_view->setMarginWidth( mWidth );
  4676. d->m_view->setMarginHeight( mHeight );
  4677. // restore link cursor position
  4678. // nth node is active. value is set in checkCompleted()
  4679. stream >> d->m_focusNodeNumber;
  4680. d->m_focusNodeRestored = false;
  4681. stream >> d->m_cacheId;
  4682. stream >> encoding >> sheetUsed >> docState;
  4683. d->m_encoding = encoding;
  4684. d->m_sheetUsed = sheetUsed;
  4685. int zoomFactor;
  4686. stream >> zoomFactor;
  4687. setZoomFactor(zoomFactor);
  4688. stream >> d->m_httpHeaders;
  4689. stream >> d->m_pageServices;
  4690. stream >> d->m_pageReferrer;
  4691. // Restore ssl data
  4692. stream >> d->m_ssl_in_use
  4693. >> d->m_ssl_peer_certificate
  4694. >> d->m_ssl_peer_chain
  4695. >> d->m_ssl_peer_ip
  4696. >> d->m_ssl_cipher
  4697. >> d->m_ssl_cipher_desc
  4698. >> d->m_ssl_cipher_version
  4699. >> d->m_ssl_cipher_used_bits
  4700. >> d->m_ssl_cipher_bits
  4701. >> d->m_ssl_cert_state
  4702. >> d->m_ssl_parent_ip
  4703. >> d->m_ssl_parent_cert;
  4704. setPageSecurity( d->m_ssl_in_use ? Encrypted : NotCrypted );
  4705. stream >> frameCount >> frameNames >> frameServiceTypes >> frameServiceNames
  4706. >> frameURLs >> frameStateBuffers;
  4707. d->m_bComplete = false;
  4708. d->m_bLoadEventEmitted = false;
  4709. // kdDebug( 6050 ) << "restoreState() docState.count() = " << docState.count() << endl;
  4710. // kdDebug( 6050 ) << "m_url " << m_url.url() << " <-> " << u.url() << endl;
  4711. // kdDebug( 6050 ) << "m_frames.count() " << d->m_frames.count() << " <-> " << frameCount << endl;
  4712. if (d->m_cacheId == old_cacheId)
  4713. {
  4714. // Partial restore
  4715. d->m_redirectionTimer.stop();
  4716. FrameIt fIt = d->m_frames.begin();
  4717. const FrameIt fEnd = d->m_frames.end();
  4718. for (; fIt != fEnd; ++fIt )
  4719. (*fIt)->m_bCompleted = false;
  4720. fIt = d->m_frames.begin();
  4721. TQStringList::ConstIterator fNameIt = frameNames.begin();
  4722. TQStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
  4723. TQStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
  4724. KURL::List::ConstIterator fURLIt = frameURLs.begin();
  4725. TQValueList<TQByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
  4726. for (; fIt != fEnd; ++fIt, ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
  4727. {
  4728. khtml::ChildFrame* const child = *fIt;
  4729. // kdDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt << endl;
  4730. if ( child->m_name != *fNameIt || child->m_serviceType != *fServiceTypeIt )
  4731. {
  4732. child->m_bPreloaded = true;
  4733. child->m_name = *fNameIt;
  4734. child->m_serviceName = *fServiceNameIt;
  4735. processObjectRequest( child, *fURLIt, *fServiceTypeIt );
  4736. }
  4737. if ( child->m_part )
  4738. {
  4739. child->m_bCompleted = false;
  4740. if ( child->m_extension && !(*fBufferIt).isEmpty() )
  4741. {
  4742. TQDataStream frameStream( *fBufferIt, IO_ReadOnly );
  4743. child->m_extension->restoreState( frameStream );
  4744. }
  4745. else
  4746. child->m_part->openURL( *fURLIt );
  4747. }
  4748. }
  4749. KParts::URLArgs args( d->m_extension->urlArgs() );
  4750. args.xOffset = xOffset;
  4751. args.yOffset = yOffset;
  4752. args.docState = docState;
  4753. d->m_extension->setURLArgs( args );
  4754. d->m_view->resizeContents( wContents, hContents);
  4755. d->m_view->setContentsPos( xOffset, yOffset );
  4756. m_url = u;
  4757. }
  4758. else
  4759. {
  4760. // Full restore.
  4761. closeURL();
  4762. // We must force a clear because we want to be sure to delete all
  4763. // frames.
  4764. d->m_bCleared = false;
  4765. clear();
  4766. d->m_encoding = encoding;
  4767. d->m_sheetUsed = sheetUsed;
  4768. TQStringList::ConstIterator fNameIt = frameNames.begin();
  4769. const TQStringList::ConstIterator fNameEnd = frameNames.end();
  4770. TQStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
  4771. TQStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
  4772. KURL::List::ConstIterator fURLIt = frameURLs.begin();
  4773. TQValueList<TQByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
  4774. for (; fNameIt != fNameEnd; ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
  4775. {
  4776. khtml::ChildFrame* const newChild = new khtml::ChildFrame;
  4777. newChild->m_bPreloaded = true;
  4778. newChild->m_name = *fNameIt;
  4779. newChild->m_serviceName = *fServiceNameIt;
  4780. // kdDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt << endl;
  4781. const FrameIt childFrame = d->m_frames.append( newChild );
  4782. processObjectRequest( *childFrame, *fURLIt, *fServiceTypeIt );
  4783. (*childFrame)->m_bPreloaded = true;
  4784. if ( (*childFrame)->m_part )
  4785. {
  4786. if ( (*childFrame)->m_extension )
  4787. if ( (*childFrame)->m_extension && !(*fBufferIt).isEmpty() )
  4788. {
  4789. TQDataStream frameStream( *fBufferIt, IO_ReadOnly );
  4790. (*childFrame)->m_extension->restoreState( frameStream );
  4791. }
  4792. else
  4793. (*childFrame)->m_part->openURL( *fURLIt );
  4794. }
  4795. }
  4796. KParts::URLArgs args( d->m_extension->urlArgs() );
  4797. args.xOffset = xOffset;
  4798. args.yOffset = yOffset;
  4799. args.docState = docState;
  4800. d->m_extension->setURLArgs( args );
  4801. if (!KHTMLPageCache::self()->isComplete(d->m_cacheId))
  4802. {
  4803. d->m_restored = true;
  4804. openURL( u );
  4805. d->m_restored = false;
  4806. }
  4807. else
  4808. {
  4809. restoreURL( u );
  4810. }
  4811. }
  4812. }
  4813. void KHTMLPart::show()
  4814. {
  4815. if ( d->m_view )
  4816. d->m_view->show();
  4817. }
  4818. void KHTMLPart::hide()
  4819. {
  4820. if ( d->m_view )
  4821. d->m_view->hide();
  4822. }
  4823. DOM::Node KHTMLPart::nodeUnderMouse() const
  4824. {
  4825. return d->m_view->nodeUnderMouse();
  4826. }
  4827. DOM::Node KHTMLPart::nonSharedNodeUnderMouse() const
  4828. {
  4829. return d->m_view->nonSharedNodeUnderMouse();
  4830. }
  4831. void KHTMLPart::emitSelectionChanged()
  4832. {
  4833. emit d->m_extension->enableAction( "copy", hasSelection() );
  4834. if ( d->m_findDialog )
  4835. d->m_findDialog->setHasSelection( hasSelection() );
  4836. emit d->m_extension->selectionInfo( selectedText() );
  4837. emit selectionChanged();
  4838. }
  4839. int KHTMLPart::zoomFactor() const
  4840. {
  4841. return d->m_zoomFactor;
  4842. }
  4843. // ### make the list configurable ?
  4844. static const int zoomSizes[] = { 20, 40, 60, 80, 90, 95, 100, 105, 110, 120, 140, 160, 180, 200, 250, 300 };
  4845. static const int zoomSizeCount = (sizeof(zoomSizes) / sizeof(int));
  4846. static const int minZoom = 20;
  4847. static const int maxZoom = 300;
  4848. // My idea of useful stepping ;-) (LS)
  4849. extern const int KDE_NO_EXPORT fastZoomSizes[] = { 20, 50, 75, 90, 100, 120, 150, 200, 300 };
  4850. extern const int KDE_NO_EXPORT fastZoomSizeCount = sizeof fastZoomSizes / sizeof fastZoomSizes[0];
  4851. void KHTMLPart::slotIncZoom()
  4852. {
  4853. zoomIn(zoomSizes, zoomSizeCount);
  4854. }
  4855. void KHTMLPart::slotDecZoom()
  4856. {
  4857. zoomOut(zoomSizes, zoomSizeCount);
  4858. }
  4859. void KHTMLPart::slotIncZoomFast()
  4860. {
  4861. zoomIn(fastZoomSizes, fastZoomSizeCount);
  4862. }
  4863. void KHTMLPart::slotDecZoomFast()
  4864. {
  4865. zoomOut(fastZoomSizes, fastZoomSizeCount);
  4866. }
  4867. void KHTMLPart::zoomIn(const int stepping[], int count)
  4868. {
  4869. int zoomFactor = d->m_zoomFactor;
  4870. if (zoomFactor < maxZoom) {
  4871. // find the entry nearest to the given zoomsizes
  4872. for (int i = 0; i < count; ++i)
  4873. if (stepping[i] > zoomFactor) {
  4874. zoomFactor = stepping[i];
  4875. break;
  4876. }
  4877. setZoomFactor(zoomFactor);
  4878. }
  4879. }
  4880. void KHTMLPart::zoomOut(const int stepping[], int count)
  4881. {
  4882. int zoomFactor = d->m_zoomFactor;
  4883. if (zoomFactor > minZoom) {
  4884. // find the entry nearest to the given zoomsizes
  4885. for (int i = count-1; i >= 0; --i)
  4886. if (stepping[i] < zoomFactor) {
  4887. zoomFactor = stepping[i];
  4888. break;
  4889. }
  4890. setZoomFactor(zoomFactor);
  4891. }
  4892. }
  4893. void KHTMLPart::setZoomFactor (int percent)
  4894. {
  4895. if (percent < minZoom) percent = minZoom;
  4896. if (percent > maxZoom) percent = maxZoom;
  4897. if (d->m_zoomFactor == percent) return;
  4898. d->m_zoomFactor = percent;
  4899. if(d->m_doc) {
  4900. TQApplication::setOverrideCursor( tqwaitCursor );
  4901. if (d->m_doc->styleSelector())
  4902. d->m_doc->styleSelector()->computeFontSizes(d->m_doc->paintDeviceMetrics(), d->m_zoomFactor);
  4903. d->m_doc->recalcStyle( NodeImpl::Force );
  4904. TQApplication::restoreOverrideCursor();
  4905. }
  4906. ConstFrameIt it = d->m_frames.begin();
  4907. const ConstFrameIt end = d->m_frames.end();
  4908. for (; it != end; ++it )
  4909. if ( !( *it )->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
  4910. KParts::ReadOnlyPart* const p = ( *it )->m_part;
  4911. static_cast<KHTMLPart*>( p )->setZoomFactor(d->m_zoomFactor);
  4912. }
  4913. if ( d->m_guiProfile == BrowserViewGUI ) {
  4914. d->m_paDecZoomFactor->setEnabled( d->m_zoomFactor > minZoom );
  4915. d->m_paIncZoomFactor->setEnabled( d->m_zoomFactor < maxZoom );
  4916. }
  4917. }
  4918. void KHTMLPart::slotZoomView( int delta )
  4919. {
  4920. if ( delta < 0 )
  4921. slotIncZoom();
  4922. else
  4923. slotDecZoom();
  4924. }
  4925. void KHTMLPart::setStatusBarText( const TQString& text, StatusBarPriority p)
  4926. {
  4927. if (!d->m_statusMessagesEnabled)
  4928. return;
  4929. d->m_statusBarText[p] = text;
  4930. // shift handling ?
  4931. TQString tobe = d->m_statusBarText[BarHoverText];
  4932. if (tobe.isEmpty())
  4933. tobe = d->m_statusBarText[BarOverrideText];
  4934. if (tobe.isEmpty()) {
  4935. tobe = d->m_statusBarText[BarDefaultText];
  4936. if (!tobe.isEmpty() && d->m_jobspeed)
  4937. tobe += " ";
  4938. if (d->m_jobspeed)
  4939. tobe += i18n( "(%1/s)" ).arg( KIO::convertSize( d->m_jobspeed ) );
  4940. }
  4941. tobe = "<qt>"+tobe;
  4942. emit ReadOnlyPart::setStatusBarText(tobe);
  4943. }
  4944. void KHTMLPart::setJSStatusBarText( const TQString &text )
  4945. {
  4946. setStatusBarText(text, BarOverrideText);
  4947. }
  4948. void KHTMLPart::setJSDefaultStatusBarText( const TQString &text )
  4949. {
  4950. setStatusBarText(text, BarDefaultText);
  4951. }
  4952. TQString KHTMLPart::jsStatusBarText() const
  4953. {
  4954. return d->m_statusBarText[BarOverrideText];
  4955. }
  4956. TQString KHTMLPart::jsDefaultStatusBarText() const
  4957. {
  4958. return d->m_statusBarText[BarDefaultText];
  4959. }
  4960. TQString KHTMLPart::referrer() const
  4961. {
  4962. return d->m_referrer;
  4963. }
  4964. TQString KHTMLPart::pageReferrer() const
  4965. {
  4966. KURL referrerURL = KURL( d->m_pageReferrer );
  4967. if (referrerURL.isValid())
  4968. {
  4969. TQString protocol = referrerURL.protocol();
  4970. if ((protocol == "http") ||
  4971. ((protocol == "https") && (m_url.protocol() == "https")))
  4972. {
  4973. referrerURL.setRef(TQString());
  4974. referrerURL.setUser(TQString());
  4975. referrerURL.setPass(TQString());
  4976. return referrerURL.url();
  4977. }
  4978. }
  4979. return TQString();
  4980. }
  4981. TQString KHTMLPart::lastModified() const
  4982. {
  4983. if ( d->m_lastModified.isEmpty() && m_url.isLocalFile() ) {
  4984. // Local file: set last-modified from the file's mtime.
  4985. // Done on demand to save time when this isn't needed - but can lead
  4986. // to slightly wrong results if updating the file on disk w/o reloading.
  4987. TQDateTime lastModif = TQFileInfo( m_url.path() ).lastModified();
  4988. d->m_lastModified = lastModif.toString( Qt::LocalDate );
  4989. }
  4990. //kdDebug(6050) << "KHTMLPart::lastModified: " << d->m_lastModified << endl;
  4991. return d->m_lastModified;
  4992. }
  4993. void KHTMLPart::slotLoadImages()
  4994. {
  4995. if (d->m_doc )
  4996. d->m_doc->docLoader()->setAutoloadImages( !d->m_doc->docLoader()->autoloadImages() );
  4997. ConstFrameIt it = d->m_frames.begin();
  4998. const ConstFrameIt end = d->m_frames.end();
  4999. for (; it != end; ++it )
  5000. if ( !( *it )->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
  5001. KParts::ReadOnlyPart* const p = ( *it )->m_part;
  5002. static_cast<KHTMLPart*>( p )->slotLoadImages();
  5003. }
  5004. }
  5005. void KHTMLPart::reparseConfiguration()
  5006. {
  5007. KHTMLSettings *settings = KHTMLFactory::defaultHTMLSettings();
  5008. settings->init();
  5009. setAutoloadImages( settings->autoLoadImages() );
  5010. if (d->m_doc)
  5011. d->m_doc->docLoader()->setShowAnimations( settings->showAnimations() );
  5012. d->m_bOpenMiddleClick = settings->isOpenMiddleClickEnabled();
  5013. d->m_bBackRightClick = settings->isBackRightClickEnabled();
  5014. d->m_bJScriptEnabled = settings->isJavaScriptEnabled(m_url.host());
  5015. setDebugScript( settings->isJavaScriptDebugEnabled() );
  5016. d->m_bJavaEnabled = settings->isJavaEnabled(m_url.host());
  5017. d->m_bPluginsEnabled = settings->isPluginsEnabled(m_url.host());
  5018. d->m_metaRefreshEnabled = settings->isAutoDelayedActionsEnabled ();
  5019. delete d->m_settings;
  5020. d->m_settings = new KHTMLSettings(*KHTMLFactory::defaultHTMLSettings());
  5021. TQApplication::setOverrideCursor( tqwaitCursor );
  5022. khtml::CSSStyleSelector::reparseConfiguration();
  5023. if(d->m_doc) d->m_doc->updateStyleSelector();
  5024. TQApplication::restoreOverrideCursor();
  5025. if (KHTMLFactory::defaultHTMLSettings()->isAdFilterEnabled())
  5026. runAdFilter();
  5027. }
  5028. TQStringList KHTMLPart::frameNames() const
  5029. {
  5030. TQStringList res;
  5031. ConstFrameIt it = d->m_frames.begin();
  5032. const ConstFrameIt end = d->m_frames.end();
  5033. for (; it != end; ++it )
  5034. if (!(*it)->m_bPreloaded)
  5035. res += (*it)->m_name;
  5036. return res;
  5037. }
  5038. TQPtrList<KParts::ReadOnlyPart> KHTMLPart::frames() const
  5039. {
  5040. TQPtrList<KParts::ReadOnlyPart> res;
  5041. ConstFrameIt it = d->m_frames.begin();
  5042. const ConstFrameIt end = d->m_frames.end();
  5043. for (; it != end; ++it )
  5044. if (!(*it)->m_bPreloaded)
  5045. res.append( (*it)->m_part );
  5046. return res;
  5047. }
  5048. bool KHTMLPart::openURLInFrame( const KURL &url, const KParts::URLArgs &urlArgs )
  5049. {
  5050. kdDebug( 6050 ) << this << "KHTMLPart::openURLInFrame " << url << endl;
  5051. FrameIt it = d->m_frames.find( urlArgs.frameName );
  5052. if ( it == d->m_frames.end() )
  5053. return false;
  5054. // Inform someone that we are about to show something else.
  5055. if ( !urlArgs.lockHistory() )
  5056. emit d->m_extension->openURLNotify();
  5057. requestObject( *it, url, urlArgs );
  5058. return true;
  5059. }
  5060. void KHTMLPart::setDNDEnabled( bool b )
  5061. {
  5062. d->m_bDnd = b;
  5063. }
  5064. bool KHTMLPart::dndEnabled() const
  5065. {
  5066. return d->m_bDnd;
  5067. }
  5068. void KHTMLPart::customEvent( TQCustomEvent *event )
  5069. {
  5070. if ( khtml::MousePressEvent::test( event ) )
  5071. {
  5072. khtmlMousePressEvent( static_cast<khtml::MousePressEvent *>( event ) );
  5073. return;
  5074. }
  5075. if ( khtml::MouseDoubleClickEvent::test( event ) )
  5076. {
  5077. khtmlMouseDoubleClickEvent( static_cast<khtml::MouseDoubleClickEvent *>( event ) );
  5078. return;
  5079. }
  5080. if ( khtml::MouseMoveEvent::test( event ) )
  5081. {
  5082. khtmlMouseMoveEvent( static_cast<khtml::MouseMoveEvent *>( event ) );
  5083. return;
  5084. }
  5085. if ( khtml::MouseReleaseEvent::test( event ) )
  5086. {
  5087. khtmlMouseReleaseEvent( static_cast<khtml::MouseReleaseEvent *>( event ) );
  5088. return;
  5089. }
  5090. if ( khtml::DrawContentsEvent::test( event ) )
  5091. {
  5092. khtmlDrawContentsEvent( static_cast<khtml::DrawContentsEvent *>( event ) );
  5093. return;
  5094. }
  5095. KParts::ReadOnlyPart::customEvent( event );
  5096. }
  5097. /** returns the position of the first inline text box of the line at
  5098. * coordinate y in renderNode
  5099. *
  5100. * This is a helper function for line-by-line text selection.
  5101. */
  5102. static bool firstRunAt(khtml::RenderObject *renderNode, int y, NodeImpl *&startNode, long &startOffset)
  5103. {
  5104. for (khtml::RenderObject *n = renderNode; n; n = n->nextSibling()) {
  5105. if (n->isText()) {
  5106. khtml::RenderText* const textRenderer = static_cast<khtml::RenderText *>(n);
  5107. const khtml::InlineTextBoxArray &runs = textRenderer->inlineTextBoxes();
  5108. const unsigned lim = runs.count();
  5109. for (unsigned i = 0; i != lim; ++i) {
  5110. if (runs[i]->m_y == y && textRenderer->element()) {
  5111. startNode = textRenderer->element();
  5112. startOffset = runs[i]->m_start;
  5113. return true;
  5114. }
  5115. }
  5116. }
  5117. if (firstRunAt(n->firstChild(), y, startNode, startOffset)) {
  5118. return true;
  5119. }
  5120. }
  5121. return false;
  5122. }
  5123. /** returns the position of the last inline text box of the line at
  5124. * coordinate y in renderNode
  5125. *
  5126. * This is a helper function for line-by-line text selection.
  5127. */
  5128. static bool lastRunAt(khtml::RenderObject *renderNode, int y, NodeImpl *&endNode, long &endOffset)
  5129. {
  5130. khtml::RenderObject *n = renderNode;
  5131. if (!n) {
  5132. return false;
  5133. }
  5134. khtml::RenderObject *next;
  5135. while ((next = n->nextSibling())) {
  5136. n = next;
  5137. }
  5138. while (1) {
  5139. if (lastRunAt(n->firstChild(), y, endNode, endOffset)) {
  5140. return true;
  5141. }
  5142. if (n->isText()) {
  5143. khtml::RenderText* const textRenderer = static_cast<khtml::RenderText *>(n);
  5144. const khtml::InlineTextBoxArray &runs = textRenderer->inlineTextBoxes();
  5145. for (int i = (int)runs.count()-1; i >= 0; --i) {
  5146. if (runs[i]->m_y == y && textRenderer->element()) {
  5147. endNode = textRenderer->element();
  5148. endOffset = runs[i]->m_start + runs[i]->m_len;
  5149. return true;
  5150. }
  5151. }
  5152. }
  5153. if (n == renderNode) {
  5154. return false;
  5155. }
  5156. n = n->previousSibling();
  5157. }
  5158. }
  5159. void KHTMLPart::khtmlMousePressEvent( khtml::MousePressEvent *event )
  5160. {
  5161. DOM::DOMString url = event->url();
  5162. TQMouseEvent *_mouse = event->qmouseEvent();
  5163. DOM::Node innerNode = event->innerNode();
  5164. d->m_mousePressNode = innerNode;
  5165. d->m_dragStartPos = _mouse->pos();
  5166. if ( !event->url().isNull() ) {
  5167. d->m_strSelectedURL = event->url().string();
  5168. d->m_strSelectedURLTarget = event->target().string();
  5169. }
  5170. else
  5171. d->m_strSelectedURL = d->m_strSelectedURLTarget = TQString();
  5172. if ( _mouse->button() == Qt::LeftButton ||
  5173. _mouse->button() == Qt::MidButton )
  5174. {
  5175. d->m_bMousePressed = true;
  5176. #ifndef KHTML_NO_SELECTION
  5177. if ( _mouse->button() == Qt::LeftButton )
  5178. {
  5179. if ( (!d->m_strSelectedURL.isNull() && !isEditable())
  5180. || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) )
  5181. return;
  5182. if ( !innerNode.isNull() && innerNode.handle()->renderer()) {
  5183. int offset = 0;
  5184. DOM::NodeImpl* node = 0;
  5185. khtml::RenderObject::SelPointState state;
  5186. innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(),
  5187. event->absX()-innerNode.handle()->renderer()->xPos(),
  5188. event->absY()-innerNode.handle()->renderer()->yPos(), node, offset, state );
  5189. d->m_extendMode = d->ExtendByChar;
  5190. #ifdef KHTML_NO_CARET
  5191. d->m_selectionStart = node;
  5192. d->m_startOffset = offset;
  5193. //if ( node )
  5194. // kdDebug(6005) << "KHTMLPart::khtmlMousePressEvent selectionStart=" << d->m_selectionStart.handle()->renderer()
  5195. // << " offset=" << d->m_startOffset << endl;
  5196. //else
  5197. // kdDebug(6005) << "KHTML::khtmlMousePressEvent selectionStart=(nil)" << endl;
  5198. d->m_selectionEnd = d->m_selectionStart;
  5199. d->m_endOffset = d->m_startOffset;
  5200. d->m_doc->clearSelection();
  5201. #else // KHTML_NO_CARET
  5202. d->m_view->moveCaretTo(node, offset, (_mouse->state() & ShiftButton) == 0);
  5203. #endif // KHTML_NO_CARET
  5204. d->m_initialNode = d->m_selectionStart;
  5205. d->m_initialOffset = d->m_startOffset;
  5206. // kdDebug(6000) << "press: initOfs " << d->m_initialOffset << endl;
  5207. }
  5208. else
  5209. {
  5210. #ifndef KHTML_NO_CARET
  5211. // simply leave it. Is this a good idea?
  5212. #else
  5213. d->m_selectionStart = DOM::Node();
  5214. d->m_selectionEnd = DOM::Node();
  5215. #endif
  5216. }
  5217. emitSelectionChanged();
  5218. startAutoScroll();
  5219. }
  5220. #else
  5221. d->m_dragLastPos = _mouse->globalPos();
  5222. #endif
  5223. }
  5224. if ( _mouse->button() == Qt::RightButton && parentPart() != 0 && d->m_bBackRightClick )
  5225. {
  5226. d->m_bRightMousePressed = true;
  5227. } else if ( _mouse->button() == Qt::RightButton )
  5228. {
  5229. popupMenu( d->m_strSelectedURL );
  5230. // might be deleted, don't touch "this"
  5231. }
  5232. }
  5233. void KHTMLPart::khtmlMouseDoubleClickEvent( khtml::MouseDoubleClickEvent *event )
  5234. {
  5235. TQMouseEvent *_mouse = event->qmouseEvent();
  5236. if ( _mouse->button() == Qt::LeftButton )
  5237. {
  5238. d->m_bMousePressed = true;
  5239. DOM::Node innerNode = event->innerNode();
  5240. // Find selectionStart again, khtmlMouseReleaseEvent lost it
  5241. if ( !innerNode.isNull() && innerNode.handle()->renderer()) {
  5242. int offset = 0;
  5243. DOM::NodeImpl* node = 0;
  5244. khtml::RenderObject::SelPointState state;
  5245. innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(),
  5246. event->absX()-innerNode.handle()->renderer()->xPos(),
  5247. event->absY()-innerNode.handle()->renderer()->yPos(), node, offset, state);
  5248. //kdDebug() << k_funcinfo << "checkSelectionPoint returned node=" << node << " offset=" << offset << endl;
  5249. if ( node && node->renderer() )
  5250. {
  5251. // Extend selection to a complete word (double-click) or line (triple-click)
  5252. bool selectLine = (event->clickCount() == 3);
  5253. d->m_extendMode = selectLine ? d->ExtendByLine : d->ExtendByWord;
  5254. // Extend existing selection if Shift was pressed
  5255. if (_mouse->state() & ShiftButton) {
  5256. d->caretNode() = node;
  5257. d->caretOffset() = offset;
  5258. d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
  5259. d->m_selectionStart.handle(), d->m_startOffset,
  5260. d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
  5261. d->m_initialNode = d->m_extendAtEnd ? d->m_selectionStart : d->m_selectionEnd;
  5262. d->m_initialOffset = d->m_extendAtEnd ? d->m_startOffset : d->m_endOffset;
  5263. } else {
  5264. d->m_selectionStart = d->m_selectionEnd = node;
  5265. d->m_startOffset = d->m_endOffset = offset;
  5266. d->m_startBeforeEnd = true;
  5267. d->m_initialNode = node;
  5268. d->m_initialOffset = offset;
  5269. }
  5270. // kdDebug(6000) << "dblclk: initOfs " << d->m_initialOffset << endl;
  5271. // Extend the start
  5272. extendSelection( d->m_selectionStart.handle(), d->m_startOffset, d->m_selectionStart, d->m_startOffset, !d->m_startBeforeEnd, selectLine );
  5273. // Extend the end
  5274. extendSelection( d->m_selectionEnd.handle(), d->m_endOffset, d->m_selectionEnd, d->m_endOffset, d->m_startBeforeEnd, selectLine );
  5275. //kdDebug() << d->m_selectionStart.handle() << " " << d->m_startOffset << " - " <<
  5276. // d->m_selectionEnd.handle() << " " << d->m_endOffset << endl;
  5277. emitSelectionChanged();
  5278. d->m_doc
  5279. ->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
  5280. d->m_selectionEnd.handle(),d->m_endOffset);
  5281. #ifndef KHTML_NO_CARET
  5282. bool v = d->m_view->placeCaret();
  5283. emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
  5284. #endif
  5285. startAutoScroll();
  5286. }
  5287. }
  5288. }
  5289. }
  5290. void KHTMLPart::extendSelection( DOM::NodeImpl* node, long offset, DOM::Node& selectionNode, long& selectionOffset, bool right, bool selectLines )
  5291. {
  5292. khtml::RenderObject* obj = node->renderer();
  5293. if (obj->isText() && selectLines) {
  5294. int pos;
  5295. khtml::RenderText *renderer = static_cast<khtml::RenderText *>(obj);
  5296. khtml::InlineTextBox *run = renderer->findInlineTextBox( offset, pos );
  5297. DOMString t = node->nodeValue();
  5298. DOM::NodeImpl* selNode = 0;
  5299. long selOfs = 0;
  5300. if (!run)
  5301. return;
  5302. int selectionPointY = run->m_y;
  5303. // Go up to first non-inline element.
  5304. khtml::RenderObject *renderNode = renderer;
  5305. while (renderNode && renderNode->isInline())
  5306. renderNode = renderNode->parent();
  5307. renderNode = renderNode->firstChild();
  5308. if (right) {
  5309. // Look for all the last child in the block that is on the same line
  5310. // as the selection point.
  5311. if (!lastRunAt (renderNode, selectionPointY, selNode, selOfs))
  5312. return;
  5313. } else {
  5314. // Look for all the first child in the block that is on the same line
  5315. // as the selection point.
  5316. if (!firstRunAt (renderNode, selectionPointY, selNode, selOfs))
  5317. return;
  5318. }
  5319. selectionNode = selNode;
  5320. selectionOffset = selOfs;
  5321. return;
  5322. }
  5323. TQString str;
  5324. int len = 0;
  5325. if ( obj->isText() ) { // can be false e.g. when double-clicking on a disabled submit button
  5326. str = static_cast<khtml::RenderText *>(obj)->data().string();
  5327. len = str.length();
  5328. }
  5329. //kdDebug() << "extendSelection right=" << right << " offset=" << offset << " len=" << len << " Starting at obj=" << obj << endl;
  5330. TQChar ch;
  5331. do {
  5332. // Last char was ok, point to it
  5333. if ( node ) {
  5334. selectionNode = node;
  5335. selectionOffset = offset;
  5336. }
  5337. // Get another char
  5338. while ( obj && ( (right && offset >= len-1) || (!right && offset <= 0) ) )
  5339. {
  5340. obj = right ? obj->objectBelow() : obj->objectAbove();
  5341. //kdDebug() << "obj=" << obj << endl;
  5342. if ( obj ) {
  5343. //kdDebug() << "isText=" << obj->isText() << endl;
  5344. str = TQString();
  5345. if ( obj->isText() )
  5346. str = static_cast<khtml::RenderText *>(obj)->data().string();
  5347. else if ( obj->isBR() )
  5348. str = '\n';
  5349. else if ( !obj->isInline() ) {
  5350. obj = 0L; // parag limit -> done
  5351. break;
  5352. }
  5353. len = str.length();
  5354. //kdDebug() << "str=" << str << " length=" << len << endl;
  5355. // set offset - note that the first thing will be a ++ or -- on it.
  5356. if ( right )
  5357. offset = -1;
  5358. else
  5359. offset = len;
  5360. }
  5361. }
  5362. if ( !obj ) // end of parag or document
  5363. break;
  5364. node = obj->element();
  5365. if ( right )
  5366. {
  5367. Q_ASSERT( offset < len-1 );
  5368. ++offset;
  5369. }
  5370. else
  5371. {
  5372. Q_ASSERT( offset > 0 );
  5373. --offset;
  5374. }
  5375. // Test that char
  5376. ch = str[ (int)offset ];
  5377. //kdDebug() << " offset=" << offset << " ch=" << TQString(ch) << endl;
  5378. } while ( !ch.isSpace() && !ch.isPunct() );
  5379. // make offset point after last char
  5380. if (right) ++selectionOffset;
  5381. }
  5382. #ifndef KHTML_NO_SELECTION
  5383. void KHTMLPart::extendSelectionTo(int x, int y, int absX, int absY, const DOM::Node &innerNode)
  5384. {
  5385. int offset;
  5386. //kdDebug(6000) << "KHTMLPart::khtmlMouseMoveEvent x=" << event->x() << " y=" << event->y() << endl;
  5387. DOM::NodeImpl* node=0;
  5388. khtml::RenderObject::SelPointState state;
  5389. innerNode.handle()->renderer()->checkSelectionPoint( x, y,
  5390. absX-innerNode.handle()->renderer()->xPos(),
  5391. absY-innerNode.handle()->renderer()->yPos(), node, offset, state);
  5392. if (!node || !node->renderer()) return;
  5393. // Words at the beginning/end of line cannot be deselected in
  5394. // ExtendByWord mode. Therefore, do not enforce it if the selection
  5395. // point does not match the node under the mouse cursor.
  5396. bool withinNode = innerNode == node;
  5397. // we have to get to know if end is before start or not...
  5398. // shouldn't be null but it can happen with dynamic updating of nodes
  5399. if (d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() ||
  5400. d->m_initialNode.isNull() ||
  5401. !d->m_selectionStart.handle()->renderer() ||
  5402. !d->m_selectionEnd.handle()->renderer()) return;
  5403. if (d->m_extendMode != d->ExtendByChar) {
  5404. // check whether we should extend at the front, or at the back
  5405. bool caretBeforeInit = RangeImpl::compareBoundaryPoints(
  5406. d->caretNode().handle(), d->caretOffset(),
  5407. d->m_initialNode.handle(), d->m_initialOffset) <= 0;
  5408. bool nodeBeforeInit = RangeImpl::compareBoundaryPoints(node, offset,
  5409. d->m_initialNode.handle(), d->m_initialOffset) <= 0;
  5410. // have to fix up start to point to the original end
  5411. if (caretBeforeInit != nodeBeforeInit) {
  5412. // kdDebug(6000) << "extto cbi: " << caretBeforeInit << " startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << " initOfs " << d->m_initialOffset << endl;
  5413. extendSelection(d->m_initialNode.handle(), d->m_initialOffset,
  5414. d->m_extendAtEnd ? d->m_selectionStart : d->m_selectionEnd,
  5415. d->m_extendAtEnd ? d->m_startOffset : d->m_endOffset,
  5416. nodeBeforeInit, d->m_extendMode == d->ExtendByLine);
  5417. }
  5418. }
  5419. d->caretNode() = node;
  5420. d->caretOffset() = offset;
  5421. //kdDebug( 6000 ) << "setting end of selection to " << d->m_selectionEnd.handle() << "/" << d->m_endOffset << endl;
  5422. d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
  5423. d->m_selectionStart.handle(), d->m_startOffset,
  5424. d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
  5425. if ( !d->m_selectionStart.isNull() && !d->m_selectionEnd.isNull() )
  5426. {
  5427. // kdDebug(6000) << "extto: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << " initOfs " << d->m_initialOffset << endl;
  5428. if (d->m_extendMode != d->ExtendByChar && withinNode)
  5429. extendSelection( node, offset, d->caretNode(), d->caretOffset(), d->m_startBeforeEnd ^ !d->m_extendAtEnd, d->m_extendMode == d->ExtendByLine );
  5430. if (d->m_selectionEnd == d->m_selectionStart && d->m_endOffset < d->m_startOffset)
  5431. d->m_doc
  5432. ->setSelection(d->m_selectionStart.handle(),d->m_endOffset,
  5433. d->m_selectionEnd.handle(),d->m_startOffset);
  5434. else if (d->m_startBeforeEnd)
  5435. d->m_doc
  5436. ->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
  5437. d->m_selectionEnd.handle(),d->m_endOffset);
  5438. else
  5439. d->m_doc
  5440. ->setSelection(d->m_selectionEnd.handle(),d->m_endOffset,
  5441. d->m_selectionStart.handle(),d->m_startOffset);
  5442. }
  5443. #ifndef KHTML_NO_CARET
  5444. d->m_view->placeCaret();
  5445. #endif
  5446. }
  5447. bool KHTMLPart::isExtendingSelection() const
  5448. {
  5449. // This is it, the whole detection. khtmlMousePressEvent only sets this
  5450. // on LMB or MMB, but never on RMB. As text selection doesn't work for MMB,
  5451. // it's sufficient to only rely on this flag to detect selection extension.
  5452. return d->m_bMousePressed;
  5453. }
  5454. #endif // KHTML_NO_SELECTION
  5455. void KHTMLPart::khtmlMouseMoveEvent( khtml::MouseMoveEvent *event )
  5456. {
  5457. TQMouseEvent *_mouse = event->qmouseEvent();
  5458. if( d->m_bRightMousePressed && parentPart() != 0 && d->m_bBackRightClick )
  5459. {
  5460. popupMenu( d->m_strSelectedURL );
  5461. d->m_strSelectedURL = d->m_strSelectedURLTarget = TQString();
  5462. d->m_bRightMousePressed = false;
  5463. }
  5464. DOM::DOMString url = event->url();
  5465. DOM::DOMString target = event->target();
  5466. DOM::Node innerNode = event->innerNode();
  5467. #ifndef QT_NO_DRAGANDDROP
  5468. if( d->m_bDnd && d->m_bMousePressed &&
  5469. ( (!d->m_strSelectedURL.isEmpty() && !isEditable())
  5470. || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) ) ) {
  5471. if ( ( d->m_dragStartPos - _mouse->pos() ).manhattanLength() <= KGlobalSettings::dndEventDelay() )
  5472. return;
  5473. TQPixmap pix;
  5474. HTMLImageElementImpl *img = 0L;
  5475. TQDragObject *drag = 0;
  5476. KURL u;
  5477. // tqDebug("****************** Event URL: %s", url.string().latin1());
  5478. // tqDebug("****************** Event Target: %s", target.string().latin1());
  5479. // Normal image...
  5480. if ( url.length() == 0 && innerNode.handle() && innerNode.handle()->id() == ID_IMG )
  5481. {
  5482. img = static_cast<HTMLImageElementImpl *>(innerNode.handle());
  5483. u = KURL( completeURL( khtml::parseURL(img->getAttribute(ATTR_SRC)).string() ) );
  5484. pix = KMimeType::mimeType("image/png")->pixmap(KIcon::Desktop);
  5485. }
  5486. else
  5487. {
  5488. // Text or image link...
  5489. u = completeURL( d->m_strSelectedURL );
  5490. pix = KMimeType::pixmapForURL(u, 0, KIcon::Desktop, KIcon::SizeMedium);
  5491. }
  5492. u.setPass(TQString());
  5493. KURLDrag* urlDrag = new KURLDrag( u, img ? 0 : d->m_view->viewport() );
  5494. if ( !d->m_referrer.isEmpty() )
  5495. urlDrag->metaData()["referrer"] = d->m_referrer;
  5496. if( img && img->complete()) {
  5497. KMultipleDrag *mdrag = new KMultipleDrag( d->m_view->viewport() );
  5498. mdrag->addDragObject( new TQImageDrag( img->currentImage(), 0L ) );
  5499. mdrag->addDragObject( urlDrag );
  5500. drag = mdrag;
  5501. }
  5502. else
  5503. drag = urlDrag;
  5504. if ( !pix.isNull() )
  5505. drag->setPixmap( pix );
  5506. stopAutoScroll();
  5507. if(drag)
  5508. drag->drag();
  5509. // when we finish our drag, we need to undo our mouse press
  5510. d->m_bMousePressed = false;
  5511. d->m_strSelectedURL = d->m_strSelectedURLTarget = TQString();
  5512. return;
  5513. }
  5514. #endif
  5515. // Not clicked -> mouse over stuff
  5516. if ( !d->m_bMousePressed )
  5517. {
  5518. // The mouse is over something
  5519. if ( url.length() )
  5520. {
  5521. bool shiftPressed = ( _mouse->state() & ShiftButton );
  5522. // Image map
  5523. if ( !innerNode.isNull() && innerNode.elementId() == ID_IMG )
  5524. {
  5525. HTMLImageElementImpl *i = static_cast<HTMLImageElementImpl *>(innerNode.handle());
  5526. if ( i && i->isServerMap() )
  5527. {
  5528. khtml::RenderObject *r = i->renderer();
  5529. if(r)
  5530. {
  5531. int absx, absy, vx, vy;
  5532. r->absolutePosition(absx, absy);
  5533. view()->contentsToViewport( absx, absy, vx, vy );
  5534. int x(_mouse->x() - vx), y(_mouse->y() - vy);
  5535. d->m_overURL = url.string() + TQString("?%1,%2").arg(x).arg(y);
  5536. d->m_overURLTarget = target.string();
  5537. overURL( d->m_overURL, target.string(), shiftPressed );
  5538. return;
  5539. }
  5540. }
  5541. }
  5542. // normal link
  5543. if ( d->m_overURL.isEmpty() || d->m_overURL != url || d->m_overURLTarget != target )
  5544. {
  5545. d->m_overURL = url.string();
  5546. d->m_overURLTarget = target.string();
  5547. overURL( d->m_overURL, target.string(), shiftPressed );
  5548. }
  5549. }
  5550. else // Not over a link...
  5551. {
  5552. // reset to "default statusbar text"
  5553. resetHoverText();
  5554. }
  5555. }
  5556. else {
  5557. #ifndef KHTML_NO_SELECTION
  5558. // selection stuff
  5559. if( d->m_bMousePressed && innerNode.handle() && innerNode.handle()->renderer() &&
  5560. ( (_mouse->state() & Qt::LeftButton) != 0 )) {
  5561. extendSelectionTo(event->x(), event->y(),
  5562. event->absX(), event->absY(), innerNode);
  5563. #else
  5564. if ( d->m_doc && d->m_view ) {
  5565. TQPoint diff( _mouse->globalPos() - d->m_dragLastPos );
  5566. if ( abs( diff.x() ) > 64 || abs( diff.y() ) > 64 ) {
  5567. d->m_view->scrollBy( -diff.x(), -diff.y() );
  5568. d->m_dragLastPos = _mouse->globalPos();
  5569. }
  5570. #endif
  5571. }
  5572. }
  5573. }
  5574. void KHTMLPart::khtmlMouseReleaseEvent( khtml::MouseReleaseEvent *event )
  5575. {
  5576. DOM::Node innerNode = event->innerNode();
  5577. d->m_mousePressNode = DOM::Node();
  5578. if ( d->m_bMousePressed ) {
  5579. setStatusBarText(TQString(), BarHoverText);
  5580. stopAutoScroll();
  5581. }
  5582. // Used to prevent mouseMoveEvent from initiating a drag before
  5583. // the mouse is pressed again.
  5584. d->m_bMousePressed = false;
  5585. TQMouseEvent *_mouse = event->qmouseEvent();
  5586. if ( _mouse->button() == Qt::RightButton && parentPart() != 0 && d->m_bBackRightClick )
  5587. {
  5588. d->m_bRightMousePressed = false;
  5589. KParts::BrowserInterface *tmp_iface = d->m_extension->browserInterface();
  5590. if( tmp_iface ) {
  5591. tmp_iface->callMethod( "goHistory(int)", -1 );
  5592. }
  5593. }
  5594. #ifndef QT_NO_CLIPBOARD
  5595. if ((d->m_guiProfile == BrowserViewGUI) && (_mouse->button() == Qt::MidButton) && (event->url().isNull())) {
  5596. kdDebug( 6050 ) << "KHTMLPart::khtmlMouseReleaseEvent() MMB shouldOpen="
  5597. << d->m_bOpenMiddleClick << endl;
  5598. if (d->m_bOpenMiddleClick) {
  5599. KHTMLPart *p = this;
  5600. while (p->parentPart()) p = p->parentPart();
  5601. p->d->m_extension->pasteRequest();
  5602. }
  5603. }
  5604. #endif
  5605. #ifndef KHTML_NO_SELECTION
  5606. // delete selection in case start and end position are at the same point
  5607. if(d->m_selectionStart == d->m_selectionEnd && d->m_startOffset == d->m_endOffset) {
  5608. #ifndef KHTML_NO_CARET
  5609. d->m_extendAtEnd = true;
  5610. #else
  5611. d->m_selectionStart = 0;
  5612. d->m_selectionEnd = 0;
  5613. d->m_startOffset = 0;
  5614. d->m_endOffset = 0;
  5615. #endif
  5616. emitSelectionChanged();
  5617. } else {
  5618. // we have to get to know if end is before start or not...
  5619. // kdDebug(6000) << "rel: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << endl;
  5620. DOM::Node n = d->m_selectionStart;
  5621. d->m_startBeforeEnd = false;
  5622. if( d->m_selectionStart == d->m_selectionEnd ) {
  5623. if( d->m_startOffset < d->m_endOffset )
  5624. d->m_startBeforeEnd = true;
  5625. } else {
  5626. #if 0
  5627. while(!n.isNull()) {
  5628. if(n == d->m_selectionEnd) {
  5629. d->m_startBeforeEnd = true;
  5630. break;
  5631. }
  5632. DOM::Node next = n.firstChild();
  5633. if(next.isNull()) next = n.nextSibling();
  5634. while( next.isNull() && !n.parentNode().isNull() ) {
  5635. n = n.parentNode();
  5636. next = n.nextSibling();
  5637. }
  5638. n = next;
  5639. }
  5640. #else
  5641. // shouldn't be null but it can happen with dynamic updating of nodes
  5642. if (d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() ||
  5643. !d->m_selectionStart.handle()->renderer() ||
  5644. !d->m_selectionEnd.handle()->renderer()) return;
  5645. d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
  5646. d->m_selectionStart.handle(), d->m_startOffset,
  5647. d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
  5648. #endif
  5649. }
  5650. if(!d->m_startBeforeEnd)
  5651. {
  5652. DOM::Node tmpNode = d->m_selectionStart;
  5653. int tmpOffset = d->m_startOffset;
  5654. d->m_selectionStart = d->m_selectionEnd;
  5655. d->m_startOffset = d->m_endOffset;
  5656. d->m_selectionEnd = tmpNode;
  5657. d->m_endOffset = tmpOffset;
  5658. d->m_startBeforeEnd = true;
  5659. d->m_extendAtEnd = !d->m_extendAtEnd;
  5660. }
  5661. #ifndef KHTML_NO_CARET
  5662. bool v = d->m_view->placeCaret();
  5663. emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
  5664. #endif
  5665. // get selected text and paste to the clipboard
  5666. #ifndef QT_NO_CLIPBOARD
  5667. TQString text = selectedText();
  5668. text.replace(TQChar(0xa0), ' ');
  5669. disconnect( kapp->clipboard(), TQT_SIGNAL( selectionChanged()), this, TQT_SLOT( slotClearSelection()));
  5670. kapp->clipboard()->setText(text,TQClipboard::Selection);
  5671. connect( kapp->clipboard(), TQT_SIGNAL( selectionChanged()), TQT_SLOT( slotClearSelection()));
  5672. #endif
  5673. //kdDebug( 6000 ) << "selectedText = " << text << endl;
  5674. emitSelectionChanged();
  5675. //kdDebug(6000) << "rel2: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << "), caretOfs " << d->caretOffset() << endl;
  5676. }
  5677. #endif
  5678. d->m_initialNode = 0; // don't hold nodes longer than necessary
  5679. d->m_initialOffset = 0;
  5680. }
  5681. void KHTMLPart::khtmlDrawContentsEvent( khtml::DrawContentsEvent * )
  5682. {
  5683. }
  5684. void KHTMLPart::guiActivateEvent( KParts::GUIActivateEvent *event )
  5685. {
  5686. if ( event->activated() )
  5687. {
  5688. emitSelectionChanged();
  5689. emit d->m_extension->enableAction( "print", d->m_doc != 0 );
  5690. if ( !d->m_settings->autoLoadImages() && d->m_paLoadImages )
  5691. {
  5692. TQPtrList<KAction> lst;
  5693. lst.append( d->m_paLoadImages );
  5694. plugActionList( "loadImages", lst );
  5695. }
  5696. }
  5697. }
  5698. void KHTMLPart::slotPrintFrame()
  5699. {
  5700. if ( d->m_frames.count() == 0 )
  5701. return;
  5702. KParts::ReadOnlyPart *frame = currentFrame();
  5703. if (!frame)
  5704. return;
  5705. KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject( frame );
  5706. if ( !ext )
  5707. return;
  5708. TQMetaObject *mo = ext->metaObject();
  5709. int idx = mo->findSlot( "print()", true );
  5710. if ( idx >= 0 ) {
  5711. TQUObject o[ 1 ];
  5712. ext->tqt_invoke( idx, o );
  5713. }
  5714. }
  5715. void KHTMLPart::slotSelectAll()
  5716. {
  5717. KParts::ReadOnlyPart *part = currentFrame();
  5718. if (part && part->inherits("KHTMLPart"))
  5719. static_cast<KHTMLPart *>(part)->selectAll();
  5720. }
  5721. void KHTMLPart::startAutoScroll()
  5722. {
  5723. connect(&d->m_scrollTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( slotAutoScroll() ));
  5724. d->m_scrollTimer.start(100, false);
  5725. }
  5726. void KHTMLPart::stopAutoScroll()
  5727. {
  5728. disconnect(&d->m_scrollTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( slotAutoScroll() ));
  5729. if (d->m_scrollTimer.isActive())
  5730. d->m_scrollTimer.stop();
  5731. }
  5732. void KHTMLPart::slotAutoScroll()
  5733. {
  5734. if (d->m_view)
  5735. d->m_view->doAutoScroll();
  5736. else
  5737. stopAutoScroll(); // Safety
  5738. }
  5739. void KHTMLPart::runAdFilter()
  5740. {
  5741. if ( parentPart() )
  5742. parentPart()->runAdFilter();
  5743. if ( !d->m_doc )
  5744. return;
  5745. TQPtrDictIterator<khtml::CachedObject> it( d->m_doc->docLoader()->m_docObjects );
  5746. for ( ; it.current(); ++it )
  5747. if ( it.current()->type() == khtml::CachedObject::Image ) {
  5748. khtml::CachedImage *image = static_cast<khtml::CachedImage *>(it.current());
  5749. bool wasBlocked = image->m_wasBlocked;
  5750. image->m_wasBlocked = KHTMLFactory::defaultHTMLSettings()->isAdFiltered( d->m_doc->completeURL( (*it).url().string() ) );
  5751. if ( image->m_wasBlocked != wasBlocked )
  5752. image->do_notify(image->pixmap(), image->valid_rect());
  5753. }
  5754. if ( KHTMLFactory::defaultHTMLSettings()->isHideAdsEnabled() ) {
  5755. for ( NodeImpl *nextNode, *node = d->m_doc; node; node = nextNode ) {
  5756. // We might be deleting 'node' shortly.
  5757. nextNode = node->traverseNextNode();
  5758. if ( node->id() == ID_IMG ||
  5759. node->id() == ID_IFRAME ||
  5760. (node->id() == ID_INPUT && static_cast<HTMLInputElementImpl *>(node)->inputType() == HTMLInputElementImpl::IMAGE ))
  5761. {
  5762. if ( KHTMLFactory::defaultHTMLSettings()->isAdFiltered( d->m_doc->completeURL( static_cast<ElementImpl *>(node)->getAttribute(ATTR_SRC).string() ) ) )
  5763. {
  5764. // We found an IMG, IFRAME or INPUT (of type IMAGE) matching a filter.
  5765. node->ref();
  5766. NodeImpl *parent = node->parent();
  5767. if( parent )
  5768. {
  5769. int exception = 0;
  5770. parent->removeChild(node, exception);
  5771. }
  5772. node->deref();
  5773. }
  5774. }
  5775. }
  5776. }
  5777. }
  5778. void KHTMLPart::selectAll()
  5779. {
  5780. if (!d->m_doc) return;
  5781. NodeImpl *first;
  5782. if (d->m_doc->isHTMLDocument())
  5783. first = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
  5784. else
  5785. first = d->m_doc;
  5786. NodeImpl *next;
  5787. // Look for first text/cdata node that has a renderer,
  5788. // or first childless replaced element
  5789. while ( first && !(first->renderer()
  5790. && ((first->nodeType() == Node::TEXT_NODE || first->nodeType() == Node::CDATA_SECTION_NODE)
  5791. || (first->renderer()->isReplaced() && !first->renderer()->firstChild()))))
  5792. {
  5793. next = first->firstChild();
  5794. if ( !next ) next = first->nextSibling();
  5795. while( first && !next )
  5796. {
  5797. first = first->parentNode();
  5798. if ( first )
  5799. next = first->nextSibling();
  5800. }
  5801. first = next;
  5802. }
  5803. NodeImpl *last;
  5804. if (d->m_doc->isHTMLDocument())
  5805. last = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
  5806. else
  5807. last = d->m_doc;
  5808. // Look for last text/cdata node that has a renderer,
  5809. // or last childless replaced element
  5810. // ### Instead of changing this loop, use findLastSelectableNode
  5811. // in render_table.cpp (LS)
  5812. while ( last && !(last->renderer()
  5813. && ((last->nodeType() == Node::TEXT_NODE || last->nodeType() == Node::CDATA_SECTION_NODE)
  5814. || (last->renderer()->isReplaced() && !last->renderer()->lastChild()))))
  5815. {
  5816. next = last->lastChild();
  5817. if ( !next ) next = last->previousSibling();
  5818. while ( last && !next )
  5819. {
  5820. last = last->parentNode();
  5821. if ( last )
  5822. next = last->previousSibling();
  5823. }
  5824. last = next;
  5825. }
  5826. if ( !first || !last )
  5827. return;
  5828. Q_ASSERT(first->renderer());
  5829. Q_ASSERT(last->renderer());
  5830. d->m_selectionStart = first;
  5831. d->m_startOffset = 0;
  5832. d->m_selectionEnd = last;
  5833. d->m_endOffset = last->nodeValue().length();
  5834. d->m_startBeforeEnd = true;
  5835. d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
  5836. d->m_selectionEnd.handle(), d->m_endOffset );
  5837. emitSelectionChanged();
  5838. }
  5839. bool KHTMLPart::checkLinkSecurity(const KURL &linkURL,const TQString &message, const TQString &button)
  5840. {
  5841. bool linkAllowed = true;
  5842. if ( d->m_doc )
  5843. linkAllowed = kapp && kapp->authorizeURLAction("redirect", url(), linkURL);
  5844. if ( !linkAllowed ) {
  5845. khtml::Tokenizer *tokenizer = d->m_doc->tokenizer();
  5846. if (tokenizer)
  5847. tokenizer->setOnHold(true);
  5848. int response = KMessageBox::Cancel;
  5849. if (!message.isEmpty())
  5850. {
  5851. response = KMessageBox::warningContinueCancel( 0,
  5852. message.arg(linkURL.htmlURL()),
  5853. i18n( "Security Warning" ),
  5854. button);
  5855. }
  5856. else
  5857. {
  5858. KMessageBox::error( 0,
  5859. i18n( "<qt>Access by untrusted page to<BR><B>%1</B><BR> denied.").arg(linkURL.htmlURL()),
  5860. i18n( "Security Alert" ));
  5861. }
  5862. if (tokenizer)
  5863. tokenizer->setOnHold(false);
  5864. return (response==KMessageBox::Continue);
  5865. }
  5866. return true;
  5867. }
  5868. void KHTMLPart::slotPartRemoved( KParts::Part *part )
  5869. {
  5870. // kdDebug(6050) << "KHTMLPart::slotPartRemoved " << part << endl;
  5871. if ( part == d->m_activeFrame )
  5872. {
  5873. d->m_activeFrame = 0L;
  5874. if ( !part->inherits( "KHTMLPart" ) )
  5875. {
  5876. if (factory()) {
  5877. factory()->removeClient( part );
  5878. }
  5879. if (childClients()->containsRef(part)) {
  5880. removeChildClient( part );
  5881. }
  5882. }
  5883. }
  5884. }
  5885. void KHTMLPart::slotActiveFrameChanged( KParts::Part *part )
  5886. {
  5887. // kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged this=" << this << "part=" << part << endl;
  5888. if ( part == this )
  5889. {
  5890. kdError(6050) << "strange error! we activated ourselves" << endl;
  5891. assert( false );
  5892. return;
  5893. }
  5894. // kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged d->m_activeFrame=" << d->m_activeFrame << endl;
  5895. if ( d->m_activeFrame && d->m_activeFrame->widget() && d->m_activeFrame->widget()->inherits( TQFRAME_OBJECT_NAME_STRING ) )
  5896. {
  5897. TQFrame *frame = static_cast<TQFrame *>( d->m_activeFrame->widget() );
  5898. if (frame->frameStyle() != TQFrame::NoFrame)
  5899. {
  5900. frame->setFrameStyle( TQFrame::StyledPanel | TQFrame::Sunken);
  5901. frame->repaint();
  5902. }
  5903. }
  5904. if( d->m_activeFrame && !d->m_activeFrame->inherits( "KHTMLPart" ) )
  5905. {
  5906. if (factory()) {
  5907. factory()->removeClient( d->m_activeFrame );
  5908. }
  5909. removeChildClient( d->m_activeFrame );
  5910. }
  5911. if( part && !part->inherits( "KHTMLPart" ) )
  5912. {
  5913. if (factory()) {
  5914. factory()->addClient( part );
  5915. }
  5916. insertChildClient( part );
  5917. }
  5918. d->m_activeFrame = part;
  5919. if ( d->m_activeFrame && d->m_activeFrame->widget()->inherits( TQFRAME_OBJECT_NAME_STRING ) )
  5920. {
  5921. TQFrame *frame = static_cast<TQFrame *>( d->m_activeFrame->widget() );
  5922. if (frame->frameStyle() != TQFrame::NoFrame)
  5923. {
  5924. frame->setFrameStyle( TQFrame::StyledPanel | TQFrame::Plain);
  5925. frame->repaint();
  5926. }
  5927. kdDebug(6050) << "new active frame " << d->m_activeFrame << endl;
  5928. }
  5929. updateActions();
  5930. // (note: childObject returns 0 if the argument is 0)
  5931. d->m_extension->setExtensionProxy( KParts::BrowserExtension::childObject( d->m_activeFrame ) );
  5932. }
  5933. void KHTMLPart::setActiveNode(const DOM::Node &node)
  5934. {
  5935. if (!d->m_doc || !d->m_view)
  5936. return;
  5937. // Set the document's active node
  5938. d->m_doc->setFocusNode(node.handle());
  5939. // Scroll the view if necessary to ensure that the new focus node is visible
  5940. TQRect rect = node.handle()->getRect();
  5941. d->m_view->ensureVisible(rect.right(), rect.bottom());
  5942. d->m_view->ensureVisible(rect.left(), rect.top());
  5943. }
  5944. DOM::Node KHTMLPart::activeNode() const
  5945. {
  5946. return DOM::Node(d->m_doc?d->m_doc->focusNode():0);
  5947. }
  5948. DOM::EventListener *KHTMLPart::createHTMLEventListener( TQString code, TQString name, NodeImpl* node )
  5949. {
  5950. KJSProxy *proxy = jScript();
  5951. if (!proxy)
  5952. return 0;
  5953. return proxy->createHTMLEventHandler( m_url.url(), name, code, node );
  5954. }
  5955. KHTMLPart *KHTMLPart::opener()
  5956. {
  5957. return d->m_opener;
  5958. }
  5959. void KHTMLPart::setOpener(KHTMLPart *_opener)
  5960. {
  5961. d->m_opener = _opener;
  5962. }
  5963. bool KHTMLPart::openedByJS()
  5964. {
  5965. return d->m_openedByJS;
  5966. }
  5967. void KHTMLPart::setOpenedByJS(bool _openedByJS)
  5968. {
  5969. d->m_openedByJS = _openedByJS;
  5970. }
  5971. void KHTMLPart::preloadStyleSheet(const TQString &url, const TQString &stylesheet)
  5972. {
  5973. khtml::Cache::preloadStyleSheet(url, stylesheet);
  5974. }
  5975. void KHTMLPart::preloadScript(const TQString &url, const TQString &script)
  5976. {
  5977. khtml::Cache::preloadScript(url, script);
  5978. }
  5979. TQCString KHTMLPart::dcopObjectId() const
  5980. {
  5981. TQCString id;
  5982. id.sprintf("html-widget%d", d->m_dcop_counter);
  5983. return id;
  5984. }
  5985. long KHTMLPart::cacheId() const
  5986. {
  5987. return d->m_cacheId;
  5988. }
  5989. bool KHTMLPart::restored() const
  5990. {
  5991. return d->m_restored;
  5992. }
  5993. bool KHTMLPart::pluginPageQuestionAsked(const TQString& mimetype) const
  5994. {
  5995. // parentPart() should be const!
  5996. KHTMLPart* parent = const_cast<KHTMLPart *>(this)->parentPart();
  5997. if ( parent )
  5998. return parent->pluginPageQuestionAsked(mimetype);
  5999. return d->m_pluginPageQuestionAsked.contains(mimetype);
  6000. }
  6001. void KHTMLPart::setPluginPageQuestionAsked(const TQString& mimetype)
  6002. {
  6003. if ( parentPart() )
  6004. parentPart()->setPluginPageQuestionAsked(mimetype);
  6005. d->m_pluginPageQuestionAsked.append(mimetype);
  6006. }
  6007. void KHTMLPart::slotAutomaticDetectionLanguage( int _id )
  6008. {
  6009. d->m_automaticDetection->setItemChecked( _id, true );
  6010. switch ( _id ) {
  6011. case 0 :
  6012. d->m_autoDetectLanguage = khtml::Decoder::SemiautomaticDetection;
  6013. break;
  6014. case 1 :
  6015. d->m_autoDetectLanguage = khtml::Decoder::Arabic;
  6016. break;
  6017. case 2 :
  6018. d->m_autoDetectLanguage = khtml::Decoder::Baltic;
  6019. break;
  6020. case 3 :
  6021. d->m_autoDetectLanguage = khtml::Decoder::CentralEuropean;
  6022. break;
  6023. case 4 :
  6024. d->m_autoDetectLanguage = khtml::Decoder::Chinese;
  6025. break;
  6026. case 5 :
  6027. d->m_autoDetectLanguage = khtml::Decoder::Greek;
  6028. break;
  6029. case 6 :
  6030. d->m_autoDetectLanguage = khtml::Decoder::Hebrew;
  6031. break;
  6032. case 7 :
  6033. d->m_autoDetectLanguage = khtml::Decoder::Japanese;
  6034. break;
  6035. case 8 :
  6036. d->m_autoDetectLanguage = khtml::Decoder::Korean;
  6037. break;
  6038. case 9 :
  6039. d->m_autoDetectLanguage = khtml::Decoder::Russian;
  6040. break;
  6041. case 10 :
  6042. d->m_autoDetectLanguage = khtml::Decoder::Thai;
  6043. break;
  6044. case 11 :
  6045. d->m_autoDetectLanguage = khtml::Decoder::Turkish;
  6046. break;
  6047. case 12 :
  6048. d->m_autoDetectLanguage = khtml::Decoder::Ukrainian;
  6049. break;
  6050. case 13 :
  6051. d->m_autoDetectLanguage = khtml::Decoder::Unicode;
  6052. break;
  6053. case 14 :
  6054. d->m_autoDetectLanguage = khtml::Decoder::WesternEuropean;
  6055. break;
  6056. default :
  6057. d->m_autoDetectLanguage = khtml::Decoder::SemiautomaticDetection;
  6058. break;
  6059. }
  6060. for ( int i = 0; i <= 14; ++i ) {
  6061. if ( i != _id )
  6062. d->m_automaticDetection->setItemChecked( i, false );
  6063. }
  6064. d->m_paSetEncoding->popupMenu()->setItemChecked( 0, true );
  6065. setEncoding( TQString(), false );
  6066. if( d->m_manualDetection )
  6067. d->m_manualDetection->setCurrentItem( -1 );
  6068. d->m_paSetEncoding->popupMenu()->setItemChecked( d->m_paSetEncoding->popupMenu()->idAt( 2 ), false );
  6069. }
  6070. khtml::Decoder *KHTMLPart::createDecoder()
  6071. {
  6072. khtml::Decoder *dec = new khtml::Decoder();
  6073. if( !d->m_encoding.isNull() )
  6074. dec->setEncoding( d->m_encoding.latin1(),
  6075. d->m_haveEncoding ? khtml::Decoder::UserChosenEncoding : khtml::Decoder::EncodingFromHTTPHeader);
  6076. else {
  6077. // Inherit the default encoding from the parent frame if there is one.
  6078. const char *defaultEncoding = (parentPart() && parentPart()->d->m_decoder)
  6079. ? parentPart()->d->m_decoder->encoding() : settings()->encoding().latin1();
  6080. dec->setEncoding(defaultEncoding, khtml::Decoder::DefaultEncoding);
  6081. }
  6082. #ifdef APPLE_CHANGES
  6083. if (d->m_doc)
  6084. d->m_doc->setDecoder(d->m_decoder);
  6085. #endif
  6086. dec->setAutoDetectLanguage( d->m_autoDetectLanguage );
  6087. return dec;
  6088. }
  6089. void KHTMLPart::emitCaretPositionChanged(const DOM::Node &node, long offset) {
  6090. emit caretPositionChanged(node, offset);
  6091. }
  6092. void KHTMLPart::restoreScrollPosition()
  6093. {
  6094. KParts::URLArgs args = d->m_extension->urlArgs();
  6095. if ( m_url.hasRef() && !d->m_restoreScrollPosition && !args.reload) {
  6096. if ( !d->m_doc || !d->m_doc->parsing() )
  6097. disconnect(d->m_view, TQT_SIGNAL(finishedLayout()), this, TQT_SLOT(restoreScrollPosition()));
  6098. if ( !gotoAnchor(m_url.encodedHtmlRef()) )
  6099. gotoAnchor(m_url.htmlRef());
  6100. return;
  6101. }
  6102. // Check whether the viewport has become large enough to encompass the stored
  6103. // offsets. If the document has been fully loaded, force the new coordinates,
  6104. // even if the canvas is too short (can happen when user resizes the window
  6105. // during loading).
  6106. if (d->m_view->contentsHeight() - d->m_view->visibleHeight() >= args.yOffset
  6107. || d->m_bComplete) {
  6108. d->m_view->setContentsPos(args.xOffset, args.yOffset);
  6109. disconnect(d->m_view, TQT_SIGNAL(finishedLayout()), this, TQT_SLOT(restoreScrollPosition()));
  6110. }
  6111. }
  6112. void KHTMLPart::openWallet(DOM::HTMLFormElementImpl *form)
  6113. {
  6114. #ifndef KHTML_NO_WALLET
  6115. KHTMLPart *p;
  6116. for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
  6117. }
  6118. if (p) {
  6119. p->openWallet(form);
  6120. return;
  6121. }
  6122. if (onlyLocalReferences()) { // avoid triggering on local apps, thumbnails
  6123. return;
  6124. }
  6125. if (d->m_wallet) {
  6126. if (d->m_bWalletOpened) {
  6127. if (d->m_wallet->isOpen()) {
  6128. form->walletOpened(d->m_wallet);
  6129. return;
  6130. }
  6131. d->m_wallet->deleteLater();
  6132. d->m_wallet = 0L;
  6133. d->m_bWalletOpened = false;
  6134. }
  6135. }
  6136. if (!d->m_wq) {
  6137. KWallet::Wallet *wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0, KWallet::Wallet::Asynchronous);
  6138. d->m_wq = new KHTMLWalletQueue(this);
  6139. d->m_wq->wallet = wallet;
  6140. connect(wallet, TQT_SIGNAL(walletOpened(bool)), d->m_wq, TQT_SLOT(walletOpened(bool)));
  6141. connect(d->m_wq, TQT_SIGNAL(walletOpened(KWallet::Wallet*)), this, TQT_SLOT(walletOpened(KWallet::Wallet*)));
  6142. }
  6143. assert(form);
  6144. d->m_wq->callers.append(KHTMLWalletQueue::Caller(form, form->getDocument()));
  6145. #endif // KHTML_NO_WALLET
  6146. }
  6147. void KHTMLPart::saveToWallet(const TQString& key, const TQMap<TQString,TQString>& data)
  6148. {
  6149. #ifndef KHTML_NO_WALLET
  6150. KHTMLPart *p;
  6151. for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
  6152. }
  6153. if (p) {
  6154. p->saveToWallet(key, data);
  6155. return;
  6156. }
  6157. if (d->m_wallet) {
  6158. if (d->m_bWalletOpened) {
  6159. if (d->m_wallet->isOpen()) {
  6160. if (!d->m_wallet->hasFolder(KWallet::Wallet::FormDataFolder())) {
  6161. d->m_wallet->createFolder(KWallet::Wallet::FormDataFolder());
  6162. }
  6163. d->m_wallet->setFolder(KWallet::Wallet::FormDataFolder());
  6164. d->m_wallet->writeMap(key, data);
  6165. return;
  6166. }
  6167. d->m_wallet->deleteLater();
  6168. d->m_wallet = 0L;
  6169. d->m_bWalletOpened = false;
  6170. }
  6171. }
  6172. if (!d->m_wq) {
  6173. KWallet::Wallet *wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0, KWallet::Wallet::Asynchronous);
  6174. d->m_wq = new KHTMLWalletQueue(this);
  6175. d->m_wq->wallet = wallet;
  6176. connect(wallet, TQT_SIGNAL(walletOpened(bool)), d->m_wq, TQT_SLOT(walletOpened(bool)));
  6177. connect(d->m_wq, TQT_SIGNAL(walletOpened(KWallet::Wallet*)), this, TQT_SLOT(walletOpened(KWallet::Wallet*)));
  6178. }
  6179. d->m_wq->savers.append(qMakePair(key, data));
  6180. #endif // KHTML_NO_WALLET
  6181. }
  6182. void KHTMLPart::dequeueWallet(DOM::HTMLFormElementImpl *form) {
  6183. #ifndef KHTML_NO_WALLET
  6184. KHTMLPart *p;
  6185. for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
  6186. }
  6187. if (p) {
  6188. p->dequeueWallet(form);
  6189. return;
  6190. }
  6191. if (d->m_wq) {
  6192. d->m_wq->callers.remove(KHTMLWalletQueue::Caller(form, form->getDocument()));
  6193. }
  6194. #endif // KHTML_NO_WALLET
  6195. }
  6196. void KHTMLPart::walletOpened(KWallet::Wallet *wallet) {
  6197. #ifndef KHTML_NO_WALLET
  6198. assert(!d->m_wallet);
  6199. assert(d->m_wq);
  6200. d->m_wq->deleteLater(); // safe?
  6201. d->m_wq = 0L;
  6202. if (!wallet) {
  6203. d->m_bWalletOpened = false;
  6204. return;
  6205. }
  6206. d->m_wallet = wallet;
  6207. d->m_bWalletOpened = true;
  6208. connect(d->m_wallet, TQT_SIGNAL(walletClosed()), TQT_SLOT(slotWalletClosed()));
  6209. if (!d->m_statusBarWalletLabel) {
  6210. d->m_statusBarWalletLabel = new KURLLabel(d->m_statusBarExtension->statusBar());
  6211. d->m_statusBarWalletLabel->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small));
  6212. d->m_statusBarWalletLabel->setSizePolicy(TQSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Fixed));
  6213. d->m_statusBarWalletLabel->setUseCursor(false);
  6214. d->m_statusBarExtension->addStatusBarItem(d->m_statusBarWalletLabel, 0, false);
  6215. d->m_statusBarWalletLabel->setPixmap(SmallIcon("wallet_open", instance()));
  6216. connect(d->m_statusBarWalletLabel, TQT_SIGNAL(leftClickedURL()), TQT_SLOT(launchWalletManager()));
  6217. connect(d->m_statusBarWalletLabel, TQT_SIGNAL(rightClickedURL()), TQT_SLOT(walletMenu()));
  6218. } else {
  6219. TQToolTip::remove(d->m_statusBarWalletLabel);
  6220. }
  6221. TQToolTip::add(d->m_statusBarWalletLabel, i18n("The wallet '%1' is open and being used for form data and passwords.").arg(KWallet::Wallet::NetworkWallet()));
  6222. #endif // KHTML_NO_WALLET
  6223. }
  6224. KWallet::Wallet *KHTMLPart::wallet()
  6225. {
  6226. #ifndef KHTML_NO_WALLET
  6227. KHTMLPart *p;
  6228. for (p = parentPart(); p && p->parentPart(); p = p->parentPart())
  6229. ;
  6230. if (p)
  6231. return p->wallet();
  6232. #endif // KHTML_NO_WALLET
  6233. return d->m_wallet;
  6234. }
  6235. void KHTMLPart::slotWalletClosed()
  6236. {
  6237. #ifndef KHTML_NO_WALLET
  6238. if (d->m_wallet) {
  6239. d->m_wallet->deleteLater();
  6240. d->m_wallet = 0L;
  6241. }
  6242. d->m_bWalletOpened = false;
  6243. if (d->m_statusBarWalletLabel) {
  6244. d->m_statusBarExtension->removeStatusBarItem(d->m_statusBarWalletLabel);
  6245. delete d->m_statusBarWalletLabel;
  6246. d->m_statusBarWalletLabel = 0L;
  6247. }
  6248. #endif // KHTML_NO_WALLET
  6249. }
  6250. void KHTMLPart::launchWalletManager()
  6251. {
  6252. #ifndef KHTML_NO_WALLET
  6253. if (!DCOPClient::mainClient()->isApplicationRegistered("kwalletmanager")) {
  6254. KApplication::startServiceByDesktopName("kwalletmanager_show");
  6255. } else {
  6256. DCOPRef r("kwalletmanager", "kwalletmanager-mainwindow#1");
  6257. r.send("show");
  6258. r.send("raise");
  6259. }
  6260. #endif // KHTML_NO_WALLET
  6261. }
  6262. void KHTMLPart::walletMenu()
  6263. {
  6264. #ifndef KHTML_NO_WALLET
  6265. KPopupMenu *m = new KPopupMenu(0L);
  6266. m->insertItem(i18n("&Close Wallet"), this, TQT_SLOT(slotWalletClosed()));
  6267. m->popup(TQCursor::pos());
  6268. #endif // KHTML_NO_WALLET
  6269. }
  6270. void KHTMLPart::slotToggleCaretMode()
  6271. {
  6272. setCaretMode(d->m_paToggleCaretMode->isChecked());
  6273. }
  6274. void KHTMLPart::setFormNotification(KHTMLPart::FormNotification fn) {
  6275. d->m_formNotification = fn;
  6276. }
  6277. KHTMLPart::FormNotification KHTMLPart::formNotification() const {
  6278. return d->m_formNotification;
  6279. }
  6280. KURL KHTMLPart::toplevelURL()
  6281. {
  6282. KHTMLPart* part = this;
  6283. while (part->parentPart())
  6284. part = part->parentPart();
  6285. if (!part)
  6286. return KURL();
  6287. return part->url();
  6288. }
  6289. bool KHTMLPart::isModified() const
  6290. {
  6291. if ( !d->m_doc )
  6292. return false;
  6293. return d->m_doc->unsubmittedFormChanges();
  6294. }
  6295. void KHTMLPart::setDebugScript( bool enable )
  6296. {
  6297. unplugActionList( "debugScriptList" );
  6298. if ( enable ) {
  6299. if (!d->m_paDebugScript) {
  6300. d->m_paDebugScript = new KAction( i18n( "JavaScript &Debugger" ), 0, this, TQT_SLOT( slotDebugScript() ), actionCollection(), "debugScript" );
  6301. }
  6302. d->m_paDebugScript->setEnabled( d->m_frame ? d->m_frame->m_jscript : 0L );
  6303. TQPtrList<KAction> lst;
  6304. lst.append( d->m_paDebugScript );
  6305. plugActionList( "debugScriptList", lst );
  6306. }
  6307. d->m_bJScriptDebugEnabled = enable;
  6308. }
  6309. void KHTMLPart::setSuppressedPopupIndicator( bool enable )
  6310. {
  6311. setSuppressedPopupIndicator( enable, 0 );
  6312. }
  6313. void KHTMLPart::setSuppressedPopupIndicator( bool enable, KHTMLPart *originPart )
  6314. {
  6315. if ( parentPart() ) {
  6316. parentPart()->setSuppressedPopupIndicator( enable, originPart );
  6317. return;
  6318. }
  6319. if ( enable && originPart ) {
  6320. d->m_openableSuppressedPopups++;
  6321. if ( d->m_suppressedPopupOriginParts.findIndex( originPart ) == -1 )
  6322. d->m_suppressedPopupOriginParts.append( originPart );
  6323. }
  6324. if ( enable && !d->m_statusBarPopupLabel ) {
  6325. d->m_statusBarPopupLabel = new KURLLabel( d->m_statusBarExtension->statusBar() );
  6326. d->m_statusBarPopupLabel->setFixedHeight( instance()->iconLoader()->currentSize( KIcon::Small) );
  6327. d->m_statusBarPopupLabel->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ));
  6328. d->m_statusBarPopupLabel->setUseCursor( false );
  6329. d->m_statusBarExtension->addStatusBarItem( d->m_statusBarPopupLabel, 0, false );
  6330. d->m_statusBarPopupLabel->setPixmap( SmallIcon( "window_suppressed", instance() ) );
  6331. TQToolTip::add( d->m_statusBarPopupLabel, i18n("This page was prevented from opening a new window via JavaScript." ) );
  6332. connect(d->m_statusBarPopupLabel, TQT_SIGNAL(leftClickedURL()), TQT_SLOT(suppressedPopupMenu()));
  6333. if (d->m_settings->jsPopupBlockerPassivePopup()) {
  6334. TQPixmap px;
  6335. px = MainBarIcon( "window_suppressed" );
  6336. 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);
  6337. }
  6338. } else if ( !enable && d->m_statusBarPopupLabel ) {
  6339. TQToolTip::remove( d->m_statusBarPopupLabel );
  6340. d->m_statusBarExtension->removeStatusBarItem( d->m_statusBarPopupLabel );
  6341. delete d->m_statusBarPopupLabel;
  6342. d->m_statusBarPopupLabel = 0L;
  6343. }
  6344. }
  6345. void KHTMLPart::suppressedPopupMenu() {
  6346. KPopupMenu *m = new KPopupMenu(0L);
  6347. m->setCheckable(true);
  6348. if ( d->m_openableSuppressedPopups )
  6349. m->insertItem(i18n("&Show Blocked Popup Window","Show %n Blocked Popup Windows", d->m_openableSuppressedPopups), this, TQT_SLOT(showSuppressedPopups()));
  6350. m->insertItem(i18n("Show Blocked Window Passive Popup &Notification"), this, TQT_SLOT(togglePopupPassivePopup()),0,57);
  6351. m->setItemChecked(57,d->m_settings->jsPopupBlockerPassivePopup());
  6352. m->insertItem(i18n("&Configure JavaScript New Window Policies..."), this, TQT_SLOT(launchJSConfigDialog()));
  6353. m->popup(TQCursor::pos());
  6354. }
  6355. void KHTMLPart::togglePopupPassivePopup() {
  6356. // Same hack as in disableJSErrorExtension()
  6357. d->m_settings->setJSPopupBlockerPassivePopup( !d->m_settings->jsPopupBlockerPassivePopup() );
  6358. DCOPClient::mainClient()->send("konqueror*", "KonquerorIface", "reparseConfiguration()", TQByteArray());
  6359. }
  6360. void KHTMLPart::showSuppressedPopups() {
  6361. for ( TQValueListIterator<TQGuardedPtr<KHTMLPart> > i = d->m_suppressedPopupOriginParts.begin();
  6362. i != d->m_suppressedPopupOriginParts.end(); ++i ) {
  6363. if (KHTMLPart* part = *i) {
  6364. KJS::Window *w = KJS::Window::retrieveWindow( part );
  6365. if (w) {
  6366. w->showSuppressedWindows();
  6367. w->forgetSuppressedWindows();
  6368. }
  6369. }
  6370. }
  6371. setSuppressedPopupIndicator( false );
  6372. d->m_openableSuppressedPopups = 0;
  6373. d->m_suppressedPopupOriginParts.clear();
  6374. }
  6375. // Extension to use for "view document source", "save as" etc.
  6376. // Using the right extension can help the viewer get into the right mode (#40496)
  6377. TQString KHTMLPart::defaultExtension() const
  6378. {
  6379. if ( !d->m_doc )
  6380. return ".html";
  6381. if ( !d->m_doc->isHTMLDocument() )
  6382. return ".xml";
  6383. return d->m_doc->htmlMode() == DOM::DocumentImpl::XHtml ? ".xhtml" : ".html";
  6384. }
  6385. bool KHTMLPart::inProgress() const
  6386. {
  6387. if (d->m_runningScripts || (d->m_doc && d->m_doc->parsing()))
  6388. return true;
  6389. // Any frame that hasn't completed yet ?
  6390. ConstFrameIt it = d->m_frames.begin();
  6391. const ConstFrameIt end = d->m_frames.end();
  6392. for (; it != end; ++it ) {
  6393. if ((*it)->m_run || !(*it)->m_bCompleted)
  6394. return true;
  6395. }
  6396. return d->m_submitForm || !d->m_redirectURL.isEmpty() || d->m_redirectionTimer.isActive() || d->m_job;
  6397. }
  6398. using namespace KParts;
  6399. #include "khtml_part.moc"
  6400. #include "khtmlpart_p.moc"