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