Eliminate the FOUCS on wired.com. innerWidth and innerHeight on window should not...
[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       updateLayout(false);
576       return Number(m_part->view()->visibleHeight());
577     case InnerWidth:
578       if (!m_part->view())
579         return Undefined();
580       updateLayout(false);
581       return Number(m_part->view()->visibleWidth());
582     case Length:
583       return Number(m_part->frames().count());
584     case _Location:
585       return Value(location());
586     case Name:
587       return String(m_part->name());
588     case _Navigator:
589     case ClientInformation: {
590       // Store the navigator in the object so we get the same one each time.
591       Navigator *n = new Navigator(exec, m_part);
592       const_cast<Window *>(this)->putDirect("navigator", n, DontDelete|ReadOnly);
593       const_cast<Window *>(this)->putDirect("clientInformation", n, DontDelete|ReadOnly);
594       return Value(n);
595     }
596 #ifdef Q_WS_QWS
597     case _Konqueror:
598       return Value(new Konqueror(m_part));
599 #endif
600     case Locationbar:
601       return Value(locationbar(exec));
602     case Menubar:
603       return Value(menubar(exec));
604     case OffscreenBuffering:
605       return Boolean(true);
606     case Opener:
607       if (!m_part->opener())
608         return Null();    // ### a null Window might be better, but == null
609       else                // doesn't work yet
610         return retrieve(m_part->opener());
611     case OuterHeight:
612     case OuterWidth:
613     {
614       if (!m_part->view())
615         return Number(0);
616       KWin::Info inf = KWin::info(m_part->view()->topLevelWidget()->winId());
617       return Number(entry->value == OuterHeight ?
618                     inf.geometry.height() : inf.geometry.width());
619     }
620     case PageXOffset:
621       if (!m_part->view())
622         return Undefined();
623       updateLayout();
624       return Number(m_part->view()->contentsX());
625     case PageYOffset:
626       if (!m_part->view())
627         return Undefined();
628       updateLayout();
629       return Number(m_part->view()->contentsY());
630     case Parent:
631       return Value(retrieve(m_part->parentPart() ? m_part->parentPart() : (KHTMLPart*)m_part));
632     case Personalbar:
633       return Value(personalbar(exec));
634     case ScreenLeft:
635     case ScreenX: {
636       if (!m_part->view())
637         return Undefined();
638 #if APPLE_CHANGES
639       // We want to use frameGeometry here instead of mapToGlobal because it goes through
640       // the windowFrame method of the WebKit's UI delegate. Also we don't want to try
641       // to do anything relative to the screen the window is on, so the code below is no
642       // good of us anyway.
643       return Number(m_part->view()->topLevelWidget()->frameGeometry().x());
644 #else
645       QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(m_part->view()));
646       return Number(m_part->view()->mapToGlobal(QPoint(0,0)).x() + sg.x());
647 #endif
648     }
649     case ScreenTop:
650     case ScreenY: {
651       if (!m_part->view())
652         return Undefined();
653 #if APPLE_CHANGES
654       // See comment above in ScreenX.
655       return Number(m_part->view()->topLevelWidget()->frameGeometry().y());
656 #else
657       QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(m_part->view()));
658       return Number(m_part->view()->mapToGlobal(QPoint(0,0)).y() + sg.y());
659 #endif
660     }
661     case ScrollX: {
662       if (!m_part->view())
663         return Undefined();
664       updateLayout();
665       return Number(m_part->view()->contentsX());
666     }
667     case ScrollY: {
668       if (!m_part->view())
669         return Undefined();
670       updateLayout();
671       return Number(m_part->view()->contentsY());
672     }
673     case Scrollbars:
674       return Value(scrollbars(exec));
675     case Statusbar:
676       return Value(statusbar(exec));
677     case Toolbar:
678       return Value(toolbar(exec));
679     case Self:
680     case _Window:
681       return Value(retrieve(m_part));
682     case Top: {
683       KHTMLPart *p = m_part;
684       while (p->parentPart())
685         p = p->parentPart();
686       return Value(retrieve(p));
687     }
688     case _Screen:
689       return Value(screen ? screen :
690                    (const_cast<Window*>(this)->screen = new Screen(exec)));
691     case Image:
692       return Value(new ImageConstructorImp(exec, m_part->document()));
693     case Option:
694       return Value(new OptionConstructorImp(exec, m_part->document()));
695     case XMLHttpRequest:
696       return Value(new XMLHttpRequestConstructorImp(exec, m_part->document()));
697     case XMLSerializer:
698       return Value(new XMLSerializerConstructorImp(exec));
699     case Focus:
700     case Blur:
701     case Close:
702         return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
703     case Alert:
704     case Confirm:
705     case Prompt:
706     case Open:
707 #if APPLE_CHANGES
708     case Print:
709 #endif
710     case Scroll: // compatibility
711     case ScrollBy:
712     case ScrollTo:
713     case MoveBy:
714     case MoveTo:
715     case ResizeBy:
716     case ResizeTo:
717     case CaptureEvents:
718     case ReleaseEvents:
719     case AddEventListener:
720     case RemoveEventListener:
721     case SetTimeout:
722     case ClearTimeout:
723     case SetInterval:
724     case ClearInterval:
725     case GetSelection:
726       if (isSafeScript(exec))
727         return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
728       else
729         return Undefined();
730     case Onabort:
731       if (isSafeScript(exec))
732         return getListener(exec,DOM::EventImpl::ABORT_EVENT);
733       else
734         return Undefined();
735     case Onblur:
736       if (isSafeScript(exec))
737         return getListener(exec,DOM::EventImpl::BLUR_EVENT);
738       else
739         return Undefined();
740     case Onchange:
741       if (isSafeScript(exec))
742         return getListener(exec,DOM::EventImpl::CHANGE_EVENT);
743       else
744         return Undefined();
745     case Onclick:
746       if (isSafeScript(exec))
747         return getListener(exec,DOM::EventImpl::KHTML_CLICK_EVENT);
748       else
749         return Undefined();
750     case Ondblclick:
751       if (isSafeScript(exec))
752         return getListener(exec,DOM::EventImpl::KHTML_DBLCLICK_EVENT);
753       else
754         return Undefined();
755     case Ondragdrop:
756       if (isSafeScript(exec))
757         return getListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT);
758       else
759         return Undefined();
760     case Onerror:
761       if (isSafeScript(exec))
762         return getListener(exec,DOM::EventImpl::KHTML_ERROR_EVENT);
763       else
764         return Undefined();
765     case Onfocus:
766       if (isSafeScript(exec))
767         return getListener(exec,DOM::EventImpl::FOCUS_EVENT);
768       else
769         return Undefined();
770     case Onkeydown:
771       if (isSafeScript(exec))
772         return getListener(exec,DOM::EventImpl::KEYDOWN_EVENT);
773       else
774         return Undefined();
775     case Onkeypress:
776       if (isSafeScript(exec))
777         return getListener(exec,DOM::EventImpl::KEYPRESS_EVENT);
778       else
779         return Undefined();
780     case Onkeyup:
781       if (isSafeScript(exec))
782         return getListener(exec,DOM::EventImpl::KEYUP_EVENT);
783       else
784         return Undefined();
785     case Onload:
786       if (isSafeScript(exec))
787         return getListener(exec,DOM::EventImpl::LOAD_EVENT);
788       else
789         return Undefined();
790     case Onmousedown:
791       if (isSafeScript(exec))
792         return getListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT);
793       else
794         return Undefined();
795     case Onmousemove:
796       if (isSafeScript(exec))
797         return getListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT);
798       else
799         return Undefined();
800     case Onmouseout:
801       if (isSafeScript(exec))
802         return getListener(exec,DOM::EventImpl::MOUSEOUT_EVENT);
803       else
804         return Undefined();
805     case Onmouseover:
806       if (isSafeScript(exec))
807         return getListener(exec,DOM::EventImpl::MOUSEOVER_EVENT);
808       else
809         return Undefined();
810     case Onmouseup:
811       if (isSafeScript(exec))
812         return getListener(exec,DOM::EventImpl::MOUSEUP_EVENT);
813       else
814         return Undefined();
815     case OnWindowMouseWheel:
816       if (isSafeScript(exec))
817         return getListener(exec, DOM::EventImpl::MOUSEWHEEL_EVENT);
818       else
819         return Undefined();
820     case Onmove:
821       if (isSafeScript(exec))
822         return getListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT);
823       else
824         return Undefined();
825     case Onreset:
826       if (isSafeScript(exec))
827         return getListener(exec,DOM::EventImpl::RESET_EVENT);
828       else
829         return Undefined();
830     case Onresize:
831       if (isSafeScript(exec))
832         return getListener(exec,DOM::EventImpl::RESIZE_EVENT);
833       else
834         return Undefined();
835     case Onscroll:
836         if (isSafeScript(exec))
837             return getListener(exec,DOM::EventImpl::SCROLL_EVENT);
838         else
839             return Undefined();
840 #if APPLE_CHANGES
841     case Onsearch:
842         if (isSafeScript(exec))
843             return getListener(exec,DOM::EventImpl::SEARCH_EVENT);
844         else
845             return Undefined();
846 #endif
847     case Onselect:
848       if (isSafeScript(exec))
849         return getListener(exec,DOM::EventImpl::SELECT_EVENT);
850       else
851         return Undefined();
852     case Onsubmit:
853       if (isSafeScript(exec))
854         return getListener(exec,DOM::EventImpl::SUBMIT_EVENT);
855       else
856         return Undefined();
857     case Onunload:
858       if (isSafeScript(exec))
859         return getListener(exec,DOM::EventImpl::UNLOAD_EVENT);
860       else
861         return Undefined();
862     case FrameElement: {
863       ElementImpl *fe = frameElement(exec, m_part);
864       if (!fe)
865         return Undefined();
866       return getDOMNode(exec, fe);
867     }
868     }
869   }
870
871   KHTMLPart *kp = m_part->findFrame( p.qstring() );
872   if (kp)
873     return Value(retrieve(kp));
874
875   // allow window[1] or parent[1] etc. (#56983)
876   bool ok;
877   unsigned int i = p.toArrayIndex(&ok);
878   if (ok) {
879     QPtrList<KParts::ReadOnlyPart> frames = m_part->frames();
880     unsigned int len = frames.count();
881     if (i < len) {
882       KParts::ReadOnlyPart* frame = frames.at(i);
883       if (frame && frame->inherits("KHTMLPart")) {
884         KHTMLPart *khtml = static_cast<KHTMLPart*>(frame);
885         return Window::retrieve(khtml);
886       }
887     }
888   }
889
890   // allow shortcuts like 'Image1' instead of document.images.Image1
891   if (isSafeScript(exec) &&
892       m_part->document().isHTMLDocument()) { // might be XML
893     DOM::HTMLCollection coll = m_part->htmlDocument().all();
894     DOM::HTMLElement element = coll.namedItem(p.string());    
895     if (!element.isNull()) {
896       return getDOMNode(exec,element);
897     }
898   }
899
900   // This isn't necessarily a bug. Some code uses if(!window.blah) window.blah=1
901   // But it can also mean something isn't loaded or implemented, hence the WARNING to help grepping.
902 #ifdef KJS_VERBOSE
903   kdDebug(6070) << "WARNING: Window::get property not found: " << p.qstring() << endl;
904 #endif
905
906   if (isSafeScript(exec))
907     return ObjectImp::get(exec, p);
908
909   return Undefined();
910 }
911
912 bool Window::hasProperty(ExecState *exec, const Identifier &p) const
913 {
914   // matches logic in get function above, but no need to handle numeric values (frame indices)
915
916   if (m_part.isNull())
917     return p == "closed";
918
919   if (getDirect(p))
920     return true;
921
922   if (Lookup::findEntry(&WindowTable, p))
923     return true;
924
925   if (m_part->findFrame(p.qstring()))
926     return true;
927
928   if (!m_part->htmlDocument().all().namedItem(p.string()).isNull())
929     return true;
930
931   return false;
932 }
933
934 void Window::put(ExecState* exec, const Identifier &propertyName, const Value &value, int attr)
935 {
936   // Called by an internal KJS call (e.g. InterpreterImp's constructor) ?
937   // If yes, save time and jump directly to ObjectImp.
938   if ( (attr != None && attr != DontDelete)
939        // Same thing if we have a local override (e.g. "var location")
940        || ( ObjectImp::getDirect(propertyName) && isSafeScript(exec)) )
941   {
942     ObjectImp::put( exec, propertyName, value, attr );
943     return;
944   }
945
946   const HashEntry* entry = Lookup::findEntry(&WindowTable, propertyName);
947   if (entry)
948   {
949 #ifdef KJS_VERBOSE
950     kdDebug(6070) << "Window("<<this<<")::put " << propertyName.qstring() << endl;
951 #endif
952     switch( entry->value ) {
953     case Status: {
954       String s = value.toString(exec);
955       m_part->setJSStatusBarText(s.value().qstring());
956       return;
957     }
958     case DefaultStatus: {
959       String s = value.toString(exec);
960       m_part->setJSDefaultStatusBarText(s.value().qstring());
961       return;
962     }
963     case _Location: {
964       KHTMLPart* p = Window::retrieveActive(exec)->m_part;
965       if (p) {
966         QString dstUrl = p->htmlDocument().completeURL(value.toString(exec).string()).string();
967         if (!dstUrl.startsWith("javascript:", false) || isSafeScript(exec))
968         {
969           bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
970 #if APPLE_CHANGES
971           // We want a new history item if this JS was called via a user gesture
972           m_part->scheduleLocationChange(dstUrl, p->referrer(), !userGesture, userGesture);
973 #else
974           m_part->scheduleLocationChange(dstUrl, p->referrer(), false /*don't lock history*/, userGesture);
975 #endif
976         }
977       }
978       return;
979     }
980     case Onabort:
981       if (isSafeScript(exec))
982         setListener(exec, DOM::EventImpl::ABORT_EVENT,value);
983       return;
984     case Onblur:
985       if (isSafeScript(exec))
986         setListener(exec, DOM::EventImpl::BLUR_EVENT,value);
987       return;
988     case Onchange:
989       if (isSafeScript(exec))
990         setListener(exec, DOM::EventImpl::CHANGE_EVENT,value);
991       return;
992     case Onclick:
993       if (isSafeScript(exec))
994         setListener(exec,DOM::EventImpl::KHTML_CLICK_EVENT,value);
995       return;
996     case Ondblclick:
997       if (isSafeScript(exec))
998         setListener(exec,DOM::EventImpl::KHTML_DBLCLICK_EVENT,value);
999       return;
1000     case Ondragdrop:
1001       if (isSafeScript(exec))
1002         setListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT,value);
1003       return;
1004     case Onerror:
1005       if (isSafeScript(exec))
1006         setListener(exec,DOM::EventImpl::KHTML_ERROR_EVENT,value);
1007       return;
1008     case Onfocus:
1009       if (isSafeScript(exec))
1010         setListener(exec,DOM::EventImpl::FOCUS_EVENT,value);
1011       return;
1012     case Onkeydown:
1013       if (isSafeScript(exec))
1014         setListener(exec,DOM::EventImpl::KEYDOWN_EVENT,value);
1015       return;
1016     case Onkeypress:
1017       if (isSafeScript(exec))
1018         setListener(exec,DOM::EventImpl::KEYPRESS_EVENT,value);
1019       return;
1020     case Onkeyup:
1021       if (isSafeScript(exec))
1022         setListener(exec,DOM::EventImpl::KEYUP_EVENT,value);
1023       return;
1024     case Onload:
1025       if (isSafeScript(exec))
1026         setListener(exec,DOM::EventImpl::LOAD_EVENT,value);
1027       return;
1028     case Onmousedown:
1029       if (isSafeScript(exec))
1030         setListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT,value);
1031       return;
1032     case Onmousemove:
1033       if (isSafeScript(exec))
1034         setListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT,value);
1035       return;
1036     case Onmouseout:
1037       if (isSafeScript(exec))
1038         setListener(exec,DOM::EventImpl::MOUSEOUT_EVENT,value);
1039       return;
1040     case Onmouseover:
1041       if (isSafeScript(exec))
1042         setListener(exec,DOM::EventImpl::MOUSEOVER_EVENT,value);
1043       return;
1044     case Onmouseup:
1045       if (isSafeScript(exec))
1046         setListener(exec,DOM::EventImpl::MOUSEUP_EVENT,value);
1047       return;
1048     case OnWindowMouseWheel:
1049       if (isSafeScript(exec))
1050         setListener(exec, DOM::EventImpl::MOUSEWHEEL_EVENT,value);
1051       return;
1052     case Onmove:
1053       if (isSafeScript(exec))
1054         setListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT,value);
1055       return;
1056     case Onreset:
1057       if (isSafeScript(exec))
1058         setListener(exec,DOM::EventImpl::RESET_EVENT,value);
1059       return;
1060     case Onresize:
1061       if (isSafeScript(exec))
1062         setListener(exec,DOM::EventImpl::RESIZE_EVENT,value);
1063       return;
1064     case Onscroll:
1065       if (isSafeScript(exec))
1066         setListener(exec,DOM::EventImpl::SCROLL_EVENT,value);
1067       return;
1068 #if APPLE_CHANGES
1069     case Onsearch:
1070         if (isSafeScript(exec))
1071             setListener(exec,DOM::EventImpl::SEARCH_EVENT,value);
1072         return;
1073 #endif
1074     case Onselect:
1075       if (isSafeScript(exec))
1076         setListener(exec,DOM::EventImpl::SELECT_EVENT,value);
1077       return;
1078     case Onsubmit:
1079       if (isSafeScript(exec))
1080         setListener(exec,DOM::EventImpl::SUBMIT_EVENT,value);
1081       return;
1082     case Onunload:
1083       if (isSafeScript(exec))
1084         setListener(exec,DOM::EventImpl::UNLOAD_EVENT,value);
1085       return;
1086     case Name:
1087       if (isSafeScript(exec))
1088 #if APPLE_CHANGES
1089         m_part->setName( value.toString(exec).qstring() );
1090 #else
1091         m_part->setName( value.toString(exec).qstring().local8Bit().data() );
1092 #endif
1093       return;
1094     default:
1095       break;
1096     }
1097   }
1098   if (isSafeScript(exec)) {
1099     //kdDebug(6070) << "Window("<<this<<")::put storing " << propertyName.qstring() << endl;
1100     ObjectImp::put(exec, propertyName, value, attr);
1101   }
1102 }
1103
1104 bool Window::toBoolean(ExecState *) const
1105 {
1106   return !m_part.isNull();
1107 }
1108
1109 int Window::installTimeout(const UString &handler, int t, bool singleShot)
1110 {
1111   return winq->installTimeout(handler, t, singleShot);
1112 }
1113
1114 int Window::installTimeout(const Value &function, List &args, int t, bool singleShot)
1115 {
1116   return winq->installTimeout(function, args, t, singleShot);
1117 }
1118
1119 void Window::clearTimeout(int timerId)
1120 {
1121   winq->clearTimeout(timerId);
1122 }
1123
1124 #if APPLE_CHANGES
1125 bool Window::hasTimeouts()
1126 {
1127     return winq->hasTimeouts();
1128 }
1129
1130 QMap<int, ScheduledAction*> *Window::pauseTimeouts(const void *key)
1131 {
1132     return winq->pauseTimeouts(key);
1133 }
1134
1135 void Window::resumeTimeouts(QMap<int, ScheduledAction*> *sa, const void *key)
1136 {
1137     return winq->resumeTimeouts(sa, key);
1138 }
1139 #endif
1140
1141 void Window::scheduleClose()
1142 {
1143   kdDebug(6070) << "Window::scheduleClose window.close() " << m_part << endl;
1144   Q_ASSERT(winq);
1145 #if APPLE_CHANGES
1146   KWQ(m_part)->scheduleClose();
1147 #else
1148   QTimer::singleShot( 0, winq, SLOT( timeoutClose() ) );
1149 #endif
1150 }
1151
1152 static bool shouldLoadAsEmptyDocument(const KURL &url)
1153 {
1154   return url.protocol().lower() == "about" || url.isEmpty();
1155 }
1156
1157 bool Window::isSafeScript (const KJS::ScriptInterpreter *origin, const KJS::ScriptInterpreter *target)
1158 {
1159     if (origin == target)
1160         return true;
1161         
1162     KHTMLPart *originPart = origin->part();
1163     KHTMLPart *targetPart = target->part();
1164
1165     // JS may be attempting to access the "window" object, which should be valid,
1166     // even if the document hasn't been constructed yet.  If the document doesn't
1167     // exist yet allow JS to access the window object.
1168     if (!targetPart->xmlDocImpl())
1169         return true;
1170
1171     DOM::DocumentImpl *originDocument = originPart->xmlDocImpl();
1172     DOM::DocumentImpl *targetDocument = targetPart->xmlDocImpl();
1173
1174     if (!targetDocument) {
1175         return false;
1176     }
1177
1178     DOM::DOMString targetDomain = targetDocument->domain();
1179
1180     // Always allow local pages to execute any JS.
1181     if (targetDomain.isNull())
1182         return true;
1183
1184     DOM::DOMString originDomain = originDocument->domain();
1185
1186     // if this document is being initially loaded as empty by its parent
1187     // or opener, allow access from any document in the same domain as
1188     // the parent or opener.
1189     if (shouldLoadAsEmptyDocument(targetPart->url())) {
1190         KHTMLPart *ancestorPart = targetPart->opener() ? targetPart->opener() : targetPart->parentPart();
1191         while (ancestorPart && shouldLoadAsEmptyDocument(ancestorPart->url())) {
1192             ancestorPart = ancestorPart->parentPart();
1193         }
1194
1195         if (ancestorPart)
1196             originDomain = ancestorPart->xmlDocImpl()->domain();
1197     }
1198
1199     if ( targetDomain == originDomain )
1200         return true;
1201
1202     if (Interpreter::shouldPrintExceptions()) {
1203         printf("Unsafe JavaScript attempt to access frame with URL %s from frame with URL %s. Domains must match.\n", 
1204              targetDocument->URL().latin1(), originDocument->URL().latin1());
1205     }
1206     QString message;
1207     message.sprintf("Unsafe JavaScript attempt to access frame with URL %s from frame with URL %s. Domains must match.\n", 
1208                   targetDocument->URL().latin1(), originDocument->URL().latin1());
1209     KWQ(targetPart)->addMessageToConsole(message, 1, QString()); //fixme: provide a real line number and sourceurl
1210
1211     return false;
1212 }
1213
1214 bool Window::isSafeScript(ExecState *exec) const
1215 {
1216   if (m_part.isNull()) { // part deleted ? can't grant access
1217     kdDebug(6070) << "Window::isSafeScript: accessing deleted part !" << endl;
1218     return false;
1219   }
1220   KHTMLPart *activePart = static_cast<KJS::ScriptInterpreter *>( exec->dynamicInterpreter() )->part();
1221   if (!activePart) {
1222     kdDebug(6070) << "Window::isSafeScript: current interpreter's part is 0L!" << endl;
1223     return false;
1224   }
1225   if ( activePart == m_part ) // Not calling from another frame, no problem.
1226     return true;
1227
1228   // JS may be attempting to access the "window" object, which should be valid,
1229   // even if the document hasn't been constructed yet.  If the document doesn't
1230   // exist yet allow JS to access the window object.
1231   if (!m_part->xmlDocImpl())
1232       return true;
1233
1234   DOM::DocumentImpl* thisDocument = m_part->xmlDocImpl();
1235   DOM::DocumentImpl* actDocument = activePart->xmlDocImpl();
1236
1237   if (!actDocument) {
1238     kdDebug(6070) << "Window::isSafeScript: active part has no document!" << endl;
1239     return false;
1240   }
1241
1242   DOM::DOMString actDomain = actDocument->domain();
1243   
1244   // Always allow local pages to execute any JS.
1245   if (actDomain.isNull())
1246     return true;
1247   
1248   DOM::DOMString thisDomain = thisDocument->domain();
1249
1250   // if this document is being initially loaded as empty by its parent
1251   // or opener, allow access from any document in the same domain as
1252   // the parent or opener.
1253   if (shouldLoadAsEmptyDocument(m_part->url())) {
1254     KHTMLPart *ancestorPart = m_part->opener() ? m_part->opener() : m_part->parentPart();
1255     while (ancestorPart && shouldLoadAsEmptyDocument(ancestorPart->url())) {
1256       ancestorPart = ancestorPart->parentPart();
1257     }
1258     
1259     if (ancestorPart)
1260       thisDomain = ancestorPart->xmlDocImpl()->domain();
1261   }
1262
1263   //kdDebug(6070) << "current domain:" << actDomain.string() << ", frame domain:" << thisDomain.string() << endl;
1264   if ( actDomain == thisDomain )
1265     return true;
1266
1267 #if APPLE_CHANGES
1268   if (Interpreter::shouldPrintExceptions()) {
1269       printf("Unsafe JavaScript attempt to access frame with URL %s from frame with URL %s. Domains must match.\n", 
1270              thisDocument->URL().latin1(), actDocument->URL().latin1());
1271   }
1272   QString message;
1273   message.sprintf("Unsafe JavaScript attempt to access frame with URL %s from frame with URL %s. Domains must match.\n", 
1274                   thisDocument->URL().latin1(), actDocument->URL().latin1());
1275   KWQ(m_part)->addMessageToConsole(message, 1, QString());
1276 #endif
1277   
1278   kdWarning(6070) << "Javascript: access denied for current frame '" << actDomain.string() << "' to frame '" << thisDomain.string() << "'" << endl;
1279   return false;
1280 }
1281
1282 void Window::setListener(ExecState *exec, int eventId, Value func)
1283 {
1284   if (!isSafeScript(exec))
1285     return;
1286   DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(m_part->htmlDocument().handle());
1287   if (!doc)
1288     return;
1289
1290   doc->setHTMLWindowEventListener(eventId,getJSEventListener(func,true));
1291 }
1292
1293 Value Window::getListener(ExecState *exec, int eventId) const
1294 {
1295   if (!isSafeScript(exec))
1296     return Undefined();
1297   DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(m_part->htmlDocument().handle());
1298   if (!doc)
1299     return Undefined();
1300
1301   DOM::EventListener *listener = doc->getHTMLWindowEventListener(eventId);
1302   if (listener && static_cast<JSEventListener*>(listener)->listenerObjImp())
1303     return static_cast<JSEventListener*>(listener)->listenerObj();
1304   else
1305     return Null();
1306 }
1307
1308 JSEventListener *Window::getJSEventListener(const Value& val, bool html)
1309 {
1310   // This function is so hot that it's worth coding it directly with imps.
1311   if (val.type() != ObjectType)
1312     return 0;
1313   ObjectImp *listenerObject = static_cast<ObjectImp *>(val.imp());
1314
1315   JSEventListener *existingListener = jsEventListeners[listenerObject];
1316   if (existingListener)
1317     return existingListener;
1318
1319   // Note that the JSEventListener constructor adds it to our jsEventListeners list
1320   return new JSEventListener(Object(listenerObject), Object(this), html);
1321 }
1322
1323 JSUnprotectedEventListener *Window::getJSUnprotectedEventListener(const Value& val, bool html)
1324 {
1325   // This function is so hot that it's worth coding it directly with imps.
1326   if (val.type() != ObjectType)
1327     return 0;
1328   ObjectImp *listenerObject = static_cast<ObjectImp *>(val.imp());
1329
1330   JSUnprotectedEventListener *existingListener = jsUnprotectedEventListeners[listenerObject];
1331   if (existingListener)
1332     return existingListener;
1333
1334   // Note that the JSUnprotectedEventListener constructor adds it to
1335   // our jsUnprotectedEventListeners list
1336   return new JSUnprotectedEventListener(Object(listenerObject), Object(this), html);
1337 }
1338
1339 JSLazyEventListener *Window::getJSLazyEventListener(const QString& code, DOM::NodeImpl *node, int lineNumber)
1340 {
1341   return new JSLazyEventListener(code, Object(this), node, lineNumber);
1342 }
1343
1344 void Window::clear( ExecState *exec )
1345 {
1346   KJS::Interpreter::lock();
1347   kdDebug(6070) << "Window::clear " << this << endl;
1348   delete winq;
1349   winq = new WindowQObject(this);;
1350   // Get rid of everything, those user vars could hold references to DOM nodes
1351   deleteAllProperties( exec );
1352   // Really delete those properties, so that the DOM nodes get deref'ed
1353   KJS::Collector::collect();
1354   // Now recreate a working global object for the next URL that will use us
1355   KJS::Interpreter *interpreter = KJSProxy::proxy( m_part )->interpreter();
1356   interpreter->initGlobalObject();
1357   KJS::Interpreter::unlock();
1358 }
1359
1360 void Window::setCurrentEvent( DOM::Event *evt )
1361 {
1362   m_evt = evt;
1363   //kdDebug(6070) << "Window " << this << " (part=" << m_part << ")::setCurrentEvent m_evt=" << evt << endl;
1364 }
1365
1366 Value WindowFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
1367 {
1368   if (!thisObj.inherits(&Window::info)) {
1369     Object err = Error::create(exec,TypeError);
1370     exec->setException(err);
1371     return err;
1372   }
1373   Window *window = static_cast<Window *>(thisObj.imp());
1374   QString str, str2;
1375
1376   KHTMLPart *part = window->m_part;
1377   if (!part)
1378     return Undefined();
1379
1380   KHTMLView *widget = part->view();
1381   Value v = args[0];
1382   UString s = v.toString(exec);
1383   str = s.qstring();
1384
1385   switch (id) {
1386   case Window::Alert:
1387     if (part && part->xmlDocImpl())
1388       part->xmlDocImpl()->updateRendering();
1389 #if APPLE_CHANGES
1390     KWQ(part)->runJavaScriptAlert(str);
1391 #else
1392     KMessageBox::error(widget, QStyleSheet::convertFromPlainText(str), "JavaScript");
1393 #endif
1394     return Undefined();
1395   case Window::Confirm:
1396     if (part && part->xmlDocImpl())
1397       part->xmlDocImpl()->updateRendering();
1398 #if APPLE_CHANGES
1399     return Boolean(KWQ(part)->runJavaScriptConfirm(str));
1400 #else
1401     return Boolean((KMessageBox::warningYesNo(widget, QStyleSheet::convertFromPlainText(str), "JavaScript",
1402                                                 i18n("OK"), i18n("Cancel")) == KMessageBox::Yes));
1403 #endif
1404   case Window::Prompt:
1405     if (part && part->xmlDocImpl())
1406       part->xmlDocImpl()->updateRendering();
1407     bool ok;
1408 #if APPLE_CHANGES
1409     ok = KWQ(part)->runJavaScriptPrompt(str, args.size() >= 2 ? args[1].toString(exec).qstring() : QString::null, str2);
1410 #else
1411     if (args.size() >= 2)
1412       str2 = QInputDialog::getText(i18n("Konqueror: Prompt"),
1413                                    QStyleSheet::convertFromPlainText(str),
1414                                    QLineEdit::Normal,
1415                                    args[1].toString(exec).qstring(), &ok);
1416     else
1417       str2 = QInputDialog::getText(i18n("Konqueror: Prompt"),
1418                                    QStyleSheet::convertFromPlainText(str),
1419                                    QLineEdit::Normal,
1420                                    QString::null, &ok);
1421 #endif
1422     if ( ok )
1423         return String(str2);
1424     else
1425         return Null();
1426   case Window::Open:
1427   {
1428     KConfig *config = new KConfig("konquerorrc");
1429     config->setGroup("Java/JavaScript Settings");
1430 #if !APPLE_CHANGES
1431     int policy = config->readUnsignedNumEntry( "WindowOpenPolicy", 0 ); // 0=allow, 1=ask, 2=deny, 3=smart
1432 #else    
1433     int policy = config->readUnsignedNumEntry( part->settings(), "WindowOpenPolicy", 0 ); // 0=allow, 1=ask, 2=deny, 3=smart
1434 #endif
1435     delete config;
1436     if ( policy == 1 ) {
1437 #if !APPLE_CHANGES
1438       if ( KMessageBox::questionYesNo(widget,
1439                                       i18n( "This site is trying to open up a new browser "
1440                                             "window using Javascript.\n"
1441                                             "Do you want to allow this?" ),
1442                                       i18n( "Confirmation: Javascript Popup" ) ) == KMessageBox::Yes )
1443 #endif
1444         policy = 0;
1445     } else if ( policy == 3 ) // smart
1446     {
1447       // window.open disabled unless from a key/mouse event
1448       if (static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture())
1449 #if !APPLE_CHANGES
1450         policy = 0;
1451 #else
1452       {
1453         policy = 0;
1454         LOG(PopupBlocking, "Allowed JavaScript window open of %s", args[0].toString(exec).qstring().ascii());
1455       } else {
1456         LOG(PopupBlocking, "Blocked JavaScript window open of %s", args[0].toString(exec).qstring().ascii());
1457       }
1458 #endif
1459     }
1460
1461     QString frameName = !args[1].isNull() && args[1].type() != UndefinedType ?
1462                         args[1].toString(exec).qstring()
1463                         : QString("_blank");
1464
1465     if ( policy != 0 && !(part->findFrame(frameName) || frameName == "_top" || frameName == "_parent" || frameName == "_self")) {
1466       return Undefined();
1467     } else {
1468       if (v.type() == UndefinedType)
1469         str = QString();
1470
1471       KParts::WindowArgs winargs;
1472
1473       // scan feature argument
1474       v = args[2];
1475       QString features;
1476       if (!v.isNull() && v.type() != UndefinedType && v.toString(exec).size() > 0) {
1477         features = v.toString(exec).qstring();
1478         // specifying window params means false defaults
1479         winargs.menuBarVisible = false;
1480         winargs.toolBarsVisible = false;
1481         winargs.statusBarVisible = false;
1482 #if APPLE_CHANGES
1483         winargs.scrollbarsVisible = true;
1484 #endif
1485         QStringList flist = QStringList::split(',', features);
1486         QStringList::ConstIterator it = flist.begin();
1487         while (it != flist.end()) {
1488           QString s = *it++;
1489           QString key, val;
1490           int pos = s.find('=');
1491           if (pos >= 0) {
1492             key = s.left(pos).stripWhiteSpace().lower();
1493             val = s.mid(pos + 1).stripWhiteSpace().lower();
1494             int spacePos = val.find(' ');
1495             if (spacePos != -1) {
1496               val = val.left(spacePos);
1497             }
1498
1499             int scnum = QApplication::desktop()->screenNumber(widget->topLevelWidget());
1500
1501             QRect screen = QApplication::desktop()->screenGeometry(scnum);
1502             if (key == "left" || key == "screenx") {
1503               bool ok;
1504               double d = val.toDouble(&ok);
1505               if (d != 0 || ok) {
1506                 d += screen.x();
1507                 if (d < screen.x() || d > screen.right())
1508                   d = screen.x(); // only safe choice until size is determined
1509                 winargs.x = (int)d;
1510 #if APPLE_CHANGES
1511                 winargs.xSet = true;
1512 #endif
1513               }
1514             } else if (key == "top" || key == "screeny") {
1515               bool ok;
1516               double d = val.toDouble(&ok);
1517               if (d != 0 || ok) {
1518                 d += screen.y();
1519                 if (d < screen.y() || d > screen.bottom())
1520                   d = screen.y(); // only safe choice until size is determined
1521                 winargs.y = (int)d;
1522 #if APPLE_CHANGES
1523                 winargs.ySet = true;
1524 #endif
1525               }
1526             } else if (key == "height") {
1527               bool ok;
1528               double d = val.toDouble(&ok);
1529               if (d != 0 || ok) {
1530 #if !APPLE_CHANGES
1531                 d += 2*qApp->style().pixelMetric( QStyle::PM_DefaultFrameWidth ) + 2;
1532 #endif
1533                 if (d > screen.height())  // should actually check workspace
1534                   d = screen.height();
1535                 if (d < 100)
1536                   d = 100;
1537                 winargs.height = (int)d;
1538 #if APPLE_CHANGES
1539                 winargs.heightSet = true;
1540 #endif
1541               }
1542             } else if (key == "width") {
1543               bool ok;
1544               double d = val.toDouble(&ok);
1545               if (d != 0 || ok) {
1546 #if !APPLE_CHANGES
1547                 d += 2*qApp->style().pixelMetric( QStyle::PM_DefaultFrameWidth ) + 2;
1548 #endif
1549                 if (d > screen.width())    // should actually check workspace
1550                   d = screen.width();
1551                 if (d < 100)
1552                   d = 100;
1553                 winargs.width = (int)d;
1554 #if APPLE_CHANGES
1555                 winargs.widthSet = true;
1556 #endif
1557               }
1558             } else {
1559               goto boolargs;
1560             }
1561             continue;
1562           } else {
1563             // leaving away the value gives true
1564             key = s.stripWhiteSpace().lower();
1565             val = "1";
1566           }
1567         boolargs:
1568           if (key == "menubar")
1569             winargs.menuBarVisible = (val == "1" || val == "yes");
1570           else if (key == "toolbar")
1571             winargs.toolBarsVisible = (val == "1" || val == "yes");
1572           else if (key == "location")  // ### missing in WindowArgs
1573             winargs.toolBarsVisible = (val == "1" || val == "yes");
1574           else if (key == "status" || key == "statusbar")
1575             winargs.statusBarVisible = (val == "1" || val == "yes");
1576           else if (key == "resizable")
1577             winargs.resizable = (val == "1" || val == "yes");
1578           else if (key == "fullscreen")
1579             winargs.fullscreen = (val == "1" || val == "yes");
1580 #if APPLE_CHANGES
1581           else if (key == "scrollbars")
1582             winargs.scrollbarsVisible = !(val == "0" || val == "no");
1583 #endif
1584         }
1585       }
1586
1587       // prepare arguments
1588       KURL url;
1589       KHTMLPart* activePart = Window::retrieveActive(exec)->m_part;
1590       if (!str.isEmpty())
1591       {
1592         if (activePart)
1593           url = activePart->htmlDocument().completeURL(str).string();
1594       }
1595
1596       KParts::URLArgs uargs;
1597       uargs.frameName = frameName;
1598       if ( uargs.frameName == "_top" )
1599       {
1600           while ( part->parentPart() )
1601               part = part->parentPart();
1602
1603           const Window* window = Window::retrieveWindow(part);
1604           if (!url.url().startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
1605             bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
1606             part->scheduleLocationChange(url.url(), activePart->referrer(), false/*don't lock history*/, userGesture);
1607           }
1608           return Window::retrieve(part);
1609       }
1610       if ( uargs.frameName == "_parent" )
1611       {
1612           if ( part->parentPart() )
1613               part = part->parentPart();
1614
1615           const Window* window = Window::retrieveWindow(part);
1616           if (!url.url().startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
1617             bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
1618             part->scheduleLocationChange(url.url(), activePart->referrer(), false/*don't lock history*/, userGesture);
1619           }
1620           return Window::retrieve(part);
1621       }
1622       uargs.serviceType = "text/html";
1623
1624       // request window (new or existing if framename is set)
1625       KParts::ReadOnlyPart *newPart = 0L;
1626       uargs.metaData()["referrer"] = activePart->referrer();
1627       emit part->browserExtension()->createNewWindow("", uargs,winargs,newPart);
1628       if (newPart && newPart->inherits("KHTMLPart")) {
1629         KHTMLPart *khtmlpart = static_cast<KHTMLPart*>(newPart);
1630         //qDebug("opener set to %p (this Window's part) in new Window %p  (this Window=%p)",part,win,window);
1631         khtmlpart->setOpener(part);
1632         khtmlpart->setOpenedByJS(true);
1633         
1634         if (khtmlpart->document().isNull()) {
1635             DocumentImpl *oldDoc = part->xmlDocImpl();
1636             if (oldDoc && oldDoc->baseURL() != 0)
1637                 khtmlpart->begin(oldDoc->baseURL());
1638             else
1639                 khtmlpart->begin();
1640             
1641             khtmlpart->write("<HTML><BODY>");
1642             khtmlpart->end();
1643
1644             if (oldDoc) {
1645               kdDebug(6070) << "Setting domain to " << oldDoc->domain().string() << endl;
1646               khtmlpart->xmlDocImpl()->setDomain( oldDoc->domain(), true );
1647               khtmlpart->xmlDocImpl()->setBaseURL( oldDoc->baseURL() );
1648             }
1649         }
1650 #if APPLE_CHANGES
1651         if (!url.isEmpty()) {
1652           const Window* window = Window::retrieveWindow(khtmlpart);
1653           if (!url.url().startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
1654             bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
1655             khtmlpart->scheduleLocationChange(url.url(), activePart->referrer(), false, userGesture);
1656           } 
1657         }
1658 #else
1659         uargs.serviceType = QString::null;
1660         if (uargs.frameName == "_blank")
1661           uargs.frameName = QString::null;
1662         if (!url.isEmpty()) {
1663           uargs.metaData()["referrer"] = activePart->referrer();
1664           emit khtmlpart->browserExtension()->openURLRequest(url,uargs);
1665         }
1666 #endif
1667         return Window::retrieve(khtmlpart); // global object
1668       } else
1669         return Undefined();
1670     }
1671   }
1672 #if APPLE_CHANGES
1673   case Window::Print:
1674     part->print();
1675     return Undefined();
1676 #endif
1677   case Window::ScrollBy:
1678     window->updateLayout();
1679     if(args.size() >= 2 && widget)
1680       widget->scrollBy(args[0].toInt32(exec), args[1].toInt32(exec));
1681     return Undefined();
1682   case Window::Scroll:
1683   case Window::ScrollTo:
1684     window->updateLayout();
1685     if(args.size() >= 2 && widget)
1686       widget->setContentsPos(args[0].toInt32(exec), args[1].toInt32(exec));
1687     return Undefined();
1688   case Window::MoveBy:
1689     if(args.size() >= 2 && widget)
1690     {
1691       QWidget * tl = widget->topLevelWidget();
1692           QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(tl));
1693       QPoint dest = tl->pos() + QPoint( args[0].toInt32(exec), args[1].toInt32(exec) );
1694       // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
1695       if ( dest.x() >= sg.x() && dest.y() >= sg.x() &&
1696            dest.x()+tl->width() <= sg.width()+sg.x() &&
1697            dest.y()+tl->height() <= sg.height()+sg.y() )
1698         tl->move( dest );
1699     }
1700     return Undefined();
1701   case Window::MoveTo:
1702     if(args.size() >= 2 && widget)
1703     {
1704       QWidget * tl = widget->topLevelWidget();
1705           QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(tl));
1706       QPoint dest( args[0].toInt32(exec)+sg.x(), args[1].toInt32(exec)+sg.y() );
1707       // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
1708       if ( dest.x() >= sg.x() && dest.y() >= sg.y() &&
1709            dest.x()+tl->width() <= sg.width()+sg.x() &&
1710            dest.y()+tl->height() <= sg.height()+sg.y() )
1711         tl->move( dest );
1712     }
1713     return Undefined();
1714   case Window::ResizeBy:
1715     if(args.size() >= 2 && widget)
1716     {
1717       QWidget * tl = widget->topLevelWidget();
1718       QSize dest = tl->size() + QSize( args[0].toInt32(exec), args[1].toInt32(exec) );
1719           QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(tl));
1720       // Security check: within desktop limits and bigger than 100x100 (per spec)
1721       if ( tl->x()+dest.width() <= sg.x()+sg.width() &&
1722            tl->y()+dest.height() <= sg.y()+sg.height() &&
1723            dest.width() >= 100 && dest.height() >= 100 )
1724       {
1725         // Take into account the window frame
1726         int deltaWidth = tl->frameGeometry().width() - tl->width();
1727         int deltaHeight = tl->frameGeometry().height() - tl->height();
1728         tl->resize( dest.width() - deltaWidth, dest.height() - deltaHeight );
1729       }
1730     }
1731     return Undefined();
1732   case Window::ResizeTo:
1733     if(args.size() >= 2 && widget)
1734     {
1735       QWidget * tl = widget->topLevelWidget();
1736       QSize dest = QSize( args[0].toInt32(exec), args[1].toInt32(exec) );
1737           QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(tl));
1738       // Security check: within desktop limits and bigger than 100x100 (per spec)
1739       if ( tl->x()+dest.width() <= sg.x()+sg.width() &&
1740            tl->y()+dest.height() <= sg.y()+sg.height() &&
1741            dest.width() >= 100 && dest.height() >= 100 )
1742       {
1743         // Take into account the window frame
1744         int deltaWidth = tl->frameGeometry().width() - tl->width();
1745         int deltaHeight = tl->frameGeometry().height() - tl->height();
1746         tl->resize( dest.width() - deltaWidth, dest.height() - deltaHeight );
1747       }
1748     }
1749     return Undefined();
1750   case Window::SetTimeout:
1751     if (!window->isSafeScript(exec))
1752         return Undefined();
1753     if (args.size() >= 2 && v.isA(StringType)) {
1754       int i = args[1].toInt32(exec);
1755       int r = (const_cast<Window*>(window))->installTimeout(s, i, true /*single shot*/);
1756       return Number(r);
1757     }
1758     else if (args.size() >= 2 && v.isA(ObjectType) && Object::dynamicCast(v).implementsCall()) {
1759       Value func = args[0];
1760       int i = args[1].toInt32(exec);
1761
1762       // All arguments after the second should go to the function
1763       // FIXME: could be more efficient
1764       List funcArgs = args.copyTail().copyTail();
1765
1766       int r = (const_cast<Window*>(window))->installTimeout(func, funcArgs, i, true /*single shot*/);
1767       return Number(r);
1768     }
1769     else
1770       return Undefined();
1771   case Window::SetInterval:
1772     if (!window->isSafeScript(exec))
1773         return Undefined();
1774     if (args.size() >= 2 && v.isA(StringType)) {
1775       int i = args[1].toInt32(exec);
1776       int r = (const_cast<Window*>(window))->installTimeout(s, i, false);
1777       return Number(r);
1778     }
1779     else if (args.size() >= 2 && !Object::dynamicCast(v).isNull() &&
1780              Object::dynamicCast(v).implementsCall()) {
1781       Value func = args[0];
1782       int i = args[1].toInt32(exec);
1783
1784       // All arguments after the second should go to the function
1785       // FIXME: could be more efficient
1786       List funcArgs = args.copyTail().copyTail();
1787
1788       int r = (const_cast<Window*>(window))->installTimeout(func, funcArgs, i, false);
1789       return Number(r);
1790     }
1791     else
1792       return Undefined();
1793   case Window::ClearTimeout:
1794   case Window::ClearInterval:
1795     if (!window->isSafeScript(exec))
1796         return Undefined();
1797     (const_cast<Window*>(window))->clearTimeout(v.toInt32(exec));
1798     return Undefined();
1799   case Window::Focus:
1800     if (widget)
1801       widget->setActiveWindow();
1802     return Undefined();
1803   case Window::GetSelection:
1804     if (!window->isSafeScript(exec))
1805         return Undefined();
1806     return Value(window->selection());
1807   case Window::Blur:
1808 #if APPLE_CHANGES
1809     KWQ(part)->unfocusWindow();
1810 #else
1811     // TODO
1812 #endif
1813     return Undefined();
1814   case Window::Close:
1815     /* From http://developer.netscape.com/docs/manuals/js/client/jsref/window.htm :
1816        The close method closes only windows opened by JavaScript using the open method.
1817        If you attempt to close any other window, a confirm is generated, which
1818        lets the user choose whether the window closes.
1819        This is a security feature to prevent "mail bombs" containing self.close().
1820        However, if the window has only one document (the current one) in its
1821        session history, the close is allowed without any confirm. This is a
1822        special case for one-off windows that need to open other windows and
1823        then dispose of themselves.
1824     */
1825     if (!part->openedByJS())
1826     {
1827       // To conform to the SPEC, we only ask if the window
1828       // has more than one entry in the history (NS does that too).
1829       History history(exec,part);
1830       if ( history.get( exec, lengthPropertyName ).toInt32(exec) <= 1
1831 #if APPLE_CHANGES
1832            // FIXME: How are we going to handle this?
1833 #else
1834            || KMessageBox::questionYesNo( window->part()->view(), i18n("Close window?"), i18n("Confirmation Required") ) == KMessageBox::Yes
1835 #endif
1836            )
1837         (const_cast<Window*>(window))->scheduleClose();
1838     }
1839     else
1840     {
1841       (const_cast<Window*>(window))->scheduleClose();
1842     }
1843     return Undefined();
1844   case Window::CaptureEvents:
1845   case Window::ReleaseEvents:
1846         // If anyone implements these, they need the safescript security check.
1847         if (!window->isSafeScript(exec))
1848             return Undefined();
1849
1850     // Do nothing for now. These are NS-specific legacy calls.
1851     break;
1852   case Window::AddEventListener: {
1853         if (!window->isSafeScript(exec))
1854             return Undefined();
1855         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
1856         if (listener) {
1857             DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl *>(part->document().handle());
1858             if (docimpl)
1859                 docimpl->addWindowEventListener(DOM::EventImpl::typeToId(args[0].toString(exec).string()),listener,args[2].toBoolean(exec));
1860         }
1861         return Undefined();
1862     }
1863   case Window::RemoveEventListener: {
1864         if (!window->isSafeScript(exec))
1865             return Undefined();
1866         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
1867         if (listener) {
1868             DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl *>(part->document().handle());
1869             if (docimpl)
1870                 docimpl->removeWindowEventListener(DOM::EventImpl::typeToId(args[0].toString(exec).string()),listener,args[2].toBoolean(exec));
1871         }
1872         return Undefined();
1873     }
1874
1875   }
1876   return Undefined();
1877 }
1878
1879 void Window::updateLayout(bool ignoreStylesheets) const
1880 {
1881   DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl *>(m_part->document().handle());
1882   if (docimpl) {
1883     if (ignoreStylesheets)
1884       docimpl->updateLayoutIgnorePendingStylesheets();
1885     else
1886       docimpl->updateLayout();
1887   }
1888 }
1889
1890
1891 ////////////////////// ScheduledAction ////////////////////////
1892
1893 ScheduledAction::ScheduledAction(Object _func, List _args, bool _singleShot)
1894 {
1895   //kdDebug(6070) << "ScheduledAction::ScheduledAction(isFunction) " << this << endl;
1896   func = _func;
1897   args = _args;
1898   isFunction = true;
1899   singleShot = _singleShot;
1900 }
1901
1902 ScheduledAction::ScheduledAction(const QString &_code, bool _singleShot)
1903 {
1904   //kdDebug(6070) << "ScheduledAction::ScheduledAction(!isFunction) " << this << endl;
1905   //func = 0;
1906   //args = 0;
1907   code = _code;
1908   isFunction = false;
1909   singleShot = _singleShot;
1910 }
1911
1912
1913 void ScheduledAction::execute(Window *window)
1914 {
1915   ScriptInterpreter *interpreter = static_cast<ScriptInterpreter *>(KJSProxy::proxy(window->m_part)->interpreter());
1916
1917   interpreter->setProcessingTimerCallback(true);
1918
1919   //kdDebug(6070) << "ScheduledAction::execute " << this << endl;
1920   if (isFunction) {
1921     if (func.implementsCall()) {
1922       // #### check this
1923       Q_ASSERT( window->m_part );
1924       if ( window->m_part )
1925       {
1926         KJS::Interpreter *interpreter = KJSProxy::proxy( window->m_part )->interpreter();
1927         ExecState *exec = interpreter->globalExec();
1928         Q_ASSERT( window == interpreter->globalObject().imp() );
1929         Object obj( window );
1930         Interpreter::lock();
1931         func.call(exec,obj,args); // note that call() creates its own execution state for the func call
1932         Interpreter::unlock();
1933         if ( exec->hadException() ) {
1934 #if APPLE_CHANGES
1935           Interpreter::lock();
1936           char *message = exec->exception().toObject(exec).get(exec, messagePropertyName).toString(exec).ascii();
1937           int lineNumber =  exec->exception().toObject(exec).get(exec, "line").toInt32(exec);
1938           Interpreter::unlock();
1939           if (Interpreter::shouldPrintExceptions()) {
1940             printf("(timer):%s\n", message);
1941           }
1942           KWQ(window->m_part)->addMessageToConsole(message, lineNumber, QString());
1943 #endif
1944           exec->clearException();
1945         }
1946       }
1947     }
1948   }
1949   else {
1950     window->m_part->executeScript(code);
1951   }
1952
1953   // Update our document's rendering following the execution of the timeout callback.
1954   DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(window->m_part->document().handle());
1955   doc->updateRendering();
1956   
1957   interpreter->setProcessingTimerCallback(false);
1958 }
1959
1960 ScheduledAction::~ScheduledAction()
1961 {
1962   //kdDebug(6070) << "ScheduledAction::~ScheduledAction " << this << endl;
1963 }
1964
1965 ////////////////////// WindowQObject ////////////////////////
1966
1967 WindowQObject::WindowQObject(Window *w)
1968   : parent(w)
1969 {
1970   //kdDebug(6070) << "WindowQObject::WindowQObject " << this << endl;
1971   part = parent->m_part;
1972   connect( parent->m_part, SIGNAL( destroyed() ),
1973            this, SLOT( parentDestroyed() ) );
1974 }
1975
1976 WindowQObject::~WindowQObject()
1977 {
1978   //kdDebug(6070) << "WindowQObject::~WindowQObject " << this << endl;
1979   parentDestroyed(); // reuse same code
1980 }
1981
1982 void WindowQObject::parentDestroyed()
1983 {
1984   //kdDebug(6070) << "WindowQObject::parentDestroyed " << this << " we have " << scheduledActions.count() << " actions in the map" << endl;
1985   killTimers();
1986   QMapIterator<int,ScheduledAction*> it;
1987   for (it = scheduledActions.begin(); it != scheduledActions.end(); ++it) {
1988     ScheduledAction *action = *it;
1989     //kdDebug(6070) << "WindowQObject::parentDestroyed deleting action " << action << endl;
1990     delete action;
1991   }
1992   scheduledActions.clear();
1993 }
1994
1995 int WindowQObject::installTimeout(const UString &handler, int t, bool singleShot)
1996 {
1997   //kdDebug(6070) << "WindowQObject::installTimeout " << this << " " << handler.ascii() << endl;
1998   int id = startTimer(t);
1999   ScheduledAction *action = new ScheduledAction(handler.qstring(),singleShot);
2000   scheduledActions.insert(id, action);
2001   //kdDebug(6070) << this << " got id=" << id << " action=" << action << " - now having " << scheduledActions.count() << " actions"<<endl;
2002   return id;
2003 }
2004
2005 int WindowQObject::installTimeout(const Value &func, List args, int t, bool singleShot)
2006 {
2007   Object objFunc = Object::dynamicCast( func );
2008   int id = startTimer(t);
2009   scheduledActions.insert(id, new ScheduledAction(objFunc,args,singleShot));
2010   return id;
2011 }
2012
2013 QMap<int, ScheduledAction*> *WindowQObject::pauseTimeouts(const void *key)
2014 {
2015     QMapIterator<int,ScheduledAction*> it;
2016
2017     QMap<int, KJS::ScheduledAction*>*pausedActions = new QMap<int, KJS::ScheduledAction*>;
2018     for (it = scheduledActions.begin(); it != scheduledActions.end(); ++it) {
2019         int timerId = it.key();
2020         pauseTimer (timerId, key);
2021         pausedActions->insert(timerId, it.data());
2022     }
2023     scheduledActions.clear();
2024     return pausedActions;
2025 }
2026
2027 void WindowQObject::resumeTimeouts(QMap<int, ScheduledAction*> *sa, const void *key)
2028 {
2029     QMapIterator<int,ScheduledAction*> it;
2030     for (it = sa->begin(); it != sa->end(); ++it) {
2031         int timerId = it.key();
2032         scheduledActions.insert(timerId, it.data());
2033     }
2034     sa->clear();
2035     resumeTimers (key, this);
2036 }
2037
2038 void WindowQObject::clearTimeout(int timerId, bool delAction)
2039 {
2040   //kdDebug(6070) << "WindowQObject::clearTimeout " << this << " timerId=" << timerId << " delAction=" << delAction << endl;
2041   killTimer(timerId);
2042   if (delAction) {
2043     QMapIterator<int,ScheduledAction*> it = scheduledActions.find(timerId);
2044     if (it != scheduledActions.end()) {
2045       ScheduledAction *action = *it;
2046       scheduledActions.remove(it);
2047       delete action;
2048     }
2049   }
2050 }
2051
2052 void WindowQObject::timerEvent(QTimerEvent *e)
2053 {
2054   QMapIterator<int,ScheduledAction*> it = scheduledActions.find(e->timerId());
2055   if (it != scheduledActions.end()) {
2056     ScheduledAction *action = *it;
2057     bool singleShot = action->singleShot;
2058     //kdDebug(6070) << "WindowQObject::timerEvent " << this << " action=" << action << " singleShot:" << singleShot << endl;
2059
2060     // remove single shots installed by setTimeout()
2061     if (singleShot)
2062     {
2063       clearTimeout(e->timerId(),false);
2064       scheduledActions.remove(it);
2065     }
2066         
2067     if (!parent->part().isNull())
2068       action->execute(parent);
2069
2070     // It is important to test singleShot and not action->singleShot here - the
2071     // action could have been deleted already if not single shot and if the
2072     // JS code called by execute() calls clearTimeout().
2073     if (singleShot)
2074       delete action;
2075   } else
2076     kdWarning(6070) << "WindowQObject::timerEvent this=" << this << " timer " << e->timerId()
2077                     << " not found (" << scheduledActions.count() << " actions in map)" << endl;
2078 }
2079
2080 void WindowQObject::timeoutClose()
2081 {
2082   if (!parent->part().isNull())
2083   {
2084     //kdDebug(6070) << "WindowQObject::timeoutClose -> closing window" << endl;
2085     delete parent->m_part;
2086   }
2087 }
2088
2089 #if APPLE_CHANGES
2090 bool WindowQObject::hasTimeouts()
2091 {
2092     return scheduledActions.count();
2093 }
2094 #endif
2095
2096 Value FrameArray::get(ExecState *exec, const Identifier &p) const
2097 {
2098 #ifdef KJS_VERBOSE
2099   kdDebug(6070) << "FrameArray::get " << p.qstring() << " part=" << (void*)part << endl;
2100 #endif
2101   if (part.isNull())
2102     return Undefined();
2103
2104   QPtrList<KParts::ReadOnlyPart> frames = part->frames();
2105   unsigned int len = frames.count();
2106   if (p == lengthPropertyName)
2107     return Number(len);
2108   else if (p== "location") // non-standard property, but works in NS and IE
2109   {
2110     Object obj = Object::dynamicCast( Window::retrieve( part ) );
2111     if ( !obj.isNull() )
2112       return obj.get( exec, "location" );
2113     return Undefined();
2114   }
2115
2116   // check for the name or number
2117   KParts::ReadOnlyPart *frame = part->findFrame(p.qstring());
2118   if (!frame) {
2119     bool ok;
2120     unsigned int i = p.toArrayIndex(&ok);
2121     if (ok && i < len)
2122       frame = frames.at(i);
2123   }
2124
2125   // we are potentially fetching a reference to a another Window object here.
2126   // i.e. we may be accessing objects from another interpreter instance.
2127   // Therefore we have to be a bit careful with memory managment.
2128   if (frame && frame->inherits("KHTMLPart")) {
2129     KHTMLPart *khtml = static_cast<KHTMLPart*>(frame);
2130     return Window::retrieve(khtml);
2131   }
2132
2133   return ObjectImp::get(exec, p);
2134 }
2135
2136 UString FrameArray::toString(ExecState *) const
2137 {
2138   return "[object FrameArray]";
2139 }
2140
2141 ////////////////////// Location Object ////////////////////////
2142
2143 const ClassInfo Location::info = { "Location", 0, 0, 0 };
2144 /*
2145 @begin LocationTable 11
2146   hash          Location::Hash          DontDelete
2147   host          Location::Host          DontDelete
2148   hostname      Location::Hostname      DontDelete
2149   href          Location::Href          DontDelete
2150   pathname      Location::Pathname      DontDelete
2151   port          Location::Port          DontDelete
2152   protocol      Location::Protocol      DontDelete
2153   search        Location::Search        DontDelete
2154   [[==]]        Location::EqualEqual    DontDelete|ReadOnly
2155   toString      Location::ToString      DontDelete|Function 0
2156   replace       Location::Replace       DontDelete|Function 1
2157   reload        Location::Reload        DontDelete|Function 0
2158 @end
2159 */
2160 IMPLEMENT_PROTOFUNC(LocationFunc)
2161 Location::Location(KHTMLPart *p) : m_part(p)
2162 {
2163   //kdDebug(6070) << "Location::Location " << this << " m_part=" << (void*)m_part << endl;
2164 }
2165
2166 Location::~Location()
2167 {
2168   //kdDebug(6070) << "Location::~Location " << this << " m_part=" << (void*)m_part << endl;
2169 }
2170
2171 Value Location::get(ExecState *exec, const Identifier &p) const
2172 {
2173 #ifdef KJS_VERBOSE
2174   kdDebug(6070) << "Location::get " << p.qstring() << " m_part=" << (void*)m_part << endl;
2175 #endif
2176
2177   if (m_part.isNull())
2178     return Undefined();
2179   
2180   const Window* window = Window::retrieveWindow(m_part);
2181   if (!window || !window->isSafeScript(exec))
2182       return Undefined();
2183
2184   KURL url = m_part->url();
2185   const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
2186   if (entry)
2187     switch (entry->value) {
2188     case Hash:
2189       return String( url.ref().isNull() ? QString("") : "#" + url.ref() );
2190     case Host: {
2191       UString str = url.host();
2192       if (url.port())
2193         str += ":" + QString::number((int)url.port());
2194       return String(str);
2195       // Note: this is the IE spec. The NS spec swaps the two, it says
2196       // "The hostname property is the concatenation of the host and port properties, separated by a colon."
2197       // Bleh.
2198     }
2199     case Hostname:
2200       return String( url.host() );
2201     case Href:
2202       if (!url.hasPath())
2203         return String( url.prettyURL()+"/" );
2204       else
2205         return String( url.prettyURL() );
2206     case Pathname:
2207       return String( url.path().isEmpty() ? QString("/") : url.path() );
2208     case Port:
2209       return String( url.port() ? QString::number((int)url.port()) : QString::fromLatin1("") );
2210     case Protocol:
2211       return String( url.protocol()+":" );
2212     case Search:
2213       return String( url.query() );
2214     case EqualEqual: // [[==]]
2215       return String(toString(exec));
2216     case ToString:
2217       return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
2218     }
2219   // Look for overrides
2220   ValueImp * val = ObjectImp::getDirect(p);
2221   if (val)
2222     return Value(val);
2223   if (entry)
2224     switch (entry->value) {
2225     case Replace:
2226       return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
2227     case Reload:
2228       return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
2229     }
2230
2231   return Undefined();
2232 }
2233
2234 void Location::put(ExecState *exec, const Identifier &p, const Value &v, int attr)
2235 {
2236 #ifdef KJS_VERBOSE
2237   kdDebug(6070) << "Location::put " << p.qstring() << " m_part=" << (void*)m_part << endl;
2238 #endif
2239   if (m_part.isNull())
2240     return;
2241
2242   QString str = v.toString(exec).qstring();
2243   KURL url = m_part->url();
2244   const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
2245   if (entry)
2246     switch (entry->value) {
2247     case Href: {
2248       KHTMLPart* p = Window::retrieveActive(exec)->part();
2249       if ( p )
2250         url = p->htmlDocument().completeURL( str ).string();
2251       else
2252         url = str;
2253       break;
2254     }
2255     case Hash:
2256       url.setRef(str);
2257       break;
2258     case Host: {
2259       QString host = str.left(str.find(":"));
2260       QString port = str.mid(str.find(":")+1);
2261       url.setHost(host);
2262       url.setPort(port.toUInt());
2263       break;
2264     }
2265     case Hostname:
2266       url.setHost(str);
2267       break;
2268     case Pathname:
2269       url.setPath(str);
2270       break;
2271     case Port:
2272       url.setPort(str.toUInt());
2273       break;
2274     case Protocol:
2275       url.setProtocol(str);
2276       break;
2277     case Search:
2278       url.setQuery(str);
2279       break;
2280     }
2281   else {
2282     ObjectImp::put(exec, p, v, attr);
2283     return;
2284   }
2285
2286   const Window* window = Window::retrieveWindow(m_part);
2287   KHTMLPart* activePart = Window::retrieveActive(exec)->part();
2288   if (!url.url().startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
2289     bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
2290 #if APPLE_CHANGES
2291     // We want a new history item if this JS was called via a user gesture
2292     m_part->scheduleLocationChange(url.url(), activePart->referrer(), !userGesture, userGesture);
2293 #else
2294     m_part->scheduleLocationChange(url.url(), activePart->referrer(), false /*don't lock history*/, userGesture);
2295 #endif
2296   }
2297 }
2298
2299 Value Location::toPrimitive(ExecState *exec, Type) const
2300 {
2301   return String(toString(exec));
2302 }
2303
2304 UString Location::toString(ExecState *) const
2305 {
2306   if (!m_part->url().hasPath())
2307     return m_part->url().prettyURL()+"/";
2308   else
2309     return m_part->url().prettyURL();
2310 }
2311
2312 Value LocationFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
2313 {
2314   if (!thisObj.inherits(&Location::info)) {
2315     Object err = Error::create(exec,TypeError);
2316     exec->setException(err);
2317     return err;
2318   }
2319   Location *location = static_cast<Location *>(thisObj.imp());
2320   KHTMLPart *part = location->part();
2321   if (part) {
2322       
2323     Window* window = Window::retrieveWindow(part);
2324     if (!window->isSafeScript(exec) && id != Location::Replace)
2325         return Undefined();
2326       
2327     switch (id) {
2328     case Location::Replace:
2329     {
2330       QString str = args[0].toString(exec).qstring();
2331       KHTMLPart* p = Window::retrieveActive(exec)->part();
2332       if ( p ) {
2333         const Window* window = Window::retrieveWindow(part);
2334         if (!str.startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
2335           bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
2336           part->scheduleLocationChange(p->htmlDocument().completeURL(str).string(), p->referrer(), true /*lock history*/, userGesture);
2337         }
2338       }
2339       break;
2340     }
2341     case Location::Reload:
2342     {
2343       const Window* window = Window::retrieveWindow(part);
2344       KHTMLPart* activePart = Window::retrieveActive(exec)->part();
2345       if (!part->url().url().startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
2346         bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
2347         part->scheduleLocationChange(part->url().url(), activePart->referrer(), true/*lock history*/, userGesture);
2348       }
2349       break;
2350     }
2351     case Location::ToString:
2352       return String(location->toString(exec));
2353     }
2354   } else
2355     kdDebug(6070) << "LocationFunc::tryExecute - no part!" << endl;
2356   return Undefined();
2357 }
2358
2359 ////////////////////// Selection Object ////////////////////////
2360
2361 const ClassInfo Selection::info = { "Selection", 0, 0, 0 };
2362 /*
2363 @begin SelectionTable 19
2364   anchorNode                Selection::AnchorNode                        DontDelete|ReadOnly
2365   anchorOffset              Selection::AnchorOffset                  DontDelete|ReadOnly
2366   focusNode                 Selection::FocusNode                         DontDelete|ReadOnly
2367   focusOffset               Selection::FocusOffset                       DontDelete|ReadOnly
2368   baseNode                  Selection::AnchorNode                        DontDelete|ReadOnly
2369   baseOffset                Selection::AnchorOffset              DontDelete|ReadOnly
2370   extentNode                Selection::FocusNode                 DontDelete|ReadOnly
2371   extentOffset              Selection::FocusOffset                       DontDelete|ReadOnly
2372   isCollapsed               Selection::IsCollapsed                       DontDelete|ReadOnly
2373   type                      Selection::_Type                     DontDelete|ReadOnly
2374   [[==]]                        Selection::EqualEqual                DontDelete|ReadOnly
2375   toString                  Selection::ToString                  DontDelete|Function 0
2376   collapse                  Selection::Collapse                  DontDelete|Function 2
2377   collapseToEnd             Selection::CollapseToEnd             DontDelete|Function 0
2378   collapseToStart           Selection::CollapseToStart           DontDelete|Function 0
2379   empty                     Selection::Empty                     DontDelete|Function 0
2380   setBaseAndExtent          Selection::SetBaseAndExtent          DontDelete|Function 4
2381   setPosition               Selection::SetPosition               DontDelete|Function 2
2382   modify                    Selection::Modify                    DontDelete|Function 3
2383 @end
2384 */
2385 IMPLEMENT_PROTOFUNC(SelectionFunc)
2386 Selection::Selection(KHTMLPart *p) : m_part(p)
2387 {
2388   //kdDebug(6070) << "Selection::Selection " << this << " m_part=" << (void*)m_part << endl;
2389 }
2390
2391 Selection::~Selection()
2392 {
2393   //kdDebug(6070) << "Selection::~Selection " << this << " m_part=" << (void*)m_part << endl;
2394 }
2395
2396 Value Selection::get(ExecState *exec, const Identifier &p) const
2397 {
2398 #ifdef KJS_VERBOSE
2399   kdDebug(6070) << "Selection::get " << p.qstring() << " m_part=" << (void*)m_part << endl;
2400 #endif
2401
2402   if (m_part.isNull())
2403     return Undefined();
2404   
2405   const Window* window = Window::retrieveWindow(m_part);
2406   if (!window || !window->isSafeScript(exec))
2407       return Undefined();
2408
2409   DocumentImpl *docimpl = m_part->xmlDocImpl();
2410   if (docimpl)
2411     docimpl->updateLayoutIgnorePendingStylesheets();
2412
2413   KURL url = m_part->url();
2414   const HashEntry *entry = Lookup::findEntry(&SelectionTable, p);
2415   if (entry)
2416     switch (entry->value) {
2417         case AnchorNode:
2418         case BaseNode:
2419             return getDOMNode(exec, Node(m_part->selection().base().node()));
2420         case AnchorOffset:
2421         case BaseOffset:
2422             return Number(m_part->selection().base().offset());
2423         case FocusNode:
2424         case ExtentNode:
2425             return getDOMNode(exec, Node(m_part->selection().extent().node()));
2426         case FocusOffset:
2427         case ExtentOffset:
2428             return Number(m_part->selection().extent().offset());
2429         case IsCollapsed:
2430             return Boolean(!m_part->selection().isRange());
2431         case _Type: {
2432             switch (m_part->selection().state()) {
2433                 case khtml::Selection::NONE:
2434                     return String("None");
2435                 case khtml::Selection::CARET:
2436                     return String("Caret");
2437                 case khtml::Selection::RANGE:
2438                     return String("Range");
2439             }
2440         }
2441         case EqualEqual:
2442             return String(toString(exec));
2443         case ToString:
2444           return lookupOrCreateFunction<SelectionFunc>(exec,p,this,entry->value,entry->params,entry->attr);
2445     }
2446     // Look for overrides
2447     ValueImp * val = ObjectImp::getDirect(p);
2448     if (val)
2449         return Value(val);
2450     if (entry)
2451         switch (entry->value) {
2452             case Collapse:
2453             case CollapseToEnd:
2454             case CollapseToStart:
2455             case Empty:
2456             case SetBaseAndExtent:
2457             case SetPosition:
2458             case Modify:
2459                 return lookupOrCreateFunction<SelectionFunc>(exec,p,this,entry->value,entry->params,entry->attr);
2460         }
2461
2462     return Undefined();
2463 }
2464
2465 void Selection::put(ExecState *exec, const Identifier &p, const Value &v, int attr)
2466 {
2467 }
2468
2469 Value Selection::toPrimitive(ExecState *exec, Type) const
2470 {
2471   return String(toString(exec));
2472 }
2473
2474 UString Selection::toString(ExecState *) const
2475 {
2476     if (!m_part->selection().isRange())
2477         return UString("");
2478     return UString(m_part->selection().toRange().toString());
2479 }
2480
2481 Value SelectionFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
2482 {
2483     if (!thisObj.inherits(&Selection::info)) {
2484         Object err = Error::create(exec,TypeError);
2485         exec->setException(err);
2486         return err;
2487     }
2488     Selection *selection = static_cast<Selection *>(thisObj.imp());
2489     KHTMLPart *part = selection->part();
2490     if (part) {
2491         DocumentImpl *docimpl = part->xmlDocImpl();
2492         if (docimpl)
2493             docimpl->updateLayoutIgnorePendingStylesheets();
2494             
2495         switch (id) {
2496             case Selection::Collapse:
2497                 TypingCommand::closeTyping(part->lastEditCommand());
2498                 part->setSelection(khtml::Selection(Position(KJS::toNode(args[0]).handle(), args[1].toInt32(exec)), khtml::SEL_DEFAULT_AFFINITY));
2499                 break;
2500             case Selection::CollapseToEnd:
2501                 TypingCommand::closeTyping(part->lastEditCommand());
2502                 part->setSelection(khtml::Selection(part->selection().end(), part->selection().endAffinity()));
2503                 break;
2504             case Selection::CollapseToStart:
2505                 TypingCommand::closeTyping(part->lastEditCommand());
2506                 part->setSelection(khtml::Selection(part->selection().start(), part->selection().startAffinity()));
2507                 break;
2508             case Selection::Empty:
2509                 TypingCommand::closeTyping(part->lastEditCommand());
2510                 part->clearSelection();
2511                 break;
2512             case Selection::SetBaseAndExtent: {
2513                 TypingCommand::closeTyping(part->lastEditCommand());
2514                 Position base(KJS::toNode(args[0]).handle(), args[1].toInt32(exec));
2515                 Position extent(KJS::toNode(args[2]).handle(), args[3].toInt32(exec));
2516                 part->setSelection(khtml::Selection(base, khtml::SEL_DEFAULT_AFFINITY, extent, khtml::SEL_DEFAULT_AFFINITY));
2517                 break;
2518             }
2519             case Selection::SetPosition:
2520                 TypingCommand::closeTyping(part->lastEditCommand());
2521                 part->setSelection(khtml::Selection(Position(KJS::toNode(args[0]).handle(), args[1].toInt32(exec)), khtml::SEL_DEFAULT_AFFINITY));
2522                 break;
2523             case Selection::Modify: {
2524                 TypingCommand::closeTyping(part->lastEditCommand());
2525                 khtml::Selection s(part->selection());
2526                 khtml::Selection::EAlter alter = khtml::Selection::MOVE;
2527                 if (args[0].toString(exec).string().lower() == "extend")
2528                     alter = khtml::Selection::EXTEND;
2529                 DOMString directionString = args[1].toString(exec).string().lower();
2530                 khtml::Selection::EDirection direction = khtml::Selection::FORWARD;
2531                 if (directionString == "backward")
2532                     direction = khtml::Selection::BACKWARD;
2533                 else if (directionString == "left")
2534                     direction = khtml::Selection::LEFT;
2535                 if (directionString == "right")
2536                     direction = khtml::Selection::RIGHT;
2537                 khtml::ETextGranularity granularity = khtml::CHARACTER;
2538                 DOMString granularityString = args[2].toString(exec).string().lower();
2539                 if (granularityString == "word")
2540                     granularity = khtml::WORD;
2541                 else if (granularityString == "line")
2542                     granularity = khtml::LINE;
2543                 else if (granularityString == "pargraph")
2544                     granularity = khtml::PARAGRAPH;
2545                 s.modify(alter, direction, granularity);
2546                 part->setSelection(s);
2547                 part->setSelectionGranularity(granularity);
2548             }
2549         }
2550     }
2551
2552     return Undefined();
2553 }
2554
2555 ////////////////////// BarInfo Object ////////////////////////
2556
2557 const ClassInfo BarInfo::info = { "BarInfo", 0, 0, 0 };
2558 /*
2559 @begin BarInfoTable 1
2560   visible                BarInfo::Visible                        DontDelete|ReadOnly
2561 @end
2562 */
2563 BarInfo::BarInfo(ExecState *exec, KHTMLPart *p, Type barType) 
2564   : ObjectImp(exec->lexicalInterpreter()->builtinObjectPrototype())
2565   , m_part(p)
2566   , m_type(barType)
2567 {
2568 }
2569
2570 BarInfo::~BarInfo()
2571 {
2572 }
2573
2574 Value BarInfo::get(ExecState *exec, const Identifier &p) const
2575 {
2576   if (m_part.isNull())
2577     return Undefined();
2578   
2579   const HashEntry *entry = Lookup::findEntry(&BarInfoTable, p);
2580   if (entry && entry->value == Visible) {
2581     switch (m_type) {
2582     case Locationbar:
2583 #if APPLE_CHANGES
2584       return Boolean(KWQ(m_part)->locationbarVisible());
2585 #endif
2586     case Menubar: 
2587 #if APPLE_CHANGES
2588       return Boolean(KWQ(m_part)->locationbarVisible());
2589 #endif
2590     case Personalbar:
2591 #if APPLE_CHANGES
2592       return Boolean(KWQ(m_part)->personalbarVisible());
2593 #endif
2594     case Scrollbars: 
2595 #if APPLE_CHANGES
2596       return Boolean(KWQ(m_part)->scrollbarsVisible());
2597 #endif
2598     case Statusbar:
2599 #if APPLE_CHANGES
2600       return Boolean(KWQ(m_part)->statusbarVisible());
2601 #endif
2602     case Toolbar:
2603 #if APPLE_CHANGES
2604       return Boolean(KWQ(m_part)->toolbarVisible());
2605 #endif
2606     default:
2607       return Boolean(false);
2608     }
2609   }
2610   
2611   return Undefined();
2612 }
2613
2614 void BarInfo::put(ExecState *exec, const Identifier &p, const Value &v, int attr)
2615 {
2616 }
2617
2618 ////////////////////// History Object ////////////////////////
2619
2620 const ClassInfo History::info = { "History", 0, 0, 0 };
2621 /*
2622 @begin HistoryTable 4
2623   length        History::Length         DontDelete|ReadOnly
2624   back          History::Back           DontDelete|Function 0
2625   forward       History::Forward        DontDelete|Function 0
2626   go            History::Go             DontDelete|Function 1
2627 @end
2628 */
2629 IMPLEMENT_PROTOFUNC(HistoryFunc)
2630
2631 Value History::get(ExecState *exec, const Identifier &p) const
2632 {
2633   return lookupGet<HistoryFunc,History,ObjectImp>(exec,p,&HistoryTable,this);
2634 }
2635
2636 Value History::getValueProperty(ExecState *, int token) const
2637 {
2638   switch (token) {
2639   case Length:
2640   {
2641     KParts::BrowserExtension *ext = part->browserExtension();
2642     if ( !ext )
2643       return Number( 0 );
2644
2645     KParts::BrowserInterface *iface = ext->browserInterface();
2646     if ( !iface )
2647       return Number( 0 );
2648
2649     QVariant length = iface->property( "historyLength" );
2650
2651     if ( length.type() != QVariant::UInt )
2652       return Number( 0 );
2653
2654     return Number( length.toUInt() );
2655   }
2656   default:
2657     kdWarning() << "Unhandled token in History::getValueProperty : " << token << endl;
2658     return Undefined();
2659   }
2660 }
2661
2662 UString History::toString(ExecState *exec) const
2663 {
2664   return "[object History]";
2665 }
2666
2667 Value HistoryFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
2668 {
2669   if (!thisObj.inherits(&History::info)) {
2670     Object err = Error::create(exec,TypeError);
2671     exec->setException(err);
2672     return err;
2673   }
2674   History *history = static_cast<History *>(thisObj.imp());
2675
2676   int steps;
2677   switch (id) {
2678   case History::Back:
2679     steps = -1;
2680     break;
2681   case History::Forward:
2682     steps = 1;
2683     break;
2684   case History::Go:
2685     steps = args[0].toInt32(exec);
2686     break;
2687   default:
2688     return Undefined();
2689   }
2690
2691   history->part->scheduleHistoryNavigation(steps);
2692   return Undefined();
2693 }
2694
2695 /////////////////////////////////////////////////////////////////////////////
2696
2697 #ifdef Q_WS_QWS
2698
2699 const ClassInfo Konqueror::info = { "Konqueror", 0, 0, 0 };
2700
2701 bool Konqueror::hasProperty(ExecState *exec, const Identifier &p) const
2702 {
2703   if ( p.qstring().startsWith( "goHistory" ) ) return false;
2704
2705   return true;
2706 }
2707
2708 Value Konqueror::get(ExecState *exec, const Identifier &p) const
2709 {
2710   if ( p == "goHistory" || part->url().protocol() != "http" || part->url().host() != "localhost" )
2711     return Undefined();
2712
2713   KParts::BrowserExtension *ext = part->browserExtension();
2714   if ( ext ) {
2715     KParts::BrowserInterface *iface = ext->browserInterface();
2716     if ( iface ) {
2717       QVariant prop = iface->property( p.qstring().latin1() );
2718
2719       if ( prop.isValid() ) {
2720         switch( prop.type() ) {
2721         case QVariant::Int:
2722           return Number( prop.toInt() );
2723         case QVariant::String:
2724           return String( prop.toString() );
2725         default:
2726           break;
2727         }
2728       }
2729     }
2730   }
2731
2732   return /*Function*/( new KonquerorFunc(this, p.qstring().latin1() ) );
2733 }
2734
2735 Value KonquerorFunc::tryCall(ExecState *exec, Object &, const List &args)
2736 {
2737   KParts::BrowserExtension *ext = konqueror->part->browserExtension();
2738
2739   if(!ext)
2740     return Undefined();
2741
2742   KParts::BrowserInterface *iface = ext->browserInterface();
2743
2744   if ( !iface )
2745     return Undefined();
2746
2747   QCString n = m_name.data();
2748   n += "()";
2749   iface->callMethod( n.data(), QVariant() );
2750
2751   return Undefined();
2752 }
2753
2754 UString Konqueror::toString(ExecState *) const
2755 {
2756   return UString("[object Konqueror]");
2757 }
2758
2759 #endif
2760 /////////////////////////////////////////////////////////////////////////////
2761
2762 #include "kjs_window.moc"
2763