khtml Library API Documentation

khtml_part.cpp

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