Home | History | Annotate | Download | only in libwnnDictionary
      1 /*
      2  * Copyright (C) 2008-2012  OMRON SOFTWARE Co., Ltd.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 #include "jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni.h"
     17 
     18 #include "nj_lib.h"
     19 #include "nj_err.h"
     20 #include "nj_ext.h"
     21 #include "nj_dic.h"
     22 
     23 
     24 #include <stdlib.h>
     25 #include <string.h>
     26 #include <dlfcn.h>
     27 
     28 #include "OpenWnnJni.h"
     29 
     30 
     31 #include "predef_table.h"
     32 
     33 /**
     34  * functions for internal use
     35  */
     36 static void clearDictionaryStructure( NJ_DIC_INFO* dicInfo ) {
     37 	dicInfo->type		= 0;
     38 	dicInfo->handle		= NULL;
     39 /*	dicInfo->srhCache	= NULL; */
     40 
     41 	dicInfo->dic_freq[ NJ_MODE_TYPE_HENKAN ].base = 0;
     42 	dicInfo->dic_freq[ NJ_MODE_TYPE_HENKAN ].high = 0;
     43 }
     44 
     45 static NJ_CHAR convertUTFCharToNjChar( NJ_UINT8* src )
     46 {
     47     NJ_CHAR     ret;
     48     NJ_UINT8*   dst;
     49 
     50     /* convert UTF-16BE character to NJ_CHAR format */
     51     dst = ( NJ_UINT8* )&ret;
     52     dst[ 0 ] = src[ 0 ];
     53     dst[ 1 ] = src[ 1 ];
     54 
     55     return ret;
     56 }
     57 
     58 static int convertStringToNjChar( JNIEnv *env, NJ_CHAR* dst, jstring srcJ, int maxChars )
     59 {
     60 	const unsigned char*	src;
     61 
     62 	src = ( const unsigned char* )( ( *env )->GetStringUTFChars( env, srcJ, NULL ) );
     63 	if( src != NULL ) {
     64 		int     i, o;
     65 
     66         /* convert UTF-8 to UTF-16BE */
     67         for( i = o = 0 ; src[ i ] != 0x00 && o < maxChars ; ) {
     68 			NJ_UINT8* dst_tmp;
     69 			dst_tmp = ( NJ_UINT8* )&( dst[ o ] );
     70 
     71             if( ( src[ i ] & 0x80 ) == 0x00 ) {
     72                 /* U+0000 ... U+007f */
     73                 /* 8[0xxxxxxx] -> 16BE[00000000 0xxxxxxx] */
     74                 dst_tmp[ 0 ] = 0x00;
     75                 dst_tmp[ 1 ] = src[ i + 0 ] & 0x7f;
     76                 i++;
     77                 o++;
     78             } else if( ( src[ i ] & 0xe0 ) == 0xc0 ) {
     79                 /* U+0080 ... U+07ff */
     80                 /* 8[110xxxxx 10yyyyyy] -> 16BE[00000xxx xxyyyyyy] */
     81                 if( src[ i + 1 ] == 0x00 ) {
     82                     break;
     83                 }
     84                 dst_tmp[ 0 ] = ( ( src[ i + 0 ] & 0x1f ) >> 2 );
     85                 dst_tmp[ 1 ] = ( ( src[ i + 0 ] & 0x1f ) << 6 ) |   ( src[ i + 1 ] & 0x3f );
     86                 i += 2;
     87                 o++;
     88             } else if( ( src[ i ] & 0xf0 ) == 0xe0 ) {
     89                 /* U+0800 ... U+ffff */
     90                 /* 8[1110xxxx 10yyyyyy 10zzzzzz] -> 16BE[xxxxyyyy yyzzzzzz] */
     91                 if( src[ i + 1 ] == 0x00 || src[ i + 2 ] == 0x00 ) {
     92                     break;
     93                 }
     94                 dst_tmp[ 0 ] = ( ( src[ i + 0 ] & 0x0f ) << 4 ) | ( ( src[ i + 1 ] & 0x3f ) >> 2 );
     95                 dst_tmp[ 1 ] = ( ( src[ i + 1 ] & 0x3f ) << 6 ) |   ( src[ i + 2 ] & 0x3f );
     96                 i += 3;
     97                 o++;
     98             } else if( ( src[ i ] & 0xf8 ) == 0xf0 ) {
     99                 NJ_UINT8    dst1, dst2, dst3;
    100                 /* U+10000 ... U+10ffff */
    101                 /* 8[11110www 10xxxxxx 10yyyyyy 10zzzzzz] -> 32BE[00000000 000wwwxx xxxxyyyy yyzzzzzz] */
    102                 /*                                        -> 16BE[110110WW XXxxxxyy 110111yy yyzzzzzz] */
    103                 /*                                                      -- --======       == --------  */
    104                 /*                                                      dst1   dst2          dst3      */
    105                 /*                                        "wwwxx"(00001-10000) - 1 = "WWXX"(0000-1111) */
    106                 if( !( o < maxChars - 1 ) ) {
    107                     /* output buffer is full */
    108                     break;
    109                 }
    110                 if( src[ i + 1 ] == 0x00 || src[ i + 2 ] == 0x00 || src[ i + 3 ] == 0x00 ) {
    111                     break;
    112                 }
    113                 dst1 = ( ( ( src[ i + 0 ] & 0x07 ) << 2 ) | ( ( src[ i + 1 ] & 0x3f ) >> 4 ) ) - 1;
    114                 dst2 =   ( ( src[ i + 1 ] & 0x3f ) << 4 ) | ( ( src[ i + 2 ] & 0x3f ) >> 2 );
    115                 dst3 =   ( ( src[ i + 2 ] & 0x3f ) << 6 ) |   ( src[ i + 3 ] & 0x3f );
    116 
    117                 dst_tmp[ 0 ] = 0xd8 | ( ( dst1 & 0x0c ) >> 2 );
    118                 dst_tmp[ 1 ] =        ( ( dst1 & 0x03 ) << 6 ) | ( ( dst2 & 0xfc ) >> 2 );
    119                 dst_tmp[ 2 ] = 0xdc |                            ( ( dst2 & 0x03 ) );
    120                 dst_tmp[ 3 ] =                                                              dst3;
    121                 i += 4;
    122                 o += 2;
    123             } else {    /* Broken code */
    124                 break;
    125             }
    126         }
    127         dst[ o ] = NJ_CHAR_NUL;
    128 
    129 		( *env )->ReleaseStringUTFChars( env, srcJ, ( const char* )src );
    130 		return 0;
    131 	}
    132 	/* If retrieveing the string failed, return an error code */
    133 	return NJ_SET_ERR_VAL(NJ_FUNC_JNI_CONVERT_STR_TO_NJC, NJ_ERR_JNI_FUNC_FAILED);
    134 }
    135 
    136 static int convertNjCharToString( JNIEnv* env, jstring* dstJ, NJ_CHAR* src, int maxChars )
    137 {
    138     char        dst[ (NJ_MAX_LEN + NJ_MAX_RESULT_LEN + NJ_TERM_LEN ) * 3 + 1 ];
    139 
    140 	int		i, o;
    141 
    142 	/* convert UTF-16BE to a UTF-8 */
    143 	for( i = o = 0 ; src[ i ] != 0x0000 && i < maxChars ; ) {
    144 		NJ_UINT8* src_tmp;
    145 		src_tmp = ( NJ_UINT8* )&( src[ i ] );
    146 
    147         if( src_tmp[ 0 ] == 0x00 && src_tmp[ 1 ] <= 0x7f ) {
    148             /* U+0000 ... U+007f */
    149             /* 16BE[00000000 0xxxxxxx] -> 8[0xxxxxxx] */
    150             dst[ o + 0 ] = src_tmp[ 1 ] & 0x007f;
    151             i++;
    152             o++;
    153         } else if ( src_tmp[ 0 ] <= 0x07 ) {
    154             /* U+0080 ... U+07ff */
    155             /* 16BE[00000xxx xxyyyyyy] -> 8[110xxxxx 10yyyyyy] */
    156             dst[ o + 0 ] = 0xc0 | ( ( src_tmp[ 0 ] & 0x07 ) << 2 ) | ( ( src_tmp[ 1 ] & 0xc0 ) >> 6 );
    157             dst[ o + 1 ] = 0x80 |                                    ( ( src_tmp[ 1 ] & 0x3f ) );
    158             i++;
    159             o += 2;
    160         } else if ( src_tmp[ 0 ] >= 0xd8 && src_tmp[ 0 ] <= 0xdb ) {
    161             NJ_UINT8    src1, src2, src3;
    162             /* U+10000 ... U+10ffff (surrogate pair) */
    163             /* 32BE[00000000 000wwwxx xxxxyyyy yyzzzzzz] -> 8[11110www 10xxxxxx 10yyyyyy 10zzzzzz] */
    164             /* 16BE[110110WW XXxxxxyy 110111yy yyzzzzzz]                                           */
    165             /*            -- --======       == --------                                            */
    166             /*            src1 src2            src3                                                */
    167             /* "WWXX"(0000-1111) + 1 = "wwwxx"(0001-10000)                                         */
    168             if( !( i < maxChars - 1 ) || src_tmp[ 2 ] < 0xdc || src_tmp[ 2 ] > 0xdf ) {
    169                 /* That is broken code */
    170                 break;
    171             }
    172             src1 = ( ( ( src_tmp[ 0 ] & 0x03 ) << 2 ) | ( ( src_tmp[ 1 ] & 0xc0 ) >> 6 )                               ) + 1;
    173             src2 =                                      ( ( src_tmp[ 1 ] & 0x3f ) << 2 ) | ( ( src_tmp[ 2 ] & 0x03 ) );
    174             src3 =                                                                             src_tmp[ 3 ];
    175 
    176             dst[ o + 0 ] = 0xf0 | ( ( src1 & 0x1c ) >> 2 );
    177             dst[ o + 1 ] = 0x80 | ( ( src1 & 0x03 ) << 4 ) | ( ( src2 & 0xf0 ) >> 4 );
    178             dst[ o + 2 ] = 0x80 |                            ( ( src2 & 0x0f ) << 2 ) | ( ( src3 & 0xc0 ) >> 6 );
    179             dst[ o + 3 ] = 0x80 |                                                         ( src3 & 0x3f );
    180             i += 2;
    181             o += 4;
    182         } else {
    183             /* U+0800 ... U+ffff (except range of surrogate pair) */
    184             /* 16BE[xxxxyyyy yyzzzzzz] -> 8[1110xxxx 10yyyyyy 10zzzzzz] */
    185             dst[ o + 0 ] = 0xe0 | ( ( src_tmp[ 0 ] & 0xf0 ) >> 4 );
    186             dst[ o + 1 ] = 0x80 | ( ( src_tmp[ 0 ] & 0x0f ) << 2 ) | ( ( src_tmp[ 1 ] & 0xc0 ) >> 6  );
    187             dst[ o + 2 ] = 0x80 |                                    ( ( src_tmp[ 1 ] & 0x3f ) );
    188             i++;
    189             o += 3;
    190         }
    191 	}
    192 	dst[ o ] = 0x00;
    193 
    194 	*dstJ = ( *env )->NewStringUTF( env, dst );
    195 
    196 	/* If NewString() failed, return an error code */
    197 	return ( *dstJ == NULL ) ? NJ_SET_ERR_VAL(NJ_FUNC_JNI_CONVERT_NJC_TO_STR, NJ_ERR_JNI_FUNC_FAILED) : 0;
    198 }
    199 
    200 /*
    201  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
    202  * Method:    createWnnWork
    203  * Signature: (Ljava/lang/String;)J
    204  */
    205 JNIEXPORT jlong JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_createWnnWork
    206   (JNIEnv *env, jobject obj, jstring dicLibPathJ)
    207 {
    208 	NJ_JNIWORK*		work;
    209 
    210 	/* Allocating the internal work area */
    211 	work = ( NJ_JNIWORK* )malloc( sizeof( NJ_JNIWORK ) );
    212 	if( work != NULL ) {
    213 		NJ_UINT32*		dic_size;
    214 		NJ_UINT8*		dic_type;
    215         NJ_UINT8**      dic_data;
    216         NJ_UINT8**      con_data;
    217 		const char*		dicLibPath;
    218 		NJ_INT16		result;
    219 		int				i;
    220 
    221 		/* Initialize the work area */
    222 		memset( work, 0x00, sizeof( NJ_JNIWORK ) );
    223 
    224 		/* Load the dictionary library which is specified by dicLibPathJ */
    225 		if( dicLibPathJ == NULL ||
    226 			( dicLibPath = ( *env )->GetStringUTFChars( env, dicLibPathJ, 0 ) ) == NULL ) {
    227 			free( work );
    228 			return 0;
    229 		}
    230 
    231 		work->dicLibHandle = ( void* )dlopen( dicLibPath, RTLD_LAZY );
    232 		( *env )->ReleaseStringUTFChars( env, dicLibPathJ, dicLibPath );
    233 
    234 		if( work->dicLibHandle == NULL ) {
    235 			free( work );
    236 			return 0;
    237 		}
    238 
    239 		/* Retrieve data pointers of dictionary from the dictionary library, and put to internal work area */
    240 		dic_size = ( NJ_UINT32* )dlsym( work->dicLibHandle, "dic_size" );
    241 		dic_type = ( NJ_UINT8* )dlsym( work->dicLibHandle, "dic_type" );
    242         dic_data = ( NJ_UINT8** )dlsym( work->dicLibHandle, "dic_data" );
    243 		if( dic_size == NULL || dic_type == NULL || dic_data == NULL ) {
    244 			dlclose( work->dicLibHandle );
    245 			free( work );
    246 			return 0;
    247 		}
    248 
    249 		for( i = 0 ; i < NJ_MAX_DIC ; i++ ) {
    250             work->dicHandle[ i ]    = dic_data[ i ];
    251 			work->dicSize[ i ]      = dic_size[ i ];
    252 			work->dicType[ i ]      = dic_type[ i ];
    253 		}
    254 
    255         /* Set the rule dictionary if the rule data exist */
    256         con_data = ( NJ_UINT8** )dlsym( work->dicLibHandle, "con_data" );
    257         if( con_data != NULL ) {
    258             work->dicSet.rHandle[ NJ_MODE_TYPE_HENKAN ] = con_data[ 0 ];
    259         }
    260 
    261 		/* Execute the initialize method to initialize the internal work area */
    262 		result = njx_init( &( work->wnnClass ) );
    263 
    264 		if( result >= 0 ) {
    265             jlong   jresult;
    266 
    267             *( NJ_JNIWORK** )&jresult = work;
    268 			return jresult;
    269 		}
    270 
    271 		/* If allocating a byte array failed, free all resource, and return NULL */
    272 		dlclose( work->dicLibHandle );
    273 		free( work );
    274 	}
    275 	/* If allocating the internal work area failed, return NULL */
    276 	return 0;
    277 }
    278 
    279 /*
    280  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
    281  * Method:    freeWnnWork
    282  * Signature: (J)I
    283  */
    284 JNIEXPORT jint JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_freeWnnWork
    285   (JNIEnv *env, jobject obj, jlong wnnWork)
    286 {
    287 	NJ_JNIWORK*	work;
    288 
    289 	work = *( NJ_JNIWORK** )&wnnWork;
    290 	if( work != NULL ) {
    291 		/* If the internal work area was not yet released, remove that */
    292         if( work->dicLibHandle != NULL ) {
    293         	dlclose( work->dicLibHandle );
    294             work->dicLibHandle = NULL;
    295         }
    296 		free( work );
    297 
    298 		return 0;
    299 	}
    300 
    301 	/* freeWnnWork() is always successful even if the internal work area was already released */
    302 	return 0;
    303 }
    304 
    305 /*
    306  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
    307  * Method:    clearDictionaryParameters
    308  * Signature: (J)I
    309  */
    310 JNIEXPORT jint JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_clearDictionaryParameters
    311   (JNIEnv *env, jobject obj, jlong wnnWork)
    312 {
    313 	NJ_JNIWORK*	work;
    314 
    315 	work = *( NJ_JNIWORK** )&wnnWork;
    316 	if( work != NULL ) {
    317 		int				index;
    318 
    319 		/* Clear all dictionary set information structure and reset search state */
    320 		for( index = 0 ; index < NJ_MAX_DIC ; index++ ) {
    321     		clearDictionaryStructure( &( work->dicSet.dic[ index ] ) );
    322 		}
    323         work->flag = NJ_JNI_FLAG_NONE;
    324 
    325         /* Clear the cache information */
    326         memset( work->dicSet.keyword, 0x00, sizeof( work->dicSet.keyword ) );
    327 
    328 		return 0;
    329 	}
    330 
    331 	/* If the internal work area was already released, return an error code */
    332 	return NJ_SET_ERR_VAL(NJ_FUNC_JNI_CLEAR_DICTIONARY_PARAMETERS, NJ_ERR_NOT_ALLOCATED);
    333 }
    334 
    335 /*
    336  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
    337  * Method:    setDictionaryParameter
    338  * Signature: (JIII)I
    339  */
    340 JNIEXPORT jint JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_setDictionaryParameter
    341   (JNIEnv *env, jobject obj, jlong wnnWork, jint index, jint base, jint high)
    342 {
    343 	NJ_JNIWORK*	work;
    344 
    345 	if( ( index < 0  || index > NJ_MAX_DIC-1 ) ||
    346 		( base <  -1 || base > 1000 ) ||
    347 		( high <  -1 || high > 1000 ) ) {
    348 		/* If a invalid parameter was specified, return an error code */
    349 		return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SET_DICTIONARY_PARAMETERS, NJ_ERR_INVALID_PARAM);
    350 	}
    351 
    352 	work = *( NJ_JNIWORK** )&wnnWork;
    353 	if( work != NULL ) {
    354 		/* Create the dictionary set information structure */
    355 		if( base < 0 || high < 0 || base > high ) {
    356 			/* If -1 was specified to base or high, clear that dictionary information structure */
    357             /* If base is larger than high, clear that dictionary information structure */
    358     		clearDictionaryStructure( &( work->dicSet.dic[ index ] ) );
    359 		} else {
    360 			/* Set the dictionary informatin structure */
    361     		work->dicSet.dic[ index ].type		= work->dicType[ index ];
    362     		work->dicSet.dic[ index ].handle	= work->dicHandle[ index ];
    363     		work->dicSet.dic[ index ].srhCache	= &( work->srhCache[ index ] );
    364 
    365     		work->dicSet.dic[ index ].dic_freq[ NJ_MODE_TYPE_HENKAN ].base = base;
    366     		work->dicSet.dic[ index ].dic_freq[ NJ_MODE_TYPE_HENKAN ].high = high;
    367 		}
    368 
    369         /* Reset search state because the dicionary information was changed */
    370         work->flag = NJ_JNI_FLAG_NONE;
    371 
    372 		return 0;
    373 	}
    374 
    375 	/* If the internal work area was already released, return an error code */
    376 	return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SET_DICTIONARY_PARAMETERS, NJ_ERR_NOT_ALLOCATED);
    377 }
    378 
    379 /*
    380  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
    381  * Method:    searchWord
    382  * Signature: (JIILjava/lang/String;)I
    383  */
    384 JNIEXPORT jint JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_searchWord
    385   (JNIEnv *env, jobject obj, jlong wnnWork, jint operation, jint order, jstring keyString)
    386 {
    387 	NJ_JNIWORK*	work;
    388 
    389 	if( !( operation == jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_SEARCH_EXACT ||
    390            operation == jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_SEARCH_PREFIX ||
    391            operation == jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_SEARCH_LINK ) ||
    392 		!( order == jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_ORDER_BY_FREQUENCY ||
    393            order == jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_ORDER_BY_KEY ) ||
    394 		   keyString == NULL ) {
    395 		/* If a invalid parameter was specified, return an error code */
    396 		return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SEARCH_WORD, NJ_ERR_INVALID_PARAM);
    397 	}
    398 
    399 	work = *( NJ_JNIWORK** )&wnnWork;
    400 	if( work != NULL ) {
    401         if( ( *env )->GetStringLength( env, keyString ) > NJ_MAX_LEN ) {
    402             /* If too long key string was specified, return "No result is found" */
    403             work->flag &= ~NJ_JNI_FLAG_ENABLE_CURSOR;
    404             work->flag &= ~NJ_JNI_FLAG_ENABLE_RESULT;
    405             return 0;
    406         }
    407 
    408 		if( convertStringToNjChar( env, work->keyString, keyString, NJ_MAX_LEN ) >= 0 ) {
    409             jint    result;
    410 
    411 			/* Set the structure for search */
    412 			memset( &( work->cursor ), 0x00, sizeof( NJ_CURSOR ) );
    413 			work->cursor.cond.operation	= operation;
    414 			work->cursor.cond.mode		= order;
    415 			work->cursor.cond.ds		= &( work->dicSet );
    416 			work->cursor.cond.yomi		= work->keyString;
    417    			work->cursor.cond.charset	= &( work->approxSet );
    418 
    419             /* If the link search feature is specified, set the predict search information to structure */
    420             if( operation == jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_SEARCH_LINK ) {
    421                 work->cursor.cond.yomi  = work->previousStroke;
    422                 work->cursor.cond.kanji = work->previousCandidate;
    423             }
    424 
    425 			/* Search a specified word */
    426             memcpy( &( work->wnnClass.dic_set ), &( work->dicSet ), sizeof( NJ_DIC_SET ) );
    427 			result = ( jint )njx_search_word( &( work->wnnClass ), &( work->cursor ) );
    428 
    429             /* If a result is found, enable getNextWord method */
    430             if( result == 1 ) {
    431                 work->flag |= NJ_JNI_FLAG_ENABLE_CURSOR;
    432             } else {
    433                 work->flag &= ~NJ_JNI_FLAG_ENABLE_CURSOR;
    434             }
    435             work->flag &= ~NJ_JNI_FLAG_ENABLE_RESULT;
    436 
    437             return result;
    438 		}
    439 		/* If converting the string failed, return an error code */
    440 		return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SEARCH_WORD, NJ_ERR_INTERNAL);
    441 	}
    442 
    443 	/* If the internal work area was already released, return an error code */
    444 	return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SEARCH_WORD, NJ_ERR_NOT_ALLOCATED);
    445 }
    446 
    447 /*
    448  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
    449  * Method:    getNextWord
    450  * Signature: (JI)I
    451  */
    452 JNIEXPORT jint JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_getNextWord
    453   (JNIEnv *env, jclass obj, jlong wnnWork, jint length)
    454 {
    455 	NJ_JNIWORK*	work;
    456 
    457 	work = *( NJ_JNIWORK** )&wnnWork;
    458 	if( work != NULL ) {
    459         if( work->flag & NJ_JNI_FLAG_ENABLE_CURSOR ) {
    460             jint    result;
    461 
    462        		/* Get a specified word and search a next word */
    463             if( length <= 0 ) {
    464         		result = ( jint )njx_get_word( &( work->wnnClass ), &( work->cursor ), &( work->result ) );
    465             } else {
    466                 do {
    467             		result = ( jint )njx_get_word( &( work->wnnClass ), &( work->cursor ), &( work->result ) );
    468                     if( length == ( NJ_GET_YLEN_FROM_STEM( &( work->result.word ) ) + NJ_GET_YLEN_FROM_FZK( &( work->result.word ) ) ) ) {
    469                         break;
    470                     }
    471                 } while( result > 0 );
    472             }
    473 
    474             /* If a result is found, enable getStroke, getCandidate, getFrequency methods */
    475             if( result > 0 ) {
    476                 work->flag |= NJ_JNI_FLAG_ENABLE_RESULT;
    477             } else {
    478                 work->flag &= ~NJ_JNI_FLAG_ENABLE_RESULT;
    479             }
    480             return result;
    481         } else {
    482             /* When njx_search_word() was not yet called, return "No result is found" */
    483             return 0;
    484         }
    485 	}
    486 
    487 	/* If the internal work area was already released, return an error code */
    488 	return NJ_SET_ERR_VAL(NJ_FUNC_JNI_GET_WORD, NJ_ERR_NOT_ALLOCATED);
    489 }
    490 
    491 /*
    492  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
    493  * Method:    getStroke
    494  * Signature: (J)Ljava/lang/String;
    495  */
    496 JNIEXPORT jstring JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_getStroke
    497   (JNIEnv *env, jobject obj, jlong wnnWork)
    498 {
    499 	NJ_JNIWORK*	work;
    500 
    501 	work = *( NJ_JNIWORK** )&wnnWork;
    502 	if( work != NULL ) {
    503    		jstring		str;
    504 
    505         if( work->flag & NJ_JNI_FLAG_ENABLE_RESULT ) {
    506     		NJ_CHAR		stroke[ NJ_MAX_LEN + NJ_TERM_LEN ];
    507 
    508     		if( njx_get_stroke( &( work->wnnClass ), &( work->result ), stroke, sizeof( NJ_CHAR ) * ( NJ_MAX_LEN + NJ_TERM_LEN ) ) >= 0 &&
    509     			convertNjCharToString( env, &str, stroke, NJ_MAX_LEN ) >= 0 ) {
    510     			return str;
    511     		}
    512         } else {
    513             /* When njx_get_word() was not yet called, return "No result is found" */
    514             if( convertNjCharToString( env, &str, ( NJ_CHAR* )"\x00\x00", NJ_MAX_LEN ) >= 0 ) {
    515                 return str;
    516             }
    517         }
    518 	}
    519 
    520 	/* If the internal work area was already released, return an error status */
    521 	return NULL;
    522 }
    523 
    524 /*
    525  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
    526  * Method:    getCandidate
    527  * Signature: (J)Ljava/lang/String;
    528  */
    529 JNIEXPORT jstring JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_getCandidate
    530   (JNIEnv *env, jobject obj, jlong wnnWork)
    531 {
    532 	NJ_JNIWORK*	work;
    533 
    534 	work = *( NJ_JNIWORK** )&wnnWork;
    535 	if( work != NULL ) {
    536    		jstring		str;
    537 
    538         if( work->flag & NJ_JNI_FLAG_ENABLE_RESULT ) {
    539     		NJ_CHAR		candidate[ NJ_MAX_LEN + NJ_TERM_LEN ];
    540 
    541     		if( njx_get_candidate( &( work->wnnClass ), &( work->result ), candidate, sizeof( NJ_CHAR ) * ( NJ_MAX_RESULT_LEN + NJ_TERM_LEN ) ) >= 0 &&
    542     			convertNjCharToString( env, &str, candidate, NJ_MAX_RESULT_LEN ) >= 0 ) {
    543     			return str;
    544             }
    545         } else {
    546             /* When njx_get_word() was not yet called, return "No result is found" */
    547             if( convertNjCharToString( env, &str, ( NJ_CHAR* )"\x00\x00", NJ_MAX_RESULT_LEN ) >= 0 ) {
    548                 return str;
    549             }
    550         }
    551 	}
    552 
    553 	/* If the internal work area was already released, return an error status */
    554 	return NULL;
    555 }
    556 
    557 /*
    558  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
    559  * Method:    getFrequency
    560  * Signature: (J)I
    561  */
    562 JNIEXPORT jint JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_getFrequency
    563   (JNIEnv *env, jobject obj, jlong wnnWork)
    564 {
    565 	NJ_JNIWORK*	work;
    566 
    567 	work = *( NJ_JNIWORK** )&wnnWork;
    568 	if( work != NULL ) {
    569         if( work->flag & NJ_JNI_FLAG_ENABLE_RESULT ) {
    570     		return ( jint )( work->result.word.stem.hindo );
    571         } else {
    572             /* When njx_get_word() was not yet called, return "No result is found" */
    573             return 0;
    574         }
    575 	}
    576 
    577 	/* If the internal work area was already released, return an error code */
    578 	return NJ_SET_ERR_VAL(NJ_FUNC_JNI_GET_FREQUENCY, NJ_ERR_NOT_ALLOCATED);
    579 }
    580 
    581 /*
    582  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
    583  * Method:    clearApproxPatterns
    584  * Signature: (J)V
    585  */
    586 JNIEXPORT void JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_clearApproxPatterns
    587   (JNIEnv *env, jobject obj, jlong wnnWork)
    588 {
    589 	NJ_JNIWORK*	work;
    590 
    591 	work = *( NJ_JNIWORK** )&wnnWork;
    592 	if( work != NULL ) {
    593 		int			i;
    594 
    595         /* Clear state */
    596         work->flag = NJ_JNI_FLAG_NONE;
    597 
    598         /* Clear approximate patterns */
    599 		work->approxSet.charset_count = 0;
    600 		for( i = 0 ; i < NJ_MAX_CHARSET ; i++ ) {
    601 			work->approxSet.from[ i ] = NULL;
    602 			work->approxSet.to[ i ]   = NULL;
    603 		}
    604 
    605         /* Clear the cache information */
    606         memset( work->dicSet.keyword, 0x00, sizeof( work->dicSet.keyword ) );
    607 	}
    608 }
    609 
    610 /*
    611  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
    612  * Method:    setApproxPattern
    613  * Signature: (JLjava/lang/String;Ljava/lang/String;)I
    614  */
    615 JNIEXPORT jint JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_setApproxPattern__JLjava_lang_String_2Ljava_lang_String_2
    616   (JNIEnv *env, jobject obj, jlong wnnWork, jstring srcJ, jstring dstJ)
    617 {
    618 	NJ_JNIWORK*	work;
    619 
    620 	if( srcJ == NULL || ( *env )->GetStringLength( env, srcJ ) == 0 || ( *env )->GetStringLength( env, srcJ ) > 1 ||
    621 		dstJ == NULL || ( *env )->GetStringLength( env, dstJ ) == 0 || ( *env )->GetStringLength( env, dstJ ) > 3 ) {
    622 		/* If a invalid parameter was specified, return an error code */
    623 		return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SET_APPROX_PATTERN, NJ_ERR_INVALID_PARAM);
    624 	}
    625 
    626 	work = *( NJ_JNIWORK** )&wnnWork;
    627 	if( work != NULL ) {
    628 		if( work->approxSet.charset_count < NJ_MAX_CHARSET ) {
    629 			NJ_CHAR*		from;
    630 			NJ_CHAR*		to;
    631 
    632 			/* Set pointers of string to store approximate informations */
    633 			from = work->approxStr + NJ_APPROXSTORE_SIZE * work->approxSet.charset_count;
    634 			to   = work->approxStr + NJ_APPROXSTORE_SIZE * work->approxSet.charset_count + NJ_MAX_CHARSET_FROM_LEN + NJ_TERM_LEN;
    635 			work->approxSet.from[ work->approxSet.charset_count ] = from;
    636 			work->approxSet.to[ work->approxSet.charset_count ]   = to;
    637 
    638 			/* Convert approximate informations to internal format */
    639 			if( convertStringToNjChar( env, from, srcJ, NJ_MAX_CHARSET_FROM_LEN ) >= 0 &&
    640 				convertStringToNjChar( env, to, dstJ, NJ_MAX_CHARSET_TO_LEN )   >= 0 ) {
    641 				work->approxSet.charset_count++;
    642 
    643                 /* Reset search state because the seach condition was changed */
    644                 work->flag = NJ_JNI_FLAG_NONE;
    645 
    646 				return 0;
    647 			}
    648 
    649 			/* If converting informations failed, reset pointers, and return an error code */
    650 			work->approxSet.from[ work->approxSet.charset_count ] = NULL;
    651 			work->approxSet.to[ work->approxSet.charset_count ]   = NULL;
    652 			return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SET_APPROX_PATTERN, NJ_ERR_INTERNAL);
    653 		}
    654 		/* If the approx pattern registration area was full, return an error code */
    655 		return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SET_APPROX_PATTERN, NJ_ERR_APPROX_PATTERN_IS_FULL);
    656 	}
    657 
    658 	/* If the internal work area was already released, return an error code */
    659 	return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SET_APPROX_PATTERN, NJ_ERR_NOT_ALLOCATED);
    660 }
    661 
    662 /*
    663  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
    664  * Method:    setApproxPattern
    665  * Signature: (JI)I
    666  */
    667 JNIEXPORT jint JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_setApproxPattern__JI
    668   (JNIEnv *env, jclass obj, jlong wnnWork, jint approxPattern)
    669 {
    670 	NJ_JNIWORK	*work;
    671 
    672 	if( !( approxPattern == jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_APPROX_PATTERN_EN_TOUPPER ||
    673 		   approxPattern == jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_APPROX_PATTERN_EN_TOLOWER ||
    674 		   approxPattern == jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_APPROX_PATTERN_EN_QWERTY_NEAR ||
    675 		   approxPattern == jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_APPROX_PATTERN_EN_QWERTY_NEAR_UPPER ||
    676 		   approxPattern == jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_APPROX_PATTERN_JAJP_12KEY_NORMAL ) ) {
    677 		/* If a invalid parameter was specified, return an error code */
    678 		return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SET_APPROX_PATTERN, NJ_ERR_INVALID_PARAM);
    679 	}
    680 
    681 	work = *( NJ_JNIWORK** )&wnnWork;
    682 	if( work != NULL ) {
    683 		const PREDEF_APPROX_PATTERN*	pattern;
    684 
    685         pattern = predefinedApproxPatterns[ approxPattern ];
    686 		if( work->approxSet.charset_count + pattern->size <= NJ_MAX_CHARSET ) {
    687 			int     i;
    688 
    689 			for( i = 0 ; i < pattern->size ; i++ ) {
    690 				NJ_CHAR*    from;
    691 				NJ_CHAR*    to;
    692 
    693 				/* Set pointers of string to store approximate informations */
    694 				from = work->approxStr + NJ_APPROXSTORE_SIZE * ( work->approxSet.charset_count + i );
    695 				to   = work->approxStr + NJ_APPROXSTORE_SIZE * ( work->approxSet.charset_count + i ) + NJ_MAX_CHARSET_FROM_LEN + NJ_TERM_LEN;
    696 				work->approxSet.from[ work->approxSet.charset_count + i ] = from;
    697 				work->approxSet.to[ work->approxSet.charset_count + i ]   = to;
    698 
    699 				/* Set approximate pattern */
    700 				from[ 0 ] = convertUTFCharToNjChar( pattern->from + i * 2 );    /* "2" means the size of UTF-16BE */
    701 				from[ 1 ] = 0x0000;
    702 
    703 				to[ 0 ] = convertUTFCharToNjChar( pattern->to + i * 2 );        /* "2" means the size of UTF-16BE */
    704 				to[ 1 ] = 0x0000;
    705 			}
    706 			work->approxSet.charset_count += pattern->size;
    707 
    708             /* Reset search state because the seach condition was changed */
    709             work->flag = NJ_JNI_FLAG_NONE;
    710 
    711 			return 0;
    712 		}
    713 		/* If the approx pattern registration area was full, return an error code */
    714 		return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SET_APPROX_PATTERN, NJ_ERR_APPROX_PATTERN_IS_FULL);
    715 	}
    716 
    717 	/* If the internal work area was already released, return an error code */
    718 	return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SET_APPROX_PATTERN, NJ_ERR_NOT_ALLOCATED);
    719 }
    720 
    721 /*
    722  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
    723  * Method:    getLeftPartOfSpeech
    724  * Signature: (J)I
    725  */
    726 JNIEXPORT jint JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_getLeftPartOfSpeech
    727   (JNIEnv *env, jclass obj, jlong wnnWork)
    728 {
    729 	NJ_JNIWORK*	work;
    730 
    731 	work = *( NJ_JNIWORK** )&wnnWork;
    732 	if( work != NULL ) {
    733         return NJ_GET_FPOS_FROM_STEM( &( work->result.word ) );
    734     }
    735 
    736 	/* If the internal work area was already released, return an error code */
    737 	return NJ_SET_ERR_VAL(NJ_FUNC_JNI_GET_LEFT_PART_OF_SPEECH, NJ_ERR_NOT_ALLOCATED);
    738 }
    739 
    740 /*
    741  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
    742  * Method:    getRightPartOfSpeech
    743  * Signature: (J)I
    744  */
    745 JNIEXPORT jint JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_getRightPartOfSpeech
    746   (JNIEnv *env, jclass obj, jlong wnnWork)
    747 {
    748 	NJ_JNIWORK*	work;
    749 
    750 	work = *( NJ_JNIWORK** )&wnnWork;
    751 	if( work != NULL ) {
    752         return NJ_GET_BPOS_FROM_STEM( &( work->result.word ) );
    753     }
    754 
    755 	/* If the internal work area was already released, return an error code */
    756 	return NJ_SET_ERR_VAL(NJ_FUNC_JNI_GET_RIGHT_PART_OF_SPEECH, NJ_ERR_NOT_ALLOCATED);
    757 }
    758 
    759 /*
    760  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
    761  * Method:    clearResult
    762  * Signature: (J)V
    763  */
    764 JNIEXPORT void JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_clearResult
    765   (JNIEnv *env, jclass obj, jlong wnnWork)
    766 {
    767 	NJ_JNIWORK*	work;
    768 
    769 	work = *( NJ_JNIWORK** )&wnnWork;
    770 	if( work != NULL ) {
    771         /* Clear the current word information */
    772         memset( &( work->result ), 0x00, sizeof( NJ_RESULT ) );
    773         memset( &( work->previousStroke ), 0x00, sizeof( work->previousStroke ) );
    774         memset( &( work->previousCandidate ), 0x00, sizeof( work->previousCandidate ) );
    775     }
    776 
    777     /* In this method, No error reports. */
    778 }
    779 
    780 /*
    781  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
    782  * Method:    setLeftPartOfSpeech
    783  * Signature: (JI)I
    784  */
    785 JNIEXPORT jint JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_setLeftPartOfSpeech
    786   (JNIEnv *env, jclass obj, jlong wnnWork, jint leftPartOfSpeech)
    787 {
    788 	NJ_JNIWORK*	work;
    789 
    790 	work = *( NJ_JNIWORK** )&wnnWork;
    791 	if( work != NULL ) {
    792         NJ_UINT16   lcount = 0, rcount = 0;
    793 
    794         if( work->dicSet.rHandle[ NJ_MODE_TYPE_HENKAN ] == NULL ) {
    795             /* No rule dictionary was set */
    796         	return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SET_LEFT_PART_OF_SPEECH, NJ_ERR_NO_RULEDIC);
    797         }
    798 
    799         njd_r_get_count( work->dicSet.rHandle[ NJ_MODE_TYPE_HENKAN ], &lcount, &rcount );
    800 
    801         if( leftPartOfSpeech < 1 || leftPartOfSpeech > lcount ) {
    802     		/* If a invalid parameter was specified, return an error code */
    803     		return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SET_LEFT_PART_OF_SPEECH, NJ_ERR_INVALID_PARAM);
    804         }
    805 
    806         NJ_SET_FPOS_TO_STEM( &( work->result.word ), leftPartOfSpeech );
    807         return 0;
    808     }
    809 
    810 	/* If the internal work area was already released, return an error code */
    811 	return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SET_LEFT_PART_OF_SPEECH, NJ_ERR_NOT_ALLOCATED);
    812 }
    813 
    814 /*
    815  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
    816  * Method:    setRightPartOfSpeech
    817  * Signature: (JI)I
    818  */
    819 JNIEXPORT jint JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_setRightPartOfSpeech
    820   (JNIEnv *env, jclass obj, jlong wnnWork, jint rightPartOfSpeech)
    821 {
    822 	NJ_JNIWORK*	work;
    823 
    824 	work = *( NJ_JNIWORK** )&wnnWork;
    825 	if( work != NULL ) {
    826         NJ_UINT16   lcount = 0, rcount = 0;
    827 
    828         if( work->dicSet.rHandle[ NJ_MODE_TYPE_HENKAN ] == NULL ) {
    829             /* No rule dictionary was set */
    830         	return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SET_RIGHT_PART_OF_SPEECH, NJ_ERR_NO_RULEDIC);
    831         }
    832 
    833         njd_r_get_count( work->dicSet.rHandle[ NJ_MODE_TYPE_HENKAN ], &lcount, &rcount );
    834 
    835         if( rightPartOfSpeech < 1 || rightPartOfSpeech > rcount ) {
    836     		/* If a invalid parameter was specified, return an error code */
    837     		return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SET_RIGHT_PART_OF_SPEECH, NJ_ERR_INVALID_PARAM);
    838         }
    839 
    840         NJ_SET_BPOS_TO_STEM( &( work->result.word ), rightPartOfSpeech );
    841         return 0;
    842     }
    843 
    844 	/* If the internal work area was already released, return an error code */
    845 	return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SET_RIGHT_PART_OF_SPEECH, NJ_ERR_NOT_ALLOCATED);
    846 }
    847 
    848 /*
    849  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
    850  * Method:    setStroke
    851  * Signature: (JLjava/lang/String;)I
    852  */
    853 JNIEXPORT jint JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_setStroke
    854   (JNIEnv *env, jclass obj, jlong wnnWork, jstring stroke)
    855 {
    856 	NJ_JNIWORK*	work;
    857 
    858     if( stroke == NULL ) {
    859 		/* If a invalid parameter was specified, return an error code */
    860 		return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SET_STROKE, NJ_ERR_INVALID_PARAM);
    861     }
    862 
    863 	work = *( NJ_JNIWORK** )&wnnWork;
    864 	if( work != NULL ) {
    865         if( ( *env )->GetStringLength( env, stroke ) > NJ_MAX_LEN ) {
    866     		/* If a invalid parameter was specified, return an error code */
    867         	return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SET_STROKE, NJ_ERR_YOMI_TOO_LONG);
    868         }
    869 
    870         /* Store stroke string */
    871 		if( convertStringToNjChar( env, work->previousStroke, stroke, NJ_MAX_LEN ) >= 0 ) {
    872             return 0;
    873         }
    874 
    875 		/* If converting the string failed, return an error code */
    876 		return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SET_STROKE, NJ_ERR_INTERNAL);
    877     }
    878 
    879 	/* If the internal work area was already released, return an error code */
    880 	return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SET_STROKE, NJ_ERR_NOT_ALLOCATED);
    881 }
    882 
    883 /*
    884  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
    885  * Method:    setCandidate
    886  * Signature: (JLjava/lang/String;)I
    887  */
    888 JNIEXPORT jint JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_setCandidate
    889   (JNIEnv *env, jclass obj, jlong wnnWork, jstring candidate)
    890 {
    891 	NJ_JNIWORK*	work;
    892 
    893     if( candidate == NULL ) {
    894 		/* If a invalid parameter was specified, return an error code */
    895 		return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SET_CANDIDATE, NJ_ERR_INVALID_PARAM);
    896     }
    897 
    898 	work = *( NJ_JNIWORK** )&wnnWork;
    899 	if( work != NULL ) {
    900         if( ( *env )->GetStringLength( env, candidate ) > NJ_MAX_RESULT_LEN ) {
    901     		/* If a invalid parameter was specified, return an error code */
    902         	return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SET_CANDIDATE, NJ_ERR_CANDIDATE_TOO_LONG);
    903         }
    904 
    905         /* Store candidate string */
    906 		if( convertStringToNjChar( env, work->previousCandidate, candidate, NJ_MAX_RESULT_LEN ) >= 0 ) {
    907             return 0;
    908         }
    909 
    910 		/* If converting the string failed, return an error code */
    911 		return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SET_CANDIDATE, NJ_ERR_INTERNAL);
    912     }
    913 
    914 	/* If the internal work area was already released, return an error code */
    915 	return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SET_CANDIDATE, NJ_ERR_NOT_ALLOCATED);
    916 }
    917 
    918 /*
    919  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
    920  * Method:    selectWord
    921  * Signature: (J)I
    922  */
    923 JNIEXPORT jint JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_selectWord
    924   (JNIEnv *env, jclass obj, jlong wnnWork)
    925 {
    926 	NJ_JNIWORK*	work;
    927 
    928 	work = *( NJ_JNIWORK** )&wnnWork;
    929 	if( work != NULL ) {
    930         /* Put the previous word information to engine */
    931         memcpy( &( work->wnnClass.dic_set ), &( work->dicSet ), sizeof( NJ_DIC_SET ) );
    932         return ( jint )njx_select( &( work->wnnClass ), &( work->result ) );
    933     }
    934 
    935 	/* If the internal work area was already released, return an error code */
    936 	return NJ_SET_ERR_VAL(NJ_FUNC_JNI_SELECT_WORD, NJ_ERR_NOT_ALLOCATED);
    937 }
    938 
    939 /*
    940  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
    941  * Method:    getLeftPartOfSpeechSpecifiedType
    942  * Signature: (JI)I
    943  */
    944 JNIEXPORT jint JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_getLeftPartOfSpeechSpecifiedType
    945   (JNIEnv *env, jclass obj, jlong wnnWork, jint type)
    946 {
    947 	NJ_JNIWORK*	work;
    948 
    949 	work = *( NJ_JNIWORK** )&wnnWork;
    950 	if( work != NULL ) {
    951         switch( type ) {
    952         case jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_POS_TYPE_V1:
    953             type = NJ_HINSI_V1_F;
    954             break;
    955         case jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_POS_TYPE_V2:
    956             type = NJ_HINSI_V2_F;
    957             break;
    958         case jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_POS_TYPE_V3:
    959             type = NJ_HINSI_V3_F;
    960             break;
    961         case jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_POS_TYPE_BUNTOU:
    962     		/* No part of speech is defined at this type */
    963             return 0;
    964         case jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_POS_TYPE_TANKANJI:
    965             type = NJ_HINSI_TANKANJI_F;
    966             break;
    967         case jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_POS_TYPE_SUUJI:
    968     		/* No part of speech is defined at this type */
    969             return 0;
    970         case jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_POS_TYPE_MEISI:
    971             type = NJ_HINSI_MEISI_F;
    972             break;
    973         case jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_POS_TYPE_JINMEI:
    974             type = NJ_HINSI_JINMEI_F;
    975             break;
    976         case jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_POS_TYPE_CHIMEI:
    977             type = NJ_HINSI_CHIMEI_F;
    978             break;
    979         case jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_POS_TYPE_KIGOU:
    980             type = NJ_HINSI_KIGOU_F;
    981             break;
    982         default:
    983     		/* If a invalid parameter was specified, return an error code */
    984         	return NJ_SET_ERR_VAL(NJ_FUNC_JNI_GET_LEFT_PART_OF_SPEECH_SPECIFIED_TYPE, NJ_ERR_INVALID_PARAM);
    985         }
    986         return ( jint )njd_r_get_hinsi( work->dicSet.rHandle[ NJ_MODE_TYPE_HENKAN ], type );
    987     }
    988 
    989 	/* If the internal work area was already released, return an error code */
    990 	return NJ_SET_ERR_VAL(NJ_FUNC_JNI_GET_LEFT_PART_OF_SPEECH_SPECIFIED_TYPE, NJ_ERR_NOT_ALLOCATED);
    991 }
    992 
    993 /*
    994  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
    995  * Method:    getRightPartOfSpeechSpecifiedType
    996  * Signature: (JI)I
    997  */
    998 JNIEXPORT jint JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_getRightPartOfSpeechSpecifiedType
    999   (JNIEnv *env, jclass obj, jlong wnnWork, jint type)
   1000 {
   1001 	NJ_JNIWORK*	work;
   1002 
   1003 	work = *( NJ_JNIWORK** )&wnnWork;
   1004 	if( work != NULL ) {
   1005         switch( type ) {
   1006         case jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_POS_TYPE_V1:
   1007     		/* No part of speech is defined at this type */
   1008             return 0;
   1009         case jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_POS_TYPE_V2:
   1010     		/* No part of speech is defined at this type */
   1011             return 0;
   1012         case jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_POS_TYPE_V3:
   1013     		/* No part of speech is defined at this type */
   1014             return 0;
   1015         case jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_POS_TYPE_BUNTOU:
   1016             type = NJ_HINSI_BUNTOU_B;
   1017             break;
   1018         case jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_POS_TYPE_TANKANJI:
   1019             type = NJ_HINSI_TANKANJI_B;
   1020             break;
   1021         case jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_POS_TYPE_SUUJI:
   1022             type = NJ_HINSI_SUUJI_B;
   1023             break;
   1024         case jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_POS_TYPE_MEISI:
   1025             type = NJ_HINSI_MEISI_B;
   1026             break;
   1027         case jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_POS_TYPE_JINMEI:
   1028             type = NJ_HINSI_JINMEI_B;
   1029             break;
   1030         case jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_POS_TYPE_CHIMEI:
   1031             type = NJ_HINSI_CHIMEI_B;
   1032             break;
   1033         case jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_POS_TYPE_KIGOU:
   1034             type = NJ_HINSI_KIGOU_B;
   1035             break;
   1036         default:
   1037     		/* If a invalid parameter was specified, return an error code */
   1038         	return NJ_SET_ERR_VAL(NJ_FUNC_JNI_GET_LEFT_PART_OF_SPEECH_SPECIFIED_TYPE, NJ_ERR_INVALID_PARAM);
   1039         }
   1040         return ( jint )njd_r_get_hinsi( work->dicSet.rHandle[ NJ_MODE_TYPE_HENKAN ], type );
   1041     }
   1042 
   1043 	/* If the internal work area was already released, return an error code */
   1044 	return NJ_SET_ERR_VAL(NJ_FUNC_JNI_GET_RIGHT_PART_OF_SPEECH_SPECIFIED_TYPE, NJ_ERR_NOT_ALLOCATED);
   1045 }
   1046 
   1047 /*
   1048  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
   1049  * Method:    getConnectArray
   1050  * Signature: (JI)[B
   1051  */
   1052 JNIEXPORT jbyteArray JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_getConnectArray
   1053   (JNIEnv *env, jclass obj, jlong wnnWork, jint leftPartOfSpeech)
   1054 {
   1055 	NJ_JNIWORK*	work;
   1056 
   1057 	work = *( NJ_JNIWORK** )&wnnWork;
   1058 	if( work != NULL ) {
   1059         NJ_UINT16   lcount = 0, rcount = 0;
   1060         jbyteArray  resultJ;
   1061 
   1062         if( work->dicSet.rHandle[ NJ_MODE_TYPE_HENKAN ] == NULL ) {
   1063             /* No rule dictionary was set */
   1064         	return NULL;
   1065         }
   1066 
   1067         njd_r_get_count( work->dicSet.rHandle[ NJ_MODE_TYPE_HENKAN ], &lcount, &rcount );
   1068 
   1069         if( leftPartOfSpeech < 0 || leftPartOfSpeech > lcount ) {
   1070             /* Invalid POS is specified */
   1071             return NULL;
   1072         }
   1073 
   1074         /* 1-origin */
   1075         resultJ = ( *env )->NewByteArray( env, rcount + 1 );
   1076 
   1077         if( resultJ != NULL ) {
   1078             jbyte   *result;
   1079             result = ( *env )->GetByteArrayElements( env, resultJ, NULL );
   1080 
   1081             if( result != NULL ) {
   1082                 int         i;
   1083                 NJ_UINT8*   connect;
   1084 
   1085                 if( leftPartOfSpeech == 0 ) {
   1086                     for( i = 0 ; i < rcount + 1 ; i++ ) {
   1087                         result[ i ] = 0;
   1088                     }
   1089                 } else {
   1090                     /* Get the packed connect array */
   1091                     njd_r_get_connect( work->dicSet.rHandle[ NJ_MODE_TYPE_HENKAN ], leftPartOfSpeech, NJ_RULE_TYPE_FTOB, &connect );
   1092 
   1093                     /* Extract connect array from bit field */
   1094                     result[ 0 ] = 0;
   1095 
   1096                     for( i = 0 ; i < rcount ; i++ ) {
   1097                         if( connect[ i / 8 ] & (0x80 >> (i % 8))) {
   1098                             result[ i + 1 ] = 1;
   1099                         } else {
   1100                             result[ i + 1 ] = 0;
   1101                         }
   1102                     }
   1103                 }
   1104 
   1105                 ( *env )->ReleaseByteArrayElements( env, resultJ, result, 0 );
   1106                 return resultJ;
   1107             }
   1108         }
   1109 		/* If allocating the return area failed, return an error code */
   1110        	return NULL;
   1111     }
   1112 	/* If the internal work area was already released, return an error code */
   1113     return NULL;
   1114 }
   1115 
   1116 /*
   1117  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
   1118  * Method:    getNumberOfLeftPOS
   1119  * Signature: (J)I
   1120  */
   1121 JNIEXPORT jint JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_getNumberOfLeftPOS
   1122   (JNIEnv *env, jclass obj, jlong wnnWork)
   1123 {
   1124 	NJ_JNIWORK*	work;
   1125 
   1126 	work = *( NJ_JNIWORK** )&wnnWork;
   1127 	if( work != NULL ) {
   1128         if( work->dicSet.rHandle[ NJ_MODE_TYPE_HENKAN ] == NULL ) {
   1129             /* No rule dictionary was set */
   1130             return 0;
   1131         } else {
   1132             NJ_UINT16   lcount = 0, rcount = 0;
   1133 
   1134             njd_r_get_count( work->dicSet.rHandle[ NJ_MODE_TYPE_HENKAN ], &lcount, &rcount );
   1135             return lcount;
   1136         }
   1137     }
   1138 
   1139 	/* If the internal work area was already released, return an error code */
   1140 	return NJ_SET_ERR_VAL(NJ_FUNC_JNI_GET_NUMBER_OF_LEFT_POS, NJ_ERR_NOT_ALLOCATED);
   1141 }
   1142 
   1143 /*
   1144  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
   1145  * Method:    getNumberOfRightPOS
   1146  * Signature: (J)I
   1147  */
   1148 JNIEXPORT jint JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_getNumberOfRightPOS
   1149   (JNIEnv *env, jclass obj, jlong wnnWork)
   1150 {
   1151 	NJ_JNIWORK*	work;
   1152 
   1153 	work = *( NJ_JNIWORK** )&wnnWork;
   1154 	if( work != NULL ) {
   1155         if( work->dicSet.rHandle[ NJ_MODE_TYPE_HENKAN ] == NULL ) {
   1156             /* No rule dictionary was set */
   1157             return 0;
   1158         } else {
   1159             NJ_UINT16   lcount = 0, rcount = 0;
   1160 
   1161             njd_r_get_count( work->dicSet.rHandle[ NJ_MODE_TYPE_HENKAN ], &lcount, &rcount );
   1162             return rcount;
   1163         }
   1164     }
   1165 
   1166 	/* If the internal work area was already released, return an error code */
   1167 	return NJ_SET_ERR_VAL(NJ_FUNC_JNI_GET_NUMBER_OF_RIGHT_POS, NJ_ERR_NOT_ALLOCATED);
   1168 }
   1169 
   1170 /*
   1171  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
   1172  * Method:    getApproxPattern
   1173  * Signature: (JLjava/lang/String;)[Ljava/lang/String;
   1174  */
   1175 JNIEXPORT jobjectArray JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_getApproxPattern
   1176   (JNIEnv *env, jclass obj, jlong wnnWork, jstring srcJ)
   1177 {
   1178 	NJ_JNIWORK*	work;
   1179 
   1180 	if( srcJ == NULL || ( *env )->GetStringLength( env, srcJ ) == 0 || ( *env )->GetStringLength( env, srcJ ) > 1 ) {
   1181 		/* If a invalid parameter was specified, return an error code */
   1182 		return NULL;
   1183 	}
   1184 
   1185 	work = *( NJ_JNIWORK** )&wnnWork;
   1186 	if( work != NULL ) {
   1187         int         i, outIndex, outCount;
   1188         NJ_CHAR     from[ NJ_MAX_CHARSET_FROM_LEN + NJ_TERM_LEN ];
   1189 
   1190         if( convertStringToNjChar( env, from, srcJ, NJ_MAX_CHARSET_FROM_LEN ) >= 0 ) {
   1191             outCount = 0;
   1192             for( i = 0 ; i < work->approxSet.charset_count ; i++ ) {
   1193                 if( nj_strcmp( from, work->approxSet.from[ i ] ) == 0 ) {
   1194                     outCount++;
   1195                 }
   1196             }
   1197 
   1198             jclass strC = ( *env )->FindClass( env, "java/lang/String" );
   1199 
   1200             if( strC != NULL ) {
   1201                 jobjectArray retJ = ( *env )->NewObjectArray( env, outCount, strC, NULL );
   1202 
   1203                 if( retJ != NULL ) {
   1204                     for( i = outIndex = 0 ; i < work->approxSet.charset_count ; i++ ) {
   1205                         if( nj_strcmp( from, work->approxSet.from[ i ] ) == 0 ) {
   1206                             jstring dstJ;
   1207 
   1208                             if( convertNjCharToString( env, &dstJ, work->approxSet.to[ i ], NJ_MAX_CHARSET_TO_LEN ) < 0 ) {
   1209                                 return NULL;
   1210                             }
   1211 
   1212                             ( *env )->SetObjectArrayElement( env, retJ, outIndex++, dstJ );
   1213                         }
   1214 
   1215                     }
   1216                     return retJ;
   1217                 }
   1218             }
   1219         }
   1220         /* If the internal error occured, return an error code */
   1221         return NULL;
   1222     }
   1223 
   1224 	/* If the internal work area was already released, return an error code */
   1225 	return NULL;
   1226 }
   1227 
   1228 /*
   1229  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
   1230  * Method:    createBindArray
   1231  * Signature: (JLjava/lang/String;II)[Ljava/lang/String;
   1232  */
   1233 JNIEXPORT jobjectArray JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_createBindArray
   1234   (JNIEnv *env, jclass obj, jlong wnnWork, jstring keyStringJ, jint maxBindsOfQuery, jint maxPatternOfApprox)
   1235 {
   1236 	NJ_JNIWORK*	work;
   1237 
   1238 	if( keyStringJ == NULL ) {
   1239 		/* If a invalid parameter was specified, return an error code */
   1240 		return NULL;
   1241 	}
   1242 
   1243 	work = *( NJ_JNIWORK** )&wnnWork;
   1244 	if( work != NULL ) {
   1245         /* create the string array for result */
   1246         jclass strC = ( *env )->FindClass( env, "java/lang/String" );
   1247 
   1248         if( strC != NULL ) {
   1249             jobjectArray retJ = ( *env )->NewObjectArray( env, maxBindsOfQuery * (maxPatternOfApprox+1), strC, NULL );
   1250 
   1251             if( retJ != NULL ) {
   1252                 NJ_CHAR     keyString[ NJ_MAX_LEN + NJ_TERM_LEN ];
   1253 
   1254                 if( convertStringToNjChar( env, keyString, keyStringJ, NJ_MAX_LEN ) >= 0 ) {
   1255                     int         queryLen, outIndex, approxPattern;
   1256                     NJ_CHAR     baseStr[ NJ_MAX_LEN + NJ_MAX_CHARSET_TO_LEN + NJ_TERM_LEN ];
   1257 
   1258                     outIndex = 0;
   1259                     baseStr[ 0 ] = NJ_CHAR_NUL;
   1260 
   1261                     for( queryLen = 0 ; queryLen < maxBindsOfQuery && keyString[ queryLen ] != NJ_CHAR_NUL ; queryLen++ ) {
   1262                         int i;
   1263 
   1264                         for( i = -1, approxPattern = -1 ; i < work->approxSet.charset_count ; i++ ) {
   1265                             if( i == -1 || keyString[ queryLen ] == work->approxSet.from[ i ][ 0 ] ) {
   1266                                 int tailOffset = 0;
   1267 
   1268                                 if( i == -1 ) {
   1269                                     if(   *( ( NJ_UINT8* )( &keyString[ queryLen ] ) + 0 ) == 0x00 &&
   1270                                         ( *( ( NJ_UINT8* )( &keyString[ queryLen ] ) + 1 ) == 0x25 ||       /* '%' */
   1271                                           *( ( NJ_UINT8* )( &keyString[ queryLen ] ) + 1 ) == 0x5c ||       /* '\' */
   1272                                           *( ( NJ_UINT8* )( &keyString[ queryLen ] ) + 1 ) == 0x5f ) ) {    /* '_' */
   1273                                         *( ( NJ_UINT8* )( &baseStr[ queryLen + 0 ] ) + 0 ) = 0x00;
   1274                                         *( ( NJ_UINT8* )( &baseStr[ queryLen + 0 ] ) + 1 ) = 0x5c;  /* '\' */
   1275                                                            baseStr[ queryLen + 1 ] = keyString[ queryLen ];
   1276                                         tailOffset = 2;
   1277                                     } else {
   1278                                         baseStr[ queryLen + 0 ] = keyString[ queryLen ];
   1279                                         tailOffset = 1;
   1280                                     }
   1281                                 } else {
   1282                                     nj_strcpy( &baseStr[ queryLen ], work->approxSet.to[ i ] );
   1283                                     tailOffset = nj_strlen( work->approxSet.to[ i ] );
   1284                                 }
   1285 
   1286                                 *( ( NJ_UINT8* )( &baseStr[ queryLen + tailOffset     ] ) + 0 ) = 0x00;
   1287                                 *( ( NJ_UINT8* )( &baseStr[ queryLen + tailOffset     ] ) + 1 ) = 0x25;  /* '%' */
   1288                                                    baseStr[ queryLen + tailOffset + 1 ]         = NJ_CHAR_NUL;
   1289 
   1290                                 jstring dstJ;
   1291                                 if( convertNjCharToString( env, &dstJ, baseStr, NJ_MAX_LEN ) < 0 ) {
   1292                                     return NULL;
   1293                                 }
   1294 
   1295                                 ( *env )->SetObjectArrayElement( env, retJ, outIndex++, dstJ );
   1296                                 approxPattern++;
   1297                             }
   1298                         }
   1299                         for( ; approxPattern < maxPatternOfApprox ; approxPattern++ ) {
   1300                             jstring dstJ = ( *env )->NewStringUTF( env, "" );
   1301                             if( dstJ == NULL ) {
   1302                                 return NULL;
   1303                             }
   1304                             ( *env )->SetObjectArrayElement( env, retJ, outIndex++, dstJ );
   1305                         }
   1306 
   1307                         *( ( NJ_UINT8* )( &baseStr[ queryLen     ] ) + 0 ) = 0x00;
   1308                         *( ( NJ_UINT8* )( &baseStr[ queryLen     ] ) + 1 ) = 0x5f;  /* '_' */
   1309                                            baseStr[ queryLen + 1 ]         = NJ_CHAR_NUL;
   1310                     }
   1311 
   1312                     for( ; queryLen < maxBindsOfQuery ; queryLen++ ) {
   1313                         for( approxPattern = -1 ; approxPattern < maxPatternOfApprox ; approxPattern++ ) {
   1314                             jstring dstJ = ( *env )->NewStringUTF( env, "%" );
   1315                             if( dstJ == NULL ) {
   1316                                 return NULL;
   1317                             }
   1318                             ( *env )->SetObjectArrayElement( env, retJ, outIndex++, dstJ );
   1319                         }
   1320                     }
   1321 
   1322                     return retJ;
   1323                 }
   1324             }
   1325         }
   1326         /* If the internal error occured, return an error code */
   1327         return NULL;
   1328     }
   1329 
   1330 	/* If the internal work area was already released, return an error code */
   1331 	return NULL;
   1332 }
   1333 
   1334 /*
   1335  * Class:     jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni
   1336  * Method:    createQueryStringBase
   1337  * Signature: (JIILjava/lang/String;)Ljava/lang/String;
   1338  */
   1339 JNIEXPORT jstring JNICALL Java_jp_co_omronsoft_openwnn_OpenWnnDictionaryImplJni_createQueryStringBase
   1340   (JNIEnv *env, jclass obj, jlong wnnWork, jint maxBindsOfQuery, jint maxPatternOfApprox, jstring keyColumnNameJ)
   1341 {
   1342     NJ_JNIWORK*	work;
   1343     jstring retJ = NULL;
   1344 
   1345 	if( keyColumnNameJ == NULL ) {
   1346 		/* If a invalid parameter was specified, return an error code */
   1347 		return NULL;
   1348 	}
   1349 
   1350 	work = *( NJ_JNIWORK** )&wnnWork;
   1351 	if( work != NULL ) {
   1352     	const unsigned char* keyName = ( const unsigned char* )( ( *env )->GetStringUTFChars( env, keyColumnNameJ, NULL ) );
   1353 
   1354         if( keyName != NULL ) {
   1355             int keyLength = strlen( ( char* )keyName );
   1356 
   1357             char *dst = ( char* )malloc( maxBindsOfQuery * ( ( 1 + keyLength + 18 + 1 + 5 ) +
   1358                                                              ( ( 4 + keyLength + 18 ) * maxPatternOfApprox ) +
   1359                                                              1 ) );
   1360             if( dst != NULL ) {
   1361                 int queryLen, dstPtr;
   1362 
   1363             	for( queryLen = dstPtr = 0 ; queryLen < maxBindsOfQuery ; queryLen++ ) {
   1364                     int approxPattern;
   1365 
   1366                     strcpy( &dst[ dstPtr                 ], "(" );
   1367                     strcpy( &dst[ dstPtr + 1             ], ( char* )keyName );
   1368                     strcpy( &dst[ dstPtr + 1 + keyLength ], " like ? escape '\x5c'" );
   1369                     dstPtr += 1 + keyLength + 18;
   1370 
   1371             		for( approxPattern = 0 ; approxPattern < maxPatternOfApprox ; approxPattern++ ) {
   1372                         strcpy( &dst[ dstPtr                 ], " or " );
   1373                         strcpy( &dst[ dstPtr + 4             ], ( char* )keyName );
   1374                         strcpy( &dst[ dstPtr + 4 + keyLength ], " like ? escape '\x5c'" );
   1375                         dstPtr += 4 + keyLength + 18;
   1376             		}
   1377                     strcpy( &dst[ dstPtr ], ")" );
   1378                     dstPtr++;
   1379 
   1380             		if( queryLen != maxBindsOfQuery-1 ) {
   1381                         strcpy( &dst[ dstPtr ], " and " );
   1382                         dstPtr += 5;
   1383             		}
   1384             	}
   1385 
   1386                 dst[ dstPtr ] = '\0';
   1387                 retJ = ( *env )->NewStringUTF( env, dst );
   1388 
   1389                 free( dst );
   1390             }
   1391 
   1392        		( *env )->ReleaseStringUTFChars( env, keyColumnNameJ, ( const char* )keyName );
   1393         }
   1394     }
   1395 	return retJ;
   1396 }
   1397 
   1398