mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-18 22:26:30 +01:00
Merge remote-tracking branch 'origin/android_branch' into android_branch
This commit is contained in:
commit
53774eb807
22 changed files with 260 additions and 45 deletions
|
@ -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);
|
||||
|
|
|
@ -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 -->
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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];
|
||||
|
|
Loading…
Reference in a new issue