Reviewed by Adele.
[WebKit-https.git] / WebCore / bindings / objc / DOM.mm
1 /*
2  * Copyright (C) 2004-2006 Apple Computer, Inc.  All rights reserved.
3  * Copyright (C) 2006 James G. Speth (speth@end.com)
4  * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
26  */
27
28 #import "config.h"
29 #import "DOM.h"
30
31 #import "CDATASection.h"
32 #import "CSSStyleSheet.h"
33 #import "Comment.h"
34 #import "DOMImplementationFront.h"
35 #import "DOMInternal.h"
36 #import "DOMPrivate.h"
37 #import "Document.h"
38 #import "DocumentFragment.h"
39 #import "DocumentType.h"
40 #import "EntityReference.h"
41 #import "Event.h"
42 #import "EventListener.h"
43 #import "EventTarget.h"
44 #import "ExceptionHandlers.h"
45 #import "FontData.h"
46 #import "FoundationExtras.h"
47 #import "Frame.h"
48 #import "HTMLDocument.h"
49 #import "HTMLNames.h"
50 #import "HTMLPlugInElement.h"
51 #import "Image.h"
52 #import "IntRect.h"
53 #import "NodeFilter.h"
54 #import "NodeFilterCondition.h"
55 #import "NodeIterator.h"
56 #import "NodeList.h"
57 #import "ProcessingInstruction.h"
58 #import "QualifiedName.h"
59 #import "Range.h"
60 #import "RenderImage.h"
61 #import "Text.h"
62 #import "TreeWalker.h"
63 #import "WebScriptObjectPrivate.h"
64 #import "csshelper.h"
65 #import <objc/objc-class.h>
66 #import <wtf/HashMap.h>
67
68 #if ENABLE(SVG)
69 #import "SVGDocument.h"
70 #import "SVGElement.h"
71 #import "SVGNames.h"
72 #endif
73
74 namespace WebCore {
75
76 class ObjCEventListener : public EventListener {
77 public:
78     static ObjCEventListener* find(id <DOMEventListener>);
79     static ObjCEventListener* create(id <DOMEventListener>);
80
81 private:
82     ObjCEventListener(id <DOMEventListener>);
83     virtual ~ObjCEventListener();
84
85     virtual void handleEvent(Event*, bool isWindowEvent);
86
87     id <DOMEventListener> m_listener;
88 };
89
90 typedef HashMap<id, ObjCEventListener*> ListenerMap;
91 static ListenerMap* listenerMap;
92
93 } // namespace WebCore
94
95
96 //------------------------------------------------------------------------------------------
97 // DOMNode
98
99 namespace WebCore {
100
101 typedef HashMap<const QualifiedName::QualifiedNameImpl*, Class> ObjCClassMap;
102 static ObjCClassMap* elementClassMap;
103
104 static void addElementClass(const QualifiedName& tag, Class objCClass)
105 {
106     elementClassMap->set(tag.impl(), objCClass);
107 }
108
109 static void createElementClassMap()
110 {
111     // Create the table.
112     elementClassMap = new ObjCClassMap;
113
114     // FIXME: Reflect marquee once the API has been determined.
115
116     // Populate it with HTML and SVG element classes.
117     addElementClass(HTMLNames::aTag, [DOMHTMLAnchorElement class]);
118     addElementClass(HTMLNames::appletTag, [DOMHTMLAppletElement class]);
119     addElementClass(HTMLNames::areaTag, [DOMHTMLAreaElement class]);
120     addElementClass(HTMLNames::baseTag, [DOMHTMLBaseElement class]);
121     addElementClass(HTMLNames::basefontTag, [DOMHTMLBaseFontElement class]);
122     addElementClass(HTMLNames::bodyTag, [DOMHTMLBodyElement class]);
123     addElementClass(HTMLNames::brTag, [DOMHTMLBRElement class]);
124     addElementClass(HTMLNames::buttonTag, [DOMHTMLButtonElement class]);
125     addElementClass(HTMLNames::canvasTag, [DOMHTMLImageElement class]);
126     addElementClass(HTMLNames::captionTag, [DOMHTMLTableCaptionElement class]);
127     addElementClass(HTMLNames::colTag, [DOMHTMLTableColElement class]);
128     addElementClass(HTMLNames::colgroupTag, [DOMHTMLTableColElement class]);
129     addElementClass(HTMLNames::dirTag, [DOMHTMLDirectoryElement class]);
130     addElementClass(HTMLNames::divTag, [DOMHTMLDivElement class]);
131     addElementClass(HTMLNames::dlTag, [DOMHTMLDListElement class]);
132     addElementClass(HTMLNames::fieldsetTag, [DOMHTMLFieldSetElement class]);
133     addElementClass(HTMLNames::fontTag, [DOMHTMLFontElement class]);
134     addElementClass(HTMLNames::formTag, [DOMHTMLFormElement class]);
135     addElementClass(HTMLNames::frameTag, [DOMHTMLFrameElement class]);
136     addElementClass(HTMLNames::framesetTag, [DOMHTMLFrameSetElement class]);
137     addElementClass(HTMLNames::h1Tag, [DOMHTMLHeadingElement class]);
138     addElementClass(HTMLNames::h2Tag, [DOMHTMLHeadingElement class]);
139     addElementClass(HTMLNames::h3Tag, [DOMHTMLHeadingElement class]);
140     addElementClass(HTMLNames::h4Tag, [DOMHTMLHeadingElement class]);
141     addElementClass(HTMLNames::h5Tag, [DOMHTMLHeadingElement class]);
142     addElementClass(HTMLNames::h6Tag, [DOMHTMLHeadingElement class]);
143     addElementClass(HTMLNames::headTag, [DOMHTMLHeadElement class]);
144     addElementClass(HTMLNames::hrTag, [DOMHTMLHRElement class]);
145     addElementClass(HTMLNames::htmlTag, [DOMHTMLHtmlElement class]);
146     addElementClass(HTMLNames::iframeTag, [DOMHTMLIFrameElement class]);
147     addElementClass(HTMLNames::imgTag, [DOMHTMLImageElement class]);
148     addElementClass(HTMLNames::inputTag, [DOMHTMLInputElement class]);
149     addElementClass(HTMLNames::isindexTag, [DOMHTMLIsIndexElement class]);
150     addElementClass(HTMLNames::labelTag, [DOMHTMLLabelElement class]);
151     addElementClass(HTMLNames::legendTag, [DOMHTMLLegendElement class]);
152     addElementClass(HTMLNames::liTag, [DOMHTMLLIElement class]);
153     addElementClass(HTMLNames::linkTag, [DOMHTMLLinkElement class]);
154     addElementClass(HTMLNames::listingTag, [DOMHTMLPreElement class]);
155     addElementClass(HTMLNames::mapTag, [DOMHTMLMapElement class]);
156     addElementClass(HTMLNames::menuTag, [DOMHTMLMenuElement class]);
157     addElementClass(HTMLNames::metaTag, [DOMHTMLMetaElement class]);
158     addElementClass(HTMLNames::objectTag, [DOMHTMLObjectElement class]);
159     addElementClass(HTMLNames::olTag, [DOMHTMLOListElement class]);
160     addElementClass(HTMLNames::optgroupTag, [DOMHTMLOptGroupElement class]);
161     addElementClass(HTMLNames::optionTag, [DOMHTMLOptionElement class]);
162     addElementClass(HTMLNames::pTag, [DOMHTMLParagraphElement class]);
163     addElementClass(HTMLNames::paramTag, [DOMHTMLParamElement class]);
164     addElementClass(HTMLNames::preTag, [DOMHTMLPreElement class]);
165     addElementClass(HTMLNames::qTag, [DOMHTMLQuoteElement class]);
166     addElementClass(HTMLNames::scriptTag, [DOMHTMLScriptElement class]);
167     addElementClass(HTMLNames::keygenTag, [DOMHTMLSelectElement class]);
168     addElementClass(HTMLNames::selectTag, [DOMHTMLSelectElement class]);
169     addElementClass(HTMLNames::styleTag, [DOMHTMLStyleElement class]);
170     addElementClass(HTMLNames::tableTag, [DOMHTMLTableElement class]);
171     addElementClass(HTMLNames::tbodyTag, [DOMHTMLTableSectionElement class]);
172     addElementClass(HTMLNames::tdTag, [DOMHTMLTableCellElement class]);
173     addElementClass(HTMLNames::textareaTag, [DOMHTMLTextAreaElement class]);
174     addElementClass(HTMLNames::tfootTag, [DOMHTMLTableSectionElement class]);
175     addElementClass(HTMLNames::theadTag, [DOMHTMLTableSectionElement class]);
176     addElementClass(HTMLNames::titleTag, [DOMHTMLTitleElement class]);
177     addElementClass(HTMLNames::trTag, [DOMHTMLTableRowElement class]);
178     addElementClass(HTMLNames::ulTag, [DOMHTMLUListElement class]);
179
180 #if ENABLE(SVG)
181     addElementClass(SVGNames::aTag, [DOMSVGAElement class]);
182 #if ENABLE(SVG_EXPERIMENTAL_FEATURES)
183     addElementClass(SVGNames::animateTag, [DOMSVGAnimateElement class]);
184     addElementClass(SVGNames::animateColorTag, [DOMSVGAnimateColorElement class]);
185     addElementClass(SVGNames::animateTransformTag, [DOMSVGAnimateTransformElement class]);
186 #endif
187     addElementClass(SVGNames::circleTag, [DOMSVGCircleElement class]);
188     addElementClass(SVGNames::clipPathTag, [DOMSVGClipPathElement class]);
189     addElementClass(SVGNames::cursorTag, [DOMSVGCursorElement class]);
190     addElementClass(SVGNames::defsTag, [DOMSVGDefsElement class]);
191     addElementClass(SVGNames::descTag, [DOMSVGDescElement class]);
192     addElementClass(SVGNames::ellipseTag, [DOMSVGEllipseElement class]);
193 #if ENABLE(SVG_EXPERIMENTAL_FEATURES)
194     addElementClass(SVGNames::feBlendTag, [DOMSVGFEBlendElement class]);
195     addElementClass(SVGNames::feColorMatrixTag, [DOMSVGFEColorMatrixElement class]);
196     addElementClass(SVGNames::feComponentTransferTag, [DOMSVGFEComponentTransferElement class]);
197     addElementClass(SVGNames::feCompositeTag, [DOMSVGFECompositeElement class]);
198     addElementClass(SVGNames::feDiffuseLightingTag, [DOMSVGFEDiffuseLightingElement class]);
199     addElementClass(SVGNames::feDisplacementMapTag, [DOMSVGFEDisplacementMapElement class]);
200     addElementClass(SVGNames::feDistantLightTag, [DOMSVGFEDistantLightElement class]);
201     addElementClass(SVGNames::feFloodTag, [DOMSVGFEFloodElement class]);
202     addElementClass(SVGNames::feFuncATag, [DOMSVGFEFuncAElement class]);
203     addElementClass(SVGNames::feFuncBTag, [DOMSVGFEFuncBElement class]);
204     addElementClass(SVGNames::feFuncGTag, [DOMSVGFEFuncGElement class]);
205     addElementClass(SVGNames::feFuncRTag, [DOMSVGFEFuncRElement class]);
206     addElementClass(SVGNames::feGaussianBlurTag, [DOMSVGFEGaussianBlurElement class]);
207     addElementClass(SVGNames::feImageTag, [DOMSVGFEImageElement class]);
208     addElementClass(SVGNames::feMergeTag, [DOMSVGFEMergeElement class]);
209     addElementClass(SVGNames::feMergeNodeTag, [DOMSVGFEMergeNodeElement class]);
210     addElementClass(SVGNames::feOffsetTag, [DOMSVGFEOffsetElement class]);
211     addElementClass(SVGNames::fePointLightTag, [DOMSVGFEPointLightElement class]);
212     addElementClass(SVGNames::feSpecularLightingTag, [DOMSVGFESpecularLightingElement class]);
213     addElementClass(SVGNames::feSpotLightTag, [DOMSVGFESpotLightElement class]);
214     addElementClass(SVGNames::feTileTag, [DOMSVGFETileElement class]);
215     addElementClass(SVGNames::feTurbulenceTag, [DOMSVGFETurbulenceElement class]);
216     addElementClass(SVGNames::filterTag, [DOMSVGFilterElement class]);
217     addElementClass(SVGNames::foreignObjectTag, [DOMSVGForeignObjectElement class]);
218 #endif
219     addElementClass(SVGNames::gTag, [DOMSVGGElement class]);
220     addElementClass(SVGNames::imageTag, [DOMSVGImageElement class]);
221     addElementClass(SVGNames::lineTag, [DOMSVGLineElement class]);
222     addElementClass(SVGNames::linearGradientTag, [DOMSVGLinearGradientElement class]);
223     addElementClass(SVGNames::markerTag, [DOMSVGMarkerElement class]);
224     addElementClass(SVGNames::maskTag, [DOMSVGMaskElement class]);
225     addElementClass(SVGNames::metadataTag, [DOMSVGMetadataElement class]);
226     addElementClass(SVGNames::pathTag, [DOMSVGPathElement class]);
227     addElementClass(SVGNames::patternTag, [DOMSVGPatternElement class]);
228     addElementClass(SVGNames::polygonTag, [DOMSVGPolygonElement class]);
229     addElementClass(SVGNames::polylineTag, [DOMSVGPolylineElement class]);
230     addElementClass(SVGNames::radialGradientTag, [DOMSVGRadialGradientElement class]);
231     addElementClass(SVGNames::rectTag, [DOMSVGRectElement class]);
232     addElementClass(SVGNames::scriptTag, [DOMSVGScriptElement class]);
233     addElementClass(SVGNames::setTag, [DOMSVGSetElement class]);
234     addElementClass(SVGNames::stopTag, [DOMSVGStopElement class]);
235     addElementClass(SVGNames::styleTag, [DOMSVGStyleElement class]);
236     addElementClass(SVGNames::svgTag, [DOMSVGSVGElement class]);
237     addElementClass(SVGNames::switchTag, [DOMSVGSwitchElement class]);
238     addElementClass(SVGNames::symbolTag, [DOMSVGSymbolElement class]);
239     addElementClass(SVGNames::textTag, [DOMSVGTextElement class]);
240     addElementClass(SVGNames::titleTag, [DOMSVGTitleElement class]);
241     addElementClass(SVGNames::trefTag, [DOMSVGTRefElement class]);
242     addElementClass(SVGNames::tspanTag, [DOMSVGTSpanElement class]);
243     addElementClass(SVGNames::useTag, [DOMSVGUseElement class]);
244     addElementClass(SVGNames::viewTag, [DOMSVGViewElement class]);
245 #endif
246 }
247
248 static Class elementClass(const QualifiedName& tag, Class defaultClass)
249 {
250     if (!elementClassMap)
251         createElementClassMap();
252     Class objcClass = elementClassMap->get(tag.impl());
253     if (!objcClass)
254         objcClass = defaultClass;
255     return objcClass;
256 }
257
258 static NSArray *kit(const Vector<IntRect>& rects)
259 {
260     size_t size = rects.size();
261     NSMutableArray *array = [NSMutableArray arrayWithCapacity:size];
262     for (size_t i = 0; i < size; ++i)
263         [array addObject:[NSValue valueWithRect:rects[i]]];
264     return array;
265 }
266
267 } // namespace WebCore
268
269 @implementation DOMNode (WebCoreInternal)
270
271 // FIXME: should this go in the main implementation?
272 - (NSString *)description
273 {
274     if (!_internal)
275         return [NSString stringWithFormat:@"<%@: null>", [[self class] description], self];
276
277     NSString *value = [self nodeValue];
278     if (value)
279         return [NSString stringWithFormat:@"<%@ [%@]: %p '%@'>",
280             [[self class] description], [self nodeName], _internal, value];
281
282     return [NSString stringWithFormat:@"<%@ [%@]: %p>", [[self class] description], [self nodeName], _internal];
283 }
284
285 - (id)_initWithNode:(WebCore::Node *)impl
286 {
287     ASSERT(impl);
288
289     [super _init];
290     _internal = reinterpret_cast<DOMObjectInternal*>(impl);
291     impl->ref();
292     WebCore::addDOMWrapper(self, impl);
293     return self;
294 }
295
296 + (DOMNode *)_nodeWith:(WebCore::Node *)impl
297 {
298     if (!impl)
299         return nil;
300
301     id cachedInstance;
302     cachedInstance = WebCore::getDOMWrapper(impl);
303     if (cachedInstance)
304         return [[cachedInstance retain] autorelease];
305
306     Class wrapperClass = nil;
307     switch (impl->nodeType()) {
308         case WebCore::Node::ELEMENT_NODE:
309             if (impl->isHTMLElement())
310                 wrapperClass = WebCore::elementClass(static_cast<WebCore::HTMLElement*>(impl)->tagQName(), [DOMHTMLElement class]);
311 #if ENABLE(SVG)
312             else if (impl->isSVGElement())
313                 wrapperClass = WebCore::elementClass(static_cast<WebCore::SVGElement*>(impl)->tagQName(), [DOMSVGElement class]);
314 #endif
315             else
316                 wrapperClass = [DOMElement class];
317             break;
318         case WebCore::Node::ATTRIBUTE_NODE:
319             wrapperClass = [DOMAttr class];
320             break;
321         case WebCore::Node::TEXT_NODE:
322             wrapperClass = [DOMText class];
323             break;
324         case WebCore::Node::CDATA_SECTION_NODE:
325             wrapperClass = [DOMCDATASection class];
326             break;
327         case WebCore::Node::ENTITY_REFERENCE_NODE:
328             wrapperClass = [DOMEntityReference class];
329             break;
330         case WebCore::Node::ENTITY_NODE:
331             wrapperClass = [DOMEntity class];
332             break;
333         case WebCore::Node::PROCESSING_INSTRUCTION_NODE:
334             wrapperClass = [DOMProcessingInstruction class];
335             break;
336         case WebCore::Node::COMMENT_NODE:
337             wrapperClass = [DOMComment class];
338             break;
339         case WebCore::Node::DOCUMENT_NODE:
340             if (static_cast<WebCore::Document*>(impl)->isHTMLDocument())
341                 wrapperClass = [DOMHTMLDocument class];
342 #if ENABLE(SVG)
343             else if (static_cast<WebCore::Document*>(impl)->isSVGDocument())
344                 wrapperClass = [DOMSVGDocument class];
345 #endif
346             else
347                 wrapperClass = [DOMDocument class];
348             break;
349         case WebCore::Node::DOCUMENT_TYPE_NODE:
350             wrapperClass = [DOMDocumentType class];
351             break;
352         case WebCore::Node::DOCUMENT_FRAGMENT_NODE:
353             wrapperClass = [DOMDocumentFragment class];
354             break;
355         case WebCore::Node::NOTATION_NODE:
356             wrapperClass = [DOMNotation class];
357             break;
358         case WebCore::Node::XPATH_NAMESPACE_NODE:
359             // FIXME: Create an XPath objective C wrapper
360             // See http://bugs.webkit.org/show_bug.cgi?id=8755
361             return nil;
362     }
363     return [[[wrapperClass alloc] _initWithNode:impl] autorelease];
364 }
365
366 + (id <DOMEventTarget>)_eventTargetWith:(WebCore::EventTarget *)eventTarget
367 {
368     if (!eventTarget)
369         return nil;
370     
371     // We don't have an ObjC binding for XMLHttpRequest
372     return [DOMNode _nodeWith:eventTarget->toNode()];
373 }
374
375 - (WebCore::Node *)_node
376 {
377     return reinterpret_cast<WebCore::Node*>(_internal);
378 }
379
380 - (KJS::Bindings::RootObject*)_rootObject
381 {
382     if (WebCore::Node *n = [self _node]) {
383         if (WebCore::Frame* frame = n->document()->frame())
384             return frame->bindingRootObject();
385     }
386     return 0;
387 }
388
389 @end
390
391 @implementation DOMNode (DOMNodeExtensions)
392
393 // FIXME: This should be implemented in Node so we don't have to fetch the renderer.
394 // If it was, we could even autogenerate.
395 - (NSRect)boundingBox
396 {
397     WebCore::RenderObject *renderer = [self _node]->renderer();
398     if (renderer)
399         return renderer->absoluteBoundingBoxRect();
400     return NSZeroRect;
401 }
402
403 // FIXME: This should be implemented in Node so we don't have to fetch the renderer.
404 // If it was, we could even autogenerate.
405 - (NSArray *)lineBoxRects
406 {
407     WebCore::RenderObject *renderer = [self _node]->renderer();
408     if (renderer) {
409         Vector<WebCore::IntRect> rects;
410         renderer->addLineBoxRects(rects);
411         return kit(rects);
412     }
413     return nil;
414 }
415
416 @end
417
418 @implementation DOMRange (DOMRangeExtensions)
419
420 - (NSRect)boundingBox
421 {
422     return [self _range]->boundingBox();
423 }
424
425 - (NSArray *)lineBoxRects
426 {
427     Vector<WebCore::IntRect> rects;
428     [self _range]->addLineBoxRects(rects);
429     return kit(rects);
430 }
431
432 @end
433
434 // FIXME: this should be auto-generated
435 @implementation DOMNode (DOMEventTarget)
436
437 - (void)addEventListener:(NSString *)type listener:(id <DOMEventListener>)listener useCapture:(BOOL)useCapture
438 {
439     if (![self _node]->isEventTargetNode())
440         WebCore::raiseDOMException(DOM_NOT_SUPPORTED_ERR);
441     
442     WebCore::EventListener *wrapper = WebCore::ObjCEventListener::create(listener);
443     WebCore::EventTargetNodeCast([self _node])->addEventListener(type, wrapper, useCapture);
444     wrapper->deref();
445 }
446
447 - (void)addEventListener:(NSString *)type :(id <DOMEventListener>)listener :(BOOL)useCapture
448 {
449     // FIXME: this method can be removed once Mail changes to use the new method <rdar://problem/4746649>
450     [self addEventListener:type listener:listener useCapture:useCapture];
451 }
452
453 - (void)removeEventListener:(NSString *)type listener:(id <DOMEventListener>)listener useCapture:(BOOL)useCapture
454 {
455     if (![self _node]->isEventTargetNode())
456         WebCore::raiseDOMException(DOM_NOT_SUPPORTED_ERR);
457
458     if (WebCore::EventListener *wrapper = WebCore::ObjCEventListener::find(listener))
459         WebCore::EventTargetNodeCast([self _node])->removeEventListener(type, wrapper, useCapture);
460 }
461
462 - (void)removeEventListener:(NSString *)type :(id <DOMEventListener>)listener :(BOOL)useCapture
463 {
464     // FIXME: this method can be removed once Mail changes to use the new method <rdar://problem/4746649>
465     [self removeEventListener:type listener:listener useCapture:useCapture];
466 }
467
468 - (BOOL)dispatchEvent:(DOMEvent *)event
469 {
470     if (![self _node]->isEventTargetNode())
471         WebCore::raiseDOMException(DOM_NOT_SUPPORTED_ERR);
472
473     WebCore::ExceptionCode ec = 0;
474     BOOL result = WebCore::EventTargetNodeCast([self _node])->dispatchEvent([event _event], ec);
475     WebCore::raiseOnDOMError(ec);
476     return result;
477 }
478
479 @end
480
481 //------------------------------------------------------------------------------------------
482 // DOMElement
483
484 // FIXME: this should be auto-generated in DOMElement.mm
485 @implementation DOMElement (DOMElementAppKitExtensions)
486
487 // FIXME: this should be implemented in the implementation
488 - (NSImage*)image
489 {
490     WebCore::RenderObject* renderer = [self _element]->renderer();
491     if (renderer && renderer->isImage()) {
492         WebCore::RenderImage* img = static_cast<WebCore::RenderImage*>(renderer);
493         if (img->cachedImage() && !img->cachedImage()->errorOccurred())
494             return img->cachedImage()->image()->getNSImage();
495     }
496     return nil;
497 }
498
499 @end
500
501 @implementation DOMElement (WebPrivate)
502
503 // FIXME: this should be implemented in the implementation
504 - (NSFont *)_font
505 {
506     WebCore::RenderObject* renderer = [self _element]->renderer();
507     if (renderer)
508         return renderer->style()->font().primaryFont()->getNSFont();
509     return nil;
510 }
511
512 // FIXME: this should be implemented in the implementation
513 - (NSData *)_imageTIFFRepresentation
514 {
515     WebCore::RenderObject* renderer = [self _element]->renderer();
516     if (renderer && renderer->isImage()) {
517         WebCore::RenderImage* img = static_cast<WebCore::RenderImage*>(renderer);
518         if (img->cachedImage() && !img->cachedImage()->errorOccurred())
519             return (NSData*)(img->cachedImage()->image()->getTIFFRepresentation());
520     }
521     return nil;
522 }
523
524 // FIXME: this should be implemented in the implementation
525 - (NSURL *)_getURLAttribute:(NSString *)name
526 {
527     ASSERT(name);
528     WebCore::Element* element = [self _element];
529     ASSERT(element);
530     return WebCore::KURL(element->document()->completeURL(parseURL(element->getAttribute(name)).deprecatedString())).getNSURL();
531 }
532
533 // FIXME: this should be implemented in the implementation
534 - (void *)_NPObject
535 {
536     WebCore::Element* element = [self _element];
537     if (element->hasTagName(WebCore::HTMLNames::appletTag) || element->hasTagName(WebCore::HTMLNames::embedTag) || element->hasTagName(WebCore::HTMLNames::objectTag))
538         return static_cast<WebCore::HTMLPlugInElement*>(element)->getNPObject();
539     return 0;
540 }
541
542 // FIXME: this should be implemented in the implementation
543 - (BOOL)isFocused
544 {
545     WebCore::Element* impl = [self _element];
546     if (impl->document()->focusedNode() == impl)
547         return YES;
548     return NO;
549 }
550
551 @end
552
553
554 //------------------------------------------------------------------------------------------
555 // DOMRange
556
557 @implementation DOMRange (WebPrivate)
558
559 - (NSString *)description
560 {
561     if (!_internal)
562         return @"<DOMRange: null>";
563     return [NSString stringWithFormat:@"<DOMRange: %@ %d %@ %d>",
564                [self startContainer], [self startOffset], [self endContainer], [self endOffset]];
565 }
566
567 // FIXME: this should be removed as soon as all internal Apple uses of it have been replaced with
568 // calls to the public method - (NSString *)text.
569 - (NSString *)_text
570 {
571     return [self text];
572 }
573
574 @end
575
576
577 //------------------------------------------------------------------------------------------
578 // DOMNodeFilter
579
580 // FIXME: This implementation should be in it's own file.
581
582 @implementation DOMNodeFilter
583
584 - (id)_initWithNodeFilter:(WebCore::NodeFilter *)impl
585 {
586     ASSERT(impl);
587
588     [super _init];
589     _internal = reinterpret_cast<DOMObjectInternal*>(impl);
590     impl->ref();
591     WebCore::addDOMWrapper(self, impl);
592     return self;
593 }
594
595 + (DOMNodeFilter *)_nodeFilterWith:(WebCore::NodeFilter *)impl
596 {
597     if (!impl)
598         return nil;
599     
600     id cachedInstance;
601     cachedInstance = WebCore::getDOMWrapper(impl);
602     if (cachedInstance)
603         return [[cachedInstance retain] autorelease];
604     
605     return [[[self alloc] _initWithNodeFilter:impl] autorelease];
606 }
607
608 - (WebCore::NodeFilter *)_nodeFilter
609 {
610     return reinterpret_cast<WebCore::NodeFilter*>(_internal);
611 }
612
613 - (void)dealloc
614 {
615     if (_internal)
616         reinterpret_cast<WebCore::NodeFilter*>(_internal)->deref();
617     [super dealloc];
618 }
619
620 - (void)finalize
621 {
622     if (_internal)
623         reinterpret_cast<WebCore::NodeFilter*>(_internal)->deref();
624     [super finalize];
625 }
626
627 - (short)acceptNode:(DOMNode *)node
628 {
629     return [self _nodeFilter]->acceptNode([node _node]);
630 }
631
632 @end
633
634
635 //------------------------------------------------------------------------------------------
636 // ObjCNodeFilterCondition
637
638 class ObjCNodeFilterCondition : public WebCore::NodeFilterCondition {
639 public:
640     ObjCNodeFilterCondition(id <DOMNodeFilter>);
641     virtual ~ObjCNodeFilterCondition();
642     virtual short acceptNode(WebCore::Node*) const;
643
644 private:
645     ObjCNodeFilterCondition(const ObjCNodeFilterCondition&);
646     ObjCNodeFilterCondition &operator=(const ObjCNodeFilterCondition&);
647
648     id <DOMNodeFilter> m_filter;
649 };
650
651 ObjCNodeFilterCondition::ObjCNodeFilterCondition(id <DOMNodeFilter> filter)
652     : m_filter(filter)
653 {
654     ASSERT(m_filter);
655     HardRetain(m_filter);
656 }
657
658 ObjCNodeFilterCondition::~ObjCNodeFilterCondition()
659 {
660     HardRelease(m_filter);
661 }
662
663 short ObjCNodeFilterCondition::acceptNode(WebCore::Node* node) const
664 {
665     if (!node)
666         return WebCore::NodeFilter::FILTER_REJECT;
667     return [m_filter acceptNode:[DOMNode _nodeWith:node]];
668 }
669
670
671 //------------------------------------------------------------------------------------------
672 // DOMDocument (DOMDocumentTraversal)
673
674 // FIXME: this should be auto-generated in DOMDocument.mm
675 @implementation DOMDocument (DOMDocumentTraversal)
676
677 - (DOMNodeIterator *)createNodeIterator:(DOMNode *)root whatToShow:(unsigned)whatToShow filter:(id <DOMNodeFilter>)filter expandEntityReferences:(BOOL)expandEntityReferences
678 {
679     RefPtr<WebCore::NodeFilter> cppFilter;
680     if (filter)
681         cppFilter = new WebCore::NodeFilter(new ObjCNodeFilterCondition(filter));
682     WebCore::ExceptionCode ec = 0;
683     RefPtr<WebCore::NodeIterator> impl = [self _document]->createNodeIterator([root _node], whatToShow, cppFilter, expandEntityReferences, ec);
684     WebCore::raiseOnDOMError(ec);
685     return [DOMNodeIterator _nodeIteratorWith:impl.get() filter:filter];
686 }
687
688 - (DOMTreeWalker *)createTreeWalker:(DOMNode *)root whatToShow:(unsigned)whatToShow filter:(id <DOMNodeFilter>)filter expandEntityReferences:(BOOL)expandEntityReferences
689 {
690     RefPtr<WebCore::NodeFilter> cppFilter;
691     if (filter)
692         cppFilter = new WebCore::NodeFilter(new ObjCNodeFilterCondition(filter));
693     WebCore::ExceptionCode ec = 0;
694     RefPtr<WebCore::TreeWalker> impl = [self _document]->createTreeWalker([root _node], whatToShow, cppFilter, expandEntityReferences, ec);
695     WebCore::raiseOnDOMError(ec);
696     return [DOMTreeWalker _treeWalkerWith:impl.get() filter:filter];
697 }
698
699 @end
700
701 @implementation DOMDocument (DOMDocumentTraversalDeprecated)
702
703 - (DOMNodeIterator *)createNodeIterator:(DOMNode *)root :(unsigned)whatToShow :(id <DOMNodeFilter>)filter :(BOOL)expandEntityReferences
704 {
705     return [self createNodeIterator:root whatToShow:whatToShow filter:filter expandEntityReferences:expandEntityReferences];
706 }
707
708 - (DOMTreeWalker *)createTreeWalker:(DOMNode *)root :(unsigned)whatToShow :(id <DOMNodeFilter>)filter :(BOOL)expandEntityReferences
709 {
710     return [self createTreeWalker:root whatToShow:whatToShow filter:filter expandEntityReferences:expandEntityReferences];
711 }
712
713 @end
714
715
716 //------------------------------------------------------------------------------------------
717 // ObjCEventListener
718
719 namespace WebCore {
720
721 ObjCEventListener* ObjCEventListener::find(id <DOMEventListener> listener)
722 {
723     if (ListenerMap* map = listenerMap)
724         return map->get(listener);
725     return 0;
726 }
727
728 ObjCEventListener *ObjCEventListener::create(id <DOMEventListener> listener)
729 {
730     ObjCEventListener* wrapper = find(listener);
731     if (!wrapper)
732         wrapper = new ObjCEventListener(listener);
733     wrapper->ref();
734     return wrapper;
735 }
736
737 ObjCEventListener::ObjCEventListener(id <DOMEventListener> listener)
738     : m_listener([listener retain])
739 {
740     ListenerMap* map = listenerMap;
741     if (!map) {
742         map = new ListenerMap;
743         listenerMap = map;
744     }
745     map->set(listener, this);
746 }
747
748 ObjCEventListener::~ObjCEventListener()
749 {
750     listenerMap->remove(m_listener);
751     [m_listener release];
752 }
753
754 void ObjCEventListener::handleEvent(Event* event, bool)
755 {
756     [m_listener handleEvent:[DOMEvent _eventWith:event]];
757 }
758
759 } // namespace WebCore