Merge branch 'android_branch' into android_translate

This commit is contained in:
Eric House 2019-12-30 22:40:38 -08:00
commit ef9a148eb4
64 changed files with 1946 additions and 729 deletions

View file

@ -1,9 +1,13 @@
def INITIAL_CLIENT_VERS = 9
def VERSION_CODE_BASE = 146
def VERSION_NAME = '4.4.150'
def VERSION_CODE_BASE = 148
def VERSION_NAME = '4.4.152'
def FABRIC_API_KEY = System.getenv("FABRIC_API_KEY")
def BUILD_INFO_NAME = "build-info.txt"
// AID must start with F (first 4 bits) and be from 5 to 16 bytes long
def NFC_AID_XW4 = "FC8FF510B360"
def NFC_AID_XW4d = "FDDA0A3EB5E5"
boolean forFDroid = hasProperty('forFDroid')
// Get the git revision we're using. Since fdroid modifies files as
@ -35,6 +39,7 @@ android {
// default changes and .travis.yml can be kept in sync
buildToolsVersion '27.0.3'
defaultConfig {
// HostApduService requires 19. But is it a problem?
minSdkVersion 14
targetSdkVersion 28 // must match ../build.gradle
versionCode VERSION_CODE_BASE
@ -88,6 +93,8 @@ android {
buildConfigField "boolean", "RELAYINVITE_SUPPORTED", "false"
buildConfigField "String", "VARIANT_NAME", "\"Google Play Store\""
buildConfigField "int", "VARIANT_CODE", "1"
buildConfigField "String", "NFC_AID", "\"${NFC_AID_XW4}\""
resValue "string", "nfc_aid", "$NFC_AID_XW4"
}
xw4fdroid {
@ -101,10 +108,12 @@ android {
buildConfigField "String", "VARIANT_NAME", "\"F-Droid\""
buildConfigField "int", "VARIANT_CODE", "2"
buildConfigField "boolean", "FOR_FDROID", "true"
buildConfigField "String", "NFC_AID", "\"${NFC_AID_XW4}\""
resValue "string", "nfc_aid", "$NFC_AID_XW4"
}
xw4d {
dimension "variant"
buildConfigField "String", "DB_NAME", "\"xwddb\"";
buildConfigField "String", "DB_NAME", "\"xwddb\""
applicationId "org.eehouse.android.xw4dbg"
manifestPlaceholders = [ FABRIC_API_KEY: "$FABRIC_API_KEY", APP_ID: applicationId, ]
resValue "string", "app_name", "CrossDbg"
@ -115,11 +124,13 @@ android {
buildConfigField "int", "VARIANT_CODE", "3"
buildConfigField "boolean", "REPORT_LOCKS", "true"
buildConfigField "boolean", "MOVE_VIA_NFC", "true"
buildConfigField "String", "NFC_AID", "\"${NFC_AID_XW4d}\""
resValue "string", "nfc_aid", "$NFC_AID_XW4d"
}
xw4dNoSMS {
dimension "variant"
buildConfigField "String", "DB_NAME", "\"xwddb\"";
buildConfigField "String", "DB_NAME", "\"xwddb\""
applicationId "org.eehouse.android.xw4dbg"
manifestPlaceholders = [ FABRIC_API_KEY: "$FABRIC_API_KEY", APP_ID: applicationId, ]
resValue "string", "app_name", "CrossDbg"
@ -130,6 +141,8 @@ android {
buildConfigField "int", "VARIANT_CODE", "4"
buildConfigField "boolean", "REPORT_LOCKS", "true"
buildConfigField "boolean", "MOVE_VIA_NFC", "true"
buildConfigField "String", "NFC_AID", "\"${NFC_AID_XW4d}\""
resValue "string", "nfc_aid", "$NFC_AID_XW4d"
}
xw4SMS {
@ -142,6 +155,8 @@ android {
buildConfigField "boolean", "RELAYINVITE_SUPPORTED", "false"
buildConfigField "String", "VARIANT_NAME", "\"FOSS\""
buildConfigField "int", "VARIANT_CODE", "5"
buildConfigField "String", "NFC_AID", "\"${NFC_AID_XW4}\""
resValue "string", "nfc_aid", "$NFC_AID_XW4"
}
// WARNING: "all" breaks things. Seems to be a keyword. Need
@ -390,8 +405,8 @@ task makeBuildAssets() {
out += "date: ${date}\n"
// I want the variant, but that's harder. Here's a quick hack from SO.
String target = gradle.startParameter.taskNames[-1]
out += "target: ${target}\n"
// String target = gradle.startParameter.taskNames[0]
// out += "target: ${target}\n"
String diff = "git diff".execute().text.trim()
if (diff) {

View file

@ -32,10 +32,10 @@
<uses-feature android:name="android.hardware.telephony"
android:required = "false"
/>
<uses-feature android:name="android.hardware.nfc" android:required="false" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc.hce" android:required="false" />
<application android:icon="@drawable/icon48x48"
android:label="@string/app_name"
@ -62,12 +62,6 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="@string/xwords_nfc_mime" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
@ -213,5 +207,14 @@
</intent-filter>
</service>
<service android:name="NFCCardService" android:exported="true"
android:permission="android.permission.BIND_NFC_SERVICE">
<intent-filter>
<action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/>
</intent-filter>
<meta-data android:name="android.nfc.cardemulation.host_apdu_service"
android:resource="@xml/apduservice"/>
</service>
</application>
</manifest>

View file

@ -13,11 +13,9 @@
</style>
</head>
<body>
<h2>CrossWords 4.4.150 release</h2>
<h2>CrossWords 4.4.152 release</h2>
<p>This release speeds move delivery for newly-installed games and
hides invite-via-NFC on Android 10 (since it doesn't work
there).</p>
<p>This release fixes a nasty crash in some non-English versions.</p>
<div id="survey">
<p>Please <a href="https://www.surveymonkey.com/s/GX3XLHR">take
@ -25,13 +23,17 @@
CrossWords.</p>
</div>
<h3>New with this release</h3>
<h3>New with this (and previous) release</h3>
<ul>
<li>Improve message delivery for new installs</li>
<li>Don't offer NFC on Android 10, where it's broken</li>
<li>Improve board layout on taller, narrower screens</li>
<li>Fix occasional stall sending chat messages</li>
<li>Fix another (very rare!) type of stall</li>
<li>Fix crash with some localized versions (Weblate problem...)</li>
<li>Tweak network traffic arrows on game board</li>
<li>Fix crash dragging tiles</li>
<li>Fix invite-via-NFC for Android 10 (and improve for earlier
Android versions)</li>
<li>Add ability to send moves via NFC</li>
<li>More translations (via Weblate) in Catalan, French, German,
Japanese, Norwegian, Polish, and Spanish</li>
<li>Fix a couple of other crashes reported via Google (thanks!)</li>
</ul>
<p>(The full changelog
@ -39,7 +41,7 @@
<h3>Next up</h3>
<ul>
<li>Look for a workaround to allow NFC on Android 10</li>
<li>Improve move-via-NFC</li>
<li>Support duplicate-style play (popular in France)</li>
<li>Improve play-by-data-sms workaround
using <a href="https://github.com/eehouse/nbsproxy">NBSProxy</a></li>

View file

@ -689,7 +689,7 @@ public class BTService extends XWJIService {
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if ( null != adapter ) {
for ( BluetoothDevice dev : adapter.getBondedDevices() ) {
Log.d( TAG, "%s => %s", dev.getName(), dev.getAddress() );
// Log.d( TAG, "%s => %s", dev.getName(), dev.getAddress() );
if ( btName.equals( dev.getName() ) ) {
btAddr = dev.getAddress();
s_namesToAddrs.put( btName, btAddr );
@ -771,14 +771,14 @@ public class BTService extends XWJIService {
{
Context context = XWApp.getContext();
ConnStatusHandler
.updateStatusOut( context, null, CommsConnType.COMMS_CONN_BT, success );
.updateStatusOut( context, CommsConnType.COMMS_CONN_BT, success );
}
private static void updateStatusIn( boolean success )
{
Context context = XWApp.getContext();
ConnStatusHandler
.updateStatusIn( context, null, CommsConnType.COMMS_CONN_BT, success );
.updateStatusIn( context, CommsConnType.COMMS_CONN_BT, success );
}
private static class KillerIn extends Thread implements AutoCloseable {

View file

@ -72,12 +72,13 @@ import org.eehouse.android.xw4.jni.XwJNI.GamePtr;
import org.eehouse.android.xw4.jni.XwJNI;
import org.eehouse.android.xw4.loc.LocUtils;
import org.eehouse.android.xw4.TilePickAlert.TilePickState;
import org.eehouse.android.xw4.NFCUtils.Wrapper;
public class BoardDelegate extends DelegateBase
implements TransportProcs.TPMsgHandler, View.OnClickListener,
DwnldDelegate.DownloadFinishedListener,
ConnStatusHandler.ConnStatusCBacks,
NFCUtils.NFCActor {
Wrapper.Procs {
private static final String TAG = BoardDelegate.class.getSimpleName();
private static final int SCREEN_ON_TIME = 10 * 60 * 1000; // 10 mins
@ -126,6 +127,8 @@ public class BoardDelegate extends DelegateBase
private DBAlert m_inviteAlert;
private boolean m_haveStartedShowing;
private Wrapper mNFCWrapper;
public class TimerRunnable implements Runnable {
private int m_why;
private int m_when;
@ -170,7 +173,7 @@ public class BoardDelegate extends DelegateBase
private boolean alertOrderAt( StartAlertOrder ord )
{
boolean result = m_mySIS.mAlertOrder == ord;
Log.d( TAG, "alertOrderAt(%s) => %b", ord, result );
// Log.d( TAG, "alertOrderAt(%s) => %b", ord, result );
return result;
}
@ -558,6 +561,9 @@ public class BoardDelegate extends DelegateBase
m_isFirstLaunch = null == savedInstanceState;
getBundledData( savedInstanceState );
int devID = DevID.getNFCDevID( m_activity );
mNFCWrapper = Wrapper.init( m_activity, this, devID );
m_utils = new BoardUtilCtxt();
m_timers = new TimerRunnable[4]; // needs to be in sync with
// XWTimerReason
@ -601,9 +607,6 @@ public class BoardDelegate extends DelegateBase
m_jniThreadRef.setDaemonOnce( true );
m_jniThreadRef.startOnce();
// Don't seem to need to unregister...
NFCUtils.register( m_activity, BoardDelegate.this );
setBackgroundColor();
setKeepScreenOn();
@ -633,6 +636,7 @@ public class BoardDelegate extends DelegateBase
protected void onResume()
{
super.onResume();
Wrapper.setResumed( mNFCWrapper, true );
if ( null != m_jniThreadRef ) {
doResume( false );
} else {
@ -642,6 +646,7 @@ public class BoardDelegate extends DelegateBase
protected void onPause()
{
Wrapper.setResumed( mNFCWrapper, false );
closeIfFinishing( false );
m_handler = null;
ConnStatusHandler.setHandler( null );
@ -1097,9 +1102,6 @@ public class BoardDelegate extends DelegateBase
case LOOKUP_ACTION:
launchLookup( m_mySIS.words, m_gi.dictLang );
break;
case NFC_TO_SELF:
GamesListDelegate.sendNFCToSelf( m_activity, makeNFCMessage() );
break;
case DROP_RELAY_ACTION:
dropConViaAndRestart(CommsConnType.COMMS_CONN_RELAY);
break;
@ -1273,10 +1275,7 @@ public class BoardDelegate extends DelegateBase
? (SentInvitesInfo)params[0] : null;
switch( means ) {
case NFC:
if ( XWPrefs.getNFCToSelfEnabled( m_activity ) ) {
makeConfirmThenBuilder( R.string.nfc_to_self, Action.NFC_TO_SELF )
.show();
} else if ( ! NFCUtils.nfcAvail( m_activity )[1] ) {
if ( ! NFCUtils.nfcAvail( m_activity )[1] ) {
showDialogFragment( DlgID.ENABLE_NFC );
} else {
makeOkOnlyBuilder( R.string.nfc_just_tap ).show();
@ -1515,22 +1514,49 @@ public class BoardDelegate extends DelegateBase
}
//////////////////////////////////////////////////
// NFCUtils.NFCActor
// ConnStatusHandler.ConnStatusCBacks
//////////////////////////////////////////////////
@Override
public String makeNFCMessage()
public void invalidateParent()
{
Log.d( TAG, "makeNFCMessage(): m_mySIS.nMissing: %d", m_mySIS.nMissing );
String data = null;
runOnUiThread(new Runnable() {
@Override
public void run() {
m_view.invalidate();
}
});
}
@Override
public void onStatusClicked()
{
onStatusClicked( m_jniGamePtr );
}
@Override
public Handler getHandler()
{
return m_handler;
}
////////////////////////////////////////////////////////////
// NFCCardService.Wrapper.Procs
////////////////////////////////////////////////////////////
@Override
public void onReadingChange( boolean nowReading )
{
// Do we need this?
}
private byte[] getInvite()
{
byte[] result = null;
if ( 0 < m_mySIS.nMissing // Isn't there a better test??
&& DeviceRole.SERVER_ISSERVER == m_gi.serverRole ) {
Log.d( TAG, "makeNFCMessage(): invite case" );
NetLaunchInfo nli = new NetLaunchInfo( m_gi );
Assert.assertTrue( 0 <= m_nGuestDevs );
nli.forceChannel = 1 + m_nGuestDevs;
Assert.assertTrue( m_connTypes.contains( CommsConnType.COMMS_CONN_NFC ) );
for ( Iterator<CommsConnType> iter = m_connTypes.iterator();
iter.hasNext(); ) {
CommsConnType typ = iter.next();
@ -1558,46 +1584,9 @@ public class BoardDelegate extends DelegateBase
typ.toString() );
}
}
data = nli.makeLaunchJSON();
if ( null != data ) {
recordInviteSent( InviteMeans.NFC, null );
result = nli.asByteArray();
}
} else if ( BuildConfig.MOVE_VIA_NFC ) {
Log.d( TAG, "makeNFCMessage(): move case" );
byte[][] msgs = XwJNI.comms_getPending( m_jniGamePtr );
data = NFCUtils.makeMsgsJSON( m_gi.gameID, msgs );
} else {
Log.d( TAG, "makeNFCMessage(): other (bad!!) case" );
Assert.assertFalse( BuildConfig.DEBUG );
}
Log.d( TAG, "makeNFCMessage() => %s", data );
return data;
}
//////////////////////////////////////////////////
// ConnStatusHandler.ConnStatusCBacks
//////////////////////////////////////////////////
@Override
public void invalidateParent()
{
runOnUiThread(new Runnable() {
@Override
public void run() {
m_view.invalidate();
}
});
}
@Override
public void onStatusClicked()
{
onStatusClicked( m_jniGamePtr );
}
@Override
public Handler getHandler()
{
return m_handler;
return result;
}
private void launchPhoneNumberInvite( int nMissing, SentInvitesInfo info,
@ -2269,8 +2258,15 @@ public class BoardDelegate extends DelegateBase
if ( null == m_jniThread ) {
m_jniThread = m_jniThreadRef.retain();
m_gi = m_jniThread.getGI();
m_summary = m_jniThread.getSummary();
Wrapper.setGameID( mNFCWrapper, m_gi.gameID );
byte[] invite = getInvite();
if ( null != invite ) {
NFCUtils.addInvitationFor( invite, m_gi.gameID );
}
m_view.startHandling( m_activity, m_jniThread, m_connTypes );
handleViaThread( JNICmd.CMD_START );

View file

@ -181,7 +181,7 @@ public class CommsTransport implements TransportProcs,
addIncoming();
}
ConnStatusHandler.
updateStatusIn( m_context, null,
updateStatusIn( m_context,
CommsConnType.COMMS_CONN_RELAY,
0 <= nRead );
}
@ -190,7 +190,7 @@ public class CommsTransport implements TransportProcs,
if ( null != m_bytesOut ) {
int nWritten = channel.write( m_bytesOut );
ConnStatusHandler.
updateStatusOut( m_context, null,
updateStatusOut( m_context,
CommsConnType.COMMS_CONN_RELAY,
0 < nWritten );
}
@ -444,6 +444,7 @@ public class CommsTransport implements TransportProcs,
.sendPacket( context, addr.p2p_addr, gameID, buf );
break;
case COMMS_CONN_NFC:
nSent = NFCUtils.addMsgFor( buf, gameID );
break;
default:
Assert.fail();

View file

@ -30,6 +30,7 @@ import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.provider.Settings;
import android.text.format.DateUtils;
import android.graphics.PorterDuff.Mode;
import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType;
import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnTypeSet;
@ -47,6 +48,7 @@ public class ConnStatusHandler {
private static final String TAG = ConnStatusHandler.class.getSimpleName();
private static final String RECS_KEY = TAG + "/recs";
private static final String STALL_STATS_KEY = TAG + "/stall_stats";
private static final int ORANGE = 0XFFFFA500;
public interface ConnStatusCBacks {
public void invalidateParent();
@ -178,10 +180,6 @@ public class ConnStatusHandler {
R.string.connstat_net_fmt,
connTypes.toString( context, true )));
for ( CommsConnType typ : connTypes.getTypes() ) {
if ( ! typ.isSelectable() ) {
continue;
}
sb.append( String.format( "\n\n*** %s ", typ.longName( context ) ) );
String did = addDebugInfo( context, gamePtr, addr, typ );
if ( null != did ) {
@ -363,12 +361,23 @@ public class ConnStatusHandler {
updateStatusImpl( context, cbacks, connType, success, true );
}
public static void updateStatusIn( Context context, CommsConnType connType,
boolean success )
{
updateStatusImpl( context, null, connType, success, true );
}
public static void updateStatusOut( Context context, ConnStatusCBacks cbacks,
CommsConnType connType, boolean success )
{
updateStatusImpl( context, cbacks, connType, success, false );
}
public static void updateStatusOut( Context context, CommsConnType connType, boolean success )
{
updateStatusImpl( context, null, connType, success, false );
}
private static void updateStatusImpl( Context context, ConnStatusCBacks cbacks,
CommsConnType connType, boolean success,
boolean isIn )
@ -457,7 +466,7 @@ public class ConnStatusHandler {
- scratchR.height()) );
drawIn( canvas, res, R.drawable.multigame__gen, scratchR );
if ( BuildConfig.DEBUG && 0 < s_moveCount ) {
if ( 0 < s_moveCount && XWPrefs.moveCountEnabled( context ) ) {
String str = String.format( "%d", s_moveCount );
s_fillPaint.setColor( Color.BLACK );
canvas.drawText( str, s_rect.left + (s_rect.width() / 2),
@ -480,16 +489,10 @@ public class ConnStatusHandler {
private static void drawArrow( Canvas canvas, Resources res, Rect rect,
boolean isIn )
{
int arrowID;
boolean showSuccesses = s_showSuccesses[isIn? SUCCESS_IN : SUCCESS_OUT];
if ( isIn ) {
arrowID = showSuccesses ?
R.drawable.in_arrow_active : R.drawable.in_arrow;
} else {
arrowID = showSuccesses ?
R.drawable.out_arrow_active : R.drawable.out_arrow;
}
drawIn( canvas, res, arrowID, rect );
int color = showSuccesses ? ORANGE : Color.WHITE;
int arrowID = isIn ? R.drawable.in_arrow__gen : R.drawable.out_arrow__gen;
drawIn( canvas, res, arrowID, rect, color );
}
// This gets rid of lint warning, but I don't like it as it
@ -569,9 +572,19 @@ public class ConnStatusHandler {
}
private static void drawIn( Canvas canvas, Resources res, int id, Rect rect )
{
drawIn( canvas, res, id, rect, Color.WHITE );
}
private static void drawIn( Canvas canvas, Resources res, int id, Rect rect, int color )
{
Drawable icon = res.getDrawable( id );
Assert.assertTrue( icon.getBounds().width() == icon.getBounds().height() );
if ( Color.WHITE != color ) {
icon = icon.mutate();
icon.setColorFilter( color, Mode.MULTIPLY );
}
Assert.assertTrue( icon.getBounds().width() == icon.getBounds().height()
|| !BuildConfig.DEBUG );
icon.setBounds( rect );
icon.draw( canvas );
}

View file

@ -35,17 +35,26 @@ import java.util.Arrays;
public class DBHelper extends SQLiteOpenHelper {
private static final String TAG = DBHelper.class.getSimpleName();
public static final String TABLE_NAME_SUM = "summaries";
public static final String TABLE_NAME_OBITS = "obits";
public static final String TABLE_NAME_DICTBROWSE = "dictbrowse";
public static final String TABLE_NAME_DICTINFO = "dictinfo";
public static final String TABLE_NAME_GROUPS = "groups";
public static final String TABLE_NAME_STUDYLIST = "study";
public static final String TABLE_NAME_LOC = "loc";
public static final String TABLE_NAME_PAIRS = "pairs";
public static final String TABLE_NAME_INVITES = "invites";
public static final String TABLE_NAME_CHAT = "chat";
public static final String TABLE_NAME_LOGS = "logs";
public enum TABLE_NAMES {
SUM( "summaries", 0 ),
OBITS( "obits", 5 ),
DICTBROWSE( "dictbrowse", 12 ),
DICTINFO( "dictinfo", 12 ),
GROUPS( "groups", 14 ),
STUDYLIST( "study", 18 ),
LOC( "loc", 20 ),
PAIRS( "pairs", 21 ),
INVITES( "invites", 24 ),
CHAT( "chat", 25 ),
LOGS( "logs", 26 );
private String mName;
private int mAddedVersion;
private TABLE_NAMES(String name, int start) { mName = name; mAddedVersion = start; }
@Override
public String toString() { return mName; }
private int addedVersion() { return mAddedVersion; }
}
private static final String DB_NAME = BuildConfig.DB_NAME;
private static final int DB_VERSION = 29;
@ -245,11 +254,11 @@ public class DBHelper extends SQLiteOpenHelper {
@Override
public void onCreate( SQLiteDatabase db )
{
createTable( db, TABLE_NAME_SUM, s_summaryColsAndTypes );
createTable( db, TABLE_NAME_OBITS, s_obitsColsAndTypes );
createTable( db, TABLE_NAME_DICTINFO, s_dictInfoColsAndTypes );
createTable( db, TABLE_NAME_DICTBROWSE, s_dictBrowseColsAndTypes );
forceRowidHigh( db, TABLE_NAME_SUM );
createTable( db, TABLE_NAMES.SUM, s_summaryColsAndTypes );
createTable( db, TABLE_NAMES.OBITS, s_obitsColsAndTypes );
createTable( db, TABLE_NAMES.DICTINFO, s_dictInfoColsAndTypes );
createTable( db, TABLE_NAMES.DICTBROWSE, s_dictBrowseColsAndTypes );
forceRowidHigh( db, TABLE_NAMES.SUM );
createGroupsTable( db, false );
createStudyTable( db );
createLocTable( db );
@ -269,7 +278,7 @@ public class DBHelper extends SQLiteOpenHelper {
boolean madeChatTable = false;
switch( oldVersion ) {
case 5:
createTable( db, TABLE_NAME_OBITS, s_obitsColsAndTypes );
createTable( db, TABLE_NAMES.OBITS, s_obitsColsAndTypes );
case 6:
addSumColumn( db, TURN );
addSumColumn( db, GIFLAGS );
@ -285,8 +294,8 @@ public class DBHelper extends SQLiteOpenHelper {
case 11:
addSumColumn( db, REMOTEDEVS );
case 12:
createTable( db, TABLE_NAME_DICTINFO, s_dictInfoColsAndTypes );
createTable( db, TABLE_NAME_DICTBROWSE, s_dictBrowseColsAndTypes );
createTable( db, TABLE_NAMES.DICTINFO, s_dictInfoColsAndTypes );
createTable( db, TABLE_NAMES.DICTBROWSE, s_dictBrowseColsAndTypes );
case 13:
addSumColumn( db, LASTMOVE );
case 14:
@ -296,8 +305,8 @@ public class DBHelper extends SQLiteOpenHelper {
moveToCurGames( db );
case 16:
addSumColumn( db, VISID );
setColumnsEqual( db, TABLE_NAME_SUM, VISID, "rowid" );
makeAutoincrement( db, TABLE_NAME_SUM, s_summaryColsAndTypes );
setColumnsEqual( db, TABLE_NAMES.SUM, VISID, "rowid" );
makeAutoincrement( db, TABLE_NAMES.SUM, s_summaryColsAndTypes );
madeSumTable = true;
case 17:
if ( !madeSumTable ) {
@ -336,25 +345,14 @@ public class DBHelper extends SQLiteOpenHelper {
}
case 28:
if ( !madeChatTable ) {
addColumn( db, TABLE_NAME_CHAT, s_chatsSchema, CHATTIME );
addColumn( db, TABLE_NAMES.CHAT, s_chatsSchema, CHATTIME );
}
break;
default:
db.execSQL( "DROP TABLE " + TABLE_NAME_SUM + ";" );
TableAndVersion[] tav = new TableAndVersion[] {
new TableAndVersion( TABLE_NAME_OBITS, 5 ),
new TableAndVersion( TABLE_NAME_DICTINFO, 12 ),
new TableAndVersion( TABLE_NAME_DICTBROWSE, 12 ),
new TableAndVersion( TABLE_NAME_GROUPS, 14 ),
new TableAndVersion( TABLE_NAME_STUDYLIST, 18 ),
new TableAndVersion( TABLE_NAME_LOC, 20 ),
new TableAndVersion( TABLE_NAME_PAIRS, 21 ),
};
for ( TableAndVersion entry : tav ) {
if ( oldVersion >= 1 + entry.addedVersion ) {
db.execSQL( "DROP TABLE " + entry.name + ";" );
for ( TABLE_NAMES table : TABLE_NAMES.values() ) {
if ( oldVersion >= 1 + table.addedVersion() ) {
db.execSQL( "DROP TABLE " + table + ";" );
}
}
onCreate( db );
@ -363,10 +361,10 @@ public class DBHelper extends SQLiteOpenHelper {
private void addSumColumn( SQLiteDatabase db, String colName )
{
addColumn( db, TABLE_NAME_SUM, s_summaryColsAndTypes, colName );
addColumn( db, TABLE_NAMES.SUM, s_summaryColsAndTypes, colName );
}
private void addColumn( SQLiteDatabase db, String tableName,
private void addColumn( SQLiteDatabase db, TABLE_NAMES tableName,
String[][] colsAndTypes, String colName )
{
String colType = null;
@ -382,7 +380,7 @@ public class DBHelper extends SQLiteOpenHelper {
db.execSQL( cmd );
}
private void createTable( SQLiteDatabase db, String name, String[][] data )
private void createTable( SQLiteDatabase db, TABLE_NAMES name, String[][] data )
{
StringBuilder query =
new StringBuilder( String.format("CREATE TABLE %s (", name ) );
@ -404,7 +402,7 @@ public class DBHelper extends SQLiteOpenHelper {
isUpgrade = 0 < countGames( db );
}
createTable( db, TABLE_NAME_GROUPS, s_groupsSchema );
createTable( db, TABLE_NAMES.GROUPS, s_groupsSchema );
// Create an empty group name
ContentValues values = new ContentValues();
@ -412,50 +410,50 @@ public class DBHelper extends SQLiteOpenHelper {
values.put( GROUPNAME, LocUtils.getString( m_context, false,
R.string.group_cur_games) );
values.put( EXPANDED, 1 );
long curGroup = db.insert( TABLE_NAME_GROUPS, null, values );
long curGroup = insert( db, TABLE_NAMES.GROUPS, values );
// place all existing games in the initial unnamed group
values = new ContentValues();
values.put( GROUPID, curGroup );
db.update( DBHelper.TABLE_NAME_SUM, values, null, null );
db.update( DBHelper.TABLE_NAMES.SUM.toString(), values, null, null );
}
values = new ContentValues();
values.put( GROUPNAME, LocUtils.getString( m_context, false,
R.string.group_new_games) );
values.put( EXPANDED, 1 );
long newGroup = db.insert( TABLE_NAME_GROUPS, null, values );
long newGroup = insert( db, TABLE_NAMES.GROUPS, values );
XWPrefs.setDefaultNewGameGroup( m_context, newGroup );
}
private void createStudyTable( SQLiteDatabase db )
{
createTable( db, TABLE_NAME_STUDYLIST, s_studySchema );
createTable( db, TABLE_NAMES.STUDYLIST, s_studySchema );
}
private void createLocTable( SQLiteDatabase db )
{
createTable( db, TABLE_NAME_LOC, s_locSchema );
createTable( db, TABLE_NAMES.LOC, s_locSchema );
}
private void createPairsTable( SQLiteDatabase db )
{
createTable( db, TABLE_NAME_PAIRS, s_pairsSchema );
createTable( db, TABLE_NAMES.PAIRS, s_pairsSchema );
}
private void createInvitesTable( SQLiteDatabase db )
{
createTable( db, TABLE_NAME_INVITES, s_invitesSchema );
createTable( db, TABLE_NAMES.INVITES, s_invitesSchema );
}
private void createChatsTable( SQLiteDatabase db )
{
createTable( db, TABLE_NAME_CHAT, s_chatsSchema );
createTable( db, TABLE_NAMES.CHAT, s_chatsSchema );
}
private void createLogsTable( SQLiteDatabase db )
{
createTable( db, TABLE_NAME_LOGS, s_logsSchema );
createTable( db, TABLE_NAMES.LOGS, s_logsSchema );
}
// Move all existing games to the row previously named "cur games'
@ -465,19 +463,18 @@ public class DBHelper extends SQLiteOpenHelper {
R.string.group_cur_games );
String[] columns = { "rowid" };
String selection = String.format( "%s = '%s'", GROUPNAME, name );
Cursor cursor = db.query( DBHelper.TABLE_NAME_GROUPS, columns,
selection, null, null, null, null );
Cursor cursor = query( db, TABLE_NAMES.GROUPS, columns, selection );
if ( 1 == cursor.getCount() && cursor.moveToFirst() ) {
long rowid = cursor.getLong( cursor.getColumnIndex("rowid") );
ContentValues values = new ContentValues();
values.put( GROUPID, rowid );
db.update( DBHelper.TABLE_NAME_SUM, values, null, null );
update( db, TABLE_NAMES.SUM, values, null );
}
cursor.close();
}
private void makeAutoincrement( SQLiteDatabase db, String name,
private void makeAutoincrement( SQLiteDatabase db, TABLE_NAMES name,
String[][] data )
{
db.beginTransaction();
@ -524,7 +521,7 @@ public class DBHelper extends SQLiteOpenHelper {
}
}
private void setColumnsEqual( SQLiteDatabase db, String table,
private void setColumnsEqual( SQLiteDatabase db, TABLE_NAMES table,
String dest, String src )
{
String query = String.format( "UPDATE %s set %s = %s", table,
@ -532,7 +529,7 @@ public class DBHelper extends SQLiteOpenHelper {
db.execSQL( query );
}
private void forceRowidHigh( SQLiteDatabase db, String name )
private void forceRowidHigh( SQLiteDatabase db, TABLE_NAMES name )
{
long now = Utils.getCurSeconds();
// knock 20 years off; whose clock can be that far back?
@ -546,7 +543,7 @@ public class DBHelper extends SQLiteOpenHelper {
private int countGames( SQLiteDatabase db )
{
final String query = "SELECT COUNT(*) FROM " + TABLE_NAME_SUM;
final String query = "SELECT COUNT(*) FROM " + TABLE_NAMES.SUM;
Cursor cursor = db.rawQuery( query, null );
cursor.moveToFirst();
@ -555,7 +552,7 @@ public class DBHelper extends SQLiteOpenHelper {
return result;
}
private static String[] getColumns( SQLiteDatabase db, String name )
private static String[] getColumns( SQLiteDatabase db, TABLE_NAMES name )
{
String query = String.format( "SELECT * FROM %s LIMIT 1", name );
Cursor cursor = db.rawQuery( query, null );
@ -564,12 +561,27 @@ public class DBHelper extends SQLiteOpenHelper {
return colNames;
}
private class TableAndVersion {
public String name;
public int addedVersion;
public TableAndVersion( String nn, int vers ) {
name = nn; addedVersion = vers;
}
static Cursor query( SQLiteDatabase db, TABLE_NAMES table, String[] columns,
String selection, String orderBy )
{
return db.query( table.toString(), columns, selection,
null, null, null, orderBy );
}
static Cursor query( SQLiteDatabase db, TABLE_NAMES table, String[] columns,
String selection )
{
return query( db, table, columns, selection, null );
}
public static int update( SQLiteDatabase db, TABLE_NAMES table, ContentValues values,
String selection )
{
return db.update( table.toString(), values, selection, null );
}
static long insert( SQLiteDatabase db, TABLE_NAMES table, ContentValues values )
{
return db.insert( table.toString(), null, values );
}
}

View file

@ -33,7 +33,7 @@ import android.graphics.BitmapFactory;
import android.os.Environment;
import android.text.TextUtils;
import org.eehouse.android.xw4.DBHelper.TABLE_NAMES;
import org.eehouse.android.xw4.DictUtils.DictLoc;
import org.eehouse.android.xw4.DlgDelegate.DlgClickNotify.InviteMeans;
import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType;
@ -151,8 +151,7 @@ public class DBUtils {
String selection = String.format( ROW_ID_FMT, lock.getRowid() );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.SUM, columns, selection );
if ( 1 == cursor.getCount() && cursor.moveToFirst() ) {
summary = new GameSummary();
summary.nMoves = cursor
@ -350,10 +349,9 @@ public class DBUtils {
synchronized( s_dbHelper ) {
if ( null == summary ) {
s_db.delete( DBHelper.TABLE_NAME_SUM, selection, null );
delete( TABLE_NAMES.SUM, selection );
} else {
long result = s_db.update( DBHelper.TABLE_NAME_SUM,
values, selection, null );
long result = update( TABLE_NAMES.SUM, values, selection );
Assert.assertTrue( result >= 0 );
}
notifyListeners( rowid, GameChangeType.GAME_CHANGED );
@ -404,8 +402,7 @@ public class DBUtils {
String[] columns = { DBHelper.DICTLANG };
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.SUM, columns, selection );
result = cursor.getCount();
cursor.close();
@ -425,8 +422,7 @@ public class DBUtils {
String[] columns = { DBHelper.DICTLANG };
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.SUM, columns, selection );
result = cursor.getCount();
cursor.close();
}
@ -442,8 +438,7 @@ public class DBUtils {
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.SUM, columns, selection );
int indx = cursor.getColumnIndex( DBHelper.CONTYPE );
while ( cursor.moveToNext() ) {
CommsConnTypeSet typs = new CommsConnTypeSet( cursor.getInt(indx) );
@ -622,8 +617,7 @@ public class DBUtils {
String orderBy = DBHelper.TIMESTAMP + " DESC";
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_INVITES, columns,
selection, null, null, null, orderBy );
Cursor cursor = DBHelper.query( s_db, TABLE_NAMES.INVITES, columns, selection, orderBy );
if ( 0 < cursor.getCount() ) {
int indxMns = cursor.getColumnIndex( DBHelper.MEANS );
int indxTS = cursor.getColumnIndex( DBHelper.TIMESTAMP );
@ -654,7 +648,7 @@ public class DBUtils {
initDB( context );
synchronized( s_dbHelper ) {
s_db.insert( DBHelper.TABLE_NAME_INVITES, null, values );
insert( TABLE_NAMES.INVITES, values );
}
}
@ -663,7 +657,7 @@ public class DBUtils {
{
ContentValues values = new ContentValues();
values.put( column, value );
updateRow( null, DBHelper.TABLE_NAME_SUM, rowid, values );
updateRow( null, TABLE_NAMES.SUM, rowid, values );
}
public static void setMsgFlags( long rowid, int flags )
@ -685,8 +679,7 @@ public class DBUtils {
String[] columns = { column };
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.SUM, columns, selection );
if ( 1 == cursor.getCount() && cursor.moveToFirst() ) {
result =
cursor.getInt( cursor.getColumnIndex(column));
@ -730,8 +723,7 @@ public class DBUtils {
initDB( context );
synchronized( s_dbHelper ) {
long result = s_db.update( DBHelper.TABLE_NAME_SUM,
values, selection, null );
long result = update( TABLE_NAMES.SUM, values, selection );
Assert.assertTrue( result >= 0 );
@ -745,8 +737,7 @@ public class DBUtils {
values.putNull( DBHelper.THUMBNAIL );
initDB( context );
synchronized( s_dbHelper ) {
long result = s_db.update( DBHelper.TABLE_NAME_SUM,
values, null, null );
long result = update( TABLE_NAMES.SUM, values, null );
notifyListeners( ROWIDS_ALL, GameChangeType.GAME_CHANGED );
}
@ -759,8 +750,7 @@ public class DBUtils {
String selection = String.format( ROW_ID_FMT, rowid );
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.SUM, columns, selection );
if ( 1 == cursor.getCount() && cursor.moveToFirst() ) {
result =
cursor.getString( cursor.getColumnIndex(DBHelper.RELAYID) );
@ -779,8 +769,7 @@ public class DBUtils {
DBHelper.GROUPID, getArchiveGroup( context ) );
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.SUM, columns, selection );
int indx1 = cursor.getColumnIndex( ROW_ID );
int indx2 = cursor.getColumnIndex( DBHelper.CONTYPE );
for ( int ii = 0; cursor.moveToNext(); ++ii ) {
@ -802,8 +791,7 @@ public class DBUtils {
String selection = String.format( "%s = 0", DBHelper.GAME_OVER );
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.SUM, columns, selection );
int indx = cursor.getColumnIndex( DBHelper.CONTYPE );
while ( cursor.moveToNext() ) {
CommsConnTypeSet typs = new CommsConnTypeSet( cursor.getInt(indx) );
@ -823,8 +811,7 @@ public class DBUtils {
String selection = DBHelper.RELAYID + "='" + relayID + "'";
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.SUM, columns, selection );
result = new long[cursor.getCount()];
for ( int ii = 0; cursor.moveToNext(); ++ii ) {
result[ii] = cursor.getLong( cursor.getColumnIndex(ROW_ID) );
@ -841,8 +828,7 @@ public class DBUtils {
String selection = String.format( DBHelper.GAMEID + "=%d", gameID );
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.SUM, columns, selection );
result = new long[cursor.getCount()];
for ( int ii = 0; cursor.moveToNext(); ++ii ) {
result[ii] = cursor.getLong( cursor.getColumnIndex(ROW_ID) );
@ -869,8 +855,7 @@ public class DBUtils {
String selection = String.format( ROW_ID + "=%d", rowid );
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.SUM, columns, selection );
Assert.assertTrue( 1 >= cursor.getCount() );
result = 1 == cursor.getCount();
cursor.close();
@ -888,8 +873,7 @@ public class DBUtils {
new HashMap<String, HashSet<Integer> >();
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.SUM, columns, selection );
while ( cursor.moveToNext() ) {
int col = cursor.getColumnIndex( DBHelper.GAMEID );
int gameID = cursor.getInt( col );
@ -936,9 +920,7 @@ public class DBUtils {
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.SUM, columns, selection );
if ( cursor.moveToNext() ) {
int indx = cursor.getColumnIndex( columns[0] );
result = new Date( cursor.getLong( indx ) );
@ -958,9 +940,7 @@ public class DBUtils {
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.SUM, columns, selection );
int count = cursor.getCount();
if ( 0 < count ) {
result = new String[count];
@ -1002,7 +982,7 @@ public class DBUtils {
synchronized( s_dbHelper ) {
try {
long result = s_db.replaceOrThrow( DBHelper.TABLE_NAME_OBITS,
long result = s_db.replaceOrThrow( TABLE_NAMES.OBITS.toString(),
"", values );
} catch ( Exception ex ) {
Log.ex( TAG, ex );
@ -1018,8 +998,7 @@ public class DBUtils {
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_OBITS, columns,
null, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.OBITS, columns, null );
if ( 0 < cursor.getCount() ) {
int idIndex = cursor.getColumnIndex( DBHelper.RELAYID );
int seedIndex = cursor.getColumnIndex( DBHelper.SEED );
@ -1050,7 +1029,7 @@ public class DBUtils {
for ( Obit obit: obits ) {
String selection = String.format( fmt, obit.m_relayID,
obit.m_seed );
s_db.delete( DBHelper.TABLE_NAME_OBITS, selection, null );
delete( TABLE_NAMES.OBITS, selection );
}
}
}
@ -1078,7 +1057,7 @@ public class DBUtils {
synchronized( s_dbHelper ) {
values.put( DBHelper.VISID, maxVISID( s_db ) );
long rowid = s_db.insert( DBHelper.TABLE_NAME_SUM, null, values );
long rowid = insert( TABLE_NAMES.SUM, values );
setCached( rowid, null ); // force reread
@ -1106,7 +1085,7 @@ public class DBUtils {
}
values.put( DBHelper.LASTPLAY_TIME, timestamp );
updateRow( context, DBHelper.TABLE_NAME_SUM, rowid, values );
updateRow( context, TABLE_NAMES.SUM, rowid, values );
setCached( rowid, null ); // force reread
if ( ROWID_NOTFOUND != rowid ) { // Means new game?
@ -1126,9 +1105,7 @@ public class DBUtils {
String selection = String.format( ROW_ID_FMT, rowid );
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.SUM, columns, selection );
if ( 1 == cursor.getCount() && cursor.moveToFirst() ) {
result = cursor.getBlob( cursor
.getColumnIndex(DBHelper.SNAPSHOT));
@ -1163,13 +1140,13 @@ public class DBUtils {
initDB( context );
synchronized( s_dbHelper ) {
s_db.delete( DBHelper.TABLE_NAME_SUM, selSummaries, null );
delete( TABLE_NAMES.SUM, selSummaries );
// Delete invitations too
s_db.delete( DBHelper.TABLE_NAME_INVITES, selInvites, null );
delete( TABLE_NAMES.INVITES, selInvites );
// Delete chats too -- same sel as for invites
s_db.delete( DBHelper.TABLE_NAME_CHAT, selInvites, null );
delete( TABLE_NAMES.CHAT, selInvites );
deleteCurChatsSync( s_db, rowid );
@ -1185,9 +1162,7 @@ public class DBUtils {
String selection = String.format( ROW_ID_FMT, rowid );
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.SUM, columns, selection );
if ( 1 == cursor.getCount() && cursor.moveToFirst() ) {
result = cursor.getInt( cursor
.getColumnIndex(DBHelper.VISID));
@ -1206,9 +1181,7 @@ public class DBUtils {
String selection = String.format( ROW_ID_FMT, rowid );
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.SUM, columns, selection );
if ( 1 == cursor.getCount() && cursor.moveToFirst() ) {
result = cursor.getString( cursor
.getColumnIndex(DBHelper.GAME_NAME));
@ -1223,7 +1196,7 @@ public class DBUtils {
{
ContentValues values = new ContentValues();
values.put( DBHelper.GAME_NAME, name );
updateRow( context, DBHelper.TABLE_NAME_SUM, rowid, values );
updateRow( context, TABLE_NAMES.SUM, rowid, values );
}
private static HistoryPair[] convertChatString( Context context, long rowid,
@ -1291,8 +1264,7 @@ public class DBUtils {
String selection = String.format( "%s=%d", DBHelper.ROW, rowid );
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_CHAT, columns,
selection, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.CHAT, columns, selection );
if ( 0 < cursor.getCount() ) {
result = new HistoryPair[cursor.getCount()];
int msgIndex = cursor.getColumnIndex( DBHelper.MESSAGE );
@ -1386,8 +1358,7 @@ public class DBUtils {
DBHelper.NEXTNAG, now );
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.SUM, columns, selection );
int count = cursor.getCount();
if ( 0 < count ) {
result = new NeedsNagInfo[count];
@ -1417,8 +1388,7 @@ public class DBUtils {
String selection = "NOT " + DBHelper.NEXTNAG + "= 0";
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.SUM, columns, selection );
if ( cursor.moveToNext() ) {
result = cursor.getLong( cursor.getColumnIndex( "min" ) );
}
@ -1431,7 +1401,7 @@ public class DBUtils {
{
String updateQuery = "update %s set %s = ? "
+ " WHERE %s = ? ";
updateQuery = String.format( updateQuery, DBHelper.TABLE_NAME_SUM,
updateQuery = String.format( updateQuery, DBHelper.TABLE_NAMES.SUM,
DBHelper.NEXTNAG, ROW_ID );
initDB( context );
@ -1484,8 +1454,7 @@ public class DBUtils {
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.SUM, columns, selection );
if ( 1 == cursor.getCount() && cursor.moveToFirst() ) {
data = cursor.getBlob( cursor.
getColumnIndex(DBHelper.THUMBNAIL));
@ -1504,7 +1473,7 @@ public class DBUtils {
HashMap<Long, Integer> result = new HashMap<Long, Integer>();
String query = "SELECT %s, count(%s) as cnt FROM %s GROUP BY %s";
query = String.format( query, DBHelper.GROUPID, DBHelper.GROUPID,
DBHelper.TABLE_NAME_SUM, DBHelper.GROUPID );
DBHelper.TABLE_NAMES.SUM, DBHelper.GROUPID );
Cursor cursor = db.rawQuery( query, null );
int rowIndex = cursor.getColumnIndex( DBHelper.GROUPID );
@ -1573,13 +1542,8 @@ public class DBUtils {
DBHelper.TURN };
String orderBy = DBHelper.LASTMOVE;
String selection = String.format( "%s=%d", DBHelper.GROUPID, groupID );
Cursor cursor = db.query( DBHelper.TABLE_NAME_SUM, columns,
selection,
null, // args
null, // groupBy,
null, // having
orderBy
);
Cursor cursor = DBHelper.query( db, TABLE_NAMES.SUM, columns,
selection, orderBy );
// We want the earliest LASTPLAY_TIME (i.e. the first we see
// since they're in order) that's a local turn, if any,
@ -1625,13 +1589,7 @@ public class DBUtils {
String[] columns = { ROW_ID };
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_SUM, columns,
null, // selection
null, // args
null, // groupBy
null, // having
null
);
Cursor cursor = query( TABLE_NAMES.SUM, columns, null );
result = cursor.getCount();
cursor.close();
}
@ -1660,7 +1618,7 @@ public class DBUtils {
String[] columns = { ROW_ID, DBHelper.HASMSGS };
String selection = String.format( "%s=%d", DBHelper.GROUPID, groupID );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_SUM, columns,
Cursor cursor = s_db.query( TABLE_NAMES.SUM.toString(), columns,
selection, // selection
null, // args
null, // groupBy
@ -1695,13 +1653,7 @@ public class DBUtils {
}
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, // selection
null, // args
null, // groupBy
null, // having
null //orderby
);
Cursor cursor = query( TABLE_NAMES.SUM, columns, selection );
if ( cursor.moveToNext() ) {
int index = cursor.getColumnIndex( DBHelper.GROUPID );
result = cursor.getLong( index );
@ -1732,7 +1684,7 @@ public class DBUtils {
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_GROUPS, columns,
Cursor cursor = s_db.query( TABLE_NAMES.GROUPS.toString(), columns,
selection, selArgs,
null, // groupBy
null, // having
@ -1758,8 +1710,7 @@ public class DBUtils {
// initDB( context ); <- getGroups will have called this
synchronized( s_dbHelper ) {
rowid = s_db.insert( DBHelper.TABLE_NAME_GROUPS, null,
values );
rowid = insert( TABLE_NAMES.GROUPS, values );
}
invalGroupsCache();
}
@ -1778,9 +1729,8 @@ public class DBUtils {
initDB( context );
synchronized( s_dbHelper ) {
s_db.delete( DBHelper.TABLE_NAME_SUM, selectionGames, null );
s_db.delete( DBHelper.TABLE_NAME_GROUPS, selectionGroups, null );
delete( TABLE_NAMES.SUM, selectionGames );
delete( TABLE_NAMES.GROUPS, selectionGroups );
}
invalGroupsCache();
}
@ -1790,7 +1740,7 @@ public class DBUtils {
{
ContentValues values = new ContentValues();
values.put( DBHelper.GROUPNAME, name );
updateRow( context, DBHelper.TABLE_NAME_GROUPS, groupid, values );
updateRow( context, TABLE_NAMES.GROUPS, groupid, values );
invalGroupsCache();
}
@ -1799,7 +1749,7 @@ public class DBUtils {
{
ContentValues values = new ContentValues();
values.put( DBHelper.EXPANDED, expanded? 1 : 0 );
updateRow( context, DBHelper.TABLE_NAME_GROUPS, groupid, values );
updateRow( context, TABLE_NAMES.GROUPS, groupid, values );
invalGroupsCache();
}
@ -1820,7 +1770,7 @@ public class DBUtils {
Assert.assertTrue( GROUPID_UNSPEC != groupID );
ContentValues values = new ContentValues();
values.put( DBHelper.GROUPID, groupID );
updateRow( context, DBHelper.TABLE_NAME_SUM, rowid, values );
updateRow( context, TABLE_NAMES.SUM, rowid, values );
invalGroupsCache();
notifyListeners( rowid, GameChangeType.GAME_MOVED );
}
@ -1832,9 +1782,7 @@ public class DBUtils {
String selection = String.format( ROW_ID_FMT, rowid );
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_SUM, columns,
selection, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.SUM, columns, selection );
if ( 1 == cursor.getCount() && cursor.moveToFirst() ) {
result =
cursor.getString( cursor
@ -1852,7 +1800,7 @@ public class DBUtils {
initDB( context );
synchronized( s_dbHelper ) {
for ( ContentValues values : valuess ) {
s_db.insert( DBHelper.TABLE_NAME_CHAT, null, values );
insert( TABLE_NAMES.CHAT, values );
}
}
}
@ -1885,15 +1833,14 @@ public class DBUtils {
String selection = String.format( "%s = %d", DBHelper.ROW, rowid );
initDB( context );
synchronized( s_dbHelper ) {
s_db.delete( DBHelper.TABLE_NAME_CHAT, selection, null );
delete( TABLE_NAMES.CHAT, selection );
// for now, remove any old-format history too. Later when it's
// removed once converted (after that process is completely
// debugged), this can be removed.
ContentValues values = new ContentValues();
values.putNull( DBHelper.CHAT_HISTORY );
updateRowImpl( s_db, DBHelper.TABLE_NAME_SUM, rowid, values );
updateRowImpl( s_db, TABLE_NAMES.SUM, rowid, values );
}
}
@ -1977,8 +1924,7 @@ public class DBUtils {
name, DBHelper.LOC, loc.ordinal() );
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_DICTBROWSE, columns,
selection, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.DICTBROWSE, columns, selection );
if ( 1 >= cursor.getCount() && cursor.moveToFirst() ) {
result = new DictBrowseState();
result.m_pos = cursor.getInt( cursor
@ -2033,12 +1979,11 @@ public class DBUtils {
initDB( context );
synchronized( s_dbHelper ) {
int result = s_db.update( DBHelper.TABLE_NAME_DICTBROWSE,
values, selection, null );
int result = update( TABLE_NAMES.DICTBROWSE, values, selection );
if ( 0 == result ) {
values.put( DBHelper.DICTNAME, name );
values.put( DBHelper.LOC, loc.ordinal() );
s_db.insert( DBHelper.TABLE_NAME_DICTBROWSE, null, values );
insert( TABLE_NAMES.DICTBROWSE, values );
}
}
}
@ -2059,11 +2004,10 @@ public class DBUtils {
values.put( DBHelper.MD5SUM, sum );
initDB( context );
synchronized( s_dbHelper ) {
int result = s_db.update( DBHelper.TABLE_NAME_DICTINFO,
values, selection, null );
int result = update( TABLE_NAMES.DICTINFO, values, selection );
if ( 0 == result ) {
values.put( DBHelper.DICTNAME, name );
long rowid = s_db.insert( DBHelper.TABLE_NAME_DICTINFO, null, values );
long rowid = insert( TABLE_NAMES.DICTINFO, values );
Assert.assertTrue( rowid > 0 || !BuildConfig.DEBUG );
}
}
@ -2079,8 +2023,7 @@ public class DBUtils {
String selection = String.format( NAME_FMT, DBHelper.DICTNAME, name );
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_DICTINFO, columns,
selection, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.DICTINFO, columns, selection );
if ( 1 == cursor.getCount() && cursor.moveToFirst() ) {
result = new DictInfo();
result.name = name;
@ -2113,12 +2056,10 @@ public class DBUtils {
initDB( context );
synchronized( s_dbHelper ) {
int result = s_db.update( DBHelper.TABLE_NAME_DICTINFO,
values, selection, null );
int result = update( TABLE_NAMES.DICTINFO, values, selection );
if ( 0 == result ) {
values.put( DBHelper.DICTNAME, dal.name );
long rowid = s_db.insert( DBHelper.TABLE_NAME_DICTINFO, null,
values );
long rowid = insert( TABLE_NAMES.DICTINFO, values );
Assert.assertTrue( rowid > 0 || !BuildConfig.DEBUG );
}
}
@ -2135,8 +2076,8 @@ public class DBUtils {
initDB( context );
synchronized( s_dbHelper ) {
s_db.update( DBHelper.TABLE_NAME_DICTINFO, values, selection, null );
s_db.update( DBHelper.TABLE_NAME_DICTBROWSE, values, selection, null );
update( TABLE_NAMES.DICTINFO, values, selection );
update( TABLE_NAMES.DICTBROWSE, values, selection );
}
}
@ -2147,9 +2088,9 @@ public class DBUtils {
initDB( context );
synchronized( s_dbHelper ) {
int removed = s_db.delete( DBHelper.TABLE_NAME_DICTINFO, selection, args );
int removed = delete( TABLE_NAMES.DICTINFO, selection, args );
// Log.d( TAG, "removed %d rows from %s", removed, DBHelper.TABLE_NAME_DICTINFO );
removed = s_db.delete( DBHelper.TABLE_NAME_DICTBROWSE, selection, args );
removed = delete( TABLE_NAMES.DICTBROWSE, selection, args );
// Log.d( TAG, "removed %d rows from %s", removed, DBHelper.TABLE_NAME_DICTBROWSE );
}
}
@ -2176,7 +2117,7 @@ public class DBUtils {
initDB( context );
synchronized( s_dbHelper ) {
s_db.insert( DBHelper.TABLE_NAME_STUDYLIST, null, values );
insert( TABLE_NAMES.STUDYLIST, values );
}
notifyStudyListListeners( word, lang );
}
@ -2190,7 +2131,7 @@ public class DBUtils {
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_STUDYLIST, columns,
Cursor cursor = s_db.query( TABLE_NAMES.STUDYLIST.toString(), columns,
null, null, groupBy, null, null );
int count = cursor.getCount();
result = new int[count];
@ -2215,8 +2156,8 @@ public class DBUtils {
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_STUDYLIST, columns,
selection, null, null, null, orderBy );
Cursor cursor = DBHelper.query( s_db, TABLE_NAMES.STUDYLIST, columns,
selection, orderBy );
int count = cursor.getCount();
result = new String[count];
if ( 0 < count ) {
@ -2241,7 +2182,7 @@ public class DBUtils {
initDB( context );
synchronized( s_dbHelper ) {
s_db.delete( DBHelper.TABLE_NAME_STUDYLIST, selection, null );
delete( TABLE_NAMES.STUDYLIST, selection );
}
}
@ -2259,13 +2200,13 @@ public class DBUtils {
String insertQuery = "insert into %s (%s, %s, %s, %s) "
+ " VALUES (?, ?, ?, ?)";
insertQuery = String.format( insertQuery, DBHelper.TABLE_NAME_LOC,
insertQuery = String.format( insertQuery, TABLE_NAMES.LOC,
DBHelper.KEY, DBHelper.LOCALE,
DBHelper.BLESSED, DBHelper.XLATION );
String updateQuery = "update %s set %s = ? "
+ " WHERE %s = ? and %s = ? and %s = ?";
updateQuery = String.format( updateQuery, DBHelper.TABLE_NAME_LOC,
updateQuery = String.format( updateQuery, TABLE_NAMES.LOC,
DBHelper.XLATION, DBHelper.KEY,
DBHelper.LOCALE, DBHelper.BLESSED );
@ -2319,8 +2260,7 @@ public class DBUtils {
initDB( context );
synchronized( s_dbHelper ) {
Cursor cursor = s_db.query( DBHelper.TABLE_NAME_LOC, columns,
selection, null, null, null, null );
Cursor cursor = query( TABLE_NAMES.LOC, columns, selection );
int keyIndex = cursor.getColumnIndex( DBHelper.KEY );
int valueIndex = cursor.getColumnIndex( DBHelper.XLATION );
int blessedIndex = cursor.getColumnIndex( DBHelper.BLESSED );
@ -2345,7 +2285,7 @@ public class DBUtils {
initDB( context );
synchronized( s_dbHelper ) {
s_db.delete( DBHelper.TABLE_NAME_LOC, selection, null );
delete( TABLE_NAMES.LOC, selection );
}
}
@ -2355,18 +2295,17 @@ public class DBUtils {
ContentValues values = new ContentValues();
values.put( DBHelper.VALUE, value );
long result = db.update( DBHelper.TABLE_NAME_PAIRS,
values, selection, null );
long result = DBHelper.update( db, TABLE_NAMES.PAIRS, values, selection );
if ( 0 == result ) {
values.put( DBHelper.KEY, key );
db.insert( DBHelper.TABLE_NAME_PAIRS, null, values );
DBHelper.insert( db, TABLE_NAMES.PAIRS, values );
}
}
private static void delStringsLikeSync( SQLiteDatabase db, String like )
{
String selection = String.format( "%s LIKE '%s'", DBHelper.KEY, like );
db.delete( DBHelper.TABLE_NAME_PAIRS, selection, null );
delete( db, TABLE_NAMES.PAIRS, selection, null );
}
private static String getStringForSync( SQLiteDatabase db, String key, String dflt )
@ -2374,8 +2313,7 @@ public class DBUtils {
String selection = String.format( "%s = '%s'", DBHelper.KEY, key );
String[] columns = { DBHelper.VALUE };
Cursor cursor = db.query( DBHelper.TABLE_NAME_PAIRS, columns,
selection, null, null, null, null );
Cursor cursor = DBHelper.query( db, TABLE_NAMES.PAIRS, columns, selection );
Assert.assertTrue( 1 >= cursor.getCount() );
int indx = cursor.getColumnIndex( DBHelper.VALUE );
if ( cursor.moveToNext() ) {
@ -2536,13 +2474,13 @@ public class DBUtils {
initDB( context );
synchronized( s_dbHelper ) {
long rowid = s_db.insert( DBHelper.TABLE_NAME_LOGS, null, values );
long rowid = insert( TABLE_NAMES.LOGS, values );
if ( 0 == (rowid % (LOGLIMIT / 10)) ) {
String where =
String.format( "not rowid in (select rowid from %s order by TIMESTAMP desc limit %d)",
DBHelper.TABLE_NAME_LOGS, LOGLIMIT );
int nGone = s_db.delete( DBHelper.TABLE_NAME_LOGS, where, null );
TABLE_NAMES.LOGS, LOGLIMIT );
int nGone = delete( TABLE_NAMES.LOGS, where );
Log.i( TAG, "appendLog(): deleted %d rows", nGone );
}
}
@ -2587,7 +2525,7 @@ public class DBUtils {
// {
// ContentValues values = new ContentValues();
// values.putNull( DBHelper.CHAT_HISTORY );
// updateRow( context, DBHelper.TABLE_NAME_SUM, rowid, values );
// updateRow( context, DBHelper.TABLE_NAMES.SUM, rowid, values );
// }
private static void initDB( Context context )
@ -2603,15 +2541,15 @@ public class DBUtils {
}
}
private static int updateRowImpl( SQLiteDatabase db, String table,
private static int updateRowImpl( SQLiteDatabase db, TABLE_NAMES table,
long rowid, ContentValues values )
{
String selection = String.format( ROW_ID_FMT, rowid );
return db.update( table, values, selection, null );
return DBHelper.update( db, table, values, selection );
}
private static void updateRow( Context context, String table,
private static void updateRow( Context context, TABLE_NAMES table,
long rowid, ContentValues values )
{
initDB( context );
@ -2627,7 +2565,7 @@ public class DBUtils {
{
int result = 1;
String query = String.format( "SELECT max(%s) FROM %s", DBHelper.VISID,
DBHelper.TABLE_NAME_SUM );
TABLE_NAMES.SUM );
Cursor cursor = null;
try {
cursor = db.rawQuery( query, null );
@ -2676,4 +2614,39 @@ public class DBUtils {
s_cachedRowID = rowid;
s_cachedBytes = bytes;
}
private static Cursor query( TABLE_NAMES table, String[] columns, String selection )
{
return DBHelper.query( s_db, table, columns, selection );
}
private static int delete( SQLiteDatabase db, TABLE_NAMES table, String selection, String[] args )
{
return db.delete( table.toString(), selection, args );
}
private static int delete( SQLiteDatabase db, TABLE_NAMES table, String selection )
{
return delete( db, table, selection, null );
}
private static int delete( TABLE_NAMES table, String selection )
{
return delete( s_db, table, selection, null );
}
private static int delete( TABLE_NAMES table, String selection, String[] args )
{
return delete( s_db, table, selection, args );
}
private static int update( TABLE_NAMES table, ContentValues values, String selection )
{
return DBHelper.update( s_db, table, values, selection );
}
private static long insert( TABLE_NAMES table, ContentValues values )
{
return DBHelper.insert( s_db, table, values );
}
}

View file

@ -158,14 +158,18 @@ public class DbgUtils {
// return TextUtils.join( ", ", asStrs );
// }
// public static String hexDump( byte[] bytes )
// {
// StringBuilder dump = new StringBuilder();
// for ( byte byt : bytes ) {
// dump.append( String.format( "%02x ", byt ) );
// }
// return dump.toString();
// }
public static String hexDump( byte[] bytes )
{
String result = "<null>";
if ( null != bytes ) {
StringBuilder dump = new StringBuilder();
for ( byte byt : bytes ) {
dump.append( String.format( "%02x ", byt ) );
}
result = dump.toString();
}
return result;
}
private static List<DeadlockWatch> sLockHolders = new ArrayList<>();

View file

@ -37,6 +37,7 @@ public class DevID {
private static final String DEVID_KEY = "DevID.devid_key";
private static final String DEVID_ACK_KEY = "key_relay_regid_ackd2";
private static final String FCM_REGVERS_KEY = "key_fcmvers_regid";
private static final String NFC_DEVID_KEY = "key_nfc_devid";
private static String s_relayDevID;
private static int s_asInt;
@ -118,31 +119,21 @@ public class DevID {
DBUtils.setBoolFor( context, DEVID_ACK_KEY, false );
}
public static String getGCMDevID( Context context )
// Just a random number I hang onto as long as possible
private static int[] sNFCDevID = {0};
public static int getNFCDevID( Context context )
{
return "";
// int curVers = Utils.getAppVersion( context );
// int storedVers = DBUtils.getIntFor( context, GCM_REGVERS_KEY, 0 );
// // TRANSITIONAL
// if ( 0 == storedVers ) {
// storedVers = XWPrefs.getPrefsInt( context,
// R.string.key_gcmvers_regid, 0 );
// if ( 0 != storedVers ) {
// DBUtils.setIntFor( context, GCM_REGVERS_KEY, storedVers );
// }
// }
// String result;
// if ( 0 != storedVers && storedVers < curVers ) {
// result = ""; // Don't trust what registrar has
// } else {
// result = GCMStub.getRegistrationId( context );
// }
// return result;
synchronized ( sNFCDevID ) {
if ( 0 == sNFCDevID[0] ) {
int devid = DBUtils.getIntFor( context, NFC_DEVID_KEY, 0 );
while ( 0 == devid ) {
devid = Utils.nextRandomInt();
DBUtils.setIntFor( context, NFC_DEVID_KEY, devid );
}
sNFCDevID[0] = devid;
}
Log.d( TAG, "getNFCDevID() => %d", sNFCDevID[0] );
return sNFCDevID[0];
}
public static void clearGCMDevID( Context context )
{
DBUtils.setBoolFor( context, DEVID_ACK_KEY, false );
}
}

View file

@ -76,7 +76,6 @@ public class DlgDelegate {
VALUES_ACTION,
SMS_CONFIG_ACTION,
BUTTON_BROWSEALL_ACTION,
NFC_TO_SELF,
DROP_RELAY_ACTION,
DROP_SMS_ACTION,
INVITE_SMS_DATA,

View file

@ -1246,19 +1246,12 @@ public class GameConfigDelegate extends DelegateBase
if ( null != m_jniThread ) {
applyChanges( m_jniThread.getLock(), forceNew );
} else {
try ( GameLock lock = GameLock.tryLock( m_rowid ) ) {
try ( GameLock lock = GameLock.lock( m_rowid, 100L ) ) {
applyChanges( lock, forceNew );
} catch ( GameLock.GameLockedException gle ) {
Log.e( TAG, "applyChanges(): failed to get lock" );
}
}
// }
// GameLock gameLock = m_jniThread == null
// ? GameLock.tryLock( m_rowid ) : m_jniThread.getLock();
// GameUtils.applyChanges( m_activity, m_gi, m_car, m_disabMap,
// gameLock, forceNew );
// DBUtils.saveThumbnail( m_activity, gameLock, null ); // clear it
// if ( null == m_jniThread ) {
// gameLock.unlock();
// }
}
}

View file

@ -33,7 +33,6 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.eehouse.android.xw4.jni.GameSummary;
import org.eehouse.android.xw4.jni.JNIThread;
import org.eehouse.android.xw4.loc.LocUtils;
@ -250,7 +249,7 @@ public class GameListItem extends LinearLayout
case R.string.game_summary_field_empty:
break;
case R.string.game_summary_field_gameid:
value = String.format( "%X", m_summary.gameID );
value = String.format( "%d", m_summary.gameID );
break;
case R.string.game_summary_field_rowid:
value = String.format( "%d", m_rowid );
@ -336,6 +335,13 @@ public class GameListItem extends LinearLayout
findViewById( R.id.has_chat_marker )
.setVisibility( hasChat ? View.VISIBLE : View.GONE );
if ( XWPrefs.moveCountEnabled( m_context ) ) {
TextView tv = (TextView)findViewById( R.id.n_pending );
int nPending = summary.nPacketsPending;
String str = nPending == 0 ? "" : String.format( "%d", nPending );
tv.setText( str );
}
String roleSummary = summary.summarizeRole( m_context, m_rowid );
m_role.setVisibility( null == roleSummary ? View.GONE : View.VISIBLE );
if ( null != roleSummary ) {

View file

@ -109,7 +109,7 @@ public class GamesListDelegate extends ListDelegateBase
}
int groupSelItem;
boolean nextIsSolo;
boolean moveAfterNewGroup;
long[] moveAfterNewGroup;
Set<Long> selGames;
Set<Long> selGroupIDs;
}
@ -818,7 +818,7 @@ public class GamesListDelegate extends ListDelegateBase
@Override
public void onClick( DialogInterface dlg,
int item ) {
m_mySIS.moveAfterNewGroup = true;
m_mySIS.moveAfterNewGroup = games;
showDialogFragment( DlgID.NEW_GROUP );
}
} )
@ -1596,7 +1596,7 @@ public class GamesListDelegate extends ListDelegateBase
break;
case R.id.games_menu_newgroup:
m_mySIS.moveAfterNewGroup = false;
m_mySIS.moveAfterNewGroup = null;
showDialogFragment( DlgID.NEW_GROUP );
break;
@ -2353,14 +2353,14 @@ public class GamesListDelegate extends ListDelegateBase
private boolean tryNFCIntent( Intent intent )
{
boolean result = false;
String data = NFCUtils.getFromIntent( intent );
byte[] data = NFCUtils.getFromIntent( intent );
if ( null != data ) {
NetLaunchInfo nli = NetLaunchInfo.makeFrom( m_activity, data );
if ( null != nli && nli.isValid() ) {
startNewNetGame( nli );
result = true;
} else {
NFCUtils.receiveMsgs( m_activity, data );
Assert.assertFalse( BuildConfig.DEBUG );
}
}
return result;
@ -2448,11 +2448,10 @@ public class GamesListDelegate extends ListDelegateBase
private void showNewGroupIf()
{
if ( m_mySIS.moveAfterNewGroup ) {
m_mySIS.moveAfterNewGroup = false;
Long[] games = m_mySIS.selGames
.toArray( new Long[m_mySIS.selGames.size()] );
showDialogFragment( DlgID.CHANGE_GROUP, (Object)games );
long[] games = m_mySIS.moveAfterNewGroup;
if ( null != games ) {
m_mySIS.moveAfterNewGroup = null;
showDialogFragment( DlgID.CHANGE_GROUP, games );
}
}
@ -2844,10 +2843,12 @@ public class GamesListDelegate extends ListDelegateBase
;
}
public static void sendNFCToSelf( Context context, String data )
public static void postNFCInvite( Context context, byte[] data )
{
Intent intent = makeSelfIntent( context );
NFCUtils.populateIntent( intent, data );
Intent intent = makeSelfIntent( context )
.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK )
;
NFCUtils.populateIntent( context, intent, data );
context.startActivity( intent );
}

View file

@ -79,7 +79,7 @@ public class InviteChoicesAlert extends DlgDelegateAlert {
if ( WiDirWrapper.enabled() ) {
add( items, means, R.string.invite_choice_p2p, InviteMeans.WIFIDIRECT );
}
if ( XWPrefs.getNFCToSelfEnabled( context ) || NFCUtils.nfcAvail( context )[0] ) {
if ( NFCUtils.nfcAvail( context )[0] ) {
add( items, means, R.string.invite_choice_nfc, InviteMeans.NFC );
}
add( items, means, R.string.slmenu_copy_sel, InviteMeans.CLIPBOARD );

View file

@ -79,6 +79,11 @@ public class MultiMsgSink implements TransportProcs {
.sendPacket( m_context, addr.p2p_addr, gameID, buf );
}
int sendViaNFC( byte[] buf, int gameID )
{
return NFCUtils.addMsgFor( buf, gameID );
}
public int numSent()
{
return m_sentSet.size();
@ -107,13 +112,13 @@ public class MultiMsgSink implements TransportProcs {
nSent = sendViaP2P( buf, gameID, addr );
break;
case COMMS_CONN_NFC:
Log.d( TAG, "transportSend(): got for NFC" );
nSent = sendViaNFC( buf, gameID );
break;
default:
Assert.fail();
break;
}
Log.i( TAG, "transportSend(): sent %d msgs for game %d/%x via %s",
Log.i( TAG, "transportSend(): sent %d bytes for game %d/%x via %s",
nSent, gameID, gameID, typ.toString() );
if ( 0 < nSent ) {
Log.d( TAG, "transportSend: adding %s", msgID );

View file

@ -66,8 +66,7 @@ public class NBSProto {
DbgUtils.showf( context, "Got msg %d", s_nReceived );
}
ConnStatusHandler.updateStatusIn( context, null,
CommsConnType.COMMS_CONN_SMS,
ConnStatusHandler.updateStatusIn( context, CommsConnType.COMMS_CONN_SMS,
true );
}
@ -380,8 +379,7 @@ public class NBSProto {
DbgUtils.showf( context, "Sent msg %d", s_nSent );
}
ConnStatusHandler.updateStatusOut( context, null,
CommsConnType.COMMS_CONN_SMS,
ConnStatusHandler.updateStatusOut( context, CommsConnType.COMMS_CONN_SMS,
success );
}

View file

@ -0,0 +1,157 @@
/* -*- compile-command: "find-and-gradle.sh inXw4dDeb"; -*- */
/*
* Copyright 2019 by Eric House (xwords@eehouse.org). All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.eehouse.android.xw4;
import android.app.Activity;
import android.content.Context;
import android.nfc.cardemulation.HostApduService;
import android.os.Bundle;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.eehouse.android.xw4.NFCUtils.HEX_STR;
import org.eehouse.android.xw4.NFCUtils.MsgToken;
public class NFCCardService extends HostApduService {
private static final String TAG = NFCCardService.class.getSimpleName();
private static final int LEN_OFFSET = 4;
private int mMyDevID;
// Remove this once we don't need logging to confirm stuff's loading
@Override
public void onCreate()
{
super.onCreate();
mMyDevID = DevID.getNFCDevID( this );
Log.d( TAG, "onCreate() got mydevid %d", mMyDevID );
}
private int mGameID;
@Override
public byte[] processCommandApdu( byte[] apdu, Bundle extras )
{
// Log.d( TAG, "processCommandApdu(%s)", DbgUtils.hexDump(apdu ) );
HEX_STR resStr = HEX_STR.STATUS_FAILED;
boolean isAidCase = false;
if ( null != apdu ) {
if ( HEX_STR.CMD_MSG_PART.matchesFrom( apdu ) ) {
resStr = HEX_STR.STATUS_SUCCESS;
byte[] all = NFCUtils.reassemble( this, apdu, HEX_STR.CMD_MSG_PART );
if ( null != all ) {
NFCUtils.addToMsgThread( this, all );
}
} else {
Log.d( TAG, "processCommandApdu(): aid case?" );
if ( ! HEX_STR.DEFAULT_CLA.matchesFrom( apdu ) ) {
resStr = HEX_STR.CLA_NOT_SUPPORTED;
} else if ( ! HEX_STR.SELECT_INS.matchesFrom( apdu, 1 ) ) {
resStr = HEX_STR.INS_NOT_SUPPORTED;
} else if ( LEN_OFFSET >= apdu.length ) {
Log.d( TAG, "processCommandApdu(): apdu too short" );
// Not long enough for length byte
} else {
try {
ByteArrayInputStream bais
= new ByteArrayInputStream( apdu, LEN_OFFSET,
apdu.length - LEN_OFFSET );
byte aidLen = (byte)bais.read();
Log.d( TAG, "aidLen=%d", aidLen );
if ( bais.available() >= aidLen + 1 ) {
byte[] aidPart = new byte[aidLen];
bais.read( aidPart );
String aidStr = Utils.ba2HexStr( aidPart );
if ( BuildConfig.NFC_AID.equals( aidStr ) ) {
byte minVersion = (byte)bais.read();
byte maxVersion = (byte)bais.read();
if ( minVersion == NFCUtils.VERSION_1 ) {
int devID = NFCUtils.numFrom( bais );
Log.d( TAG, "processCommandApdu(): read "
+ "remote devID: %d", devID );
mGameID = NFCUtils.numFrom( bais );
Log.d( TAG, "read gameID: %d", mGameID );
if ( 0 < bais.available() ) {
Log.d( TAG, "processCommandApdu(): "
+ "leaving anything behind?" );
}
resStr = HEX_STR.STATUS_SUCCESS;
isAidCase = true;
} else {
Log.e( TAG, "unexpected version %d; I'm too old?",
minVersion );
}
} else {
Log.e( TAG, "aid mismatch: got %s but wanted %s",
aidStr, BuildConfig.NFC_AID );
}
}
} catch ( IOException ioe ) {
Assert.assertFalse( BuildConfig.DEBUG );
}
}
}
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
baos.write( resStr.asBA() );
if ( HEX_STR.STATUS_SUCCESS == resStr ) {
if ( isAidCase ) {
baos.write( NFCUtils.VERSION_1 ); // min
baos.write( NFCUtils.numTo( mMyDevID ) );
} else {
MsgToken token = NFCUtils.getMsgsFor( mGameID );
byte[][] tmp = NFCUtils.wrapMsg( token, Short.MAX_VALUE );
Assert.assertTrue( 1 == tmp.length || !BuildConfig.DEBUG );
baos.write( tmp[0] );
}
}
} catch ( IOException ioe ) {
Assert.assertFalse( BuildConfig.DEBUG );
}
byte[] result = baos.toByteArray();
Log.d( TAG, "processCommandApdu(%s) => %s", DbgUtils.hexDump( apdu ),
DbgUtils.hexDump( result ) );
// this comes out of transceive() below!!!
return result;
} // processCommandApdu
@Override
public void onDeactivated( int reason )
{
String str = "<other>";
switch ( reason ) {
case HostApduService.DEACTIVATION_LINK_LOSS:
str = "DEACTIVATION_LINK_LOSS";
break;
case HostApduService.DEACTIVATION_DESELECTED:
str = "DEACTIVATION_DESELECTED";
break;
}
Log.d( TAG, "onDeactivated(reason=%s)", str );
}
}

View file

@ -294,6 +294,7 @@ public class NetLaunchInfo implements Serializable {
addP2PInfo( context );
break;
case COMMS_CONN_NFC:
addNFCInfo();
break;
default:
Assert.fail();

View file

@ -735,8 +735,8 @@ public class RelayService extends XWJIService
Log.e( TAG, "fail sending to %s", udpSocket );
Log.ex( TAG, ex );
Log.i( TAG, "Restarting threads to force new socket" );
ConnStatusHandler.updateStatusOut( service, null,
CommsConnType.COMMS_CONN_RELAY,
ConnStatusHandler
.updateStatusOut( service, CommsConnType.COMMS_CONN_RELAY,
true );
closeUDPSocket( udpSocket );

View file

@ -615,6 +615,40 @@ public class Utils {
return Looper.getMainLooper().equals(Looper.myLooper());
}
// But see hexArray above
private static final String HEX_CHARS = "0123456789ABCDEF";
private static char[] HEX_CHARS_ARRAY = HEX_CHARS.toCharArray();
public static String ba2HexStr( byte[] input )
{
StringBuffer sb = new StringBuffer();
for ( byte byt : input ) {
sb.append(HEX_CHARS_ARRAY[(byt >> 4) & 0x0F]);
sb.append(HEX_CHARS_ARRAY[byt & 0x0F]);
}
String result = sb.toString();
return result;
}
public static byte[] hexStr2ba( String data )
{
data = data.toUpperCase();
Assert.assertTrue( 0 == data.length() % 2 );
byte[] result = new byte[data.length() / 2];
for (int ii = 0; ii < data.length(); ii += 2 ) {
int one = HEX_CHARS.indexOf(data.charAt(ii));
Assert.assertTrue( one >= 0 );
int two = HEX_CHARS.indexOf(data.charAt(ii + 1));
Assert.assertTrue( two >= 0 );
result[ii/2] = (byte)((one << 4) | two);
}
return result;
}
public static String base64Encode( byte[] in )
{
return Base64.encodeToString( in, Base64.NO_WRAP );

View file

@ -172,15 +172,15 @@ public class WiDirService extends XWService {
private static void updateStatusOut( boolean success )
{
ConnStatusHandler
.updateStatusOut( XWApp.getContext(), null,
.updateStatusOut( XWApp.getContext(),
CommsConnType.COMMS_CONN_P2P, success );
}
private static void updateStatusIn( boolean success )
{
ConnStatusHandler
.updateStatusIn( XWApp.getContext(), null,
CommsConnType.COMMS_CONN_P2P, success );
.updateStatusIn( XWApp.getContext(), CommsConnType.COMMS_CONN_P2P,
success );
}
public static void init( Context context )

View file

@ -61,9 +61,10 @@ public class XWPrefs {
return getPrefsBoolean( context, R.string.key_enable_dup_invite, false );
}
public static boolean getNFCToSelfEnabled( Context context )
public static boolean moveCountEnabled( Context context )
{
return getPrefsBoolean( context, R.string.key_enable_nfc_toself, false );
return getPrefsBoolean( context, R.string.key_enable_pending_count,
BuildConfig.DEBUG );
}
public static boolean getIgnoreFCM( Context context )

View file

@ -80,6 +80,8 @@ public class CommsAddrRec {
id = R.string.invite_choice_data_sms; break;
case COMMS_CONN_P2P:
id = R.string.invite_choice_p2p; break;
case COMMS_CONN_NFC:
id = R.string.invite_choice_nfc; break;
default:
Assert.assertFalse( BuildConfig.DEBUG );
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 B

View file

@ -38,6 +38,11 @@
android:paddingLeft="8dip"
android:paddingRight="8dip"
>
<!-- Shown only when BuildConfig.DEBUG == true -->
<TextView android:id="@+id/n_pending"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<ImageView android:id="@+id/game_type_marker"
android:layout_width="fill_parent"
android:layout_height="fill_parent"

View file

@ -126,7 +126,7 @@
<string name="key_na_dicts">key_na_dicts</string>
<string name="key_enable_debug">key_enable_debug</string>
<string name="key_enable_dup_invite">key_enable_dup_invite</string>
<string name="key_enable_nfc_toself">key_enable_nfc_toself</string>
<string name="key_enable_pending_count">key_enable_pending_count</string>
<string name="key_enable_sms_toself">key_enable_sms_toself</string>
<string name="key_show_fcm">key_show_fcm2</string>
<string name="key_nag_intervals">key_nag_intervals</string>
@ -152,7 +152,6 @@
<!-- other -->
<string name="default_host">eehouse.org</string>
<!-- <string name="default_host">10.0.3.2</string> -->
<string name="xwords_nfc_mime">application/org.eehouse.android.xw4</string>
<string name="invite_host">eehouse.org</string>
<string name="invite_mime">application/x-xwordsinvite</string>
<!--string name="invite_mime">text/plain</string-->

View file

@ -58,7 +58,7 @@
how far along they are. I may list "tiles left" someday
instead... -->
<plurals name="moves_fmt">
<item quantity="one">%1$d move played</item>
<item quantity="one">One move played</item>
<item quantity="other">%1$d moves played</item>
</plurals>
<!-- When you select the gamel_menu_delete_all menuitem or
@ -457,7 +457,7 @@
invititation while trying to warn him not to send duplicates.
The number of players missing is substituted for "%1$d". -->
<plurals name="invite_msg_fmt">
<item quantity="one">This game is waiting for %1$d remote
<item quantity="one">This game is waiting for one remote
player. Would you like to invite someone to join -- assuming you
haven\'t already?</item>
<item quantity="other">This game is waiting for %1$d remote
@ -677,6 +677,7 @@
<!-- First line in the remaining tiles dialog (reached by tapping
the number at left end of the scoreboard) -->
<plurals name="strd_remains_header_fmt">
<item quantity="one">One tile left in pool.</item>
<item quantity="other">%1$d tiles left in pool.</item>
</plurals>
<!-- Intro to the paragraph listing all of the tiles remaining -->
@ -1039,7 +1040,7 @@
substituted for "%1$s". (The funky \u003c and friends are
encodings for the greater-than and less-than symbols which
are not legal in xml strings.)-->
<string name="invite_htm_fmt">&lt;a href=\"%1$s\"&gt;Tap here&lt;/a&gt; (or the full link below to join this game. If you already have CrossWords you can open the attachment to do so). &lt;br \\&gt; &lt;br \\&gt; (Full link: %1$s )</string>
<string name="invite_htm_fmt">Tap the full link below to join this game. &lt;br \\&gt; &lt;br \\&gt; (Full link: %1$s )</string>
<string name="invite_sms_fmt">Tap the link to accept my
invitation and join a CrossWords game: %1$s
</string>
@ -1845,9 +1846,9 @@
<!-- -->
<string name="new_app_avail">Tap to download and install</string>
<!-- Used in formatting final scores display -->
<string name="str_winner_fmt" formatted="false">[Winner] %s: %d</string>
<string name="str_resigned_fmt" formatted="false">[Resigned] %s: %d</string>
<string name="str_placer_fmt" formatted="false">[#%d] %s: %d</string>
<string name="str_winner_fmt" formatted="false">[Winner] %1$s: %2$d</string>
<string name="str_resigned_fmt" formatted="false">[Resigned] %1$s: %2$d</string>
<string name="str_placer_fmt" formatted="false">[#%1$d] %2$s: %3$d</string>
<!-- -->
<string name="inform_dict_diffversion_fmt">You and the host of this
game are using different versions of the wordlist %1$s.</string>
@ -2078,6 +2079,7 @@
<!-- formatting for last move summary in notifications -->
<string name="lmi_pass_fmt">%1$s passed (0 points)</string>
<plurals name="lmi_move_fmt">
<item quantity="one">%1$s played %2$s for one point</item>
<item quantity="other">%1$s played %2$s for %3$d points</item>
</plurals>
<plurals name="lmi_trade_fmt">
@ -2197,9 +2199,9 @@
<string name="enable_dupes_title">Accept duplicate invites</string>
<string name="xlations_locale">Fake locale for translation</string>
<string name="enable_dupes_summary">Accept invitations more than once</string>
<string name="enable_pending_count_title">Show Pending messages</string>
<string name="enable_pending_count_summary">Show number not yet acknowledged</string>
<string name="nag_intervals">Reminder intervals (minutes1,minutes2,…)</string>
<string name="enable_nfc_toself_title">Enable NFC to self</string>
<string name="enable_nfc_toself_summary">Fake invitation to aid debugging</string>
<string name="enable_sms_toself_title">Short-circuit SMS to self</string>
<string name="enable_sms_toself_summary">Skip radio when phone numbers same</string>
<string name="force_radio_title">Pretend to have radio</string>
@ -2398,4 +2400,6 @@
words.\n\nUse this feature to check the validity of words you\'re
thinking of playing, or to look up an unfamiliar word provided as a
hint.</string>
<string name="servicedesc">For transmitting CrossWords moves</string>
</resources>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/servicedesc"
android:requireDeviceUnlock="false">
<aid-group android:description="@string/servicedesc"
android:category="other">
<aid-filter android:name="@string/nfc_aid"/>
</aid-group>
</host-apdu-service>

View file

@ -390,10 +390,10 @@
android:defaultValue="false"
/>
<CheckBoxPreference android:key="@string/key_enable_nfc_toself"
android:title="@string/enable_nfc_toself_title"
android:summary="@string/enable_nfc_toself_summary"
android:defaultValue="false"
<CheckBoxPreference android:key="@string/key_enable_pending_count"
android:title="@string/enable_pending_count_title"
android:summary="@string/enable_pending_count_summary"
android:defaultValue="@bool/DEBUG"
/>
<PreferenceScreen android:title="@string/pref_group_relay_title"

View file

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="195.92358mm"
height="79.111778mm"
viewBox="0 0 195.92358 79.111778"
version="1.1"
id="svg3810"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="in_arrow.svg">
<defs
id="defs3804" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.9899495"
inkscape:cx="266.75131"
inkscape:cy="51.719447"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1016"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1" />
<metadata
id="metadata3807">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-6.7984033,-83.405656)">
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.24818733px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 191.75867,98.253193 H 18.036751 l 0.250672,23.805047 49.181436,31.70363 -3.87143,-30.38207 128.420741,3.3716 z"
id="path3898"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<path
style="stroke-width:0.42193675"
d="m 191.88842,112.50226 0.12975,14.24913 -14.71489,-0.19817 c -21.90426,-0.29498 -90.295127,-0.92186 -100.512257,-0.9213 l -8.900147,5.7e-4 v 14.06469 c 0,7.95668 -0.183273,14.06469 -0.422017,14.06469 -0.232125,0 -11.392904,-7.13332 -24.801736,-15.85181 l -24.3797,-15.85182 -0.125341,-11.90249 -0.125331,-11.902557 h 86.860959 86.86096 z"
id="path3900"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccsccssscccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="195.92358mm"
height="79.111778mm"
viewBox="0 0 195.92358 79.111778"
version="1.1"
id="svg3810"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="out_arrow.svg">
<defs
id="defs3804" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.9899495"
inkscape:cx="463.73105"
inkscape:cy="51.719447"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1016"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1" />
<metadata
id="metadata3807">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-6.7984033,-83.405656)">
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.24740678px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 18.283263,143.90286 H 192.0312 l -0.25071,-23.652 -49.1888,-31.499813 3.87201,30.186753 -128.439977,-3.34993 z"
id="path3898"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<path
style="stroke-width:0.42060974"
d="m 18.153493,129.7454 -0.12977,-14.15753 14.717103,0.19689 c 21.907537,0.2931 90.308644,0.91595 100.527304,0.91538 l 8.90148,-5.5e-4 v -13.97427 c 0,-7.905537 0.1833,-13.974273 0.42208,-13.974273 0.23216,0 11.39461,7.087454 24.80545,15.749903 l 24.38335,15.74991 0.12536,11.82597 0.12535,11.82603 H 105.15723 18.283263 Z"
id="path3900"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccsccssscccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -148,7 +148,6 @@ and_xport_sendNoConn( const XP_U8* buf, XP_U16 len, const XP_UCHAR* msgNo,
static void
and_xport_countChanged( void* closure, XP_U16 count )
{
XP_LOGF( "%s(count=%d)", __func__, count );
AndTransportProcs* aprocs = (AndTransportProcs*)closure;
if ( NULL != aprocs && NULL != aprocs->jxport ) {
JNIEnv* env = ENVFORME( aprocs->ti );

View file

@ -24,7 +24,7 @@
<string name="tile_button_txt_fmt">%1$s%2$d</string>
<string name="chat_sender_fmt">%1$s</string>
<string name="bkng_settings_text">设置</string>
<string name="str_placer_fmt" formatted="false">【#%d】%s%d</string>
<string name="str_placer_fmt" formatted="false">【#%1$d】%2$s%3$d</string>
<string name="group_cur_games">我的游戏</string>
<string name="group_new_games">新游戏</string>
<plurals name="group_name_fmt">

View file

@ -59,7 +59,7 @@
how far along they are. I may list "tiles left" someday
instead... -->
<plurals name="moves_fmt">
<item quantity="one">%1$d evom deyalp</item>
<item quantity="one">1 evom deyalp</item>
<item quantity="other">%1$d sevom deyalp</item>
</plurals>
<!-- When you select the gamel_menu_delete_all menuitem or
@ -2204,8 +2204,6 @@
<string name="xlations_locale">Ekaf elacol rof noitalsnart</string>
<string name="enable_dupes_summary">Tpecca snoitativni erom naht ecno</string>
<string name="nag_intervals">Rednimer slavretni ,2setunim,1setunim(...)</string>
<string name="enable_nfc_toself_title">Elbane CFN ot fles</string>
<string name="enable_nfc_toself_summary">Ekaf noitativni ot dia gniggubed</string>
<string name="enable_sms_toself_title">Tiucric-trohs SMS ot fles</string>
<string name="enable_sms_toself_summary">Piks oidar nehw enohp srebmun emas</string>
<string name="force_radio_title">Dneterp ot evah oidar</string>

View file

@ -186,7 +186,7 @@
<string name="summary_relay_conn_fmt">Partida en joc a la sala «%1$s»</string>
<string name="summary_relay_gameover_fmt">Partida finalitzada en la sala «%1$s»</string>
<plurals name="moves_fmt">
<item quantity="one">%1$d jugada feta</item>
<item quantity="one">1 jugada feta</item>
<item quantity="other">%1$d jugades fetes</item>
</plurals>
<string name="button_delete">Suprimeix</string>
@ -265,7 +265,7 @@ que connecti via el repetidor.</string>
<string name="entering_trade">Toqueu les fitxes per a seleccionar-les…</string>
<string name="no_moves_made">(Encara no s\'ha fet cap jugada)</string>
<plurals name="invite_msg_fmt">
<item quantity="one">Aquesta partida està esperant a %1$d jugador remot. Si encara no ho heu fet, voleu convidar algú a unir-s\'hi?</item>
<item quantity="one">Aquesta partida està esperant a 1 jugador remot. Si encara no ho heu fet, voleu convidar algú a unir-s\'hi?</item>
<item quantity="other">Aquesta partida està esperant a %1$d jugadors remots. Si encara no ho heu fet, voleu convidar algú a unir-s\'hi?</item>
</plurals>
<string name="invite_if_nfc">O simplement toqueu per a convidar, si l\'altre aparell també té Android Beaming i és a prop.</string>
@ -285,7 +285,7 @@ que connecti via el repetidor.</string>
<item quantity="other">Queden %1$d fitxes al sac.</item>
</plurals>
<plurals name="strd_remains_expl_fmt">
<item quantity="one">Hi ha %1$d fitxa romanent als faristols ocults:
<item quantity="one">Hi ha 1 fitxa romanent als faristols ocults:
\n</item>
<item quantity="other">Hi ha %1$d fitxes romanents als faristols ocults:
\n</item>
@ -477,9 +477,9 @@ Introduïu el vostre nom aquí. S\'usarà en crear partides noves. (Podreu
<string name="new_dict_avail_fmt">Toqueu per a actualitzar %1$s</string>
<string name="new_app_avail_fmt">Versió nova de %1$s</string>
<string name="new_app_avail">Toqueu per a baixar i instal·lar</string>
<string name="str_winner_fmt" formatted="false">[Victòria] %s: %d</string>
<string name="str_placer_fmt" formatted="false">[#%d] %s: %d</string>
<string name="str_resigned_fmt" formatted="false">[Abandonament] %s: %d</string>
<string name="str_winner_fmt" formatted="false">[Victòria] %1$s: %2$d</string>
<string name="str_placer_fmt" formatted="false">[#%1$d] %2$s: %3$d</string>
<string name="str_resigned_fmt" formatted="false">[Abandonament] %1$s: %2$d</string>
<string name="inform_dict_title">Els diccionaris no coincideixen</string>
<string name="inform_dict_download">" (primer l\'heu de baixar.)"</string>
<string name="inform_dict_diffdict_fmt">Esteu usant el diccionari %1$s però l\'amfitrió de la partida usa %2$s. Voleu usar %3$s també?</string>
@ -722,8 +722,6 @@ Introduïu el vostre nom aquí. S\'usarà en crear partides noves. (Podreu
<string name="netstats_title">Estadístiques de la partida en xarxa</string>
<string name="git_rev_title">ID de la versió de codi font</string>
<string name="proxy_port">Port de l\'aparell repetidor</string>
<string name="enable_nfc_toself_title">Habilita NFC a un mateix</string>
<string name="enable_nfc_toself_summary">Simula la invitació per a ajudar a la depuració</string>
<string name="enable_sms_toself_title">SMS curtcircuit a un mateix</string>
<string name="force_radio_title">Simula tenir ràdio</string>
<string name="radio_name_real">No ho simulis</string>
@ -826,7 +824,7 @@ Introduïu el vostre nom aquí. S\'usarà en crear partides noves. (Podreu
aquesta partida. N\'estem esperant resposta.
Useu el botó de tornar a convidar si penseu que
la invitació no ha arribat.</item>
<item quantity="other">Ja heu enviat $1$d invitacions a
<item quantity="other">Ja heu enviat %1$d invitacions a
aquesta partida. N\'estem esperant resposta.
de %2$d destinataris. Useu el botó de tornar a
convidar si penseu que les invitacions no ha arribat.</item>
@ -838,7 +836,7 @@ de %2$d destinataris. Useu el botó de tornar a
<string name="invite_choice_relay">Internet/repetidor</string>
<string name="invite_choice_p2p">Directe per Wifi</string>
<string name="chat_hint">Escriviu aquí...</string>
<string name="notify_title_turn_fmt">Teniu el torn en la partida $1$s</string>
<string name="notify_title_turn_fmt">Teniu el torn en la partida %1$s</string>
<string name="invite_notice_title">Partida nova via invitació</string>
<string name="new_relay_body">Toqueu per a obrir una partida nova</string>
<string name="relay_invite_title">Invitació via repetidor</string>
@ -854,7 +852,7 @@ aparells seleccionats?</string>
(Ho esteu fent servir en una partida.)</item>
<item quantity="other">
(Ho esteu fent servir en $1$d partides.)</item>
(Ho esteu fent servir en %1$d partides.)</item>
</plurals>
<string name="rematch_name_fmt">%1$s</string>
<string name="button_reinvite">Torna a convidar</string>
@ -906,7 +904,7 @@ aparells seleccionats?</string>
<string name="bt_pair_settings">Aparella\'n més</string>
<plurals name="invite_relay_desc_fmt">
<item quantity="one">Comproveu l\'aparell que voleu convidar a la partida nova, després toqueu «%2$s».</item>
<item quantity="other">Comproveu els $1$d aparells que voleu convidar a la partida nova, després toqueu «%2$s».</item>
<item quantity="other">Comproveu els %1$d aparells que voleu convidar a la partida nova, després toqueu «%2$s».</item>
</plurals>
<string name="invite_p2p_desc_extra">Només es mostren els aparells que són disponibles actualment. Si un aparell proper no es mostra, assegureu-vos que la WiFi és habilitada, que té el CrossWords instal·lat i que el joc via «WiFi Direct» és habilitat.</string>
<string name="empty_p2p_inviter">Ara mateix no hi ha cap aparell accessible via WiFiDirect que tingui el CrossWords instal·lat.</string>
@ -915,13 +913,9 @@ aparells seleccionats?</string>
<item quantity="one">Esteu segur de voler suprimir el número de telèfon seleccionat?</item>
<item quantity="other">Esteu segur de voler suprimir els %1$d números de telèfon seleccionats?</item>
</plurals>
<plurals name="invite_p2p_desc_fmt">
<item quantity="one">Seleccioneu el nom de l\'aparell WiFiDirect que voleu convidar a la partida nova, després toqueu «%2$s».</item>
<item quantity="other">Seleccioneu els noms dels aparells WiFiDirect que voleu convidar a la partida nova, després toqueu «%2$s».</item>
</plurals>
<plurals name="confirm_clear_relay_fmt">
<item quantity="one">Esteu segur de voler suprimir el registre RelayID seleccionat?</item>
<item quantity="other">Esteu segur de voler suprimir els registres RelayID seleccionats?</item>
<item quantity="other">Esteu segur de voler suprimir els %1$d registres RelayID seleccionats?</item>
</plurals>
<string name="invites_net_fmt">S\'han enviat les invitacions per a la partida connectada via %1$s:</string>
<string name="warn_relay_disabled">El joc via repetidor es troba inhabilitat en aquest aparell. No s\'enviarà ni rebrà cap moviment via el repetidor.</string>
@ -939,7 +933,7 @@ aparells seleccionats?</string>
<string name="rel_invite_title">Títol de la invitació per repetidor</string>
<string name="fetching_from_relay">Recupera les partides del repetidor</string>
<string name="rematch_sent_toast">S\'han enviat les invitacions per a tornar a jugar</string>
<string name="not_again_dfltname_fmt">Esteu fent servir el nom de jugador predeterminat «%1%s». Voleu personalitzar-lo amb el vostre nom abans de crear aquesta partida\?</string>
<string name="not_again_dfltname_fmt">Esteu fent servir el nom de jugador predeterminat «%1$s». Voleu personalitzar-lo amb el vostre nom abans de crear aquesta partida\?</string>
<string name="sms_invite_rationale">CrossWords necessita permís per a enviar una invitació via SMS.</string>
<string name="button_ask_again">Torna-ho a demanar</string>
<string name="sms_send_failed">No s\'ha pogut enviar l\'SMS</string>
@ -976,7 +970,7 @@ aparells seleccionats?</string>
<string name="ok_with_robots">D\'acord (robots)</string>
<string name="sms_invite_flakey">Aquesta opció nova executa l\'aplicació de missatgeria SMS amb una invitació llesta per a enviar, si funciona. Cada aplicació de missatgeria SMS és diferent i algunes no cooperen.</string>
<string name="sms_invite_fail">No és pot iniciar l\'aplicació de missatgeria SMS</string>
<string name="msg_dev_deleted_fmt">La partida amb nom «%1%s» s\'ha suprimit en un altre aparell. No hi podreu jugar mai més.</string>
<string name="msg_dev_deleted_fmt">La partida amb nom «%1$s» s\'ha suprimit en un altre aparell. No hi podreu jugar mai més.</string>
<string name="invite_choice_data_sms">SMS de dades</string>
<string name="empty_bt_inviter">Encara no s\'ha detectat cap aparell aparellat.</string>
<string name="checkbox_archive">Mou a l\'arxiu</string>

View file

@ -59,7 +59,7 @@
how far along they are. I may list "tiles left" someday
instead... -->
<plurals name="moves_fmt">
<item quantity="one">%1$d MOVE PLAYED</item>
<item quantity="one">1 MOVE PLAYED</item>
<item quantity="other">%1$d MOVES PLAYED</item>
</plurals>
<!-- When you select the gamel_menu_delete_all menuitem or
@ -2204,8 +2204,6 @@
<string name="xlations_locale">FAKE LOCALE FOR TRANSLATION</string>
<string name="enable_dupes_summary">ACCEPT INVITATIONS MORE THAN ONCE</string>
<string name="nag_intervals">REMINDER INTERVALS (MINUTES1,MINUTES2,...)</string>
<string name="enable_nfc_toself_title">ENABLE NFC TO SELF</string>
<string name="enable_nfc_toself_summary">FAKE INVITATION TO AID DEBUGGING</string>
<string name="enable_sms_toself_title">SHORT-CIRCUIT SMS TO SELF</string>
<string name="enable_sms_toself_summary">SKIP RADIO WHEN PHONE NUMBERS SAME</string>
<string name="force_radio_title">PRETEND TO HAVE RADIO</string>

View file

@ -84,7 +84,6 @@
<string name="password_label">Heslo</string>
<string name="player_edit_title">Hráč</string>
<string name="players_label_standalone">Hráči</string>
<string name="players_label_host_fmt">Hráči -- lokální a očekávaní</string>
<string name="button_add_player">Přidat hráče</string>
<string name="button_juggle_players">Přehodit hráče</string>
<string name="dicts_item_select">Nastavit jako výchozí</string>
@ -131,7 +130,6 @@
<string name="msg_no_room">Žádný server si nezaregistroval místnost s tímto jménem.</string>
<string name="msg_dup_room">Jiný server si již zaregistroval místnost s tímto jménem. Přejmenujte ji nebo to zkuste později.</string>
<string name="msg_lost_other">Relay ztratil kontakt s nějakým zařízením ve hře.</string>
<string name="ids_badwords_fmt">Slovo[a] %1$s nebylo nalezeno ve slovníku.</string>
<string name="badwords_accept"> Chcete přesto přijmout tento tah?</string>
<string name="badwords_lost"> Tah ztracen.</string>
<string name="badwords_title">Neplatné slovo[a]</string>

View file

@ -12,7 +12,7 @@
<string name="summary_invites_out">Eingeladene Spieler</string>
<string name="gameOver">Partie beendet</string>
<plurals name="moves_fmt">
<item quantity="one">%1$d Zug gespielt</item>
<item quantity="one">1 Zug gespielt</item>
<item quantity="other">%1$d Züge gespielt</item>
</plurals>
<string name="button_delete">Löschen</string>
@ -102,7 +102,7 @@
<string name="players_label_standalone">Spieler (zum Bearbeiten antippen)</string>
<string name="players_label_host_fmt">Spieler (%1$d lokal, %2$d extern)</string>
<string name="join_room">Öffentlichen Raum betreten</string>
<string name="public_names_progress_fmt">Öffentliche Räume für %1$ d-Spieler-Partien in %2$ s werden geholt.</string>
<string name="public_names_progress_fmt">Öffentliche Räume für %1$d-Spieler-Partien in %2$s werden geholt.</string>
<string name="no_name_found_fmt">Keine öffentlichen Räume für %1$d-Spieler-Partien in %2$s gefunden. Versuchen Sie zu aktualisieren oder erzeugen Sie Ihre eigenen.</string>
<string name="use_timer">Spieluhr aktivieren</string>
<string name="phonies_spinner_prompt">Wie „falsche Wörter\" behandelt werden (Wörter, die nicht in der Wortliste sind)</string>
@ -128,7 +128,7 @@
<string name="entering_trade">Spielsteine durch Antippen auswählen …</string>
<string name="no_moves_made">(Noch keine Züge)</string>
<plurals name="invite_msg_fmt">
<item quantity="one">Diese Partie wartet auf %1$d externen Spieler. Wollen Sie noch jemanden einladen falls Sie das nicht bereits haben?</item>
<item quantity="one">Diese Partie wartet auf 1 externen Spieler. Wollen Sie noch jemanden einladen falls Sie das nicht bereits haben?</item>
<item quantity="other">Diese Partie wartet auf %1$d externe Spieler. Wollen Sie noch jemanden einladen falls Sie das nicht bereits haben?</item>
</plurals>
<plurals name="invite_sent_fmt">
@ -330,7 +330,7 @@
<string name="button_save">Speichern</string>
<string name="button_discard">Verwerfen</string>
<string name="button_retry">Erneut versuchen</string>
<string name="dup_game_query_fmt">Sie haben bereits eine Partie, die anscheinend von der selben Einladung erzeugt wurde (auf 1$s). Sind Sie sicher, dass Sie eine weitere erzeugen wollen?</string>
<string name="dup_game_query_fmt">Sie haben bereits eine Partie, die anscheinend von der selben Einladung erzeugt wurde (auf %1$s). Sind Sie sicher, dass Sie eine weitere erzeugen wollen?</string>
<string name="info_title">Zur Information …</string>
<string name="tile_button_txt_fmt">%1$s (%2$d)</string>
<string name="tile_pick_summary_fmt">Aktuelle Auswahl: %1$s</string>
@ -506,11 +506,11 @@
<string name="gamel_menu_checkupdates">Auf Aktualisierungen prüfen</string>
<string name="checkupdates_none_found">Alles ist auf dem neuesten Stand.</string>
<string name="new_dict_avail">Neue Wortliste verfügbar</string>
<string name="new_dict_avail_fmt">Tippen Sie, um %1$ s zu aktualisieren</string>
<string name="new_app_avail_fmt">Neue Version von %1$ s</string>
<string name="new_dict_avail_fmt">Tippen Sie, um %1$s zu aktualisieren</string>
<string name="new_app_avail_fmt">Neue Version von %1$s</string>
<string name="new_app_avail">Zum Herunterladen und Installieren antippen</string>
<string name="str_winner_fmt" formatted="false">[Gewinner] %s: %d</string>
<string name="str_resigned_fmt" formatted="false">[Aufgegeben] %s: %d</string>
<string name="str_winner_fmt" formatted="false">[Gewinner] %1$s: %2$d</string>
<string name="str_resigned_fmt" formatted="false">[Aufgegeben] %1$s: %2$d</string>
<string name="inform_dict_diffversion_fmt">Sie und der Server dieser Partie benutzen verschiedene Versionen der Wortliste %1$s.</string>
<string name="inform_dict_title">Wortlisten stimmen nicht überein</string>
<string name="inform_dict_diffdict_fmt">Sie benutzen die Wortliste %1$s, aber der Server der Partie benutzt %2$s. Wollen Sie auch %3$s benutzen?</string>
@ -630,7 +630,7 @@
<string name="loc_item_check">Überprüfen</string>
<string name="loc_item_copy_eng">Englisch kopieren</string>
<string name="loc_fmts_mismatch">Ungültige Übersetzung: Eine übersetzte Zeichenfolge muss die gleichen Formatierungszeichen enthalten (z. B. %1$s) wie das Original.</string>
<string name="not_again_fmt_expl">Diese Zeichenfolge enthält spezielle Formatierungszeichen (z. B. 1$s). Vergewissern Sie sich, das Ihre Übersetzung die gleichen wie das Original enthält.
<string name="not_again_fmt_expl">Diese Zeichenfolge enthält spezielle Formatierungszeichen (z. B. %1$s). Vergewissern Sie sich, das Ihre Übersetzung die gleichen wie das Original enthält.
\n
\n(Sie können erst speichern, wenn das der Fall ist.)</string>
<string name="remote_empty">Wortliste wird vom Server geladen …</string>
@ -675,7 +675,7 @@
<string name="prev_player">Ihr Gegner</string>
<string name="lmi_pass_fmt">%1$s hat gepasst (0 Punkte)</string>
<plurals name="lmi_move_fmt">
<item quantity="one">%1$s hat %2$s gespielt im Wert von %3$d Punkten</item>
<item quantity="one">%1$s hat %2$s gespielt im Wert von 1 Punkten</item>
<item quantity="other"/>
</plurals>
<plurals name="lmi_trade_fmt">
@ -740,13 +740,12 @@
<string name="gamel_menu_writegit">Git-Informationen in die Zwischenablage kopieren</string>
<string name="enable_dupes_summary">Einladungen mehrfach annehmen</string>
<string name="nag_intervals">Erinnerungsintervall (Minuten1, Minuten2, …)</string>
<string name="enable_nfc_toself_summary">Pseudo-Einladung zur Fehlersuche</string>
<string name="radio_name_gsm">GSM</string>
<string name="radio_name_cdma">CDMA</string>
<string name="got_langdict_title">Standard-Wortliste für Sprache holen</string>
<string name="got_langdict_summary">Kein zweites Mal versuchen</string>
<string name="pref_item_update_title">Zwischen den einzelnen Versionen aktualisieren</string>
<string name="checking_for_fmt">Wortlisten werden in %1$ s gesucht …</string>
<string name="checking_for_fmt">Wortlisten werden in %1$s gesucht …</string>
<string name="db_store_done">Schreiben auf SD-Karte abgeschlossen.</string>
<string name="seeking_relay">Verbinde mit Zwischenstation …</string>
<string name="no_relay_conn">Diese Partie ist für eine Verbindung über die Zwischenstation (Internet) konfiguriert, konnte aber keine Verbindung aufbauen.
@ -804,7 +803,7 @@
<item quantity="other"/>
</plurals>
<plurals name="strd_remains_expl_fmt">
<item quantity="one">Noch %1$d Spielstein in den nicht gezeigten Ablagen:
<item quantity="one">Noch 1 Spielstein in den nicht gezeigten Ablagen:
\n</item>
<item quantity="other">"Noch %1$d Spielsteine im Säckchen und den nicht gezeigten Ablagen: "</item>
</plurals>
@ -848,7 +847,7 @@
\n
\n(Wird von %1$d Partien benutzt.)"</item>
</plurals>
<string name="str_placer_fmt" formatted="false">[Nr. %d] %s: %d</string>
<string name="str_placer_fmt" formatted="false">[Nr. %1$d] %2$s: %3$d</string>
<string name="inform_dict_download">" (Sie müssen es zuerst herunterladen.)"</string>
<string name="list_group_default">Neue Partien hier einstellen</string>
<string name="list_group_moveup">Nach oben verschieben</string>
@ -881,7 +880,6 @@
<string name="gamel_menu_storedb">Partien auf SD-Kartie speichern</string>
<string name="enable_dupes_title">Doppelte Einladungen annehmen</string>
<string name="xlations_locale">Pseudo-Locale zum Übersetzen</string>
<string name="enable_nfc_toself_title">NFC-Selbstverbindung aktivieren</string>
<string name="enable_sms_toself_title">SMS-Selbstverbindung aktivieren</string>
<string name="enable_sms_toself_summary">Mobilfunk weglassen bei gleichen Nummern</string>
<string name="force_radio_title">Mobilfunk vortäuschen</string>

View file

@ -12,7 +12,7 @@
<string name="summary_invites_out_fmt">Jugadores invitados en la sala \"%1$s\"</string>
<string name="gameOver">Fin de la partida</string>
<plurals name="moves_fmt">
<item quantity="one">%1$d movimiento realizado</item>
<item quantity="one">1 movimiento realizado</item>
<item quantity="other">%1$d movimientos realizados</item>
</plurals>
<string name="button_delete">Borrar</string>
@ -121,10 +121,6 @@
<item quantity="one">"La partida está esperando un jugador remoto. Si aún no lo has hecho, ¿te gustaría invitar a alguien a unirse\?"</item>
<item quantity="other">"La partida está esperando %1$d jugadores remotos. Si aún no lo has hecho, ¿te gustaría invitar a alguien a unirse\?"</item>
</plurals>
<plurals name="invite_sent_fmt">
<item quantity="one">Ya has invitado a un jugador remoto a esta partida. Estamos esperando su respuesta. Por favor, pulsa el botón \"invitar de nuevo\" si crees que la invitación no se ha enviado.</item>
<item quantity="other">Ya has enviado %1$d invitaciones para esta partida. Estamos esperando sus respuestas. Por favor, pulsa el botón \"invitar de nuevo\" si crees que las invitaciones no se han enviado.</item>
</plurals>
<string name="invited_msg">Esta partida ha sido creada a partir de una invitación que has recibido. La partida comenzará tan pronto como se pueda conectar con el remitente y cualquier otro invitado.</string>
<string name="invite_if_nfc">O simplemente pulsa para invitar -- si el otro dispositivo tiene también Android Beaming y está cerca.</string>
<string name="invite_multiple">" (Estás esperando a varios jugadores remotos. No tienes que invitarlos a todos a la vez, pero esta alerta no será descartada hasta que todos hayan sido invitados y las invitaciones aceptadas.)"</string>

View file

@ -58,7 +58,7 @@
how far along they are. I may list "tiles left" someday
instead... -->
<plurals name="moves_fmt">
<item quantity="one">%1$d coup joué</item>
<item quantity="one">1 coup joué</item>
<item quantity="other">%1$d coups joués</item>
</plurals>
<!-- When you select the gamel_menu_delete_all menuitem or
@ -763,7 +763,7 @@ restants]</string>
<!--<string name="strd_remains_header_fmt">%1$d tiles left in pool.</string>-->
<!--<string name="strd_remains_header_fmt">%1$d jetons restants dans le sac.</string>-->
<plurals name="strd_remains_header_fmt">
<item quantity="one">%1$d jeton restant dans le sac.</item>
<item quantity="one">1 jeton restant dans le sac.</item>
<item quantity="other">%1$d jetons restants dans le sac.</item>
</plurals>
<!-- Intro to the paragraph lisiting all of the tiles remaining -->
@ -774,7 +774,7 @@ tous les chevalets :\n</string>-->
<plurals name="strd_remains_expl_fmt">
<item quantity="one">Un jeton restant dans les chevalets cachés :
\n</item>
<item quantity="other">%d jetons restants dans le sac et les chevalets cachés :
<item quantity="other">%1$d jetons restants dans le sac et les chevalets cachés :
\n</item>
</plurals>
<!-- text of dialog shown when the menu item board_menu_undo_last
@ -2252,11 +2252,11 @@ réseau.)</string>-->
<string name="new_app_avail">Toucher pour télécharger et installer</string>
<!-- Used in formatting final scores display -->
<!--<string name="str_winner_fmt" formatted="false">[Winner] %s: %d</string>-->
<string name="str_winner_fmt" formatted="false">[Vainqueur] %s : %d</string>
<string name="str_winner_fmt" formatted="false">[Vainqueur] %1$s : %2$d</string>
<!--<string name="str_resigned_fmt" formatted="false">[Resigned] %s: %d</string>-->
<string name="str_resigned_fmt" formatted="false">[Abandon] %s : %d</string>
<string name="str_resigned_fmt" formatted="false">[Abandon] %1$s : %2$d</string>
<!--<string name="str_placer_fmt" formatted="false">[#%d] %s: %d</string>-->
<string name="str_placer_fmt" formatted="false">[%de] %s : %d</string>
<string name="str_placer_fmt" formatted="false">[%1$de] %2$s : %3$d</string>
<!-- -->
<!--<string name="inform_dict_diffversion_fmt">You and the host of this
game are using different versions of the wordlist %1$s.</string>-->
@ -2653,7 +2653,7 @@ pour voir ce qui est disponible.</string>
<!--<string name="lmi_move_fmt">%1$s played %2$s for %3$d points</string>-->
<!--<string name="lmi_move_fmt">%1$s a joué %2$s pour %3$d points</string>-->
<plurals name="lmi_move_fmt">
<item quantity="one">%1$s a joué %2$s pour %3$d point</item>
<item quantity="one">%1$s a joué %2$s pour un point</item>
<item quantity="other">%1$s a joué %2$s pour %3$d points</item>
</plurals>
<!--<string name="lmi_trade_fmt">%1$s traded %2$d tiles</string>-->
@ -2763,7 +2763,7 @@ d\'autres joueurs quand elle sera ouverte.)</string>
<!--<string name="nplayers_fmt">%1$d player[s]</string>-->
<!--<string name="nplayers_fmt">%1$d joueur[s]</string>-->
<plurals name="nplayers_fmt">
<item quantity="one">%1$d joueur</item>
<item quantity="one">1 joueur</item>
<item quantity="other">%1$d joueurs</item>
</plurals>
<!--XLATE-ME-->
@ -2924,13 +2924,6 @@ les release builds)</string>
<!--XLATE-ME-->
<!--<string name="nag_intervals">Reminder intervals (minutes1,minutes2,...)</string>-->
<string name="nag_intervals">Intervalles des rappels (minutes1,minutes2,…)</string>
<!--XLATE-ME-->
<!--<string name="enable_nfc_toself_title">Enable NFC to self</string>-->
<string name="enable_nfc_toself_title">Activer la NFC à soi-même</string>
<!--XLATE-ME-->
<!--<string name="enable_nfc_toself_summary">Fake invitation to aid debugging</string>-->
<string name="enable_nfc_toself_summary">Fausse invitation pour aider le
débuggage</string>
<!--XLATE-ME-->
<!--<string name="enable_sms_toself_title">Short-circuit SMS to self</string>-->
<string name="enable_sms_toself_title">Court-circuiter les SMS vers soi-même</string>
@ -3145,10 +3138,6 @@ Merci de me faire savoir si vous aimez cette fonctionnalité, de signaler les pl
<string name="invite_choice_p2p">Wifi Direct</string>
<string name="bt_pair_settings">En appairer d\'autres</string>
<string name="p2p_invite_title">Invitation par WiFi direct</string>
<plurals name="invite_p2p_desc_fmt">
<item quantity="one">Sélectionnez le nom de l\'appareil WiFi Direct que vous souhaitez inviter à votre nouvelle partie, puis touchez \"%2$s\".</item>
<item quantity="other">Sélectionnez les noms des appareils WiFi Direct que vous souhaitez inviter à votre nouvelle partie, puis touchez \"%2$s\".</item>
</plurals>
<string name="invite_p2p_desc_extra">Seuls les appareils actuellement disponibles sont affichés. Si un appareil à proximité ne s\'affiche pas, assurez-vous que le WiFi est allumé, que CrossWords est installé, et que le WiFi Direct est activé.</string>
<string name="empty_p2p_inviter">Il n\'y a actuellement pas d\'appareils accessibles par WiFi Direct qui ont CrossWords installé.</string>
<string name="not_again_comms_p2p">Utiliser le WiFi Direct pour jouer contre un appareil faisant du WiFi Direct, sur lequel CrossWords est installé.</string>
@ -3212,7 +3201,7 @@ Vous pouvez la ré-ouvrir pour que la permission soit redemandée. Ou vous pouve
<string name="button_scan">Rescanner</string>
<plurals name="confirm_clear_bt_fmt">
<item quantity="one">Êtes-vous sûr de vouloir oublier l\'appareil sélectionné \?</item>
<item quantity="other">"Êtes-vous sûr de vouloir oublier les %1d appareils sélectionnés \?"</item>
<item quantity="other">"Êtes-vous sûr de vouloir oublier les %1$d appareils sélectionnés \?"</item>
</plurals>
<string name="confirm_clear_bt_postscript">"
\n

View file

@ -331,7 +331,7 @@
<string name="history_title">ゲームの履歴</string>
<string name="finalscores_title">最終スコア</string>
<string name="ids_endnow">辞めてもよろしいですか?</string>
<string name="str_resigned_fmt" formatted="false">[辞めました] %s: %d</string>
<string name="str_resigned_fmt" formatted="false">[辞めました] %1$s: %2$d</string>
<string name="query_title">質問…</string>
<string name="newbie_title">ヒントがあります</string>
<string name="button_notagain">今後表示しない</string>
@ -505,8 +505,8 @@
<string name="new_dict_avail_fmt">タップすると %1$s を更新</string>
<string name="new_app_avail_fmt">新しいバージョンの %1$s</string>
<string name="new_app_avail">タップすると、ダウンロードとインストール</string>
<string name="str_winner_fmt" formatted="false">[勝ち] %s: %d</string>
<string name="str_placer_fmt" formatted="false">[#%d] %s: %d</string>
<string name="str_winner_fmt" formatted="false">[勝ち] %1$s: %2$d</string>
<string name="str_placer_fmt" formatted="false">[#%1$d] %2$s: %3$d</string>
<string name="inform_dict_diffversion_fmt">あなたとこのゲームのホストは、異なるバージョンの単語リスト %1$s を使用しています。</string>
<string name="inform_dict_title">単語リストの不一致</string>
<string name="inform_dict_diffdict_fmt">あなたは単語リスト %1$s を使用していますが、ゲームのホストは %2$s を使用しています。%3$s も使用しますか?</string>
@ -727,8 +727,6 @@
<string name="xlations_locale">翻訳の擬似地域</string>
<string name="enable_dupes_summary">2 回以上の招待を受け入れます</string>
<string name="nag_intervals">リマインダーの間隔 (分1、分2、...)</string>
<string name="enable_nfc_toself_title">自分への NFC を有効にする</string>
<string name="enable_nfc_toself_summary">デバッグを支援するための擬似招待状</string>
<string name="enable_sms_toself_title">自分に SMS を短絡させる</string>
<string name="enable_sms_toself_summary">電話番号が同じときに無線をスキップします</string>
<string name="force_radio_title">無線があるとみなす</string>
@ -855,12 +853,6 @@
<string name="invite_choice_p2p">Wifi ダイレクト</string>
<string name="bt_pair_settings">ペアの詳細</string>
<string name="p2p_invite_title">WiFi ダイレクトへの招待</string>
<plurals name="invite_p2p_desc_fmt">
<item quantity="one">新しいゲームに招待する WiFi
ダイレクトデバイスの名前を選択し、
\"%2$s\" をタップしてください。</item>
<item quantity="other"/>
</plurals>
<string name="invite_p2p_desc_extra">現在利用可能なデバイスだけが表示されます。
近くのデバイス表示されていない場合、WiFi がオンになっていること、
クロスワードがインストールされていること、WiFi ダイレクトのプレイが

View file

@ -12,7 +12,7 @@
<string name="summary_invites_out_fmt">Spillere invitert til rom \"%1$s\"</string>
<string name="gameOver">Spill over</string>
<plurals name="moves_fmt">
<item quantity="one">%1$d trekk gjort</item>
<item quantity="one">1 trekk gjort</item>
<item quantity="other">%1$d trekk gjort</item>
</plurals>
<string name="button_delete">Slett</string>
@ -388,7 +388,7 @@
<string name="nag_warn_last_fmt">Siste advarsel: %1$s</string>
<string name="prev_player">Din motstander</string>
<plurals name="lmi_move_fmt">
<item quantity="one">%1$s spilte %2$s for %3$d poeng</item>
<item quantity="one">%1$s spilte %2$s for 1 poeng</item>
<item quantity="other"/>
</plurals>
<string name="lmi_phony_fmt">%1$s mistet en tur</string>
@ -566,10 +566,6 @@
<string name="invite_subject_fmt">La oss spille CrossWords (rom %1$s)</string>
<string name="invite_chooser_fmt">Send invitasjon via %1$s</string>
<string name="invite_chooser_email">e-post</string>
<plurals name="query_trade_fmt">
<item quantity="one">Er du sikker på at du ønsker å bytte valgt fil (%2$s)?</item>
<item quantity="other">Er du sikker på at du ønsker å bytte valgt filer (%2$s)?</item>
</plurals>
<string name="chat_title_fmt">Sludring for %1$s</string>
<string name="str_no_empties_in_turn">Tomme felter kan ikke dele spilte flis.</string>
<string name="str_two_tiles_first_move">Må spille to eller flere flis i første trekk.</string>
@ -623,8 +619,8 @@
\nDu kan skru på spill via SMS nå, eller senere.</string>
<string name="button_enable_relay">Skru på relé-spill</string>
<string name="button_disable_relay">Skru av relé-spill</string>
<string name="str_winner_fmt" formatted="false">[Seierherre] %s: %d</string>
<string name="str_resigned_fmt" formatted="false">[Resignert] %d: %d</string>
<string name="str_winner_fmt" formatted="false">[Seierherre] %1$s: %2$d</string>
<string name="str_resigned_fmt" formatted="false">[Resignert] %1$s: %2$d</string>
<string name="inform_dict_title">Samsvarte ikke med ordliste</string>
<string name="reload_new_dict_fmt">Gjeninnlaster spill med %1$s</string>
<string name="default_loc_summary">(Ikke i eksternt-/SD-kort -minne)</string>
@ -681,8 +677,6 @@
<string name="enable_dupes_title">Godta duplikatinvitasjoner</string>
<string name="xlations_locale">Juks til lokale for oversettelse</string>
<string name="nag_intervals">Påminnelsesintervall (minutt1,minutt2,…)</string>
<string name="enable_nfc_toself_title">Skru på NFC til egen enhet</string>
<string name="enable_nfc_toself_summary">Juks til invitasjon for å hjelpe i feilrettingsøyemed</string>
<string name="enable_smsproto_title">Bruk ny/eksperimentell SMS-kode</string>
<string name="enable_smsproto_summary">(Krever at motparten bruker det også)</string>
<string name="nfc_to_self">Send via NFC til egen ehet?</string>
@ -764,7 +758,7 @@
<string name="warn_relay_later">Du kan skru på relé-spill nå, eller senere.</string>
<string name="warn_relay_remove">Du kan skru på relé-spill nå, eller senere, eller fjerne det fra dette spillet.</string>
<string name="warn_relay_havegames">Er du sikker på at du ønsker å skru av spill på relé-et</string>
<string name="str_placer_fmt" formatted="false">[Nr.%d] %s: %d</string>
<string name="str_placer_fmt" formatted="false">[Nr.%1$d] %2$s: %3$d</string>
<string name="inform_dict_diffversion_fmt">Du og verten for dette spillet bruker forskjellige versjoner av ordlisten %1$s.</string>
<string name="square_tiles_summary">Selv om de kan være høyere</string>
<string name="enable_nfc">NFC er skrudd av på denne enheten. Du kan bruke systeminnstillingene for å skru det på.</string>
@ -798,10 +792,6 @@
\n
\n(Sletting av arkivgruppen er trygt fordi den vil bli gjenopprettet igjen når det trengs.)</string>
<string name="pick_faceup">Plukk flis med bokstavene avdekt</string>
<plurals name="invite_p2p_desc_fmt">
<item quantity="one">Velg navnet på Wi-Fi Direct-enheten du ønsker å invitere til spillet ditt, trykk så \"%2$s\".</item>
<item quantity="other">Velg navnet på Wi-Fi Direct-enhetene du ønsker å invitere til spillet ditt, trykk så \"%2$s\".</item>
</plurals>
<string name="invite_p2p_desc_extra">Kun spillere som er tilgjengelig vises. Hvis en enhet i nærheten ikke vises, forsikre deg om at Wi-Fi er slått på, og at CrossWords er installert, og at spill via Wi-Fi Direct er påslått.</string>
<string name="empty_relay_inviter">Listen over enheter er tom. Bruk \"Skann spill\"-knappen for å skanne dine gamle spill for motstandere. Bruk \"+\"knappen for å skrive inn enhets-ID-er direkte.</string>
<plurals name="confirm_clear_relay_fmt">

View file

@ -15,7 +15,7 @@
<string name="summary_relay_gameover_fmt">Spel voorbij is kamer \"%1$s\"</string>
<string name="gameOver">Spel voorbij</string>
<plurals name="moves_fmt">
<item quantity="one">%1$d zet gespeeld</item>
<item quantity="one">1 zet gespeeld</item>
<item quantity="other">%1$d zetten gespeeld</item>
</plurals>
<string name="button_delete">Verwijder</string>
@ -41,11 +41,11 @@
<string name="rename_label">Verander de naam van dit spel naar:</string>
<string name="rename_label_caveat">Verander de naam van dit spel (op dit apparaat) naar:</string>
<plurals name="confirm_seldeletes_fmt">
<item quantity="one">Weet je zeker dat je %1$d geselecteerd spel wilt verwijderen? Deze actie kan niet ongedaan gemaakt worden.</item>
<item quantity="one">Weet je zeker dat je 1 geselecteerd spel wilt verwijderen? Deze actie kan niet ongedaan gemaakt worden.</item>
<item quantity="other">Weet je zeker dat je %1$d geselecteerde spellen wilt verwijderen? Deze actie kan niet ongedaan gemaakt worden.</item>
</plurals>
<plurals name="confirm_reset_fmt">
<item quantity="one">Weet je zeker dat je %1$d geselecteerd spel wilt resetten?\n\n(Resetten verwijderd alle zetten en verbindingsinformatie.)</item>
<item quantity="one">Weet je zeker dat je 1 geselecteerd spel wilt resetten?\n\n(Resetten verwijderd alle zetten en verbindingsinformatie.)</item>
<item quantity="other">Weet je zeker dat je %1$d geselecteerde spellen wilt resetten?\n\n(Resetten verwijderd alle zetten en verbindingsinformatie.)</item>
</plurals>
<string name="title_dicts_list">CrossWords Woordenlijsten</string>
@ -120,14 +120,14 @@
<string name="bonus_w3x_summary">3W</string>
<string name="no_moves_made">(Nog geen zetten gedaan)</string>
<plurals name="invite_msg_fmt">
<item quantity="one">Dit spel wacht op %1$d speler op afstand. Wil je iemand uitnodigen om mee te doen, indien je dit nog niet gedaan hebt?</item>
<item quantity="one">Dit spel wacht op 1 speler op afstand. Wil je iemand uitnodigen om mee te doen, indien je dit nog niet gedaan hebt?</item>
<item quantity="other">Dit spel wacht op %1$d spelers op afstand. Wil je iemand uitnodigen om mee te doen, indien je dit nog niet gedaan hebt?</item>
</plurals>
<string name="invite_if_nfc">Of druk om uit te nodigen, indien het andere apparaat dichtbij is en Android Beam (NFC) ondersteund.</string>
<string name="invite_multiple">" (Je verwacht meerdere spelers op afstand. Je hoeft ze niet allemaal tegelijk uit te nodigen, maar dit bericht zal niet verdwijnen totdat iedereen uitgenodigd is en de uitnodiging geaccepteerd heeft.)"</string>
<string name="pts">pntn</string>
<plurals name="msg_relay_waiting_fmt">
<item quantity="one">Apparaat %1$d verbonden met relay in kamer \"%2$s\". Wachtend op %3$d speler.</item>
<item quantity="one">Apparaat 1 verbonden met relay in kamer \"%2$s\". Wachtend op %1$d speler.</item>
<item quantity="other">Apparaat %1$d verbonden met relay in kamer \"%2$s\". Wachtend op %3$d spelers.</item>
</plurals>
<string name="msg_relay_all_here_fmt">Alle spelers spelers zijn hier in kamer \"%1$s\".</string>
@ -181,11 +181,11 @@
<string name="str_bonus_all">Bonus voor het gebruiken van alle letters: 50\n</string>
<string name="strd_turn_score_fmt">Score voor beurt: %1$d\n</string>
<plurals name="strd_remains_header_fmt">
<item quantity="one">%1$d letter in de zak.</item>
<item quantity="one">1 letter in de zak.</item>
<item quantity="other">%1$d letters in de zak.</item>
</plurals>
<plurals name="strd_remains_expl_fmt">
<item quantity="one">%1$d letter in de zak en op alle rekken:\n</item>
<item quantity="one">1 letter in de zak en op alle rekken:\n</item>
<item quantity="other">%1$d letters in de zak en op alle rekken:\n</item>
</plurals>
<string name="confirm_undo_last">Weet je zeker dat je de laatste zet ongedaan wilt maken? (Je kan deze niet opnieuw uitvoeren.)</string>
@ -439,7 +439,7 @@
<string name="new_name_body_fmt">%1$s heeft je uitgenodigd om te spelen</string>
<string name="button_sms_add">Importeer contact</string>
<plurals name="invite_sms_desc_fmt">
<item quantity="one">Selecteer %1$d telefoonnummer dat je voor je nieuwe spel uit wilt nodigen en druk op \"%2$s\".</item>
<item quantity="one">Selecteer 1 telefoonnummer dat je voor je nieuwe spel uit wilt nodigen en druk op \"%2$s\".</item>
<item quantity="other">Selecteer de %1$d telefoonnummers die je voor je nieuwe spel uit wilt nodigen en druk op \"%2$s\".</item>
</plurals>
<string name="manual_owner_name">(Niet in contacten)</string>
@ -496,12 +496,12 @@
<string name="new_dict_avail_fmt">Druk om %1$s te updaten</string>
<string name="new_app_avail_fmt">Nieuwe versie van %1$s</string>
<string name="new_app_avail">Druk om te downloaden en te installeren</string>
<string name="str_winner_fmt" formatted="false">[Winnaar] %s: %d</string>
<string name="str_resigned_fmt" formatted="false">[Opgegeven] %s: %d</string>
<string name="str_placer_fmt" formatted="false">[#%d] %s: %d</string>
<string name="str_winner_fmt" formatted="false">[Winnaar] %1$s: %2$d</string>
<string name="str_resigned_fmt" formatted="false">[Opgegeven] %1$s: %2$d</string>
<string name="str_placer_fmt" formatted="false">[#%1$d] %2$s: %3$d</string>
<string name="inform_dict_diffversion_fmt">Jij en de host van dit spel gebruiken een verschillende versie van de woordenlijst %1$s.</string>
<string name="inform_dict_title">Woordenlijsten komen niet overeen</string>
<string name="inform_dict_diffdict_fmt">Jij gebruikt woordenlijst %1$s, maar de host gebruikt %2$s. Wil je ook %2$s gebruiken?</string>
<string name="inform_dict_diffdict_fmt">Jij gebruikt woordenlijst %1$s, maar de host gebruikt %2$s. Wil je ook %3$s gebruiken?</string>
<string name="inform_dict_download">" (Je zult deze eerst moeten downloaden.)"</string>
<string name="reload_new_dict_fmt">Spel herladen met %1$s</string>
<string name="missing_dict_title">Wachten op speluitnodiging</string>
@ -661,7 +661,7 @@
<string name="prev_player">Jouw tegenstander</string>
<string name="lmi_pass_fmt">%1$s heeft de beurt overgeslagen (0 punten)</string>
<plurals name="lmi_move_fmt">
<item quantity="one">%1$s speelde %2$s voor %3$d punt</item>
<item quantity="one">%1$s speelde %2$s voor 1 punt</item>
<item quantity="other">%1$s speelde %2$s voor %3$d punten</item>
</plurals>
<plurals name="lmi_trade_fmt">
@ -682,7 +682,7 @@
<string name="use_defaults">Standaard</string>
<string name="nplayers_prompt">Hoeveelheid op dit apparaat</string>
<plurals name="nplayers_fmt">
<item quantity="one">%1$d speler</item>
<item quantity="one">1 speler</item>
<item quantity="other">%1$d spelers</item>
</plurals>
<string name="err_dup_invite_fmt">Dubbele uitnodiging geweigerd: apparaat \"%1$s\" heeft al een uitnodiging voor dit spel geaccepteerd.</string>
@ -729,8 +729,6 @@
<string name="xlations_locale">Neppe taal voor vertalingen</string>
<string name="enable_dupes_summary">Accepteer uitnodigingen meer dan eens</string>
<string name="nag_intervals">Herinnering intervallen (minuten1,minuten2,...)</string>
<string name="enable_nfc_toself_title">Schakel NFC naar zelf in</string>
<string name="enable_nfc_toself_summary">Nepuitnodiging om debuggen te ondersteunen</string>
<string name="enable_sms_toself_title">Stuur SMS berichten naar zelf</string>
<string name="enable_sms_toself_summary">Schakel radio over als telefoonnummers gelijk zijn</string>
<string name="force_radio_title">Doe net alsof er een radio is</string>

View file

@ -217,7 +217,7 @@
<string name="not_again_dfltname_fmt">Używasz domyślnej nazwy gracza \"%1$s\". Czy chciałbyś spersonalizować swoje imię przed utworzeniem tej gry\?</string>
<string name="robot_name_fmt">%1$s (robot)</string>
<plurals name="moves_fmt">
<item quantity="one">%1$d ruch zagrany</item>
<item quantity="one">1 ruch zagrany</item>
<item quantity="few">%1$d ruchy zagrane</item>
<item quantity="many">%1$d ruchów zagranych</item>
</plurals>
@ -323,7 +323,7 @@
\n</string>
<string name="strs_move_across_fmt">przenieś (od %1$s w poprzek)
\n</string>
<string name="strs_move_down_fmt">przenieś (z %1$ w dół)
<string name="strs_move_down_fmt">przenieś (z %1$s w dół)
\n</string>
<string name="strs_tray_at_start_fmt">Półka na początku: %1$s
\n</string>
@ -569,9 +569,8 @@
<string name="new_dict_avail_fmt">Stuknij, aby zaktualizować %1$s</string>
<string name="new_app_avail_fmt">Nowa wersja %1$s</string>
<string name="new_app_avail">Stuknij, aby pobrać i zainstalować</string>
<string name="str_winner_fmt" formatted="false">[Zwycięzca] %1$s</string>
<string name="str_resigned_fmt" formatted="false">[Zrezygnował] %s: %d</string>
<string name="str_placer_fmt" formatted="false">[#%d] %s: %d</string>
<string name="str_resigned_fmt" formatted="false">[Zrezygnował] %1$s: %2$d</string>
<string name="str_placer_fmt" formatted="false">[#%1$d] %2$s: %3$d</string>
<string name="inform_dict_diffversion_fmt">Ty i gospodarz tej gry używacie różnych wersji listy słów %1$s.</string>
<string name="inform_dict_title">Niedopasowanie listy słów</string>
<string name="inform_dict_diffdict_fmt">Używasz listy słów %1$s, ale gospodarz gry używa %2$s. Czy chciałbyś również użyć %3$s\?</string>
@ -709,7 +708,7 @@
<string name="prev_player">Twój przeciwnik</string>
<string name="lmi_pass_fmt">%1$s minęło (0 punktów)</string>
<plurals name="lmi_move_fmt">
<item quantity="one">%1$s zagrał %2$s za %3$d punktów</item>
<item quantity="one">%1$s zagrał %2$s za 1 punktów</item>
<item quantity="few"/>
<item quantity="many"/>
</plurals>
@ -784,8 +783,6 @@
<string name="xlations_locale">Fałszywy język do tłumaczenia</string>
<string name="enable_dupes_summary">Akceptuj zaproszenia więcej niż raz</string>
<string name="nag_intervals">Przypomnienie w odstępach (1 minuty, 2 minut,...)</string>
<string name="enable_nfc_toself_title">Włącz NFC dla siebie (samoczynnie\?)</string>
<string name="enable_nfc_toself_summary">Fałszywe zaproszenie do pomocy w debugowaniu</string>
<string name="enable_sms_toself_title">Akceptuj SMS do siebie</string>
<string name="radio_name_gsm">GSM</string>
<string name="radio_name_cdma">CDMA</string>
@ -907,7 +904,7 @@
<string name="pick_faceup">Wybierz odkryte kafelki</string>
<string name="menu_juggle">Wymieszaj kafelki</string>
<string name="pct_suffix">" %."</string>
<string name="add_to_study_fmt">Dodaj %1$ do listy nauki</string>
<string name="add_to_study_fmt">Dodaj %1$s do listy nauki</string>
<string name="title_studyon">Włącz listę nauki</string>
<string name="gamel_menu_study">Lista do nauczenia…</string>
<string name="add_done_fmt">%1$s dodane do %2$s listy do nauki</string>

View file

@ -1744,17 +1744,17 @@
<string name="show_wordlist_browser">Listas de palavras</string>
<string name="rename_label_caveat">Altere o nome deste jogo (apenas neste dispositivo) para:</string>
<plurals name="confirm_seldeletes_fmt">
<item quantity="one">Você tem certeza que deseja excluir o %1$d jogo selecionado? Esta ação não poderá ser desfeita.</item>
<item quantity="one">Você tem certeza que deseja excluir o 1 jogo selecionado? Esta ação não poderá ser desfeita.</item>
<item quantity="other">Você tem certeza que deseja excluir os %1$d jogos selecionados? Esta ação não poderá ser desfeita.</item>
</plurals>
<plurals name="confirm_reset_fmt">
<item quantity="one">Você tem certeza de que deseja redefinir o %1$d jogo selecionado?\n\n(Redefinir apaga todos os movimentos e as informações de conexão.)</item>
<item quantity="one">Você tem certeza de que deseja redefinir o 1 jogo selecionado?\n\n(Redefinir apaga todos os movimentos e as informações de conexão.)</item>
<item quantity="other">Você tem certeza de que deseja redefinir os %1$d jogos selecionados?\n\n(Redefinir apaga todos os movimentos e as informações de conexão.)</item>
</plurals>
<string name="summary_invites_out">Jogadores convidados</string>
<string name="summary_invites_out_fmt">Jogadores convidados para a sala \"%1$s\"</string>
<plurals name="moves_fmt">
<item quantity="one">%1$d movimento jogado</item>
<item quantity="one">1 movimento jogado</item>
<item quantity="other">%1$d movimenotos jogados</item>
</plurals>
<plurals name="confirm_delete_dict_fmt">
@ -1765,7 +1765,7 @@
<string name="set_default_message_fmt">Para quais jogadores deve a list de palavras %1$s ser o predefinição para os jogos novos\? (O idioma de %2$s será a predefinição para ambos.)</string>
<string name="connect_label_fmt">Conexão (através de %1$s)</string>
<plurals name="invite_msg_fmt">
<item quantity="one">Este jogo está aguardando %1$d jogador remoto. Gostaria de convidar alguém para se juntar -- supondo que você ainda não o fez\?</item>
<item quantity="one">Este jogo está aguardando 1 jogador remoto. Gostaria de convidar alguém para se juntar -- supondo que você ainda não o fez\?</item>
<item quantity="other">Este jogo está aguardando %1$d jogadores remotos. Gostaria de convidar alguém para se juntar -- supondo que você ainda não o fez\?</item>
</plurals>
<string name="list_item_netstats">Conexões…</string>

View file

@ -950,7 +950,6 @@
<string name="msg_dev_deleted">XLATE ME: This game has been deleted on
another device. You will not be able to play any
further.</string>
<string name="ids_badwords_fmt">Slovo[á] %1$s nebolo nájdené v slovníku.</string>
<string name="badwords_accept"> Chcete napriek tomu potvrdiť tento ťah?</string>
<string name="badwords_lost"> Ťah stratený.</string>
<string name="badwords_title">Neplatné slovo[á]</string>

View file

@ -12,6 +12,7 @@ s_prefix = 'XLATE ME: '
# languages in which it's ok to make a standalone quantity="one" into
# quantity="other"
g_oneToOthers = ['values-ja']
g_formatsPat = re.compile( '(%\d\$[sd])', re.DOTALL | re.MULTILINE )
sComment = """
DO NOT EDIT THIS FILE!!!!
@ -19,6 +20,10 @@ sComment = """
Any changes you make to it will be lost.
"""
def exitWithError(msg):
print 'ERROR:', msg
sys.exit(1)
def usage():
print "usage:", sys.argv[0], '[-k <list-o-dirs>]'
sys.exit(1)
@ -85,9 +90,8 @@ def pluralsIsSame(engNames, plurals):
for item in plurals.getchildren():
text = item.text
if not text or 0 == len(text):
print "bogus empty plurals item in", plurals.get('name')
exitWithError( "bogus empty plurals item in " + plurals.get('name'))
engItem = engItem
sys.exit(1)
quantity = item.get('quantity')
if quantity in strings:
@ -119,8 +123,7 @@ def checkPlurals( engNames, elem, src, verbose ):
for item in elem.getchildren():
if 0 == len(item.text):
ok = False
print 'bad empty item', name
sys.exit(1)
exitWithError( 'bad empty item ' + name )
return ok
def loadPlural(plural):
@ -138,11 +141,15 @@ def writeDoc(doc, src, dest):
out = open( dest, "w" )
out.write( etree.tostring( doc, pretty_print=True, encoding="utf-8", xml_declaration=True ) )
def exitWithFormatError(engSet, otherSet, name, path):
exitWithError( 'formats set mismatch: ' + str(engSet) \
+ ' vs ' + str(otherSet) + '; ' + name \
+ ' in file ' + path )
def checkOrConvertString(engNames, elem, verbose):
name = elem.get('name')
if not elem.text:
print "ERROR: elem", name, "is empty"
sys.exit(1)
exitWithError( 'elem' + name + " is empty" )
elif not name in engNames or elem.text.startswith(s_prefix):
ok = False
elif not 'string' == engNames[name]['type']:
@ -167,7 +174,7 @@ def checkOrConvertString(engNames, elem, verbose):
ok = True
return ok
def checkAndCopy( parser, engNames, src, dest, verbose ):
def checkAndCopy( parser, engNames, engFormats, src, dest, verbose ):
doc = etree.parse(src, parser)
# strings
@ -179,8 +186,43 @@ def checkAndCopy( parser, engNames, src, dest, verbose ):
if not checkPlurals(engNames, elem, src, verbose):
elem.getparent().remove(elem)
formats = getFormats( doc, src )
for name in formats:
if name in formats and not engFormats[name] == formats[name]:
exitWithFormatError( engFormats[name], formats[name], name, dest )
writeDoc(doc, src, dest)
def setForElem( elem, name ):
result = set()
splits = re.split( g_formatsPat, elem.text )
nParts = len(splits)
if 1 < nParts:
for ii in range(nParts):
part = splits[ii]
if re.match( g_formatsPat, part ):
result.add( part )
# print 'setForElem(', name, ') =>', result
return result
def getFormats( doc, path ):
result = {}
for elem in doc.findall('string'):
name = elem.get('name')
result[name] = setForElem( elem, name )
for elem in doc.findall('plurals'):
name = elem.get('name')
for item in elem.findall('item'):
quantity = item.get('quantity')
if not item.text or 0 == len(item.text):
exitWithError( 'plurals ' + name + ' has empty quantity ' + quantity \
+ ' in file ' + lang )
else:
add = name + '/' + quantity
result[add] = setForElem( item, add )
# print 'getFormats(', path, ') => ', result
return result
def main():
# add these via params later
excepts = ['values-ca_PS', 'values-ba_CK']
@ -198,12 +240,12 @@ def main():
# summarize the english file
wd = os.path.dirname(sys.argv[0])
path = wd + '/../app/src/main/res/values/strings.xml'
engNames = {}
engFormats = {}
parser = etree.XMLParser(remove_blank_text=True, encoding="utf-8")
engDoc = etree.parse(path, parser)
pat = re.compile( '(%\d\$[sd])', re.DOTALL | re.MULTILINE )
engFormats = getFormats( engDoc, path )
engNames = {}
for typ in ['string', 'plurals']:
for elem in engDoc.findall(typ):
name = elem.get('name')
@ -227,7 +269,7 @@ def main():
verbose = 0 == len(verboses) or 0 < len([verb for verb in verboses if verb in path])
print "*** looking at %s ***" % (path)
dest = path.replace( 'res_src', 'app/src/main/res', 1 )
checkAndCopy( parser, engNames, path, dest, verbose )
checkAndCopy( parser, engNames, engFormats, path, dest, verbose )
##############################################################################
if __name__ == '__main__':

View file

@ -2382,19 +2382,16 @@ XP_Bool
coordToCell( const BoardCtxt* board, XP_S16 xx, XP_S16 yy, XP_U16* colP,
XP_U16* rowP )
{
XP_U16 col, row;
XP_U16 maxCols = model_numCols( board->model );
const XP_U16 maxCols = model_numCols( board->model );
XP_S16 gotCol = -1;
XP_S16 gotRow = -1;
const ScrollData* hsd = &board->sd[SCROLL_H];
const ScrollData* vsd = &board->sd[SCROLL_V];
xx -= board->boardBounds.left;
yy -= board->boardBounds.top;
if ( xx >= 0 && yy >= 0 ) {
for ( col = hsd->offset; col < maxCols; ++col ) {
const ScrollData* hsd = &board->sd[SCROLL_H];
for ( XP_U16 col = hsd->offset; col < maxCols; ++col ) {
xx -= hsd->dims[col];
if ( xx <= 0 ) {
gotCol = col;
@ -2402,8 +2399,9 @@ coordToCell( const BoardCtxt* board, XP_S16 xx, XP_S16 yy, XP_U16* colP,
}
}
for ( row = vsd->offset; row < maxCols; ++row ) {
yy -= vsd->dims[col];
const ScrollData* vsd = &board->sd[SCROLL_V];
for ( XP_U16 row = vsd->offset; row < maxCols; ++row ) {
yy -= vsd->dims[row];
if ( yy <= 0 ) {
gotRow = row;
break;

View file

@ -373,7 +373,7 @@ drawCell( BoardCtxt* board, const XP_U16 col, const XP_U16 row, XP_Bool skipBlan
XP_Bool success = XP_TRUE;
XP_Rect cellRect = {0};
Tile tile;
XP_Bool isBlank, isEmpty, recent, pending = XP_FALSE;
XP_Bool isBlank, isEmpty, recent = XP_FALSE, pending = XP_FALSE;
XWBonusType bonus;
ModelCtxt* model = board->model;
DictionaryCtxt* dict = model_getDictionary( model );

View file

@ -2647,26 +2647,27 @@ comms_getStats( CommsCtxt* comms, XWStreamCtxt* stream )
(XP_UCHAR*)"msg queue len: %d\n", comms->queueLen );
stream_catString( stream, buf );
XP_U16 indx = 0;
for ( elem = comms->msgQueueHead; !!elem; elem = elem->next ) {
XP_SNPRINTF( buf, sizeof(buf),
" - channelNo=%.4X; msgID=" XP_LD "; len=%d\n",
elem->channelNo, elem->msgID, elem->len );
"%d: - channelNo=%.4X; msgID=" XP_LD "; len=%d\n",
indx++, elem->channelNo, elem->msgID, elem->len );
stream_catString( stream, buf );
}
for ( rec = comms->recs; !!rec; rec = rec->next ) {
XP_SNPRINTF( (XP_UCHAR*)buf, sizeof(buf),
(XP_UCHAR*)" Stats for channel: %.4X\n",
(XP_UCHAR*)"Stats for channel %.4X\n",
rec->channelNo );
stream_catString( stream, buf );
XP_SNPRINTF( (XP_UCHAR*)buf, sizeof(buf),
(XP_UCHAR*)"Last msg sent: " XP_LD "\n",
(XP_UCHAR*)" Last msg sent: " XP_LD "; ",
rec->nextMsgID );
stream_catString( stream, buf );
XP_SNPRINTF( (XP_UCHAR*)buf, sizeof(buf),
(XP_UCHAR*)"Last msg received: %d\n",
(XP_UCHAR*)"last msg received: %d\n",
rec->lastMsgRcd );
stream_catString( stream, buf );
}

View file

@ -47,6 +47,7 @@
#endif
#define MAX_COLS MAX_ROWS
#define STREAM_VERS_DUPLICATE 0x1B
#define STREAM_VERS_DISABLEDS 0x1A
#define STREAM_VERS_DEVIDS 0x19
#define STREAM_VERS_MULTIADDR 0x18
@ -88,7 +89,7 @@
#define STREAM_VERS_405 0x01
/* search for FIX_NEXT_VERSION_CHANGE next time this is changed */
#define CUR_STREAM_VERS STREAM_VERS_DISABLEDS
#define CUR_STREAM_VERS STREAM_VERS_DUPLICATE
typedef struct XP_Rect {
XP_S16 left;

View file

@ -339,7 +339,8 @@ game_saveSucceeded( const XWGame* game, XP_U16 saveToken )
}
XP_Bool
game_receiveMessage( XWGame* game, XWStreamCtxt* stream, CommsAddrRec* retAddr )
game_receiveMessage( XWGame* game, XWStreamCtxt* stream,
const CommsAddrRec* retAddr )
{
ServerCtxt* server = game->server;
CommsMsgState commsState;
@ -486,7 +487,9 @@ gi_copy( MPFORMAL CurGameInfo* destGI, const CurGameInfo* srcGI )
destGI->phoniesAction = srcGI->phoniesAction;
destGI->allowPickTiles = srcGI->allowPickTiles;
destGI->forceChannel = srcGI->forceChannel;
XP_LOGF( "%s: copied forceChannel: %d", __func__, destGI->forceChannel );
destGI->inDuplicateMode = srcGI->inDuplicateMode;
XP_LOGF( "%s: copied forceChannel: %d; inDuplicateMode: %d", __func__,
destGI->forceChannel, destGI->inDuplicateMode );
for ( srcPl = srcGI->players, destPl = destGI->players, ii = 0;
ii < nPlayers; ++srcPl, ++destPl, ++ii ) {
@ -565,6 +568,9 @@ gi_readFromStream( MPFORMAL XWStreamCtxt* stream, CurGameInfo* gi )
gi->phoniesAction = (XWPhoniesChoice)stream_getBits( stream, 2 );
gi->timerEnabled = stream_getBits( stream, 1 );
gi->inDuplicateMode = strVersion >= STREAM_VERS_DUPLICATE
? stream_getBits( stream, 1 )
: XP_FALSE;
if ( strVersion >= STREAM_VERS_41B4 ) {
gi->allowPickTiles = stream_getBits( stream, 1 );
gi->allowHintRect = stream_getBits( stream, 1 );
@ -640,6 +646,7 @@ gi_writeToStream( XWStreamCtxt* stream, const CurGameInfo* gi )
stream_putBits( stream, 1, gi->hintsNotAllowed );
stream_putBits( stream, 2, gi->phoniesAction );
stream_putBits( stream, 1, gi->timerEnabled );
stream_putBits( stream, 1, gi->inDuplicateMode );
stream_putBits( stream, 1, gi->allowPickTiles );
stream_putBits( stream, 1, gi->allowHintRect );
stream_putBits( stream, 1, gi->confirmBTConnect );

View file

@ -84,7 +84,7 @@ void game_saveToStream( const XWGame* game, const CurGameInfo* gi,
void game_saveSucceeded( const XWGame* game, XP_U16 saveToken );
XP_Bool game_receiveMessage( XWGame* game, XWStreamCtxt* stream,
CommsAddrRec* retAddr );
const CommsAddrRec* retAddr );
void game_dispose( XWGame* game );

View file

@ -58,6 +58,7 @@ typedef struct CurGameInfo {
XP_Bool timerEnabled;
XP_Bool allowPickTiles;
XP_Bool allowHintRect;
XP_Bool inDuplicateMode;
XWPhoniesChoice phoniesAction;
XP_Bool confirmBTConnect; /* only used for BT */
} CurGameInfo;

View file

@ -89,8 +89,10 @@ nli_saveToStream( const NetLaunchInfo* nli, XWStreamCtxt* stream )
if ( types_hasType( nli->_conTypes, COMMS_CONN_RELAY ) ) {
stringToStream( stream, nli->room );
stringToStream( stream, nli->inviteID );
if ( 0 == NLI_VERSION ) {
stream_putU32( stream, nli->devID );
}
}
if ( types_hasType( nli->_conTypes, COMMS_CONN_BT ) ) {
stringToStream( stream, nli->btName );
stringToStream( stream, nli->btAddress );
@ -128,8 +130,10 @@ nli_makeFromStream( NetLaunchInfo* nli, XWStreamCtxt* stream )
if ( types_hasType( nli->_conTypes, COMMS_CONN_RELAY ) ) {
stringFromStreamHere( stream, nli->room, sizeof(nli->room) );
stringFromStreamHere( stream, nli->inviteID, sizeof(nli->inviteID) );
if ( version == 0 ) {
nli->devID = stream_getU32( stream );
}
}
if ( types_hasType( nli->_conTypes, COMMS_CONN_BT ) ) {
stringFromStreamHere( stream, nli->btName, sizeof(nli->btName) );
stringFromStreamHere( stream, nli->btAddress, sizeof(nli->btAddress) );

View file

@ -1,6 +1,6 @@
/* -*- compile-command: "cd ../linux && make -j3 MEMDEBUG=TRUE"; -*- */
/*
* Copyright 1997-2009 by Eric House (xwords@eehouse.org). All rights
* Copyright 1997 - 2019 by Eric House (xwords@eehouse.org). All rights
* reserved.
*
* This program is free software; you can redistribute it and/or
@ -84,6 +84,7 @@ typedef struct ServerVolatiles {
typedef struct ServerNonvolatiles {
XP_U32 lastMoveTime; /* seconds of last turn change */
XP_S32 dupTimerExpires;
XP_U8 nDevices;
XW_State gameState;
XW_State stateAfterShow;
@ -103,6 +104,9 @@ typedef struct ServerNonvolatiles {
RemoteAddress addresses[MAX_NUM_PLAYERS];
XWStreamCtxt* prevMoveStream; /* save it to print later */
XWStreamCtxt* prevWordsStream;
XP_Bool dupTurnsMade[MAX_NUM_PLAYERS];
XP_Bool dupTurnsForced[MAX_NUM_PLAYERS];
XP_Bool dupTurnsSent; /* used on client only */
} ServerNonvolatiles;
struct ServerCtxt {
@ -290,6 +294,9 @@ getNV( XWStreamCtxt* stream, ServerNonvolatiles* nv, XP_U16 nPlayers )
if ( STREAM_VERS_DICTNAME <= version ) {
nv->lastMoveTime = stream_getU32( stream );
}
if ( STREAM_VERS_DUPLICATE <= version ) {
nv->dupTimerExpires = stream_getU32( stream );
}
if ( version < STREAM_VERS_SERVER_SAVES_TOSHOW ) {
/* no longer used */
@ -327,6 +334,15 @@ getNV( XWStreamCtxt* stream, ServerNonvolatiles* nv, XP_U16 nPlayers )
}
/* XP_LOGF( "%s: read streamVersion: 0x%x", __func__, nv->streamVersion ); */
#endif
if ( version >= STREAM_VERS_DUPLICATE ) {
for ( ii = 0; ii < nPlayers; ++ii ) {
nv->dupTurnsMade[ii] = stream_getBits( stream, 1 );
XP_LOGF( "%s(): dupTurnsMade[%d]: %d", __func__, ii, nv->dupTurnsMade[ii] );
nv->dupTurnsForced[ii] = stream_getBits( stream, 1 );
}
nv->dupTurnsSent = stream_getBits( stream, 1 );
}
} /* getNV */
static void
@ -335,6 +351,7 @@ putNV( XWStreamCtxt* stream, const ServerNonvolatiles* nv, XP_U16 nPlayers )
XP_U16 ii;
stream_putU32( stream, nv->lastMoveTime );
stream_putU32( stream, nv->dupTimerExpires );
/* number of players is upper limit on device count */
stream_putBits( stream, NDEVICES_NBITS, nv->nDevices-1 );
@ -358,6 +375,12 @@ putNV( XWStreamCtxt* stream, const ServerNonvolatiles* nv, XP_U16 nPlayers )
stream_putU8( stream, nv->streamVersion );
/* XP_LOGF( "%s: wrote streamVersion: 0x%x", __func__, nv->streamVersion ); */
#endif
for ( ii = 0; ii < nPlayers; ++ii ) {
stream_putBits( stream, 1, nv->dupTurnsMade[ii] );
stream_putBits( stream, 1, nv->dupTurnsForced[ii] );
}
stream_putBits( stream, 1, nv->dupTurnsSent );
} /* putNV */
static XWStreamCtxt*

View file

@ -0,0 +1,36 @@
# -*-mode: Makefile -*-
# Copyright 2016 by Eric House (xwords@eehouse.org). All rights
# reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
XWLANG=ODS8
LANGCODE=fr_FR
DICTNOTE = "From ods8.zip submitted by a user"
TARGET_TYPE ?= WINCE
include ../Makefile.langcommon
# use sed to strip the bogus utf8 identifier. There must be a better
# way, e.g. with iconv.
$(XWLANG)Main.dict.gz: $(XWDICTPATH)/French/ods8.txt
cat $< | tr -d '\r' | sed 's,\xEF\xBB\xBF,,' | tr a-z A-Z | gzip >$@
# Everything but creating of the Main.dict file is inherited from the
# "parent" Makefile.langcommon in the parent directory.
clean: clean_common
rm -f $(XWLANG)Main.dict.gz *.bin $(XWLANG)*.pdb $(XWLANG)*.seb

View file

@ -178,27 +178,6 @@ makeDictForStream( CommonGlobals* cGlobals, XWStreamCtxt* stream )
return dict;
}
static XP_Bool
processMessage( CommonGlobals* cGlobals, XWStreamCtxt* stream,
const CommsAddrRec* from, XP_Bool doDo )
{
XWGame* game = &cGlobals->game;
CommsMsgState state;
XP_Bool received = comms_checkIncomingStream( game->comms, stream, from, &state );
XP_Bool draw = received && server_receiveMessage( game->server, stream );
comms_msgProcessed( game->comms, &state, !draw );
if ( doDo && draw ) {
ServerCtxt* server = cGlobals->game.server;
XP_U16 ii;
for ( ii = 0; ii < 5; ++ii ) {
(void)server_do( server );
}
}
return draw;
}
void
gameGotBuf( CommonGlobals* cGlobals, XP_Bool hasDraw, const XP_U8* buf,
XP_U16 len, const CommsAddrRec* from )
@ -208,7 +187,7 @@ gameGotBuf( CommonGlobals* cGlobals, XP_Bool hasDraw, const XP_U8* buf,
XWGame* game = &cGlobals->game;
XWStreamCtxt* stream = stream_from_msgbuf( cGlobals, buf, len );
if ( !!stream ) {
redraw = processMessage( cGlobals, stream, from, XP_FALSE );
redraw = game_receiveMessage( game, stream, from );
if ( redraw ) {
saveGame( cGlobals );
}
@ -433,7 +412,7 @@ handle_messages_from( CommonGlobals* cGlobals, const TransportProcs* procs,
stream = mem_stream_make_raw( MPPARM(cGlobals->util->mpool)
params->vtMgr );
stream_putBytes( stream, buf, len );
(void)processMessage( cGlobals, stream, NULL, XP_TRUE );
(void)game_receiveMessage( &cGlobals->game, stream, NULL );
stream_destroy( stream );
}
@ -483,7 +462,7 @@ read_pipe_then_close( CommonGlobals* cGlobals, const TransportProcs* procs )
stream = mem_stream_make_raw( MPPARM(cGlobals->util->mpool)
params->vtMgr );
stream_putBytes( stream, buf, len );
(void)processMessage( cGlobals, stream, NULL, XP_TRUE );
(void)game_receiveMessage( &cGlobals->game, stream, NULL );
stream_destroy( stream );
}
@ -1162,7 +1141,7 @@ linux_relay_ioproc( GIOChannel* source, GIOCondition condition, gpointer data )
CommsAddrRec addr = {0};
addr_addType( &addr, COMMS_CONN_RELAY );
redraw = processMessage( cGlobals, inboundS, &addr, XP_FALSE );
redraw = game_receiveMessage( &cGlobals->game, inboundS, &addr );
stream_destroy( inboundS );
}