/**
 * Copyright (C) 2009 Samsung Electronics Co., Ltd. All rights reserved.
 *
 * Mobile Communication Division,
 * Digital Media & Communications Business, Samsung Electronics Co., Ltd.
 *
 * This software and its documentation are confidential and proprietary
 * information of Samsung Electronics Co., Ltd.  No part of the software and
 * documents may be copied, reproduced, transmitted, translated, or reduced to
 * any electronic medium or machine-readable form without the prior written
 * consent of Samsung Electronics.
 *
 * Samsung Electronics makes no representations with respect to the contents,
 * and assumes no responsibility for any errors that might appear in the
 * software and documents. This publication and the contents hereof are subject
 * to change without notice.
 */

#include "et9imuUtil.h"

/*----------------------------------------------------------------------------
 *  Callback Functions
 *----------------------------------------------------------------------------*/
ET9STATUS ET9FARCALL ET9_ConvertSymb(
    void    *pConvertInfo,                  /**< pointer to an integration layer object */
    ET9SYMB *psConvertSymb                  /**< converting symbol (in & out) */
)
{
	ET9STATUS wStatus = ET9STATUS_NONE;

	// TODO:

	return wStatus;
}

ET9STATUS ET9FARCALL ET9_BufFreeRead(
    void          *pBufferReadInfo,                 /**< pointer to an integration layer object */
    ET9U16         wNumberOfReadSymbols,            /**< specifies the number of symbols to be read */
    ET9SYMB       *psDest,                          /**< buffer for the data */
    ET9U16        *pwSymbolsRead                    /**< pointer to the variable that receives the number of symbols read */
)
{
	ET9STATUS wStatus = ET9STATUS_NONE;

	// TODO:

	return wStatus;
}

/*----------------------------------------------------------------------------
 * Get Functions
 *----------------------------------------------------------------------------*/
#ifdef ET9_FULL_INTERFACE
ET9STATUS ET9FARCALL ET9Word_GetWordSymbInfo(JNIEnv *env, jclass jcls, ET9WordSymbInfo *WordSymbInfo, jobject jobj)
{
	jclass cls;
	ET9WordSymbInfoPrivate WordSymbInfoPrivate;
	ET9SymbInfo SymbsInfo;

	if(env == NULL || WordSymbInfo == NULL)
		return ET9STATUS_INVALID_MEMORY;

	cls = (*env)->GetObjectClass(env, jobj);
   
	WordSymbInfo->dwStateBits  = (*env)->GetIntField   (env, jobj, (*env)->GetFieldID(env, cls, "dwStateBits",  "I"));

	SymbsInfo = WordSymbInfo->SymbsInfo[0];
   
	ET9Word_GetSymbsInfo(env, cls, &SymbsInfo, jobj);
	WordSymbInfo->bNumSymbs    = (*env)->GetByteField  (env, jobj, (*env)->GetFieldID(env, cls, "bNumSymbs",    "B"));
	WordSymbInfo->wInitOK      = (*env)->GetShortField (env, jobj, (*env)->GetFieldID(env, cls, "wInitOK",      "S"));

	WordSymbInfoPrivate = WordSymbInfo->Private;
	ET9Word_GetWordSymbInfoPrivate(env, cls, &WordSymbInfoPrivate, jobj);

	return ET9STATUS_NONE;
}

