make bad phonies alert non-blocking

Continue conversion of alerts that required blocking the JNI thread. Now
board_commitTurn() takes a second boolean indicating whether phonies
found have been approved by user. Common code informs user, and if he
approves client code calls board_commitTurn() again. In case where
turn's lost there's no call to make back, but there's the undesirable
change that if a robot moves next its move will be reported on top of
the turn-lost alert. Ideally new alerts would appear under, not on top
of, those that have not yet been dismissed.
This commit is contained in:
Eric House 2017-02-20 07:20:19 -08:00
parent 42aef7b85c
commit c271202faa
17 changed files with 133 additions and 129 deletions

View file

@ -275,7 +275,7 @@ public class BoardDelegate extends DelegateBase
lstnr = new OnClickListener() { lstnr = new OnClickListener() {
public void onClick( DialogInterface dialog, public void onClick( DialogInterface dialog,
int whichButton ) { int whichButton ) {
handleViaThread( JNICmd.CMD_COMMIT_TRUE ); handleViaThread( JNICmd.CMD_COMMIT, true, true );
} }
}; };
dialog = ab.setMessage( msg ) dialog = ab.setMessage( msg )
@ -286,8 +286,21 @@ public class BoardDelegate extends DelegateBase
} }
break; break;
case DLG_BADWORDS_BLK: case NOTIFY_BADWORDS: {
checkBlocking(); lstnr = new OnClickListener() {
public void onClick( DialogInterface dlg, int bx ) {
handleViaThread( JNICmd.CMD_COMMIT, true, false );
}
};
dialog = ab.setTitle( R.string.phonies_found_title )
.setMessage( (String)params[0] )
.setPositiveButton( R.string.button_yes, lstnr )
.setNegativeButton( android.R.string.cancel, null )
.create();
}
break;
case DLG_BADWORDS:
case DLG_SCORES: { case DLG_SCORES: {
int title = (Integer)params[0]; int title = (Integer)params[0];
String msg = (String)params[1]; String msg = (String)params[1];
@ -917,7 +930,7 @@ public class BoardDelegate extends DelegateBase
break; break;
case R.id.board_menu_trade_commit: case R.id.board_menu_trade_commit:
cmd = JNICmd.CMD_COMMIT_FALSE; cmd = JNICmd.CMD_COMMIT;
break; break;
case R.id.board_menu_trade_cancel: case R.id.board_menu_trade_cancel:
cmd = JNICmd.CMD_CANCELTRADE; cmd = JNICmd.CMD_CANCELTRADE;
@ -1045,7 +1058,7 @@ public class BoardDelegate extends DelegateBase
Utils.launchSettings( m_activity ); Utils.launchSettings( m_activity );
break; break;
case COMMIT_ACTION: case COMMIT_ACTION:
cmd = JNICmd.CMD_COMMIT_FALSE; cmd = JNICmd.CMD_COMMIT;
break; break;
case SHOW_EXPL_ACTION: case SHOW_EXPL_ACTION:
showToast( m_toastStr ); showToast( m_toastStr );
@ -1240,7 +1253,7 @@ public class BoardDelegate extends DelegateBase
public void onClick( View view ) public void onClick( View view )
{ {
if ( view == m_exchCommmitButton ) { if ( view == m_exchCommmitButton ) {
handleViaThread( JNICmd.CMD_COMMIT_FALSE ); handleViaThread( JNICmd.CMD_COMMIT );
} else if ( view == m_exchCancelButton ) { } else if ( view == m_exchCancelButton ) {
handleViaThread( JNICmd.CMD_CANCELTRADE ); handleViaThread( JNICmd.CMD_CANCELTRADE );
} }
@ -2034,33 +2047,21 @@ public class BoardDelegate extends DelegateBase
handleViaThread( JNICmd.CMD_POST_OVER ); handleViaThread( JNICmd.CMD_POST_OVER );
} }
// public void yOffsetChange( int maxOffset, int oldOffset, int newOffset )
// {
// DbgUtils.logf( "yOffsetChange(maxOffset=%d)", maxOffset );
// m_view.setVerticalScrollBarEnabled( maxOffset > 0 );
// }
@Override @Override
public boolean warnIllegalWord( String dict, String[] words, int turn, public void notifyIllegalWords( String dict, String[] words, int turn,
boolean turnLost ) boolean turnLost )
{ {
boolean accept = turnLost;
String wordsString = TextUtils.join( ", ", words ); String wordsString = TextUtils.join( ", ", words );
String message = String message =
getString( R.string.ids_badwords_fmt, wordsString, dict ); getString( R.string.ids_badwords_fmt, wordsString, dict );
if ( turnLost ) { if ( turnLost ) {
waitBlockingDialog( DlgID.DLG_BADWORDS_BLK, 0, R.string.badwords_title, showDialogFragment( DlgID.DLG_BADWORDS, R.string.badwords_title,
message + getString( R.string.badwords_lost ) ); message + getString( R.string.badwords_lost ) );
} else { } else {
Assert.fail(); String msg = message + getString( R.string.badwords_accept );
// String dlgBytes = message + getString( R.string.badwords_accept ); showDialogFragment( DlgID.NOTIFY_BADWORDS, msg );
// accept = 0 != waitBlockingDialog( DlgID.QUERY_REQUEST_BLK, 0,
// R.string.query_title,
// dlgBytes );
} }
return accept;
} }
// Let's have this block in case there are multiple messages. If // Let's have this block in case there are multiple messages. If

View file

@ -57,7 +57,8 @@ public enum DlgID {
, WARN_NODICT , WARN_NODICT
, WARN_NODICT_NEW , WARN_NODICT_NEW
, WARN_NODICT_SUBST , WARN_NODICT_SUBST
, DLG_BADWORDS_BLK , DLG_BADWORDS
, NOTIFY_BADWORDS
, QUERY_MOVE , QUERY_MOVE
, QUERY_TRADE , QUERY_TRADE
, PICK_TILE_REQUESTBLANK , PICK_TILE_REQUESTBLANK

View file

@ -71,8 +71,7 @@ public class JNIThread extends Thread {
CMD_KEYDOWN, CMD_KEYDOWN,
CMD_KEYUP, CMD_KEYUP,
CMD_TIMER_FIRED, CMD_TIMER_FIRED,
CMD_COMMIT_FALSE, CMD_COMMIT,
CMD_COMMIT_TRUE,
CMD_JUGGLE, CMD_JUGGLE,
CMD_FLIP, CMD_FLIP,
CMD_TOGGLE_TRAY, CMD_TOGGLE_TRAY,
@ -544,13 +543,14 @@ public class JNIThread extends Thread {
draw = processKeyEvent( elem.m_cmd, (XwJNI.XP_Key)args[0], barr ); draw = processKeyEvent( elem.m_cmd, (XwJNI.XP_Key)args[0], barr );
break; break;
case CMD_COMMIT_FALSE: case CMD_COMMIT:
draw = XwJNI.board_commitTurn( m_jniGamePtr, false ); boolean phoniesConfirmed = args.length < 1
? false : (Boolean)args[0];
boolean turnConfirmed = args.length < 2
? false : (Boolean)args[1];
draw = XwJNI.board_commitTurn( m_jniGamePtr, phoniesConfirmed,
turnConfirmed );
break; break;
case CMD_COMMIT_TRUE:
draw = XwJNI.board_commitTurn( m_jniGamePtr, true );
break;
case CMD_JUGGLE: case CMD_JUGGLE:
draw = XwJNI.board_juggleTray( m_jniGamePtr ); draw = XwJNI.board_juggleTray( m_jniGamePtr );
break; break;

View file

@ -141,7 +141,7 @@ public interface UtilCtxt {
// Don't need this unless we have a scroll thumb to indicate position // Don't need this unless we have a scroll thumb to indicate position
//void yOffsetChange( int maxOffset, int oldOffset, int newOffset ); //void yOffsetChange( int maxOffset, int oldOffset, int newOffset );
boolean warnIllegalWord( String dict, String[] words, int turn, void notifyIllegalWords( String dict, String[] words, int turn,
boolean turnLost ); boolean turnLost );
void showChat( String msg, int fromIndx, String fromName ); void showChat( String msg, int fromIndx, String fromName );

View file

@ -282,11 +282,10 @@ public class UtilCtxtImpl implements UtilCtxt {
subclassOverride( "notifyGameOver" ); subclassOverride( "notifyGameOver" );
} }
public boolean warnIllegalWord( String dict, String[] words, int turn, public void notifyIllegalWords( String dict, String[] words, int turn,
boolean turnLost ) boolean turnLost )
{ {
subclassOverride( "warnIllegalWord" ); subclassOverride( "notifyIllegalWords" );
return false;
} }
// These need to go into some sort of chat DB, not dropped. // These need to go into some sort of chat DB, not dropped.

View file

@ -299,7 +299,9 @@ public class XwJNI {
public static native boolean board_showTray( GamePtr gamePtr ); public static native boolean board_showTray( GamePtr gamePtr );
public static native boolean board_toggle_showValues( GamePtr gamePtr ); public static native boolean board_toggle_showValues( GamePtr gamePtr );
public static native boolean board_commitTurn( GamePtr gamePtr, public static native boolean board_commitTurn( GamePtr gamePtr,
boolean alreadyConfirmed ); boolean phoniesConfirmed,
boolean turnConfirmed );
public static native boolean board_flip( GamePtr gamePtr ); public static native boolean board_flip( GamePtr gamePtr );
public static native boolean board_replaceTiles( GamePtr gamePtr ); public static native boolean board_replaceTiles( GamePtr gamePtr );
public static native int board_getSelPlayer( GamePtr gamePtr ); public static native int board_getSelPlayer( GamePtr gamePtr );

View file

@ -897,6 +897,8 @@
found in the word list) --> found in the word list) -->
<string name="default_phonies">Handle phonies</string> <string name="default_phonies">Handle phonies</string>
<string name="phonies_found_title">Phonies found</string>
<!-- default number of minutes on timer for new games --> <!-- default number of minutes on timer for new games -->
<string name="initial_player_minutes">Timer minutes per player</string> <string name="initial_player_minutes">Timer minutes per player</string>

View file

@ -454,25 +454,23 @@ and_util_getUserQuantityString( XW_UtilCtxt* uc, XP_U16 stringCode, XP_U16 quant
return result; return result;
} }
static XP_Bool static void
and_util_warnIllegalWord( XW_UtilCtxt* uc, BadWordInfo* bwi, and_util_notifyIllegalWords( XW_UtilCtxt* uc, BadWordInfo* bwi,
XP_U16 turn, XP_Bool turnLost ) XP_U16 turn, XP_Bool turnLost )
{ {
jboolean result = XP_FALSE; UTIL_CBK_HEADER("notifyIllegalWords",
UTIL_CBK_HEADER("warnIllegalWord", "(Ljava/lang/String;[Ljava/lang/String;IZ)V" );
"(Ljava/lang/String;[Ljava/lang/String;IZ)Z" );
XP_ASSERT( bwi->nWords > 0 ); XP_ASSERT( bwi->nWords > 0 );
if ( bwi->nWords > 0 ) { if ( bwi->nWords > 0 ) {
jobjectArray jwords = makeStringArray( env, bwi->nWords, jobjectArray jwords = makeStringArray( env, bwi->nWords,
(const XP_UCHAR**)bwi->words ); (const XP_UCHAR**)bwi->words );
XP_ASSERT( !!bwi->dictName ); XP_ASSERT( !!bwi->dictName );
jstring jname = (*env)->NewStringUTF( env, bwi->dictName ); jstring jname = (*env)->NewStringUTF( env, bwi->dictName );
result = (*env)->CallBooleanMethod( env, util->jutil, mid, (*env)->CallVoidMethod( env, util->jutil, mid,
jname, jwords, turn, turnLost ); jname, jwords, turn, turnLost );
deleteLocalRefs( env, jwords, jname, DELETE_NO_REF ); deleteLocalRefs( env, jwords, jname, DELETE_NO_REF );
} }
UTIL_CBK_TAIL(); UTIL_CBK_TAIL();
return result;
} }
#ifdef XWFEATURE_CHAT #ifdef XWFEATURE_CHAT
@ -732,7 +730,7 @@ makeUtil( MPFORMAL EnvThreadInfo* ti, jobject jutil, CurGameInfo* gi,
SET_PROC(makeEmptyDict); SET_PROC(makeEmptyDict);
SET_PROC(getUserString); SET_PROC(getUserString);
SET_PROC(getUserQuantityString); SET_PROC(getUserQuantityString);
SET_PROC(warnIllegalWord); SET_PROC(notifyIllegalWords);
#ifdef XWFEATURE_CHAT #ifdef XWFEATURE_CHAT
SET_PROC(showChat); SET_PROC(showChat);
#endif #endif

View file

@ -1282,11 +1282,13 @@ Java_org_eehouse_android_xw4_jni_XwJNI_board_1toggle_1showValues
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_org_eehouse_android_xw4_jni_XwJNI_board_1commitTurn Java_org_eehouse_android_xw4_jni_XwJNI_board_1commitTurn
(JNIEnv* env, jclass C, GamePtrType gamePtr, jboolean alreadyConfirmed) (JNIEnv* env, jclass C, GamePtrType gamePtr, jboolean phoniesConfirmed,
jboolean turnConfirmed)
{ {
jboolean result; jboolean result;
XWJNI_START(); XWJNI_START();
result = board_commitTurn( state->game.board, alreadyConfirmed ); result = board_commitTurn( state->game.board, phoniesConfirmed,
turnConfirmed );
XWJNI_END(); XWJNI_END();
return result; return result;
} }

View file

@ -984,8 +984,14 @@ hideMiniWindow( BoardCtxt* board, XP_Bool destroy, MiniWindowType winType )
#endif #endif
#endif #endif
typedef struct _BadWordList {
BadWordInfo bwi;
XP_UCHAR buf[256];
XP_U16 index;
} BadWordList;
static void static void
warnBadWords( const XP_UCHAR* word, XP_Bool isLegal, saveBadWords( const XP_UCHAR* word, XP_Bool isLegal,
const DictionaryCtxt* XP_UNUSED(dict), const DictionaryCtxt* XP_UNUSED(dict),
#ifdef XWFEATURE_BOARDWORDS #ifdef XWFEATURE_BOARDWORDS
const MoveInfo* XP_UNUSED(movei), const MoveInfo* XP_UNUSED(movei),
@ -993,22 +999,14 @@ warnBadWords( const XP_UCHAR* word, XP_Bool isLegal,
#endif #endif
void* closure ) void* closure )
{ {
XP_Bool ok = XP_TRUE;
if ( !isLegal ) { if ( !isLegal ) {
BadWordInfo bwi = {0}; BadWordList* bwlp = (BadWordList*)closure;
BoardCtxt* board = (BoardCtxt*)closure; bwlp->bwi.words[bwlp->bwi.nWords] = &bwlp->buf[bwlp->index];
XP_S16 turn = server_getCurrentTurn( board->server, NULL ); XP_STRCAT( &bwlp->buf[bwlp->index], word );
bwlp->index += XP_STRLEN(word) + 1;
bwi.nWords = 1; ++bwlp->bwi.nWords;
bwi.words[0] = word;
bwi.dictName =
dict_getShortName( model_getPlayerDict( board->model, turn ) );
ok = !board->badWordRejected
&& util_warnIllegalWord( board->util, &bwi, turn, XP_FALSE );
board->badWordRejected = !ok || board->badWordRejected;
} }
} /* warnBadWords */ } /* saveBadWords */
static void static void
boardNotifyTrade( BoardCtxt* board, const TrayTileSet* tiles ) boardNotifyTrade( BoardCtxt* board, const TrayTileSet* tiles )
@ -1025,7 +1023,8 @@ boardNotifyTrade( BoardCtxt* board, const TrayTileSet* tiles )
} }
XP_Bool XP_Bool
board_commitTurn( BoardCtxt* board, XP_Bool alreadyConfirmed ) board_commitTurn( BoardCtxt* board, XP_Bool phoniesConfirmed,
XP_Bool turnConfirmed /* includes trade */ )
{ {
XP_Bool result = XP_FALSE; XP_Bool result = XP_FALSE;
const XP_S16 turn = server_getCurrentTurn( board->server, NULL ); const XP_S16 turn = server_getCurrentTurn( board->server, NULL );
@ -1038,7 +1037,7 @@ board_commitTurn( BoardCtxt* board, XP_Bool alreadyConfirmed )
} else if ( 0 == model_getNumTilesTotal( board->model, turn ) ) { } else if ( 0 == model_getNumTilesTotal( board->model, turn ) ) {
/* game's over but still undoable so turn hasn't changed; do /* game's over but still undoable so turn hasn't changed; do
nothing */ nothing */
} else if ( alreadyConfirmed || checkRevealTray( board ) ) { } else if ( phoniesConfirmed || turnConfirmed || checkRevealTray( board ) ) {
if ( pti->tradeInProgress ) { if ( pti->tradeInProgress ) {
TileBit traySelBits = pti->traySelBits; TileBit traySelBits = pti->traySelBits;
result = XP_TRUE; /* there's at least the window to clean up result = XP_TRUE; /* there's at least the window to clean up
@ -1049,7 +1048,7 @@ board_commitTurn( BoardCtxt* board, XP_Bool alreadyConfirmed )
} else { } else {
TrayTileSet selTiles; TrayTileSet selTiles;
getSelTiles( board, traySelBits, &selTiles ); getSelTiles( board, traySelBits, &selTiles );
if ( alreadyConfirmed ) { if ( turnConfirmed ) {
/* server_commitTrade() changes selPlayer, so board_endTrade /* server_commitTrade() changes selPlayer, so board_endTrade
must be called first() */ must be called first() */
(void)board_endTrade( board ); (void)board_endTrade( board );
@ -1061,11 +1060,10 @@ board_commitTurn( BoardCtxt* board, XP_Bool alreadyConfirmed )
} }
} else { } else {
XWStreamCtxt* stream = NULL; XWStreamCtxt* stream = NULL;
XP_Bool legal = alreadyConfirmed; XP_Bool legal = turnConfirmed;
BadWordList bwl = {0};
if ( !legal ) { if ( !legal ) {
WordNotifierInfo info;
XP_Bool warn;
stream = mem_stream_make( MPPARM(board->mpool) stream = mem_stream_make( MPPARM(board->mpool)
util_getVTManager(board->util), NULL, util_getVTManager(board->util), NULL,
CHANNEL_NONE, (MemStreamCloseCallback)NULL ); CHANNEL_NONE, (MemStreamCloseCallback)NULL );
@ -1074,27 +1072,30 @@ board_commitTurn( BoardCtxt* board, XP_Bool alreadyConfirmed )
STR_COMMIT_CONFIRM); STR_COMMIT_CONFIRM);
stream_catString( stream, str ); stream_catString( stream, str );
warn = board->util->gameInfo->phoniesAction == PHONIES_WARN; XP_Bool warn = board->util->gameInfo->phoniesAction == PHONIES_WARN;
WordNotifierInfo info;
board->badWordRejected = XP_FALSE; if ( warn ) {
info.proc = warnBadWords; info.proc = saveBadWords;
info.closure = board; info.closure = &bwl;
}
legal = model_checkMoveLegal( board->model, turn, stream, legal = model_checkMoveLegal( board->model, turn, stream,
warn? &info:(WordNotifierInfo*)NULL); warn? &info:(WordNotifierInfo*)NULL);
} }
if ( !legal || board->badWordRejected ) { if ( 0 < bwl.bwi.nWords && !phoniesConfirmed ) {
result = XP_FALSE; bwl.bwi.dictName =
dict_getShortName( model_getPlayerDict( board->model, turn ) );
util_notifyIllegalWords( board->util, &bwl.bwi, turn, XP_FALSE );
} else { } else {
/* Hide the tray so no peeking. Leave it hidden even if user /* Hide the tray so no peeking. Leave it hidden even if user
cancels as otherwise another player could get around cancels as otherwise another player could get around
passwords and peek at tiles. */ passwords and peek at tiles. */
if ( !alreadyConfirmed if ( !turnConfirmed
&& gi_countLocalPlayers( board->gi, XP_TRUE ) > 1 ) { && gi_countLocalPlayers( board->gi, XP_TRUE ) > 1 ) {
result = board_hideTray( board ); result = board_hideTray( board );
} }
if ( board->skipCommitConfirm || alreadyConfirmed ) { if ( board->skipCommitConfirm || turnConfirmed ) {
result = server_commitMove( board->server ) || result; result = server_commitMove( board->server ) || result;
/* invalidate all tiles in case we'll be drawing this tray /* invalidate all tiles in case we'll be drawing this tray
again rather than some other -- as is the case in a again rather than some other -- as is the case in a

View file

@ -176,7 +176,8 @@ XP_Bool board_setBlankValue( BoardCtxt* board, XP_U16 XP_UNUSED(player),
void board_resetEngine( BoardCtxt* board ); void board_resetEngine( BoardCtxt* board );
XP_Bool board_commitTurn( BoardCtxt* board, XP_Bool alreadyConfirmed ); XP_Bool board_commitTurn( BoardCtxt* board, XP_Bool phoniesConfirmed,
XP_Bool turnConfirmed );
void board_pushTimerSave( BoardCtxt* board ); void board_pushTimerSave( BoardCtxt* board );
void board_popTimerSave( BoardCtxt* board ); void board_popTimerSave( BoardCtxt* board );

View file

@ -169,7 +169,6 @@ struct BoardCtxt {
XP_Bool showGrid; XP_Bool showGrid;
XP_Bool gameOver; XP_Bool gameOver;
XP_Bool leftHanded; XP_Bool leftHanded;
XP_Bool badWordRejected;
XP_Bool timerPending; XP_Bool timerPending;
XP_Bool disableArrow; XP_Bool disableArrow;
XP_Bool hideValsInTray; XP_Bool hideValsInTray;

View file

@ -1618,7 +1618,7 @@ badWordMoveUndoAndTellUser( ServerCtxt* server, BadWordInfo* bwi )
model_rejectPreviousMove( model, server->pool, &turn ); model_rejectPreviousMove( model, server->pool, &turn );
util_warnIllegalWord( server->vol.util, bwi, turn, XP_TRUE ); util_notifyIllegalWords( server->vol.util, bwi, turn, XP_TRUE );
} /* badWordMoveUndoAndTellUser */ } /* badWordMoveUndoAndTellUser */
EngineCtxt* EngineCtxt*

View file

@ -460,7 +460,7 @@ handleActionInTray( BoardCtxt* board, XP_S16 index, XP_Bool onDivider )
} }
#endif #endif
} else if ( index == -(MAX_TRAY_TILES) ) { /* pending score tile */ } else if ( index == -(MAX_TRAY_TILES) ) { /* pending score tile */
result = board_commitTurn( board, XP_FALSE ); result = board_commitTurn( board, XP_FALSE, XP_FALSE );
#if defined XWFEATURE_TRAYUNDO_ALL #if defined XWFEATURE_TRAYUNDO_ALL
} else if ( index < 0 ) { /* other empty area */ } else if ( index < 0 ) { /* other empty area */
/* it better be true */ /* it better be true */

View file

@ -159,7 +159,7 @@ typedef struct UtilVtable {
XP_U16 stringCode, XP_U16 stringCode,
XP_U16 quantity ); XP_U16 quantity );
XP_Bool (*m_util_warnIllegalWord)( XW_UtilCtxt* uc, BadWordInfo* bwi, void (*m_util_notifyIllegalWords)( XW_UtilCtxt* uc, BadWordInfo* bwi,
XP_U16 turn, XP_Bool turnLost ); XP_U16 turn, XP_Bool turnLost );
void (*m_util_remSelected)(XW_UtilCtxt* uc); void (*m_util_remSelected)(XW_UtilCtxt* uc);
@ -302,8 +302,8 @@ struct XW_UtilCtxt {
#define util_getUserQuantityString( uc, c, q ) \ #define util_getUserQuantityString( uc, c, q ) \
(uc)->vtable->m_util_getUserQuantityString((uc),(c),(q)) (uc)->vtable->m_util_getUserQuantityString((uc),(c),(q))
#define util_warnIllegalWord( uc, w, p, b ) \ #define util_notifyIllegalWords( uc, w, p, b ) \
(uc)->vtable->m_util_warnIllegalWord((uc),(w),(p),(b)) (uc)->vtable->m_util_notifyIllegalWords((uc),(w),(p),(b))
#define util_remSelected( uc ) \ #define util_remSelected( uc ) \
(uc)->vtable->m_util_remSelected((uc)) (uc)->vtable->m_util_remSelected((uc))

View file

@ -620,7 +620,7 @@ static XP_Bool
handleCommit( CursesAppGlobals* globals ) handleCommit( CursesAppGlobals* globals )
{ {
globals->doDraw = board_commitTurn( globals->cGlobals.game.board, globals->doDraw = board_commitTurn( globals->cGlobals.game.board,
XP_FALSE ); XP_FALSE, XP_FALSE );
return XP_TRUE; return XP_TRUE;
} /* handleCommit */ } /* handleCommit */
@ -1371,15 +1371,14 @@ curses_util_turnChanged( XW_UtilCtxt* XP_UNUSED(uc), XP_S16 newTurn )
} }
#endif #endif
static XP_Bool static void
curses_util_warnIllegalWord( XW_UtilCtxt* XP_UNUSED(uc), curses_util_notifyIllegalWords( XW_UtilCtxt* XP_UNUSED(uc),
BadWordInfo* XP_UNUSED(bwi), BadWordInfo* XP_UNUSED(bwi),
XP_U16 XP_UNUSED(player), XP_U16 XP_UNUSED(player),
XP_Bool XP_UNUSED(turnLost) ) XP_Bool XP_UNUSED(turnLost) )
{ {
XP_WARNF( "curses_util_warnIllegalWord not implemented" ); XP_WARNF( "curses_util_notifyIllegalWords not implemented" );
return XP_FALSE; } /* curses_util_notifyIllegalWord */
} /* curses_util_warnIllegalWord */
static void static void
curses_util_remSelected( XW_UtilCtxt* uc ) curses_util_remSelected( XW_UtilCtxt* uc )
@ -1445,7 +1444,7 @@ setupCursesUtilCallbacks( CursesAppGlobals* globals, XW_UtilCtxt* util )
#ifdef XWFEATURE_TURNCHANGENOTIFY #ifdef XWFEATURE_TURNCHANGENOTIFY
util->vtable->m_util_turnChanged = curses_util_turnChanged; util->vtable->m_util_turnChanged = curses_util_turnChanged;
#endif #endif
util->vtable->m_util_warnIllegalWord = curses_util_warnIllegalWord; util->vtable->m_util_notifyIllegalWords = curses_util_notifyIllegalWords;
util->vtable->m_util_remSelected = curses_util_remSelected; util->vtable->m_util_remSelected = curses_util_remSelected;
#ifndef XWFEATURE_STANDALONE_ONLY #ifndef XWFEATURE_STANDALONE_ONLY
util->vtable->m_util_makeStreamFromAddr = curses_util_makeStreamFromAddr; util->vtable->m_util_makeStreamFromAddr = curses_util_makeStreamFromAddr;

View file

@ -1445,7 +1445,7 @@ handle_trade_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
static void static void
handle_done_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals ) handle_done_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
{ {
if ( board_commitTurn( globals->cGlobals.game.board, XP_FALSE ) ) { if ( board_commitTurn( globals->cGlobals.game.board, XP_FALSE, XP_FALSE ) ) {
board_draw( globals->cGlobals.game.board ); board_draw( globals->cGlobals.game.board );
disenable_buttons( globals ); disenable_buttons( globals );
} }
@ -1543,7 +1543,7 @@ handle_hide_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
static void static void
handle_commit_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals ) handle_commit_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
{ {
if ( board_commitTurn( globals->cGlobals.game.board, XP_FALSE ) ) { if ( board_commitTurn( globals->cGlobals.game.board, XP_FALSE, XP_FALSE ) ) {
board_draw( globals->cGlobals.game.board ); board_draw( globals->cGlobals.game.board );
} }
} /* handle_commit_button */ } /* handle_commit_button */
@ -2117,49 +2117,48 @@ gtk_util_requestTime( XW_UtilCtxt* uc )
globals->idleID = g_idle_add( idle_func, globals ); globals->idleID = g_idle_add( idle_func, globals );
} /* gtk_util_requestTime */ } /* gtk_util_requestTime */
static XP_Bool static gint
gtk_util_warnIllegalWord( XW_UtilCtxt* uc, BadWordInfo* bwi, XP_U16 player, ask_bad_words( gpointer data )
XP_Bool turnLost ) {
GtkGameGlobals* globals = (GtkGameGlobals*)data;
CommonGlobals* cGlobals = &globals->cGlobals;
if ( GTK_RESPONSE_YES == gtkask( globals->window, cGlobals->question,
GTK_BUTTONS_YES_NO, NULL ) ) {
board_commitTurn( cGlobals->game.board, XP_TRUE, XP_FALSE );
}
return 0;
}
static void
gtk_util_notifyIllegalWords( XW_UtilCtxt* uc, BadWordInfo* bwi, XP_U16 player,
XP_Bool turnLost )
{ {
XP_Bool result;
GtkGameGlobals* globals = (GtkGameGlobals*)uc->closure; GtkGameGlobals* globals = (GtkGameGlobals*)uc->closure;
CommonGlobals* cGlobals = &globals->cGlobals;
char buf[300]; char buf[300];
gchar* strs = g_strjoinv( "\", \"", (gchar**)bwi->words );
if ( turnLost ) { if ( turnLost ) {
char wordsBuf[256]; XP_UCHAR* name = cGlobals->gi->players[player].name;
XP_U16 i;
XP_UCHAR* name = globals->cGlobals.gi->players[player].name;
XP_ASSERT( !!name ); XP_ASSERT( !!name );
for ( i = 0, wordsBuf[0] = '\0'; ; ) {
char wordBuf[18];
sprintf( wordBuf, "\"%s\"", bwi->words[i] );
strcat( wordsBuf, wordBuf );
if ( ++i == bwi->nWords ) {
break;
}
strcat( wordsBuf, ", " );
}
sprintf( buf, "Player %d (%s) played illegal word[s] %s; loses turn.", sprintf( buf, "Player %d (%s) played illegal word[s] %s; loses turn.",
player+1, name, wordsBuf ); player+1, name, strs );
if ( globals->cGlobals.params->skipWarnings ) { if ( cGlobals->params->skipWarnings ) {
XP_LOGF( "%s", buf ); XP_LOGF( "%s", buf );
} else { } else {
gtkUserError( globals, buf ); gtkUserError( globals, buf );
} }
result = XP_TRUE;
} else { } else {
XP_ASSERT( bwi->nWords == 1 ); sprintf( cGlobals->question, "Word[s] \"%s\" not in the current dictionary (%s). "
sprintf( buf, "Word \"%s\" not in the current dictionary (%s). " "Use anyway?", strs, bwi->dictName );
"Use it anyway?", bwi->words[0], bwi->dictName );
result = GTK_RESPONSE_YES == gtkask( globals->window, buf,
GTK_BUTTONS_YES_NO, NULL );
}
return result; (void)g_idle_add( ask_bad_words, globals );
} /* gtk_util_warnIllegalWord */ }
g_free( strs );
} /* gtk_util_notifyIllegalWords */
static void static void
gtk_util_remSelected( XW_UtilCtxt* uc ) gtk_util_remSelected( XW_UtilCtxt* uc )
@ -2276,7 +2275,7 @@ ask_move( gpointer data )
gint chosen = gtkask( globals->window, cGlobals->question, buttons, NULL ); gint chosen = gtkask( globals->window, cGlobals->question, buttons, NULL );
if ( GTK_RESPONSE_OK == chosen || chosen == GTK_RESPONSE_YES ) { if ( GTK_RESPONSE_OK == chosen || chosen == GTK_RESPONSE_YES ) {
BoardCtxt* board = cGlobals->game.board; BoardCtxt* board = cGlobals->game.board;
if ( board_commitTurn( board, XP_TRUE ) ) { if ( board_commitTurn( board, XP_TRUE, XP_TRUE ) ) {
board_draw( board ); board_draw( board );
} }
} }
@ -2315,7 +2314,7 @@ ask_trade( gpointer data )
cGlobals->question, cGlobals->question,
GTK_BUTTONS_YES_NO, NULL ) ) { GTK_BUTTONS_YES_NO, NULL ) ) {
BoardCtxt* board = cGlobals->game.board; BoardCtxt* board = cGlobals->game.board;
if ( board_commitTurn( board, XP_TRUE ) ) { if ( board_commitTurn( board, XP_TRUE, XP_TRUE ) ) {
board_draw( board ); board_draw( board );
} }
} }
@ -2488,7 +2487,7 @@ setupGtkUtilCallbacks( GtkGameGlobals* globals, XW_UtilCtxt* util )
util->vtable->m_util_setTimer = gtk_util_setTimer; util->vtable->m_util_setTimer = gtk_util_setTimer;
util->vtable->m_util_clearTimer = gtk_util_clearTimer; util->vtable->m_util_clearTimer = gtk_util_clearTimer;
util->vtable->m_util_requestTime = gtk_util_requestTime; util->vtable->m_util_requestTime = gtk_util_requestTime;
util->vtable->m_util_warnIllegalWord = gtk_util_warnIllegalWord; util->vtable->m_util_notifyIllegalWords = gtk_util_notifyIllegalWords;
util->vtable->m_util_remSelected = gtk_util_remSelected; util->vtable->m_util_remSelected = gtk_util_remSelected;
#ifndef XWFEATURE_STANDALONE_ONLY #ifndef XWFEATURE_STANDALONE_ONLY
util->vtable->m_util_makeStreamFromAddr = gtk_util_makeStreamFromAddr; util->vtable->m_util_makeStreamFromAddr = gtk_util_makeStreamFromAddr;