khtml Library API Documentation

kjs_window.cpp

00001 // -*- c-basic-offset: 2 -*-
00002 /*
00003  *  This file is part of the KDE libraries
00004  *  Copyright (C) 2000-2003 Harri Porten (porten@kde.org)
00005  *  Copyright (C) 2001-2003 David Faure (faure@kde.org)
00006  *  Copyright (C) 2003 Apple Computer, Inc.
00007  *
00008  *  This library is free software; you can redistribute it and/or
00009  *  modify it under the terms of the GNU Library General Public
00010  *  License as published by the Free Software Foundation; either
00011  *  version 2 of the License, or (at your option) any later version.
00012  *
00013  *  This library is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  *  Library General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU Library General Public
00019  *  License along with this library; if not, write to the Free Software
00020  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  */
00022 #include "config.h"
00023 
00024 #include <qstylesheet.h>
00025 #include <qtimer.h>
00026 #include <qpaintdevicemetrics.h>
00027 #include <qapplication.h>
00028 #include <kdebug.h>
00029 #include <kmessagebox.h>
00030 #include <kinputdialog.h>
00031 #include <klocale.h>
00032 #include <kparts/browserinterface.h>
00033 #include <kwin.h>
00034 
00035 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00036 #include <kwinmodule.h> // schroder
00037 #endif
00038 
00039 #include <kbookmarkmanager.h>
00040 #include <kglobalsettings.h>
00041 #include <assert.h>
00042 #include <qstyle.h>
00043 #include <qobjectlist.h>
00044 #include <kstringhandler.h>
00045 
00046 #include "kjs_proxy.h"
00047 #include "kjs_window.h"
00048 #include "kjs_navigator.h"
00049 #include "kjs_mozilla.h"
00050 #include "kjs_html.h"
00051 #include "kjs_range.h"
00052 #include "kjs_traversal.h"
00053 #include "kjs_css.h"
00054 #include "kjs_events.h"
00055 #include "xmlhttprequest.h"
00056 #include "xmlserializer.h"
00057 
00058 #include "khtmlview.h"
00059 #include "khtml_part.h"
00060 #include "khtmlpart_p.h"
00061 #include "khtml_settings.h"
00062 #include "xml/dom2_eventsimpl.h"
00063 #include "xml/dom_docimpl.h"
00064 #include "misc/htmltags.h"
00065 #include "html/html_documentimpl.h"
00066 #include "rendering/render_frames.h"
00067 
00068 using namespace KJS;
00069 
00070 namespace KJS {
00071 
00072   class History : public ObjectImp {
00073     friend class HistoryFunc;
00074   public:
00075     History(ExecState *exec, KHTMLPart *p)
00076       : ObjectImp(exec->interpreter()->builtinObjectPrototype()), part(p) { }
00077     virtual Value get(ExecState *exec, const Identifier &propertyName) const;
00078     Value getValueProperty(ExecState *exec, int token) const;
00079     virtual const ClassInfo* classInfo() const { return &info; }
00080     static const ClassInfo info;
00081     enum { Back, Forward, Go, Length };
00082   private:
00083     QGuardedPtr<KHTMLPart> part;
00084   };
00085 
00086   class External : public ObjectImp {
00087     friend class ExternalFunc;
00088   public:
00089     External(ExecState *exec, KHTMLPart *p)
00090       : ObjectImp(exec->interpreter()->builtinObjectPrototype()), part(p) { }
00091     virtual Value get(ExecState *exec, const Identifier &propertyName) const;
00092     virtual const ClassInfo* classInfo() const { return &info; }
00093     static const ClassInfo info;
00094     enum { AddFavorite };
00095   private:
00096     QGuardedPtr<KHTMLPart> part;
00097   };
00098 
00099   class FrameArray : public ObjectImp {
00100   public:
00101     FrameArray(ExecState *exec, KHTMLPart *p)
00102       : ObjectImp(exec->interpreter()->builtinObjectPrototype()), part(p) { }
00103     virtual Value get(ExecState *exec, const Identifier &propertyName) const;
00104   private:
00105     QGuardedPtr<KHTMLPart> part;
00106   };
00107 
00108 #ifdef Q_WS_QWS
00109   class KonquerorFunc : public DOMFunction {
00110   public:
00111     KonquerorFunc(const Konqueror* k, const char* name)
00112       : DOMFunction(), konqueror(k), m_name(name) { }
00113     virtual Value tryCall(ExecState *exec, Object &thisObj, const List &args);
00114 
00115   private:
00116     const Konqueror* konqueror;
00117     QCString m_name;
00118   };
00119 #endif
00120 } // namespace KJS
00121 
00122 #include "kjs_window.lut.h"
00123 #include "rendering/render_replaced.h"
00124 
00126 
00127 // table for screen object
00128 /*
00129 @begin ScreenTable 7
00130   height        Screen::Height      DontEnum|ReadOnly
00131   width         Screen::Width       DontEnum|ReadOnly
00132   colorDepth    Screen::ColorDepth  DontEnum|ReadOnly
00133   pixelDepth    Screen::PixelDepth  DontEnum|ReadOnly
00134   availLeft     Screen::AvailLeft   DontEnum|ReadOnly
00135   availTop      Screen::AvailTop    DontEnum|ReadOnly
00136   availHeight   Screen::AvailHeight DontEnum|ReadOnly
00137   availWidth    Screen::AvailWidth  DontEnum|ReadOnly
00138 @end
00139 */
00140 
00141 const ClassInfo Screen::info = { "Screen", 0, &ScreenTable, 0 };
00142 
00143 // We set the object prototype so that toString is implemented
00144 Screen::Screen(ExecState *exec)
00145   : ObjectImp(exec->interpreter()->builtinObjectPrototype()) {}
00146 
00147 Value Screen::get(ExecState *exec, const Identifier &p) const
00148 {
00149 #ifdef KJS_VERBOSE
00150   kdDebug(6070) << "Screen::get " << p.qstring() << endl;
00151 #endif
00152   return lookupGetValue<Screen,ObjectImp>(exec,p,&ScreenTable,this);
00153 }
00154 
00155 Value Screen::getValueProperty(ExecState *exec, int token) const
00156 {
00157 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00158   KWinModule info(0, KWinModule::INFO_DESKTOP);
00159 #endif
00160   QWidget *thisWidget = Window::retrieveActive(exec)->part()->widget();
00161   QRect sg = KGlobalSettings::desktopGeometry(thisWidget);
00162 
00163   switch( token ) {
00164   case Height:
00165     return Number(sg.height());
00166   case Width:
00167     return Number(sg.width());
00168   case ColorDepth:
00169   case PixelDepth: {
00170     QPaintDeviceMetrics m(QApplication::desktop());
00171     return Number(m.depth());
00172   }
00173   case AvailLeft: {
00174 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00175     QRect clipped = info.workArea().intersect(sg);
00176     return Number(clipped.x()-sg.x());
00177 #else
00178     return Number(10);
00179 #endif
00180   }
00181   case AvailTop: {
00182 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00183     QRect clipped = info.workArea().intersect(sg);
00184     return Number(clipped.y()-sg.y());
00185 #else
00186     return Number(10);
00187 #endif
00188   }
00189   case AvailHeight: {
00190 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00191     QRect clipped = info.workArea().intersect(sg);
00192     return Number(clipped.height());
00193 #else
00194     return Number(100);
00195 #endif
00196   }
00197   case AvailWidth: {
00198 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00199     QRect clipped = info.workArea().intersect(sg);
00200     return Number(clipped.width());
00201 #else
00202     return Number(100);
00203 #endif
00204   }
00205   default:
00206     kdDebug(6070) << "WARNING: Screen::getValueProperty unhandled token " << token << endl;
00207     return Undefined();
00208   }
00209 }
00210 
00212 
00213 const ClassInfo Window::info = { "Window", 0, &WindowTable, 0 };
00214 
00215 /*
00216 @begin WindowTable 87
00217   closed    Window::Closed      DontDelete|ReadOnly
00218   crypto    Window::Crypto      DontDelete|ReadOnly
00219   defaultStatus Window::DefaultStatus   DontDelete
00220   defaultstatus Window::DefaultStatus   DontDelete
00221   status    Window::Status      DontDelete
00222   document  Window::Document    DontDelete|ReadOnly
00223   Node      Window::Node        DontDelete
00224   Event     Window::EventCtor   DontDelete
00225   Range     Window::Range       DontDelete
00226   NodeFilter    Window::NodeFilter  DontDelete
00227   DOMException  Window::DOMException    DontDelete
00228   CSSRule   Window::CSSRule     DontDelete
00229   frames    Window::Frames      DontDelete|ReadOnly
00230   history   Window::_History    DontDelete|ReadOnly
00231   external  Window::_External   DontDelete|ReadOnly
00232   event     Window::Event       DontDelete|ReadOnly
00233   innerHeight   Window::InnerHeight DontDelete|ReadOnly
00234   innerWidth    Window::InnerWidth  DontDelete|ReadOnly
00235   length    Window::Length      DontDelete|ReadOnly
00236   location  Window::_Location   DontDelete
00237   name      Window::Name        DontDelete
00238   navigator Window::_Navigator  DontDelete|ReadOnly
00239   clientInformation Window::ClientInformation   DontDelete|ReadOnly
00240   konqueror Window::_Konqueror  DontDelete|ReadOnly
00241   offscreenBuffering    Window::OffscreenBuffering  DontDelete|ReadOnly
00242   opener    Window::Opener      DontDelete|ReadOnly
00243   outerHeight   Window::OuterHeight DontDelete|ReadOnly
00244   outerWidth    Window::OuterWidth  DontDelete|ReadOnly
00245   pageXOffset   Window::PageXOffset DontDelete|ReadOnly
00246   pageYOffset   Window::PageYOffset DontDelete|ReadOnly
00247   parent    Window::Parent      DontDelete|ReadOnly
00248   personalbar   Window::Personalbar DontDelete|ReadOnly
00249   screenX   Window::ScreenX     DontDelete|ReadOnly
00250   screenY   Window::ScreenY     DontDelete|ReadOnly
00251   scrollbars    Window::Scrollbars  DontDelete|ReadOnly
00252   scroll    Window::Scroll      DontDelete|Function 2
00253   scrollBy  Window::ScrollBy    DontDelete|Function 2
00254   scrollTo  Window::ScrollTo    DontDelete|Function 2
00255   moveBy    Window::MoveBy      DontDelete|Function 2
00256   moveTo    Window::MoveTo      DontDelete|Function 2
00257   resizeBy  Window::ResizeBy    DontDelete|Function 2
00258   resizeTo  Window::ResizeTo    DontDelete|Function 2
00259   self      Window::Self        DontDelete|ReadOnly
00260   window    Window::_Window     DontDelete|ReadOnly
00261   top       Window::Top     DontDelete|ReadOnly
00262   screen    Window::_Screen     DontDelete|ReadOnly
00263   Image     Window::Image       DontDelete|ReadOnly
00264   Option    Window::Option      DontDelete|ReadOnly
00265   XMLHttpRequest Window::XMLHttpRequest DontDelete|ReadOnly
00266   XMLSerializer Window::XMLSerializer   DontDelete|ReadOnly
00267   alert     Window::Alert       DontDelete|Function 1
00268   confirm   Window::Confirm     DontDelete|Function 1
00269   prompt    Window::Prompt      DontDelete|Function 2
00270   open      Window::Open        DontDelete|Function 3
00271   setTimeout    Window::SetTimeout  DontDelete|Function 2
00272   clearTimeout  Window::ClearTimeout    DontDelete|Function 1
00273   focus     Window::Focus       DontDelete|Function 0
00274   blur      Window::Blur        DontDelete|Function 0
00275   close     Window::Close       DontDelete|Function 0
00276   setInterval   Window::SetInterval DontDelete|Function 2
00277   clearInterval Window::ClearInterval   DontDelete|Function 1
00278   captureEvents Window::CaptureEvents   DontDelete|Function 0
00279   releaseEvents Window::ReleaseEvents   DontDelete|Function 0
00280   print     Window::Print       DontDelete|Function 0
00281   addEventListener  Window::AddEventListener    DontDelete|Function 3
00282   removeEventListener   Window::RemoveEventListener DontDelete|Function 3
00283 # IE extension
00284   navigate  Window::Navigate    DontDelete|Function 1
00285 # Mozilla extension
00286   sidebar   Window::SideBar     DontDelete|ReadOnly
00287 
00288 # Warning, when adding a function to this object you need to add a case in Window::get
00289 
00290 # Event handlers
00291 # IE also has: onactivate, onbefore/afterprint, onbeforedeactivate/unload, oncontrolselect,
00292 # ondeactivate, onhelp, onmovestart/end, onresizestart/end, onscroll.
00293 # It doesn't have onabort, onchange, ondragdrop (but NS has that last one).
00294   onabort   Window::Onabort     DontDelete
00295   onblur    Window::Onblur      DontDelete
00296   onchange  Window::Onchange    DontDelete
00297   onclick   Window::Onclick     DontDelete
00298   ondblclick    Window::Ondblclick  DontDelete
00299   ondragdrop    Window::Ondragdrop  DontDelete
00300   onerror   Window::Onerror     DontDelete
00301   onfocus   Window::Onfocus     DontDelete
00302   onkeydown Window::Onkeydown   DontDelete
00303   onkeypress    Window::Onkeypress  DontDelete
00304   onkeyup   Window::Onkeyup     DontDelete
00305   onload    Window::Onload      DontDelete
00306   onmousedown   Window::Onmousedown DontDelete
00307   onmousemove   Window::Onmousemove DontDelete
00308   onmouseout    Window::Onmouseout  DontDelete
00309   onmouseover   Window::Onmouseover DontDelete
00310   onmouseup Window::Onmouseup   DontDelete
00311   onmove    Window::Onmove      DontDelete
00312   onreset   Window::Onreset     DontDelete
00313   onresize  Window::Onresize    DontDelete
00314   onselect  Window::Onselect    DontDelete
00315   onsubmit  Window::Onsubmit    DontDelete
00316   onunload  Window::Onunload    DontDelete
00317 @end
00318 */
00319 IMPLEMENT_PROTOFUNC_DOM(WindowFunc)
00320 
00321 Window::Window(khtml::ChildFrame *p)
00322   : ObjectImp(/*no proto*/), m_frame(p), screen(0), history(0), external(0), m_frames(0), loc(0), m_evt(0)
00323 {
00324   winq = new WindowQObject(this);
00325   //kdDebug(6070) << "Window::Window this=" << this << " part=" << m_part << " " << m_part->name() << endl;
00326 }
00327 
00328 Window::~Window()
00329 {
00330   delete winq;
00331 }
00332 
00333 Window *Window::retrieveWindow(KParts::ReadOnlyPart *p)
00334 {
00335   Object obj = Object::dynamicCast( retrieve( p ) );
00336 #ifndef NDEBUG
00337   // obj should never be null, except when javascript has been disabled in that part.
00338   KHTMLPart *part = ::qt_cast<KHTMLPart *>(p);
00339   if ( part && part->jScriptEnabled() )
00340   {
00341     assert( !obj.isNull() );
00342 #ifndef QWS
00343     assert( dynamic_cast<KJS::Window*>(obj.imp()) ); // type checking
00344 #endif
00345   }
00346 #endif
00347   if ( obj.isNull() ) // JS disabled
00348     return 0;
00349   return static_cast<KJS::Window*>(obj.imp());
00350 }
00351 
00352 Window *Window::retrieveActive(ExecState *exec)
00353 {
00354   ValueImp *imp = exec->interpreter()->globalObject().imp();
00355   assert( imp );
00356 #ifndef QWS
00357   assert( dynamic_cast<KJS::Window*>(imp) );
00358 #endif
00359   return static_cast<KJS::Window*>(imp);
00360 }
00361 
00362 Value Window::retrieve(KParts::ReadOnlyPart *p)
00363 {
00364   assert(p);
00365   KHTMLPart * part = ::qt_cast<KHTMLPart *>(p);
00366   KJSProxy *proxy = 0L;
00367   if (!part) {
00368     part = ::qt_cast<KHTMLPart *>(p->parent());
00369     if (part)
00370       proxy = part->framejScript(p);
00371   } else
00372     proxy = part->jScript();
00373   if (proxy) {
00374 #ifdef KJS_VERBOSE
00375     kdDebug(6070) << "Window::retrieve part=" << part << " '" << part->name() << "' interpreter=" << proxy->interpreter() << " window=" << proxy->interpreter()->globalObject().imp() << endl;
00376 #endif
00377     return proxy->interpreter()->globalObject(); // the Global object is the "window"
00378   } else {
00379 #ifdef KJS_VERBOSE
00380     kdDebug(6070) << "Window::retrieve part=" << p << " '" << p->name() << "' no jsproxy." << endl;
00381 #endif
00382     return Undefined(); // This can happen with JS disabled on the domain of that window
00383   }
00384 }
00385 
00386 Location *Window::location() const
00387 {
00388   if (!loc)
00389     const_cast<Window*>(this)->loc = new Location(m_frame);
00390   return loc;
00391 }
00392 
00393 ObjectImp* Window::frames( ExecState* exec ) const
00394 {
00395   KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
00396   if (part)
00397     return m_frames ? m_frames :
00398       (const_cast<Window*>(this)->m_frames = new FrameArray(exec, part));
00399   return 0L;
00400 }
00401 
00402 // reference our special objects during garbage collection
00403 void Window::mark()
00404 {
00405   ObjectImp::mark();
00406   if (screen && !screen->marked())
00407     screen->mark();
00408   if (history && !history->marked())
00409     history->mark();
00410   if (external && !external->marked())
00411     external->mark();
00412   if (m_frames && !m_frames->marked())
00413     m_frames->mark();
00414   //kdDebug(6070) << "Window::mark " << this << " marking loc=" << loc << endl;
00415   if (loc && !loc->marked())
00416     loc->mark();
00417   if (winq)
00418     winq->mark();
00419 }
00420 
00421 bool Window::hasProperty(ExecState *exec, const Identifier &p) const
00422 {
00423   // we don't want any operations on a closed window
00424   if (m_frame.isNull() || m_frame->m_part.isNull())
00425     return ( p == "closed" );
00426 
00427   if (ObjectImp::hasProperty(exec, p))
00428     return true;
00429 
00430   if (Lookup::findEntry(&WindowTable, p))
00431     return true;
00432 
00433   KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
00434   if (!part)
00435       return false;
00436 
00437   QString q = p.qstring();
00438   if (part->findFramePart(p.qstring()))
00439     return true;
00440   // allow window[1] or parent[1] etc. (#56983)
00441   bool ok;
00442   unsigned int i = p.toArrayIndex(&ok);
00443   if (ok) {
00444     QPtrList<KParts::ReadOnlyPart> frames = part->frames();
00445     unsigned int len = frames.count();
00446     if (i < len)
00447       return true;
00448   }
00449 
00450   // allow shortcuts like 'Image1' instead of document.images.Image1
00451   if (part->document().isHTMLDocument()) { // might be XML
00452     DOM::HTMLDocument doc = part->htmlDocument();
00453     // Keep in sync with tryGet
00454     NamedTagLengthDeterminer::TagLength tags[3] = {
00455       {ID_IMG, 0, 0L}, {ID_FORM, 0, 0L}, {ID_APPLET, 0, 0L}
00456     };
00457     NamedTagLengthDeterminer(p.string(), tags, 3)(doc.handle());
00458     for (int i = 0; i < 3; i++)
00459       if (tags[i].length > 0)
00460         return true;
00461 
00462     return !doc.getElementById(p.string()).isNull();
00463   }
00464 
00465   return false;
00466 }
00467 
00468 UString Window::toString(ExecState *) const
00469 {
00470   return "[object Window]";
00471 }
00472 
00473 Value Window::get(ExecState *exec, const Identifier &p) const
00474 {
00475 #ifdef KJS_VERBOSE
00476   kdDebug(6070) << "Window("<<this<<")::get " << p.qstring() << endl;
00477 #endif
00478   // we don't want any operations on a closed window
00479   if (m_frame.isNull() || m_frame->m_part.isNull()) {
00480     if ( p == "closed" )
00481       return Boolean( true );
00482     return Undefined();
00483   }
00484 
00485   // Look for overrides first
00486   Value val = ObjectImp::get(exec, p);
00487   if (!val.isA(UndefinedType)) {
00488     //kdDebug(6070) << "Window::get found dynamic property '" << p.ascii() << "'" << endl;
00489     return isSafeScript(exec) ? val : Undefined();
00490   }
00491 
00492   const HashEntry* entry = Lookup::findEntry(&WindowTable, p);
00493   KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
00494 
00495   // properties that work on all windows
00496   if (entry) {
00497     // ReadOnlyPart first
00498     switch(entry->value) {
00499     case Closed:
00500       return Boolean( false );
00501     case _Location:
00502         // No isSafeScript test here, we must be able to _set_ location.href (#49819)
00503       return Value(location());
00504     case _Window:
00505     case Self:
00506       return retrieve(m_frame->m_part);
00507     default:
00508         break;
00509     }
00510     if (!part)
00511         return Undefined();
00512     // KHTMLPart next
00513     switch(entry->value) {
00514     case Frames:
00515       return Value(frames(exec));
00516     case Opener:
00517       if (!part->opener())
00518         return Null();    // ### a null Window might be better, but == null
00519       else                // doesn't work yet
00520         return retrieve(part->opener());
00521     case Parent:
00522       return retrieve(part->parentPart() ? part->parentPart() : (KHTMLPart*)part);
00523     case Top: {
00524       KHTMLPart *p = part;
00525       while (p->parentPart())
00526         p = p->parentPart();
00527       return retrieve(p);
00528     }
00529     case Alert:
00530     case Confirm:
00531     case Prompt:
00532     case Open:
00533     case Focus:
00534     case Blur:
00535       return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
00536     default:
00537       break;
00538     }
00539   } else if (!part) {
00540     // not a  KHTMLPart
00541     QString rvalue;
00542     KParts::LiveConnectExtension::Type rtype;
00543     unsigned long robjid;
00544     if (m_frame->m_liveconnect &&
00545         isSafeScript(exec) &&
00546         m_frame->m_liveconnect->get(0, p.qstring(), rtype, robjid, rvalue))
00547       return getLiveConnectValue(m_frame->m_liveconnect, p.qstring(), rtype, rvalue, robjid);
00548     return Undefined();
00549   }
00550   // properties that only work on safe windows
00551   if (isSafeScript(exec) &&  entry)
00552   {
00553     //kdDebug(6070) << "token: " << entry->value << endl;
00554     switch( entry->value ) {
00555     case Crypto:
00556       return Undefined(); // ###
00557     case DefaultStatus:
00558       return String(UString(part->jsDefaultStatusBarText()));
00559     case Status:
00560       return String(UString(part->jsStatusBarText()));
00561     case Document:
00562       if (part->document().isNull()) {
00563         kdDebug(6070) << "Document.write: adding <HTML><BODY> to create document" << endl;
00564         part->begin();
00565         part->write("<HTML><BODY>");
00566         part->end();
00567       }
00568       return getDOMNode(exec,part->document());
00569     case Node:
00570       return getNodeConstructor(exec);
00571     case Range:
00572       return getRangeConstructor(exec);
00573     case NodeFilter:
00574       return getNodeFilterConstructor(exec);
00575     case DOMException:
00576       return getDOMExceptionConstructor(exec);
00577     case CSSRule:
00578       return getCSSRuleConstructor(exec);
00579     case EventCtor:
00580       return getEventConstructor(exec);
00581     case _History:
00582       return Value(history ? history :
00583                    (const_cast<Window*>(this)->history = new History(exec,part)));
00584 
00585     case _External:
00586       return Value(external ? external :
00587                    (const_cast<Window*>(this)->external = new External(exec,part)));
00588 
00589     case Event:
00590       if (m_evt)
00591         return getDOMEvent(exec,*m_evt);
00592       else {
00593 #ifdef KJS_VERBOSE
00594         kdDebug(6070) << "WARNING: window(" << this << "," << part->name() << ").event, no event!" << endl;
00595 #endif
00596         return Undefined();
00597       }
00598     case InnerHeight:
00599       if (!part->view())
00600         return Undefined();
00601       khtml::RenderWidget::flushWidgetResizes(); // make sure frames have their final size
00602       return Number(part->view()->visibleHeight());
00603     case InnerWidth:
00604       if (!part->view())
00605         return Undefined();
00606       khtml::RenderWidget::flushWidgetResizes(); // make sure frames have their final size
00607       return Number(part->view()->visibleWidth());
00608     case Length:
00609       return Number(part->frames().count());
00610     case Name:
00611       return String(part->name());
00612     case SideBar:
00613       return Value(new MozillaSidebarExtension(exec, part));
00614     case _Navigator:
00615     case ClientInformation: {
00616       // Store the navigator in the object so we get the same one each time.
00617       Value nav( new Navigator(exec, part) );
00618       const_cast<Window *>(this)->put(exec, "navigator", nav, DontDelete|ReadOnly|Internal);
00619       const_cast<Window *>(this)->put(exec, "clientInformation", nav, DontDelete|ReadOnly|Internal);
00620       return nav;
00621     }
00622 #ifdef Q_WS_QWS
00623     case _Konqueror: {
00624       Value k( new Konqueror(exec, part) );
00625       const_cast<Window *>(this)->put(exec, "konqueror", k, DontDelete|ReadOnly|Internal);
00626       return k;
00627     }
00628 #endif
00629     case OffscreenBuffering:
00630       return Boolean(true);
00631     case OuterHeight:
00632     case OuterWidth:
00633     {
00634       if (!part->widget())
00635         return Number(0);
00636       KWin::WindowInfo inf = KWin::windowInfo(part->widget()->topLevelWidget()->winId());
00637       return Number(entry->value == OuterHeight ?
00638                     inf.geometry().height() : inf.geometry().width());
00639     }
00640     case PageXOffset:
00641       return Number(part->view()->contentsX());
00642     case PageYOffset:
00643       return Number(part->view()->contentsY());
00644     case Personalbar:
00645       return Undefined(); // ###
00646     case ScreenLeft:
00647     case ScreenX: {
00648       if (!part->view())
00649         return Undefined();
00650       QRect sg = KGlobalSettings::desktopGeometry(part->view());
00651       return Number(part->view()->mapToGlobal(QPoint(0,0)).x() + sg.x());
00652     }
00653     case ScreenTop:
00654     case ScreenY: {
00655       if (!part->view())
00656         return Undefined();
00657       QRect sg = KGlobalSettings::desktopGeometry(part->view());
00658       return Number(part->view()->mapToGlobal(QPoint(0,0)).y() + sg.y());
00659     }
00660     case ScrollX: {
00661       if (!part->view())
00662         return Undefined();
00663       return Number(part->view()->contentsX());
00664     }
00665     case ScrollY: {
00666       if (!part->view())
00667         return Undefined();
00668       return Number(part->view()->contentsY());
00669     }
00670     case Scrollbars:
00671       return Undefined(); // ###
00672     case _Screen:
00673       return Value(screen ? screen :
00674                    (const_cast<Window*>(this)->screen = new Screen(exec)));
00675     case Image:
00676       return Value(new ImageConstructorImp(exec, part->document()));
00677     case Option:
00678       return Value(new OptionConstructorImp(exec, part->document()));
00679     case XMLHttpRequest:
00680       return Value(new XMLHttpRequestConstructorImp(exec, part->document()));
00681     case XMLSerializer:
00682       return Value(new XMLSerializerConstructorImp(exec));
00683     case Close:
00684     case Scroll: // compatibility
00685     case ScrollBy:
00686     case ScrollTo:
00687     case MoveBy:
00688     case MoveTo:
00689     case ResizeBy:
00690     case ResizeTo:
00691     case CaptureEvents:
00692     case ReleaseEvents:
00693     case AddEventListener:
00694     case RemoveEventListener:
00695     case SetTimeout:
00696     case ClearTimeout:
00697     case SetInterval:
00698     case ClearInterval:
00699     case Print:
00700       return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
00701     // IE extension
00702     case Navigate:
00703       // Disabled in NS-compat mode. Supported by default - can't hurt, unless someone uses
00704       // if (navigate) to test for IE (unlikely).
00705       if ( exec->interpreter()->compatMode() == Interpreter::NetscapeCompat )
00706         return Undefined();
00707       return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
00708     case Onabort:
00709       return getListener(exec,DOM::EventImpl::ABORT_EVENT);
00710     case Onblur:
00711       return getListener(exec,DOM::EventImpl::BLUR_EVENT);
00712     case Onchange:
00713       return getListener(exec,DOM::EventImpl::CHANGE_EVENT);
00714     case Onclick:
00715       return getListener(exec,DOM::EventImpl::KHTML_ECMA_CLICK_EVENT);
00716     case Ondblclick:
00717       return getListener(exec,DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT);
00718     case Ondragdrop:
00719       return getListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT);
00720     case Onerror:
00721       return getListener(exec,DOM::EventImpl::KHTML_ERROR_EVENT);
00722     case Onfocus:
00723       return getListener(exec,DOM::EventImpl::FOCUS_EVENT);
00724     case Onkeydown:
00725       return getListener(exec,DOM::EventImpl::KEYDOWN_EVENT);
00726     case Onkeypress:
00727       return getListener(exec,DOM::EventImpl::KHTML_KEYPRESS_EVENT);
00728     case Onkeyup:
00729       return getListener(exec,DOM::EventImpl::KEYUP_EVENT);
00730     case Onload:
00731       return getListener(exec,DOM::EventImpl::LOAD_EVENT);
00732     case Onmousedown:
00733       return getListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT);
00734     case Onmousemove:
00735       return getListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT);
00736     case Onmouseout:
00737       return getListener(exec,DOM::EventImpl::MOUSEOUT_EVENT);
00738     case Onmouseover:
00739       return getListener(exec,DOM::EventImpl::MOUSEOVER_EVENT);
00740     case Onmouseup:
00741       return getListener(exec,DOM::EventImpl::MOUSEUP_EVENT);
00742     case Onmove:
00743       return getListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT);
00744     case Onreset:
00745       return getListener(exec,DOM::EventImpl::RESET_EVENT);
00746     case Onresize:
00747       return getListener(exec,DOM::EventImpl::RESIZE_EVENT);
00748     case Onselect:
00749       return getListener(exec,DOM::EventImpl::SELECT_EVENT);
00750     case Onsubmit:
00751       return getListener(exec,DOM::EventImpl::SUBMIT_EVENT);
00752     case Onunload:
00753       return getListener(exec,DOM::EventImpl::UNLOAD_EVENT);
00754     }
00755   }
00756   KParts::ReadOnlyPart *rop = part->findFramePart( p.qstring() );
00757   if (rop)
00758     return retrieve(rop);
00759 
00760   // allow window[1] or parent[1] etc. (#56983)
00761   bool ok;
00762   unsigned int i = p.toArrayIndex(&ok);
00763   if (ok) {
00764     QPtrList<KParts::ReadOnlyPart> frames = part->frames();
00765     unsigned int len = frames.count();
00766     if (i < len) {
00767       KParts::ReadOnlyPart* frame = frames.at(i);
00768       if (frame)
00769         return Window::retrieve(frame);
00770     }
00771   }
00772 
00773   // allow shortcuts like 'Image1' instead of document.images.Image1
00774   if (isSafeScript(exec) &&
00775       part->document().isHTMLDocument()) { // might be XML
00776     // This is only for images, forms, layers and applets, see KJS::HTMLDocument::tryGet
00777     DOM::HTMLDocument doc = part->htmlDocument();
00778     NamedTagLengthDeterminer::TagLength tags[4] = {
00779       {ID_IMG, 0, 0L}, {ID_FORM, 0, 0L}, {ID_APPLET, 0, 0L}, {ID_LAYER, 0, 0L}
00780     };
00781     NamedTagLengthDeterminer(p.string(), tags, 4)(doc.handle());
00782     for (int i = 0; i < 4; i++)
00783       if (tags[i].length > 0) {
00784         if (tags[i].length == 1)
00785           return getDOMNode(exec, tags[i].last);
00786         // Get all the items with the same name
00787         return getDOMNodeList(exec, DOM::NodeList(new DOM::NamedTagNodeListImpl(doc.handle(), tags[i].id, p.string())));
00788     }
00789 
00790     DOM::Element element = doc.getElementById(p.string() );
00791     if ( !element.isNull() )
00792       return getDOMNode(exec, element );
00793   }
00794 
00795   // This isn't necessarily a bug. Some code uses if(!window.blah) window.blah=1
00796   // But it can also mean something isn't loaded or implemented, hence the WARNING to help grepping.
00797 #ifdef KJS_VERBOSE
00798   kdDebug(6070) << "WARNING: Window::get property not found: " << p.qstring() << endl;
00799 #endif
00800   return Undefined();
00801 }
00802 
00803 void Window::put(ExecState* exec, const Identifier &propertyName, const Value &value, int attr)
00804 {
00805   // Called by an internal KJS call (e.g. InterpreterImp's constructor) ?
00806   // If yes, save time and jump directly to ObjectImp.
00807   if ( (attr != None && attr != DontDelete) ||
00808        // Same thing if we have a local override (e.g. "var location")
00809        ( isSafeScript( exec ) && ObjectImp::getDirect(propertyName) ) )
00810   {
00811     ObjectImp::put( exec, propertyName, value, attr );
00812     return;
00813   }
00814 
00815   const HashEntry* entry = Lookup::findEntry(&WindowTable, propertyName);
00816   if (entry && !m_frame.isNull() && !m_frame->m_part.isNull())
00817   {
00818 #ifdef KJS_VERBOSE
00819     kdDebug(6070) << "Window("<<this<<")::put " << propertyName.qstring() << endl;
00820 #endif
00821     switch( entry->value) {
00822     case _Location:
00823       goURL(exec, value.toString(exec).qstring(), false /*don't lock history*/);
00824       return;
00825     default:
00826       break;
00827     }
00828     KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
00829     if (part) {
00830     switch( entry->value ) {
00831     case Status: {
00832       if  (isSafeScript(exec) && part->settings()->windowStatusPolicy(part->url().host())
00833         == KHTMLSettings::KJSWindowStatusAllow) {
00834       String s = value.toString(exec);
00835       part->setJSStatusBarText(s.value().qstring());
00836       }
00837       return;
00838     }
00839     case DefaultStatus: {
00840       if (isSafeScript(exec) && part->settings()->windowStatusPolicy(part->url().host())
00841         == KHTMLSettings::KJSWindowStatusAllow) {
00842       String s = value.toString(exec);
00843       part->setJSDefaultStatusBarText(s.value().qstring());
00844       }
00845       return;
00846     }
00847     case Onabort:
00848       if (isSafeScript(exec))
00849         setListener(exec, DOM::EventImpl::ABORT_EVENT,value);
00850       return;
00851     case Onblur:
00852       if (isSafeScript(exec))
00853         setListener(exec, DOM::EventImpl::BLUR_EVENT,value);
00854       return;
00855     case Onchange:
00856       if (isSafeScript(exec))
00857         setListener(exec, DOM::EventImpl::CHANGE_EVENT,value);
00858       return;
00859     case Onclick:
00860       if (isSafeScript(exec))
00861         setListener(exec,DOM::EventImpl::KHTML_ECMA_CLICK_EVENT,value);
00862       return;
00863     case Ondblclick:
00864       if (isSafeScript(exec))
00865         setListener(exec,DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT,value);
00866       return;
00867     case Ondragdrop:
00868       if (isSafeScript(exec))
00869         setListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT,value);
00870       return;
00871     case Onerror:
00872       if (isSafeScript(exec))
00873         setListener(exec,DOM::EventImpl::KHTML_ERROR_EVENT,value);
00874       return;
00875     case Onfocus:
00876       if (isSafeScript(exec))
00877         setListener(exec,DOM::EventImpl::FOCUS_EVENT,value);
00878       return;
00879     case Onkeydown:
00880       if (isSafeScript(exec))
00881         setListener(exec,DOM::EventImpl::KEYDOWN_EVENT,value);
00882       return;
00883     case Onkeypress:
00884       if (isSafeScript(exec))
00885         setListener(exec,DOM::EventImpl::KHTML_KEYPRESS_EVENT,value);
00886       return;
00887     case Onkeyup:
00888       if (isSafeScript(exec))
00889         setListener(exec,DOM::EventImpl::KEYUP_EVENT,value);
00890       return;
00891     case Onload:
00892       if (isSafeScript(exec))
00893         setListener(exec,DOM::EventImpl::LOAD_EVENT,value);
00894       return;
00895     case Onmousedown:
00896       if (isSafeScript(exec))
00897         setListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT,value);
00898       return;
00899     case Onmousemove:
00900       if (isSafeScript(exec))
00901         setListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT,value);
00902       return;
00903     case Onmouseout:
00904       if (isSafeScript(exec))
00905         setListener(exec,DOM::EventImpl::MOUSEOUT_EVENT,value);
00906       return;
00907     case Onmouseover:
00908       if (isSafeScript(exec))
00909         setListener(exec,DOM::EventImpl::MOUSEOVER_EVENT,value);
00910       return;
00911     case Onmouseup:
00912       if (isSafeScript(exec))
00913         setListener(exec,DOM::EventImpl::MOUSEUP_EVENT,value);
00914       return;
00915     case Onmove:
00916       if (isSafeScript(exec))
00917         setListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT,value);
00918       return;
00919     case Onreset:
00920       if (isSafeScript(exec))
00921         setListener(exec,DOM::EventImpl::RESET_EVENT,value);
00922       return;
00923     case Onresize:
00924       if (isSafeScript(exec))
00925         setListener(exec,DOM::EventImpl::RESIZE_EVENT,value);
00926       return;
00927     case Onselect:
00928       if (isSafeScript(exec))
00929         setListener(exec,DOM::EventImpl::SELECT_EVENT,value);
00930       return;
00931     case Onsubmit:
00932       if (isSafeScript(exec))
00933         setListener(exec,DOM::EventImpl::SUBMIT_EVENT,value);
00934       return;
00935     case Onunload:
00936       if (isSafeScript(exec))
00937         setListener(exec,DOM::EventImpl::UNLOAD_EVENT,value);
00938       return;
00939     case Name:
00940       if (isSafeScript(exec))
00941         part->setName( value.toString(exec).qstring().local8Bit().data() );
00942       return;
00943     default:
00944       break;
00945     }
00946     }
00947   }
00948   if (m_frame->m_liveconnect &&
00949       isSafeScript(exec) &&
00950       m_frame->m_liveconnect->put(0, propertyName.qstring(), value.toString(exec).qstring()))
00951     return;
00952   if (isSafeScript(exec)) {
00953     //kdDebug(6070) << "Window("<<this<<")::put storing " << propertyName.qstring() << endl;
00954     ObjectImp::put(exec, propertyName, value, attr);
00955   }
00956 }
00957 
00958 bool Window::toBoolean(ExecState *) const
00959 {
00960   return !m_frame.isNull() && !m_frame->m_part.isNull();
00961 }
00962 
00963 void Window::scheduleClose()
00964 {
00965   kdDebug(6070) << "Window::scheduleClose window.close() " << m_frame << endl;
00966   Q_ASSERT(winq);
00967   QTimer::singleShot( 0, winq, SLOT( timeoutClose() ) );
00968 }
00969 
00970 void Window::closeNow()
00971 {
00972   if (m_frame.isNull() || m_frame->m_part.isNull()) {
00973     kdDebug(6070) << k_funcinfo << "part is deleted already" << endl;
00974   } else {
00975     KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
00976     if (!part) {
00977       kdDebug(6070) << "closeNow on non KHTML part" << endl;
00978     } else {
00979       //kdDebug(6070) << k_funcinfo << " -> closing window" << endl;
00980       // We want to make sure that window.open won't find this part by name.
00981       part->setName( 0 );
00982       part->deleteLater();
00983       part = 0;
00984     }
00985   }
00986 }
00987 
00988 void Window::afterScriptExecution()
00989 {
00990   DOM::DocumentImpl::updateDocumentsRendering();
00991   QValueList<DelayedAction> delayedActions = m_delayed;
00992   m_delayed.clear();
00993   QValueList<DelayedAction>::Iterator it = delayedActions.begin();
00994   for ( ; it != delayedActions.end() ; ++it )
00995   {
00996     switch ((*it).actionId) {
00997     case DelayedClose:
00998       scheduleClose();
00999       return; // stop here, in case of multiple actions
01000     case DelayedGoHistory:
01001       goHistory( (*it).param.toInt() );
01002       break;
01003     case NullAction:
01004       // FIXME: anything needs to be done here?  This is warning anyways.
01005       break;
01006     };
01007   }
01008 }
01009 
01010 bool Window::checkIsSafeScript(KParts::ReadOnlyPart *activePart) const
01011 {
01012   if (m_frame.isNull() || m_frame->m_part.isNull()) { // part deleted ? can't grant access
01013     kdDebug(6070) << "Window::isSafeScript: accessing deleted part !" << endl;
01014     return false;
01015   }
01016   if (!activePart) {
01017     kdDebug(6070) << "Window::isSafeScript: current interpreter's part is 0L!" << endl;
01018     return false;
01019   }
01020    if ( activePart == m_frame->m_part ) // Not calling from another frame, no problem.
01021      return true;
01022 
01023   KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
01024   if (!part)
01025     return true; // not a KHTMLPart
01026 
01027   if ( part->document().isNull() )
01028     return true; // allow to access a window that was just created (e.g. with window.open("about:blank"))
01029 
01030   DOM::HTMLDocument thisDocument = part->htmlDocument();
01031   if ( thisDocument.isNull() ) {
01032     kdDebug(6070) << "Window::isSafeScript: trying to access an XML document !?" << endl;
01033     return false;
01034   }
01035 
01036   KHTMLPart *activeKHTMLPart = ::qt_cast<KHTMLPart *>(activePart);
01037   if (!activeKHTMLPart)
01038     return true; // not a KHTMLPart
01039 
01040   DOM::HTMLDocument actDocument = activeKHTMLPart->htmlDocument();
01041   if ( actDocument.isNull() ) {
01042     kdDebug(6070) << "Window::isSafeScript: active part has no document!" << endl;
01043     return false;
01044   }
01045   DOM::DOMString actDomain = actDocument.domain();
01046   DOM::DOMString thisDomain = thisDocument.domain();
01047 
01048   if ( actDomain == thisDomain ) {
01049 #ifdef KJS_VERBOSE
01050     //kdDebug(6070) << "JavaScript: access granted, domain is '" << actDomain.string() << "'" << endl;
01051 #endif
01052     return true;
01053   }
01054 
01055   kdDebug(6070) << "WARNING: JavaScript: access denied for current frame '" << actDomain.string() << "' to frame '" << thisDomain.string() << "'" << endl;
01056   // TODO after 3.1: throw security exception (exec->setException())
01057   return false;
01058 }
01059 
01060 void Window::setListener(ExecState *exec, int eventId, Value func)
01061 {
01062   KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
01063   if (!part || !isSafeScript(exec))
01064     return;
01065   DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(part->htmlDocument().handle());
01066   if (!doc)
01067     return;
01068 
01069   doc->setHTMLWindowEventListener(eventId,getJSEventListener(func,true));
01070 }
01071 
01072 Value Window::getListener(ExecState *exec, int eventId) const
01073 {
01074   KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
01075   if (!part || !isSafeScript(exec))
01076     return Undefined();
01077   DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(part->htmlDocument().handle());
01078   if (!doc)
01079     return Undefined();
01080 
01081   DOM::EventListener *listener = doc->getHTMLWindowEventListener(eventId);
01082   if (listener && static_cast<JSEventListener*>(listener)->listenerObjImp())
01083     return static_cast<JSEventListener*>(listener)->listenerObj();
01084   else
01085     return Null();
01086 }
01087 
01088 
01089 JSEventListener *Window::getJSEventListener(const Value& val, bool html)
01090 {
01091   // This function is so hot that it's worth coding it directly with imps.
01092   KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
01093   if (!part || val.type() != ObjectType)
01094     return 0;
01095 
01096   // It's ObjectType, so it must be valid.
01097   Object listenerObject = Object::dynamicCast(val);
01098   ObjectImp *listenerObjectImp = listenerObject.imp();
01099 
01100   // 'listener' is not a simple ecma function. (Always use sanity checks: Better safe than sorry!)
01101   if (!listenerObject.implementsCall() && part && part->jScript() && part->jScript()->interpreter())
01102   {
01103     Interpreter *interpreter = part->jScript()->interpreter();
01104 
01105     // 'listener' probably is an EventListener object containing a 'handleEvent' function.
01106     Value handleEventValue = listenerObject.get(interpreter->globalExec(), Identifier("handleEvent"));
01107     Object handleEventObject = Object::dynamicCast(handleEventValue);
01108 
01109     if(handleEventObject.isValid() && handleEventObject.implementsCall())
01110     {
01111       listenerObject = handleEventObject;
01112       listenerObjectImp = handleEventObject.imp();
01113     }
01114   }
01115 
01116   JSEventListener *existingListener = jsEventListeners[listenerObjectImp];
01117   if (existingListener)
01118     return existingListener;
01119 
01120   // Note that the JSEventListener constructor adds it to our jsEventListeners list
01121   return new JSEventListener(listenerObject, listenerObjectImp, Object(this), html);
01122 }
01123 
01124 JSLazyEventListener *Window::getJSLazyEventListener(const QString& code, const QString& name, bool html)
01125 {
01126   return new JSLazyEventListener(code, name, Object(this), html);
01127 }
01128 
01129 void Window::clear( ExecState *exec )
01130 {
01131   delete winq;
01132   winq = 0L;
01133   // Get rid of everything, those user vars could hold references to DOM nodes
01134   deleteAllProperties( exec );
01135 
01136   // Break the dependency between the listeners and their object
01137   QPtrDictIterator<JSEventListener> it(jsEventListeners);
01138   for (; it.current(); ++it)
01139     it.current()->clear();
01140   // Forget about the listeners (the DOM::NodeImpls will delete them)
01141   jsEventListeners.clear();
01142 
01143   if (m_frame) {
01144     KJSProxy* proxy = m_frame->m_jscript;
01145     if (proxy) // i.e. JS not disabled
01146     {
01147       winq = new WindowQObject(this);
01148       // Now recreate a working global object for the next URL that will use us
01149       KJS::Interpreter *interpreter = proxy->interpreter();
01150       interpreter->initGlobalObject();
01151     }
01152   }
01153 }
01154 
01155 void Window::setCurrentEvent( DOM::Event *evt )
01156 {
01157   m_evt = evt;
01158   //kdDebug(6070) << "Window " << this << " (part=" << m_part << ")::setCurrentEvent m_evt=" << evt << endl;
01159 }
01160 
01161 void Window::goURL(ExecState* exec, const QString& url, bool lockHistory)
01162 {
01163   Window* active = Window::retrieveActive(exec);
01164   KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
01165   KHTMLPart *active_part = ::qt_cast<KHTMLPart *>(active->part());
01166   // Complete the URL using the "active part" (running interpreter)
01167   if (active_part && part) {
01168     if (url[0] == QChar('#')) {
01169       part->gotoAnchor(url.mid(1));
01170     } else {
01171       QString dstUrl = active_part->htmlDocument().completeURL(url).string();
01172       KURL dst( dstUrl );
01173       KURL partURL( part->url() );
01174       // Remove refs for the comparison
01175       dst.setRef( QString::null );
01176       partURL.setRef( QString::null );
01177       kdDebug(6070) << "Window::goURL dstUrl=" << dst.prettyURL() << " partURL=" << partURL.prettyURL()
01178                    << " identical: " << partURL.equals( dst, true ) << endl;
01179 
01180       // check if we're allowed to inject javascript
01181       // SYNC check with khtml_part.cpp::slotRedirect!
01182       if ( isSafeScript(exec) ||
01183             dstUrl.find(QString::fromLatin1("javascript:"), 0, false) != 0 )
01184           part->scheduleRedirection(-1,
01185                                 dstUrl,
01186                                   lockHistory);
01187     }
01188   } else if (!part && !m_frame->m_part.isNull()) {
01189     KParts::BrowserExtension *b = KParts::BrowserExtension::childObject(m_frame->m_part);
01190     if (b)
01191       b->emit openURLRequest(m_frame->m_frame->element()->getDocument()->completeURL(url));
01192     kdDebug() << "goURL for ROPart" << endl;
01193   }
01194 }
01195 
01196 KParts::ReadOnlyPart *Window::part() const {
01197     return m_frame.isNull() ? 0L : static_cast<KParts::ReadOnlyPart *>(m_frame->m_part);
01198 }
01199 
01200 void Window::delayedGoHistory( int steps )
01201 {
01202     m_delayed.append( DelayedAction( DelayedGoHistory, steps ) );
01203 }
01204 
01205 void Window::goHistory( int steps )
01206 {
01207   KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
01208   if(!part)
01209       // TODO history readonlypart
01210     return;
01211   KParts::BrowserExtension *ext = part->browserExtension();
01212   if(!ext)
01213     return;
01214   KParts::BrowserInterface *iface = ext->browserInterface();
01215 
01216   if ( !iface )
01217     return;
01218 
01219   iface->callMethod( "goHistory(int)", steps );
01220   //emit ext->goHistory(steps);
01221 }
01222 
01223 void KJS::Window::resizeTo(QWidget* tl, int width, int height)
01224 {
01225   KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
01226   if(!part)
01227       // TODO resizeTo readonlypart
01228     return;
01229   KParts::BrowserExtension *ext = part->browserExtension();
01230   if (!ext) {
01231     kdDebug(6070) << "Window::resizeTo found no browserExtension" << endl;
01232     return;
01233   }
01234 
01235   // Security check: within desktop limits and bigger than 100x100 (per spec)
01236   if ( width < 100 || height < 100 ) {
01237     kdDebug(6070) << "Window::resizeTo refused, window would be too small ("<<width<<","<<height<<")" << endl;
01238     return;
01239   }
01240 
01241   QRect sg = KGlobalSettings::desktopGeometry(tl);
01242 
01243   if ( width > sg.width() || height > sg.height() ) {
01244     kdDebug(6070) << "Window::resizeTo refused, window would be too big ("<<width<<","<<height<<")" << endl;
01245     return;
01246   }
01247 
01248   kdDebug(6070) << "resizing to " << width << "x" << height << endl;
01249 
01250   emit ext->resizeTopLevelWidget( width, height );
01251 
01252   // If the window is out of the desktop, move it up/left
01253   // (maybe we should use workarea instead of sg, otherwise the window ends up below kicker)
01254   int right = tl->x() + tl->frameGeometry().width();
01255   int bottom = tl->y() + tl->frameGeometry().height();
01256   int moveByX = 0;
01257   int moveByY = 0;
01258   if ( right > sg.right() )
01259     moveByX = - right + sg.right(); // always <0
01260   if ( bottom > sg.bottom() )
01261     moveByY = - bottom + sg.bottom(); // always <0
01262   if ( moveByX || moveByY )
01263     emit ext->moveTopLevelWidget( tl->x() + moveByX , tl->y() + moveByY );
01264 }
01265 
01266 Value Window::openWindow(ExecState *exec, const List& args)
01267 {
01268   KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
01269   if (!part)
01270     return Undefined();
01271   KHTMLView *widget = part->view();
01272   Value v = args[0];
01273   QString str = v.toString(exec).qstring();
01274 
01275   // prepare arguments
01276   KURL url;
01277   if (!str.isEmpty())
01278   {
01279     KHTMLPart* p = ::qt_cast<KHTMLPart *>(Window::retrieveActive(exec)->m_frame->m_part);
01280     if ( p )
01281       url = p->htmlDocument().completeURL(str).string();
01282     if ( !p ||
01283          !static_cast<DOM::DocumentImpl*>(p->htmlDocument().handle())->isURLAllowed(url.url()) )
01284       return Undefined();
01285   }
01286 
01287   KHTMLSettings::KJSWindowOpenPolicy policy =
01288         part->settings()->windowOpenPolicy(part->url().host());
01289   if ( policy == KHTMLSettings::KJSWindowOpenAsk ) {
01290     emit part->browserExtension()->requestFocus(part);
01291     QString caption;
01292     if (!part->url().host().isEmpty())
01293       caption = part->url().host() + " - ";
01294     caption += i18n( "Confirmation: JavaScript Popup" );
01295     if ( KMessageBox::questionYesNo(widget,
01296                                     str.isEmpty() ?
01297                                     i18n( "This site is requesting to open up a new browser "
01298                                           "window via JavaScript.\n"
01299                                           "Do you want to allow this?" ) :
01300                                     i18n( "<qt>This site is requesting to open<p>%1</p>in a new browser window via JavaScript.<br />"
01301                                           "Do you want to allow this?</qt>").arg(KStringHandler::csqueeze(url.htmlURL(),  100)),
01302                                     caption ) == KMessageBox::Yes )
01303       policy = KHTMLSettings::KJSWindowOpenAllow;
01304   } else if ( policy == KHTMLSettings::KJSWindowOpenSmart )
01305   {
01306     // window.open disabled unless from a key/mouse event
01307     if (static_cast<ScriptInterpreter *>(exec->interpreter())->isWindowOpenAllowed())
01308       policy = KHTMLSettings::KJSWindowOpenAllow;
01309   }
01310   if ( policy != KHTMLSettings::KJSWindowOpenAllow ) {
01311     return Undefined();
01312   } else {
01313     KParts::WindowArgs winargs;
01314 
01315     // scan feature argument
01316     QString features;
01317     if (args.size()>2) {
01318       features = args[2].toString(exec).qstring();
01319       // specifying window params means false defaults
01320       winargs.menuBarVisible = false;
01321       winargs.toolBarsVisible = false;
01322       winargs.statusBarVisible = false;
01323       QStringList flist = QStringList::split(',', features);
01324       QStringList::ConstIterator it = flist.begin();
01325       while (it != flist.end()) {
01326         QString s = *it++;
01327         QString key, val;
01328         int pos = s.find('=');
01329         if (pos >= 0) {
01330           key = s.left(pos).stripWhiteSpace().lower();
01331           val = s.mid(pos + 1).stripWhiteSpace().lower();
01332           QRect screen = KGlobalSettings::desktopGeometry(widget->topLevelWidget());
01333 
01334           if (key == "left" || key == "screenx") {
01335             winargs.x = (int)val.toFloat() + screen.x();
01336             if (winargs.x < screen.x() || winargs.x > screen.right())
01337               winargs.x = screen.x(); // only safe choice until size is determined
01338           } else if (key == "top" || key == "screeny") {
01339             winargs.y = (int)val.toFloat() + screen.y();
01340             if (winargs.y < screen.y() || winargs.y > screen.bottom())
01341               winargs.y = screen.y(); // only safe choice until size is determined
01342           } else if (key == "height") {
01343             winargs.height = (int)val.toFloat() + 2*qApp->style().pixelMetric( QStyle::PM_DefaultFrameWidth ) + 2;
01344             if (winargs.height > screen.height())  // should actually check workspace
01345               winargs.height = screen.height();
01346             if (winargs.height < 100)
01347               winargs.height = 100;
01348           } else if (key == "width") {
01349             winargs.width = (int)val.toFloat() + 2*qApp->style().pixelMetric( QStyle::PM_DefaultFrameWidth ) + 2;
01350             if (winargs.width > screen.width())    // should actually check workspace
01351               winargs.width = screen.width();
01352             if (winargs.width < 100)
01353               winargs.width = 100;
01354           } else {
01355             goto boolargs;
01356           }
01357           continue;
01358         } else {
01359           // leaving away the value gives true
01360           key = s.stripWhiteSpace().lower();
01361           val = "1";
01362         }
01363       boolargs:
01364         if (key == "menubar")
01365           winargs.menuBarVisible = (val == "1" || val == "yes");
01366         else if (key == "toolbar")
01367           winargs.toolBarsVisible = (val == "1" || val == "yes");
01368         else if (key == "location")  // ### missing in WindowArgs
01369           winargs.toolBarsVisible = (val == "1" || val == "yes");
01370         else if (key == "status" || key == "statusbar")
01371           winargs.statusBarVisible = (val == "1" || val == "yes");
01372         else if (key == "resizable")
01373           winargs.resizable = (val == "1" || val == "yes");
01374         else if (key == "fullscreen")
01375           winargs.fullscreen = (val == "1" || val == "yes");
01376       }
01377     }
01378 
01379     KParts::URLArgs uargs;
01380     KHTMLPart *p = part;
01381     uargs.frameName = args.size() > 1 ?
01382                       args[1].toString(exec).qstring()
01383                       : QString("_blank");
01384     if ( uargs.frameName.lower() == "_top" )
01385     {
01386       while ( p->parentPart() )
01387         p = p->parentPart();
01388       Window::retrieveWindow(p)->goURL(exec, url.url(), false /*don't lock history*/);
01389       return Window::retrieve(p);
01390     }
01391     if ( uargs.frameName.lower() == "_parent" )
01392     {
01393       if ( p->parentPart() )
01394         p = p->parentPart();
01395       Window::retrieveWindow(p)->goURL(exec, url.url(), false /*don't lock history*/);
01396       return Window::retrieve(p);
01397     }
01398     if ( uargs.frameName.lower() == "_self")
01399     {
01400       Window::retrieveWindow(p)->goURL(exec, url.url(), false /*don't lock history*/);
01401       return Window::retrieve(p);
01402     }
01403     if ( uargs.frameName.lower() == "replace" )
01404     {
01405       Window::retrieveWindow(p)->goURL(exec, url.url(), true /*lock history*/);
01406       return Window::retrieve(p);
01407     }
01408     uargs.serviceType = "text/html";
01409 
01410     // request window (new or existing if framename is set)
01411     KParts::ReadOnlyPart *newPart = 0L;
01412     emit p->browserExtension()->createNewWindow(KURL(), uargs,winargs,newPart);
01413     if (newPart && ::qt_cast<KHTMLPart*>(newPart)) {
01414       KHTMLPart *khtmlpart = static_cast<KHTMLPart*>(newPart);
01415       //qDebug("opener set to %p (this Window's part) in new Window %p  (this Window=%p)",part,win,window);
01416       khtmlpart->setOpener(p);
01417       khtmlpart->setOpenedByJS(true);
01418       if (khtmlpart->document().isNull()) {
01419         khtmlpart->begin();
01420         khtmlpart->write("<HTML><BODY>");
01421         khtmlpart->end();
01422         if ( p->docImpl() ) {
01423           //kdDebug(6070) << "Setting domain to " << p->docImpl()->domain().string() << endl;
01424           khtmlpart->docImpl()->setDomain( p->docImpl()->domain());
01425           khtmlpart->docImpl()->setBaseURL( p->docImpl()->baseURL() );
01426         }
01427       }
01428       uargs.serviceType = QString::null;
01429       if (uargs.frameName.lower() == "_blank")
01430         uargs.frameName = QString::null;
01431       if (!url.isEmpty())
01432         emit khtmlpart->browserExtension()->openURLRequest(url,uargs);
01433       return Window::retrieve(khtmlpart); // global object
01434     } else
01435       return Undefined();
01436   }
01437 }
01438 
01439 Value WindowFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
01440 {
01441   KJS_CHECK_THIS( Window, thisObj );
01442   Window *window = static_cast<Window *>(thisObj.imp());
01443   QString str, str2;
01444 
01445   KHTMLPart *part = ::qt_cast<KHTMLPart *>(window->m_frame->m_part);
01446   if (!part)
01447     return Undefined();
01448 
01449   KHTMLView *widget = part->view();
01450   Value v = args[0];
01451   UString s = v.toString(exec);
01452   str = s.qstring();
01453 
01454   QString caption;
01455   if (part && !part->url().host().isEmpty())
01456     caption = part->url().host() + " - ";
01457   caption += "JavaScript"; // TODO: i18n
01458   // functions that work everywhere
01459   switch(id) {
01460   case Window::Alert:
01461     if (!widget->dialogsAllowed())
01462       return Undefined();
01463     if ( part && part->xmlDocImpl() )
01464       part->xmlDocImpl()->updateRendering();
01465     if ( part )
01466       emit part->browserExtension()->requestFocus(part);
01467     KMessageBox::error(widget, QStyleSheet::convertFromPlainText(str), caption);
01468     return Undefined();
01469   case Window::Confirm:
01470     if (!widget->dialogsAllowed())
01471       return Undefined();
01472     if ( part && part->xmlDocImpl() )
01473       part->xmlDocImpl()->updateRendering();
01474     if ( part )
01475       emit part->browserExtension()->requestFocus(part);
01476     return Boolean((KMessageBox::warningYesNo(widget, QStyleSheet::convertFromPlainText(str), caption,
01477                                                 KStdGuiItem::ok(), KStdGuiItem::cancel()) == KMessageBox::Yes));
01478   case Window::Prompt:
01479     if (!widget->dialogsAllowed())
01480       return Undefined();
01481     if ( part && part->xmlDocImpl() )
01482       part->xmlDocImpl()->updateRendering();
01483     if ( part )
01484       emit part->browserExtension()->requestFocus(part);
01485     bool ok;
01486     if (args.size() >= 2)
01487       str2 = KInputDialog::getText(caption,
01488                                    QStyleSheet::convertFromPlainText(str),
01489                                    args[1].toString(exec).qstring(), &ok, widget);
01490     else
01491       str2 = KInputDialog::getText(caption,
01492                                    QStyleSheet::convertFromPlainText(str),
01493                                    QString::null, &ok, widget);
01494     if ( ok )
01495         return String(str2);
01496     else
01497         return Null();
01498   case Window::Open:
01499     return window->openWindow(exec, args);
01500   case Window::Navigate:
01501     window->goURL(exec, args[0].toString(exec).qstring(), false /*don't lock history*/);
01502     return Undefined();
01503   case Window::Focus: {
01504     KHTMLSettings::KJSWindowFocusPolicy policy =
01505         part->settings()->windowFocusPolicy(part->url().host());
01506     if(policy == KHTMLSettings::KJSWindowFocusAllow && widget) {
01507       widget->topLevelWidget()->raise();
01508       KWin::deIconifyWindow( widget->topLevelWidget()->winId() );
01509       widget->setActiveWindow();
01510       emit part->browserExtension()->requestFocus(part);
01511     }
01512     return Undefined();
01513   }
01514   case Window::Blur:
01515     // TODO
01516     return Undefined();
01517   };
01518 
01519 
01520   // now unsafe functions..
01521   if (!window->isSafeScript(exec))
01522     return Undefined();
01523 
01524   switch (id) {
01525   case Window::ScrollBy:
01526     if(args.size() == 2 && widget)
01527       widget->scrollBy(args[0].toInt32(exec), args[1].toInt32(exec));
01528     return Undefined();
01529   case Window::Scroll:
01530   case Window::ScrollTo:
01531     if(args.size() == 2 && widget)
01532       widget->setContentsPos(args[0].toInt32(exec), args[1].toInt32(exec));
01533     return Undefined();
01534   case Window::MoveBy: {
01535     KHTMLSettings::KJSWindowMovePolicy policy =
01536         part->settings()->windowMovePolicy(part->url().host());
01537     if(policy == KHTMLSettings::KJSWindowMoveAllow && args.size() == 2 && widget)
01538     {
01539       KParts::BrowserExtension *ext = part->browserExtension();
01540       if (ext) {
01541         QWidget * tl = widget->topLevelWidget();
01542         QRect sg = KGlobalSettings::desktopGeometry(tl);
01543 
01544         QPoint dest = tl->pos() + QPoint( args[0].toInt32(exec), args[1].toInt32(exec) );
01545         // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
01546         if ( dest.x() >= sg.x() && dest.y() >= sg.x() &&
01547              dest.x()+tl->width() <= sg.width()+sg.x() &&
01548              dest.y()+tl->height() <= sg.height()+sg.y() )
01549           emit ext->moveTopLevelWidget( dest.x(), dest.y() );
01550       }
01551     }
01552     return Undefined();
01553   }
01554   case Window::MoveTo: {
01555     KHTMLSettings::KJSWindowMovePolicy policy =
01556         part->settings()->windowMovePolicy(part->url().host());
01557     if(policy == KHTMLSettings::KJSWindowMoveAllow && args.size() == 2 && widget)
01558     {
01559       KParts::BrowserExtension *ext = part->browserExtension();
01560       if (ext) {
01561         QWidget * tl = widget->topLevelWidget();
01562         QRect sg = KGlobalSettings::desktopGeometry(tl);
01563 
01564         QPoint dest( args[0].toInt32(exec)+sg.x(), args[1].toInt32(exec)+sg.y() );
01565         // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
01566         if ( dest.x() >= sg.x() && dest.y() >= sg.y() &&
01567              dest.x()+tl->width() <= sg.width()+sg.x() &&
01568              dest.y()+tl->height() <= sg.height()+sg.y() )
01569         emit ext->moveTopLevelWidget( dest.x(), dest.y() );
01570       }
01571     }
01572     return Undefined();
01573   }
01574   case Window::ResizeBy: {
01575     KHTMLSettings::KJSWindowResizePolicy policy =
01576         part->settings()->windowResizePolicy(part->url().host());
01577     if(policy == KHTMLSettings::KJSWindowResizeAllow
01578             && args.size() == 2 && widget)
01579     {
01580       QWidget * tl = widget->topLevelWidget();
01581       QRect geom = tl->frameGeometry();
01582       window->resizeTo( tl,
01583                         geom.width() + args[0].toInt32(exec),
01584                         geom.height() + args[1].toInt32(exec) );
01585     }
01586     return Undefined();
01587   }
01588   case Window::ResizeTo: {
01589     KHTMLSettings::KJSWindowResizePolicy policy =
01590                part->settings()->windowResizePolicy(part->url().host());
01591     if(policy == KHTMLSettings::KJSWindowResizeAllow
01592                && args.size() == 2 && widget)
01593     {
01594       QWidget * tl = widget->topLevelWidget();
01595       window->resizeTo( tl, args[0].toInt32(exec), args[1].toInt32(exec) );
01596     }
01597     return Undefined();
01598   }
01599   case Window::SetTimeout:
01600   case Window::SetInterval: {
01601     bool singleShot;
01602     int i; // timeout interval
01603     if (args.size() == 0)
01604       return Undefined();
01605     if (args.size() > 1) {
01606       singleShot = (id == Window::SetTimeout);
01607       i = args[1].toInt32(exec);
01608     } else {
01609       // second parameter is missing. Emulate Mozilla behavior.
01610       singleShot = true;
01611       i = 4;
01612     }
01613     if (v.isA(StringType)) {
01614       int r = (const_cast<Window*>(window))->winq->installTimeout(Identifier(s), i, singleShot );
01615       return Number(r);
01616     }
01617     else if (v.isA(ObjectType) && Object::dynamicCast(v).implementsCall()) {
01618       Object func = Object::dynamicCast(v);
01619       List funcArgs;
01620       ListIterator it = args.begin();
01621       int argno = 0;
01622       while (it != args.end()) {
01623     Value arg = it++;
01624     if (argno++ >= 2)
01625         funcArgs.append(arg);
01626       }
01627       if (args.size() < 2)
01628     funcArgs.append(Number(i));
01629       int r = (const_cast<Window*>(window))->winq->installTimeout(func, funcArgs, i, singleShot );
01630       return Number(r);
01631     }
01632     else
01633       return Undefined();
01634   }
01635   case Window::ClearTimeout:
01636   case Window::ClearInterval:
01637     (const_cast<Window*>(window))->winq->clearTimeout(v.toInt32(exec));
01638     return Undefined();
01639   case Window::Close: {
01640     /* From http://developer.netscape.com/docs/manuals/js/client/jsref/window.htm :
01641        The close method closes only windows opened by JavaScript using the open method.
01642        If you attempt to close any other window, a confirm is generated, which
01643        lets the user choose whether the window closes.
01644        This is a security feature to prevent "mail bombs" containing self.close().
01645        However, if the window has only one document (the current one) in its
01646        session history, the close is allowed without any confirm. This is a
01647        special case for one-off windows that need to open other windows and
01648        then dispose of themselves.
01649     */
01650     bool doClose = false;
01651     if (!part->openedByJS())
01652     {
01653       // To conform to the SPEC, we only ask if the window
01654       // has more than one entry in the history (NS does that too).
01655       History history(exec,part);
01656 
01657       if ( history.get( exec, "length" ).toInt32(exec) <= 1 )
01658       {
01659         doClose = true;
01660       }
01661       else
01662       {
01663         // Can we get this dialog with tabs??? Does it close the window or the tab in that case?
01664         emit part->browserExtension()->requestFocus(part);
01665         if ( KMessageBox::questionYesNo( window->part()->widget(), i18n("Close window?"), i18n("Confirmation Required") )
01666              == KMessageBox::Yes )
01667           doClose = true;
01668       }
01669     }
01670     else
01671       doClose = true;
01672 
01673     if (doClose)
01674     {
01675       // If this is the current window (the one the interpreter runs in),
01676       // then schedule a delayed close (so that the script terminates first).
01677       // But otherwise, close immediately. This fixes w=window.open("","name");w.close();window.open("name");
01678       if ( Window::retrieveActive(exec) == window ) {
01679         if (widget) {
01680           // quit all dialogs of this view
01681           // this fixes 'setTimeout('self.close()',1000); alert("Hi");' crash
01682           widget->closeChildDialogs();
01683         }
01684         //kdDebug() << "scheduling delayed close"  << endl;
01685         // We'll close the window at the end of the script execution
01686         Window* w = const_cast<Window*>(window);
01687         w->m_delayed.append( Window::DelayedAction( Window::DelayedClose ) );
01688       } else {
01689         //kdDebug() << "closing NOW"  << endl;
01690         (const_cast<Window*>(window))->closeNow();
01691       }
01692     }
01693     return Undefined();
01694   }
01695   case Window::Print:
01696     if ( widget ) {
01697       // ### TODO emit onbeforeprint event
01698       widget->print();
01699       // ### TODO emit onafterprint event
01700     }
01701   case Window::CaptureEvents:
01702   case Window::ReleaseEvents:
01703     // Do nothing for now. These are NS-specific legacy calls.
01704     break;
01705   case Window::AddEventListener: {
01706         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
01707         if (listener) {
01708         DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl *>(part->document().handle());
01709             docimpl->addWindowEventListener(DOM::EventImpl::typeToId(args[0].toString(exec).string()),listener,args[2].toBoolean(exec));
01710         }
01711         return Undefined();
01712     }
01713   case Window::RemoveEventListener: {
01714         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
01715         if (listener) {
01716         DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl *>(part->document().handle());
01717             docimpl->removeWindowEventListener(DOM::EventImpl::typeToId(args[0].toString(exec).string()),listener,args[2].toBoolean(exec));
01718         }
01719         return Undefined();
01720     }
01721 
01722   }
01723   return Undefined();
01724 }
01725 
01727 
01728 // KDE 4: Make those parameters const ... &
01729 ScheduledAction::ScheduledAction(Object _func, List _args, QTime _nextTime, int _interval, bool _singleShot,
01730                   int _timerId)
01731 {
01732   //kdDebug(6070) << "ScheduledAction::ScheduledAction(isFunction) " << this << endl;
01733   func = static_cast<ObjectImp*>(_func.imp());
01734   args = _args;
01735   isFunction = true;
01736   singleShot = _singleShot;
01737   nextTime = _nextTime;
01738   interval = _interval;
01739   executing = false;
01740   timerId = _timerId;
01741 }
01742 
01743 // KDE 4: Make it const QString &
01744 ScheduledAction::ScheduledAction(QString _code, QTime _nextTime, int _interval, bool _singleShot, int _timerId)
01745 {
01746   //kdDebug(6070) << "ScheduledAction::ScheduledAction(!isFunction) " << this << endl;
01747   //func = 0;
01748   //args = 0;
01749   func = 0;
01750   code = _code;
01751   isFunction = false;
01752   singleShot = _singleShot;
01753   nextTime = _nextTime;
01754   interval = _interval;
01755   executing = false;
01756   timerId = _timerId;
01757 }
01758 
01759 void ScheduledAction::execute(Window *window)
01760 {
01761   KHTMLPart *part = ::qt_cast<KHTMLPart *>(window->m_frame->m_part);
01762   if (!part)
01763     return;
01764   ScriptInterpreter *interpreter = static_cast<ScriptInterpreter *>(part->jScript()->interpreter());
01765 
01766   interpreter->setProcessingTimerCallback(true);
01767 
01768   //kdDebug(6070) << "ScheduledAction::execute " << this << endl;
01769   if (isFunction) {
01770     if (func->implementsCall()) {
01771       // #### check this
01772       Q_ASSERT( part );
01773       if ( part )
01774       {
01775         KJS::Interpreter *interpreter = part->jScript()->interpreter();
01776         ExecState *exec = interpreter->globalExec();
01777         Q_ASSERT( window == interpreter->globalObject().imp() );
01778         Object obj( window );
01779         func->call(exec,obj,args); // note that call() creates its own execution state for the func call
01780         if (exec->hadException())
01781           exec->clearException();
01782 
01783         // Update our document's rendering following the execution of the timeout callback.
01784         part->document().updateRendering();
01785       }
01786     }
01787   }
01788   else {
01789     part->executeScript(DOM::Node(), code);
01790   }
01791 
01792   interpreter->setProcessingTimerCallback(false);
01793 }
01794 
01795 void ScheduledAction::mark()
01796 {
01797   if (func && !func->marked())
01798     func->mark();
01799   args.mark();
01800 }
01801 
01802 ScheduledAction::~ScheduledAction()
01803 {
01804   //kdDebug(6070) << "ScheduledAction::~ScheduledAction " << this << endl;
01805 }
01806 
01808 
01809 WindowQObject::WindowQObject(Window *w)
01810   : parent(w)
01811 {
01812   //kdDebug(6070) << "WindowQObject::WindowQObject " << this << endl;
01813   if ( !parent->m_frame )
01814       kdDebug(6070) << "WARNING: null part in " << k_funcinfo << endl;
01815   else
01816       connect( parent->m_frame, SIGNAL( destroyed() ),
01817                this, SLOT( parentDestroyed() ) );
01818   pausedTime = 0;
01819   lastTimerId = 0;
01820 }
01821 
01822 WindowQObject::~WindowQObject()
01823 {
01824   //kdDebug(6070) << "WindowQObject::~WindowQObject " << this << endl;
01825   parentDestroyed(); // reuse same code
01826 }
01827 
01828 void WindowQObject::parentDestroyed()
01829 {
01830   killTimers();
01831 
01832   QPtrListIterator<ScheduledAction> it(scheduledActions);
01833   for (; it.current(); ++it)
01834     delete it.current();
01835   scheduledActions.clear();
01836 }
01837 
01838 int WindowQObject::installTimeout(const Identifier &handler, int t, bool singleShot)
01839 {
01840   int id = ++lastTimerId;
01841   if (t < 10) t = 10;
01842   QTime nextTime = QTime::currentTime().addMSecs(-pausedTime).addMSecs(t);
01843   ScheduledAction *action = new ScheduledAction(handler.qstring(),nextTime,t,singleShot,id);
01844   scheduledActions.append(action);
01845   setNextTimer();
01846   return id;
01847 }
01848 
01849 int WindowQObject::installTimeout(const Value &func, List args, int t, bool singleShot)
01850 {
01851   Object objFunc = Object::dynamicCast( func );
01852   if (!objFunc.isValid())
01853     return 0;
01854   int id = ++lastTimerId;
01855   if (t < 10) t = 10;
01856   QTime nextTime = QTime::currentTime().addMSecs(-pausedTime).addMSecs(t);
01857   ScheduledAction *action = new ScheduledAction(objFunc,args,nextTime,t,singleShot,id);
01858   scheduledActions.append(action);
01859   setNextTimer();
01860   return id;
01861 }
01862 
01863 void WindowQObject::clearTimeout(int timerId)
01864 {
01865   QPtrListIterator<ScheduledAction> it(scheduledActions);
01866   for (; it.current(); ++it) {
01867     ScheduledAction *action = it.current();
01868     if (action->timerId == timerId) {
01869       scheduledActions.removeRef(action);
01870       if (!action->executing)
01871     delete action;
01872       return;
01873     }
01874   }
01875 }
01876 
01877 bool WindowQObject::hasTimers() const
01878 {
01879   return scheduledActions.count();
01880 }
01881 
01882 void WindowQObject::mark()
01883 {
01884   QPtrListIterator<ScheduledAction> it(scheduledActions);
01885   for (; it.current(); ++it)
01886     it.current()->mark();
01887 }
01888 
01889 void WindowQObject::timerEvent(QTimerEvent *)
01890 {
01891   killTimers();
01892 
01893   if (scheduledActions.isEmpty())
01894     return;
01895 
01896   QTime currentActual = QTime::currentTime();
01897   QTime currentAdjusted = currentActual.addMSecs(-pausedTime);
01898 
01899   // Work out which actions are to be executed. We take a separate copy of
01900   // this list since the main one may be modified during action execution
01901   QPtrList<ScheduledAction> toExecute;
01902   QPtrListIterator<ScheduledAction> it(scheduledActions);
01903   for (; it.current(); ++it)
01904     if (currentAdjusted >= it.current()->nextTime)
01905       toExecute.append(it.current());
01906 
01907   // ### verify that the window can't be closed (and action deleted) during execution
01908   it = QPtrListIterator<ScheduledAction>(toExecute);
01909   for (; it.current(); ++it) {
01910     ScheduledAction *action = it.current();
01911     if (!scheduledActions.containsRef(action)) // removed by clearTimeout()
01912       continue;
01913 
01914     action->executing = true; // prevent deletion in clearTimeout()
01915 
01916     if (action->singleShot)
01917       scheduledActions.removeRef(action);
01918     if (parent->part())
01919       action->execute(parent);
01920 
01921     action->executing = false;
01922 
01923     if (!scheduledActions.containsRef(action))
01924       delete action;
01925     else
01926       action->nextTime = action->nextTime.addMSecs(action->interval);
01927   }
01928 
01929   pausedTime += currentActual.msecsTo(QTime::currentTime());
01930 
01931   // Work out when next event is to occur
01932   setNextTimer();
01933 }
01934 
01935 void WindowQObject::setNextTimer()
01936 {
01937   if (scheduledActions.isEmpty())
01938     return;
01939 
01940   QPtrListIterator<ScheduledAction> it(scheduledActions);
01941   QTime nextTime = it.current()->nextTime;
01942   for (++it; it.current(); ++it)
01943     if (nextTime > it.current()->nextTime)
01944       nextTime = it.current()->nextTime;
01945 
01946   QTime nextTimeActual = nextTime.addMSecs(pausedTime);
01947   int nextInterval = QTime::currentTime().msecsTo(nextTimeActual);
01948   if (nextInterval < 0)
01949     nextInterval = 0;
01950   startTimer(nextInterval);
01951 }
01952 
01953 void WindowQObject::timeoutClose()
01954 {
01955   parent->closeNow();
01956 }
01957 
01958 Value FrameArray::get(ExecState *exec, const Identifier &p) const
01959 {
01960 #ifdef KJS_VERBOSE
01961   kdDebug(6070) << "FrameArray::get " << p.qstring() << " part=" << (void*)part << endl;
01962 #endif
01963   if (part.isNull())
01964     return Undefined();
01965 
01966   QPtrList<KParts::ReadOnlyPart> frames = part->frames();
01967   unsigned int len = frames.count();
01968   if (p == lengthPropertyName)
01969     return Number(len);
01970   else if (p== "location") // non-standard property, but works in NS and IE
01971   {
01972     Object obj = Object::dynamicCast( Window::retrieve( part ) );
01973     if ( !obj.isNull() )
01974       return obj.get( exec, "location" );
01975     return Undefined();
01976   }
01977 
01978   // check for the name or number
01979   KParts::ReadOnlyPart *frame = part->findFramePart(p.qstring());
01980   if (!frame) {
01981     bool ok;
01982     unsigned int i = p.toArrayIndex(&ok);
01983     if (ok && i < len)
01984       frame = frames.at(i);
01985   }
01986 
01987   // we are potentially fetching a reference to a another Window object here.
01988   // i.e. we may be accessing objects from another interpreter instance.
01989   // Therefore we have to be a bit careful with memory management.
01990   if (frame) {
01991     return Window::retrieve(frame);
01992   }
01993 
01994   return ObjectImp::get(exec, p);
01995 }
01996 
01998 
01999 const ClassInfo Location::info = { "Location", 0, &LocationTable, 0 };
02000 /*
02001 @begin LocationTable 11
02002   hash      Location::Hash      DontDelete
02003   host      Location::Host      DontDelete
02004   hostname  Location::Hostname  DontDelete
02005   href      Location::Href      DontDelete
02006   pathname  Location::Pathname  DontDelete
02007   port      Location::Port      DontDelete
02008   protocol  Location::Protocol  DontDelete
02009   search    Location::Search    DontDelete
02010   [[==]]    Location::EqualEqual    DontDelete|ReadOnly
02011   assign    Location::Assign    DontDelete|Function 1
02012   toString  Location::ToString  DontDelete|Function 0
02013   replace   Location::Replace   DontDelete|Function 1
02014   reload    Location::Reload    DontDelete|Function 0
02015 @end
02016 */
02017 IMPLEMENT_PROTOFUNC_DOM(LocationFunc)
02018 Location::Location(khtml::ChildFrame *f) : m_frame(f)
02019 {
02020   //kdDebug(6070) << "Location::Location " << this << " m_part=" << (void*)m_part << endl;
02021 }
02022 
02023 Location::~Location()
02024 {
02025   //kdDebug(6070) << "Location::~Location " << this << " m_part=" << (void*)m_part << endl;
02026 }
02027 
02028 KParts::ReadOnlyPart *Location::part() const {
02029   return m_frame ? static_cast<KParts::ReadOnlyPart *>(m_frame->m_part) : 0L;
02030 }
02031 
02032 Value Location::get(ExecState *exec, const Identifier &p) const
02033 {
02034 #ifdef KJS_VERBOSE
02035   kdDebug(6070) << "Location::get " << p.qstring() << " m_part=" << (void*)m_frame->m_part << endl;
02036 #endif
02037 
02038   if (m_frame.isNull() || m_frame->m_part.isNull())
02039     return Undefined();
02040 
02041   const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
02042 
02043   // properties that work on all Location objects
02044   if ( entry && entry->value == Replace )
02045       return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
02046 
02047   // XSS check
02048   const Window* window = Window::retrieveWindow( m_frame->m_part );
02049   if ( !window || !window->isSafeScript(exec) )
02050     return Undefined();
02051 
02052   KURL url = m_frame->m_part->url();
02053   if (entry)
02054     switch (entry->value) {
02055     case Hash:
02056       return String( url.ref().isNull() ? QString("") : "#" + url.ref() );
02057     case Host: {
02058       UString str = url.host();
02059       if (url.port())
02060         str += ":" + QString::number((int)url.port());
02061       return String(str);
02062       // Note: this is the IE spec. The NS spec swaps the two, it says
02063       // "The hostname property is the concatenation of the host and port properties, separated by a colon."
02064       // Bleh.
02065     }
02066     case Hostname:
02067       return String( url.host() );
02068     case Href:
02069       if (!url.hasPath())
02070         return String( url.prettyURL()+"/" );
02071       else
02072         return String( url.prettyURL() );
02073     case Pathname:
02074       return String( url.path().isEmpty() ? QString("/") : url.path() );
02075     case Port:
02076       return String( url.port() ? QString::number((int)url.port()) : QString::fromLatin1("") );
02077     case Protocol:
02078       return String( url.protocol()+":" );
02079     case Search:
02080       return String( url.query() );
02081     case EqualEqual: // [[==]]
02082       return String(toString(exec));
02083     case ToString:
02084       return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
02085     }
02086   // Look for overrides
02087   ValueImp * val = ObjectImp::getDirect(p);
02088   if (val)
02089     return Value(val);
02090   if (entry && (entry->attr & Function))
02091     return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
02092 
02093   return Undefined();
02094 }
02095 
02096 void Location::put(ExecState *exec, const Identifier &p, const Value &v, int attr)
02097 {
02098 #ifdef KJS_VERBOSE
02099   kdDebug(6070) << "Location::put " << p.qstring() << " m_part=" << (void*)m_frame->m_part << endl;
02100 #endif
02101   if (m_frame.isNull() || m_frame->m_part.isNull())
02102     return;
02103 
02104   // XSS check
02105   const Window* window = Window::retrieveWindow( m_frame->m_part );
02106   if ( !window || !window->isSafeScript(exec) )
02107     return;
02108 
02109   QString str = v.toString(exec).qstring();
02110   KURL url = m_frame->m_part->url();
02111   const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
02112   if (entry)
02113     switch (entry->value) {
02114     case Href: {
02115       KHTMLPart* p =::qt_cast<KHTMLPart*>(Window::retrieveActive(exec)->part());
02116       if ( p )
02117         url = p->htmlDocument().completeURL( str ).string();
02118       else
02119         url = str;
02120       break;
02121     }
02122     case Hash:
02123       // when the hash is already the same ignore it
02124       if (str == url.ref()) return;
02125       url.setRef(str);
02126       break;
02127     case Host: {
02128       QString host = str.left(str.find(":"));
02129       QString port = str.mid(str.find(":")+1);
02130       url.setHost(host);
02131       url.setPort(port.toUInt());
02132       break;
02133     }
02134     case Hostname:
02135       url.setHost(str);
02136       break;
02137     case Pathname:
02138       url.setPath(str);
02139       break;
02140     case Port:
02141       url.setPort(str.toUInt());
02142       break;
02143     case Protocol:
02144       url.setProtocol(str);
02145       break;
02146     case Search:
02147       url.setQuery(str);
02148       break;
02149     }
02150   else {
02151     ObjectImp::put(exec, p, v, attr);
02152     return;
02153   }
02154 
02155   Window::retrieveWindow(m_frame->m_part)->goURL(exec, url.url(), false /* don't lock history*/ );
02156 }
02157 
02158 Value Location::toPrimitive(ExecState *exec, Type) const
02159 {
02160   if (m_frame) {
02161     Window* window = Window::retrieveWindow( m_frame->m_part );
02162     if ( window && window->isSafeScript(exec) )
02163       return String(toString(exec));
02164   }
02165   return Undefined();
02166 }
02167 
02168 UString Location::toString(ExecState *exec) const
02169 {
02170   if (m_frame) {
02171     Window* window = Window::retrieveWindow( m_frame->m_part );
02172     if ( window && window->isSafeScript(exec) )
02173     {
02174       if (!m_frame->m_part->url().hasPath())
02175         return m_frame->m_part->url().prettyURL()+"/";
02176       else
02177         return m_frame->m_part->url().prettyURL();
02178     }
02179   }
02180   return "";
02181 }
02182 
02183 Value LocationFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
02184 {
02185   KJS_CHECK_THIS( Location, thisObj );
02186   Location *location = static_cast<Location *>(thisObj.imp());
02187   KParts::ReadOnlyPart *part = location->part();
02188 
02189   if (!part) return Undefined();
02190 
02191   Window* window = Window::retrieveWindow(part);
02192 
02193   if ( !window->isSafeScript(exec) && id != Location::Replace)
02194       return Undefined();
02195 
02196   switch (id) {
02197   case Location::Assign:
02198   case Location::Replace:
02199     Window::retrieveWindow(part)->goURL(exec, args[0].toString(exec).qstring(),
02200             id == Location::Replace);
02201     break;
02202   case Location::Reload: {
02203     KHTMLPart *khtmlpart = ::qt_cast<KHTMLPart *>(part);
02204     if (part)
02205       khtmlpart->scheduleRedirection(-1, part->url().url(), true/*lock history*/);
02206     break;
02207   }
02208   case Location::ToString:
02209     return String(location->toString(exec));
02210   }
02211   return Undefined();
02212 }
02213 
02215 
02216 const ClassInfo External::info = { "External", 0, 0, 0 };
02217 /*
02218 @begin ExternalTable 4
02219   addFavorite   External::AddFavorite   DontDelete|Function 1
02220 @end
02221 */
02222 IMPLEMENT_PROTOFUNC_DOM(ExternalFunc)
02223 
02224 Value External::get(ExecState *exec, const Identifier &p) const
02225 {
02226   return lookupGetFunction<ExternalFunc,ObjectImp>(exec,p,&ExternalTable,this);
02227 }
02228 
02229 Value ExternalFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
02230 {
02231   KJS_CHECK_THIS( External, thisObj );
02232   External *external = static_cast<External *>(thisObj.imp());
02233 
02234   KHTMLPart *part = external->part;
02235   if (!part)
02236     return Undefined();
02237 
02238   KHTMLView *widget = part->view();
02239 
02240   switch (id) {
02241   case External::AddFavorite:
02242   {
02243     if (!widget->dialogsAllowed())
02244       return Undefined();
02245     part->xmlDocImpl()->updateRendering();
02246     if (args.size() != 1 && args.size() != 2)
02247       return Undefined();
02248 
02249     QString url = args[0].toString(exec).qstring();
02250     QString title;
02251     if (args.size() == 2)
02252       title = args[1].toString(exec).qstring();
02253 
02254     // AK - don't do anything yet, for the moment i
02255     // just wanted the base js handling code in cvs
02256     return Undefined();
02257 
02258     QString question;
02259     if ( title.isEmpty() )
02260       question = i18n("Do you want a bookmark pointing to the location \"%1\" to be added to your collection?")
02261                  .arg(url);
02262     else
02263       question = i18n("Do you want a bookmark pointing to the location \"%1\" titled \"%2\" to be added to your collection?")
02264                  .arg(url).arg(title);
02265 
02266     emit part->browserExtension()->requestFocus(part);
02267 
02268     QString caption;
02269     if (!part->url().host().isEmpty())
02270        caption = part->url().host() + " - ";
02271     caption += i18n("JavaScript Attempted Bookmark Insert");
02272 
02273     if (KMessageBox::warningYesNo(
02274           widget, question, caption,
02275           i18n("Insert"), i18n("Disallow")) == KMessageBox::Yes)
02276     {
02277       KBookmarkManager *mgr = KBookmarkManager::userBookmarksManager();
02278       mgr->addBookmarkDialog(url,title);
02279     }
02280     break;
02281   }
02282   default:
02283     return Undefined();
02284   }
02285 
02286   return Undefined();
02287 }
02288 
02290 
02291 const ClassInfo History::info = { "History", 0, 0, 0 };
02292 /*
02293 @begin HistoryTable 4
02294   length    History::Length     DontDelete|ReadOnly
02295   back      History::Back       DontDelete|Function 0
02296   forward   History::Forward    DontDelete|Function 0
02297   go        History::Go     DontDelete|Function 1
02298 @end
02299 */
02300 IMPLEMENT_PROTOFUNC_DOM(HistoryFunc)
02301 
02302 Value History::get(ExecState *exec, const Identifier &p) const
02303 {
02304   return lookupGet<HistoryFunc,History,ObjectImp>(exec,p,&HistoryTable,this);
02305 }
02306 
02307 Value History::getValueProperty(ExecState *, int token) const
02308 {
02309   // if previous or next is implemented, make sure its not a major
02310   // privacy leak (see i.e. http://security.greymagic.com/adv/gm005-op/)
02311   switch (token) {
02312   case Length:
02313   {
02314     KParts::BrowserExtension *ext = part->browserExtension();
02315     if ( !ext )
02316       return Number( 0 );
02317 
02318     KParts::BrowserInterface *iface = ext->browserInterface();
02319     if ( !iface )
02320       return Number( 0 );
02321 
02322     QVariant length = iface->property( "historyLength" );
02323 
02324     if ( length.type() != QVariant::UInt )
02325       return Number( 0 );
02326 
02327     return Number( length.toUInt() );
02328   }
02329   default:
02330     kdDebug(6070) << "WARNING: Unhandled token in History::getValueProperty : " << token << endl;
02331     return Undefined();
02332   }
02333 }
02334 
02335 Value HistoryFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
02336 {
02337   KJS_CHECK_THIS( History, thisObj );
02338   History *history = static_cast<History *>(thisObj.imp());
02339 
02340   Value v = args[0];
02341   Number n;
02342   if(!v.isNull())
02343     n = v.toInteger(exec);
02344 
02345   int steps;
02346   switch (id) {
02347   case History::Back:
02348     steps = -1;
02349     break;
02350   case History::Forward:
02351     steps = 1;
02352     break;
02353   case History::Go:
02354     steps = n.intValue();
02355     break;
02356   default:
02357     return Undefined();
02358   }
02359 
02360   // Special case for go(0) from a frame -> reload only the frame
02361   // go(i!=0) from a frame navigates into the history of the frame only,
02362   // in both IE and NS (but not in Mozilla).... we can't easily do that
02363   // in Konqueror...
02364   if (!steps) // add && history->part->parentPart() to get only frames, but doesn't matter
02365   {
02366     history->part->openURL( history->part->url() ); 
02367   } else
02368   {
02369     // Delay it.
02370     // Testcase: history.back(); alert("hello");
02371     Window* window = Window::retrieveWindow( history->part );
02372     window->delayedGoHistory( steps );
02373   }
02374   return Undefined();
02375 }
02376 
02378 
02379 #ifdef Q_WS_QWS
02380 
02381 const ClassInfo Konqueror::info = { "Konqueror", 0, 0, 0 };
02382 
02383 bool Konqueror::hasProperty(ExecState *exec, const Identifier &p) const
02384 {
02385   if ( p.qstring().startsWith( "goHistory" ) ) return false;
02386 
02387   return true;
02388 }
02389 
02390 Value Konqueror::get(ExecState *exec, const Identifier &p) const
02391 {
02392   if ( p == "goHistory" || part->url().protocol() != "http" || part->url().host() != "localhost" )
02393     return Undefined();
02394 
02395   KParts::BrowserExtension *ext = part->browserExtension();
02396   if ( ext ) {
02397     KParts::BrowserInterface *iface = ext->browserInterface();
02398     if ( iface ) {
02399       QVariant prop = iface->property( p.qstring().latin1() );
02400 
02401       if ( prop.isValid() ) {
02402         switch( prop.type() ) {
02403         case QVariant::Int:
02404           return Number( prop.toInt() );
02405         case QVariant::String:
02406           return String( prop.toString() );
02407         default:
02408           break;
02409         }
02410       }
02411     }
02412   }
02413 
02414   return Value( new KonquerorFunc(this, p.qstring().latin1() ) );
02415 }
02416 
02417 Value KonquerorFunc::tryCall(ExecState *exec, Object &, const List &args)
02418 {
02419   KParts::BrowserExtension *ext = konqueror->part->browserExtension();
02420 
02421   if(!ext)
02422     return Undefined();
02423 
02424   KParts::BrowserInterface *iface = ext->browserInterface();
02425 
02426   if ( !iface )
02427     return Undefined();
02428 
02429   QCString n = m_name.data();
02430   n += "()";
02431   iface->callMethod( n.data(), QVariant() );
02432 
02433   return Undefined();
02434 }
02435 
02436 UString Konqueror::toString(ExecState *) const
02437 {
02438   return UString("[object Konqueror]");
02439 }
02440 
02441 #endif
02442 
02443 
02444 #include "kjs_window.moc"
KDE Logo
This file is part of the documentation for khtml Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Jul 22 10:18:36 2005 by doxygen 1.3.6 written by Dimitri van Heesch, © 1997-2003