From 7c4198c05efe525c368e32c28cd8caecb114d13e Mon Sep 17 00:00:00 2001 From: ehouse Date: Sat, 16 Jan 2010 14:16:27 +0000 Subject: [PATCH] implement util_getUserString and features like formatRemainingTiles that display a bunch of text. Started working on util_userQuery. --- xwords4/android/LocalizedStrIncludes.h | 55 +++-- .../android/XWords4/res/values/strings.xml | 34 +++ .../eehouse/android/xw4/BoardActivity.java | 194 ++++++++++++++++-- .../eehouse/android/xw4/jni/XW_UtilCtxt.java | 34 +++ .../org/eehouse/android/xw4/jni/XwJNI.java | 6 + xwords4/android/andutils.c | 19 +- xwords4/android/andutils.h | 4 +- xwords4/android/utilwrapper.c | 45 +++- xwords4/android/xwjni.c | 73 ++++++- 9 files changed, 414 insertions(+), 50 deletions(-) diff --git a/xwords4/android/LocalizedStrIncludes.h b/xwords4/android/LocalizedStrIncludes.h index 837d8c174..f536f224b 100644 --- a/xwords4/android/LocalizedStrIncludes.h +++ b/xwords4/android/LocalizedStrIncludes.h @@ -1,34 +1,33 @@ - - -/* stub this out for now. Need a localization strategy that uses - string.xml */ +/* Keep these in sync with the constants in XW_UtilCtxt.java */ #ifndef _LOCALIZEDSTRINCLUDES_H_ #define _LOCALIZEDSTRINCLUDES_H_ -# define STRD_ROBOT_TRADED 1000 -# define STR_ROBOT_MOVED 1001 -# define STRS_VALUES_HEADER 1002 -# define STRD_REMAINING_TILES_ADD 1003 -# define STRD_UNUSED_TILES_SUB 1004 -# define STR_REMOTE_MOVED 1005 -# define STRD_TIME_PENALTY_SUB 1006 -# define STR_PASS 1000 -# define STRS_MOVE_ACROSS 1000 -# define STRS_MOVE_DOWN 1000 -# define STRS_TRAY_AT_START 1000 -# define STRSS_TRADED_FOR 1000 -# define STR_PHONY_REJECTED 1000 -# define STRD_CUMULATIVE_SCORE 1000 -# define STRS_NEW_TILES 1000 -# define STR_PASSED 1000 -# define STRSD_SUMMARYSCORED 1000 -# define STRD_TRADED 1000 -# define STR_LOSTTURN 1000 -# define STR_COMMIT_CONFIRM 1000 -# define STR_LOCAL_NAME 1000 -# define STR_NONLOCAL_NAME 1000 -# define STR_BONUS_ALL 1000 -# define STRD_TURN_SCORE 1000 +# define STRD_ROBOT_TRADED 1 +# define STR_ROBOT_MOVED 2 +# define STRS_VALUES_HEADER 3 +# define STRD_REMAINING_TILES_ADD 4 +# define STRD_UNUSED_TILES_SUB 5 +# define STR_REMOTE_MOVED 6 +# define STRD_TIME_PENALTY_SUB 7 +# define STR_PASS 8 +# define STRS_MOVE_ACROSS 9 +# define STRS_MOVE_DOWN 10 +# define STRS_TRAY_AT_START 11 +# define STRSS_TRADED_FOR 12 +# define STR_PHONY_REJECTED 13 +# define STRD_CUMULATIVE_SCORE 14 +# define STRS_NEW_TILES 15 +# define STR_PASSED 16 +# define STRSD_SUMMARYSCORED 17 +# define STRD_TRADED 18 +# define STR_LOSTTURN 19 +# define STR_COMMIT_CONFIRM 20 +# define STR_LOCAL_NAME 21 +# define STR_NONLOCAL_NAME 22 +# define STR_BONUS_ALL 23 +# define STRD_TURN_SCORE 24 + +# define N_AND_USER_STRINGS 24 #endif diff --git a/xwords4/android/XWords4/res/values/strings.xml b/xwords4/android/XWords4/res/values/strings.xml index fcf13cc28..dbe065d8e 100644 --- a/xwords4/android/XWords4/res/values/strings.xml +++ b/xwords4/android/XWords4/res/values/strings.xml @@ -47,6 +47,8 @@ OK Cancel + Yes + No Name: Open @@ -54,8 +56,14 @@ Error Error loading game + A question... + Are you sure you want to trade the selected tiles? + Pick tile + Remaining tiles + Tile Counts and Values + Game History Turn done @@ -85,4 +93,30 @@ Delete all Hidden games + + Robot traded tiles %d this turn. + The robot made this move: + %s counts/values: + + %d [all remaining tiles] + - %d [unused tiles] + Remote player made this move: + + - %d [time] + move (from %s across) + move (from %s down) + Tray at start: %s + Traded %s for %s. + Illegal word in move; turn lost! + Cumulative score: %d + New tiles: %s + Passed + + %s:%d + Lost turn + Commit the current move? + %s + %s (remote) + Bonus for using all tiles: 50 + Score for turn: %d + diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java index 53784fd14..7731a06b9 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java @@ -18,6 +18,9 @@ import android.content.res.Configuration; import android.content.Intent; import java.util.concurrent.Semaphore; import android.net.Uri; +import android.app.Dialog; +import android.app.AlertDialog; +import android.content.DialogInterface; import org.eehouse.android.xw4.jni.*; @@ -33,6 +36,12 @@ public class BoardActivity extends Activity implements XW_UtilCtxt, Runnable { private TimerRunnable[] m_timers; private String m_path; + private final int DLG_OKONLY = 1; + private final int DLG_QUERY = 2; + private String m_dlgBytes = null; + private int m_dlgTitle; + private boolean m_dlgResult; + // call startActivityForResult synchronously private Semaphore m_forResultWait = new Semaphore(0); private int m_resultCode = 0; @@ -55,8 +64,41 @@ public class BoardActivity extends Activity implements XW_UtilCtxt, Runnable { m_jniThread.handle( JNIThread.JNICmd.CMD_TIMER_FIRED, new Object[] { m_why, m_when, m_handle } ); } + } + + @Override + protected Dialog onCreateDialog( int id ) + { + Dialog dialog = null; + switch ( id ) { + case DLG_OKONLY: + dialog = new AlertDialog.Builder( BoardActivity.this ) + //.setIcon( R.drawable.alert_dialog_icon ) + .setTitle( m_dlgTitle ) + .setMessage( m_dlgBytes ) + .setPositiveButton( R.string.button_ok, + new DialogInterface.OnClickListener() { + public void onClick( DialogInterface dialog, + int whichButton ) { + Utils.logf( "Ok clicked" ); + } + }) + .create(); + break; + } + return dialog; + } // onCreateDialog + + @Override + protected void onPrepareDialog( int id, Dialog dialog ) + { + Utils.logf( "onPrepareDialog(id=" + id + ")" ); + dialog.setTitle( m_dlgTitle ); + ((AlertDialog)dialog).setMessage( m_dlgBytes ); + super.onPrepareDialog( id, dialog ); } + @Override protected void onCreate( Bundle savedInstanceState ) { super.onCreate( savedInstanceState ); @@ -156,45 +198,63 @@ public class BoardActivity extends Activity implements XW_UtilCtxt, Runnable { return true; } - public boolean onOptionsItemSelected(MenuItem item) { + public boolean onOptionsItemSelected( MenuItem item ) + { boolean handled = true; + JNIThread.JNICmd cmd = JNIThread.JNICmd.CMD_NONE; switch (item.getItemId()) { case R.id.board_menu_done: - m_jniThread.handle( JNIThread.JNICmd.CMD_COMMIT ); + cmd = JNIThread.JNICmd.CMD_COMMIT; break; case R.id.board_menu_juggle: - m_jniThread.handle( JNIThread.JNICmd.CMD_JUGGLE ); + cmd = JNIThread.JNICmd.CMD_JUGGLE; break; case R.id.board_menu_flip: - m_jniThread.handle( JNIThread.JNICmd.CMD_FLIP ); + cmd = JNIThread.JNICmd.CMD_FLIP; break; case R.id.board_menu_trade: - m_jniThread.handle( JNIThread.JNICmd.CMD_TOGGLE_TRADE ); + cmd = JNIThread.JNICmd.CMD_TOGGLE_TRADE; break; case R.id.board_menu_tray: - m_jniThread.handle( JNIThread.JNICmd.CMD_TOGGLE_TRAY ); + cmd = JNIThread.JNICmd.CMD_TOGGLE_TRAY; break; case R.id.board_menu_undo_current: - m_jniThread.handle( JNIThread.JNICmd.CMD_UNDO_CUR ); + cmd = JNIThread.JNICmd.CMD_UNDO_CUR; break; case R.id.board_menu_undo_last: - m_jniThread.handle( JNIThread.JNICmd.CMD_UNDO_LAST ); + cmd = JNIThread.JNICmd.CMD_UNDO_LAST; break; case R.id.board_menu_hint: - m_jniThread.handle( JNIThread.JNICmd.CMD_HINT ); + cmd = JNIThread.JNICmd.CMD_HINT; break; case R.id.board_menu_hint_next: - m_jniThread.handle( JNIThread.JNICmd.CMD_NEXT_HINT ); + cmd = JNIThread.JNICmd.CMD_NEXT_HINT; break; case R.id.board_menu_values: - m_jniThread.handle( JNIThread.JNICmd.CMD_VALUES ); + cmd = JNIThread.JNICmd.CMD_VALUES; break; case R.id.board_menu_game_counts: + handled = true; + m_dlgBytes = XwJNI.server_formatDictCounts( m_jniGamePtr, 3 ); + m_dlgTitle = R.string.counts_values_title; + showDialog( DLG_OKONLY ); + break; case R.id.board_menu_game_left: - case R.id.board_menu_game_info: + handled = true; + m_dlgBytes = XwJNI.board_formatRemainingTiles( m_jniGamePtr ); + m_dlgTitle = R.string.tiles_left_title; + showDialog( DLG_OKONLY ); + break; case R.id.board_menu_game_history: + boolean gameOver = XwJNI.server_getGameIsOver( m_jniGamePtr ); + m_dlgBytes = XwJNI.model_writeGameHistory( m_jniGamePtr, gameOver ); + m_dlgTitle = R.string.history_title; + showDialog( DLG_OKONLY ); + break; + + case R.id.board_menu_game_info: case R.id.board_menu_game_final: case R.id.board_menu_game_resend: case R.id.board_menu_file_prefs: @@ -209,6 +269,10 @@ public class BoardActivity extends Activity implements XW_UtilCtxt, Runnable { handled = false; } + if ( handled && cmd != JNIThread.JNICmd.CMD_NONE ) { + m_jniThread.handle( cmd ); + } + return handled; } @@ -353,4 +417,110 @@ public class BoardActivity extends Activity implements XW_UtilCtxt, Runnable { { return !m_jniThread.busy(); } + + public String getUserString( int stringCode ) + { + int id = 0; + switch( stringCode ) { + case XW_UtilCtxt.STRD_ROBOT_TRADED: + id = R.string.strd_robot_traded; + break; + case XW_UtilCtxt.STR_ROBOT_MOVED: + id = R.string.str_robot_moved; + break; + case XW_UtilCtxt.STRS_VALUES_HEADER: + id = R.string.strs_values_header; + break; + case XW_UtilCtxt.STRD_REMAINING_TILES_ADD: + id = R.string.strd_remaining_tiles_add; + break; + case XW_UtilCtxt.STRD_UNUSED_TILES_SUB: + id = R.string.strd_unused_tiles_sub; + break; + case XW_UtilCtxt.STR_REMOTE_MOVED: + id = R.string.str_remote_moved; + break; + case XW_UtilCtxt.STRD_TIME_PENALTY_SUB: + id = R.string.strd_time_penalty_sub; + break; + case XW_UtilCtxt.STR_PASS: + id = R.string.str_pass; + break; + case XW_UtilCtxt.STRS_MOVE_ACROSS: + id = R.string.strs_move_across; + break; + case XW_UtilCtxt.STRS_MOVE_DOWN: + id = R.string.strs_move_down; + break; + case XW_UtilCtxt.STRS_TRAY_AT_START: + id = R.string.strs_tray_at_start; + break; + case XW_UtilCtxt.STRSS_TRADED_FOR: + id = R.string.strss_traded_for; + break; + case XW_UtilCtxt.STR_PHONY_REJECTED: + id = R.string.str_phony_rejected; + break; + case XW_UtilCtxt.STRD_CUMULATIVE_SCORE: + id = R.string.strd_cumulative_score; + break; + case XW_UtilCtxt.STRS_NEW_TILES: + id = R.string.strs_new_tiles; + break; + case XW_UtilCtxt.STR_PASSED: + id = R.string.str_passed; + break; + case XW_UtilCtxt.STRSD_SUMMARYSCORED: + id = R.string.strsd_summaryscored; + break; + case XW_UtilCtxt.STRD_TRADED: + id = R.string.strd_traded; + break; + case XW_UtilCtxt.STR_LOSTTURN: + id = R.string.str_lostturn; + break; + case XW_UtilCtxt.STR_COMMIT_CONFIRM: + id = R.string.str_commit_confirm; + break; + case XW_UtilCtxt.STR_LOCAL_NAME: + id = R.string.str_local_name; + break; + case XW_UtilCtxt.STR_NONLOCAL_NAME: + id = R.string.str_nonlocal_name; + break; + case XW_UtilCtxt.STR_BONUS_ALL: + id = R.string.str_bonus_all; + break; + case XW_UtilCtxt.STRD_TURN_SCORE: + id = R.string.strd_turn_score; + break; + default: + Utils.logf( "no such stringCode: " + stringCode ); + } + + String result; + if ( 0 == id ) { + result = ""; + } else { + result = getString( id ); + } + return result; + } + + public boolean userQuery( int id, String query ) + { + switch( id ) { + case XW_UtilCtxt.QUERY_COMMIT_TRADE: + query = getString( R.string.query_trade ); + break; + case XW_UtilCtxt.QUERY_COMMIT_TURN: + case XW_UtilCtxt.QUERY_ROBOT_MOVE: + case XW_UtilCtxt.QUERY_ROBOT_TRADE: + break; + } + + // Need to figure out how this thing can block. + return true; + } + } // class BoardActivity diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/XW_UtilCtxt.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/XW_UtilCtxt.java index b1c8d3b2f..530ab0b8f 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/XW_UtilCtxt.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/XW_UtilCtxt.java @@ -17,6 +17,40 @@ public interface XW_UtilCtxt { void clearTimer( int why ); void requestTime(); void remSelected(); + + + static final int STRD_ROBOT_TRADED = 1; + static final int STR_ROBOT_MOVED = 2; + static final int STRS_VALUES_HEADER = 3; + static final int STRD_REMAINING_TILES_ADD = 4; + static final int STRD_UNUSED_TILES_SUB = 5; + static final int STR_REMOTE_MOVED = 6; + static final int STRD_TIME_PENALTY_SUB = 7; + static final int STR_PASS = 8; + static final int STRS_MOVE_ACROSS = 9; + static final int STRS_MOVE_DOWN = 10; + static final int STRS_TRAY_AT_START = 11; + static final int STRSS_TRADED_FOR = 12; + static final int STR_PHONY_REJECTED = 13; + static final int STRD_CUMULATIVE_SCORE = 14; + static final int STRS_NEW_TILES = 15; + static final int STR_PASSED = 16; + static final int STRSD_SUMMARYSCORED = 17; + static final int STRD_TRADED = 18; + static final int STR_LOSTTURN = 19; + static final int STR_COMMIT_CONFIRM = 20; + static final int STR_LOCAL_NAME = 21; + static final int STR_NONLOCAL_NAME = 22; + static final int STR_BONUS_ALL = 23; + static final int STRD_TURN_SCORE = 24; + String getUserString( int stringCode ); + + static final int QUERY_COMMIT_TURN = 0; + static final int QUERY_COMMIT_TRADE = 1; + static final int QUERY_ROBOT_MOVE = 2; + static final int QUERY_ROBOT_TRADE = 3; + boolean userQuery( int id, String query ); + // Don't need this unless we have a scroll thumb to indicate position //void yOffsetChange( int oldOffset, int newOffset ); diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/XwJNI.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/XwJNI.java index 959ed37f1..8b6fe2af5 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/XwJNI.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/XwJNI.java @@ -77,6 +77,12 @@ public class XwJNI { boolean[] workRemains ); public static native boolean board_beginTrade( int gamePtr ); + public static native String board_formatRemainingTiles( int gamePtr ); + public static native void server_handleUndo( int gamePtr ); public static native boolean server_do( int gamePtr ); + public static native String server_formatDictCounts( int gamePtr, int nCols ); + public static native boolean server_getGameIsOver( int gamePtr ); + + public static native String model_writeGameHistory( int gamePtr, boolean gameOver ); } diff --git a/xwords4/android/andutils.c b/xwords4/android/andutils.c index 092b4b79a..092c4f32e 100644 --- a/xwords4/android/andutils.c +++ b/xwords4/android/andutils.c @@ -3,6 +3,7 @@ #include "andutils.h" #include "comtypes.h" +#include "xwstream.h" void and_assert( const char* test, int line, const char* file, const char* func ) @@ -102,13 +103,15 @@ setString( JNIEnv* env, jobject obj, const char* name, const XP_UCHAR* value ) bool success = false; jclass cls = (*env)->GetObjectClass( env, obj ); jfieldID fid = (*env)->GetFieldID( env, cls, name, "Ljava/lang/String;" ); + (*env)->DeleteLocalRef( env, cls ); + if ( 0 != fid ) { jstring str = (*env)->NewStringUTF( env, value ); (*env)->SetObjectField( env, obj, fid, str ); success = true; (*env)->DeleteLocalRef( env, str ); } - (*env)->DeleteLocalRef( env, cls ); + return success; } @@ -213,6 +216,20 @@ makeStringArray( JNIEnv *env, int siz, const XP_UCHAR** vals ) return jarray; } +jstring +streamToJString( MPFORMAL JNIEnv *env, XWStreamCtxt* stream ) +{ + int len = stream_getSize( stream ); + XP_UCHAR* buf = XP_MALLOC( mpool, 1 + len ); + stream_getBytes( stream, buf, len ); + buf[len] = '\0'; + + jstring jstr = (*env)->NewStringUTF( env, buf ); + + XP_FREE( mpool, buf ); + return jstr; +} + jmethodID getMethodID( JNIEnv* env, jobject obj, const char* proc, const char* sig ) { diff --git a/xwords4/android/andutils.h b/xwords4/android/andutils.h index 75a3cf4e9..32832d08f 100644 --- a/xwords4/android/andutils.h +++ b/xwords4/android/andutils.h @@ -5,7 +5,8 @@ #include -#include "xptypes.h" +#include "comtypes.h" +#include "mempool.h" XP_U32 and_ntohl(XP_U32 l); XP_U16 and_ntohs(XP_U16 l); @@ -26,6 +27,7 @@ jintArray makeIntArray( JNIEnv *env, int size, const jint* vals ); int getIntFromArray( JNIEnv* env, jintArray arr, bool del ); jobjectArray makeStringArray( JNIEnv *env, int size, const XP_UCHAR** vals ); +jstring streamToJString( MPFORMAL JNIEnv* env, XWStreamCtxt* stream ); /* Note: jmethodID can be cached. Should not look up more than once. */ jmethodID getMethodID( JNIEnv* env, jobject obj, const char* proc, diff --git a/xwords4/android/utilwrapper.c b/xwords4/android/utilwrapper.c index 44563e8bb..35b4019c8 100644 --- a/xwords4/android/utilwrapper.c +++ b/xwords4/android/utilwrapper.c @@ -23,6 +23,7 @@ #include "utilwrapper.h" #include "andutils.h" +#include "LocalizedStrIncludes.h" typedef struct _TimerStorage { XWTimerProc proc; @@ -34,6 +35,7 @@ typedef struct _AndUtil { JNIEnv** env; jobject j_util; /* global ref to object implementing XW_UtilCtxt */ TimerStorage timerStorage[NUM_TIMERS_PLUS_ONE]; + XP_UCHAR* userStrings[N_AND_USER_STRINGS]; } AndUtil; @@ -76,7 +78,19 @@ and_util_userError( XW_UtilCtxt* uc, UtilErrID id ) static XP_Bool and_util_userQuery( XW_UtilCtxt* uc, UtilQueryID id, XWStreamCtxt* stream ) { - XP_LOGF( "%s(id=%d)", __func__, id ); + XP_ASSERT( id < QUERY_LAST_COMMON ); + UTIL_CBK_HEADER("userQuery", "(ILjava/lang/String;)Z" ); + + jstring jstr = NULL; + if ( NULL != stream ) { + jstr = streamToJString( MPPARM(util->util.mpool) env, stream ); + } + jboolean result = (*env)->CallBooleanMethod( env, util->j_util, mid, + id, jstr ); + if ( NULL != jstr ) { + (*env)->DeleteLocalRef( env, jstr ); + } + return result; } static XP_S16 @@ -225,8 +239,27 @@ and_util_makeEmptyDict( XW_UtilCtxt* uc ) static const XP_UCHAR* and_util_getUserString( XW_UtilCtxt* uc, XP_U16 stringCode ) { - LOG_FUNC(); - return ""; + UTIL_CBK_HEADER("getUserString", "(I)Ljava/lang/String;" ); + int index = stringCode - 1; /* see LocalizedStrIncludes.h */ + XP_ASSERT( index < VSIZE( util->userStrings ) ); + + if ( ! util->userStrings[index] ) { + jstring jresult = (*env)->CallObjectMethod( env, util->j_util, mid, + stringCode ); + jsize len = (*env)->GetStringUTFLength( env, jresult ); + XP_UCHAR* buf = XP_MALLOC( util->util.mpool, len + 1 ); + + const char* jchars = (*env)->GetStringUTFChars( env, jresult, NULL ); + XP_MEMCPY( buf, jchars, len ); + buf[len] = '\0'; + XP_LOGF( "got string from java: %s", buf ); + (*env)->ReleaseStringUTFChars( env, jresult, jchars ); + (*env)->DeleteLocalRef( env, jresult ); + util->userStrings[index] = buf; + } + + LOG_RETURNF( "%s", util->userStrings[index] ); + return util->userStrings[index]; } @@ -342,6 +375,12 @@ destroyUtil( XW_UtilCtxt* utilc ) { AndUtil* util = (AndUtil*)utilc; JNIEnv *env = *util->env; + + int ii; + for ( ii = 0; ii < VSIZE(util->userStrings); ++ii ) { + XP_FREE( util->util.mpool, util->userStrings[ii] ); + } + (*env)->DeleteGlobalRef( env, util->j_util ); XP_FREE( util->util.mpool, util->util.vtable ); XP_FREE( util->util.mpool, util ); diff --git a/xwords4/android/xwjni.c b/xwords4/android/xwjni.c index 2e00ec9b0..04dae532b 100644 --- a/xwords4/android/xwjni.c +++ b/xwords4/android/xwjni.c @@ -14,9 +14,7 @@ #include "utilwrapper.h" #include "drawwrapper.h" #include "anddict.h" - - -/* static JNIEnv* g_env = NULL; */ +#include "andutils.h" static CurGameInfo* makeGI( MPFORMAL JNIEnv* env, jobject j_gi ) @@ -59,9 +57,9 @@ makeGI( MPFORMAL JNIEnv* env, jobject j_gi ) getBool( env, jlp, "isRobot", &lp->isRobot ); getBool( env, jlp, "isLocal", &lp->isLocal ); - getString( env, jlp, "name", &buf, VSIZE(buf) ); + getString( env, jlp, "name", buf, VSIZE(buf) ); lp->name = copyString( mpool, buf ); - getString( env, jlp, "password", &buf, VSIZE(buf) ); + getString( env, jlp, "password", buf, VSIZE(buf) ); lp->password = copyString( mpool, buf ); lp->secondsUsed = 0; @@ -132,6 +130,14 @@ loadCommonPrefs( JNIEnv* env, CommonPrefs* cp, jobject j_cp ) return success; } +static XWStreamCtxt* +and_empty_stream( MPFORMAL AndGlobals* globals ) +{ + XWStreamCtxt* stream = mem_stream_make( MPPARM(mpool) globals->vtMgr, + NULL, 0, NULL ); + return stream; +} + /**************************************************** * These two methods are stateless: no gamePtr ****************************************************/ @@ -630,3 +636,60 @@ Java_org_eehouse_android_xw4_jni_XwJNI_timerFired XWJNI_END(); return result; } + +JNIEXPORT jstring JNICALL +Java_org_eehouse_android_xw4_jni_XwJNI_board_1formatRemainingTiles +(JNIEnv* env, jclass C, jint gamePtr ) +{ + jstring result; + XWJNI_START(); + XWStreamCtxt* stream = mem_stream_make( MPPARM(mpool) globals->vtMgr, + NULL, 0, NULL ); + board_formatRemainingTiles( state->game.board, stream ); + result = streamToJString( MPPARM(mpool) env, stream ); + stream_destroy( stream ); + (*env)->DeleteLocalRef( env, result ); + + XWJNI_END(); + return result; +} + +JNIEXPORT jstring JNICALL +Java_org_eehouse_android_xw4_jni_XwJNI_server_1formatDictCounts +( JNIEnv* env, jclass C, jint gamePtr, jint nCols ) +{ + jstring result; + XWJNI_START(); + XWStreamCtxt* stream = and_empty_stream( MPPARM(mpool) globals ); + server_formatDictCounts( state->game.server, stream, nCols ); + result = streamToJString( MPPARM(mpool) env, stream ); + stream_destroy( stream ); + (*env)->DeleteLocalRef( env, result ); + XWJNI_END(); + return result; +} + +JNIEXPORT jboolean JNICALL +Java_org_eehouse_android_xw4_jni_XwJNI_server_1getGameIsOver +( JNIEnv* env, jclass C, jint gamePtr ) +{ + jboolean result; + XWJNI_START(); + result = server_getGameIsOver( state->game.server ); + XWJNI_END(); + return result; +} + +JNIEXPORT jstring JNICALL +Java_org_eehouse_android_xw4_jni_XwJNI_model_1writeGameHistory +( JNIEnv* env, jclass C, jint gamePtr, jboolean gameOver ) +{ + jstring result; + XWJNI_START(); + XWStreamCtxt* stream = and_empty_stream( MPPARM(mpool) globals ); + model_writeGameHistory( state->game.model, stream, state->game.server, + gameOver ); + result = streamToJString( MPPARM(mpool) env, stream ); + XWJNI_END(); + return result; +}