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