ET9STATUS ET9FARCALL ET9Word_GetSymbsInfo(JNIEnv *env, jclass jcls, ET9SymbInfo * SymbsInfo, jobject jobj)
{
	jobject jobj_SymbsInfo;
	jint data_len;
	jint nLoop;

	if(env == NULL || SymbsInfo == NULL)
		return ET9STATUS_INVALID_MEMORY;
   
	jobj_SymbsInfo = (*env)->GetObjectField(env, jobj, (*env)->GetFieldID(env, jcls, "SymbsInfo", "[Lcom/xt9/core/Xt9Datatype$S_ET9SymbInfo;"));

	data_len = (*env)->GetArrayLength(env, (*env)->GetObjectArrayElement(env, jobj_SymbsInfo, 0));
   
	for(nLoop = 0; nLoop < ET9MAXWORDSIZE; nLoop++)
	{
		jint new_data_len = (*env)->GetArrayLength(env, (*env)->GetObjectArrayElement(env, jobj_SymbsInfo, nLoop));
		jobject jobj_SymbsInfo_sub = (*env)->GetObjectArrayElement(env, jobj_SymbsInfo, nLoop);
		jclass cls_SymbsInfo_sub = (*env)->GetObjectClass(env, jobj_SymbsInfo_sub);
		ET9DataPerBaseSym DataPerBaseSym;

		DataPerBaseSym = SymbsInfo->DataPerBaseSym[0];

		ET9Word_GetDataPerBaseSym(env, cls_SymbsInfo_sub, &DataPerBaseSym, jobj_SymbsInfo_sub);
      
		SymbsInfo[nLoop].sLockedSymb = (*env)->GetShortField(env, jobj_SymbsInfo_sub, (*env)->GetFieldID(env, cls_SymbsInfo_sub, "sLockedSymb", "S"));
		SymbsInfo[nLoop].wTapX = (*env)->GetShortField(env, jobj_SymbsInfo_sub, (*env)->GetFieldID(env, cls_SymbsInfo_sub, "wTapX", "S"));
		SymbsInfo[nLoop].wTapY = (*env)->GetShortField(env, jobj_SymbsInfo_sub, (*env)->GetFieldID(env, cls_SymbsInfo_sub, "wTapY", "S"));
		SymbsInfo[nLoop].eInputType = (*env)->GetByteField(env, jobj_SymbsInfo_sub, (*env)->GetFieldID(env, cls_SymbsInfo_sub, "eInputTypes", "B"));
		SymbsInfo[nLoop].eShiftState = (*env)->GetByteField(env, jobj_SymbsInfo_sub, (*env)->GetFieldID(env, cls_SymbsInfo_sub, "eShiftState", "B"));
		SymbsInfo[nLoop].wInputIndex = (*env)->GetShortField(env, jobj_SymbsInfo_sub, (*env)->GetFieldID(env, cls_SymbsInfo_sub, "wInputIndex", "S"));
		SymbsInfo[nLoop].wKeyIndex = (*env)->GetShortField(env, jobj_SymbsInfo_sub, (*env)->GetFieldID(env, cls_SymbsInfo_sub, "wKeyIndex", "S"));
		SymbsInfo[nLoop].bAmbigType = (*env)->GetByteField(env, jobj_SymbsInfo_sub, (*env)->GetFieldID(env, cls_SymbsInfo_sub, "bAmbigType", "B"));
		SymbsInfo[nLoop].bNumBaseSyms = (*env)->GetByteField(env, jobj_SymbsInfo_sub, (*env)->GetFieldID(env, cls_SymbsInfo_sub, "bNumBaseSyms", "B"));
		SymbsInfo[nLoop].bSymbType = (*env)->GetByteField(env, jobj_SymbsInfo_sub, (*env)->GetFieldID(env, cls_SymbsInfo_sub, "bSymbType", "B"));
		SymbsInfo[nLoop].bLocked = (*env)->GetByteField(env, jobj_SymbsInfo_sub, (*env)->GetFieldID(env, cls_SymbsInfo_sub, "bLocked", "B"));
		SymbsInfo[nLoop].bLockLanguageSource = (*env)->GetByteField(env, jobj_SymbsInfo_sub, (*env)->GetFieldID(env, cls_SymbsInfo_sub, "bLockLanguageSource", "B"));
		SymbsInfo[nLoop].wKeyLayoutType = (*env)->GetShortField(env, jobj_SymbsInfo_sub, (*env)->GetFieldID(env, cls_SymbsInfo_sub, "wKeyLayoutType", "S"));
		SymbsInfo[nLoop].bAutoDowncase = (*env)->GetByteField(env, jobj_SymbsInfo_sub, (*env)->GetFieldID(env, cls_SymbsInfo_sub, "bAutoDowncase", "B"));
		SymbsInfo[nLoop].bForcedLowercase = (*env)->GetByteField(env, jobj_SymbsInfo_sub, (*env)->GetFieldID(env, cls_SymbsInfo_sub, "bForcedLowercase", "B"));
	}

	return ET9STATUS_NONE;
}

