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