khtml Library API Documentation

kjs_dom.cpp

00001 // -*- c-basic-offset: 2 -*-
00002 /*
00003  *  This file is part of the KDE libraries
00004  *  Copyright (C) 2000 Harri Porten (porten@kde.org)
00005  *  Copyright (C) 2003 Apple Computer, Inc.
00006  *
00007  *  This library is free software; you can redistribute it and/or
00008  *  modify it under the terms of the GNU Library General Public
00009  *  License as published by the Free Software Foundation; either
00010  *  version 2 of the License, or (at your option) any later version.
00011  *
00012  *  This library is distributed in the hope that it will be useful,
00013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  *  Library General Public License for more details.
00016  *
00017  *  You should have received a copy of the GNU Library General Public
00018  *  License along with this library; if not, write to the Free Software
00019  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  */
00021 
00022 #include <khtmlview.h>
00023 #include "xml/dom2_eventsimpl.h"
00024 #include "rendering/render_canvas.h"
00025 #include "rendering/render_layer.h"
00026 #include "xml/dom_nodeimpl.h"
00027 #include "xml/dom_docimpl.h"
00028 #include "misc/htmltags.h" // ID_*
00029 #include "misc/htmlattrs.h" // ATTR_*
00030 #include "html/html_baseimpl.h"
00031 #include <kdebug.h>
00032 #include <khtml_part.h>
00033 
00034 #include "kjs_dom.h"
00035 #include "kjs_html.h"
00036 #include "kjs_css.h"
00037 #include "kjs_range.h"
00038 #include "kjs_traversal.h"
00039 #include "kjs_events.h"
00040 #include "kjs_views.h"
00041 #include "kjs_window.h"
00042 #include "dom/dom_exception.h"
00043 #include "kjs_dom.lut.h"
00044 #include "khtmlpart_p.h"
00045 
00046 using namespace KJS;
00047 
00048 // -------------------------------------------------------------------------
00049 /* Source for DOMNodeProtoTable.
00050 @begin DOMNodeProtoTable 13
00051   insertBefore  DOMNode::InsertBefore   DontDelete|Function 2
00052   replaceChild  DOMNode::ReplaceChild   DontDelete|Function 2
00053   removeChild   DOMNode::RemoveChild    DontDelete|Function 1
00054   appendChild   DOMNode::AppendChild    DontDelete|Function 1
00055   hasAttributes DOMNode::HasAttributes  DontDelete|Function 0
00056   hasChildNodes DOMNode::HasChildNodes  DontDelete|Function 0
00057   cloneNode DOMNode::CloneNode  DontDelete|Function 1
00058 # DOM2
00059   normalize DOMNode::Normalize  DontDelete|Function 0
00060   isSupported   DOMNode::IsSupported    DontDelete|Function 2
00061 # from the EventTarget interface
00062   addEventListener  DOMNode::AddEventListener   DontDelete|Function 3
00063   removeEventListener   DOMNode::RemoveEventListener    DontDelete|Function 3
00064   dispatchEvent     DOMNode::DispatchEvent  DontDelete|Function 1
00065 # IE extensions
00066   contains  DOMNode::Contains       DontDelete|Function 1
00067   insertAdjacentHTML    DOMNode::InsertAdjacentHTML DontDelete|Function 2
00068 # "DOM level 0" (from Gecko DOM reference; also in WinIE)
00069   item          DOMNode::Item           DontDelete|Function 1
00070 @end
00071 */
00072 DEFINE_PROTOTYPE("DOMNode",DOMNodeProto)
00073 IMPLEMENT_PROTOFUNC_DOM(DOMNodeProtoFunc)
00074 IMPLEMENT_PROTOTYPE(DOMNodeProto,DOMNodeProtoFunc)
00075 
00076 const ClassInfo DOMNode::info = { "Node", 0, &DOMNodeTable, 0 };
00077 
00078 DOMNode::DOMNode(ExecState *exec, const DOM::Node& n)
00079   : DOMObject(DOMNodeProto::self(exec)), node(n)
00080 {
00081 }
00082 
00083 DOMNode::DOMNode(const Object& proto, const DOM::Node& n)
00084   : DOMObject(proto), node(n)
00085 {
00086 }
00087 
00088 DOMNode::~DOMNode()
00089 {
00090   ScriptInterpreter::forgetDOMObject(node.handle());
00091 }
00092 
00093 bool DOMNode::toBoolean(ExecState *) const
00094 {
00095     return !node.isNull();
00096 }
00097 
00098 /* Source for DOMNodeTable.
00099 @begin DOMNodeTable 53
00100   nodeName  DOMNode::NodeName   DontDelete|ReadOnly
00101   nodeValue DOMNode::NodeValue  DontDelete
00102   nodeType  DOMNode::NodeType   DontDelete|ReadOnly
00103   parentNode    DOMNode::ParentNode DontDelete|ReadOnly
00104   parentElement DOMNode::ParentElement  DontDelete|ReadOnly
00105   childNodes    DOMNode::ChildNodes DontDelete|ReadOnly
00106   firstChild    DOMNode::FirstChild DontDelete|ReadOnly
00107   lastChild DOMNode::LastChild  DontDelete|ReadOnly
00108   previousSibling  DOMNode::PreviousSibling DontDelete|ReadOnly
00109   nextSibling   DOMNode::NextSibling    DontDelete|ReadOnly
00110   attributes    DOMNode::Attributes DontDelete|ReadOnly
00111   namespaceURI  DOMNode::NamespaceURI   DontDelete|ReadOnly
00112 # DOM2
00113   prefix    DOMNode::Prefix     DontDelete
00114   localName DOMNode::LocalName  DontDelete|ReadOnly
00115   ownerDocument DOMNode::OwnerDocument  DontDelete|ReadOnly
00116 # Event handlers
00117 # IE also has: onactivate, onbefore*, oncontextmenu, oncontrolselect, oncut,
00118 # ondeactivate, ondrag*, ondrop, onfocusin, onfocusout, onhelp, onmousewheel,
00119 # onmove*, onpaste, onpropertychange, onreadystatechange, onresizeend/start,
00120 # onselectionchange, onstop
00121   onabort   DOMNode::OnAbort        DontDelete
00122   onblur    DOMNode::OnBlur         DontDelete
00123   onchange  DOMNode::OnChange       DontDelete
00124   onclick   DOMNode::OnClick        DontDelete
00125   ondblclick    DOMNode::OnDblClick     DontDelete
00126   ondragdrop    DOMNode::OnDragDrop     DontDelete
00127   onerror   DOMNode::OnError        DontDelete
00128   onfocus   DOMNode::OnFocus            DontDelete
00129   onkeydown DOMNode::OnKeyDown      DontDelete
00130   onkeypress    DOMNode::OnKeyPress     DontDelete
00131   onkeyup   DOMNode::OnKeyUp        DontDelete
00132   onload    DOMNode::OnLoad         DontDelete
00133   onmousedown   DOMNode::OnMouseDown        DontDelete
00134   onmousemove   DOMNode::OnMouseMove        DontDelete
00135   onmouseout    DOMNode::OnMouseOut     DontDelete
00136   onmouseover   DOMNode::OnMouseOver        DontDelete
00137   onmouseup DOMNode::OnMouseUp      DontDelete
00138   onmove    DOMNode::OnMove         DontDelete
00139   onreset   DOMNode::OnReset        DontDelete
00140   onresize  DOMNode::OnResize       DontDelete
00141   onselect  DOMNode::OnSelect       DontDelete
00142   onsubmit  DOMNode::OnSubmit       DontDelete
00143   onunload  DOMNode::OnUnload       DontDelete
00144 # IE extensions
00145   offsetLeft    DOMNode::OffsetLeft     DontDelete|ReadOnly
00146   offsetTop DOMNode::OffsetTop      DontDelete|ReadOnly
00147   offsetWidth   DOMNode::OffsetWidth        DontDelete|ReadOnly
00148   offsetHeight  DOMNode::OffsetHeight       DontDelete|ReadOnly
00149   offsetParent  DOMNode::OffsetParent       DontDelete|ReadOnly
00150   clientWidth   DOMNode::ClientWidth        DontDelete|ReadOnly
00151   clientHeight  DOMNode::ClientHeight       DontDelete|ReadOnly
00152   scrollLeft    DOMNode::ScrollLeft     DontDelete
00153   scrollTop DOMNode::ScrollTop      DontDelete
00154   scrollWidth   DOMNode::ScrollWidth            DontDelete|ReadOnly
00155   scrollHeight  DOMNode::ScrollHeight           DontDelete|ReadOnly
00156   sourceIndex   DOMNode::SourceIndex        DontDelete|ReadOnly
00157 @end
00158 */
00159 Value DOMNode::tryGet(ExecState *exec, const Identifier &propertyName) const
00160 {
00161 #ifdef KJS_VERBOSE
00162   kdDebug(6070) << "DOMNode::tryGet " << propertyName.qstring() << endl;
00163 #endif
00164   return DOMObjectLookupGetValue<DOMNode, DOMObject>(exec, propertyName, &DOMNodeTable, this);
00165 }
00166 
00167 Value DOMNode::getValueProperty(ExecState *exec, int token) const
00168 {
00169   switch (token) {
00170   case NodeName:
00171     return String(node.nodeName());
00172   case NodeValue:
00173     return getString(node.nodeValue()); // initially null, per domts/level1/core/hc_documentcreateelement.html
00174   case NodeType:
00175     return Number((unsigned int)node.nodeType());
00176   case ParentNode:
00177     return getDOMNode(exec,node.parentNode());
00178   case ParentElement: // IE only apparently
00179     return getDOMNode(exec,node.parentNode());
00180   case ChildNodes:
00181     return getDOMNodeList(exec,node.childNodes());
00182   case FirstChild:
00183     return getDOMNode(exec,node.firstChild());
00184   case LastChild:
00185     return getDOMNode(exec,node.lastChild());
00186   case PreviousSibling:
00187     return getDOMNode(exec,node.previousSibling());
00188   case NextSibling:
00189     return getDOMNode(exec,node.nextSibling());
00190   case Attributes:
00191     return getDOMNamedNodeMap(exec,node.attributes());
00192   case NamespaceURI:
00193     return getString(node.namespaceURI()); // Moz returns null if not set (dom/namespaces.html)
00194   case Prefix:
00195     return getString(node.prefix());  // Moz returns null if not set (dom/namespaces.html)
00196   case LocalName:
00197     return getString(node.localName());  // Moz returns null if not set (dom/namespaces.html)
00198   case OwnerDocument:
00199     return getDOMNode(exec,node.ownerDocument());
00200   case OnAbort:
00201     return getListener(DOM::EventImpl::ABORT_EVENT);
00202   case OnBlur:
00203     return getListener(DOM::EventImpl::BLUR_EVENT);
00204   case OnChange:
00205     return getListener(DOM::EventImpl::CHANGE_EVENT);
00206   case OnClick:
00207     return getListener(DOM::EventImpl::KHTML_ECMA_CLICK_EVENT);
00208   case OnDblClick:
00209     return getListener(DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT);
00210   case OnDragDrop:
00211     return getListener(DOM::EventImpl::KHTML_DRAGDROP_EVENT);
00212   case OnError:
00213     return getListener(DOM::EventImpl::KHTML_ERROR_EVENT);
00214   case OnFocus:
00215     return getListener(DOM::EventImpl::FOCUS_EVENT);
00216   case OnKeyDown:
00217     return getListener(DOM::EventImpl::KEYDOWN_EVENT);
00218   case OnKeyPress:
00219     return getListener(DOM::EventImpl::KHTML_KEYPRESS_EVENT);
00220   case OnKeyUp:
00221     return getListener(DOM::EventImpl::KEYUP_EVENT);
00222   case OnLoad:
00223     return getListener(DOM::EventImpl::LOAD_EVENT);
00224   case OnMouseDown:
00225     return getListener(DOM::EventImpl::MOUSEDOWN_EVENT);
00226   case OnMouseMove:
00227     return getListener(DOM::EventImpl::MOUSEMOVE_EVENT);
00228   case OnMouseOut:
00229     return getListener(DOM::EventImpl::MOUSEOUT_EVENT);
00230   case OnMouseOver:
00231     return getListener(DOM::EventImpl::MOUSEOVER_EVENT);
00232   case OnMouseUp:
00233     return getListener(DOM::EventImpl::MOUSEUP_EVENT);
00234   case OnMove:
00235     return getListener(DOM::EventImpl::KHTML_MOVE_EVENT);
00236   case OnReset:
00237     return getListener(DOM::EventImpl::RESET_EVENT);
00238   case OnResize:
00239     return getListener(DOM::EventImpl::RESIZE_EVENT);
00240   case OnSelect:
00241     return getListener(DOM::EventImpl::SELECT_EVENT);
00242   case OnSubmit:
00243     return getListener(DOM::EventImpl::SUBMIT_EVENT);
00244   case OnUnload:
00245     return getListener(DOM::EventImpl::UNLOAD_EVENT);
00246   case SourceIndex: {
00247     // Retrieves the ordinal position of the object, in source order, as the object
00248     // appears in the document's all collection
00249     // i.e. document.all[n.sourceIndex] == n
00250     DOM::Document doc = node.ownerDocument();
00251     if (doc.isHTMLDocument()) {
00252       DOM::HTMLCollection all = static_cast<DOM::HTMLDocument>(doc).all();
00253       unsigned long i = 0;
00254       DOM::Node n = all.firstItem();
00255       for ( ; !n.isNull() && n != node; n = all.nextItem() )
00256         ++i;
00257       Q_ASSERT( !n.isNull() ); // node not in document.all !?
00258       return Number(i);
00259     }
00260   }
00261   default:
00262     // no DOM standard, found in IE only
00263 
00264     // Make sure our layout is up to date before we allow a query on these attributes.
00265     DOM::DocumentImpl* docimpl = node.handle()->getDocument();
00266     if (docimpl) {
00267       docimpl->updateLayout();
00268     }
00269 
00270     khtml::RenderObject *rend = node.handle()->renderer();
00271 
00272     switch (token) {
00273     case OffsetLeft:
00274       return rend ? static_cast<Value>( Number( rend->offsetLeft() ) ) : Undefined();
00275     case OffsetTop:
00276       return rend ? static_cast<Value>(  Number( rend->offsetTop() ) ) : Undefined();
00277     case OffsetWidth:
00278       return rend ? static_cast<Value>(  Number( rend->offsetWidth() ) ) : Undefined();
00279     case OffsetHeight:
00280       return rend ? static_cast<Value>(  Number( rend->offsetHeight() ) ) : Undefined();
00281     case OffsetParent:
00282     {
00283       khtml::RenderObject* par = rend ? rend->offsetParent() : 0;
00284       return getDOMNode( exec, par ? par->element() : 0 );
00285     }
00286     case ClientWidth:
00287       return rend ? static_cast<Value>( Number( rend->clientWidth() ) ) : Undefined();
00288     case ClientHeight:
00289       return rend ? static_cast<Value>( Number( rend->clientHeight() ) ) : Undefined();
00290     case ScrollWidth:
00291       return rend ? static_cast<Value>( Number(rend->scrollWidth()) ) : Undefined();
00292     case ScrollHeight:
00293       return rend ? static_cast<Value>( Number(rend->scrollHeight()) ) : Undefined();
00294     case ScrollLeft:
00295       return Number( rend && rend->layer() ? rend->layer()->scrollXOffset() : 0 );
00296     case ScrollTop:
00297       return Number( rend && rend->layer() ? rend->layer()->scrollYOffset() : 0 );
00298     default:
00299       kdDebug(6070) << "WARNING: Unhandled token in DOMNode::getValueProperty : " << token << endl;
00300       break;
00301     }
00302   }
00303   return Undefined();
00304 }
00305 
00306 
00307 void DOMNode::tryPut(ExecState *exec, const Identifier& propertyName, const Value& value, int attr)
00308 {
00309 #ifdef KJS_VERBOSE
00310   kdDebug(6070) << "DOMNode::tryPut " << propertyName.qstring() << endl;
00311 #endif
00312   DOMObjectLookupPut<DOMNode,DOMObject>(exec, propertyName, value, attr,
00313                                         &DOMNodeTable, this );
00314 }
00315 
00316 void DOMNode::putValueProperty(ExecState *exec, int token, const Value& value, int /*attr*/)
00317 {
00318   switch (token) {
00319   case NodeValue:
00320     node.setNodeValue(value.toString(exec).string());
00321     break;
00322   case Prefix:
00323     node.setPrefix(value.toString(exec).string());
00324     break;
00325   case OnAbort:
00326     setListener(exec,DOM::EventImpl::ABORT_EVENT,value);
00327     break;
00328   case OnBlur:
00329     setListener(exec,DOM::EventImpl::BLUR_EVENT,value);
00330     break;
00331   case OnChange:
00332     setListener(exec,DOM::EventImpl::CHANGE_EVENT,value);
00333     break;
00334   case OnClick:
00335     setListener(exec,DOM::EventImpl::KHTML_ECMA_CLICK_EVENT,value);
00336     break;
00337   case OnDblClick:
00338     setListener(exec,DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT,value);
00339     break;
00340   case OnDragDrop:
00341     setListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT,value);
00342     break;
00343   case OnError:
00344     setListener(exec,DOM::EventImpl::KHTML_ERROR_EVENT,value);
00345     break;
00346   case OnFocus:
00347     setListener(exec,DOM::EventImpl::FOCUS_EVENT,value);
00348     break;
00349   case OnKeyDown:
00350     setListener(exec,DOM::EventImpl::KEYDOWN_EVENT,value);
00351     break;
00352   case OnKeyPress:
00353     setListener(exec,DOM::EventImpl::KHTML_KEYPRESS_EVENT,value);
00354     break;
00355   case OnKeyUp:
00356     setListener(exec,DOM::EventImpl::KEYUP_EVENT,value);
00357     break;
00358   case OnLoad:
00359     setListener(exec,DOM::EventImpl::LOAD_EVENT,value);
00360     break;
00361   case OnMouseDown:
00362     setListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT,value);
00363     break;
00364   case OnMouseMove:
00365     setListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT,value);
00366     break;
00367   case OnMouseOut:
00368     setListener(exec,DOM::EventImpl::MOUSEOUT_EVENT,value);
00369     break;
00370   case OnMouseOver:
00371     setListener(exec,DOM::EventImpl::MOUSEOVER_EVENT,value);
00372     break;
00373   case OnMouseUp:
00374     setListener(exec,DOM::EventImpl::MOUSEUP_EVENT,value);
00375     break;
00376   case OnMove:
00377     setListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT,value);
00378     break;
00379   case OnReset:
00380     setListener(exec,DOM::EventImpl::RESET_EVENT,value);
00381     break;
00382   case OnResize:
00383     setListener(exec,DOM::EventImpl::RESIZE_EVENT,value);
00384     break;
00385   case OnSelect:
00386     setListener(exec,DOM::EventImpl::SELECT_EVENT,value);
00387     break;
00388   case OnSubmit:
00389     setListener(exec,DOM::EventImpl::SUBMIT_EVENT,value);
00390     break;
00391   case OnUnload:
00392     setListener(exec,DOM::EventImpl::UNLOAD_EVENT,value);
00393     break;
00394   case ScrollTop: {
00395     khtml::RenderObject *rend = node.handle() ? node.handle()->renderer() : 0L;
00396     if (rend && rend->layer() && rend->style()->hidesOverflow())
00397         rend->layer()->scrollToYOffset(value.toInt32(exec));
00398     break;
00399   }
00400   case ScrollLeft: {
00401     khtml::RenderObject *rend = node.handle() ? node.handle()->renderer() : 0L;
00402     if (rend && rend->layer() && rend->style()->hidesOverflow())
00403       rend->layer()->scrollToXOffset(value.toInt32(exec));
00404     break;
00405   }
00406   default:
00407     kdDebug(6070) << "WARNING: DOMNode::putValueProperty unhandled token " << token << endl;
00408   }
00409 }
00410 
00411 Value DOMNode::toPrimitive(ExecState *exec, Type /*preferred*/) const
00412 {
00413   if (node.isNull())
00414     return Null();
00415 
00416   return String(toString(exec));
00417 }
00418 
00419 UString DOMNode::toString(ExecState *) const
00420 {
00421   if (node.isNull())
00422     return "null";
00423   UString s;
00424 
00425   DOM::Element e = node;
00426   if ( !e.isNull() ) {
00427     s = e.nodeName().string();
00428   } else
00429     s = className(); // fallback
00430 
00431   return "[object " + s + "]";
00432 }
00433 
00434 void DOMNode::setListener(ExecState *exec, int eventId, const Value& func) const
00435 {
00436   node.handle()->setHTMLEventListener(eventId,Window::retrieveActive(exec)->getJSEventListener(func,true));
00437 }
00438 
00439 Value DOMNode::getListener(int eventId) const
00440 {
00441   DOM::EventListener *listener = node.handle()->getHTMLEventListener(eventId);
00442   JSEventListener *jsListener = static_cast<JSEventListener*>(listener);
00443   if ( jsListener && jsListener->listenerObjImp() )
00444     return jsListener->listenerObj();
00445   else
00446     return Null();
00447 }
00448 
00449 void DOMNode::pushEventHandlerScope(ExecState *, ScopeChain &) const
00450 {
00451 }
00452 
00453 Value DOMNodeProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
00454 {
00455   KJS_CHECK_THIS( DOMNode, thisObj );
00456   DOM::Node node = static_cast<DOMNode *>( thisObj.imp() )->toNode();
00457   switch (id) {
00458     case DOMNode::HasAttributes:
00459       return Boolean(node.hasAttributes());
00460     case DOMNode::HasChildNodes:
00461       return Boolean(node.hasChildNodes());
00462     case DOMNode::CloneNode:
00463       return getDOMNode(exec,node.cloneNode(args[0].toBoolean(exec)));
00464     case DOMNode::Normalize:
00465       node.normalize();
00466       return Undefined();
00467     case DOMNode::IsSupported:
00468       return Boolean(node.isSupported(args[0].toString(exec).string(),args[1].toString(exec).string()));
00469     case DOMNode::AddEventListener: {
00470         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
00471         node.addEventListener(args[0].toString(exec).string(),listener,args[2].toBoolean(exec));
00472         return Undefined();
00473     }
00474     case DOMNode::RemoveEventListener: {
00475         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
00476         node.removeEventListener(args[0].toString(exec).string(),listener,args[2].toBoolean(exec));
00477         return Undefined();
00478     }
00479     case DOMNode::DispatchEvent:
00480       return Boolean(node.dispatchEvent(toEvent(args[0])));
00481     case DOMNode::AppendChild:
00482       return getDOMNode(exec,node.appendChild(toNode(args[0])));
00483     case DOMNode::RemoveChild:
00484       return getDOMNode(exec,node.removeChild(toNode(args[0])));
00485     case DOMNode::InsertBefore:
00486       return getDOMNode(exec,node.insertBefore(toNode(args[0]), toNode(args[1])));
00487     case DOMNode::ReplaceChild:
00488       return getDOMNode(exec,node.replaceChild(toNode(args[0]), toNode(args[1])));
00489     case DOMNode::Contains:
00490     {
00491     DOM::Node other = toNode(args[0]);
00492     if (!other.isNull() && node.nodeType()==DOM::Node::ELEMENT_NODE)
00493     {
00494         DOM::NodeBaseImpl *impl = static_cast<DOM::NodeBaseImpl *>(node.handle());
00495         bool retval = other.handle()->isAncestor(impl);
00496         return Boolean(retval);
00497     }
00498         return Undefined();
00499     }
00500     case DOMNode::InsertAdjacentHTML:
00501     {
00502       // see http://www.faqts.com/knowledge_base/view.phtml/aid/5756 
00503       // and http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/insertAdjacentHTML.asp 
00504       Range range = node.ownerDocument().createRange();
00505 
00506       range.setStartBefore(node);
00507 
00508       DocumentFragment docFrag = range.createContextualFragment(args[1].toString(exec).string());
00509 
00510       DOMString where = args[0].toString(exec).string();
00511 
00512       if (where == "beforeBegin" || where == "BeforeBegin")
00513         node.parentNode().insertBefore(docFrag, node);
00514       else if (where == "afterBegin" || where == "AfterBegin")
00515         node.insertBefore(docFrag, node.firstChild());
00516       else if (where == "beforeEnd" || where == "BeforeEnd")
00517         return getDOMNode(exec, node.appendChild(docFrag));
00518       else if (where == "afterEnd" || where == "AfterEnd")
00519         if (!node.nextSibling().isNull())
00520       node.parentNode().insertBefore(docFrag, node.nextSibling());
00521     else
00522       node.parentNode().appendChild(docFrag);
00523 
00524       return Undefined();
00525     }
00526     case DOMNode::Item:
00527       return getDOMNode(exec, node.childNodes().item(static_cast<unsigned long>(args[0].toNumber(exec))));
00528   }
00529 
00530   return Undefined();
00531 }
00532 
00533 // -------------------------------------------------------------------------
00534 
00535 /*
00536 @begin DOMNodeListProtoTable 2
00537   item      DOMNodeList::Item       DontDelete|Function 1
00538 # IE extension (IE treats DOMNodeList like an HTMLCollection)
00539   namedItem DOMNodeList::NamedItem      DontDelete|Function 1
00540 @end
00541 */
00542 DEFINE_PROTOTYPE("DOMNodeList", DOMNodeListProto)
00543 IMPLEMENT_PROTOFUNC_DOM(DOMNodeListProtoFunc)
00544 IMPLEMENT_PROTOTYPE(DOMNodeListProto,DOMNodeListProtoFunc)
00545 
00546 const ClassInfo DOMNodeList::info = { "NodeList", 0, 0, 0 };
00547 
00548 DOMNodeList::DOMNodeList(ExecState *exec, const DOM::NodeList& l)
00549  : DOMObject(DOMNodeListProto::self(exec)), list(l) { }
00550 
00551 DOMNodeList::~DOMNodeList()
00552 {
00553   ScriptInterpreter::forgetDOMObject(list.handle());
00554 }
00555 
00556 // We have to implement hasProperty since we don't use a hashtable for 'length'
00557 // ## this breaks "for (..in..)" though.
00558 bool DOMNodeList::hasProperty(ExecState *exec, const Identifier &p) const
00559 {
00560   if (p == lengthPropertyName)
00561     return true;
00562   // ## missing: accept p if array index or item id...
00563   return ObjectImp::hasProperty(exec, p);
00564 }
00565 
00566 Value DOMNodeList::tryGet(ExecState *exec, const Identifier &p) const
00567 {
00568 #ifdef KJS_VERBOSE
00569   kdDebug(6070) << "DOMNodeList::tryGet " << p.ascii() << endl;
00570 #endif
00571   if (p == lengthPropertyName)
00572     return Number(list.length());
00573 
00574   // Look in the prototype (for functions) before assuming it's an item's name
00575   Object proto = Object::dynamicCast(prototype());
00576   if (!proto.isNull() && proto.hasProperty(exec,p))
00577     return proto.get(exec,p);
00578 
00579   Value result;
00580 
00581   // array index ?
00582   bool ok;
00583   long unsigned int idx = p.toULong(&ok);
00584   if (ok)
00585     result = getDOMNode(exec,list.item(idx));
00586   else {
00587     // Find by ID
00588     DOM::HTMLElement e;
00589     unsigned long l = list.length();
00590     bool found = false;
00591 
00592     for ( unsigned long i = 0; i < l; i++ )
00593       if ( ( e = list.item( i ) ).id() == p.string() ) {
00594         result = getDOMNode(exec, list.item( i ) );
00595         found = true;
00596         break;
00597       }
00598 
00599     if ( !found )
00600       result = ObjectImp::get(exec, p);
00601   }
00602 
00603   return result;
00604 }
00605 
00606 // Need to support both get and call, so that list[0] and list(0) work.
00607 Value DOMNodeList::call(ExecState *exec, Object &thisObj, const List &args)
00608 {
00609   // This code duplication is necessary, DOMNodeList isn't a DOMFunction
00610   Value val;
00611   try {
00612     val = tryCall(exec, thisObj, args);
00613   }
00614   // pity there's no way to distinguish between these in JS code
00615   catch (...) {
00616     Object err = Error::create(exec, GeneralError, "Exception from DOMNodeList");
00617     exec->setException(err);
00618   }
00619   return val;
00620 }
00621 
00622 Value DOMNodeList::tryCall(ExecState *exec, Object &, const List &args)
00623 {
00624   // Do not use thisObj here. See HTMLCollection.
00625   UString s = args[0].toString(exec);
00626 
00627   // index-based lookup?
00628   bool ok;
00629   unsigned int u = s.toULong(&ok);
00630   if (ok)
00631     return getDOMNode(exec,list.item(u));
00632 
00633   // try lookup by name
00634   // ### NodeList::namedItem() would be cool to have
00635   // ### do we need to support the same two arg overload as in HTMLCollection?
00636   Value result = tryGet(exec, Identifier(s));
00637 
00638   if (result.isValid())
00639     return result;
00640 
00641   return Undefined();
00642 }
00643 
00644 // Not a prototype class currently, but should probably be converted to one
00645 Value DOMNodeListProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
00646 {
00647   KJS_CHECK_THIS( KJS::DOMNodeList, thisObj );
00648   DOM::NodeList list = static_cast<DOMNodeList *>(thisObj.imp())->nodeList();
00649   switch (id) {
00650   case KJS::DOMNodeList::Item:
00651     return getDOMNode(exec, list.item(args[0].toInt32(exec)));
00652   case KJS::DOMNodeList::NamedItem:
00653   {
00654     // Not a real namedItem implementation like the one HTMLCollection has.
00655     // This is only an IE extension...
00656     DOM::HTMLElement e;
00657     unsigned long len = list.length();
00658     DOM::DOMString s = args[0].toString(exec).string();
00659 
00660     for ( unsigned long i = 0; i < len; i++ )
00661     {
00662       e = list.item( i );
00663       if ( !e.isNull() && (
00664              e.id() == s || static_cast<ElementImpl *>(e.handle())->getAttribute(ATTR_NAME) == s )
00665       )
00666       {
00667         return getDOMNode(exec, e );
00668       }
00669     }
00670     return Null(); // see HTMLCollection::NamedItem implementation
00671   }
00672   default:
00673     return Undefined();
00674   }
00675 }
00676 
00677 // -------------------------------------------------------------------------
00678 
00679 const ClassInfo DOMAttr::info = { "Attr", &DOMNode::info, &DOMAttrTable, 0 };
00680 
00681 /* Source for DOMAttrTable.
00682 @begin DOMAttrTable 5
00683   name      DOMAttr::Name       DontDelete|ReadOnly
00684   specified DOMAttr::Specified  DontDelete|ReadOnly
00685   value     DOMAttr::ValueProperty  DontDelete
00686   ownerElement  DOMAttr::OwnerElement   DontDelete|ReadOnly
00687 @end
00688 */
00689 Value DOMAttr::tryGet(ExecState *exec, const Identifier &propertyName) const
00690 {
00691 #ifdef KJS_VERBOSE
00692   kdDebug(6070) << "DOMAttr::tryGet " << propertyName.qstring() << endl;
00693 #endif
00694   return DOMObjectLookupGetValue<DOMAttr,DOMNode>(exec, propertyName,
00695                                                   &DOMAttrTable, this );
00696 }
00697 
00698 Value DOMAttr::getValueProperty(ExecState *exec, int token) const
00699 {
00700   switch (token) {
00701   case Name:
00702     return String(static_cast<DOM::Attr>(node).name());
00703   case Specified:
00704     return Boolean(static_cast<DOM::Attr>(node).specified());
00705   case ValueProperty:
00706     return String(static_cast<DOM::Attr>(node).value());
00707   case OwnerElement: // DOM2
00708     return getDOMNode(exec,static_cast<DOM::Attr>(node).ownerElement());
00709   }
00710   return Value(); // not reached
00711 }
00712 
00713 void DOMAttr::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
00714 {
00715 #ifdef KJS_VERBOSE
00716   kdDebug(6070) << "DOMAttr::tryPut " << propertyName.qstring() << endl;
00717 #endif
00718   DOMObjectLookupPut<DOMAttr,DOMNode>(exec, propertyName, value, attr,
00719                                       &DOMAttrTable, this );
00720 }
00721 
00722 void DOMAttr::putValueProperty(ExecState *exec, int token, const Value& value, int /*attr*/)
00723 {
00724   switch (token) {
00725   case ValueProperty:
00726     static_cast<DOM::Attr>(node).setValue(value.toString(exec).string());
00727     return;
00728   default:
00729     kdDebug(6070) << "WARNING: DOMAttr::putValueProperty unhandled token " << token << endl;
00730   }
00731 }
00732 
00733 // -------------------------------------------------------------------------
00734 
00735 /* Source for DOMDocumentProtoTable.
00736 @begin DOMDocumentProtoTable 23
00737   createElement   DOMDocument::CreateElement                   DontDelete|Function 1
00738   createDocumentFragment DOMDocument::CreateDocumentFragment   DontDelete|Function 1
00739   createTextNode  DOMDocument::CreateTextNode                  DontDelete|Function 1
00740   createComment   DOMDocument::CreateComment                   DontDelete|Function 1
00741   createCDATASection DOMDocument::CreateCDATASection           DontDelete|Function 1
00742   createProcessingInstruction DOMDocument::CreateProcessingInstruction DontDelete|Function 1
00743   createAttribute DOMDocument::CreateAttribute                 DontDelete|Function 1
00744   createEntityReference DOMDocument::CreateEntityReference     DontDelete|Function 1
00745   getElementsByTagName  DOMDocument::GetElementsByTagName      DontDelete|Function 1
00746   importNode           DOMDocument::ImportNode                 DontDelete|Function 2
00747   createElementNS      DOMDocument::CreateElementNS            DontDelete|Function 2
00748   createAttributeNS    DOMDocument::CreateAttributeNS          DontDelete|Function 2
00749   getElementsByTagNameNS  DOMDocument::GetElementsByTagNameNS  DontDelete|Function 2
00750   getElementById     DOMDocument::GetElementById               DontDelete|Function 1
00751   createRange        DOMDocument::CreateRange                  DontDelete|Function 0
00752   createNodeIterator DOMDocument::CreateNodeIterator           DontDelete|Function 3
00753   createTreeWalker   DOMDocument::CreateTreeWalker             DontDelete|Function 4
00754   createEvent        DOMDocument::CreateEvent                  DontDelete|Function 1
00755   getOverrideStyle   DOMDocument::GetOverrideStyle             DontDelete|Function 2
00756   abort              DOMDocument::Abort                        DontDelete|Function 0
00757   load               DOMDocument::Load                         DontDelete|Function 1
00758   loadXML            DOMDocument::LoadXML                      DontDelete|Function 2
00759 @end
00760 */
00761 DEFINE_PROTOTYPE("DOMDocument", DOMDocumentProto)
00762 IMPLEMENT_PROTOFUNC_DOM(DOMDocumentProtoFunc)
00763 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMDocumentProto, DOMDocumentProtoFunc, DOMNodeProto)
00764 
00765 const ClassInfo DOMDocument::info = { "Document", &DOMNode::info, &DOMDocumentTable, 0 };
00766 
00767 /* Source for DOMDocumentTable.
00768 @begin DOMDocumentTable 4
00769   doctype         DOMDocument::DocType                         DontDelete|ReadOnly
00770   implementation  DOMDocument::Implementation                  DontDelete|ReadOnly
00771   documentElement DOMDocument::DocumentElement                 DontDelete|ReadOnly
00772   styleSheets     DOMDocument::StyleSheets                     DontDelete|ReadOnly
00773   preferredStylesheetSet  DOMDocument::PreferredStylesheetSet  DontDelete|ReadOnly
00774   selectedStylesheetSet  DOMDocument::SelectedStylesheetSet    DontDelete
00775   readyState      DOMDocument::ReadyState                      DontDelete|ReadOnly
00776   defaultView     DOMDocument::DefaultView                     DontDelete|ReadOnly
00777   async           DOMDocument::Async                           DontDelete
00778 @end
00779 */
00780 
00781 DOMDocument::DOMDocument(ExecState *exec, const DOM::Document& d)
00782   : DOMNode(DOMDocumentProto::self(exec), d) { }
00783 
00784 DOMDocument::DOMDocument(const Object& proto, const DOM::Document& d)
00785   : DOMNode(proto, d) { }
00786 
00787 DOMDocument::~DOMDocument()
00788 {
00789   ScriptInterpreter::forgetDOMObject(node.handle());
00790 }
00791 
00792 Value DOMDocument::tryGet(ExecState *exec, const Identifier &propertyName) const
00793 {
00794 #ifdef KJS_VERBOSE
00795   kdDebug(6070) << "DOMDocument::tryGet " << propertyName.qstring() << endl;
00796 #endif
00797   return DOMObjectLookupGetValue<DOMDocument, DOMNode>(
00798     exec, propertyName, &DOMDocumentTable, this);
00799 }
00800 
00801 Value DOMDocument::getValueProperty(ExecState *exec, int token) const
00802 {
00803   DOM::Document doc = static_cast<DOM::Document>(node);
00804 
00805   switch(token) {
00806   case DocType:
00807     return getDOMNode(exec,doc.doctype());
00808   case Implementation:
00809     return getDOMDOMImplementation(exec,doc.implementation());
00810   case DocumentElement:
00811     return getDOMNode(exec,doc.documentElement());
00812   case StyleSheets:
00813     //kdDebug() << "DOMDocument::StyleSheets, returning " << doc.styleSheets().length() << " stylesheets" << endl;
00814     return getDOMStyleSheetList(exec, doc.styleSheets(), doc);
00815   case DOMDocument::DefaultView: // DOM2
00816     return getDOMAbstractView(exec, doc.defaultView());
00817   case PreferredStylesheetSet:
00818     return String(doc.preferredStylesheetSet());
00819   case SelectedStylesheetSet:
00820     return String(doc.selectedStylesheetSet());
00821   case ReadyState:
00822     {
00823     DOM::DocumentImpl* docimpl = node.handle()->getDocument();
00824     if ( docimpl && docimpl->view() )
00825     {
00826       KHTMLPart* part = docimpl->view()->part();
00827       if ( part ) {
00828         if (part->d->m_bComplete) return String("complete");
00829         if (docimpl->parsing()) return String("loading");
00830         return String("loaded");
00831         // What does the interactive value mean ?
00832         // Missing support for "uninitialized"
00833       }
00834     }
00835     return Undefined();
00836     }
00837   case Async:
00838     return Boolean(doc.async());
00839   default:
00840     kdDebug(6070) << "WARNING: DOMDocument::getValueProperty unhandled token " << token << endl;
00841     return Value();
00842   }
00843 }
00844 
00845 void DOMDocument::tryPut(ExecState *exec, const Identifier& propertyName, const Value& value, int attr)
00846 {
00847 #ifdef KJS_VERBOSE
00848   kdDebug(6070) << "DOMDocument::tryPut " << propertyName.qstring() << endl;
00849 #endif
00850   DOMObjectLookupPut<DOMDocument,DOMNode>(exec, propertyName, value, attr, &DOMDocumentTable, this );
00851 }
00852 
00853 void DOMDocument::putValueProperty(ExecState *exec, int token, const Value& value, int /*attr*/)
00854 {
00855   DOM::Document doc = static_cast<DOM::Document>(node);
00856   switch (token) {
00857     case SelectedStylesheetSet: {
00858       doc.setSelectedStylesheetSet(value.toString(exec).string());
00859       break;
00860     }
00861     case Async: {
00862       doc.setAsync(value.toBoolean(exec));
00863       break;
00864     }
00865   }
00866 }
00867 
00868 Value DOMDocumentProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
00869 {
00870   KJS_CHECK_THIS( KJS::DOMDocument, thisObj );
00871   DOM::Node node = static_cast<DOMNode *>( thisObj.imp() )->toNode();
00872   DOM::Document doc = static_cast<DOM::Document>(node);
00873   String str = args[0].toString(exec);
00874   DOM::DOMString s = str.value().string();
00875 
00876   switch(id) {
00877   case DOMDocument::CreateElement:
00878     return getDOMNode(exec,doc.createElement(s));
00879   case DOMDocument::CreateDocumentFragment:
00880     return getDOMNode(exec,doc.createDocumentFragment());
00881   case DOMDocument::CreateTextNode:
00882     return getDOMNode(exec,doc.createTextNode(s));
00883   case DOMDocument::CreateComment:
00884     return getDOMNode(exec,doc.createComment(s));
00885   case DOMDocument::CreateCDATASection:
00886     return getDOMNode(exec,doc.createCDATASection(s));  /* TODO: okay ? */
00887   case DOMDocument::CreateProcessingInstruction:
00888     return getDOMNode(exec,doc.createProcessingInstruction(args[0].toString(exec).string(),
00889                                                                  args[1].toString(exec).string()));
00890   case DOMDocument::CreateAttribute:
00891     return getDOMNode(exec,doc.createAttribute(s));
00892   case DOMDocument::CreateEntityReference:
00893     return getDOMNode(exec,doc.createEntityReference(args[0].toString(exec).string()));
00894   case DOMDocument::GetElementsByTagName:
00895     return getDOMNodeList(exec,doc.getElementsByTagName(s));
00896   case DOMDocument::ImportNode: // DOM2
00897     return getDOMNode(exec,doc.importNode(toNode(args[0]), args[1].toBoolean(exec)));
00898   case DOMDocument::CreateElementNS: // DOM2
00899     return getDOMNode(exec,doc.createElementNS(args[0].toString(exec).string(), args[1].toString(exec).string()));
00900   case DOMDocument::CreateAttributeNS: // DOM2
00901     return getDOMNode(exec,doc.createAttributeNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
00902   case DOMDocument::GetElementsByTagNameNS: // DOM2
00903     return getDOMNodeList(exec,doc.getElementsByTagNameNS(args[0].toString(exec).string(),
00904                                                           args[1].toString(exec).string()));
00905   case DOMDocument::GetElementById:
00906 #ifdef KJS_VERBOSE
00907   kdDebug(6070) << "DOMDocument::GetElementById looking for " << args[0].toString(exec).string() << endl;
00908 #endif
00909     return getDOMNode(exec,doc.getElementById(args[0].toString(exec).string()));
00910   case DOMDocument::CreateRange:
00911     return getDOMRange(exec,doc.createRange());
00912   case DOMDocument::CreateNodeIterator:
00913     if (args[2].isA(NullType)) {
00914         DOM::NodeFilter filter;
00915         return getDOMNodeIterator(exec,
00916                                   doc.createNodeIterator(toNode(args[0]),
00917                                                          (long unsigned int)(args[1].toNumber(exec)),
00918                                                          filter,args[3].toBoolean(exec)));
00919     }
00920     else {
00921       Object obj = Object::dynamicCast(args[2]);
00922       if (!obj.isNull())
00923       {
00924         DOM::CustomNodeFilter *customFilter = new JSNodeFilter(obj);
00925         DOM::NodeFilter filter = DOM::NodeFilter::createCustom(customFilter);
00926         return getDOMNodeIterator(exec,
00927           doc.createNodeIterator(
00928             toNode(args[0]),(long unsigned int)(args[1].toNumber(exec)),
00929             filter,args[3].toBoolean(exec)));
00930       }// else?
00931     }
00932   case DOMDocument::CreateTreeWalker:
00933     return getDOMTreeWalker(exec,doc.createTreeWalker(toNode(args[0]),(long unsigned int)(args[1].toNumber(exec)),
00934              toNodeFilter(args[2]),args[3].toBoolean(exec)));
00935   case DOMDocument::CreateEvent:
00936     return getDOMEvent(exec,doc.createEvent(s));
00937   case DOMDocument::GetOverrideStyle: {
00938     DOM::Node arg0 = toNode(args[0]);
00939     if (arg0.nodeType() != DOM::Node::ELEMENT_NODE)
00940       return Undefined(); // throw exception?
00941     else
00942       return getDOMCSSStyleDeclaration(exec,doc.getOverrideStyle(static_cast<DOM::Element>(arg0),args[1].toString(exec).string()));
00943   }
00944   case DOMDocument::Abort:
00945     doc.abort();
00946     break;
00947   case DOMDocument::Load: {
00948     Window* active = Window::retrieveActive(exec);
00949     // Complete the URL using the "active part" (running interpreter). We do this for the security
00950     // check and to make sure we load exactly the same url as we have verified to be safe
00951     KHTMLPart *khtmlpart = ::qt_cast<KHTMLPart *>(active->part());
00952     if (khtmlpart) {
00953       // Security: only allow documents to be loaded from the same host
00954       QString dstUrl = khtmlpart->htmlDocument().completeURL(s).string();
00955       KParts::ReadOnlyPart *part = static_cast<KJS::ScriptInterpreter*>(exec->interpreter())->part();
00956       if (part->url().host() == KURL(dstUrl).host()) {
00957     kdDebug(6070) << "JavaScript: access granted for document.load() of " << dstUrl << endl;
00958     doc.load(dstUrl);
00959       }
00960       else {
00961     kdDebug(6070) << "JavaScript: access denied for document.load() of " << dstUrl << endl;
00962       }
00963     }
00964     break;
00965   }
00966   case DOMDocument::LoadXML:
00967     doc.loadXML(s);
00968     break;
00969   default:
00970     break;
00971   }
00972 
00973   return Undefined();
00974 }
00975 
00976 // -------------------------------------------------------------------------
00977 
00978 /* Source for DOMElementProtoTable.
00979 @begin DOMElementProtoTable 17
00980   getAttribute      DOMElement::GetAttribute    DontDelete|Function 1
00981   setAttribute      DOMElement::SetAttribute    DontDelete|Function 2
00982   removeAttribute   DOMElement::RemoveAttribute DontDelete|Function 1
00983   getAttributeNode  DOMElement::GetAttributeNode    DontDelete|Function 1
00984   setAttributeNode  DOMElement::SetAttributeNode    DontDelete|Function 2
00985   removeAttributeNode   DOMElement::RemoveAttributeNode DontDelete|Function 1
00986   getElementsByTagName  DOMElement::GetElementsByTagName    DontDelete|Function 1
00987   hasAttribute      DOMElement::HasAttribute    DontDelete|Function 1
00988   getAttributeNS    DOMElement::GetAttributeNS  DontDelete|Function 2
00989   setAttributeNS    DOMElement::SetAttributeNS  DontDelete|Function 3
00990   removeAttributeNS DOMElement::RemoveAttributeNS   DontDelete|Function 2
00991   getAttributeNodeNS    DOMElement::GetAttributeNodeNS  DontDelete|Function 2
00992   setAttributeNodeNS    DOMElement::SetAttributeNodeNS  DontDelete|Function 1
00993   getElementsByTagNameNS DOMElement::GetElementsByTagNameNS DontDelete|Function 2
00994   hasAttributeNS    DOMElement::HasAttributeNS  DontDelete|Function 2
00995 @end
00996 */
00997 DEFINE_PROTOTYPE("DOMElement",DOMElementProto)
00998 IMPLEMENT_PROTOFUNC_DOM(DOMElementProtoFunc)
00999 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMElementProto,DOMElementProtoFunc,DOMNodeProto)
01000 
01001 const ClassInfo DOMElement::info = { "Element", &DOMNode::info, &DOMElementTable, 0 };
01002 /* Source for DOMElementTable.
01003 @begin DOMElementTable 3
01004   tagName   DOMElement::TagName                         DontDelete|ReadOnly
01005   style     DOMElement::Style                           DontDelete|ReadOnly
01006 @end
01007 */
01008 DOMElement::DOMElement(ExecState *exec, const DOM::Element& e)
01009   : DOMNode(DOMElementProto::self(exec), e) { }
01010 
01011 DOMElement::DOMElement(const Object& proto, const DOM::Element& e)
01012   : DOMNode(proto, e) { }
01013 
01014 Value DOMElement::tryGet(ExecState *exec, const Identifier &propertyName) const
01015 {
01016 #ifdef KJS_VERBOSE
01017   kdDebug(6070) << "DOMElement::tryGet " << propertyName.qstring() << endl;
01018 #endif
01019   DOM::Element element = static_cast<DOM::Element>(node);
01020 
01021   const HashEntry* entry = Lookup::findEntry(&DOMElementTable, propertyName);
01022   if (entry)
01023   {
01024     switch( entry->value ) {
01025     case TagName:
01026       return String(element.tagName());
01027     case Style:
01028       return getDOMCSSStyleDeclaration(exec,element.style());
01029     default:
01030       kdDebug(6070) << "WARNING: Unhandled token in DOMElement::tryGet : " << entry->value << endl;
01031       break;
01032     }
01033   }
01034   // We have to check in DOMNode before giving access to attributes, otherwise
01035   // onload="..." would make onload return the string (attribute value) instead of
01036   // the listener object (function).
01037   if (DOMNode::hasProperty(exec, propertyName))
01038     return DOMNode::tryGet(exec, propertyName);
01039 
01040   DOM::DOMString attr = element.getAttribute( propertyName.string() );
01041   // Give access to attributes
01042   if ( !attr.isNull() )
01043     return String( attr );
01044 
01045   return Undefined();
01046 }
01047 
01048 Value DOMElementProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
01049 {
01050   KJS_CHECK_THIS( KJS::DOMNode, thisObj ); // node should be enough here, given the cast
01051   DOM::Node node = static_cast<DOMNode *>( thisObj.imp() )->toNode();
01052   DOM::Element element = static_cast<DOM::Element>(node);
01053 
01054   switch(id) {
01055     case DOMElement::GetAttribute:
01056       return String(element.getAttribute(args[0].toString(exec).string()));
01057     case DOMElement::SetAttribute:
01058       element.setAttribute(args[0].toString(exec).string(),args[1].toString(exec).string());
01059       return Undefined();
01060     case DOMElement::RemoveAttribute:
01061       element.removeAttribute(args[0].toString(exec).string());
01062       return Undefined();
01063     case DOMElement::GetAttributeNode:
01064       return getDOMNode(exec,element.getAttributeNode(args[0].toString(exec).string()));
01065     case DOMElement::SetAttributeNode:
01066       return getDOMNode(exec,element.setAttributeNode((new DOMNode(exec,KJS::toNode(args[0])))->toNode()));
01067     case DOMElement::RemoveAttributeNode:
01068       return getDOMNode(exec,element.removeAttributeNode((new DOMNode(exec,KJS::toNode(args[0])))->toNode()));
01069     case DOMElement::GetElementsByTagName:
01070       return getDOMNodeList(exec,element.getElementsByTagName(args[0].toString(exec).string()));
01071     case DOMElement::HasAttribute: // DOM2
01072       return Boolean(element.hasAttribute(args[0].toString(exec).string()));
01073     case DOMElement::GetAttributeNS: // DOM2
01074       return String(element.getAttributeNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
01075     case DOMElement::SetAttributeNS: // DOM2
01076       element.setAttributeNS(args[0].toString(exec).string(),args[1].toString(exec).string(),args[2].toString(exec).string());
01077       return Undefined();
01078     case DOMElement::RemoveAttributeNS: // DOM2
01079       element.removeAttributeNS(args[0].toString(exec).string(),args[1].toString(exec).string());
01080       return Undefined();
01081     case DOMElement::GetAttributeNodeNS: // DOM2
01082       return getDOMNode(exec,element.getAttributeNodeNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
01083     case DOMElement::SetAttributeNodeNS: // DOM2
01084       return getDOMNode(exec,element.setAttributeNodeNS((new DOMNode(exec,KJS::toNode(args[0])))->toNode()));
01085     case DOMElement::GetElementsByTagNameNS: // DOM2
01086       return getDOMNodeList(exec,element.getElementsByTagNameNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
01087     case DOMElement::HasAttributeNS: // DOM2
01088       return Boolean(element.hasAttributeNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
01089   default:
01090     return Undefined();
01091   }
01092 }
01093 
01094 // -------------------------------------------------------------------------
01095 
01096 /* Source for DOMDOMImplementationProtoTable.
01097 @begin DOMDOMImplementationProtoTable 5
01098   hasFeature        DOMDOMImplementation::HasFeature        DontDelete|Function 2
01099   createCSSStyleSheet   DOMDOMImplementation::CreateCSSStyleSheet   DontDelete|Function 2
01100 # DOM2
01101   createDocumentType    DOMDOMImplementation::CreateDocumentType    DontDelete|Function 3
01102   createDocument    DOMDOMImplementation::CreateDocument        DontDelete|Function 3
01103   createHTMLDocument    DOMDOMImplementation::CreateHTMLDocument        DontDelete|Function 1
01104 @end
01105 */
01106 DEFINE_PROTOTYPE("DOMImplementation",DOMDOMImplementationProto)
01107 IMPLEMENT_PROTOFUNC_DOM(DOMDOMImplementationProtoFunc)
01108 IMPLEMENT_PROTOTYPE(DOMDOMImplementationProto,DOMDOMImplementationProtoFunc)
01109 
01110 const ClassInfo DOMDOMImplementation::info = { "DOMImplementation", 0, 0, 0 };
01111 
01112 DOMDOMImplementation::DOMDOMImplementation(ExecState *exec, const DOM::DOMImplementation& i)
01113   : DOMObject(DOMDOMImplementationProto::self(exec)), implementation(i) { }
01114 
01115 DOMDOMImplementation::~DOMDOMImplementation()
01116 {
01117   ScriptInterpreter::forgetDOMObject(implementation.handle());
01118 }
01119 
01120 Value DOMDOMImplementationProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
01121 {
01122   KJS_CHECK_THIS( KJS::DOMDOMImplementation, thisObj );
01123   DOM::DOMImplementation implementation = static_cast<DOMDOMImplementation *>( thisObj.imp() )->toImplementation();
01124 
01125   switch(id) {
01126   case DOMDOMImplementation::HasFeature:
01127     return Boolean(implementation.hasFeature(args[0].toString(exec).string(),args[1].toString(exec).string()));
01128   case DOMDOMImplementation::CreateDocumentType: // DOM2
01129     return getDOMNode(exec,implementation.createDocumentType(args[0].toString(exec).string(),args[1].toString(exec).string(),args[2].toString(exec).string()));
01130   case DOMDOMImplementation::CreateDocument: { // DOM2
01131     // Initially set the URL to document of the creator... this is so that it resides in the same
01132     // host/domain for security checks. The URL will be updated if Document.load() is called.
01133     KHTMLPart *part = ::qt_cast<KHTMLPart*>(static_cast<KJS::ScriptInterpreter*>(exec->interpreter())->part());
01134     if (part) {
01135       Document doc = implementation.createDocument(args[0].toString(exec).string(),args[1].toString(exec).string(),toNode(args[2]));
01136       KURL url = static_cast<DocumentImpl*>(part->document().handle())->URL();
01137       static_cast<DocumentImpl*>(doc.handle())->setURL(url.url());
01138       return getDOMNode(exec,doc);
01139     }
01140     break;
01141   }
01142   case DOMDOMImplementation::CreateCSSStyleSheet: // DOM2
01143     return getDOMStyleSheet(exec,implementation.createCSSStyleSheet(args[0].toString(exec).string(),args[1].toString(exec).string()));
01144   case DOMDOMImplementation::CreateHTMLDocument: // DOM2-HTML
01145     return getDOMNode(exec, implementation.createHTMLDocument(args[0].toString(exec).string()));
01146   default:
01147     break;
01148   }
01149   return Undefined();
01150 }
01151 
01152 // -------------------------------------------------------------------------
01153 
01154 const ClassInfo DOMDocumentType::info = { "DocumentType", &DOMNode::info, &DOMDocumentTypeTable, 0 };
01155 
01156 /* Source for DOMDocumentTypeTable.
01157 @begin DOMDocumentTypeTable 6
01158   name          DOMDocumentType::Name       DontDelete|ReadOnly
01159   entities      DOMDocumentType::Entities   DontDelete|ReadOnly
01160   notations     DOMDocumentType::Notations  DontDelete|ReadOnly
01161 # DOM2
01162   publicId      DOMDocumentType::PublicId   DontDelete|ReadOnly
01163   systemId      DOMDocumentType::SystemId   DontDelete|ReadOnly
01164   internalSubset    DOMDocumentType::InternalSubset DontDelete|ReadOnly
01165 @end
01166 */
01167 DOMDocumentType::DOMDocumentType(ExecState *exec, const DOM::DocumentType& dt)
01168   : DOMNode( /*### no proto yet*/exec, dt ) { }
01169 
01170 Value DOMDocumentType::tryGet(ExecState *exec, const Identifier &propertyName) const
01171 {
01172 #ifdef KJS_VERBOSE
01173   kdDebug(6070) << "DOMDocumentType::tryGet " << propertyName.qstring() << endl;
01174 #endif
01175   return DOMObjectLookupGetValue<DOMDocumentType, DOMNode>(exec, propertyName, &DOMDocumentTypeTable, this);
01176 }
01177 
01178 Value DOMDocumentType::getValueProperty(ExecState *exec, int token) const
01179 {
01180   DOM::DocumentType type = static_cast<DOM::DocumentType>(node);
01181   switch (token) {
01182   case Name:
01183     return String(type.name());
01184   case Entities:
01185     return getDOMNamedNodeMap(exec,type.entities());
01186   case Notations:
01187     return getDOMNamedNodeMap(exec,type.notations());
01188   case PublicId: // DOM2
01189     return String(type.publicId());
01190   case SystemId: // DOM2
01191     return String(type.systemId());
01192   case InternalSubset: // DOM2
01193     return getString(type.internalSubset()); // can be null, see domts/level2/core/internalSubset01.html
01194   default:
01195     kdDebug(6070) << "WARNING: DOMDocumentType::getValueProperty unhandled token " << token << endl;
01196     return Value();
01197   }
01198 }
01199 
01200 // -------------------------------------------------------------------------
01201 
01202 /* Source for DOMNamedNodeMapProtoTable.
01203 @begin DOMNamedNodeMapProtoTable 7
01204   getNamedItem      DOMNamedNodeMap::GetNamedItem       DontDelete|Function 1
01205   setNamedItem      DOMNamedNodeMap::SetNamedItem       DontDelete|Function 1
01206   removeNamedItem   DOMNamedNodeMap::RemoveNamedItem    DontDelete|Function 1
01207   item          DOMNamedNodeMap::Item           DontDelete|Function 1
01208 # DOM2
01209   getNamedItemNS    DOMNamedNodeMap::GetNamedItemNS     DontDelete|Function 2
01210   setNamedItemNS    DOMNamedNodeMap::SetNamedItemNS     DontDelete|Function 1
01211   removeNamedItemNS DOMNamedNodeMap::RemoveNamedItemNS  DontDelete|Function 2
01212 @end
01213 */
01214 DEFINE_PROTOTYPE("NamedNodeMap", DOMNamedNodeMapProto)
01215 IMPLEMENT_PROTOFUNC_DOM(DOMNamedNodeMapProtoFunc)
01216 IMPLEMENT_PROTOTYPE(DOMNamedNodeMapProto,DOMNamedNodeMapProtoFunc)
01217 
01218 const ClassInfo DOMNamedNodeMap::info = { "NamedNodeMap", 0, 0, 0 };
01219 
01220 DOMNamedNodeMap::DOMNamedNodeMap(ExecState *exec, const DOM::NamedNodeMap& m)
01221   : DOMObject(DOMNamedNodeMapProto::self(exec)), map(m) { }
01222 
01223 DOMNamedNodeMap::~DOMNamedNodeMap()
01224 {
01225   ScriptInterpreter::forgetDOMObject(map.handle());
01226 }
01227 
01228 // We have to implement hasProperty since we don't use a hashtable for 'length'
01229 // ## this breaks "for (..in..)" though.
01230 bool DOMNamedNodeMap::hasProperty(ExecState *exec, const Identifier &p) const
01231 {
01232   if (p == lengthPropertyName)
01233     return true;
01234   // ## missing? array index
01235   return DOMObject::hasProperty(exec, p);
01236 }
01237 
01238 Value DOMNamedNodeMap::tryGet(ExecState* exec, const Identifier &p) const
01239 {
01240   if (p == lengthPropertyName)
01241     return Number(map.length());
01242 
01243   // array index ?
01244   bool ok;
01245   long unsigned int idx = p.toULong(&ok);
01246   if (ok)
01247     return getDOMNode(exec,map.item(idx));
01248 
01249   // Anything else (including functions, defined in the prototype)
01250   return DOMObject::tryGet(exec, p);
01251 }
01252 
01253 Value DOMNamedNodeMapProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
01254 {
01255   KJS_CHECK_THIS( KJS::DOMNamedNodeMap, thisObj );
01256   DOM::NamedNodeMap map = static_cast<DOMNamedNodeMap *>(thisObj.imp())->toMap();
01257 
01258   switch(id) {
01259     case DOMNamedNodeMap::GetNamedItem:
01260       return getDOMNode(exec, map.getNamedItem(args[0].toString(exec).string()));
01261     case DOMNamedNodeMap::SetNamedItem:
01262       return getDOMNode(exec, map.setNamedItem((new DOMNode(exec,KJS::toNode(args[0])))->toNode()));
01263     case DOMNamedNodeMap::RemoveNamedItem:
01264       return getDOMNode(exec, map.removeNamedItem(args[0].toString(exec).string()));
01265     case DOMNamedNodeMap::Item:
01266       return getDOMNode(exec, map.item(args[0].toInt32(exec)));
01267     case DOMNamedNodeMap::GetNamedItemNS: // DOM2
01268       return getDOMNode(exec, map.getNamedItemNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
01269     case DOMNamedNodeMap::SetNamedItemNS: // DOM2
01270       return getDOMNode(exec, map.setNamedItemNS(toNode(args[0])));
01271     case DOMNamedNodeMap::RemoveNamedItemNS: // DOM2
01272       return getDOMNode(exec, map.removeNamedItemNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
01273     default:
01274       break;
01275   }
01276 
01277   return Undefined();
01278 }
01279 
01280 // -------------------------------------------------------------------------
01281 
01282 const ClassInfo DOMProcessingInstruction::info = { "ProcessingInstruction", &DOMNode::info, &DOMProcessingInstructionTable, 0 };
01283 
01284 /* Source for DOMProcessingInstructionTable.
01285 @begin DOMProcessingInstructionTable 3
01286   target    DOMProcessingInstruction::Target    DontDelete|ReadOnly
01287   data      DOMProcessingInstruction::Data      DontDelete
01288   sheet     DOMProcessingInstruction::Sheet     DontDelete|ReadOnly
01289 @end
01290 */
01291 Value DOMProcessingInstruction::tryGet(ExecState *exec, const Identifier &propertyName) const
01292 {
01293   return DOMObjectLookupGetValue<DOMProcessingInstruction, DOMNode>(exec, propertyName, &DOMProcessingInstructionTable, this);
01294 }
01295 
01296 Value DOMProcessingInstruction::getValueProperty(ExecState *exec, int token) const
01297 {
01298   switch (token) {
01299   case Target:
01300     return String(static_cast<DOM::ProcessingInstruction>(node).target());
01301   case Data:
01302     return String(static_cast<DOM::ProcessingInstruction>(node).data());
01303   case Sheet:
01304     return getDOMStyleSheet(exec,static_cast<DOM::ProcessingInstruction>(node).sheet());
01305   default:
01306     kdDebug(6070) << "WARNING: DOMProcessingInstruction::getValueProperty unhandled token " << token << endl;
01307     return Value();
01308   }
01309 }
01310 
01311 void DOMProcessingInstruction::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
01312 {
01313   // Not worth using the hashtable for this one ;)
01314   if (propertyName == "data")
01315     static_cast<DOM::ProcessingInstruction>(node).setData(value.toString(exec).string());
01316   else
01317     DOMNode::tryPut(exec, propertyName,value,attr);
01318 }
01319 
01320 // -------------------------------------------------------------------------
01321 
01322 const ClassInfo DOMNotation::info = { "Notation", &DOMNode::info, &DOMNotationTable, 0 };
01323 
01324 /* Source for DOMNotationTable.
01325 @begin DOMNotationTable 2
01326   publicId      DOMNotation::PublicId   DontDelete|ReadOnly
01327   systemId      DOMNotation::SystemId   DontDelete|ReadOnly
01328 @end
01329 */
01330 Value DOMNotation::tryGet(ExecState *exec, const Identifier &propertyName) const
01331 {
01332   return DOMObjectLookupGetValue<DOMNotation, DOMNode>(exec, propertyName, &DOMNotationTable, this);
01333 }
01334 
01335 Value DOMNotation::getValueProperty(ExecState *, int token) const
01336 {
01337   switch (token) {
01338   case PublicId:
01339     return String(static_cast<DOM::Notation>(node).publicId());
01340   case SystemId:
01341     return String(static_cast<DOM::Notation>(node).systemId());
01342   default:
01343     kdDebug(6070) << "WARNING: DOMNotation::getValueProperty unhandled token " << token << endl;
01344     return Value();
01345   }
01346 }
01347 
01348 // -------------------------------------------------------------------------
01349 
01350 const ClassInfo DOMEntity::info = { "Entity", &DOMNode::info, 0, 0 };
01351 
01352 /* Source for DOMEntityTable.
01353 @begin DOMEntityTable 2
01354   publicId      DOMEntity::PublicId     DontDelete|ReadOnly
01355   systemId      DOMEntity::SystemId     DontDelete|ReadOnly
01356   notationName      DOMEntity::NotationName DontDelete|ReadOnly
01357 @end
01358 */
01359 Value DOMEntity::tryGet(ExecState *exec, const Identifier &propertyName) const
01360 {
01361   return DOMObjectLookupGetValue<DOMEntity, DOMNode>(exec, propertyName, &DOMEntityTable, this);
01362 }
01363 
01364 Value DOMEntity::getValueProperty(ExecState *, int token) const
01365 {
01366   switch (token) {
01367   case PublicId:
01368     return String(static_cast<DOM::Entity>(node).publicId());
01369   case SystemId:
01370     return String(static_cast<DOM::Entity>(node).systemId());
01371   case NotationName:
01372     return String(static_cast<DOM::Entity>(node).notationName());
01373   default:
01374     kdDebug(6070) << "WARNING: DOMEntity::getValueProperty unhandled token " << token << endl;
01375     return Value();
01376   }
01377 }
01378 
01379 // -------------------------------------------------------------------------
01380 
01381 bool KJS::checkNodeSecurity(ExecState *exec, const DOM::Node& n)
01382 {
01383   // Check to see if the currently executing interpreter is allowed to access the specified node
01384   if (n.isNull())
01385     return true;
01386   KHTMLView *view = n.handle()->getDocument()->view();
01387   Window* win = view && view->part() ? Window::retrieveWindow(view->part()) : 0L;
01388   if ( !win || !win->isSafeScript(exec) )
01389     return false;
01390   return true;
01391 }
01392 
01393 Value KJS::getDOMNode(ExecState *exec, const DOM::Node& n)
01394 {
01395   DOMObject *ret = 0;
01396   if (n.isNull())
01397     return Null();
01398   ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->interpreter());
01399   if ((ret = interp->getDOMObject(n.handle())))
01400     return Value(ret);
01401 
01402   switch (n.nodeType()) {
01403     case DOM::Node::ELEMENT_NODE:
01404       if (static_cast<DOM::Element>(n).isHTMLElement())
01405         ret = new HTMLElement(exec, static_cast<DOM::HTMLElement>(n));
01406       else
01407         ret = new DOMElement(exec, static_cast<DOM::Element>(n));
01408       break;
01409     case DOM::Node::ATTRIBUTE_NODE:
01410       ret = new DOMAttr(exec, static_cast<DOM::Attr>(n));
01411       break;
01412     case DOM::Node::TEXT_NODE:
01413     case DOM::Node::CDATA_SECTION_NODE:
01414       ret = new DOMText(exec, static_cast<DOM::Text>(n));
01415       break;
01416     case DOM::Node::ENTITY_REFERENCE_NODE:
01417       ret = new DOMNode(exec, n);
01418       break;
01419     case DOM::Node::ENTITY_NODE:
01420       ret = new DOMEntity(exec, static_cast<DOM::Entity>(n));
01421       break;
01422     case DOM::Node::PROCESSING_INSTRUCTION_NODE:
01423       ret = new DOMProcessingInstruction(exec, static_cast<DOM::ProcessingInstruction>(n));
01424       break;
01425     case DOM::Node::COMMENT_NODE:
01426       ret = new DOMCharacterData(exec, static_cast<DOM::CharacterData>(n));
01427       break;
01428     case DOM::Node::DOCUMENT_NODE:
01429       if (static_cast<DOM::Document>(n).isHTMLDocument())
01430         ret = new HTMLDocument(exec, static_cast<DOM::HTMLDocument>(n));
01431       else
01432         ret = new DOMDocument(exec, static_cast<DOM::Document>(n));
01433       break;
01434     case DOM::Node::DOCUMENT_TYPE_NODE:
01435       ret = new DOMDocumentType(exec, static_cast<DOM::DocumentType>(n));
01436       break;
01437     case DOM::Node::DOCUMENT_FRAGMENT_NODE:
01438       ret = new DOMNode(exec, n);
01439       break;
01440     case DOM::Node::NOTATION_NODE:
01441       ret = new DOMNotation(exec, static_cast<DOM::Notation>(n));
01442       break;
01443     default:
01444       ret = new DOMNode(exec, n);
01445   }
01446   interp->putDOMObject(n.handle(),ret);
01447 
01448   return Value(ret);
01449 }
01450 
01451 Value KJS::getDOMNamedNodeMap(ExecState *exec, const DOM::NamedNodeMap& m)
01452 {
01453   return Value(cacheDOMObject<DOM::NamedNodeMap, KJS::DOMNamedNodeMap>(exec, m));
01454 }
01455 
01456 Value KJS::getDOMNodeList(ExecState *exec, const DOM::NodeList& l)
01457 {
01458   return Value(cacheDOMObject<DOM::NodeList, KJS::DOMNodeList>(exec, l));
01459 }
01460 
01461 Value KJS::getDOMDOMImplementation(ExecState *exec, const DOM::DOMImplementation& i)
01462 {
01463   return Value(cacheDOMObject<DOM::DOMImplementation, KJS::DOMDOMImplementation>(exec, i));
01464 }
01465 
01466 // -------------------------------------------------------------------------
01467 
01468 const ClassInfo NodeConstructor::info = { "NodeConstructor", 0, &NodeConstructorTable, 0 };
01469 /* Source for NodeConstructorTable.
01470 @begin NodeConstructorTable 11
01471   ELEMENT_NODE      DOM::Node::ELEMENT_NODE     DontDelete|ReadOnly
01472   ATTRIBUTE_NODE    DOM::Node::ATTRIBUTE_NODE       DontDelete|ReadOnly
01473   TEXT_NODE     DOM::Node::TEXT_NODE        DontDelete|ReadOnly
01474   CDATA_SECTION_NODE    DOM::Node::CDATA_SECTION_NODE   DontDelete|ReadOnly
01475   ENTITY_REFERENCE_NODE DOM::Node::ENTITY_REFERENCE_NODE    DontDelete|ReadOnly
01476   ENTITY_NODE       DOM::Node::ENTITY_NODE      DontDelete|ReadOnly
01477   PROCESSING_INSTRUCTION_NODE DOM::Node::PROCESSING_INSTRUCTION_NODE DontDelete|ReadOnly
01478   COMMENT_NODE      DOM::Node::COMMENT_NODE     DontDelete|ReadOnly
01479   DOCUMENT_NODE     DOM::Node::DOCUMENT_NODE        DontDelete|ReadOnly
01480   DOCUMENT_TYPE_NODE    DOM::Node::DOCUMENT_TYPE_NODE   DontDelete|ReadOnly
01481   DOCUMENT_FRAGMENT_NODE DOM::Node::DOCUMENT_FRAGMENT_NODE  DontDelete|ReadOnly
01482   NOTATION_NODE     DOM::Node::NOTATION_NODE        DontDelete|ReadOnly
01483 @end
01484 */
01485 
01486 NodeConstructor::NodeConstructor(ExecState *exec)
01487   : DOMObject(exec->interpreter()->builtinObjectPrototype())
01488 {
01489 }
01490 
01491 Value NodeConstructor::tryGet(ExecState *exec, const Identifier &propertyName) const
01492 {
01493   return DOMObjectLookupGetValue<NodeConstructor, DOMObject>(exec, propertyName, &NodeConstructorTable, this);
01494 }
01495 
01496 Value NodeConstructor::getValueProperty(ExecState *, int token) const
01497 {
01498   // We use the token as the value to return directly
01499   return Number((unsigned int)token);
01500 #if 0
01501   switch (token) {
01502   case ELEMENT_NODE:
01503     return Number((unsigned int)DOM::Node::ELEMENT_NODE);
01504   case ATTRIBUTE_NODE:
01505     return Number((unsigned int)DOM::Node::ATTRIBUTE_NODE);
01506   case TEXT_NODE:
01507     return Number((unsigned int)DOM::Node::TEXT_NODE);
01508   case CDATA_SECTION_NODE:
01509     return Number((unsigned int)DOM::Node::CDATA_SECTION_NODE);
01510   case ENTITY_REFERENCE_NODE:
01511     return Number((unsigned int)DOM::Node::ENTITY_REFERENCE_NODE);
01512   case ENTITY_NODE:
01513     return Number((unsigned int)DOM::Node::ENTITY_NODE);
01514   case PROCESSING_INSTRUCTION_NODE:
01515     return Number((unsigned int)DOM::Node::PROCESSING_INSTRUCTION_NODE);
01516   case COMMENT_NODE:
01517     return Number((unsigned int)DOM::Node::COMMENT_NODE);
01518   case DOCUMENT_NODE:
01519     return Number((unsigned int)DOM::Node::DOCUMENT_NODE);
01520   case DOCUMENT_TYPE_NODE:
01521     return Number((unsigned int)DOM::Node::DOCUMENT_TYPE_NODE);
01522   case DOCUMENT_FRAGMENT_NODE:
01523     return Number((unsigned int)DOM::Node::DOCUMENT_FRAGMENT_NODE);
01524   case NOTATION_NODE:
01525     return Number((unsigned int)DOM::Node::NOTATION_NODE);
01526   default:
01527     kdDebug(6070) << "WARNING: NodeConstructor::getValueProperty unhandled token " << token << endl;
01528     return Value();
01529   }
01530 #endif
01531 }
01532 
01533 Object KJS::getNodeConstructor(ExecState *exec)
01534 {
01535   return Object(cacheGlobalObject<NodeConstructor>(exec, "[[node.constructor]]"));
01536 }
01537 
01538 // -------------------------------------------------------------------------
01539 
01540 const ClassInfo DOMExceptionConstructor::info = { "DOMExceptionConstructor", 0, 0, 0 };
01541 
01542 /* Source for DOMExceptionConstructorTable.
01543 @begin DOMExceptionConstructorTable 15
01544   INDEX_SIZE_ERR        DOM::DOMException::INDEX_SIZE_ERR       DontDelete|ReadOnly
01545   DOMSTRING_SIZE_ERR        DOM::DOMException::DOMSTRING_SIZE_ERR   DontDelete|ReadOnly
01546   HIERARCHY_REQUEST_ERR     DOM::DOMException::HIERARCHY_REQUEST_ERR    DontDelete|ReadOnly
01547   WRONG_DOCUMENT_ERR        DOM::DOMException::WRONG_DOCUMENT_ERR   DontDelete|ReadOnly
01548   INVALID_CHARACTER_ERR     DOM::DOMException::INVALID_CHARACTER_ERR    DontDelete|ReadOnly
01549   NO_DATA_ALLOWED_ERR       DOM::DOMException::NO_DATA_ALLOWED_ERR  DontDelete|ReadOnly
01550   NO_MODIFICATION_ALLOWED_ERR   DOM::DOMException::NO_MODIFICATION_ALLOWED_ERR  DontDelete|ReadOnly
01551   NOT_FOUND_ERR         DOM::DOMException::NOT_FOUND_ERR        DontDelete|ReadOnly
01552   NOT_SUPPORTED_ERR     DOM::DOMException::NOT_SUPPORTED_ERR    DontDelete|ReadOnly
01553   INUSE_ATTRIBUTE_ERR       DOM::DOMException::INUSE_ATTRIBUTE_ERR  DontDelete|ReadOnly
01554   INVALID_STATE_ERR     DOM::DOMException::INVALID_STATE_ERR    DontDelete|ReadOnly
01555   SYNTAX_ERR            DOM::DOMException::SYNTAX_ERR       DontDelete|ReadOnly
01556   INVALID_MODIFICATION_ERR  DOM::DOMException::INVALID_MODIFICATION_ERR DontDelete|ReadOnly
01557   NAMESPACE_ERR         DOM::DOMException::NAMESPACE_ERR        DontDelete|ReadOnly
01558   INVALID_ACCESS_ERR        DOM::DOMException::INVALID_ACCESS_ERR   DontDelete|ReadOnly
01559 @end
01560 */
01561 
01562 DOMExceptionConstructor::DOMExceptionConstructor(ExecState* exec)
01563   : DOMObject(exec->interpreter()->builtinObjectPrototype())
01564 {
01565 }
01566 
01567 Value DOMExceptionConstructor::tryGet(ExecState *exec, const Identifier &propertyName) const
01568 {
01569   return DOMObjectLookupGetValue<DOMExceptionConstructor, DOMObject>(exec, propertyName, &DOMExceptionConstructorTable, this);
01570 }
01571 
01572 Value DOMExceptionConstructor::getValueProperty(ExecState *, int token) const
01573 {
01574   // We use the token as the value to return directly
01575   return Number((unsigned int)token);
01576 #if 0
01577   switch (token) {
01578   case INDEX_SIZE_ERR:
01579     return Number((unsigned int)DOM::DOMException::INDEX_SIZE_ERR);
01580   case DOMSTRING_SIZE_ERR:
01581     return Number((unsigned int)DOM::DOMException::DOMSTRING_SIZE_ERR);
01582   case HIERARCHY_REQUEST_ERR:
01583     return Number((unsigned int)DOM::DOMException::HIERARCHY_REQUEST_ERR);
01584   case WRONG_DOCUMENT_ERR:
01585     return Number((unsigned int)DOM::DOMException::WRONG_DOCUMENT_ERR);
01586   case INVALID_CHARACTER_ERR:
01587     return Number((unsigned int)DOM::DOMException::INVALID_CHARACTER_ERR);
01588   case NO_DATA_ALLOWED_ERR:
01589     return Number((unsigned int)DOM::DOMException::NO_DATA_ALLOWED_ERR);
01590   case NO_MODIFICATION_ALLOWED_ERR:
01591     return Number((unsigned int)DOM::DOMException::NO_MODIFICATION_ALLOWED_ERR);
01592   case NOT_FOUND_ERR:
01593     return Number((unsigned int)DOM::DOMException::NOT_FOUND_ERR);
01594   case NOT_SUPPORTED_ERR:
01595     return Number((unsigned int)DOM::DOMException::NOT_SUPPORTED_ERR);
01596   case INUSE_ATTRIBUTE_ERR:
01597     return Number((unsigned int)DOM::DOMException::INUSE_ATTRIBUTE_ERR);
01598   case INVALID_STATE_ERR:
01599     return Number((unsigned int)DOM::DOMException::INVALID_STATE_ERR);
01600   case SYNTAX_ERR:
01601     return Number((unsigned int)DOM::DOMException::SYNTAX_ERR);
01602   case INVALID_MODIFICATION_ERR:
01603     return Number((unsigned int)DOM::DOMException::INVALID_MODIFICATION_ERR);
01604   case NAMESPACE_ERR:
01605     return Number((unsigned int)DOM::DOMException::NAMESPACE_ERR);
01606   case INVALID_ACCESS_ERR:
01607     return Number((unsigned int)DOM::DOMException::INVALID_ACCESS_ERR);
01608   default:
01609     kdDebug(6070) << "WARNING: DOMExceptionConstructor::getValueProperty unhandled token " << token << endl;
01610     return Value();
01611   }
01612 #endif
01613 }
01614 
01615 Object KJS::getDOMExceptionConstructor(ExecState *exec)
01616 {
01617   return cacheGlobalObject<DOMExceptionConstructor>(exec, "[[DOMException.constructor]]");
01618 }
01619 
01620 // -------------------------------------------------------------------------
01621 
01622 const ClassInfo KJS::DOMNamedNodesCollection::info = { "DOMNamedNodesCollection", 0, 0, 0 };
01623 
01624 // Such a collection is usually very short-lived, it only exists
01625 // for constructs like document.forms.<name>[1],
01626 // so it shouldn't be a problem that it's storing all the nodes (with the same name). (David)
01627 DOMNamedNodesCollection::DOMNamedNodesCollection(ExecState *exec, const QValueList<DOM::Node>& nodes )
01628   : DOMObject(exec->interpreter()->builtinObjectPrototype()),
01629   m_nodes(nodes)
01630 {
01631   // Maybe we should ref (and deref in the dtor) the nodes, though ?
01632 }
01633 
01634 Value DOMNamedNodesCollection::tryGet(ExecState *exec, const Identifier &propertyName) const
01635 {
01636   kdDebug(6070) << k_funcinfo << propertyName.ascii() << endl;
01637   if (propertyName == lengthPropertyName)
01638     return Number(m_nodes.count());
01639   // index?
01640   bool ok;
01641   unsigned int u = propertyName.toULong(&ok);
01642   if (ok && u < m_nodes.count()) {
01643     DOM::Node node = m_nodes[u];
01644     return getDOMNode(exec,node);
01645   }
01646   return DOMObject::tryGet(exec,propertyName);
01647 }
01648 
01649 // -------------------------------------------------------------------------
01650 
01651 const ClassInfo DOMCharacterData::info = { "CharacterImp",
01652                       &DOMNode::info, &DOMCharacterDataTable, 0 };
01653 /*
01654 @begin DOMCharacterDataTable 2
01655   data      DOMCharacterData::Data      DontDelete
01656   length    DOMCharacterData::Length    DontDelete|ReadOnly
01657 @end
01658 @begin DOMCharacterDataProtoTable 7
01659   substringData DOMCharacterData::SubstringData DontDelete|Function 2
01660   appendData    DOMCharacterData::AppendData    DontDelete|Function 1
01661   insertData    DOMCharacterData::InsertData    DontDelete|Function 2
01662   deleteData    DOMCharacterData::DeleteData    DontDelete|Function 2
01663   replaceData   DOMCharacterData::ReplaceData   DontDelete|Function 2
01664 @end
01665 */
01666 DEFINE_PROTOTYPE("DOMCharacterData",DOMCharacterDataProto)
01667 IMPLEMENT_PROTOFUNC_DOM(DOMCharacterDataProtoFunc)
01668 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMCharacterDataProto,DOMCharacterDataProtoFunc, DOMNodeProto)
01669 
01670 DOMCharacterData::DOMCharacterData(ExecState *exec, const DOM::CharacterData& d)
01671  : DOMNode(DOMCharacterDataProto::self(exec), d) {}
01672 
01673 DOMCharacterData::DOMCharacterData(const Object& proto, const DOM::CharacterData& d)
01674  : DOMNode(proto, d) {}
01675 
01676 Value DOMCharacterData::tryGet(ExecState *exec, const Identifier &p) const
01677 {
01678 #ifdef KJS_VERBOSE
01679   kdDebug(6070)<<"DOMCharacterData::tryGet "<<p.string().string()<<endl;
01680 #endif
01681   return DOMObjectLookupGetValue<DOMCharacterData,DOMNode>(exec,p,&DOMCharacterDataTable,this);
01682 }
01683 
01684 Value DOMCharacterData::getValueProperty(ExecState *, int token) const
01685 {
01686   DOM::CharacterData data = static_cast<DOM::CharacterData>(node);
01687   switch (token) {
01688   case Data:
01689     return String(data.data());
01690   case Length:
01691     return Number(data.length());
01692  default:
01693    kdDebug(6070) << "WARNING: Unhandled token in DOMCharacterData::getValueProperty : " << token << endl;
01694    return Value();
01695   }
01696 }
01697 
01698 void DOMCharacterData::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
01699 {
01700   if (propertyName == "data")
01701     static_cast<DOM::CharacterData>(node).setData(value.toString(exec).string());
01702   else
01703     DOMNode::tryPut(exec, propertyName,value,attr);
01704 }
01705 
01706 Value DOMCharacterDataProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
01707 {
01708   KJS_CHECK_THIS( KJS::DOMCharacterData, thisObj );
01709   DOM::CharacterData data = static_cast<DOMCharacterData *>(thisObj.imp())->toData();
01710   switch(id) {
01711     case DOMCharacterData::SubstringData:
01712       return String(data.substringData(args[0].toInteger(exec),args[1].toInteger(exec)));
01713     case DOMCharacterData::AppendData:
01714       data.appendData(args[0].toString(exec).string());
01715       return Undefined();
01716       break;
01717     case DOMCharacterData::InsertData:
01718       data.insertData(args[0].toInteger(exec),args[1].toString(exec).string());
01719       return  Undefined();
01720       break;
01721     case DOMCharacterData::DeleteData:
01722       data.deleteData(args[0].toInteger(exec),args[1].toInteger(exec));
01723       return  Undefined();
01724       break;
01725     case DOMCharacterData::ReplaceData:
01726       data.replaceData(args[0].toInteger(exec),args[1].toInteger(exec),args[2].toString(exec).string());
01727       return Undefined();
01728       break;
01729     default:
01730       return Undefined();
01731   }
01732 }
01733 
01734 // -------------------------------------------------------------------------
01735 
01736 const ClassInfo DOMText::info = { "Text",
01737                  &DOMCharacterData::info, 0, 0 };
01738 /*
01739 @begin DOMTextProtoTable 1
01740   splitText DOMText::SplitText  DontDelete|Function 1
01741 @end
01742 */
01743 DEFINE_PROTOTYPE("DOMText",DOMTextProto)
01744 IMPLEMENT_PROTOFUNC_DOM(DOMTextProtoFunc)
01745 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMTextProto,DOMTextProtoFunc,DOMCharacterDataProto)
01746 
01747 DOMText::DOMText(ExecState *exec, const DOM::Text& t)
01748   : DOMCharacterData(DOMTextProto::self(exec), t) { }
01749 
01750 Value DOMText::tryGet(ExecState *exec, const Identifier &p) const
01751 {
01752   if (p.isEmpty())
01753     return Undefined(); // ### TODO
01754   else
01755     return DOMCharacterData::tryGet(exec, p);
01756 }
01757 
01758 Value DOMTextProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
01759 {
01760   KJS_CHECK_THIS( KJS::DOMText, thisObj );
01761   DOM::Text text = static_cast<DOMText *>(thisObj.imp())->toText();
01762   switch(id) {
01763     case DOMText::SplitText:
01764       return getDOMNode(exec,text.splitText(args[0].toInteger(exec)));
01765       break;
01766     default:
01767       return Undefined();
01768   }
01769 }
KDE Logo
This file is part of the documentation for khtml Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun Jan 15 13:34:47 2006 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003