ET9STATUS ET9FARCALL ET9Word_GetDataPerBaseSym(JNIEnv *env, jclass jcls, ET9DataPerBaseSym *DataPerBaseSym, jobject jobj)
{
	jint nLoop;
	jobject jobj_DataPerBaseSym;

	if(env == NULL || DataPerBaseSym == NULL)
		return ET9STATUS_INVALID_MEMORY;

	jobj_DataPerBaseSym = (*env)->GetObjectField(env, jobj, (*env)->GetFieldID(env, jcls, "DataPerBaseSym", "[Lcom/xt9/core/Xt9Datatype$S_ET9DataPerBaseSym;"));
   
	for(nLoop = 0; nLoop < ET9MAXBASESYMBS; nLoop++)
	{
		jobject jobj_DataPerBaseSym_sub = (*env)->GetObjectArrayElement(env, jobj_DataPerBaseSym, nLoop);
		jclass cls_DataPerBaseSym_sub = (*env)->GetObjectClass(env, jobj_DataPerBaseSym_sub);
		
		GetCharObjectArray(env, cls_DataPerBaseSym_sub, DataPerBaseSym->sChar,
				(*env)->GetObjectField(env, jobj_DataPerBaseSym_sub, (*env)->GetFieldID(env, cls_DataPerBaseSym_sub, "sChar", "[C")),
				ET9MAXALTSYMBS);
		GetCharObjectArray(env, cls_DataPerBaseSym_sub, DataPerBaseSym->sUpperCaseChar,
				(*env)->GetObjectField(env, jobj_DataPerBaseSym_sub, (*env)->GetFieldID(env, cls_DataPerBaseSym_sub, "sUpperCaseChar", "[C")),
				ET9MAXALTSYMBS);
		DataPerBaseSym->bSymFreq = (*env)->GetByteField(env, jobj_DataPerBaseSym_sub, (*env)->GetFieldID(env, cls_DataPerBaseSym_sub, "bSymFreq", "B"));
		DataPerBaseSym->bNumSymsToMatch = (*env)->GetByteField(env, jobj_DataPerBaseSym_sub, (*env)->GetFieldID(env, cls_DataPerBaseSym_sub, "bNumSymsToMatch", "B"));
		DataPerBaseSym->bDefaultCharIndex = (*env)->GetByteField(env, jobj_DataPerBaseSym_sub, (*env)->GetFieldID(env, cls_DataPerBaseSym_sub, "bDefaultCharIndex", "B"));
	}

	return ET9STATUS_NONE;
}

