rev 54094 : 8257853: Remove dependencies on JNF's JNI utility functions in AWT and 2D code
rev 54095 : 8259343: [macOS] Update JNI error handling in Cocoa code.
rev 54098 : 8260616: Removing remaining JNF dependencies in the java.desktop module
8259729: Missed JNFInstanceOf -> IsInstanceOf conversion

   1 /*
   2  * Copyright (c) 2011, 2016, 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 #import "JNIUtilities.h"
  31 
  32 static jclass sjc_CAccessibility = NULL;
  33 #define GET_CACCESSIBLITY_CLASS() \
  34      GET_CLASS(sjc_CAccessibility, "sun/lwawt/macosx/CAccessibility");
  35 #define GET_CACCESSIBLITY_CLASS_RETURN(ret) \
  36      GET_CLASS_RETURN(sjc_CAccessibility, "sun/lwawt/macosx/CAccessibility", ret);
  37 
  38 static jmethodID sjm_getAccessibleText = NULL;
  39 #define GET_ACCESSIBLETEXT_METHOD_RETURN(ret) \
  40     GET_CACCESSIBLITY_CLASS_RETURN(ret); \
  41     GET_STATIC_METHOD_RETURN(sjm_getAccessibleText, sjc_CAccessibility, "getAccessibleText", \
  42               "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/AccessibleText;", ret);
  43 
  44 static jclass sjc_CAccessibleText = NULL;
  45 #define GET_CACCESSIBLETEXT_CLASS() \
  46     GET_CLASS(sjc_CAccessibleText, "sun/lwawt/macosx/CAccessibleText");
  47 #define GET_CACCESSIBLETEXT_CLASS_RETURN(ret) \
  48     GET_CLASS_RETURN(sjc_CAccessibleText, "sun/lwawt/macosx/CAccessibleText", ret);
  49 
  50 static jmethodID sjm_getAccessibleEditableText = NULL;
  51 #define GET_ACCESSIBLEEDITABLETEXT_METHOD_RETURN(ret) \
  52     GET_CACCESSIBLETEXT_CLASS_RETURN(ret); \
  53     GET_STATIC_METHOD_RETURN(sjm_getAccessibleEditableText, sjc_CAccessibleText, "getAccessibleEditableText", \
  54               "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/AccessibleEditableText;", ret);
  55 




  56 
  57 /*
  58  * Converts an int array to an NSRange wrapped inside an NSValue
  59  * takes [start, end] values and returns [start, end - start]
  60  */
  61 NSValue *javaIntArrayToNSRangeValue(JNIEnv* env, jintArray array) {
  62     jint *values = (*env)->GetIntArrayElements(env, array, 0);
  63     if (values == NULL) {
  64         // Note: Java will not be on the stack here so a java exception can't happen and no need to call ExceptionCheck.
  65         NSLog(@"%s failed calling GetIntArrayElements", __FUNCTION__);
  66         return nil;
  67     };
  68     NSValue *value = [NSValue valueWithRange:NSMakeRange(values[0], values[1] - values[0])];
  69     (*env)->ReleaseIntArrayElements(env, array, values, 0);
  70     return value;
  71 }
  72 
  73 @implementation JavaTextAccessibility
  74 
  75 // based strongly upon NSTextViewAccessibility:accessibilityAttributeNames
  76 - (NSArray *)initializeAttributeNamesWithEnv:(JNIEnv *)env
  77 {
  78     static NSArray *attributes = nil;
  79 
  80     if (attributes == nil) {
  81         //APPKIT_LOCK;
  82         if (attributes == nil) {
  83             NSMutableArray *temp = [[super initializeAttributeNamesWithEnv:env] mutableCopy];
  84             //[temp removeObject:NSAccessibilityTitleAttribute]; // title may have been set in the superclass implementation - some static text reports from java that it has a name
  85             [temp addObjectsFromArray:[NSArray arrayWithObjects:
  86                 NSAccessibilityValueAttribute,
  87                 NSAccessibilitySelectedTextAttribute,
  88                 NSAccessibilitySelectedTextRangeAttribute,
  89                 NSAccessibilityNumberOfCharactersAttribute,
  90                 NSAccessibilityVisibleCharacterRangeAttribute,
  91                 NSAccessibilityInsertionPointLineNumberAttribute,
  92                 //    NSAccessibilitySharedTextUIElementsAttribute, // cmcnote: investigate what these two are for. currently unimplemented
  93                 //    NSAccessibilitySharedCharacterRangeAttribute,
  94                 nil]];
  95             attributes = [[NSArray alloc] initWithArray:temp];
  96             [temp release];
  97         }
  98         //APPKIT_UNLOCK;
  99     }
 100     return attributes;
 101 }
 102 
 103 // copied from NSTextViewAccessibility.
 104 - (NSArray *)accessibilityParameterizedAttributeNames
 105 {
 106     static NSArray *attributes = nil;
 107 
 108     if (attributes == nil) {
 109         //APPKIT_LOCK;
 110         if (attributes == nil) {
 111             attributes = [[NSArray alloc] initWithObjects:
 112                 NSAccessibilityLineForIndexParameterizedAttribute,
 113                 NSAccessibilityRangeForLineParameterizedAttribute,
 114                 NSAccessibilityStringForRangeParameterizedAttribute,
 115                 NSAccessibilityRangeForPositionParameterizedAttribute,
 116                 NSAccessibilityRangeForIndexParameterizedAttribute,
 117                 NSAccessibilityBoundsForRangeParameterizedAttribute,
 118                 //NSAccessibilityRTFForRangeParameterizedAttribute, // cmcnote: not sure when/how these three are used. Investigate. radr://3960026
 119                 //NSAccessibilityStyleRangeForIndexParameterizedAttribute,
 120                 //NSAccessibilityAttributedStringForRangeParameterizedAttribute,
 121                 nil];
 122         }
 123         //APPKIT_UNLOCK;
 124     }
 125     return attributes;
 126 }
 127 
 128 - (NSString *)accessibilityValueAttribute
 129 {
 130     JNIEnv *env = [ThreadUtilities getJNIEnv];
 131     GET_CACCESSIBLITY_CLASS_RETURN(nil);
 132     DECLARE_STATIC_METHOD_RETURN(sjm_getAccessibleName, sjc_CAccessibility, "getAccessibleName",
 133                           "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;", nil);
 134     if ([[self accessibilityRoleAttribute] isEqualToString:NSAccessibilityStaticTextRole]) {
 135         // if it's static text, the AppKit AXValue is the java accessibleName
 136         jobject axName = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility,
 137                            sjm_getAccessibleName, fAccessible, fComponent);
 138         CHECK_EXCEPTION();
 139         if (axName != NULL) {
 140             NSString* str = JavaStringToNSString(env, axName);
 141             (*env)->DeleteLocalRef(env, axName);
 142             return str;
 143         }
 144         // value is still nil if no accessibleName for static text. Below, try to get the accessibleText.
 145     }
 146 
 147     // cmcnote: inefficient to make three distinct JNI calls. Coalesce. radr://3951923
 148     GET_ACCESSIBLETEXT_METHOD_RETURN(@"");
 149     jobject axText = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility,
 150                       sjm_getAccessibleText, fAccessible, fComponent);
 151     CHECK_EXCEPTION();
 152     if (axText == NULL) return nil;
 153     (*env)->DeleteLocalRef(env, axText);
 154 
 155     GET_ACCESSIBLEEDITABLETEXT_METHOD_RETURN(nil);
 156     jobject axEditableText = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText,
 157                        sjm_getAccessibleEditableText, fAccessible, fComponent);
 158     CHECK_EXCEPTION();
 159     if (axEditableText == NULL) return nil;
 160 
 161     DECLARE_STATIC_METHOD_RETURN(jm_getTextRange, sjc_CAccessibleText, "getTextRange",
 162                     "(Ljavax/accessibility/AccessibleEditableText;IILjava/awt/Component;)Ljava/lang/String;", nil);
 163     jobject jrange = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getTextRange,
 164                        axEditableText, 0, getAxTextCharCount(env, axEditableText, fComponent), fComponent);
 165     CHECK_EXCEPTION();
 166     NSString *string = JavaStringToNSString(env, jrange);
 167 
 168     (*env)->DeleteLocalRef(env, jrange);
 169     (*env)->DeleteLocalRef(env, axEditableText);
 170 
 171     if (string == nil) string = @"";
 172     return string;
 173 }
 174 
 175 - (BOOL)accessibilityIsValueAttributeSettable
 176 {
 177     // if text is enabled and editable, it's settable (according to NSCellTextAttributesAccessibility)
 178     BOOL isEnabled = [(NSNumber *)[self accessibilityEnabledAttribute] boolValue];
 179     if (!isEnabled) return NO;
 180 
 181     JNIEnv* env = [ThreadUtilities getJNIEnv];
 182     GET_ACCESSIBLEEDITABLETEXT_METHOD_RETURN(NO);
 183     jobject axEditableText = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText,
 184                      sjm_getAccessibleEditableText, fAccessible, fComponent);
 185     CHECK_EXCEPTION();
 186     if (axEditableText == NULL) return NO;
 187     (*env)->DeleteLocalRef(env, axEditableText);
 188     return YES;
 189 }
 190 
 191 - (void)accessibilitySetValueAttribute:(id)value
 192 {
 193 // cmcnote: should set the accessibleEditableText to the stringValue of value - AccessibleEditableText.setTextContents(String s)
 194 #ifdef JAVA_AX_DEBUG
 195     NSLog(@"Not yet implemented: %s\n", __FUNCTION__); // radr://3954018
 196 #endif
 197 }
 198 
 199 // Currently selected text (NSString)
 200 - (NSString *)accessibilitySelectedTextAttribute
 201 {
 202     JNIEnv* env = [ThreadUtilities getJNIEnv];
 203     GET_CACCESSIBLETEXT_CLASS_RETURN(nil);
 204     DECLARE_STATIC_METHOD_RETURN(jm_getSelectedText, sjc_CAccessibleText, "getSelectedText",
 205               "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;", nil);
 206     jobject axText = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getSelectedText,
 207                         fAccessible, fComponent);
 208     CHECK_EXCEPTION();
 209     if (axText == NULL) return @"";
 210     NSString* str = JavaStringToNSString(env, axText);
 211     (*env)->DeleteLocalRef(env, axText);
 212     return str;
 213 }
 214 
 215 - (BOOL)accessibilityIsSelectedTextAttributeSettable
 216 {
 217     return YES; //cmcnote: for AXTextField that's selectable, it's settable. Investigate further.
 218 }
 219 
 220 - (void)accessibilitySetSelectedTextAttribute:(id)value
 221 {
 222 #ifdef JAVA_AX_DEBUG_PARMS
 223     if (![value isKindOfClass:[NSString class]]) {
 224         JavaAccessibilityRaiseSetAttributeToIllegalTypeException(__FUNCTION__, self, NSAccessibilitySelectedTextAttribute, value);
 225         return;
 226     }
 227 #endif
 228 
 229     JNIEnv *env = [ThreadUtilities getJNIEnv];
 230     jstring jstringValue = NSStringToJavaString(env, (NSString *)value);
 231     GET_CACCESSIBLETEXT_CLASS();
 232     DECLARE_STATIC_METHOD(jm_setSelectedText, sjc_CAccessibleText, "setSelectedText",
 233                    "(Ljavax/accessibility/Accessible;Ljava/awt/Component;Ljava/lang/String;)V");
 234     (*env)->CallStaticVoidMethod(env, sjc_CAccessibleText, jm_setSelectedText,
 235               fAccessible, fComponent, jstringValue);
 236     CHECK_EXCEPTION();
 237 }
 238 
 239 // Range of selected text (NSValue)
 240 - (NSValue *)accessibilitySelectedTextRangeAttribute
 241 {
 242     JNIEnv *env = [ThreadUtilities getJNIEnv];
 243     GET_CACCESSIBLETEXT_CLASS_RETURN(nil);
 244     DECLARE_STATIC_METHOD_RETURN(jm_getSelectedTextRange, sjc_CAccessibleText, "getSelectedTextRange",
 245            "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)[I", nil);
 246     jintArray axTextRange = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText,
 247                 jm_getSelectedTextRange, fAccessible, fComponent);
 248     CHECK_EXCEPTION();
 249     if (axTextRange == NULL) return nil;
 250 
 251     return javaIntArrayToNSRangeValue(env, axTextRange);
 252 }
 253 
 254 - (BOOL)accessibilityIsSelectedTextRangeAttributeSettable
 255 {
 256     return [(NSNumber *)[self accessibilityEnabledAttribute] boolValue]; // cmcnote: also may want to find out if isSelectable. Investigate.
 257 }
 258 
 259 - (void)accessibilitySetSelectedTextRangeAttribute:(id)value
 260 {
 261 #ifdef JAVA_AX_DEBUG_PARMS
 262     if (!([value isKindOfClass:[NSValue class]] && strcmp([(NSValue *)value objCType], @encode(NSRange)) == 0)) {
 263         JavaAccessibilityRaiseSetAttributeToIllegalTypeException(__FUNCTION__, self, NSAccessibilitySelectedTextRangeAttribute, value);
 264         return;
 265     }
 266 #endif
 267 
 268     NSRange range = [(NSValue *)value rangeValue];
 269     jint startIndex = range.location;
 270     jint endIndex = startIndex + range.length;
 271 
 272     JNIEnv *env = [ThreadUtilities getJNIEnv];
 273     GET_CACCESSIBLETEXT_CLASS();
 274     DECLARE_STATIC_METHOD(jm_setSelectedTextRange, sjc_CAccessibleText, "setSelectedTextRange",
 275                   "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)V");
 276     (*env)->CallStaticVoidMethod(env, sjc_CAccessibleText, jm_setSelectedTextRange,
 277                   fAccessible, fComponent, startIndex, endIndex);
 278     CHECK_EXCEPTION();
 279 }
 280 
 281 - (NSNumber *)accessibilityNumberOfCharactersAttribute
 282 {
 283     // cmcnote: should coalesce these two calls - radr://3951923
 284     // also, static text doesn't always have accessibleText. if axText is null, should get the charcount of the accessibleName instead
 285     JNIEnv *env = [ThreadUtilities getJNIEnv];
 286     GET_ACCESSIBLETEXT_METHOD_RETURN(nil);
 287     jobject axText = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility,
 288                      sjm_getAccessibleText, fAccessible, fComponent);
 289     CHECK_EXCEPTION();
 290     NSNumber* num = [NSNumber numberWithInt:getAxTextCharCount(env, axText, fComponent)];
 291     (*env)->DeleteLocalRef(env, axText);
 292     return num;
 293 }
 294 
 295 - (BOOL)accessibilityIsNumberOfCharactersAttributeSettable
 296 {
 297     return NO; // according to NSTextViewAccessibility.m and NSCellTextAttributesAccessibility.m
 298 }
 299 
 300 - (NSValue *)accessibilityVisibleCharacterRangeAttribute
 301 {
 302     JNIEnv *env = [ThreadUtilities getJNIEnv];
 303     GET_CACCESSIBLETEXT_CLASS_RETURN(nil);
 304     DECLARE_STATIC_METHOD_RETURN(jm_getVisibleCharacterRange, sjc_CAccessibleText, "getVisibleCharacterRange",
 305                           "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)[I", nil);
 306     jintArray axTextRange = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText,
 307                  jm_getVisibleCharacterRange, fAccessible, fComponent);
 308     CHECK_EXCEPTION();
 309     if (axTextRange == NULL) return nil;
 310 
 311     return javaIntArrayToNSRangeValue(env, axTextRange);
 312 }
 313 
 314 - (BOOL)accessibilityIsVisibleCharacterRangeAttributeSettable
 315 {
 316 #ifdef JAVA_AX_DEBUG
 317     NSLog(@"Not yet implemented: %s\n", __FUNCTION__);
 318 #endif
 319     return NO;
 320 }
 321 
 322 - (NSValue *)accessibilityInsertionPointLineNumberAttribute
 323 {
 324     JNIEnv *env = [ThreadUtilities getJNIEnv];
 325     GET_CACCESSIBLETEXT_CLASS_RETURN(nil);
 326     DECLARE_STATIC_METHOD_RETURN(jm_getLineNumberForInsertionPoint, sjc_CAccessibleText,
 327              "getLineNumberForInsertionPoint", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)I", nil);
 328     jint row = (*env)->CallStaticIntMethod(env, sjc_CAccessibleText,
 329                   jm_getLineNumberForInsertionPoint, fAccessible, fComponent);
 330     CHECK_EXCEPTION();
 331     if (row < 0) return nil;
 332     return [NSNumber numberWithInt:row];
 333 }
 334 
 335 - (BOOL)accessibilityIsInsertionPointLineNumberAttributeSettable
 336 {
 337 #ifdef JAVA_AX_DEBUG
 338     NSLog(@"Not yet implemented: %s\n", __FUNCTION__);
 339 #endif
 340     return NO;
 341 }
 342 
 343 // parameterized attributes
 344 
 345 //
 346 // Usage of accessibilityBoundsForRangeAttributeForParameter:
 347 // ---
 348 // called by VoiceOver when interacting with text via ctrl-option-shift-downArrow.
 349 // Need to know bounding box for the character / word / line of interest in
 350 // order to draw VoiceOver cursor
 351 //
 352 - (NSValue *)accessibilityBoundsForRangeAttributeForParameter:(id)parameter
 353 {
 354 #ifdef JAVA_AX_DEBUG_PARMS
 355     if (!([parameter isKindOfClass:[NSValue class]] && strcmp([(NSValue *)parameter objCType], @encode(NSRange)) == 0)) {
 356         JavaAccessibilityRaiseIllegalParameterTypeException(__FUNCTION__, self, NSAccessibilityBoundsForRangeParameterizedAttribute, parameter);
 357         return nil;
 358     }
 359 #endif
 360 
 361     NSRange range = [(NSValue *)parameter rangeValue];
 362 
 363     JNIEnv *env = [ThreadUtilities getJNIEnv];
 364     GET_CACCESSIBLETEXT_CLASS_RETURN(nil);
 365     DECLARE_STATIC_METHOD_RETURN(jm_getBoundsForRange, sjc_CAccessibleText, "getBoundsForRange",
 366                          "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)[D", nil);
 367     jdoubleArray axBounds = (jdoubleArray)(*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getBoundsForRange,
 368                               fAccessible, fComponent, range.location, range.length);
 369     CHECK_EXCEPTION();
 370     if (axBounds == NULL) return nil;
 371 
 372     // We cheat because we know that the array is 4 elements long (x, y, width, height)
 373     jdouble *values = (*env)->GetDoubleArrayElements(env, axBounds, 0);
 374     CHECK_EXCEPTION();
 375     if (values == NULL) {
 376         // Note: Java will not be on the stack here so a java exception can't happen and no need to call ExceptionCheck.
 377         NSLog(@"%s failed calling GetDoubleArrayElements", __FUNCTION__);
 378         return nil;
 379     };
 380     NSRect bounds;
 381     bounds.origin.x = values[0];
 382     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
 383     bounds.size.width = values[2];
 384     bounds.size.height = values[3];
 385     NSValue *result = [NSValue valueWithRect:bounds];
 386     (*env)->ReleaseDoubleArrayElements(env, axBounds, values, 0);
 387     return result;
 388 }
 389 
 390 - (NSNumber *)accessibilityLineForIndexAttributeForParameter:(id)parameter
 391 {
 392     NSNumber *line = (NSNumber *) parameter;
 393     if (line == nil) return nil;
 394 
 395     JNIEnv *env = [ThreadUtilities getJNIEnv];
 396     GET_CACCESSIBLETEXT_CLASS_RETURN(nil);
 397     DECLARE_STATIC_METHOD_RETURN(jm_getLineNumberForIndex, sjc_CAccessibleText, "getLineNumberForIndex",
 398                            "(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)I", nil);
 399     jint row = (*env)->CallStaticIntMethod(env, sjc_CAccessibleText, jm_getLineNumberForIndex,
 400                        fAccessible, fComponent, [line intValue]);
 401     CHECK_EXCEPTION();
 402     if (row < 0) return nil;
 403     return [NSNumber numberWithInt:row];
 404 }
 405 
 406 - (NSValue *)accessibilityRangeForLineAttributeForParameter:(id)parameter
 407 {
 408     NSNumber *line = (NSNumber *) parameter;
 409     if (line == nil) return nil;
 410 
 411     JNIEnv *env = [ThreadUtilities getJNIEnv];
 412     GET_CACCESSIBLETEXT_CLASS_RETURN(nil);
 413     DECLARE_STATIC_METHOD_RETURN(jm_getRangeForLine, sjc_CAccessibleText, "getRangeForLine",
 414                  "(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)[I", nil);
 415     jintArray axTextRange = (jintArray)(*env)->CallStaticObjectMethod(env, sjc_CAccessibleText,
 416                 jm_getRangeForLine, fAccessible, fComponent, [line intValue]);
 417     CHECK_EXCEPTION();
 418     if (axTextRange == NULL) return nil;
 419 
 420     return javaIntArrayToNSRangeValue(env,axTextRange);
 421 }
 422 
 423 //
 424 // Usage of accessibilityStringForRangeAttributeForParameter:
 425 // ---
 426 // called by VoiceOver when interacting with text via ctrl-option-shift-downArrow.
 427 // VO needs to know the particular string its currently dealing with so it can
 428 // speak the string
 429 //
 430 - (NSString *)accessibilityStringForRangeAttributeForParameter:(id)parameter
 431 {
 432 #ifdef JAVA_AX_DEBUG_PARMS
 433     if (!([parameter isKindOfClass:[NSValue class]] && strcmp([(NSValue *)parameter objCType], @encode(NSRange)) == 0)) {
 434         JavaAccessibilityRaiseIllegalParameterTypeException(__FUNCTION__, self, NSAccessibilityBoundsForRangeParameterizedAttribute, parameter);
 435         return nil;
 436     }
 437 #endif
 438 
 439     NSRange range = [(NSValue *)parameter rangeValue];
 440 
 441     JNIEnv *env = [ThreadUtilities getJNIEnv];
 442     GET_CACCESSIBLETEXT_CLASS_RETURN(nil);
 443     DECLARE_STATIC_METHOD_RETURN(jm_getStringForRange, sjc_CAccessibleText, "getStringForRange",
 444                  "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)Ljava/lang/String;", nil);
 445     jstring jstringForRange = (jstring)(*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getStringForRange,
 446                             fAccessible, fComponent, range.location, range.length);
 447     CHECK_EXCEPTION();
 448     if (jstringForRange == NULL) return @"";
 449     NSString* str = JavaStringToNSString(env, jstringForRange);
 450     (*env)->DeleteLocalRef(env, jstringForRange);
 451     return str;
 452 }
 453 
 454 //
 455 // Usage of accessibilityRangeForPositionAttributeForParameter:
 456 // ---
 457 // cmcnote: I'm not sure when this is called / how it's used. Investigate.
 458 // probably could be used in a special text-only accessibilityHitTest to
 459 // find the index of the string under the mouse?
 460 //
 461 - (NSValue *)accessibilityRangeForPositionAttributeForParameter:(id)parameter
 462 {
 463 #ifdef JAVA_AX_DEBUG_PARMS
 464     if (!([parameter isKindOfClass:[NSValue class]] && strcmp([(NSValue *)parameter objCType], @encode(NSPoint)) == 0)) {
 465         JavaAccessibilityRaiseIllegalParameterTypeException(__FUNCTION__, self, NSAccessibilityRangeForPositionParameterizedAttribute, parameter);
 466         return nil;
 467     }
 468 #endif
 469 
 470     NSPoint point = [(NSValue *)parameter pointValue]; // point is in screen coords
 471     point.y = [[[[self view] window] screen] frame].size.height - point.y; // flip into java screen coords (0 is at upper-left corner of screen)
 472 
 473     JNIEnv *env = [ThreadUtilities getJNIEnv];
 474     GET_CACCESSIBLETEXT_CLASS_RETURN(nil);
 475     DECLARE_STATIC_METHOD_RETURN(jm_getCharacterIndexAtPosition, sjc_CAccessibleText, "getCharacterIndexAtPosition",
 476                            "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)I", nil);
 477     jint charIndex = (*env)->CallStaticIntMethod(env, sjc_CAccessibleText, jm_getCharacterIndexAtPosition,
 478                             fAccessible, fComponent, point.x, point.y);
 479     CHECK_EXCEPTION();
 480     if (charIndex == -1) return nil;
 481 
 482     // AccessibleText.getIndexAtPoint returns -1 for an invalid point
 483     NSRange range = NSMakeRange(charIndex, 1); //range's length is 1 - one-character range
 484     return [NSValue valueWithRange:range];
 485 }
 486 
 487 //
 488 // Usage of accessibilityRangeForIndexAttributeForParameter:
 489 // ---
 490 // cmcnote: I'm not sure when this is called / how it's used. Investigate.
 491 // AppKit version calls: [string rangeOfComposedCharacterSequenceAtIndex:index]
 492 // We call: CAccessibility.getRangeForIndex, which calls AccessibleText.getAtIndex(AccessibleText.WORD, index)
 493 // to determine the word closest to the given index. Then we find the length/location of this string.
 494 //
 495 - (NSValue *)accessibilityRangeForIndexAttributeForParameter:(id)parameter
 496 {
 497 #ifdef JAVA_AX_DEBUG_PARMS
 498     if (![parameter isKindOfClass:[NSNumber class]]) {
 499         JavaAccessibilityRaiseIllegalParameterTypeException(__FUNCTION__, self, NSAccessibilityRangeForIndexParameterizedAttribute, parameter);
 500         return nil;
 501     }
 502 #endif
 503 
 504     NSUInteger index = [(NSNumber *)parameter unsignedIntegerValue];
 505 
 506     JNIEnv *env = [ThreadUtilities getJNIEnv];
 507     GET_CACCESSIBLETEXT_CLASS_RETURN(nil);
 508     DECLARE_STATIC_METHOD_RETURN(jm_getRangeForIndex, sjc_CAccessibleText, "getRangeForIndex",
 509                     "(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)[I", nil);
 510     jintArray axTextRange = (jintArray)(*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getRangeForIndex,
 511                               fAccessible, fComponent, index);
 512     CHECK_EXCEPTION();
 513     if (axTextRange == NULL) return nil;
 514 
 515     return javaIntArrayToNSRangeValue(env, axTextRange);
 516 }
 517 
 518 /*
 519  * - (NSDictionary *)getActions:(JNIEnv *)env { ... }
 520  *
 521  * In the future, possibly add support: Editable text has AXShowMenu.
 522  * Textfields have AXConfirm.
 523  *
 524  * Note: JLabels (static text) in JLists have a press/click selection action
 525  *   which is currently handled in superclass JavaComponentAccessibility.
 526  *   If function is added here be sure to use [super getActions:env] for JLabels.
 527  */
 528 
 529 @end
--- EOF ---