implement dictChanged. And so that utf8 dicts could be opened without

their games being drawn (no BoardActivity around) break the two
android-only callbacks out of UtilCtxt and into a new JNIUtils
interface that then requires new handing in C.
This commit is contained in:
eehouse 2010-02-11 13:27:09 +00:00
parent 099cf66a79
commit bd611bb6f4
22 changed files with 372 additions and 161 deletions

View file

@ -32,6 +32,7 @@ local_SRC_FILES += \
xportwrapper.c \
anddict.c \
andutils.c \
jniutlswrapper.c \
COMMON_PATH=../../../common

View file

@ -8,11 +8,12 @@
#include "xptypes.h"
#include "dictnry.h"
#include "strutils.h"
#include "andutils.h"
#include "utilwrapper.h"
typedef struct _AndDictionaryCtxt {
DictionaryCtxt super;
XW_UtilCtxt* util;
JNIUtilCtxt* jniutil;
JNIEnv *env;
XP_U8* bytes;
} AndDictionaryCtxt;
@ -22,7 +23,8 @@ dict_splitFaces( DictionaryCtxt* dict, const XP_U8* bytes,
XP_U16 nBytes, XP_U16 nFaces )
{
XP_UCHAR* faces = (XP_UCHAR*)XP_CALLOC( dict->mpool, nBytes + nFaces );
XP_UCHAR** ptrs = (XP_UCHAR**)XP_CALLOC( dict->mpool, nFaces * sizeof(ptrs[0]));
const XP_UCHAR** ptrs = (const XP_UCHAR**)
XP_CALLOC( dict->mpool, nFaces * sizeof(ptrs[0]));
XP_U16 ii;
XP_UCHAR* next = faces;
@ -112,7 +114,7 @@ andMakeBitmap( AndDictionaryCtxt* ctxt, XP_U8** ptrp )
}
JNIEnv* env = ctxt->env;
bitmap = and_util_makeJBitmap( ctxt->util, nCols, nRows, colors );
bitmap = and_util_makeJBitmap( ctxt->jniutil, nCols, nRows, colors );
jobject tmp = (*env)->NewGlobalRef( env, bitmap );
XP_ASSERT( tmp == bitmap );
(*env)->DeleteLocalRef( env, bitmap );
@ -176,7 +178,7 @@ splitFaces_via_java( JNIEnv* env, AndDictionaryCtxt* ctxt, const XP_U8* ptr,
int nBytes;
int ii;
jobject jstrarr = and_util_splitFaces( ctxt->util, ptr, nFaceBytes );
jobject jstrarr = and_util_splitFaces( ctxt->jniutil, ptr, nFaceBytes );
XP_ASSERT( (*env)->GetArrayLength( env, jstrarr ) == nFaces );
for ( ii = 0; ii < nFaces; ++ii ) {
@ -204,8 +206,8 @@ splitFaces_via_java( JNIEnv* env, AndDictionaryCtxt* ctxt, const XP_U8* ptr,
(*env)->DeleteLocalRef( env, jstrarr );
XP_UCHAR* faces = (XP_UCHAR*)XP_CALLOC( ctxt->super.mpool, indx );
XP_UCHAR** ptrs = (XP_UCHAR**)XP_CALLOC( ctxt->super.mpool,
nFaces * sizeof(ptrs[0]));
const XP_UCHAR** ptrs = (const XP_UCHAR**)
XP_CALLOC( ctxt->super.mpool, nFaces * sizeof(ptrs[0]));
XP_MEMCPY( faces, facesBuf, indx );
for ( ii = 0; ii < nFaces; ++ii ) {
@ -373,6 +375,20 @@ and_dictionary_destroy( DictionaryCtxt* dict )
LOG_RETURN_VOID();
}
jobject
and_dictionary_getChars( JNIEnv* env, DictionaryCtxt* dict )
{
AndDictionaryCtxt* anddict = (AndDictionaryCtxt*)dict;
XP_ASSERT( env == anddict->env );
/* This is cheating: specials will be rep'd as 1,2, etc. But as long as
java code wants to ignore them anyway that's ok. Otherwise need to
use dict_tilesToString() */
XP_U16 nFaces = dict_numTileFaces( dict );
jobject jstrs = makeStringArray( env, nFaces, dict->facePtrs );
return jstrs;
}
DictionaryCtxt*
and_dictionary_make_empty( MPFORMAL_NOCOMMA )
{
@ -384,7 +400,7 @@ and_dictionary_make_empty( MPFORMAL_NOCOMMA )
}
DictionaryCtxt*
makeDict( MPFORMAL JNIEnv *env, XW_UtilCtxt* util, jbyteArray jbytes )
makeDict( MPFORMAL JNIEnv *env, JNIUtilCtxt* jniutil, jbyteArray jbytes )
{
XP_Bool formatOk = XP_TRUE;
XP_Bool isUTF8 = XP_FALSE;
@ -392,7 +408,6 @@ makeDict( MPFORMAL JNIEnv *env, XW_UtilCtxt* util, jbyteArray jbytes )
AndDictionaryCtxt* anddict = NULL;
jsize len = (*env)->GetArrayLength( env, jbytes );
XP_LOGF( "%s: got %d bytes", __func__, len );
XP_U8* localBytes = XP_MALLOC( mpool, len );
jbyte* src = (*env)->GetByteArrayElements( env, jbytes, NULL );
@ -406,7 +421,7 @@ makeDict( MPFORMAL JNIEnv *env, XW_UtilCtxt* util, jbyteArray jbytes )
anddict->bytes = localBytes;
anddict->env = env;
anddict->util = util;
anddict->jniutil = jniutil;
parseDict( anddict, localBytes, len );
setBlankTile( &anddict->super );

View file

@ -5,14 +5,17 @@
#include "dictnry.h"
#include "comtypes.h"
#include "jniutlswrapper.h"
void
dict_splitFaces( DictionaryCtxt* dict, const XP_U8* bytes,
XP_U16 nBytes, XP_U16 nFaces );
DictionaryCtxt* makeDict( MPFORMAL JNIEnv *env, XW_UtilCtxt* util,
DictionaryCtxt* makeDict( MPFORMAL JNIEnv *env, JNIUtilCtxt* jniutil,
jbyteArray bytes );
DictionaryCtxt* and_dictionary_make_empty( MPFORMAL_NOCOMMA );
jobject and_dictionary_getChars( JNIEnv* env, DictionaryCtxt* dict );
#endif

View file

@ -11,6 +11,7 @@ typedef struct _AndGlobals {
CurGameInfo* gi;
DrawCtx* dctx;
XW_UtilCtxt* util;
struct JNIUtilCtxt* jniutil;
TransportProcs* xportProcs;
struct JNIState* state;
} AndGlobals;

View file

@ -109,6 +109,7 @@ makeDSI( AndDraw* draw, int indx, const DrawScoreInfo* dsi )
#define DRAW_CBK_HEADER(nam,sig) \
AndDraw* draw = (AndDraw*)dctx; \
JNIEnv* env = *draw->env; \
XP_ASSERT( !!draw->jdraw ); \
jmethodID mid = getMethodID( env, draw->jdraw, nam, sig );
static void
@ -209,7 +210,9 @@ and_draw_score_drawPlayer( DrawCtx* dctx,
static XP_Bool
and_draw_boardBegin( DrawCtx* dctx, const XP_Rect* rect, DrawFocusState dfs )
{
return XP_TRUE;
AndDraw* draw = (AndDraw*)dctx;
XP_Bool result = NULL != draw->jdraw;
return result;
}
static XP_Bool
@ -380,7 +383,11 @@ and_draw_objFinished( DrawCtx* dctx, BoardObjectType typ,
static void
and_draw_dictChanged( DrawCtx* dctx, const DictionaryCtxt* dict )
{
LOG_FUNC();
AndDraw* draw = (AndDraw*)dctx;
if ( NULL != draw->jdraw ) {
DRAW_CBK_HEADER( "dictChanged", "(I)V" );
(*env)->CallVoidMethod( env, draw->jdraw, mid, (jint)dict );
}
}
static const XP_UCHAR*

View file

@ -0,0 +1,93 @@
/* -*-mode: C; compile-command: "../../scripts/ndkbuild.sh"; -*- */
/*
* Copyright 2001-2010 by Eric House (xwords@eehouse.org). All rights
* reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "strutils.h"
#include "jniutlswrapper.h"
#include "andutils.h"
struct JNIUtilCtxt {
JNIEnv** envp;
jobject jjniutil;
MPSLOT;
};
JNIUtilCtxt*
makeJNIUtil( MPFORMAL JNIEnv** envp, jobject jniutls )
{
JNIUtilCtxt* ctxt = (JNIUtilCtxt*)XP_CALLOC( mpool, sizeof( *ctxt ) );
JNIEnv* env = *envp;
ctxt->envp = envp;
ctxt->jjniutil = (*env)->NewGlobalRef( env, jniutls );
MPASSIGN( ctxt->mpool, mpool );
return ctxt;
}
void
destroyJNIUtil( JNIUtilCtxt** ctxtp )
{
JNIUtilCtxt* ctxt = *ctxtp;
if ( !!ctxt ) {
JNIEnv* env = *ctxt->envp;
(*env)->DeleteGlobalRef( env, ctxt->jjniutil );
XP_FREE( ctxt->mpool, ctxt );
*ctxtp = NULL;
}
}
/* These are called from anddict.c, not via vtable */
jobject
and_util_makeJBitmap( JNIUtilCtxt* jniutil, int nCols, int nRows,
const jboolean* colors )
{
jobject bitmap;
JNIEnv* env = *jniutil->envp;
jmethodID mid
= getMethodID( env, jniutil->jjniutil, "makeBitmap",
"(II[Z)Landroid/graphics/drawable/BitmapDrawable;" );
jbooleanArray jcolors = makeBooleanArray( env, nCols*nRows, colors );
bitmap = (*env)->CallObjectMethod( env, jniutil->jjniutil, mid,
nCols, nRows, jcolors );
(*env)->DeleteLocalRef( env, jcolors );
return bitmap;
}
jobject
and_util_splitFaces( JNIUtilCtxt* jniutil, const XP_U8* bytes, jsize len )
{
jobject strarray = NULL;
JNIEnv* env = *jniutil->envp;
jmethodID mid
= getMethodID( env, jniutil->jjniutil, "splitFaces",
"([B)[Ljava/lang/String;" );
jbyteArray jbytes = (*env)->NewByteArray( env, len );
jbyte* jp = (*env)->GetByteArrayElements( env, jbytes, NULL );
XP_MEMCPY( jp, bytes, len );
(*env)->ReleaseByteArrayElements( env, jbytes, jp, 0 );
strarray = (*env)->CallObjectMethod( env, jniutil->jjniutil, mid, jbytes );
(*env)->DeleteLocalRef( env, jbytes );
return strarray;
}

View file

@ -0,0 +1,38 @@
/* -*-mode: C; fill-column: 76; c-basic-offset: 4; -*- */
/*
* Copyright 2001-2010 by Eric House (xwords@eehouse.org). All rights
* reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _JNIUTLSWRAPPER_H_
#define _JNIUTLSWRAPPER_H_
#include <jni.h>
#include "util.h"
#include "andglobals.h"
typedef struct JNIUtilCtxt JNIUtilCtxt;
JNIUtilCtxt* makeJNIUtil( MPFORMAL JNIEnv** env, jobject jniutls );
void destroyJNIUtil( JNIUtilCtxt** jniu );
jobject and_util_makeJBitmap( JNIUtilCtxt* jniu, int nCols, int nRows,
const jboolean* colors );
jobject and_util_splitFaces( JNIUtilCtxt* jniu, const XP_U8* bytes, int len );
#endif

View file

@ -287,13 +287,11 @@ and_util_getUserString( XW_UtilCtxt* uc, XP_U16 stringCode )
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] );
result = util->userStrings[index];
UTIL_CBK_TAIL();
return result;
@ -350,42 +348,6 @@ and_util_engineStopping( XW_UtilCtxt* uc )
}
#endif
/* These are called from anddict.c, not via vtable */
jobject
and_util_makeJBitmap( XW_UtilCtxt* uc, int nCols, int nRows,
const jboolean* colors )
{
jobject bitmap;
UTIL_CBK_HEADER( "makeBitmap",
"(II[Z)Landroid/graphics/drawable/BitmapDrawable;" );
jbooleanArray jcolors = makeBooleanArray( env, nCols*nRows, colors );
bitmap = (*env)->CallObjectMethod( env, util->jutil, mid,
nCols, nRows, jcolors );
(*env)->DeleteLocalRef( env, jcolors );
UTIL_CBK_TAIL();
return bitmap;
}
jobject
and_util_splitFaces( XW_UtilCtxt* uc, const XP_U8* bytes, jsize len )
{
jobject strarray;
UTIL_CBK_HEADER( "splitFaces", "([B)[Ljava/lang/String;" );
jbyteArray jbytes = (*env)->NewByteArray( env, len );
jbyte* jp = (*env)->GetByteArrayElements( env, jbytes, NULL );
XP_MEMCPY( jp, bytes, len );
(*env)->ReleaseByteArrayElements( env, jbytes, jp, 0 );
strarray = (*env)->CallObjectMethod( env, util->jutil, mid, jbytes );
(*env)->DeleteLocalRef( env, jbytes );
UTIL_CBK_TAIL();
return strarray;
}
XW_UtilCtxt*
makeUtil( MPFORMAL JNIEnv** envp, jobject jutil, CurGameInfo* gi,
AndGlobals* closure )
@ -447,7 +409,6 @@ makeUtil( MPFORMAL JNIEnv** envp, jobject jutil, CurGameInfo* gi,
void
destroyUtil( XW_UtilCtxt** utilc )
{
LOG_FUNC();
AndUtil* util = (AndUtil*)*utilc;
JNIEnv *env = *util->env;
@ -465,5 +426,4 @@ destroyUtil( XW_UtilCtxt** utilc )
XP_FREE( util->util.mpool, util->util.vtable );
XP_FREE( util->util.mpool, util );
*utilc = NULL;
LOG_RETURN_VOID();
}

View file

@ -33,8 +33,4 @@ void destroyUtil( XW_UtilCtxt** util );
bool utilTimerFired( XW_UtilCtxt* util, XWTimerReason why, int handle );
jobject and_util_makeJBitmap( XW_UtilCtxt* util, int nCols, int nRows,
const jboolean* colors );
jobject and_util_splitFaces( XW_UtilCtxt* uc, const XP_U8* bytes, int len );
#endif

View file

@ -102,8 +102,6 @@ makeXportProcs( MPFORMAL JNIEnv** envp, jobject jxport )
{
AndTransportProcs* aprocs = NULL;
XP_LOGF( "%s: jxport=%p", __func__, jxport );
JNIEnv* env = *envp;
aprocs = (AndTransportProcs*)XP_CALLOC( mpool, sizeof(*aprocs) );
if ( NULL != jxport ) {
@ -119,7 +117,6 @@ makeXportProcs( MPFORMAL JNIEnv** envp, jobject jxport )
aprocs->tp.rerror = and_xport_relayError;
aprocs->tp.closure = aprocs;
LOG_RETURNF( "%p", aprocs );
return (TransportProcs*)aprocs;
}

View file

@ -16,6 +16,7 @@
#include "xportwrapper.h"
#include "anddict.h"
#include "andutils.h"
#include "jniutlswrapper.h"
static CurGameInfo*
makeGI( MPFORMAL JNIEnv* env, jobject j_gi )
@ -219,6 +220,32 @@ Java_org_eehouse_android_xw4_jni_XwJNI_comms_1getInitialAddr
setJAddrRec( env, jaddr, &addr );
}
/* Dictionary methods: don't use gamePtr */
JNIEXPORT jboolean JNICALL
Java_org_eehouse_android_xw4_jni_XwJNI_dict_1tilesAreSame
( JNIEnv* env, jclass C, jint dictPtr1, jint dictPtr2 )
{
LOG_FUNC();
jboolean result;
const DictionaryCtxt* dict1 = (DictionaryCtxt*)dictPtr1;
const DictionaryCtxt* dict2 = (DictionaryCtxt*)dictPtr2;
result = dict_tilesAreSame( dict1, dict2 );
LOG_RETURNF( "%d", result );
return result;
}
JNIEXPORT jobjectArray JNICALL
Java_org_eehouse_android_xw4_jni_XwJNI_dict_1getChars
( JNIEnv* env, jclass C, jint dictPtr )
{
LOG_FUNC();
jobject result = NULL;
result = and_dictionary_getChars( env, (DictionaryCtxt*)dictPtr );
(*env)->DeleteLocalRef( env, result );
LOG_RETURNF( "%p", result );
return result;
}
typedef struct _JNIState {
XWGame game;
JNIEnv* env;
@ -262,15 +289,16 @@ Java_org_eehouse_android_xw4_jni_XwJNI_initJNI
JNIEXPORT void JNICALL
Java_org_eehouse_android_xw4_jni_XwJNI_game_1makeNewGame
( JNIEnv* env, jclass C, jint gamePtr, jobject j_gi, jobject j_util,
jobject j_draw, jobject j_cp, jobject j_procs, jbyteArray jDictBytes )
( JNIEnv* env, jclass C, jint gamePtr, jobject j_gi, jobject j_util,
jobject jniu, jobject j_draw, jobject j_cp, jobject j_procs,
jbyteArray jDictBytes )
{
XWJNI_START();
CurGameInfo* gi = makeGI( MPPARM(mpool) env, j_gi );
globals->gi = gi;
XW_UtilCtxt* util = makeUtil( MPPARM(mpool) &state->env, j_util, gi,
globals );
globals->util = util;
globals->util = makeUtil( MPPARM(mpool) &state->env, j_util, gi,
globals );
globals->jniutil = makeJNIUtil( MPPARM(mpool) &state->env, jniu );
DrawCtx* dctx = makeDraw( MPPARM(mpool) &state->env, j_draw );
globals->dctx = dctx;
globals->xportProcs = makeXportProcs( MPPARM(mpool) &state->env, j_procs );
@ -278,10 +306,11 @@ Java_org_eehouse_android_xw4_jni_XwJNI_game_1makeNewGame
loadCommonPrefs( env, &cp, j_cp );
XP_LOGF( "calling game_makeNewGame" );
game_makeNewGame( MPPARM(mpool) &state->game, gi, util, dctx, &cp,
game_makeNewGame( MPPARM(mpool) &state->game, gi, globals->util, dctx, &cp,
globals->xportProcs );
DictionaryCtxt* dict = makeDict( MPPARM(mpool) env, util, jDictBytes );
DictionaryCtxt* dict = makeDict( MPPARM(mpool) env, globals->jniutil,
jDictBytes );
#ifdef STUBBED_DICT
if ( !dict ) {
XP_LOGF( "falling back to stubbed dict" );
@ -312,6 +341,7 @@ JNIEXPORT void JNICALL Java_org_eehouse_android_xw4_jni_XwJNI_game_1dispose
destroyDraw( &globals->dctx );
destroyXportProcs( &globals->xportProcs );
destroyUtil( &globals->util );
destroyJNIUtil( &globals->jniutil );
vtmgr_destroy( MPPARM(mpool) globals->vtMgr );
state->env = oldEnv;
@ -323,8 +353,8 @@ JNIEXPORT void JNICALL Java_org_eehouse_android_xw4_jni_XwJNI_game_1dispose
JNIEXPORT jboolean JNICALL
Java_org_eehouse_android_xw4_jni_XwJNI_game_1makeFromStream
( JNIEnv* env, jclass C, jint gamePtr, jbyteArray jstream,
jobject /*out*/jgi, jbyteArray jdict, jobject jutil, jobject jdraw,
jobject jcp, jobject jprocs )
jobject /*out*/jgi, jbyteArray jdict, jobject jutil, jobject jniu,
jobject jdraw, jobject jcp, jobject jprocs )
{
jboolean result;
XWJNI_START();
@ -332,7 +362,8 @@ Java_org_eehouse_android_xw4_jni_XwJNI_game_1makeFromStream
globals->gi = (CurGameInfo*)XP_CALLOC( mpool, sizeof(*globals->gi) );
globals->util = makeUtil( MPPARM(mpool) &state->env,
jutil, globals->gi, globals );
DictionaryCtxt* dict = makeDict( MPPARM(mpool) env, globals->util, jdict );
globals->jniutil = makeJNIUtil( MPPARM(mpool) &state->env, jniu );
DictionaryCtxt* dict = makeDict( MPPARM(mpool) env, globals->jniutil, jdict );
globals->dctx = makeDraw( MPPARM(mpool) &state->env, jdraw );
globals->xportProcs = makeXportProcs( MPPARM(mpool) &state->env, jprocs );
@ -357,6 +388,7 @@ Java_org_eehouse_android_xw4_jni_XwJNI_game_1makeFromStream
dict_destroy( dict );
dict = NULL;
destroyUtil( &globals->util );
destroyJNIUtil( &globals->jniutil );
destroyGI( MPPARM(mpool) &globals->gi );
}
@ -371,12 +403,19 @@ Java_org_eehouse_android_xw4_jni_XwJNI_game_1saveToStream
jbyteArray result;
XWJNI_START();
CurGameInfo* gi = makeGI( MPPARM(mpool) env, jgi );
/* Use our copy of gi if none's provided. That's because only the caller
knows if its gi should win -- user has changed game config -- or if
ours should -- changes like remote players being added. */
CurGameInfo* gi =
(NULL == jgi) ? globals->gi : makeGI( MPPARM(mpool) env, jgi );
XWStreamCtxt* stream = mem_stream_make( MPPARM(mpool) globals->vtMgr,
NULL, 0, NULL );
game_saveToStream( &state->game, gi, stream );
destroyGI( MPPARM(mpool) &gi );
if ( NULL != jgi ) {
destroyGI( MPPARM(mpool) &gi );
}
int nBytes = stream_getSize( stream );
result = (*env)->NewByteArray( env, nBytes );

View file

@ -1,4 +1,4 @@
/* -*- compile-command: "cd ../../../../../; ant reinstall"; -*- */
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
package org.eehouse.android.xw4;
@ -9,12 +9,10 @@ import android.view.MenuItem;
import android.view.MenuInflater;
import android.content.res.AssetManager;
import java.io.InputStream;
import java.io.InputStreamReader;
import android.os.Handler;
import android.os.Message;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.ByteArrayInputStream;
import android.content.res.Configuration;
import android.content.Intent;
import java.util.concurrent.Semaphore;
@ -22,9 +20,6 @@ import android.net.Uri;
import android.app.Dialog;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.Bitmap;
import java.util.ArrayList;
import android.content.res.Resources;
import org.eehouse.android.xw4.jni.*;
@ -51,6 +46,7 @@ public class BoardActivity extends Activity implements UtilCtxt {
private int m_dlgTitle;
private boolean m_dlgResult;
private CommonPrefs m_cp;
private JNIUtils m_jniu;
// call startActivityForResult synchronously
private Semaphore m_forResultWait = new Semaphore(0);
@ -113,6 +109,7 @@ public class BoardActivity extends Activity implements UtilCtxt {
super.onCreate( savedInstanceState );
m_cp = CommonPrefs.get();
m_jniu = JNIUtilsImpl.get();
setContentView( R.layout.board );
m_handler = new Handler();
@ -147,9 +144,9 @@ public class BoardActivity extends Activity implements UtilCtxt {
if ( null == stream ||
! XwJNI.game_makeFromStream( m_jniGamePtr, stream,
m_gi, dictBytes, this,
m_view, m_cp, m_xport ) ) {
XwJNI.game_makeNewGame( m_jniGamePtr, m_gi, this, m_view,
m_cp, m_xport, dictBytes );
m_jniu, m_view, m_cp, m_xport ) ) {
XwJNI.game_makeNewGame( m_jniGamePtr, m_gi, this, m_jniu,
m_view, m_cp, m_xport, dictBytes );
}
m_jniThread = new
@ -193,7 +190,7 @@ public class BoardActivity extends Activity implements UtilCtxt {
protected void onDestroy()
{
byte[] state = XwJNI.game_saveToStream( m_jniGamePtr, m_gi );
byte[] state = XwJNI.game_saveToStream( m_jniGamePtr, null );
Utils.saveGame( this, state, m_path );
if ( null != m_xport ) {
@ -596,63 +593,4 @@ public class BoardActivity extends Activity implements UtilCtxt {
m_jniThread.handle( JNIThread.JNICmd.CMD_POST_OVER,
R.string.finalscores_title );
}
public BitmapDrawable makeBitmap( int width, int height, boolean[] colors )
{
Bitmap bitmap = Bitmap.createBitmap( width, height,
Bitmap.Config.ARGB_8888 );
int indx = 0;
for ( int yy = 0; yy < height; ++yy ) {
for ( int xx = 0; xx < width; ++xx ) {
boolean pixelSet = colors[indx++];
bitmap.setPixel( xx, yy, pixelSet? 0xFF000000 : 0x00FFFFFF );
}
}
// Doesn't compile if pass getResources(). Maybe the
// "deprecated" API is really the only one?
return new BitmapDrawable( /*getResources(), */bitmap );
}
/** Working around lack of utf8 support on the JNI side: given a
* utf-8 string with embedded small number vals starting with 0,
* convert into individual strings. The 0 is the problem: it's
* not valid utf8. So turn it and the other nums into strings and
* catch them on the other side.
*/
public String[] splitFaces( byte[] chars )
{
ArrayList<String> al = new ArrayList<String>();
int ii = 0;
ByteArrayInputStream bais = new ByteArrayInputStream( chars );
InputStreamReader isr = new InputStreamReader( bais );
int[] codePoints = new int[1];
for ( ; ; ) {
int chr = -1;
try {
chr = isr.read();
} catch ( java.io.IOException ioe ) {
Utils.logf( ioe.toString() );
}
if ( -1 == chr ) {
break;
} else {
String letter;
if ( chr < 32 ) {
letter = String.format( "%d", chr );
} else {
codePoints[0] = chr;
letter = new String( codePoints, 0, 1 );
}
al.add( letter );
}
}
String[] result = al.toArray( new String[al.size()] );
return result;
}
} // class BoardActivity

View file

@ -1,4 +1,4 @@
/* -*- compile-command: "cd ../../../../../; ant reinstall"; -*- */
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
package org.eehouse.android.xw4;
@ -37,6 +37,7 @@ public class BoardView extends View implements DrawCtx,
private String[] m_scores;
private Rect m_boundsScratch;
private String m_remText;
private int m_dictPtr = 0;
private static final int BLACK = 0xFF000000;
private static final int WHITE = 0xFFFFFFFF;
@ -359,6 +360,22 @@ public class BoardView extends View implements DrawCtx,
}
}
public void dictChanged( int dictPtr )
{
Utils.logf( "BoardView::dictChanged" );
if ( m_dictPtr != dictPtr ) {
if ( m_dictPtr == 0 || !XwJNI.dict_tilesAreSame( m_dictPtr, dictPtr ) ) {
String[] chars = XwJNI.dict_getChars( dictPtr );
for ( String str : chars ) {
if ( str.length() > 0 && str.charAt(0) >= 32 ) {
Utils.logf( "got " + str );
}
}
}
m_dictPtr = dictPtr;
}
}
private void drawTileImpl( Rect rect, String text,
BitmapDrawable[] bitmaps, int val,
int flags, boolean clearBack )

View file

@ -1,4 +1,4 @@
/* -*- compile-command: "cd ../../../../../; ant reinstall"; -*- */
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
/*
* Copyright (C) 2007 The Android Open Source Project
@ -241,9 +241,10 @@ public class GameConfig extends Activity implements View.OnClickListener {
byte[] dictBytes = Utils.openDict( this, m_gi.dictName );
int gamePtr = XwJNI.initJNI();
if ( !XwJNI.game_makeFromStream( gamePtr, stream, m_gi, dictBytes,
m_cp ) ) {
XwJNI.game_makeNewGame( gamePtr, m_gi, m_cp, dictBytes );
if ( !XwJNI.game_makeFromStream( gamePtr, stream, JNIUtilsImpl.get(),
m_gi, dictBytes, m_cp ) ) {
XwJNI.game_makeNewGame( gamePtr, m_gi, JNIUtilsImpl.get(),
m_cp, dictBytes );
}
int curSel = listAvailableDicts( m_gi.dictName );
@ -616,7 +617,8 @@ public class GameConfig extends Activity implements View.OnClickListener {
byte[] dictBytes = Utils.openDict( this, m_gi.dictName );
int gamePtr = XwJNI.initJNI();
XwJNI.game_makeNewGame( gamePtr, m_gi, m_cp, dictBytes );
XwJNI.game_makeNewGame( gamePtr, m_gi, JNIUtilsImpl.get(),
m_cp, dictBytes );
if ( null != m_car ) {
XwJNI.comms_setAddr( gamePtr, m_car );

View file

@ -77,7 +77,11 @@ public class CommonPrefs {
{
String key = s_context.getString( id );
String val = sp.getString( key, "" );
return 0xFF000000 | Integer.decode( val );
try {
return 0xFF000000 | Integer.decode( val );
} catch ( java.lang.NumberFormatException nfe ) {
return 0xFF7F7F7F;
}
}
/*

View file

@ -47,4 +47,6 @@ public interface DrawCtx {
void objFinished( /*BoardObjectType*/int typ, Rect rect, int dfs );
void dictChanged( int dictPtr );
}

View file

@ -61,7 +61,6 @@ public class JNIThread extends Thread {
}
public JNIThread( int gamePtr, CurGameInfo gi, Handler handler ) {
Utils.logf( "in JNIThread()" );
m_jniGamePtr = gamePtr;
m_gi = gi;
m_handler = handler;

View file

@ -0,0 +1,12 @@
/* -*- compile-command: "cd ../../../../../../; ant install"; -*- */
package org.eehouse.android.xw4.jni;
import android.graphics.drawable.BitmapDrawable;
public interface JNIUtils {
// Stuff I can't do in C....
BitmapDrawable makeBitmap( int width, int height, boolean[] colors );
String[] splitFaces( byte[] chars );
}

View file

@ -0,0 +1,84 @@
/* -*- compile-command: "cd ../../../../../../; ant install"; -*- */
package org.eehouse.android.xw4.jni;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.Bitmap;
import java.util.ArrayList;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import org.eehouse.android.xw4.*;
public class JNIUtilsImpl implements JNIUtils {
private static JNIUtils s_impl = null;
private JNIUtilsImpl(){}
public static JNIUtils get()
{
if ( null == s_impl ) {
s_impl = new JNIUtilsImpl();
}
return s_impl;
}
public BitmapDrawable makeBitmap( int width, int height, boolean[] colors )
{
Bitmap bitmap = Bitmap.createBitmap( width, height,
Bitmap.Config.ARGB_8888 );
int indx = 0;
for ( int yy = 0; yy < height; ++yy ) {
for ( int xx = 0; xx < width; ++xx ) {
boolean pixelSet = colors[indx++];
bitmap.setPixel( xx, yy, pixelSet? 0xFF000000 : 0x00FFFFFF );
}
}
// Doesn't compile if pass getResources(). Maybe the
// "deprecated" API is really the only one?
return new BitmapDrawable( /*getResources(), */bitmap );
}
/** Working around lack of utf8 support on the JNI side: given a
* utf-8 string with embedded small number vals starting with 0,
* convert into individual strings. The 0 is the problem: it's
* not valid utf8. So turn it and the other nums into strings and
* catch them on the other side.
*/
public String[] splitFaces( byte[] chars )
{
ArrayList<String> al = new ArrayList<String>();
int ii = 0;
ByteArrayInputStream bais = new ByteArrayInputStream( chars );
InputStreamReader isr = new InputStreamReader( bais );
int[] codePoints = new int[1];
for ( ; ; ) {
int chr = -1;
try {
chr = isr.read();
} catch ( java.io.IOException ioe ) {
Utils.logf( ioe.toString() );
}
if ( -1 == chr ) {
break;
} else {
String letter;
if ( chr < 32 ) {
letter = String.format( "%d", chr );
} else {
codePoints[0] = chr;
letter = new String( codePoints, 0, 1 );
}
al.add( letter );
}
}
String[] result = al.toArray( new String[al.size()] );
return result;
}
}

View file

@ -1,4 +1,4 @@
/* -*- compile-command: "cd ../../../../../../; ant reinstall"; -*- */
/* -*- compile-command: "cd ../../../../../../; ant install"; -*- */
package org.eehouse.android.xw4.jni;
@ -81,12 +81,6 @@ public interface UtilCtxt {
void userError( int id );
void notifyGameOver();
BitmapDrawable makeBitmap( int width, int height, boolean[] colors );
String[] splitFaces( byte[] chars );
// Don't need this unless we have a scroll thumb to indicate position
//void yOffsetChange( int oldOffset, int newOffset );
}

View file

@ -1,4 +1,4 @@
/* -*- compile-command: "cd ../../../../../../; ant reinstall"; -*- */
/* -*- compile-command: "cd ../../../../../../; ant install"; -*- */
package org.eehouse.android.xw4.jni;
@ -28,6 +28,7 @@ public class XwJNI {
public static native void game_makeNewGame( int gamePtr,
CurGameInfo gi,
UtilCtxt util,
JNIUtils jniu,
DrawCtx draw, CommonPrefs cp,
TransportProcs procs,
byte[] dict );
@ -37,25 +38,29 @@ public class XwJNI {
CurGameInfo gi,
byte[] dict,
UtilCtxt util,
JNIUtils jniu,
DrawCtx draw,
CommonPrefs cp,
TransportProcs procs );
// leave out options params for when game won't be rendered or
// played
public static void game_makeNewGame( int gamePtr, CurGameInfo gi,
CommonPrefs cp, byte[] dict ) {
game_makeNewGame( gamePtr, gi, (UtilCtxt)null,
public static void game_makeNewGame( int gamePtr, CurGameInfo gi,
JNIUtils jniu, CommonPrefs cp,
byte[] dict ) {
game_makeNewGame( gamePtr, gi, (UtilCtxt)null, jniu,
(DrawCtx)null, cp, (TransportProcs)null, dict );
}
public static boolean game_makeFromStream( int gamePtr,
byte[] stream,
JNIUtils jniu,
CurGameInfo gi,
byte[] dict,
CommonPrefs cp ) {
return game_makeFromStream( gamePtr, stream, gi, dict, (UtilCtxt)null,
(DrawCtx)null, cp, (TransportProcs)null );
jniu, (DrawCtx)null, cp,
(TransportProcs)null );
}
public static native boolean game_receiveMessage( int gamePtr,
@ -119,4 +124,8 @@ public class XwJNI {
public static native void comms_start( int gamePtr );
public static native void comms_getAddr( int gamePtr, CommsAddrRec addr );
public static native void comms_setAddr( int gamePtr, CommsAddrRec addr );
// Dicts
public static native boolean dict_tilesAreSame( int dictPtr1, int dictPtr2 );
public static native String[] dict_getChars( int dictPtr );
}

View file

@ -73,7 +73,7 @@ struct DictionaryCtxt {
necessarily the entry point for search!! */
XP_UCHAR* name;
XP_UCHAR* faces;
XP_UCHAR** facePtrs;
const XP_UCHAR** facePtrs;
XP_U8* countsAndValues;
SpecialBitmaps* bitmaps;