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