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