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