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