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