ET9STATUS ET9FARCALL ET9Word_GetWordSymbInfoPrivate(JNIEnv *env, jclass jcls, ET9WordSymbInfoPrivate *WordSymbInfoPrivate, jobject jobj)
{
	jclass cls_Private;
	jobject jobj_Private;
	ET9SimpleWord SimpleWord;
	ET9SavedInputWords SavedInputWords;
   
	if(env == NULL || WordSymbInfoPrivate == NULL)
		return ET9STATUS_INVALID_MEMORY;
   
	jobj_Private = (*env)->GetObjectField(env, jobj, (*env)->GetFieldID(env, jcls, "Private", "Lcom/xt9/core/Xt9Datatype$S_ET9WordSymbInfoPrivate;"));
	cls_Private = (*env)->GetObjectClass(env, jobj_Private);
	WordSymbInfoPrivate->bLastShiftState = (*env)->GetByteField(env, jobj_Private, (*env)->GetFieldID(env, cls_Private, "bLastShiftState", "B"));
	WordSymbInfoPrivate->eCurrPostShiftMode = (*env)->GetByteField(env, jobj_Private, (*env)->GetFieldID(env, cls_Private, "eCurrPostShiftMode", "B"));
	WordSymbInfoPrivate->bCurrSelListIndex = (*env)->GetByteField(env, jobj_Private, (*env)->GetFieldID(env, cls_Private, "bCurrSelListIndex", "B"));
	WordSymbInfoPrivate->bCompoundingDownshift = (*env)->GetByteField(env, jobj_Private, (*env)->GetFieldID(env, cls_Private, "bCompoundingDownshift", "B"));
	WordSymbInfoPrivate->wAutocapCast = (*env)->GetShortField(env, jobj_Private, (*env)->GetFieldID(env, cls_Private, "wAutocapCast", "S"));
	WordSymbInfoPrivate->eAutocapWord = (*env)->GetByteField(env, jobj_Private, (*env)->GetFieldID(env, cls_Private, "eAutocapWord", "B"));
	WordSymbInfoPrivate->bSwitchLanguage = (*env)->GetByteField(env, jobj_Private, (*env)->GetFieldID(env, cls_Private, "bSwitchLanguage", "B"));
	WordSymbInfoPrivate->bRequiredLocate = (*env)->GetBooleanField(env, jobj_Private, (*env)->GetFieldID(env, cls_Private, "bRequiredLocate", "Z"));
	WordSymbInfoPrivate->bRequiredVerifyInput = (*env)->GetBooleanField(env, jobj_Private, (*env)->GetFieldID(env, cls_Private, "bRequiredVerifyInput", "Z"));
	WordSymbInfoPrivate->bRequiredLastShiftState = (*env)->GetByteField(env, jobj_Private, (*env)->GetFieldID(env, cls_Private, "bRequiredLastShiftState", "B"));
	WordSymbInfoPrivate->bInputRestarted = (*env)->GetBooleanField(env, jobj_Private, (*env)->GetFieldID(env, cls_Private, "bInputRestarted", "Z"));
	WordSymbInfoPrivate->bPreventWhiteSpaceInput = (*env)->GetBooleanField(env, jobj_Private, (*env)->GetFieldID(env, cls_Private, "bPreventWhiteSpaceInput", "Z"));
	WordSymbInfoPrivate->wIDBVersionStrSize = (*env)->GetShortField(env, jobj_Private, (*env)->GetFieldID(env, cls_Private, "wIDBVersionStrSize", "S"));
	GetShortObjectArray(env, cls_Private, WordSymbInfoPrivate->szIDBVersion,
						(*env)->GetObjectField(env, jobj_Private, (*env)->GetFieldID(env, cls_Private, "szIDBVersion", "[S")),
						ET9MAXVERSIONSTR);
	//g_WordSymbInfo.Private.szIDBVersion[nLoop] = (*env)->GetShortArrayElements(env, );
	//TODO
	//S_ET9BaseLingInfo[]    ppEditionsList
	//()V

	SimpleWord = WordSymbInfoPrivate->sRequiredWord;
	ET9Word_GetSimpleWords(env, cls_Private, &SimpleWord, jobj_Private);

	SavedInputWords = WordSymbInfoPrivate->sSavedInputWords;
	ET9Word_GetSavedInputWords(env, cls_Private, &SavedInputWords, jobj_Private);

	return ET9STATUS_NONE;
}


