d96b54cada6b4642c6adce220e24abd5d7af705f
[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();
576       return Number(m_part->view()->visibleHeight());
577     case InnerWidth:
578       if (!m_part->view())
579         return Undefined();
580       updateLayout();
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() const
1880 {
1881   DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl *>(m_part->document().handle());
1882   if (docimpl) {
1883     docimpl->updateLayoutIgnorePendingStylesheets();
1884   }
1885 }
1886
1887
1888 ////////////////////// ScheduledAction ////////////////////////
1889
1890 ScheduledAction::ScheduledAction(Object _func, List _args, bool _singleShot)
1891 {
1892   //kdDebug(6070) << "ScheduledAction::ScheduledAction(isFunction) " << this << endl;
1893   func = _func;
1894   args = _args;
1895   isFunction = true;
1896   singleShot = _singleShot;
1897 }
1898
1899 ScheduledAction::ScheduledAction(const QString &_code, bool _singleShot)
1900 {
1901   //kdDebug(6070) << "ScheduledAction::ScheduledAction(!isFunction) " << this << endl;
1902   //func = 0;
1903   //args = 0;
1904   code = _code;
1905   isFunction = false;
1906   singleShot = _singleShot;
1907 }
1908
1909
1910 void ScheduledAction::execute(Window *window)
1911 {
1912   ScriptInterpreter *interpreter = static_cast<ScriptInterpreter *>(KJSProxy::proxy(window->m_part)->interpreter());
1913
1914   interpreter->setProcessingTimerCallback(true);
1915
1916   //kdDebug(6070) << "ScheduledAction::execute " << this << endl;
1917   if (isFunction) {
1918     if (func.implementsCall()) {
1919       // #### check this
1920       Q_ASSERT( window->m_part );
1921       if ( window->m_part )
1922       {
1923         KJS::Interpreter *interpreter = KJSProxy::proxy( window->m_part )->interpreter();
1924         ExecState *exec = interpreter->globalExec();
1925         Q_ASSERT( window == interpreter->globalObject().imp() );
1926         Object obj( window );
1927         Interpreter::lock();
1928         func.call(exec,obj,args); // note that call() creates its own execution state for the func call
1929         Interpreter::unlock();
1930         if ( exec->hadException() ) {
1931 #if APPLE_CHANGES
1932           Interpreter::lock();
1933           char *message = exec->exception().toObject(exec).get(exec, messagePropertyName).toString(exec).ascii();
1934           int lineNumber =  exec->exception().toObject(exec).get(exec, "line").toInt32(exec);
1935           Interpreter::unlock();
1936           if (Interpreter::shouldPrintExceptions()) {
1937             printf("(timer):%s\n", message);
1938           }
1939           KWQ(window->m_part)->addMessageToConsole(message, lineNumber, QString());
1940 #endif
1941           exec->clearException();
1942         }
1943       }
1944     }
1945   }
1946   else {
1947     window->m_part->executeScript(code);
1948   }
1949
1950   // Update our document's rendering following the execution of the timeout callback.
1951   DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(window->m_part->document().handle());
1952   doc->updateRendering();
1953   
1954   interpreter->setProcessingTimerCallback(false);
1955 }
1956
1957 ScheduledAction::~ScheduledAction()
1958 {
1959   //kdDebug(6070) << "ScheduledAction::~ScheduledAction " << this << endl;
1960 }
1961
1962 ////////////////////// WindowQObject ////////////////////////
1963
1964 WindowQObject::WindowQObject(Window *w)
1965   : parent(w)
1966 {
1967   //kdDebug(6070) << "WindowQObject::WindowQObject " << this << endl;
1968   part = parent->m_part;
1969   connect( parent->m_part, SIGNAL( destroyed() ),
1970            this, SLOT( parentDestroyed() ) );
1971 }
1972
1973 WindowQObject::~WindowQObject()
1974 {
1975   //kdDebug(6070) << "WindowQObject::~WindowQObject " << this << endl;
1976   parentDestroyed(); // reuse same code
1977 }
1978
1979 void WindowQObject::parentDestroyed()
1980 {
1981   //kdDebug(6070) << "WindowQObject::parentDestroyed " << this << " we have " << scheduledActions.count() << " actions in the map" << endl;
1982   killTimers();
1983   QMapIterator<int,ScheduledAction*> it;
1984   for (it = scheduledActions.begin(); it != scheduledActions.end(); ++it) {
1985     ScheduledAction *action = *it;
1986     //kdDebug(6070) << "WindowQObject::parentDestroyed deleting action " << action << endl;
1987     delete action;
1988   }
1989   scheduledActions.clear();
1990 }
1991
1992 int WindowQObject::installTimeout(const UString &handler, int t, bool singleShot)
1993 {
1994   //kdDebug(6070) << "WindowQObject::installTimeout " << this << " " << handler.ascii() << endl;
1995   int id = startTimer(t);
1996   ScheduledAction *action = new ScheduledAction(handler.qstring(),singleShot);
1997   scheduledActions.insert(id, action);
1998   //kdDebug(6070) << this << " got id=" << id << " action=" << action << " - now having " << scheduledActions.count() << " actions"<<endl;
1999   return id;
2000 }
2001
2002 int WindowQObject::installTimeout(const Value &func, List args, int t, bool singleShot)
2003 {
2004   Object objFunc = Object::dynamicCast( func );
2005   int id = startTimer(t);
2006   scheduledActions.insert(id, new ScheduledAction(objFunc,args,singleShot));
2007   return id;
2008 }
2009
2010 QMap<int, ScheduledAction*> *WindowQObject::pauseTimeouts(const void *key)
2011 {
2012     QMapIterator<int,ScheduledAction*> it;
2013
2014     QMap<int, KJS::ScheduledAction*>*pausedActions = new QMap<int, KJS::ScheduledAction*>;
2015     for (it = scheduledActions.begin(); it != scheduledActions.end(); ++it) {
2016         int timerId = it.key();
2017         pauseTimer (timerId, key);
2018         pausedActions->insert(timerId, it.data());
2019     }
2020     scheduledActions.clear();
2021     return pausedActions;
2022 }
2023
2024 void WindowQObject::resumeTimeouts(QMap<int, ScheduledAction*> *sa, const void *key)
2025 {
2026     QMapIterator<int,ScheduledAction*> it;
2027     for (it = sa->begin(); it != sa->end(); ++it) {
2028         int timerId = it.key();
2029         scheduledActions.insert(timerId, it.data());
2030     }
2031     sa->clear();
2032     resumeTimers (key, this);
2033 }
2034
2035 void WindowQObject::clearTimeout(int timerId, bool delAction)
2036 {
2037   //kdDebug(6070) << "WindowQObject::clearTimeout " << this << " timerId=" << timerId << " delAction=" << delAction << endl;
2038   killTimer(timerId);
2039   if (delAction) {
2040     QMapIterator<int,ScheduledAction*> it = scheduledActions.find(timerId);
2041     if (it != scheduledActions.end()) {
2042       ScheduledAction *action = *it;
2043       scheduledActions.remove(it);
2044       delete action;
2045     }
2046   }
2047 }
2048
2049 void WindowQObject::timerEvent(QTimerEvent *e)
2050 {
2051   QMapIterator<int,ScheduledAction*> it = scheduledActions.find(e->timerId());
2052   if (it != scheduledActions.end()) {
2053     ScheduledAction *action = *it;
2054     bool singleShot = action->singleShot;
2055     //kdDebug(6070) << "WindowQObject::timerEvent " << this << " action=" << action << " singleShot:" << singleShot << endl;
2056
2057     // remove single shots installed by setTimeout()
2058     if (singleShot)
2059     {
2060       clearTimeout(e->timerId(),false);
2061       scheduledActions.remove(it);
2062     }
2063         
2064     if (!parent->part().isNull())
2065       action->execute(parent);
2066
2067     // It is important to test singleShot and not action->singleShot here - the
2068     // action could have been deleted already if not single shot and if the
2069     // JS code called by execute() calls clearTimeout().
2070     if (singleShot)
2071       delete action;
2072   } else
2073     kdWarning(6070) << "WindowQObject::timerEvent this=" << this << " timer " << e->timerId()
2074                     << " not found (" << scheduledActions.count() << " actions in map)" << endl;
2075 }
2076
2077 void WindowQObject::timeoutClose()
2078 {
2079   if (!parent->part().isNull())
2080   {
2081     //kdDebug(6070) << "WindowQObject::timeoutClose -> closing window" << endl;
2082     delete parent->m_part;
2083   }
2084 }
2085
2086 #if APPLE_CHANGES
2087 bool WindowQObject::hasTimeouts()
2088 {
2089     return scheduledActions.count();
2090 }
2091 #endif
2092
2093 Value FrameArray::get(ExecState *exec, const Identifier &p) const
2094 {
2095 #ifdef KJS_VERBOSE
2096   kdDebug(6070) << "FrameArray::get " << p.qstring() << " part=" << (void*)part << endl;
2097 #endif
2098   if (part.isNull())
2099     return Undefined();
2100
2101   QPtrList<KParts::ReadOnlyPart> frames = part->frames();
2102   unsigned int len = frames.count();
2103   if (p == lengthPropertyName)
2104     return Number(len);
2105   else if (p== "location") // non-standard property, but works in NS and IE
2106   {
2107     Object obj = Object::dynamicCast( Window::retrieve( part ) );
2108     if ( !obj.isNull() )
2109       return obj.get( exec, "location" );
2110     return Undefined();
2111   }
2112
2113   // check for the name or number
2114   KParts::ReadOnlyPart *frame = part->findFrame(p.qstring());
2115   if (!frame) {
2116     bool ok;
2117     unsigned int i = p.toArrayIndex(&ok);
2118     if (ok && i < len)
2119       frame = frames.at(i);
2120   }
2121
2122   // we are potentially fetching a reference to a another Window object here.
2123   // i.e. we may be accessing objects from another interpreter instance.
2124   // Therefore we have to be a bit careful with memory managment.
2125   if (frame && frame->inherits("KHTMLPart")) {
2126     KHTMLPart *khtml = static_cast<KHTMLPart*>(frame);
2127     return Window::retrieve(khtml);
2128   }
2129
2130   return ObjectImp::get(exec, p);
2131 }
2132
2133 UString FrameArray::toString(ExecState *) const
2134 {
2135   return "[object FrameArray]";
2136 }
2137
2138 ////////////////////// Location Object ////////////////////////
2139
2140 const ClassInfo Location::info = { "Location", 0, 0, 0 };
2141 /*
2142 @begin LocationTable 11
2143   hash          Location::Hash          DontDelete
2144   host          Location::Host          DontDelete
2145   hostname      Location::Hostname      DontDelete
2146   href          Location::Href          DontDelete
2147   pathname      Location::Pathname      DontDelete
2148   port          Location::Port          DontDelete
2149   protocol      Location::Protocol      DontDelete
2150   search        Location::Search        DontDelete
2151   [[==]]        Location::EqualEqual    DontDelete|ReadOnly
2152   toString      Location::ToString      DontDelete|Function 0
2153   replace       Location::Replace       DontDelete|Function 1
2154   reload        Location::Reload        DontDelete|Function 0
2155 @end
2156 */
2157 IMPLEMENT_PROTOFUNC(LocationFunc)
2158 Location::Location(KHTMLPart *p) : m_part(p)
2159 {
2160   //kdDebug(6070) << "Location::Location " << this << " m_part=" << (void*)m_part << endl;
2161 }
2162
2163 Location::~Location()
2164 {
2165   //kdDebug(6070) << "Location::~Location " << this << " m_part=" << (void*)m_part << endl;
2166 }
2167
2168 Value Location::get(ExecState *exec, const Identifier &p) const
2169 {
2170 #ifdef KJS_VERBOSE
2171   kdDebug(6070) << "Location::get " << p.qstring() << " m_part=" << (void*)m_part << endl;
2172 #endif
2173
2174   if (m_part.isNull())
2175     return Undefined();
2176   
2177   const Window* window = Window::retrieveWindow(m_part);
2178   if (!window || !window->isSafeScript(exec))
2179       return Undefined();
2180
2181   KURL url = m_part->url();
2182   const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
2183   if (entry)
2184     switch (entry->value) {
2185     case Hash:
2186       return String( url.ref().isNull() ? QString("") : "#" + url.ref() );
2187     case Host: {
2188       UString str = url.host();
2189       if (url.port())
2190         str += ":" + QString::number((int)url.port());
2191       return String(str);
2192       // Note: this is the IE spec. The NS spec swaps the two, it says
2193       // "The hostname property is the concatenation of the host and port properties, separated by a colon."
2194       // Bleh.
2195     }
2196     case Hostname:
2197       return String( url.host() );
2198     case Href:
2199       if (!url.hasPath())
2200         return String( url.prettyURL()+"/" );
2201       else
2202         return String( url.prettyURL() );
2203     case Pathname:
2204       return String( url.path().isEmpty() ? QString("/") : url.path() );
2205     case Port:
2206       return String( url.port() ? QString::number((int)url.port()) : QString::fromLatin1("") );
2207     case Protocol:
2208       return String( url.protocol()+":" );
2209     case Search:
2210       return String( url.query() );
2211     case EqualEqual: // [[==]]
2212       return String(toString(exec));
2213     case ToString:
2214       return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
2215     }
2216   // Look for overrides
2217   ValueImp * val = ObjectImp::getDirect(p);
2218   if (val)
2219     return Value(val);
2220   if (entry)
2221     switch (entry->value) {
2222     case Replace:
2223       return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
2224     case Reload:
2225       return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
2226     }
2227
2228   return Undefined();
2229 }
2230
2231 void Location::put(ExecState *exec, const Identifier &p, const Value &v, int attr)
2232 {
2233 #ifdef KJS_VERBOSE
2234   kdDebug(6070) << "Location::put " << p.qstring() << " m_part=" << (void*)m_part << endl;
2235 #endif
2236   if (m_part.isNull())
2237     return;
2238
2239   QString str = v.toString(exec).qstring();
2240   KURL url = m_part->url();
2241   const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
2242   if (entry)
2243     switch (entry->value) {
2244     case Href: {
2245       KHTMLPart* p = Window::retrieveActive(exec)->part();
2246       if ( p )
2247         url = p->htmlDocument().completeURL( str ).string();
2248       else
2249         url = str;
2250       break;
2251     }
2252     case Hash:
2253       url.setRef(str);
2254       break;
2255     case Host: {
2256       QString host = str.left(str.find(":"));
2257       QString port = str.mid(str.find(":")+1);
2258       url.setHost(host);
2259       url.setPort(port.toUInt());
2260       break;
2261     }
2262     case Hostname:
2263       url.setHost(str);
2264       break;
2265     case Pathname:
2266       url.setPath(str);
2267       break;
2268     case Port:
2269       url.setPort(str.toUInt());
2270       break;
2271     case Protocol:
2272       url.setProtocol(str);
2273       break;
2274     case Search:
2275       url.setQuery(str);
2276       break;
2277     }
2278   else {
2279     ObjectImp::put(exec, p, v, attr);
2280     return;
2281   }
2282
2283   const Window* window = Window::retrieveWindow(m_part);
2284   KHTMLPart* activePart = Window::retrieveActive(exec)->part();
2285   if (!url.url().startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
2286     bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
2287 #if APPLE_CHANGES
2288     // We want a new history item if this JS was called via a user gesture
2289     m_part->scheduleLocationChange(url.url(), activePart->referrer(), !userGesture, userGesture);
2290 #else
2291     m_part->scheduleLocationChange(url.url(), activePart->referrer(), false /*don't lock history*/, userGesture);
2292 #endif
2293   }
2294 }
2295
2296 Value Location::toPrimitive(ExecState *exec, Type) const
2297 {
2298   return String(toString(exec));
2299 }
2300
2301 UString Location::toString(ExecState *) const
2302 {
2303   if (!m_part->url().hasPath())
2304     return m_part->url().prettyURL()+"/";
2305   else
2306     return m_part->url().prettyURL();
2307 }
2308
2309 Value LocationFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
2310 {
2311   if (!thisObj.inherits(&Location::info)) {
2312     Object err = Error::create(exec,TypeError);
2313     exec->setException(err);
2314     return err;
2315   }
2316   Location *location = static_cast<Location *>(thisObj.imp());
2317   KHTMLPart *part = location->part();
2318   if (part) {
2319       
2320     Window* window = Window::retrieveWindow(part);
2321     if (!window->isSafeScript(exec) && id != Location::Replace)
2322         return Undefined();
2323       
2324     switch (id) {
2325     case Location::Replace:
2326     {
2327       QString str = args[0].toString(exec).qstring();
2328       KHTMLPart* p = Window::retrieveActive(exec)->part();
2329       if ( p ) {
2330         const Window* window = Window::retrieveWindow(part);
2331         if (!str.startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
2332           bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
2333           part->scheduleLocationChange(p->htmlDocument().completeURL(str).string(), p->referrer(), true /*lock history*/, userGesture);
2334         }
2335       }
2336       break;
2337     }
2338     case Location::Reload:
2339     {
2340       const Window* window = Window::retrieveWindow(part);
2341       KHTMLPart* activePart = Window::retrieveActive(exec)->part();
2342       if (!part->url().url().startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
2343         bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
2344         part->scheduleLocationChange(part->url().url(), activePart->referrer(), true/*lock history*/, userGesture);
2345       }
2346       break;
2347     }
2348     case Location::ToString:
2349       return String(location->toString(exec));
2350     }
2351   } else
2352     kdDebug(6070) << "LocationFunc::tryExecute - no part!" << endl;
2353   return Undefined();
2354 }
2355
2356 ////////////////////// Selection Object ////////////////////////
2357
2358 const ClassInfo Selection::info = { "Selection", 0, 0, 0 };
2359 /*
2360 @begin SelectionTable 19
2361   anchorNode                Selection::AnchorNode                        DontDelete|ReadOnly
2362   anchorOffset              Selection::AnchorOffset                  DontDelete|ReadOnly
2363   focusNode                 Selection::FocusNode                         DontDelete|ReadOnly
2364   focusOffset               Selection::FocusOffset                       DontDelete|ReadOnly
2365   baseNode                  Selection::AnchorNode                        DontDelete|ReadOnly
2366   baseOffset                Selection::AnchorOffset              DontDelete|ReadOnly
2367   extentNode                Selection::FocusNode                 DontDelete|ReadOnly
2368   extentOffset              Selection::FocusOffset                       DontDelete|ReadOnly
2369   isCollapsed               Selection::IsCollapsed                       DontDelete|ReadOnly
2370   type                      Selection::_Type                     DontDelete|ReadOnly
2371   [[==]]                        Selection::EqualEqual                DontDelete|ReadOnly
2372   toString                  Selection::ToString                  DontDelete|Function 0
2373   collapse                  Selection::Collapse                  DontDelete|Function 2
2374   collapseToEnd             Selection::CollapseToEnd             DontDelete|Function 0
2375   collapseToStart           Selection::CollapseToStart           DontDelete|Function 0
2376   empty                     Selection::Empty                     DontDelete|Function 0
2377   setBaseAndExtent          Selection::SetBaseAndExtent          DontDelete|Function 4
2378   setPosition               Selection::SetPosition               DontDelete|Function 2
2379   modify                    Selection::Modify                    DontDelete|Function 3
2380 @end
2381 */
2382 IMPLEMENT_PROTOFUNC(SelectionFunc)
2383 Selection::Selection(KHTMLPart *p) : m_part(p)
2384 {
2385   //kdDebug(6070) << "Selection::Selection " << this << " m_part=" << (void*)m_part << endl;
2386 }
2387
2388 Selection::~Selection()
2389 {
2390   //kdDebug(6070) << "Selection::~Selection " << this << " m_part=" << (void*)m_part << endl;
2391 }
2392
2393 Value Selection::get(ExecState *exec, const Identifier &p) const
2394 {
2395 #ifdef KJS_VERBOSE
2396   kdDebug(6070) << "Selection::get " << p.qstring() << " m_part=" << (void*)m_part << endl;
2397 #endif
2398
2399   if (m_part.isNull())
2400     return Undefined();
2401   
2402   const Window* window = Window::retrieveWindow(m_part);
2403   if (!window || !window->isSafeScript(exec))
2404       return Undefined();
2405
2406   DocumentImpl *docimpl = m_part->xmlDocImpl();
2407   if (docimpl)
2408     docimpl->updateLayoutIgnorePendingStylesheets();
2409
2410   KURL url = m_part->url();
2411   const HashEntry *entry = Lookup::findEntry(&SelectionTable, p);
2412   if (entry)
2413     switch (entry->value) {
2414         case AnchorNode:
2415         case BaseNode:
2416             return getDOMNode(exec, Node(m_part->selection().base().node()));
2417         case AnchorOffset:
2418         case BaseOffset:
2419             return Number(m_part->selection().base().offset());
2420         case FocusNode:
2421         case ExtentNode:
2422             return getDOMNode(exec, Node(m_part->selection().extent().node()));
2423         case FocusOffset:
2424         case ExtentOffset:
2425             return Number(m_part->selection().extent().offset());
2426         case IsCollapsed:
2427             return Boolean(!m_part->selection().isRange());
2428         case _Type: {
2429             switch (m_part->selection().state()) {
2430                 case khtml::Selection::NONE:
2431                     return String("None");
2432                 case khtml::Selection::CARET:
2433                     return String("Caret");
2434                 case khtml::Selection::RANGE:
2435                     return String("Range");
2436             }
2437         }
2438         case EqualEqual:
2439             return String(toString(exec));
2440         case ToString:
2441           return lookupOrCreateFunction<SelectionFunc>(exec,p,this,entry->value,entry->params,entry->attr);
2442     }
2443     // Look for overrides
2444     ValueImp * val = ObjectImp::getDirect(p);
2445     if (val)
2446         return Value(val);
2447     if (entry)
2448         switch (entry->value) {
2449             case Collapse:
2450             case CollapseToEnd:
2451             case CollapseToStart:
2452             case Empty:
2453             case SetBaseAndExtent:
2454             case SetPosition:
2455             case Modify:
2456                 return lookupOrCreateFunction<SelectionFunc>(exec,p,this,entry->value,entry->params,entry->attr);
2457         }
2458
2459     return Undefined();
2460 }
2461
2462 void Selection::put(ExecState *exec, const Identifier &p, const Value &v, int attr)
2463 {
2464 }
2465
2466 Value Selection::toPrimitive(ExecState *exec, Type) const
2467 {
2468   return String(toString(exec));
2469 }
2470
2471 UString Selection::toString(ExecState *) const
2472 {
2473     if (!m_part->selection().isRange())
2474         return UString("");
2475     return UString(m_part->selection().toRange().toString());
2476 }
2477
2478 Value SelectionFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
2479 {
2480     if (!thisObj.inherits(&Selection::info)) {
2481         Object err = Error::create(exec,TypeError);
2482         exec->setException(err);
2483         return err;
2484     }
2485     Selection *selection = static_cast<Selection *>(thisObj.imp());
2486     KHTMLPart *part = selection->part();
2487     if (part) {
2488         DocumentImpl *docimpl = part->xmlDocImpl();
2489         if (docimpl)
2490             docimpl->updateLayoutIgnorePendingStylesheets();
2491             
2492         switch (id) {
2493             case Selection::Collapse:
2494                 TypingCommand::closeTyping(part->lastEditCommand());
2495                 part->setSelection(khtml::Selection(Position(KJS::toNode(args[0]).handle(), args[1].toInt32(exec)), khtml::SEL_DEFAULT_AFFINITY));
2496                 break;
2497             case Selection::CollapseToEnd:
2498                 TypingCommand::closeTyping(part->lastEditCommand());
2499                 part->setSelection(khtml::Selection(part->selection().end(), part->selection().endAffinity()));
2500                 break;
2501             case Selection::CollapseToStart:
2502                 TypingCommand::closeTyping(part->lastEditCommand());
2503                 part->setSelection(khtml::Selection(part->selection().start(), part->selection().startAffinity()));
2504                 break;
2505             case Selection::Empty:
2506                 TypingCommand::closeTyping(part->lastEditCommand());
2507                 part->clearSelection();
2508                 break;
2509             case Selection::SetBaseAndExtent: {
2510                 TypingCommand::closeTyping(part->lastEditCommand());
2511                 Position base(KJS::toNode(args[0]).handle(), args[1].toInt32(exec));
2512                 Position extent(KJS::toNode(args[2]).handle(), args[3].toInt32(exec));
2513                 part->setSelection(khtml::Selection(base, khtml::SEL_DEFAULT_AFFINITY, extent, khtml::SEL_DEFAULT_AFFINITY));
2514                 break;
2515             }
2516             case Selection::SetPosition:
2517                 TypingCommand::closeTyping(part->lastEditCommand());
2518                 part->setSelection(khtml::Selection(Position(KJS::toNode(args[0]).handle(), args[1].toInt32(exec)), khtml::SEL_DEFAULT_AFFINITY));
2519                 break;
2520             case Selection::Modify: {
2521                 TypingCommand::closeTyping(part->lastEditCommand());
2522                 khtml::Selection s(part->selection());
2523                 khtml::Selection::EAlter alter = khtml::Selection::MOVE;
2524                 if (args[0].toString(exec).string().lower() == "extend")
2525                     alter = khtml::Selection::EXTEND;
2526                 DOMString directionString = args[1].toString(exec).string().lower();
2527                 khtml::Selection::EDirection direction = khtml::Selection::FORWARD;
2528                 if (directionString == "backward")
2529                     direction = khtml::Selection::BACKWARD;
2530                 else if (directionString == "left")
2531                     direction = khtml::Selection::LEFT;
2532                 if (directionString == "right")
2533                     direction = khtml::Selection::RIGHT;
2534                 khtml::ETextGranularity granularity = khtml::CHARACTER;
2535                 DOMString granularityString = args[2].toString(exec).string().lower();
2536                 if (granularityString == "word")
2537                     granularity = khtml::WORD;
2538                 else if (granularityString == "line")
2539                     granularity = khtml::LINE;
2540                 else if (granularityString == "pargraph")
2541                     granularity = khtml::PARAGRAPH;
2542                 s.modify(alter, direction, granularity);
2543                 part->setSelection(s);
2544                 part->setSelectionGranularity(granularity);
2545             }
2546         }
2547     }
2548
2549     return Undefined();
2550 }
2551
2552 ////////////////////// BarInfo Object ////////////////////////
2553
2554 const ClassInfo BarInfo::info = { "BarInfo", 0, 0, 0 };
2555 /*
2556 @begin BarInfoTable 1
2557   visible                BarInfo::Visible                        DontDelete|ReadOnly
2558 @end
2559 */
2560 BarInfo::BarInfo(ExecState *exec, KHTMLPart *p, Type barType) 
2561   : ObjectImp(exec->lexicalInterpreter()->builtinObjectPrototype())
2562   , m_part(p)
2563   , m_type(barType)
2564 {
2565 }
2566
2567 BarInfo::~BarInfo()
2568 {
2569 }
2570
2571 Value BarInfo::get(ExecState *exec, const Identifier &p) const
2572 {
2573   if (m_part.isNull())
2574     return Undefined();
2575   
2576   const HashEntry *entry = Lookup::findEntry(&BarInfoTable, p);
2577   if (entry && entry->value == Visible) {
2578     switch (m_type) {
2579     case Locationbar:
2580 #if APPLE_CHANGES
2581       return Boolean(KWQ(m_part)->locationbarVisible());
2582 #endif
2583     case Menubar: 
2584 #if APPLE_CHANGES
2585       return Boolean(KWQ(m_part)->locationbarVisible());
2586 #endif
2587     case Personalbar:
2588 #if APPLE_CHANGES
2589       return Boolean(KWQ(m_part)->personalbarVisible());
2590 #endif
2591     case Scrollbars: 
2592 #if APPLE_CHANGES
2593       return Boolean(KWQ(m_part)->scrollbarsVisible());
2594 #endif
2595     case Statusbar:
2596 #if APPLE_CHANGES
2597       return Boolean(KWQ(m_part)->statusbarVisible());
2598 #endif
2599     case Toolbar:
2600 #if APPLE_CHANGES
2601       return Boolean(KWQ(m_part)->toolbarVisible());
2602 #endif
2603     default:
2604       return Boolean(false);
2605     }
2606   }
2607   
2608   return Undefined();
2609 }
2610
2611 void BarInfo::put(ExecState *exec, const Identifier &p, const Value &v, int attr)
2612 {
2613 }
2614
2615 ////////////////////// History Object ////////////////////////
2616
2617 const ClassInfo History::info = { "History", 0, 0, 0 };
2618 /*
2619 @begin HistoryTable 4
2620   length        History::Length         DontDelete|ReadOnly
2621   back          History::Back           DontDelete|Function 0
2622   forward       History::Forward        DontDelete|Function 0
2623   go            History::Go             DontDelete|Function 1
2624 @end
2625 */
2626 IMPLEMENT_PROTOFUNC(HistoryFunc)
2627
2628 Value History::get(ExecState *exec, const Identifier &p) const
2629 {
2630   return lookupGet<HistoryFunc,History,ObjectImp>(exec,p,&HistoryTable,this);
2631 }
2632
2633 Value History::getValueProperty(ExecState *, int token) const
2634 {
2635   switch (token) {
2636   case Length:
2637   {
2638     KParts::BrowserExtension *ext = part->browserExtension();
2639     if ( !ext )
2640       return Number( 0 );
2641
2642     KParts::BrowserInterface *iface = ext->browserInterface();
2643     if ( !iface )
2644       return Number( 0 );
2645
2646     QVariant length = iface->property( "historyLength" );
2647
2648     if ( length.type() != QVariant::UInt )
2649       return Number( 0 );
2650
2651     return Number( length.toUInt() );
2652   }
2653   default:
2654     kdWarning() << "Unhandled token in History::getValueProperty : " << token << endl;
2655     return Undefined();
2656   }
2657 }
2658
2659 UString History::toString(ExecState *exec) const
2660 {
2661   return "[object History]";
2662 }
2663
2664 Value HistoryFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
2665 {
2666   if (!thisObj.inherits(&History::info)) {
2667     Object err = Error::create(exec,TypeError);
2668     exec->setException(err);
2669     return err;
2670   }
2671   History *history = static_cast<History *>(thisObj.imp());
2672
2673   int steps;
2674   switch (id) {
2675   case History::Back:
2676     steps = -1;
2677     break;
2678   case History::Forward:
2679     steps = 1;
2680     break;
2681   case History::Go:
2682     steps = args[0].toInt32(exec);
2683     break;
2684   default:
2685     return Undefined();
2686   }
2687
2688   history->part->scheduleHistoryNavigation(steps);
2689   return Undefined();
2690 }
2691
2692 /////////////////////////////////////////////////////////////////////////////
2693
2694 #ifdef Q_WS_QWS
2695
2696 const ClassInfo Konqueror::info = { "Konqueror", 0, 0, 0 };
2697
2698 bool Konqueror::hasProperty(ExecState *exec, const Identifier &p) const
2699 {
2700   if ( p.qstring().startsWith( "goHistory" ) ) return false;
2701
2702   return true;
2703 }
2704
2705 Value Konqueror::get(ExecState *exec, const Identifier &p) const
2706 {
2707   if ( p == "goHistory" || part->url().protocol() != "http" || part->url().host() != "localhost" )
2708     return Undefined();
2709
2710   KParts::BrowserExtension *ext = part->browserExtension();
2711   if ( ext ) {
2712     KParts::BrowserInterface *iface = ext->browserInterface();
2713     if ( iface ) {
2714       QVariant prop = iface->property( p.qstring().latin1() );
2715
2716       if ( prop.isValid() ) {
2717         switch( prop.type() ) {
2718         case QVariant::Int:
2719           return Number( prop.toInt() );
2720         case QVariant::String:
2721           return String( prop.toString() );
2722         default:
2723           break;
2724         }
2725       }
2726     }
2727   }
2728
2729   return /*Function*/( new KonquerorFunc(this, p.qstring().latin1() ) );
2730 }
2731
2732 Value KonquerorFunc::tryCall(ExecState *exec, Object &, const List &args)
2733 {
2734   KParts::BrowserExtension *ext = konqueror->part->browserExtension();
2735
2736   if(!ext)
2737     return Undefined();
2738
2739   KParts::BrowserInterface *iface = ext->browserInterface();
2740
2741   if ( !iface )
2742     return Undefined();
2743
2744   QCString n = m_name.data();
2745   n += "()";
2746   iface->callMethod( n.data(), QVariant() );
2747
2748   return Undefined();
2749 }
2750
2751 UString Konqueror::toString(ExecState *) const
2752 {
2753   return UString("[object Konqueror]");
2754 }
2755
2756 #endif
2757 /////////////////////////////////////////////////////////////////////////////
2758
2759 #include "kjs_window.moc"
2760