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