ET9STATUS ET9FARCALL ET9Word_GetSavedInputWords(JNIEnv *env, jclass jcls, ET9SavedInputWords *SavedInputWords, jobject jobj)
{
	jclass cls_sSavedInputWords;
	jobject jobj_sSavedInputWords;
   ET9SavedInputWord SavedWords;
   ET9SavedInputSymb Inputs;
   
	if(env == NULL || SavedInputWords == NULL)
		return ET9STATUS_INVALID_MEMORY;
   
	jobj_sSavedInputWords = (*env)->GetObjectField(env, jobj, (*env)->GetFieldID(env, jcls, "sSavedInputWords", "Lcom/xt9/core/Xt9Datatype$S_ET9SavedInputWords;"));
	cls_sSavedInputWords = (*env)->GetObjectClass(env, jobj_sSavedInputWords);
	SavedInputWords->wCurrInputSaveIndex = (*env)->GetShortField(env, jobj_sSavedInputWords, (*env)->GetFieldID(env, cls_sSavedInputWords, "wCurrInputSaveIndex", "S"));

	SavedWords = SavedInputWords->pSavedWords[0];
	ET9Word_GetSavedInputWord(env, cls_sSavedInputWords, &SavedWords, jobj_sSavedInputWords);
	GetShortObjectArray(env, cls_sSavedInputWords, SavedInputWords->sWords,
						(*env)->GetObjectField(env, jobj_sSavedInputWords, (*env)->GetFieldID(env, cls_sSavedInputWords, "sWords", "[S")),
						ET9SAVEINPUTSTORESIZE);

	ET9Word_GetSavedInputSymb(env, cls_sSavedInputWords, &Inputs, jobj_sSavedInputWords);

   return ET9STATUS_NONE;
}


ET9STATUS ET9FARCALL ET9Word_GetSavedInputWord(JNIEnv *env, jclass jcls, ET9SavedInputWord *pSavedWords, jobject jobj)
{
   jobject jobj_SavedWords;
   jint nLoop;
   
   if(env == NULL || pSavedWords == NULL)
      return ET9STATUS_INVALID_MEMORY;

   jobj_SavedWords = (*env)->GetObjectField(env, jobj, (*env)->GetFieldID(env, jcls, "pSavedWords", "[Lcom/xt9/core/Xt9Datatype$S_ET9SavedInputWorld;"));

   for(nLoop = 0; nLoop < ET9MAXSAVEINPUTWORDS; nLoop++)
   {
      jobject jobj_SavedWords_sub = (*env)->GetObjectArrayElement(env, jobj_SavedWords, nLoop);
      jclass cls_SavedWords_sub = (*env)->GetObjectClass(env, jobj_SavedWords_sub);
      
      pSavedWords->wStorePos = (*env)->GetShortField(env, jobj_SavedWords_sub, (*env)->GetFieldID(env, cls_SavedWords_sub, "wStorePos", "S"));
      pSavedWords->wWordLen = (*env)->GetShortField(env, jobj_SavedWords_sub, (*env)->GetFieldID(env, cls_SavedWords_sub, "wWordLen", "S"));
      pSavedWords->wInputLen = (*env)->GetShortField(env, jobj_SavedWords_sub, (*env)->GetFieldID(env, cls_SavedWords_sub, "wInputLen", "S"));
      pSavedWords->bLastShiftState = (*env)->GetByteField(env, jobj_SavedWords_sub, (*env)->GetFieldID(env, cls_SavedWords_sub, "bLastShiftState", "B"));
   }

   return ET9STATUS_NONE;
}

