kjs_traversal.cpp

00001 // -*- c-basic-offset: 2 -*-
00002 /*
00003  *  This file is part of the KDE libraries
00004  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
00005  *
00006  *  This library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Library General Public
00008  *  License as published by the Free Software Foundation; either
00009  *  version 2 of the License, or (at your option) any later version.
00010  *
00011  *  This library is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  *  Library General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU Library General Public
00017  *  License along with this library; if not, write to the Free Software
00018  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00019  */
00020 
00021 #include "kjs_traversal.h"
00022 #include "kjs_traversal.lut.h"
00023 #include "kjs_proxy.h"
00024 #include <dom/dom_node.h>
00025 #include <xml/dom_nodeimpl.h>
00026 #include <xml/dom_docimpl.h>
00027 #include <khtmlview.h>
00028 #include <khtml_part.h>
00029 #include <kdebug.h>
00030 
00031 using namespace KJS;
00032 
00033 // -------------------------------------------------------------------------
00034 
00035 const ClassInfo DOMNodeIterator::info = { "NodeIterator", 0, &DOMNodeIteratorTable, 0 };
00036 /*
00037 @begin DOMNodeIteratorTable 5
00038   root              DOMNodeIterator::Root           DontDelete|ReadOnly
00039   whatToShow            DOMNodeIterator::WhatToShow     DontDelete|ReadOnly
00040   filter            DOMNodeIterator::Filter         DontDelete|ReadOnly
00041   expandEntityReferences    DOMNodeIterator::ExpandEntityReferences DontDelete|ReadOnly
00042 @end
00043 @begin DOMNodeIteratorProtoTable 3
00044   nextNode  DOMNodeIterator::NextNode   DontDelete|Function 0
00045   previousNode  DOMNodeIterator::PreviousNode   DontDelete|Function 0
00046   detach    DOMNodeIterator::Detach     DontDelete|Function 0
00047 @end
00048 */
00049 DEFINE_PROTOTYPE("DOMNodeIterator",DOMNodeIteratorProto)
00050 IMPLEMENT_PROTOFUNC_DOM(DOMNodeIteratorProtoFunc)
00051 IMPLEMENT_PROTOTYPE(DOMNodeIteratorProto,DOMNodeIteratorProtoFunc)
00052 
00053 DOMNodeIterator::DOMNodeIterator(ExecState *exec, DOM::NodeIterator ni)
00054   : DOMObject(DOMNodeIteratorProto::self(exec)), nodeIterator(ni) {}
00055 
00056 DOMNodeIterator::~DOMNodeIterator()
00057 {
00058   ScriptInterpreter::forgetDOMObject(nodeIterator.handle());
00059 }
00060 
00061 Value DOMNodeIterator::tryGet(ExecState *exec, const Identifier &p) const
00062 {
00063   return DOMObjectLookupGetValue<DOMNodeIterator,DOMObject>(exec,p,&DOMNodeIteratorTable,this);
00064 }
00065 
00066 Value DOMNodeIterator::getValueProperty(ExecState *exec, int token) const
00067 {
00068   DOM::NodeIterator ni(nodeIterator);
00069   switch (token) {
00070   case Root:
00071     return getDOMNode(exec,ni.root());
00072   case WhatToShow:
00073     return Number(ni.whatToShow());
00074   case Filter:
00075     return getDOMNodeFilter(exec,ni.filter());
00076   case ExpandEntityReferences:
00077     return Boolean(ni.expandEntityReferences());
00078  default:
00079    kdDebug(6070) << "WARNING: Unhandled token in DOMNodeIterator::getValueProperty : " << token << endl;
00080    return Value();
00081   }
00082 }
00083 
00084 Value DOMNodeIteratorProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &)
00085 {
00086   KJS_CHECK_THIS( KJS::DOMNodeIterator, thisObj );
00087   DOM::NodeIterator nodeIterator = static_cast<DOMNodeIterator *>(thisObj.imp())->toNodeIterator();
00088   switch (id) {
00089   case DOMNodeIterator::PreviousNode:
00090     return getDOMNode(exec,nodeIterator.previousNode());
00091   case DOMNodeIterator::NextNode:
00092     return getDOMNode(exec,nodeIterator.nextNode());
00093   case DOMNodeIterator::Detach:
00094     nodeIterator.detach();
00095     return Undefined();
00096   }
00097   return Undefined();
00098 }
00099 
00100 Value KJS::getDOMNodeIterator(ExecState *exec, DOM::NodeIterator ni)
00101 {
00102   return cacheDOMObject<DOM::NodeIterator, DOMNodeIterator>(exec, ni);
00103 }
00104 
00105 
00106 // -------------------------------------------------------------------------
00107 
00108 const ClassInfo NodeFilterConstructor::info = { "NodeFilterConstructor", 0, &NodeFilterConstructorTable, 0 };
00109 /*
00110 @begin NodeFilterConstructorTable 17
00111   FILTER_ACCEPT     DOM::NodeFilter::FILTER_ACCEPT  DontDelete|ReadOnly
00112   FILTER_REJECT     DOM::NodeFilter::FILTER_REJECT  DontDelete|ReadOnly
00113   FILTER_SKIP       DOM::NodeFilter::FILTER_SKIP    DontDelete|ReadOnly
00114   SHOW_ALL      DOM::NodeFilter::SHOW_ALL   DontDelete|ReadOnly
00115   SHOW_ELEMENT      DOM::NodeFilter::SHOW_ELEMENT   DontDelete|ReadOnly
00116   SHOW_ATTRIBUTE    DOM::NodeFilter::SHOW_ATTRIBUTE DontDelete|ReadOnly
00117   SHOW_TEXT     DOM::NodeFilter::SHOW_TEXT  DontDelete|ReadOnly
00118   SHOW_CDATA_SECTION    DOM::NodeFilter::SHOW_CDATA_SECTION DontDelete|ReadOnly
00119   SHOW_ENTITY_REFERENCE DOM::NodeFilter::SHOW_ENTITY_REFERENCE  DontDelete|ReadOnly
00120   SHOW_ENTITY       DOM::NodeFilter::SHOW_ENTITY    DontDelete|ReadOnly
00121   SHOW_PROCESSING_INSTRUCTION   DOM::NodeFilter::SHOW_PROCESSING_INSTRUCTION    DontDelete|ReadOnly
00122   SHOW_COMMENT      DOM::NodeFilter::SHOW_COMMENT   DontDelete|ReadOnly
00123   SHOW_DOCUMENT     DOM::NodeFilter::SHOW_DOCUMENT  DontDelete|ReadOnly
00124   SHOW_DOCUMENT_TYPE    DOM::NodeFilter::SHOW_DOCUMENT_TYPE DontDelete|ReadOnly
00125   SHOW_DOCUMENT_FRAGMENT    DOM::NodeFilter::SHOW_DOCUMENT_FRAGMENT DontDelete|ReadOnly
00126   SHOW_NOTATION     DOM::NodeFilter::SHOW_NOTATION  DontDelete|ReadOnly
00127 @end
00128 */
00129 
00130 NodeFilterConstructor::NodeFilterConstructor(ExecState* exec)
00131   : DOMObject(exec->interpreter()->builtinObjectPrototype())
00132 {
00133 }
00134 
00135 Value NodeFilterConstructor::tryGet(ExecState *exec, const Identifier &p) const
00136 {
00137   return DOMObjectLookupGetValue<NodeFilterConstructor,DOMObject>(exec,p,&NodeFilterConstructorTable,this);
00138 }
00139 
00140 Value NodeFilterConstructor::getValueProperty(ExecState *, int token) const
00141 {
00142   // We use the token as the value to return directly
00143   return Number(token);
00144 }
00145 
00146 Value KJS::getNodeFilterConstructor(ExecState *exec)
00147 {
00148   return cacheGlobalObject<NodeFilterConstructor>(exec, "[[nodeFilter.constructor]]");
00149 }
00150 
00151 // -------------------------------------------------------------------------
00152 
00153 const ClassInfo DOMNodeFilter::info = { "NodeFilter", 0, 0, 0 };
00154 /*
00155 @begin DOMNodeFilterProtoTable 1
00156   acceptNode    DOMNodeFilter::AcceptNode   DontDelete|Function 0
00157 @end
00158 */
00159 DEFINE_PROTOTYPE("DOMNodeFilter",DOMNodeFilterProto)
00160 IMPLEMENT_PROTOFUNC_DOM(DOMNodeFilterProtoFunc)
00161 IMPLEMENT_PROTOTYPE(DOMNodeFilterProto,DOMNodeFilterProtoFunc)
00162 
00163 DOMNodeFilter::DOMNodeFilter(ExecState *exec, DOM::NodeFilter nf)
00164   : DOMObject(DOMNodeFilterProto::self(exec)), nodeFilter(nf) {}
00165 
00166 DOMNodeFilter::~DOMNodeFilter()
00167 {
00168   ScriptInterpreter::forgetDOMObject(nodeFilter.handle());
00169 }
00170 
00171 Value DOMNodeFilterProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
00172 {
00173   KJS_CHECK_THIS( KJS::DOMNodeFilter, thisObj );
00174   DOM::NodeFilter nodeFilter = static_cast<DOMNodeFilter *>(thisObj.imp())->toNodeFilter();
00175   switch (id) {
00176     case DOMNodeFilter::AcceptNode:
00177       return Number(nodeFilter.acceptNode(toNode(args[0])));
00178   }
00179   return Undefined();
00180 }
00181 
00182 Value KJS::getDOMNodeFilter(ExecState *exec, DOM::NodeFilter nf)
00183 {
00184   return cacheDOMObject<DOM::NodeFilter, DOMNodeFilter>(exec, nf);
00185 }
00186 
00187 // -------------------------------------------------------------------------
00188 
00189 const ClassInfo DOMTreeWalker::info = { "TreeWalker", 0, &DOMTreeWalkerTable, 0 };
00190 /*
00191 @begin DOMTreeWalkerTable 5
00192   root          DOMTreeWalker::Root     DontDelete|ReadOnly
00193   whatToShow        DOMTreeWalker::WhatToShow   DontDelete|ReadOnly
00194   filter        DOMTreeWalker::Filter       DontDelete|ReadOnly
00195   expandEntityReferences DOMTreeWalker::ExpandEntityReferences  DontDelete|ReadOnly
00196   currentNode       DOMTreeWalker::CurrentNode  DontDelete
00197 @end
00198 @begin DOMTreeWalkerProtoTable 7
00199   parentNode    DOMTreeWalker::ParentNode   DontDelete|Function 0
00200   firstChild    DOMTreeWalker::FirstChild   DontDelete|Function 0
00201   lastChild DOMTreeWalker::LastChild    DontDelete|Function 0
00202   previousSibling DOMTreeWalker::PreviousSibling    DontDelete|Function 0
00203   nextSibling   DOMTreeWalker::NextSibling  DontDelete|Function 0
00204   previousNode  DOMTreeWalker::PreviousNode DontDelete|Function 0
00205   nextNode  DOMTreeWalker::NextNode     DontDelete|Function 0
00206 @end
00207 */
00208 DEFINE_PROTOTYPE("DOMTreeWalker",DOMTreeWalkerProto)
00209 IMPLEMENT_PROTOFUNC_DOM(DOMTreeWalkerProtoFunc)
00210 IMPLEMENT_PROTOTYPE(DOMTreeWalkerProto,DOMTreeWalkerProtoFunc)
00211 
00212 DOMTreeWalker::DOMTreeWalker(ExecState *exec, DOM::TreeWalker tw)
00213   : DOMObject(DOMTreeWalkerProto::self(exec)), treeWalker(tw) {}
00214 
00215 DOMTreeWalker::~DOMTreeWalker()
00216 {
00217   ScriptInterpreter::forgetDOMObject(treeWalker.handle());
00218 }
00219 
00220 Value DOMTreeWalker::tryGet(ExecState *exec, const Identifier &p) const
00221 {
00222   return DOMObjectLookupGetValue<DOMTreeWalker,DOMObject>(exec,p,&DOMTreeWalkerTable,this);
00223 }
00224 
00225 Value DOMTreeWalker::getValueProperty(ExecState *exec, int token) const
00226 {
00227   DOM::TreeWalker tw(treeWalker);
00228   switch (token) {
00229   case Root:
00230     return getDOMNode(exec,tw.root());
00231   case WhatToShow:
00232     return Number(tw.whatToShow());
00233   case Filter:
00234     return getDOMNodeFilter(exec,tw.filter());
00235   case ExpandEntityReferences:
00236     return Boolean(tw.expandEntityReferences());
00237   case CurrentNode:
00238     return getDOMNode(exec,tw.currentNode());
00239   default:
00240     kdDebug(6070) << "WARNING: Unhandled token in DOMTreeWalker::getValueProperty : " << token << endl;
00241     return Value();
00242   }
00243 }
00244 
00245 void DOMTreeWalker::tryPut(ExecState *exec, const Identifier &propertyName,
00246                            const Value& value, int attr)
00247 {
00248   if (propertyName == "currentNode") {
00249     treeWalker.setCurrentNode(toNode(value));
00250   }
00251   else
00252     ObjectImp::put(exec, propertyName, value, attr);
00253 }
00254 
00255 Value DOMTreeWalkerProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &)
00256 {
00257   KJS_CHECK_THIS( KJS::DOMTreeWalker, thisObj );
00258   DOM::TreeWalker treeWalker = static_cast<DOMTreeWalker *>(thisObj.imp())->toTreeWalker();
00259   switch (id) {
00260     case DOMTreeWalker::ParentNode:
00261       return getDOMNode(exec,treeWalker.parentNode());
00262     case DOMTreeWalker::FirstChild:
00263       return getDOMNode(exec,treeWalker.firstChild());
00264     case DOMTreeWalker::LastChild:
00265       return getDOMNode(exec,treeWalker.lastChild());
00266     case DOMTreeWalker::PreviousSibling:
00267       return getDOMNode(exec,treeWalker.previousSibling());
00268     case DOMTreeWalker::NextSibling:
00269       return getDOMNode(exec,treeWalker.nextSibling());
00270     case DOMTreeWalker::PreviousNode:
00271       return getDOMNode(exec,treeWalker.previousSibling());
00272     case DOMTreeWalker::NextNode:
00273       return getDOMNode(exec,treeWalker.nextNode());
00274   }
00275   return Undefined();
00276 }
00277 
00278 Value KJS::getDOMTreeWalker(ExecState *exec, DOM::TreeWalker tw)
00279 {
00280   return cacheDOMObject<DOM::TreeWalker, DOMTreeWalker>(exec, tw);
00281 }
00282 
00283 DOM::NodeFilter KJS::toNodeFilter(const Value& val)
00284 {
00285   Object obj = Object::dynamicCast(val);
00286   if (!obj.isValid() || !obj.inherits(&DOMNodeFilter::info))
00287     return DOM::NodeFilter();
00288 
00289   const DOMNodeFilter *dobj = static_cast<const DOMNodeFilter*>(obj.imp());
00290   return dobj->toNodeFilter();
00291 }
00292 
00293 // -------------------------------------------------------------------------
00294 
00295 JSNodeFilter::JSNodeFilter(Object & _filter) : DOM::CustomNodeFilter(), filter( _filter )
00296 {
00297 }
00298 
00299 JSNodeFilter::~JSNodeFilter()
00300 {
00301 }
00302 
00303 short JSNodeFilter::acceptNode(const DOM::Node &n)
00304 {
00305   KHTMLView *view = static_cast<DOM::DocumentImpl *>( n.handle()->docPtr()->document() )->view();
00306   if (!view)
00307       return DOM::NodeFilter::FILTER_REJECT;
00308 
00309   KHTMLPart *part = view->part();
00310   KJSProxy *proxy = part->jScript();
00311   if (proxy) {
00312     ExecState *exec = proxy->interpreter()->globalExec();
00313     Object acceptNodeFunc = Object::dynamicCast( filter.get(exec, "acceptNode") );
00314     if (acceptNodeFunc.implementsCall()) {
00315       List args;
00316       args.append(getDOMNode(exec,n));
00317       Value result = acceptNodeFunc.call(exec,filter,args);
00318       if (exec->hadException())
00319     exec->clearException();
00320       return result.toInteger(exec);
00321     }
00322   }
00323 
00324   return DOM::NodeFilter::FILTER_REJECT;
00325 }
KDE Home | KDE Accessibility Home | Description of Access Keys