From b9d0469cfe1d30b9cecb7c93d42c5c009da50c1c Mon Sep 17 00:00:00 2001 From: Eric House Date: Fri, 1 Nov 2013 19:09:05 -0700 Subject: [PATCH 01/10] fix OFFSET_OF ptr size to quiet compiler --- xwords4/common/comtypes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xwords4/common/comtypes.h b/xwords4/common/comtypes.h index d841696f6..66e297752 100644 --- a/xwords4/common/comtypes.h +++ b/xwords4/common/comtypes.h @@ -240,7 +240,7 @@ typedef struct _PlayerDicts { # define DEBUG_ASSIGN(a,b) #endif -#define OFFSET_OF(typ,var) ((XP_U16)&(((typ*) 0)->var)) +#define OFFSET_OF(typ,var) ((XP_U32)&(((typ*) 0)->var)) #ifndef RELAY_NAME_DEFAULT # define RELAY_NAME_DEFAULT "eehouse.org" From cc994368aa72ece4b0d9081aebbd001b08d01f47 Mon Sep 17 00:00:00 2001 From: Eric House Date: Fri, 1 Nov 2013 19:10:08 -0700 Subject: [PATCH 02/10] move ints and booleans between java and c structs using arrays of data rather than a ton of nearly identical function calls. --- xwords4/android/XWords4/jni/andutils.c | 78 ++++++++++++++++++++++++++ xwords4/android/XWords4/jni/andutils.h | 18 ++++++ xwords4/android/XWords4/jni/xwjni.c | 51 +++++++++-------- 3 files changed, 123 insertions(+), 24 deletions(-) diff --git a/xwords4/android/XWords4/jni/andutils.c b/xwords4/android/XWords4/jni/andutils.c index 33e4689fd..c3530ce08 100644 --- a/xwords4/android/XWords4/jni/andutils.c +++ b/xwords4/android/XWords4/jni/andutils.c @@ -88,6 +88,30 @@ getInt( JNIEnv* env, jobject obj, const char* name ) return result; } +void +getInts( JNIEnv* env, void* cobj, jobject jobj, const SetInfo* sis, XP_U16 nSis ) +{ + int ii; + for ( ii = 0; ii < nSis; ++ii ) { + const SetInfo* si = &sis[ii]; + uint8_t* ptr = ((uint8_t*)cobj) + si->offset; + int val = getInt( env, jobj, si->name ); + switch( si->siz ) { + case 4: + *(uint32_t*)ptr = val; + break; + case 2: + *(uint16_t*)ptr = val; + break; + case 1: + *ptr = val; + break; + } + /* XP_LOGF( "%s: wrote int %s of size %dwith val %d at offset %d", */ + /* __func__, si->name, si->siz, val, si->offset ); */ + } +} + void setInt( JNIEnv* env, jobject obj, const char* name, int value ) { @@ -99,6 +123,34 @@ setInt( JNIEnv* env, jobject obj, const char* name, int value ) deleteLocalRef( env, cls ); } +void +setInts( JNIEnv* env, jobject jobj, void* cobj, const SetInfo* sis, XP_U16 nSis ) +{ + int ii; + for ( ii = 0; ii < nSis; ++ii ) { + const SetInfo* si = &sis[ii]; + uint8_t* ptr = ((uint8_t*)cobj) + si->offset; + int val; + switch( si->siz ) { + case 4: + val = *(uint32_t*)ptr; + break; + case 2: + val = *(uint16_t*)ptr; + break; + case 1: + val = *ptr; + break; + default: + val = 0; + XP_ASSERT(0); + } + setInt( env, jobj, si->name, val ); + /* XP_LOGF( "%s: read int %s of size %d with val %d from offset %d", */ + /* __func__, si->name, si->siz, val, si->offset ); */ + } +} + bool setBool( JNIEnv* env, jobject obj, const char* name, bool value ) { @@ -114,6 +166,19 @@ setBool( JNIEnv* env, jobject obj, const char* name, bool value ) return success; } +void +setBools( JNIEnv* env, jobject jobj, void* cobj, const SetInfo* sis, XP_U16 nSis ) +{ + int ii; + for ( ii = 0; ii < nSis; ++ii ) { + const SetInfo* si = &sis[ii]; + XP_Bool val = *(XP_Bool*)(((uint8_t*)cobj)+si->offset); + setBool( env, jobj, si->name, val ); + /* XP_LOGF( "%s: read bool %s with val %d from offset %d", __func__, */ + /* si->name, val, si->offset ); */ + } +} + bool setString( JNIEnv* env, jobject obj, const char* name, const XP_UCHAR* value ) { @@ -210,6 +275,19 @@ getBool( JNIEnv* env, jobject obj, const char* name ) return result; } +void +getBools( JNIEnv* env, void* cobj, jobject jobj, const SetInfo* sis, XP_U16 nSis ) +{ + int ii; + for ( ii = 0; ii < nSis; ++ii ) { + const SetInfo* si = &sis[ii]; + XP_Bool val = getBool( env, jobj, si->name ); + *(XP_Bool*)(((uint8_t*)cobj)+si->offset) = val; + /* XP_LOGF( "%s: wrote bool %s with val %d at offset %d", __func__, */ + /* si->name, val, si->offset ); */ + } +} + jintArray makeIntArray( JNIEnv *env, int siz, const jint* vals ) { diff --git a/xwords4/android/XWords4/jni/andutils.h b/xwords4/android/XWords4/jni/andutils.h index 4d4e62584..f14d644e1 100644 --- a/xwords4/android/XWords4/jni/andutils.h +++ b/xwords4/android/XWords4/jni/andutils.h @@ -33,10 +33,28 @@ void and_send_on_close( XWStreamCtxt* stream, void* closure ); XWStreamCtxt* and_empty_stream( MPFORMAL AndGlobals* globals ); +typedef struct _SetInfo { + const char* name; + int offset; + int siz; +} SetInfo; +#define ARR_MEMBER(obj, fld) { .name = #fld, \ + .offset = OFFSET_OF(obj, fld), \ + .siz = sizeof(((obj *)0)->fld) \ + } + int getInt( JNIEnv* env, jobject obj, const char* name ); void setInt( JNIEnv* env, jobject obj, const char* name, int value ); +void setInts( JNIEnv* env, jobject jobj, void* cobj, + const SetInfo* sis, XP_U16 nSis ); +void getInts( JNIEnv* env, void* cobj, jobject jobj, + const SetInfo* sis, XP_U16 nSis ); bool getBool( JNIEnv* env, jobject obj, const char* name ); +void getBools( JNIEnv* env, void* cobj, jobject jobj, + const SetInfo* sis, XP_U16 nSis ); bool setBool( JNIEnv* env, jobject obj, const char* name, bool value ); +void setBools( JNIEnv* env, jobject jobj, void* cobj, + const SetInfo* sis, XP_U16 nSis ); bool setString( JNIEnv* env, jobject obj, const char* name, const XP_UCHAR* value ); void getString( JNIEnv* env, jobject jlp, const char* name, XP_UCHAR* buf, int bufLen ); diff --git a/xwords4/android/XWords4/jni/xwjni.c b/xwords4/android/XWords4/jni/xwjni.c index 4df3ba83e..4aae6f509 100644 --- a/xwords4/android/XWords4/jni/xwjni.c +++ b/xwords4/android/XWords4/jni/xwjni.c @@ -39,47 +39,54 @@ #include "jniutlswrapper.h" #include "paths.h" +static const SetInfo gi_ints[] = { + ARR_MEMBER( CurGameInfo, nPlayers ) + ,ARR_MEMBER( CurGameInfo, gameSeconds ) + ,ARR_MEMBER( CurGameInfo, boardSize ) + ,ARR_MEMBER( CurGameInfo, gameID ) + ,ARR_MEMBER( CurGameInfo, dictLang ) +}; + +static const SetInfo gi_bools[] = { + ARR_MEMBER( CurGameInfo, hintsNotAllowed ) + ,ARR_MEMBER( CurGameInfo, timerEnabled ) + ,ARR_MEMBER( CurGameInfo, allowPickTiles ) + ,ARR_MEMBER( CurGameInfo, allowHintRect ) +}; + static CurGameInfo* -makeGI( MPFORMAL JNIEnv* env, jobject j_gi ) +makeGI( MPFORMAL JNIEnv* env, jobject jgi ) { CurGameInfo* gi = (CurGameInfo*)XP_CALLOC( mpool, sizeof(*gi) ); XP_UCHAR buf[256]; /* in case needs whole path */ - gi->nPlayers = getInt( env, j_gi, "nPlayers"); - gi->gameSeconds = getInt( env, j_gi, "gameSeconds"); - gi->boardSize = getInt( env, j_gi, "boardSize" ); + getInts( env, (void*)gi, jgi, gi_ints, VSIZE(gi_ints) ); + getBools( env, (void*)gi, jgi, gi_bools, VSIZE(gi_bools) ); /* Unlike on other platforms, gi is created without a call to game_makeNewGame, which sets gameID. So check here if it's still unset and if necessary set it -- including back in the java world. */ - gi->gameID = getInt( env, j_gi, "gameID" ); if ( 0 == gi->gameID ) { while ( 0 == gi->gameID ) { gi->gameID = getCurSeconds( env ); } - setInt( env, j_gi, "gameID", gi->gameID ); + setInt( env, jgi, "gameID", gi->gameID ); } - gi->dictLang = getInt( env, j_gi, "dictLang" ); - gi->hintsNotAllowed = getBool( env, j_gi, "hintsNotAllowed" ); - gi->timerEnabled = getBool( env, j_gi, "timerEnabled" ); - gi->allowPickTiles = getBool( env, j_gi, "allowPickTiles" ); - gi->allowHintRect = getBool( env, j_gi, "allowHintRect" ); - gi->phoniesAction = - jenumFieldToInt( env, j_gi, "phoniesAction", + jenumFieldToInt( env, jgi, "phoniesAction", PKG_PATH("jni/CurGameInfo$XWPhoniesChoice") ); gi->serverRole = - jenumFieldToInt( env, j_gi, "serverRole", + jenumFieldToInt( env, jgi, "serverRole", PKG_PATH("jni/CurGameInfo$DeviceRole")); - getString( env, j_gi, "dictName", buf, VSIZE(buf) ); + getString( env, jgi, "dictName", buf, VSIZE(buf) ); gi->dictName = copyString( mpool, buf ); XP_ASSERT( gi->nPlayers <= MAX_NUM_PLAYERS ); jobject jplayers; - if ( getObject( env, j_gi, "players", "[L" PKG_PATH("jni/LocalPlayer") ";", + if ( getObject( env, jgi, "players", "[L" PKG_PATH("jni/LocalPlayer") ";", &jplayers ) ) { int ii; for ( ii = 0; ii < gi->nPlayers; ++ii ) { @@ -114,14 +121,10 @@ static void setJGI( JNIEnv* env, jobject jgi, const CurGameInfo* gi ) { // set fields - setInt( env, jgi, "nPlayers", gi->nPlayers ); - setInt( env, jgi, "gameSeconds", gi->gameSeconds ); - setInt( env, jgi, "boardSize", gi->boardSize ); - setInt( env, jgi, "gameID", gi->gameID ); - setInt( env, jgi, "dictLang", gi->dictLang ); - setBool( env, jgi, "hintsNotAllowed", gi->hintsNotAllowed ); - setBool( env, jgi, "timerEnabled", gi->timerEnabled ); - setBool( env, jgi, "allowPickTiles", gi->allowPickTiles ); + + setInts( env, jgi, (void*)gi, gi_ints, VSIZE(gi_ints) ); + setBools( env, jgi, (void*)gi, gi_bools, VSIZE(gi_bools) ); + setString( env, jgi, "dictName", gi->dictName ); intToJenumField( env, jgi, gi->phoniesAction, "phoniesAction", From 4ae79f6f27e2e2fc61aaaa6bd4930a9aabf3ffe9 Mon Sep 17 00:00:00 2001 From: Eric House Date: Fri, 1 Nov 2013 21:16:52 -0700 Subject: [PATCH 03/10] apply contributed patch making Makefile variable naming match required conventions for CLEAR_VARS. --- xwords4/android/XWords4/jni/Android.mk | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/xwords4/android/XWords4/jni/Android.mk b/xwords4/android/XWords4/jni/Android.mk index 83af1a2fc..b60f6f5eb 100644 --- a/xwords4/android/XWords4/jni/Android.mk +++ b/xwords4/android/XWords4/jni/Android.mk @@ -4,17 +4,17 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) COMMON_PATH=../../../common -local_C_INCLUDES+= \ +LOCAL_C_INCLUDES+= \ -I$(LOCAL_PATH)/$(COMMON_PATH) \ -I$(LOCAL_PATH)/../../../relay \ -local_LDLIBS += -llog +LOCAL_LDLIBS += -llog ifeq ($(BUILD_TARGET),debug) - local_DEBUG = -DMEM_DEBUG -DDEBUG -DENABLE_LOGGING -DCOMMS_CHECKSUM -Wno-unused-but-set-variable + LOCAL_DEBUG = -DMEM_DEBUG -DDEBUG -DENABLE_LOGGING -DCOMMS_CHECKSUM -Wno-unused-but-set-variable endif -local_DEFINES += \ - $(local_DEBUG) \ +LOCAL_DEFINES += \ + $(LOCAL_DEBUG) \ -DXWFEATURE_RELAY \ -DXWFEATURE_SMS \ -DXWFEATURE_COMMSACK \ @@ -42,12 +42,13 @@ local_DEFINES += \ -D__LITTLE_ENDIAN \ ifeq ($(CHAT_ENABLED),true) - local_DEFINES += -DXWFEATURE_CHAT + + LOCAL_DEFINES += -DXWFEATURE_CHAT endif # -DXWFEATURE_SCOREONEPASS \ -local_SRC_FILES += \ +LOCAL_SRC_FILES += \ xwjni.c \ utilwrapper.c \ drawwrapper.c \ @@ -58,7 +59,7 @@ local_SRC_FILES += \ COMMON_PATH=../../../common -common_SRC_FILES += \ +COMMON_SRC_FILES += \ $(COMMON_PATH)/boarddrw.c \ $(COMMON_PATH)/scorebdp.c \ $(COMMON_PATH)/dragdrpp.c \ @@ -81,9 +82,12 @@ common_SRC_FILES += \ $(COMMON_PATH)/dbgutil.c \ -LOCAL_CFLAGS+=$(local_C_INCLUDES) $(local_DEFINES) -Wall -LOCAL_SRC_FILES := $(linux_SRC_FILES) $(local_SRC_FILES) $(common_SRC_FILES) +LOCAL_CFLAGS+=$(LOCAL_C_INCLUDES) $(LOCAL_DEFINES) +LOCAL_SRC_FILES := $(linux_SRC_FILES) $(LOCAL_SRC_FILES) $(COMMON_SRC_FILES) LOCAL_MODULE := xwjni LOCAL_LDLIBS := -L${SYSROOT}/usr/lib -llog -lz include $(BUILD_SHARED_LIBRARY) + +COMMON_SRC_FILES := +COMMON_PATH := From 251ad5de25ecc17c056586783bb8700473d4b8a0 Mon Sep 17 00:00:00 2001 From: Eric House Date: Fri, 1 Nov 2013 21:22:42 -0700 Subject: [PATCH 04/10] apply contributed patch adding x86 version of libxwjni.so --- xwords4/android/XWords4/jni/Application.mk | 1 + 1 file changed, 1 insertion(+) create mode 100644 xwords4/android/XWords4/jni/Application.mk diff --git a/xwords4/android/XWords4/jni/Application.mk b/xwords4/android/XWords4/jni/Application.mk new file mode 100644 index 000000000..7a1599bb9 --- /dev/null +++ b/xwords4/android/XWords4/jni/Application.mk @@ -0,0 +1 @@ +APP_ABI := armeabi x86 From b151cb977e47a980b5f07fd90c82ba1bc9c011bf Mon Sep 17 00:00:00 2001 From: Eric House Date: Sun, 3 Nov 2013 05:22:20 -0800 Subject: [PATCH 05/10] apply patches from Brendan Le Foll to enable x86 ndk support --- xwords4/android/XWords4/jni/Android.mk | 24 +++++++++++++--------- xwords4/android/XWords4/jni/Application.mk | 1 + 2 files changed, 15 insertions(+), 10 deletions(-) create mode 100644 xwords4/android/XWords4/jni/Application.mk diff --git a/xwords4/android/XWords4/jni/Android.mk b/xwords4/android/XWords4/jni/Android.mk index 83af1a2fc..b60f6f5eb 100644 --- a/xwords4/android/XWords4/jni/Android.mk +++ b/xwords4/android/XWords4/jni/Android.mk @@ -4,17 +4,17 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) COMMON_PATH=../../../common -local_C_INCLUDES+= \ +LOCAL_C_INCLUDES+= \ -I$(LOCAL_PATH)/$(COMMON_PATH) \ -I$(LOCAL_PATH)/../../../relay \ -local_LDLIBS += -llog +LOCAL_LDLIBS += -llog ifeq ($(BUILD_TARGET),debug) - local_DEBUG = -DMEM_DEBUG -DDEBUG -DENABLE_LOGGING -DCOMMS_CHECKSUM -Wno-unused-but-set-variable + LOCAL_DEBUG = -DMEM_DEBUG -DDEBUG -DENABLE_LOGGING -DCOMMS_CHECKSUM -Wno-unused-but-set-variable endif -local_DEFINES += \ - $(local_DEBUG) \ +LOCAL_DEFINES += \ + $(LOCAL_DEBUG) \ -DXWFEATURE_RELAY \ -DXWFEATURE_SMS \ -DXWFEATURE_COMMSACK \ @@ -42,12 +42,13 @@ local_DEFINES += \ -D__LITTLE_ENDIAN \ ifeq ($(CHAT_ENABLED),true) - local_DEFINES += -DXWFEATURE_CHAT + + LOCAL_DEFINES += -DXWFEATURE_CHAT endif # -DXWFEATURE_SCOREONEPASS \ -local_SRC_FILES += \ +LOCAL_SRC_FILES += \ xwjni.c \ utilwrapper.c \ drawwrapper.c \ @@ -58,7 +59,7 @@ local_SRC_FILES += \ COMMON_PATH=../../../common -common_SRC_FILES += \ +COMMON_SRC_FILES += \ $(COMMON_PATH)/boarddrw.c \ $(COMMON_PATH)/scorebdp.c \ $(COMMON_PATH)/dragdrpp.c \ @@ -81,9 +82,12 @@ common_SRC_FILES += \ $(COMMON_PATH)/dbgutil.c \ -LOCAL_CFLAGS+=$(local_C_INCLUDES) $(local_DEFINES) -Wall -LOCAL_SRC_FILES := $(linux_SRC_FILES) $(local_SRC_FILES) $(common_SRC_FILES) +LOCAL_CFLAGS+=$(LOCAL_C_INCLUDES) $(LOCAL_DEFINES) +LOCAL_SRC_FILES := $(linux_SRC_FILES) $(LOCAL_SRC_FILES) $(COMMON_SRC_FILES) LOCAL_MODULE := xwjni LOCAL_LDLIBS := -L${SYSROOT}/usr/lib -llog -lz include $(BUILD_SHARED_LIBRARY) + +COMMON_SRC_FILES := +COMMON_PATH := diff --git a/xwords4/android/XWords4/jni/Application.mk b/xwords4/android/XWords4/jni/Application.mk new file mode 100644 index 000000000..7a1599bb9 --- /dev/null +++ b/xwords4/android/XWords4/jni/Application.mk @@ -0,0 +1 @@ +APP_ABI := armeabi x86 From 5a65bca12aff3c819e9aefa8239037b019c6f8d7 Mon Sep 17 00:00:00 2001 From: Eric House Date: Sun, 3 Nov 2013 12:12:25 -0800 Subject: [PATCH 06/10] add board functions to figure layout (position and size of board, tray, etc.), removing need for each client to do it itself. --- xwords4/common/board.c | 112 ++++++++++++++++++++++++++++++++++++++ xwords4/common/board.h | 49 ++++++++++++----- xwords4/common/game.h | 35 +----------- xwords4/common/gameinfo.h | 68 +++++++++++++++++++++++ 4 files changed, 217 insertions(+), 47 deletions(-) create mode 100644 xwords4/common/gameinfo.h diff --git a/xwords4/common/board.c b/xwords4/common/board.c index 82acc8a7a..2ef2d7f23 100644 --- a/xwords4/common/board.c +++ b/xwords4/common/board.c @@ -389,6 +389,118 @@ board_reset( BoardCtxt* board ) setTimerIf( board ); } /* board_reset */ +#ifdef COMMON_LAYOUT +void +board_figureLayout( BoardCtxt* board, const CurGameInfo* gi, + XP_U16 fontHt, XP_U16 fontWidth, XP_Bool squareTiles, + const XP_Rect* bounds, BoardDims* dimsp ) +{ + BoardDims ldims; + XP_MEMSET( &ldims, 0, sizeof(ldims) ); + + XP_U16 nCells = gi->boardSize; + XP_U16 maxCellSize = 4 * fontHt; + XP_U16 trayHt; + XP_U16 scoreHt; + XP_U16 wantHt; + XP_U16 nToScroll; + XP_Bool firstPass; + + ldims.left = bounds->left; + ldims.top = bounds->top; + + for ( firstPass = XP_TRUE; ; ) { + ldims.width = bounds->width; + + XP_U16 cellSize = bounds->width / nCells; + if ( cellSize > maxCellSize ) { + cellSize = maxCellSize; + + XP_U16 boardWidth = nCells * cellSize; + ldims.width = boardWidth; + } + ldims.maxCellSize = maxCellSize; + + // Now determine if vertical scrolling will be necessary. + // There's a minimum tray and scoreboard height. If we can + // fit them and all cells no scrolling's needed. Otherwise + // determine the minimum number that must be hidden to fit. + // Finally grow scoreboard and tray to use whatever's left. + trayHt = 2 * cellSize; + scoreHt = (cellSize * 3) / 2; + wantHt = trayHt + scoreHt + (cellSize * nCells); + if ( wantHt <= bounds->height ) { + nToScroll = 0; + } else { + // Scrolling's required if we use cell width sufficient to + // fill the screen. But perhaps we don't need to. + int cellWidth = 2 * (bounds->height / ( 4 + 3 + (2*nCells))); + if ( firstPass && cellWidth >= fontHt ) { + firstPass = XP_FALSE; + ldims.width = nCells * cellWidth; + continue; + } else { + nToScroll = nCells - + ((bounds->height - trayHt - scoreHt) / cellSize); + } + } + + XP_U16 heightUsed = trayHt + scoreHt + (nCells - nToScroll) * cellSize; + XP_U16 heightLeft = bounds->height - heightUsed; + if ( 0 < heightLeft ) { + if ( heightLeft > (cellSize * 3 / 2) ) { + heightLeft = cellSize * 3 / 2; + } + heightLeft /= 3; + scoreHt += heightLeft; + + trayHt += heightLeft * 2; + if ( squareTiles && trayHt > (bounds->width / 7) ) { + trayHt = bounds->width / 7; + } + heightUsed = trayHt + scoreHt + ((nCells - nToScroll) * cellSize); + } + + ldims.trayHt = trayHt; + ldims.scoreHt = scoreHt; + + ldims.boardHt = cellSize * nCells; + ldims.trayTop = scoreHt + (cellSize * (nCells-nToScroll)); + ldims.height = heightUsed; + ldims.cellSize = cellSize; + + if ( gi->timerEnabled ) { + ldims.timerWidth = fontWidth * XP_STRLEN("-00:00"); + } + break; + } + + if ( !!dimsp ) { + XP_MEMCPY( dimsp, &ldims, sizeof(ldims) ); + } else { + board_applyLayout( board, &ldims ); + } +} + +void +board_applyLayout( BoardCtxt* board, const BoardDims* dims ) +{ + board_setPos( board, dims->left, dims->top + dims->scoreHt, + dims->width, dims->top + dims->scoreHt + dims->boardHt, + dims->maxCellSize, XP_FALSE ); + + board_setScoreboardLoc( board, dims->left, dims->top, + dims->width - dims->timerWidth, + dims->scoreHt, XP_TRUE ); + + board_setTimerLoc( board, dims->left + dims->width - dims->timerWidth, + dims->top, dims->timerWidth, dims->scoreHt ); + + board_setTrayLoc( board, dims->left, dims->trayTop, + dims->width, dims->trayHt, dims->width / 20 ); +} +#endif + void board_setPos( BoardCtxt* board, XP_U16 left, XP_U16 top, XP_U16 width, XP_U16 height, XP_U16 maxCellSz, diff --git a/xwords4/common/board.h b/xwords4/common/board.h index 9bce19bb4..b08b091d6 100644 --- a/xwords4/common/board.h +++ b/xwords4/common/board.h @@ -22,6 +22,7 @@ #include "comtypes.h" #include "model.h" +#include "gameinfo.h" #include "server.h" #include "draw.h" #include "xwstream.h" @@ -57,7 +58,6 @@ typedef enum { /* typedef struct BoardCtxt BoardCtxt; */ - BoardCtxt* board_make( MPFORMAL ModelCtxt* model, ServerCtxt* server, DrawCtx* draw, XW_UtilCtxt* util ); BoardCtxt* board_makeFromStream( MPFORMAL XWStreamCtxt* stream, @@ -70,10 +70,44 @@ void board_destroy( BoardCtxt* board ); void board_writeToStream( const BoardCtxt* board, XWStreamCtxt* stream ); +void board_reset( BoardCtxt* board ); + + /* Layout. Either done internally or by client */ +#ifdef COMMON_LAYOUT + +typedef struct _BoardDims { + XP_U16 left, top; + XP_U16 width, height; + XP_U16 scoreHt; + XP_U16 boardHt; + XP_U16 trayTop, trayHt; + XP_U16 cellSize, maxCellSize; + XP_U16 timerWidth; +} BoardDims; + +void board_figureLayout( BoardCtxt* board, const CurGameInfo* gi, + XP_U16 fontHt, XP_U16 fontWidth, + XP_Bool squareTiles, const XP_Rect* bounds, + /* out */ BoardDims* dims ); +void board_applyLayout( BoardCtxt* board, const BoardDims* dims ); + +#endif + +/* These four aren't needed if COMMON_LAYOUT defined */ void board_setPos( BoardCtxt* board, XP_U16 left, XP_U16 top, XP_U16 width, XP_U16 height, XP_U16 maxCellSize, XP_Bool leftHanded ); -void board_reset( BoardCtxt* board ); +void board_setScoreboardLoc( BoardCtxt* board, + XP_U16 scoreLeft, XP_U16 scoreTop, + XP_U16 scoreWidth, XP_U16 scoreHeight, + XP_Bool divideHorizontally ); +void board_setTimerLoc( BoardCtxt* board, + XP_U16 timerLeft, XP_U16 timerTop, + XP_U16 timerWidth, XP_U16 timerHeight ); +void board_setTrayLoc( BoardCtxt* board, XP_U16 trayLeft, XP_U16 trayTop, + XP_U16 trayWidth, XP_U16 trayHeight, + XP_U16 minDividerWidth ); + /* Vertical scroll support; offset is in rows, not pixels */ XP_Bool board_setYOffset( BoardCtxt* board, XP_U16 newOffset ); @@ -88,13 +122,6 @@ XP_Bool board_canHint( const BoardCtxt* board ); /* zoomBy: >0: zoom in; < 0: zoom out; 0: query only */ XP_Bool board_zoom( BoardCtxt* board, XP_S16 zoomBy, XP_Bool* canInOut ); -void board_setScoreboardLoc( BoardCtxt* board, - XP_U16 scoreLeft, XP_U16 scoreTop, - XP_U16 scoreWidth, XP_U16 scoreHeight, - XP_Bool divideHorizontally ); -void board_setTimerLoc( BoardCtxt* board, - XP_U16 timerLeft, XP_U16 timerTop, - XP_U16 timerWidth, XP_U16 timerHeight ); void board_invalAll( BoardCtxt* board ); void board_invalRect( BoardCtxt* board, XP_Rect* rect ); #ifdef XWFEATURE_ACTIVERECT @@ -123,7 +150,6 @@ BoardObjectType board_getFocusOwner( BoardCtxt* board ); void board_hiliteCellAt( BoardCtxt* board, XP_U16 col, XP_U16 row ); - void board_resetEngine( BoardCtxt* board ); XP_Bool board_commitTurn( BoardCtxt* board ); @@ -155,9 +181,6 @@ XP_Bool board_focusChanged( BoardCtxt* board, BoardObjectType typ, /******************** Tray methods ********************/ #define NO_TILES ((TileBit)0) -void board_setTrayLoc( BoardCtxt* board, XP_U16 trayLeft, XP_U16 trayTop, - XP_U16 trayWidth, XP_U16 trayHeight, - XP_U16 minDividerWidth ); XP_Bool board_hideTray( BoardCtxt* board ); XP_Bool board_showTray( BoardCtxt* board ); XW_TrayVisState board_getTrayVisState( const BoardCtxt* board ); diff --git a/xwords4/common/game.h b/xwords4/common/game.h index 2e143581b..5266187a9 100644 --- a/xwords4/common/game.h +++ b/xwords4/common/game.h @@ -21,6 +21,7 @@ #ifndef _GAME_H_ #define _GAME_H_ +#include "gameinfo.h" #include "model.h" #include "board.h" #include "comms.h" @@ -31,40 +32,6 @@ extern "C" { #endif -typedef struct LocalPlayer { - XP_UCHAR* name; - XP_UCHAR* password; - XP_UCHAR* dictName; - XP_U16 secondsUsed; - XP_Bool isLocal; - XP_U8 robotIQ; /* 0 means not a robot; 1-100 means how - dumb is it with 1 meaning very smart */ -} LocalPlayer; - -#define LP_IS_ROBOT(lp) ((lp)->robotIQ != 0) -#define LP_IS_LOCAL(lp) ((lp)->isLocal) - -#define DUMB_ROBOT 0 -#define SMART_ROBOT 1 - -typedef struct CurGameInfo { - XP_UCHAR* dictName; - LocalPlayer players[MAX_NUM_PLAYERS]; - XP_U32 gameID; /* uniquely identifies game */ - XP_U16 gameSeconds; /* for timer */ - XP_LangCode dictLang; - XP_U8 nPlayers; - XP_U8 boardSize; - DeviceRole serverRole; - - XP_Bool hintsNotAllowed; - XP_Bool timerEnabled; - XP_Bool allowPickTiles; - XP_Bool allowHintRect; - XWPhoniesChoice phoniesAction; - XP_Bool confirmBTConnect; /* only used for BT */ -} CurGameInfo; - typedef struct _GameStateInfo { XP_U16 visTileCount; XW_TrayVisState trayVisState; diff --git a/xwords4/common/gameinfo.h b/xwords4/common/gameinfo.h new file mode 100644 index 000000000..8dd114caa --- /dev/null +++ b/xwords4/common/gameinfo.h @@ -0,0 +1,68 @@ +/* -*- compile-command: "cd ../linux && make -j3 MEMDEBUG=TRUE"; -*- */ +/* + * Copyright 2001-2013 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 _GAMEINFO_H_ +#define _GAMEINFO_H_ + +#include "server.h" + +#ifdef CPLUS +extern "C" { +#endif + +typedef struct LocalPlayer { + XP_UCHAR* name; + XP_UCHAR* password; + XP_UCHAR* dictName; + XP_U16 secondsUsed; + XP_Bool isLocal; + XP_U8 robotIQ; /* 0 means not a robot; 1-100 means how + dumb is it with 1 meaning very smart */ +} LocalPlayer; + +#define LP_IS_ROBOT(lp) ((lp)->robotIQ != 0) +#define LP_IS_LOCAL(lp) ((lp)->isLocal) + +#define DUMB_ROBOT 0 +#define SMART_ROBOT 1 + +typedef struct CurGameInfo { + XP_UCHAR* dictName; + LocalPlayer players[MAX_NUM_PLAYERS]; + XP_U32 gameID; /* uniquely identifies game */ + XP_U16 gameSeconds; /* for timer */ + XP_LangCode dictLang; + XP_U8 nPlayers; + XP_U8 boardSize; + DeviceRole serverRole; + + XP_Bool hintsNotAllowed; + XP_Bool timerEnabled; + XP_Bool allowPickTiles; + XP_Bool allowHintRect; + XWPhoniesChoice phoniesAction; + XP_Bool confirmBTConnect; /* only used for BT */ +} CurGameInfo; + +#ifdef CPLUS +} +#endif + +#endif From 184ac28ebc140474956bb31c0403687c1746148e Mon Sep 17 00:00:00 2001 From: Eric House Date: Sun, 3 Nov 2013 12:15:53 -0800 Subject: [PATCH 07/10] fix to compile, and in gtk case to work, when COMMON_LAYOUT defined --- xwords4/linux/cursesmain.c | 8 +++-- xwords4/linux/gtkboard.c | 69 +++++++++++++++++++++++--------------- xwords4/linux/linuxmain.c | 5 ++- 3 files changed, 52 insertions(+), 30 deletions(-) diff --git a/xwords4/linux/cursesmain.c b/xwords4/linux/cursesmain.c index 239e9c291..2810c8d8a 100644 --- a/xwords4/linux/cursesmain.c +++ b/xwords4/linux/cursesmain.c @@ -1635,8 +1635,12 @@ passKeyToBoard( CursesAppGlobals* globals, char ch ) static void positionSizeStuff( CursesAppGlobals* globals, int width, int height ) { - XP_U16 cellWidth, cellHt, scoreLeft, scoreWidth; BoardCtxt* board = globals->cGlobals.game.board; +#ifdef COMMON_LAYOUT + XP_USE( width ); + XP_USE( height ); +#else + XP_U16 cellWidth, cellHt, scoreLeft, scoreWidth; int remWidth = width; int nRows = globals->cGlobals.gi->boardSize; @@ -1680,7 +1684,7 @@ positionSizeStuff( CursesAppGlobals* globals, int width, int height ) /* no divider -- yet */ /* board_setTrayVisible( globals.board, XP_TRUE, XP_FALSE ); */ - +#endif board_invalAll( board ); } /* positionSizeStuff */ diff --git a/xwords4/linux/gtkboard.c b/xwords4/linux/gtkboard.c index e180f228d..d46b71c28 100644 --- a/xwords4/linux/gtkboard.c +++ b/xwords4/linux/gtkboard.c @@ -598,7 +598,29 @@ static gboolean configure_event( GtkWidget* widget, GdkEventConfigure* XP_UNUSED(event), GtkGameGlobals* globals ) { - short bdWidth, bdHeight; + if ( globals->draw == NULL ) { + createOrLoadObjects( globals ); + } + + CommonGlobals* cGlobals = &globals->cGlobals; + BoardCtxt* board = cGlobals->game.board; + + short bdWidth = widget->allocation.width - (GTK_RIGHT_MARGIN + + GTK_BOARD_LEFT_MARGIN); + short bdHeight = widget->allocation.height - (GTK_TOP_MARGIN + GTK_BOTTOM_MARGIN) + - GTK_MIN_TRAY_SCALEV - GTK_BOTTOM_MARGIN; + +#ifdef COMMON_LAYOUT + XP_ASSERT( !cGlobals->params->verticalScore ); /* not supported */ + + XP_Rect rect = { .left = GTK_BOARD_LEFT, .top = GTK_HOR_SCORE_TOP, + .width = bdWidth, .height = bdHeight + }; + BoardDims dims; + board_figureLayout( board, cGlobals->gi, 16, 16, XP_FALSE, &rect, &dims ); + board_applyLayout( board, &dims ); + +#else short timerLeft, timerTop; gint hscale, vscale; gint trayTop; @@ -607,48 +629,39 @@ configure_event( GtkWidget* widget, GdkEventConfigure* XP_UNUSED(event), gint nCols; gint nRows; - if ( globals->draw == NULL ) { - createOrLoadObjects( globals ); - } - - nCols = globals->cGlobals.gi->boardSize; + nCols = cGlobals->gi->boardSize; nRows = nCols; - bdWidth = widget->allocation.width - (GTK_RIGHT_MARGIN - + GTK_BOARD_LEFT_MARGIN); - if ( globals->cGlobals.params->verticalScore ) { + if ( cGlobals->params->verticalScore ) { bdWidth -= GTK_VERT_SCORE_WIDTH; } - bdHeight = widget->allocation.height - (GTK_TOP_MARGIN + GTK_BOTTOM_MARGIN) - - GTK_MIN_TRAY_SCALEV - GTK_BOTTOM_MARGIN; hscale = bdWidth / nCols; - if ( 0 != globals->cGlobals.params->nHidden ) { + if ( 0 != cGlobals->params->nHidden ) { vscale = hscale; } else { vscale = (bdHeight / (nCols + GTK_TRAY_HT_ROWS)); /* makd tray height 3x cell height */ } - if ( !globals->cGlobals.params->verticalScore ) { + if ( !cGlobals->params->verticalScore ) { boardTop += GTK_HOR_SCORE_HEIGHT; } trayTop = boardTop + (vscale * nRows); /* move tray up if part of board's meant to be hidden */ - trayTop -= vscale * globals->cGlobals.params->nHidden; - board_setPos( globals->cGlobals.game.board, GTK_BOARD_LEFT, boardTop, + trayTop -= vscale * cGlobals->params->nHidden; + board_setPos( board, GTK_BOARD_LEFT, boardTop, hscale * nCols, vscale * nRows, hscale * 4, XP_FALSE ); - /* board_setScale( globals->cGlobals.game.board, hscale, vscale ); */ - globals->gridOn = XP_TRUE; + /* board_setScale( board, hscale, vscale ); */ - if ( !!globals->cGlobals.game.comms ) { + if ( !!cGlobals->game.comms ) { netStatWidth = GTK_NETSTAT_WIDTH; } timerTop = GTK_TIMER_TOP; - if ( globals->cGlobals.params->verticalScore ) { + if ( cGlobals->params->verticalScore ) { timerLeft = GTK_BOARD_LEFT + (hscale*nCols) + 1; - board_setScoreboardLoc( globals->cGlobals.game.board, + board_setScoreboardLoc( board, timerLeft, GTK_VERT_SCORE_TOP, GTK_VERT_SCORE_WIDTH, @@ -658,7 +671,7 @@ configure_event( GtkWidget* widget, GdkEventConfigure* XP_UNUSED(event), } else { timerLeft = GTK_BOARD_LEFT + (hscale*nCols) - GTK_TIMER_WIDTH - netStatWidth; - board_setScoreboardLoc( globals->cGlobals.game.board, + board_setScoreboardLoc( board, GTK_BOARD_LEFT, GTK_HOR_SCORE_TOP, timerLeft-GTK_BOARD_LEFT, GTK_HOR_SCORE_HEIGHT, @@ -667,24 +680,26 @@ configure_event( GtkWidget* widget, GdkEventConfigure* XP_UNUSED(event), } /* Still pending: do this for the vertical score case */ - if ( globals->cGlobals.game.comms ) { + if ( cGlobals->game.comms ) { globals->netStatLeft = timerLeft + GTK_TIMER_WIDTH; globals->netStatTop = 0; } - board_setTimerLoc( globals->cGlobals.game.board, timerLeft, timerTop, + board_setTimerLoc( board, timerLeft, timerTop, GTK_TIMER_WIDTH, GTK_HOR_SCORE_HEIGHT ); - board_setTrayLoc( globals->cGlobals.game.board, GTK_TRAY_LEFT, trayTop, + board_setTrayLoc( board, GTK_TRAY_LEFT, trayTop, hscale * nCols, vscale * GTK_TRAY_HT_ROWS + 10, GTK_DIVIDER_WIDTH ); +#endif + globals->gridOn = XP_TRUE; + setCtrlsForTray( globals ); - - board_invalAll( globals->cGlobals.game.board ); + board_invalAll( board ); XP_Bool inOut[2]; - board_zoom( globals->cGlobals.game.board, 0, inOut ); + board_zoom( board, 0, inOut ); setZoomButtons( globals, inOut ); return TRUE; diff --git a/xwords4/linux/linuxmain.c b/xwords4/linux/linuxmain.c index a568c3d86..5ee2b1161 100644 --- a/xwords4/linux/linuxmain.c +++ b/xwords4/linux/linuxmain.c @@ -989,7 +989,10 @@ send_or_close( CommonGlobals* cGlobals, const XP_U8* buf, size_t len ) cGlobals->socket = -1; /* delete all pending packets since the socket's bad */ - g_slist_free_full( cGlobals->packetQueue, free_elem_proc ); + for ( GSList* iter = cGlobals->packetQueue; !!iter; iter = iter->next ) { + free_elem_proc( iter->data ); + } + g_slist_free( cGlobals->packetQueue ); cGlobals->packetQueue = NULL; } LOG_RETURNF( "%d", success ); From e01af60dabbb82c2d1411a0779cf7caa5eba225e Mon Sep 17 00:00:00 2001 From: Eric House Date: Sun, 3 Nov 2013 12:17:20 -0800 Subject: [PATCH 08/10] build with COMMON_LAYOUT defined, and when off-by-default debug pref is on use it instead of java-side layout. --- xwords4/android/XWords4/jni/Android.mk | 1 + xwords4/android/XWords4/jni/andutils.c | 2 +- xwords4/android/XWords4/jni/xwjni.c | 71 +++++++++ .../XWords4/res/values/common_rsrc.xml | 1 + xwords4/android/XWords4/res/xml/xwprefs.xml | 5 + .../org/eehouse/android/xw4/BoardDims.java | 1 + .../org/eehouse/android/xw4/BoardView.java | 144 ++++++++++-------- .../eehouse/android/xw4/jni/JNIThread.java | 48 +++--- .../org/eehouse/android/xw4/jni/XwJNI.java | 12 ++ 9 files changed, 198 insertions(+), 87 deletions(-) diff --git a/xwords4/android/XWords4/jni/Android.mk b/xwords4/android/XWords4/jni/Android.mk index b60f6f5eb..c99c35a1e 100644 --- a/xwords4/android/XWords4/jni/Android.mk +++ b/xwords4/android/XWords4/jni/Android.mk @@ -37,6 +37,7 @@ LOCAL_DEFINES += \ -DHASH_STREAM \ -DXWFEATURE_BASE64 \ -DXWFEATURE_DEVID \ + -DCOMMON_LAYOUT \ -DINITIAL_CLIENT_VERS=${INITIAL_CLIENT_VERS} \ -DRELAY_ROOM_DEFAULT=\"\" \ -D__LITTLE_ENDIAN \ diff --git a/xwords4/android/XWords4/jni/andutils.c b/xwords4/android/XWords4/jni/andutils.c index c3530ce08..f9c45c288 100644 --- a/xwords4/android/XWords4/jni/andutils.c +++ b/xwords4/android/XWords4/jni/andutils.c @@ -107,7 +107,7 @@ getInts( JNIEnv* env, void* cobj, jobject jobj, const SetInfo* sis, XP_U16 nSis *ptr = val; break; } - /* XP_LOGF( "%s: wrote int %s of size %dwith val %d at offset %d", */ + /* XP_LOGF( "%s: wrote int %s of size %d with val %d at offset %d", */ /* __func__, si->name, si->siz, val, si->offset ); */ } } diff --git a/xwords4/android/XWords4/jni/xwjni.c b/xwords4/android/XWords4/jni/xwjni.c index 4aae6f509..0d365d5db 100644 --- a/xwords4/android/XWords4/jni/xwjni.c +++ b/xwords4/android/XWords4/jni/xwjni.c @@ -158,6 +158,36 @@ setJGI( JNIEnv* env, jobject jgi, const CurGameInfo* gi ) } } /* setJGI */ +#ifdef COMMON_LAYOUT +static const SetInfo bd_ints[] = { + ARR_MEMBER( BoardDims, left ) + ,ARR_MEMBER( BoardDims, top ) + ,ARR_MEMBER( BoardDims, width ) + ,ARR_MEMBER( BoardDims, height ) + ,ARR_MEMBER( BoardDims, scoreHt ) + ,ARR_MEMBER( BoardDims, boardHt ) + ,ARR_MEMBER( BoardDims, trayTop ) + ,ARR_MEMBER( BoardDims, trayHt ) + ,ARR_MEMBER( BoardDims, cellSize ) + ,ARR_MEMBER( BoardDims, maxCellSize ) + ,ARR_MEMBER( BoardDims, timerWidth ) +}; + +static void +dimsJToC( JNIEnv* env, BoardDims* out, jobject jdims ) +{ + getInts( env, (void*)out, jdims, bd_ints, VSIZE(bd_ints) ); +} + +static void +dimsCtoJ( JNIEnv* env, jobject jdims, const BoardDims* in ) +{ + LOG_FUNC(); + setInts( env, jdims, (void*)in, bd_ints, VSIZE(bd_ints) ); + LOG_RETURN_VOID(); +} +#endif + static void destroyGI( MPFORMAL CurGameInfo** gip ) { @@ -601,6 +631,47 @@ Java_org_eehouse_android_xw4_jni_XwJNI_board_1draw return result; } +#ifdef COMMON_LAYOUT +JNIEXPORT void JNICALL +Java_org_eehouse_android_xw4_jni_XwJNI_board_1figureLayout +( JNIEnv* env, jclass C, jint gamePtr, jobject jgi, jint fontHt, jint fontWidth, + jboolean squareTiles, jobject jbounds, jobject jdims ) +{ + LOG_FUNC(); + XWJNI_START(); + CurGameInfo* gi = makeGI( MPPARM(mpool) env, jgi ); + + XP_Rect bounds; + bounds.left = getInt( env, jbounds, "left" ); + bounds.top = getInt( env, jbounds, "top" ); + bounds.width = getInt( env, jbounds, "right" ) - bounds.left; + bounds.height = getInt( env, jbounds, "bottom" ) - bounds.top; + + BoardDims dims; + board_figureLayout( state->game.board, gi, fontHt, fontWidth, + squareTiles, &bounds, ((!!jdims) ? &dims : NULL) ); + + destroyGI( MPPARM(mpool) &gi ); + + if ( !!jdims ) { + dimsCtoJ( env, jdims, &dims ); + } + XWJNI_END(); + LOG_RETURN_VOID(); +} + +JNIEXPORT void JNICALL +Java_org_eehouse_android_xw4_jni_XwJNI_board_1applyLayout +( JNIEnv* env, jclass C, jint gamePtr, jobject jdims ) +{ + XWJNI_START(); + BoardDims dims; + dimsJToC( env, &dims, jdims ); + board_applyLayout( state->game.board, &dims ); + XWJNI_END(); +} +#endif + JNIEXPORT void JNICALL Java_org_eehouse_android_xw4_jni_XwJNI_board_1setPos (JNIEnv *env, jclass C, jint gamePtr, jint left, jint top, jint width, diff --git a/xwords4/android/XWords4/res/values/common_rsrc.xml b/xwords4/android/XWords4/res/values/common_rsrc.xml index f7af55629..f89799cb7 100644 --- a/xwords4/android/XWords4/res/values/common_rsrc.xml +++ b/xwords4/android/XWords4/res/values/common_rsrc.xml @@ -103,6 +103,7 @@ key_na_browseall key_na_values key_enable_debug + key_enable_commlayt key_download_path diff --git a/xwords4/android/XWords4/res/xml/xwprefs.xml b/xwords4/android/XWords4/res/xml/xwprefs.xml index fb690b6e7..c384a57dc 100644 --- a/xwords4/android/XWords4/res/xml/xwprefs.xml +++ b/xwords4/android/XWords4/res/xml/xwprefs.xml @@ -299,6 +299,11 @@ android:summary="Menuitems etc." android:defaultValue="false" /> +