ET9STATUS ET9FARCALL ET9Word_GetSavedInputSymb(JNIEnv *env, jclass jcls, ET9SavedInputSymb *pInputs, jobject jobj)
{
   jobject jobj_Inputs;
   jint nLoop;
   
   if(env == NULL || pInputs == NULL)
      return ET9STATUS_INVALID_MEMORY;

   jobj_Inputs = (*env)->GetObjectField(env, jobj, (*env)->GetFieldID(env, jcls, "sInputs", "[Lcom/xt9/core/Xt9Datatype$S_ET9SavedInputSymb;"));

   for(nLoop = 0; nLoop < ET9SAVEINPUTSTORESIZE; nLoop++)
   {
      jobject jobj_Inputs_sub = (*env)->GetObjectArrayElement(env, jobj_Inputs, nLoop);
      jclass cls_Inputs_sub = (*env)->GetObjectClass(env, jobj_Inputs_sub);
      
      pInputs->eInputType = (*env)->GetByteField(env, jobj_Inputs_sub, (*env)->GetFieldID(env, cls_Inputs_sub, "eInputType", "B"));
      pInputs->bLocked = (*env)->GetBooleanField(env, jobj_Inputs_sub, (*env)->GetFieldID(env, cls_Inputs_sub, "bLocked", "Z"));
      pInputs->eShiftState = (*env)->GetByteField(env, jobj_Inputs_sub, (*env)->GetFieldID(env, cls_Inputs_sub, "eShiftState", "B"));
      pInputs->bForcedLowercase = (*env)->GetByteField(env, jobj_Inputs_sub, (*env)->GetFieldID(env, cls_Inputs_sub, "bForcedLowercase", "B"));
      pInputs->bInputIndex = (*env)->GetShortField(env, jobj_Inputs_sub, (*env)->GetFieldID(env, cls_Inputs_sub, "bInputIndex", "S"));
      pInputs->wKeyIndex = (*env)->GetShortField(env, jobj_Inputs_sub, (*env)->GetFieldID(env, cls_Inputs_sub, "wKeyIndex", "S"));
      pInputs->wTapX = (*env)->GetShortField(env, jobj_Inputs_sub, (*env)->GetFieldID(env, cls_Inputs_sub, "wTapX", "S"));
      pInputs->wTapY = (*env)->GetShortField(env, jobj_Inputs_sub, (*env)->GetFieldID(env, cls_Inputs_sub, "wTapY", "S"));
      pInputs->sSymb = (*env)->GetShortField(env, jobj_Inputs_sub, (*env)->GetFieldID(env, cls_Inputs_sub, "sSymb", "S"));
   }

   return ET9STATUS_NONE;
}
#endif // ET9_FULL_INTERFACE

#ifdef ET9_LITE_INTERFACE
ET9STATUS ET9FARCALL ET9Word_GetSimpleWords(JNIEnv	*env, jclass jcls, ET9SimpleWord *SimpleWord, jobject jobj)
{
	jclass cls;

	if(env == NULL || SimpleWord == NULL)
		return ET9STATUS_INVALID_MEMORY;

	cls = (*env)->GetObjectClass(env, jobj);

	SimpleWord->wLen     = (*env)->GetShortField(env, jobj, (*env)->GetFieldID(env, cls, "wLen",     "S"));
	SimpleWord->wCompLen = (*env)->GetShortField(env, jobj, (*env)->GetFieldID(env, cls, "wCompLen", "S"));

	GetCharObjectArray(env, jcls, SimpleWord->sString,
		(*env)->GetObjectField(env, jobj, (*env)->GetFieldID(env, cls, "sString", "[C")), ET9MAXWORDSIZE);

   return ET9STATUS_NONE;
}
#endif // ET9_LITE_INTERFACE

/*----------------------------------------------------------------------------
 * Set Functions
 *----------------------------------------------------------------------------*/
#ifdef ET9_FULL_INTERFACE
ET9STATUS ET9FARCALL ET9Word_SetWordSymbInfo(JNIEnv *env, jclass jcls, jobject *jobj, ET9WordSymbInfo WordSymbInfo)
{
	jclass cls;

	if(env == NULL || jobj == NULL)
		return ET9STATUS_INVALID_MEMORY;

	cls = (*env)->GetObjectClass(env,* jobj);

	return ET9STATUS_NONE;
}
#endif // ET9_FULL_INTERFACE

