AX: cleanup style and naming and code in accessibility search mechanism
[WebKit-https.git] / Source / WebCore / accessibility / mac / WebAccessibilityObjectWrapper.mm
1 /*
2  * Copyright (C) 2008, 2009, 2010, 2011 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  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #import "config.h"
30 #import "WebAccessibilityObjectWrapper.h"
31
32 #if HAVE(ACCESSIBILITY)
33
34 #import "AXObjectCache.h"
35 #import "AccessibilityARIAGridRow.h"
36 #import "AccessibilityList.h"
37 #import "AccessibilityListBox.h"
38 #import "AccessibilityRenderObject.h"
39 #import "AccessibilityScrollView.h"
40 #import "AccessibilitySpinButton.h"
41 #import "AccessibilityTable.h"
42 #import "AccessibilityTableCell.h"
43 #import "AccessibilityTableColumn.h"
44 #import "AccessibilityTableRow.h"
45 #import "Chrome.h"
46 #import "ColorMac.h"
47 #import "Frame.h"
48 #import "FrameLoaderClient.h"
49 #import "FrameSelection.h"
50 #import "HTMLAnchorElement.h"
51 #import "HTMLAreaElement.h"
52 #import "HTMLFrameOwnerElement.h"
53 #import "HTMLImageElement.h"
54 #import "HTMLInputElement.h"
55 #import "HTMLNames.h"
56 #import "HTMLTextAreaElement.h"
57 #import "LocalizedStrings.h"
58 #import "Page.h"
59 #import "RenderTextControl.h"
60 #import "RenderView.h"
61 #import "RenderWidget.h"
62 #import "ScrollView.h"
63 #import "SimpleFontData.h"
64 #import "TextCheckerClient.h"
65 #import "TextCheckingHelper.h"
66 #import "TextIterator.h"
67 #import "WebCoreFrameView.h"
68 #import "WebCoreObjCExtras.h"
69 #import "WebCoreSystemInterface.h"
70 #import "htmlediting.h"
71 #import "visible_units.h"
72
73 using namespace WebCore;
74 using namespace HTMLNames;
75 using namespace std;
76
77 // Cell Tables
78 #ifndef NSAccessibilitySelectedCellsAttribute
79 #define NSAccessibilitySelectedCellsAttribute @"AXSelectedCells"
80 #endif
81
82 #ifndef NSAccessibilityVisibleCellsAttribute
83 #define NSAccessibilityVisibleCellsAttribute @"AXVisibleCells"
84 #endif
85
86 #ifndef NSAccessibilityRowHeaderUIElementsAttribute
87 #define NSAccessibilityRowHeaderUIElementsAttribute @"AXRowHeaderUIElements"
88 #endif
89
90 #ifndef NSAccessibilityRowIndexRangeAttribute
91 #define NSAccessibilityRowIndexRangeAttribute @"AXRowIndexRange"
92 #endif
93
94 #ifndef NSAccessibilityColumnIndexRangeAttribute
95 #define NSAccessibilityColumnIndexRangeAttribute @"AXColumnIndexRange"
96 #endif
97
98 #ifndef NSAccessibilityCellForColumnAndRowParameterizedAttribute
99 #define NSAccessibilityCellForColumnAndRowParameterizedAttribute @"AXCellForColumnAndRow"
100 #endif
101
102 #ifndef NSAccessibilityCellRole
103 #define NSAccessibilityCellRole @"AXCell"
104 #endif
105
106 // Lists
107 #ifndef NSAccessibilityContentListSubrole
108 #define NSAccessibilityContentListSubrole @"AXContentList"
109 #endif
110
111 #ifndef NSAccessibilityDefinitionListSubrole
112 #define NSAccessibilityDefinitionListSubrole @"AXDefinitionList"
113 #endif
114
115 // Miscellaneous
116 #ifndef NSAccessibilityBlockQuoteLevelAttribute
117 #define NSAccessibilityBlockQuoteLevelAttribute @"AXBlockQuoteLevel"
118 #endif
119
120 #ifndef NSAccessibilityAccessKeyAttribute
121 #define NSAccessibilityAccessKeyAttribute @"AXAccessKey"
122 #endif
123
124 #ifndef NSAccessibilityLanguageAttribute
125 #define NSAccessibilityLanguageAttribute @"AXLanguage"
126 #endif
127
128 #ifndef NSAccessibilityRequiredAttribute
129 #define NSAccessibilityRequiredAttribute @"AXRequired"
130 #endif
131
132 #ifndef NSAccessibilityInvalidAttribute
133 #define NSAccessibilityInvalidAttribute @"AXInvalid"
134 #endif
135
136 #ifndef NSAccessibilityOwnsAttribute
137 #define NSAccessibilityOwnsAttribute @"AXOwns"
138 #endif
139
140 #ifndef NSAccessibilityGrabbedAttribute
141 #define NSAccessibilityGrabbedAttribute @"AXGrabbed"
142 #endif
143
144 #ifndef NSAccessibilityDropEffectsAttribute
145 #define NSAccessibilityDropEffectsAttribute @"AXDropEffects"
146 #endif
147
148 #ifndef NSAccessibilityARIALiveAttribute
149 #define NSAccessibilityARIALiveAttribute @"AXARIALive"
150 #endif
151
152 #ifndef NSAccessibilityARIAAtomicAttribute
153 #define NSAccessibilityARIAAtomicAttribute @"AXARIAAtomic"
154 #endif
155
156 #ifndef NSAccessibilityARIARelevantAttribute
157 #define NSAccessibilityARIARelevantAttribute @"AXARIARelevant"
158 #endif
159
160 #ifndef NSAccessibilityARIABusyAttribute
161 #define NSAccessibilityARIABusyAttribute @"AXARIABusy"
162 #endif
163
164 #ifndef NSAccessibilityLoadingProgressAttribute
165 #define NSAccessibilityLoadingProgressAttribute @"AXLoadingProgress"
166 #endif
167
168 #ifndef NSAccessibilityHasPopupAttribute
169 #define NSAccessibilityHasPopupAttribute @"AXHasPopup"
170 #endif
171
172 #ifndef NSAccessibilityPlaceholderValueAttribute
173 #define NSAccessibilityPlaceholderValueAttribute @"AXPlaceholderValue"
174 #endif
175
176 // Search
177 #ifndef NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute
178 #define NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute @"AXUIElementsForSearchPredicate"
179 #endif
180
181 // Search Keys
182 #ifndef NSAccessibilityAnyTypeSearchKey
183 #define NSAccessibilityAnyTypeSearchKey @"AXAnyTypeSearchKey"
184 #endif
185
186 #ifndef NSAccessibilityBlockquoteSameLevelSearchKey
187 #define NSAccessibilityBlockquoteSameLevelSearchKey @"AXBlockquoteSameLevelSearchKey"
188 #endif
189
190 #ifndef NSAccessibilityBlockquoteSearchKey
191 #define NSAccessibilityBlockquoteSearchKey @"AXBlockquoteSearchKey"
192 #endif
193
194 #ifndef NSAccessibilityBoldFontSearchKey
195 #define NSAccessibilityBoldFontSearchKey @"AXBoldFontSearchKey"
196 #endif
197
198 #ifndef NSAccessibilityButtonSearchKey
199 #define NSAccessibilityButtonSearchKey @"AXButtonSearchKey"
200 #endif
201
202 #ifndef NSAccessibilityCheckBoxSearchKey
203 #define NSAccessibilityCheckBoxSearchKey @"AXCheckBoxSearchKey"
204 #endif
205
206 #ifndef NSAccessibilityControlSearchKey
207 #define NSAccessibilityControlSearchKey @"AXControlSearchKey"
208 #endif
209
210 #ifndef NSAccessibilityDifferentTypeSearchKey
211 #define NSAccessibilityDifferentTypeSearchKey @"AXDifferentTypeSearchKey"
212 #endif
213
214 #ifndef NSAccessibilityFontChangeSearchKey
215 #define NSAccessibilityFontChangeSearchKey @"AXFontChangeSearchKey"
216 #endif
217
218 #ifndef NSAccessibilityFontColorChangeSearchKey
219 #define NSAccessibilityFontColorChangeSearchKey @"AXFontColorChangeSearchKey"
220 #endif
221
222 #ifndef NSAccessibilityFrameSearchKey
223 #define NSAccessibilityFrameSearchKey @"AXFrameSearchKey"
224 #endif
225
226 #ifndef NSAccessibilityGraphicSearchKey
227 #define NSAccessibilityGraphicSearchKey @"AXGraphicSearchKey"
228 #endif
229
230 #ifndef NSAccessibilityHeadingLevel1SearchKey
231 #define NSAccessibilityHeadingLevel1SearchKey @"AXHeadingLevel1SearchKey"
232 #endif
233
234 #ifndef NSAccessibilityHeadingLevel2SearchKey
235 #define NSAccessibilityHeadingLevel2SearchKey @"AXHeadingLevel2SearchKey"
236 #endif
237
238 #ifndef NSAccessibilityHeadingLevel3SearchKey
239 #define NSAccessibilityHeadingLevel3SearchKey @"AXHeadingLevel3SearchKey"
240 #endif
241
242 #ifndef NSAccessibilityHeadingLevel4SearchKey
243 #define NSAccessibilityHeadingLevel4SearchKey @"AXHeadingLevel4SearchKey"
244 #endif
245
246 #ifndef NSAccessibilityHeadingLevel5SearchKey
247 #define NSAccessibilityHeadingLevel5SearchKey @"AXHeadingLevel5SearchKey"
248 #endif
249
250 #ifndef NSAccessibilityHeadingLevel6SearchKey
251 #define NSAccessibilityHeadingLevel6SearchKey @"AXHeadingLevel6SearchKey"
252 #endif
253
254 #ifndef NSAccessibilityHeadingSameLevelSearchKey
255 #define NSAccessibilityHeadingSameLevelSearchKey @"AXHeadingSameLevelSearchKey"
256 #endif
257
258 #ifndef NSAccessibilityHeadingSearchKey
259 #define NSAccessibilityHeadingSearchKey @"AXHeadingSearchKey"
260 #endif
261
262 #ifndef NSAccessibilityItalicFontSearchKey
263 #define NSAccessibilityItalicFontSearchKey @"AXItalicFontSearchKey"
264 #endif
265
266 #ifndef NSAccessibilityLandmarkSearchKey
267 #define NSAccessibilityLandmarkSearchKey @"AXLandmarkSearchKey"
268 #endif
269
270 #ifndef NSAccessibilityLinkSearchKey
271 #define NSAccessibilityLinkSearchKey @"AXLinkSearchKey"
272 #endif
273
274 #ifndef NSAccessibilityListSearchKey
275 #define NSAccessibilityListSearchKey @"AXListSearchKey"
276 #endif
277
278 #ifndef NSAccessibilityLiveRegionSearchKey
279 #define NSAccessibilityLiveRegionSearchKey @"AXLiveRegionSearchKey"
280 #endif
281
282 #ifndef NSAccessibilityMisspelledWordSearchKey
283 #define NSAccessibilityMisspelledWordSearchKey @"AXMisspelledWordSearchKey"
284 #endif
285
286 #ifndef NSAccessibilityPlainTextSearchKey
287 #define NSAccessibilityPlainTextSearchKey @"AXPlainTextSearchKey"
288 #endif
289
290 #ifndef NSAccessibilityRadioGroupSearchKey
291 #define NSAccessibilityRadioGroupSearchKey @"AXRadioGroupSearchKey"
292 #endif
293
294 #ifndef NSAccessibilitySameTypeSearchKey
295 #define NSAccessibilitySameTypeSearchKey @"AXSameTypeSearchKey"
296 #endif
297
298 #ifndef NSAccessibilityStaticTextSearchKey
299 #define NSAccessibilityStaticTextSearchKey @"AXStaticTextSearchKey"
300 #endif
301
302 #ifndef NSAccessibilityStyleChangeSearchKey
303 #define NSAccessibilityStyleChangeSearchKey @"AXStyleChangeSearchKey"
304 #endif
305
306 #ifndef NSAccessibilityTableSameLevelSearchKey
307 #define NSAccessibilityTableSameLevelSearchKey @"AXTableSameLevelSearchKey"
308 #endif
309
310 #ifndef NSAccessibilityTableSearchKey
311 #define NSAccessibilityTableSearchKey @"AXTableSearchKey"
312 #endif
313
314 #ifndef NSAccessibilityTextFieldSearchKey
315 #define NSAccessibilityTextFieldSearchKey @"AXTextFieldSearchKey"
316 #endif
317
318 #ifndef NSAccessibilityUnderlineSearchKey
319 #define NSAccessibilityUnderlineSearchKey @"AXUnderlineSearchKey"
320 #endif
321
322 #ifndef NSAccessibilityUnvisitedLinkSearchKey
323 #define NSAccessibilityUnvisitedLinkSearchKey @"AXUnvisitedLinkSearchKey"
324 #endif
325
326 #ifndef NSAccessibilityVisitedLinkSearchKey
327 #define NSAccessibilityVisitedLinkSearchKey @"AXVisitedLinkSearchKey"
328 #endif
329
330
331 @interface NSObject (WebKitAccessibilityArrayCategory)
332
333 - (NSUInteger)accessibilityIndexOfChild:(id)child;
334 - (NSUInteger)accessibilityArrayAttributeCount:(NSString *)attribute;
335 - (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount;
336
337 @end
338
339 @implementation WebAccessibilityObjectWrapper
340
341 - (id)initWithAccessibilityObject:(AccessibilityObject*)axObject
342 {
343     if (!(self = [super init]))
344         return nil;
345
346     m_object = axObject;
347     return self;
348 }
349
350 - (void)unregisterUniqueIdForUIElement
351 {
352     wkUnregisterUniqueIdForElement(self);
353 }
354
355 - (void)detach
356 {
357     // Send unregisterUniqueIdForUIElement unconditionally because if it is
358     // ever accidentally not done (via other bugs in our AX implementation) you
359     // end up with a crash like <rdar://problem/4273149>.  It is safe and not
360     // expensive to send even if the object is not registered.
361     [self unregisterUniqueIdForUIElement];
362     m_object = 0;
363 }
364
365 - (BOOL)updateObjectBackingStore
366 {
367     // Calling updateBackingStore() can invalidate this element so self must be retained.
368     // If it does become invalidated, m_object will be nil.
369     [[self retain] autorelease];
370     
371     if (!m_object)
372         return NO;
373     
374     m_object->updateBackingStore();
375     if (!m_object)
376         return NO;
377     
378     return YES;
379 }
380
381 - (AccessibilityObject*)accessibilityObject
382 {
383     return m_object;
384 }
385
386 - (NSView*)attachmentView
387 {
388     ASSERT(m_object->isAttachment());
389     Widget* widget = m_object->widgetForAttachmentView();
390     if (!widget)
391         return nil;
392     return NSAccessibilityUnignoredDescendant(widget->platformWidget());
393 }
394
395 #pragma mark SystemInterface wrappers
396
397 static inline id CFAutoreleaseHelper(CFTypeRef obj)
398 {
399     if (obj)
400         CFMakeCollectable(obj);
401     [(id)obj autorelease];
402     return (id)obj;
403 }
404
405 static inline BOOL AXObjectIsTextMarker(id obj)
406 {
407     return obj != nil && CFGetTypeID(obj) == wkGetAXTextMarkerTypeID();    
408 }
409
410 static inline BOOL AXObjectIsTextMarkerRange(id obj)
411 {
412     return obj != nil && CFGetTypeID(obj) == wkGetAXTextMarkerRangeTypeID();    
413 }
414
415 static id AXTextMarkerRange(id startMarker, id endMarker)
416 {
417     ASSERT(startMarker != nil);
418     ASSERT(endMarker != nil);
419     ASSERT(CFGetTypeID(startMarker) == wkGetAXTextMarkerTypeID());
420     ASSERT(CFGetTypeID(endMarker) == wkGetAXTextMarkerTypeID());
421     return CFAutoreleaseHelper(wkCreateAXTextMarkerRange((CFTypeRef)startMarker, (CFTypeRef)endMarker));
422 }
423
424 static id AXTextMarkerRangeStart(id range)
425 {
426     ASSERT(range != nil);
427     ASSERT(CFGetTypeID(range) == wkGetAXTextMarkerRangeTypeID());
428     return CFAutoreleaseHelper(wkCopyAXTextMarkerRangeStart(range));    
429 }
430
431 static id AXTextMarkerRangeEnd(id range)
432 {
433     ASSERT(range != nil);
434     ASSERT(CFGetTypeID(range) == wkGetAXTextMarkerRangeTypeID());
435     return CFAutoreleaseHelper(wkCopyAXTextMarkerRangeEnd(range));    
436 }
437
438 #pragma mark Search helpers
439
440 typedef HashMap<String, AccessibilitySearchKey> AccessibilitySearchKeyMap;
441
442 struct SearchKeyEntry {
443     String key;
444     AccessibilitySearchKey value;
445 };
446
447 static AccessibilitySearchKeyMap* createAccessibilitySearchKeyMap()
448 {
449     const SearchKeyEntry searchKeys[] = {
450         { NSAccessibilityAnyTypeSearchKey, AnyTypeSearchKey },
451         { NSAccessibilityBlockquoteSameLevelSearchKey, BlockquoteSameLevelSearchKey },
452         { NSAccessibilityBlockquoteSearchKey, BlockquoteSearchKey },
453         { NSAccessibilityBoldFontSearchKey, BoldFontSearchKey },
454         { NSAccessibilityButtonSearchKey, ButtonSearchKey },
455         { NSAccessibilityCheckBoxSearchKey, CheckBoxSearchKey },
456         { NSAccessibilityControlSearchKey, ControlSearchKey },
457         { NSAccessibilityDifferentTypeSearchKey, DifferentTypeSearchKey },
458         { NSAccessibilityFontChangeSearchKey, FontChangeSearchKey },
459         { NSAccessibilityFontColorChangeSearchKey, FontColorChangeSearchKey },
460         { NSAccessibilityFrameSearchKey, FrameSearchKey },
461         { NSAccessibilityGraphicSearchKey, GraphicSearchKey },
462         { NSAccessibilityHeadingLevel1SearchKey, HeadingLevel1SearchKey },
463         { NSAccessibilityHeadingLevel2SearchKey, HeadingLevel2SearchKey },
464         { NSAccessibilityHeadingLevel3SearchKey, HeadingLevel3SearchKey },
465         { NSAccessibilityHeadingLevel4SearchKey, HeadingLevel4SearchKey },
466         { NSAccessibilityHeadingLevel5SearchKey, HeadingLevel5SearchKey },
467         { NSAccessibilityHeadingLevel6SearchKey, HeadingLevel6SearchKey },
468         { NSAccessibilityHeadingSameLevelSearchKey, HeadingSameLevelSearchKey },
469         { NSAccessibilityHeadingSearchKey, HeadingSearchKey },
470         { NSAccessibilityItalicFontSearchKey, ItalicFontSearchKey },
471         { NSAccessibilityLandmarkSearchKey, LandmarkSearchKey },
472         { NSAccessibilityLinkSearchKey, LinkSearchKey },
473         { NSAccessibilityListSearchKey, ListSearchKey },
474         { NSAccessibilityLiveRegionSearchKey, LiveRegionSearchKey },
475         { NSAccessibilityMisspelledWordSearchKey, MisspelledWordSearchKey },
476         { NSAccessibilityPlainTextSearchKey, PlainTextSearchKey },
477         { NSAccessibilityRadioGroupSearchKey, RadioGroupSearchKey },
478         { NSAccessibilitySameTypeSearchKey, SameTypeSearchKey },
479         { NSAccessibilityStaticTextSearchKey, StaticTextSearchKey },
480         { NSAccessibilityStyleChangeSearchKey, StyleChangeSearchKey },
481         { NSAccessibilityTableSameLevelSearchKey, TableSameLevelSearchKey },
482         { NSAccessibilityTableSearchKey, TableSearchKey },
483         { NSAccessibilityTextFieldSearchKey, TextFieldSearchKey },
484         { NSAccessibilityUnderlineSearchKey, UnderlineSearchKey },
485         { NSAccessibilityUnvisitedLinkSearchKey, UnvisitedLinkSearchKey },
486         { NSAccessibilityVisitedLinkSearchKey, VisitedLinkSearchKey }
487     };
488     
489     AccessibilitySearchKeyMap* searchKeyMap = new AccessibilitySearchKeyMap;
490     for (size_t i = 0; i < WTF_ARRAY_LENGTH(searchKeys); i++)
491         searchKeyMap->set(searchKeys[i].key, searchKeys[i].value);
492     
493     return searchKeyMap;
494 }
495
496 static AccessibilitySearchKey accessibilitySearchKeyForString(const String& value)
497 {
498     if (value.isEmpty())
499         return AnyTypeSearchKey;
500     
501     static const AccessibilitySearchKeyMap* searchKeyMap = createAccessibilitySearchKeyMap();
502     
503     AccessibilitySearchKey searchKey = searchKeyMap->get(value);
504     
505     return searchKey ? searchKey : AnyTypeSearchKey;
506 }
507
508 #pragma mark Text Marker helpers
509
510 static id textMarkerForVisiblePosition(AXObjectCache* cache, const VisiblePosition& visiblePos)
511 {
512     ASSERT(cache);
513     
514     TextMarkerData textMarkerData;
515     cache->textMarkerDataForVisiblePosition(textMarkerData, visiblePos);
516     if (!textMarkerData.axID)
517         return nil;
518     
519     return CFAutoreleaseHelper(wkCreateAXTextMarker(&textMarkerData, sizeof(textMarkerData)));
520 }
521
522 - (id)textMarkerForVisiblePosition:(const VisiblePosition &)visiblePos
523 {
524     return textMarkerForVisiblePosition(m_object->axObjectCache(), visiblePos);
525 }
526
527 static VisiblePosition visiblePositionForTextMarker(AXObjectCache* cache, CFTypeRef textMarker)
528 {
529     ASSERT(cache);
530
531     if (!textMarker)
532         return VisiblePosition();
533     TextMarkerData textMarkerData;
534     if (!wkGetBytesFromAXTextMarker(textMarker, &textMarkerData, sizeof(textMarkerData)))
535         return VisiblePosition();
536     
537     return cache->visiblePositionForTextMarkerData(textMarkerData);
538 }
539
540 - (VisiblePosition)visiblePositionForTextMarker:(id)textMarker
541 {
542     return visiblePositionForTextMarker(m_object->axObjectCache(), textMarker);
543 }
544
545 static VisiblePosition visiblePositionForStartOfTextMarkerRange(AXObjectCache *cache, id textMarkerRange)
546 {
547     return visiblePositionForTextMarker(cache, AXTextMarkerRangeStart(textMarkerRange));
548 }
549
550 static VisiblePosition visiblePositionForEndOfTextMarkerRange(AXObjectCache *cache, id textMarkerRange)
551 {
552     return visiblePositionForTextMarker(cache, AXTextMarkerRangeEnd(textMarkerRange));
553 }
554
555 static id textMarkerRangeFromMarkers(id textMarker1, id textMarker2)
556 {
557     if (!textMarker1 || !textMarker2)
558         return nil;
559         
560     return AXTextMarkerRange(textMarker1, textMarker2);
561 }
562
563 static void AXAttributeStringSetFont(NSMutableAttributedString* attrString, NSString* attribute, NSFont* font, NSRange range)
564 {
565     NSDictionary* dict;
566     
567     if (font) {
568         dict = [NSDictionary dictionaryWithObjectsAndKeys:
569             [font fontName]                             , NSAccessibilityFontNameKey,
570             [font familyName]                           , NSAccessibilityFontFamilyKey,
571             [font displayName]                          , NSAccessibilityVisibleNameKey,
572             [NSNumber numberWithFloat:[font pointSize]] , NSAccessibilityFontSizeKey,
573         nil];
574
575         [attrString addAttribute:attribute value:dict range:range];
576     } else
577         [attrString removeAttribute:attribute range:range];
578     
579 }
580
581 static CGColorRef CreateCGColorIfDifferent(NSColor* nsColor, CGColorRef existingColor)
582 {
583     // get color information assuming NSDeviceRGBColorSpace 
584     NSColor* rgbColor = [nsColor colorUsingColorSpaceName:NSDeviceRGBColorSpace];
585     if (rgbColor == nil)
586         rgbColor = [NSColor blackColor];
587     CGFloat components[4];
588     [rgbColor getRed:&components[0] green:&components[1] blue:&components[2] alpha:&components[3]];
589     
590     // create a new CGColorRef to return
591     CGColorSpaceRef cgColorSpace = CGColorSpaceCreateDeviceRGB();
592     CGColorRef cgColor = CGColorCreate(cgColorSpace, components);
593     CGColorSpaceRelease(cgColorSpace);
594     
595     // check for match with existing color
596     if (existingColor && CGColorEqualToColor(cgColor, existingColor)) {
597         CGColorRelease(cgColor);
598         cgColor = 0;
599     }
600     
601     return cgColor;
602 }
603
604 static void AXAttributeStringSetColor(NSMutableAttributedString* attrString, NSString* attribute, NSColor* color, NSRange range)
605 {
606     if (color) {
607         CGColorRef existingColor = (CGColorRef) [attrString attribute:attribute atIndex:range.location effectiveRange:nil];
608         CGColorRef cgColor = CreateCGColorIfDifferent(color, existingColor);
609         if (cgColor) {
610             [attrString addAttribute:attribute value:(id)cgColor range:range];
611             CGColorRelease(cgColor);
612         }
613     } else
614         [attrString removeAttribute:attribute range:range];
615 }
616
617 static void AXAttributeStringSetNumber(NSMutableAttributedString* attrString, NSString* attribute, NSNumber* number, NSRange range)
618 {
619     if (number)
620         [attrString addAttribute:attribute value:number range:range];
621     else
622         [attrString removeAttribute:attribute range:range];
623 }
624
625 static void AXAttributeStringSetStyle(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
626 {
627     RenderStyle* style = renderer->style();
628
629     // set basic font info
630     AXAttributeStringSetFont(attrString, NSAccessibilityFontTextAttribute, style->font().primaryFont()->getNSFont(), range);
631
632     // set basic colors
633     AXAttributeStringSetColor(attrString, NSAccessibilityForegroundColorTextAttribute, nsColor(style->visitedDependentColor(CSSPropertyColor)), range);
634     AXAttributeStringSetColor(attrString, NSAccessibilityBackgroundColorTextAttribute, nsColor(style->visitedDependentColor(CSSPropertyBackgroundColor)), range);
635
636     // set super/sub scripting
637     EVerticalAlign alignment = style->verticalAlign();
638     if (alignment == SUB)
639         AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:(-1)], range);
640     else if (alignment == SUPER)
641         AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:1], range);
642     else
643         [attrString removeAttribute:NSAccessibilitySuperscriptTextAttribute range:range];
644     
645     // set shadow
646     if (style->textShadow())
647         AXAttributeStringSetNumber(attrString, NSAccessibilityShadowTextAttribute, [NSNumber numberWithBool:YES], range);
648     else
649         [attrString removeAttribute:NSAccessibilityShadowTextAttribute range:range];
650     
651     // set underline and strikethrough
652     int decor = style->textDecorationsInEffect();
653     if ((decor & UNDERLINE) == 0) {
654         [attrString removeAttribute:NSAccessibilityUnderlineTextAttribute range:range];
655         [attrString removeAttribute:NSAccessibilityUnderlineColorTextAttribute range:range];
656     }
657     
658     if ((decor & LINE_THROUGH) == 0) {
659         [attrString removeAttribute:NSAccessibilityStrikethroughTextAttribute range:range];
660         [attrString removeAttribute:NSAccessibilityStrikethroughColorTextAttribute range:range];
661     }
662
663     if ((decor & (UNDERLINE | LINE_THROUGH)) != 0) {
664         // find colors using quirk mode approach (strict mode would use current
665         // color for all but the root line box, which would use getTextDecorationColors)
666         Color underline, overline, linethrough;
667         renderer->getTextDecorationColors(decor, underline, overline, linethrough);
668         
669         if ((decor & UNDERLINE) != 0) {
670             AXAttributeStringSetNumber(attrString, NSAccessibilityUnderlineTextAttribute, [NSNumber numberWithBool:YES], range);
671             AXAttributeStringSetColor(attrString, NSAccessibilityUnderlineColorTextAttribute, nsColor(underline), range);
672         }
673
674         if ((decor & LINE_THROUGH) != 0) {
675             AXAttributeStringSetNumber(attrString, NSAccessibilityStrikethroughTextAttribute, [NSNumber numberWithBool:YES], range);
676             AXAttributeStringSetColor(attrString, NSAccessibilityStrikethroughColorTextAttribute, nsColor(linethrough), range);
677         }
678     }
679 }
680
681 static void AXAttributeStringSetBlockquoteLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
682 {
683     AccessibilityObject* obj = renderer->document()->axObjectCache()->getOrCreate(renderer);
684     int quoteLevel = obj->blockquoteLevel();
685     
686     if (quoteLevel)
687         [attrString addAttribute:NSAccessibilityBlockQuoteLevelAttribute value:[NSNumber numberWithInt:quoteLevel] range:range];
688     else
689         [attrString removeAttribute:NSAccessibilityBlockQuoteLevelAttribute range:range];
690 }
691
692 static void AXAttributeStringSetSpelling(NSMutableAttributedString* attrString, Node* node, const UChar* chars, int charLength, NSRange range)
693 {
694     if (unifiedTextCheckerEnabled(node->document()->frame())) {
695         // Check the spelling directly since document->markersForNode() does not store the misspelled marking when the cursor is in a word.
696         TextCheckerClient* checker = node->document()->frame()->editor()->textChecker();
697
698         // checkTextOfParagraph is the only spelling/grammar checker implemented in WK1 and WK2
699         Vector<TextCheckingResult> results;
700         checkTextOfParagraph(checker, chars, charLength, TextCheckingTypeSpelling, results);
701
702         size_t size = results.size();
703         NSNumber* trueValue = [NSNumber numberWithBool:YES];
704         for (unsigned i = 0; i < size; i++) {
705             const TextCheckingResult& result = results[i];
706             AXAttributeStringSetNumber(attrString, NSAccessibilityMisspelledTextAttribute, trueValue, NSMakeRange(result.location + range.location, result.length));
707         }
708         return;
709     }
710
711     int currentPosition = 0;
712     while (charLength > 0) {
713         const UChar* charData = chars + currentPosition;
714         TextCheckerClient* checker = node->document()->frame()->editor()->textChecker();
715         
716         int misspellingLocation = -1;
717         int misspellingLength = 0;
718         checker->checkSpellingOfString(charData, charLength, &misspellingLocation, &misspellingLength);
719         if (misspellingLocation == -1 || !misspellingLength)
720             break;
721         
722         NSRange spellRange = NSMakeRange(range.location + currentPosition + misspellingLocation, misspellingLength);
723         AXAttributeStringSetNumber(attrString, NSAccessibilityMisspelledTextAttribute, [NSNumber numberWithBool:YES], spellRange);
724         charLength -= (misspellingLocation + misspellingLength);
725         currentPosition += (misspellingLocation + misspellingLength);
726     }
727 }
728
729 static void AXAttributeStringSetHeadingLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
730 {
731     if (!renderer)
732         return;
733     
734     AccessibilityObject* parentObject = renderer->document()->axObjectCache()->getOrCreate(renderer->parent());
735     int parentHeadingLevel = parentObject->headingLevel();
736     
737     if (parentHeadingLevel)
738         [attrString addAttribute:@"AXHeadingLevel" value:[NSNumber numberWithInt:parentHeadingLevel] range:range];
739     else
740         [attrString removeAttribute:@"AXHeadingLevel" range:range];
741 }
742
743 static void AXAttributeStringSetElement(NSMutableAttributedString* attrString, NSString* attribute, AccessibilityObject* object, NSRange range)
744 {
745     if (object && object->isAccessibilityRenderObject()) {
746         // make a serializable AX object
747         
748         RenderObject* renderer = static_cast<AccessibilityRenderObject*>(object)->renderer();
749         if (!renderer)
750             return;
751         
752         Document* doc = renderer->document();
753         if (!doc)
754             return;
755         
756         AXObjectCache* cache = doc->axObjectCache();
757         if (!cache)
758             return;
759
760         AXUIElementRef axElement = wkCreateAXUIElementRef(object->wrapper());
761         if (axElement) {
762             [attrString addAttribute:attribute value:(id)axElement range:range];
763             CFRelease(axElement);
764         }
765     } else
766         [attrString removeAttribute:attribute range:range];
767 }
768
769 static void AXAttributedStringAppendText(NSMutableAttributedString* attrString, Node* node, const UChar* chars, int length)
770 {
771     // skip invisible text
772     if (!node->renderer())
773         return;
774
775     // easier to calculate the range before appending the string
776     NSRange attrStringRange = NSMakeRange([attrString length], length);
777     
778     // append the string from this node
779     [[attrString mutableString] appendString:[NSString stringWithCharacters:chars length:length]];
780
781     // add new attributes and remove irrelevant inherited ones
782     // NOTE: color attributes are handled specially because -[NSMutableAttributedString addAttribute: value: range:] does not merge
783     // identical colors.  Workaround is to not replace an existing color attribute if it matches what we are adding.  This also means
784     // we cannot just pre-remove all inherited attributes on the appended string, so we have to remove the irrelevant ones individually.
785
786     // remove inherited attachment from prior AXAttributedStringAppendReplaced
787     [attrString removeAttribute:NSAccessibilityAttachmentTextAttribute range:attrStringRange];
788     [attrString removeAttribute:NSAccessibilityMisspelledTextAttribute range:attrStringRange];
789     
790     // set new attributes
791     AXAttributeStringSetStyle(attrString, node->renderer(), attrStringRange);
792     AXAttributeStringSetHeadingLevel(attrString, node->renderer(), attrStringRange);
793     AXAttributeStringSetBlockquoteLevel(attrString, node->renderer(), attrStringRange);
794     AXAttributeStringSetElement(attrString, NSAccessibilityLinkTextAttribute, AccessibilityObject::anchorElementForNode(node), attrStringRange);
795     
796     // do spelling last because it tends to break up the range
797     AXAttributeStringSetSpelling(attrString, node, chars, length, attrStringRange);
798 }
799
800 static NSString* nsStringForReplacedNode(Node* replacedNode)
801 {
802     // we should always be given a rendered node and a replaced node, but be safe
803     // replaced nodes are either attachments (widgets) or images
804     if (!replacedNode || !replacedNode->renderer() || !replacedNode->renderer()->isReplaced() || replacedNode->isTextNode()) {
805         ASSERT_NOT_REACHED();
806         return nil;
807     }
808
809     // create an AX object, but skip it if it is not supposed to be seen
810     RefPtr<AccessibilityObject> obj = replacedNode->renderer()->document()->axObjectCache()->getOrCreate(replacedNode->renderer());
811     if (obj->accessibilityIsIgnored())
812         return nil;
813     
814     // use the attachmentCharacter to represent the replaced node
815     const UniChar attachmentChar = NSAttachmentCharacter;
816     return [NSString stringWithCharacters:&attachmentChar length:1];
817 }
818
819 - (NSAttributedString*)doAXAttributedStringForTextMarkerRange:(id)textMarkerRange
820 {
821     if (!m_object)
822         return nil;
823     
824     // extract the start and end VisiblePosition
825     VisiblePosition startVisiblePosition = visiblePositionForStartOfTextMarkerRange(m_object->axObjectCache(), textMarkerRange);
826     if (startVisiblePosition.isNull())
827         return nil;
828
829     VisiblePosition endVisiblePosition = visiblePositionForEndOfTextMarkerRange(m_object->axObjectCache(), textMarkerRange);
830     if (endVisiblePosition.isNull())
831         return nil;
832
833     VisiblePositionRange visiblePositionRange(startVisiblePosition, endVisiblePosition);
834     // iterate over the range to build the AX attributed string
835     NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] init];
836     TextIterator it(makeRange(startVisiblePosition, endVisiblePosition).get());
837     while (!it.atEnd()) {
838         // locate the node and starting offset for this range
839         int exception = 0;
840         Node* node = it.range()->startContainer(exception);
841         ASSERT(node == it.range()->endContainer(exception));
842         int offset = it.range()->startOffset(exception);
843
844         // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX)
845         if (it.length() != 0) {
846             // Add the text of the list marker item if necessary.
847             String listMarkerText = m_object->listMarkerTextForNodeAndPosition(node, VisiblePosition(it.range()->startPosition()));
848             if (!listMarkerText.isEmpty())
849                 AXAttributedStringAppendText(attrString, node, listMarkerText.characters(), listMarkerText.length());
850             
851             AXAttributedStringAppendText(attrString, node, it.characters(), it.length());
852         } else {
853             Node* replacedNode = node->childNode(offset);
854             NSString *attachmentString = nsStringForReplacedNode(replacedNode);
855             if (attachmentString) {
856                 NSRange attrStringRange = NSMakeRange([attrString length], [attachmentString length]);
857
858                 // append the placeholder string
859                 [[attrString mutableString] appendString:attachmentString];
860
861                 // remove all inherited attributes
862                 [attrString setAttributes:nil range:attrStringRange];
863
864                 // add the attachment attribute
865                 AccessibilityObject* obj = replacedNode->renderer()->document()->axObjectCache()->getOrCreate(replacedNode->renderer());
866                 AXAttributeStringSetElement(attrString, NSAccessibilityAttachmentTextAttribute, obj, attrStringRange);
867             }
868         }
869         it.advance();
870     }
871
872     return [attrString autorelease];
873 }
874
875 static id textMarkerRangeFromVisiblePositions(AXObjectCache *cache, VisiblePosition startPosition, VisiblePosition endPosition)
876 {
877     id startTextMarker = textMarkerForVisiblePosition(cache, startPosition);
878     id endTextMarker = textMarkerForVisiblePosition(cache, endPosition);
879     return textMarkerRangeFromMarkers(startTextMarker, endTextMarker);
880 }
881
882 - (id)textMarkerRangeFromVisiblePositions:(VisiblePosition)startPosition endPosition:(VisiblePosition)endPosition
883 {
884     return textMarkerRangeFromVisiblePositions(m_object->axObjectCache(), startPosition, endPosition);
885 }
886
887 - (NSArray*)accessibilityActionNames
888 {
889     if (![self updateObjectBackingStore])
890         return nil;
891
892     static NSArray* actionElementActions = [[NSArray alloc] initWithObjects: NSAccessibilityPressAction, NSAccessibilityShowMenuAction, nil];
893     static NSArray* defaultElementActions = [[NSArray alloc] initWithObjects: NSAccessibilityShowMenuAction, nil];
894     static NSArray* menuElementActions = [[NSArray alloc] initWithObjects: NSAccessibilityCancelAction, NSAccessibilityPressAction, nil];
895     static NSArray* sliderActions = [[NSArray alloc] initWithObjects: NSAccessibilityIncrementAction, NSAccessibilityDecrementAction, nil];
896
897     NSArray *actions;
898     if (m_object->actionElement() || m_object->isButton()) 
899         actions = actionElementActions;
900     else if (m_object->isMenuRelated())
901         actions = menuElementActions;
902     else if (m_object->isSlider())
903         actions = sliderActions;
904     else if (m_object->isAttachment())
905         actions = [[self attachmentView] accessibilityActionNames];
906     else
907         actions = defaultElementActions;
908
909     return actions;
910 }
911
912 - (NSArray*)additionalAccessibilityAttributeNames
913 {
914     if (!m_object)
915         return nil;
916
917     NSMutableArray *additional = [NSMutableArray array];
918     if (m_object->supportsARIAOwns())
919         [additional addObject:NSAccessibilityOwnsAttribute];
920
921     if (m_object->supportsARIAExpanded())
922         [additional addObject:NSAccessibilityExpandedAttribute];
923     
924     if (m_object->isScrollbar())
925         [additional addObject:NSAccessibilityOrientationAttribute];
926     
927     if (m_object->supportsARIADragging())
928         [additional addObject:NSAccessibilityGrabbedAttribute];
929
930     if (m_object->supportsARIADropping())
931         [additional addObject:NSAccessibilityDropEffectsAttribute];
932
933     if (m_object->isAccessibilityTable() && static_cast<AccessibilityTable*>(m_object)->supportsSelectedRows())
934         [additional addObject:NSAccessibilitySelectedRowsAttribute];        
935     
936     if (m_object->supportsARIALiveRegion()) {
937         [additional addObject:NSAccessibilityARIALiveAttribute];
938         [additional addObject:NSAccessibilityARIARelevantAttribute];
939     }
940     
941     if (m_object->sortDirection() != SortDirectionNone)
942         [additional addObject:NSAccessibilitySortDirectionAttribute];
943         
944     // If an object is a child of a live region, then add these
945     if (m_object->isInsideARIALiveRegion()) {
946         [additional addObject:NSAccessibilityARIAAtomicAttribute];
947         [additional addObject:NSAccessibilityARIABusyAttribute];
948     }
949     
950     if (m_object->ariaHasPopup())
951         [additional addObject:NSAccessibilityHasPopupAttribute];
952     
953     return additional;
954 }
955
956 - (NSArray*)accessibilityAttributeNames
957 {
958     if (![self updateObjectBackingStore])
959         return nil;
960     
961     if (m_object->isAttachment())
962         return [[self attachmentView] accessibilityAttributeNames];
963
964     static NSArray* attributes = nil;
965     static NSArray* anchorAttrs = nil;
966     static NSArray* webAreaAttrs = nil;
967     static NSArray* textAttrs = nil;
968     static NSArray* listAttrs = nil;
969     static NSArray* listBoxAttrs = nil;
970     static NSArray* rangeAttrs = nil;
971     static NSArray* commonMenuAttrs = nil;
972     static NSArray* menuAttrs = nil;
973     static NSArray* menuBarAttrs = nil;
974     static NSArray* menuItemAttrs = nil;
975     static NSArray* menuButtonAttrs = nil;
976     static NSArray* controlAttrs = nil;
977     static NSArray* tableAttrs = nil;
978     static NSArray* tableRowAttrs = nil;
979     static NSArray* tableColAttrs = nil;
980     static NSArray* tableCellAttrs = nil;
981     static NSArray* groupAttrs = nil;
982     static NSArray* inputImageAttrs = nil;
983     static NSArray* passwordFieldAttrs = nil;
984     static NSArray* tabListAttrs = nil;
985     static NSArray* comboBoxAttrs = nil;
986     static NSArray* outlineAttrs = nil;
987     static NSArray* outlineRowAttrs = nil;
988     static NSArray* buttonAttrs = nil;
989     static NSArray* scrollViewAttrs = nil;
990     static NSArray* incrementorAttrs = nil;
991     NSMutableArray* tempArray;
992     if (attributes == nil) {
993         attributes = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
994                       NSAccessibilitySubroleAttribute,
995                       NSAccessibilityRoleDescriptionAttribute,
996                       NSAccessibilityChildrenAttribute,
997                       NSAccessibilityHelpAttribute,
998                       NSAccessibilityParentAttribute,
999                       NSAccessibilityPositionAttribute,
1000                       NSAccessibilitySizeAttribute,
1001                       NSAccessibilityTitleAttribute,
1002                       NSAccessibilityDescriptionAttribute,
1003                       NSAccessibilityValueAttribute,
1004                       NSAccessibilityFocusedAttribute,
1005                       NSAccessibilityEnabledAttribute,
1006                       NSAccessibilityWindowAttribute,
1007                       @"AXSelectedTextMarkerRange",
1008                       @"AXStartTextMarker",
1009                       @"AXEndTextMarker",
1010                       @"AXVisited",
1011                       NSAccessibilityLinkedUIElementsAttribute,
1012                       NSAccessibilitySelectedAttribute,
1013                       NSAccessibilityBlockQuoteLevelAttribute,
1014                       NSAccessibilityTopLevelUIElementAttribute,
1015                       nil];
1016     }
1017     if (commonMenuAttrs == nil) {
1018         commonMenuAttrs = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
1019                             NSAccessibilityRoleDescriptionAttribute,
1020                             NSAccessibilityChildrenAttribute,
1021                             NSAccessibilityParentAttribute,
1022                             NSAccessibilityEnabledAttribute,
1023                             NSAccessibilityPositionAttribute,
1024                             NSAccessibilitySizeAttribute,
1025                             nil];
1026     }
1027     if (anchorAttrs == nil) {
1028         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1029         [tempArray addObject:NSAccessibilityURLAttribute];
1030         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1031         anchorAttrs = [[NSArray alloc] initWithArray:tempArray];
1032         [tempArray release];
1033     }
1034     if (webAreaAttrs == nil) {
1035         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1036         [tempArray addObject:@"AXLinkUIElements"];
1037         [tempArray addObject:@"AXLoaded"];
1038         [tempArray addObject:@"AXLayoutCount"];
1039         [tempArray addObject:NSAccessibilityLoadingProgressAttribute];
1040         [tempArray addObject:NSAccessibilityURLAttribute];
1041         webAreaAttrs = [[NSArray alloc] initWithArray:tempArray];
1042         [tempArray release];
1043     }
1044     if (textAttrs == nil) {
1045         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1046         [tempArray addObject:NSAccessibilityNumberOfCharactersAttribute];
1047         [tempArray addObject:NSAccessibilitySelectedTextAttribute];
1048         [tempArray addObject:NSAccessibilitySelectedTextRangeAttribute];
1049         [tempArray addObject:NSAccessibilityVisibleCharacterRangeAttribute];
1050         [tempArray addObject:NSAccessibilityInsertionPointLineNumberAttribute];
1051         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1052         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1053         [tempArray addObject:NSAccessibilityRequiredAttribute];
1054         [tempArray addObject:NSAccessibilityInvalidAttribute];
1055         [tempArray addObject:NSAccessibilityPlaceholderValueAttribute];
1056         textAttrs = [[NSArray alloc] initWithArray:tempArray];
1057         [tempArray release];
1058     }
1059     if (listAttrs == nil) {
1060         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1061         [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1062         [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1063         [tempArray addObject:NSAccessibilityOrientationAttribute];
1064         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1065         listAttrs = [[NSArray alloc] initWithArray:tempArray];
1066         [tempArray release];
1067     }
1068     if (listBoxAttrs == nil) {
1069         tempArray = [[NSMutableArray alloc] initWithArray:listAttrs];    
1070         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1071         [tempArray addObject:NSAccessibilityRequiredAttribute];
1072         [tempArray addObject:NSAccessibilityInvalidAttribute];
1073         listBoxAttrs = [[NSArray alloc] initWithArray:tempArray];
1074         [tempArray release];
1075     }
1076     if (rangeAttrs == nil) {
1077         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1078         [tempArray addObject:NSAccessibilityMinValueAttribute];
1079         [tempArray addObject:NSAccessibilityMaxValueAttribute];
1080         [tempArray addObject:NSAccessibilityOrientationAttribute];
1081         [tempArray addObject:NSAccessibilityValueDescriptionAttribute];
1082         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1083         rangeAttrs = [[NSArray alloc] initWithArray:tempArray];
1084         [tempArray release];
1085     }
1086     if (menuBarAttrs == nil) {
1087         tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1088         [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1089         [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1090         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1091         menuBarAttrs = [[NSArray alloc] initWithArray:tempArray];
1092         [tempArray release];
1093     }
1094     if (menuAttrs == nil) {
1095         tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1096         [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1097         [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1098         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1099         menuAttrs = [[NSArray alloc] initWithArray:tempArray];
1100         [tempArray release];
1101     }
1102     if (menuItemAttrs == nil) {
1103         tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1104         [tempArray addObject:NSAccessibilityTitleAttribute];
1105         [tempArray addObject:NSAccessibilityHelpAttribute];
1106         [tempArray addObject:NSAccessibilitySelectedAttribute];
1107         [tempArray addObject:(NSString*)kAXMenuItemCmdCharAttribute];
1108         [tempArray addObject:(NSString*)kAXMenuItemCmdVirtualKeyAttribute];
1109         [tempArray addObject:(NSString*)kAXMenuItemCmdGlyphAttribute];
1110         [tempArray addObject:(NSString*)kAXMenuItemCmdModifiersAttribute];
1111         [tempArray addObject:(NSString*)kAXMenuItemMarkCharAttribute];
1112         [tempArray addObject:(NSString*)kAXMenuItemPrimaryUIElementAttribute];
1113         [tempArray addObject:NSAccessibilityServesAsTitleForUIElementsAttribute];
1114         menuItemAttrs = [[NSArray alloc] initWithArray:tempArray];
1115         [tempArray release];
1116     }
1117     if (menuButtonAttrs == nil) {
1118         menuButtonAttrs = [[NSArray alloc] initWithObjects:NSAccessibilityRoleAttribute,
1119             NSAccessibilityRoleDescriptionAttribute,
1120             NSAccessibilityParentAttribute,
1121             NSAccessibilityPositionAttribute,
1122             NSAccessibilitySizeAttribute,
1123             NSAccessibilityWindowAttribute,
1124             NSAccessibilityEnabledAttribute,
1125             NSAccessibilityFocusedAttribute,
1126             NSAccessibilityTitleAttribute,
1127             NSAccessibilityChildrenAttribute, nil];
1128     }
1129     if (controlAttrs == nil) {
1130         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1131         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1132         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1133         [tempArray addObject:NSAccessibilityRequiredAttribute];
1134         [tempArray addObject:NSAccessibilityInvalidAttribute];
1135         controlAttrs = [[NSArray alloc] initWithArray:tempArray];
1136         [tempArray release];
1137     }
1138     if (incrementorAttrs == nil) {
1139         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1140         [tempArray addObject:NSAccessibilityIncrementButtonAttribute];
1141         [tempArray addObject:NSAccessibilityDecrementButtonAttribute];
1142         incrementorAttrs = [[NSArray alloc] initWithArray:tempArray];
1143         [tempArray release];
1144     }
1145     if (buttonAttrs == nil) {
1146         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1147         // Buttons should not expose AXValue.
1148         [tempArray removeObject:NSAccessibilityValueAttribute];
1149         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1150         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1151         buttonAttrs = [[NSArray alloc] initWithArray:tempArray];
1152         [tempArray release];
1153     }
1154     if (comboBoxAttrs == nil) {
1155         tempArray = [[NSMutableArray alloc] initWithArray:controlAttrs];
1156         [tempArray addObject:NSAccessibilityExpandedAttribute];
1157         comboBoxAttrs = [[NSArray alloc] initWithArray:tempArray];
1158         [tempArray release];        
1159     }
1160     if (tableAttrs == nil) {
1161         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1162         [tempArray addObject:NSAccessibilityRowsAttribute];
1163         [tempArray addObject:NSAccessibilityVisibleRowsAttribute];
1164         [tempArray addObject:NSAccessibilityColumnsAttribute];
1165         [tempArray addObject:NSAccessibilityVisibleColumnsAttribute];
1166         [tempArray addObject:NSAccessibilityVisibleCellsAttribute];
1167         [tempArray addObject:(NSString *)kAXColumnHeaderUIElementsAttribute];
1168         [tempArray addObject:NSAccessibilityRowHeaderUIElementsAttribute];
1169         [tempArray addObject:NSAccessibilityHeaderAttribute];
1170         tableAttrs = [[NSArray alloc] initWithArray:tempArray];
1171         [tempArray release];
1172     }
1173     if (tableRowAttrs == nil) {
1174         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1175         [tempArray addObject:NSAccessibilityIndexAttribute];
1176         tableRowAttrs = [[NSArray alloc] initWithArray:tempArray];
1177         [tempArray release];
1178     }
1179     if (tableColAttrs == nil) {
1180         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1181         [tempArray addObject:NSAccessibilityIndexAttribute];
1182         [tempArray addObject:NSAccessibilityHeaderAttribute];
1183         [tempArray addObject:NSAccessibilityRowsAttribute];
1184         [tempArray addObject:NSAccessibilityVisibleRowsAttribute];
1185         tableColAttrs = [[NSArray alloc] initWithArray:tempArray];
1186         [tempArray release];
1187     }
1188     if (tableCellAttrs == nil) {
1189         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1190         [tempArray addObject:NSAccessibilityRowIndexRangeAttribute];
1191         [tempArray addObject:NSAccessibilityColumnIndexRangeAttribute];
1192         tableCellAttrs = [[NSArray alloc] initWithArray:tempArray];
1193         [tempArray release];        
1194     }
1195     if (groupAttrs == nil) {
1196         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1197         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1198         groupAttrs = [[NSArray alloc] initWithArray:tempArray];
1199         [tempArray release];
1200     }
1201     if (inputImageAttrs == nil) {
1202         tempArray = [[NSMutableArray alloc] initWithArray:buttonAttrs];
1203         [tempArray addObject:NSAccessibilityURLAttribute];
1204         inputImageAttrs = [[NSArray alloc] initWithArray:tempArray];
1205         [tempArray release];
1206     }
1207     if (passwordFieldAttrs == nil) {
1208         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1209         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1210         [tempArray addObject:NSAccessibilityRequiredAttribute];
1211         [tempArray addObject:NSAccessibilityInvalidAttribute];
1212         [tempArray addObject:NSAccessibilityPlaceholderValueAttribute];
1213         passwordFieldAttrs = [[NSArray alloc] initWithArray:tempArray];
1214         [tempArray release];
1215     }
1216     if (tabListAttrs == nil) {
1217         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1218         [tempArray addObject:NSAccessibilityTabsAttribute];
1219         [tempArray addObject:NSAccessibilityContentsAttribute];
1220         tabListAttrs = [[NSArray alloc] initWithArray:tempArray];
1221         [tempArray release];        
1222     }
1223     if (outlineAttrs == nil) {
1224         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1225         [tempArray addObject:NSAccessibilitySelectedRowsAttribute];
1226         [tempArray addObject:NSAccessibilityRowsAttribute];
1227         [tempArray addObject:NSAccessibilityColumnsAttribute];
1228         outlineAttrs = [[NSArray alloc] initWithArray:tempArray];
1229         [tempArray release];
1230     }
1231     if (outlineRowAttrs == nil) {
1232         tempArray = [[NSMutableArray alloc] initWithArray:tableRowAttrs];
1233         [tempArray addObject:NSAccessibilityDisclosingAttribute];
1234         [tempArray addObject:NSAccessibilityDisclosedByRowAttribute];
1235         [tempArray addObject:NSAccessibilityDisclosureLevelAttribute];
1236         [tempArray addObject:NSAccessibilityDisclosedRowsAttribute];
1237         outlineRowAttrs = [[NSArray alloc] initWithArray:tempArray];
1238         [tempArray release];
1239     }
1240     if (scrollViewAttrs == nil) {
1241         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1242         [tempArray addObject:NSAccessibilityContentsAttribute];
1243         [tempArray addObject:NSAccessibilityHorizontalScrollBarAttribute];
1244         [tempArray addObject:NSAccessibilityVerticalScrollBarAttribute];
1245         scrollViewAttrs = [[NSArray alloc] initWithArray:tempArray];
1246         [tempArray release];
1247     }
1248     
1249     NSArray *objectAttributes = attributes;
1250     
1251     if (m_object->isPasswordField())
1252         objectAttributes = passwordFieldAttrs;
1253
1254     else if (m_object->isWebArea())
1255         objectAttributes = webAreaAttrs;
1256     
1257     else if (m_object->isTextControl())
1258         objectAttributes = textAttrs;
1259
1260     else if (m_object->isAnchor() || m_object->isImage() || m_object->isLink())
1261         objectAttributes = anchorAttrs;
1262
1263     else if (m_object->isAccessibilityTable())
1264         objectAttributes = tableAttrs;
1265     else if (m_object->isTableColumn())
1266         objectAttributes = tableColAttrs;
1267     else if (m_object->isTableCell())
1268         objectAttributes = tableCellAttrs;
1269     else if (m_object->isTableRow()) {
1270         // An ARIA table row can be collapsed and expanded, so it needs the extra attributes.
1271         if (m_object->isARIATreeGridRow())
1272             objectAttributes = outlineRowAttrs;
1273         else
1274             objectAttributes = tableRowAttrs;
1275     }
1276     
1277     else if (m_object->isTree())
1278         objectAttributes = outlineAttrs;
1279     else if (m_object->isTreeItem())
1280         objectAttributes = outlineRowAttrs;
1281     
1282     else if (m_object->isListBox())
1283         objectAttributes = listBoxAttrs;
1284     else if (m_object->isList())
1285         objectAttributes = listAttrs;
1286     
1287     else if (m_object->isComboBox())
1288         objectAttributes = comboBoxAttrs;
1289     
1290     else if (m_object->isProgressIndicator() || m_object->isSlider())
1291         objectAttributes = rangeAttrs;
1292
1293     // These are processed in order because an input image is a button, and a button is a control.
1294     else if (m_object->isInputImage())
1295         objectAttributes = inputImageAttrs;
1296     else if (m_object->isButton())
1297         objectAttributes = buttonAttrs;
1298     else if (m_object->isControl())
1299         objectAttributes = controlAttrs;
1300     
1301     else if (m_object->isGroup() || m_object->isListItem())
1302         objectAttributes = groupAttrs;
1303     else if (m_object->isTabList())
1304         objectAttributes = tabListAttrs;
1305     else if (m_object->isScrollView())
1306         objectAttributes = scrollViewAttrs;
1307     else if (m_object->isSpinButton())
1308         objectAttributes = incrementorAttrs;
1309     
1310     else if (m_object->isMenu())
1311         objectAttributes = menuAttrs;
1312     else if (m_object->isMenuBar())
1313         objectAttributes = menuBarAttrs;
1314     else if (m_object->isMenuButton())
1315         objectAttributes = menuButtonAttrs;
1316     else if (m_object->isMenuItem())
1317         objectAttributes = menuItemAttrs;
1318     
1319     NSArray *additionalAttributes = [self additionalAccessibilityAttributeNames];
1320     if ([additionalAttributes count])
1321         objectAttributes = [objectAttributes arrayByAddingObjectsFromArray:additionalAttributes];
1322     
1323     return objectAttributes;
1324 }
1325
1326 - (VisiblePositionRange)visiblePositionRangeForTextMarkerRange:(id)textMarkerRange
1327 {
1328     if (!textMarkerRange)
1329         return VisiblePositionRange();
1330     AXObjectCache* cache = m_object->axObjectCache();
1331     return VisiblePositionRange(visiblePositionForStartOfTextMarkerRange(cache, textMarkerRange), visiblePositionForEndOfTextMarkerRange(cache, textMarkerRange));
1332 }
1333
1334 - (NSArray*)renderWidgetChildren
1335 {
1336     Widget* widget = m_object->widget();
1337     if (!widget)
1338         return nil;
1339     return [(widget->platformWidget()) accessibilityAttributeValue: NSAccessibilityChildrenAttribute];
1340 }
1341
1342 - (id)remoteAccessibilityParentObject
1343 {
1344     if (!m_object || !m_object->document() || !m_object->document()->frame())
1345         return nil;
1346     
1347     return m_object->document()->frame()->loader()->client()->accessibilityRemoteObject();
1348 }
1349
1350 static void convertToVector(NSArray* array, AccessibilityObject::AccessibilityChildrenVector& vector)
1351 {
1352     unsigned length = [array count];
1353     vector.reserveInitialCapacity(length);
1354     for (unsigned i = 0; i < length; ++i) {
1355         AccessibilityObject* obj = [[array objectAtIndex:i] accessibilityObject];
1356         if (obj)
1357             vector.append(obj);
1358     }
1359 }
1360
1361 static NSMutableArray* convertToNSArray(const AccessibilityObject::AccessibilityChildrenVector& vector)
1362 {
1363     unsigned length = vector.size();
1364     NSMutableArray* array = [NSMutableArray arrayWithCapacity: length];
1365     for (unsigned i = 0; i < length; ++i) {
1366         WebAccessibilityObjectWrapper* wrapper = vector[i]->wrapper();
1367         ASSERT(wrapper);
1368         if (wrapper) {
1369             // we want to return the attachment view instead of the object representing the attachment.
1370             // otherwise, we get palindrome errors in the AX hierarchy
1371             if (vector[i]->isAttachment() && [wrapper attachmentView])
1372                 [array addObject:[wrapper attachmentView]];
1373             else
1374                 [array addObject:wrapper];
1375         }
1376     }
1377     return array;
1378 }
1379
1380 - (id)textMarkerRangeForSelection
1381 {
1382     VisibleSelection selection = m_object->selection();
1383     if (selection.isNone())
1384         return nil;
1385     return [self textMarkerRangeFromVisiblePositions:selection.visibleStart() endPosition:selection.visibleEnd()];
1386 }
1387
1388 - (NSValue *)position
1389 {
1390     LayoutRect rect = m_object->elementRect();
1391     NSPoint point;
1392     
1393     FrameView* frameView = m_object->documentFrameView();
1394
1395     // WebKit1 code path... platformWidget() exists.
1396     if (frameView && frameView->platformWidget()) {
1397     
1398         // The Cocoa accessibility API wants the lower-left corner.
1399         point = NSMakePoint(rect.x(), rect.maxY());
1400         
1401         if (frameView) {
1402             NSView* view = frameView->documentView();
1403             point = [[view window] convertBaseToScreen:[view convertPoint: point toView:nil]];
1404         }
1405     } else {
1406         
1407         // Find the appropriate scroll view to use to convert the contents to the window.
1408         ScrollView* scrollView = 0;
1409         for (AccessibilityObject* parent = m_object->parentObject(); parent; parent = parent->parentObject()) {
1410             if (parent->isAccessibilityScrollView()) {
1411                 scrollView = toAccessibilityScrollView(parent)->scrollView();
1412                 break;
1413             }
1414         }
1415
1416         if (scrollView)
1417             rect = scrollView->contentsToRootView(rect);
1418         
1419         if (m_object->page())
1420             point = m_object->page()->chrome()->rootViewToScreen(rect).location();
1421         else
1422             point = rect.location();
1423     }
1424     
1425     return [NSValue valueWithPoint:point];
1426 }
1427
1428 typedef HashMap<int, NSString*> AccessibilityRoleMap;
1429
1430 static const AccessibilityRoleMap& createAccessibilityRoleMap()
1431 {
1432     struct RoleEntry {
1433         AccessibilityRole value;
1434         NSString* string;
1435     };
1436     
1437     static const RoleEntry roles[] = {
1438         { UnknownRole, NSAccessibilityUnknownRole },
1439         { ButtonRole, NSAccessibilityButtonRole },
1440         { RadioButtonRole, NSAccessibilityRadioButtonRole },
1441         { CheckBoxRole, NSAccessibilityCheckBoxRole },
1442         { SliderRole, NSAccessibilitySliderRole },
1443         { TabGroupRole, NSAccessibilityTabGroupRole },
1444         { TextFieldRole, NSAccessibilityTextFieldRole },
1445         { StaticTextRole, NSAccessibilityStaticTextRole },
1446         { TextAreaRole, NSAccessibilityTextAreaRole },
1447         { ScrollAreaRole, NSAccessibilityScrollAreaRole },
1448         { PopUpButtonRole, NSAccessibilityPopUpButtonRole },
1449         { MenuButtonRole, NSAccessibilityMenuButtonRole },
1450         { TableRole, NSAccessibilityTableRole },
1451         { ApplicationRole, NSAccessibilityApplicationRole },
1452         { GroupRole, NSAccessibilityGroupRole },
1453         { RadioGroupRole, NSAccessibilityRadioGroupRole },
1454         { ListRole, NSAccessibilityListRole },
1455         { DirectoryRole, NSAccessibilityListRole },
1456         { ScrollBarRole, NSAccessibilityScrollBarRole },
1457         { ValueIndicatorRole, NSAccessibilityValueIndicatorRole },
1458         { ImageRole, NSAccessibilityImageRole },
1459         { MenuBarRole, NSAccessibilityMenuBarRole },
1460         { MenuRole, NSAccessibilityMenuRole },
1461         { MenuItemRole, NSAccessibilityMenuItemRole },
1462         { ColumnRole, NSAccessibilityColumnRole },
1463         { RowRole, NSAccessibilityRowRole },
1464         { ToolbarRole, NSAccessibilityToolbarRole },
1465         { BusyIndicatorRole, NSAccessibilityBusyIndicatorRole },
1466         { ProgressIndicatorRole, NSAccessibilityProgressIndicatorRole },
1467         { WindowRole, NSAccessibilityWindowRole },
1468         { DrawerRole, NSAccessibilityDrawerRole },
1469         { SystemWideRole, NSAccessibilitySystemWideRole },
1470         { OutlineRole, NSAccessibilityOutlineRole },
1471         { IncrementorRole, NSAccessibilityIncrementorRole },
1472         { BrowserRole, NSAccessibilityBrowserRole },
1473         { ComboBoxRole, NSAccessibilityComboBoxRole },
1474         { SplitGroupRole, NSAccessibilitySplitGroupRole },
1475         { SplitterRole, NSAccessibilitySplitterRole },
1476         { ColorWellRole, NSAccessibilityColorWellRole },
1477         { GrowAreaRole, NSAccessibilityGrowAreaRole },
1478         { SheetRole, NSAccessibilitySheetRole },
1479         { HelpTagRole, NSAccessibilityHelpTagRole },
1480         { MatteRole, NSAccessibilityMatteRole }, 
1481         { RulerRole, NSAccessibilityRulerRole },
1482         { RulerMarkerRole, NSAccessibilityRulerMarkerRole },
1483         { LinkRole, NSAccessibilityLinkRole },
1484         { DisclosureTriangleRole, NSAccessibilityDisclosureTriangleRole },
1485         { GridRole, NSAccessibilityGridRole },
1486         { WebCoreLinkRole, NSAccessibilityLinkRole }, 
1487         { ImageMapLinkRole, NSAccessibilityLinkRole },
1488         { ImageMapRole, @"AXImageMap" },
1489         { ListMarkerRole, @"AXListMarker" },
1490         { WebAreaRole, @"AXWebArea" },
1491         { HeadingRole, @"AXHeading" },
1492         { ListBoxRole, NSAccessibilityListRole },
1493         { ListBoxOptionRole, NSAccessibilityStaticTextRole },
1494 #if ACCESSIBILITY_TABLES
1495         { CellRole, NSAccessibilityCellRole },
1496 #else
1497         { CellRole, NSAccessibilityGroupRole },
1498 #endif
1499         { TableHeaderContainerRole, NSAccessibilityGroupRole },
1500         { DefinitionListDefinitionRole, NSAccessibilityGroupRole },
1501         { DefinitionListTermRole, NSAccessibilityGroupRole },
1502         { SliderThumbRole, NSAccessibilityValueIndicatorRole },
1503         { LandmarkApplicationRole, NSAccessibilityGroupRole },
1504         { LandmarkBannerRole, NSAccessibilityGroupRole },
1505         { LandmarkComplementaryRole, NSAccessibilityGroupRole },
1506         { LandmarkContentInfoRole, NSAccessibilityGroupRole },
1507         { LandmarkMainRole, NSAccessibilityGroupRole },
1508         { LandmarkNavigationRole, NSAccessibilityGroupRole },
1509         { LandmarkSearchRole, NSAccessibilityGroupRole },
1510         { ApplicationAlertRole, NSAccessibilityGroupRole },
1511         { ApplicationAlertDialogRole, NSAccessibilityGroupRole },
1512         { ApplicationDialogRole, NSAccessibilityGroupRole },
1513         { ApplicationLogRole, NSAccessibilityGroupRole },
1514         { ApplicationMarqueeRole, NSAccessibilityGroupRole },
1515         { ApplicationStatusRole, NSAccessibilityGroupRole },
1516         { ApplicationTimerRole, NSAccessibilityGroupRole },
1517         { DocumentRole, NSAccessibilityGroupRole },
1518         { DocumentArticleRole, NSAccessibilityGroupRole },
1519         { DocumentMathRole, NSAccessibilityGroupRole },
1520         { DocumentNoteRole, NSAccessibilityGroupRole },
1521         { DocumentRegionRole, NSAccessibilityGroupRole },
1522         { UserInterfaceTooltipRole, NSAccessibilityGroupRole },
1523         { TabRole, NSAccessibilityRadioButtonRole },
1524         { TabListRole, NSAccessibilityTabGroupRole },
1525         { TabPanelRole, NSAccessibilityGroupRole },
1526         { TreeRole, NSAccessibilityOutlineRole },
1527         { TreeItemRole, NSAccessibilityRowRole },
1528         { ListItemRole, NSAccessibilityGroupRole },
1529         { ParagraphRole, NSAccessibilityGroupRole },
1530         { LabelRole, NSAccessibilityGroupRole },
1531         { DivRole, NSAccessibilityGroupRole },
1532         { FormRole, NSAccessibilityGroupRole },
1533         { SpinButtonRole, NSAccessibilityIncrementorRole }
1534     };
1535     AccessibilityRoleMap& roleMap = *new AccessibilityRoleMap;
1536     
1537     const unsigned numRoles = sizeof(roles) / sizeof(roles[0]);
1538     for (unsigned i = 0; i < numRoles; ++i)
1539         roleMap.set(roles[i].value, roles[i].string);
1540     return roleMap;
1541 }
1542
1543 static NSString* roleValueToNSString(AccessibilityRole value)
1544 {
1545     ASSERT(value);
1546     static const AccessibilityRoleMap& roleMap = createAccessibilityRoleMap();
1547     return roleMap.get(value);
1548 }
1549
1550 - (NSString*)role
1551 {
1552     if (m_object->isAttachment())
1553         return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleAttribute];
1554     NSString* string = roleValueToNSString(m_object->roleValue());
1555     if (string != nil)
1556         return string;
1557     return NSAccessibilityUnknownRole;
1558 }
1559
1560 - (NSString*)subrole
1561 {
1562     if (m_object->isPasswordField())
1563         return NSAccessibilitySecureTextFieldSubrole;
1564     
1565     if (m_object->isAttachment()) {
1566         NSView* attachView = [self attachmentView];
1567         if ([[attachView accessibilityAttributeNames] containsObject:NSAccessibilitySubroleAttribute]) {
1568             return [attachView accessibilityAttributeValue:NSAccessibilitySubroleAttribute];
1569         }
1570     }
1571     
1572     if (m_object->isSpinButtonPart()) {
1573         if (toAccessibilitySpinButtonPart(m_object)->isIncrementor())
1574             return NSAccessibilityIncrementArrowSubrole;
1575
1576         return NSAccessibilityDecrementArrowSubrole;
1577     }
1578     
1579     if (m_object->isTreeItem())
1580         return NSAccessibilityOutlineRowSubrole;
1581     
1582     if (m_object->isList()) {
1583         AccessibilityList* listObject = static_cast<AccessibilityList*>(m_object);
1584         if (listObject->isUnorderedList() || listObject->isOrderedList())
1585             return NSAccessibilityContentListSubrole;
1586         if (listObject->isDefinitionList())
1587             return NSAccessibilityDefinitionListSubrole;
1588     }
1589     
1590     // ARIA content subroles.
1591     switch (m_object->roleValue()) {
1592         case LandmarkApplicationRole:
1593             return @"AXLandmarkApplication";
1594         case LandmarkBannerRole:
1595             return @"AXLandmarkBanner";
1596         case LandmarkComplementaryRole:
1597             return @"AXLandmarkComplementary";
1598         case LandmarkContentInfoRole:
1599             return @"AXLandmarkContentInfo";
1600         case LandmarkMainRole:
1601             return @"AXLandmarkMain";
1602         case LandmarkNavigationRole:
1603             return @"AXLandmarkNavigation";
1604         case LandmarkSearchRole:
1605             return @"AXLandmarkSearch";
1606         case ApplicationAlertRole:
1607             return @"AXApplicationAlert";
1608         case ApplicationAlertDialogRole:
1609             return @"AXApplicationAlertDialog";
1610         case ApplicationDialogRole:
1611             return @"AXApplicationDialog";
1612         case ApplicationLogRole:
1613             return @"AXApplicationLog";
1614         case ApplicationMarqueeRole:
1615             return @"AXApplicationMarquee";
1616         case ApplicationStatusRole:
1617             return @"AXApplicationStatus";
1618         case ApplicationTimerRole:
1619             return @"AXApplicationTimer";
1620         case DocumentRole:
1621             return @"AXDocument";
1622         case DocumentArticleRole:
1623             return @"AXDocumentArticle";
1624         case DocumentMathRole:
1625             return @"AXDocumentMath";
1626         case DocumentNoteRole:
1627             return @"AXDocumentNote";
1628         case DocumentRegionRole:
1629             return @"AXDocumentRegion";
1630         case UserInterfaceTooltipRole:
1631             return @"AXUserInterfaceTooltip";
1632         case TabPanelRole:
1633             return @"AXTabPanel";
1634         case DefinitionListTermRole:
1635             return @"AXTerm";
1636         case DefinitionListDefinitionRole:
1637             return @"AXDefinition";
1638         // Default doesn't return anything, so roles defined below can be chosen.
1639         default:
1640             break;
1641     }
1642     
1643     if (m_object->isMediaTimeline())
1644         return NSAccessibilityTimelineSubrole;
1645
1646     return nil;
1647 }
1648
1649 - (NSString*)roleDescription
1650 {
1651     if (!m_object)
1652         return nil;
1653
1654     // attachments have the AXImage role, but a different subrole
1655     if (m_object->isAttachment())
1656         return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleDescriptionAttribute];
1657     
1658     NSString* axRole = [self role];
1659     
1660     if ([axRole isEqualToString:NSAccessibilityGroupRole]) {
1661         switch (m_object->roleValue()) {
1662             default:
1663                 return NSAccessibilityRoleDescription(NSAccessibilityGroupRole, [self subrole]);
1664             case LandmarkApplicationRole:
1665                 return AXARIAContentGroupText(@"ARIALandmarkApplication");
1666             case LandmarkBannerRole:
1667                 return AXARIAContentGroupText(@"ARIALandmarkBanner");
1668             case LandmarkComplementaryRole:
1669                 return AXARIAContentGroupText(@"ARIALandmarkComplementary");
1670             case LandmarkContentInfoRole:
1671                 return AXARIAContentGroupText(@"ARIALandmarkContentInfo");
1672             case LandmarkMainRole:
1673                 return AXARIAContentGroupText(@"ARIALandmarkMain");
1674             case LandmarkNavigationRole:
1675                 return AXARIAContentGroupText(@"ARIALandmarkNavigation");
1676             case LandmarkSearchRole:
1677                 return AXARIAContentGroupText(@"ARIALandmarkSearch");
1678             case ApplicationAlertRole:
1679                 return AXARIAContentGroupText(@"ARIAApplicationAlert");
1680             case ApplicationAlertDialogRole:
1681                 return AXARIAContentGroupText(@"ARIAApplicationAlertDialog");
1682             case ApplicationDialogRole:
1683                 return AXARIAContentGroupText(@"ARIAApplicationDialog");
1684             case ApplicationLogRole:
1685                 return AXARIAContentGroupText(@"ARIAApplicationLog");
1686             case ApplicationMarqueeRole:
1687                 return AXARIAContentGroupText(@"ARIAApplicationMarquee");
1688             case ApplicationStatusRole:
1689                 return AXARIAContentGroupText(@"ARIAApplicationStatus");
1690             case ApplicationTimerRole:
1691                 return AXARIAContentGroupText(@"ARIAApplicationTimer");
1692             case DocumentRole:
1693                 return AXARIAContentGroupText(@"ARIADocument");
1694             case DocumentArticleRole:
1695                 return AXARIAContentGroupText(@"ARIADocumentArticle");
1696             case DocumentMathRole:
1697                 return AXARIAContentGroupText(@"ARIADocumentMath");
1698             case DocumentNoteRole:
1699                 return AXARIAContentGroupText(@"ARIADocumentNote");
1700             case DocumentRegionRole:
1701                 return AXARIAContentGroupText(@"ARIADocumentRegion");
1702             case UserInterfaceTooltipRole:
1703                 return AXARIAContentGroupText(@"ARIAUserInterfaceTooltip");
1704             case TabPanelRole:
1705                 return AXARIAContentGroupText(@"ARIATabPanel");
1706             case DefinitionListTermRole:
1707                 return AXDefinitionListTermText();
1708             case DefinitionListDefinitionRole:
1709                 return AXDefinitionListDefinitionText();
1710         }
1711     }        
1712     
1713     if ([axRole isEqualToString:@"AXWebArea"])
1714         return AXWebAreaText();
1715     
1716     if ([axRole isEqualToString:@"AXLink"])
1717         return AXLinkText();
1718     
1719     if ([axRole isEqualToString:@"AXListMarker"])
1720         return AXListMarkerText();
1721     
1722     if ([axRole isEqualToString:@"AXImageMap"])
1723         return AXImageMapText();
1724
1725     if ([axRole isEqualToString:@"AXHeading"])
1726         return AXHeadingText();
1727
1728     // AppKit also returns AXTab for the role description for a tab item.
1729     if (m_object->isTabItem())
1730         return NSAccessibilityRoleDescription(@"AXTab", nil);
1731     
1732     // We should try the system default role description for all other roles.
1733     // If we get the same string back, then as a last resort, return unknown.
1734     NSString* defaultRoleDescription = NSAccessibilityRoleDescription(axRole, [self subrole]);
1735     if (![defaultRoleDescription isEqualToString:axRole])
1736         return defaultRoleDescription;
1737
1738     return NSAccessibilityRoleDescription(NSAccessibilityUnknownRole, nil);
1739 }
1740
1741 - (id)scrollViewParent
1742 {
1743     if (!m_object || !m_object->isAccessibilityScrollView())
1744         return nil;
1745     
1746     // If this scroll view provides it's parent object (because it's a sub-frame), then
1747     // we should not find the remoteAccessibilityParent.
1748     if (m_object->parentObject())
1749         return nil;
1750     
1751     AccessibilityScrollView* scrollView = toAccessibilityScrollView(m_object);
1752     ScrollView* scroll = scrollView->scrollView();
1753     if (!scroll)
1754         return nil;
1755     
1756     if (scroll->platformWidget())
1757         return NSAccessibilityUnignoredAncestor(scroll->platformWidget());
1758
1759     return [self remoteAccessibilityParentObject];
1760 }
1761
1762 // FIXME: split up this function in a better way.  
1763 // suggestions: Use a hash table that maps attribute names to function calls,
1764 // or maybe pointers to member functions
1765 - (id)accessibilityAttributeValue:(NSString*)attributeName
1766 {
1767     if (![self updateObjectBackingStore])
1768         return nil;
1769     
1770     if ([attributeName isEqualToString: NSAccessibilityRoleAttribute])
1771         return [self role];
1772
1773     if ([attributeName isEqualToString: NSAccessibilitySubroleAttribute])
1774         return [self subrole];
1775
1776     if ([attributeName isEqualToString: NSAccessibilityRoleDescriptionAttribute])
1777         return [self roleDescription];
1778
1779     if ([attributeName isEqualToString: NSAccessibilityParentAttribute]) {
1780
1781         // This will return the parent of the AXWebArea, if this is a web area.
1782         id scrollViewParent = [self scrollViewParent];
1783         if (scrollViewParent)
1784             return scrollViewParent;
1785         
1786         // Tree item (changed to AXRows) can only report the tree (AXOutline) as its parent.
1787         if (m_object->isTreeItem()) {
1788             AccessibilityObject* parent = m_object->parentObjectUnignored();
1789             while (parent) {
1790                 if (parent->isTree())
1791                     return parent->wrapper();
1792                 parent = parent->parentObjectUnignored();
1793             }
1794         }
1795         
1796         AccessibilityObject* parent = m_object->parentObjectUnignored();
1797         if (!parent)
1798             return nil;
1799
1800         // In WebKit1, the scroll view is provided by the system (the attachment view), so the parent
1801         // should be reported directly as such.
1802         if (m_object->isWebArea() && parent->isAttachment())
1803             return [parent->wrapper() attachmentView];
1804         
1805         return parent->wrapper();
1806     }
1807
1808     if ([attributeName isEqualToString: NSAccessibilityChildrenAttribute]) {
1809         if (m_object->children().isEmpty()) {
1810             NSArray* children = [self renderWidgetChildren];
1811             if (children != nil)
1812                 return children;
1813         }
1814
1815         // The tree's (AXOutline) children are supposed to be its rows and columns.
1816         // The ARIA spec doesn't have columns, so we just need rows.
1817         if (m_object->isTree())
1818             return [self accessibilityAttributeValue:NSAccessibilityRowsAttribute];
1819
1820         // A tree item should only expose its content as its children (not its rows)
1821         if (m_object->isTreeItem()) {
1822             AccessibilityObject::AccessibilityChildrenVector contentCopy;
1823             m_object->ariaTreeItemContent(contentCopy);
1824             return convertToNSArray(contentCopy);
1825         }
1826         
1827         return convertToNSArray(m_object->children());
1828     }
1829     
1830     if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) {
1831         if (m_object->isListBox()) {
1832             AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
1833             m_object->selectedChildren(selectedChildrenCopy);
1834             return convertToNSArray(selectedChildrenCopy);
1835         }
1836         return nil;
1837     }
1838     
1839     if ([attributeName isEqualToString: NSAccessibilityVisibleChildrenAttribute]) {
1840         if (m_object->isListBox()) {
1841             AccessibilityObject::AccessibilityChildrenVector visibleChildrenCopy;
1842             m_object->visibleChildren(visibleChildrenCopy);
1843             return convertToNSArray(visibleChildrenCopy);
1844         }
1845         else if (m_object->isList())
1846             return [self accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
1847
1848         return nil;
1849     }
1850     
1851     
1852     if (m_object->isWebArea()) {
1853         if ([attributeName isEqualToString:@"AXLinkUIElements"]) {
1854             AccessibilityObject::AccessibilityChildrenVector links;
1855             static_cast<AccessibilityRenderObject*>(m_object)->getDocumentLinks(links);
1856             return convertToNSArray(links);
1857         }
1858         if ([attributeName isEqualToString:@"AXLoaded"])
1859             return [NSNumber numberWithBool:m_object->isLoaded()];
1860         if ([attributeName isEqualToString:@"AXLayoutCount"])
1861             return [NSNumber numberWithInt:m_object->layoutCount()];
1862         if ([attributeName isEqualToString:NSAccessibilityLoadingProgressAttribute])
1863             return [NSNumber numberWithDouble:m_object->estimatedLoadingProgress()];
1864     }
1865     
1866     if (m_object->isTextControl()) {
1867         if ([attributeName isEqualToString: NSAccessibilityNumberOfCharactersAttribute]) {
1868             int length = m_object->textLength();
1869             if (length < 0)
1870                 return nil;
1871             return [NSNumber numberWithUnsignedInt:length];
1872         }
1873         if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) {
1874             String selectedText = m_object->selectedText();
1875             if (selectedText.isNull())
1876                 return nil;
1877             return (NSString*)selectedText;
1878         }
1879         if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) {
1880             PlainTextRange textRange = m_object->selectedTextRange();
1881             if (textRange.isNull())
1882                 return [NSValue valueWithRange:NSMakeRange(0, 0)];
1883             return [NSValue valueWithRange:NSMakeRange(textRange.start, textRange.length)];
1884         }
1885         // TODO: Get actual visible range. <rdar://problem/4712101>
1886         if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])
1887             return m_object->isPasswordField() ? nil : [NSValue valueWithRange: NSMakeRange(0, m_object->textLength())];
1888         if ([attributeName isEqualToString: NSAccessibilityInsertionPointLineNumberAttribute]) {
1889             // if selectionEnd > 0, then there is selected text and this question should not be answered
1890             if (m_object->isPasswordField() || m_object->selectionEnd() > 0)
1891                 return nil;
1892             int lineNumber = m_object->lineForPosition(m_object->visiblePositionForIndex(m_object->selectionStart(), true));
1893             if (lineNumber < 0)
1894                 return nil;
1895             return [NSNumber numberWithInt:lineNumber];
1896         }
1897     }
1898     
1899     if ([attributeName isEqualToString: NSAccessibilityURLAttribute]) {
1900         KURL url = m_object->url();
1901         if (url.isNull())
1902             return nil;
1903         return (NSURL*)url;
1904     }
1905
1906     if (m_object->isSpinButton()) {
1907         if ([attributeName isEqualToString:NSAccessibilityIncrementButtonAttribute])
1908             return toAccessibilitySpinButton(m_object)->incrementButton()->wrapper();
1909         if ([attributeName isEqualToString:NSAccessibilityDecrementButtonAttribute])
1910             return toAccessibilitySpinButton(m_object)->decrementButton()->wrapper();
1911     }
1912     
1913     if ([attributeName isEqualToString: @"AXVisited"])
1914         return [NSNumber numberWithBool: m_object->isVisited()];
1915     
1916     if ([attributeName isEqualToString: NSAccessibilityTitleAttribute]) {
1917         if (m_object->isAttachment()) {
1918             if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityTitleAttribute]) 
1919                 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityTitleAttribute];
1920         }
1921         return m_object->title();
1922     }
1923     
1924     if ([attributeName isEqualToString: NSAccessibilityDescriptionAttribute]) {
1925         if (m_object->isAttachment()) {
1926             if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityDescriptionAttribute])
1927                 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityDescriptionAttribute];
1928         }
1929         return m_object->accessibilityDescription();
1930     }
1931
1932     if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) {
1933         if (m_object->isAttachment()) {
1934             if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityValueAttribute]) 
1935                 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityValueAttribute];
1936         }
1937         if (m_object->isProgressIndicator() || m_object->isSlider() || m_object->isScrollbar())
1938             return [NSNumber numberWithFloat:m_object->valueForRange()];
1939         if (m_object->roleValue() == SliderThumbRole)
1940             return [NSNumber numberWithFloat:m_object->parentObject()->valueForRange()];
1941         if (m_object->isHeading())
1942             return [NSNumber numberWithInt:m_object->headingLevel()];
1943         
1944         if (m_object->isCheckboxOrRadio()) {
1945             switch (m_object->checkboxOrRadioValue()) {
1946             case ButtonStateOff:
1947                 return [NSNumber numberWithInt:0];
1948             case ButtonStateOn:
1949                 return [NSNumber numberWithInt:1];
1950             case ButtonStateMixed:
1951                 return [NSNumber numberWithInt:2];
1952             }
1953         }
1954
1955         // radio groups return the selected radio button as the AXValue
1956         if (m_object->isRadioGroup()) {
1957             AccessibilityObject* radioButton = m_object->selectedRadioButton();
1958             if (!radioButton)
1959                 return nil;
1960             return radioButton->wrapper();
1961         }
1962         
1963         if (m_object->isTabList()) {
1964             AccessibilityObject* tabItem = m_object->selectedTabItem();
1965             if (!tabItem)
1966                 return nil;
1967             return tabItem->wrapper();
1968         }
1969         
1970         if (m_object->isTabItem())
1971             return [NSNumber numberWithInt:m_object->isSelected()];
1972         
1973         return m_object->stringValue();
1974     }
1975
1976     if ([attributeName isEqualToString: NSAccessibilityMinValueAttribute])
1977         return [NSNumber numberWithFloat:m_object->minValueForRange()];
1978
1979     if ([attributeName isEqualToString: NSAccessibilityMaxValueAttribute])
1980         return [NSNumber numberWithFloat:m_object->maxValueForRange()];
1981
1982     if ([attributeName isEqualToString: NSAccessibilityHelpAttribute])
1983         return m_object->helpText();
1984
1985     if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])
1986         return [NSNumber numberWithBool: m_object->isFocused()];
1987
1988     if ([attributeName isEqualToString: NSAccessibilityEnabledAttribute])
1989         return [NSNumber numberWithBool: m_object->isEnabled()];
1990
1991     if ([attributeName isEqualToString: NSAccessibilitySizeAttribute]) {
1992         LayoutSize s = m_object->size();
1993         return [NSValue valueWithSize: NSMakeSize(s.width(), s.height())];
1994     }
1995
1996     if ([attributeName isEqualToString: NSAccessibilityPositionAttribute])
1997         return [self position];
1998
1999     if ([attributeName isEqualToString: NSAccessibilityWindowAttribute] ||
2000         [attributeName isEqualToString: NSAccessibilityTopLevelUIElementAttribute]) {
2001         
2002         id remoteParent = [self remoteAccessibilityParentObject];
2003         if (remoteParent)
2004             return [remoteParent accessibilityAttributeValue:attributeName];
2005         
2006         FrameView* fv = m_object->documentFrameView();
2007         if (fv)
2008             return [fv->platformWidget() window];
2009         return nil;
2010     }
2011     
2012     if ([attributeName isEqualToString:NSAccessibilityAccessKeyAttribute]) {
2013         AtomicString accessKey = m_object->accessKey();
2014         if (accessKey.isNull())
2015             return nil;
2016         return accessKey;
2017     }
2018     
2019     if ([attributeName isEqualToString:NSAccessibilityTabsAttribute]) {
2020         if (m_object->isTabList()) {
2021             AccessibilityObject::AccessibilityChildrenVector tabsChildren;
2022             m_object->tabChildren(tabsChildren);
2023             return convertToNSArray(tabsChildren);
2024         }
2025     }
2026     
2027     if ([attributeName isEqualToString:NSAccessibilityContentsAttribute]) {
2028         // The contents of a tab list are all the children except the tabs.
2029         if (m_object->isTabList()) {
2030             AccessibilityObject::AccessibilityChildrenVector children = m_object->children();
2031             AccessibilityObject::AccessibilityChildrenVector tabsChildren;
2032             m_object->tabChildren(tabsChildren);
2033
2034             AccessibilityObject::AccessibilityChildrenVector contents;
2035             unsigned childrenSize = children.size();
2036             for (unsigned k = 0; k < childrenSize; ++k) {
2037                 if (tabsChildren.find(children[k]) == WTF::notFound)
2038                     contents.append(children[k]);
2039             }
2040             return convertToNSArray(contents);
2041         } else if (m_object->isScrollView()) {
2042             AccessibilityObject::AccessibilityChildrenVector children = m_object->children();
2043             
2044             // A scrollView's contents are everything except the scroll bars.
2045             AccessibilityObject::AccessibilityChildrenVector contents;
2046             unsigned childrenSize = children.size();
2047             for (unsigned k = 0; k < childrenSize; ++k) {
2048                 if (!children[k]->isScrollbar())
2049                     contents.append(children[k]);
2050             }
2051             return convertToNSArray(contents);            
2052         }
2053     }    
2054     
2055     if (m_object->isAccessibilityTable()) {
2056         // TODO: distinguish between visible and non-visible rows
2057         if ([attributeName isEqualToString:NSAccessibilityRowsAttribute] || 
2058             [attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) {
2059             return convertToNSArray(static_cast<AccessibilityTable*>(m_object)->rows());
2060         }
2061         // TODO: distinguish between visible and non-visible columns
2062         if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute] || 
2063             [attributeName isEqualToString:NSAccessibilityVisibleColumnsAttribute]) {
2064             return convertToNSArray(static_cast<AccessibilityTable*>(m_object)->columns());
2065         }
2066         
2067         if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
2068             AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2069             m_object->selectedChildren(selectedChildrenCopy);
2070             return convertToNSArray(selectedChildrenCopy);
2071         }
2072         
2073         // HTML tables don't support these
2074         if ([attributeName isEqualToString:NSAccessibilitySelectedColumnsAttribute] || 
2075             [attributeName isEqualToString:NSAccessibilitySelectedCellsAttribute])
2076             return nil;
2077         
2078         if ([attributeName isEqualToString:(NSString *)kAXColumnHeaderUIElementsAttribute]) {
2079             AccessibilityObject::AccessibilityChildrenVector columnHeaders;
2080             static_cast<AccessibilityTable*>(m_object)->columnHeaders(columnHeaders);
2081             return convertToNSArray(columnHeaders);            
2082         }
2083         
2084         if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
2085             AccessibilityObject* headerContainer = static_cast<AccessibilityTable*>(m_object)->headerContainer();
2086             if (headerContainer)
2087                 return headerContainer->wrapper();
2088             return nil;
2089         }
2090
2091         if ([attributeName isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) {
2092             AccessibilityObject::AccessibilityChildrenVector rowHeaders;
2093             static_cast<AccessibilityTable*>(m_object)->rowHeaders(rowHeaders);
2094             return convertToNSArray(rowHeaders);                        
2095         }
2096         
2097         if ([attributeName isEqualToString:NSAccessibilityVisibleCellsAttribute]) {
2098             AccessibilityObject::AccessibilityChildrenVector cells;
2099             static_cast<AccessibilityTable*>(m_object)->cells(cells);
2100             return convertToNSArray(cells);
2101         }        
2102     }
2103     
2104     if (m_object->isTableColumn()) {
2105         if ([attributeName isEqualToString:NSAccessibilityIndexAttribute])
2106             return [NSNumber numberWithInt:static_cast<AccessibilityTableColumn*>(m_object)->columnIndex()];
2107         
2108         // rows attribute for a column is the list of all the elements in that column at each row
2109         if ([attributeName isEqualToString:NSAccessibilityRowsAttribute] || 
2110             [attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) {
2111             return convertToNSArray(static_cast<AccessibilityTableColumn*>(m_object)->children());
2112         }
2113         if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
2114             AccessibilityObject* header = static_cast<AccessibilityTableColumn*>(m_object)->headerObject();
2115             if (!header)
2116                 return nil;
2117             return header->wrapper();
2118         }
2119     }
2120     
2121     if (m_object->isTableCell()) {
2122         if ([attributeName isEqualToString:NSAccessibilityRowIndexRangeAttribute]) {
2123             pair<int, int> rowRange;
2124             static_cast<AccessibilityTableCell*>(m_object)->rowIndexRange(rowRange);
2125             return [NSValue valueWithRange:NSMakeRange(rowRange.first, rowRange.second)];
2126         }  
2127         if ([attributeName isEqualToString:NSAccessibilityColumnIndexRangeAttribute]) {
2128             pair<int, int> columnRange;
2129             static_cast<AccessibilityTableCell*>(m_object)->columnIndexRange(columnRange);
2130             return [NSValue valueWithRange:NSMakeRange(columnRange.first, columnRange.second)];
2131         }  
2132     }
2133     
2134     if (m_object->isTree()) {
2135         if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
2136             AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2137             m_object->selectedChildren(selectedChildrenCopy);
2138             return convertToNSArray(selectedChildrenCopy);
2139         }
2140         if ([attributeName isEqualToString:NSAccessibilityRowsAttribute]) {
2141             AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2142             m_object->ariaTreeRows(rowsCopy);
2143             return convertToNSArray(rowsCopy);            
2144         }
2145         
2146         // TreeRoles do not support columns, but Mac AX expects to be able to ask about columns at the least.
2147         if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute])
2148             return [NSArray array];
2149     }
2150
2151     if ([attributeName isEqualToString:NSAccessibilityIndexAttribute]) {
2152         if (m_object->isTreeItem()) {
2153             AccessibilityObject* parent = m_object->parentObject();
2154             for (; parent && !parent->isTree(); parent = parent->parentObject())
2155             { }
2156             
2157             if (!parent)
2158                 return nil;
2159             
2160             // Find the index of this item by iterating the parents.
2161             AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2162             parent->ariaTreeRows(rowsCopy);
2163             size_t count = rowsCopy.size();
2164             for (size_t k = 0; k < count; ++k)
2165                 if (rowsCopy[k]->wrapper() == self)
2166                     return [NSNumber numberWithUnsignedInt:k];
2167             
2168             return nil;
2169         }
2170         if (m_object->isTableRow()) {
2171             if ([attributeName isEqualToString:NSAccessibilityIndexAttribute])
2172                 return [NSNumber numberWithInt:static_cast<AccessibilityTableRow*>(m_object)->rowIndex()];
2173         }
2174     }    
2175     
2176     // The rows that are considered inside this row. 
2177     if ([attributeName isEqualToString:NSAccessibilityDisclosedRowsAttribute]) {
2178         if (m_object->isTreeItem()) {
2179             AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2180             m_object->ariaTreeItemDisclosedRows(rowsCopy);
2181             return convertToNSArray(rowsCopy);    
2182         } else if (m_object->isARIATreeGridRow()) {
2183             AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2184             static_cast<AccessibilityARIAGridRow*>(m_object)->disclosedRows(rowsCopy);
2185             return convertToNSArray(rowsCopy);    
2186         }
2187     }
2188     
2189     // The row that contains this row. It should be the same as the first parent that is a treeitem.
2190     if ([attributeName isEqualToString:NSAccessibilityDisclosedByRowAttribute]) {
2191         if (m_object->isTreeItem()) {
2192             AccessibilityObject* parent = m_object->parentObject();
2193             while (parent) {
2194                 if (parent->isTreeItem())
2195                     return parent->wrapper();
2196                 // If the parent is the tree itself, then this value == nil.
2197                 if (parent->isTree())
2198                     return nil;
2199                 parent = parent->parentObject();
2200             }
2201             return nil;
2202         } else if (m_object->isARIATreeGridRow()) {
2203             AccessibilityObject* row = static_cast<AccessibilityARIAGridRow*>(m_object)->disclosedByRow();
2204             if (!row)
2205                 return nil;
2206             return row->wrapper();
2207         }
2208     }
2209
2210     if ([attributeName isEqualToString:NSAccessibilityDisclosureLevelAttribute])
2211         return [NSNumber numberWithInt:m_object->hierarchicalLevel()];
2212     if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
2213         return [NSNumber numberWithBool:m_object->isExpanded()];
2214     
2215     if ((m_object->isListBox() || m_object->isList()) && [attributeName isEqualToString:NSAccessibilityOrientationAttribute])
2216         return NSAccessibilityVerticalOrientationValue;
2217
2218     if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"])
2219         return [self textMarkerRangeForSelection];
2220     
2221     if (m_object->isAccessibilityRenderObject()) {
2222         RenderObject* renderer = static_cast<AccessibilityRenderObject*>(m_object)->renderer();
2223         if (!renderer)
2224             return nil;
2225         
2226         if ([attributeName isEqualToString: @"AXStartTextMarker"])
2227             return [self textMarkerForVisiblePosition:startOfDocument(renderer->document())];
2228         if ([attributeName isEqualToString: @"AXEndTextMarker"])
2229             return [self textMarkerForVisiblePosition:endOfDocument(renderer->document())];
2230
2231         if ([attributeName isEqualToString:NSAccessibilityBlockQuoteLevelAttribute])
2232             return [NSNumber numberWithInt:m_object->blockquoteLevel()];
2233         if ([attributeName isEqualToString:@"AXTableLevel"])
2234             return [NSNumber numberWithInt:m_object->tableLevel()];
2235     } else {
2236         AccessibilityObject* parent = m_object->parentObjectUnignored();
2237         if (!parent)
2238             return [NSNumber numberWithInt:0];
2239         
2240         if ([attributeName isEqualToString:NSAccessibilityBlockQuoteLevelAttribute])
2241             return [parent->wrapper() accessibilityAttributeValue:NSAccessibilityBlockQuoteLevelAttribute];
2242         if ([attributeName isEqualToString:@"AXTableLevel"])
2243             return [parent->wrapper() accessibilityAttributeValue:@"AXTableLevel"];
2244     }
2245     
2246     if ([attributeName isEqualToString: NSAccessibilityLinkedUIElementsAttribute]) {
2247         AccessibilityObject::AccessibilityChildrenVector linkedUIElements;
2248         m_object->linkedUIElements(linkedUIElements);
2249         if (linkedUIElements.size() == 0)
2250             return nil;
2251         return convertToNSArray(linkedUIElements);
2252     }
2253
2254     if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute])
2255         return [NSNumber numberWithBool:m_object->isSelected()];
2256
2257     if ([attributeName isEqualToString: NSAccessibilityServesAsTitleForUIElementsAttribute] && m_object->isMenuButton()) {
2258         AccessibilityObject* uiElement = static_cast<AccessibilityRenderObject*>(m_object)->menuForMenuButton();
2259         if (uiElement)
2260             return [NSArray arrayWithObject:uiElement->wrapper()];
2261     }
2262
2263     if ([attributeName isEqualToString:NSAccessibilityTitleUIElementAttribute]) {
2264         AccessibilityObject* obj = m_object->titleUIElement();
2265         if (obj)
2266             return obj->wrapper();
2267         return nil;
2268     }
2269     
2270     if ([attributeName isEqualToString:NSAccessibilityValueDescriptionAttribute])
2271         return m_object->valueDescription();
2272     
2273     if ([attributeName isEqualToString:NSAccessibilityOrientationAttribute]) {
2274         AccessibilityOrientation elementOrientation = m_object->orientation();
2275         if (elementOrientation == AccessibilityOrientationVertical)
2276             return NSAccessibilityVerticalOrientationValue;
2277         if (elementOrientation == AccessibilityOrientationHorizontal)
2278             return NSAccessibilityHorizontalOrientationValue;
2279         return nil;
2280     }
2281     
2282     if ([attributeName isEqualToString:NSAccessibilityHorizontalScrollBarAttribute]) {
2283         AccessibilityObject* scrollBar = m_object->scrollBar(AccessibilityOrientationHorizontal);
2284         if (scrollBar)
2285             return scrollBar->wrapper();
2286         return nil;
2287     }
2288     if ([attributeName isEqualToString:NSAccessibilityVerticalScrollBarAttribute]) {
2289         AccessibilityObject* scrollBar = m_object->scrollBar(AccessibilityOrientationVertical);
2290         if (scrollBar)
2291             return scrollBar->wrapper();
2292         return nil;
2293     }
2294     
2295     if ([attributeName isEqualToString:NSAccessibilitySortDirectionAttribute]) {
2296         switch (m_object->sortDirection()) {
2297         case SortDirectionAscending:
2298             return NSAccessibilityAscendingSortDirectionValue;
2299         case SortDirectionDescending:
2300             return NSAccessibilityDescendingSortDirectionValue;
2301         default:
2302             return NSAccessibilityUnknownSortDirectionValue;
2303         }
2304     }
2305     
2306     if ([attributeName isEqualToString:NSAccessibilityLanguageAttribute]) 
2307         return m_object->language();
2308     
2309     if ([attributeName isEqualToString:NSAccessibilityExpandedAttribute])
2310         return [NSNumber numberWithBool:m_object->isExpanded()];
2311     
2312     if ([attributeName isEqualToString:NSAccessibilityRequiredAttribute])
2313         return [NSNumber numberWithBool:m_object->isRequired()];
2314
2315     if ([attributeName isEqualToString:NSAccessibilityInvalidAttribute])
2316         return m_object->invalidStatus();
2317     
2318     if ([attributeName isEqualToString:NSAccessibilityOwnsAttribute]) {
2319         AccessibilityObject::AccessibilityChildrenVector ariaOwns;
2320         m_object->ariaOwnsElements(ariaOwns);
2321         return convertToNSArray(ariaOwns);
2322     }
2323     
2324     if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
2325         return [NSNumber numberWithBool:m_object->isARIAGrabbed()];
2326     
2327     if ([attributeName isEqualToString:NSAccessibilityDropEffectsAttribute]) {
2328         Vector<String> dropEffects;
2329         m_object->determineARIADropEffects(dropEffects);
2330         size_t length = dropEffects.size();
2331
2332         NSMutableArray* dropEffectsArray = [NSMutableArray arrayWithCapacity:length];
2333         for (size_t i = 0; i < length; ++i)
2334             [dropEffectsArray addObject:dropEffects[i]];
2335         return dropEffectsArray;
2336     }
2337     
2338     if ([attributeName isEqualToString:NSAccessibilityPlaceholderValueAttribute])
2339         return m_object->placeholderValue();
2340     
2341     if ([attributeName isEqualToString:NSAccessibilityHasPopupAttribute])
2342         return [NSNumber numberWithBool:m_object->ariaHasPopup()];
2343     
2344     // ARIA Live region attributes.
2345     if ([attributeName isEqualToString:NSAccessibilityARIALiveAttribute])
2346         return m_object->ariaLiveRegionStatus();
2347     if ([attributeName isEqualToString:NSAccessibilityARIARelevantAttribute])
2348          return m_object->ariaLiveRegionRelevant();
2349     if ([attributeName isEqualToString:NSAccessibilityARIAAtomicAttribute])
2350         return [NSNumber numberWithBool:m_object->ariaLiveRegionAtomic()];
2351     if ([attributeName isEqualToString:NSAccessibilityARIABusyAttribute])
2352         return [NSNumber numberWithBool:m_object->ariaLiveRegionBusy()];
2353     
2354     // this is used only by DumpRenderTree for testing
2355     if ([attributeName isEqualToString:@"AXClickPoint"])
2356         return [NSValue valueWithPoint:m_object->clickPoint()];
2357     
2358     // This is used by DRT to verify CSS3 speech works.
2359     if ([attributeName isEqualToString:@"AXDRTSpeechAttribute"]) {
2360         ESpeak speakProperty = m_object->speakProperty();
2361         switch (speakProperty) {
2362         case SpeakNone:
2363             return @"none";
2364         case SpeakSpellOut:
2365             return @"spell-out";
2366         case SpeakDigits:
2367             return @"digits";
2368         case SpeakLiteralPunctuation:
2369             return @"literal-punctuation";
2370         case SpeakNoPunctuation:
2371             return @"no-punctuation";
2372         default:
2373         case SpeakNormal:
2374             return @"normal";
2375         }
2376     }
2377     
2378     return nil;
2379 }
2380
2381 - (id)accessibilityFocusedUIElement
2382 {
2383     if (![self updateObjectBackingStore])
2384         return nil;
2385
2386     RefPtr<AccessibilityObject> focusedObj = m_object->focusedUIElement();
2387
2388     if (!focusedObj)
2389         return nil;
2390     
2391     return focusedObj->wrapper();
2392 }
2393
2394 - (id)accessibilityHitTest:(NSPoint)point
2395 {
2396     if (![self updateObjectBackingStore])
2397         return nil;
2398
2399     m_object->updateChildrenIfNecessary();
2400     RefPtr<AccessibilityObject> axObject = m_object->accessibilityHitTest(IntPoint(point));
2401     if (axObject)
2402         return NSAccessibilityUnignoredAncestor(axObject->wrapper());
2403     return NSAccessibilityUnignoredAncestor(self);
2404 }
2405
2406 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName
2407 {
2408     if (![self updateObjectBackingStore])
2409         return nil;
2410
2411     if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"])
2412         return YES;
2413
2414     if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])
2415         return m_object->canSetFocusAttribute();
2416
2417     if ([attributeName isEqualToString: NSAccessibilityValueAttribute])
2418         return m_object->canSetValueAttribute();
2419
2420     if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute])
2421         return m_object->canSetSelectedAttribute();
2422     
2423     if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute])
2424         return m_object->canSetSelectedChildrenAttribute();
2425
2426     if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
2427         return m_object->canSetExpandedAttribute();
2428
2429     if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute])
2430         return YES;
2431
2432     if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute] ||
2433         [attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute] ||
2434         [attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])
2435         return m_object->canSetTextRangeAttributes();
2436     
2437     if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
2438         return YES;
2439     
2440     return NO;
2441 }
2442
2443 // accessibilityShouldUseUniqueId is an AppKit method we override so that
2444 // objects will be given a unique ID, and therefore allow AppKit to know when they
2445 // become obsolete (e.g. when the user navigates to a new web page, making this one
2446 // unrendered but not deallocated because it is in the back/forward cache).
2447 // It is important to call NSAccessibilityUnregisterUniqueIdForUIElement in the
2448 // appropriate place (e.g. dealloc) to remove these non-retained references from
2449 // AppKit's id mapping tables. We do this in detach by calling unregisterUniqueIdForUIElement.
2450 //
2451 // Registering an object is also required for observing notifications. Only registered objects can be observed.
2452 - (BOOL)accessibilityIsIgnored
2453 {
2454     if (![self updateObjectBackingStore])
2455         return YES;
2456
2457     if (m_object->isAttachment())
2458         return [[self attachmentView] accessibilityIsIgnored];
2459     return m_object->accessibilityIsIgnored();
2460 }
2461
2462 - (NSArray* )accessibilityParameterizedAttributeNames
2463 {
2464     if (![self updateObjectBackingStore])
2465         return nil;
2466
2467     if (m_object->isAttachment()) 
2468         return nil;
2469
2470     static NSArray* paramAttrs = nil;
2471     static NSArray* textParamAttrs = nil;
2472     static NSArray* tableParamAttrs = nil;
2473     if (paramAttrs == nil) {
2474         paramAttrs = [[NSArray alloc] initWithObjects:
2475                       @"AXUIElementForTextMarker",
2476                       @"AXTextMarkerRangeForUIElement",
2477                       @"AXLineForTextMarker",
2478                       @"AXTextMarkerRangeForLine",
2479                       @"AXStringForTextMarkerRange",
2480                       @"AXTextMarkerForPosition",
2481                       @"AXBoundsForTextMarkerRange",
2482                       @"AXAttributedStringForTextMarkerRange",
2483                       @"AXTextMarkerRangeForUnorderedTextMarkers",
2484                       @"AXNextTextMarkerForTextMarker",
2485                       @"AXPreviousTextMarkerForTextMarker",
2486                       @"AXLeftWordTextMarkerRangeForTextMarker",
2487                       @"AXRightWordTextMarkerRangeForTextMarker",
2488                       @"AXLeftLineTextMarkerRangeForTextMarker",
2489                       @"AXRightLineTextMarkerRangeForTextMarker",
2490                       @"AXSentenceTextMarkerRangeForTextMarker",
2491                       @"AXParagraphTextMarkerRangeForTextMarker",
2492                       @"AXNextWordEndTextMarkerForTextMarker",
2493                       @"AXPreviousWordStartTextMarkerForTextMarker",
2494                       @"AXNextLineEndTextMarkerForTextMarker",
2495                       @"AXPreviousLineStartTextMarkerForTextMarker",
2496                       @"AXNextSentenceEndTextMarkerForTextMarker",
2497                       @"AXPreviousSentenceStartTextMarkerForTextMarker",
2498                       @"AXNextParagraphEndTextMarkerForTextMarker",
2499                       @"AXPreviousParagraphStartTextMarkerForTextMarker",
2500                       @"AXStyleTextMarkerRangeForTextMarker",
2501                       @"AXLengthForTextMarkerRange",
2502                       NSAccessibilityBoundsForRangeParameterizedAttribute,
2503                       NSAccessibilityStringForRangeParameterizedAttribute,
2504                       NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute,
2505                       nil];
2506     }
2507
2508     if (textParamAttrs == nil) {
2509         NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];
2510         [tempArray addObject:(NSString*)kAXLineForIndexParameterizedAttribute];
2511         [tempArray addObject:(NSString*)kAXRangeForLineParameterizedAttribute];
2512         [tempArray addObject:(NSString*)kAXStringForRangeParameterizedAttribute];
2513         [tempArray addObject:(NSString*)kAXRangeForPositionParameterizedAttribute];
2514         [tempArray addObject:(NSString*)kAXRangeForIndexParameterizedAttribute];
2515         [tempArray addObject:(NSString*)kAXBoundsForRangeParameterizedAttribute];
2516         [tempArray addObject:(NSString*)kAXRTFForRangeParameterizedAttribute];
2517         [tempArray addObject:(NSString*)kAXAttributedStringForRangeParameterizedAttribute];
2518         [tempArray addObject:(NSString*)kAXStyleRangeForIndexParameterizedAttribute];
2519         textParamAttrs = [[NSArray alloc] initWithArray:tempArray];
2520         [tempArray release];
2521     }
2522     if (tableParamAttrs == nil) {
2523         NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];
2524         [tempArray addObject:NSAccessibilityCellForColumnAndRowParameterizedAttribute];
2525         tableParamAttrs = [[NSArray alloc] initWithArray:tempArray];
2526         [tempArray release];
2527     }
2528     
2529     if (m_object->isPasswordField())
2530         return [NSArray array];
2531     
2532     if (!m_object->isAccessibilityRenderObject())
2533         return paramAttrs;
2534
2535     if (m_object->isTextControl())
2536         return textParamAttrs;
2537     
2538     if (m_object->isAccessibilityTable())
2539         return tableParamAttrs;
2540     
2541     if (m_object->isMenuRelated())
2542         return nil;
2543
2544     return paramAttrs;
2545 }
2546
2547 - (void)accessibilityPerformPressAction
2548 {
2549     if (![self updateObjectBackingStore])
2550         return;
2551
2552     if (m_object->isAttachment())
2553         [[self attachmentView] accessibilityPerformAction:NSAccessibilityPressAction];
2554     else
2555         m_object->press();    
2556 }
2557
2558 - (void)accessibilityPerformIncrementAction
2559 {
2560     if (![self updateObjectBackingStore])
2561         return;
2562
2563     if (m_object->isAttachment())
2564         [[self attachmentView] accessibilityPerformAction:NSAccessibilityIncrementAction];
2565     else
2566         m_object->increment();    
2567 }
2568
2569 - (void)accessibilityPerformDecrementAction
2570 {
2571     if (![self updateObjectBackingStore])
2572         return;
2573
2574     if (m_object->isAttachment())
2575         [[self attachmentView] accessibilityPerformAction:NSAccessibilityDecrementAction];
2576     else
2577         m_object->decrement();    
2578 }
2579
2580 - (void)accessibilityPerformShowMenuAction
2581 {
2582     if (m_object->roleValue() == ComboBoxRole)
2583         m_object->setIsExpanded(true);
2584     else {
2585         // This needs to be performed in an iteration of the run loop that did not start from an AX call. 
2586         // If it's the same run loop iteration, the menu open notification won't be sent
2587         [self performSelector:@selector(accessibilityShowContextMenu) withObject:nil afterDelay:0.0];
2588     }
2589 }
2590
2591 - (void)accessibilityShowContextMenu
2592 {    
2593     FrameView* frameView = m_object->documentFrameView();
2594     if (!frameView)
2595         return;
2596     Frame* frame = frameView->frame();
2597     if (!frame)
2598         return;
2599     Page* page = frame->page();
2600     if (!page)
2601         return;
2602
2603     // Simulate a click in the middle of the object.
2604     LayoutPoint clickPoint = m_object->clickPoint();
2605     
2606     PlatformMouseEvent mouseEvent(clickPoint, clickPoint, RightButton, MouseEventPressed, 1, false, false, false, false, currentTime());
2607     bool handled = frame->eventHandler()->sendContextMenuEvent(mouseEvent);
2608     if (handled)
2609         page->chrome()->showContextMenu();
2610 }
2611
2612 - (void)accessibilityPerformAction:(NSString*)action
2613 {
2614     if (![self updateObjectBackingStore])
2615         return;
2616
2617     if ([action isEqualToString:NSAccessibilityPressAction])
2618         [self accessibilityPerformPressAction];
2619     
2620     else if ([action isEqualToString:NSAccessibilityShowMenuAction])
2621         [self accessibilityPerformShowMenuAction];
2622
2623     else if ([action isEqualToString:NSAccessibilityIncrementAction])
2624         [self accessibilityPerformIncrementAction];
2625
2626     else if ([action isEqualToString:NSAccessibilityDecrementAction])
2627         [self accessibilityPerformDecrementAction];
2628 }
2629
2630 - (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attributeName
2631 {
2632     if (![self updateObjectBackingStore])
2633         return;
2634
2635     id textMarkerRange = nil;
2636     NSNumber*               number = nil;
2637     NSString*               string = nil;
2638     NSRange                 range = {0, 0};
2639     NSArray*                array = nil;
2640     
2641     // decode the parameter
2642     if (AXObjectIsTextMarkerRange(value))
2643         textMarkerRange = value;
2644
2645     else if ([value isKindOfClass:[NSNumber self]])
2646         number = value;
2647
2648     else if ([value isKindOfClass:[NSString self]])
2649         string = value;
2650     
2651     else if ([value isKindOfClass:[NSValue self]])
2652         range = [value rangeValue];
2653     
2654     else if ([value isKindOfClass:[NSArray self]])
2655         array = value;
2656     
2657     // handle the command
2658     if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"]) {
2659         ASSERT(textMarkerRange);
2660         m_object->setSelectedVisiblePositionRange([self visiblePositionRangeForTextMarkerRange:textMarkerRange]);        
2661     } else if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute]) {
2662         ASSERT(number);
2663         m_object->setFocused([number intValue] != 0);
2664     } else if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) {
2665         if (number && m_object->canSetNumericValue())
2666             m_object->setValue([number floatValue]);
2667         else if (string)
2668             m_object->setValue(string);
2669     } else if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute]) {
2670         if (!number)
2671             return;
2672         m_object->setSelected([number boolValue]);
2673     } else if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) {
2674         if (!array || m_object->roleValue() != ListBoxRole)
2675             return;
2676         AccessibilityObject::AccessibilityChildrenVector selectedChildren;
2677         convertToVector(array, selectedChildren);
2678         static_cast<AccessibilityListBox*>(m_object)->setSelectedChildren(selectedChildren);
2679     } else if (m_object->isTextControl()) {
2680         if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) {
2681             m_object->setSelectedText(string);
2682         } else if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) {
2683             m_object->setSelectedTextRange(PlainTextRange(range.location, range.length));
2684         } else if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute]) {
2685             m_object->makeRangeVisible(PlainTextRange(range.location, range.length));
2686         }
2687     } else if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
2688         m_object->setIsExpanded([number boolValue]);
2689     else if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
2690         AccessibilityObject::AccessibilityChildrenVector selectedRows;
2691         convertToVector(array, selectedRows);
2692         if (m_object->isTree() || m_object->isAccessibilityTable())
2693             m_object->setSelectedRows(selectedRows);
2694     } else if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
2695         m_object->setARIAGrabbed([number boolValue]);
2696 }
2697
2698 static RenderObject* rendererForView(NSView* view)
2699 {
2700     if (![view conformsToProtocol:@protocol(WebCoreFrameView)])
2701         return 0;
2702
2703     NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view;
2704     Frame* frame = [frameView _web_frame];
2705     if (!frame)
2706         return 0;
2707
2708     Node* node = frame->document()->ownerElement();
2709     if (!node)
2710         return 0;
2711
2712     return node->renderer();
2713 }
2714
2715 - (id)_accessibilityParentForSubview:(NSView*)subview
2716 {   
2717     RenderObject* renderer = rendererForView(subview);
2718     if (!renderer)
2719         return nil;
2720
2721     AccessibilityObject* obj = renderer->document()->axObjectCache()->getOrCreate(renderer);
2722     if (obj)
2723         return obj->parentObjectUnignored()->wrapper();
2724     return nil;
2725 }
2726
2727 - (NSString*)accessibilityActionDescription:(NSString*)action
2728 {
2729     // we have no custom actions
2730     return NSAccessibilityActionDescription(action);
2731 }
2732
2733 // The CFAttributedStringType representation of the text associated with this accessibility
2734 // object that is specified by the given range.
2735 - (NSAttributedString*)doAXAttributedStringForRange:(NSRange)range
2736 {
2737     PlainTextRange textRange = PlainTextRange(range.location, range.length);
2738     VisiblePositionRange visiblePosRange = m_object->visiblePositionRangeForRange(textRange);
2739     return [self doAXAttributedStringForTextMarkerRange:[self textMarkerRangeFromVisiblePositions:visiblePosRange.start endPosition:visiblePosRange.end]];
2740 }
2741
2742 // The RTF representation of the text associated with this accessibility object that is
2743 // specified by the given range.
2744 - (NSData*)doAXRTFForRange:(NSRange)range
2745 {
2746     NSAttributedString* attrString = [self doAXAttributedStringForRange:range];
2747     return [attrString RTFFromRange: NSMakeRange(0, [attrString length]) documentAttributes: nil];
2748 }
2749
2750 - (id)accessibilityAttributeValue:(NSString*)attribute forParameter:(id)parameter
2751 {
2752     id textMarker = nil;
2753     id textMarkerRange = nil;
2754     NSNumber* number = nil;
2755     NSArray* array = nil;
2756     NSDictionary* dictionary = nil;
2757     RefPtr<AccessibilityObject> uiElement = 0;
2758     NSPoint point = NSZeroPoint;
2759     bool pointSet = false;
2760     NSRange range = {0, 0};
2761     bool rangeSet = false;
2762     
2763     // basic parameter validation
2764     if (!m_object || !attribute || !parameter)
2765         return nil;
2766
2767     if (![self updateObjectBackingStore])
2768         return nil;
2769     
2770     // common parameter type check/casting.  Nil checks in handlers catch wrong type case.
2771     // NOTE: This assumes nil is not a valid parameter, because it is indistinguishable from
2772     // a parameter of the wrong type.
2773     if (AXObjectIsTextMarker(parameter))
2774         textMarker = parameter;
2775
2776     else if (AXObjectIsTextMarkerRange(parameter))
2777         textMarkerRange = parameter;
2778
2779     else if ([parameter isKindOfClass:[WebAccessibilityObjectWrapper self]])
2780         uiElement = [(WebAccessibilityObjectWrapper*)parameter accessibilityObject];
2781
2782     else if ([parameter isKindOfClass:[NSNumber self]])
2783         number = parameter;
2784
2785     else if ([parameter isKindOfClass:[NSArray self]])
2786         array = parameter;
2787
2788     else if ([parameter isKindOfClass:[NSDictionary self]])
2789         dictionary = parameter;
2790
2791     else if ([parameter isKindOfClass:[NSValue self]] && strcmp([(NSValue*)parameter objCType], @encode(NSPoint)) == 0) {
2792         pointSet = true;
2793         point = [(NSValue*)parameter pointValue];
2794
2795     } else if ([parameter isKindOfClass:[NSValue self]] && strcmp([(NSValue*)parameter objCType], @encode(NSRange)) == 0) {
2796         rangeSet = true;
2797         range = [(NSValue*)parameter rangeValue];
2798     } else {
2799         // Attribute type is not supported. Allow super to handle.
2800         return [super accessibilityAttributeValue:attribute forParameter:parameter];
2801     }
2802     
2803     // dispatch
2804     if ([attribute isEqualToString:NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute]) {
2805         AccessibilityObject* startObject = 0;
2806         if ([[dictionary objectForKey:@"AXStartElement"] isKindOfClass:[WebAccessibilityObjectWrapper self]])
2807             startObject = [(WebAccessibilityObjectWrapper*)[dictionary objectForKey:@"AXStartElement"] accessibilityObject];
2808         
2809         AccessibilitySearchDirection searchDirection = SearchDirectionNext;
2810         if ([[dictionary objectForKey:@"AXDirection"] isKindOfClass:[NSString self]])
2811             searchDirection = ([(NSString*)[dictionary objectForKey:@"AXDirection"] isEqualToString:@"AXDirectionNext"]) ? SearchDirectionNext : SearchDirectionPrevious;
2812         
2813         AccessibilitySearchKey searchKey = AnyTypeSearchKey;
2814         if ([[dictionary objectForKey:@"AXSearchKey"] isKindOfClass:[NSString self]])
2815             searchKey = accessibilitySearchKeyForString((CFStringRef)[dictionary objectForKey:@"AXSearchKey"]);
2816         
2817         String searchText;
2818         if ([[dictionary objectForKey:@"AXSearchText"] isKindOfClass:[NSString self]])
2819             searchText = (CFStringRef)[dictionary objectForKey:@"AXSearchText"];
2820         
2821         unsigned resultsLimit = 0;
2822         if ([[dictionary objectForKey:@"AXResultsLimit"] isKindOfClass:[NSNumber self]])
2823             resultsLimit = [(NSNumber*)[dictionary objectForKey:@"AXResultsLimit"] unsignedIntValue];
2824         
2825         AccessibilitySearchCriteria criteria = {startObject, searchDirection, searchKey, &searchText, resultsLimit};
2826
2827         AccessibilityObject::AccessibilityChildrenVector results;
2828         m_object->findMatchingObjects(&criteria, results);
2829         
2830         return convertToNSArray(results);
2831     }
2832
2833     if ([attribute isEqualToString:@"AXUIElementForTextMarker"]) {
2834         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
2835         AccessibilityObject* axObject = m_object->accessibilityObjectForPosition(visiblePos);
2836         if (!axObject)
2837             return nil;
2838         return axObject->wrapper();
2839     }
2840
2841     if ([attribute isEqualToString:@"AXTextMarkerRangeForUIElement"]) {
2842         VisiblePositionRange vpRange = uiElement.get()->visiblePositionRange();
2843         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
2844     }
2845
2846     if ([attribute isEqualToString:@"AXLineForTextMarker"]) {
2847         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
2848         return [NSNumber numberWithUnsignedInt:m_object->lineForPosition(visiblePos)];
2849     }
2850
2851     if ([attribute isEqualToString:@"AXTextMarkerRangeForLine"]) {
2852         VisiblePositionRange vpRange = m_object->visiblePositionRangeForLine([number intValue]);
2853         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
2854     }
2855
2856     if ([attribute isEqualToString:@"AXStringForTextMarkerRange"]) {
2857         VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];
2858         return m_object->stringForVisiblePositionRange(visiblePosRange);
2859     }
2860
2861     if ([attribute isEqualToString:@"AXTextMarkerForPosition"]) {
2862         IntPoint webCorePoint = IntPoint(point);
2863         return pointSet ? [self textMarkerForVisiblePosition:m_object->visiblePositionForPoint(webCorePoint)] : nil;
2864     }
2865
2866     if ([attribute isEqualToString:@"AXBoundsForTextMarkerRange"]) {
2867         VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];
2868         NSRect rect = m_object->boundsForVisiblePositionRange(visiblePosRange);
2869         return [NSValue valueWithRect:rect];
2870     }
2871     
2872     if ([attribute isEqualToString:NSAccessibilityBoundsForRangeParameterizedAttribute]) {
2873         VisiblePosition start = m_object->visiblePositionForIndex(range.location);
2874         VisiblePosition end = m_object->visiblePositionForIndex(range.location+range.length);
2875         if (start.isNull() || end.isNull())
2876             return nil;
2877         NSRect rect = m_object->boundsForVisiblePositionRange(VisiblePositionRange(start, end));
2878         return [NSValue valueWithRect:rect];
2879     }
2880     
2881     if ([attribute isEqualToString:NSAccessibilityStringForRangeParameterizedAttribute]) {
2882         VisiblePosition start = m_object->visiblePositionForIndex(range.location);
2883         VisiblePosition end = m_object->visiblePositionForIndex(range.location+range.length);
2884         if (start.isNull() || end.isNull())
2885             return nil;
2886         return m_object->stringForVisiblePositionRange(VisiblePositionRange(start, end));
2887     }
2888
2889     if ([attribute isEqualToString:@"AXAttributedStringForTextMarkerRange"])
2890         return [self doAXAttributedStringForTextMarkerRange:textMarkerRange];
2891
2892     if ([attribute isEqualToString:@"AXTextMarkerRangeForUnorderedTextMarkers"]) {
2893         if ([array count] < 2)
2894             return nil;
2895
2896         id textMarker1 = [array objectAtIndex:0];
2897         id textMarker2 = [array objectAtIndex:1];
2898         if (!AXObjectIsTextMarker(textMarker1) || !AXObjectIsTextMarker(textMarker2))
2899             return nil;
2900
2901         VisiblePosition visiblePos1 = [self visiblePositionForTextMarker:(textMarker1)];
2902         VisiblePosition visiblePos2 = [self visiblePositionForTextMarker:(textMarker2)];
2903         VisiblePositionRange vpRange = m_object->visiblePositionRangeForUnorderedPositions(visiblePos1, visiblePos2);
2904         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
2905     }
2906
2907     if ([attribute isEqualToString:@"AXNextTextMarkerForTextMarker"]) {
2908         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
2909         return [self textMarkerForVisiblePosition:m_object->nextVisiblePosition(visiblePos)];
2910     }
2911
2912     if ([attribute isEqualToString:@"AXPreviousTextMarkerForTextMarker"]) {
2913         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
2914         return [self textMarkerForVisiblePosition:m_object->previousVisiblePosition(visiblePos)];
2915     }
2916
2917     if ([attribute isEqualToString:@"AXLeftWordTextMarkerRangeForTextMarker"]) {
2918         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
2919         VisiblePositionRange vpRange = m_object->positionOfLeftWord(visiblePos);
2920         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
2921     }
2922
2923     if ([attribute isEqualToString:@"AXRightWordTextMarkerRangeForTextMarker"]) {
2924         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
2925         VisiblePositionRange vpRange = m_object->positionOfRightWord(visiblePos);
2926         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
2927     }
2928
2929     if ([attribute isEqualToString:@"AXLeftLineTextMarkerRangeForTextMarker"]) {
2930         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
2931         VisiblePositionRange vpRange = m_object->leftLineVisiblePositionRange(visiblePos);
2932         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
2933     }
2934
2935     if ([attribute isEqualToString:@"AXRightLineTextMarkerRangeForTextMarker"]) {
2936         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
2937         VisiblePositionRange vpRange = m_object->rightLineVisiblePositionRange(visiblePos);
2938         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
2939     }
2940
2941     if ([attribute isEqualToString:@"AXSentenceTextMarkerRangeForTextMarker"]) {
2942         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
2943         VisiblePositionRange vpRange = m_object->sentenceForPosition(visiblePos);
2944         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
2945     }
2946
2947     if ([attribute isEqualToString:@"AXParagraphTextMarkerRangeForTextMarker"]) {
2948         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
2949         VisiblePositionRange vpRange = m_object->paragraphForPosition(visiblePos);
2950         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
2951     }
2952
2953     if ([attribute isEqualToString:@"AXNextWordEndTextMarkerForTextMarker"]) {
2954         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
2955         return [self textMarkerForVisiblePosition:m_object->nextWordEnd(visiblePos)];
2956     }
2957     
2958     if ([attribute isEqualToString:@"AXPreviousWordStartTextMarkerForTextMarker"]) {
2959         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
2960         return [self textMarkerForVisiblePosition:m_object->previousWordStart(visiblePos)];
2961     }
2962
2963     if ([attribute isEqualToString:@"AXNextLineEndTextMarkerForTextMarker"]) {
2964         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
2965         return [self textMarkerForVisiblePosition:m_object->nextLineEndPosition(visiblePos)];
2966     }
2967
2968     if ([attribute isEqualToString:@"AXPreviousLineStartTextMarkerForTextMarker"]) {
2969         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
2970         return [self textMarkerForVisiblePosition:m_object->previousLineStartPosition(visiblePos)];
2971     }
2972
2973     if ([attribute isEqualToString:@"AXNextSentenceEndTextMarkerForTextMarker"]) {
2974         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
2975         return [self textMarkerForVisiblePosition:m_object->nextSentenceEndPosition(visiblePos)];
2976     }
2977
2978     if ([attribute isEqualToString:@"AXPreviousSentenceStartTextMarkerForTextMarker"]) {
2979         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
2980         return [self textMarkerForVisiblePosition:m_object->previousSentenceStartPosition(visiblePos)];
2981     }
2982
2983     if ([attribute isEqualToString:@"AXNextParagraphEndTextMarkerForTextMarker"]) {
2984         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
2985         return [self textMarkerForVisiblePosition:m_object->nextParagraphEndPosition(visiblePos)];
2986     }
2987
2988     if ([attribute isEqualToString:@"AXPreviousParagraphStartTextMarkerForTextMarker"]) {
2989         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
2990         return [self textMarkerForVisiblePosition:m_object->previousParagraphStartPosition(visiblePos)];
2991     }
2992
2993     if ([attribute isEqualToString:@"AXStyleTextMarkerRangeForTextMarker"]) {
2994         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
2995         VisiblePositionRange vpRange = m_object->styleRangeForPosition(visiblePos);
2996         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
2997     }
2998
2999     if ([attribute isEqualToString:@"AXLengthForTextMarkerRange"]) {
3000         VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];
3001         int length = m_object->lengthForVisiblePositionRange(visiblePosRange);
3002         if (length < 0)
3003             return nil;
3004         return [NSNumber numberWithInt:length];
3005     }
3006
3007     // Used only by DumpRenderTree (so far).
3008     if ([attribute isEqualToString:@"AXStartTextMarkerForTextMarkerRange"]) {
3009         VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];
3010         return [self textMarkerForVisiblePosition:visiblePosRange.start];
3011     }
3012
3013     if ([attribute isEqualToString:@"AXEndTextMarkerForTextMarkerRange"]) {
3014         VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];
3015         return [self textMarkerForVisiblePosition:visiblePosRange.end];
3016     }
3017     
3018     if (m_object->isAccessibilityTable()) {
3019         if ([attribute isEqualToString:NSAccessibilityCellForColumnAndRowParameterizedAttribute]) {
3020             if (array == nil || [array count] != 2)
3021                 return nil;
3022             AccessibilityTableCell* cell = static_cast<AccessibilityTable*>(m_object)->cellForColumnAndRow([[array objectAtIndex:0] unsignedIntValue], [[array objectAtIndex:1] unsignedIntValue]);
3023             if (!cell)
3024                 return nil;
3025             
3026             return cell->wrapper();
3027         }
3028     }
3029
3030     if (m_object->isTextControl()) {
3031         if ([attribute isEqualToString: (NSString *)kAXLineForIndexParameterizedAttribute]) {
3032             int lineNumber = m_object->doAXLineForIndex([number intValue]);
3033             if (lineNumber < 0)
3034                 return nil;
3035             return [NSNumber numberWithUnsignedInt:lineNumber];
3036         }
3037
3038         if ([attribute isEqualToString: (NSString *)kAXRangeForLineParameterizedAttribute]) {
3039             PlainTextRange textRange = m_object->doAXRangeForLine([number intValue]);
3040             return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)];
3041         }
3042
3043         if ([attribute isEqualToString: (NSString*)kAXStringForRangeParameterizedAttribute]) {
3044             PlainTextRange plainTextRange = PlainTextRange(range.location, range.length);
3045             return rangeSet ? (id)(m_object->doAXStringForRange(plainTextRange)) : nil;
3046         }
3047
3048         if ([attribute isEqualToString: (NSString*)kAXRangeForPositionParameterizedAttribute]) {
3049             if (!pointSet)
3050                 return nil;
3051             IntPoint webCorePoint = IntPoint(point);
3052             PlainTextRange textRange = m_object->doAXRangeForPosition(webCorePoint);
3053             return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)];
3054         }
3055
3056         if ([attribute isEqualToString: (NSString*)kAXRangeForIndexParameterizedAttribute]) {
3057             PlainTextRange textRange = m_object->doAXRangeForIndex([number intValue]);
3058             return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)];
3059         }
3060
3061         if ([attribute isEqualToString: (NSString*)kAXBoundsForRangeParameterizedAttribute]) {
3062             if (!rangeSet)
3063                 return nil;
3064             PlainTextRange plainTextRange = PlainTextRange(range.location, range.length);
3065             NSRect rect = m_object->doAXBoundsForRange(plainTextRange);
3066             return [NSValue valueWithRect:rect];
3067         }
3068
3069         if ([attribute isEqualToString: (NSString*)kAXRTFForRangeParameterizedAttribute])
3070             return rangeSet ? [self doAXRTFForRange:range] : nil;
3071
3072         if ([attribute isEqualToString: (NSString*)kAXAttributedStringForRangeParameterizedAttribute])
3073             return rangeSet ? [self doAXAttributedStringForRange:range] : nil;
3074
3075         if ([attribute isEqualToString: (NSString*)kAXStyleRangeForIndexParameterizedAttribute]) {
3076             PlainTextRange textRange = m_object->doAXStyleRangeForIndex([number intValue]);
3077             return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)];
3078         }