Improve the display of apple.com. innerWidth and innerHeight refer to the size...
[WebKit-https.git] / WebCore / khtml / ecma / kjs_window.cpp
1 // -*- c-basic-offset: 2 -*-
2 /*
3  *  This file is part of the KDE libraries
4  *  Copyright (C) 2000 Harri Porten (porten@kde.org)
5  *  Copyright (C) 2003 Apple Computer, Inc.
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Lesser General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public
18  *  License along with this library; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include <qstylesheet.h>
23 #include <qtimer.h>
24 #include <qinputdialog.h>
25 #include <qpaintdevicemetrics.h>
26 #include <qapplication.h>
27 #include <kdebug.h>
28 #include <kmessagebox.h>
29 #include <klocale.h>
30 #include <kparts/browserinterface.h>
31 #include <kwin.h>
32 #include <kwinmodule.h>
33 #include <kconfig.h>
34 #include <assert.h>
35 #include <qstyle.h>
36 #include "rendering/render_canvas.h"
37
38 #if APPLE_CHANGES
39 #include "KWQLogging.h"
40 #include "KWQKConfigBase.h"
41 #endif
42 #include <kjs/collector.h>
43 #include "kjs_proxy.h"
44 #include "kjs_window.h"
45 #include "kjs_navigator.h"
46 #include "kjs_html.h"
47 #include "kjs_range.h"
48 #include "kjs_traversal.h"
49 #include "kjs_css.h"
50 #include "kjs_events.h"
51 #include "xmlhttprequest.h"
52 #include "xmlserializer.h"
53
54 #include "khtmlview.h"
55 #include "khtml_part.h"
56 #include "dom/dom_string.h"
57 #include "dom/dom_node.h"
58 #include "editing/htmlediting.h"
59 #include "editing/selection.h"
60 #include "xml/dom2_eventsimpl.h"
61 #include "xml/dom_docimpl.h"
62 #include "xml/dom_elementimpl.h"
63 #include "xml/dom_position.h"
64 #include "html/html_documentimpl.h"
65
66 #include "misc/htmltags.h"
67
68 using DOM::DocumentImpl;
69 using DOM::DOMString;
70 using DOM::ElementImpl;
71 using DOM::Node;
72 using DOM::Position;
73 using khtml::TypingCommand;
74
75 using namespace KJS;
76
77 namespace KJS {
78
79 ////////////////////// History Object ////////////////////////
80
81   class History : public ObjectImp {
82     friend class HistoryFunc;
83   public:
84     History(ExecState *exec, KHTMLPart *p)
85       : ObjectImp(exec->lexicalInterpreter()->builtinObjectPrototype()), part(p) { }
86     virtual Value get(ExecState *exec, const Identifier &propertyName) const;
87     Value getValueProperty(ExecState *exec, int token) const;
88     virtual const ClassInfo* classInfo() const { return &info; }
89     static const ClassInfo info;
90     enum { Back, Forward, Go, Length };
91     virtual UString toString(ExecState *exec) const;
92   private:
93     QGuardedPtr<KHTMLPart> part;
94   };
95
96   class FrameArray : public ObjectImp {
97   public:
98     FrameArray(ExecState *exec, KHTMLPart *p)
99       : ObjectImp(exec->lexicalInterpreter()->builtinObjectPrototype()), part(p) { }
100     virtual Value get(ExecState *exec, const Identifier &propertyName) const;
101     virtual UString toString(ExecState *exec) const;
102   private:
103     QGuardedPtr<KHTMLPart> part;
104   };
105
106 #ifdef Q_WS_QWS
107   class KonquerorFunc : public DOMFunction {
108   public:
109     KonquerorFunc(const Konqueror* k, const char* name)
110       : DOMFunction(), konqueror(k), m_name(name) { }
111     virtual Value tryCall(ExecState *exec, Object &thisObj, const List &args);
112
113   private:
114     const Konqueror* konqueror;
115     QCString m_name;
116   };
117 #endif
118 }; // namespace KJS
119
120 #include "kjs_window.lut.h"
121
122 ////////////////////// Screen Object ////////////////////////
123
124 // table for screen object
125 /*
126 @begin ScreenTable 7
127   height        Screen::Height          DontEnum|ReadOnly
128   width         Screen::Width           DontEnum|ReadOnly
129   colorDepth    Screen::ColorDepth      DontEnum|ReadOnly
130   pixelDepth    Screen::PixelDepth      DontEnum|ReadOnly
131   availLeft     Screen::AvailLeft       DontEnum|ReadOnly
132   availTop      Screen::AvailTop        DontEnum|ReadOnly
133   availHeight   Screen::AvailHeight     DontEnum|ReadOnly
134   availWidth    Screen::AvailWidth      DontEnum|ReadOnly
135 @end
136 */
137
138 const ClassInfo Screen::info = { "Screen", 0, &ScreenTable, 0 };
139
140 // We set the object prototype so that toString is implemented
141 Screen::Screen(ExecState *exec)
142   : ObjectImp(exec->lexicalInterpreter()->builtinObjectPrototype()) {}
143
144 Value Screen::get(ExecState *exec, const Identifier &p) const
145 {
146 #ifdef KJS_VERBOSE
147   kdDebug(6070) << "Screen::get " << p.qstring() << endl;
148 #endif
149   return lookupGetValue<Screen,ObjectImp>(exec,p,&ScreenTable,this);
150 }
151
152 Value Screen::getValueProperty(ExecState *exec, int token) const
153 {
154   KWinModule info;
155   QWidget *thisWidget = Window::retrieveActive(exec)->part()->view();
156   QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(thisWidget));
157
158   switch( token ) {
159   case Height:
160     return Number(sg.height());
161   case Width:
162     return Number(sg.width());
163   case ColorDepth:
164   case PixelDepth: {
165     QPaintDeviceMetrics m(QApplication::desktop());
166     return Number(m.depth());
167   }
168   case AvailLeft: {
169     QRect clipped = info.workArea().intersect(sg);
170     return Number(clipped.x()-sg.x());
171   }
172   case AvailTop: {
173     QRect clipped = info.workArea().intersect(sg);
174     return Number(clipped.y()-sg.y());
175   }
176   case AvailHeight: {
177     QRect clipped = info.workArea().intersect(sg);
178     return Number(clipped.height());
179   }
180   case AvailWidth: {
181     QRect clipped = info.workArea().intersect(sg);
182     return Number(clipped.width());
183   }
184   default:
185     kdWarning() << "Screen::getValueProperty unhandled token " << token << endl;
186     return Undefined();
187   }
188 }
189
190 ////////////////////// Window Object ////////////////////////
191
192 const ClassInfo Window::info = { "Window", 0, &WindowTable, 0 };
193
194 /*
195 @begin WindowTable 91
196   closed        Window::Closed          DontDelete|ReadOnly
197   crypto        Window::Crypto          DontDelete|ReadOnly
198   defaultStatus Window::DefaultStatus   DontDelete
199   defaultstatus Window::DefaultStatus   DontDelete
200   status        Window::Status          DontDelete
201   document      Window::Document        DontDelete|ReadOnly
202   Node          Window::Node            DontDelete
203   Event         Window::EventCtor       DontDelete
204   Range         Window::Range           DontDelete
205   NodeFilter    Window::NodeFilter      DontDelete
206   DOMException  Window::DOMException    DontDelete
207   CSSRule       Window::CSSRule         DontDelete
208   frames        Window::Frames          DontDelete|ReadOnly
209   history       Window::_History        DontDelete|ReadOnly
210   event         Window::Event           DontDelete
211   innerHeight   Window::InnerHeight     DontDelete|ReadOnly
212   innerWidth    Window::InnerWidth      DontDelete|ReadOnly
213   length        Window::Length          DontDelete|ReadOnly
214   location      Window::_Location       DontDelete
215   locationbar   Window::Locationbar     DontDelete
216   name          Window::Name            DontDelete
217   navigator     Window::_Navigator      DontDelete|ReadOnly
218   clientInformation     Window::ClientInformation       DontDelete|ReadOnly
219   konqueror     Window::_Konqueror      DontDelete|ReadOnly
220   menubar       Window::Menubar         DontDelete|ReadOnly
221   offscreenBuffering    Window::OffscreenBuffering      DontDelete|ReadOnly
222   opener        Window::Opener          DontDelete|ReadOnly
223   outerHeight   Window::OuterHeight     DontDelete|ReadOnly
224   outerWidth    Window::OuterWidth      DontDelete|ReadOnly
225   pageXOffset   Window::PageXOffset     DontDelete|ReadOnly
226   pageYOffset   Window::PageYOffset     DontDelete|ReadOnly
227   parent        Window::Parent          DontDelete|ReadOnly
228   personalbar   Window::Personalbar     DontDelete|ReadOnly
229   screenX       Window::ScreenX         DontDelete|ReadOnly
230   screenY       Window::ScreenY         DontDelete|ReadOnly
231   screenLeft    Window::ScreenLeft      DontDelete|ReadOnly
232   screenTop     Window::ScreenTop       DontDelete|ReadOnly
233   scrollbars    Window::Scrollbars      DontDelete|ReadOnly
234   statusbar     Window::Statusbar       DontDelete|ReadOnly
235   toolbar       Window::Toolbar         DontDelete|ReadOnly
236   scroll        Window::Scroll          DontDelete|Function 2
237   scrollBy      Window::ScrollBy        DontDelete|Function 2
238   scrollTo      Window::ScrollTo        DontDelete|Function 2
239   scrollX       Window::ScrollX         DontDelete|ReadOnly
240   scrollY       Window::ScrollY         DontDelete|ReadOnly
241   moveBy        Window::MoveBy          DontDelete|Function 2
242   moveTo        Window::MoveTo          DontDelete|Function 2
243   resizeBy      Window::ResizeBy        DontDelete|Function 2
244   resizeTo      Window::ResizeTo        DontDelete|Function 2
245   self          Window::Self            DontDelete|ReadOnly
246   window        Window::_Window         DontDelete|ReadOnly
247   top           Window::Top             DontDelete|ReadOnly
248   screen        Window::_Screen         DontDelete|ReadOnly
249   Image         Window::Image           DontDelete|ReadOnly
250   Option        Window::Option          DontDelete|ReadOnly
251   XMLHttpRequest        Window::XMLHttpRequest  DontDelete|ReadOnly
252   XMLSerializer Window::XMLSerializer   DontDelete|ReadOnly
253   alert         Window::Alert           DontDelete|Function 1
254   confirm       Window::Confirm         DontDelete|Function 1
255   prompt        Window::Prompt          DontDelete|Function 2
256   open          Window::Open            DontDelete|Function 3
257   print         Window::Print           DontDelete|Function 2
258   setTimeout    Window::SetTimeout      DontDelete|Function 2
259   clearTimeout  Window::ClearTimeout    DontDelete|Function 1
260   focus         Window::Focus           DontDelete|Function 0
261   getSelection  Window::GetSelection    DontDelete|Function 0
262   blur          Window::Blur            DontDelete|Function 0
263   close         Window::Close           DontDelete|Function 0
264   setInterval   Window::SetInterval     DontDelete|Function 2
265   clearInterval Window::ClearInterval   DontDelete|Function 1
266   captureEvents Window::CaptureEvents   DontDelete|Function 0
267   releaseEvents Window::ReleaseEvents   DontDelete|Function 0
268 # Warning, when adding a function to this object you need to add a case in Window::get
269   addEventListener      Window::AddEventListener        DontDelete|Function 3
270   removeEventListener   Window::RemoveEventListener     DontDelete|Function 3
271   onabort       Window::Onabort         DontDelete
272   onblur        Window::Onblur          DontDelete
273   onchange      Window::Onchange        DontDelete
274   onclick       Window::Onclick         DontDelete
275   ondblclick    Window::Ondblclick      DontDelete
276   ondragdrop    Window::Ondragdrop      DontDelete
277   onerror       Window::Onerror         DontDelete
278   onfocus       Window::Onfocus         DontDelete
279   onkeydown     Window::Onkeydown       DontDelete
280   onkeypress    Window::Onkeypress      DontDelete
281   onkeyup       Window::Onkeyup         DontDelete
282   onload        Window::Onload          DontDelete
283   onmousedown   Window::Onmousedown     DontDelete
284   onmousemove   Window::Onmousemove     DontDelete
285   onmouseout    Window::Onmouseout      DontDelete
286   onmouseover   Window::Onmouseover     DontDelete
287   onmouseup     Window::Onmouseup       DontDelete
288   onmousewheel  Window::OnWindowMouseWheel      DontDelete
289   onmove        Window::Onmove          DontDelete
290   onreset       Window::Onreset         DontDelete
291   onresize      Window::Onresize        DontDelete
292   onscroll      Window::Onscroll        DontDelete
293   onsearch      Window::Onsearch        DontDelete
294   onselect      Window::Onselect        DontDelete
295   onsubmit      Window::Onsubmit        DontDelete
296   onunload      Window::Onunload        DontDelete
297   frameElement  Window::FrameElement    DontDelete|ReadOnly
298 @end
299 */
300 IMPLEMENT_PROTOFUNC(WindowFunc)
301
302 Window::Window(KHTMLPart *p)
303   : ObjectImp(/*no proto*/)
304   , m_part(p)
305   , screen(0)
306   , history(0)
307   , frames(0)
308   , loc(0)
309   , m_selection(0)
310   , m_locationbar(0)
311   , m_menubar(0)
312   , m_personalbar(0)
313   , m_scrollbars(0)
314   , m_statusbar(0)
315   , m_toolbar(0)
316   , m_evt(0)
317 {
318   winq = new WindowQObject(this);
319   //kdDebug(6070) << "Window::Window this=" << this << " part=" << m_part << " " << m_part->name() << endl;
320 }
321
322 Window::~Window()
323 {
324   kdDebug(6070) << "Window::~Window this=" << this << " part=" << m_part << endl;
325   delete winq;
326 }
327
328 KJS::Interpreter *Window::interpreter() const
329 {
330     return KJSProxy::proxy( m_part )->interpreter();
331 }
332
333 Window *Window::retrieveWindow(KHTMLPart *p)
334 {
335   Object obj = Object::dynamicCast( retrieve( p ) );
336 #ifndef NDEBUG
337   // obj should never be null, except when javascript has been disabled in that part.
338   if ( p && p->jScriptEnabled() )
339   {
340     assert( !obj.isNull() );
341 #ifndef QWS
342     //assert( dynamic_cast<KJS::Window*>(obj.imp()) ); // type checking
343 #endif
344   }
345 #endif
346   if ( obj.isNull() ) // JS disabled
347     return 0;
348   return static_cast<KJS::Window*>(obj.imp());
349 }
350
351 Window *Window::retrieveActive(ExecState *exec)
352 {
353   ValueImp *imp = exec->dynamicInterpreter()->globalObject().imp();
354   assert( imp );
355 #ifndef QWS
356   //assert( dynamic_cast<KJS::Window*>(imp) );
357 #endif
358   return static_cast<KJS::Window*>(imp);
359 }
360
361 Value Window::retrieve(KHTMLPart *p)
362 {
363   assert(p);
364   KJSProxy *proxy = KJSProxy::proxy( p );
365   if (proxy) {
366 #ifdef KJS_VERBOSE
367     kdDebug(6070) << "Window::retrieve part=" << p << " interpreter=" << proxy->interpreter() << " window=" << proxy->interpreter()->globalObject().imp() << endl;
368 #endif
369     return proxy->interpreter()->globalObject(); // the Global object is the "window"
370   } else
371     return Undefined(); // This can happen with JS disabled on the domain of that window
372 }
373
374 Location *Window::location() const
375 {
376   if (!loc)
377     const_cast<Window*>(this)->loc = new Location(m_part);
378   return loc;
379 }
380
381 Selection *Window::selection() const
382 {
383   if (!m_selection)
384     const_cast<Window*>(this)->m_selection = new Selection(m_part);
385   return m_selection;
386 }
387
388 BarInfo *Window::locationbar(ExecState *exec) const
389 {
390   if (!m_locationbar)
391     const_cast<Window*>(this)->m_locationbar = new BarInfo(exec, m_part, BarInfo::Locationbar);
392   return m_locationbar;
393 }
394
395 BarInfo *Window::menubar(ExecState *exec) const
396 {
397   if (!m_menubar)
398     const_cast<Window*>(this)->m_menubar = new BarInfo(exec, m_part, BarInfo::Menubar);
399   return m_menubar;
400 }
401
402 BarInfo *Window::personalbar(ExecState *exec) const
403 {
404   if (!m_personalbar)
405     const_cast<Window*>(this)->m_personalbar = new BarInfo(exec, m_part, BarInfo::Personalbar);
406   return m_personalbar;
407 }
408
409 BarInfo *Window::statusbar(ExecState *exec) const
410 {
411   if (!m_statusbar)
412     const_cast<Window*>(this)->m_statusbar = new BarInfo(exec, m_part, BarInfo::Statusbar);
413   return m_statusbar;
414 }
415
416 BarInfo *Window::toolbar(ExecState *exec) const
417 {
418   if (!m_toolbar)
419     const_cast<Window*>(this)->m_toolbar = new BarInfo(exec, m_part, BarInfo::Toolbar);
420   return m_toolbar;
421 }
422
423 BarInfo *Window::scrollbars(ExecState *exec) const
424 {
425   if (!m_scrollbars)
426     const_cast<Window*>(this)->m_scrollbars = new BarInfo(exec, m_part, BarInfo::Scrollbars);
427   return m_scrollbars;
428 }
429
430 // reference our special objects during garbage collection
431 void Window::mark()
432 {
433   ObjectImp::mark();
434   if (screen && !screen->marked())
435     screen->mark();
436   if (history && !history->marked())
437     history->mark();
438   if (frames && !frames->marked())
439     frames->mark();
440   //kdDebug(6070) << "Window::mark " << this << " marking loc=" << loc << endl;
441   if (loc && !loc->marked())
442     loc->mark();
443   if (m_selection && !m_selection->marked())
444     m_selection->mark();
445   if (m_locationbar && !m_locationbar->marked())
446     m_locationbar->mark();
447   if (m_menubar && !m_menubar->marked())
448     m_menubar->mark();
449   if (m_personalbar && !m_personalbar->marked())
450     m_personalbar->mark();
451   if (m_scrollbars && !m_scrollbars->marked())
452     m_scrollbars->mark();
453   if (m_statusbar && !m_statusbar->marked())
454     m_statusbar->mark();
455   if (m_toolbar && !m_toolbar->marked())
456     m_toolbar->mark();
457 }
458
459 UString Window::toString(ExecState *) const
460 {
461   return "[object Window]";
462 }
463
464 static ElementImpl *frameElement(ExecState *exec, KHTMLPart *part)
465 {
466     // Find the frame element.
467     DocumentImpl *document = part->xmlDocImpl();
468     if (!document)
469         return 0;
470     ElementImpl *frameElement = document->ownerElement();
471     if (!frameElement)
472         return 0;
473
474     // Find the window object for the frame element, and do a cross-domain check.
475     DocumentImpl *frameElementDocument = frameElement->getDocument();
476     if (!frameElementDocument)
477         return 0;
478     KHTMLPart *frameElementPart = frameElementDocument->part();
479     if (!frameElementPart)
480         return 0;
481     Window *frameElementWindow = Window::retrieveWindow(frameElementPart);
482     if (!frameElementWindow)
483         return 0;
484     if (!frameElementWindow->isSafeScript(exec))
485         return 0;
486
487     return frameElement;
488 }
489
490 Value Window::get(ExecState *exec, const Identifier &p) const
491 {
492 #ifdef KJS_VERBOSE
493   kdDebug(6070) << "Window("<<this<<")::get " << p.qstring() << endl;
494 #endif
495   if ( p == "closed" )
496     return Boolean(m_part.isNull());
497
498   // we don't want any properties other than "closed" on a closed window
499   if (m_part.isNull())
500     return Undefined();
501
502   // Look for overrides first
503   ValueImp * val = ObjectImp::getDirect(p);
504   if (val) {
505     //kdDebug(6070) << "Window::get found dynamic property '" << p.ascii() << "'" << endl;
506     if (isSafeScript(exec))
507       return Value(val);
508   }
509
510   // Check for child frames by name before built-in properties to
511   // match behavior of other browsers.
512   KHTMLPart *childFrame = m_part->childFrameNamed(p.ustring().qstring());
513   if (childFrame) 
514     return retrieve(childFrame);
515
516   const HashEntry* entry = Lookup::findEntry(&WindowTable, p);
517   if (entry)
518   {
519     //kdDebug(6070) << "token: " << entry->value << endl;
520     switch( entry->value ) {
521     case Crypto:
522       return Undefined(); // ###
523     case DefaultStatus:
524       return String(UString(m_part->jsDefaultStatusBarText()));
525     case Status:
526       return String(UString(m_part->jsStatusBarText()));
527     case Document:
528       if (isSafeScript(exec))
529       {
530         if (m_part->document().isNull()) {
531 #if APPLE_CHANGES
532           KWQ(m_part)->createEmptyDocument();
533 #endif
534           kdDebug(6070) << "Document.write: adding <HTML><BODY> to create document" << endl;
535           m_part->begin();
536           m_part->write("<HTML><BODY>");
537           m_part->end();
538         }
539         Value val = getDOMNode(exec,m_part->document());
540         return val;
541       }
542       else
543         return Undefined();
544     case Node:
545       return getNodeConstructor(exec);
546     case Range:
547       return getRangeConstructor(exec);
548     case NodeFilter:
549       return getNodeFilterConstructor(exec);
550     case DOMException:
551       return getDOMExceptionConstructor(exec);
552     case CSSRule:
553       return getCSSRuleConstructor(exec);
554     case EventCtor:
555       return getEventConstructor(exec);
556     case Frames:
557       return Value(frames ? frames :
558                    (const_cast<Window*>(this)->frames = new FrameArray(exec,m_part)));
559     case _History:
560       return Value(history ? history :
561                    (const_cast<Window*>(this)->history = new History(exec,m_part)));
562
563     case Event:
564       if (m_evt)
565         return getDOMEvent(exec,*m_evt);
566       else {
567 #ifdef KJS_VERBOSE
568         kdWarning(6070) << "window(" << this << "," << m_part->name() << ").event, no event!" << endl;
569 #endif
570         return Undefined();
571       }
572     case InnerHeight:
573       if (!m_part->view())
574         return Undefined();
575       return Number(m_part->view()->visibleHeight());
576     case InnerWidth:
577       if (!m_part->view())
578         return Undefined();
579       return Number(m_part->view()->visibleWidth());
580     case Length:
581       return Number(m_part->frames().count());
582     case _Location:
583       return Value(location());
584     case Name:
585       return String(m_part->name());
586     case _Navigator:
587     case ClientInformation: {
588       // Store the navigator in the object so we get the same one each time.
589       Navigator *n = new Navigator(exec, m_part);
590       const_cast<Window *>(this)->putDirect("navigator", n, DontDelete|ReadOnly);
591       const_cast<Window *>(this)->putDirect("clientInformation", n, DontDelete|ReadOnly);
592       return Value(n);
593     }
594 #ifdef Q_WS_QWS
595     case _Konqueror:
596       return Value(new Konqueror(m_part));
597 #endif
598     case Locationbar:
599       return Value(locationbar(exec));
600     case Menubar:
601       return Value(menubar(exec));
602     case OffscreenBuffering:
603       return Boolean(true);
604     case Opener:
605       if (!m_part->opener())
606         return Null();    // ### a null Window might be better, but == null
607       else                // doesn't work yet
608         return retrieve(m_part->opener());
609     case OuterHeight:
610     case OuterWidth:
611     {
612       if (!m_part->view())
613         return Number(0);
614       KWin::Info inf = KWin::info(m_part->view()->topLevelWidget()->winId());
615       return Number(entry->value == OuterHeight ?
616                     inf.geometry.height() : inf.geometry.width());
617     }
618     case PageXOffset:
619       if (!m_part->view())
620         return Undefined();
621       updateLayout();
622       return Number(m_part->view()->contentsX());
623     case PageYOffset:
624       if (!m_part->view())
625         return Undefined();
626       updateLayout();
627       return Number(m_part->view()->contentsY());
628     case Parent:
629       return Value(retrieve(m_part->parentPart() ? m_part->parentPart() : (KHTMLPart*)m_part));
630     case Personalbar:
631       return Value(personalbar(exec));
632     case ScreenLeft:
633     case ScreenX: {
634       if (!m_part->view())
635         return Undefined();
636 #if APPLE_CHANGES
637       // We want to use frameGeometry here instead of mapToGlobal because it goes through
638       // the windowFrame method of the WebKit's UI delegate. Also we don't want to try
639       // to do anything relative to the screen the window is on, so the code below is no
640       // good of us anyway.
641       return Number(m_part->view()->topLevelWidget()->frameGeometry().x());
642 #else
643       QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(m_part->view()));
644       return Number(m_part->view()->mapToGlobal(QPoint(0,0)).x() + sg.x());
645 #endif
646     }
647     case ScreenTop:
648     case ScreenY: {
649       if (!m_part->view())
650         return Undefined();
651 #if APPLE_CHANGES
652       // See comment above in ScreenX.
653       return Number(m_part->view()->topLevelWidget()->frameGeometry().y());
654 #else
655       QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(m_part->view()));
656       return Number(m_part->view()->mapToGlobal(QPoint(0,0)).y() + sg.y());
657 #endif
658     }
659     case ScrollX: {
660       if (!m_part->view())
661         return Undefined();
662       updateLayout();
663       return Number(m_part->view()->contentsX());
664     }
665     case ScrollY: {
666       if (!m_part->view())
667         return Undefined();
668       updateLayout();
669       return Number(m_part->view()->contentsY());
670     }
671     case Scrollbars:
672       return Value(scrollbars(exec));
673     case Statusbar:
674       return Value(statusbar(exec));
675     case Toolbar:
676       return Value(toolbar(exec));
677     case Self:
678     case _Window:
679       return Value(retrieve(m_part));
680     case Top: {
681       KHTMLPart *p = m_part;
682       while (p->parentPart())
683         p = p->parentPart();
684       return Value(retrieve(p));
685     }
686     case _Screen:
687       return Value(screen ? screen :
688                    (const_cast<Window*>(this)->screen = new Screen(exec)));
689     case Image:
690       return Value(new ImageConstructorImp(exec, m_part->document()));
691     case Option:
692       return Value(new OptionConstructorImp(exec, m_part->document()));
693     case XMLHttpRequest:
694       return Value(new XMLHttpRequestConstructorImp(exec, m_part->document()));
695     case XMLSerializer:
696       return Value(new XMLSerializerConstructorImp(exec));
697     case Focus:
698     case Blur:
699     case Close:
700         return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
701     case Alert:
702     case Confirm:
703     case Prompt:
704     case Open:
705 #if APPLE_CHANGES
706     case Print:
707 #endif
708     case Scroll: // compatibility
709     case ScrollBy:
710     case ScrollTo:
711     case MoveBy:
712     case MoveTo:
713     case ResizeBy:
714     case ResizeTo:
715     case CaptureEvents:
716     case ReleaseEvents:
717     case AddEventListener:
718     case RemoveEventListener:
719     case SetTimeout:
720     case ClearTimeout:
721     case SetInterval:
722     case ClearInterval:
723     case GetSelection:
724       if (isSafeScript(exec))
725         return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
726       else
727         return Undefined();
728     case Onabort:
729       if (isSafeScript(exec))
730         return getListener(exec,DOM::EventImpl::ABORT_EVENT);
731       else
732         return Undefined();
733     case Onblur:
734       if (isSafeScript(exec))
735         return getListener(exec,DOM::EventImpl::BLUR_EVENT);
736       else
737         return Undefined();
738     case Onchange:
739       if (isSafeScript(exec))
740         return getListener(exec,DOM::EventImpl::CHANGE_EVENT);
741       else
742         return Undefined();
743     case Onclick:
744       if (isSafeScript(exec))
745         return getListener(exec,DOM::EventImpl::KHTML_CLICK_EVENT);
746       else
747         return Undefined();
748     case Ondblclick:
749       if (isSafeScript(exec))
750         return getListener(exec,DOM::EventImpl::KHTML_DBLCLICK_EVENT);
751       else
752         return Undefined();
753     case Ondragdrop:
754       if (isSafeScript(exec))
755         return getListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT);
756       else
757         return Undefined();
758     case Onerror:
759       if (isSafeScript(exec))
760         return getListener(exec,DOM::EventImpl::KHTML_ERROR_EVENT);
761       else
762         return Undefined();
763     case Onfocus:
764       if (isSafeScript(exec))
765         return getListener(exec,DOM::EventImpl::FOCUS_EVENT);
766       else
767         return Undefined();
768     case Onkeydown:
769       if (isSafeScript(exec))
770         return getListener(exec,DOM::EventImpl::KEYDOWN_EVENT);
771       else
772         return Undefined();
773     case Onkeypress:
774       if (isSafeScript(exec))
775         return getListener(exec,DOM::EventImpl::KEYPRESS_EVENT);
776       else
777         return Undefined();
778     case Onkeyup:
779       if (isSafeScript(exec))
780         return getListener(exec,DOM::EventImpl::KEYUP_EVENT);
781       else
782         return Undefined();
783     case Onload:
784       if (isSafeScript(exec))
785         return getListener(exec,DOM::EventImpl::LOAD_EVENT);
786       else
787         return Undefined();
788     case Onmousedown:
789       if (isSafeScript(exec))
790         return getListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT);
791       else
792         return Undefined();
793     case Onmousemove:
794       if (isSafeScript(exec))
795         return getListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT);
796       else
797         return Undefined();
798     case Onmouseout:
799       if (isSafeScript(exec))
800         return getListener(exec,DOM::EventImpl::MOUSEOUT_EVENT);
801       else
802         return Undefined();
803     case Onmouseover:
804       if (isSafeScript(exec))
805         return getListener(exec,DOM::EventImpl::MOUSEOVER_EVENT);
806       else
807         return Undefined();
808     case Onmouseup:
809       if (isSafeScript(exec))
810         return getListener(exec,DOM::EventImpl::MOUSEUP_EVENT);
811       else
812         return Undefined();
813     case OnWindowMouseWheel:
814       if (isSafeScript(exec))
815         return getListener(exec, DOM::EventImpl::MOUSEWHEEL_EVENT);
816       else
817         return Undefined();
818     case Onmove:
819       if (isSafeScript(exec))
820         return getListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT);
821       else
822         return Undefined();
823     case Onreset:
824       if (isSafeScript(exec))
825         return getListener(exec,DOM::EventImpl::RESET_EVENT);
826       else
827         return Undefined();
828     case Onresize:
829       if (isSafeScript(exec))
830         return getListener(exec,DOM::EventImpl::RESIZE_EVENT);
831       else
832         return Undefined();
833     case Onscroll:
834         if (isSafeScript(exec))
835             return getListener(exec,DOM::EventImpl::SCROLL_EVENT);
836         else
837             return Undefined();
838 #if APPLE_CHANGES
839     case Onsearch:
840         if (isSafeScript(exec))
841             return getListener(exec,DOM::EventImpl::SEARCH_EVENT);
842         else
843             return Undefined();
844 #endif
845     case Onselect:
846       if (isSafeScript(exec))
847         return getListener(exec,DOM::EventImpl::SELECT_EVENT);
848       else
849         return Undefined();
850     case Onsubmit:
851       if (isSafeScript(exec))
852         return getListener(exec,DOM::EventImpl::SUBMIT_EVENT);
853       else
854         return Undefined();
855     case Onunload:
856       if (isSafeScript(exec))
857         return getListener(exec,DOM::EventImpl::UNLOAD_EVENT);
858       else
859         return Undefined();
860     case FrameElement: {
861       ElementImpl *fe = frameElement(exec, m_part);
862       if (!fe)
863         return Undefined();
864       return getDOMNode(exec, fe);
865     }
866     }
867   }
868
869   KHTMLPart *kp = m_part->findFrame( p.qstring() );
870   if (kp)
871     return Value(retrieve(kp));
872
873   // allow window[1] or parent[1] etc. (#56983)
874   bool ok;
875   unsigned int i = p.toArrayIndex(&ok);
876   if (ok) {
877     QPtrList<KParts::ReadOnlyPart> frames = m_part->frames();
878     unsigned int len = frames.count();
879     if (i < len) {
880       KParts::ReadOnlyPart* frame = frames.at(i);
881       if (frame && frame->inherits("KHTMLPart")) {
882         KHTMLPart *khtml = static_cast<KHTMLPart*>(frame);
883         return Window::retrieve(khtml);
884       }
885     }
886   }
887
888   // allow shortcuts like 'Image1' instead of document.images.Image1
889   if (isSafeScript(exec) &&
890       m_part->document().isHTMLDocument()) { // might be XML
891     DOM::HTMLCollection coll = m_part->htmlDocument().all();
892     DOM::HTMLElement element = coll.namedItem(p.string());    
893     if (!element.isNull()) {
894       return getDOMNode(exec,element);
895     }
896   }
897
898   // This isn't necessarily a bug. Some code uses if(!window.blah) window.blah=1
899   // But it can also mean something isn't loaded or implemented, hence the WARNING to help grepping.
900 #ifdef KJS_VERBOSE
901   kdDebug(6070) << "WARNING: Window::get property not found: " << p.qstring() << endl;
902 #endif
903
904   if (isSafeScript(exec))
905     return ObjectImp::get(exec, p);
906
907   return Undefined();
908 }
909
910 bool Window::hasProperty(ExecState *exec, const Identifier &p) const
911 {
912   // matches logic in get function above, but no need to handle numeric values (frame indices)
913
914   if (m_part.isNull())
915     return p == "closed";
916
917   if (getDirect(p))
918     return true;
919
920   if (Lookup::findEntry(&WindowTable, p))
921     return true;
922
923   if (m_part->findFrame(p.qstring()))
924     return true;
925
926   if (!m_part->htmlDocument().all().namedItem(p.string()).isNull())
927     return true;
928
929   return false;
930 }
931
932 void Window::put(ExecState* exec, const Identifier &propertyName, const Value &value, int attr)
933 {
934   // Called by an internal KJS call (e.g. InterpreterImp's constructor) ?
935   // If yes, save time and jump directly to ObjectImp.
936   if ( (attr != None && attr != DontDelete)
937        // Same thing if we have a local override (e.g. "var location")
938        || ( ObjectImp::getDirect(propertyName) && isSafeScript(exec)) )
939   {
940     ObjectImp::put( exec, propertyName, value, attr );
941     return;
942   }
943
944   const HashEntry* entry = Lookup::findEntry(&WindowTable, propertyName);
945   if (entry)
946   {
947 #ifdef KJS_VERBOSE
948     kdDebug(6070) << "Window("<<this<<")::put " << propertyName.qstring() << endl;
949 #endif
950     switch( entry->value ) {
951     case Status: {
952       String s = value.toString(exec);
953       m_part->setJSStatusBarText(s.value().qstring());
954       return;
955     }
956     case DefaultStatus: {
957       String s = value.toString(exec);
958       m_part->setJSDefaultStatusBarText(s.value().qstring());
959       return;
960     }
961     case _Location: {
962       KHTMLPart* p = Window::retrieveActive(exec)->m_part;
963       if (p) {
964         QString dstUrl = p->htmlDocument().completeURL(value.toString(exec).string()).string();
965         if (!dstUrl.startsWith("javascript:", false) || isSafeScript(exec))
966         {
967           bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
968 #if APPLE_CHANGES
969           // We want a new history item if this JS was called via a user gesture
970           m_part->scheduleLocationChange(dstUrl, p->referrer(), !userGesture, userGesture);
971 #else
972           m_part->scheduleLocationChange(dstUrl, p->referrer(), false /*don't lock history*/, userGesture);
973 #endif
974         }
975       }
976       return;
977     }
978     case Onabort:
979       if (isSafeScript(exec))
980         setListener(exec, DOM::EventImpl::ABORT_EVENT,value);
981       return;
982     case Onblur:
983       if (isSafeScript(exec))
984         setListener(exec, DOM::EventImpl::BLUR_EVENT,value);
985       return;
986     case Onchange:
987       if (isSafeScript(exec))
988         setListener(exec, DOM::EventImpl::CHANGE_EVENT,value);
989       return;
990     case Onclick:
991       if (isSafeScript(exec))
992         setListener(exec,DOM::EventImpl::KHTML_CLICK_EVENT,value);
993       return;
994     case Ondblclick:
995       if (isSafeScript(exec))
996         setListener(exec,DOM::EventImpl::KHTML_DBLCLICK_EVENT,value);
997       return;
998     case Ondragdrop:
999       if (isSafeScript(exec))
1000         setListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT,value);
1001       return;
1002     case Onerror:
1003       if (isSafeScript(exec))
1004         setListener(exec,DOM::EventImpl::KHTML_ERROR_EVENT,value);
1005       return;
1006     case Onfocus:
1007       if (isSafeScript(exec))
1008         setListener(exec,DOM::EventImpl::FOCUS_EVENT,value);
1009       return;
1010     case Onkeydown:
1011       if (isSafeScript(exec))
1012         setListener(exec,DOM::EventImpl::KEYDOWN_EVENT,value);
1013       return;
1014     case Onkeypress:
1015       if (isSafeScript(exec))
1016         setListener(exec,DOM::EventImpl::KEYPRESS_EVENT,value);
1017       return;
1018     case Onkeyup:
1019       if (isSafeScript(exec))
1020         setListener(exec,DOM::EventImpl::KEYUP_EVENT,value);
1021       return;
1022     case Onload:
1023       if (isSafeScript(exec))
1024         setListener(exec,DOM::EventImpl::LOAD_EVENT,value);
1025       return;
1026     case Onmousedown:
1027       if (isSafeScript(exec))
1028         setListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT,value);
1029       return;
1030     case Onmousemove:
1031       if (isSafeScript(exec))
1032         setListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT,value);
1033       return;
1034     case Onmouseout:
1035       if (isSafeScript(exec))
1036         setListener(exec,DOM::EventImpl::MOUSEOUT_EVENT,value);
1037       return;
1038     case Onmouseover:
1039       if (isSafeScript(exec))
1040         setListener(exec,DOM::EventImpl::MOUSEOVER_EVENT,value);
1041       return;
1042     case Onmouseup:
1043       if (isSafeScript(exec))
1044         setListener(exec,DOM::EventImpl::MOUSEUP_EVENT,value);
1045       return;
1046     case OnWindowMouseWheel:
1047       if (isSafeScript(exec))
1048         setListener(exec, DOM::EventImpl::MOUSEWHEEL_EVENT,value);
1049       return;
1050     case Onmove:
1051       if (isSafeScript(exec))
1052         setListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT,value);
1053       return;
1054     case Onreset:
1055       if (isSafeScript(exec))
1056         setListener(exec,DOM::EventImpl::RESET_EVENT,value);
1057       return;
1058     case Onresize:
1059       if (isSafeScript(exec))
1060         setListener(exec,DOM::EventImpl::RESIZE_EVENT,value);
1061       return;
1062     case Onscroll:
1063       if (isSafeScript(exec))
1064         setListener(exec,DOM::EventImpl::SCROLL_EVENT,value);
1065       return;
1066 #if APPLE_CHANGES
1067     case Onsearch:
1068         if (isSafeScript(exec))
1069             setListener(exec,DOM::EventImpl::SEARCH_EVENT,value);
1070         return;
1071 #endif
1072     case Onselect:
1073       if (isSafeScript(exec))
1074         setListener(exec,DOM::EventImpl::SELECT_EVENT,value);
1075       return;
1076     case Onsubmit:
1077       if (isSafeScript(exec))
1078         setListener(exec,DOM::EventImpl::SUBMIT_EVENT,value);
1079       return;
1080     case Onunload:
1081       if (isSafeScript(exec))
1082         setListener(exec,DOM::EventImpl::UNLOAD_EVENT,value);
1083       return;
1084     case Name:
1085       if (isSafeScript(exec))
1086 #if APPLE_CHANGES
1087         m_part->setName( value.toString(exec).qstring() );
1088 #else
1089         m_part->setName( value.toString(exec).qstring().local8Bit().data() );
1090 #endif
1091       return;
1092     default:
1093       break;
1094     }
1095   }
1096   if (isSafeScript(exec)) {
1097     //kdDebug(6070) << "Window("<<this<<")::put storing " << propertyName.qstring() << endl;
1098     ObjectImp::put(exec, propertyName, value, attr);
1099   }
1100 }
1101
1102 bool Window::toBoolean(ExecState *) const
1103 {
1104   return !m_part.isNull();
1105 }
1106
1107 int Window::installTimeout(const UString &handler, int t, bool singleShot)
1108 {
1109   return winq->installTimeout(handler, t, singleShot);
1110 }
1111
1112 int Window::installTimeout(const Value &function, List &args, int t, bool singleShot)
1113 {
1114   return winq->installTimeout(function, args, t, singleShot);
1115 }
1116
1117 void Window::clearTimeout(int timerId)
1118 {
1119   winq->clearTimeout(timerId);
1120 }
1121
1122 #if APPLE_CHANGES
1123 bool Window::hasTimeouts()
1124 {
1125     return winq->hasTimeouts();
1126 }
1127
1128 QMap<int, ScheduledAction*> *Window::pauseTimeouts(const void *key)
1129 {
1130     return winq->pauseTimeouts(key);
1131 }
1132
1133 void Window::resumeTimeouts(QMap<int, ScheduledAction*> *sa, const void *key)
1134 {
1135     return winq->resumeTimeouts(sa, key);
1136 }
1137 #endif
1138
1139 void Window::scheduleClose()
1140 {
1141   kdDebug(6070) << "Window::scheduleClose window.close() " << m_part << endl;
1142   Q_ASSERT(winq);
1143 #if APPLE_CHANGES
1144   KWQ(m_part)->scheduleClose();
1145 #else
1146   QTimer::singleShot( 0, winq, SLOT( timeoutClose() ) );
1147 #endif
1148 }
1149
1150 static bool shouldLoadAsEmptyDocument(const KURL &url)
1151 {
1152   return url.protocol().lower() == "about" || url.isEmpty();
1153 }
1154
1155 bool Window::isSafeScript (const KJS::ScriptInterpreter *origin, const KJS::ScriptInterpreter *target)
1156 {
1157     if (origin == target)
1158         return true;
1159         
1160     KHTMLPart *originPart = origin->part();
1161     KHTMLPart *targetPart = target->part();
1162
1163     // JS may be attempting to access the "window" object, which should be valid,
1164     // even if the document hasn't been constructed yet.  If the document doesn't
1165     // exist yet allow JS to access the window object.
1166     if (!targetPart->xmlDocImpl())
1167         return true;
1168
1169     DOM::DocumentImpl *originDocument = originPart->xmlDocImpl();
1170     DOM::DocumentImpl *targetDocument = targetPart->xmlDocImpl();
1171
1172     if (!targetDocument) {
1173         return false;
1174     }
1175
1176     DOM::DOMString targetDomain = targetDocument->domain();
1177
1178     // Always allow local pages to execute any JS.
1179     if (targetDomain.isNull())
1180         return true;
1181
1182     DOM::DOMString originDomain = originDocument->domain();
1183
1184     // if this document is being initially loaded as empty by its parent
1185     // or opener, allow access from any document in the same domain as
1186     // the parent or opener.
1187     if (shouldLoadAsEmptyDocument(targetPart->url())) {
1188         KHTMLPart *ancestorPart = targetPart->opener() ? targetPart->opener() : targetPart->parentPart();
1189         while (ancestorPart && shouldLoadAsEmptyDocument(ancestorPart->url())) {
1190             ancestorPart = ancestorPart->parentPart();
1191         }
1192
1193         if (ancestorPart)
1194             originDomain = ancestorPart->xmlDocImpl()->domain();
1195     }
1196
1197     if ( targetDomain == originDomain )
1198         return true;
1199
1200     if (Interpreter::shouldPrintExceptions()) {
1201         printf("Unsafe JavaScript attempt to access frame with URL %s from frame with URL %s. Domains must match.\n", 
1202              targetDocument->URL().latin1(), originDocument->URL().latin1());
1203     }
1204     QString message;
1205     message.sprintf("Unsafe JavaScript attempt to access frame with URL %s from frame with URL %s. Domains must match.\n", 
1206                   targetDocument->URL().latin1(), originDocument->URL().latin1());
1207     KWQ(targetPart)->addMessageToConsole(message, 1, QString()); //fixme: provide a real line number and sourceurl
1208
1209     return false;
1210 }
1211
1212 bool Window::isSafeScript(ExecState *exec) const
1213 {
1214   if (m_part.isNull()) { // part deleted ? can't grant access
1215     kdDebug(6070) << "Window::isSafeScript: accessing deleted part !" << endl;
1216     return false;
1217   }
1218   KHTMLPart *activePart = static_cast<KJS::ScriptInterpreter *>( exec->dynamicInterpreter() )->part();
1219   if (!activePart) {
1220     kdDebug(6070) << "Window::isSafeScript: current interpreter's part is 0L!" << endl;
1221     return false;
1222   }
1223   if ( activePart == m_part ) // Not calling from another frame, no problem.
1224     return true;
1225
1226   // JS may be attempting to access the "window" object, which should be valid,
1227   // even if the document hasn't been constructed yet.  If the document doesn't
1228   // exist yet allow JS to access the window object.
1229   if (!m_part->xmlDocImpl())
1230       return true;
1231
1232   DOM::DocumentImpl* thisDocument = m_part->xmlDocImpl();
1233   DOM::DocumentImpl* actDocument = activePart->xmlDocImpl();
1234
1235   if (!actDocument) {
1236     kdDebug(6070) << "Window::isSafeScript: active part has no document!" << endl;
1237     return false;
1238   }
1239
1240   DOM::DOMString actDomain = actDocument->domain();
1241   
1242   // Always allow local pages to execute any JS.
1243   if (actDomain.isNull())
1244     return true;
1245   
1246   DOM::DOMString thisDomain = thisDocument->domain();
1247
1248   // if this document is being initially loaded as empty by its parent
1249   // or opener, allow access from any document in the same domain as
1250   // the parent or opener.
1251   if (shouldLoadAsEmptyDocument(m_part->url())) {
1252     KHTMLPart *ancestorPart = m_part->opener() ? m_part->opener() : m_part->parentPart();
1253     while (ancestorPart && shouldLoadAsEmptyDocument(ancestorPart->url())) {
1254       ancestorPart = ancestorPart->parentPart();
1255     }
1256     
1257     if (ancestorPart)
1258       thisDomain = ancestorPart->xmlDocImpl()->domain();
1259   }
1260
1261   //kdDebug(6070) << "current domain:" << actDomain.string() << ", frame domain:" << thisDomain.string() << endl;
1262   if ( actDomain == thisDomain )
1263     return true;
1264
1265 #if APPLE_CHANGES
1266   if (Interpreter::shouldPrintExceptions()) {
1267       printf("Unsafe JavaScript attempt to access frame with URL %s from frame with URL %s. Domains must match.\n", 
1268              thisDocument->URL().latin1(), actDocument->URL().latin1());
1269   }
1270   QString message;
1271   message.sprintf("Unsafe JavaScript attempt to access frame with URL %s from frame with URL %s. Domains must match.\n", 
1272                   thisDocument->URL().latin1(), actDocument->URL().latin1());
1273   KWQ(m_part)->addMessageToConsole(message, 1, QString());
1274 #endif
1275   
1276   kdWarning(6070) << "Javascript: access denied for current frame '" << actDomain.string() << "' to frame '" << thisDomain.string() << "'" << endl;
1277   return false;
1278 }
1279
1280 void Window::setListener(ExecState *exec, int eventId, Value func)
1281 {
1282   if (!isSafeScript(exec))
1283     return;
1284   DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(m_part->htmlDocument().handle());
1285   if (!doc)
1286     return;
1287
1288   doc->setHTMLWindowEventListener(eventId,getJSEventListener(func,true));
1289 }
1290
1291 Value Window::getListener(ExecState *exec, int eventId) const
1292 {
1293   if (!isSafeScript(exec))
1294     return Undefined();
1295   DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(m_part->htmlDocument().handle());
1296   if (!doc)
1297     return Undefined();
1298
1299   DOM::EventListener *listener = doc->getHTMLWindowEventListener(eventId);
1300   if (listener && static_cast<JSEventListener*>(listener)->listenerObjImp())
1301     return static_cast<JSEventListener*>(listener)->listenerObj();
1302   else
1303     return Null();
1304 }
1305
1306 JSEventListener *Window::getJSEventListener(const Value& val, bool html)
1307 {
1308   // This function is so hot that it's worth coding it directly with imps.
1309   if (val.type() != ObjectType)
1310     return 0;
1311   ObjectImp *listenerObject = static_cast<ObjectImp *>(val.imp());
1312
1313   JSEventListener *existingListener = jsEventListeners[listenerObject];
1314   if (existingListener)
1315     return existingListener;
1316
1317   // Note that the JSEventListener constructor adds it to our jsEventListeners list
1318   return new JSEventListener(Object(listenerObject), Object(this), html);
1319 }
1320
1321 JSUnprotectedEventListener *Window::getJSUnprotectedEventListener(const Value& val, bool html)
1322 {
1323   // This function is so hot that it's worth coding it directly with imps.
1324   if (val.type() != ObjectType)
1325     return 0;
1326   ObjectImp *listenerObject = static_cast<ObjectImp *>(val.imp());
1327
1328   JSUnprotectedEventListener *existingListener = jsUnprotectedEventListeners[listenerObject];
1329   if (existingListener)
1330     return existingListener;
1331
1332   // Note that the JSUnprotectedEventListener constructor adds it to
1333   // our jsUnprotectedEventListeners list
1334   return new JSUnprotectedEventListener(Object(listenerObject), Object(this), html);
1335 }
1336
1337 JSLazyEventListener *Window::getJSLazyEventListener(const QString& code, DOM::NodeImpl *node, int lineNumber)
1338 {
1339   return new JSLazyEventListener(code, Object(this), node, lineNumber);
1340 }
1341
1342 void Window::clear( ExecState *exec )
1343 {
1344   KJS::Interpreter::lock();
1345   kdDebug(6070) << "Window::clear " << this << endl;
1346   delete winq;
1347   winq = new WindowQObject(this);;
1348   // Get rid of everything, those user vars could hold references to DOM nodes
1349   deleteAllProperties( exec );
1350   // Really delete those properties, so that the DOM nodes get deref'ed
1351   KJS::Collector::collect();
1352   // Now recreate a working global object for the next URL that will use us
1353   KJS::Interpreter *interpreter = KJSProxy::proxy( m_part )->interpreter();
1354   interpreter->initGlobalObject();
1355   KJS::Interpreter::unlock();
1356 }
1357
1358 void Window::setCurrentEvent( DOM::Event *evt )
1359 {
1360   m_evt = evt;
1361   //kdDebug(6070) << "Window " << this << " (part=" << m_part << ")::setCurrentEvent m_evt=" << evt << endl;
1362 }
1363
1364 Value WindowFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
1365 {
1366   if (!thisObj.inherits(&Window::info)) {
1367     Object err = Error::create(exec,TypeError);
1368     exec->setException(err);
1369     return err;
1370   }
1371   Window *window = static_cast<Window *>(thisObj.imp());
1372   QString str, str2;
1373
1374   KHTMLPart *part = window->m_part;
1375   if (!part)
1376     return Undefined();
1377
1378   KHTMLView *widget = part->view();
1379   Value v = args[0];
1380   UString s = v.toString(exec);
1381   str = s.qstring();
1382
1383   switch (id) {
1384   case Window::Alert:
1385     if (part && part->xmlDocImpl())
1386       part->xmlDocImpl()->updateRendering();
1387 #if APPLE_CHANGES
1388     KWQ(part)->runJavaScriptAlert(str);
1389 #else
1390     KMessageBox::error(widget, QStyleSheet::convertFromPlainText(str), "JavaScript");
1391 #endif
1392     return Undefined();
1393   case Window::Confirm:
1394     if (part && part->xmlDocImpl())
1395       part->xmlDocImpl()->updateRendering();
1396 #if APPLE_CHANGES
1397     return Boolean(KWQ(part)->runJavaScriptConfirm(str));
1398 #else
1399     return Boolean((KMessageBox::warningYesNo(widget, QStyleSheet::convertFromPlainText(str), "JavaScript",
1400                                                 i18n("OK"), i18n("Cancel")) == KMessageBox::Yes));
1401 #endif
1402   case Window::Prompt:
1403     if (part && part->xmlDocImpl())
1404       part->xmlDocImpl()->updateRendering();
1405     bool ok;
1406 #if APPLE_CHANGES
1407     ok = KWQ(part)->runJavaScriptPrompt(str, args.size() >= 2 ? args[1].toString(exec).qstring() : QString::null, str2);
1408 #else
1409     if (args.size() >= 2)
1410       str2 = QInputDialog::getText(i18n("Konqueror: Prompt"),
1411                                    QStyleSheet::convertFromPlainText(str),
1412                                    QLineEdit::Normal,
1413                                    args[1].toString(exec).qstring(), &ok);
1414     else
1415       str2 = QInputDialog::getText(i18n("Konqueror: Prompt"),
1416                                    QStyleSheet::convertFromPlainText(str),
1417                                    QLineEdit::Normal,
1418                                    QString::null, &ok);
1419 #endif
1420     if ( ok )
1421         return String(str2);
1422     else
1423         return Null();
1424   case Window::Open:
1425   {
1426     KConfig *config = new KConfig("konquerorrc");
1427     config->setGroup("Java/JavaScript Settings");
1428 #if !APPLE_CHANGES
1429     int policy = config->readUnsignedNumEntry( "WindowOpenPolicy", 0 ); // 0=allow, 1=ask, 2=deny, 3=smart
1430 #else    
1431     int policy = config->readUnsignedNumEntry( part->settings(), "WindowOpenPolicy", 0 ); // 0=allow, 1=ask, 2=deny, 3=smart
1432 #endif
1433     delete config;
1434     if ( policy == 1 ) {
1435 #if !APPLE_CHANGES
1436       if ( KMessageBox::questionYesNo(widget,
1437                                       i18n( "This site is trying to open up a new browser "
1438                                             "window using Javascript.\n"
1439                                             "Do you want to allow this?" ),
1440                                       i18n( "Confirmation: Javascript Popup" ) ) == KMessageBox::Yes )
1441 #endif
1442         policy = 0;
1443     } else if ( policy == 3 ) // smart
1444     {
1445       // window.open disabled unless from a key/mouse event
1446       if (static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture())
1447 #if !APPLE_CHANGES
1448         policy = 0;
1449 #else
1450       {
1451         policy = 0;
1452         LOG(PopupBlocking, "Allowed JavaScript window open of %s", args[0].toString(exec).qstring().ascii());
1453       } else {
1454         LOG(PopupBlocking, "Blocked JavaScript window open of %s", args[0].toString(exec).qstring().ascii());
1455       }
1456 #endif
1457     }
1458
1459     QString frameName = !args[1].isNull() && args[1].type() != UndefinedType ?
1460                         args[1].toString(exec).qstring()
1461                         : QString("_blank");
1462
1463     if ( policy != 0 && !(part->findFrame(frameName) || frameName == "_top" || frameName == "_parent" || frameName == "_self")) {
1464       return Undefined();
1465     } else {
1466       if (v.type() == UndefinedType)
1467         str = QString();
1468
1469       KParts::WindowArgs winargs;
1470
1471       // scan feature argument
1472       v = args[2];
1473       QString features;
1474       if (!v.isNull() && v.type() != UndefinedType && v.toString(exec).size() > 0) {
1475         features = v.toString(exec).qstring();
1476         // specifying window params means false defaults
1477         winargs.menuBarVisible = false;
1478         winargs.toolBarsVisible = false;
1479         winargs.statusBarVisible = false;
1480 #if APPLE_CHANGES
1481         winargs.scrollbarsVisible = true;
1482 #endif
1483         QStringList flist = QStringList::split(',', features);
1484         QStringList::ConstIterator it = flist.begin();
1485         while (it != flist.end()) {
1486           QString s = *it++;
1487           QString key, val;
1488           int pos = s.find('=');
1489           if (pos >= 0) {
1490             key = s.left(pos).stripWhiteSpace().lower();
1491             val = s.mid(pos + 1).stripWhiteSpace().lower();
1492             int spacePos = val.find(' ');
1493             if (spacePos != -1) {
1494               val = val.left(spacePos);
1495             }
1496
1497             int scnum = QApplication::desktop()->screenNumber(widget->topLevelWidget());
1498
1499             QRect screen = QApplication::desktop()->screenGeometry(scnum);
1500             if (key == "left" || key == "screenx") {
1501               bool ok;
1502               double d = val.toDouble(&ok);
1503               if (d != 0 || ok) {
1504                 d += screen.x();
1505                 if (d < screen.x() || d > screen.right())
1506                   d = screen.x(); // only safe choice until size is determined
1507                 winargs.x = (int)d;
1508 #if APPLE_CHANGES
1509                 winargs.xSet = true;
1510 #endif
1511               }
1512             } else if (key == "top" || key == "screeny") {
1513               bool ok;
1514               double d = val.toDouble(&ok);
1515               if (d != 0 || ok) {
1516                 d += screen.y();
1517                 if (d < screen.y() || d > screen.bottom())
1518                   d = screen.y(); // only safe choice until size is determined
1519                 winargs.y = (int)d;
1520 #if APPLE_CHANGES
1521                 winargs.ySet = true;
1522 #endif
1523               }
1524             } else if (key == "height") {
1525               bool ok;
1526               double d = val.toDouble(&ok);
1527               if (d != 0 || ok) {
1528 #if !APPLE_CHANGES
1529                 d += 2*qApp->style().pixelMetric( QStyle::PM_DefaultFrameWidth ) + 2;
1530 #endif
1531                 if (d > screen.height())  // should actually check workspace
1532                   d = screen.height();
1533                 if (d < 100)
1534                   d = 100;
1535                 winargs.height = (int)d;
1536 #if APPLE_CHANGES
1537                 winargs.heightSet = true;
1538 #endif
1539               }
1540             } else if (key == "width") {
1541               bool ok;
1542               double d = val.toDouble(&ok);
1543               if (d != 0 || ok) {
1544 #if !APPLE_CHANGES
1545                 d += 2*qApp->style().pixelMetric( QStyle::PM_DefaultFrameWidth ) + 2;
1546 #endif
1547                 if (d > screen.width())    // should actually check workspace
1548                   d = screen.width();
1549                 if (d < 100)
1550                   d = 100;
1551                 winargs.width = (int)d;
1552 #if APPLE_CHANGES
1553                 winargs.widthSet = true;
1554 #endif
1555               }
1556             } else {
1557               goto boolargs;
1558             }
1559             continue;
1560           } else {
1561             // leaving away the value gives true
1562             key = s.stripWhiteSpace().lower();
1563             val = "1";
1564           }
1565         boolargs:
1566           if (key == "menubar")
1567             winargs.menuBarVisible = (val == "1" || val == "yes");
1568           else if (key == "toolbar")
1569             winargs.toolBarsVisible = (val == "1" || val == "yes");
1570           else if (key == "location")  // ### missing in WindowArgs
1571             winargs.toolBarsVisible = (val == "1" || val == "yes");
1572           else if (key == "status" || key == "statusbar")
1573             winargs.statusBarVisible = (val == "1" || val == "yes");
1574           else if (key == "resizable")
1575             winargs.resizable = (val == "1" || val == "yes");
1576           else if (key == "fullscreen")
1577             winargs.fullscreen = (val == "1" || val == "yes");
1578 #if APPLE_CHANGES
1579           else if (key == "scrollbars")
1580             winargs.scrollbarsVisible = !(val == "0" || val == "no");
1581 #endif
1582         }
1583       }
1584
1585       // prepare arguments
1586       KURL url;
1587       KHTMLPart* activePart = Window::retrieveActive(exec)->m_part;
1588       if (!str.isEmpty())
1589       {
1590         if (activePart)
1591           url = activePart->htmlDocument().completeURL(str).string();
1592       }
1593
1594       KParts::URLArgs uargs;
1595       uargs.frameName = frameName;
1596       if ( uargs.frameName == "_top" )
1597       {
1598           while ( part->parentPart() )
1599               part = part->parentPart();
1600
1601           const Window* window = Window::retrieveWindow(part);
1602           if (!url.url().startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
1603             bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
1604             part->scheduleLocationChange(url.url(), activePart->referrer(), false/*don't lock history*/, userGesture);
1605           }
1606           return Window::retrieve(part);
1607       }
1608       if ( uargs.frameName == "_parent" )
1609       {
1610           if ( part->parentPart() )
1611               part = part->parentPart();
1612
1613           const Window* window = Window::retrieveWindow(part);
1614           if (!url.url().startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
1615             bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
1616             part->scheduleLocationChange(url.url(), activePart->referrer(), false/*don't lock history*/, userGesture);
1617           }
1618           return Window::retrieve(part);
1619       }
1620       uargs.serviceType = "text/html";
1621
1622       // request window (new or existing if framename is set)
1623       KParts::ReadOnlyPart *newPart = 0L;
1624       uargs.metaData()["referrer"] = activePart->referrer();
1625       emit part->browserExtension()->createNewWindow("", uargs,winargs,newPart);
1626       if (newPart && newPart->inherits("KHTMLPart")) {
1627         KHTMLPart *khtmlpart = static_cast<KHTMLPart*>(newPart);
1628         //qDebug("opener set to %p (this Window's part) in new Window %p  (this Window=%p)",part,win,window);
1629         khtmlpart->setOpener(part);
1630         khtmlpart->setOpenedByJS(true);
1631         
1632         if (khtmlpart->document().isNull()) {
1633             DocumentImpl *oldDoc = part->xmlDocImpl();
1634             if (oldDoc && oldDoc->baseURL() != 0)
1635                 khtmlpart->begin(oldDoc->baseURL());
1636             else
1637                 khtmlpart->begin();
1638             
1639             khtmlpart->write("<HTML><BODY>");
1640             khtmlpart->end();
1641
1642             if (oldDoc) {
1643               kdDebug(6070) << "Setting domain to " << oldDoc->domain().string() << endl;
1644               khtmlpart->xmlDocImpl()->setDomain( oldDoc->domain(), true );
1645               khtmlpart->xmlDocImpl()->setBaseURL( oldDoc->baseURL() );
1646             }
1647         }
1648 #if APPLE_CHANGES
1649         if (!url.isEmpty()) {
1650           const Window* window = Window::retrieveWindow(khtmlpart);
1651           if (!url.url().startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
1652             bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
1653             khtmlpart->scheduleLocationChange(url.url(), activePart->referrer(), false, userGesture);
1654           } 
1655         }
1656 #else
1657         uargs.serviceType = QString::null;
1658         if (uargs.frameName == "_blank")
1659           uargs.frameName = QString::null;
1660         if (!url.isEmpty()) {
1661           uargs.metaData()["referrer"] = activePart->referrer();
1662           emit khtmlpart->browserExtension()->openURLRequest(url,uargs);
1663         }
1664 #endif
1665         return Window::retrieve(khtmlpart); // global object
1666       } else
1667         return Undefined();
1668     }
1669   }
1670 #if APPLE_CHANGES
1671   case Window::Print:
1672     part->print();
1673     return Undefined();
1674 #endif
1675   case Window::ScrollBy:
1676     window->updateLayout();
1677     if(args.size() >= 2 && widget)
1678       widget->scrollBy(args[0].toInt32(exec), args[1].toInt32(exec));
1679     return Undefined();
1680   case Window::Scroll:
1681   case Window::ScrollTo:
1682     window->updateLayout();
1683     if(args.size() >= 2 && widget)
1684       widget->setContentsPos(args[0].toInt32(exec), args[1].toInt32(exec));
1685     return Undefined();
1686   case Window::MoveBy:
1687     if(args.size() >= 2 && widget)
1688     {
1689       QWidget * tl = widget->topLevelWidget();
1690           QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(tl));
1691       QPoint dest = tl->pos() + QPoint( args[0].toInt32(exec), args[1].toInt32(exec) );
1692       // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
1693       if ( dest.x() >= sg.x() && dest.y() >= sg.x() &&
1694            dest.x()+tl->width() <= sg.width()+sg.x() &&
1695            dest.y()+tl->height() <= sg.height()+sg.y() )
1696         tl->move( dest );
1697     }
1698     return Undefined();
1699   case Window::MoveTo:
1700     if(args.size() >= 2 && widget)
1701     {
1702       QWidget * tl = widget->topLevelWidget();
1703           QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(tl));
1704       QPoint dest( args[0].toInt32(exec)+sg.x(), args[1].toInt32(exec)+sg.y() );
1705       // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
1706       if ( dest.x() >= sg.x() && dest.y() >= sg.y() &&
1707            dest.x()+tl->width() <= sg.width()+sg.x() &&
1708            dest.y()+tl->height() <= sg.height()+sg.y() )
1709         tl->move( dest );
1710     }
1711     return Undefined();
1712   case Window::ResizeBy:
1713     if(args.size() >= 2 && widget)
1714     {
1715       QWidget * tl = widget->topLevelWidget();
1716       QSize dest = tl->size() + QSize( args[0].toInt32(exec), args[1].toInt32(exec) );
1717           QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(tl));
1718       // Security check: within desktop limits and bigger than 100x100 (per spec)
1719       if ( tl->x()+dest.width() <= sg.x()+sg.width() &&
1720            tl->y()+dest.height() <= sg.y()+sg.height() &&
1721            dest.width() >= 100 && dest.height() >= 100 )
1722       {
1723         // Take into account the window frame
1724         int deltaWidth = tl->frameGeometry().width() - tl->width();
1725         int deltaHeight = tl->frameGeometry().height() - tl->height();
1726         tl->resize( dest.width() - deltaWidth, dest.height() - deltaHeight );
1727       }
1728     }
1729     return Undefined();
1730   case Window::ResizeTo:
1731     if(args.size() >= 2 && widget)
1732     {
1733       QWidget * tl = widget->topLevelWidget();
1734       QSize dest = QSize( args[0].toInt32(exec), args[1].toInt32(exec) );
1735           QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(tl));
1736       // Security check: within desktop limits and bigger than 100x100 (per spec)
1737       if ( tl->x()+dest.width() <= sg.x()+sg.width() &&
1738            tl->y()+dest.height() <= sg.y()+sg.height() &&
1739            dest.width() >= 100 && dest.height() >= 100 )
1740       {
1741         // Take into account the window frame
1742         int deltaWidth = tl->frameGeometry().width() - tl->width();
1743         int deltaHeight = tl->frameGeometry().height() - tl->height();
1744         tl->resize( dest.width() - deltaWidth, dest.height() - deltaHeight );
1745       }
1746     }
1747     return Undefined();
1748   case Window::SetTimeout:
1749     if (!window->isSafeScript(exec))
1750         return Undefined();
1751     if (args.size() >= 2 && v.isA(StringType)) {
1752       int i = args[1].toInt32(exec);
1753       int r = (const_cast<Window*>(window))->installTimeout(s, i, true /*single shot*/);
1754       return Number(r);
1755     }
1756     else if (args.size() >= 2 && v.isA(ObjectType) && Object::dynamicCast(v).implementsCall()) {
1757       Value func = args[0];
1758       int i = args[1].toInt32(exec);
1759
1760       // All arguments after the second should go to the function
1761       // FIXME: could be more efficient
1762       List funcArgs = args.copyTail().copyTail();
1763
1764       int r = (const_cast<Window*>(window))->installTimeout(func, funcArgs, i, true /*single shot*/);
1765       return Number(r);
1766     }
1767     else
1768       return Undefined();
1769   case Window::SetInterval:
1770     if (!window->isSafeScript(exec))
1771         return Undefined();
1772     if (args.size() >= 2 && v.isA(StringType)) {
1773       int i = args[1].toInt32(exec);
1774       int r = (const_cast<Window*>(window))->installTimeout(s, i, false);
1775       return Number(r);
1776     }
1777     else if (args.size() >= 2 && !Object::dynamicCast(v).isNull() &&
1778              Object::dynamicCast(v).implementsCall()) {
1779       Value func = args[0];
1780       int i = args[1].toInt32(exec);
1781
1782       // All arguments after the second should go to the function
1783       // FIXME: could be more efficient
1784       List funcArgs = args.copyTail().copyTail();
1785
1786       int r = (const_cast<Window*>(window))->installTimeout(func, funcArgs, i, false);
1787       return Number(r);
1788     }
1789     else
1790       return Undefined();
1791   case Window::ClearTimeout:
1792   case Window::ClearInterval:
1793     if (!window->isSafeScript(exec))
1794         return Undefined();
1795     (const_cast<Window*>(window))->clearTimeout(v.toInt32(exec));
1796     return Undefined();
1797   case Window::Focus:
1798     if (widget)
1799       widget->setActiveWindow();
1800     return Undefined();
1801   case Window::GetSelection:
1802     if (!window->isSafeScript(exec))
1803         return Undefined();
1804     return Value(window->selection());
1805   case Window::Blur:
1806 #if APPLE_CHANGES
1807     KWQ(part)->unfocusWindow();
1808 #else
1809     // TODO
1810 #endif
1811     return Undefined();
1812   case Window::Close:
1813     /* From http://developer.netscape.com/docs/manuals/js/client/jsref/window.htm :
1814        The close method closes only windows opened by JavaScript using the open method.
1815        If you attempt to close any other window, a confirm is generated, which
1816        lets the user choose whether the window closes.
1817        This is a security feature to prevent "mail bombs" containing self.close().
1818        However, if the window has only one document (the current one) in its
1819        session history, the close is allowed without any confirm. This is a
1820        special case for one-off windows that need to open other windows and
1821        then dispose of themselves.
1822     */
1823     if (!part->openedByJS())
1824     {
1825       // To conform to the SPEC, we only ask if the window
1826       // has more than one entry in the history (NS does that too).
1827       History history(exec,part);
1828       if ( history.get( exec, lengthPropertyName ).toInt32(exec) <= 1
1829 #if APPLE_CHANGES
1830            // FIXME: How are we going to handle this?
1831 #else
1832            || KMessageBox::questionYesNo( window->part()->view(), i18n("Close window?"), i18n("Confirmation Required") ) == KMessageBox::Yes
1833 #endif
1834            )
1835         (const_cast<Window*>(window))->scheduleClose();
1836     }
1837     else
1838     {
1839       (const_cast<Window*>(window))->scheduleClose();
1840     }
1841     return Undefined();
1842   case Window::CaptureEvents:
1843   case Window::ReleaseEvents:
1844         // If anyone implements these, they need the safescript security check.
1845         if (!window->isSafeScript(exec))
1846             return Undefined();
1847
1848     // Do nothing for now. These are NS-specific legacy calls.
1849     break;
1850   case Window::AddEventListener: {
1851         if (!window->isSafeScript(exec))
1852             return Undefined();
1853         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
1854         if (listener) {
1855             DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl *>(part->document().handle());
1856             if (docimpl)
1857                 docimpl->addWindowEventListener(DOM::EventImpl::typeToId(args[0].toString(exec).string()),listener,args[2].toBoolean(exec));
1858         }
1859         return Undefined();
1860     }
1861   case Window::RemoveEventListener: {
1862         if (!window->isSafeScript(exec))
1863             return Undefined();
1864         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
1865         if (listener) {
1866             DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl *>(part->document().handle());
1867             if (docimpl)
1868                 docimpl->removeWindowEventListener(DOM::EventImpl::typeToId(args[0].toString(exec).string()),listener,args[2].toBoolean(exec));
1869         }
1870         return Undefined();
1871     }
1872
1873   }
1874   return Undefined();
1875 }
1876
1877 void Window::updateLayout() const
1878 {
1879   DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl *>(m_part->document().handle());
1880   if (docimpl)
1881     docimpl->updateLayoutIgnorePendingStylesheets();
1882 }
1883
1884
1885 ////////////////////// ScheduledAction ////////////////////////
1886
1887 ScheduledAction::ScheduledAction(Object _func, List _args, bool _singleShot)
1888 {
1889   //kdDebug(6070) << "ScheduledAction::ScheduledAction(isFunction) " << this << endl;
1890   func = _func;
1891   args = _args;
1892   isFunction = true;
1893   singleShot = _singleShot;
1894 }
1895
1896 ScheduledAction::ScheduledAction(const QString &_code, bool _singleShot)
1897 {
1898   //kdDebug(6070) << "ScheduledAction::ScheduledAction(!isFunction) " << this << endl;
1899   //func = 0;
1900   //args = 0;
1901   code = _code;
1902   isFunction = false;
1903   singleShot = _singleShot;
1904 }
1905
1906
1907 void ScheduledAction::execute(Window *window)
1908 {
1909   ScriptInterpreter *interpreter = static_cast<ScriptInterpreter *>(KJSProxy::proxy(window->m_part)->interpreter());
1910
1911   interpreter->setProcessingTimerCallback(true);
1912
1913   //kdDebug(6070) << "ScheduledAction::execute " << this << endl;
1914   if (isFunction) {
1915     if (func.implementsCall()) {
1916       // #### check this
1917       Q_ASSERT( window->m_part );
1918       if ( window->m_part )
1919       {
1920         KJS::Interpreter *interpreter = KJSProxy::proxy( window->m_part )->interpreter();
1921         ExecState *exec = interpreter->globalExec();
1922         Q_ASSERT( window == interpreter->globalObject().imp() );
1923         Object obj( window );
1924         Interpreter::lock();
1925         func.call(exec,obj,args); // note that call() creates its own execution state for the func call
1926         Interpreter::unlock();
1927         if ( exec->hadException() ) {
1928 #if APPLE_CHANGES
1929           Interpreter::lock();
1930           char *message = exec->exception().toObject(exec).get(exec, messagePropertyName).toString(exec).ascii();
1931           int lineNumber =  exec->exception().toObject(exec).get(exec, "line").toInt32(exec);
1932           Interpreter::unlock();
1933           if (Interpreter::shouldPrintExceptions()) {
1934             printf("(timer):%s\n", message);
1935           }
1936           KWQ(window->m_part)->addMessageToConsole(message, lineNumber, QString());
1937 #endif
1938           exec->clearException();
1939         }
1940       }
1941     }
1942   }
1943   else {
1944     window->m_part->executeScript(code);
1945   }
1946
1947   // Update our document's rendering following the execution of the timeout callback.
1948   DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(window->m_part->document().handle());
1949   doc->updateRendering();
1950   
1951   interpreter->setProcessingTimerCallback(false);
1952 }
1953
1954 ScheduledAction::~ScheduledAction()
1955 {
1956   //kdDebug(6070) << "ScheduledAction::~ScheduledAction " << this << endl;
1957 }
1958
1959 ////////////////////// WindowQObject ////////////////////////
1960
1961 WindowQObject::WindowQObject(Window *w)
1962   : parent(w)
1963 {
1964   //kdDebug(6070) << "WindowQObject::WindowQObject " << this << endl;
1965   part = parent->m_part;
1966   connect( parent->m_part, SIGNAL( destroyed() ),
1967            this, SLOT( parentDestroyed() ) );
1968 }
1969
1970 WindowQObject::~WindowQObject()
1971 {
1972   //kdDebug(6070) << "WindowQObject::~WindowQObject " << this << endl;
1973   parentDestroyed(); // reuse same code
1974 }
1975
1976 void WindowQObject::parentDestroyed()
1977 {
1978   //kdDebug(6070) << "WindowQObject::parentDestroyed " << this << " we have " << scheduledActions.count() << " actions in the map" << endl;
1979   killTimers();
1980   QMapIterator<int,ScheduledAction*> it;
1981   for (it = scheduledActions.begin(); it != scheduledActions.end(); ++it) {
1982     ScheduledAction *action = *it;
1983     //kdDebug(6070) << "WindowQObject::parentDestroyed deleting action " << action << endl;
1984     delete action;
1985   }
1986   scheduledActions.clear();
1987 }
1988
1989 int WindowQObject::installTimeout(const UString &handler, int t, bool singleShot)
1990 {
1991   //kdDebug(6070) << "WindowQObject::installTimeout " << this << " " << handler.ascii() << endl;
1992   int id = startTimer(t);
1993   ScheduledAction *action = new ScheduledAction(handler.qstring(),singleShot);
1994   scheduledActions.insert(id, action);
1995   //kdDebug(6070) << this << " got id=" << id << " action=" << action << " - now having " << scheduledActions.count() << " actions"<<endl;
1996   return id;
1997 }
1998
1999 int WindowQObject::installTimeout(const Value &func, List args, int t, bool singleShot)
2000 {
2001   Object objFunc = Object::dynamicCast( func );
2002   int id = startTimer(t);
2003   scheduledActions.insert(id, new ScheduledAction(objFunc,args,singleShot));
2004   return id;
2005 }
2006
2007 QMap<int, ScheduledAction*> *WindowQObject::pauseTimeouts(const void *key)
2008 {
2009     QMapIterator<int,ScheduledAction*> it;
2010
2011     QMap<int, KJS::ScheduledAction*>*pausedActions = new QMap<int, KJS::ScheduledAction*>;
2012     for (it = scheduledActions.begin(); it != scheduledActions.end(); ++it) {
2013         int timerId = it.key();
2014         pauseTimer (timerId, key);
2015         pausedActions->insert(timerId, it.data());
2016     }
2017     scheduledActions.clear();
2018     return pausedActions;
2019 }
2020
2021 void WindowQObject::resumeTimeouts(QMap<int, ScheduledAction*> *sa, const void *key)
2022 {
2023     QMapIterator<int,ScheduledAction*> it;
2024     for (it = sa->begin(); it != sa->end(); ++it) {
2025         int timerId = it.key();
2026         scheduledActions.insert(timerId, it.data());
2027     }
2028     sa->clear();
2029     resumeTimers (key, this);
2030 }
2031
2032 void WindowQObject::clearTimeout(int timerId, bool delAction)
2033 {
2034   //kdDebug(6070) << "WindowQObject::clearTimeout " << this << " timerId=" << timerId << " delAction=" << delAction << endl;
2035   killTimer(timerId);
2036   if (delAction) {
2037     QMapIterator<int,ScheduledAction*> it = scheduledActions.find(timerId);
2038     if (it != scheduledActions.end()) {
2039       ScheduledAction *action = *it;
2040       scheduledActions.remove(it);
2041       delete action;
2042     }
2043   }
2044 }
2045
2046 void WindowQObject::timerEvent(QTimerEvent *e)
2047 {
2048   QMapIterator<int,ScheduledAction*> it = scheduledActions.find(e->timerId());
2049   if (it != scheduledActions.end()) {
2050     ScheduledAction *action = *it;
2051     bool singleShot = action->singleShot;
2052     //kdDebug(6070) << "WindowQObject::timerEvent " << this << " action=" << action << " singleShot:" << singleShot << endl;
2053
2054     // remove single shots installed by setTimeout()
2055     if (singleShot)
2056     {
2057       clearTimeout(e->timerId(),false);
2058       scheduledActions.remove(it);
2059     }
2060         
2061     if (!parent->part().isNull())
2062       action->execute(parent);
2063
2064     // It is important to test singleShot and not action->singleShot here - the
2065     // action could have been deleted already if not single shot and if the
2066     // JS code called by execute() calls clearTimeout().
2067     if (singleShot)
2068       delete action;
2069   } else
2070     kdWarning(6070) << "WindowQObject::timerEvent this=" << this << " timer " << e->timerId()
2071                     << " not found (" << scheduledActions.count() << " actions in map)" << endl;
2072 }
2073
2074 void WindowQObject::timeoutClose()
2075 {
2076   if (!parent->part().isNull())
2077   {
2078     //kdDebug(6070) << "WindowQObject::timeoutClose -> closing window" << endl;
2079     delete parent->m_part;
2080   }
2081 }
2082
2083 #if APPLE_CHANGES
2084 bool WindowQObject::hasTimeouts()
2085 {
2086     return scheduledActions.count();
2087 }
2088 #endif
2089
2090 Value FrameArray::get(ExecState *exec, const Identifier &p) const
2091 {
2092 #ifdef KJS_VERBOSE
2093   kdDebug(6070) << "FrameArray::get " << p.qstring() << " part=" << (void*)part << endl;
2094 #endif
2095   if (part.isNull())
2096     return Undefined();
2097
2098   QPtrList<KParts::ReadOnlyPart> frames = part->frames();
2099   unsigned int len = frames.count();
2100   if (p == lengthPropertyName)
2101     return Number(len);
2102   else if (p== "location") // non-standard property, but works in NS and IE
2103   {
2104     Object obj = Object::dynamicCast( Window::retrieve( part ) );
2105     if ( !obj.isNull() )
2106       return obj.get( exec, "location" );
2107     return Undefined();
2108   }
2109
2110   // check for the name or number
2111   KParts::ReadOnlyPart *frame = part->findFrame(p.qstring());
2112   if (!frame) {
2113     bool ok;
2114     unsigned int i = p.toArrayIndex(&ok);
2115     if (ok && i < len)
2116       frame = frames.at(i);
2117   }
2118
2119   // we are potentially fetching a reference to a another Window object here.
2120   // i.e. we may be accessing objects from another interpreter instance.
2121   // Therefore we have to be a bit careful with memory managment.
2122   if (frame && frame->inherits("KHTMLPart")) {
2123     KHTMLPart *khtml = static_cast<KHTMLPart*>(frame);
2124     return Window::retrieve(khtml);
2125   }
2126
2127   return ObjectImp::get(exec, p);
2128 }
2129
2130 UString FrameArray::toString(ExecState *) const
2131 {
2132   return "[object FrameArray]";
2133 }
2134
2135 ////////////////////// Location Object ////////////////////////
2136
2137 const ClassInfo Location::info = { "Location", 0, 0, 0 };
2138 /*
2139 @begin LocationTable 11
2140   hash          Location::Hash          DontDelete
2141   host          Location::Host          DontDelete
2142   hostname      Location::Hostname      DontDelete
2143   href          Location::Href          DontDelete
2144   pathname      Location::Pathname      DontDelete
2145   port          Location::Port          DontDelete
2146   protocol      Location::Protocol      DontDelete
2147   search        Location::Search        DontDelete
2148   [[==]]        Location::EqualEqual    DontDelete|ReadOnly
2149   toString      Location::ToString      DontDelete|Function 0
2150   replace       Location::Replace       DontDelete|Function 1
2151   reload        Location::Reload        DontDelete|Function 0
2152 @end
2153 */
2154 IMPLEMENT_PROTOFUNC(LocationFunc)
2155 Location::Location(KHTMLPart *p) : m_part(p)
2156 {
2157   //kdDebug(6070) << "Location::Location " << this << " m_part=" << (void*)m_part << endl;
2158 }
2159
2160 Location::~Location()
2161 {
2162   //kdDebug(6070) << "Location::~Location " << this << " m_part=" << (void*)m_part << endl;
2163 }
2164
2165 Value Location::get(ExecState *exec, const Identifier &p) const
2166 {
2167 #ifdef KJS_VERBOSE
2168   kdDebug(6070) << "Location::get " << p.qstring() << " m_part=" << (void*)m_part << endl;
2169 #endif
2170
2171   if (m_part.isNull())
2172     return Undefined();
2173   
2174   const Window* window = Window::retrieveWindow(m_part);
2175   if (!window || !window->isSafeScript(exec))
2176       return Undefined();
2177
2178   KURL url = m_part->url();
2179   const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
2180   if (entry)
2181     switch (entry->value) {
2182     case Hash:
2183       return String( url.ref().isNull() ? QString("") : "#" + url.ref() );
2184     case Host: {
2185       UString str = url.host();
2186       if (url.port())
2187         str += ":" + QString::number((int)url.port());
2188       return String(str);
2189       // Note: this is the IE spec. The NS spec swaps the two, it says
2190       // "The hostname property is the concatenation of the host and port properties, separated by a colon."
2191       // Bleh.
2192     }
2193     case Hostname:
2194       return String( url.host() );
2195     case Href:
2196       if (!url.hasPath())
2197         return String( url.prettyURL()+"/" );
2198       else
2199         return String( url.prettyURL() );
2200     case Pathname:
2201       return String( url.path().isEmpty() ? QString("/") : url.path() );
2202     case Port:
2203       return String( url.port() ? QString::number((int)url.port()) : QString::fromLatin1("") );
2204     case Protocol:
2205       return String( url.protocol()+":" );
2206     case Search:
2207       return String( url.query() );
2208     case EqualEqual: // [[==]]
2209       return String(toString(exec));
2210     case ToString:
2211       return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
2212     }
2213   // Look for overrides
2214   ValueImp * val = ObjectImp::getDirect(p);
2215   if (val)
2216     return Value(val);
2217   if (entry)
2218     switch (entry->value) {
2219     case Replace:
2220       return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
2221     case Reload:
2222       return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
2223     }
2224
2225   return Undefined();
2226 }
2227
2228 void Location::put(ExecState *exec, const Identifier &p, const Value &v, int attr)
2229 {
2230 #ifdef KJS_VERBOSE
2231   kdDebug(6070) << "Location::put " << p.qstring() << " m_part=" << (void*)m_part << endl;
2232 #endif
2233   if (m_part.isNull())
2234     return;
2235
2236   QString str = v.toString(exec).qstring();
2237   KURL url = m_part->url();
2238   const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
2239   if (entry)
2240     switch (entry->value) {
2241     case Href: {
2242       KHTMLPart* p = Window::retrieveActive(exec)->part();
2243       if ( p )
2244         url = p->htmlDocument().completeURL( str ).string();
2245       else
2246         url = str;
2247       break;
2248     }
2249     case Hash:
2250       url.setRef(str);
2251       break;
2252     case Host: {
2253       QString host = str.left(str.find(":"));
2254       QString port = str.mid(str.find(":")+1);
2255       url.setHost(host);
2256       url.setPort(port.toUInt());
2257       break;
2258     }
2259     case Hostname:
2260       url.setHost(str);
2261       break;
2262     case Pathname:
2263       url.setPath(str);
2264       break;
2265     case Port:
2266       url.setPort(str.toUInt());
2267       break;
2268     case Protocol:
2269       url.setProtocol(str);
2270       break;
2271     case Search:
2272       url.setQuery(str);
2273       break;
2274     }
2275   else {
2276     ObjectImp::put(exec, p, v, attr);
2277     return;
2278   }
2279
2280   const Window* window = Window::retrieveWindow(m_part);
2281   KHTMLPart* activePart = Window::retrieveActive(exec)->part();
2282   if (!url.url().startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
2283     bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
2284 #if APPLE_CHANGES
2285     // We want a new history item if this JS was called via a user gesture
2286     m_part->scheduleLocationChange(url.url(), activePart->referrer(), !userGesture, userGesture);
2287 #else
2288     m_part->scheduleLocationChange(url.url(), activePart->referrer(), false /*don't lock history*/, userGesture);
2289 #endif
2290   }
2291 }
2292
2293 Value Location::toPrimitive(ExecState *exec, Type) const
2294 {
2295   return String(toString(exec));
2296 }
2297
2298 UString Location::toString(ExecState *) const
2299 {
2300   if (!m_part->url().hasPath())
2301     return m_part->url().prettyURL()+"/";
2302   else
2303     return m_part->url().prettyURL();
2304 }
2305
2306 Value LocationFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
2307 {
2308   if (!thisObj.inherits(&Location::info)) {
2309     Object err = Error::create(exec,TypeError);
2310     exec->setException(err);
2311     return err;
2312   }
2313   Location *location = static_cast<Location *>(thisObj.imp());
2314   KHTMLPart *part = location->part();
2315   if (part) {
2316       
2317     Window* window = Window::retrieveWindow(part);
2318     if (!window->isSafeScript(exec) && id != Location::Replace)
2319         return Undefined();
2320       
2321     switch (id) {
2322     case Location::Replace:
2323     {
2324       QString str = args[0].toString(exec).qstring();
2325       KHTMLPart* p = Window::retrieveActive(exec)->part();
2326       if ( p ) {
2327         const Window* window = Window::retrieveWindow(part);
2328         if (!str.startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
2329           bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
2330           part->scheduleLocationChange(p->htmlDocument().completeURL(str).string(), p->referrer(), true /*lock history*/, userGesture);
2331         }
2332       }
2333       break;
2334     }
2335     case Location::Reload:
2336     {
2337       const Window* window = Window::retrieveWindow(part);
2338       KHTMLPart* activePart = Window::retrieveActive(exec)->part();
2339       if (!part->url().url().startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
2340         bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
2341         part->scheduleLocationChange(part->url().url(), activePart->referrer(), true/*lock history*/, userGesture);
2342       }
2343       break;
2344     }
2345     case Location::ToString:
2346       return String(location->toString(exec));
2347     }
2348   } else
2349     kdDebug(6070) << "LocationFunc::tryExecute - no part!" << endl;
2350   return Undefined();
2351 }
2352
2353 ////////////////////// Selection Object ////////////////////////
2354
2355 const ClassInfo Selection::info = { "Selection", 0, 0, 0 };
2356 /*
2357 @begin SelectionTable 19
2358   anchorNode                Selection::AnchorNode                        DontDelete|ReadOnly
2359   anchorOffset              Selection::AnchorOffset                  DontDelete|ReadOnly
2360   focusNode                 Selection::FocusNode                         DontDelete|ReadOnly
2361   focusOffset               Selection::FocusOffset                       DontDelete|ReadOnly
2362   baseNode                  Selection::AnchorNode                        DontDelete|ReadOnly
2363   baseOffset                Selection::AnchorOffset              DontDelete|ReadOnly
2364   extentNode                Selection::FocusNode                 DontDelete|ReadOnly
2365   extentOffset              Selection::FocusOffset                       DontDelete|ReadOnly
2366   isCollapsed               Selection::IsCollapsed                       DontDelete|ReadOnly
2367   type                      Selection::_Type                     DontDelete|ReadOnly
2368   [[==]]                        Selection::EqualEqual                DontDelete|ReadOnly
2369   toString                  Selection::ToString                  DontDelete|Function 0
2370   collapse                  Selection::Collapse                  DontDelete|Function 2
2371   collapseToEnd             Selection::CollapseToEnd             DontDelete|Function 0
2372   collapseToStart           Selection::CollapseToStart           DontDelete|Function 0
2373   empty                     Selection::Empty                     DontDelete|Function 0
2374   setBaseAndExtent          Selection::SetBaseAndExtent          DontDelete|Function 4
2375   setPosition               Selection::SetPosition               DontDelete|Function 2
2376   modify                    Selection::Modify                    DontDelete|Function 3
2377 @end
2378 */
2379 IMPLEMENT_PROTOFUNC(SelectionFunc)
2380 Selection::Selection(KHTMLPart *p) : m_part(p)
2381 {
2382   //kdDebug(6070) << "Selection::Selection " << this << " m_part=" << (void*)m_part << endl;
2383 }
2384
2385 Selection::~Selection()
2386 {
2387   //kdDebug(6070) << "Selection::~Selection " << this << " m_part=" << (void*)m_part << endl;
2388 }
2389
2390 Value Selection::get(ExecState *exec, const Identifier &p) const
2391 {
2392 #ifdef KJS_VERBOSE
2393   kdDebug(6070) << "Selection::get " << p.qstring() << " m_part=" << (void*)m_part << endl;
2394 #endif
2395
2396   if (m_part.isNull())
2397     return Undefined();
2398   
2399   const Window* window = Window::retrieveWindow(m_part);
2400   if (!window || !window->isSafeScript(exec))
2401       return Undefined();
2402
2403   DocumentImpl *docimpl = m_part->xmlDocImpl();
2404   if (docimpl)
2405     docimpl->updateLayoutIgnorePendingStylesheets();
2406
2407   KURL url = m_part->url();
2408   const HashEntry *entry = Lookup::findEntry(&SelectionTable, p);
2409   if (entry)
2410     switch (entry->value) {
2411         case AnchorNode:
2412         case BaseNode:
2413             return getDOMNode(exec, Node(m_part->selection().base().node()));
2414         case AnchorOffset:
2415         case BaseOffset:
2416             return Number(m_part->selection().base().offset());
2417         case FocusNode:
2418         case ExtentNode:
2419             return getDOMNode(exec, Node(m_part->selection().extent().node()));
2420         case FocusOffset:
2421         case ExtentOffset:
2422             return Number(m_part->selection().extent().offset());
2423         case IsCollapsed:
2424             return Boolean(!m_part->selection().isRange());
2425         case _Type: {
2426             switch (m_part->selection().state()) {
2427                 case khtml::Selection::NONE:
2428                     return String("None");
2429                 case khtml::Selection::CARET:
2430                     return String("Caret");
2431                 case khtml::Selection::RANGE:
2432                     return String("Range");
2433             }
2434         }
2435         case EqualEqual:
2436             return String(toString(exec));
2437         case ToString:
2438           return lookupOrCreateFunction<SelectionFunc>(exec,p,this,entry->value,entry->params,entry->attr);
2439     }
2440     // Look for overrides
2441     ValueImp * val = ObjectImp::getDirect(p);
2442     if (val)
2443         return Value(val);
2444     if (entry)
2445         switch (entry->value) {
2446             case Collapse:
2447             case CollapseToEnd:
2448             case CollapseToStart:
2449             case Empty:
2450             case SetBaseAndExtent:
2451             case SetPosition:
2452             case Modify:
2453                 return lookupOrCreateFunction<SelectionFunc>(exec,p,this,entry->value,entry->params,entry->attr);
2454         }
2455
2456     return Undefined();
2457 }
2458
2459 void Selection::put(ExecState *exec, const Identifier &p, const Value &v, int attr)
2460 {
2461 }
2462
2463 Value Selection::toPrimitive(ExecState *exec, Type) const
2464 {
2465   return String(toString(exec));
2466 }
2467
2468 UString Selection::toString(ExecState *) const
2469 {
2470     if (!m_part->selection().isRange())
2471         return UString("");
2472     return UString(m_part->selection().toRange().toString());
2473 }
2474
2475 Value SelectionFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
2476 {
2477     if (!thisObj.inherits(&Selection::info)) {
2478         Object err = Error::create(exec,TypeError);
2479         exec->setException(err);
2480         return err;
2481     }
2482     Selection *selection = static_cast<Selection *>(thisObj.imp());
2483     KHTMLPart *part = selection->part();
2484     if (part) {
2485         DocumentImpl *docimpl = part->xmlDocImpl();
2486         if (docimpl)
2487             docimpl->updateLayoutIgnorePendingStylesheets();
2488             
2489         switch (id) {
2490             case Selection::Collapse:
2491                 TypingCommand::closeTyping(part->lastEditCommand());
2492                 part->setSelection(khtml::Selection(Position(KJS::toNode(args[0]).handle(), args[1].toInt32(exec)), khtml::SEL_DEFAULT_AFFINITY));
2493                 break;
2494             case Selection::CollapseToEnd:
2495                 TypingCommand::closeTyping(part->lastEditCommand());
2496                 part->setSelection(khtml::Selection(part->selection().end(), part->selection().endAffinity()));
2497                 break;
2498             case Selection::CollapseToStart:
2499                 TypingCommand::closeTyping(part->lastEditCommand());
2500                 part->setSelection(khtml::Selection(part->selection().start(), part->selection().startAffinity()));
2501                 break;
2502             case Selection::Empty:
2503                 TypingCommand::closeTyping(part->lastEditCommand());
2504                 part->clearSelection();
2505                 break;
2506             case Selection::SetBaseAndExtent: {
2507                 TypingCommand::closeTyping(part->lastEditCommand());
2508                 Position base(KJS::toNode(args[0]).handle(), args[1].toInt32(exec));
2509                 Position extent(KJS::toNode(args[2]).handle(), args[3].toInt32(exec));
2510                 part->setSelection(khtml::Selection(base, khtml::SEL_DEFAULT_AFFINITY, extent, khtml::SEL_DEFAULT_AFFINITY));
2511                 break;
2512             }
2513             case Selection::SetPosition:
2514                 TypingCommand::closeTyping(part->lastEditCommand());
2515                 part->setSelection(khtml::Selection(Position(KJS::toNode(args[0]).handle(), args[1].toInt32(exec)), khtml::SEL_DEFAULT_AFFINITY));
2516                 break;
2517             case Selection::Modify: {
2518                 TypingCommand::closeTyping(part->lastEditCommand());
2519                 khtml::Selection s(part->selection());
2520                 khtml::Selection::EAlter alter = khtml::Selection::MOVE;
2521                 if (args[0].toString(exec).string().lower() == "extend")
2522                     alter = khtml::Selection::EXTEND;
2523                 DOMString directionString = args[1].toString(exec).string().lower();
2524                 khtml::Selection::EDirection direction = khtml::Selection::FORWARD;
2525                 if (directionString == "backward")
2526                     direction = khtml::Selection::BACKWARD;
2527                 else if (directionString == "left")
2528                     direction = khtml::Selection::LEFT;
2529                 if (directionString == "right")
2530                     direction = khtml::Selection::RIGHT;
2531                 khtml::ETextGranularity granularity = khtml::CHARACTER;
2532                 DOMString granularityString = args[2].toString(exec).string().lower();
2533                 if (granularityString == "word")
2534                     granularity = khtml::WORD;
2535                 else if (granularityString == "line")
2536                     granularity = khtml::LINE;
2537                 else if (granularityString == "pargraph")
2538                     granularity = khtml::PARAGRAPH;
2539                 s.modify(alter, direction, granularity);
2540                 part->setSelection(s);
2541                 part->setSelectionGranularity(granularity);
2542             }
2543         }
2544     }
2545
2546     return Undefined();
2547 }
2548
2549 ////////////////////// BarInfo Object ////////////////////////
2550
2551 const ClassInfo BarInfo::info = { "BarInfo", 0, 0, 0 };
2552 /*
2553 @begin BarInfoTable 1
2554   visible                BarInfo::Visible                        DontDelete|ReadOnly
2555 @end
2556 */
2557 BarInfo::BarInfo(ExecState *exec, KHTMLPart *p, Type barType) 
2558   : ObjectImp(exec->lexicalInterpreter()->builtinObjectPrototype())
2559   , m_part(p)
2560   , m_type(barType)
2561 {
2562 }
2563
2564 BarInfo::~BarInfo()
2565 {
2566 }
2567
2568 Value BarInfo::get(ExecState *exec, const Identifier &p) const
2569 {
2570   if (m_part.isNull())
2571     return Undefined();
2572   
2573   const HashEntry *entry = Lookup::findEntry(&BarInfoTable, p);
2574   if (entry && entry->value == Visible) {
2575     switch (m_type) {
2576     case Locationbar:
2577 #if APPLE_CHANGES
2578       return Boolean(KWQ(m_part)->locationbarVisible());
2579 #endif
2580     case Menubar: 
2581 #if APPLE_CHANGES
2582       return Boolean(KWQ(m_part)->locationbarVisible());
2583 #endif
2584     case Personalbar:
2585 #if APPLE_CHANGES
2586       return Boolean(KWQ(m_part)->personalbarVisible());
2587 #endif
2588     case Scrollbars: 
2589 #if APPLE_CHANGES
2590       return Boolean(KWQ(m_part)->scrollbarsVisible());
2591 #endif
2592     case Statusbar:
2593 #if APPLE_CHANGES
2594       return Boolean(KWQ(m_part)->statusbarVisible());
2595 #endif
2596     case Toolbar:
2597 #if APPLE_CHANGES
2598       return Boolean(KWQ(m_part)->toolbarVisible());
2599 #endif
2600     default:
2601       return Boolean(false);
2602     }
2603   }
2604   
2605   return Undefined();
2606 }
2607
2608 void BarInfo::put(ExecState *exec, const Identifier &p, const Value &v, int attr)
2609 {
2610 }
2611
2612 ////////////////////// History Object ////////////////////////
2613
2614 const ClassInfo History::info = { "History", 0, 0, 0 };
2615 /*
2616 @begin HistoryTable 4
2617   length        History::Length         DontDelete|ReadOnly
2618   back          History::Back           DontDelete|Function 0
2619   forward       History::Forward        DontDelete|Function 0
2620   go            History::Go             DontDelete|Function 1
2621 @end
2622 */
2623 IMPLEMENT_PROTOFUNC(HistoryFunc)
2624
2625 Value History::get(ExecState *exec, const Identifier &p) const
2626 {
2627   return lookupGet<HistoryFunc,History,ObjectImp>(exec,p,&HistoryTable,this);
2628 }
2629
2630 Value History::getValueProperty(ExecState *, int token) const
2631 {
2632   switch (token) {
2633   case Length:
2634   {
2635     KParts::BrowserExtension *ext = part->browserExtension();
2636     if ( !ext )
2637       return Number( 0 );
2638
2639     KParts::BrowserInterface *iface = ext->browserInterface();
2640     if ( !iface )
2641       return Number( 0 );
2642
2643     QVariant length = iface->property( "historyLength" );
2644
2645     if ( length.type() != QVariant::UInt )
2646       return Number( 0 );
2647
2648     return Number( length.toUInt() );
2649   }
2650   default:
2651     kdWarning() << "Unhandled token in History::getValueProperty : " << token << endl;
2652     return Undefined();
2653   }
2654 }
2655
2656 UString History::toString(ExecState *exec) const
2657 {
2658   return "[object History]";
2659 }
2660
2661 Value HistoryFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
2662 {
2663   if (!thisObj.inherits(&History::info)) {
2664     Object err = Error::create(exec,TypeError);
2665     exec->setException(err);
2666     return err;
2667   }
2668   History *history = static_cast<History *>(thisObj.imp());
2669
2670   int steps;
2671   switch (id) {
2672   case History::Back:
2673     steps = -1;
2674     break;
2675   case History::Forward:
2676     steps = 1;
2677     break;
2678   case History::Go:
2679     steps = args[0].toInt32(exec);
2680     break;
2681   default:
2682     return Undefined();
2683   }
2684
2685   history->part->scheduleHistoryNavigation(steps);
2686   return Undefined();
2687 }
2688
2689 /////////////////////////////////////////////////////////////////////////////
2690
2691 #ifdef Q_WS_QWS
2692
2693 const ClassInfo Konqueror::info = { "Konqueror", 0, 0, 0 };
2694
2695 bool Konqueror::hasProperty(ExecState *exec, const Identifier &p) const
2696 {
2697   if ( p.qstring().startsWith( "goHistory" ) ) return false;
2698
2699   return true;
2700 }
2701
2702 Value Konqueror::get(ExecState *exec, const Identifier &p) const
2703 {
2704   if ( p == "goHistory" || part->url().protocol() != "http" || part->url().host() != "localhost" )
2705     return Undefined();
2706
2707   KParts::BrowserExtension *ext = part->browserExtension();
2708   if ( ext ) {
2709     KParts::BrowserInterface *iface = ext->browserInterface();
2710     if ( iface ) {
2711       QVariant prop = iface->property( p.qstring().latin1() );
2712
2713       if ( prop.isValid() ) {
2714         switch( prop.type() ) {
2715         case QVariant::Int:
2716           return Number( prop.toInt() );
2717         case QVariant::String:
2718           return String( prop.toString() );
2719         default:
2720           break;
2721         }
2722       }
2723     }
2724   }
2725
2726   return /*Function*/( new KonquerorFunc(this, p.qstring().latin1() ) );
2727 }
2728
2729 Value KonquerorFunc::tryCall(ExecState *exec, Object &, const List &args)
2730 {
2731   KParts::BrowserExtension *ext = konqueror->part->browserExtension();
2732
2733   if(!ext)
2734     return Undefined();
2735
2736   KParts::BrowserInterface *iface = ext->browserInterface();
2737
2738   if ( !iface )
2739     return Undefined();
2740
2741   QCString n = m_name.data();
2742   n += "()";
2743   iface->callMethod( n.data(), QVariant() );
2744
2745   return Undefined();
2746 }
2747
2748 UString Konqueror::toString(ExecState *) const
2749 {
2750   return UString("[object Konqueror]");
2751 }
2752
2753 #endif
2754 /////////////////////////////////////////////////////////////////////////////
2755
2756 #include "kjs_window.moc"
2757