#ifdef ET9_LITE_INTERFACE
ET9STATUS ET9FARCALL ET9Word_SetSimpleWords(JNIEnv *env, jclass jcls, jobject *jobj, ET9SimpleWord SimpleWord)
{
	jclass cls;

	if(env == NULL || jobj == NULL)
		return ET9STATUS_INVALID_MEMORY;

	cls = (*env)->GetObjectClass(env, *jobj);

	(*env)->SetShortField(env, *jobj, (*env)->GetFieldID(env, cls, "wLen",     "S"), SimpleWord.wLen);
	(*env)->SetShortField(env, *jobj, (*env)->GetFieldID(env, cls, "wCompLen", "S"), SimpleWord.wCompLen);

	SetCharObjectArray(env, jcls, 
		(*env)->GetObjectField(env, *jobj, (*env)->GetFieldID(env, cls, "sString", "[C")), SimpleWord.sString, ET9MAXWORDSIZE);

	return ET9STATUS_NONE;
}
#endif // ET9_LITE_INTERFACE

ET9STATUS ET9FARCALL ET9_GetTracePoint(JNIEnv *env, jclass jcls, ET9TracePoint *pTracePoint, jobjectArray jobjArray, jint nTracePointCount)
{
	jint nLoop;
	jint data_len;
	if(env == NULL || jobjArray == NULL)
		return ET9STATUS_INVALID_MEMORY;
	if(nTracePointCount < 0)
		return ET9STATUS_INVALID_MEMORY;

	nTracePointCount = nTracePointCount <  ET9_TRACE_MAX_POINTS ? nTracePointCount : ET9_TRACE_MAX_POINTS;
	
	for(nLoop = 0; nLoop < nTracePointCount; nLoop++)
	{
		jobject jobj_sub = (*env)->GetObjectArrayElement(env, jobjArray, nLoop);
		jclass cls_sub = (*env)->GetObjectClass(env, jobj_sub);

		pTracePoint[nLoop].nX = (*env)->GetLongField(env, jobj_sub, (*env)->GetFieldID(env, cls_sub, "nX", "J"));
		pTracePoint[nLoop].nY = (*env)->GetLongField(env, jobj_sub, (*env)->GetFieldID(env, cls_sub, "nY", "J"));

		(*env)->DeleteLocalRef(env, cls_sub);
		(*env)->DeleteLocalRef(env, jobj_sub);

	}

	return ET9STATUS_NONE;
}

ET9STATUS ET9FARCALL ET9CP_SetPhrase(JNIEnv *env, jclass jcls, jobject *jobj, ET9CPPhrase* psPharse)
{
	jclass cls;

	if(env == NULL || jobj == NULL)
		return ET9STATUS_INVALID_MEMORY;

	cls = (*env)->GetObjectClass(env, *jobj);

	(*env)->SetByteField(env, *jobj, (*env)->GetFieldID(env, cls, "bLen",     "B"), psPharse->bLen);

	SetCharObjectArray(env, jcls, 
		(*env)->GetObjectField(env, *jobj, (*env)->GetFieldID(env, cls, "pSymbs", "[C")), psPharse->pSymbs, ET9CPMAXPHRASESIZE);

	return ET9STATUS_NONE;
}

ET9STATUS ET9FARCALL ET9CP_GetPhrase(JNIEnv *env, jclass jcls, ET9CPPhrase* psPharse, jobject jobj)
{
	jclass cls;

	if(env == NULL || psPharse == NULL)
		return ET9STATUS_INVALID_MEMORY;

	cls = (*env)->GetObjectClass(env, jobj);

	psPharse->bLen     = (*env)->GetShortField(env, jobj, (*env)->GetFieldID(env, cls, "bLen",     "B"));

	GetCharObjectArray(env, jcls, psPharse->pSymbs,
		(*env)->GetObjectField(env, jobj, (*env)->GetFieldID(env, cls, "pSymbs", "[C")), ET9CPMAXPHRASESIZE);

   return ET9STATUS_NONE;
}

