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 Harri Porten (porten@kde.org)
00005  *
00006  *  This library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Library General Public
00008  *  License as published by the Free Software Foundation; either
00009  *  version 2 of the License, or (at your option) any later version.
00010  *
00011  *  This library is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  *  Library General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU Library General Public
00017  *  License along with this library; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  */
00020 
00021 #include <qstylesheet.h>
00022 #include <qtimer.h>
00023 #include <qpaintdevicemetrics.h>
00024 #include <qapplication.h>
00025 #include <kdebug.h>
00026 #include <kmessagebox.h>
00027 #include <klineeditdlg.h>
00028 #include <klocale.h>
00029 #include <kparts/browserinterface.h>
00030 #include <kwin.h>
00031 #include <kwinmodule.h>
00032 #include <kconfig.h>
00033 #include <assert.h>
00034 #include <qstyle.h>
00035 #include <qobjectlist.h>
00036 
00037 #include "kjs_proxy.h"
00038 #include "kjs_window.h"
00039 #include "kjs_navigator.h"
00040 #include "kjs_html.h"
00041 #include "kjs_range.h"
00042 #include "kjs_traversal.h"
00043 #include "kjs_css.h"
00044 #include "kjs_events.h"
00045 
00046 #include "khtmlview.h"
00047 #include "khtml_part.h"
00048 #include "khtml_settings.h"
00049 #include "xml/dom2_eventsimpl.h"
00050 #include "xml/dom_docimpl.h"
00051 #include "html/html_documentimpl.h"
00052 
00053 using namespace KJS;
00054 
00055 namespace KJS {
00056 
00058 
00059   class History : public ObjectImp {
00060     friend class HistoryFunc;
00061   public:
00062     History(ExecState *exec, KHTMLPart *p)
00063       : ObjectImp(exec->interpreter()->builtinObjectPrototype()), part(p) { }
00064     virtual Value get(ExecState *exec, const UString &propertyName) const;
00065     Value getValueProperty(ExecState *exec, int token) const;
00066     virtual const ClassInfo* classInfo() const { return &info; }
00067     static const ClassInfo info;
00068     enum { Back, Forward, Go, Length };
00069   private:
00070     QGuardedPtr<KHTMLPart> part;
00071   };
00072 
00073   class FrameArray : public ObjectImp {
00074   public:
00075     FrameArray(ExecState *exec, KHTMLPart *p)
00076       : ObjectImp(exec->interpreter()->builtinObjectPrototype()), part(p) { }
00077     virtual Value get(ExecState *exec, const UString &propertyName) const;
00078   private:
00079     QGuardedPtr<KHTMLPart> part;
00080   };
00081 
00082 #ifdef Q_WS_QWS
00083   class KonquerorFunc : public DOMFunction {
00084   public:
00085     KonquerorFunc(const Konqueror* k, const char* name)
00086       : DOMFunction(), konqueror(k), m_name(name) { }
00087     virtual Value tryCall(ExecState *exec, Object &thisObj, const List &args);
00088 
00089   private:
00090     const Konqueror* konqueror;
00091     QCString m_name;
00092   };
00093 #endif
00094 }; // namespace KJS
00095 
00096 #include "kjs_window.lut.h"
00097 
00099 
00100 // table for screen object
00101 /*
00102 @begin ScreenTable 7
00103   height        Screen::Height      DontEnum|ReadOnly
00104   width         Screen::Width       DontEnum|ReadOnly
00105   colorDepth    Screen::ColorDepth  DontEnum|ReadOnly
00106   pixelDepth    Screen::PixelDepth  DontEnum|ReadOnly
00107   availLeft     Screen::AvailLeft   DontEnum|ReadOnly
00108   availTop      Screen::AvailTop    DontEnum|ReadOnly
00109   availHeight   Screen::AvailHeight DontEnum|ReadOnly
00110   availWidth    Screen::AvailWidth  DontEnum|ReadOnly
00111 @end
00112 */
00113 
00114 const ClassInfo Screen::info = { "Screen", 0, &ScreenTable, 0 };
00115 
00116 // We set the object prototype so that toString is implemented
00117 Screen::Screen(ExecState *exec)
00118   : ObjectImp(exec->interpreter()->builtinObjectPrototype()) {}
00119 
00120 Value Screen::get(ExecState *exec, const UString &p) const
00121 {
00122 #ifdef KJS_VERBOSE
00123   kdDebug(6070) << "Screen::get " << p.qstring() << endl;
00124 #endif
00125   return lookupGetValue<Screen,ObjectImp>(exec,p,&ScreenTable,this);
00126 }
00127 
00128 Value Screen::getValueProperty(ExecState *exec, int token) const
00129 {
00130   KWinModule info;
00131   QWidget *thisWidget = Window::retrieveActive(exec)->part()->view();
00132   QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(thisWidget));
00133 
00134   switch( token ) {
00135   case Height:
00136     return Number(sg.height());
00137   case Width:
00138     return Number(sg.width());
00139   case ColorDepth:
00140   case PixelDepth: {
00141     QPaintDeviceMetrics m(QApplication::desktop());
00142     return Number(m.depth());
00143   }
00144   case AvailLeft: {
00145     QRect clipped = info.workArea().intersect(sg);
00146     return Number(clipped.x()-sg.x());
00147   }
00148   case AvailTop: {
00149     QRect clipped = info.workArea().intersect(sg);
00150     return Number(clipped.y()-sg.y());
00151   }
00152   case AvailHeight: {
00153     QRect clipped = info.workArea().intersect(sg);
00154     return Number(clipped.height());
00155   }
00156   case AvailWidth: {
00157     QRect clipped = info.workArea().intersect(sg);
00158     return Number(clipped.width());
00159   }
00160   default:
00161     kdWarning(6070) << "Screen::getValueProperty unhandled token " << token << endl;
00162     return Undefined();
00163   }
00164 }
00165 
00167 
00168 const ClassInfo Window::info = { "Window", 0, &WindowTable, 0 };
00169 
00170 /*
00171 @begin WindowTable 86
00172   closed    Window::Closed      DontDelete|ReadOnly
00173   crypto    Window::Crypto      DontDelete|ReadOnly
00174   defaultStatus Window::DefaultStatus   DontDelete
00175   defaultstatus Window::DefaultStatus   DontDelete
00176   status    Window::Status      DontDelete
00177   document  Window::Document    DontDelete|ReadOnly
00178   Node      Window::Node        DontDelete
00179   Event     Window::EventCtor   DontDelete
00180   Range     Window::Range       DontDelete
00181   NodeFilter    Window::NodeFilter  DontDelete
00182   DOMException  Window::DOMException    DontDelete
00183   CSSRule   Window::CSSRule     DontDelete
00184   frames    Window::Frames      DontDelete|ReadOnly
00185   history   Window::_History    DontDelete|ReadOnly
00186   event     Window::Event       DontDelete|ReadOnly
00187   innerHeight   Window::InnerHeight DontDelete|ReadOnly
00188   innerWidth    Window::InnerWidth  DontDelete|ReadOnly
00189   length    Window::Length      DontDelete|ReadOnly
00190   location  Window::_Location   DontDelete
00191   name      Window::Name        DontDelete
00192   navigator Window::_Navigator  DontDelete|ReadOnly
00193   clientInformation Window::ClientInformation   DontDelete|ReadOnly
00194   konqueror Window::_Konqueror  DontDelete|ReadOnly
00195   offscreenBuffering    Window::OffscreenBuffering  DontDelete|ReadOnly
00196   opener    Window::Opener      DontDelete|ReadOnly
00197   outerHeight   Window::OuterHeight DontDelete|ReadOnly
00198   outerWidth    Window::OuterWidth  DontDelete|ReadOnly
00199   pageXOffset   Window::PageXOffset DontDelete|ReadOnly
00200   pageYOffset   Window::PageYOffset DontDelete|ReadOnly
00201   parent    Window::Parent      DontDelete|ReadOnly
00202   personalbar   Window::Personalbar DontDelete|ReadOnly
00203   screenX   Window::ScreenX     DontDelete|ReadOnly
00204   screenY   Window::ScreenY     DontDelete|ReadOnly
00205   scrollbars    Window::Scrollbars  DontDelete|ReadOnly
00206   scroll    Window::Scroll      DontDelete|Function 2
00207   scrollBy  Window::ScrollBy    DontDelete|Function 2
00208   scrollTo  Window::ScrollTo    DontDelete|Function 2
00209   moveBy    Window::MoveBy      DontDelete|Function 2
00210   moveTo    Window::MoveTo      DontDelete|Function 2
00211   resizeBy  Window::ResizeBy    DontDelete|Function 2
00212   resizeTo  Window::ResizeTo    DontDelete|Function 2
00213   self      Window::Self        DontDelete|ReadOnly
00214   window    Window::_Window     DontDelete|ReadOnly
00215   top       Window::Top     DontDelete|ReadOnly
00216   screen    Window::_Screen     DontDelete|ReadOnly
00217   Image     Window::Image       DontDelete|ReadOnly
00218   Option    Window::Option      DontDelete|ReadOnly
00219   alert     Window::Alert       DontDelete|Function 1
00220   confirm   Window::Confirm     DontDelete|Function 1
00221   prompt    Window::Prompt      DontDelete|Function 2
00222   open      Window::Open        DontDelete|Function 3
00223   setTimeout    Window::SetTimeout  DontDelete|Function 2
00224   clearTimeout  Window::ClearTimeout    DontDelete|Function 1
00225   focus     Window::Focus       DontDelete|Function 0
00226   blur      Window::Blur        DontDelete|Function 0
00227   close     Window::Close       DontDelete|Function 0
00228   setInterval   Window::SetInterval DontDelete|Function 2
00229   clearInterval Window::ClearInterval   DontDelete|Function 1
00230   print     Window::Print       DontDelete|Function 0
00231   addEventListener  Window::AddEventListener    DontDelete|Function 3
00232   removeEventListener   Window::RemoveEventListener DontDelete|Function 3
00233 # Warning, when adding a function to this object you need to add a case in Window::get
00234 # Event handlers
00235 # IE also has: onactivate, onbefore/afterprint, onbeforedeactivate/unload, oncontrolselect,
00236 # ondeactivate, onhelp, onmovestart/end, onresizestart/end, onscroll.
00237 # It doesn't have onabort, onchange, ondragdrop (but NS has that last one).
00238   onabort   Window::Onabort     DontDelete
00239   onblur    Window::Onblur      DontDelete
00240   onchange  Window::Onchange    DontDelete
00241   onclick   Window::Onclick     DontDelete
00242   ondblclick    Window::Ondblclick  DontDelete
00243   ondragdrop    Window::Ondragdrop  DontDelete
00244   onerror   Window::Onerror     DontDelete
00245   onfocus   Window::Onfocus     DontDelete
00246   onkeydown Window::Onkeydown   DontDelete
00247   onkeypress    Window::Onkeypress  DontDelete
00248   onkeyup   Window::Onkeyup     DontDelete
00249   onload    Window::Onload      DontDelete
00250   onmousedown   Window::Onmousedown DontDelete
00251   onmousemove   Window::Onmousemove DontDelete
00252   onmouseout    Window::Onmouseout  DontDelete
00253   onmouseover   Window::Onmouseover DontDelete
00254   onmouseup Window::Onmouseup   DontDelete
00255   onmove    Window::Onmove      DontDelete
00256   onreset   Window::Onreset     DontDelete
00257   onresize  Window::Onresize    DontDelete
00258   onselect  Window::Onselect    DontDelete
00259   onsubmit  Window::Onsubmit    DontDelete
00260   onunload  Window::Onunload    DontDelete
00261 @end
00262 */
00263 IMPLEMENT_PROTOFUNC_DOM(WindowFunc)
00264 
00265 Window::Window(KHTMLPart *p)
00266   : ObjectImp(/*no proto*/), m_part(p), screen(0), history(0), m_frames(0), loc(0), m_evt(0)
00267 {
00268   winq = new WindowQObject(this);
00269   //kdDebug(6070) << "Window::Window this=" << this << " part=" << m_part << " " << m_part->name() << endl;
00270 }
00271 
00272 Window::~Window()
00273 {
00274   kdDebug(6070) << "Window::~Window this=" << this << " part=" << m_part << endl;
00275   delete winq;
00276 }
00277 
00278 Window *Window::retrieveWindow(KHTMLPart *p)
00279 {
00280   Object obj = Object::dynamicCast( retrieve( p ) );
00281 #ifndef NDEBUG
00282   // obj should never be null, except when javascript has been disabled in that part.
00283   if ( p && p->jScriptEnabled() )
00284   {
00285     assert( !obj.isNull() );
00286 #ifndef QWS
00287     assert( dynamic_cast<KJS::Window*>(obj.imp()) ); // type checking
00288 #endif
00289   }
00290 #endif
00291   if ( obj.isNull() ) // JS disabled
00292     return 0;
00293   return static_cast<KJS::Window*>(obj.imp());
00294 }
00295 
00296 Window *Window::retrieveActive(ExecState *exec)
00297 {
00298   ValueImp *imp = exec->interpreter()->globalObject().imp();
00299   assert( imp );
00300 #ifndef QWS
00301   assert( dynamic_cast<KJS::Window*>(imp) );
00302 #endif
00303   return static_cast<KJS::Window*>(imp);
00304 }
00305 
00306 Value Window::retrieve(KHTMLPart *p)
00307 {
00308   assert(p);
00309   KJSProxy *proxy = KJSProxy::proxy( p );
00310   if (proxy) {
00311 #ifdef KJS_VERBOSE
00312     kdDebug(6070) << "Window::retrieve part=" << p << " '" << p->name() << "' interpreter=" << proxy->interpreter() << " window=" << proxy->interpreter()->globalObject().imp() << endl;
00313 #endif
00314     return proxy->interpreter()->globalObject(); // the Global object is the "window"
00315   } else {
00316 #ifdef KJS_VERBOSE
00317     kdDebug(6070) << "Window::retrieve part=" << p << " '" << p->name() << "' no jsproxy." << endl;
00318 #endif
00319     return Undefined(); // This can happen with JS disabled on the domain of that window
00320   }
00321 }
00322 
00323 Location *Window::location() const
00324 {
00325   if (!loc)
00326     const_cast<Window*>(this)->loc = new Location(m_part);
00327   return loc;
00328 }
00329 
00330 ObjectImp* Window::frames( ExecState* exec ) const
00331 {
00332   return m_frames ? m_frames :
00333     (const_cast<Window*>(this)->m_frames = new FrameArray(exec,m_part));
00334 }
00335 
00336 // reference our special objects during garbage collection
00337 void Window::mark()
00338 {
00339   ObjectImp::mark();
00340   if (screen && !screen->marked())
00341     screen->mark();
00342   if (history && !history->marked())
00343     history->mark();
00344   if (m_frames && !m_frames->marked())
00345     m_frames->mark();
00346   //kdDebug(6070) << "Window::mark " << this << " marking loc=" << loc << endl;
00347   if (loc && !loc->marked())
00348     loc->mark();
00349 }
00350 
00351 bool Window::hasProperty(ExecState *exec, const UString &p) const
00352 {
00353   if (p == "closed")
00354     return true;
00355 
00356   // we don't want any operations on a closed window
00357   if (m_part.isNull())
00358     return false;
00359 
00360   if (ObjectImp::hasProperty(exec, p))
00361     return true;
00362 
00363   if (Lookup::findEntry(&WindowTable, p))
00364     return true;
00365 
00366   QString q = p.qstring();
00367   if (m_part->findFrame(p.qstring()))
00368     return true;
00369 
00370   // allow shortcuts like 'Image1' instead of document.images.Image1
00371   if (m_part->document().isHTMLDocument()) { // might be XML
00372     DOM::HTMLCollection coll = m_part->htmlDocument().all();
00373     DOM::HTMLElement element = coll.namedItem(q);
00374     if (!element.isNull())
00375       return true;
00376   }
00377 
00378   return false;
00379 }
00380 
00381 UString Window::toString(ExecState *) const
00382 {
00383   return "[object Window]";
00384 }
00385 
00386 Value Window::get(ExecState *exec, const UString &p) const
00387 {
00388 #ifdef KJS_VERBOSE
00389   kdDebug(6070) << "Window("<<this<<")::get " << p.qstring() << endl;
00390 #endif
00391   if ( p == "closed" )
00392     return Boolean(m_part.isNull());
00393 
00394   // we don't want any operations on a closed window
00395   if (m_part.isNull())
00396     return Undefined();
00397 
00398   // Look for overrides first
00399   Value val = ObjectImp::get(exec, p);
00400   if (!val.isA(UndefinedType)) {
00401     //kdDebug(6070) << "Window::get found dynamic property '" << p.ascii() << "'" << endl;
00402     return isSafeScript(exec) ? val : Undefined();
00403   }
00404 
00405   const HashEntry* entry = Lookup::findEntry(&WindowTable, p);
00406 
00407   // properties that work on all windows
00408   if (entry) {
00409     switch(entry->value) {
00410     case Closed:
00411       return Boolean( false );
00412     case _Location:
00413       // No isSafeScript test here, we must be able to _set_ location.href (#49819)
00414       return Value(location());
00415     case Frames:
00416       return Value(frames(exec));
00417     case Opener:
00418       if (!m_part->opener())
00419         return Null();    // ### a null Window might be better, but == null
00420       else                // doesn't work yet
00421         return retrieve(m_part->opener());
00422     case Parent:
00423       return retrieve(m_part->parentPart() ? m_part->parentPart() : (KHTMLPart*)m_part);
00424     case _Window:
00425     case Self:
00426       return retrieve(m_part);
00427     case Top: {
00428       KHTMLPart *p = m_part;
00429       while (p->parentPart())
00430         p = p->parentPart();
00431       return retrieve(p);
00432     }
00433     case Alert:
00434     case Confirm:
00435     case Prompt:
00436     case Open:
00437     case Focus:
00438     case Blur:
00439       return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
00440     default:
00441       break;
00442     }
00443   }
00444 
00445   // properties that only work on safe windows
00446   if (isSafeScript(exec) && entry)
00447   {
00448     //kdDebug(6070) << "token: " << entry->value << endl;
00449     switch( entry->value ) {
00450     case Crypto:
00451       return Undefined(); // ###
00452     case DefaultStatus:
00453       return String(UString(m_part->jsDefaultStatusBarText()));
00454     case Status:
00455       return String(UString(m_part->jsStatusBarText()));
00456     case Document:
00457       if (m_part->document().isNull()) {
00458         kdDebug(6070) << "Document.write: adding <HTML><BODY> to create document" << endl;
00459         m_part->begin();
00460         m_part->write("<HTML><BODY>");
00461         m_part->end();
00462       }
00463       return getDOMNode(exec,m_part->document());
00464     case Node:
00465       return getNodeConstructor(exec);
00466     case Range:
00467       return getRangeConstructor(exec);
00468     case NodeFilter:
00469       return getNodeFilterConstructor(exec);
00470     case DOMException:
00471       return getDOMExceptionConstructor(exec);
00472     case CSSRule:
00473       return getCSSRuleConstructor(exec);
00474     case EventCtor:
00475       return getEventConstructor(exec);
00476     case _History:
00477       return Value(history ? history :
00478                    (const_cast<Window*>(this)->history = new History(exec,m_part)));
00479 
00480     case Event:
00481       if (m_evt)
00482         return getDOMEvent(exec,*m_evt);
00483       else {
00484 #ifdef KJS_VERBOSE
00485         kdWarning(6070) << "window(" << this << "," << m_part->name() << ").event, no event!" << endl;
00486 #endif
00487         return Undefined();
00488       }
00489     case InnerHeight:
00490       if (!m_part->view())
00491         return Undefined();
00492       return Number(m_part->view()->visibleHeight());
00493     case InnerWidth:
00494       if (!m_part->view())
00495         return Undefined();
00496       return Number(m_part->view()->visibleWidth());
00497     case Length:
00498       return Number(m_part->frames().count());
00499     case Name:
00500       return String(m_part->name());
00501     case _Navigator:
00502     case ClientInformation: {
00503       // Store the navigator in the object so we get the same one each time.
00504       Value nav( new Navigator(exec, m_part) );
00505       const_cast<Window *>(this)->put(exec, "navigator", nav, DontDelete|ReadOnly|Internal);
00506       const_cast<Window *>(this)->put(exec, "clientInformation", nav, DontDelete|ReadOnly|Internal);
00507       return nav;
00508     }
00509 #ifdef Q_WS_QWS
00510     case _Konqueror: {
00511       Value k( new Konqueror(exec, m_part) );
00512       const_cast<Window *>(this)->put(exec, "konqueror", k, DontDelete|ReadOnly|Internal);
00513       return k;
00514     }
00515 #endif
00516     case OffscreenBuffering:
00517       return Boolean(true);
00518     case OuterHeight:
00519     case OuterWidth:
00520     {
00521       if (!m_part->widget())
00522         return Number(0);
00523       KWin::Info inf = KWin::info(m_part->widget()->topLevelWidget()->winId());
00524       return Number(entry->value == OuterHeight ?
00525                     inf.geometry.height() : inf.geometry.width());
00526     }
00527     case PageXOffset:
00528       return Number(m_part->view()->contentsX());
00529     case PageYOffset:
00530       return Number(m_part->view()->contentsY());
00531     case Personalbar:
00532       return Undefined(); // ###
00533     case ScreenLeft:
00534     case ScreenX: {
00535       if (!m_part->view())
00536         return Undefined();
00537       QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(m_part->view()));
00538       return Number(m_part->view()->mapToGlobal(QPoint(0,0)).x() + sg.x());
00539     }
00540     case ScreenTop:
00541     case ScreenY: {
00542       if (!m_part->view())
00543         return Undefined();
00544       QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(m_part->view()));
00545       return Number(m_part->view()->mapToGlobal(QPoint(0,0)).y() + sg.y());
00546     }
00547     case ScrollX: {
00548       if (!m_part->view())
00549         return Undefined();
00550       return Number(m_part->view()->contentsX());
00551     }
00552     case ScrollY: {
00553       if (!m_part->view())
00554         return Undefined();
00555       return Number(m_part->view()->contentsY());
00556     }
00557     case Scrollbars:
00558       return Undefined(); // ###
00559     case _Screen:
00560       return Value(screen ? screen :
00561                    (const_cast<Window*>(this)->screen = new Screen(exec)));
00562     case Image:
00563       return Value(new ImageConstructorImp(exec, m_part->document()));
00564     case Option:
00565       return Value(new OptionConstructorImp(exec, m_part->document()));
00566     case Close:
00567     case Scroll: // compatibility
00568     case ScrollBy:
00569     case ScrollTo:
00570     case MoveBy:
00571     case MoveTo:
00572     case ResizeBy:
00573     case ResizeTo:
00574     case AddEventListener:
00575     case RemoveEventListener:
00576       return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
00577     case SetTimeout:
00578     case ClearTimeout:
00579     case SetInterval:
00580     case ClearInterval:
00581     case Print:
00582       return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
00583     case Onabort:
00584       return getListener(exec,DOM::EventImpl::ABORT_EVENT);
00585     case Onblur:
00586       return getListener(exec,DOM::EventImpl::BLUR_EVENT);
00587     case Onchange:
00588       return getListener(exec,DOM::EventImpl::CHANGE_EVENT);
00589     case Onclick:
00590       return getListener(exec,DOM::EventImpl::KHTML_ECMA_CLICK_EVENT);
00591     case Ondblclick:
00592       return getListener(exec,DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT);
00593     case Ondragdrop:
00594       return getListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT);
00595     case Onerror:
00596       return getListener(exec,DOM::EventImpl::KHTML_ERROR_EVENT);
00597     case Onfocus:
00598       return getListener(exec,DOM::EventImpl::FOCUS_EVENT);
00599     case Onkeydown:
00600       return getListener(exec,DOM::EventImpl::KHTML_KEYDOWN_EVENT);
00601     case Onkeypress:
00602       return getListener(exec,DOM::EventImpl::KHTML_KEYPRESS_EVENT);
00603     case Onkeyup:
00604       return getListener(exec,DOM::EventImpl::KHTML_KEYUP_EVENT);
00605     case Onload:
00606       return getListener(exec,DOM::EventImpl::LOAD_EVENT);
00607     case Onmousedown:
00608       return getListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT);
00609     case Onmousemove:
00610       return getListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT);
00611     case Onmouseout:
00612       return getListener(exec,DOM::EventImpl::MOUSEOUT_EVENT);
00613     case Onmouseover:
00614       return getListener(exec,DOM::EventImpl::MOUSEOVER_EVENT);
00615     case Onmouseup:
00616       return getListener(exec,DOM::EventImpl::MOUSEUP_EVENT);
00617     case Onmove:
00618       return getListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT);
00619     case Onreset:
00620       return getListener(exec,DOM::EventImpl::RESET_EVENT);
00621     case Onresize:
00622       return getListener(exec,DOM::EventImpl::RESIZE_EVENT);
00623     case Onselect:
00624       return getListener(exec,DOM::EventImpl::SELECT_EVENT);
00625     case Onsubmit:
00626       return getListener(exec,DOM::EventImpl::SUBMIT_EVENT);
00627     case Onunload:
00628       return getListener(exec,DOM::EventImpl::UNLOAD_EVENT);
00629     }
00630   }
00631   KHTMLPart *kp = m_part->findFrame( p.qstring() );
00632   if (kp)
00633     return retrieve(kp);
00634 
00635   // allow shortcuts like 'Image1' instead of document.images.Image1
00636   if (isSafeScript(exec) &&
00637       m_part->document().isHTMLDocument()) { // might be XML
00638     DOM::HTMLCollection coll = m_part->htmlDocument().all();
00639     DOM::HTMLElement element = coll.namedItem(p.string());
00640     if (!element.isNull()) {
00641       return getDOMNode(exec,element);
00642     }
00643   }
00644 
00645 #if 0 
00646   // give access to functions (and variables ?) from parent frameset
00647   if (m_part->parentPart())
00648   {
00649     Object parentObject = Object::dynamicCast( retrieve(m_part->parentPart()) );
00650     if ( !parentObject.isNull() )
00651     {
00652       Value ret = parentObject.get(exec,p);
00653       if (ret.type() != UndefinedType ) {
00654 #ifdef KJS_VERBOSE
00655         kdDebug(6070) << "Window::get property " << p.qstring() << " found in parent part" << endl;
00656 #endif
00657         return ret;
00658       }
00659     }
00660   }
00661 #endif
00662 
00663   // This isn't necessarily a bug. Some code uses if(!window.blah) window.blah=1
00664   // But it can also mean something isn't loaded or implemented, hence the WARNING to help grepping.
00665 #ifdef KJS_VERBOSE
00666   kdDebug(6070) << "WARNING: Window::get property not found: " << p.qstring() << endl;
00667 #endif
00668   return Undefined();
00669 }
00670 
00671 void Window::put(ExecState* exec, const UString &propertyName, const Value &value, int attr)
00672 {
00673   // Called by an internal KJS call (e.g. InterpreterImp's constructor) ?
00674   // If yes, save time and jump directly to ObjectImp.
00675   if ( (attr != None && attr != DontDelete)
00676        // Same thing if we have a local override (e.g. "var location")
00677        || ( ObjectImp::getDirect(propertyName) && isSafeScript(exec)) )
00678   {
00679     ObjectImp::put( exec, propertyName, value, attr );
00680     return;
00681   }
00682 
00683   const HashEntry* entry = Lookup::findEntry(&WindowTable, propertyName);
00684   if (entry)
00685   {
00686 #ifdef KJS_VERBOSE
00687     kdDebug(6070) << "Window("<<this<<")::put " << propertyName.qstring() << endl;
00688 #endif
00689     switch( entry->value ) {
00690     case Status: {
00691       if ( isSafeScript(exec) ) {
00692         String s = value.toString(exec);
00693         m_part->setJSStatusBarText(s.value().qstring());
00694       }
00695       return;
00696     }
00697     case DefaultStatus: {
00698       if ( isSafeScript(exec) ) {
00699         String s = value.toString(exec);
00700         m_part->setJSDefaultStatusBarText(s.value().qstring());
00701       }
00702       return;
00703     }
00704     case _Location:
00705       goURL(exec, value.toString(exec).qstring());
00706       return;
00707     case Onabort:
00708       if (isSafeScript(exec))
00709         setListener(exec, DOM::EventImpl::ABORT_EVENT,value);
00710       return;
00711     case Onblur:
00712       if (isSafeScript(exec))
00713         setListener(exec, DOM::EventImpl::BLUR_EVENT,value);
00714       return;
00715     case Onchange:
00716       if (isSafeScript(exec))
00717         setListener(exec, DOM::EventImpl::CHANGE_EVENT,value);
00718       return;
00719     case Onclick:
00720       if (isSafeScript(exec))
00721         setListener(exec,DOM::EventImpl::KHTML_ECMA_CLICK_EVENT,value);
00722       return;
00723     case Ondblclick:
00724       if (isSafeScript(exec))
00725         setListener(exec,DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT,value);
00726       return;
00727     case Ondragdrop:
00728       if (isSafeScript(exec))
00729         setListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT,value);
00730       return;
00731     case Onerror:
00732       if (isSafeScript(exec))
00733         setListener(exec,DOM::EventImpl::KHTML_ERROR_EVENT,value);
00734       return;
00735     case Onfocus:
00736       if (isSafeScript(exec))
00737         setListener(exec,DOM::EventImpl::FOCUS_EVENT,value);
00738       return;
00739     case Onkeydown:
00740       if (isSafeScript(exec))
00741         setListener(exec,DOM::EventImpl::KHTML_KEYDOWN_EVENT,value);
00742       return;
00743     case Onkeypress:
00744       if (isSafeScript(exec))
00745         setListener(exec,DOM::EventImpl::KHTML_KEYPRESS_EVENT,value);
00746       return;
00747     case Onkeyup:
00748       if (isSafeScript(exec))
00749         setListener(exec,DOM::EventImpl::KHTML_KEYUP_EVENT,value);
00750       return;
00751     case Onload:
00752       if (isSafeScript(exec))
00753         setListener(exec,DOM::EventImpl::LOAD_EVENT,value);
00754       return;
00755     case Onmousedown:
00756       if (isSafeScript(exec))
00757         setListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT,value);
00758       return;
00759     case Onmousemove:
00760       if (isSafeScript(exec))
00761         setListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT,value);
00762       return;
00763     case Onmouseout:
00764       if (isSafeScript(exec))
00765         setListener(exec,DOM::EventImpl::MOUSEOUT_EVENT,value);
00766       return;
00767     case Onmouseover:
00768       if (isSafeScript(exec))
00769         setListener(exec,DOM::EventImpl::MOUSEOVER_EVENT,value);
00770       return;
00771     case Onmouseup:
00772       if (isSafeScript(exec))
00773         setListener(exec,DOM::EventImpl::MOUSEUP_EVENT,value);
00774       return;
00775     case Onmove:
00776       if (isSafeScript(exec))
00777         setListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT,value);
00778       return;
00779     case Onreset:
00780       if (isSafeScript(exec))
00781         setListener(exec,DOM::EventImpl::RESET_EVENT,value);
00782       return;
00783     case Onresize:
00784       if (isSafeScript(exec))
00785         setListener(exec,DOM::EventImpl::RESIZE_EVENT,value);
00786       return;
00787     case Onselect:
00788       if (isSafeScript(exec))
00789         setListener(exec,DOM::EventImpl::SELECT_EVENT,value);
00790       return;
00791     case Onsubmit:
00792       if (isSafeScript(exec))
00793         setListener(exec,DOM::EventImpl::SUBMIT_EVENT,value);
00794       return;
00795     case Onunload:
00796       if (isSafeScript(exec))
00797         setListener(exec,DOM::EventImpl::UNLOAD_EVENT,value);
00798       return;
00799     case Name:
00800       if (isSafeScript(exec))
00801         m_part->setName( value.toString(exec).qstring().local8Bit().data() );
00802       return;
00803     default:
00804       break;
00805     }
00806   }
00807   if (isSafeScript(exec)) {
00808     //kdDebug(6070) << "Window("<<this<<")::put storing " << propertyName.qstring() << endl;
00809     ObjectImp::put(exec, propertyName, value, attr);
00810   }
00811 }
00812 
00813 bool Window::toBoolean(ExecState *) const
00814 {
00815   return !m_part.isNull();
00816 }
00817 
00818 int Window::installTimeout(const UString &handler, int t, bool singleShot)
00819 {
00820   return winq->installTimeout(handler, t, singleShot);
00821 }
00822 
00823 void Window::clearTimeout(int timerId)
00824 {
00825   winq->clearTimeout(timerId);
00826 }
00827 
00828 void Window::scheduleClose()
00829 {
00830   kdDebug(6070) << "Window::scheduleClose window.close() " << m_part << endl;
00831   Q_ASSERT(winq);
00832   QTimer::singleShot( 0, winq, SLOT( timeoutClose() ) );
00833 }
00834 
00835 void Window::closeNow()
00836 {
00837   if (!m_part.isNull())
00838   {
00839     //kdDebug(6070) << k_funcinfo << " -> closing window" << endl;
00840     // We want to make sure that window.open won't find this part by name.
00841     m_part->setName( 0 );
00842     m_part->deleteLater();
00843     m_part = 0;
00844   } else
00845     kdDebug(6070) << k_funcinfo << "part is deleted already" << endl;
00846 }
00847 
00848 void Window::afterScriptExecution()
00849 {
00850   DOM::DocumentImpl::updateDocumentsRendering();
00851   QValueList<DelayedAction> delayedActions = m_delayed;
00852   m_delayed.clear();
00853   QValueList<DelayedAction>::Iterator it = delayedActions.begin();
00854   for ( ; it != delayedActions.end() ; ++it )
00855   {
00856     switch ((*it).actionId) {
00857     case DelayedClose:
00858       scheduleClose();
00859       return; // stop here, in case of multiple actions
00860     case DelayedGoHistory:
00861       goHistory( (*it).param.toInt() );
00862       break;
00863     };
00864   }
00865 }
00866 
00867 bool Window::isSafeScript(ExecState *exec) const
00868 {
00869   if (m_part.isNull()) { // part deleted ? can't grant access
00870     kdDebug(6070) << "Window::isSafeScript: accessing deleted part !" << endl;
00871     return false;
00872   }
00873   KHTMLPart *activePart = static_cast<KJS::ScriptInterpreter *>( exec->interpreter() )->part();
00874   if (!activePart) {
00875     kdDebug(6070) << "Window::isSafeScript: current interpreter's part is 0L!" << endl;
00876     return false;
00877   }
00878   if ( activePart == m_part ) // Not calling from another frame, no problem.
00879     return true;
00880 
00881   if ( m_part->document().isNull() )
00882     return true; // allow to access a window that was just created (e.g. with window.open("about:blank"))
00883 
00884   DOM::HTMLDocument thisDocument = m_part->htmlDocument();
00885   if ( thisDocument.isNull() ) {
00886     kdDebug(6070) << "Window::isSafeScript: trying to access an XML document !?" << endl;
00887     return false;
00888   }
00889 
00890   DOM::HTMLDocument actDocument = activePart->htmlDocument();
00891   if ( actDocument.isNull() ) {
00892     kdDebug(6070) << "Window::isSafeScript: active part has no document!" << endl;
00893     return false;
00894   }
00895   DOM::DOMString actDomain = actDocument.domain();
00896   DOM::DOMString thisDomain = thisDocument.domain();
00897 
00898   if ( actDomain == thisDomain ) {
00899     //kdDebug(6070) << "JavaScript: access granted, domain is '" << actDomain.string() << "'" << endl;
00900     return true;
00901   }
00902 
00903   kdWarning(6070) << "JavaScript: access denied for current frame '" << actDomain.string() << "' to frame '" << thisDomain.string() << "'" << endl;
00904   // TODO after 3.1: throw security exception (exec->setException())
00905   return false;
00906 }
00907 
00908 void Window::setListener(ExecState *exec, int eventId, Value func)
00909 {
00910   if (!isSafeScript(exec))
00911     return;
00912   DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(m_part->htmlDocument().handle());
00913   if (!doc)
00914     return;
00915 
00916   doc->setWindowEventListener(eventId,getJSEventListener(func,true));
00917 }
00918 
00919 Value Window::getListener(ExecState *exec, int eventId) const
00920 {
00921   if (!isSafeScript(exec))
00922     return Undefined();
00923   DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(m_part->htmlDocument().handle());
00924   if (!doc)
00925     return Undefined();
00926 
00927   DOM::EventListener *listener = doc->getWindowEventListener(eventId);
00928   if (listener)
00929     return static_cast<JSEventListener*>(listener)->listenerObj();
00930   else
00931     return Null();
00932 }
00933 
00934 
00935 JSEventListener *Window::getJSEventListener(const Value& val, bool html)
00936 {
00937   // This function is so hot that it's worth coding it directly with imps.
00938   if (val.type() != ObjectType)
00939     return 0;
00940   ObjectImp *listenerObject = static_cast<ObjectImp *>(val.imp());
00941 
00942   QPtrListIterator<JSEventListener> it(jsEventListeners);
00943   for (; it.current(); ++it)
00944     if (it.current()->listenerObjImp() == listenerObject)
00945       return it.current();
00946 
00947   // Note that the JSEventListener constructor adds it to our jsEventListeners list
00948   return new JSEventListener(Object(listenerObject), Object(this), html);
00949 }
00950 
00951 void Window::clear( ExecState *exec )
00952 {
00953   kdDebug(6070) << "Window::clear " << this << endl;
00954   delete winq;
00955   winq = 0L;
00956   // Get rid of everything, those user vars could hold references to DOM nodes
00957   deleteAllProperties( exec );
00958 
00959   // Break the dependency between the listeners and their object
00960   QPtrListIterator<JSEventListener> it(jsEventListeners);
00961   for (; it.current(); ++it)
00962     it.current()->clear();
00963   // Forget about the listeners (the DOM::NodeImpls will delete them)
00964   jsEventListeners.clear();
00965 
00966   if (!m_part.isNull()) {
00967     KJSProxy* proxy = KJSProxy::proxy( m_part );
00968     if (proxy) // i.e. JS not disabled
00969     {
00970       winq = new WindowQObject(this);
00971       // Now recreate a working global object for the next URL that will use us
00972       KJS::Interpreter *interpreter = proxy->interpreter();
00973       interpreter->initGlobalObject();
00974     }
00975   }
00976 }
00977 
00978 void Window::setCurrentEvent( DOM::Event *evt )
00979 {
00980   m_evt = evt;
00981   //kdDebug(6070) << "Window " << this << " (part=" << m_part << ")::setCurrentEvent m_evt=" << evt << endl;
00982 }
00983 
00984 void Window::goURL(ExecState* exec, const QString& url, bool lockHistory)
00985 {
00986   Window* active = Window::retrieveActive(exec);
00987   // Complete the URL using the "active part" (running interpreter)
00988   if (active->part()) {
00989     QString dstUrl = active->part()->htmlDocument().completeURL(url).string();
00990     kdDebug() << "Window::goURL dstUrl=" << dstUrl << " m_part->url()=" << m_part->url().url() << endl;
00991     // Check if the URL is the current one. No [infinite] redirect in that case.
00992     if ( m_part->url().cmp( KURL(dstUrl), true ) )
00993         return;
00994 
00995     // check if we're allowed to inject javascript
00996     // SYNC check with khtml_part.cpp::slotRedirect!
00997     if ( isSafeScript(exec) ||
00998             dstUrl.find(QString::fromLatin1("javascript:"), 0, false) != 0 )
00999       m_part->scheduleRedirection(-1,
01000                                 dstUrl,
01001                                   lockHistory);
01002   }
01003 }
01004 
01005 void Window::delayedGoHistory( int steps )
01006 {
01007     m_delayed.append( DelayedAction( DelayedGoHistory, steps ) );
01008 }
01009 
01010 void Window::goHistory( int steps )
01011 {
01012   KParts::BrowserExtension *ext = m_part->browserExtension();
01013   if(!ext)
01014     return;
01015   KParts::BrowserInterface *iface = ext->browserInterface();
01016 
01017   if ( !iface )
01018     return;
01019 
01020   iface->callMethod( "goHistory(int)", steps );
01021   //emit ext->goHistory(steps);
01022 }
01023 
01024 void KJS::Window::resizeTo(QWidget* tl, int width, int height)
01025 {
01026   // Security check: within desktop limits and bigger than 100x100 (per spec)
01027   if ( width < 100 || height < 100 ) {
01028     kdDebug(6070) << "Window::resizeTo refused, window would be too small ("<<width<<","<<height<<")" << endl;
01029     return;
01030   }
01031   QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(tl));
01032   if ( width > sg.width() || height > sg.height() ) {
01033     kdDebug(6070) << "Window::resizeTo refused, window would be too big ("<<width<<","<<height<<")" << endl;
01034     return;
01035   }
01036 
01037   // Take into account the window frame - so that (width,height) is the external window size
01038   // ### (is that correct? for window.open it's the size of the HTML area...)
01039   int deltaWidth = tl->frameGeometry().width() - tl->width();
01040   int deltaHeight = tl->frameGeometry().height() - tl->height();
01041 
01042   kdDebug() << "resizing to " << width - deltaWidth << "x" << height - deltaHeight << endl;
01043 
01044   tl->resize( width - deltaWidth, height - deltaHeight );
01045 
01046   // If the window is out of the desktop, move it up/left
01047   // (maybe we should use workarea instead of sg, otherwise the window ends up below kicker)
01048   int right = tl->x() + tl->frameGeometry().width();
01049   int bottom = tl->y() + tl->frameGeometry().height();
01050   int moveByX = 0;
01051   int moveByY = 0;
01052   if ( right > sg.right() )
01053     moveByX = - right + sg.right(); // always <0
01054   if ( bottom > sg.bottom() )
01055     moveByY = - bottom + sg.bottom(); // always <0
01056   if ( moveByX || moveByY )
01057     tl->move( tl->x() + moveByX , tl->y() + moveByY );
01058 }
01059 
01060 Value Window::openWindow(ExecState *exec, const List& args)
01061 {
01062   KHTMLView *widget = m_part->view();
01063   Value v = args[0];
01064   UString s = v.toString(exec);
01065   QString str = s.qstring();
01066 
01067   KConfig *config = new KConfig( "konquerorrc" );
01068   config->setGroup( "Java/JavaScript Settings" );
01069   int policy = config->readUnsignedNumEntry(  "WindowOpenPolicy", 0 ); // 0=allow, 1=ask, 2=deny, 3=smart
01070   delete config;
01071   if (  policy == 1 ) {
01072     if ( KMessageBox::questionYesNo(widget,
01073                                     i18n( "This site is trying to open up a new browser "
01074                                           "window using JavaScript.\n"
01075                                           "Do you want to allow this?" ),
01076                                     i18n( "Confirmation: JavaScript Popup" ) ) == KMessageBox::Yes )
01077       policy = 0;
01078   } else if ( policy == 3 )
01079   {
01080     // window.open disabled unless from a key/mouse event
01081     if (static_cast<ScriptInterpreter *>(exec->interpreter())->isWindowOpenAllowed())
01082       policy = 0;
01083   }
01084   if ( policy != 0 ) {
01085     return Undefined();
01086   } else {
01087     KParts::WindowArgs winargs;
01088 
01089     // scan feature argument
01090     QString features;
01091     if (args.size()>2) {
01092       features = args[2].toString(exec).qstring();
01093       // specifying window params means false defaults
01094       winargs.menuBarVisible = false;
01095       winargs.toolBarsVisible = false;
01096       winargs.statusBarVisible = false;
01097       QStringList flist = QStringList::split(',', features);
01098       QStringList::ConstIterator it = flist.begin();
01099       while (it != flist.end()) {
01100         QString s = *it++;
01101         QString key, val;
01102         int pos = s.find('=');
01103         if (pos >= 0) {
01104           key = s.left(pos).stripWhiteSpace().lower();
01105           val = s.mid(pos + 1).stripWhiteSpace().lower();
01106 
01107           int scnum = QApplication::desktop()->screenNumber(widget->topLevelWidget());
01108 
01109           QRect screen = QApplication::desktop()->screenGeometry(scnum);
01110           if (key == "left" || key == "screenx") {
01111             winargs.x = val.toInt() + screen.x();
01112             if (winargs.x < screen.x() || winargs.x > screen.right())
01113               winargs.x = screen.x(); // only safe choice until size is determined
01114           } else if (key == "top" || key == "screeny") {
01115             winargs.y = val.toInt() + screen.y();
01116             if (winargs.y < screen.y() || winargs.y > screen.bottom())
01117               winargs.y = screen.y(); // only safe choice until size is determined
01118           } else if (key == "height") {
01119             winargs.height = val.toInt() + 2*qApp->style().pixelMetric( QStyle::PM_DefaultFrameWidth ) + 2;
01120             if (winargs.height > screen.height())  // should actually check workspace
01121               winargs.height = screen.height();
01122             if (winargs.height < 100)
01123               winargs.height = 100;
01124           } else if (key == "width") {
01125             winargs.width = val.toInt() + 2*qApp->style().pixelMetric( QStyle::PM_DefaultFrameWidth ) + 2;
01126             if (winargs.width > screen.width())    // should actually check workspace
01127               winargs.width = screen.width();
01128             if (winargs.width < 100)
01129               winargs.width = 100;
01130           } else {
01131             goto boolargs;
01132           }
01133           continue;
01134         } else {
01135           // leaving away the value gives true
01136           key = s.stripWhiteSpace().lower();
01137           val = "1";
01138         }
01139       boolargs:
01140         if (key == "menubar")
01141           winargs.menuBarVisible = (val == "1" || val == "yes");
01142         else if (key == "toolbar")
01143           winargs.toolBarsVisible = (val == "1" || val == "yes");
01144         else if (key == "location")  // ### missing in WindowArgs
01145           winargs.toolBarsVisible = (val == "1" || val == "yes");
01146         else if (key == "status" || key == "statusbar")
01147           winargs.statusBarVisible = (val == "1" || val == "yes");
01148         else if (key == "resizable")
01149           winargs.resizable = (val == "1" || val == "yes");
01150         else if (key == "fullscreen")
01151           winargs.fullscreen = (val == "1" || val == "yes");
01152       }
01153     }
01154 
01155     // prepare arguments
01156     KURL url;
01157     if (!str.isEmpty())
01158     {
01159       KHTMLPart* p = Window::retrieveActive(exec)->m_part;
01160       if ( p )
01161         url = p->htmlDocument().completeURL(str).string();
01162       if ( !p ||
01163            !static_cast<DOM::DocumentImpl*>(p->htmlDocument().handle())->isURLAllowed(url.url()) )
01164           return Undefined();
01165     }
01166 
01167     KParts::URLArgs uargs;
01168     KHTMLPart *p = m_part;
01169     uargs.frameName = args.size() > 1 ?
01170                       args[1].toString(exec).qstring()
01171                       : QString("_blank");
01172     if ( uargs.frameName == "_top" )
01173     {
01174       while ( p->parentPart() )
01175         p = p->parentPart();
01176       Window::retrieveWindow(p)->goURL(exec, url.url(), false /*don't lock history*/);
01177       return Window::retrieve(p);
01178     }
01179     if ( uargs.frameName == "_parent" )
01180     {
01181       if ( p->parentPart() )
01182         p = p->parentPart();
01183       Window::retrieveWindow(p)->goURL(exec, url.url(), false /*don't lock history*/);
01184       return Window::retrieve(p);
01185     }
01186     uargs.serviceType = "text/html";
01187 
01188     // request window (new or existing if framename is set)
01189     KParts::ReadOnlyPart *newPart = 0L;
01190     emit p->browserExtension()->createNewWindow("", uargs,winargs,newPart);
01191     if (newPart && newPart->inherits("KHTMLPart")) {
01192       KHTMLPart *khtmlpart = static_cast<KHTMLPart*>(newPart);
01193       //qDebug("opener set to %p (this Window's part) in new Window %p  (this Window=%p)",part,win,window);
01194       khtmlpart->setOpener(p);
01195       khtmlpart->setOpenedByJS(true);
01196       if (khtmlpart->document().isNull()) {
01197         khtmlpart->begin();
01198         khtmlpart->write("<HTML><BODY>");
01199         khtmlpart->end();
01200         if ( p->docImpl() ) {
01201           kdDebug(6070) << "Setting domain to " << p->docImpl()->domain().string() << endl;
01202           khtmlpart->docImpl()->setDomain( p->docImpl()->domain());
01203           khtmlpart->docImpl()->setBaseURL( p->docImpl()->baseURL() );
01204         }
01205       }
01206       uargs.serviceType = QString::null;
01207       if (uargs.frameName == "_blank")
01208         uargs.frameName = QString::null;
01209       if (!url.isEmpty())
01210         emit khtmlpart->browserExtension()->openURLRequest(url,uargs);
01211       return Window::retrieve(khtmlpart); // global object
01212     } else
01213       return Undefined();
01214   }
01215 }
01216 
01217 Value WindowFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
01218 {
01219   KJS_CHECK_THIS( Window, thisObj );
01220   Window *window = static_cast<Window *>(thisObj.imp());
01221   QString str, str2;
01222 
01223   KHTMLPart *part = window->m_part;
01224   if (!part)
01225     return Undefined();
01226 
01227   KHTMLView *widget = part->view();
01228   Value v = args[0];
01229   UString s = v.toString(exec);
01230   str = s.qstring();
01231 
01232   // functions that work everywhere
01233   switch(id) {
01234   case Window::Alert:
01235     if (!widget->dialogsAllowed())
01236       return Undefined();
01237     part->xmlDocImpl()->updateRendering();
01238     KMessageBox::error(widget, QStyleSheet::convertFromPlainText(str), "JavaScript");
01239     return Undefined();
01240   case Window::Confirm:
01241     if (!widget->dialogsAllowed())
01242       return Undefined();
01243     part->xmlDocImpl()->updateRendering();
01244     return Boolean((KMessageBox::warningYesNo(widget, QStyleSheet::convertFromPlainText(str), "JavaScript",
01245                                                 i18n("OK"), i18n("Cancel")) == KMessageBox::Yes));
01246   case Window::Prompt:
01247     part->xmlDocImpl()->updateRendering();
01248     bool ok;
01249     if (args.size() >= 2)
01250       str2 = KLineEditDlg::getText(i18n("Konqueror: Prompt"),
01251                                    QStyleSheet::convertFromPlainText(str),
01252                                    args[1].toString(exec).qstring(), &ok);
01253     else
01254       str2 = KLineEditDlg::getText(i18n("Konqueror: Prompt"),
01255                                    QStyleSheet::convertFromPlainText(str),
01256                                    QString::null, &ok);
01257     if ( ok )
01258         return String(str2);
01259     else
01260         return Null();
01261   case Window::Open:
01262     return window->openWindow(exec, args);
01263   case Window::Focus: {
01264     if(widget)
01265       widget->setActiveWindow();
01266     return Undefined();
01267   }
01268   case Window::Blur:
01269     // TODO
01270     return Undefined();
01271   };
01272 
01273 
01274   // now unsafe functions..
01275   if (!window->isSafeScript(exec))
01276     return Undefined();
01277 
01278   switch (id) {
01279   case Window::Scroll:
01280   case Window::ScrollBy:
01281     if(args.size() == 2 && widget)
01282       widget->scrollBy(args[0].toInt32(exec), args[1].toInt32(exec));
01283     return Undefined();
01284   case Window::ScrollTo:
01285     if(args.size() == 2 && widget)
01286       widget->setContentsPos(args[0].toInt32(exec), args[1].toInt32(exec));
01287     return Undefined();
01288   case Window::MoveBy: {
01289     if(args.size() == 2 && widget)
01290     {
01291       QWidget * tl = widget->topLevelWidget();
01292       QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(tl));
01293       QPoint dest = tl->pos() + QPoint( args[0].toInt32(exec), args[1].toInt32(exec) );
01294       // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
01295       if ( dest.x() >= sg.x() && dest.y() >= sg.x() &&
01296            dest.x()+tl->width() <= sg.width()+sg.x() &&
01297            dest.y()+tl->height() <= sg.height()+sg.y() )
01298         tl->move( dest );
01299     }
01300     return Undefined();
01301   }
01302   case Window::MoveTo: {
01303     if(args.size() == 2 && widget)
01304     {
01305       QWidget * tl = widget->topLevelWidget();
01306       QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(tl));
01307       QPoint dest( args[0].toInt32(exec)+sg.x(), args[1].toInt32(exec)+sg.y() );
01308       // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
01309       if ( dest.x() >= sg.x() && dest.y() >= sg.y() &&
01310            dest.x()+tl->width() <= sg.width()+sg.x() &&
01311            dest.y()+tl->height() <= sg.height()+sg.y() )
01312         tl->move( dest );
01313     }
01314     return Undefined();
01315   }
01316   case Window::ResizeBy: {
01317     if(args.size() == 2 && widget)
01318     {
01319       QWidget * tl = widget->topLevelWidget();
01320       window->resizeTo( tl, tl->width() + args[0].toInt32(exec), tl->height() + args[1].toInt32(exec) );
01321     }
01322     return Undefined();
01323   }
01324   case Window::ResizeTo: {
01325     if(args.size() == 2 && widget)
01326     {
01327       QWidget * tl = widget->topLevelWidget();
01328       window->resizeTo( tl, args[0].toInt32(exec), args[1].toInt32(exec) );
01329     }
01330     return Undefined();
01331   }
01332   case Window::SetTimeout:
01333     if (args.size() == 2 && v.isA(StringType)) {
01334       int i = args[1].toInt32(exec);
01335       int r = (const_cast<Window*>(window))->installTimeout(s, i, true /*single shot*/);
01336       return Number(r);
01337     }
01338     else if (args.size() >= 2 && v.isA(ObjectType) && Object::dynamicCast(v).implementsCall()) {
01339       Value func = args[0];
01340       int i = args[1].toInt32(exec);
01341 #if 0
01342 //  ### TODO
01343       List *funcArgs = args.copy();
01344       funcArgs->removeFirst(); // all args after 2 go to the function
01345       funcArgs->removeFirst();
01346 #endif
01347       if ( args.size() > 2 )
01348         kdWarning(6070) << "setTimeout(more than 2 args) is not fully implemented!" << endl;
01349       int r = (const_cast<Window*>(window))->installTimeout(s, i, true /*single shot*/);
01350       return Number(r);
01351     }
01352     else
01353       return Undefined();
01354   case Window::SetInterval:
01355     if (args.size() >= 2 && v.isA(StringType)) {
01356       int i = args[1].toInt32(exec);
01357       int r = (const_cast<Window*>(window))->installTimeout(s, i, false);
01358       return Number(r);
01359     }
01360     else if (args.size() >= 2 && !Object::dynamicCast(v).isNull() &&
01361          Object::dynamicCast(v).implementsCall()) {
01362       Value func = args[0];
01363       int i = args[1].toInt32(exec);
01364 #if 0
01365 // ### TODO
01366       List *funcArgs = args.copy();
01367       funcArgs->removeFirst(); // all args after 2 go to the function
01368       funcArgs->removeFirst();
01369 #endif
01370       int r = (const_cast<Window*>(window))->installTimeout(s, i, false);
01371       return Number(r);
01372     }
01373     else
01374       return Undefined();
01375   case Window::ClearTimeout:
01376   case Window::ClearInterval:
01377     (const_cast<Window*>(window))->clearTimeout(v.toInt32(exec));
01378     return Undefined();
01379  case Window::Blur:
01380     // TODO
01381     return Undefined();
01382   case Window::Close: {
01383     /* From http://developer.netscape.com/docs/manuals/js/client/jsref/window.htm :
01384        The close method closes only windows opened by JavaScript using the open method.
01385        If you attempt to close any other window, a confirm is generated, which
01386        lets the user choose whether the window closes.
01387        This is a security feature to prevent "mail bombs" containing self.close().
01388        However, if the window has only one document (the current one) in its
01389        session history, the close is allowed without any confirm. This is a
01390        special case for one-off windows that need to open other windows and
01391        then dispose of themselves.
01392     */
01393     bool doClose = false;
01394     if (!part->openedByJS())
01395     {
01396       // To conform to the SPEC, we only ask if the window
01397       // has more than one entry in the history (NS does that too).
01398       History history(exec,part);
01399       if ( history.get( exec, "length" ).toInt32(exec) <= 1 ||
01400            KMessageBox::questionYesNo( window->part()->widget(), i18n("Close window?"), i18n("Confirmation Required") ) == KMessageBox::Yes )
01401         doClose = true;
01402     }
01403     else
01404       doClose = true;
01405 
01406     if (doClose)
01407     {
01408       // If this is the current window (the one the interpreter runs in),
01409       // then schedule a delayed close (so that the script terminates first).
01410       // But otherwise, close immediately. This fixes w=window.open("","name");w.close();window.open("name");
01411       if ( Window::retrieveActive(exec) == window ) {
01412         if (widget) {
01413           // quit all dialogs of this view
01414           // this fixes 'setTimeout('self.close()',1000); alert("Hi");' crash
01415           widget->closeChildDialogs();
01416         }
01417         //kdDebug() << "scheduling delayed close"  << endl;
01418         // We'll close the window at the end of the script execution
01419         Window* w = const_cast<Window*>(window);
01420         w->m_delayed.append( Window::DelayedAction( Window::DelayedClose ) );
01421       } else {
01422         //kdDebug() << "closing NOW"  << endl;
01423         (const_cast<Window*>(window))->closeNow();
01424       }
01425     }
01426     return Undefined();
01427   }
01428   case Window::Print:
01429     if ( widget ) {
01430       // ### TODO emit onbeforeprint event
01431       widget->print();
01432       // ### TODO emit onafterprint event
01433     }
01434   case Window::AddEventListener: {
01435         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
01436         DOM::Document doc = part->document();
01437         if (doc.isHTMLDocument()) {
01438             DOM::HTMLDocument htmlDoc = doc;
01439             htmlDoc.body().addEventListener(args[0].toString(exec).string(),listener,args[2].toBoolean(exec));
01440         }
01441         else
01442             doc.addEventListener(args[0].toString(exec).string(),listener,args[2].toBoolean(exec));
01443         return Undefined();
01444     }
01445   case Window::RemoveEventListener: {
01446         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
01447         DOM::Document doc = part->document();
01448         if (doc.isHTMLDocument()) {
01449             DOM::HTMLDocument htmlDoc = doc;
01450             htmlDoc.body().removeEventListener(args[0].toString(exec).string(),listener,args[2].toBoolean(exec));
01451         }
01452         else
01453             doc.removeEventListener(args[0].toString(exec).string(),listener,args[2].toBoolean(exec));
01454         return Undefined();
01455     }
01456     break;
01457   }
01458   return Undefined();
01459 }
01460 
01462 
01463 ScheduledAction::ScheduledAction(Object _func, List _args, bool _singleShot)
01464 {
01465   //kdDebug(6070) << "ScheduledAction::ScheduledAction(isFunction) " << this << endl;
01466   func = _func;
01467   args = _args;
01468   isFunction = true;
01469   singleShot = _singleShot;
01470 }
01471 
01472 ScheduledAction::ScheduledAction(QString _code, bool _singleShot)
01473 {
01474   //kdDebug(6070) << "ScheduledAction::ScheduledAction(!isFunction) " << this << endl;
01475   //func = 0;
01476   //args = 0;
01477   code = _code;
01478   isFunction = false;
01479   singleShot = _singleShot;
01480 }
01481 
01482 void ScheduledAction::execute(Window *window)
01483 {
01484   ScriptInterpreter *interpreter = static_cast<ScriptInterpreter *>(KJSProxy::proxy(window->m_part)->interpreter());
01485 
01486   interpreter->setProcessingTimerCallback(true);
01487 
01488   //kdDebug(6070) << "ScheduledAction::execute " << this << endl;
01489   if (isFunction) {
01490     if (func.implementsCall()) {
01491       // #### check this
01492       Q_ASSERT( window->m_part );
01493       if ( window->m_part )
01494       {
01495         KJS::Interpreter *interpreter = KJSProxy::proxy( window->m_part )->interpreter();
01496         ExecState *exec = interpreter->globalExec();
01497         Q_ASSERT( window == interpreter->globalObject().imp() );
01498         Object obj( window );
01499         func.call(exec,obj,args); // note that call() creates its own execution state for the func call
01500       }
01501     }
01502   }
01503   else {
01504     window->m_part->executeScript(code);
01505   }
01506 
01507   interpreter->setProcessingTimerCallback(false);
01508 }
01509 
01510 ScheduledAction::~ScheduledAction()
01511 {
01512   //kdDebug(6070) << "ScheduledAction::~ScheduledAction " << this << endl;
01513 }
01514 
01516 
01517 WindowQObject::WindowQObject(Window *w)
01518   : parent(w)
01519 {
01520   //kdDebug(6070) << "WindowQObject::WindowQObject " << this << endl;
01521   part = parent->m_part;
01522   if ( !part )
01523       kdWarning(6070) << "null part in " << k_funcinfo << endl;
01524   else
01525       connect( part, SIGNAL( destroyed() ),
01526                this, SLOT( parentDestroyed() ) );
01527 }
01528 
01529 WindowQObject::~WindowQObject()
01530 {
01531   //kdDebug(6070) << "WindowQObject::~WindowQObject " << this << endl;
01532   parentDestroyed(); // reuse same code
01533 }
01534 
01535 void WindowQObject::parentDestroyed()
01536 {
01537   //kdDebug(6070) << "WindowQObject::parentDestroyed " << this << " we have " << scheduledActions.count() << " actions in the map" << endl;
01538   killTimers();
01539   QMapIterator<int,ScheduledAction*> it;
01540   for (it = scheduledActions.begin(); it != scheduledActions.end(); ++it) {
01541     ScheduledAction *action = *it;
01542     //kdDebug(6070) << "WindowQObject::parentDestroyed deleting action " << action << endl;
01543     delete action;
01544   }
01545   scheduledActions.clear();
01546 }
01547 
01548 int WindowQObject::installTimeout(const UString &handler, int t, bool singleShot)
01549 {
01550   //kdDebug(6070) << "WindowQObject::installTimeout " << this << " " << handler.ascii() << " milliseconds=" << t << endl;
01551   if (t < 10) t = 10;
01552   int id = startTimer(t);
01553   ScheduledAction *action = new ScheduledAction(handler.qstring(),singleShot);
01554   scheduledActions.insert(id, action);
01555   //kdDebug(6070) << this << " got id=" << id << " action=" << action << " - now having " << scheduledActions.count() << " actions"<<endl;
01556   return id;
01557 }
01558 
01559 int WindowQObject::installTimeout(const Value &func, List args, int t, bool singleShot)
01560 {
01561   Object objFunc = Object::dynamicCast( func );
01562   if (t < 10) t = 10;
01563   int id = startTimer(t);
01564   scheduledActions.insert(id, new ScheduledAction(objFunc,args,singleShot));
01565   return id;
01566 }
01567 
01568 void WindowQObject::clearTimeout(int timerId, bool delAction)
01569 {
01570   //kdDebug(6070) << "WindowQObject::clearTimeout " << this << " timerId=" << timerId << " delAction=" << delAction << endl;
01571   killTimer(timerId);
01572   if (delAction) {
01573     QMapIterator<int,ScheduledAction*> it = scheduledActions.find(timerId);
01574     if (it != scheduledActions.end()) {
01575       ScheduledAction *action = *it;
01576       scheduledActions.remove(it);
01577       delete action;
01578     }
01579   }
01580 }
01581 
01582 void WindowQObject::timerEvent(QTimerEvent *e)
01583 {
01584   QMapIterator<int,ScheduledAction*> it = scheduledActions.find(e->timerId());
01585   if (it != scheduledActions.end()) {
01586     ScheduledAction *action = *it;
01587     bool singleShot = action->singleShot;
01588     //kdDebug(6070) << "WindowQObject::timerEvent " << this << " action=" << action << " singleShot:" << singleShot << endl;
01589 
01590     // remove single shots installed by setTimeout()
01591     if (singleShot)
01592     {
01593       clearTimeout(e->timerId(),false);
01594       scheduledActions.remove(it);
01595     }
01596     if (!parent->part().isNull())
01597       action->execute(parent);
01598 
01599     // It is important to test singleShot and not action->singleShot here - the
01600     // action could have been deleted already if not single shot and if the
01601     // JS code called by execute() calls clearTimeout().
01602     if (singleShot)
01603       delete action;
01604   } else
01605     kdWarning(6070) << "WindowQObject::timerEvent this=" << this << " timer " << e->timerId()
01606                     << " not found (" << scheduledActions.count() << " actions in map)" << endl;
01607 }
01608 
01609 void WindowQObject::timeoutClose()
01610 {
01611   parent->closeNow();
01612 }
01613 
01614 Value FrameArray::get(ExecState *exec, const UString &p) const
01615 {
01616 #ifdef KJS_VERBOSE
01617   kdDebug(6070) << "FrameArray::get " << p.qstring() << " part=" << (void*)part << endl;
01618 #endif
01619   if (part.isNull())
01620     return Undefined();
01621 
01622   QPtrList<KParts::ReadOnlyPart> frames = part->frames();
01623   int len = frames.count();
01624   if (p == "length")
01625     return Number(len);
01626   else if (p== "location") // non-standard property, but works in NS and IE
01627   {
01628     Object obj = Object::dynamicCast( Window::retrieve( part ) );
01629     if ( !obj.isNull() )
01630       return obj.get( exec, "location" );
01631     return Undefined();
01632   }
01633 
01634   // check for the name or number
01635   KParts::ReadOnlyPart *frame = part->findFrame(p.qstring());
01636   if (!frame) {
01637     int i = (int)p.toDouble();
01638     if (i >= 0 && i < len)
01639       frame = frames.at(i);
01640   }
01641 
01642   // we are potentially fetching a reference to a another Window object here.
01643   // i.e. we may be accessing objects from another interpreter instance.
01644   // Therefore we have to be a bit careful with memory managment.
01645   if (frame && frame->inherits("KHTMLPart")) {
01646     KHTMLPart *khtml = static_cast<KHTMLPart*>(frame);
01647     return Window::retrieve(khtml);
01648   }
01649 
01650   return ObjectImp::get(exec, p);
01651 }
01652 
01654 
01655 const ClassInfo Location::info = { "Location", 0, &LocationTable, 0 };
01656 /*
01657 @begin LocationTable 11
01658   hash      Location::Hash      DontDelete
01659   host      Location::Host      DontDelete
01660   hostname  Location::Hostname  DontDelete
01661   href      Location::Href      DontDelete
01662   pathname  Location::Pathname  DontDelete
01663   port      Location::Port      DontDelete
01664   protocol  Location::Protocol  DontDelete
01665   search    Location::Search    DontDelete
01666   [[==]]    Location::EqualEqual    DontDelete|ReadOnly
01667   assign    Location::Assign    DontDelete|Function 1
01668   toString  Location::ToString  DontDelete|Function 0
01669   replace   Location::Replace   DontDelete|Function 1
01670   reload    Location::Reload    DontDelete|Function 0
01671 @end
01672 */
01673 IMPLEMENT_PROTOFUNC_DOM(LocationFunc)
01674 Location::Location(KHTMLPart *p) : m_part(p)
01675 {
01676   //kdDebug(6070) << "Location::Location " << this << " m_part=" << (void*)m_part << endl;
01677 }
01678 
01679 Location::~Location()
01680 {
01681   //kdDebug(6070) << "Location::~Location " << this << " m_part=" << (void*)m_part << endl;
01682 }
01683 
01684 Value Location::get(ExecState *exec, const UString &p) const
01685 {
01686 #ifdef KJS_VERBOSE
01687   kdDebug(6070) << "Location::get " << p.qstring() << " m_part=" << (void*)m_part << endl;
01688 #endif
01689 
01690   if (m_part.isNull())
01691     return Undefined();
01692 
01693   const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
01694 
01695   // properties that work on all Location objects
01696   if ( entry && entry->value == Replace )
01697       return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
01698 
01699   // XSS check
01700   const Window* window = Window::retrieveWindow( m_part );
01701   if ( !window || !window->isSafeScript(exec) )
01702     return Undefined();
01703 
01704   KURL url = m_part->url();
01705   if (entry)
01706     switch (entry->value) {
01707     case Hash:
01708       return String( url.ref().isNull() ? QString("") : "#" + url.ref() );
01709     case Host: {
01710       UString str = url.host();
01711       if (url.port())
01712         str += ":" + QString::number((int)url.port());
01713       return String(str);
01714       // Note: this is the IE spec. The NS spec swaps the two, it says
01715       // "The hostname property is the concatenation of the host and port properties, separated by a colon."
01716       // Bleh.
01717     }
01718     case Hostname:
01719       return String( url.host() );
01720     case Href:
01721       if (!url.hasPath())
01722         return String( url.prettyURL()+"/" );
01723       else
01724         return String( url.prettyURL() );
01725     case Pathname:
01726       return String( url.path().isEmpty() ? QString("/") : url.path() );
01727     case Port:
01728       return String( url.port() ? QString::number((int)url.port()) : QString::fromLatin1("") );
01729     case Protocol:
01730       return String( url.protocol()+":" );
01731     case Search:
01732       return String( url.query() );
01733     case EqualEqual: // [[==]]
01734       return String(toString(exec));
01735     case ToString:
01736       return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
01737     }
01738   // Look for overrides
01739   ValueImp * val = ObjectImp::getDirect(p);
01740   if (val)
01741     return Value(val);
01742   if (entry && (entry->attr & Function))
01743     return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
01744 
01745   return Undefined();
01746 }
01747 
01748 void Location::put(ExecState *exec, const UString &p, const Value &v, int attr)
01749 {
01750 #ifdef KJS_VERBOSE
01751   kdDebug(6070) << "Location::put " << p.qstring() << " m_part=" << (void*)m_part << endl;
01752 #endif
01753   if (m_part.isNull())
01754     return;
01755 
01756   // XSS check
01757   const Window* window = Window::retrieveWindow( m_part );
01758   if ( !window || !window->isSafeScript(exec) )
01759     return;
01760 
01761   QString str = v.toString(exec).qstring();
01762   KURL url = m_part->url();
01763   const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
01764   if (entry)
01765     switch (entry->value) {
01766     case Href: {
01767       KHTMLPart* p = Window::retrieveActive(exec)->part();
01768       if ( p )
01769         url = p->htmlDocument().completeURL( str ).string();
01770       else
01771         url = str;
01772       break;
01773     }
01774     case Hash:
01775       // when the hash is already the same ignore it
01776       if (str == url.ref()) return;
01777       url.setRef(str);
01778       break;
01779     case Host: {
01780       QString host = str.left(str.find(":"));
01781       QString port = str.mid(str.find(":")+1);
01782       url.setHost(host);
01783       url.setPort(port.toUInt());
01784       break;
01785     }
01786     case Hostname:
01787       url.setHost(str);
01788       break;
01789     case Pathname:
01790       url.setPath(str);
01791       break;
01792     case Port:
01793       url.setPort(str.toUInt());
01794       break;
01795     case Protocol:
01796       url.setProtocol(str);
01797       break;
01798     case Search:
01799       url.setQuery(str);
01800       break;
01801     }
01802   else {
01803     ObjectImp::put(exec, p, v, attr);
01804     return;
01805   }
01806 
01807   Window::retrieveWindow(m_part)->goURL(exec, url.url(), false /* don't lock history*/ );
01808 }
01809 
01810 Value Location::toPrimitive(ExecState *exec, Type) const
01811 {
01812   Window* window = Window::retrieveWindow( m_part );
01813   if ( window && window->isSafeScript(exec) )
01814     return String(toString(exec));
01815   return Undefined();
01816 }
01817 
01818 UString Location::toString(ExecState *exec) const
01819 {
01820   Window* window = Window::retrieveWindow( m_part );
01821   if ( window && window->isSafeScript(exec) )
01822   {
01823     if (!m_part->url().hasPath())
01824       return m_part->url().prettyURL()+"/";
01825     else
01826       return m_part->url().prettyURL();
01827   }
01828   return "";
01829 }
01830 
01831 Value LocationFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
01832 {
01833   KJS_CHECK_THIS( Location, thisObj );
01834   Location *location = static_cast<Location *>(thisObj.imp());
01835   KHTMLPart *part = location->part();
01836 
01837   if (!part) return Undefined();
01838 
01839   Window* window = Window::retrieveWindow(part);
01840 
01841   if ( !window->isSafeScript(exec) && id != Location::Replace)
01842       return Undefined();
01843 
01844   switch (id) {
01845   case Location::Assign:
01846   case Location::Replace:
01847     Window::retrieveWindow(part)->goURL(exec, args[0].toString(exec).qstring(), 
01848             id == Location::Replace);
01849     break;
01850   case Location::Reload:
01851     part->scheduleRedirection(-1, part->url().url(), true/*lock history*/);
01852     break;
01853   case Location::ToString:
01854     return String(location->toString(exec));
01855   }
01856   return Undefined();
01857 }
01858 
01860 
01861 const ClassInfo History::info = { "History", 0, 0, 0 };
01862 /*
01863 @begin HistoryTable 4
01864   length    History::Length     DontDelete|ReadOnly
01865   back      History::Back       DontDelete|Function 0
01866   forward   History::Forward    DontDelete|Function 0
01867   go        History::Go     DontDelete|Function 1
01868 @end
01869 */
01870 IMPLEMENT_PROTOFUNC_DOM(HistoryFunc)
01871 
01872 Value History::get(ExecState *exec, const UString &p) const
01873 {
01874   return lookupGet<HistoryFunc,History,ObjectImp>(exec,p,&HistoryTable,this);
01875 }
01876 
01877 Value History::getValueProperty(ExecState *, int token) const
01878 {
01879   switch (token) {
01880   case Length:
01881   {
01882     KParts::BrowserExtension *ext = part->browserExtension();
01883     if ( !ext )
01884       return Number( 0 );
01885 
01886     KParts::BrowserInterface *iface = ext->browserInterface();
01887     if ( !iface )
01888       return Number( 0 );
01889 
01890     QVariant length = iface->property( "historyLength" );
01891 
01892     if ( length.type() != QVariant::UInt )
01893       return Number( 0 );
01894 
01895     return Number( length.toUInt() );
01896   }
01897   default:
01898     kdWarning(6070) << "Unhandled token in History::getValueProperty : " << token << endl;
01899     return Undefined();
01900   }
01901 }
01902 
01903 Value HistoryFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
01904 {
01905   KJS_CHECK_THIS( History, thisObj );
01906   History *history = static_cast<History *>(thisObj.imp());
01907 
01908   Value v = args[0];
01909   Number n;
01910   if(!v.isNull())
01911     n = v.toInteger(exec);
01912 
01913   int steps;
01914   switch (id) {
01915   case History::Back:
01916     steps = -1;
01917     break;
01918   case History::Forward:
01919     steps = 1;
01920     break;
01921   case History::Go:
01922     steps = n.intValue();
01923     break;
01924   default:
01925     return Undefined();
01926   }
01927 
01928   // Special case for go(0) from a frame -> reload only the frame
01929   // go(i!=0) from a frame navigates into the history of the frame only,
01930   // in both IE and NS (but not in Mozilla).... we can't easily do that
01931   // in Konqueror...
01932   if (!steps) // add && history->part->parentPart() to get only frames, but doesn't matter
01933   {
01934     history->part->openURL( history->part->url() ); 
01935   } else
01936   {
01937     // Delay it.
01938     // Testcase: history.back(); alert("hello");
01939     Window* window = Window::retrieveWindow( history->part );
01940     window->delayedGoHistory( steps );
01941   }
01942   return Undefined();
01943 }
01944 
01946 
01947 #ifdef Q_WS_QWS
01948 
01949 const ClassInfo Konqueror::info = { "Konqueror", 0, 0, 0 };
01950 
01951 bool Konqueror::hasProperty(ExecState *exec, const UString &p) const
01952 {
01953   if ( p.qstring().startsWith( "goHistory" ) ) return false;
01954 
01955   return true;
01956 }
01957 
01958 Value Konqueror::get(ExecState *exec, const UString &p) const
01959 {
01960   if ( p == "goHistory" || part->url().protocol() != "http" || part->url().host() != "localhost" )
01961     return Undefined();
01962 
01963   KParts::BrowserExtension *ext = part->browserExtension();
01964   if ( ext ) {
01965     KParts::BrowserInterface *iface = ext->browserInterface();
01966     if ( iface ) {
01967       QVariant prop = iface->property( p.qstring().latin1() );
01968 
01969       if ( prop.isValid() ) {
01970         switch( prop.type() ) {
01971         case QVariant::Int:
01972           return Number( prop.toInt() );
01973         case QVariant::String:
01974           return String( prop.toString() );
01975         default:
01976           break;
01977         }
01978       }
01979     }
01980   }
01981 
01982   return /*Function*/( new KonquerorFunc(this, p.qstring().latin1() ) );
01983 }
01984 
01985 Value KonquerorFunc::tryCall(ExecState *exec, Object &, const List &args)
01986 {
01987   KParts::BrowserExtension *ext = konqueror->part->browserExtension();
01988 
01989   if(!ext)
01990     return Undefined();
01991 
01992   KParts::BrowserInterface *iface = ext->browserInterface();
01993 
01994   if ( !iface )
01995     return Undefined();
01996 
01997   QCString n = m_name.data();
01998   n += "()";
01999   iface->callMethod( n.data(), QVariant() );
02000 
02001   return Undefined();
02002 }
02003 
02004 UString Konqueror::toString(ExecState *) const
02005 {
02006   return UString("[object Konqueror]");
02007 }
02008 
02009 #endif
02010 
02011 
02012 #include "kjs_window.moc"
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.0.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Oct 8 12:22:41 2003 by doxygen 1.2.18 written by Dimitri van Heesch, © 1997-2001