Merge remote-tracking branch 'origin/android_branch' into android_branch

This commit is contained in:
Eric House 2012-09-24 20:08:14 -07:00
commit 53774eb807
22 changed files with 260 additions and 45 deletions

View file

@ -262,6 +262,27 @@ and_util_informUndo( XW_UtilCtxt* uc )
UTIL_CBK_TAIL();
}
static void
and_util_informNetDict( XW_UtilCtxt* uc, const XP_UCHAR* oldName,
const XP_UCHAR* newName, const XP_UCHAR* newSum,
XWPhoniesChoice phoniesAction )
{
LOG_FUNC();
UTIL_CBK_HEADER( "informNetDict",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;L"
PKG_PATH("jni/CurGameInfo$XWPhoniesChoice") ";)V" );
jstring jnew = (*env)->NewStringUTF( env, newName );
jstring jsum = (*env)->NewStringUTF( env, newSum );
jstring jold = (*env)->NewStringUTF( env, oldName );
jobject jphon = intToJEnum( env, phoniesAction,
PKG_PATH("jni/CurGameInfo$XWPhoniesChoice") );
(*env)->CallVoidMethod( env, util->jutil, mid, jold, jnew, jsum, jphon );
deleteLocalRefs( env, jnew, jold, jsum, jphon, DELETE_NO_REF );
UTIL_CBK_TAIL();
}
static void
and_util_notifyGameOver( XW_UtilCtxt* uc )
{
@ -400,14 +421,17 @@ and_util_warnIllegalWord( XW_UtilCtxt* uc, BadWordInfo* bwi,
XP_U16 turn, XP_Bool turnLost )
{
jboolean result = XP_FALSE;
UTIL_CBK_HEADER("warnIllegalWord", "([Ljava/lang/String;IZ)Z" );
UTIL_CBK_HEADER("warnIllegalWord",
"(Ljava/lang/String;[Ljava/lang/String;IZ)Z" );
XP_ASSERT( bwi->nWords > 0 );
if ( bwi->nWords > 0 ) {
jobjectArray jwords = makeStringArray( env, bwi->nWords,
(const XP_UCHAR**)bwi->words );
XP_ASSERT( !!bwi->dictName );
jstring jname = (*env)->NewStringUTF( env, bwi->dictName );
result = (*env)->CallBooleanMethod( env, util->jutil, mid,
jwords, turn, turnLost );
deleteLocalRef( env, jwords );
jname, jwords, turn, turnLost );
deleteLocalRefs( env, jwords, jname, DELETE_NO_REF );
}
UTIL_CBK_TAIL();
return result;
@ -578,6 +602,7 @@ makeUtil( MPFORMAL JNIEnv** envp, jobject jutil, CurGameInfo* gi,
#endif
SET_PROC(informMove);
SET_PROC(informUndo);
SET_PROC(informNetDict);
SET_PROC(notifyGameOver);
SET_PROC(hiliteCell);
SET_PROC(engineProgressCallback);

View file

@ -629,8 +629,8 @@
phonies_disallow is the current setting and a "phony" is
played. One of the two following strings will be appended
-->
<string name="ids_badwords">Word[s] %s not found in
wordlist.</string>
<string name="ids_badwords">Word[s] %1$s not found in
wordlist %2$s.</string>
<!-- Appended to the above in the phonies_warn case. User may
ignore the warning -->

View file

@ -1472,6 +1472,22 @@ public class BoardActivity extends XWActivity
nonBlockingDialog( DLG_OKONLY, getString( R.string.remote_undone ) );
}
@Override
public void informNetDict( String oldName, String newName, String newSum,
CurGameInfo.XWPhoniesChoice phonies )
{
// If it's same dict and same sum, we're good. That
// should be the normal case. Otherwise: if same name but
// different sum, notify and offer to upgrade. If
// different name, offer to install.
String oldSum = DictLangCache.getDictMD5Sum( BoardActivity.this,
oldName );
String str = String.format( "informNetDict(%s, %s, %s, %s, %s)",
oldName, oldSum, newName, newSum,
phonies.toString() );
nonBlockingDialog( DLG_OKONLY, str );
}
@Override
public void notifyGameOver()
{
@ -1484,10 +1500,10 @@ public class BoardActivity extends XWActivity
// m_view.setVerticalScrollBarEnabled( maxOffset > 0 );
// }
@Override
public boolean warnIllegalWord( String[] words, int turn,
public boolean warnIllegalWord( String dict, String[] words, int turn,
boolean turnLost )
{
DbgUtils.logf( "warnIllegalWord" );
DbgUtils.logf( "warnIllegalWord(dict=%s)", dict );
boolean accept = turnLost;
StringBuffer sb = new StringBuffer();
@ -1499,7 +1515,8 @@ public class BoardActivity extends XWActivity
sb.append( "; " );
}
String message = getString( R.string.ids_badwords, sb.toString() );
String message =
getString( R.string.ids_badwords, sb.toString(), dict );
if ( turnLost ) {
nonBlockingDialog( DLG_BADWORDS,

View file

@ -197,7 +197,12 @@ public class DictLangCache {
public static String getDictMD5Sum( Context context, String dict )
{
return getInfo( context, dict ).md5Sum;
String result = null;
DictInfo info = getInfo( context, dict );
if ( null != info ) {
result = info.md5Sum;
}
return result;
}
public static int getDictLangCode( Context context, String dict )

View file

@ -53,7 +53,7 @@ import org.eehouse.android.xw4.jni.XwJNI;
public class SMSService extends Service {
private static final String INSTALL_URL = "http://eehouse.org/_/aa.htm ";
private static final String INSTALL_URL = "http://eehouse.org/_/a.py/a ";
private static final int MAX_SMS_LEN = 140; // ??? differs by network
private static final String MSG_SENT = "MSG_SENT";

View file

@ -116,6 +116,9 @@ public interface UtilCtxt {
void informMove( String expl, String words );
void informUndo();
void informNetDict( String oldName, String newName, String newSum,
CurGameInfo.XWPhoniesChoice phonies );
void informMissing( boolean isServer, CommsAddrRec.CommsConnType connType,
int nMissingPlayers );
@ -123,7 +126,8 @@ public interface UtilCtxt {
// Don't need this unless we have a scroll thumb to indicate position
//void yOffsetChange( int maxOffset, int oldOffset, int newOffset );
boolean warnIllegalWord( String[] words, int turn, boolean turnLost );
boolean warnIllegalWord( String dict, String[] words, int turn,
boolean turnLost );
void showChat( String msg );

View file

@ -222,6 +222,12 @@ public class UtilCtxtImpl implements UtilCtxt {
subclassOverride( "informUndo" );
}
public void informNetDict( String oldName, String newName, String newSum,
CurGameInfo.XWPhoniesChoice phonies )
{
subclassOverride( "informNetDict" );
}
public void informMissing( boolean isServer,
CommsAddrRec.CommsConnType connType,
int nMissingPlayers )
@ -236,7 +242,8 @@ public class UtilCtxtImpl implements UtilCtxt {
subclassOverride( "notifyGameOver" );
}
public boolean warnIllegalWord( String[] words, int turn, boolean turnLost )
public boolean warnIllegalWord( String dict, String[] words, int turn,
boolean turnLost )
{
subclassOverride( "warnIllegalWord" );
return false;

View file

@ -735,6 +735,7 @@ hideMiniWindow( BoardCtxt* board, XP_Bool destroy, MiniWindowType winType )
static XP_Bool
warnBadWords( const XP_UCHAR* word, XP_Bool isLegal,
const DictionaryCtxt* XP_UNUSED(dict),
#ifdef XWFEATURE_BOARDWORDS
const MoveInfo* XP_UNUSED(movei),
XP_U16 XP_UNUSED(start), XP_U16 XP_UNUSED(end),

View file

@ -47,6 +47,7 @@
#endif
#define MAX_COLS MAX_ROWS
#define STREAM_VERS_DICTNAME 0x15
#ifdef HASH_STREAM
# define STREAM_VERS_HASHSTREAM 0x14
#endif
@ -81,13 +82,7 @@
#define STREAM_VERS_41B4 0x02
#define STREAM_VERS_405 0x01
#ifdef STREAM_VERS_HASHSTREAM
# define CUR_STREAM_VERS STREAM_VERS_HASHSTREAM
#elif MAX_COLS > 16
# define CUR_STREAM_VERS STREAM_VERS_BIGBOARD
#else
# define CUR_STREAM_VERS STREAM_VERS_BLUETOOTH2
#endif
#define CUR_STREAM_VERS STREAM_VERS_DICTNAME
typedef struct XP_Rect {
XP_S16 left;

View file

@ -78,6 +78,7 @@ static void writePlayerCtxt( const ModelCtxt* model, XWStreamCtxt* stream,
const PlayerCtxt* pc );
static XP_U16 model_getRecentPassCount( ModelCtxt* model );
static XP_Bool recordWord( const XP_UCHAR* word, XP_Bool isLegal,
const DictionaryCtxt* dict,
#ifdef XWFEATURE_BOARDWORDS
const MoveInfo* movei, XP_U16 start, XP_U16 end,
#endif
@ -2147,6 +2148,7 @@ typedef struct _FirstWordData {
static XP_Bool
getFirstWord( const XP_UCHAR* word, XP_Bool XP_UNUSED(isLegal),
const DictionaryCtxt* XP_UNUSED(dict),
#ifdef XWFEATURE_BOARDWORDS
const MoveInfo* XP_UNUSED(movei), XP_U16 XP_UNUSED(start),
XP_U16 XP_UNUSED(end),
@ -2246,6 +2248,7 @@ appendWithCR( XWStreamCtxt* stream, const XP_UCHAR* word, XP_U16* counter )
static XP_Bool
recordWord( const XP_UCHAR* word, XP_Bool XP_UNUSED(isLegal),
const DictionaryCtxt* XP_UNUSED(dict),
#ifdef XWFEATURE_BOARDWORDS
const MoveInfo* XP_UNUSED(movei), XP_U16 XP_UNUSED(start),
XP_U16 XP_UNUSED(end),
@ -2277,6 +2280,7 @@ typedef struct _ListWordsThroughInfo {
static XP_Bool
listWordsThrough( const XP_UCHAR* word, XP_Bool XP_UNUSED(isLegal),
const DictionaryCtxt* XP_UNUSED(dict),
const MoveInfo* movei, XP_U16 start, XP_U16 end,
void* closure )
{

View file

@ -248,6 +248,7 @@ void model_countAllTrayTiles( ModelCtxt* model, XP_U16* counts,
/********************* scoring ********************/
typedef XP_Bool (*WordNotifierProc)( const XP_UCHAR* word, XP_Bool isLegal,
const DictionaryCtxt* dict,
#ifdef XWFEATURE_BOARDWORDS
const MoveInfo* movei, XP_U16 start,
XP_U16 end,

View file

@ -674,7 +674,7 @@ scoreWord( const ModelCtxt* model, XP_U16 turn,
XP_UCHAR buf[(MAX_ROWS*2)+1];
dict_tilesToString( dict, checkWordBuf, len, buf,
sizeof(buf) );
(void)(*notifyInfo->proc)( buf, legal,
(void)(*notifyInfo->proc)( buf, legal, dict,
#ifdef XWFEATURE_BOARDWORDS
movei, start, end,
#endif

View file

@ -1231,8 +1231,6 @@ client_readInitialMessage( ServerCtxt* server, XWStreamCtxt* stream )
gi_readFromStream( MPPARM(server->mpool) stream, &localGI );
localGI.serverRole = SERVER_ISCLIENT;
/* so it's not lost (HACK!). Without this, a client won't have a default
dict name when a new game is started. */
localGI.dictName = copyString( server->mpool, gi->dictName );
gi_copy( MPPARM(server->mpool) gi, &localGI );
@ -1241,6 +1239,17 @@ client_readInitialMessage( ServerCtxt* server, XWStreamCtxt* stream )
newDict = util_makeEmptyDict( server->vol.util );
dict_loadFromStream( newDict, stream );
#ifdef STREAM_VERS_BIGBOARD
if ( STREAM_VERS_DICTNAME <= streamVersion ) {
XP_UCHAR name[128];
XP_UCHAR sum[128];
stringFromStreamHere( stream, name, VSIZE(name) );
stringFromStreamHere( stream, sum, VSIZE(sum) );
util_informNetDict( server->vol.util, gi->dictName, name,
sum, localGI.phoniesAction );
}
#endif
channelNo = stream_getAddress( stream );
XP_ASSERT( channelNo != 0 );
server->nv.addresses[0].channelNo = channelNo;
@ -1373,7 +1382,12 @@ server_sendInitialMessage( ServerCtxt* server )
gi_writeToStream( stream, &localGI );
dict_writeToStream( dict, stream );
#ifdef STREAM_VERS_BIGBOARD
if ( STREAM_VERS_DICTNAME <= addr->streamVersion ) {
stringToStream( stream, dict_getShortName(dict) );
stringToStream( stream, dict_getMd5Sum(dict) );
}
#endif
/* send tiles currently in tray */
for ( ii = 0; ii < nPlayers; ++ii ) {
model_trayToStream( model, ii, stream );
@ -1393,9 +1407,9 @@ freeBWI( MPFORMAL BadWordInfo* bwi )
{
XP_U16 nWords = bwi->nWords;
XP_FREEP( mpool, &bwi->dictName );
while ( nWords-- ) {
XP_FREE( mpool, (XP_UCHAR*)bwi->words[nWords] );
bwi->words[nWords] = (XP_UCHAR*)NULL;
XP_FREEP( mpool, &bwi->words[nWords] );
}
bwi->nWords = 0;
@ -1409,7 +1423,9 @@ bwiToStream( XWStreamCtxt* stream, BadWordInfo* bwi )
const XP_UCHAR** sp;
stream_putBits( stream, 4, nWords );
if ( STREAM_VERS_DICTNAME <= stream_getVersion( stream ) ) {
stringToStream( stream, bwi->dictName );
}
for ( sp = bwi->words; nWords > 0; --nWords, ++sp ) {
stringToStream( stream, *sp );
}
@ -1423,6 +1439,8 @@ bwiFromStream( MPFORMAL XWStreamCtxt* stream, BadWordInfo* bwi )
const XP_UCHAR** sp = bwi->words;
bwi->nWords = nWords;
bwi->dictName = ( STREAM_VERS_DICTNAME <= stream_getVersion( stream ) )
? stringFromStream( mpool, stream ) : NULL;
for ( sp = bwi->words; nWords; ++sp, --nWords ) {
*sp = (const XP_UCHAR*)stringFromStream( mpool, stream );
}
@ -1861,6 +1879,7 @@ server_setGameOverListener( ServerCtxt* server, GameOverListener gol,
static XP_Bool
storeBadWords( const XP_UCHAR* word, XP_Bool isLegal,
const DictionaryCtxt* dict,
#ifdef XWFEATURE_BOARDWORDS
const MoveInfo* XP_UNUSED(movei), XP_U16 XP_UNUSED(start),
XP_U16 XP_UNUSED(end),
@ -1869,9 +1888,12 @@ storeBadWords( const XP_UCHAR* word, XP_Bool isLegal,
{
if ( !isLegal ) {
ServerCtxt* server = (ServerCtxt*)closure;
const XP_UCHAR* name = dict_getShortName( dict );
XP_LOGF( "storeBadWords called with \"%s\"", word );
XP_LOGF( "storeBadWords called with \"%s\" (name=%s)", word, name );
if ( NULL == server->illegalWordInfo.dictName ) {
server->illegalWordInfo.dictName = copyString( server->mpool, name );
}
server->illegalWordInfo.words[server->illegalWordInfo.nWords++]
= copyString( server->mpool, word );
}

View file

@ -82,6 +82,7 @@ typedef struct PickInfo {
typedef struct BadWordInfo {
XP_U16 nWords;
XP_UCHAR* dictName;
const XP_UCHAR* words[MAX_TRAY_TILES+1]; /* can form in both directions */
} BadWordInfo;
@ -129,6 +130,11 @@ typedef struct UtilVtable {
void (*m_util_informMove)( XW_UtilCtxt* uc, XWStreamCtxt* expl,
XWStreamCtxt* words );
void (*m_util_informUndo)( XW_UtilCtxt* uc );
void (*m_util_informNetDict)( XW_UtilCtxt* uc, const XP_UCHAR* oldName,
const XP_UCHAR* newName,
const XP_UCHAR* newSum,
XWPhoniesChoice phoniesAction );
void (*m_util_notifyGameOver)( XW_UtilCtxt* uc );
XP_Bool (*m_util_hiliteCell)( XW_UtilCtxt* uc, XP_U16 col, XP_U16 row );
@ -244,6 +250,8 @@ struct XW_UtilCtxt {
(uc)->vtable->m_util_informMove( (uc),(e),(w))
#define util_informUndo(uc) \
(uc)->vtable->m_util_informUndo( (uc))
#define util_informNetDict(uc, on, nn, ns, pa ) \
(uc)->vtable->m_util_informNetDict( (uc), (on), (nn), (ns), (pa) )
#define util_notifyGameOver( uc ) \
(uc)->vtable->m_util_notifyGameOver((uc))

View file

@ -394,6 +394,16 @@ curses_util_notifyGameOver( XW_UtilCtxt* uc )
}
} /* curses_util_notifyGameOver */
static void
curses_util_informNetDict( XW_UtilCtxt* uc, const XP_UCHAR* oldName,
const XP_UCHAR* newName, const XP_UCHAR* newSum,
XWPhoniesChoice phoniesAction )
{
XP_USE(uc);
XP_USE(phoniesAction);
XP_LOGF( "%s: %s => %s (cksum: %s)", __func__, oldName, newName, newSum );
}
static XP_Bool
curses_util_hiliteCell( XW_UtilCtxt* uc,
XP_U16 XP_UNUSED(col), XP_U16 XP_UNUSED(row) )
@ -1516,6 +1526,7 @@ setupCursesUtilCallbacks( CursesAppGlobals* globals, XW_UtilCtxt* util )
util->vtable->m_util_informMove = curses_util_informMove;
util->vtable->m_util_informUndo = curses_util_informUndo;
util->vtable->m_util_notifyGameOver = curses_util_notifyGameOver;
util->vtable->m_util_informNetDict = curses_util_informNetDict;
util->vtable->m_util_hiliteCell = curses_util_hiliteCell;
util->vtable->m_util_engineProgressCallback =
curses_util_engineProgressCallback;

View file

@ -1458,6 +1458,24 @@ gtk_util_notifyGameOver( XW_UtilCtxt* uc )
}
} /* gtk_util_notifyGameOver */
static void
gtk_util_informNetDict( XW_UtilCtxt* uc, const XP_UCHAR* oldName,
const XP_UCHAR* newName, const XP_UCHAR* newSum,
XWPhoniesChoice phoniesAction )
{
GtkAppGlobals* globals = (GtkAppGlobals*)uc->closure;
gchar buf[512];
int offset = snprintf( buf, VSIZE(buf),
"dict changing from %s to %s (sum=%s).",
oldName, newName, newSum );
if ( PHONIES_DISALLOW == phoniesAction ) {
snprintf( &buf[offset], VSIZE(buf)-offset, "%s",
"\nPHONIES_DISALLOW is set so this may lead to some surprises." );
}
(void)gtkask( globals->window, buf, GTK_BUTTONS_OK );
}
/* define this to prevent user events during debugging from stopping the engine */
/* #define DONT_ABORT_ENGINE */
@ -1983,6 +2001,7 @@ setupGtkUtilCallbacks( GtkAppGlobals* globals, XW_UtilCtxt* util )
util->vtable->m_util_informMove = gtk_util_informMove;
util->vtable->m_util_informUndo = gtk_util_informUndo;
util->vtable->m_util_notifyGameOver = gtk_util_notifyGameOver;
util->vtable->m_util_informNetDict = gtk_util_informNetDict;
util->vtable->m_util_hiliteCell = gtk_util_hiliteCell;
util->vtable->m_util_altKeyDown = gtk_util_altKeyDown;
util->vtable->m_util_engineProgressCallback =

View file

@ -49,6 +49,7 @@ typedef struct LinuxDictionaryCtxt {
/************************ Prototypes ***********************/
static XP_Bool initFromDictFile( LinuxDictionaryCtxt* dctx,
const LaunchParams* params,
const char* fileName );
static void linux_dictionary_destroy( DictionaryCtxt* dict );
static const XP_UCHAR* linux_dict_getShortName( const DictionaryCtxt* dict );
@ -57,7 +58,8 @@ static const XP_UCHAR* linux_dict_getShortName( const DictionaryCtxt* dict );
*
****************************************************************************/
DictionaryCtxt*
linux_dictionary_make( MPFORMAL const char* dictFileName, XP_Bool useMMap )
linux_dictionary_make( MPFORMAL const LaunchParams* params,
const char* dictFileName, XP_Bool useMMap )
{
LinuxDictionaryCtxt* result =
(LinuxDictionaryCtxt*)XP_MALLOC(mpool, sizeof(*result));
@ -69,7 +71,7 @@ linux_dictionary_make( MPFORMAL const char* dictFileName, XP_Bool useMMap )
result->useMMap = useMMap;
if ( !!dictFileName ) {
XP_Bool success = initFromDictFile( result, dictFileName );
XP_Bool success = initFromDictFile( result, params, dictFileName );
if ( success ) {
result->super.destructor = linux_dictionary_destroy;
result->super.func_dict_getShortName = linux_dict_getShortName;
@ -219,7 +221,8 @@ dict_splitFaces( DictionaryCtxt* dict, const XP_U8* utf8,
} /* dict_splitFaces */
static XP_Bool
initFromDictFile( LinuxDictionaryCtxt* dctx, const char* fileName )
initFromDictFile( LinuxDictionaryCtxt* dctx, const LaunchParams* params,
const char* fileName )
{
XP_Bool formatOk = XP_TRUE;
long curPos, dictLength;
@ -231,15 +234,20 @@ initFromDictFile( LinuxDictionaryCtxt* dctx, const char* fileName )
XP_Bool isUTF8 = XP_FALSE;
XP_Bool hasHeader = XP_FALSE;
const XP_U8* ptr;
char path[256];
if ( !getDictPath( params, fileName, path, VSIZE(path) ) ) {
XP_LOGF( "%s: path=%s", __func__, path );
goto closeAndExit;
}
struct stat statbuf;
if ( 0 != stat( fileName, &statbuf ) || 0 == statbuf.st_size ) {
if ( 0 != stat( path, &statbuf ) || 0 == statbuf.st_size ) {
goto closeAndExit;
}
dctx->dictLength = statbuf.st_size;
{
FILE* dictF = fopen( fileName, "r" );
FILE* dictF = fopen( path, "r" );
XP_ASSERT( !!dictF );
if ( dctx->useMMap ) {
dctx->dictBase = mmap( NULL, dctx->dictLength, PROT_READ,

View file

@ -18,11 +18,13 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <locale.h>
#include <string.h>
#include <netdb.h> /* gethostbyname */
#include <errno.h>
@ -74,11 +76,12 @@
#define DEFAULT_LISTEN_PORT 4998
XP_Bool
file_exists( const char* fileName )
file_exists( const char* fileName )
{
struct stat statBuf;
int statResult = stat( fileName, &statBuf );
XP_LOGF( "%s(%s)=>%d", __func__, fileName, statResult == 0 );
return statResult == 0;
} /* file_exists */
@ -489,6 +492,7 @@ typedef enum {
,CMD_TESTPRFX
,CMD_TESTMINMAX
#endif
,CMD_DICTDIR
,CMD_PLAYERDICT
,CMD_SEED
,CMD_GAMESEED
@ -581,6 +585,7 @@ static CmdInfoRec CmdInfoRecs[] = {
,{ CMD_TESTPRFX, true, "test-prefix", "list first word starting with this" }
,{ CMD_TESTMINMAX, true, "test-minmax", "M:M -- include only words whose len in range" }
#endif
,{ 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" }
,{ CMD_GAMESEED, true, "game-seed", "game seed (for relay play)" }
@ -1382,7 +1387,7 @@ walk_dict_test_all( const LaunchParams* params, GSList* testDicts,
for ( ii = 0; ii < count; ++ii ) {
gchar* name = (gchar*)g_slist_nth_data( testDicts, ii );
DictionaryCtxt* dict =
linux_dictionary_make( MPPARM(params->util->mpool) name,
linux_dictionary_make( MPPARM(params->util->mpool) params, name,
params->useMmap );
if ( NULL != dict ) {
XP_LOGF( "walk_dict_test(%s)", name );
@ -1393,6 +1398,55 @@ walk_dict_test_all( const LaunchParams* params, GSList* testDicts,
}
#endif
static void
trimDictPath( const char* input, char* buf, int bufsiz, char** path, char** dict )
{
struct stat statBuf;
int statResult = stat( input, &statBuf );
if ( 0 == statResult && S_ISLNK(statBuf.st_mode) ) {
ssize_t nWritten = readlink( input, buf, bufsiz );
buf[nWritten] = '\0';
} else {
snprintf( buf, bufsiz, "%s", input );
}
char* result = strrchr( buf, '/' );
if ( !!result ) { /* is is a full path */
*path = buf;
*result = '\0'; /* null-terminate it */
*dict = 1 + result;
} else {
*path = NULL;
*dict = buf;
}
char* dot = strrchr( *dict, '.' );
if ( !!dot && 0 == strcmp(dot, ".xwd") ) {
*dot = '\0';
}
XP_LOGF( "%s=> dict: %s; path: %s", __func__, *dict, *path );
}
XP_Bool
getDictPath( const LaunchParams *params, const char* name,
char* result, int resultLen )
{
XP_Bool success = XP_FALSE;
GSList* dictDirs;
result[0] = '\0';
for ( dictDirs = params->dictDirs; !!dictDirs; dictDirs = dictDirs->next ) {
const char* path = dictDirs->data;
char buf[256];
int len = snprintf( buf, VSIZE(buf), "%s/%s.xwd", path, name );
if ( len < VSIZE(buf) && file_exists( buf ) ) {
snprintf( result, resultLen, "%s", buf );
success = XP_TRUE;
break;
}
}
LOG_RETURNF( "%d", success );
return success;
}
int
main( int argc, char** argv )
{
@ -1413,6 +1467,9 @@ main( int argc, char** argv )
GSList* testPrefixes = NULL;
char* testMinMax = NULL;
#endif
char dictbuf[256];
char* dict;
char* path;
/* install a no-op signal handler. Later curses- or gtk-specific code
will install one that does the right thing in that context */
@ -1487,6 +1544,19 @@ main( int argc, char** argv )
mainParams.showRobotScores = XP_FALSE;
mainParams.useMmap = XP_TRUE;
char* envDictPath = getenv( "XW_DICTSPATH" );
if ( !!envDictPath ) {
char *saveptr;
for ( ; ; ) {
char* path = strtok_r( envDictPath, ":", &saveptr );
if ( !path ) {
break;
}
mainParams.dictDirs = g_slist_append( mainParams.dictDirs, path );
envDictPath = NULL;
}
}
/* serverName = mainParams.info.clientInfo.serverName = "localhost"; */
#if defined PLATFORM_GTK
@ -1526,8 +1596,12 @@ main( int argc, char** argv )
conType = COMMS_CONN_IP_DIRECT;
break;
case CMD_DICT:
mainParams.gi.dictName = copyString( mainParams.util->mpool,
(XP_UCHAR*)optarg );
trimDictPath( optarg, dictbuf, VSIZE(dictbuf), &path, &dict );
mainParams.gi.dictName = copyString( mainParams.util->mpool, dict );
if ( !path ) {
path = ".";
}
mainParams.dictDirs = g_slist_append( mainParams.dictDirs, path );
break;
#ifdef XWFEATURE_WALKDICT
case CMD_TESTDICT:
@ -1540,8 +1614,16 @@ main( int argc, char** argv )
testMinMax = optarg;
break;
#endif
case CMD_DICTDIR:
mainParams.dictDirs = g_slist_append( mainParams.dictDirs, optarg );
break;
case CMD_PLAYERDICT:
mainParams.playerDictNames[nPlayerDicts++] = optarg;
trimDictPath( optarg, dictbuf, VSIZE(dictbuf), &path, &dict );
mainParams.playerDictNames[nPlayerDicts++] = dict;
if ( !path ) {
path = ".";
}
mainParams.dictDirs = g_slist_append( mainParams.dictDirs, path );
break;
case CMD_SEED:
seed = atoi(optarg);
@ -1804,9 +1886,11 @@ main( int argc, char** argv )
}
if ( !!mainParams.gi.dictName ) {
/* char path[256]; */
/* getDictPath( &mainParams, mainParams.gi.dictName, path, VSIZE(path) ); */
mainParams.dict =
linux_dictionary_make( MPPARM(mainParams.util->mpool)
mainParams.gi.dictName,
linux_dictionary_make( MPPARM(mainParams.util->mpool) &mainParams,
mainParams.gi.dictName,
mainParams.useMmap );
XP_ASSERT( !!mainParams.dict );
mainParams.gi.dictLang = dict_getLangCode( mainParams.dict );
@ -1834,8 +1918,8 @@ main( int argc, char** argv )
const XP_UCHAR* name = mainParams.playerDictNames[ii];
if ( !!name ) {
mainParams.dicts.dicts[ii] =
linux_dictionary_make( MPPARM(mainParams.util->mpool) name,
mainParams.useMmap );
linux_dictionary_make( MPPARM(mainParams.util->mpool)
&mainParams, name, mainParams.useMmap );
}
}

View file

@ -66,6 +66,8 @@ XWStreamCtxt* streamFromFile( CommonGlobals* cGlobals, char* name,
void* closure );
XWStreamCtxt* streamFromDB( CommonGlobals* cGlobals, void* closure );
void writeToFile( XWStreamCtxt* stream, void* closure );
XP_Bool getDictPath( const LaunchParams *params, const char* name,
char* result, int resultLen );
void saveGame( CommonGlobals* cGlobals );
int blocking_read( int fd, unsigned char* buf, int len );

View file

@ -89,7 +89,7 @@ static DictionaryCtxt*
linux_util_makeEmptyDict( XW_UtilCtxt* XP_UNUSED_DBG(uctx) )
{
XP_DEBUGF( "linux_util_makeEmptyDict called" );
return linux_dictionary_make( MPPARM(uctx->mpool) NULL, XP_FALSE );
return linux_dictionary_make( MPPARM(uctx->mpool) NULL, NULL, XP_FALSE );
} /* linux_util_makeEmptyDict */
#define EM BONUS_NONE
@ -350,7 +350,6 @@ linux_util_vt_init( MPFORMAL XW_UtilCtxt* util )
util->vtable->m_util_getSquareBonus = linux_util_getSquareBonus;
util->vtable->m_util_getCurSeconds = linux_util_getCurSeconds;
util->vtable->m_util_getUserString = linux_util_getUserString;
}
void

View file

@ -32,7 +32,9 @@ void linux_debugf(const char*, ...)
__attribute__ ((format (printf, 1, 2)));
#endif
DictionaryCtxt* linux_dictionary_make( MPFORMAL const char* dictFileName, XP_Bool useMmap );
DictionaryCtxt* linux_dictionary_make( MPFORMAL const LaunchParams* mainParams,
const char* dictFileName, XP_Bool useMMap );
void linux_util_vt_init( MPFORMAL XW_UtilCtxt* util );
void linux_util_vt_destroy( XW_UtilCtxt* util );

View file

@ -48,6 +48,7 @@ typedef struct LaunchParams {
DictionaryCtxt* dict;
CurGameInfo gi;
PlayerDicts dicts;
GSList* dictDirs;
char* fileName;
XP_U16 saveFailPct;
const XP_UCHAR* playerDictNames[MAX_NUM_PLAYERS];