| /* |
| * (c) Copyright IBM Corp., 2000, 2001 |
| * All Rights Reserved. |
| */ |
| |
| /** |
| * Callback implementation. |
| */ |
| #include "swt.h" |
| #include "callback.h" |
| |
| /* --------------- callback globals ----------------- */ |
| |
| SWT_CALLBACKINFO dllCallbackInfo[MAX_CALLBACKS]; |
| jfieldID objectID; |
| jfieldID addressID; |
| jfieldID methodID; |
| jfieldID signatureID; |
| jfieldID isStaticID; |
| jfieldID argCountID; |
| jfieldID isArrayBasedID; |
| int callbackCached; |
| int initialized; |
| int counter; |
| int CallbacksEnabled = 1; |
| |
| /* --------------- callback functions --------------- */ |
| |
| /* Function name from index and number of arguments */ |
| #define FN(index, args) fn##index##_##args |
| |
| /** |
| * Functions templates |
| * |
| * NOTE: If the maximum number of arguments changes (MAX_ARGS), the number |
| * of function templates has to change accordinglly. |
| */ |
| |
| /* Function template with no arguments */ |
| #define FN_0(index) RETURN_TYPE FN(index, 0)() { return RETURN_CAST callback(index); } |
| |
| /* Function template with 1 argument */ |
| #define FN_1(index) RETURN_TYPE FN(index, 1)(int p1) { return RETURN_CAST callback(index, p1); } |
| |
| /* Function template with 2 arguments */ |
| #define FN_2(index) RETURN_TYPE FN(index, 2)(int p1, int p2) { return RETURN_CAST callback(index, p1, p2); } |
| |
| /* Function template with 3 arguments */ |
| #define FN_3(index) RETURN_TYPE FN(index, 3)(int p1, int p2, int p3) { return RETURN_CAST callback(index, p1, p2, p3); } |
| |
| /* Function template with 4 arguments */ |
| #define FN_4(index) RETURN_TYPE FN(index, 4)(int p1, int p2, int p3, int p4) { return RETURN_CAST callback(index, p1, p2, p3, p4); } |
| |
| /* Function template with 5 arguments */ |
| #define FN_5(index) RETURN_TYPE FN(index, 5)(int p1, int p2, int p3, int p4, int p5) { return RETURN_CAST callback(index, p1, p2, p3, p4, p5); } |
| |
| /* Function template with 6 arguments */ |
| #define FN_6(index) RETURN_TYPE FN(index, 6)(int p1, int p2, int p3, int p4, int p5, int p6) { return RETURN_CAST callback(index, p1, p2, p3, p4, p5, p6); } |
| |
| /* Function template with 7 arguments */ |
| #define FN_7(index) RETURN_TYPE FN(index, 7)(int p1, int p2, int p3, int p4, int p5, int p6, int p7) { return RETURN_CAST callback(index, p1, p2, p3, p4, p5, p6, p7); } |
| |
| /* Function template with 8 arguments */ |
| #define FN_8(index) RETURN_TYPE FN(index, 8)(int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8) { return RETURN_CAST callback(index, p1, p2, p3, p4, p5, p6, p7, p8); } |
| |
| /* Function template with 9 arguments */ |
| #define FN_9(index) RETURN_TYPE FN(index, 9)(int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, int p9) { return RETURN_CAST callback(index, p1, p2, p3, p4, p5, p6, p7, p8, p9); } |
| |
| /* Function template with 10 arguments */ |
| #define FN_10(index) RETURN_TYPE FN(index, 10) (int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, int p9, int p10) { return RETURN_CAST callback(index, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } |
| |
| /* Function template with 11 arguments */ |
| #define FN_11(index) RETURN_TYPE FN(index, 11) (int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, int p9, int p10, int p11) { return RETURN_CAST callback(index, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); } |
| |
| /* Function template with 12 arguments */ |
| #define FN_12(index) RETURN_TYPE FN(index, 12) (int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, int p9, int p10, int p11, int p12) { return RETURN_CAST callback(index, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); } |
| |
| /** |
| * Define all functions with the specified number of arguments. |
| * |
| * NOTE: If the maximum number of callbacks changes (MAX_CALLBACKS), |
| * this macro has to be updated. |
| */ |
| #define FN_BLOCK(args) FN_##args##(0) FN_##args##(1) FN_##args##(2) FN_##args##(3) FN_##args##(4) FN_##args##(5) FN_##args##(6) FN_##args##(7) FN_##args##(8) FN_##args##(9) FN_##args##(10) FN_##args##(11) FN_##args##(12) FN_##args##(13) FN_##args##(14) FN_##args##(15) FN_##args##(16) FN_##args##(17) FN_##args##(18) FN_##args##(19) FN_##args##(20) FN_##args##(21) FN_##args##(22) FN_##args##(23) FN_##args##(24) FN_##args##(25) FN_##args##(26) FN_##args##(27) FN_##args##(28) FN_##args##(29) FN_##args##(30) FN_##args##(31) FN_##args##(32) FN_##args##(33) FN_##args##(34) FN_##args##(35) FN_##args##(36) FN_##args##(37) FN_##args##(38) FN_##args##(39) FN_##args##(40) FN_##args##(41) FN_##args##(42) FN_##args##(43) FN_##args##(44) FN_##args##(45) FN_##args##(46) FN_##args##(47) FN_##args##(48) FN_##args##(49) FN_##args##(50) FN_##args##(51) FN_##args##(52) FN_##args##(53) FN_##args##(54) FN_##args##(55) FN_##args##(56) FN_##args##(57) FN_##args##(58) FN_##args##(59) FN_##args##(60) FN_##args##(61) FN_##args##(62) FN_##args##(63) FN_##args##(64) FN_##args##(65) FN_##args##(66) FN_##args##(67) FN_##args##(68) FN_##args##(69) FN_##args##(70) FN_##args##(71) FN_##args##(72) FN_##args##(73) FN_##args##(74) FN_##args##(75) FN_##args##(76) FN_##args##(77) FN_##args##(78) FN_##args##(79) FN_##args##(80) FN_##args##(81) FN_##args##(82) FN_##args##(83) FN_##args##(84) FN_##args##(85) FN_##args##(86) FN_##args##(87) FN_##args##(88) FN_##args##(89) FN_##args##(90) FN_##args##(91) FN_##args##(92) FN_##args##(93) FN_##args##(94) FN_##args##(95) FN_##args##(96) FN_##args##(97) FN_##args##(98) FN_##args##(99) FN_##args##(100) FN_##args##(101) FN_##args##(102) FN_##args##(103) FN_##args##(104) FN_##args##(105) FN_##args##(106) FN_##args##(107) FN_##args##(108) FN_##args##(109) FN_##args##(110) FN_##args##(111) FN_##args##(112) FN_##args##(113) FN_##args##(114) FN_##args##(115) FN_##args##(116) FN_##args##(117) FN_##args##(118) FN_##args##(119) FN_##args##(120) FN_##args##(121) FN_##args##(122) FN_##args##(123) FN_##args##(124) FN_##args##(125) FN_##args##(126) FN_##args##(127) |
| |
| /** |
| * Define all callback functions. |
| * |
| * NOTE: If the maximum number of arguments changes (MAX_ARGS), the following |
| * has to change accordinglly. |
| */ |
| FN_BLOCK(0) |
| FN_BLOCK(1) |
| FN_BLOCK(2) |
| FN_BLOCK(3) |
| FN_BLOCK(4) |
| FN_BLOCK(5) |
| FN_BLOCK(6) |
| FN_BLOCK(7) |
| FN_BLOCK(8) |
| FN_BLOCK(9) |
| FN_BLOCK(10) |
| FN_BLOCK(11) |
| FN_BLOCK(12) |
| |
| /** |
| * Initialize the function pointers for the callback routines. |
| * |
| * NOTE: If MAX_ARGS or MAX_CALLBACKS changes, the following has to be updated. |
| */ |
| #define FN_A_BLOCK(args) {(int *)FN(0, args),(int *)FN(1, args),(int *)FN(2, args),(int *)FN(3, args),(int *)FN(4, args),(int *)FN(5, args),(int *)FN(6, args),(int *)FN(7, args),(int *)FN(8, args),(int *)FN(9, args),(int *)FN(10, args),(int *)FN(11, args),(int *)FN(12, args),(int *)FN(13, args),(int *)FN(14, args),(int *)FN(15, args),(int *)FN(16, args),(int *)FN(17, args),(int *)FN(18, args),(int *)FN(19, args),(int *)FN(20, args),(int *)FN(21, args),(int *)FN(22, args),(int *)FN(23, args),(int *)FN(24, args),(int *)FN(25, args),(int *)FN(26, args),(int *)FN(27, args),(int *)FN(28, args),(int *)FN(29, args),(int *)FN(30, args),(int *)FN(31, args),(int *)FN(32, args),(int *)FN(33, args),(int *)FN(34, args),(int *)FN(35, args),(int *)FN(36, args),(int *)FN(37, args),(int *)FN(38, args),(int *)FN(39, args),(int *)FN(40, args),(int *)FN(41, args),(int *)FN(42, args),(int *)FN(43, args),(int *)FN(44, args),(int *)FN(45, args),(int *)FN(46, args),(int *)FN(47, args),(int *)FN(48, args),(int *)FN(49, args),(int *)FN(50, args),(int *)FN(51, args),(int *)FN(52, args),(int *)FN(53, args),(int *)FN(54, args),(int *)FN(55, args),(int *)FN(56, args),(int *)FN(57, args),(int *)FN(58, args),(int *)FN(59, args),(int *)FN(60, args),(int *)FN(61, args),(int *)FN(62, args),(int *)FN(63, args),(int *)FN(64, args),(int *)FN(65, args),(int *)FN(66, args),(int *)FN(67, args),(int *)FN(68, args),(int *)FN(69, args),(int *)FN(70, args),(int *)FN(71, args),(int *)FN(72, args),(int *)FN(73, args),(int *)FN(74, args),(int *)FN(75, args),(int *)FN(76, args),(int *)FN(77, args),(int *)FN(78, args),(int *)FN(79, args),(int *)FN(80, args),(int *)FN(81, args),(int *)FN(82, args),(int *)FN(83, args),(int *)FN(84, args),(int *)FN(85, args),(int *)FN(86, args),(int *)FN(87, args),(int *)FN(88, args),(int *)FN(89, args),(int *)FN(90, args),(int *)FN(91, args),(int *)FN(92, args),(int *)FN(93, args),(int *)FN(94, args),(int *)FN(95, args),(int *)FN(96, args),(int *)FN(97, args),(int *)FN(98, args),(int *)FN(99, args),(int *)FN(100, args),(int *)FN(101, args),(int *)FN(102, args),(int *)FN(103, args),(int *)FN(104, args),(int *)FN(105, args),(int *)FN(106, args),(int *)FN(107, args),(int *)FN(108, args),(int *)FN(109, args),(int *)FN(110, args),(int *)FN(111, args),(int *)FN(112, args),(int *)FN(113, args),(int *)FN(114, args),(int *)FN(115, args),(int *)FN(116, args),(int *)FN(117, args),(int *)FN(118, args),(int *)FN(119, args),(int *)FN(120, args),(int *)FN(121, args),(int *)FN(122, args),(int *)FN(123, args),(int *)FN(124, args),(int *)FN(125, args),(int *)FN(126, args),(int *)FN(127, args)}, |
| |
| int * fnx_array[MAX_ARGS+1][MAX_CALLBACKS] = { |
| FN_A_BLOCK(0) |
| FN_A_BLOCK(1) |
| FN_A_BLOCK(2) |
| FN_A_BLOCK(3) |
| FN_A_BLOCK(4) |
| FN_A_BLOCK(5) |
| FN_A_BLOCK(6) |
| FN_A_BLOCK(7) |
| FN_A_BLOCK(8) |
| FN_A_BLOCK(9) |
| FN_A_BLOCK(10) |
| FN_A_BLOCK(11) |
| FN_A_BLOCK(12) |
| }; |
| |
| |
| /* --------------- callback class calls --------------- */ |
| |
| /* |
| * Class: org_eclipse_swt_internal_Callback |
| * Method: bind |
| * Signature: (Lorg/eclipse/swt/internal/Callback;)I |
| */ |
| JNIEXPORT jint JNICALL Java_org_eclipse_swt_internal_Callback_bind |
| (JNIEnv *env, jclass that, jobject lpCallback) |
| /* |
| ** The methodID is computed once during the bind and will be valid |
| ** unless the Callback class is reloaded. |
| */ |
| { |
| DECL_GLOB(pGlob) |
| int i; |
| jclass javaClass; |
| jobject javaObject, javaMethod, javaSignature; |
| jboolean isStatic, isArrayBased; |
| jint argCount; |
| jmethodID mid; |
| const char *methodString, *sigString; |
| |
| javaClass = that; |
| if (!PGLOB(callbackCached)) { |
| PGLOB(objectID) = (*env)->GetFieldID(env,javaClass,"object","Ljava/lang/Object;"); |
| PGLOB(addressID) = (*env)->GetFieldID(env,javaClass,"address","I"); |
| PGLOB(methodID) = (*env)->GetFieldID(env,javaClass,"method","Ljava/lang/String;"); |
| PGLOB(signatureID) = (*env)->GetFieldID(env,javaClass,"signature","Ljava/lang/String;"); |
| PGLOB(isStaticID) = (*env)->GetFieldID(env,javaClass,"isStatic","Z"); |
| PGLOB(argCountID) = (*env)->GetFieldID(env,javaClass,"argCount","I"); |
| PGLOB(isArrayBasedID) = (*env)->GetFieldID(env,javaClass,"isArrayBased","Z"); |
| PGLOB(callbackCached) = 1; |
| } |
| javaObject = (*env)->GetObjectField(env,lpCallback,PGLOB(objectID)); |
| javaMethod = (*env)->GetObjectField(env,lpCallback,PGLOB(methodID)); |
| javaSignature = (*env)->GetObjectField(env,lpCallback,PGLOB(signatureID)); |
| isStatic = (*env)->GetBooleanField(env,lpCallback,PGLOB(isStaticID)); |
| argCount = (*env)->GetIntField(env,lpCallback,PGLOB(argCountID)); |
| isArrayBased = (*env)->GetBooleanField(env,lpCallback,PGLOB(isArrayBasedID)); |
| methodString = (const char *) (*env)->GetStringUTFChars(env, javaMethod, NULL); |
| sigString = (const char *) (*env)->GetStringUTFChars(env, javaSignature, NULL); |
| if (isStatic) { |
| mid = (*env)->GetStaticMethodID(env, javaObject, methodString, sigString); |
| } else { |
| javaClass = (*env)->GetObjectClass(env,javaObject); |
| /* note that this call is reusing javaClass */ |
| mid = (*env)->GetMethodID(env, javaClass, methodString, sigString); |
| } |
| (*env)->ReleaseStringUTFChars(env, javaMethod, methodString); |
| (*env)->ReleaseStringUTFChars(env, javaSignature, sigString); |
| if (PGLOB(initialized)==0) { |
| memset((void *)&PGLOB(dllCallbackInfo), 0, sizeof(PGLOB(dllCallbackInfo))); |
| PGLOB(initialized) = 1; |
| } |
| for (i=0; i<MAX_CALLBACKS; i++) { |
| if (!PGLOB(dllCallbackInfo)[i].callin) { |
| PGLOB(dllCallbackInfo)[i].callin = (*env)->NewGlobalRef(env,lpCallback); |
| PGLOB(dllCallbackInfo)[i].env = env; |
| PGLOB(dllCallbackInfo)[i].methodID = mid; |
| |
| return (jint) fnx_array[argCount][i]; |
| } |
| } |
| fprintf(stderr, "bind fail, no free callback slot ******* \n"); |
| return 0; /* this means there was no free callback slot */ |
| } |
| |
| /* |
| * Class: org_eclipse_swt_internal_Callback |
| * Method: unbind |
| * Signature: (Lorg/eclipse/swt/internal/Callback;)V |
| */ |
| JNIEXPORT void JNICALL Java_org_eclipse_swt_internal_Callback_unbind |
| (JNIEnv *env, jclass that, jobject lpCallback) |
| { |
| DECL_GLOB(pGlob) |
| int i, address, argCount; |
| if (!PGLOB(callbackCached)) return; |
| |
| address = (*env)->GetIntField(env,lpCallback,PGLOB(addressID)); |
| argCount = (*env)->GetIntField(env,lpCallback,PGLOB(argCountID)); |
| |
| for (i=0; i<MAX_CALLBACKS; i++) { |
| if ((int)fnx_array[argCount][i] == address) { |
| (*env)->DeleteGlobalRef(env, PGLOB(dllCallbackInfo)[i].callin); |
| PGLOB(dllCallbackInfo)[i].callin = 0; |
| PGLOB(dllCallbackInfo)[i].env = 0; |
| PGLOB(dllCallbackInfo)[i].methodID = 0; |
| } |
| } |
| } |
| |
| /* |
| * Class: org_eclipse_swt_internal_Callback |
| * Method: setEnabled |
| * Signature: (Z)V |
| */ |
| JNIEXPORT void JNICALL Java_org_eclipse_swt_internal_Callback_setEnabled |
| (JNIEnv *env, jclass that, jboolean enable) |
| { |
| CallbacksEnabled = enable; |
| } |
| |
| /* |
| * Class: org_eclipse_swt_internal_Callback |
| * Method: getEnabled |
| * Signature: ()Z |
| */ |
| JNIEXPORT jboolean JNICALL Java_org_eclipse_swt_internal_Callback_getEnabled |
| (JNIEnv *env, jclass that, jboolean enable) |
| { |
| return (jboolean)CallbacksEnabled; |
| } |
| |
| int callback(int index, ...) |
| { |
| if (!CallbacksEnabled) { |
| return 0; |
| } else { |
| |
| DECL_GLOB(pGlob) |
| jobject callback = PGLOB(dllCallbackInfo)[index].callin; |
| JNIEnv *env = PGLOB(dllCallbackInfo)[index].env; |
| jmethodID mid = PGLOB(dllCallbackInfo)[index].methodID; |
| jobject javaObject; |
| jboolean isStatic, isArrayBased; |
| |
| int result = 0; |
| va_list vl; |
| |
| #ifdef DEBUG_CALL_PRINTS |
| fprintf(stderr, "* callback starting %d\n", PGLOB(counter)++); |
| #endif |
| |
| /* An exception has already occurred. Allow the stack to unwind so that |
| the exception will be thrown in Java */ |
| if ((*env)->ExceptionOccurred(env)) { |
| |
| #ifdef DEBUG_CALL_PRINTS |
| fprintf(stderr, "************ java exception occurred\n"); |
| #endif |
| |
| return 0; |
| } |
| |
| javaObject = (*env)->GetObjectField(env,callback,PGLOB(objectID)); |
| isStatic = ((*env)->GetBooleanField(env,callback,PGLOB(isStaticID))) != 0; |
| isArrayBased = ((*env)->GetBooleanField(env,callback,PGLOB(isArrayBasedID))) != 0; |
| |
| va_start(vl, index); |
| if (isArrayBased) { |
| int i; |
| jint argCount = (*env)->GetIntField(env,callback,PGLOB(argCountID)); |
| jintArray javaArray = (*env)->NewIntArray(env,argCount); |
| jint *elements = (*env)->GetIntArrayElements(env,javaArray,NULL); |
| for (i=0; i<argCount; i++) { |
| elements[i] = va_arg(vl, jint); |
| } |
| (*env)->ReleaseIntArrayElements(env, javaArray, elements, 0); |
| if (isStatic) { |
| result = (*env)->CallStaticIntMethod(env, javaObject, mid, javaArray); |
| } else { |
| result = (*env)->CallIntMethod(env, javaObject, mid, javaArray); |
| } |
| (*env)->DeleteLocalRef(env, javaArray); |
| } else { |
| if (isStatic) { |
| result = (*env)->CallStaticIntMethodV(env, javaObject, mid, vl); |
| } else { |
| result = (*env)->CallIntMethodV(env, javaObject, mid, vl); |
| } |
| } |
| va_end(vl); |
| /* This call may be called many times before we return to Java. |
| We have to explicitly delete local references to avoid GP's |
| in the JDK and IBM Hursley VM. |
| */ |
| (*env)->DeleteLocalRef(env,javaObject); |
| |
| #ifdef DEBUG_CALL_PRINTS |
| fprintf(stderr, "* callback exiting %d\n", --PGLOB(counter)); |
| #endif |
| return result; |
| } |
| } |
| |
| /* |
| * Class: org_eclipse_swt_internal_Callback |
| * Method: reset |
| * Signature: ()V |
| */ |
| JNIEXPORT void JNICALL Java_org_eclipse_swt_internal_Callback_reset |
| (JNIEnv *env, jclass that) |
| { |
| DECL_GLOB(pGlob) |
| memset((void *)&PGLOB(dllCallbackInfo), 0, sizeof(PGLOB(dllCallbackInfo))); |
| } |
| |
| /* |
| * Class: org_eclipse_swt_internal_Callback |
| * Method: getPlatform |
| * Signature: ()Ljava/lang/String; |
| */ |
| JNIEXPORT jstring JNICALL Java_org_eclipse_swt_internal_Callback_getPlatform |
| (JNIEnv *env, jclass that) |
| { |
| return (*env)->NewStringUTF(env, PLATFORM); |
| } |
| |
| /* ------------- callback class calls end --------------- */ |