27b10dc0a0543efabe169e2599398f7c74756065
[WebKit-https.git] / Tools / DumpRenderTree / mac / AccessibilityUIElementMac.mm
1 /*
2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #import "config.h"
27 #import "DumpRenderTree.h"
28 #import "AccessibilityUIElement.h"
29
30 #import <Foundation/Foundation.h>
31 #import <JavaScriptCore/JSRetainPtr.h>
32 #import <JavaScriptCore/JSStringRef.h>
33 #import <JavaScriptCore/JSStringRefCF.h>
34 #import <WebKit/WebFrame.h>
35 #import <WebKit/WebHTMLView.h>
36 #import <WebKit/WebTypesInternal.h>
37 #import <wtf/RetainPtr.h>
38 #import <wtf/Vector.h>
39
40
41 #ifndef NSAccessibilityOwnsAttribute
42 #define NSAccessibilityOwnsAttribute @"AXOwns"
43 #endif
44
45 #ifndef NSAccessibilityGrabbedAttribute
46 #define NSAccessibilityGrabbedAttribute @"AXGrabbed"
47 #endif
48
49 #ifndef NSAccessibilityDropEffectsAttribute
50 #define NSAccessibilityDropEffectsAttribute @"AXDropEffects"
51 #endif
52
53 // If an unsupported attribute is passed in, it will raise an accessibility exception. These are usually caught by the Accessibility Runtime to inform
54 // the AX client app of the error. However, DRT is the AX client app, so it must catch these exceptions.
55 #define BEGIN_AX_OBJC_EXCEPTIONS @try {
56 #define END_AX_OBJC_EXCEPTIONS } @catch(NSException *e) { if (![[e name] isEqualToString:NSAccessibilityException]) @throw; }
57
58
59 typedef void (*AXPostedNotificationCallback)(id element, NSString* notification, void* context);
60
61 @interface NSObject (WebKitAccessibilityAdditions)
62 - (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount;
63 - (void)accessibilitySetShouldRepostNotifications:(BOOL)repost;
64 - (NSUInteger)accessibilityIndexOfChild:(id)child;
65 - (NSUInteger)accessibilityArrayAttributeCount:(NSString *)attribute;
66 @end
67
68 @interface NSString (JSStringRefAdditions)
69 + (NSString *)stringWithJSStringRef:(JSStringRef)jsStringRef;
70 - (JSStringRef)createJSStringRef;
71 @end
72
73 @implementation NSString (JSStringRefAdditions)
74
75 + (NSString *)stringWithJSStringRef:(JSStringRef)jsStringRef
76 {
77     if (!jsStringRef)
78         return NULL;
79     
80     CFStringRef cfString = JSStringCopyCFString(kCFAllocatorDefault, jsStringRef);
81     return [(NSString *)cfString autorelease];
82 }
83
84 - (JSStringRef)createJSStringRef
85 {
86     return JSStringCreateWithCFString((CFStringRef)self);
87 }
88
89 @end
90
91 @interface AccessibilityNotificationHandler : NSObject
92 {
93     id m_platformElement;
94     JSObjectRef m_notificationFunctionCallback;
95 }
96
97 @end
98
99 @implementation AccessibilityNotificationHandler
100
101 - (id)initWithPlatformElement:(id)platformElement
102 {
103     self = [super init];
104
105     m_platformElement = platformElement;
106     
107     // Once an object starts requesting notifications, it's on for the duration of the program.
108     // This is to avoid any race conditions between tests turning this flag on and off. Instead
109     // AccessibilityNotificationHandler can just listen when they want to.
110     [m_platformElement accessibilitySetShouldRepostNotifications:YES];
111     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_notificationReceived:) name:@"AXDRTNotification" object:nil];
112
113     return self;
114 }
115  
116 - (void)dealloc
117 {
118     [[NSNotificationCenter defaultCenter] removeObserver:self];
119     JSValueUnprotect([mainFrame globalContext], m_notificationFunctionCallback);
120     m_notificationFunctionCallback = 0;
121     
122     [super dealloc];
123 }
124
125 - (void)_notificationReceived:(NSNotification *)notification
126 {
127     NSString *notificationName = [[notification userInfo] objectForKey:@"notificationName"];
128     if (!notificationName)
129         return;
130     
131     JSRetainPtr<JSStringRef> jsNotification(Adopt, [notificationName createJSStringRef]);
132     JSValueRef argument = JSValueMakeString([mainFrame globalContext], jsNotification.get());
133     JSObjectCallAsFunction([mainFrame globalContext], m_notificationFunctionCallback, 0, 1, &argument, 0);
134 }
135
136 - (void)setCallback:(JSObjectRef)callback
137 {
138     if (!callback)
139         return;
140  
141     // Release the old callback.
142     if (m_notificationFunctionCallback) 
143         JSValueUnprotect([mainFrame globalContext], m_notificationFunctionCallback);
144     
145     m_notificationFunctionCallback = callback;
146     JSValueProtect([mainFrame globalContext], m_notificationFunctionCallback);
147 }
148
149 @end
150
151 AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element)
152     : m_element(element)
153     , m_notificationHandler(0)
154 {
155     // FIXME: ap@webkit.org says ObjC objects need to be CFRetained/CFRelease to be GC-compliant on the mac.
156     [m_element retain];
157 }
158
159 AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other)
160     : m_element(other.m_element)
161     , m_notificationHandler(0)
162 {
163     [m_element retain];
164 }
165
166 AccessibilityUIElement::~AccessibilityUIElement()
167 {
168     // The notification handler should be nil because removeNotificationListener() should have been called in the test.
169     ASSERT(!m_notificationHandler);
170     [m_element release];
171 }
172
173 static NSString* descriptionOfValue(id valueObject, id focusedAccessibilityObject)
174 {
175     if (!valueObject)
176         return NULL;
177
178     if ([valueObject isKindOfClass:[NSArray class]])
179         return [NSString stringWithFormat:@"<array of size %d>", [(NSArray*)valueObject count]];
180
181     if ([valueObject isKindOfClass:[NSNumber class]])
182         return [(NSNumber*)valueObject stringValue];
183
184     if ([valueObject isKindOfClass:[NSValue class]]) {
185         NSString* type = [NSString stringWithCString:[valueObject objCType] encoding:NSASCIIStringEncoding];
186         NSValue* value = (NSValue*)valueObject;
187         if ([type rangeOfString:@"NSRect"].length > 0)
188             return [NSString stringWithFormat:@"NSRect: %@", NSStringFromRect([value rectValue])];
189         if ([type rangeOfString:@"NSPoint"].length > 0)
190             return [NSString stringWithFormat:@"NSPoint: %@", NSStringFromPoint([value pointValue])];
191         if ([type rangeOfString:@"NSSize"].length > 0)
192             return [NSString stringWithFormat:@"NSSize: %@", NSStringFromSize([value sizeValue])];
193         if ([type rangeOfString:@"NSRange"].length > 0)
194             return [NSString stringWithFormat:@"NSRange: %@", NSStringFromRange([value rangeValue])];
195     }
196
197     // Strip absolute URL paths
198     NSString* description = [valueObject description];
199     NSRange range = [description rangeOfString:@"LayoutTests"];
200     if (range.length)
201         return [description substringFromIndex:range.location];
202
203     // Strip pointer locations
204     if ([description rangeOfString:@"0x"].length) {
205         NSString* role = [focusedAccessibilityObject accessibilityAttributeValue:NSAccessibilityRoleAttribute];
206         NSString* title = [focusedAccessibilityObject accessibilityAttributeValue:NSAccessibilityTitleAttribute];
207         if ([title length])
208             return [NSString stringWithFormat:@"<%@: '%@'>", role, title];
209         return [NSString stringWithFormat:@"<%@>", role];
210     }
211     
212     return [valueObject description];
213 }
214
215 static NSString* attributesOfElement(id accessibilityObject)
216 {
217     NSArray* supportedAttributes = [accessibilityObject accessibilityAttributeNames];
218
219     NSMutableString* attributesString = [NSMutableString string];
220     for (NSUInteger i = 0; i < [supportedAttributes count]; ++i) {
221         NSString* attribute = [supportedAttributes objectAtIndex:i];
222         
223         // Right now, position provides useless and screen-specific information, so we do not
224         // want to include it for the sake of universally passing tests.
225         if ([attribute isEqualToString:@"AXPosition"])
226             continue;
227         
228         // accessibilityAttributeValue: can throw an if an attribute is not returned.
229         // For DumpRenderTree's purpose, we should ignore those exceptions
230         BEGIN_AX_OBJC_EXCEPTIONS
231         id valueObject = [accessibilityObject accessibilityAttributeValue:attribute];
232         NSString* value = descriptionOfValue(valueObject, accessibilityObject);
233         [attributesString appendFormat:@"%@: %@\n", attribute, value];
234         END_AX_OBJC_EXCEPTIONS
235     }
236     
237     return attributesString;
238 }
239
240 static JSStringRef concatenateAttributeAndValue(NSString* attribute, NSString* value)
241 {
242     Vector<UniChar> buffer([attribute length]);
243     [attribute getCharacters:buffer.data()];
244     buffer.append(':');
245     buffer.append(' ');
246
247     Vector<UniChar> valueBuffer([value length]);
248     [value getCharacters:valueBuffer.data()];
249     buffer.append(valueBuffer);
250
251     return JSStringCreateWithCharacters(buffer.data(), buffer.size());
252 }
253
254 static void convertNSArrayToVector(NSArray* array, Vector<AccessibilityUIElement>& elementVector)
255 {
256     NSUInteger count = [array count];
257     for (NSUInteger i = 0; i < count; ++i)
258         elementVector.append(AccessibilityUIElement([array objectAtIndex:i]));
259 }
260
261 static JSStringRef descriptionOfElements(Vector<AccessibilityUIElement>& elementVector)
262 {
263     NSMutableString* allElementString = [NSMutableString string];
264     size_t size = elementVector.size();
265     for (size_t i = 0; i < size; ++i) {
266         NSString* attributes = attributesOfElement(elementVector[i].platformUIElement());
267         [allElementString appendFormat:@"%@\n------------\n", attributes];
268     }
269     
270     return [allElementString createJSStringRef];
271 }
272
273 void AccessibilityUIElement::getLinkedUIElements(Vector<AccessibilityUIElement>& elementVector)
274 {
275     BEGIN_AX_OBJC_EXCEPTIONS
276     NSArray* linkedElements = [m_element accessibilityAttributeValue:NSAccessibilityLinkedUIElementsAttribute];
277     convertNSArrayToVector(linkedElements, elementVector);
278     END_AX_OBJC_EXCEPTIONS
279 }
280
281 void AccessibilityUIElement::getDocumentLinks(Vector<AccessibilityUIElement>& elementVector)
282 {
283     BEGIN_AX_OBJC_EXCEPTIONS
284     NSArray* linkElements = [m_element accessibilityAttributeValue:@"AXLinkUIElements"];
285     convertNSArrayToVector(linkElements, elementVector);
286     END_AX_OBJC_EXCEPTIONS
287 }
288
289 void AccessibilityUIElement::getChildren(Vector<AccessibilityUIElement>& elementVector)
290 {
291     BEGIN_AX_OBJC_EXCEPTIONS
292     NSArray* children = [m_element accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
293     convertNSArrayToVector(children, elementVector);
294     END_AX_OBJC_EXCEPTIONS
295 }
296
297 void AccessibilityUIElement::getChildrenWithRange(Vector<AccessibilityUIElement>& elementVector, unsigned location, unsigned length)
298 {
299     BEGIN_AX_OBJC_EXCEPTIONS
300     NSArray* children = [m_element accessibilityArrayAttributeValues:NSAccessibilityChildrenAttribute index:location maxCount:length];
301     convertNSArrayToVector(children, elementVector);
302     END_AX_OBJC_EXCEPTIONS
303 }
304
305 int AccessibilityUIElement::childrenCount()
306 {
307     Vector<AccessibilityUIElement> children;
308     getChildren(children);
309     
310     return children.size();
311 }
312
313 AccessibilityUIElement AccessibilityUIElement::elementAtPoint(int x, int y)
314 {
315     id element = [m_element accessibilityHitTest:NSMakePoint(x, y)];
316     if (!element)
317         return nil;
318     
319     return AccessibilityUIElement(element); 
320 }
321
322 unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
323 {
324     return [m_element accessibilityIndexOfChild:element->platformUIElement()];
325 }
326
327 AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index)
328 {
329     Vector<AccessibilityUIElement> children;
330     getChildrenWithRange(children, index, 1);
331
332     if (children.size() == 1)
333         return children[0];
334     return 0;
335 }
336
337 AccessibilityUIElement AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
338 {
339     BEGIN_AX_OBJC_EXCEPTIONS
340     NSArray* objects = [m_element accessibilityAttributeValue:NSAccessibilityLinkedUIElementsAttribute];
341     if (index < [objects count])
342         return [objects objectAtIndex:index];
343     END_AX_OBJC_EXCEPTIONS
344     
345     return 0;
346 }
347
348 AccessibilityUIElement AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
349 {
350     BEGIN_AX_OBJC_EXCEPTIONS
351     NSArray* objects = [m_element accessibilityAttributeValue:NSAccessibilityOwnsAttribute];
352     if (index < [objects count])
353         return [objects objectAtIndex:index];
354     END_AX_OBJC_EXCEPTIONS
355     
356     return 0;
357 }
358
359 AccessibilityUIElement AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
360 {
361     BEGIN_AX_OBJC_EXCEPTIONS
362     NSArray* objects = [m_element accessibilityAttributeValue:NSAccessibilityLinkedUIElementsAttribute];
363     if (index < [objects count])
364         return [objects objectAtIndex:index];
365     END_AX_OBJC_EXCEPTIONS
366     
367     return 0;
368 }
369
370 AccessibilityUIElement AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
371 {
372     BEGIN_AX_OBJC_EXCEPTIONS
373     NSArray* rows = [m_element accessibilityAttributeValue:NSAccessibilityDisclosedRowsAttribute];
374     if (index < [rows count])
375         return [rows objectAtIndex:index];
376     END_AX_OBJC_EXCEPTIONS
377
378     return 0;
379 }
380
381 AccessibilityUIElement AccessibilityUIElement::selectedChildAtIndex(unsigned index) const
382 {
383     BEGIN_AX_OBJC_EXCEPTIONS
384     NSArray* array = [m_element accessibilityAttributeValue:NSAccessibilitySelectedChildrenAttribute];
385     if (index < [array count])
386         return [array objectAtIndex:index];
387     END_AX_OBJC_EXCEPTIONS
388     
389     return 0;
390 }
391
392 unsigned AccessibilityUIElement::selectedChildrenCount() const
393 {
394     BEGIN_AX_OBJC_EXCEPTIONS
395     return [m_element accessibilityArrayAttributeCount:NSAccessibilitySelectedChildrenAttribute];
396     END_AX_OBJC_EXCEPTIONS
397
398     return 0;
399 }
400
401 AccessibilityUIElement AccessibilityUIElement::selectedRowAtIndex(unsigned index)
402 {
403     BEGIN_AX_OBJC_EXCEPTIONS
404     NSArray* rows = [m_element accessibilityAttributeValue:NSAccessibilitySelectedRowsAttribute];
405     if (index < [rows count])
406         return [rows objectAtIndex:index];
407     END_AX_OBJC_EXCEPTIONS
408     
409     return 0;
410 }
411
412 AccessibilityUIElement AccessibilityUIElement::titleUIElement()
413 {
414     BEGIN_AX_OBJC_EXCEPTIONS
415     id accessibilityObject = [m_element accessibilityAttributeValue:NSAccessibilityTitleUIElementAttribute];
416     if (accessibilityObject)
417         return AccessibilityUIElement(accessibilityObject);
418     END_AX_OBJC_EXCEPTIONS
419     
420     return 0;
421 }
422
423 AccessibilityUIElement AccessibilityUIElement::parentElement()
424 {
425     BEGIN_AX_OBJC_EXCEPTIONS
426     id accessibilityObject = [m_element accessibilityAttributeValue:NSAccessibilityParentAttribute];
427     if (accessibilityObject)
428         return AccessibilityUIElement(accessibilityObject);
429     END_AX_OBJC_EXCEPTIONS
430     
431     return 0;
432 }
433
434 AccessibilityUIElement AccessibilityUIElement::disclosedByRow()
435 {
436     BEGIN_AX_OBJC_EXCEPTIONS
437     id accessibilityObject = [m_element accessibilityAttributeValue:NSAccessibilityDisclosedByRowAttribute];
438     if (accessibilityObject)
439         return AccessibilityUIElement(accessibilityObject);
440     END_AX_OBJC_EXCEPTIONS
441     
442     return 0;
443 }
444
445 JSStringRef AccessibilityUIElement::attributesOfLinkedUIElements()
446 {
447     Vector<AccessibilityUIElement> linkedElements;
448     getLinkedUIElements(linkedElements);
449     return descriptionOfElements(linkedElements);
450 }
451
452 JSStringRef AccessibilityUIElement::attributesOfDocumentLinks()
453 {
454     Vector<AccessibilityUIElement> linkElements;
455     getDocumentLinks(linkElements);
456     return descriptionOfElements(linkElements);
457 }
458
459 JSStringRef AccessibilityUIElement::attributesOfChildren()
460 {
461     Vector<AccessibilityUIElement> children;
462     getChildren(children);
463     return descriptionOfElements(children);
464 }
465
466 JSStringRef AccessibilityUIElement::allAttributes()
467 {
468     NSString* attributes = attributesOfElement(m_element);
469     return [attributes createJSStringRef];
470 }
471
472 JSStringRef AccessibilityUIElement::stringAttributeValue(JSStringRef attribute)
473 {
474     BEGIN_AX_OBJC_EXCEPTIONS
475     id value = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
476     if ([value isKindOfClass:[NSString class]])
477         return [value createJSStringRef];
478     END_AX_OBJC_EXCEPTIONS
479
480     return 0;
481 }
482
483 AccessibilityUIElement AccessibilityUIElement::uiElementAttributeValue(JSStringRef attribute) const
484 {
485     BEGIN_AX_OBJC_EXCEPTIONS
486     id uiElement = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
487     return AccessibilityUIElement(uiElement);
488     END_AX_OBJC_EXCEPTIONS
489     
490     return 0;
491 }
492
493
494 double AccessibilityUIElement::numberAttributeValue(JSStringRef attribute)
495 {
496     BEGIN_AX_OBJC_EXCEPTIONS
497     id value = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
498     if ([value isKindOfClass:[NSNumber class]])
499         return [value doubleValue];
500     END_AX_OBJC_EXCEPTIONS
501     
502     return 0;
503 }
504
505 bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute)
506 {
507     BEGIN_AX_OBJC_EXCEPTIONS
508     id value = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
509     if ([value isKindOfClass:[NSNumber class]])
510         return [value boolValue];
511     END_AX_OBJC_EXCEPTIONS
512     
513     return false;
514 }
515
516 bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute)
517 {
518     BEGIN_AX_OBJC_EXCEPTIONS
519     return [m_element accessibilityIsAttributeSettable:[NSString stringWithJSStringRef:attribute]];
520     END_AX_OBJC_EXCEPTIONS
521     
522     return false;
523 }
524
525 bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute)
526 {
527     BEGIN_AX_OBJC_EXCEPTIONS
528     return [[m_element accessibilityAttributeNames] containsObject:[NSString stringWithJSStringRef:attribute]];
529     END_AX_OBJC_EXCEPTIONS
530     
531     return false;
532 }
533
534 JSStringRef AccessibilityUIElement::parameterizedAttributeNames()
535 {
536     NSArray* supportedParameterizedAttributes = [m_element accessibilityParameterizedAttributeNames];
537     
538     NSMutableString* attributesString = [NSMutableString string];
539     for (NSUInteger i = 0; i < [supportedParameterizedAttributes count]; ++i) {
540         [attributesString appendFormat:@"%@\n", [supportedParameterizedAttributes objectAtIndex:i]];
541     }
542     
543     return [attributesString createJSStringRef];
544 }
545
546 JSStringRef AccessibilityUIElement::role()
547 {
548     BEGIN_AX_OBJC_EXCEPTIONS
549     NSString *role = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityRoleAttribute], m_element);
550     return concatenateAttributeAndValue(@"AXRole", role);
551     END_AX_OBJC_EXCEPTIONS
552     
553     return 0;
554 }
555
556 JSStringRef AccessibilityUIElement::subrole()
557 {
558     BEGIN_AX_OBJC_EXCEPTIONS
559     NSString* role = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilitySubroleAttribute], m_element);
560     return concatenateAttributeAndValue(@"AXSubrole", role);
561     END_AX_OBJC_EXCEPTIONS
562
563     return 0;
564 }
565
566 JSStringRef AccessibilityUIElement::roleDescription()
567 {
568     BEGIN_AX_OBJC_EXCEPTIONS
569     NSString* role = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityRoleDescriptionAttribute], m_element);
570     return concatenateAttributeAndValue(@"AXRoleDescription", role);
571     END_AX_OBJC_EXCEPTIONS
572     
573     return 0;
574 }
575
576 JSStringRef AccessibilityUIElement::title()
577 {
578     BEGIN_AX_OBJC_EXCEPTIONS
579     NSString* title = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityTitleAttribute], m_element);
580     return concatenateAttributeAndValue(@"AXTitle", title);
581     END_AX_OBJC_EXCEPTIONS
582
583     return 0;
584 }
585
586 JSStringRef AccessibilityUIElement::description()
587 {
588     BEGIN_AX_OBJC_EXCEPTIONS
589     id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityDescriptionAttribute], m_element);
590     return concatenateAttributeAndValue(@"AXDescription", description);
591     END_AX_OBJC_EXCEPTIONS
592
593     return 0;
594 }
595
596 JSStringRef AccessibilityUIElement::orientation() const
597 {
598     BEGIN_AX_OBJC_EXCEPTIONS
599     id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityOrientationAttribute], m_element);
600     return concatenateAttributeAndValue(@"AXOrientation", description);    
601     END_AX_OBJC_EXCEPTIONS
602
603     return 0;
604 }
605
606 JSStringRef AccessibilityUIElement::stringValue()
607 {
608     BEGIN_AX_OBJC_EXCEPTIONS
609     id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityValueAttribute], m_element);
610     return concatenateAttributeAndValue(@"AXValue", description);
611     END_AX_OBJC_EXCEPTIONS
612
613     return 0;
614 }
615
616 JSStringRef AccessibilityUIElement::language()
617 {
618     BEGIN_AX_OBJC_EXCEPTIONS
619     id description = descriptionOfValue([m_element accessibilityAttributeValue:@"AXLanguage"], m_element);
620     return concatenateAttributeAndValue(@"AXLanguage", description);
621     END_AX_OBJC_EXCEPTIONS
622
623     return 0;
624 }
625
626 JSStringRef AccessibilityUIElement::helpText() const
627 {
628     BEGIN_AX_OBJC_EXCEPTIONS
629     id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityHelpAttribute], m_element);
630     return concatenateAttributeAndValue(@"AXHelp", description);
631     END_AX_OBJC_EXCEPTIONS
632     
633     return 0;
634 }
635
636 double AccessibilityUIElement::x()
637 {
638     BEGIN_AX_OBJC_EXCEPTIONS
639     NSValue* positionValue = [m_element accessibilityAttributeValue:NSAccessibilityPositionAttribute];
640     return static_cast<double>([positionValue pointValue].x);    
641     END_AX_OBJC_EXCEPTIONS
642     
643     return 0.0f;
644 }
645
646 double AccessibilityUIElement::y()
647 {
648     BEGIN_AX_OBJC_EXCEPTIONS
649     NSValue* positionValue = [m_element accessibilityAttributeValue:NSAccessibilityPositionAttribute];
650     return static_cast<double>([positionValue pointValue].y);    
651     END_AX_OBJC_EXCEPTIONS
652     
653     return 0.0f;
654 }
655
656 double AccessibilityUIElement::width()
657 {
658     BEGIN_AX_OBJC_EXCEPTIONS
659     NSValue* sizeValue = [m_element accessibilityAttributeValue:NSAccessibilitySizeAttribute];
660     return static_cast<double>([sizeValue sizeValue].width);
661     END_AX_OBJC_EXCEPTIONS
662     
663     return 0.0f;
664 }
665
666 double AccessibilityUIElement::height()
667 {
668     BEGIN_AX_OBJC_EXCEPTIONS
669     NSValue* sizeValue = [m_element accessibilityAttributeValue:NSAccessibilitySizeAttribute];
670     return static_cast<double>([sizeValue sizeValue].height);
671     END_AX_OBJC_EXCEPTIONS
672     
673     return 0.0f;
674 }
675
676 double AccessibilityUIElement::clickPointX()
677 {
678     BEGIN_AX_OBJC_EXCEPTIONS
679     NSValue* positionValue = [m_element accessibilityAttributeValue:@"AXClickPoint"];
680     return static_cast<double>([positionValue pointValue].x);        
681     END_AX_OBJC_EXCEPTIONS
682     
683     return 0.0f;
684 }
685
686 double AccessibilityUIElement::clickPointY()
687 {
688     BEGIN_AX_OBJC_EXCEPTIONS
689     NSValue* positionValue = [m_element accessibilityAttributeValue:@"AXClickPoint"];
690     return static_cast<double>([positionValue pointValue].y);
691     END_AX_OBJC_EXCEPTIONS
692     
693     return 0.0f;
694 }
695
696 double AccessibilityUIElement::intValue() const
697 {
698     BEGIN_AX_OBJC_EXCEPTIONS
699     id value = [m_element accessibilityAttributeValue:NSAccessibilityValueAttribute];
700     if ([value isKindOfClass:[NSNumber class]])
701         return [(NSNumber*)value doubleValue]; 
702     END_AX_OBJC_EXCEPTIONS
703
704     return 0.0f;
705 }
706
707 double AccessibilityUIElement::minValue()
708 {
709     BEGIN_AX_OBJC_EXCEPTIONS
710     id value = [m_element accessibilityAttributeValue:NSAccessibilityMinValueAttribute];
711     if ([value isKindOfClass:[NSNumber class]])
712         return [(NSNumber*)value doubleValue]; 
713     END_AX_OBJC_EXCEPTIONS
714
715     return 0.0f;
716 }
717
718 double AccessibilityUIElement::maxValue()
719 {
720     BEGIN_AX_OBJC_EXCEPTIONS
721     id value = [m_element accessibilityAttributeValue:NSAccessibilityMaxValueAttribute];
722     if ([value isKindOfClass:[NSNumber class]])
723         return [(NSNumber*)value doubleValue]; 
724     END_AX_OBJC_EXCEPTIONS
725
726     return 0.0;
727 }
728
729 JSStringRef AccessibilityUIElement::valueDescription()
730 {
731     BEGIN_AX_OBJC_EXCEPTIONS
732     NSString* valueDescription = [m_element accessibilityAttributeValue:NSAccessibilityValueDescriptionAttribute];
733     if ([valueDescription isKindOfClass:[NSString class]])
734          return [valueDescription createJSStringRef];
735
736     END_AX_OBJC_EXCEPTIONS
737     return 0;
738 }
739
740 int AccessibilityUIElement::insertionPointLineNumber()
741 {
742     BEGIN_AX_OBJC_EXCEPTIONS
743     id value = [m_element accessibilityAttributeValue:NSAccessibilityInsertionPointLineNumberAttribute];
744     if ([value isKindOfClass:[NSNumber class]])
745         return [(NSNumber *)value intValue]; 
746     END_AX_OBJC_EXCEPTIONS
747     
748     return -1;
749 }
750
751 bool AccessibilityUIElement::isActionSupported(JSStringRef action)
752 {
753     BEGIN_AX_OBJC_EXCEPTIONS
754     NSArray* actions = [m_element accessibilityActionNames];
755     return [actions containsObject:[NSString stringWithJSStringRef:action]];
756     END_AX_OBJC_EXCEPTIONS
757     
758     return false;
759 }
760
761 bool AccessibilityUIElement::isEnabled()
762 {
763     BEGIN_AX_OBJC_EXCEPTIONS
764     id value = [m_element accessibilityAttributeValue:NSAccessibilityEnabledAttribute];
765     if ([value isKindOfClass:[NSNumber class]])
766         return [value boolValue];
767     END_AX_OBJC_EXCEPTIONS
768     
769     return false;
770 }
771
772 bool AccessibilityUIElement::isRequired() const
773 {
774     BEGIN_AX_OBJC_EXCEPTIONS
775     id value = [m_element accessibilityAttributeValue:@"AXRequired"];
776     if ([value isKindOfClass:[NSNumber class]])
777         return [value boolValue];
778     END_AX_OBJC_EXCEPTIONS
779     
780     return false;
781 }
782
783 bool AccessibilityUIElement::isFocused() const
784 {
785     // FIXME: implement
786     return false;
787 }
788
789 bool AccessibilityUIElement::isSelected() const
790 {
791     BEGIN_AX_OBJC_EXCEPTIONS
792     id value = [m_element accessibilityAttributeValue:NSAccessibilitySelectedAttribute];
793     if ([value isKindOfClass:[NSNumber class]])
794         return [value boolValue];
795     END_AX_OBJC_EXCEPTIONS
796     
797     return false;
798 }
799
800 bool AccessibilityUIElement::isExpanded() const
801 {
802     BEGIN_AX_OBJC_EXCEPTIONS
803     id value = [m_element accessibilityAttributeValue:NSAccessibilityExpandedAttribute];
804     if ([value isKindOfClass:[NSNumber class]])
805         return [value boolValue];
806     END_AX_OBJC_EXCEPTIONS
807     
808     return false;
809 }
810
811 bool AccessibilityUIElement::isChecked() const
812 {
813     // On the Mac, intValue()==1 if a a checkable control is checked.
814     return intValue() == 1;
815 }
816
817 int AccessibilityUIElement::hierarchicalLevel() const
818 {
819     BEGIN_AX_OBJC_EXCEPTIONS
820     id value = [m_element accessibilityAttributeValue:NSAccessibilityDisclosureLevelAttribute];
821     if ([value isKindOfClass:[NSNumber class]])
822         return [value intValue];
823     END_AX_OBJC_EXCEPTIONS
824
825     return 0;
826 }
827
828 JSStringRef AccessibilityUIElement::speak()
829 {
830     BEGIN_AX_OBJC_EXCEPTIONS
831     id value = [m_element accessibilityAttributeValue:@"AXDRTSpeechAttribute"];
832     if ([value isKindOfClass:[NSString class]])
833         return [value createJSStringRef];
834     END_AX_OBJC_EXCEPTIONS
835         
836     return 0;
837 }
838
839 bool AccessibilityUIElement::ariaIsGrabbed() const
840 {
841     BEGIN_AX_OBJC_EXCEPTIONS
842     id value = [m_element accessibilityAttributeValue:NSAccessibilityGrabbedAttribute];
843     if ([value isKindOfClass:[NSNumber class]])
844         return [value boolValue];
845     END_AX_OBJC_EXCEPTIONS
846
847     return false;
848 }
849
850 JSStringRef AccessibilityUIElement::ariaDropEffects() const
851 {
852     BEGIN_AX_OBJC_EXCEPTIONS
853     id value = [m_element accessibilityAttributeValue:NSAccessibilityDropEffectsAttribute];
854     if (![value isKindOfClass:[NSArray class]])
855         return 0;
856
857     NSMutableString* dropEffects = [NSMutableString string];
858     NSInteger length = [value count];
859     for (NSInteger k = 0; k < length; ++k) {
860         [dropEffects appendString:[value objectAtIndex:k]];
861         if (k < length - 1)
862             [dropEffects appendString:@","];
863     }
864     
865     return [dropEffects createJSStringRef];
866     END_AX_OBJC_EXCEPTIONS
867     
868     return 0;
869 }
870
871 // parameterized attributes
872 int AccessibilityUIElement::lineForIndex(int index)
873 {
874     BEGIN_AX_OBJC_EXCEPTIONS
875     id value = [m_element accessibilityAttributeValue:NSAccessibilityLineForIndexParameterizedAttribute forParameter:[NSNumber numberWithInt:index]];
876     if ([value isKindOfClass:[NSNumber class]])
877         return [(NSNumber *)value intValue]; 
878     END_AX_OBJC_EXCEPTIONS
879
880     return -1;
881 }
882
883 JSStringRef AccessibilityUIElement::rangeForLine(int line)
884 {
885     BEGIN_AX_OBJC_EXCEPTIONS
886     id value = [m_element accessibilityAttributeValue:NSAccessibilityRangeForLineParameterizedAttribute forParameter:[NSNumber numberWithInt:line]];
887     if ([value isKindOfClass:[NSValue class]]) {
888         return [NSStringFromRange([value rangeValue]) createJSStringRef];
889     }
890     END_AX_OBJC_EXCEPTIONS
891     
892     return 0;
893 }
894
895 JSStringRef AccessibilityUIElement::boundsForRange(unsigned location, unsigned length)
896 {
897     NSRange range = NSMakeRange(location, length);
898     BEGIN_AX_OBJC_EXCEPTIONS
899     id value = [m_element accessibilityAttributeValue:NSAccessibilityBoundsForRangeParameterizedAttribute forParameter:[NSValue valueWithRange:range]];
900     NSRect rect = NSMakeRect(0,0,0,0);
901     if ([value isKindOfClass:[NSValue class]])
902         rect = [value rectValue]; 
903     
904     // don't return position information because it is platform dependent
905     NSMutableString* boundsDescription = [NSMutableString stringWithFormat:@"{{%f, %f}, {%f, %f}}",-1.0f,-1.0f,rect.size.width,rect.size.height];
906     return [boundsDescription createJSStringRef];
907     END_AX_OBJC_EXCEPTIONS
908     
909     return 0;
910 }
911
912 JSStringRef AccessibilityUIElement::stringForRange(unsigned location, unsigned length)
913 {
914     NSRange range = NSMakeRange(location, length);
915     BEGIN_AX_OBJC_EXCEPTIONS
916     id string = [m_element accessibilityAttributeValue:NSAccessibilityStringForRangeParameterizedAttribute forParameter:[NSValue valueWithRange:range]];
917     if (![string isKindOfClass:[NSString class]])
918         return 0;
919     
920     return [string createJSStringRef];
921     END_AX_OBJC_EXCEPTIONS
922     
923     return 0;
924 }
925
926 JSStringRef AccessibilityUIElement::attributedStringForRange(unsigned location, unsigned length)
927 {
928     NSRange range = NSMakeRange(location, length);
929     BEGIN_AX_OBJC_EXCEPTIONS
930     NSAttributedString* string = [m_element accessibilityAttributeValue:NSAccessibilityAttributedStringForRangeParameterizedAttribute forParameter:[NSValue valueWithRange:range]];
931     if (![string isKindOfClass:[NSAttributedString class]])
932         return 0;
933     
934     NSString* stringWithAttrs = [string description];
935     return [stringWithAttrs createJSStringRef];
936     END_AX_OBJC_EXCEPTIONS
937     
938     return 0;
939 }
940
941 bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned location, unsigned length)
942 {
943     NSRange range = NSMakeRange(location, length);
944     BEGIN_AX_OBJC_EXCEPTIONS
945     NSAttributedString* string = [m_element accessibilityAttributeValue:NSAccessibilityAttributedStringForRangeParameterizedAttribute forParameter:[NSValue valueWithRange:range]];
946     if (![string isKindOfClass:[NSAttributedString class]])
947         return false;
948
949     NSDictionary* attrs = [string attributesAtIndex:0 effectiveRange:nil];
950     if([[attrs objectForKey:NSAccessibilityMisspelledTextAttribute] boolValue])
951         return true;    
952     END_AX_OBJC_EXCEPTIONS
953     
954     return false;
955 }
956
957 AccessibilityUIElement AccessibilityUIElement::uiElementForSearchPredicate(AccessibilityUIElement* startElement, bool isDirectionNext, JSStringRef searchKey, JSStringRef searchText)
958 {
959     BEGIN_AX_OBJC_EXCEPTIONS
960     NSMutableDictionary* parameter = [NSMutableDictionary dictionary];
961     [parameter setObject:(isDirectionNext) ? @"AXDirectionNext" : @"AXDirectionPrevious" forKey:@"AXDirection"];
962     [parameter setObject:[NSNumber numberWithInt:1] forKey:@"AXResultsLimit"];
963     if (startElement)
964         [parameter setObject:(id)startElement->platformUIElement() forKey:@"AXStartElement"];
965     if (searchKey)
966         [parameter setObject:[NSString stringWithJSStringRef:searchKey] forKey:@"AXSearchKey"];
967     if (searchText)
968         [parameter setObject:[NSString stringWithJSStringRef:searchText] forKey:@"AXSearchText"];
969     
970     id uiElement = [[m_element accessibilityAttributeValue:@"AXUIElementsForSearchPredicate" forParameter:parameter] lastObject];
971     return AccessibilityUIElement(uiElement);
972     END_AX_OBJC_EXCEPTIONS
973     
974     return 0;
975 }
976
977 JSStringRef AccessibilityUIElement::attributesOfColumnHeaders()
978 {
979     // not yet defined in AppKit... odd
980     BEGIN_AX_OBJC_EXCEPTIONS
981     NSArray* columnHeadersArray = [m_element accessibilityAttributeValue:@"AXColumnHeaderUIElements"];
982     Vector<AccessibilityUIElement> columnHeadersVector;
983     convertNSArrayToVector(columnHeadersArray, columnHeadersVector);
984     return descriptionOfElements(columnHeadersVector);
985     END_AX_OBJC_EXCEPTIONS
986     
987     return 0;
988 }
989
990 JSStringRef AccessibilityUIElement::attributesOfRowHeaders()
991 {
992     BEGIN_AX_OBJC_EXCEPTIONS
993     NSArray* rowHeadersArray = [m_element accessibilityAttributeValue:@"AXRowHeaderUIElements"];
994     Vector<AccessibilityUIElement> rowHeadersVector;
995     convertNSArrayToVector(rowHeadersArray, rowHeadersVector);
996     return descriptionOfElements(rowHeadersVector);
997     END_AX_OBJC_EXCEPTIONS
998     
999     return 0;
1000 }
1001
1002 JSStringRef AccessibilityUIElement::attributesOfColumns()
1003 {
1004     BEGIN_AX_OBJC_EXCEPTIONS
1005     NSArray* columnsArray = [m_element accessibilityAttributeValue:NSAccessibilityColumnsAttribute];
1006     Vector<AccessibilityUIElement> columnsVector;
1007     convertNSArrayToVector(columnsArray, columnsVector);
1008     return descriptionOfElements(columnsVector);
1009     END_AX_OBJC_EXCEPTIONS
1010     
1011     return 0;
1012 }
1013
1014 JSStringRef AccessibilityUIElement::attributesOfRows()
1015 {
1016     BEGIN_AX_OBJC_EXCEPTIONS
1017     NSArray* rowsArray = [m_element accessibilityAttributeValue:NSAccessibilityRowsAttribute];
1018     Vector<AccessibilityUIElement> rowsVector;
1019     convertNSArrayToVector(rowsArray, rowsVector);
1020     return descriptionOfElements(rowsVector);
1021     END_AX_OBJC_EXCEPTIONS
1022     
1023     return 0;
1024 }
1025
1026 JSStringRef AccessibilityUIElement::attributesOfVisibleCells()
1027 {
1028     BEGIN_AX_OBJC_EXCEPTIONS
1029     NSArray* cellsArray = [m_element accessibilityAttributeValue:@"AXVisibleCells"];
1030     Vector<AccessibilityUIElement> cellsVector;
1031     convertNSArrayToVector(cellsArray, cellsVector);
1032     return descriptionOfElements(cellsVector);
1033     END_AX_OBJC_EXCEPTIONS
1034     
1035     return 0;
1036 }
1037
1038 JSStringRef AccessibilityUIElement::attributesOfHeader()
1039 {
1040     BEGIN_AX_OBJC_EXCEPTIONS
1041     id headerObject = [m_element accessibilityAttributeValue:NSAccessibilityHeaderAttribute];
1042     if (!headerObject)
1043         return [@"" createJSStringRef];
1044     
1045     Vector<AccessibilityUIElement> headerVector;
1046     headerVector.append(headerObject);
1047     return descriptionOfElements(headerVector);
1048     END_AX_OBJC_EXCEPTIONS
1049     
1050     return 0;
1051 }
1052
1053 int AccessibilityUIElement::rowCount()
1054 {
1055     BEGIN_AX_OBJC_EXCEPTIONS
1056     return [m_element accessibilityArrayAttributeCount:NSAccessibilityRowsAttribute];
1057     END_AX_OBJC_EXCEPTIONS
1058     
1059     return 0;
1060 }
1061
1062 int AccessibilityUIElement::columnCount()
1063 {
1064     BEGIN_AX_OBJC_EXCEPTIONS
1065     return [m_element accessibilityArrayAttributeCount:NSAccessibilityColumnsAttribute];
1066     END_AX_OBJC_EXCEPTIONS
1067     
1068     return 0;
1069 }
1070
1071 int AccessibilityUIElement::indexInTable()
1072 {
1073     BEGIN_AX_OBJC_EXCEPTIONS
1074     NSNumber* indexNumber = [m_element accessibilityAttributeValue:NSAccessibilityIndexAttribute];
1075     if (indexNumber)
1076         return [indexNumber intValue];
1077     END_AX_OBJC_EXCEPTIONS
1078
1079     return -1;
1080 }
1081
1082 JSStringRef AccessibilityUIElement::rowIndexRange()
1083 {
1084     NSRange range = NSMakeRange(0,0);
1085     BEGIN_AX_OBJC_EXCEPTIONS
1086     NSValue* indexRange = [m_element accessibilityAttributeValue:@"AXRowIndexRange"];
1087     if (indexRange)
1088         range = [indexRange rangeValue];
1089     NSMutableString* rangeDescription = [NSMutableString stringWithFormat:@"{%d, %d}",range.location, range.length];
1090     return [rangeDescription createJSStringRef];
1091     END_AX_OBJC_EXCEPTIONS
1092     
1093     return 0;
1094 }
1095
1096 JSStringRef AccessibilityUIElement::columnIndexRange()
1097 {
1098     NSRange range = NSMakeRange(0,0);
1099     BEGIN_AX_OBJC_EXCEPTIONS
1100     NSNumber* indexRange = [m_element accessibilityAttributeValue:@"AXColumnIndexRange"];
1101     if (indexRange)
1102         range = [indexRange rangeValue];
1103     NSMutableString* rangeDescription = [NSMutableString stringWithFormat:@"{%d, %d}",range.location, range.length];
1104     return [rangeDescription createJSStringRef];    
1105     END_AX_OBJC_EXCEPTIONS
1106     
1107     return 0;
1108 }
1109
1110 AccessibilityUIElement AccessibilityUIElement::cellForColumnAndRow(unsigned col, unsigned row)
1111 {
1112     NSArray *colRowArray = [NSArray arrayWithObjects:[NSNumber numberWithUnsignedInt:col], [NSNumber numberWithUnsignedInt:row], nil];
1113     BEGIN_AX_OBJC_EXCEPTIONS
1114     return [m_element accessibilityAttributeValue:@"AXCellForColumnAndRow" forParameter:colRowArray];
1115     END_AX_OBJC_EXCEPTIONS    
1116
1117     return 0;
1118 }
1119
1120 AccessibilityUIElement AccessibilityUIElement::horizontalScrollbar() const
1121 {
1122     BEGIN_AX_OBJC_EXCEPTIONS
1123     return AccessibilityUIElement([m_element accessibilityAttributeValue:NSAccessibilityHorizontalScrollBarAttribute]);
1124     END_AX_OBJC_EXCEPTIONS    
1125     
1126     return 0;
1127 }
1128
1129 AccessibilityUIElement AccessibilityUIElement::verticalScrollbar() const
1130 {
1131     BEGIN_AX_OBJC_EXCEPTIONS
1132     return AccessibilityUIElement([m_element accessibilityAttributeValue:NSAccessibilityVerticalScrollBarAttribute]);
1133     END_AX_OBJC_EXCEPTIONS        
1134
1135     return 0;
1136 }
1137
1138 JSStringRef AccessibilityUIElement::selectedTextRange()
1139 {
1140     NSRange range = NSMakeRange(NSNotFound, 0);
1141     BEGIN_AX_OBJC_EXCEPTIONS
1142     NSValue *indexRange = [m_element accessibilityAttributeValue:NSAccessibilitySelectedTextRangeAttribute];
1143     if (indexRange)
1144         range = [indexRange rangeValue];
1145     NSMutableString *rangeDescription = [NSMutableString stringWithFormat:@"{%d, %d}",range.location, range.length];
1146     return [rangeDescription createJSStringRef];    
1147     END_AX_OBJC_EXCEPTIONS
1148     
1149     return 0;
1150 }
1151
1152 void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
1153 {
1154     NSRange textRange = NSMakeRange(location, length);
1155     NSValue *textRangeValue = [NSValue valueWithRange:textRange];
1156     BEGIN_AX_OBJC_EXCEPTIONS
1157     [m_element accessibilitySetValue:textRangeValue forAttribute:NSAccessibilitySelectedTextRangeAttribute];
1158     END_AX_OBJC_EXCEPTIONS
1159 }
1160
1161 void AccessibilityUIElement::increment()
1162 {
1163     BEGIN_AX_OBJC_EXCEPTIONS
1164     [m_element accessibilityPerformAction:NSAccessibilityIncrementAction];
1165     END_AX_OBJC_EXCEPTIONS
1166 }
1167
1168 void AccessibilityUIElement::decrement()
1169 {
1170     BEGIN_AX_OBJC_EXCEPTIONS
1171     [m_element accessibilityPerformAction:NSAccessibilityDecrementAction];
1172     END_AX_OBJC_EXCEPTIONS
1173 }
1174
1175 void AccessibilityUIElement::showMenu()
1176 {
1177     BEGIN_AX_OBJC_EXCEPTIONS
1178     [m_element accessibilityPerformAction:NSAccessibilityShowMenuAction];
1179     END_AX_OBJC_EXCEPTIONS
1180 }
1181
1182 void AccessibilityUIElement::press()
1183 {
1184     BEGIN_AX_OBJC_EXCEPTIONS
1185     [m_element accessibilityPerformAction:NSAccessibilityPressAction];
1186     END_AX_OBJC_EXCEPTIONS
1187 }
1188
1189 void AccessibilityUIElement::setSelectedChild(AccessibilityUIElement* element) const
1190 {
1191     BEGIN_AX_OBJC_EXCEPTIONS
1192     NSArray* array = [NSArray arrayWithObject:element->platformUIElement()];
1193     [m_element accessibilitySetValue:array forAttribute:NSAccessibilitySelectedChildrenAttribute];
1194     END_AX_OBJC_EXCEPTIONS    
1195 }
1196
1197 JSStringRef AccessibilityUIElement::accessibilityValue() const
1198 {
1199     // FIXME: implement
1200     return JSStringCreateWithCharacters(0, 0);
1201 }
1202
1203 JSStringRef AccessibilityUIElement::documentEncoding()
1204 {
1205     return JSStringCreateWithCharacters(0, 0);
1206 }
1207
1208 JSStringRef AccessibilityUIElement::documentURI()
1209 {
1210     return JSStringCreateWithCharacters(0, 0);
1211 }
1212
1213 JSStringRef AccessibilityUIElement::url()
1214 {
1215     BEGIN_AX_OBJC_EXCEPTIONS
1216     NSURL *url = [m_element accessibilityAttributeValue:NSAccessibilityURLAttribute];
1217     return [[url absoluteString] createJSStringRef];    
1218     END_AX_OBJC_EXCEPTIONS
1219     
1220     return nil;
1221 }
1222
1223 bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback)
1224 {
1225     if (!functionCallback)
1226         return false;
1227  
1228     // Mac programmers should not be adding more than one notification listener per element.
1229     // Other platforms may be different.
1230     if (m_notificationHandler)
1231         return false;
1232     m_notificationHandler = [[AccessibilityNotificationHandler alloc] initWithPlatformElement:platformUIElement()];
1233     [m_notificationHandler setCallback:functionCallback];
1234
1235     return true;
1236 }
1237
1238 void AccessibilityUIElement::removeNotificationListener()
1239 {
1240     // Mac programmers should not be trying to remove a listener that's already removed.
1241     ASSERT(m_notificationHandler);
1242
1243     [m_notificationHandler release];
1244     m_notificationHandler = nil;
1245 }
1246
1247 bool AccessibilityUIElement::isFocusable() const
1248 {
1249     bool result = false;
1250     BEGIN_AX_OBJC_EXCEPTIONS
1251     result = [m_element accessibilityIsAttributeSettable:NSAccessibilityFocusedAttribute];
1252     END_AX_OBJC_EXCEPTIONS
1253     
1254     return result;
1255 }
1256
1257 bool AccessibilityUIElement::isSelectable() const
1258 {
1259     // FIXME: implement
1260     return false;
1261 }
1262
1263 bool AccessibilityUIElement::isMultiSelectable() const
1264 {
1265     // FIXME: implement
1266     return false;
1267 }
1268
1269 bool AccessibilityUIElement::isSelectedOptionActive() const
1270 {
1271     // FIXME: implement
1272     return false;
1273 }
1274
1275 bool AccessibilityUIElement::isVisible() const
1276 {
1277     // FIXME: implement
1278     return false;
1279 }
1280
1281 bool AccessibilityUIElement::isOffScreen() const
1282 {
1283     // FIXME: implement
1284     return false;
1285 }
1286
1287 bool AccessibilityUIElement::isCollapsed() const
1288 {
1289     // FIXME: implement
1290     return false;
1291 }
1292
1293 bool AccessibilityUIElement::isIgnored() const
1294 {
1295     BOOL result = NO;
1296     BEGIN_AX_OBJC_EXCEPTIONS
1297     result = [m_element accessibilityIsIgnored];
1298     END_AX_OBJC_EXCEPTIONS
1299     return result;
1300 }
1301
1302 bool AccessibilityUIElement::hasPopup() const
1303 {
1304     BEGIN_AX_OBJC_EXCEPTIONS
1305     id value = [m_element accessibilityAttributeValue:@"AXHasPopup"];
1306     if ([value isKindOfClass:[NSNumber class]])
1307         return [value boolValue];
1308     END_AX_OBJC_EXCEPTIONS
1309
1310     return false;
1311 }
1312
1313 void AccessibilityUIElement::takeFocus()
1314 {
1315     // FIXME: implement
1316 }
1317
1318 void AccessibilityUIElement::takeSelection()
1319 {
1320     // FIXME: implement
1321 }
1322
1323 void AccessibilityUIElement::addSelection()
1324 {
1325     // FIXME: implement
1326 }
1327
1328 void AccessibilityUIElement::removeSelection()
1329 {
1330     // FIXME: implement
1331 }
1332
1333 #if SUPPORTS_AX_TEXTMARKERS
1334
1335 // Text markers
1336 AccessibilityTextMarkerRange AccessibilityUIElement::textMarkerRangeForElement(AccessibilityUIElement* element)
1337 {
1338     BEGIN_AX_OBJC_EXCEPTIONS
1339     id textMarkerRange = [m_element accessibilityAttributeValue:@"AXTextMarkerRangeForUIElement" forParameter:element->platformUIElement()];
1340     return AccessibilityTextMarkerRange(textMarkerRange);
1341     END_AX_OBJC_EXCEPTIONS
1342     
1343     return 0;
1344 }
1345
1346 int AccessibilityUIElement::textMarkerRangeLength(AccessibilityTextMarkerRange* range)
1347 {
1348     BEGIN_AX_OBJC_EXCEPTIONS
1349     NSNumber* lengthValue = [m_element accessibilityAttributeValue:@"AXLengthForTextMarkerRange" forParameter:(id)range->platformTextMarkerRange()];
1350     return [lengthValue intValue];
1351     END_AX_OBJC_EXCEPTIONS
1352     
1353     return 0;
1354 }
1355
1356 AccessibilityTextMarker AccessibilityUIElement::previousTextMarker(AccessibilityTextMarker* textMarker)
1357 {
1358     BEGIN_AX_OBJC_EXCEPTIONS
1359     id previousMarker = [m_element accessibilityAttributeValue:@"AXPreviousTextMarkerForTextMarker" forParameter:(id)textMarker->platformTextMarker()];
1360     return AccessibilityTextMarker(previousMarker);
1361     END_AX_OBJC_EXCEPTIONS
1362     
1363     return 0;
1364 }
1365
1366 AccessibilityTextMarker AccessibilityUIElement::nextTextMarker(AccessibilityTextMarker* textMarker)
1367 {
1368     BEGIN_AX_OBJC_EXCEPTIONS
1369     id nextMarker = [m_element accessibilityAttributeValue:@"AXNextTextMarkerForTextMarker" forParameter:(id)textMarker->platformTextMarker()];
1370     return AccessibilityTextMarker(nextMarker);
1371     END_AX_OBJC_EXCEPTIONS
1372     
1373     return 0;
1374 }
1375
1376 JSStringRef AccessibilityUIElement::stringForTextMarkerRange(AccessibilityTextMarkerRange* markerRange)
1377 {
1378     BEGIN_AX_OBJC_EXCEPTIONS
1379     id textString = [m_element accessibilityAttributeValue:@"AXStringForTextMarkerRange" forParameter:(id)markerRange->platformTextMarkerRange()];
1380     return [textString createJSStringRef];
1381     END_AX_OBJC_EXCEPTIONS
1382     
1383     return 0;
1384 }
1385
1386 AccessibilityTextMarkerRange AccessibilityUIElement::textMarkerRangeForMarkers(AccessibilityTextMarker* startMarker, AccessibilityTextMarker* endMarker)
1387 {
1388     BEGIN_AX_OBJC_EXCEPTIONS
1389     NSArray* textMarkers = [NSArray arrayWithObjects:(id)startMarker->platformTextMarker(), (id)endMarker->platformTextMarker(), nil];
1390     id textMarkerRange = [m_element accessibilityAttributeValue:@"AXTextMarkerRangeForUnorderedTextMarkers" forParameter:textMarkers];
1391     return AccessibilityTextMarkerRange(textMarkerRange);
1392     END_AX_OBJC_EXCEPTIONS
1393     
1394     return 0;
1395 }
1396
1397 AccessibilityTextMarker AccessibilityUIElement::startTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range)
1398 {
1399     BEGIN_AX_OBJC_EXCEPTIONS
1400     id textMarker = [m_element accessibilityAttributeValue:@"AXStartTextMarkerForTextMarkerRange" forParameter:(id)range->platformTextMarkerRange()];
1401     return AccessibilityTextMarker(textMarker);
1402     END_AX_OBJC_EXCEPTIONS
1403     
1404     return 0;    
1405 }
1406
1407 AccessibilityTextMarker AccessibilityUIElement::endTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range)
1408 {
1409     BEGIN_AX_OBJC_EXCEPTIONS
1410     id textMarker = [m_element accessibilityAttributeValue:@"AXEndTextMarkerForTextMarkerRange" forParameter:(id)range->platformTextMarkerRange()];
1411     return AccessibilityTextMarker(textMarker);
1412     END_AX_OBJC_EXCEPTIONS
1413     
1414     return 0;    
1415 }
1416
1417 AccessibilityTextMarker AccessibilityUIElement::textMarkerForPoint(int x, int y)
1418 {
1419     BEGIN_AX_OBJC_EXCEPTIONS
1420     id textMarker = [m_element accessibilityAttributeValue:@"AXTextMarkerForPosition" forParameter:[NSValue valueWithPoint:NSMakePoint(x, y)]];
1421     return AccessibilityTextMarker(textMarker);
1422     END_AX_OBJC_EXCEPTIONS
1423     
1424     return 0;    
1425 }
1426
1427 AccessibilityUIElement AccessibilityUIElement::accessibilityElementForTextMarker(AccessibilityTextMarker* marker)
1428 {
1429     BEGIN_AX_OBJC_EXCEPTIONS
1430     id uiElement = [m_element accessibilityAttributeValue:@"AXUIElementForTextMarker" forParameter:(id)marker->platformTextMarker()];
1431     return AccessibilityUIElement(uiElement);
1432     END_AX_OBJC_EXCEPTIONS
1433     
1434     return 0;  
1435 }
1436
1437 #endif // SUPPORTS_AX_TEXTMARKERS