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