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