khtml Library API Documentation

khtml_part.cpp

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