khtml Library API Documentation

khtml_part.cpp

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