jdk/src/macosx/native/sun/awt/JavaTextAccessibility.m
changeset 12047 320a714614e9
child 23010 6dadb192ad81
equal deleted inserted replaced
12046:378aa3362868 12047:320a714614e9
       
     1 /*
       
     2  * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 #import "JavaTextAccessibility.h"
       
    27 #import "JavaAccessibilityAction.h"
       
    28 #import "JavaAccessibilityUtilities.h"
       
    29 #import "ThreadUtilities.h"
       
    30 
       
    31 
       
    32 static JNF_CLASS_CACHE(sjc_CAccessibleText, "sun/lwawt/macosx/CAccessibleText");
       
    33 static JNF_STATIC_MEMBER_CACHE(sjm_getAccessibleText, sjc_CAccessibility, "getAccessibleText", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/AccessibleText;");
       
    34 static JNF_STATIC_MEMBER_CACHE(sjm_getAccessibleEditableText, sjc_CAccessibleText, "getAccessibleEditableText", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/AccessibleEditableText;");
       
    35 static JNF_STATIC_MEMBER_CACHE(sjm_getAccessibleName, sjc_CAccessibility, "getAccessibleName", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;");
       
    36 
       
    37 /*
       
    38  * Converts an int array to an NSRange wrapped inside an NSValue
       
    39  * takes [start, end] values and returns [start, end - start]
       
    40  */
       
    41 NSValue *javaIntArrayToNSRangeValue(JNIEnv* env, jintArray array) {
       
    42     jint *values = (*env)->GetIntArrayElements(env, array, 0);
       
    43     NSValue *value = [NSValue valueWithRange:NSMakeRange(values[0], values[1] - values[0])];
       
    44     (*env)->ReleaseIntArrayElements(env, array, values, 0);
       
    45     return value;
       
    46 }
       
    47 
       
    48 @implementation JavaTextAccessibility
       
    49 
       
    50 // based strongly upon NSTextViewAccessibility:accessibilityAttributeNames
       
    51 - (NSArray *)initializeAttributeNamesWithEnv:(JNIEnv *)env
       
    52 {
       
    53     static NSArray *attributes = nil;
       
    54 
       
    55     if (attributes == nil) {
       
    56         //APPKIT_LOCK;
       
    57         if (attributes == nil) {
       
    58             NSMutableArray *temp = [[super initializeAttributeNamesWithEnv:env] mutableCopy];
       
    59             //[temp removeObject:NSAccessibilityTitleAttribute]; // title may have been set in the superclass implementation - some static text reports from java that it has a name
       
    60             [temp addObjectsFromArray:[NSArray arrayWithObjects:
       
    61                 NSAccessibilityValueAttribute,
       
    62                 NSAccessibilitySelectedTextAttribute,
       
    63                 NSAccessibilitySelectedTextRangeAttribute,
       
    64                 NSAccessibilityNumberOfCharactersAttribute,
       
    65                 NSAccessibilityVisibleCharacterRangeAttribute,
       
    66                 NSAccessibilityInsertionPointLineNumberAttribute,
       
    67                 //    NSAccessibilitySharedTextUIElementsAttribute, // cmcnote: investigate what these two are for. currently unimplemented
       
    68                 //    NSAccessibilitySharedCharacterRangeAttribute,
       
    69                 nil]];
       
    70             attributes = [[NSArray alloc] initWithArray:temp];
       
    71             [temp release];
       
    72         }
       
    73         //APPKIT_UNLOCK;
       
    74     }
       
    75     return attributes;
       
    76 }
       
    77 
       
    78 // copied from NSTextViewAccessibility.
       
    79 - (NSArray *)accessibilityParameterizedAttributeNames
       
    80 {
       
    81     static NSArray *attributes = nil;
       
    82 
       
    83     if (attributes == nil) {
       
    84         //APPKIT_LOCK;
       
    85         if (attributes == nil) {
       
    86             attributes = [[NSArray alloc] initWithObjects:
       
    87                 NSAccessibilityLineForIndexParameterizedAttribute,
       
    88                 NSAccessibilityRangeForLineParameterizedAttribute,
       
    89                 NSAccessibilityStringForRangeParameterizedAttribute,
       
    90                 NSAccessibilityRangeForPositionParameterizedAttribute,
       
    91                 NSAccessibilityRangeForIndexParameterizedAttribute,
       
    92                 NSAccessibilityBoundsForRangeParameterizedAttribute,
       
    93                 //NSAccessibilityRTFForRangeParameterizedAttribute, // cmcnote: not sure when/how these three are used. Investigate. radr://3960026
       
    94                 //NSAccessibilityStyleRangeForIndexParameterizedAttribute,
       
    95                 //NSAccessibilityAttributedStringForRangeParameterizedAttribute,
       
    96                 nil];
       
    97         }
       
    98         //APPKIT_UNLOCK;
       
    99     }
       
   100     return attributes;
       
   101 }
       
   102 
       
   103 - (NSString *)accessibilityValueAttribute
       
   104 {
       
   105     JNIEnv *env = [ThreadUtilities getJNIEnv];
       
   106     if ([[self accessibilityRoleAttribute] isEqualToString:NSAccessibilityStaticTextRole]) {
       
   107         // if it's static text, the AppKit AXValue is the java accessibleName
       
   108         jobject axName = JNFCallStaticObjectMethod(env, sjm_getAccessibleName, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
       
   109         if (axName != NULL) {
       
   110             return JNFJavaToNSString(env, axName);
       
   111         }
       
   112         // value is still nil if no accessibleName for static text. Below, try to get the accessibleText.
       
   113     }
       
   114 
       
   115     // cmcnote: inefficient to make three distinct JNI calls. Coalesce. radr://3951923
       
   116     jobject axText = JNFCallStaticObjectMethod(env, sjm_getAccessibleText, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
       
   117     if (axText == NULL) return nil;
       
   118 
       
   119     jobject axEditableText = JNFCallStaticObjectMethod(env, sjm_getAccessibleEditableText, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
       
   120     if (axEditableText == NULL) return nil;
       
   121 
       
   122     static JNF_STATIC_MEMBER_CACHE(jm_getTextRange, sjc_CAccessibleText, "getTextRange", "(Ljavax/accessibility/AccessibleEditableText;IILjava/awt/Component;)Ljava/lang/String;");
       
   123     NSString *string = JNFJavaToNSString(env, JNFCallStaticObjectMethod(env, jm_getTextRange, axEditableText, 0, getAxTextCharCount(env, axEditableText, fComponent), fComponent)); // AWT_THREADING Safe (AWTRunLoop)
       
   124     if (string == nil) string = @"";
       
   125     return string;
       
   126 }
       
   127 
       
   128 - (BOOL)accessibilityIsValueAttributeSettable
       
   129 {
       
   130     // if text is enabled and editable, it's settable (according to NSCellTextAttributesAccessibility)
       
   131     BOOL isEnabled = [(NSNumber *)[self accessibilityEnabledAttribute] boolValue];
       
   132     if (!isEnabled) return NO;
       
   133 
       
   134     JNIEnv* env = [ThreadUtilities getJNIEnv];
       
   135     jobject axEditableText = JNFCallStaticObjectMethod(env, sjm_getAccessibleEditableText, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
       
   136     if (axEditableText == NULL) return NO;
       
   137     return YES;
       
   138 }
       
   139 
       
   140 - (void)accessibilitySetValueAttribute:(id)value
       
   141 {
       
   142 // cmcnote: should set the accessibleEditableText to the stringValue of value - AccessibleEditableText.setTextContents(String s)
       
   143 #ifdef JAVA_AX_DEBUG
       
   144     NSLog(@"Not yet implemented: %s\n", __FUNCTION__); // radr://3954018
       
   145 #endif
       
   146 }
       
   147 
       
   148 // Currently selected text (NSString)
       
   149 - (NSString *)accessibilitySelectedTextAttribute
       
   150 {
       
   151     JNIEnv* env = [ThreadUtilities getJNIEnv];
       
   152     static JNF_STATIC_MEMBER_CACHE(jm_getSelectedText, sjc_CAccessibleText, "getSelectedText", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;");
       
   153     jobject axText = JNFCallStaticObjectMethod(env, jm_getSelectedText, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
       
   154     if (axText == NULL) return @"";
       
   155     return JNFJavaToNSString(env, axText);
       
   156 }
       
   157 
       
   158 - (BOOL)accessibilityIsSelectedTextAttributeSettable
       
   159 {
       
   160     return YES; //cmcnote: for AXTextField that's selectable, it's settable. Investigate further.
       
   161 }
       
   162 
       
   163 - (void)accessibilitySetSelectedTextAttribute:(id)value
       
   164 {
       
   165 #ifdef JAVA_AX_DEBUG_PARMS
       
   166     if (![value isKindOfClass:[NSString class]]) {
       
   167         JavaAccessibilityRaiseSetAttributeToIllegalTypeException(__FUNCTION__, self, NSAccessibilitySelectedTextAttribute, value);
       
   168         return;
       
   169     }
       
   170 #endif
       
   171 
       
   172     JNIEnv *env = [ThreadUtilities getJNIEnv];
       
   173     jstring jstringValue = JNFNSToJavaString(env, (NSString *)value);
       
   174     static JNF_STATIC_MEMBER_CACHE(jm_setSelectedText, sjc_CAccessibleText, "setSelectedText", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;Ljava/lang/String;)V");
       
   175     JNFCallStaticVoidMethod(env, jm_setSelectedText, fAccessible, fComponent, jstringValue); // AWT_THREADING Safe (AWTRunLoop)
       
   176 }
       
   177 
       
   178 // Range of selected text (NSValue)
       
   179 - (NSValue *)accessibilitySelectedTextRangeAttribute
       
   180 {
       
   181     JNIEnv *env = [ThreadUtilities getJNIEnv];
       
   182     static JNF_STATIC_MEMBER_CACHE(jm_getSelectedTextRange, sjc_CAccessibleText, "getSelectedTextRange", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)[I");
       
   183     jintArray axTextRange = JNFCallStaticObjectMethod(env, jm_getSelectedTextRange, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
       
   184     if (axTextRange == NULL) return nil;
       
   185 
       
   186     return javaIntArrayToNSRangeValue(env, axTextRange);
       
   187 }
       
   188 
       
   189 - (BOOL)accessibilityIsSelectedTextRangeAttributeSettable
       
   190 {
       
   191     return [(NSNumber *)[self accessibilityEnabledAttribute] boolValue]; // cmcnote: also may want to find out if isSelectable. Investigate.
       
   192 }
       
   193 
       
   194 - (void)accessibilitySetSelectedTextRangeAttribute:(id)value
       
   195 {
       
   196 #ifdef JAVA_AX_DEBUG_PARMS
       
   197     if (!([value isKindOfClass:[NSValue class]] && strcmp([(NSValue *)value objCType], @encode(NSRange)) == 0)) {
       
   198         JavaAccessibilityRaiseSetAttributeToIllegalTypeException(__FUNCTION__, self, NSAccessibilitySelectedTextRangeAttribute, value);
       
   199         return;
       
   200     }
       
   201 #endif
       
   202 
       
   203     NSRange range = [(NSValue *)value rangeValue];
       
   204     jint startIndex = range.location;
       
   205     jint endIndex = startIndex + range.length;
       
   206 
       
   207     JNIEnv *env = [ThreadUtilities getJNIEnv];
       
   208     static JNF_STATIC_MEMBER_CACHE(jm_setSelectedTextRange, sjc_CAccessibleText, "setSelectedTextRange", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)V");
       
   209     JNFCallStaticVoidMethod(env, jm_setSelectedTextRange, fAccessible, fComponent, startIndex, endIndex); // AWT_THREADING Safe (AWTRunLoop)
       
   210 }
       
   211 
       
   212 - (NSNumber *)accessibilityNumberOfCharactersAttribute
       
   213 {
       
   214     // cmcnote: should coalesce these two calls - radr://3951923
       
   215     // also, static text doesn't always have accessibleText. if axText is null, should get the charcount of the accessibleName instead
       
   216     JNIEnv *env = [ThreadUtilities getJNIEnv];
       
   217     jobject axText = JNFCallStaticObjectMethod(env, sjm_getAccessibleText, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
       
   218     return [NSNumber numberWithInt:getAxTextCharCount(env, axText, fComponent)];
       
   219 }
       
   220 
       
   221 - (BOOL)accessibilityIsNumberOfCharactersAttributeSettable
       
   222 {
       
   223     return NO; // according to NSTextViewAccessibility.m and NSCellTextAttributesAccessibility.m
       
   224 }
       
   225 
       
   226 - (NSValue *)accessibilityVisibleCharacterRangeAttribute
       
   227 {
       
   228     JNIEnv *env = [ThreadUtilities getJNIEnv];
       
   229     static JNF_STATIC_MEMBER_CACHE(jm_getVisibleCharacterRange, sjc_CAccessibleText, "getVisibleCharacterRange", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)[I");
       
   230     jintArray axTextRange = JNFCallStaticObjectMethod(env, jm_getVisibleCharacterRange, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
       
   231     if (axTextRange == NULL) return nil;
       
   232 
       
   233     return javaIntArrayToNSRangeValue(env, axTextRange);
       
   234 }
       
   235 
       
   236 - (BOOL)accessibilityIsVisibleCharacterRangeAttributeSettable
       
   237 {
       
   238 #ifdef JAVA_AX_DEBUG
       
   239     NSLog(@"Not yet implemented: %s\n", __FUNCTION__);
       
   240 #endif
       
   241     return NO;
       
   242 }
       
   243 
       
   244 - (NSValue *)accessibilityInsertionPointLineNumberAttribute
       
   245 {
       
   246     JNIEnv *env = [ThreadUtilities getJNIEnv];
       
   247     static JNF_STATIC_MEMBER_CACHE(jm_getLineNumberForInsertionPoint, sjc_CAccessibleText, "getLineNumberForInsertionPoint", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)I");
       
   248     jint row = JNFCallStaticIntMethod(env, jm_getLineNumberForInsertionPoint, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
       
   249     if (row < 0) return nil;
       
   250     return [NSNumber numberWithInt:row];
       
   251 }
       
   252 
       
   253 - (BOOL)accessibilityIsInsertionPointLineNumberAttributeSettable
       
   254 {
       
   255 #ifdef JAVA_AX_DEBUG
       
   256     NSLog(@"Not yet implemented: %s\n", __FUNCTION__);
       
   257 #endif
       
   258     return NO;
       
   259 }
       
   260 
       
   261 // parameterized attributes
       
   262 
       
   263 //
       
   264 // Usage of accessibilityBoundsForRangeAttributeForParameter:
       
   265 // ---
       
   266 // called by VoiceOver when interacting with text via ctrl-option-shift-downArrow.
       
   267 // Need to know bounding box for the character / word / line of interest in
       
   268 // order to draw VoiceOver cursor
       
   269 //
       
   270 - (NSValue *)accessibilityBoundsForRangeAttributeForParameter:(id)parameter
       
   271 {
       
   272 #ifdef JAVA_AX_DEBUG_PARMS
       
   273     if (!([parameter isKindOfClass:[NSValue class]] && strcmp([(NSValue *)parameter objCType], @encode(NSRange)) == 0)) {
       
   274         JavaAccessibilityRaiseIllegalParameterTypeException(__FUNCTION__, self, NSAccessibilityBoundsForRangeParameterizedAttribute, parameter);
       
   275         return nil;
       
   276     }
       
   277 #endif
       
   278 
       
   279     NSRange range = [(NSValue *)parameter rangeValue];
       
   280 
       
   281     JNIEnv *env = [ThreadUtilities getJNIEnv];
       
   282     static JNF_STATIC_MEMBER_CACHE(jm_getBoundsForRange, sjc_CAccessibleText, "getBoundsForRange", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)[D");
       
   283     jdoubleArray axBounds = JNFCallStaticObjectMethod(env, jm_getBoundsForRange, fAccessible, fComponent, range.location, range.length); // AWT_THREADING Safe (AWTRunLoop)
       
   284     if (axBounds == NULL) return nil;
       
   285 
       
   286     // We cheat because we know that the array is 4 elements long (x, y, width, height)
       
   287     jdouble *values = (*env)->GetDoubleArrayElements(env, axBounds, 0);
       
   288     NSRect bounds;
       
   289     bounds.origin.x = values[0];
       
   290     bounds.origin.y = [[[[self view] window] screen] frame].size.height - values[1] - values[3]; //values[1] is y-coord from top-left of screen. Flip. Account for the height (values[3]) when flipping
       
   291     bounds.size.width = values[2];
       
   292     bounds.size.height = values[3];
       
   293     NSValue *result = [NSValue valueWithRect:bounds];
       
   294     (*env)->ReleaseDoubleArrayElements(env, axBounds, values, 0);
       
   295     return result;
       
   296 }
       
   297 
       
   298 - (NSNumber *)accessibilityLineForIndexAttributeForParameter:(id)parameter
       
   299 {
       
   300     NSNumber *line = (NSNumber *) parameter;
       
   301     if (line == nil) return nil;
       
   302 
       
   303     JNIEnv *env = [ThreadUtilities getJNIEnv];
       
   304     static JNF_STATIC_MEMBER_CACHE(jm_getLineNumberForIndex, sjc_CAccessibleText, "getLineNumberForIndex", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)I");
       
   305     jint row = JNFCallStaticIntMethod(env, jm_getLineNumberForIndex, fAccessible, fComponent, [line intValue]); // AWT_THREADING Safe (AWTRunLoop)
       
   306     if (row < 0) return nil;
       
   307     return [NSNumber numberWithInt:row];
       
   308 }
       
   309 
       
   310 - (NSValue *)accessibilityRangeForLineAttributeForParameter:(id)parameter
       
   311 {
       
   312     NSNumber *line = (NSNumber *) parameter;
       
   313     if (line == nil) return nil;
       
   314 
       
   315     JNIEnv *env = [ThreadUtilities getJNIEnv];
       
   316     static JNF_STATIC_MEMBER_CACHE(jm_getRangeForLine, sjc_CAccessibleText, "getRangeForLine", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)[I");
       
   317     jintArray axTextRange = JNFCallStaticObjectMethod(env, jm_getRangeForLine, fAccessible, fComponent, [line intValue]); // AWT_THREADING Safe (AWTRunLoop)
       
   318     if (axTextRange == NULL) return nil;
       
   319 
       
   320     return javaIntArrayToNSRangeValue(env,axTextRange);
       
   321 }
       
   322 
       
   323 //
       
   324 // Usage of accessibilityStringForRangeAttributeForParameter:
       
   325 // ---
       
   326 // called by VoiceOver when interacting with text via ctrl-option-shift-downArrow.
       
   327 // VO needs to know the particular string its currently dealing with so it can
       
   328 // speak the string
       
   329 //
       
   330 - (NSString *)accessibilityStringForRangeAttributeForParameter:(id)parameter
       
   331 {
       
   332 #ifdef JAVA_AX_DEBUG_PARMS
       
   333     if (!([parameter isKindOfClass:[NSValue class]] && strcmp([(NSValue *)parameter objCType], @encode(NSRange)) == 0)) {
       
   334         JavaAccessibilityRaiseIllegalParameterTypeException(__FUNCTION__, self, NSAccessibilityBoundsForRangeParameterizedAttribute, parameter);
       
   335         return nil;
       
   336     }
       
   337 #endif
       
   338 
       
   339     NSRange range = [(NSValue *)parameter rangeValue];
       
   340 
       
   341     JNIEnv *env = [ThreadUtilities getJNIEnv];
       
   342     static JNF_STATIC_MEMBER_CACHE(jm_getStringForRange, sjc_CAccessibleText, "getStringForRange", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)Ljava/lang/String;");
       
   343     jstring jstringForRange = JNFCallStaticObjectMethod(env, jm_getStringForRange, fAccessible, fComponent, range.location, range.length); // AWT_THREADING Safe (AWTRunLoop)
       
   344 
       
   345     if (jstringForRange == NULL) return @"";
       
   346     return JNFJavaToNSString(env, jstringForRange);
       
   347 }
       
   348 
       
   349 //
       
   350 // Usage of accessibilityRangeForPositionAttributeForParameter:
       
   351 // ---
       
   352 // cmcnote: I'm not sure when this is called / how it's used. Investigate.
       
   353 // probably could be used in a special text-only accessibilityHitTest to
       
   354 // find the index of the string under the mouse?
       
   355 //
       
   356 - (NSValue *)accessibilityRangeForPositionAttributeForParameter:(id)parameter
       
   357 {
       
   358 #ifdef JAVA_AX_DEBUG_PARMS
       
   359     if (!([parameter isKindOfClass:[NSValue class]] && strcmp([(NSValue *)parameter objCType], @encode(NSPoint)) == 0)) {
       
   360         JavaAccessibilityRaiseIllegalParameterTypeException(__FUNCTION__, self, NSAccessibilityRangeForPositionParameterizedAttribute, parameter);
       
   361         return nil;
       
   362     }
       
   363 #endif
       
   364 
       
   365     NSPoint point = [(NSValue *)parameter pointValue]; // point is in screen coords
       
   366     point.y = [[[[self view] window] screen] frame].size.height - point.y; // flip into java screen coords (0 is at upper-left corner of screen)
       
   367 
       
   368     JNIEnv *env = [ThreadUtilities getJNIEnv];
       
   369     static JNF_STATIC_MEMBER_CACHE(jm_getCharacterIndexAtPosition, sjc_CAccessibleText, "getCharacterIndexAtPosition", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)I");
       
   370     jint charIndex = JNFCallStaticIntMethod(env, jm_getCharacterIndexAtPosition, fAccessible, fComponent, point.x, point.y); // AWT_THREADING Safe (AWTRunLoop)
       
   371     if (charIndex == -1) return nil;
       
   372 
       
   373     // AccessibleText.getIndexAtPoint returns -1 for an invalid point
       
   374     NSRange range = NSMakeRange(charIndex, 1); //range's length is 1 - one-character range
       
   375     return [NSValue valueWithRange:range];
       
   376 }
       
   377 
       
   378 //
       
   379 // Usage of accessibilityRangeForIndexAttributeForParameter:
       
   380 // ---
       
   381 // cmcnote: I'm not sure when this is called / how it's used. Investigate.
       
   382 // AppKit version calls: [string rangeOfComposedCharacterSequenceAtIndex:index]
       
   383 // We call: CAccessibility.getRangeForIndex, which calls AccessibleText.getAtIndex(AccessibleText.WORD, index)
       
   384 // to determine the word closest to the given index. Then we find the length/location of this string.
       
   385 //
       
   386 - (NSValue *)accessibilityRangeForIndexAttributeForParameter:(id)parameter
       
   387 {
       
   388 #ifdef JAVA_AX_DEBUG_PARMS
       
   389     if (![parameter isKindOfClass:[NSNumber class]]) {
       
   390         JavaAccessibilityRaiseIllegalParameterTypeException(__FUNCTION__, self, NSAccessibilityRangeForIndexParameterizedAttribute, parameter);
       
   391         return nil;
       
   392     }
       
   393 #endif
       
   394 
       
   395     NSUInteger index = [(NSNumber *)parameter unsignedIntegerValue];
       
   396 
       
   397     JNIEnv *env = [ThreadUtilities getJNIEnv];
       
   398     static JNF_STATIC_MEMBER_CACHE(jm_getRangeForIndex, sjc_CAccessibleText, "getRangeForIndex", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)[I");
       
   399     jintArray axTextRange = JNFCallStaticObjectMethod(env, jm_getRangeForIndex, fAccessible, fComponent, index); // AWT_THREADING Safe (AWTRunLoop)
       
   400     if (axTextRange == NULL) return nil;
       
   401 
       
   402     return javaIntArrayToNSRangeValue(env, axTextRange);
       
   403 }
       
   404 
       
   405 - (NSDictionary *)getActions:(JNIEnv *)env {
       
   406     // cmcnote: this isn't correct; text can have actions. Not yet implemented. radr://3941691
       
   407     // Editable text has AXShowMenu. Textfields have AXConfirm. Static text has no actions.
       
   408 #ifdef JAVA_AX_DEBUG
       
   409     NSLog(@"Not yet implemented: %s\n", __FUNCTION__);
       
   410 #endif
       
   411     return nil;
       
   412 }
       
   413 
       
   414 @end