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