/*-------------------------------------------------------------------------
|
|
| rxtx is a native interface to serial ports in java.
|
|
| Copyright 2002-2004 Michal Hobot MichalHobot@netscape.net
|
|
| Copyright 1997-2004 by Trent Jarvi taj@parcelfarce.linux.theplanet.co.uk
|
|
|
|
|
| This library is free software; you can redistribute it and/or
|
|
| modify it under the terms of the GNU Library General Public
|
|
| License as published by the Free Software Foundation; either
|
|
| version 2 of the License, or (at your option) any later version.
|
|
|
|
|
| This library is distributed in the hope that it will be useful,
|
|
| but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
| Library General Public License for more details.
|
|
|
|
|
| You should have received a copy of the GNU Library General Public
|
|
| License along with this library; if not, write to the Free
|
|
| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
--------------------------------------------------------------------------*/
|
|
#include "StdAfx.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "rxtxHelpers.h"
|
|
|
|
/*----------------------------------------------------------
|
|
get_java_int_var
|
|
|
|
accept: env (keyhole to java)
|
|
jobj (java RXTXPort object)
|
|
return: the jint field from the java object, casted to long
|
|
exceptions: none
|
|
comments:
|
|
----------------------------------------------------------*/
|
|
long get_java_int_var( JNIEnv *env, jobject jobj, char *id)
|
|
{
|
|
long result = 0;
|
|
jclass jclazz = env->GetObjectClass(jobj);
|
|
jfieldID jfd = env->GetFieldID(jclazz, id, "I");
|
|
|
|
if( !jfd ) {
|
|
IF_DEBUG
|
|
(
|
|
env->ExceptionDescribe();
|
|
)
|
|
env->ExceptionClear();
|
|
env->DeleteLocalRef(jclazz);
|
|
return result;
|
|
}
|
|
result = (long)( env->GetIntField(jobj, jfd) );
|
|
env->DeleteLocalRef(jclazz);
|
|
return result;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------
|
|
get_java_boolean_var
|
|
|
|
accept: env (keyhole to java)
|
|
jobj (java RXTXPort object)
|
|
return: the jboolean field from the java object, converted to bool
|
|
exceptions: none
|
|
comments:
|
|
----------------------------------------------------------*/
|
|
bool get_java_boolean_var( JNIEnv *env, jobject jobj, char *id)
|
|
{
|
|
bool result = FALSE;
|
|
jclass jclazz = env->GetObjectClass(jobj);
|
|
jfieldID jfd = env->GetFieldID(jclazz, id, "Z");
|
|
|
|
if( !jfd ) {
|
|
IF_DEBUG
|
|
(
|
|
env->ExceptionDescribe();
|
|
)
|
|
env->ExceptionClear();
|
|
env->DeleteLocalRef(jclazz);
|
|
return result;
|
|
}
|
|
result = (env->GetBooleanField(jobj, jfd)) != JNI_FALSE;
|
|
env->DeleteLocalRef(jclazz);
|
|
return result;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------
|
|
get_java_boolean_var2
|
|
|
|
accept: env (keyhole to java)
|
|
jobj (java RXTXPort object)
|
|
jclazz (class of jobj)
|
|
return: the jboolean field from the java object, converted to bool
|
|
exceptions: none
|
|
comments: can be faster for fetching many variables one by one
|
|
----------------------------------------------------------*/
|
|
bool get_java_boolean_var2(JNIEnv *env, jobject jobj, jclass jclazz, char *id)
|
|
{
|
|
bool result = FALSE;
|
|
jfieldID jfd = env->GetFieldID(jclazz, id, "Z");
|
|
|
|
if( !jfd ) {
|
|
IF_DEBUG
|
|
(
|
|
env->ExceptionDescribe();
|
|
)
|
|
env->ExceptionClear();
|
|
env->DeleteLocalRef(jclazz);
|
|
return result;
|
|
}
|
|
result = (env->GetBooleanField(jobj, jfd)) != JNI_FALSE;
|
|
return result;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------
|
|
throw_java_exception
|
|
|
|
accept: env (keyhole to java)
|
|
*exc (exception class name)
|
|
*foo (function name)
|
|
*msg (error message)
|
|
perform: Throw a new java exception
|
|
return: none
|
|
exceptions: haha!
|
|
comments:
|
|
----------------------------------------------------------*/
|
|
void throw_java_exception(JNIEnv *env, const char *exc, const char *foo, const char *msg)
|
|
{
|
|
char buf[250];
|
|
jclass clazz = env->FindClass(exc);
|
|
if( !clazz ) {
|
|
IF_DEBUG
|
|
(
|
|
env->ExceptionDescribe();
|
|
)
|
|
env->ExceptionClear();
|
|
return;
|
|
}
|
|
_snprintf(buf, 60, "%s: %s in %s", exc, msg, foo);
|
|
env->ThrowNew(clazz, buf);
|
|
env->DeleteLocalRef(clazz);
|
|
}
|
|
|
|
// Unicode version:
|
|
void throw_java_exceptionW(JNIEnv *env, const char *exc, const wchar_t *foo, const wchar_t *msg)
|
|
{
|
|
wchar_t buf[500];
|
|
char *lpcBuf;
|
|
int msgLen;
|
|
|
|
jclass clazz = env->FindClass(exc);
|
|
if( !clazz ) {
|
|
env->ExceptionDescribe();
|
|
env->ExceptionClear();
|
|
return;
|
|
}
|
|
msgLen = swprintf(buf, L"%S: %s in %s", exc, msg, foo);
|
|
|
|
IF_DEBUG
|
|
(
|
|
printj(env, L"!!!!! Throwing %s\n", buf);
|
|
//MessageBox(NULL, buf, L"throw_java_exceptionW"), MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
|
|
)
|
|
|
|
lpcBuf = (char *)malloc((msgLen+1)*sizeof(wchar_t)); // Will be ok - mbs not longer than wcs
|
|
lpcBuf[msgLen] = '\0';
|
|
wcstombs(lpcBuf, buf, msgLen);
|
|
env->ThrowNew(clazz, lpcBuf);
|
|
free(lpcBuf);
|
|
env->DeleteLocalRef(clazz);
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------
|
|
get_fd
|
|
|
|
accept: env (keyhole to java)
|
|
jobj (java RXTXPort object)
|
|
return: "fd" field from the java object, as HANDLE
|
|
exceptions: none
|
|
comments:
|
|
----------------------------------------------------------*/
|
|
HANDLE get_fd(JNIEnv *env, jobject jobj)
|
|
{
|
|
HANDLE fd = (HANDLE)get_java_int_var(env, jobj, "fd");
|
|
return fd!=0?fd:INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------
|
|
get_eis
|
|
|
|
accept: env (keyhole to java)
|
|
jobj (java RXTXPort object)
|
|
return: "eis" field from the java object, as (EventInfoStruct *)
|
|
exceptions: none
|
|
comments:
|
|
----------------------------------------------------------*/
|
|
EventInfoStruct *get_eis(JNIEnv *env, jobject jobj)
|
|
{
|
|
return (EventInfoStruct *)get_java_int_var(env, jobj, "eis");
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------
|
|
printj
|
|
|
|
accept: like vwprintf()
|
|
return: number of jchars written or -1
|
|
exceptions: none
|
|
comments: prints data using System.out.print()
|
|
----------------------------------------------------------*/
|
|
int printj(JNIEnv *env, wchar_t *fmt, ...)
|
|
{
|
|
wchar_t buf[1024];
|
|
int retval;
|
|
jstring jsBuf;
|
|
jclass clsSystem, clsOut;
|
|
jfieldID jfid;
|
|
jobject objOut;
|
|
jmethodID midPrint;
|
|
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
retval = _vsnwprintf(buf, 1024, fmt, ap);
|
|
va_end(ap);
|
|
buf[1023] = '\0';
|
|
|
|
if((clsSystem = env->FindClass("java/lang/System")) == NULL)
|
|
{
|
|
IF_DEBUG
|
|
(
|
|
env->ExceptionDescribe();
|
|
)
|
|
env->ExceptionClear();
|
|
return -1;
|
|
}
|
|
|
|
if((jfid = env->GetStaticFieldID(clsSystem, "out", "Ljava/io/PrintStream;")) == NULL)
|
|
{
|
|
IF_DEBUG
|
|
(
|
|
env->ExceptionDescribe();
|
|
)
|
|
env->ExceptionClear();
|
|
env->DeleteLocalRef(clsSystem);
|
|
return -1;
|
|
}
|
|
|
|
objOut = env->GetStaticObjectField(clsSystem, jfid);
|
|
clsOut = env->GetObjectClass(objOut);
|
|
|
|
if((midPrint = env->GetMethodID(clsOut, "print", "(Ljava/lang/String;)V")) == NULL)
|
|
{
|
|
IF_DEBUG
|
|
(
|
|
env->ExceptionDescribe();
|
|
)
|
|
env->ExceptionClear();
|
|
env->DeleteLocalRef(clsOut);
|
|
env->DeleteLocalRef(clsSystem);
|
|
return -1;
|
|
}
|
|
|
|
jsBuf = env->NewString(buf, wcslen(buf));
|
|
|
|
env->CallVoidMethod(objOut, midPrint, jsBuf);
|
|
|
|
env->DeleteLocalRef(jsBuf);
|
|
env->DeleteLocalRef(clsOut);
|
|
env->DeleteLocalRef(clsSystem);
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
|
|
/*----------------------------------------------------------
|
|
CommEventThread
|
|
|
|
accept: communication structure ptr
|
|
return: 0 - normal finish, other - error
|
|
exceptions: none
|
|
comments: runs as separate thread
|
|
----------------------------------------------------------*/
|
|
DWORD __stdcall CommEventThread(LPVOID lpEventInfo)
|
|
{
|
|
DWORD dwErr;
|
|
EventInfoStruct *EventInfo = (EventInfoStruct *)lpEventInfo;
|
|
HANDLE hPort = EventInfo->fd;
|
|
|
|
// Specify a set of events to be monitored for the port.
|
|
if(!SetCommMask(hPort, EventInfo->ef))
|
|
{
|
|
dwErr = GetLastError();
|
|
IF_DEBUG
|
|
(
|
|
LPCWSTR lpMsgBuf;
|
|
CreateErrorMsg(dwErr, lpMsgBuf);
|
|
MessageBoxW(NULL, lpMsgBuf, L"!!! CommEventThread - SetCommMask() error", MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
|
|
ReleaseErrorMsg(lpMsgBuf);
|
|
)
|
|
return dwErr;
|
|
}
|
|
|
|
// Thread is ready to work
|
|
EventInfo->eventThreadReady = true;
|
|
|
|
do
|
|
{
|
|
// Wait for an event to occur for the port.
|
|
if(!WaitCommEvent(hPort, &(EventInfo->event), NULL))
|
|
{
|
|
dwErr = GetLastError();
|
|
if(dwErr == ERROR_INVALID_PARAMETER)
|
|
{ // Mask is empty - let's wait for a moment and continue
|
|
MessageBeep(MB_ICONQUESTION);
|
|
Sleep(200);
|
|
continue;
|
|
}
|
|
|
|
if(dwErr == ERROR_INVALID_HANDLE)
|
|
{ // Port was closed
|
|
//MessageBox(NULL, L"--- CommEventThread - Port closed", L"ERROR_INVALID_HANDLE", MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
|
|
free(EventInfo);
|
|
return 0;
|
|
}
|
|
|
|
IF_DEBUG
|
|
(
|
|
LPCWSTR lpMsgBuf;
|
|
WCHAR MsgBuf2[1000];
|
|
CreateErrorMsg(dwErr, lpMsgBuf);
|
|
wsprintfW(MsgBuf2, L"%ld %s, CommMask==%ld", dwErr, lpMsgBuf, EventInfo->ef);
|
|
MessageBoxW(NULL, MsgBuf2, L"!!! CommEventThread - WaitCommEvent() error", MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
|
|
ReleaseErrorMsg(lpMsgBuf);
|
|
)
|
|
return dwErr;
|
|
}
|
|
|
|
IF_DEBUG
|
|
(
|
|
MessageBeep(MB_ICONEXCLAMATION);
|
|
//MessageBoxW(NULL, L"--- RXTXPort.CommEventThread() - CommEvent", L"CommEventThread", MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
|
|
)
|
|
|
|
// Re-specify the set of events to be monitored for the port.
|
|
if(!SetCommMask(hPort, EventInfo->ef))
|
|
{
|
|
dwErr = GetLastError();
|
|
IF_DEBUG
|
|
(
|
|
LPCWSTR lpMsgBuf;
|
|
CreateErrorMsg(dwErr, lpMsgBuf);
|
|
MessageBoxW(NULL, lpMsgBuf, L"!!! CommEventThread - SetCommMask() error", MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
|
|
ReleaseErrorMsg(lpMsgBuf);
|
|
)
|
|
return dwErr;
|
|
}
|
|
|
|
if(!SetEvent(EventInfo->eventHandle))
|
|
{
|
|
dwErr = GetLastError();
|
|
if(dwErr == ERROR_INVALID_HANDLE) // Event was closed
|
|
{
|
|
//MessageBoxW(NULL, L"--- CommEventThread - Event closed", L"ERROR_INVALID_HANDLE", MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
|
|
free(EventInfo);
|
|
return 0;
|
|
}
|
|
|
|
IF_DEBUG
|
|
(
|
|
LPCWSTR lpMsgBuf;
|
|
CreateErrorMsg(dwErr, lpMsgBuf);
|
|
MessageBoxW(NULL, lpMsgBuf, L"!!! CommEventThread - SetEvent() error", MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
|
|
ReleaseErrorMsg(lpMsgBuf);
|
|
)
|
|
return dwErr;
|
|
}
|
|
|
|
// Wait for receiving and clearing event
|
|
while(EventInfo->event != 0)
|
|
Sleep(0);
|
|
|
|
} while(TRUE);
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------
|
|
setEventFlags
|
|
|
|
accept: EventFlag table
|
|
return: none
|
|
exceptions: none
|
|
comments: sets EventFlag table according to Java
|
|
MonitorThread fields
|
|
----------------------------------------------------------*/
|
|
/*void setEventFlags(JNIEnv *env, jobject jobjPort, bool ef[])
|
|
{
|
|
jfieldID jfid;
|
|
jclass cls;
|
|
jobject jobj;
|
|
jclass clsPort = env->GetObjectClass(jobjPort);
|
|
|
|
if((jfid = env->GetFieldID(clsPort, "monThread", "Lgnu/io/RXTXPort$MonitorThread;")) == NULL)
|
|
{
|
|
IF_DEBUG
|
|
(
|
|
env->ExceptionDescribe();
|
|
)
|
|
env->ExceptionClear();
|
|
env->DeleteLocalRef(clsPort);
|
|
return;
|
|
}
|
|
jobj = env->GetObjectField(jobjPort, jfid);
|
|
cls = env->GetObjectClass(jobj);
|
|
|
|
ef[SPE_DATA_AVAILABLE] = get_java_boolean_var2(env, jobj, cls, "Data");
|
|
ef[SPE_OUTPUT_BUFFER_EMPTY] = get_java_boolean_var2(env, jobj, cls, "Output");
|
|
ef[SPE_CTS] = get_java_boolean_var2(env, jobj, cls, "CTS");
|
|
ef[SPE_DSR] = get_java_boolean_var2(env, jobj, cls, "DSR");
|
|
ef[SPE_RI] = get_java_boolean_var2(env, jobj, cls, "RI");
|
|
ef[SPE_CD] = get_java_boolean_var2(env, jobj, cls, "CD");
|
|
ef[SPE_OE] = get_java_boolean_var2(env, jobj, cls, "OE");
|
|
ef[SPE_PE] = get_java_boolean_var2(env, jobj, cls, "PE");
|
|
ef[SPE_FE] = get_java_boolean_var2(env, jobj, cls, "FE");
|
|
ef[SPE_BI] = get_java_boolean_var2(env, jobj, cls, "BI");
|
|
|
|
env->DeleteLocalRef(clsPort);
|
|
env->DeleteLocalRef(cls);
|
|
env->DeleteLocalRef(jobj);
|
|
}
|
|
*/
|
|
|
|
/*----------------------------------------------------------
|
|
InitialiseEventInfoStruct
|
|
|
|
accept: Port handle
|
|
return: 0 - OK, other - error number
|
|
exceptions: none
|
|
comments: Structure for communication with thread
|
|
----------------------------------------------------------*/
|
|
int InitialiseEventInfoStruct(HANDLE hPort, EventInfoStruct **EventInfoPtr)
|
|
{
|
|
DWORD dwErr;
|
|
WCHAR wsEventName[MAX_PATH];
|
|
|
|
(*EventInfoPtr) = (EventInfoStruct *)malloc(sizeof(EventInfoStruct));
|
|
if(*EventInfoPtr == NULL)
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
memset(*EventInfoPtr, 0, sizeof(EventInfoStruct));
|
|
(*EventInfoPtr)->fd = hPort;
|
|
wsprintfW(wsEventName, L"rxtxPort.SerEvt%lx", hPort);
|
|
(*EventInfoPtr)->eventHandle = CreateEventW(NULL, FALSE, FALSE, wsEventName);
|
|
dwErr = GetLastError();
|
|
if((*EventInfoPtr)->eventHandle == NULL || dwErr == ERROR_ALREADY_EXISTS)
|
|
{
|
|
IF_DEBUG
|
|
(
|
|
LPCWSTR lpMsgBuf;
|
|
CreateErrorMsg(dwErr, lpMsgBuf);
|
|
MessageBoxW(NULL, lpMsgBuf, L"!!! InitialiseEventInfoStruct - CreateEvent() error", MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
|
|
ReleaseErrorMsg(lpMsgBuf);
|
|
)
|
|
free(*EventInfoPtr);
|
|
return dwErr;
|
|
}
|
|
|
|
// Set initial event flags: It should be not empty, but unused here and relatively rare event
|
|
(*EventInfoPtr)->ef = EV_POWER; //In WinNT you can use EV_EVENT2 instead
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------
|
|
SendEvents
|
|
|
|
accept:
|
|
return:
|
|
exceptions: none
|
|
comments: Sends events needed
|
|
----------------------------------------------------------*/
|
|
int SendEvents(JNIEnv *env, jobject jobj, DWORD dwEvent, EventInfoStruct *EventInfo, jmethodID jmSendEvent)
|
|
{
|
|
DWORD dwErrors;
|
|
COMSTAT Stat;
|
|
|
|
IF_DEBUG
|
|
(
|
|
printj(env, L"--- SendEvents(): event %#lx\n", dwEvent);
|
|
)
|
|
|
|
if(!ClearCommError(EventInfo->fd, &dwErrors, &Stat))
|
|
{
|
|
IF_DEBUG
|
|
(
|
|
LPCWSTR lpMsgBuf;
|
|
CreateErrorMsg(GetLastError(), lpMsgBuf);
|
|
printj(env, L"!!! SendEvents - ClearCommError() error: %s\n", lpMsgBuf);
|
|
ReleaseErrorMsg(lpMsgBuf);
|
|
)
|
|
return -1;
|
|
}
|
|
|
|
// Ignore not subscribed events
|
|
dwEvent &= EventInfo->ef;
|
|
|
|
if(dwEvent & EV_RXCHAR)
|
|
{
|
|
IF_DEBUG
|
|
(
|
|
printj(env, L"--- SendEvents(): EV_RXCHAR\n");
|
|
)
|
|
if(env->CallBooleanMethod(jobj, jmSendEvent, SPE_DATA_AVAILABLE, JNI_TRUE) == JNI_TRUE)
|
|
return SPE_DATA_AVAILABLE;
|
|
}
|
|
|
|
if(dwEvent & EV_TXEMPTY)
|
|
{
|
|
IF_DEBUG
|
|
(
|
|
printj(env, L"--- SendEvents(): EV_TXEMPTY\n");
|
|
)
|
|
if(env->CallBooleanMethod(jobj, jmSendEvent, SPE_OUTPUT_BUFFER_EMPTY, JNI_TRUE) == JNI_TRUE)
|
|
return SPE_OUTPUT_BUFFER_EMPTY;
|
|
}
|
|
|
|
if(dwEvent & EV_CTS)
|
|
{
|
|
IF_DEBUG
|
|
(
|
|
printj(env, L"--- SendEvents(): EV_CTS\n");
|
|
)
|
|
if(env->CallBooleanMethod(jobj, jmSendEvent, SPE_CTS, Stat.fCtsHold?JNI_TRUE:JNI_TRUE) == JNI_TRUE)
|
|
return SPE_CTS;
|
|
}
|
|
|
|
if(dwEvent & EV_DSR)
|
|
{
|
|
IF_DEBUG
|
|
(
|
|
printj(env, L"--- SendEvents(): EV_DSR\n");
|
|
)
|
|
if(env->CallBooleanMethod(jobj, jmSendEvent, SPE_DSR, Stat.fDsrHold?JNI_TRUE:JNI_TRUE) == JNI_TRUE)
|
|
return SPE_DSR;
|
|
}
|
|
|
|
if(dwEvent & EV_RING)
|
|
{
|
|
IF_DEBUG
|
|
(
|
|
printj(env, L"--- SendEvents(): EV_RING\n");
|
|
)
|
|
if(env->CallBooleanMethod(jobj, jmSendEvent, SPE_RI, JNI_TRUE) == JNI_TRUE)
|
|
return SPE_RI;
|
|
}
|
|
|
|
if(dwEvent & EV_RLSD)
|
|
{
|
|
IF_DEBUG
|
|
(
|
|
printj(env, L"--- SendEvents(): EV_RLSD\n");
|
|
)
|
|
if(env->CallBooleanMethod(jobj, jmSendEvent, SPE_CD, Stat.fRlsdHold?JNI_TRUE:JNI_TRUE) == JNI_TRUE)
|
|
return SPE_CD;
|
|
}
|
|
|
|
if(dwEvent & EV_ERR)
|
|
{
|
|
if(dwErrors & CE_OVERRUN)
|
|
{
|
|
IF_DEBUG
|
|
(
|
|
printj(env, L"--- SendEvents(): CE_OVERRUN\n");
|
|
)
|
|
if(env->CallBooleanMethod(jobj, jmSendEvent, SPE_OE, JNI_TRUE) == JNI_TRUE)
|
|
return SPE_OE;
|
|
}
|
|
|
|
if(dwErrors & CE_RXPARITY)
|
|
{
|
|
IF_DEBUG
|
|
(
|
|
printj(env, L"--- SendEvents(): CE_RXPARITY\n");
|
|
)
|
|
if(env->CallBooleanMethod(jobj, jmSendEvent, SPE_PE, JNI_TRUE) == JNI_TRUE)
|
|
return SPE_PE;
|
|
}
|
|
|
|
if(dwErrors & CE_FRAME)
|
|
{
|
|
IF_DEBUG
|
|
(
|
|
printj(env, L"--- SendEvents(): CE_FRAME\n");
|
|
)
|
|
if(env->CallBooleanMethod(jobj, jmSendEvent, SPE_FE, JNI_TRUE) == JNI_TRUE)
|
|
return SPE_FE;
|
|
}
|
|
}
|
|
|
|
if(dwEvent & EV_BREAK)
|
|
{
|
|
IF_DEBUG
|
|
(
|
|
printj(env, L"--- SendEvents(): EV_BREAK\n");
|
|
)
|
|
if(env->CallBooleanMethod(jobj, jmSendEvent, SPE_BI, JNI_TRUE) == JNI_TRUE)
|
|
return SPE_BI;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|