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