diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DictBrowseDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DictBrowseDelegate.java index 83cc3af1c..f235643ef 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DictBrowseDelegate.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DictBrowseDelegate.java @@ -308,6 +308,7 @@ public class DictBrowseDelegate extends DelegateBase switch ( dlgID ) { case CHOOSE_TILES: final byte[][] choices = (byte[][])params[0]; + final int indx = (Integer)params[1]; final String[] strs = new String[choices.length]; for ( int ii = 0; ii < choices.length; ++ii ) { strs[ii] = XwJNI.dict_tilesToStr( m_dict, choices[ii], DELIM ); @@ -327,7 +328,8 @@ public class DictBrowseDelegate extends DelegateBase public void onClick( DialogInterface dialog, int which ) { if ( 0 <= chosen[0] ) { - Assert.failDbg(); + int sel = chosen[0]; + useButtonClicked( indx, choices[sel] ); } } } ) @@ -507,7 +509,9 @@ public class DictBrowseDelegate extends DelegateBase } } - private void useButtonClicked() + private void useButtonClicked() { useButtonClicked( -1, null ); } + + private void useButtonClicked( int justFixed, byte[] fixedTiles ) { scrapeBrowseState(); Log.d( TAG, "useButtonClicked(): m_browseState: %s", m_browseState ); @@ -521,25 +525,29 @@ public class DictBrowseDelegate extends DelegateBase PatDesc[] pats = m_browseState.m_pats; for ( int ii = 0; ii < pats.length && !pending; ++ii ) { - String strPat = pats[ii].strPat; - if ( null != strPat && 0 < strPat.length() ) { - byte[][] choices = XwJNI.dict_strToTiles( m_dict, strPat ); - if ( null == choices || 0 == choices.length ) { - String langName = DictLangCache.getLangName( m_activity, m_lang ); - String msg = getString( R.string.no_tiles_exist, strPat, langName ); - makeOkOnlyBuilder( msg ) - .setActionPair( Action.SHOW_TILES, R.string.show_tiles_button ) - .show(); - pending = true; - } else if ( 1 == choices.length - || !XwJNI.dict_hasDuplicates( m_dict ) ) { - pats[ii].tilePat = choices[0]; - } else { - showDialogFragment( DlgID.CHOOSE_TILES, (Object)choices ); - pending = true; - } + if ( justFixed == ii ) { + pats[ii].tilePat = fixedTiles; } else { - pats[ii].tilePat = null; + String strPat = pats[ii].strPat; + if ( null != strPat && 0 < strPat.length() ) { + byte[][] choices = XwJNI.dict_strToTiles( m_dict, strPat ); + if ( null == choices || 0 == choices.length ) { + String langName = DictLangCache.getLangName( m_activity, m_lang ); + String msg = getString( R.string.no_tiles_exist, strPat, langName ); + makeOkOnlyBuilder( msg ) + .setActionPair( Action.SHOW_TILES, R.string.show_tiles_button ) + .show(); + pending = true; + } else if ( 1 == choices.length + || !XwJNI.dict_hasDuplicates( m_dict ) ) { + pats[ii].tilePat = choices[0]; + } else { + showDialogFragment( DlgID.CHOOSE_TILES, (Object)choices, ii ); + pending = true; + } + } else { + pats[ii].tilePat = null; + } } } diff --git a/xwords4/android/jni/xwjni.c b/xwords4/android/jni/xwjni.c index ab209dc51..1ebdb218c 100644 --- a/xwords4/android/jni/xwjni.c +++ b/xwords4/android/jni/xwjni.c @@ -2664,25 +2664,30 @@ Java_org_eehouse_android_xw4_jni_XwJNI_di_1init data->guard = GI_GUARD; #endif - jobject jdescs[3]; - PatDesc patDescs[3] = {{0}}; - jbyteArray jtiles[3]; + PatDesc patDescs[3]; + XP_MEMSET( patDescs, 0, VSIZE(patDescs) * sizeof(patDescs[0]) ); int len = 0; if ( !!jPatsArr ) { len = (*env)->GetArrayLength( env, jPatsArr ); XP_ASSERT( len == 3 ); for ( int ii = 0; ii < len ; ++ii ) { - jdescs[ii] = (*env)->GetObjectArrayElement( env, jPatsArr, ii ); - if ( !!jdescs[ii] ) { - if ( getObject( env, jdescs[ii], "tilePat", "[B", &jtiles[ii] ) ) { - patDescs[ii].nTiles = (*env)->GetArrayLength( env, jtiles[ii] ); - patDescs[ii].tiles = (Tile*) - (*env)->GetByteArrayElements( env, jtiles[ii], NULL ); - patDescs[ii].anyOrderOk = getBool( env, jdescs[ii], "anyOrderOk" ); + jobject jdesc = (*env)->GetObjectArrayElement( env, jPatsArr, ii ); + if ( !!jdesc ) { + jbyteArray jtiles; + if ( getObject( env, jdesc, "tilePat", "[B", &jtiles ) ) { + int nTiles = (*env)->GetArrayLength( env, jtiles ); + if ( 0 < nTiles ) { + patDescs[ii].nTiles = nTiles; + jbyte* tiles = (*env)->GetByteArrayElements( env, jtiles, NULL ); + XP_MEMCPY( &patDescs[ii].tiles[0], tiles, + nTiles * sizeof(patDescs[ii].tiles[0]) ); + (*env)->ReleaseByteArrayElements( env, jtiles, tiles, 0 ); + patDescs[ii].anyOrderOk = getBool( env, jdesc, "anyOrderOk" ); + } + deleteLocalRef( env, jtiles ); } - } else { - jtiles[ii] = NULL; + deleteLocalRef( env, jdesc ); } } } @@ -2691,14 +2696,6 @@ Java_org_eehouse_android_xw4_jni_XwJNI_di_1init data->iter = di_makeIter( data->dict, env, &mm, NULL, 0, !!jPatsArr ? patDescs : NULL, VSIZE(patDescs) ); - for ( int ii = 0; ii < len ; ++ii ) { - if ( !!jtiles[ii] ) { - (*env)->ReleaseByteArrayElements( env, jtiles[ii], - (jbyte*)patDescs[ii].tiles, 0 ); - deleteLocalRef( env, jtiles[ii] ); - } - } - makeIndex( data ); (void)di_firstWord( data->iter ); diff --git a/xwords4/common/dictiter.h b/xwords4/common/dictiter.h index 3bf4582fc..14af91d79 100644 --- a/xwords4/common/dictiter.h +++ b/xwords4/common/dictiter.h @@ -77,7 +77,7 @@ typedef struct DictIter DictIter; * ends-with. The first is more powerful but I'm not sure it'll ever be part * of a shipping UI.*/ typedef struct _PatDesc { - const Tile* tiles; + Tile tiles[16]; XP_U16 nTiles; XP_Bool anyOrderOk; } PatDesc; diff --git a/xwords4/linux/linuxmain.c b/xwords4/linux/linuxmain.c index 2d3037e67..f077c888e 100644 --- a/xwords4/linux/linuxmain.c +++ b/xwords4/linux/linuxmain.c @@ -832,6 +832,9 @@ typedef enum { ,CMD_TESTPAT ,CMD_TESTSTR #endif + ,CMD_TESTSTARTSW + ,CMD_TESTCONTAINS + ,CMD_TESTENDS ,CMD_DICTDIR ,CMD_PLAYERDICT ,CMD_SEED @@ -971,6 +974,10 @@ static CmdInfoRec CmdInfoRecs[] = { ,{ CMD_TESTSTR, true, "test-string", "string to be tested against test-pat; exit with non-0 if doesn't match" } #endif + ,{CMD_TESTSTARTSW, true, "test-startsw", "use as 'start-with' for pattern"} + ,{CMD_TESTCONTAINS, true, "test-contains", "use as 'contains' for pattern"} + ,{CMD_TESTENDS, true, "test-endsw", "use as 'ends-with' for pattern"} + ,{ CMD_DICTDIR, true, "dict-dir", "path to dir in which dicts will be sought" } ,{ CMD_PLAYERDICT, true, "player-dict", "dictionary name for player (in sequence)" } ,{ CMD_SEED, true, "seed", "random seed" } @@ -1941,14 +1948,45 @@ tmp_noop_sigintterm( int XP_UNUSED(sig) ) exit(0); } + +typedef struct _FTD { + PatDesc* desc; + XP_Bool called; +} FTD; + +static XP_Bool +onFoundTiles2( void* closure, const Tile* tiles, int nTiles ) +{ + FTD* data = (FTD*)closure; + if ( data->called ) { + XP_LOGFF( "ERROR: called more than once; Hungarian case???" ); + } else if ( nTiles > VSIZE(data->desc->tiles) ) { + XP_ASSERT(0); + } else { + data->called = XP_TRUE; + data->desc->nTiles = nTiles; + XP_MEMCPY( &data->desc->tiles[0], tiles, nTiles * sizeof(tiles[0]) ); + } + return XP_TRUE; +} + #ifdef XWFEATURE_WALKDICT +static void +getPat( const DictionaryCtxt* dict, const XP_UCHAR* str, PatDesc* desc ) +{ + if ( !!str && '\0' != str[0] ) { + FTD data = { .desc = desc, }; + dict_tilesForString( dict, str, 0, onFoundTiles2, &data ); + } +} + static DictIter* patsParamsToIter( const LaunchParams* params, const DictionaryCtxt* dict ) { const XP_UCHAR** strPats = NULL; const XP_UCHAR* _strPats[4]; XP_U16 nStrPats = 0; - const PatDesc* pats = NULL; + PatDesc descs[3] = {0}; XP_U16 nPatDescs = 0; if ( !!params->iterTestPats ) { @@ -1962,7 +2000,10 @@ patsParamsToIter( const LaunchParams* params, const DictionaryCtxt* dict ) strPats[ii] = iter->data; } } else if ( !!params->patStartW || !!params->patContains || !!params->patEndsW ) { - XP_ASSERT(0); + getPat( dict, params->patStartW, &descs[0] ); + getPat( dict, params->patContains, &descs[1] ); + getPat( dict, params->patEndsW, &descs[2] ); + nPatDescs = 3; /* and what about the boolean? */ } @@ -1973,7 +2014,7 @@ patsParamsToIter( const LaunchParams* params, const DictionaryCtxt* dict ) } DictIter* iter = di_makeIter( dict, NULL_XWE, dimmp, strPats, nStrPats, - pats, nPatDescs ); + descs, nPatDescs ); return iter; } @@ -2822,6 +2863,16 @@ main( int argc, char** argv ) mainParams.iterTestPatStr = optarg; break; #endif + case CMD_TESTSTARTSW: + mainParams.patStartW = optarg; + break; + case CMD_TESTCONTAINS: + mainParams.patContains = optarg; + break; + case CMD_TESTENDS: + mainParams.patEndsW = optarg; + break; + case CMD_DICTDIR: mainParams.dictDirs = g_slist_append( mainParams.dictDirs, optarg ); break;