ET9STATUS ET9FARCALL ET9CP_SetSpell(JNIEnv *env, jclass jcls, jobject *jobj, ET9CPSpell* psSpell)
{
	jclass cls;
	int i = 0;

	if(env == NULL || jobj == NULL)
		return ET9STATUS_INVALID_MEMORY;

	cls = (*env)->GetObjectClass(env, *jobj);

	(*env)->SetByteField(env, *jobj, (*env)->GetFieldID(env, cls, "bLen",     "B"), psSpell->bLen);
	for(i = 0 ; i < psSpell->bLen ; i++) {
		if(ET9CPIsBpmfUpperCaseSymbol(psSpell->pSymbs[i])) {
			psSpell->pSymbs[i] = ET9CPBpmfSymbolToLower(psSpell->pSymbs[i]);
        } else if (0x0019 == psSpell->pSymbs[i]) {
            psSpell->pSymbs[i] = 0x0027;
        } else if (0X00B1 == psSpell->pSymbs[i]) {
            psSpell->pSymbs[i] = 0x02c9;
        } else if (0X00B2 == psSpell->pSymbs[i]) {
            psSpell->pSymbs[i] = 0x02ca;
        } else if (0X00B3 == psSpell->pSymbs[i]) {
            psSpell->pSymbs[i] = 0x02c7;
        } else if (0X00B4 == psSpell->pSymbs[i]) {
            psSpell->pSymbs[i] = 0x02cb;
        } else if (0X00B5 == psSpell->pSymbs[i]) {
            psSpell->pSymbs[i] = 0x02d9;
        } else if (0x001A == psSpell->pSymbs[i]) {
            psSpell->pSymbs[i] = 0x0027;
        }
	}
	SetCharObjectArray(env, jcls, 
		(*env)->GetObjectField(env, *jobj, (*env)->GetFieldID(env, cls, "pSymbs", "[C")), psSpell->pSymbs, ET9CPMAXSPELLSIZE);

	return ET9STATUS_NONE;
}

ET9STATUS ET9FARCALL ET9CP_GetSpell(JNIEnv *env, jclass jcls, ET9CPSpell* psSpell, jobject jobj)
{
	jclass cls;

	if(env == NULL || psSpell == NULL)
		return ET9STATUS_INVALID_MEMORY;

	cls = (*env)->GetObjectClass(env, jobj);

	psSpell->bLen     = (*env)->GetShortField(env, jobj, (*env)->GetFieldID(env, cls, "bLen",     "B"));

	GetCharObjectArray(env, jcls, psSpell->pSymbs,
		(*env)->GetObjectField(env, jobj, (*env)->GetFieldID(env, cls, "pSymbs", "[C")), ET9CPMAXSPELLSIZE);

   return ET9STATUS_NONE;
}

ET9STATUS ET9FARCALL ET9KDB_SetKeyPositions(JNIEnv *env, jclass jcls, jobjectArray jobjArray, jint maxPointCount, ET9KeyPoint* psKeyPoint)
{
	jint nLoop;

	if(env == NULL || jobjArray == NULL)
		return ET9STATUS_INVALID_MEMORY;

	if(maxPointCount < 0)
		return ET9STATUS_INVALID_MEMORY;

	for(nLoop = 0; nLoop < maxPointCount; nLoop++)
	{
		jobject jobj_sub = (*env)->GetObjectArrayElement(env, jobjArray, nLoop);
		jclass cls_sub = (*env)->GetObjectClass(env, jobj_sub);

		(*env)->SetShortField(env, jobj_sub, (*env)->GetFieldID(env, cls_sub, "wLeft",     "S"), psKeyPoint[nLoop].sArea.wLeft);
		(*env)->SetShortField(env, jobj_sub, (*env)->GetFieldID(env, cls_sub, "wTop",     "S"), psKeyPoint[nLoop].sArea.wTop);
		(*env)->SetShortField(env, jobj_sub, (*env)->GetFieldID(env, cls_sub, "wRight",     "S"), psKeyPoint[nLoop].sArea.wRight);
		(*env)->SetShortField(env, jobj_sub, (*env)->GetFieldID(env, cls_sub, "wBottom",     "S"), psKeyPoint[nLoop].sArea.wBottom);

		
		(*env)->DeleteLocalRef(env, cls_sub);
		(*env)->DeleteLocalRef(env, jobj_sub);
	}

	return ET9STATUS_NONE;
}
