From e887d0a116300ebf51dd79bd59a14cfcba6d5007 Mon Sep 17 00:00:00 2001 From: Andy2 Date: Wed, 21 Sep 2011 19:04:33 -0700 Subject: [PATCH 01/11] make word lookup two-stage, first a dialog to pick the word then another to pick the URL. Hacky code takes us back to the first after the second is dismissed while only showing either if there's a choice to be made. Also add menu item to lookup all words in the game -- useful for testing when robot refuses to play multiple words but maybe also worth shipping. --- .../android/XWords4/res/menu/board_menu.xml | 2 + .../android/XWords4/res/values/strings.xml | 6 +- .../eehouse/android/xw4/BoardActivity.java | 140 +++++++++++++++--- .../eehouse/android/xw4/jni/JNIThread.java | 4 +- 4 files changed, 130 insertions(+), 22 deletions(-) diff --git a/xwords4/android/XWords4/res/menu/board_menu.xml b/xwords4/android/XWords4/res/menu/board_menu.xml index 74d6de739..f2f65c6ec 100644 --- a/xwords4/android/XWords4/res/menu/board_menu.xml +++ b/xwords4/android/XWords4/res/menu/board_menu.xml @@ -30,6 +30,8 @@ + Recent changes - Lookup word - Tap to lookup + Look up words + Tap to look up Done Pick a site Pick a site Tap word to search - + Look up %s at diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java index e56766b30..0bca30fc2 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java @@ -40,6 +40,7 @@ import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.DialogInterface; import android.content.DialogInterface.OnDismissListener; +import android.content.DialogInterface.OnCancelListener; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; @@ -80,6 +81,7 @@ public class BoardActivity extends XWActivity private static final int DLG_INVITE = DLG_OKONLY + 9; private static final int DLG_SCORES_BLK = DLG_OKONLY + 10; private static final int DLG_WORDPICK = DLG_OKONLY + 11; + private static final int DLG_URLPICK = DLG_OKONLY + 12; private static final int CHAT_REQUEST = 1; private static final int SCREEN_ON_TIME = 10 * 60 * 1000; // 10 mins @@ -104,6 +106,7 @@ public class BoardActivity extends XWActivity private static final String ROOM = "ROOM"; private static final String TOASTSTR = "TOASTSTR"; private static final String WORDS = "WORDS"; + private static final String LOOKUPITEM = "LOOKUPITEM"; private BoardView m_view; private int m_jniGamePtr; @@ -145,6 +148,7 @@ public class BoardActivity extends XWActivity private String m_room; private String m_toastStr; private String[] m_words; + private String m_word; private String[] m_langCodes; private String[] m_lookupUrls; private String[] m_lookupNames; @@ -176,6 +180,7 @@ public class BoardActivity extends XWActivity Dialog dialog = super.onCreateDialog( id ); if ( null == dialog ) { DialogInterface.OnClickListener lstnr; + DialogInterface.OnClickListener doneLstnr; AlertDialog.Builder ab; switch ( id ) { @@ -251,7 +256,7 @@ public class BoardActivity extends XWActivity lstnr = new DialogInterface.OnClickListener() { public void onClick( DialogInterface dialog, int whichButton ) { - m_jniThread.handle( JNICmd.CMD_WORDS ); + m_jniThread.handle( JNICmd.CMD_WORDS, 1 ); } }; ab.setNegativeButton( R.string.button_lookup, lstnr ); @@ -326,13 +331,66 @@ public class BoardActivity extends XWActivity } break; case DLG_WORDPICK: + initLookup(); + lstnr = new DialogInterface.OnClickListener() { + public void onClick( DialogInterface dialog, + int item ) { + lookupWord( m_words[item] ); + } + }; + doneLstnr = new DialogInterface.OnClickListener() { + public void onClick( DialogInterface dlg, + int item ) { + wordPickDone(); + } + }; dialog = new AlertDialog.Builder( this ) .setTitle( R.string.title_lookup ) - .setView( buildLookupDlg() ) - .setNegativeButton( R.string.button_done, null ) + .setItems( m_words, lstnr ) + .setNegativeButton( R.string.button_done, doneLstnr ) + .setOnCancelListener( new OnCancelListener() { + public void onCancel( DialogInterface dialog ) { + wordPickDone(); + } + } ) .create(); Utils.setRemoveOnDismiss( this, dialog, id ); break; + + case DLG_URLPICK: + DialogInterface.OnClickListener itemLstnr = + new DialogInterface.OnClickListener() { + public void onClick( DialogInterface dialog, + int item ) { + lookupWord( m_word, m_lookupUrls[item] ); + post( new Runnable() { + public void run() { + showDialog( DLG_URLPICK ); + } + } ); + } + }; + doneLstnr = new DialogInterface.OnClickListener() { + public void onClick( DialogInterface dialog, + int item ) { + urlPickDone(); + } + }; + String fmt = getString( R.string.pick_url_titlef ); + String title = String.format( fmt, m_word ); + dialog = new AlertDialog.Builder( this ) + .setTitle( title ) + .setItems( m_lookupNames, itemLstnr ) + .setNegativeButton( R.string.button_done, doneLstnr ) + .setOnCancelListener( new OnCancelListener() { + public void onCancel( DialogInterface dialog ) { + urlPickDone(); + } + } ) + .create(); + Utils.setRemoveOnDismiss( this, dialog, id ); + break; + default: // just drop it; super.onCreateDialog likely failed break; @@ -421,6 +479,7 @@ public class BoardActivity extends XWActivity outState.putString( ROOM, m_room ); outState.putString( TOASTSTR, m_toastStr ); outState.putStringArray( WORDS, m_words ); + outState.putString( LOOKUPITEM, m_word ); } private void getBundledData( Bundle bundle ) @@ -432,6 +491,7 @@ public class BoardActivity extends XWActivity m_room = bundle.getString( ROOM ); m_toastStr = bundle.getString( TOASTSTR ); m_words = bundle.getStringArray( WORDS ); + m_word = bundle.getString( LOOKUPITEM ); } } @@ -463,6 +523,8 @@ public class BoardActivity extends XWActivity // in case of change... setBackgroundColor(); setKeepScreenOn(); + } else { + lookupWord(); } } } @@ -566,6 +628,9 @@ public class BoardActivity extends XWActivity case R.id.board_menu_values: cmd = JNIThread.JNICmd.CMD_VALUES; break; + case R.id.board_menu_lookup: + m_jniThread.handle( JNICmd.CMD_WORDS, 10000 ); + break; case R.id.board_menu_game_counts: m_jniThread.handle( JNIThread.JNICmd.CMD_COUNTS_VALUES, @@ -1267,15 +1332,18 @@ public class BoardActivity extends XWActivity } break; case JNIThread.GOT_WORDS: - m_words = + String[] tmp = TextUtils.split( (String)msg.obj, "\n" ); - if ( 0 == m_words.length ) { - // drop it - // } else if ( 1 == m_words.length ) { - // lookupWord( m_words[0] ); - } else { - showDialog( DLG_WORDPICK ); + m_words = new String[tmp.length]; + for ( int ii = 0, jj = tmp.length; + ii < tmp.length; ++ii, --jj ) { + m_words[ii] = tmp[jj-1]; } + if ( 1 == m_words.length ) { + m_word = m_words[0]; + } + initLookup(); + lookupWord(); break; } } @@ -1583,17 +1651,42 @@ public class BoardActivity extends XWActivity return layout; } + private void lookupWord() + { + if ( null == m_words || 0 == m_words.length ) { + // drop it + } else if ( null != m_word ) { + lookupWord( m_word ); + } else { + showDialog( DLG_WORDPICK ); + } + } + + private void lookupWord( String word ) + { + m_word = word; + if ( 1 == m_lookupUrls.length ) { + lookupWord( word, m_lookupUrls[0] ); + } else { + showDialog( DLG_URLPICK ); + } + } + private void lookupWord( String word, String fmt ) { - String dict_url = String.format( fmt, curLangCode(), word ); - Uri uri = Uri.parse( dict_url ); - Intent intent = new Intent( Intent.ACTION_VIEW, uri ); - intent.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK ); + if ( false ) { + Utils.logf( "skipping lookupWord(%s)", word ); + } else { + String dict_url = String.format( fmt, curLangCode(), word ); + Uri uri = Uri.parse( dict_url ); + Intent intent = new Intent( Intent.ACTION_VIEW, uri ); + intent.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK ); - try { - startActivity( intent ); - } catch ( android.content.ActivityNotFoundException anfe ) { - Utils.logf( "%s", anfe.toString() ); + try { + startActivity( intent ); + } catch ( android.content.ActivityNotFoundException anfe ) { + Utils.logf( "%s", anfe.toString() ); + } } } @@ -1626,4 +1719,15 @@ public class BoardActivity extends XWActivity } } + private void urlPickDone() { + m_word = null; + if ( 1 >= m_words.length ) { + m_words = null; + } + } + + private void wordPickDone() { + m_words = null; + } + } // class BoardActivity diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/JNIThread.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/JNIThread.java index c95ac244f..737316007 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/JNIThread.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/JNIThread.java @@ -493,7 +493,9 @@ public class JNIThread extends Thread { break; case CMD_WORDS: - String words = XwJNI.server_listWordsPlayed( m_jniGamePtr, 1 ); + int nMoves = ((Integer)args[0]).intValue(); + String words = XwJNI.server_listWordsPlayed( m_jniGamePtr, + nMoves ); Message.obtain( m_handler, GOT_WORDS, words ).sendToTarget(); break; From b10453bd256a2c1158e327cd4d6af31ec5c24cc4 Mon Sep 17 00:00:00 2001 From: Andy2 Date: Thu, 22 Sep 2011 06:14:22 -0700 Subject: [PATCH 02/11] cleanup --- .../eehouse/android/xw4/BoardActivity.java | 43 +------------------ 1 file changed, 2 insertions(+), 41 deletions(-) diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java index 0bca30fc2..d09189f0c 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java @@ -1617,40 +1617,6 @@ public class BoardActivity extends XWActivity } } - private View buildLookupDlg() - { - initLookup(); - - LinearLayout layout = - (LinearLayout)Utils.inflate( this, R.layout.wordlist_view ); - - final Spinner spinner = - (Spinner)layout.findViewById( R.id.site_spinner ); - ArrayAdapter adapter = new ArrayAdapter(this, - android.R.layout.simple_spinner_item, - m_lookupNames ); - spinner.setAdapter( adapter ); - - ListView list = (ListView)layout.findViewById( R.id.words ); - adapter = new ArrayAdapter( this, - //android.R.layout.select_dialog_item, - // android.R.layout.simple_list_item_1, - android.R.layout.select_dialog_item, - m_words ) ; - list.setAdapter( adapter ); - OnItemClickListener oicl = new OnItemClickListener() { - public void onItemClick(AdapterView parent, - View view, - int position, long id ) { - int urlPos = spinner.getSelectedItemPosition(); - lookupWord( m_words[position], m_lookupUrls[urlPos] ); - } - }; - list.setOnItemClickListener( oicl ); - - return layout; - } - private void lookupWord() { if ( null == m_words || 0 == m_words.length ) { @@ -1677,7 +1643,8 @@ public class BoardActivity extends XWActivity if ( false ) { Utils.logf( "skipping lookupWord(%s)", word ); } else { - String dict_url = String.format( fmt, curLangCode(), word ); + String langCode = m_langCodes[m_gi.dictLang]; + String dict_url = String.format( fmt, langCode, word ); Uri uri = Uri.parse( dict_url ); Intent intent = new Intent( Intent.ACTION_VIEW, uri ); intent.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK ); @@ -1689,12 +1656,6 @@ public class BoardActivity extends XWActivity } } } - - private String curLangCode() - { - initLookup(); - return m_langCodes[m_gi.dictLang]; - } private void initLookup() { From 8a5667f011c6caca7687de89d8fc9baeb2dddb41 Mon Sep 17 00:00:00 2001 From: Eric House Date: Thu, 22 Sep 2011 17:16:27 -0700 Subject: [PATCH 03/11] add missing language codes --- .../XWords4/res/values/common_rsrc.xml | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/xwords4/android/XWords4/res/values/common_rsrc.xml b/xwords4/android/XWords4/res/values/common_rsrc.xml index eaaf5850d..6e3dcfb06 100644 --- a/xwords4/android/XWords4/res/values/common_rsrc.xml +++ b/xwords4/android/XWords4/res/values/common_rsrc.xml @@ -175,22 +175,22 @@ en fr de - - + tr + ar es - - - + sv + pl + da it - + nl ca + pt + ru - - - - - + cs + el + sk From 77b9fa11a5cedb5b965e4d0a7f192907a8158162 Mon Sep 17 00:00:00 2001 From: Andy2 Date: Sun, 2 Oct 2011 16:21:09 -0700 Subject: [PATCH 04/11] improving lookup words experience: replace util_userQuery(QUERY_ROBOT_MOVE) with new util_informMove(), into which the number of words formed and the words themselves are passed. The process of consing up the score explanation was already passing over the model, so storing the words is very little effort, and will save a call back into the model where the user actually wants to do the lookup. --- xwords4/common/model.c | 30 +++++++++++++++++------------- xwords4/common/model.h | 4 ++++ xwords4/common/modelp.h | 8 ++++++++ xwords4/common/server.c | 16 +++++++++++++--- xwords4/common/util.h | 5 ++++- xwords4/linux/cursesmain.c | 13 ++++++++++++- xwords4/linux/gtkmain.c | 12 +++++++++++- 7 files changed, 69 insertions(+), 19 deletions(-) diff --git a/xwords4/common/model.c b/xwords4/common/model.c index 92290be0a..f0b280320 100644 --- a/xwords4/common/model.c +++ b/xwords4/common/model.c @@ -2033,11 +2033,6 @@ model_recentPassCountOk( ModelCtxt* model ) return count < okCount; } -typedef struct _RecordWordsInfo { - XWStreamCtxt* stream; - XP_U16 nWords; -} RecordWordsInfo; - static XP_Bool recordWord( const XP_UCHAR* word, XP_Bool isLegal, void* closure ) { @@ -2049,9 +2044,23 @@ recordWord( const XP_UCHAR* word, XP_Bool isLegal, void* closure ) stream_putU8( stream, '\n' ); } stream_catString( stream, word ); + if ( NULL != info->nWordsP ) { + *info->nWordsP = info->nWords; + } return XP_TRUE; } +WordNotifierInfo* +model_initWordCounter( ModelCtxt* model, XWStreamCtxt* stream, XP_U16* nWords ) +{ + model->vol.wni.proc = recordWord; + model->vol.wni.closure = &model->vol.rwi; + model->vol.rwi.stream = stream; + model->vol.rwi.nWordsP = nWords; + model->vol.rwi.nWords = 0; + return &model->vol.wni; +} + void model_getWordsPlayed( ModelCtxt* model, XP_U16 nTurns, XWStreamCtxt* stream ) { @@ -2067,19 +2076,14 @@ model_getWordsPlayed( ModelCtxt* model, XP_U16 nTurns, XWStreamCtxt* stream ) } if ( model_undoLatestMoves( model, NULL, nTurns, NULL, NULL ) ) { - RecordWordsInfo info = { .stream = stream, .nWords = 0 }; - WordNotifierInfo notifyInfo = { .proc = recordWord, - .closure = &info, - }; - + WordNotifierInfo* ni = model_initWordCounter( model, stream, NULL ); /* Now push the undone moves back into the model one at a time. recordWord() will add each played word to the stream as it's scored */ buildModelFromStack( model, tmpStack, XP_TRUE, nEntries - nTurns + nPlayers,/* skip assignments */ - (XWStreamCtxt*)NULL, ¬ifyInfo, - (MovePrintFuncPre)NULL, (MovePrintFuncPost)NULL, - NULL ); + (XWStreamCtxt*)NULL, ni, (MovePrintFuncPre)NULL, + (MovePrintFuncPost)NULL, NULL ); } stack_destroy( tmpStack ); } diff --git a/xwords4/common/model.h b/xwords4/common/model.h index 399f3df77..c62342b10 100644 --- a/xwords4/common/model.h +++ b/xwords4/common/model.h @@ -271,6 +271,10 @@ XP_U16 figureMoveScore( const ModelCtxt* model, XP_U16 turn, MoveInfo* mvInfo, EngineCtxt* engine, XWStreamCtxt* stream, WordNotifierInfo* notifyInfo ); +/* tap into internal WordNotifierInfo */ +WordNotifierInfo* model_initWordCounter( ModelCtxt* model, XWStreamCtxt* stream, + XP_U16* nWords ); + /********************* persistence ********************/ #ifdef INCLUDE_IO_SUPPORT void model_load( ModelCtxt* model, XP_Stream* inStream ); diff --git a/xwords4/common/modelp.h b/xwords4/common/modelp.h index c3f812158..2d1085400 100644 --- a/xwords4/common/modelp.h +++ b/xwords4/common/modelp.h @@ -43,6 +43,12 @@ typedef struct PlayerCtxt { PendingTile pendingTiles[MAX_TRAY_TILES]; } PlayerCtxt; +typedef struct _RecordWordsInfo { + XWStreamCtxt* stream; + XP_U16* nWordsP; + XP_U16 nWords; +} RecordWordsInfo; + typedef struct ModelVolatiles { XW_UtilCtxt* util; struct CurGameInfo* gi; @@ -55,6 +61,8 @@ typedef struct ModelVolatiles { void* trayListenerData; DictListener dictListenerFunc; void* dictListenerData; + RecordWordsInfo rwi; + WordNotifierInfo wni; XP_U16 nTilesOnBoard; MPSLOT } ModelVolatiles; diff --git a/xwords4/common/server.c b/xwords4/common/server.c index d259cfa6e..dba489b25 100644 --- a/xwords4/common/server.c +++ b/xwords4/common/server.c @@ -92,6 +92,8 @@ typedef struct ServerNonvolatiles { RemoteAddress addresses[MAX_NUM_PLAYERS]; XWStreamCtxt* prevMoveStream; /* save it to print later */ + XWStreamCtxt* prevWordsStream; + XP_U16 prevWordCount; } ServerNonvolatiles; struct ServerCtxt { @@ -174,7 +176,8 @@ getStateStr( XW_State st ) } #endif -#ifdef DEBUG +#if 0 +//def DEBUG static void logNewState( XW_State old, XW_State newst ) { @@ -739,9 +742,14 @@ makeRobotMove( ServerCtxt* server ) model_makeTurnFromMoveInfo( model, turn, &newMove ); if ( !!stream ) { - (void)model_checkMoveLegal( model, turn, stream, NULL ); + XWStreamCtxt* wordsStream = mkServerStream( server ); + WordNotifierInfo* ni = + model_initWordCounter( model, wordsStream, + &server->nv.prevWordCount ); + (void)model_checkMoveLegal( model, turn, stream, ni ); XP_ASSERT( !server->nv.prevMoveStream ); server->nv.prevMoveStream = stream; + server->nv.prevWordsStream = wordsStream; } result = server_commitMove( server ); } else { @@ -848,8 +856,10 @@ showPrevScore( ServerCtxt* server ) stream_destroy( prevStream ); } - (void)util_userQuery( util, QUERY_ROBOT_MOVE, stream ); + util_informMove( util, stream, server->nv.prevWordsStream, + server->nv.prevWordCount ); stream_destroy( stream ); + stream_destroy( server->nv.prevWordsStream ); } SETSTATE( server, server->nv.stateAfterShow ); } /* showPrevScore */ diff --git a/xwords4/common/util.h b/xwords4/common/util.h index 00b6cf0c6..bee096c4d 100644 --- a/xwords4/common/util.h +++ b/xwords4/common/util.h @@ -66,7 +66,6 @@ typedef enum { typedef enum { QUERY_COMMIT_TURN, /* 0 means cancel; 1 means commit */ QUERY_COMMIT_TRADE, - QUERY_ROBOT_MOVE, QUERY_ROBOT_TRADE, QUERY_LAST_COMMON @@ -131,6 +130,8 @@ typedef struct UtilVtable { #ifdef XWFEATURE_TURNCHANGENOTIFY void (*m_util_turnChanged)(XW_UtilCtxt* uc); #endif + void (*m_util_informMove)( XW_UtilCtxt* uc, XWStreamCtxt* expl, + XWStreamCtxt* words, XP_U16 wordCount ); void (*m_util_notifyGameOver)( XW_UtilCtxt* uc ); XP_Bool (*m_util_hiliteCell)( XW_UtilCtxt* uc, XP_U16 col, XP_U16 row ); @@ -227,6 +228,8 @@ struct XW_UtilCtxt { # define util_turnChanged( uc ) #endif +#define util_informMove(uc,e,w,wc) \ + (uc)->vtable->m_util_informMove( (uc),(e),(w),(wc) ) #define util_notifyGameOver( uc ) \ (uc)->vtable->m_util_notifyGameOver((uc)) diff --git a/xwords4/linux/cursesmain.c b/xwords4/linux/cursesmain.c index e53810e8e..0bc9548b4 100644 --- a/xwords4/linux/cursesmain.c +++ b/xwords4/linux/cursesmain.c @@ -282,7 +282,6 @@ curses_util_userQuery( XW_UtilCtxt* uc, UtilQueryID id, XWStreamCtxt* stream ) answers[numAnswers++] = "Cancel"; answers[numAnswers++] = "Ok"; break; - case QUERY_ROBOT_MOVE: case QUERY_ROBOT_TRADE: question = strFromStream( stream ); freeMe = XP_TRUE; @@ -332,6 +331,17 @@ cursesShowFinalScores( CursesAppGlobals* globals ) stream_destroy( stream ); } /* cursesShowFinalScores */ +static void +curses_util_informMove( XW_UtilCtxt* uc, XWStreamCtxt* expl, + XWStreamCtxt* XP_UNUSED(words), + XP_U16 XP_UNUSED(wordCount) ) +{ + CursesAppGlobals* globals = (CursesAppGlobals*)uc->closure; + char* question = strFromStream( expl ); + (void)cursesask( globals, question, 1, "Ok" ); + free( question ); +} + static void curses_util_notifyGameOver( XW_UtilCtxt* uc ) { @@ -1465,6 +1475,7 @@ setupCursesUtilCallbacks( CursesAppGlobals* globals, XW_UtilCtxt* util ) util->vtable->m_util_userQuery = curses_util_userQuery; util->vtable->m_util_userPickTile = curses_util_userPickTile; util->vtable->m_util_trayHiddenChange = curses_util_trayHiddenChange; + util->vtable->m_util_informMove = curses_util_informMove; util->vtable->m_util_notifyGameOver = curses_util_notifyGameOver; util->vtable->m_util_hiliteCell = curses_util_hiliteCell; util->vtable->m_util_engineProgressCallback = diff --git a/xwords4/linux/gtkmain.c b/xwords4/linux/gtkmain.c index 0316ee376..8f04378d1 100644 --- a/xwords4/linux/gtkmain.c +++ b/xwords4/linux/gtkmain.c @@ -1386,6 +1386,16 @@ gtkShowFinalScores( const CommonGlobals* cGlobals ) free( text ); } /* gtkShowFinalScores */ +static void +gtk_util_informMove( XW_UtilCtxt* XP_UNUSED(uc), XWStreamCtxt* XP_UNUSED(expl), + XWStreamCtxt* words, XP_U16 wordCount ) +{ + XP_LOGF( "%s(wordCount=%d)", __func__, wordCount ); + char* question = strFromStream( words/*expl*/ ); + (void)gtkask( question, GTK_BUTTONS_OK ); + free( question ); +} + static void gtk_util_notifyGameOver( XW_UtilCtxt* uc ) { @@ -1763,7 +1773,6 @@ gtk_util_userQuery( XW_UtilCtxt* XP_UNUSED(uc), UtilQueryID id, case QUERY_COMMIT_TRADE: question = "Are you sure you want to trade the selected tiles?"; break; - case QUERY_ROBOT_MOVE: case QUERY_ROBOT_TRADE: question = strFromStream( stream ); freeMe = XP_TRUE; @@ -1927,6 +1936,7 @@ setupGtkUtilCallbacks( GtkAppGlobals* globals, XW_UtilCtxt* util ) util->vtable->m_util_askPassword = gtk_util_askPassword; util->vtable->m_util_trayHiddenChange = gtk_util_trayHiddenChange; util->vtable->m_util_yOffsetChange = gtk_util_yOffsetChange; + util->vtable->m_util_informMove = gtk_util_informMove; util->vtable->m_util_notifyGameOver = gtk_util_notifyGameOver; util->vtable->m_util_hiliteCell = gtk_util_hiliteCell; util->vtable->m_util_altKeyDown = gtk_util_altKeyDown; From 35e4c21f17f572980b66924020f3780ea40b35fd Mon Sep 17 00:00:00 2001 From: Andy2 Date: Sun, 2 Oct 2011 16:42:10 -0700 Subject: [PATCH 05/11] add util_informMove to jni. Use it, but not to advantage yet. --- xwords4/android/XWords4/jni/utilwrapper.c | 14 ++++++++++++++ .../src/org/eehouse/android/xw4/BoardActivity.java | 11 ++++++++--- .../src/org/eehouse/android/xw4/jni/UtilCtxt.java | 5 +++-- .../org/eehouse/android/xw4/jni/UtilCtxtImpl.java | 5 +++++ 4 files changed, 30 insertions(+), 5 deletions(-) diff --git a/xwords4/android/XWords4/jni/utilwrapper.c b/xwords4/android/XWords4/jni/utilwrapper.c index 396e78122..047f71928 100644 --- a/xwords4/android/XWords4/jni/utilwrapper.c +++ b/xwords4/android/XWords4/jni/utilwrapper.c @@ -215,6 +215,19 @@ and_util_turnChanged(XW_UtilCtxt* uc) } #endif +static void +and_util_informMove( XW_UtilCtxt* uc, XWStreamCtxt* expl, + XWStreamCtxt* words, XP_U16 wordCount ) +{ + UTIL_CBK_HEADER( "informMove", "(Ljava/lang/String;Ljava/lang/String;I)V" ); + jstring jexpl = streamToJString( MPPARM(util->util.mpool) env, expl ); + jstring jwords = streamToJString( MPPARM(util->util.mpool) env, words ); + (*env)->CallVoidMethod( env, util->jutil, mid, jexpl, jwords, wordCount ); + (*env)->DeleteLocalRef( env, jexpl ); + (*env)->DeleteLocalRef( env, jwords ); + UTIL_CBK_TAIL(); +} + static void and_util_notifyGameOver( XW_UtilCtxt* uc ) { @@ -476,6 +489,7 @@ makeUtil( MPFORMAL JNIEnv** envp, jobject jutil, CurGameInfo* gi, #ifdef XWFEATURE_TURNCHANGENOTIFY SET_PROC( turnChanged); #endif + SET_PROC(informMove); SET_PROC(notifyGameOver); SET_PROC(hiliteCell); SET_PROC(engineProgressCallback); diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java index d09189f0c..76b4a45cd 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java @@ -1128,12 +1128,10 @@ public class BoardActivity extends XWActivity // if the player after this one is also a robot and we // don't block then a second dialog will replace this one. // So block. Yuck. - case UtilCtxt.QUERY_ROBOT_MOVE: case UtilCtxt.QUERY_ROBOT_TRADE: m_dlgBytes = query; m_dlgTitle = R.string.info_title; - waitBlockingDialog( QUERY_ROBOT_MOVE == id ? - DLG_SCORES_BLK : QUERY_INFORM_BLK, 0 ); + waitBlockingDialog( QUERY_INFORM_BLK, 0 ); result = true; break; @@ -1211,6 +1209,13 @@ public class BoardActivity extends XWActivity } } // userError + public void informMove( String expl, String words, int wordCount ) + { + m_dlgBytes = expl; + m_dlgTitle = R.string.info_title; + waitBlockingDialog( DLG_SCORES_BLK, 0 ); + } + public void notifyGameOver() { m_jniThread.handle( JNIThread.JNICmd.CMD_POST_OVER ); diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/UtilCtxt.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/UtilCtxt.java index b890bb5a7..630622c30 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/UtilCtxt.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/UtilCtxt.java @@ -76,8 +76,7 @@ public interface UtilCtxt { static final int QUERY_COMMIT_TURN = 0; static final int QUERY_COMMIT_TRADE = 1; - static final int QUERY_ROBOT_MOVE = 2; - static final int QUERY_ROBOT_TRADE = 3; + static final int QUERY_ROBOT_TRADE = 2; boolean userQuery( int id, String query ); @@ -101,6 +100,8 @@ public interface UtilCtxt { static final int ERR_RELAY_BASE = 16; void userError( int id ); + void informMove( String expl, String words, int wordCount ); + void notifyGameOver(); // Don't need this unless we have a scroll thumb to indicate position //void yOffsetChange( int maxOffset, int oldOffset, int newOffset ); diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/UtilCtxtImpl.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/UtilCtxtImpl.java index 3654e082f..ad950d522 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/UtilCtxtImpl.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/UtilCtxtImpl.java @@ -185,6 +185,11 @@ public class UtilCtxtImpl implements UtilCtxt { subclassOverride( "userError" ); } + public void informMove( String expl, String words, int wordCount ) + { + subclassOverride( "informMove" ); + } + // Probably want to cache the fact that the game over notification // showed up and then display it next time game's opened. public void notifyGameOver() From 072516655e751cc64b2fefe603de145f19cd20be Mon Sep 17 00:00:00 2001 From: Andy2 Date: Mon, 3 Oct 2011 06:43:20 -0700 Subject: [PATCH 06/11] Use words list passed into informMove rather than query when user presses button. Include word in button text when there's only one. --- .../android/XWords4/res/values/strings.xml | 1 + .../eehouse/android/xw4/BoardActivity.java | 68 ++++++++++++------- .../src/org/eehouse/android/xw4/Utils.java | 6 ++ 3 files changed, 52 insertions(+), 23 deletions(-) diff --git a/xwords4/android/XWords4/res/values/strings.xml b/xwords4/android/XWords4/res/values/strings.xml index 41d4304fb..5fc7b8d93 100644 --- a/xwords4/android/XWords4/res/values/strings.xml +++ b/xwords4/android/XWords4/res/values/strings.xml @@ -1766,6 +1766,7 @@ Look up words + Look up %s Tap to look up Done diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java index 76b4a45cd..e94251b13 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java @@ -148,6 +148,7 @@ public class BoardActivity extends XWActivity private String m_room; private String m_toastStr; private String[] m_words; + private String[] m_wordsWaiting; private String m_word; private String[] m_langCodes; private String[] m_lookupUrls; @@ -239,6 +240,8 @@ public class BoardActivity extends XWActivity public void onClick( DialogInterface dialog, int whichButton ) { m_resultCode = 1; + m_words = null; // in case it's DLG_SCORES_BLK + m_wordsWaiting = null; } }; ab.setPositiveButton( QUERY_REQUEST_BLK == id ? @@ -253,13 +256,24 @@ public class BoardActivity extends XWActivity }; ab.setNegativeButton( R.string.button_no, lstnr ); } else if ( DLG_SCORES_BLK == id ) { - lstnr = new DialogInterface.OnClickListener() { - public void onClick( DialogInterface dialog, - int whichButton ) { - m_jniThread.handle( JNICmd.CMD_WORDS, 1 ); - } - }; - ab.setNegativeButton( R.string.button_lookup, lstnr ); + m_words = m_wordsWaiting; + if ( null != m_words && m_words.length > 0 ) { + String buttonTxt; + if ( m_words.length == 1 ) { + buttonTxt = Utils.format( this, + R.string.button_lookupf, + m_words[0] ); + } else { + buttonTxt = getString( R.string.button_lookup ); + } + lstnr = new DialogInterface.OnClickListener() { + public void onClick( DialogInterface dialog, + int whichButton ) { + lookupWord(); + } + }; + ab.setNegativeButton( buttonTxt, lstnr ); + } } dialog = ab.create(); @@ -478,7 +492,7 @@ public class BoardActivity extends XWActivity outState.putString( DLG_BYTES, m_dlgBytes ); outState.putString( ROOM, m_room ); outState.putString( TOASTSTR, m_toastStr ); - outState.putStringArray( WORDS, m_words ); + outState.putStringArray( WORDS, m_wordsWaiting ); outState.putString( LOOKUPITEM, m_word ); } @@ -490,7 +504,7 @@ public class BoardActivity extends XWActivity m_dlgBytes = bundle.getString( DLG_BYTES ); m_room = bundle.getString( ROOM ); m_toastStr = bundle.getString( TOASTSTR ); - m_words = bundle.getStringArray( WORDS ); + m_wordsWaiting = bundle.getStringArray( WORDS ); m_word = bundle.getString( LOOKUPITEM ); } } @@ -1213,6 +1227,8 @@ public class BoardActivity extends XWActivity { m_dlgBytes = expl; m_dlgTitle = R.string.info_title; + m_wordsWaiting = wordsToMWords( words ); + Assert.assertTrue( wordCount == m_wordsWaiting.length ); waitBlockingDialog( DLG_SCORES_BLK, 0 ); } @@ -1337,17 +1353,7 @@ public class BoardActivity extends XWActivity } break; case JNIThread.GOT_WORDS: - String[] tmp = - TextUtils.split( (String)msg.obj, "\n" ); - m_words = new String[tmp.length]; - for ( int ii = 0, jj = tmp.length; - ii < tmp.length; ++ii, --jj ) { - m_words[ii] = tmp[jj-1]; - } - if ( 1 == m_words.length ) { - m_word = m_words[0]; - } - initLookup(); + m_words = wordsToMWords( (String)msg.obj ); lookupWord(); break; } @@ -1624,6 +1630,7 @@ public class BoardActivity extends XWActivity private void lookupWord() { + initLookup(); if ( null == m_words || 0 == m_words.length ) { // drop it } else if ( null != m_word ) { @@ -1660,7 +1667,7 @@ public class BoardActivity extends XWActivity Utils.logf( "%s", anfe.toString() ); } } - } + } // lookupWord private void initLookup() { @@ -1683,17 +1690,32 @@ public class BoardActivity extends XWActivity m_lookupNames = tmpNames.toArray( new String[tmpNames.size()] ); m_lookupUrls = tmpUrls.toArray( new String[tmpUrls.size()] ); } - } + } // initLookup private void urlPickDone() { m_word = null; - if ( 1 >= m_words.length ) { + if ( null != m_words && 1 >= m_words.length ) { m_words = null; + m_wordsWaiting = null; } } private void wordPickDone() { m_words = null; + m_wordsWaiting = null; + } + + private String[] wordsToMWords( String words ) + { + String[] tmp = TextUtils.split( words, "\n" ); + String[] wordsArray = new String[tmp.length]; + for ( int ii = 0, jj = tmp.length; ii < tmp.length; ++ii, --jj ) { + wordsArray[ii] = tmp[jj-1]; + } + if ( 1 == wordsArray.length ) { + m_word = wordsArray[0]; + } + return wordsArray; } } // class BoardActivity diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/Utils.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/Utils.java index 08f778539..fe2b78a80 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/Utils.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/Utils.java @@ -212,4 +212,10 @@ public class Utils { return 0; } } + + public static String format( Context context, int id, Object... args ) + { + String fmt = context.getString( id ); + return String.format( fmt, args ); + } } From 5773466fb6da121461a760fe0441c9d352dd62b8 Mon Sep 17 00:00:00 2001 From: Andy2 Date: Tue, 4 Oct 2011 06:19:06 -0700 Subject: [PATCH 07/11] prevent lookup dialogs from coming up before button pressed by not assigning m_words too early. --- .../src/org/eehouse/android/xw4/BoardActivity.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java index e94251b13..dade5889d 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java @@ -256,19 +256,19 @@ public class BoardActivity extends XWActivity }; ab.setNegativeButton( R.string.button_no, lstnr ); } else if ( DLG_SCORES_BLK == id ) { - m_words = m_wordsWaiting; - if ( null != m_words && m_words.length > 0 ) { + if ( null != m_wordsWaiting && m_wordsWaiting.length > 0 ) { String buttonTxt; - if ( m_words.length == 1 ) { + if ( m_wordsWaiting.length == 1 ) { buttonTxt = Utils.format( this, R.string.button_lookupf, - m_words[0] ); + m_wordsWaiting[0] ); } else { buttonTxt = getString( R.string.button_lookup ); } lstnr = new DialogInterface.OnClickListener() { public void onClick( DialogInterface dialog, int whichButton ) { + m_words = m_wordsWaiting; lookupWord(); } }; @@ -1228,6 +1228,7 @@ public class BoardActivity extends XWActivity m_dlgBytes = expl; m_dlgTitle = R.string.info_title; m_wordsWaiting = wordsToMWords( words ); + Assert.assertNull( m_words ); Assert.assertTrue( wordCount == m_wordsWaiting.length ); waitBlockingDialog( DLG_SCORES_BLK, 0 ); } From 3cf1d07df35740c5cd95fd8ce868d6838bebe6c4 Mon Sep 17 00:00:00 2001 From: Andy2 Date: Tue, 4 Oct 2011 06:21:02 -0700 Subject: [PATCH 08/11] optimization: set up word-tracking invariants on init rather than each time used --- xwords4/common/model.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/xwords4/common/model.c b/xwords4/common/model.c index f0b280320..1309b56da 100644 --- a/xwords4/common/model.c +++ b/xwords4/common/model.c @@ -75,7 +75,7 @@ static void loadPlayerCtxt( XWStreamCtxt* stream, XP_U16 version, PlayerCtxt* pc ); static void writePlayerCtxt( XWStreamCtxt* stream, PlayerCtxt* pc ); static XP_U16 model_getRecentPassCount( ModelCtxt* model ); - +static XP_Bool recordWord( const XP_UCHAR* word, XP_Bool isLegal, void* clsur ); /***************************************************************************** * @@ -91,6 +91,8 @@ model_make( MPFORMAL DictionaryCtxt* dict, MPASSIGN(result->vol.mpool, mpool); result->vol.util = util; + result->vol.wni.proc = recordWord; + result->vol.wni.closure = &result->vol.rwi; model_init( result, nCols, nRows ); @@ -216,7 +218,7 @@ model_writeToTextStream( const ModelCtxt* model, XWStreamCtxt* stream ) void model_init( ModelCtxt* model, XP_U16 nCols, XP_U16 nRows ) { - ModelVolatiles vol = model->vol; + ModelVolatiles vol = model->vol; /* save vol so we don't wipe it out */ XP_ASSERT( model != NULL ); XP_MEMSET( model, 0, sizeof( *model ) ); @@ -2053,8 +2055,8 @@ recordWord( const XP_UCHAR* word, XP_Bool isLegal, void* closure ) WordNotifierInfo* model_initWordCounter( ModelCtxt* model, XWStreamCtxt* stream, XP_U16* nWords ) { - model->vol.wni.proc = recordWord; - model->vol.wni.closure = &model->vol.rwi; + XP_ASSERT( model->vol.wni.proc == recordWord ); + XP_ASSERT( model->vol.wni.closure == &model->vol.rwi ); model->vol.rwi.stream = stream; model->vol.rwi.nWordsP = nWords; model->vol.rwi.nWords = 0; From c04f981442ec4df068f36e84fd70cabe2fbfbb2d Mon Sep 17 00:00:00 2001 From: Andy2 Date: Tue, 4 Oct 2011 06:44:29 -0700 Subject: [PATCH 09/11] fix new word-list reporting to work for networked games too: create and save a second stream parallel to the existing one reporting the move scoring. Requires bump in stream version. --- xwords4/common/game.h | 3 +- xwords4/common/server.c | 67 +++++++++++++++++++++++++++-------------- 2 files changed, 47 insertions(+), 23 deletions(-) diff --git a/xwords4/common/game.h b/xwords4/common/game.h index 927d2fa17..1d967ec3b 100644 --- a/xwords4/common/game.h +++ b/xwords4/common/game.h @@ -31,6 +31,7 @@ extern "C" { #endif +#define STREAM_SAVE_PREVWORDS 0x11 #define STREAM_VERS_SERVER_SAVES_TOSHOW 0x10 #define STREAM_VERS_PLAYERDICTS 0x0F #define STREAM_SAVE_PREVMOVE 0x0E /* server saves prev move explanation */ @@ -52,7 +53,7 @@ extern "C" { #define STREAM_VERS_41B4 0x02 #define STREAM_VERS_405 0x01 -#define CUR_STREAM_VERS STREAM_VERS_SERVER_SAVES_TOSHOW +#define CUR_STREAM_VERS STREAM_SAVE_PREVWORDS typedef struct LocalPlayer { XP_UCHAR* name; diff --git a/xwords4/common/server.c b/xwords4/common/server.c index dba489b25..e4a1e0c5f 100644 --- a/xwords4/common/server.c +++ b/xwords4/common/server.c @@ -307,6 +307,26 @@ putNV( XWStreamCtxt* stream, ServerNonvolatiles* nv, XP_U16 nPlayers ) } } /* putNV */ +static XWStreamCtxt* +readStreamIf( ServerCtxt* server, XWStreamCtxt* in ) +{ + XWStreamCtxt* result = NULL; + XP_U16 len = stream_getU16( in ); + if ( 0 < len ) { + result = mkServerStream( server ); + stream_copyFromStream( in, result, len ); + } + return result; +} + +static void +writeStreamIf( XWStreamCtxt* dest, XWStreamCtxt* src ) +{ + XP_U16 len = !!src ? stream_getSize( src ) : 0; + stream_putU16( dest, len ); + stream_copyFromStream( dest, src, len ); +} + ServerCtxt* server_makeFromStream( MPFORMAL XWStreamCtxt* stream, ModelCtxt* model, CommsCtxt* comms, XW_UtilCtxt* util, XP_U16 nPlayers ) @@ -342,15 +362,11 @@ server_makeFromStream( MPFORMAL XWStreamCtxt* stream, ModelCtxt* model, } if ( version >= STREAM_SAVE_PREVMOVE ) { - XP_U16 nBytes = stream_getU16( stream ); - if ( nBytes > 0 ) { - XP_ASSERT( !server->nv.prevMoveStream ); - server->nv.prevMoveStream = mkServerStream( server ); - stream_copyFromStream( server->nv.prevMoveStream, - stream, nBytes ); - } + server->nv.prevMoveStream = readStreamIf( server, stream ); + } + if ( version >= STREAM_SAVE_PREVWORDS ) { + server->nv.prevWordsStream = readStreamIf( server, stream ); } - XP_ASSERT( stream_getU32( stream ) == sEND ); return server; @@ -361,7 +377,6 @@ server_writeToStream( ServerCtxt* server, XWStreamCtxt* stream ) { XP_U16 i; XP_U16 nPlayers = server->vol.gi->nPlayers; - XP_U16 nBytes; putNV( stream, &server->nv, nPlayers ); @@ -387,12 +402,8 @@ server_writeToStream( ServerCtxt* server, XWStreamCtxt* stream ) stream_putBits( stream, 2, 0 ); #endif - nBytes = !!server->nv.prevMoveStream ? - stream_getSize( server->nv.prevMoveStream ) : 0; - stream_putU16( stream, nBytes ); - if ( nBytes > 0 ) { - stream_copyFromStream( stream, server->nv.prevMoveStream, nBytes ); - } + writeStreamIf( stream, server->nv.prevMoveStream ); + writeStreamIf( stream, server->nv.prevWordsStream ); #ifdef DEBUG stream_putU32( stream, sEND ); @@ -420,6 +431,9 @@ cleanupServer( ServerCtxt* server ) if ( !!server->nv.prevMoveStream ) { stream_destroy( server->nv.prevMoveStream ); } + if ( !!server->nv.prevWordsStream ) { + stream_destroy( server->nv.prevWordsStream ); + } XP_MEMSET( &server->nv, 0, sizeof(server->nv) ); } /* cleanupServer */ @@ -860,6 +874,7 @@ showPrevScore( ServerCtxt* server ) server->nv.prevWordCount ); stream_destroy( stream ); stream_destroy( server->nv.prevWordsStream ); + server->nv.prevWordsStream = NULL; } SETSTATE( server, server->nv.stateAfterShow ); } /* showPrevScore */ @@ -1857,14 +1872,17 @@ makeTradeReportIf( ServerCtxt* server, const TrayTileSet* tradedTiles ) } /* makeTradeReportIf */ static XWStreamCtxt* -makeMoveReportIf( ServerCtxt* server ) +makeMoveReportIf( ServerCtxt* server, XWStreamCtxt** wordsStream ) { XWStreamCtxt* stream = NULL; if ( server->nv.showRobotScores ) { + ModelCtxt* model = server->vol.model; stream = mkServerStream( server ); - (void)model_checkMoveLegal( server->vol.model, - server->nv.currentTurn, stream, - NULL ); + *wordsStream = mkServerStream( server ); + WordNotifierInfo* ni = + model_initWordCounter( model, *wordsStream, + &server->nv.prevWordCount ); + (void)model_checkMoveLegal( model, server->nv.currentTurn, stream, ni ); } return stream; } /* makeMoveReportIf */ @@ -1889,6 +1907,7 @@ reflectMoveAndInform( ServerCtxt* server, XWStreamCtxt* stream ) XP_U16 sourceClientIndex = getIndexForDevice( server, stream_getAddress( stream ) ); XWStreamCtxt* mvStream = NULL; + XWStreamCtxt* wordsStream = NULL; XP_ASSERT( gi->serverRole == SERVER_ISSERVER ); @@ -1921,7 +1940,7 @@ reflectMoveAndInform( ServerCtxt* server, XWStreamCtxt* stream ) (TrayTileSet*)NULL, sourceClientIndex ); server->vol.showPrevMove = XP_TRUE; - mvStream = makeMoveReportIf( server ); + mvStream = makeMoveReportIf( server, &wordsStream ); model_commitTurn( model, whoMoved, &newTiles ); resetEngines( server ); @@ -1944,8 +1963,9 @@ reflectMoveAndInform( ServerCtxt* server, XWStreamCtxt* stream ) if ( !!mvStream ) { XP_ASSERT( !server->nv.prevMoveStream ); server->nv.prevMoveStream = mvStream; + XP_ASSERT( !server->nv.prevWordsStream ); + server->nv.prevWordsStream = wordsStream; } - } else { /* The client from which the move came still needs to be told. But we can't send a message now since we're burried in a message handler. @@ -1974,6 +1994,7 @@ reflectMove( ServerCtxt* server, XWStreamCtxt* stream ) TrayTileSet tradedTiles; ModelCtxt* model = server->vol.model; XWStreamCtxt* mvStream = NULL; + XWStreamCtxt* wordsStream = NULL; moveOk = XWSTATE_INTURN == server->nv.gameState; XP_ASSERT( moveOk ); /* message permanently lost if dropped here! */ @@ -1989,13 +2010,15 @@ reflectMove( ServerCtxt* server, XWStreamCtxt* stream ) mvStream = makeTradeReportIf( server, &tradedTiles ); } else { server->vol.showPrevMove = XP_TRUE; - mvStream = makeMoveReportIf( server ); + mvStream = makeMoveReportIf( server, &wordsStream ); model_commitTurn( model, whoMoved, &newTiles ); } if ( !!mvStream ) { XP_ASSERT( !server->nv.prevMoveStream ); server->nv.prevMoveStream = mvStream; + XP_ASSERT( !server->nv.prevWordsStream ); + server->nv.prevWordsStream = wordsStream; } resetEngines( server ); From 5dd21a16ea70b35842a46bf9645ffa71ad006812 Mon Sep 17 00:00:00 2001 From: Andy2 Date: Tue, 4 Oct 2011 06:45:16 -0700 Subject: [PATCH 10/11] don't crash if words stream is null, as it will be when turn's a pass. --- xwords4/android/XWords4/jni/utilwrapper.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/xwords4/android/XWords4/jni/utilwrapper.c b/xwords4/android/XWords4/jni/utilwrapper.c index 047f71928..25eb52509 100644 --- a/xwords4/android/XWords4/jni/utilwrapper.c +++ b/xwords4/android/XWords4/jni/utilwrapper.c @@ -221,10 +221,15 @@ and_util_informMove( XW_UtilCtxt* uc, XWStreamCtxt* expl, { UTIL_CBK_HEADER( "informMove", "(Ljava/lang/String;Ljava/lang/String;I)V" ); jstring jexpl = streamToJString( MPPARM(util->util.mpool) env, expl ); - jstring jwords = streamToJString( MPPARM(util->util.mpool) env, words ); + jstring jwords = !!words ? + streamToJString( MPPARM(util->util.mpool) env, words ) : NULL; (*env)->CallVoidMethod( env, util->jutil, mid, jexpl, jwords, wordCount ); (*env)->DeleteLocalRef( env, jexpl ); - (*env)->DeleteLocalRef( env, jwords ); + if ( !!jwords ) { + (*env)->DeleteLocalRef( env, jwords ); + } else { + XP_ASSERT( 0 == wordCount ); + } UTIL_CBK_TAIL(); } From f4b8b2806ec289011902b2c8fc6899e260be17ae Mon Sep 17 00:00:00 2001 From: Andy2 Date: Tue, 4 Oct 2011 06:48:53 -0700 Subject: [PATCH 11/11] remove unused parameter --- xwords4/android/XWords4/jni/utilwrapper.c | 4 ++-- .../XWords4/src/org/eehouse/android/xw4/BoardActivity.java | 3 +-- .../XWords4/src/org/eehouse/android/xw4/jni/UtilCtxt.java | 2 +- .../XWords4/src/org/eehouse/android/xw4/jni/UtilCtxtImpl.java | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/xwords4/android/XWords4/jni/utilwrapper.c b/xwords4/android/XWords4/jni/utilwrapper.c index 25eb52509..1b7adefd1 100644 --- a/xwords4/android/XWords4/jni/utilwrapper.c +++ b/xwords4/android/XWords4/jni/utilwrapper.c @@ -219,11 +219,11 @@ static void and_util_informMove( XW_UtilCtxt* uc, XWStreamCtxt* expl, XWStreamCtxt* words, XP_U16 wordCount ) { - UTIL_CBK_HEADER( "informMove", "(Ljava/lang/String;Ljava/lang/String;I)V" ); + UTIL_CBK_HEADER( "informMove", "(Ljava/lang/String;Ljava/lang/String;)V" ); jstring jexpl = streamToJString( MPPARM(util->util.mpool) env, expl ); jstring jwords = !!words ? streamToJString( MPPARM(util->util.mpool) env, words ) : NULL; - (*env)->CallVoidMethod( env, util->jutil, mid, jexpl, jwords, wordCount ); + (*env)->CallVoidMethod( env, util->jutil, mid, jexpl, jwords ); (*env)->DeleteLocalRef( env, jexpl ); if ( !!jwords ) { (*env)->DeleteLocalRef( env, jwords ); diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java index dade5889d..b60865d05 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java @@ -1223,13 +1223,12 @@ public class BoardActivity extends XWActivity } } // userError - public void informMove( String expl, String words, int wordCount ) + public void informMove( String expl, String words ) { m_dlgBytes = expl; m_dlgTitle = R.string.info_title; m_wordsWaiting = wordsToMWords( words ); Assert.assertNull( m_words ); - Assert.assertTrue( wordCount == m_wordsWaiting.length ); waitBlockingDialog( DLG_SCORES_BLK, 0 ); } diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/UtilCtxt.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/UtilCtxt.java index 630622c30..72efae8c5 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/UtilCtxt.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/UtilCtxt.java @@ -100,7 +100,7 @@ public interface UtilCtxt { static final int ERR_RELAY_BASE = 16; void userError( int id ); - void informMove( String expl, String words, int wordCount ); + void informMove( String expl, String words ); void notifyGameOver(); // Don't need this unless we have a scroll thumb to indicate position diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/UtilCtxtImpl.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/UtilCtxtImpl.java index ad950d522..5e2aeb418 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/UtilCtxtImpl.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/UtilCtxtImpl.java @@ -185,7 +185,7 @@ public class UtilCtxtImpl implements UtilCtxt { subclassOverride( "userError" ); } - public void informMove( String expl, String words, int wordCount ) + public void informMove( String expl, String words ) { subclassOverride( "informMove" ); }