From 07bc2a08aaee161515e9543c9cbb01ffe7dfb759 Mon Sep 17 00:00:00 2001 From: Eric House Date: Mon, 15 Jun 2020 17:38:09 -0700 Subject: [PATCH 01/27] changelog change --- xwords4/android/app/src/main/assets/changes.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xwords4/android/app/src/main/assets/changes.html b/xwords4/android/app/src/main/assets/changes.html index 497f840f8..d513e1322 100644 --- a/xwords4/android/app/src/main/assets/changes.html +++ b/xwords4/android/app/src/main/assets/changes.html @@ -29,7 +29,7 @@
  • Improve internet/relay play by adding a second server type (MQTT)
  • Add "under construction" icon for when thumbnail isn't available
  • Enable new "block phonies" option that won't let you use a word not in the wordlist
  • -
  • Add new Japanese translations (via Weblate)
  • +
  • Add new Japanese and Polish translations (via Weblate)
  • (The full changelog From 927f9a8f83a4f844d42539433cabd631a4b92a8c Mon Sep 17 00:00:00 2001 From: Eric House Date: Fri, 19 Jun 2020 11:50:44 -0700 Subject: [PATCH 02/27] fix to store mqtt id using properly-named key And throw in temporary code so those of us testing the stuff don't have all our existing games stop working. --- xwords4/common/device.c | 18 ++++++++++++++++-- xwords4/linux/lindutil.c | 10 ++++++---- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/xwords4/common/device.c b/xwords4/common/device.c index d6b8f541d..f547a72d7 100644 --- a/xwords4/common/device.c +++ b/xwords4/common/device.c @@ -81,7 +81,9 @@ dvc_store( XW_DUtilCtxt* dutil, XWEnv xwe ) #endif -#define MQTT_DEVID_KEY "mqtt_devid_key" +#define SUPPORT_OLD /* only needed for a short while */ +#define MQTT_DEVID_KEY_OLD "mqtt_devid_key" +#define MQTT_DEVID_KEY PERSIST_KEY("mqtt_devid_key") void dvc_getMQTTDevID( XW_DUtilCtxt* dutil, XWEnv xwe, MQTTDevID* devID ) @@ -89,8 +91,20 @@ dvc_getMQTTDevID( XW_DUtilCtxt* dutil, XWEnv xwe, MQTTDevID* devID ) MQTTDevID tmp = 0; XP_U16 len = sizeof(tmp); dutil_loadPtr( dutil, xwe, MQTT_DEVID_KEY, &tmp, &len ); + +#ifdef SUPPORT_OLD + if ( len == 0 ) { + len = sizeof(tmp); + dutil_loadPtr( dutil, xwe, MQTT_DEVID_KEY_OLD, &tmp, &len ); + if ( len == sizeof(tmp) ) { /* got the old key; now store it */ + XP_LOGFF( "storing using new key" ); + dutil_storePtr( dutil, xwe, MQTT_DEVID_KEY, &tmp, sizeof(tmp) ); + } + } +#endif + // XP_LOGFF( "len: %d; sizeof(tmp): %d", len, sizeof(tmp) ); - if ( len != sizeof(tmp) ) { /* we have it!!! */ + if ( len != sizeof(tmp) ) { /* not found, or bogus somehow */ tmp = XP_RANDOM(); tmp <<= 32; tmp |= XP_RANDOM(); diff --git a/xwords4/linux/lindutil.c b/xwords4/linux/lindutil.c index 9071074e6..4ac1d7a26 100644 --- a/xwords4/linux/lindutil.c +++ b/xwords4/linux/lindutil.c @@ -330,18 +330,20 @@ linux_dutil_loadPtr( XW_DUtilCtxt* duc, XWEnv XP_UNUSED(xwe), const XP_UCHAR* ke *lenp = buflen; } else { gchar* tmp = XP_MALLOC( duc->mpool, buflen ); - res = db_fetch( pDb, key, tmp, &buflen ); + gint tmpLen = buflen; + res = db_fetch( pDb, key, tmp, &tmpLen ); + XP_ASSERT( buflen == tmpLen ); XP_ASSERT( res == SUCCESS ); XP_ASSERT( tmp[buflen-1] == '\0' ); gsize out_len; - guchar* txt = g_base64_decode( (const gchar*)tmp, &out_len ); + guchar* binp = g_base64_decode( tmp, &out_len ); if ( out_len <= *lenp ) { - XP_MEMCPY( data, txt, out_len ); + XP_MEMCPY( data, binp, out_len ); *lenp = out_len; } XP_FREEP( duc->mpool, &tmp ); - g_free( txt ); + g_free( binp ); } } else { *lenp = 0; /* doesn't exist */ From 1398e1ed55bfbabc940c447b652f1fbe5e06a7c6 Mon Sep 17 00:00:00 2001 From: Eric House Date: Sat, 20 Jun 2020 14:43:21 -0700 Subject: [PATCH 03/27] work around NPE Not sure if the name being null is ok, but this is likely better code. --- .../main/java/org/eehouse/android/xw4/BTInviteDelegate.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BTInviteDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BTInviteDelegate.java index 868486775..da106a17f 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BTInviteDelegate.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BTInviteDelegate.java @@ -27,6 +27,7 @@ import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.Handler; +import android.text.TextUtils; import android.text.format.DateUtils; import android.view.View; import android.widget.Button; @@ -74,7 +75,7 @@ public class BTInviteDelegate extends InviteDelegate { pairs = new ArrayList<>(); } else { for ( TwoStringPair pair : pairs ) { - alreadyHave = pair.str2.equals(devName); + alreadyHave = TextUtils.equals(pair.str2, devName); if ( alreadyHave ) { break; } From 4a3f5d5a4415b7c5587eda921590784c91fd30d7 Mon Sep 17 00:00:00 2001 From: Eric House Date: Sun, 21 Jun 2020 11:32:19 -0700 Subject: [PATCH 04/27] on load, remove records missing a device Can't test because changing the class meant the thing couldn't be deserialized. Oh well. It was likely a fluke that caused the null dev entry anyway. --- .../org/eehouse/android/xw4/BTInviteDelegate.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BTInviteDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BTInviteDelegate.java index da106a17f..4367ab5b3 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BTInviteDelegate.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BTInviteDelegate.java @@ -97,7 +97,7 @@ public class BTInviteDelegate extends InviteDelegate { for ( Iterator iter = pairs.iterator(); iter.hasNext(); ) { TwoStringPair pair = iter.next(); - if ( pair.str2.equals( dev ) ) { + if ( TextUtils.equals( pair.str2, dev ) ) { iter.remove(); break; } @@ -105,6 +105,18 @@ public class BTInviteDelegate extends InviteDelegate { } } + private void removeNulls() + { + for ( Iterator iter = pairs.iterator(); + iter.hasNext(); ) { + TwoStringPair pair = iter.next(); + if ( TextUtils.isEmpty( pair.str2 ) ) { + Log.d( TAG, "removeNulls(): removing!!" ); + iter.remove(); + } + } + } + boolean empty() { return pairs == null || pairs.size() == 0; } private void sort() @@ -316,6 +328,7 @@ public class BTInviteDelegate extends InviteDelegate { if ( null == sPersisted ) { try { sPersisted = (Persisted)DBUtils.getSerializableFor( context, KEY_PERSIST ); + sPersisted.removeNulls(); // clean up earlier mistakes } catch ( Exception ex ) {} // NPE, de-serialization problems, etc. if ( null == sPersisted ) { From 96309421860fddc43cce03ea54d07dc880f171e6 Mon Sep 17 00:00:00 2001 From: Eric House Date: Sun, 21 Jun 2020 21:52:33 -0700 Subject: [PATCH 05/27] Create README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 000000000..990995fd9 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +# xwords +Clone of xwords repo from Sourceforge -- an open source implementation of rules of Scrabble(tm) for handhelds + +Just adding now. I'll edit after pulling. :-) From 04534d729e2f1af3d21aab86d13b958c20d510e3 Mon Sep 17 00:00:00 2001 From: Eric House Date: Tue, 23 Jun 2020 08:51:29 -0700 Subject: [PATCH 06/27] simplify dialogs Get rid of subclasses, since there's not the clear inheritance structure I imagined. Any dialog type might want a not-again checkbox, or to have a third button offer an unexpected option. This is a big change that needs some bake time. --- .../eehouse/android/xw4/BoardDelegate.java | 2 +- .../eehouse/android/xw4/ConfirmThenAlert.java | 11 +- .../android/xw4/ConnViaViewLayout.java | 2 +- .../org/eehouse/android/xw4/DelegateBase.java | 34 +- .../org/eehouse/android/xw4/DlgDelegate.java | 306 ++++++++---------- .../eehouse/android/xw4/DlgDelegateAlert.java | 4 + .../org/eehouse/android/xw4/DlgState.java | 2 +- .../android/xw4/GamesListDelegate.java | 2 +- .../org/eehouse/android/xw4/OkOnlyAlert.java | 10 +- .../eehouse/android/xw4/PrefsActivity.java | 23 +- .../org/eehouse/android/xw4/XWActivity.java | 13 +- 11 files changed, 187 insertions(+), 222 deletions(-) diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardDelegate.java index b6a5310e0..a9dd10721 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardDelegate.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardDelegate.java @@ -2488,7 +2488,7 @@ public class BoardDelegate extends DelegateBase boolean banned = Perm.SEND_SMS.isBanned(m_activity); int explID = banned ? R.string.banned_nbs_perms : R.string.missing_sms_perms; - DlgDelegate.ConfirmThenBuilder builder = + DlgDelegate.Builder builder = makeConfirmThenBuilder( explID, Action.DROP_SMS_ACTION ); if ( banned ) { builder.setActionPair( Action.PERMS_BANNED_INFO, diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/ConfirmThenAlert.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/ConfirmThenAlert.java index c875d674a..6b934c8fa 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/ConfirmThenAlert.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/ConfirmThenAlert.java @@ -1,6 +1,7 @@ /* -*- compile-command: "find-and-gradle.sh inXw4dDebug"; -*- */ /* - * Copyright 2017 by Eric House (xwords@eehouse.org). All rights reserved. + * Copyright 2017 - 2020 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 @@ -29,6 +30,7 @@ import org.eehouse.android.xw4.DlgDelegate.ActionPair; import org.eehouse.android.xw4.loc.LocUtils; public class ConfirmThenAlert extends DlgDelegateAlert { + private static final String TAG = ConfirmThenAlert.class.getSimpleName(); public static ConfirmThenAlert newInstance( DlgState state ) { @@ -46,8 +48,11 @@ public class ConfirmThenAlert extends DlgDelegateAlert { NotAgainView naView = addNAView( state, builder ); OnClickListener lstnr = mkCallbackClickListener( naView ); - builder.setTitle( state.m_titleId == 0 ? R.string.query_title : state.m_titleId ) - .setPositiveButton( state.m_posButton, lstnr ) + if ( 0 != state.m_titleId ) { + builder.setTitle( state.m_titleId ); + } + + builder.setPositiveButton( state.m_posButton, lstnr ) .setNegativeButton( state.m_negButton, lstnr ); if ( null != state.m_pair ) { diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/ConnViaViewLayout.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/ConnViaViewLayout.java index 85af9863c..60f037ec9 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/ConnViaViewLayout.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/ConnViaViewLayout.java @@ -181,7 +181,7 @@ public class ConnViaViewLayout extends LinearLayout { break; } - DlgDelegate.DlgDelegateBuilder builder = 0 != keyID + DlgDelegate.Builder builder = 0 != keyID ? m_dlgDlgt.makeNotAgainBuilder( msgID, keyID ) : m_dlgDlgt.makeOkOnlyBuilder( msgID ) .setActionPair( Action.PERMS_BANNED_INFO, diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java index 76dbbe2ff..95f7e7d1b 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java @@ -41,10 +41,8 @@ import android.widget.EditText; import android.widget.TextView; import org.eehouse.android.xw4.DlgDelegate.Action; -import org.eehouse.android.xw4.DlgDelegate.ConfirmThenBuilder; +import org.eehouse.android.xw4.DlgDelegate.Builder; import org.eehouse.android.xw4.DlgDelegate.DlgClickNotify; -import org.eehouse.android.xw4.DlgDelegate.NotAgainBuilder; -import org.eehouse.android.xw4.DlgDelegate.OkOnlyBuilder; import org.eehouse.android.xw4.MultiService.MultiEvent; import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType; import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnTypeSet; @@ -521,33 +519,33 @@ public class DelegateBase implements DlgClickNotify, return LocUtils.makeAlertBuilder( m_activity ); } - public NotAgainBuilder + public Builder makeNotAgainBuilder( String msg, int key, Action action ) { return m_dlgDelegate.makeNotAgainBuilder( msg, key, action ); } - public NotAgainBuilder + public Builder makeNotAgainBuilder( int msgId, int key, Action action ) { return m_dlgDelegate.makeNotAgainBuilder( msgId, key, action ); } - public NotAgainBuilder makeNotAgainBuilder( String msg, int key ) + public Builder makeNotAgainBuilder( String msg, int key ) { return m_dlgDelegate.makeNotAgainBuilder( msg, key ); } - public NotAgainBuilder makeNotAgainBuilder( int msgId, int key ) + public Builder makeNotAgainBuilder( int msgID, int key ) { - return m_dlgDelegate.makeNotAgainBuilder( msgId, key ); + return m_dlgDelegate.makeNotAgainBuilder( msgID, key ); } - public ConfirmThenBuilder makeConfirmThenBuilder( String msg, Action action ) { + public Builder makeConfirmThenBuilder( String msg, Action action ) { return m_dlgDelegate.makeConfirmThenBuilder( msg, action ); } - public ConfirmThenBuilder makeConfirmThenBuilder( int msgId, Action action ) { + public Builder makeConfirmThenBuilder( int msgId, Action action ) { return m_dlgDelegate.makeConfirmThenBuilder( msgId, action ); } @@ -578,12 +576,12 @@ public class DelegateBase implements DlgClickNotify, m_dlgDelegate.showInviteChoicesThen( action, info ); } - public OkOnlyBuilder makeOkOnlyBuilder( int msgId ) + public Builder makeOkOnlyBuilder( int msgID ) { - return m_dlgDelegate.makeOkOnlyBuilder( msgId ); + return m_dlgDelegate.makeOkOnlyBuilder( msgID ); } - public OkOnlyBuilder makeOkOnlyBuilder( String msg ) + public Builder makeOkOnlyBuilder( String msg ) { return m_dlgDelegate.makeOkOnlyBuilder( msg ); } @@ -722,12 +720,10 @@ public class DelegateBase implements DlgClickNotify, final int key = notAgainKey; runOnUiThread( new Runnable() { public void run() { - DlgDelegate.DlgDelegateBuilder builder; - if ( 0 == key ) { - builder = makeOkOnlyBuilder( msg ); - } else { - builder = makeNotAgainBuilder( msg, key ); - } + Builder builder = 0 == key + ? makeOkOnlyBuilder( msg ) + : makeNotAgainBuilder( msg, key ) + ; builder.show(); } }); diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegate.java index 9877ab87c..8887f65b2 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegate.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegate.java @@ -154,139 +154,173 @@ public class DlgDelegate { } } - public abstract class DlgDelegateBuilder { - protected String m_msgString; - protected int m_prefsNAKey; - protected Action m_onNA; - protected int m_posButton = android.R.string.ok; - protected int m_negButton = android.R.string.cancel; - protected Action m_action; - protected Object[] m_params; - protected int m_titleId = 0; - protected ActionPair m_actionPair; + public class Builder { + private final DlgState mState; - public DlgDelegateBuilder( String msg, Action action ) - { m_msgString = msg; m_action = action; } + Builder( DlgID dlgID ) { + mState = new DlgState( dlgID ) + .setPosButton( android.R.string.ok ) // default + ; + } - public DlgDelegateBuilder( int msgId, Action action ) - { this( getString(msgId), action );} + Builder setMessage( String msg ) + { + mState.setMsg( msg ); + return this; + } - public DlgDelegateBuilder setAction( Action action ) - { m_action = action; return this; } + Builder setMessageID( int msgID ) + { + mState.setMsg( getString( msgID ) ); + return this; + } - public DlgDelegateBuilder setNAKey( int keyId ) - { m_prefsNAKey = keyId; return this; } + Builder setActionPair( Action action, int strID ) + { + mState.setActionPair( new ActionPair( action, strID ) ); + return this; + } - public DlgDelegateBuilder setOnNA( Action onNA ) - { m_onNA = onNA; return this; } + Builder setAction( Action action ) + { + mState.setAction( action ); + return this; + } - public DlgDelegateBuilder setPosButton( int id ) - { m_posButton = id; return this; } + Builder setPosButton( int strID ) + { + mState.setPosButton( strID ); + return this; + } - public DlgDelegateBuilder setNegButton( int id ) - { m_negButton = id; return this; } + Builder setNegButton( int strID ) + { + mState.setNegButton( strID ); + return this; + } - public DlgDelegateBuilder setParams( Object... params ) - { m_params = params; return this; } + Builder setTitle( int strID ) + { + mState.setTitle( strID ); + return this; + } - public DlgDelegateBuilder setTitle( int titleId ) - { m_titleId = titleId; return this; } + Builder setParams( Object... params ) + { + mState.setParams( params ); + return this; + } - public DlgDelegateBuilder setActionPair( ActionPair pr ) - { m_actionPair = pr; return this; } + Builder setNAKey( int keyID ) + { + mState.setPrefsKey( keyID ); + return this; + } - public DlgDelegateBuilder setActionPair( Action actn, int id ) - { return setActionPair( new ActionPair( actn, id ) ); } + Builder setOnNA( Action onNAAction ) + { + mState.setOnNA( onNAAction ); + return this; + } - abstract void show(); - } - - public class OkOnlyBuilder extends DlgDelegateBuilder { - - public OkOnlyBuilder(String msg) { super( msg, Action.SKIP_CALLBACK ); } - public OkOnlyBuilder(int msgId) { super( msgId, Action.SKIP_CALLBACK ); } - - @Override public void show() { - showOKOnlyDialogThen( m_msgString, m_action, m_actionPair, - m_params, m_titleId ); + int naKey = mState.m_prefsNAKey; + final Action action = mState.m_action; + // Log.d( TAG, "show(): key: %d; action: %s", naKey, action ); + + if ( 0 == naKey || ! XWPrefs.getPrefsBoolean( m_activity, naKey, false ) ) { + m_dlgt.show( mState ); + } else if ( Action.SKIP_CALLBACK != action ) { + post( new Runnable() { + @Override + public void run() { + Log.d( TAG, "calling onPosButton()" ); + XWActivity xwact = (XWActivity)m_activity; + xwact.onPosButton( action, mState.m_params ); + } + }); + } } } - public class ConfirmThenBuilder extends DlgDelegateBuilder { - public ConfirmThenBuilder(String msg, Action action) {super(msg, action);} - public ConfirmThenBuilder(int msgId, Action action) {super(msgId, action);} - @Override - public void show() - { - showConfirmThen( m_prefsNAKey, m_onNA, m_msgString, m_posButton, - m_negButton, m_action, m_titleId, m_actionPair, - m_params ); - } - } - - public class NotAgainBuilder extends DlgDelegateBuilder { - public NotAgainBuilder(String msg, int key, Action action) - { super(msg, action); setNAKey( key ); } - - public NotAgainBuilder(int msgId, int key, Action action) - { super(msgId, action); m_prefsNAKey = key; } - - public NotAgainBuilder( String msg, int key ) - { super( msg, Action.SKIP_CALLBACK ); m_prefsNAKey = key; } - - public NotAgainBuilder( int msgId, int key ) - { super( msgId, Action.SKIP_CALLBACK ); m_prefsNAKey = key; } - - @Override - public void show() - { - showNotAgainDlgThen( m_msgString, m_prefsNAKey, - m_action, m_actionPair, - m_params ); - } - } - - public OkOnlyBuilder makeOkOnlyBuilder( String msg ) + public Builder makeOkOnlyBuilder( String msg ) { - return new OkOnlyBuilder( msg ); - } - public OkOnlyBuilder makeOkOnlyBuilder( int msgId ) - { - return new OkOnlyBuilder( msgId ); + // return new OkOnlyBuilder( msg ); + + Builder builder = new Builder( DlgID.DIALOG_OKONLY ) + .setMessage( msg ) + ; + return builder; } - public ConfirmThenBuilder makeConfirmThenBuilder( String msg, Action action ) + public Builder makeOkOnlyBuilder( int msgID ) { - return new ConfirmThenBuilder( msg, action ); + Builder builder = new Builder( DlgID.DIALOG_OKONLY ) + .setMessageID( msgID ) + ; + return builder; } - public ConfirmThenBuilder makeConfirmThenBuilder(int msgId, Action action) + private Builder makeConfirmThenBuilder( Action action ) { - return new ConfirmThenBuilder( msgId, action ); + return new Builder( DlgID.CONFIRM_THEN ) + .setAction( action ) + .setNegButton( android.R.string.cancel ) + ; + } + + public Builder makeConfirmThenBuilder( String msg, Action action ) + { + return makeConfirmThenBuilder( action ) + .setMessage( msg ) + ; } - public NotAgainBuilder makeNotAgainBuilder( int msgId, int key, - Action action ) + public Builder makeConfirmThenBuilder( int msgID, Action action ) { - return new NotAgainBuilder( msgId, key, action ); + return makeConfirmThenBuilder( action ) + .setMessageID( msgID ) + ; } - public NotAgainBuilder makeNotAgainBuilder( String msg, int key, - Action action ) + private Builder makeNotAgainBuilder( int key ) { - return new NotAgainBuilder( msg, key, action ); + return new Builder( DlgID.DIALOG_NOTAGAIN ) + .setNAKey( key ) + .setAction( Action.SKIP_CALLBACK ) + ; } - public NotAgainBuilder makeNotAgainBuilder( String msg, int key ) + public Builder makeNotAgainBuilder( String msg, int key, Action action ) { - return new NotAgainBuilder( msg, key ); + return makeNotAgainBuilder( key ) + .setMessage( msg ) + .setAction( action ) + ; } - public NotAgainBuilder makeNotAgainBuilder( int msgId, int key ) { - return new NotAgainBuilder( msgId, key ); + public Builder makeNotAgainBuilder( int msgID, int key, Action action ) + { + return makeNotAgainBuilder( key ) + .setMessageID( msgID ) + .setAction( action ) + ; + } + + public Builder makeNotAgainBuilder( String msg, int key ) + { + return makeNotAgainBuilder( key ) + .setMessage( msg ) + ; + } + + public Builder makeNotAgainBuilder( int msgID, int key ) + { + return makeNotAgainBuilder( key ) + .setMessageID( msgID ) + ; } public static final int SMS_BTN = AlertDialog.BUTTON_POSITIVE; @@ -309,11 +343,10 @@ public class DlgDelegate { void inviteChoiceMade( Action action, InviteMeans means, Object... params ); } public interface HasDlgDelegate { - OkOnlyBuilder makeOkOnlyBuilder( int msgID ); - OkOnlyBuilder makeOkOnlyBuilder( String msg ); - NotAgainBuilder makeNotAgainBuilder( int msgID, int prefsKey, - Action action ); - NotAgainBuilder makeNotAgainBuilder( int msgID, int prefsKey ); + Builder makeOkOnlyBuilder( int msgID ); + Builder makeOkOnlyBuilder( String msg ); + Builder makeNotAgainBuilder( int msgID, int prefsKey, Action action ); + Builder makeNotAgainBuilder( int msgID, int prefsKey ); } private Activity m_activity; @@ -337,19 +370,6 @@ public class DlgDelegate { stopProgress(); } - private void showOKOnlyDialogThen( String msg, Action action, - ActionPair more, Object[] params, - int titleId ) - { - DlgState state = new DlgState( DlgID.DIALOG_OKONLY ) - .setMsg( msg ) - .setParams( params ) - .setTitle( titleId ) - .setActionPair( more ) - .setAction(action); - m_dlgt.show( state ); - } - // Puts up alert asking to choose a reason to enable SMS, and on dismiss // calls onPosButton/onNegButton with the action and in params a Boolean // indicating whether enabling is now ok. @@ -361,62 +381,6 @@ public class DlgDelegate { m_dlgt.show( state ); } - private void showNotAgainDlgThen( String msg, int prefsKey, - final Action action, ActionPair more, - final Object[] params ) - { - if ( 0 != prefsKey - && XWPrefs.getPrefsBoolean( m_activity, prefsKey, false ) ) { - // If it's set, do the action without bothering with the - // dialog - if ( Action.SKIP_CALLBACK != action ) { - post( new Runnable() { - public void run() { - XWActivity xwact = (XWActivity)m_activity; - xwact.onPosButton( action, params ); - } - }); - } - } else { - DlgState state = new DlgState( DlgID.DIALOG_NOTAGAIN ) - .setMsg( msg) - .setPrefsKey( prefsKey ) - .setAction( action ) - .setActionPair( more ) - .setParams( params ); - m_dlgt.show( state ); - } - } - - private void showConfirmThen( int nakey, Action onNA, String msg, - int posButton, int negButton, - final Action action, int titleId, - ActionPair more, final Object[] params ) - { - if ( 0 == nakey || - ! XWPrefs.getPrefsBoolean( m_activity, nakey, false ) ) { - DlgState state = new DlgState( DlgID.CONFIRM_THEN ) - .setOnNA( onNA ) - .setMsg( msg ) - .setPosButton( posButton ) - .setNegButton( negButton ) - .setAction( action ) - .setTitle( titleId ) - .setActionPair( more ) - .setParams( params ) - .setPrefsKey( nakey ) - ; - m_dlgt.show( state ); - } else if ( Action.SKIP_CALLBACK != action ) { - post( new Runnable() { - public void run() { - XWActivity xwact = (XWActivity)m_activity; - xwact.onDismissed( action, params ); - } - }); - } - } - public void showInviteChoicesThen( final Action action, SentInvitesInfo info ) { diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegateAlert.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegateAlert.java index 03d0980b0..d676f3053 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegateAlert.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegateAlert.java @@ -89,6 +89,10 @@ abstract class DlgDelegateAlert extends XWDialogFragment { AlertDialog.Builder builder = LocUtils.makeAlertBuilder( context ); + if ( 0 != state.m_titleId ) { + builder.setTitle( state.m_titleId ); + } + populateBuilder( context, state, builder ); return create( builder ); diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgState.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgState.java index 8ec5603b8..c689f0e62 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgState.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgState.java @@ -168,7 +168,7 @@ public class DlgState implements Parcelable { private void testCanParcelize() { - if (BuildConfig.DEBUG) { + if ( BuildConfig.DEBUG ) { Parcel parcel = Parcel.obtain(); writeToParcel(parcel, 0); diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java index 85fa80846..23504db7c 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java @@ -2438,7 +2438,7 @@ public class GamesListDelegate extends ListDelegateBase boolean handled = false; String msg = intent.getStringExtra( ALERT_MSG ); if ( null != msg ) { - DlgDelegate.DlgDelegateBuilder builder = + DlgDelegate.Builder builder = makeOkOnlyBuilder( msg ); if ( intent.getBooleanExtra( WITH_EMAIL, false ) ) { builder.setActionPair( Action.SEND_EMAIL, diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/OkOnlyAlert.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/OkOnlyAlert.java index 32f49f0a0..3268129c1 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/OkOnlyAlert.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/OkOnlyAlert.java @@ -1,6 +1,7 @@ -/* -*- compile-command: "find-and-gradle.sh inXw4dDebug"; -*- */ +/* -*- compile-command: "find-and-gradle.sh inXw4dDeb"; -*- */ /* - * Copyright 2017 by Eric House (xwords@eehouse.org). All rights reserved. + * Copyright 2017 - 2020 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 @@ -40,9 +41,8 @@ public class OkOnlyAlert extends DlgDelegateAlert { public void populateBuilder( Context context, DlgState state, AlertDialog.Builder builder ) { - builder.setTitle( state.m_titleId == 0 ? R.string.info_title : state.m_titleId ) - .setMessage( state.m_msg ) - .setPositiveButton( android.R.string.ok, null ) + builder.setMessage( state.m_msg ) + .setPositiveButton( state.m_posButton, null ) ; ActionPair pair = state.m_pair; diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/PrefsActivity.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/PrefsActivity.java index ea61b4747..fd4c2b45b 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/PrefsActivity.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/PrefsActivity.java @@ -26,11 +26,8 @@ import android.content.Intent; import android.os.Bundle; import android.preference.PreferenceActivity; - import org.eehouse.android.xw4.DlgDelegate.Action; -import org.eehouse.android.xw4.DlgDelegate.ConfirmThenBuilder; -import org.eehouse.android.xw4.DlgDelegate.NotAgainBuilder; -import org.eehouse.android.xw4.DlgDelegate.OkOnlyBuilder; +import org.eehouse.android.xw4.DlgDelegate.Builder; import org.eehouse.android.xw4.loc.LocUtils; public class PrefsActivity extends PreferenceActivity @@ -102,32 +99,32 @@ public class PrefsActivity extends PreferenceActivity m_dlgt.onActivityResult( rc, resultCode, data ); } - public OkOnlyBuilder makeOkOnlyBuilder( int msgId ) + public Builder makeOkOnlyBuilder( int msgID ) { - return m_dlgt.makeOkOnlyBuilder( msgId ); + return m_dlgt.makeOkOnlyBuilder( msgID ); } - public OkOnlyBuilder makeOkOnlyBuilder( String msg ) + public Builder makeOkOnlyBuilder( String msg ) { return m_dlgt.makeOkOnlyBuilder( msg ); } - public NotAgainBuilder makeNotAgainBuilder(int msgId, int key, Action action) + public Builder makeNotAgainBuilder(int msgID, int key, Action action) { - return m_dlgt.makeNotAgainBuilder( msgId, key, action ); + return m_dlgt.makeNotAgainBuilder( msgID, key, action ); } - public NotAgainBuilder makeNotAgainBuilder( int msgId, int key ) + public Builder makeNotAgainBuilder( int msgID, int key ) { - return m_dlgt.makeNotAgainBuilder( msgId, key ); + return m_dlgt.makeNotAgainBuilder( msgID, key ); } - public ConfirmThenBuilder makeConfirmThenBuilder(String msg, Action action) + public Builder makeConfirmThenBuilder( String msg, Action action ) { return m_dlgt.makeConfirmThenBuilder( msg, action ); } - public ConfirmThenBuilder makeConfirmThenBuilder(int msgID, Action action) + public Builder makeConfirmThenBuilder( int msgID, Action action ) { return m_dlgt.makeConfirmThenBuilder( msgID, action ); } diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWActivity.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWActivity.java index 275de7ef7..639272f87 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWActivity.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWActivity.java @@ -204,23 +204,22 @@ public class XWActivity extends FragmentActivity // This are a hack! I need some way to build fragment-based alerts from // inside fragment-based alerts. - public DlgDelegate.NotAgainBuilder makeNotAgainBuilder( String msg, int keyId ) + public DlgDelegate.Builder makeNotAgainBuilder( String msg, int keyID ) { - return m_dlgt.makeNotAgainBuilder( msg, keyId ); + return m_dlgt.makeNotAgainBuilder( msg, keyID ); } - public DlgDelegate.NotAgainBuilder makeNotAgainBuilder( int msgID, int keyId ) + public DlgDelegate.Builder makeNotAgainBuilder( int msgID, int keyID ) { - return m_dlgt.makeNotAgainBuilder( msgID, keyId ); + return m_dlgt.makeNotAgainBuilder( msgID, keyID ); } - public DlgDelegate.ConfirmThenBuilder makeConfirmThenBuilder( int msgID, - Action action ) + public DlgDelegate.Builder makeConfirmThenBuilder( int msgID, Action action ) { return m_dlgt.makeConfirmThenBuilder( msgID, action ); } - public DlgDelegate.OkOnlyBuilder makeOkOnlyBuilder( int msgID ) + public DlgDelegate.Builder makeOkOnlyBuilder( int msgID ) { return m_dlgt.makeOkOnlyBuilder( msgID ); } From 4d960c2115b90befbb8b33f98089df0aa9acf5a4 Mon Sep 17 00:00:00 2001 From: Eric House Date: Tue, 23 Jun 2020 09:41:40 -0700 Subject: [PATCH 07/27] provide default Action to avoid NPE --- .../app/src/main/java/org/eehouse/android/xw4/DlgDelegate.java | 1 + 1 file changed, 1 insertion(+) diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegate.java index 8887f65b2..9b4249605 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegate.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegate.java @@ -160,6 +160,7 @@ public class DlgDelegate { Builder( DlgID dlgID ) { mState = new DlgState( dlgID ) .setPosButton( android.R.string.ok ) // default + .setAction( Action.SKIP_CALLBACK ) ; } From e72532c999df9b003336aac6ab7630d2e3105459 Mon Sep 17 00:00:00 2001 From: Eric House Date: Thu, 25 Jun 2020 10:20:19 -0700 Subject: [PATCH 08/27] more dialog cleanup get rid of subclasses that are no longer separate, since features like providing a not-again checkbox are available everywhere now. --- .../eehouse/android/xw4/BoardDelegate.java | 6 +- .../eehouse/android/xw4/ConfirmThenAlert.java | 64 ------------------- .../org/eehouse/android/xw4/DelegateBase.java | 10 +-- .../org/eehouse/android/xw4/DlgDelegate.java | 3 +- .../eehouse/android/xw4/DlgDelegateAlert.java | 41 ++++++++++-- .../org/eehouse/android/xw4/DlgState.java | 4 +- .../eehouse/android/xw4/NotAgainAlert.java | 54 ---------------- .../org/eehouse/android/xw4/OkOnlyAlert.java | 53 --------------- .../org/eehouse/android/xw4/XWActivity.java | 2 +- 9 files changed, 45 insertions(+), 192 deletions(-) delete mode 100644 xwords4/android/app/src/main/java/org/eehouse/android/xw4/ConfirmThenAlert.java delete mode 100644 xwords4/android/app/src/main/java/org/eehouse/android/xw4/NotAgainAlert.java delete mode 100644 xwords4/android/app/src/main/java/org/eehouse/android/xw4/OkOnlyAlert.java diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardDelegate.java index a9dd10721..c0e77630b 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardDelegate.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardDelegate.java @@ -315,8 +315,9 @@ public class BoardDelegate extends DelegateBase int title = (Integer)params[0]; String msg = (String)params[1]; ab.setMessage( msg ); - Assert.assertTrue( 0 != title ); - ab.setTitle( title ); + if ( 0 != title ) { + ab.setTitle( title ); + } ab.setPositiveButton( android.R.string.ok, null ); if ( DlgID.DLG_SCORES == dlgID ) { if ( null != m_mySIS.words && m_mySIS.words.length > 0 ) { @@ -2635,7 +2636,6 @@ public class BoardDelegate extends DelegateBase switch ( dlgID ) { case DLG_OKONLY: case DLG_SCORES: - dlgTitle = R.string.info_title; break; case DLG_USEDICT: case DLG_GETDICT: diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/ConfirmThenAlert.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/ConfirmThenAlert.java deleted file mode 100644 index 6b934c8fa..000000000 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/ConfirmThenAlert.java +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- compile-command: "find-and-gradle.sh inXw4dDebug"; -*- */ -/* - * Copyright 2017 - 2020 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.AlertDialog; -import android.app.Dialog; -import android.content.Context; -import android.content.DialogInterface.OnClickListener; -import android.os.Bundle; - -import org.eehouse.android.xw4.DlgDelegate.ActionPair; -import org.eehouse.android.xw4.loc.LocUtils; - -public class ConfirmThenAlert extends DlgDelegateAlert { - private static final String TAG = ConfirmThenAlert.class.getSimpleName(); - - public static ConfirmThenAlert newInstance( DlgState state ) - { - ConfirmThenAlert result = new ConfirmThenAlert(); - result.addStateArgument( state ); - return result; - } - - public ConfirmThenAlert() {} - - @Override - public void populateBuilder( Context context, DlgState state, - AlertDialog.Builder builder ) - { - NotAgainView naView = addNAView( state, builder ); - OnClickListener lstnr = mkCallbackClickListener( naView ); - - if ( 0 != state.m_titleId ) { - builder.setTitle( state.m_titleId ); - } - - builder.setPositiveButton( state.m_posButton, lstnr ) - .setNegativeButton( state.m_negButton, lstnr ); - - if ( null != state.m_pair ) { - ActionPair pair = state.m_pair; - builder.setNeutralButton( pair.buttonStr, - mkCallbackClickListener( pair, naView ) ); - } - } -} diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java index 95f7e7d1b..c4b03c067 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java @@ -483,17 +483,13 @@ public class DelegateBase implements DlgClickNotify, DlgDelegateAlert df = null; switch ( state.m_id ) { case CONFIRM_THEN: - df = ConfirmThenAlert.newInstance( state ); + case DIALOG_OKONLY: + case DIALOG_NOTAGAIN: + df = DlgDelegateAlert.newInstance( state ); break; case DIALOG_ENABLESMS: df = EnableSMSAlert.newInstance( state ); break; - case DIALOG_OKONLY: - df = OkOnlyAlert.newInstance( state ); - break; - case DIALOG_NOTAGAIN: - df = NotAgainAlert.newInstance( state ); - break; case INVITE_CHOICES_THEN: df = InviteChoicesAlert.newInstance( state ); break; diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegate.java index 9b4249605..8b62d5448 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegate.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegate.java @@ -214,7 +214,7 @@ public class DlgDelegate { Builder setNAKey( int keyID ) { - mState.setPrefsKey( keyID ); + mState.setPrefsNAKey( keyID ); return this; } @@ -291,6 +291,7 @@ public class DlgDelegate { return new Builder( DlgID.DIALOG_NOTAGAIN ) .setNAKey( key ) .setAction( Action.SKIP_CALLBACK ) + .setTitle( R.string.newbie_title ) ; } diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegateAlert.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegateAlert.java index d676f3053..37f06af6b 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegateAlert.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegateAlert.java @@ -1,6 +1,7 @@ -/* -*- compile-command: "find-and-gradle.sh inXw4dDebug"; -*- */ +/* -*- compile-command: "find-and-gradle.sh inXw4dDeb"; -*- */ /* - * Copyright 2017 by Eric House (xwords@eehouse.org). All rights reserved. + * Copyright 2017 - 2020 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 @@ -37,13 +38,20 @@ import org.eehouse.android.xw4.loc.LocUtils; /** Abstract superclass for Alerts that have moved from and are still created * inside DlgDelegate */ -abstract class DlgDelegateAlert extends XWDialogFragment { +public class DlgDelegateAlert extends XWDialogFragment { private static final String TAG = DlgDelegateAlert.class.getSimpleName(); private static final String STATE_KEY = "STATE_KEY"; private DlgState m_state; public DlgDelegateAlert() {} + public static DlgDelegateAlert newInstance( DlgState state ) + { + DlgDelegateAlert result = new DlgDelegateAlert(); + result.addStateArgument( state ); + return result; + } + protected final DlgState getState( Bundle sis ) { if ( m_state == null ) { @@ -63,18 +71,37 @@ abstract class DlgDelegateAlert extends XWDialogFragment { setArguments( state.toBundle() ); } - abstract void populateBuilder( Context context, DlgState state, - AlertDialog.Builder builder ); + protected void populateBuilder( Context context, DlgState state, + AlertDialog.Builder builder ) + { + Log.d( TAG, "populateBuilder()" ); + NotAgainView naView = addNAView( state, builder ); + + OnClickListener lstnr = mkCallbackClickListener( naView ); + if ( 0 != state.m_posButton ) { + builder.setPositiveButton( state.m_posButton, lstnr ); + } + if ( 0 != state.m_negButton ) { + builder.setNegativeButton( state.m_negButton, lstnr ); + } + + if ( null != state.m_pair ) { + ActionPair pair = state.m_pair; + builder.setNeutralButton( pair.buttonStr, + mkCallbackClickListener( pair, naView ) ); + } + } Dialog create( AlertDialog.Builder builder ) { return builder.create(); } - protected NotAgainView addNAView( DlgState state, AlertDialog.Builder builder ) + private NotAgainView addNAView( DlgState state, AlertDialog.Builder builder ) { Context context = getActivity(); NotAgainView naView = ((NotAgainView)LocUtils.inflate( context, R.layout.not_again_view )) .setMessage( state.m_msg ) - .setShowNACheckbox( 0 != state.m_prefsNAKey ); + .setShowNACheckbox( 0 != state.m_prefsNAKey ) + ; builder.setView( naView ); diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgState.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgState.java index c689f0e62..c37ca5679 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgState.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgState.java @@ -56,7 +56,7 @@ public class DlgState implements Parcelable { public DlgState setMsg( String msg ) { m_msg = msg; return this; } - public DlgState setPrefsKey( int key ) + public DlgState setPrefsNAKey( int key ) { m_prefsNAKey = key; return this; } public DlgState setAction( Action action ) { m_action = action; return this; } @@ -203,7 +203,7 @@ public class DlgState implements Parcelable { .setPosButton( posButton ) .setNegButton( negButton ) .setAction( action ) - .setPrefsKey( prefsKey ) + .setPrefsNAKey( prefsKey ) .setOnNA( onNA ) .setTitle(titleId) .setParams(params) diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/NotAgainAlert.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/NotAgainAlert.java deleted file mode 100644 index a4a49e139..000000000 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/NotAgainAlert.java +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- compile-command: "find-and-gradle.sh inXw4dDebug"; -*- */ -/* - * Copyright 2017 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.AlertDialog; -import android.content.Context; - -import org.eehouse.android.xw4.DlgDelegate.ActionPair; - -public class NotAgainAlert extends DlgDelegateAlert { - private static final String TAG = NotAgainAlert.class.getSimpleName(); - - public static NotAgainAlert newInstance( DlgState state ) - { - NotAgainAlert result = new NotAgainAlert(); - result.addStateArgument( state ); - return result; - } - - public NotAgainAlert() {} - - @Override - public void populateBuilder( Context context, DlgState state, - AlertDialog.Builder builder ) - { - NotAgainView naView = addNAView( state, builder ); - builder.setTitle( R.string.newbie_title ) - .setPositiveButton( android.R.string.ok, - mkCallbackClickListener( naView ) ); - - if ( null != state.m_pair ) { - ActionPair pair = state.m_pair; - builder.setNegativeButton( pair.buttonStr, - mkCallbackClickListener( pair, naView ) ); - } - } -} diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/OkOnlyAlert.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/OkOnlyAlert.java deleted file mode 100644 index 3268129c1..000000000 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/OkOnlyAlert.java +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- compile-command: "find-and-gradle.sh inXw4dDeb"; -*- */ -/* - * Copyright 2017 - 2020 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.AlertDialog; -import android.content.Context; - -import org.eehouse.android.xw4.DlgDelegate.ActionPair; - -public class OkOnlyAlert extends DlgDelegateAlert { - private static final String TAG = OkOnlyAlert.class.getSimpleName(); - - public static OkOnlyAlert newInstance( DlgState state ) - { - OkOnlyAlert result = new OkOnlyAlert(); - result.addStateArgument( state ); - return result; - } - - public OkOnlyAlert() {} - - @Override - public void populateBuilder( Context context, DlgState state, - AlertDialog.Builder builder ) - { - builder.setMessage( state.m_msg ) - .setPositiveButton( state.m_posButton, null ) - ; - - ActionPair pair = state.m_pair; - if ( null != pair ) { - builder.setNeutralButton( pair.buttonStr, mkCallbackClickListener( pair ) ); - } - } -} diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWActivity.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWActivity.java index 639272f87..6bbdfbadb 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWActivity.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWActivity.java @@ -287,7 +287,7 @@ public class XWActivity extends FragmentActivity df.show( fm, tag ); } } catch (IllegalStateException ise ) { - Log.d( TAG, "error showing tag %s (df: %s)", tag, df ); + Log.d( TAG, "error showing tag %s (df: %s; msg: %s)", tag, df, ise ); // DLG_SCORES is causing this for non-belongsOnBackStack() case // Assert.assertFalse( BuildConfig.DEBUG ); } From 6f049c0b27a0d9ac863a7e227d24eb0e60197057 Mon Sep 17 00:00:00 2001 From: Eric House Date: Thu, 25 Jun 2020 12:01:44 -0700 Subject: [PATCH 09/27] remove unneeded code --- .../org/eehouse/android/xw4/DlgDelegate.java | 10 ------- .../eehouse/android/xw4/DlgDelegateAlert.java | 3 -- .../org/eehouse/android/xw4/DlgState.java | 29 ++++++++++--------- .../android/xw4/GamesListDelegate.java | 16 +++------- .../app/src/main/res/values/strings.xml | 2 +- 5 files changed, 20 insertions(+), 40 deletions(-) diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegate.java index 8b62d5448..27fff5d07 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegate.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegate.java @@ -123,10 +123,6 @@ public class DlgDelegate { ASKED_PHONE_STATE, PERMS_QUERY, PERMS_BANNED_INFO, - - // Sent when not-again checkbox checked - SET_NA_DEFAULTNAME, - SET_GOT_LANGDICT, } // Action enum public static class ActionPair implements Serializable { @@ -218,12 +214,6 @@ public class DlgDelegate { return this; } - Builder setOnNA( Action onNAAction ) - { - mState.setOnNA( onNAAction ); - return this; - } - public void show() { int naKey = mState.m_prefsNAKey; diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegateAlert.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegateAlert.java index 37f06af6b..eee10f207 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegateAlert.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegateAlert.java @@ -162,9 +162,6 @@ public class DlgDelegateAlert extends XWDialogFragment { if ( 0 != state.m_prefsNAKey ) { XWPrefs.setPrefsBoolean( getActivity(), m_state.m_prefsNAKey, true ); - } else if ( null != state.m_onNAChecked ) { - DlgClickNotify notify = (DlgClickNotify)getActivity(); - notify.onPosButton( m_state.m_onNAChecked ); } } } diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgState.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgState.java index c37ca5679..a0f3a4360 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgState.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgState.java @@ -46,7 +46,6 @@ public class DlgState implements Parcelable { public int m_prefsNAKey; // These can't be serialized!!!! public Object[] m_params; - public Action m_onNAChecked; public int m_titleId; public DlgState( DlgID dlgID ) @@ -76,8 +75,6 @@ public class DlgState implements Parcelable { } public DlgState setActionPair( ActionPair pair ) { m_pair = pair; return this; } - public DlgState setOnNA( Action na ) - { m_onNAChecked = na; return this; } public DlgState setPosButton( int id ) { m_posButton = id; return this; } public DlgState setNegButton( int id ) @@ -88,6 +85,7 @@ public class DlgState implements Parcelable { @Override public String toString() { + String result; if ( BuildConfig.DEBUG) { String params = ""; if ( null != m_params ) { @@ -97,14 +95,22 @@ public class DlgState implements Parcelable { } params = TextUtils.join( ",", strs ); } - return String.format("[id: %s; msg: %s; key: %s; action: %s; pair %s; " - + "na: %s; pos: %d; neg: %d; title: %d; " - + "params: %s]", - m_id, m_msg, m_prefsNAKey, m_action, m_pair, m_onNAChecked, - m_posButton, m_negButton, m_titleId, params ); + result = new StringBuffer() + .append("{id: ").append(m_id) + .append(", msg: \"").append(m_msg) + .append("\", naKey: ").append(m_prefsNAKey) + .append(", action: ").append(m_action) + .append(", pair ").append(m_pair) + .append(", pos: ").append(m_posButton) + .append(", neg: ").append(m_negButton) + .append(", title: ").append(m_titleId) + .append(", params: [").append(params) + .append("]}") + .toString(); } else { - return super.toString(); + result = super.toString(); } + return result; } // I only need this if BuildConfig.DEBUG is true... @@ -125,7 +131,6 @@ public class DlgState implements Parcelable { && ((null == m_pair) ? (null == other.m_pair) : m_pair.equals(other.m_pair)) && m_prefsNAKey == other.m_prefsNAKey && Arrays.deepEquals( m_params, other.m_params ) - && m_onNAChecked == other.m_onNAChecked && m_titleId == other.m_titleId; } } else { @@ -159,7 +164,6 @@ public class DlgState implements Parcelable { out.writeInt( m_negButton ); out.writeInt( null == m_action ? -1 : m_action.ordinal() ); out.writeInt( m_prefsNAKey ); - out.writeInt( null == m_onNAChecked ? -1 : m_onNAChecked.ordinal() ); out.writeInt( m_titleId ); out.writeString( m_msg ); out.writeSerializable( m_params ); @@ -192,8 +196,6 @@ public class DlgState implements Parcelable { int tmp = in.readInt(); Action action = 0 > tmp ? null : Action.values()[tmp]; int prefsKey = in.readInt(); - tmp = in.readInt(); - Action onNA = 0 > tmp ? null : Action.values()[tmp]; int titleId = in.readInt(); String msg = in.readString(); Object[] params = (Object[])in.readSerializable(); @@ -204,7 +206,6 @@ public class DlgState implements Parcelable { .setNegButton( negButton ) .setAction( action ) .setPrefsNAKey( prefsKey ) - .setOnNA( onNA ) .setTitle(titleId) .setParams(params) .setActionPair(pair) diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java index 23504db7c..913344e92 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java @@ -1452,15 +1452,6 @@ public class GamesListDelegate extends ListDelegateBase } break; - case SET_NA_DEFAULTNAME: - XWPrefs.setPrefsBoolean( m_activity, R.string.key_notagain_dfltname, - true ); - break; - case SET_GOT_LANGDICT: - XWPrefs.setPrefsBoolean( m_activity, R.string.key_got_langdict, - true ); - break; - default: handled = super.onPosButton( action, params ); } @@ -2497,7 +2488,8 @@ public class GamesListDelegate extends ListDelegateBase xlateLang( lang ) ); makeConfirmThenBuilder( msg, Action.DWNLD_LOC_DICT ) .setPosButton( R.string.button_download ) - .setOnNA( Action.SET_GOT_LANGDICT ) + .setNegButton( R.string.button_no ) + .setNAKey( R.string.key_got_langdict ) .setParams( lang, name ) .show(); } @@ -2754,7 +2746,7 @@ public class GamesListDelegate extends ListDelegateBase String msg = getQuantityString( R.plurals.confirm_reset_fmt, rowIDs.length, rowIDs.length ); makeConfirmThenBuilder( msg, Action.RESET_GAMES ) - .setPosButton(R.string.button_reset) + .setPosButton( R.string.button_reset ) .setParams( rowIDs ) .show(); } @@ -2798,7 +2790,7 @@ public class GamesListDelegate extends ListDelegateBase name2 ); makeConfirmThenBuilder( msg, Action.NEW_GAME_DFLT_NAME ) - .setOnNA( Action.SET_NA_DEFAULTNAME ) + .setNAKey( R.string.key_notagain_dfltname ) .setNegButton( R.string.button_later ) .setParams( name, doConfigure ) .show(); diff --git a/xwords4/android/app/src/main/res/values/strings.xml b/xwords4/android/app/src/main/res/values/strings.xml index 4fe38432d..40a1f58a0 100644 --- a/xwords4/android/app/src/main/res/values/strings.xml +++ b/xwords4/android/app/src/main/res/values/strings.xml @@ -2058,7 +2058,7 @@ wordlists and view the ones you already have.\n\nWhat wordlists you have installed determines:\n• What languages you can play in\n• How smart the robot player is\n• What words are - legal.\n\nCheck the \"Show downloadable\" box at the top to see + legal\n\nCheck the \"Show downloadable\" box at the top to see what\'s available. Use tablet (side-by-side) layout? Use default for my device From 98d134b4919ed943b6ccacafd1f8f10de74ec1ba Mon Sep 17 00:00:00 2001 From: Eric House Date: Tue, 30 Jun 2020 09:48:08 -0700 Subject: [PATCH 10/27] rewrite some dawg perl scripts in python --- xwords4/dawg/Makefile | 2 +- xwords4/dawg/Makefile.langcommon | 14 +-- xwords4/dawg/dictstats.pl | 76 ------------ xwords4/dawg/dictstats.py | 80 +++++++++++++ xwords4/dawg/frank_mkspecials.pl | 47 -------- xwords4/dawg/xloc.pl | 76 ------------ xwords4/dawg/xloc.pm | 194 ------------------------------- xwords4/dawg/xloc.py | 153 ++++++++++++++++++++++++ 8 files changed, 241 insertions(+), 401 deletions(-) delete mode 100755 xwords4/dawg/dictstats.pl create mode 100755 xwords4/dawg/dictstats.py delete mode 100755 xwords4/dawg/frank_mkspecials.pl delete mode 100755 xwords4/dawg/xloc.pl delete mode 100644 xwords4/dawg/xloc.pm create mode 100755 xwords4/dawg/xloc.py diff --git a/xwords4/dawg/Makefile b/xwords4/dawg/Makefile index 8e0623956..736a65152 100644 --- a/xwords4/dawg/Makefile +++ b/xwords4/dawg/Makefile @@ -23,7 +23,7 @@ byodfiles.tgz: byodfiles.tar byodfiles.tar: dict2dawg rm -f $@ langinfo - tar cvf $@ ./dict2dawg ./dict2dawg.cpp ./par.pl ./xloc.pl ./xloc.pm + tar cvf $@ ./dict2dawg ./dict2dawg.cpp ./par.pl ./xloc.py for dir in $$(ls .); do \ if [ $$dir = "Hëx" ]; then \ :; \ diff --git a/xwords4/dawg/Makefile.langcommon b/xwords4/dawg/Makefile.langcommon index 04471c625..5ae03dceb 100644 --- a/xwords4/dawg/Makefile.langcommon +++ b/xwords4/dawg/Makefile.langcommon @@ -269,24 +269,24 @@ allbins: $(MAKE) TARGET_TYPE=FRANK byodbins rm palmspecials.bin -table.bin: ../xloc.pl +table.bin: ../xloc.py ifdef NEWDAWG - perl -I../ ../xloc.pl $(ENCP) -tn -out $@ + ../xloc.py $(ENCP) -tn -out $@ else - perl -I../ ../xloc.pl -t -out $@ + error endif -values.bin: ../xloc.pl - perl -I../ ../xloc.pl -v -out $@ +values.bin: ../xloc.py + ../xloc.py -v -out $@ # a binary file, two bytes, one giving the size of tiles data and the # other the number of tiles in the dict. Tiles data is utf-8 and so # number is not derivable from size. -$(XWLANG)_charcount.bin: table.bin ../xloc.pl +$(XWLANG)_charcount.bin: table.bin ../xloc.py SIZ=$$(ls -l $< | awk '{print $$5}'); \ perl -e "print pack(\"c\",$$SIZ)" > $@ TMP=/tmp/tmp$$$$; \ - perl -I../ ../xloc.pl -s -out $$TMP; \ + ../xloc.py -s -out $$TMP; \ cat $$TMP >> $@; \ rm -f $$TMP diff --git a/xwords4/dawg/dictstats.pl b/xwords4/dawg/dictstats.pl deleted file mode 100755 index 819b82e35..000000000 --- a/xwords4/dawg/dictstats.pl +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/perl - -# print stats about in input stream that's assumed to be a dictionary. -# Counts and percentages of each letter, as well as total numbers of -# words. This is not part of the dictionary build process. I use it -# for creating info.txt files for new languages and debugging the -# creation of dictionaries from new wordlists. -# -# Something like this might form the basis for choosing counts and -# values for tiles without using the conventions established by -# Scrabble players. This isn't enough, though: the frequency of -# letter tuples and triples -- how often letters appear together -- is -# a better indicator than just letter count. - -use strict; - -my @wordSizeCounts; -my %letterCounts; -my $wordCount; -my $letterCount; -my $enc = "utf8"; # this could be a cmdline arg.... - -if ( $enc ) { - binmode( STDOUT, ":encoding($enc)" ) ; - binmode( STDIN, ":encoding($enc)" ) ; -} - -while (<>) { - - chomp; - - ++$wordSizeCounts[length]; - ++$wordCount; - - foreach my $letter (split( / */ ) ) { - my $ii = ord($letter); - # special-case the bogus chars we add for "specials" - die "$0: this is a letter?: $ii" if $ii <= 32 && $ii >= 4 && $ii != 0; - ++$letterCounts{$letter}; - ++$letterCount; - } -} - -print "Number of words: $wordCount\n"; -print "Number of letters: $letterCount\n\n"; - - -print "**** word sizes ****\n"; -print "SIZE COUNT PERCENT\n"; -my $pctTotal = 0.0; -my $wordTotal = 0; -for ( my $i = 1 ; $i <= 99; ++$i ) { - my $count = $wordSizeCounts[$i]; - $wordTotal += $count; - if ( $count > 0 ) { - my $pct = (100.00 * $count)/$wordCount; - $pctTotal += $pct; - printf "%2d %6d %.2f\n", $i, $count, $pct; - } -} -printf "-------------------------------\n"; -printf " %6d %.2f\n", $wordTotal, $pctTotal; - - -print "\n\n**** Letter counts ****\n"; -print " ASCII ORD HEX PCT (of $letterCount)\n"; -my $lineNo = 1; -foreach my $key (sort keys %letterCounts) { - my $count = $letterCounts{$key}; - my $pct = (100.00 * $count) / $letterCount; - printf( "%2d: %3s %3d %x %5.2f (%d)\n", - $lineNo, $key, ord($key), ord($key), $pct, $count ); - ++$lineNo; -} - -print "\n"; diff --git a/xwords4/dawg/dictstats.py b/xwords4/dawg/dictstats.py new file mode 100755 index 000000000..28bfb631f --- /dev/null +++ b/xwords4/dawg/dictstats.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 + +import sys + +""" +print stats about in input stream that's assumed to be a dictionary. +Counts and percentages of each letter, as well as total numbers of +words. This is not part of the dictionary build process. I use it +for creating info.txt files for new languages and debugging the +creation of dictionaries from new wordlists. + +Something like this might form the basis for choosing counts and +values for tiles without using the conventions established by +Scrabble players. This isn't enough, though: the frequency of +letter tuples and triples -- how often letters appear together -- is +a better indicator than just letter count. +""" + + + +def main(): + wordSizeCounts = {} + letterCounts = {} + wordCount = 0 + letterCount = 0 + enc = 'utf8' # this could be a cmdline arg.... + + for line in sys.stdin.readlines(): + line = line.strip() + + length = len(line) + if not length in wordSizeCounts: wordSizeCounts[length] = 0 + wordSizeCounts[length] += 1 + wordCount += 1 + + for letter in line: + ii = ord(letter) + # perl did this: die "$0: this is a letter?: $ii" if $ii <= 32 && $ii >= 4 && $ii != 0; + assert ii > 32 or ii < 4 or ii == 0, 'letter {} out of range'.format(ii) + if not letter in letterCounts: letterCounts[letter] = 0 + letterCounts[letter] += 1 + letterCount += 1 + + print( 'Number of words: {}'.format(wordCount)) + print( 'Number of letters: {}'.format(letterCount)) + print('') + + print( '**** word sizes ****' ) + print( 'SIZE COUNT PERCENT' ) + pctTotal = 0.0 + wordTotal = 0 + for ii in sorted(wordSizeCounts): + count = wordSizeCounts[ii] + wordTotal += count + pct = (100.00 * count)/wordCount + pctTotal += pct + print( '{:2d} {:6d} {:02.2f}'.format(ii, count, pct)) + + print( '-------------------------------' ) + print(' {:6d} {:.2f}'.format( wordTotal, pctTotal)) + print('') + + lineNo = 1 + pctTotal = 0.0 + print( '**** Letter counts ****' ) + print( ' ASCII ORD HEX PCT (of {})'.format(letterCount)) + for letter in sorted(letterCounts): + count = letterCounts[letter] + pct = (100.00 * count) / letterCount + pctTotal += pct + print( '{:2d}: {: >6s} {:2d} {:x} {:5.2f} ({:d})' \ + .format(lineNo, letter, ord(letter), ord(letter), pct, count ) ) + lineNo += 1 + + print('percent total {:.2f}'.format( pctTotal)) + print('') + +############################################################################## +if __name__ == '__main__': + main() diff --git a/xwords4/dawg/frank_mkspecials.pl b/xwords4/dawg/frank_mkspecials.pl deleted file mode 100755 index 5c0ed4465..000000000 --- a/xwords4/dawg/frank_mkspecials.pl +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/perl - -# Copyright 2001 by Eric House (xwords@eehouse.org) -# -# 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. - -# Given arguments consisting of triples, first a string and then pbitm -# files representing bitmaps. For each triple, print out the string and -# then the converted bitmaps. - -use strict; - -while ( @ARGV ) { - my $str = shift(); - my $largebmp = shift(); - my $smallbmp = shift(); - - doOne( $str, $largebmp, $smallbmp ); -} - -sub doOne { - my ( $str, $largebmp, $smallbmp ) = @_; - - print pack( "C", length($str) ); - print $str; - - print STDERR "looking at $largebmp", "\n"; - - die "file $largebmp does not exist\n" unless -e $largebmp; - print `cat $largebmp | ../pbitm2bin.pl`; - die "file $smallbmp does not exist\n" unless -e $smallbmp; - print `cat $smallbmp | ../pbitm2bin.pl`; -} - - diff --git a/xwords4/dawg/xloc.pl b/xwords4/dawg/xloc.pl deleted file mode 100755 index 23ef0ca43..000000000 --- a/xwords4/dawg/xloc.pl +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/perl - -# Copyright 2002 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. - -# test and wrapper file for xloc.pm - -use strict; -use xloc; - -my $unicode = -1; -my $doval = 0; -my $dosize = 0; -my $enc; -my $outfile; - -my $arg; -while ( $arg = $ARGV[0] ) { - if ( $arg eq '-enc' ) { - $enc = $ARGV[1]; - shift @ARGV; - } elsif ( $arg eq "-tn" ) { - $unicode = 1; - } elsif ( $arg eq "-t" ) { - $unicode = 0; - } elsif ( $arg eq "-v" ) { - $doval = 1; - } elsif ( $arg eq "-s" ) { - $dosize = 1; - } elsif ( $arg eq '-out' ) { - $outfile = $ARGV[1]; - shift @ARGV; - } else { - die "unknown arg $arg\n"; - } - shift @ARGV; -} - -my $infoFile = "info.txt"; - -die "info file $infoFile not found\n" if ! -s $infoFile; - -my $xlocToken = xloc::ParseTileInfo($infoFile, $enc); - -if ( $enc ) { - open OUTFILE, ">:encoding($enc)", "$outfile" - or die "couldn't open $outfile"; -} else { - open OUTFILE, ">$outfile" or die "couldn't open $outfile"; -} -# For f*cking windoze linefeeds -# binmode( OUTFILE ); - -if ( $unicode ne -1 ) { - xloc::WriteMapFile( $xlocToken, $unicode, \*OUTFILE ); -} elsif ( $dosize ) { - my $count = xloc::GetNTiles( $xlocToken ); - print OUTFILE pack("c", $count ); -} elsif ( $doval ) { - xloc::WriteValuesFile( $xlocToken, \*OUTFILE ); -} - -close OUTFILE; diff --git a/xwords4/dawg/xloc.pm b/xwords4/dawg/xloc.pm deleted file mode 100644 index 2bcb624b5..000000000 --- a/xwords4/dawg/xloc.pm +++ /dev/null @@ -1,194 +0,0 @@ -#!/usr/bin/perl - -# Copyright 2002-2014 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. - -# The idea here is that all that matters about a language is stored in -# one file (possibly excepting rules for prepping a dictionary). -# There's a list of tile faces, counts and values, and also some -# name-value pairs as needed. The pairs come first, and then a list -# of tiles. - -package xloc; - -use strict; -use warnings; -# force output in utf8 -use open qw/:std :utf8/; - -BEGIN { - use Exporter (); - our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS); - - $VERSION = 1.00; - - @ISA = qw(Exporter); - @EXPORT = qw(&ParseTileInfo &GetNTiles &TileFace &TileValue - &TileCount &GetValue &WriteMapFile &WriteValuesFile); - %EXPORT_TAGS = ( ); -} - -# Returns what's meant to be an opaque object that can be passed back -# for queries. It's a hash with name-value pairs and an _INFO entry -# containing a list of tile info lists. - -sub ParseTileInfo($$) { - my ( $filePath, $enc ) = @_; - my %result; - - if ( $enc ) { - open( INPUT, "<:encoding($enc)", "$filePath" ) - or die "couldn't open $filePath"; - } else { - open( INPUT, "<$filePath" ) - or die "couldn't open $filePath"; - } - - my $inTiles = 0; - my @tiles; - while ( ) { - - chomp; - s/\#.*$//; - s/^\s*$//; # nuke all-white-space lines - next if !length; - - if ( $inTiles ) { - if ( // ) { - last; - } else { - my ( $count, $val, $face ) = m/^\s*(\w+)\s+(\w+)\s+(.*)\s*$/; - push @tiles, [ $count, $val, $face ]; - } - } elsif ( /\w:/ ) { - my ( $nam, $val ) = split ':', $_, 2; - $result{$nam} .= $val; - } elsif ( // ) { - $inTiles = 1; - } - - } - - close INPUT; - - $result{"_TILES"} = [ @tiles ]; - - return \%result; -} - -sub GetNTiles($) { - my ( $hashR ) = @_; - - my $listR = ${$hashR}{"_TILES"}; - - return 0 + @{$listR}; -} - -sub GetValue($$) { - my ( $hashR, $name ) = @_; - return ${$hashR}{$name}; -} - -sub printLetters($$) { - my ( $str, $fhr ) = @_; - my @letters = split( /\|/, $str ); - $str = join( " ", @letters ); - for ( my $key = 0; $key < length($str); ++$key ) { - my $chr = substr( $str, $key, 1 ); - print $fhr pack( "U", ord($chr) ); - } -} - -sub WriteMapFile($$$) { - my ( $hashR, $unicode, $fhr ) = @_; - - my $count = GetNTiles($hashR); - my $specialCount = 0; - for ( my $i = 0; $i < $count; ++$i ) { - my $tileR = GetNthTile( $hashR, $i ); - my $str = ${$tileR}[2]; - - if ( $str =~ /\'(.(\|.)*)\'/ ) { - printLetters( $1, $fhr ); - } elsif ( $str =~ /\"(.+)\"/ ) { - print $fhr pack( "c", $specialCount++ ); - } elsif ( $str =~ /(\d+)/ ) { - print $fhr pack( "n", $1 ); - } else { - die "WriteMapFile: unrecognized face format $str, elem $i"; - } - } -} # WriteMapFile - -sub WriteValuesFile($$) { - my ( $hashR, $fhr ) = @_; - - my $header = GetValue( $hashR,"XLOC_HEADER" ); - die "no XLOC_HEADER found" if ! $header; - - print STDERR "header is $header\n"; - - print $fhr pack( "n", hex($header) ); - - my $count = GetNTiles($hashR); - for ( my $i = 0; $i < $count; ++$i ) { - my $tileR = GetNthTile( $hashR, $i ); - - print $fhr pack( "c", TileValue($tileR) ); - print $fhr pack( "c", TileCount($tileR) ); - } - -} # WriteValuesFile - -sub GetNthTile($$) { - my ( $hashR, $n ) = @_; - my $listR = ${$hashR}{"_TILES"}; - - return ${$listR}[$n]; -} - -sub TileFace($) { - my ( $tileR ) = @_; - my $result; - - my $str = ${$tileR}[2]; - - if ( $str =~ /\'(.(\|.)*)\'/ ) { - $result = $1; - } elsif ( $str =~ /\"(.+)\"/ ) { - $result = $1; - } elsif ( $str =~ /(\d+)/ ) { - $result = chr($1); - } else { - die "TileFace: unrecognized face format: $str"; - } - return $result; -} - -sub TileValue($) { - my ( $tileR ) = @_; - - return ${$tileR}[0]; -} - -sub TileCount($) { - my ( $tileR ) = @_; - - return ${$tileR}[1]; -} - -1; diff --git a/xwords4/dawg/xloc.py b/xwords4/dawg/xloc.py new file mode 100755 index 000000000..1aef1ff0c --- /dev/null +++ b/xwords4/dawg/xloc.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python3 +import argparse, os, re, struct, sys + +def errorOut(msg): + print('ERROR: {}'.format(msg)) + sys.exit(1) + +def mkParser(): + parser = argparse.ArgumentParser() + parser.add_argument('-enc', dest = 'ENCODING', type = str, help = 'use this encoding' ) + parser.add_argument('-tn', dest = 'DO_TABLE', action = 'store_true', help = 'output table file' ) + # parser.add_argument('-tn', dest = 'UNICODE', default = False, + # action = 'store_true', help = 'assume unicode') + # parser.add_argument('-t', dest = 'UNICODE', type = str, default = True, + # action = 'store_false', help = 'DO NOT assume unicode') + parser.add_argument('-v', dest = 'DO_VALS', action = 'store_true', help = 'output values file' ) + parser.add_argument('-s', dest = 'DO_SIZE', action = 'store_true', help = 'output size file') + parser.add_argument('-out', dest = 'OUTFILE', type = str, help = 'outfile path') + return parser + +sPreComment = re.compile('^(.*)#.*$') +sVarAssign = re.compile('^(\w+):(.*)$') +sBeginTiles = re.compile('^$') +sEndTiles = re.compile('^$') +sSingleCharMatch = re.compile('\'(.(\|.)+)\'') +sSpecialsMatch = re.compile('{"(.+)"}') + +def parseTileInfo(infoFile, encoding): + result = {'_TILES' : []} + with open(infoFile, 'rt') as file: + data = file.read() + # if encoding: + # data = data.decode(encoding) + data = data.split('\n') + + inTiles = False + tiles = [] + for line in data: + # print('line at start: {}'.format(line)) + match = sPreComment.match(line) + if match: + line = match.group(1) + # print('line sans comment: {}'.format(line)) + if 0 == len(line):continue + + if inTiles: + if sEndTiles.match(line): + break + else: + (count, val, face) = line.split(None, 3) + result['_TILES'].append((count, val, face)) + elif sBeginTiles.match(line): + inTiles = True + else: + match = sVarAssign.match(line) + if match: + var = match.group(1) + if not var in result: result[var] = '' + result[var] += match.group(2) + + return result + +class XLOC(): + None + +def readXLOC(): + return XLOC() + +# sub WriteMapFile($$$) { +# my ( $hashR, $unicode, $fhr ) = @_; + +# my $count = GetNTiles($hashR); +# my $specialCount = 0; +# for ( my $i = 0; $i < $count; ++$i ) { +# my $tileR = GetNthTile( $hashR, $i ); +# my $str = ${$tileR}[2]; + +# if ( $str =~ /\'(.(\|.)*)\'/ ) { +# printLetters( $1, $fhr ); +# } elsif ( $str =~ /\"(.+)\"/ ) { +# print $fhr pack( "c", $specialCount++ ); +# } elsif ( $str =~ /(\d+)/ ) { +# print $fhr pack( "n", $1 ); +# } else { +# die "WriteMapFile: unrecognized face format $str, elem $i"; +# } +# } +# } # WriteMapFile + +def printLetters( letters, outfile ): + letters = letters.split('|') + letters = ' '.join(letters) + outfile.write(letters.encode('utf8')) + +def writeMapFile(xlocToken, outfile): + print('writeMapFile()') + tiles = xlocToken['_TILES'] + specialCount = 0 + for tile in tiles: + face = tile[2] + match = sSingleCharMatch.match(face) + if match: + print('single char: {}'.format(match.group(1))) + printLetters( match.group(1), outfile ) + continue + match = sSpecialsMatch.match(face) + if match: + print('specials char: {}'.format(match.group(1))) + outfile.write(struct.pack('B', specialCount )) + specialCount += 1 + continue + + print('bad/unmatched face: {}'.format(face)) + assert False + +def writeValuesFile(xlocToken, outfile): + header = xlocToken.get('XLOC_HEADER') or errorOut('no XLOC_HEADER found') + + print('writing header: {}'.format(header)) + outfile.write(struct.pack('!H', int(header, 16))) + + for tile in xlocToken['_TILES']: + val = int(tile[0]) + count = int(tile[1]) + outfile.write(struct.pack('BB', val, count)) + +def main(): + print('{}.main {} called'.format(sys.argv[0], sys.argv[1:])) + args = mkParser().parse_args() + assert args.OUTFILE + + infoFile = 'info.txt' + if not os.path.exists(infoFile): + errorOut('{} not found'.format(infoFile)) + xlocToken = parseTileInfo(infoFile, args.ENCODING) + + xloc = readXLOC() + + with open(args.OUTFILE, 'wb') as outfile: + if args.DO_TABLE: + writeMapFile(xlocToken, outfile); + elif args.DO_SIZE: + assert not args.DO_VALS + count = len(xlocToken['_TILES']) + outfile.write(struct.pack('!B', count)) + elif args.DO_VALS: + assert not args.DO_SIZE + writeValuesFile( xlocToken, outfile ) + + +############################################################################## +if __name__ == '__main__': + main() From 10ae99fb5ecab53a89101698f9c40b800b94fc2b Mon Sep 17 00:00:00 2001 From: Eric House Date: Tue, 30 Jun 2020 20:06:20 -0700 Subject: [PATCH 11/27] remove files I'll never need again --- xwords4/dawg/allchars.pl | 10 - xwords4/dawg/dict2dawg.pl | 857 -------------------------------------- xwords4/dawg/par.pl | 234 ----------- 3 files changed, 1101 deletions(-) delete mode 100755 xwords4/dawg/allchars.pl delete mode 100755 xwords4/dawg/dict2dawg.pl delete mode 100755 xwords4/dawg/par.pl diff --git a/xwords4/dawg/allchars.pl b/xwords4/dawg/allchars.pl deleted file mode 100755 index 361376ef8..000000000 --- a/xwords4/dawg/allchars.pl +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/perl - -# Print all ascii characters (for pasting into Makefiles etc. when you -# don't know what key combination produces them) - -use strict; - -for ( my $i = int(' '); $i <= 255; ++$i ) { - printf "%.3d: %c\n", $i, $i; -} diff --git a/xwords4/dawg/dict2dawg.pl b/xwords4/dawg/dict2dawg.pl deleted file mode 100755 index 064dff84e..000000000 --- a/xwords4/dawg/dict2dawg.pl +++ /dev/null @@ -1,857 +0,0 @@ -#!/usr/bin/perl - -############################################################################## -# adapted from C++ code Copyright (C) 2000 Falk Hueffner -# This version Copyright (C) 2002 Eric House (xwords@eehouse.org) -# -# 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 -############################################################################## - -# inputs: 0. Name of file mapping letters to 0..31 values. In English -# case just contains A..Z. This will be used to translate the tries -# on output. -# 1. Max number of bytes per binary output file. -# -# 2. Basename of binary files for output. - -# 3. Name of file to which to write the number of the -# startNode, since I'm not rewriting a bunch of code to expect Falk's -# '*' node at the start. -# - -# In STDIN, the text file to be compressed. It absolutely -# must be sorted. The sort doesn't have to follow the order in the -# map file, however. - -# This is meant eventually to be runnable as part of a cgi system for -# letting users generate Crosswords dicts online. - - - -use strict; -use POSIX; - -my $gFirstDiff; -my @gCurrentWord; -my $gCurrentWord; # save so can check for sortedness -my $gDone = 0; -my @gInputStrings; -my $gNeedsSort = 1; # read from cmd line eventually -my @gNodes; # final array of nodes -my $gNBytesPerOutfile = 0xFFFFFFFF; -my $gTableFile; -my $gOutFileBase; -my $gStartNodeOut; -my $gInFileName; -my $gKillIfMissing = 1; -my $gTermChar = '/n'; -my $gDumpText = 0; # dump the dict as text after? -my $gCountFile; -my $gBytesPerNodeFile; # where to write whether node size 3 or 4 -my $gWordCount = 0; -my %gTableHash; -my $gBlankIndex; -my @gRevMap; -my $debug = 0; -my %gSubsHash; -my $gForceFour = 0; # use four bytes regardless of need? -my $gNBytesPerNode; -my $gUseUnicode; - -main(); - -exit; - -############################################################################## - -sub main() { - - if ( !parseARGV() ) { - usage(); - exit(); - } - - makeTableHash(); - - my $infile; - - if ( $gInFileName ) { - open $infile, "<$gInFileName"; - } else { - $infile = \*STDIN; - } - - @gInputStrings = parseAndSort( $infile ); - if ( $gInFileName ) { - close $infile; - } - - # Do I need this stupid thing? Better to move the first row to - # the front of the array and patch everything else. Or fix the - # non-palm dictionary format to include the offset of the first - # node. - - my $dummyNode = 0xFFFFFFFF; - @gNodes = ( $dummyNode ); - - readNextWord(); - - my $firstRootChildOffset = buildNode(0); - - moveTopToFront( \$firstRootChildOffset ); - - if ( $gStartNodeOut ) { - writeOutStartNode( $gStartNodeOut, $firstRootChildOffset ); - } - - print STDERR "\n... dumping table ...\n" if $debug; - printNodes( \@gNodes, "done with main" ) if $debug; - - # write out the number of nodes if requested - if ( $gCountFile ) { - open OFILE, "> $gCountFile"; - print OFILE pack( "N", $gWordCount ); - close OFILE; - print STDERR "wrote out: got $gWordCount words\n"; - } - - if ( $gOutFileBase ) { - emitNodes( $gNBytesPerOutfile, $gOutFileBase ); - } - - if ( $gDumpText && @gNodes > 0 ) { - printOneLevel( $firstRootChildOffset, "" ); - } - - if ( $gBytesPerNodeFile ) { - open OFILE, "> $gBytesPerNodeFile"; - print OFILE $gNBytesPerNode; - close OFILE; - } - print STDERR "Used $gNBytesPerNode per node.\n"; -} # main - -# We now have an array of nodes with the last subarray being the -# logical top of the tree. Move them to the start, fixing all fco -# refs, so that legacy code like Palm can assume top==0. -# -# Note: It'd probably be a bit faster to integrate this with emitNodes -# -- unless I need to have an in-memory list that can be used for -# lookups. But that's best for debugging, so keep it this way for now. -# -# Also Note: the first node is a dummy that can and should be tossed -# now. - -sub moveTopToFront($) { - my ( $firstRef ) = @_; - - my $firstChild = ${$firstRef}; - ${$firstRef} = 0; - my @lastSub; - - if ( $firstChild > 0 ) { - # remove the last (the root) subarray - @lastSub = splice( @gNodes, $firstChild ); - } else { - die "there should be no words!!" if $gWordCount != 0; - } - # remove the first (garbage) node - shift @gNodes; - - my $diff; - if ( $firstChild > 0 ) { - # -1 because all move down by 1; see prev line - $diff = @lastSub - 1; - die "something wrong with len\n" if $diff < 0; - } else { - $diff = 0; - } - - # stick it on the front - splice( @gNodes, 0, 0, @lastSub); - - # We add $diff to everything. There's no subtracting because - # nobody had any refs to the top list. - - for ( my $i = 0; $i < @gNodes; ++$i ) { - my $fco = TrieNodeGetFirstChildOffset( $gNodes[$i] ); - if ( $fco != 0 ) { # 0 means NONE, not 0th!! - TrieNodeSetFirstChildOffset( \$gNodes[$i], $fco+$diff ); - } - } -} # moveTopToFront - - -sub buildNode { - my ( $depth ) = @_; - - if ( @gCurrentWord == $depth ) { - # End of word reached. If the next word isn't a continuation - # of the current one, then we've reached the bottom of the - # recursion tree. - readNextWord(); - if ($gFirstDiff < $depth || $gDone) { - return 0; - } - } - - my @newedges; - - do { - my $letter = $gCurrentWord[$depth]; - my $isTerminal = @gCurrentWord - 1 == $depth ? 1:0; - - my $nodeOffset = buildNode($depth+1); - my $newNode = MakeTrieNode($letter, $isTerminal, $nodeOffset); - push( @newedges, $newNode ); - - } while ( ($gFirstDiff == $depth) && !$gDone); - - TrieNodeSetIsLastSibling( \@newedges[@newedges-1], 1 ); - - return addNodes( \@newedges ); -} # buildNode - -sub addNodes { - my ( $newedgesR ) = @_; - - my $found = findSubArray( $newedgesR ); - - if ( $found >= 0 ) { - die "0 is an invalid match!!!" if $found == 0; - return $found; - } else { - - my $firstFreeIndex = @gNodes; - - print STDERR "adding...\n" if $debug; - printNodes( $newedgesR ) if $debug; - - push @gNodes, (@{$newedgesR}); - - registerSubArray( $newedgesR, $firstFreeIndex ); - return $firstFreeIndex; - } -} # addNodes - -sub printNode { - my ( $index, $node ) = @_; - - print STDERR "[$index] "; - - my $letter = TrieNodeGetLetter($node); - printf( STDERR - "letter=%d(%s); isTerminal=%d; isLastSib=%d; fco=%d;\n", - $letter, "" . $gRevMap[$letter], - TrieNodeGetIsTerminal($node), - TrieNodeGetIsLastSibling($node), - TrieNodeGetFirstChildOffset($node)); -} # printNode - -sub printNodes { - my ( $nodesR, $name ) = @_; - - my $len = @{$nodesR}; - # print "printNodes($name): len = $len\n"; - - for ( my $i = 0; $i < $len; ++$i ) { - my $node = ${$nodesR}[$i]; - printNode( $i, $node ); - } - -} - - -# Hashing. We'll keep a hash of offsets into the existing nodes -# array, and as the key use a string that represents the entire sub -# array. Since the key is what we're matching for, there should never -# be more than one value per hash and so we don't need buckets. -# Return -1 if there's no match. - -sub findSubArray { - my ( $newedgesR ) = @_; - - my $key = join('', @{$newedgesR}); - - if ( exists( $gSubsHash{$key} ) ) { - return $gSubsHash{$key}; - } else { - return -1; - } -} # findSubArray - -# add to the hash -sub registerSubArray { - my ( $edgesR, $nodeLoc ) = @_; - - my $key = join( '', @{$edgesR} ); - - if ( exists $gSubsHash{$key} ) { - die "entry for key shouldn't exist!!"; - } else { - $gSubsHash{$key} = $nodeLoc; - } - -} # registerSubArray - -sub toWord($) { - my ( $tileARef ) = @_; - my $word = ""; - - foreach my $tile (@$tileARef) { - foreach my $letter (keys (%gTableHash) ) { - if ( $tile == $gTableHash{$letter} ) { - $word .= $letter; - last; - } - } - } - - return $word; -} - -sub readNextWord() { - my @word; - - if ( !$gDone ) { - $gDone = @gInputStrings == 0; - if ( !$gDone ) { - @word = @{shift @gInputStrings}; - } else { - print STDERR "gDone set to true\n" if $debug; - } - - print STDERR "got word: ", join(',',@word), "\n" if $debug; - } - my $numCommonLetters = 0; - my $len = @word; - if ( @gCurrentWord < $len ) { - $len = @gCurrentWord; - } - - while ( @gCurrentWord[$numCommonLetters] eq @word[$numCommonLetters] - && $numCommonLetters < $len) { - ++$numCommonLetters; - } - - $gFirstDiff = $numCommonLetters; - if ( #$debug && - @gCurrentWord > 0 && @word > 0 - && !firstBeforeSecond( \@gCurrentWord, \@word ) ) { - die "words ", join(",",@gCurrentWord), " (" . toWord(\@gCurrentWord) . - ") and " . join(",", @word) . " (" . toWord(\@word) . - ") out of order"; - } - @gCurrentWord = @word; -} # readNextWord - -sub firstBeforeSecond { - my ( $firstR, $secondR ) = @_; - - for ( my $i = 0; ; ++$i ) { - - # if we reach the end of the first word/list, we're done. - if ( $i == @{$firstR} ) { - die "duplicate!!!" if $i == @{$secondR}; - return 1; - # but if we reach the second end first, we've failed - } elsif ( $i == @{$secondR} ) { - return 0; - } - - my $diff = ${$firstR}[$i] <=> ${$secondR}[$i]; - - if ( $diff == 0 ) { - next; - } else { - return $diff < 0; - } - } -} # firstBeforeSecond - -# passed to sort. Should remain unprototyped for effeciency's sake - -sub cmpWords { - - my $lenA = @{$a}; - my $lenB = @{$b}; - my $min = $lenA > $lenB? $lenB: $lenA; - - for ( my $i = 0; $i < $min; ++$i ) { - my $ac = ${$a}[$i]; - my $bc = ${$b}[$i]; - - my $res = $ac <=> $bc; - - if ( $res != 0 ) { - return $res; # we're done - } - } - - # If we got here, they match up to their common length. Longer is - # greater. - my $res = @{$a} <=> @{$b}; - return $res; # which is longer? -} # cmpWords - -sub parseAndSort() { - my ( $infile ) = @_; - - my @wordlist; - my @word; - - my $lastWord; - WORDLOOP: - for ( ; ; ) { - - my $dropWord = 0; - splice @word; # empty it - - # for each byte - for ( ; ; ) { - my $byt = getc($infile); - - if ( $byt eq undef ) { - last WORDLOOP; - } elsif ( $byt eq $gTermChar ) { - if ( !$dropWord ) { - push @wordlist, [ @word ]; - ++$gWordCount; - } - $lastWord = ""; - next WORDLOOP; - } elsif ( exists( $gTableHash{$byt} ) ) { - if ( !$dropWord ) { - push @word, $gTableHash{$byt}; - die "word too long" if @word > 15; - if ( $gKillIfMissing ) { - $lastWord .= $byt; - } - } - } elsif ($gKillIfMissing) { - die "$0: chr $byt (", $byt+0, ") not in map file $gTableFile\n" - . "last word was $lastWord\n"; - } else { - $dropWord = 1; - splice @word; # lose anything we already have - } - } - } - - if ( $gNeedsSort && ($gWordCount > 0) ) { - print STDERR "starting sort...\n" if $debug; - @wordlist = sort cmpWords @wordlist; - print STDERR "sort finished\n" if $debug; - } - - print STDERR "length of list is ", @wordlist + 0, ".\n" if $debug; - - return @wordlist; -} # parseAndSort - -# Print binary representation of trie array. This isn't used yet, but -# eventually it'll want to dump to multiple files appropriate for Palm -# that can be catenated together on other platforms. There'll need to -# be a file giving the offset of the first node too. Also, might want -# to move to 4-byte representation when the input can't otherwise be -# handled. - -sub dumpNodes { - - for ( my $i = 0; $i < @gNodes; ++$i ) { - my $node = $gNodes[$i]; - my $bstr = pack( "I", $node ); - print STDOUT $bstr; - } -} - -############################################################################## -# Little node-field setters and getters to hide what bits represent -# what. -# -# high bit (31) is ACCEPTING bit -# next bit (30) is LAST_SIBLING bit -# next 6 bits (29-24) are tile bit (allowing alphabets of 64 letters) -# final 24 bits (23-0) are the index of the first child (fco) -# -############################################################################## - -sub TrieNodeSetIsTerminal { - my ( $nodeR, $isTerminal ) = @_; - - if ( $isTerminal ) { - ${$nodeR} |= (1 << 31); - } else { - ${$nodeR} &= ~(1 << 31); - } -} - -sub TrieNodeGetIsTerminal { - my ( $node ) = @_; - return ($node & (1 << 31)) != 0; -} - -sub TrieNodeSetIsLastSibling { - my ( $nodeR, $isLastSibling ) = @_; - if ( $isLastSibling ) { - ${$nodeR} |= (1 << 30); - } else { - ${$nodeR} &= ~(1 << 30); - } -} - -sub TrieNodeGetIsLastSibling { - my ( $node ) = @_; - return ($node & (1 << 30)) != 0; -} - -sub TrieNodeSetLetter { - my ( $nodeR, $letter ) = @_; - - die "$0: letter ", $letter, " too big" if $letter >= 64; - - my $mask = ~(0x3F << 24); - ${$nodeR} &= $mask; # clear all the bits - ${$nodeR} |= ($letter << 24); # set new ones -} - -sub TrieNodeGetLetter { - my ( $node ) = @_; - $node >>= 24; - $node &= 0x3F; # is 3f ok for 3-byte case??? - return $node; -} - -sub TrieNodeSetFirstChildOffset { - my ( $nodeR, $fco ) = @_; - - die "$0: $fco larger than 24 bits" if ($fco & 0xFF000000) != 0; - - my $mask = ~0x00FFFFFF; - ${$nodeR} &= $mask; # clear all the bits - ${$nodeR} |= $fco; # set new ones -} - -sub TrieNodeGetFirstChildOffset { - my ( $node ) = @_; - $node &= 0x00FFFFFF; # 24 bits - return $node; -} - - -sub MakeTrieNode { - my ( $letter, $isTerminal, $firstChildOffset, $isLastSibling ) = @_; - my $result = 0; - - TrieNodeSetIsTerminal( \$result, $isTerminal ); - TrieNodeSetIsLastSibling( \$result, $isLastSibling ); - TrieNodeSetLetter( \$result, $letter ); - TrieNodeSetFirstChildOffset( \$result, $firstChildOffset ); - - return $result; -} # MakeTrieNode - -# Caller may need to know the offset of the first top-level node. -# Write it here. -sub writeOutStartNode { - my ( $startNodeOut, $firstRootChildOffset ) = @_; - - open NODEOUT, ">$startNodeOut"; - print NODEOUT pack( "N", $firstRootChildOffset ); - close NODEOUT; -} # writeOutStartNode - -# build the hash for translating. I'm using a hash assuming it'll be -# fast. Key is the letter; value is the 0..31 value to be output. -sub makeTableHash { - my $i; - open TABLEFILE, "< $gTableFile"; - - splice @gRevMap; # empty it - - for ( $i = 0; ; ++$i ) { - my $ch = getc(TABLEFILE); - if ( $ch eq undef ) { - last; - } - - if ( $gUseUnicode ) { # skip the first byte each time: tmp HACK!!! - $ch = getc(TABLEFILE); - } - if ( $ch eq undef ) { - last; - } - - push @gRevMap, $ch; - - if ( ord($ch) == 0 ) { # blank - $gBlankIndex = $i; - next; # we want to increment i when blank seen since - # it is a tile value - } - - die "$0: $gTableFile too large\n" if $i > 64; - die "$0: only blank (0) can be 64th char\n" if ($i == 64 && $ch != 0); - - $gTableHash{$ch} = $i; - } - - close TABLEFILE; -} # makeTableHash - -# emitNodes. "input" is $gNodes. From it we write up to -# $nBytesPerOutfile to files named $outFileBase0..n, mapping the -# letter field down to 5 bits with a hash built from $tableFile. If -# at any point we encounter a letter not in the hash we fail with an -# error. - -sub emitNodes($$) { - my ( $nBytesPerOutfile, $outFileBase ) = @_; - - # now do the emit. - - # is 17 bits enough? - printf STDERR ("There are %d (0x%x) nodes in this DAWG.\n", - 0 + @gNodes, 0 + @gNodes ); - my $nTiles = 0 + keys(%gTableHash); # blank is not included in this count! - if ( @gNodes > 0x1FFFF || $gForceFour || $nTiles > 32 ) { - $gNBytesPerNode = 4; - } elsif ( $nTiles < 32 ) { - $gNBytesPerNode = 3; - } else { - if ( $gBlankIndex == 32 ) { # blank - print STDERR "blank's at 32; 3-byte-nodes still ok\n"; - $gNBytesPerNode = 3; - } else { - die "$0: move blank to last position in info.txt for smaller DAWG"; - } - } - - my $nextIndex = 0; - my $nextFileNum = 0; - - for ( $nextFileNum = 0; ; ++$nextFileNum ) { - - if ( $nextIndex >= @gNodes ) { - last; # we're done - } - - die "Too many outfiles; infinite loop?" if $nextFileNum > 99; - - my $outName = sprintf("${outFileBase}_%03d.bin", $nextFileNum); - open OUTFILE, "> $outName"; - binmode( OUTFILE ); - my $curSize = 0; - - while ( $nextIndex < @gNodes ) { - - # scan to find the next terminal - my $i; - for ( $i = $nextIndex; - !TrieNodeGetIsLastSibling($gNodes[$i]); - ++$i ) { - - # do nothing but a sanity check - if ( $i >= @gNodes) { - die "bad trie format: last node not last sibling" ; - } - - } - ++$i; # move beyond the terminal - my $nextSize = ($i - $nextIndex) * $gNBytesPerNode; - if ($curSize + $nextSize > $nBytesPerOutfile) { - last; - } else { - # emit the subarray - while ( $nextIndex < $i ) { - outputNode( $gNodes[$nextIndex], $gNBytesPerNode, - \*OUTFILE ); - ++$nextIndex; - } - $curSize += $nextSize; - } - } - - close OUTFILE; - } - -} # emitNodes - -sub printWord { - my ( $str ) = @_; - - print STDERR "$str\n"; -} - -# print out the entire dictionary, as text, to STDERR. - -sub printOneLevel { - - my ( $index, $str ) = @_; - - for ( ; ; ) { - - my $newStr = $str; - my $node = $gNodes[$index++]; - - my $lindx = $gRevMap[TrieNodeGetLetter($node)]; - - if ( ord($lindx) >= 0x20 ) { - $newStr .= "$lindx"; - } else { - print STDERR "sub space" if $debug; - $newStr .= "\\" . chr('0'+$lindx); - } - - if ( TrieNodeGetIsTerminal($node) ) { - printWord( $newStr ); - } - - my $fco = TrieNodeGetFirstChildOffset( $node ); - if ( $fco != 0 ) { - printOneLevel( $fco, $newStr ); - } - - if ( TrieNodeGetIsLastSibling($node) ) { - last; - } - } -} - -sub outputNode ($$$) { - my ( $node, $nBytes, $outfile ) = @_; - - my $fco = TrieNodeGetFirstChildOffset($node); - my $fourthByte; - - if ( $nBytes == 4 ) { - $fourthByte = $fco >> 16; - die "$0: fco too big" if $fourthByte > 0xFF; - $fco &= 0xFFFF; - } - - # Formats are different depending on whether it's to have 3- or - # 4-byte nodes. - - # Here's what the three-byte node looks like. 16 bits plus one - # burried in the last byte for the next node address, five for a - # character/tile and one each for accepting and last-edge. - - # 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - # |-------- 16 bits of next node address -------| | | | |-tile indx-| - # | | | - # accepting bit ---+ | | - # last edge bit ------+ | - # ---- last bit (17th on next node addr)---------+ - - # The four-byte format adds a byte at the right end for - # addressing, but removes the extra bit (5) in order to let the - # chars field be six bits. Bits 7 and 6 remain the same. - - # write the fco (less that one bit). We want two bytes worth - # in three-byte mode, and three in four-byte mode - - # first two bytes are low-word of fco, regardless of format - for ( my $i = 1; $i >= 0; --$i ) { - my $tmp = ($fco >> ($i * 8)) & 0xFF; - print $outfile pack( "C", $tmp ); - } - $fco >>= 16; # it should now be 1 or 0 - die "fco not 1 or 0" if $fco > 1; - - my $chIn5 = TrieNodeGetLetter($node); - my $bits = $chIn5; - die "$0: char $bits too big" if $bits > 0x1F && $nBytes == 3; - - if ( TrieNodeGetIsLastSibling($node) ) { - $bits |= 0x40; - } - if ( TrieNodeGetIsTerminal($node) ) { - $bits |= 0x80; - } - - # We set the 17th next-node bit only in 3-byte case (where char is - # 5 bits) - if ( $nBytes == 3 && $fco != 0 ) { - $bits |= 0x20; - } - print $outfile pack( "C", $bits ); - - # the final byte, if in use - if ( $nBytes == 4 ) { - print $outfile pack( "C", $fourthByte ); - } -} # outputNode - -sub usage { - print STDERR "usage: $0 \n" - . "\t[-b bytesPerFile] (default = 0xFFFFFFFF)\n" - . "\t-m mapFile\n" - . "\t-mn mapFile (unicode)\n" - . "\t-ob outFileBase\n" - . "\t-sn start node out file\n" - . "\t[-if input file name] -- default = stdin\n" - . "\t[-term ch] (word terminator -- default = '\\0'\n" - . "\t[-nosort] (input already sorted in accord with -m; " . - " default=sort'\n" - . "\t[-dump] (write dictionary as text to STDERR for testing)\n" - . "\t[-force4](use 4 bytes per node regardless of need)\n" - . "\t[-r] (reject words with letters not in mapfile)\n" - . "\t[-k] (kill if any letters no in mapfile -- default)\n" - . "\t[-debug] (print a bunch of stuff)\n" - ; - -} # usage - -sub parseARGV { - - my $arg; - while ( my $arg = shift(@ARGV) ) { - - SWITCH: { - if ($arg =~ /-b/) {$gNBytesPerOutfile = shift(@ARGV), last SWITCH;} - if ($arg =~ /-mn/) {$gTableFile = shift(@ARGV); - $gUseUnicode = 1; - last SWITCH;} - if ($arg =~ /-m/) {$gTableFile = shift(@ARGV); last SWITCH;} - if ($arg =~ /-ob/) {$gOutFileBase = shift(@ARGV), last SWITCH;} - if ($arg =~ /-sn/) {$gStartNodeOut = shift(@ARGV), last SWITCH;} - if ($arg =~ /-if/) {$gInFileName = shift(@ARGV), last SWITCH;} - if ($arg =~ /-r/) {$gKillIfMissing = 0; last SWITCH;} - if ($arg =~ /-k/) {$gKillIfMissing = 1; last SWITCH;} - if ($arg =~ /-term/) {$gTermChar = chr(shift(@ARGV)); last SWITCH;} - if ($arg =~ /-dump/) {$gDumpText = 1; last SWITCH;} - if ($arg =~ /-nosort/) {$gNeedsSort = 0; last SWITCH;} - if ($arg =~ /-wc/) {$gCountFile = shift(@ARGV); last SWITCH;} - if ($arg =~ /-ns/) {$gBytesPerNodeFile = shift(@ARGV); last SWITCH;} - if ($arg =~ /-force4/) {$gForceFour = 1; last SWITCH;} - # accept -fsize for compatibility with c++ version (but drop it) - if ($arg =~ /-fsize/) {shift(@ARGV); last SWITCH;} - if ($arg =~ /-debug/) {$debug = 1; last SWITCH;} - die "unexpected arg $arg\n"; - } - } - - - print STDERR "gNBytesPerOutfile=$gNBytesPerOutfile\n" if $debug; - print STDERR "gTableFile=$gTableFile\n" if $debug; - print STDERR "gOutFileBase=$gOutFileBase\n" if $debug; - print STDERR "gStartNodeOut=$gStartNodeOut\n" if $debug; - printf STDERR "gTermChar=%s(%d)\n", $gTermChar, ord($gTermChar) if $debug; - - return $gTableFile; - -} # parseARGV diff --git a/xwords4/dawg/par.pl b/xwords4/dawg/par.pl deleted file mode 100755 index 024c58943..000000000 --- a/xwords4/dawg/par.pl +++ /dev/null @@ -1,234 +0,0 @@ -#!/usr/bin/perl - -# Copyright 2002 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. - -# Only enough of par's features to support building a crosswords dict -# pdb - -use strict; - -my $debug = 0; - - -# stolen from par source -my $PRC_FLAGS_RESOURCE = (0x1<<0); -my $PRC_FLAGS_READONLY = (0x1<<1); -my $PRC_FLAGS_DIRTY = (0x1<<2); -my $PRC_FLAGS_BACKUP = (0x1<<3); -my $PRC_FLAGS_NEWER = (0x1<<4); -my $PRC_FLAGS_RESET = (0x1<<5); -my $PRC_FLAGS_COPYPREVENT = (0x1<<6); -my $PRC_FLAGS_STREAM = (0x1<<7); -my $PRC_FLAGS_HIDDEN = (0x1<<8); -my $PRC_FLAGS_LAUNCHABLE = (0x1<<9); -my $PRC_FLAGS_RECYCLABLE = (0x1<<10); -my $PRC_FLAGS_BUNDLE = (0x1<<11); -my $PRC_FLAGS_OPEN = (0x1<<15); - - -my $gAttrs = 0; -my $gVersion = 1; # par defaults this to 1 - -my $cmd = shift( @ARGV ); -die "only 'c' supported now" if $cmd ne "c" && $cmd ne "-c"; - -readHOptions( \@ARGV ); - -my $dbfile = shift( @ARGV ); -my $name = shift( @ARGV ); -die "name $name too long" if length($name) > 31; -my $type = shift( @ARGV ); -die "type $type must be of length 4" if length($type) != 4; -my $cid = shift( @ARGV ); -die "cid $cid must be of length 4" if length($cid) != 4; - -my @fileNames; -my @fileLengths; - -my $nFiles = 0; - -while ( @ARGV > 0 ) { - my $filename = shift( @ARGV ); - push @fileNames, $filename; - push @fileLengths, -s $filename; - ++$nFiles; -} - -# from par's prcp.h; thanks djw! -# typedef struct prc_file_t { -# prc_byte_t name[32]; -# prc_byte_t flags[2]; -# prc_byte_t version[2]; -# prc_byte_t ctime[4]; -# prc_byte_t mtime[4]; -# prc_byte_t btime[4]; -# prc_byte_t modnum[4]; -# prc_byte_t appinfo[4]; -# prc_byte_t sortinfo[4]; -# prc_byte_t type[4]; -# prc_byte_t cid[4]; -# prc_byte_t unique_id_seed[4]; -# prc_byte_t next_record_list[4]; -# prc_byte_t nrecords[2]; -# } prc_file_t; - -my $str; -my $offset = 0; - -open OUTFILE, "> $dbfile" or die "couldn't open outfile $dbfile for writing"; - -# print the string, then pad with 0s -$offset = length($name); -print OUTFILE $name; -while ( $offset < 32 ) { - print OUTFILE pack("c", 0); - ++$offset; -} - -$str = pack("n", $gAttrs); # flags -print OUTFILE $str; -$offset += length($str); - -$str = pack("n", $gVersion); # version -print OUTFILE $str; -$offset += length($str); - -my $time = time() + 2082844800; -$str = pack("NNN", $time, $time, 0); # ctime, mtime, btime -print OUTFILE $str; -$offset += length($str); - -$str = pack("N", 0 ); # mod num -print OUTFILE $str; -$offset += length($str); - -$str = pack("N", 0 ); # appinfo -print OUTFILE $str; -$offset += length($str); - -$str = pack("N", 0 ); # sortinfo -print OUTFILE $str; -$offset += length($str); - - -print OUTFILE $type; # type -print OUTFILE $cid; # cid -$offset += 8; - -$str = pack("NN", 0, 0 ); # unique_id_seed, next_record_list -print OUTFILE $str; -$offset += length($str); - -$str = pack("n", $nFiles ); # nrecords -print OUTFILE $str; -$offset += length($str); - -$offset += $nFiles * 8; -$offset += 2; # djw adds 2 bytes after size list; see below -foreach my $len ( @fileLengths ) { - print OUTFILE pack( "N", $offset ); - print OUTFILE pack( "N", 0 ); - $offset += $len; -} - -print OUTFILE pack( "n", 0 ); # djw does this sans comment: flush.c, line 87 - -foreach my $file ( @fileNames ) { - open INFILE, "<$file" or die "couldn't open infile $file\n"; - my $buffer; - while ( read INFILE, $buffer, 1024 ) { - print OUTFILE $buffer; - } - close INFILE; -} - - -close OUTFILE; - -exit 0; - -############################################################################## -# Subroutines -############################################################################## - -sub readHOptions { - - my ( $argvR ) = @_; - - for ( ; ; ) { - my $opt = ${$argvR}[0]; - - if ( $opt !~ /^-/ ) { - last; - } - - # it starts with a '-': use it; else don't consume anything - shift @{$argvR}; - - if ( $opt eq "-a" ) { - my $attrs = shift @{$argvR}; - processAttrString( $attrs ); - } elsif ( $opt eq "-v" ) { - $gVersion = shift @{$argvR}; - } else { - die "what's with \"$opt\": -a and -v are the only hattrs supported"; - } - } - -} # readHOptions - -sub processAttrString { - - my ( $attrs ) = @_; - - foreach my $flag ( split /\|/, $attrs ) { - - print STDERR "looking at flag $flag\n" if $debug; - - if ( $flag =~ /resource/ ) { - $gAttrs |= $PRC_FLAGS_RESOURCE; - die "resource attr not supported"; - } elsif ( $flag =~ /readonly/ ) { - $gAttrs |= $PRC_FLAGS_READONLY; - } elsif ( $flag =~ /dirty/ ) { - $gAttrs |= $PRC_FLAGS_DIRTY; - } elsif ( $flag =~ /backup/ ) { - $gAttrs |= $PRC_FLAGS_BACKUP; - } elsif ( $flag =~ /newer/ ) { - $gAttrs |= $PRC_FLAGS_NEWER; - } elsif ( $flag =~ /reset/ ) { - $gAttrs |= $PRC_FLAGS_RESET; - } elsif ( $flag =~ /copyprevent/ ) { - $gAttrs |= $PRC_FLAGS_COPYPREVENT; - } elsif ( $flag =~ /stream/ ) { - $gAttrs |= $PRC_FLAGS_STREAM; - die "stream attr not supported"; - } elsif ( $flag =~ /hidden/ ) { - $gAttrs |= $PRC_FLAGS_HIDDEN; - } elsif ( $flag =~ /launchable/ ) { - $gAttrs |= $PRC_FLAGS_LAUNCHABLE; - } elsif ( $flag =~ /recyclable/ ) { - $gAttrs |= $PRC_FLAGS_RECYCLABLE; - } elsif ( $flag =~ /bundle/ ) { - $gAttrs |= $PRC_FLAGS_BUNDLE; - } elsif ( $flag =~ /open/ ) { - $gAttrs |= $PRC_FLAGS_OPEN; - } else { - die "flag $flag not supportd"; - } - } -} # processAttrString From a7343f6a1d618860bccafc40cdc1e2ee9f6f78b2 Mon Sep 17 00:00:00 2001 From: Eric House Date: Wed, 1 Jul 2020 10:44:26 -0700 Subject: [PATCH 12/27] convert two more perl scripts to python --- xwords4/dawg/Makefile.langcommon | 2 +- xwords4/dawg/frank_mkspecials.py | 49 +++++++++++++++++++++++ xwords4/dawg/pbitm2bin.py | 68 ++++++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+), 1 deletion(-) create mode 100755 xwords4/dawg/frank_mkspecials.py create mode 100755 xwords4/dawg/pbitm2bin.py diff --git a/xwords4/dawg/Makefile.langcommon b/xwords4/dawg/Makefile.langcommon index 5ae03dceb..7a89557d3 100644 --- a/xwords4/dawg/Makefile.langcommon +++ b/xwords4/dawg/Makefile.langcommon @@ -213,7 +213,7 @@ endif # For each entry in the table whose face < 32, there needs to be a pair of # pbitm files and a string giving the printing form -frankspecials.bin: ../frank_mkspecials.pl $(BMPFILES) +frankspecials.bin: ../frank_mkspecials.py $(BMPFILES) $< $(BLANK_INFO) $(LANG_SPECIAL_INFO) > $@ $(XWLANG)%.$(FRANK_EXT): dawg$(XWLANG)%.stamp $(XWLANG)%_flags.bin $(XWLANG)%_newheader.bin $(XWLANG)_charcount.bin table.bin values.bin frankspecials.bin diff --git a/xwords4/dawg/frank_mkspecials.py b/xwords4/dawg/frank_mkspecials.py new file mode 100755 index 000000000..0d69af876 --- /dev/null +++ b/xwords4/dawg/frank_mkspecials.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 + +# Copyright 2001 - 2020 by Eric House (xwords@eehouse.org) +# +# 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. + +# Given arguments consisting of triples, first a string and then pbitm +# files representing bitmaps. For each triple, print out the string and +# then the converted bitmaps. + +import os, subprocess, struct, sys + +def doFile(bmp): + assert os.path.exists(bmp), 'no such file: {}'.format(bmp) + with open(bmp, 'r') as file: + subprocess.run(['../pbitm2bin.py'], stdin=file) + +def doOne( face, largebmp, smallbmp ): + # print('doOne({}, {}, {})'.format(face, largebmp, smallbmp), file=sys.stderr) + with os.fdopen(sys.stdout.fileno(), 'wb', closefd=False) as stdout: + encoded = face.encode('utf-8') + stdout.write(struct.pack('B', len(encoded))) + stdout.write(encoded) + + for fil in [ largebmp, smallbmp ]: + print('looking at {}'.format(fil), file=sys.stderr) + doFile(fil) + +def main(): + argv = sys.argv + for first in range(1, len(argv), 3): + (face, largebmp, smallbmp) = argv[first:first+3] + doOne(face, largebmp, smallbmp) + +############################################################################## +if __name__ == '__main__': + main() diff --git a/xwords4/dawg/pbitm2bin.py b/xwords4/dawg/pbitm2bin.py new file mode 100755 index 000000000..2e8bd78f0 --- /dev/null +++ b/xwords4/dawg/pbitm2bin.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 +# +# Copyright 2001-2020 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. +# +# +# Given a pbitm on stdin, a text bitmap file where '#' indicates a set +# bit and '-' indicates a clear bit, convert into binary form (on +# stdout) where there's one bit per bit plus a byte each for the width +# and height. Nothing for bitdepth at this point. And no padding: if +# the number of bits in a row isn't a multiple of 8 then one byte will +# hold the last bits of one row and the first of another. + +import os, struct, sys + +lines = [ line.strip() for line in sys.stdin ] +nRows = len(lines) +nCols = 0 +bits = '' + +# first gather information and sanity-check the data + +for line in lines: + lineLen = len(line) + if nCols == 0: + nCols = lineLen + else: + assert nCols == lineLen, 'line of inconsistent length' + bits += line + +with os.fdopen(sys.stdout.fileno(), "wb", closefd=False) as stdout: + stdout.write(struct.pack('B', nCols)) + + # if we've been given an empty file, print out a single null byte + # and be done. That'll be the convention for "non-existant + # bitmap". + + if nCols > 0: + stdout.write(struct.pack( 'B', nRows ) ) + print( 'emitting {}x{} bitmap'.format(nCols, nRows), file=sys.stderr) + + while bits: + cur = bits[:8] + bits = bits[8:] + + byt = 0 + for indx in range(len(cur)): + ch = cur[indx] + assert ch == '-' or ch == '#', "char {} neither '#' nor '-'".format(ch) + if ch == '#': byt |= 1 << (7 - indx) + + stdout.write(struct.pack( 'B', byt )) + + stdout.flush() From 41a600d2f1219510c784168406be56411471ccf0 Mon Sep 17 00:00:00 2001 From: Eric House Date: Wed, 1 Jul 2020 11:03:55 -0700 Subject: [PATCH 13/27] add Makefile as symlink --- xwords4/dawg/Italian/Makefile | 33 +-------------------------------- 1 file changed, 1 insertion(+), 32 deletions(-) mode change 100644 => 120000 xwords4/dawg/Italian/Makefile diff --git a/xwords4/dawg/Italian/Makefile b/xwords4/dawg/Italian/Makefile deleted file mode 100644 index 7b876d008..000000000 --- a/xwords4/dawg/Italian/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -# -*-mode: Makefile -*- -# Copyright 2002-2004 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=Italian -LANGCODE=it_IT - -TARGET_TYPE ?= WINCE - -include ../Makefile.langcommon - -$(XWLANG)Main.dict.gz: $(XWDICTPATH)/Italian/ITALIANO.txt.gz - zcat $< | tr a-z A-Z | grep '^[A-IL-VZ]*$$' | 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 diff --git a/xwords4/dawg/Italian/Makefile b/xwords4/dawg/Italian/Makefile new file mode 120000 index 000000000..47350dba5 --- /dev/null +++ b/xwords4/dawg/Italian/Makefile @@ -0,0 +1 @@ +./Makefile.zinga \ No newline at end of file From cc2b61af7d99169a382f322020eb81bd9b7d008e Mon Sep 17 00:00:00 2001 From: Eric House Date: Wed, 1 Jul 2020 20:55:56 -0700 Subject: [PATCH 14/27] tweaks for byod --- xwords4/dawg/English/Makefile.CollegeEng | 7 ++++--- xwords4/dawg/Hungarian/info.txt | 2 ++ xwords4/dawg/Makefile.langcommon | 10 ++++++---- xwords4/linux/scripts/discon_ok2.py | 2 +- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/xwords4/dawg/English/Makefile.CollegeEng b/xwords4/dawg/English/Makefile.CollegeEng index 2f360bead..7547a7cbb 100644 --- a/xwords4/dawg/English/Makefile.CollegeEng +++ b/xwords4/dawg/English/Makefile.CollegeEng @@ -1,5 +1,6 @@ # -*- mode: makefile; compile-command: "make -f Makefile.CollegeEng"; -*- -# Copyright 2002 by Eric House (xwords@eehouse.org). All rights reserved. +# Copyright 2002 - 2020 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 @@ -22,10 +23,10 @@ DICTNOTE = "From the old PalmOS app Niggle" include ../Makefile.langcommon -SOURCEDICT ?= $(XWDICTPATH)/English/CollegeEng.dict.gz +SOURCEDICT ?= $(XWDICTPATH)/English/CollegeEng.dict $(XWLANG)Main.dict.gz: $(SOURCEDICT) Makefile - zcat $< | tr -d '\r' | tr [a-z] [A-Z] | grep -e "^[A-Z]\{2,15\}$$" | \ + cat $< | tr -d '\r' | tr [a-z] [A-Z] | grep -e "^[A-Z]\{2,15\}$$" | \ gzip -c > $@ # Everything but creating of the Main.dict file is inherited from the diff --git a/xwords4/dawg/Hungarian/info.txt b/xwords4/dawg/Hungarian/info.txt index 3768603a9..6ef10c62a 100644 --- a/xwords4/dawg/Hungarian/info.txt +++ b/xwords4/dawg/Hungarian/info.txt @@ -3,6 +3,8 @@ LANGCODE:hu_HU CHARSET: utf-8 +BUILD_FLAGS:ALLOWS_DUPLICATES + # High bit means "official". Next 7 bits are an enum where # Hungarian==0x14. Low byte is padding XLOC_HEADER:0x9400 diff --git a/xwords4/dawg/Makefile.langcommon b/xwords4/dawg/Makefile.langcommon index 7a89557d3..da54cc32e 100644 --- a/xwords4/dawg/Makefile.langcommon +++ b/xwords4/dawg/Makefile.langcommon @@ -193,6 +193,8 @@ byodbins: table.bin values.bin frankspecials.bin info.txt else ifeq ($(TARGET_TYPE),WINCE) +byodbins: table.bin charcount.bin values.bin frankspecials.bin info.txt + ### WINCE section here ### all: $(XWLANG)2to8.xwd $(XWLANG)2to9.xwd $(XWLANG)2to15.xwd ../mkxwdcab.pl -f $< @@ -216,8 +218,8 @@ endif frankspecials.bin: ../frank_mkspecials.py $(BMPFILES) $< $(BLANK_INFO) $(LANG_SPECIAL_INFO) > $@ -$(XWLANG)%.$(FRANK_EXT): dawg$(XWLANG)%.stamp $(XWLANG)%_flags.bin $(XWLANG)%_newheader.bin $(XWLANG)_charcount.bin table.bin values.bin frankspecials.bin - cat $(XWLANG)$*_flags.bin $(XWLANG)$*_newheader.bin $(XWLANG)_charcount.bin table.bin values.bin \ +$(XWLANG)%.$(FRANK_EXT): dawg$(XWLANG)%.stamp $(XWLANG)%_flags.bin $(XWLANG)%_newheader.bin charcount.bin table.bin values.bin frankspecials.bin + cat $(XWLANG)$*_flags.bin $(XWLANG)$*_newheader.bin charcount.bin table.bin values.bin \ frankspecials.bin $(XWLANG)StartLoc.bin \ $$(ls dawg$(XWLANG)$*_*.bin) > $@ cp $@ saveme.bin @@ -254,7 +256,7 @@ dawg$(XWLANG)%.stamp: $(XWLANG)Main.dict.gz $(DICT2DAWG) table.bin ../Makefile.l start=$$(echo $@ | sed -e 's/dawg$(XWLANG)\([0-9]*\)to[0-9]*.stamp/\1/'); \ end=$$(echo $@ | sed -e 's/dawg$(XWLANG)[0-9]*to\([0-9]*\).stamp/\1/'); \ echo $${start} and $${end}; \ - zcat $< | $(BOWDLERIZER) | $(DICT2DAWG) $(DICT2DAWGARGS) $(TABLE_ARG) table.bin -b 28000 \ + zcat $< | $(BOWDLERIZER) | $(DICT2DAWG) $(DICT2DAWGARGS) $(TABLE_ARG) table.bin \ -ob dawg$(XWLANG)$* $(ENCP) \ -sn $(XWLANG)StartLoc.bin -min $${start} -max $${end} \ -wc $(XWLANG)$*_wordcount.bin $(FORCE_4) -ns $(XWLANG)$*_nodesize.bin @@ -282,7 +284,7 @@ values.bin: ../xloc.py # a binary file, two bytes, one giving the size of tiles data and the # other the number of tiles in the dict. Tiles data is utf-8 and so # number is not derivable from size. -$(XWLANG)_charcount.bin: table.bin ../xloc.py +charcount.bin: table.bin ../xloc.py SIZ=$$(ls -l $< | awk '{print $$5}'); \ perl -e "print pack(\"c\",$$SIZ)" > $@ TMP=/tmp/tmp$$$$; \ diff --git a/xwords4/linux/scripts/discon_ok2.py b/xwords4/linux/scripts/discon_ok2.py index 370a8be80..b2703faae 100755 --- a/xwords4/linux/scripts/discon_ok2.py +++ b/xwords4/linux/scripts/discon_ok2.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -import re, os, sys, getopt, shutil, threading, requests, json, glob +import re, os, sys, shutil, threading, requests, json, glob import argparse, datetime, random, signal, subprocess, time from shutil import rmtree From 52aeb6991da9dba00859bc98105a88ab3c5a6a8f Mon Sep 17 00:00:00 2001 From: Eric House Date: Fri, 3 Jul 2020 19:06:16 -0700 Subject: [PATCH 15/27] more tweaks for byod --- xwords4/dawg/Makefile.langcommon | 3 +- xwords4/dawg/xloc.py | 58 +++++++++++--------------------- 2 files changed, 20 insertions(+), 41 deletions(-) diff --git a/xwords4/dawg/Makefile.langcommon b/xwords4/dawg/Makefile.langcommon index da54cc32e..fa07f27bc 100644 --- a/xwords4/dawg/Makefile.langcommon +++ b/xwords4/dawg/Makefile.langcommon @@ -187,8 +187,7 @@ $(XWLANG)%.atts: #recreate it each time based on params echo '_PERM|global+read-only|"r"' >> $@ # the files to export for byod -byodbins: table.bin values.bin frankspecials.bin info.txt - +byodbins: table.bin charcount.bin values.bin frankspecials.bin info.txt else ifeq ($(TARGET_TYPE),WINCE) diff --git a/xwords4/dawg/xloc.py b/xwords4/dawg/xloc.py index 1aef1ff0c..9ceeba81b 100755 --- a/xwords4/dawg/xloc.py +++ b/xwords4/dawg/xloc.py @@ -9,6 +9,7 @@ def mkParser(): parser = argparse.ArgumentParser() parser.add_argument('-enc', dest = 'ENCODING', type = str, help = 'use this encoding' ) parser.add_argument('-tn', dest = 'DO_TABLE', action = 'store_true', help = 'output table file' ) + # parser.add_argument('-tn', dest = 'UNICODE', default = False, # action = 'store_true', help = 'assume unicode') # parser.add_argument('-t', dest = 'UNICODE', type = str, default = True, @@ -16,6 +17,11 @@ def mkParser(): parser.add_argument('-v', dest = 'DO_VALS', action = 'store_true', help = 'output values file' ) parser.add_argument('-s', dest = 'DO_SIZE', action = 'store_true', help = 'output size file') parser.add_argument('-out', dest = 'OUTFILE', type = str, help = 'outfile path') + + parser.add_argument('--table-file', dest = 'TABLE_FILE', type = str, help = 'write table file here') + parser.add_argument('--size-file', dest = 'SIZE_FILE', type = str, help = 'write size file here') + parser.add_argument('--vals-file', dest = 'VALS_FILE', type = str, help = 'write vals file here') + return parser sPreComment = re.compile('^(.*)#.*$') @@ -60,33 +66,6 @@ def parseTileInfo(infoFile, encoding): return result -class XLOC(): - None - -def readXLOC(): - return XLOC() - -# sub WriteMapFile($$$) { -# my ( $hashR, $unicode, $fhr ) = @_; - -# my $count = GetNTiles($hashR); -# my $specialCount = 0; -# for ( my $i = 0; $i < $count; ++$i ) { -# my $tileR = GetNthTile( $hashR, $i ); -# my $str = ${$tileR}[2]; - -# if ( $str =~ /\'(.(\|.)*)\'/ ) { -# printLetters( $1, $fhr ); -# } elsif ( $str =~ /\"(.+)\"/ ) { -# print $fhr pack( "c", $specialCount++ ); -# } elsif ( $str =~ /(\d+)/ ) { -# print $fhr pack( "n", $1 ); -# } else { -# die "WriteMapFile: unrecognized face format $str, elem $i"; -# } -# } -# } # WriteMapFile - def printLetters( letters, outfile ): letters = letters.split('|') letters = ' '.join(letters) @@ -127,26 +106,27 @@ def writeValuesFile(xlocToken, outfile): def main(): print('{}.main {} called'.format(sys.argv[0], sys.argv[1:])) args = mkParser().parse_args() - assert args.OUTFILE infoFile = 'info.txt' if not os.path.exists(infoFile): errorOut('{} not found'.format(infoFile)) xlocToken = parseTileInfo(infoFile, args.ENCODING) - xloc = readXLOC() - - with open(args.OUTFILE, 'wb') as outfile: - if args.DO_TABLE: + if args.DO_TABLE or args.TABLE_FILE: + path = args.TABLE_FILE or args.OUTFILE + with open(path, 'wb') as outfile: writeMapFile(xlocToken, outfile); - elif args.DO_SIZE: - assert not args.DO_VALS - count = len(xlocToken['_TILES']) - outfile.write(struct.pack('!B', count)) - elif args.DO_VALS: - assert not args.DO_SIZE - writeValuesFile( xlocToken, outfile ) + if args.DO_SIZE or args.SIZE_FILE: + path = args.SIZE_FILE or args.OUTFILE + with open(path, 'wb') as outfile: + count = len(xlocToken['_TILES']) + outfile.write(struct.pack('B', count)) + + if args.DO_VALS or args.VALS_FILE: + path = args.VALS_FILE or args.OUTFILE + with open(path, 'wb') as outfile: + writeValuesFile( xlocToken, outfile ) ############################################################################## if __name__ == '__main__': From 8a35b61808426d7dd2b3ef9233e2e82874cbd0bc Mon Sep 17 00:00:00 2001 From: Eric House Date: Fri, 3 Jul 2020 20:56:45 -0700 Subject: [PATCH 16/27] don't exit badly when piped --- xwords4/dawg/dawg2dict.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/xwords4/dawg/dawg2dict.py b/xwords4/dawg/dawg2dict.py index 460ca8c33..6a4da909d 100755 --- a/xwords4/dawg/dawg2dict.py +++ b/xwords4/dawg/dawg2dict.py @@ -66,7 +66,8 @@ def eatBitmap( fh ): if nCols > 0: nRows = int(oneByteFmt.unpack(fh.read(oneByteFmt.size))[0]) nBytes = ((nRows*nCols)+7) // 8 - print('eatBitmap(): skipping', nBytes, 'bytes; nCols:', nCols, 'nRows:', nRows) + print('eatBitmap(): skipping {} bytes; nCols: {}, nRows: {}:'.format(nBytes,nCols, nRows),\ + file=sys.stderr) fh.read(nBytes) def loadSpecialData( fh, data ): @@ -187,8 +188,7 @@ def process(args): numFaces = int(oneByteFmt.unpack(dawg.read(oneByteFmt.size))[0]) if not isUTF8: numFaceBytes = numFaces * 2 - if numFaces > 64: - error("too many faces: " + numFaces) + assert numFaces <= 64, 'too many faces: {}'.format(numFaces) print( 'numFaceBytes: {}, numFaces: {}'.format(numFaceBytes, numFaces), file=sys.stderr ) print( 'TODO: confirm checksum', file=sys.stderr ) @@ -227,7 +227,9 @@ def process(args): # assert len(words) == nWords if args.DUMP_WORDS: for word in words: - print(word) + # if we're piped to head we'll get an exception, so just exit + try: print(word) + except: break def mkParser(): parser = argparse.ArgumentParser() From a2335064daaf745d1d63a50de492cef7147f5c48 Mon Sep 17 00:00:00 2001 From: Eric House Date: Fri, 3 Jul 2020 20:58:47 -0700 Subject: [PATCH 17/27] add LANGFILTER so byod can build Hungarian --- xwords4/dawg/Hungarian/info.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/xwords4/dawg/Hungarian/info.txt b/xwords4/dawg/Hungarian/info.txt index 6ef10c62a..eab5f0148 100644 --- a/xwords4/dawg/Hungarian/info.txt +++ b/xwords4/dawg/Hungarian/info.txt @@ -5,6 +5,18 @@ CHARSET: utf-8 BUILD_FLAGS:ALLOWS_DUPLICATES +LANGFILTER: tr -d '\r' +LANGFILTER: | tr [aábcdeéfghiíjklmnnyoóöőprtuúüűvzs] [AÁBCDEÉFGHIÍJKLMNNYOÓÖŐPRTUÚÜŰVZS] +LANGFILTER: | sed -e 's,^\(.*\)CS\(.*\)$,\11\2\n\1CS\2,g' +LANGFILTER: | sed -e 's,GY,2,g' +LANGFILTER: | sed -e 's,LY,3,g' +LANGFILTER: | sed -e 's,NY,4,g' +LANGFILTER: | sed -e 's,^\(.*\)SZ\(.*\)$,\15\2\n\1SZ\2,g' +LANGFILTER: | sed -e 's,TY,6,g' +LANGFILTER: | sed -e 's,^\(.*\)ZS\(.*\)$,\17\2\n\1ZS\2,g' +LANGFILTER: | grep '^[1-7AÁBCDEÉFGHIÍJKLMNOÓÖŐPRSTUÚÜŰVZ]\{2,15\}$' +LANGFILTER: | tr '1234567' '\001\002\003\004\005\006\007' + # High bit means "official". Next 7 bits are an enum where # Hungarian==0x14. Low byte is padding XLOC_HEADER:0x9400 From 45e7e716b9c05db8536edf6f5237dfef7c9ae6e7 Mon Sep 17 00:00:00 2001 From: Eric House Date: Tue, 7 Jul 2020 10:37:23 -0700 Subject: [PATCH 18/27] improving prep of byod files --- xwords4/dawg/mkbyodbins.sh | 7 +++++++ xwords4/dawg/xloc.py | 1 - 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100755 xwords4/dawg/mkbyodbins.sh diff --git a/xwords4/dawg/mkbyodbins.sh b/xwords4/dawg/mkbyodbins.sh new file mode 100755 index 000000000..1ae648281 --- /dev/null +++ b/xwords4/dawg/mkbyodbins.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +for INFO in $(ls */info.txt); do + DIR=$(dirname $INFO) + echo "*** processing $(basename $DIRNAME) ***" + (cd $DIR && make byodbins) +done diff --git a/xwords4/dawg/xloc.py b/xwords4/dawg/xloc.py index 9ceeba81b..1eb56b1ac 100755 --- a/xwords4/dawg/xloc.py +++ b/xwords4/dawg/xloc.py @@ -79,7 +79,6 @@ def writeMapFile(xlocToken, outfile): face = tile[2] match = sSingleCharMatch.match(face) if match: - print('single char: {}'.format(match.group(1))) printLetters( match.group(1), outfile ) continue match = sSpecialsMatch.match(face) From 729fb5d6b7e2dd3b763c530f043cda2eca3b2750 Mon Sep 17 00:00:00 2001 From: Eric House Date: Tue, 7 Jul 2020 11:54:45 -0700 Subject: [PATCH 19/27] fix to include optional info.txt info --- xwords4/dawg/Makefile.langcommon | 8 +++++--- xwords4/dawg/mkbyodbins.sh | 4 ++-- xwords4/dawg/xloc.py | 6 +++--- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/xwords4/dawg/Makefile.langcommon b/xwords4/dawg/Makefile.langcommon index fa07f27bc..549b04b31 100644 --- a/xwords4/dawg/Makefile.langcommon +++ b/xwords4/dawg/Makefile.langcommon @@ -16,9 +16,11 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -ifndef XWDICTPATH -$(error XWDICTPATH is not set) -endif +# This breaks generating byod files on otherwise-unconfigured +# machines. Move it perhaps? +# ifndef XWDICTPATH +# $(error XWDICTPATH is not set) +# endif ifneq ($(DIRTY_LIST),) BOWDLERIZER = ../remove-dirty.py $(DIRTY_LIST) diff --git a/xwords4/dawg/mkbyodbins.sh b/xwords4/dawg/mkbyodbins.sh index 1ae648281..fedd03483 100755 --- a/xwords4/dawg/mkbyodbins.sh +++ b/xwords4/dawg/mkbyodbins.sh @@ -2,6 +2,6 @@ for INFO in $(ls */info.txt); do DIR=$(dirname $INFO) - echo "*** processing $(basename $DIRNAME) ***" - (cd $DIR && make byodbins) + echo "*** processing $(basename $DIR) ***" + (cd $DIR && make clean byodbins) done diff --git a/xwords4/dawg/xloc.py b/xwords4/dawg/xloc.py index 1eb56b1ac..c329ebd34 100755 --- a/xwords4/dawg/xloc.py +++ b/xwords4/dawg/xloc.py @@ -28,8 +28,8 @@ sPreComment = re.compile('^(.*)#.*$') sVarAssign = re.compile('^(\w+):(.*)$') sBeginTiles = re.compile('^$') sEndTiles = re.compile('^$') -sSingleCharMatch = re.compile('\'(.(\|.)+)\'') -sSpecialsMatch = re.compile('{"(.+)"}') +sSingleCharMatch = re.compile("'(.(\|.)*)'") +sSpecialsMatch = re.compile('{"(.+)"(,.+)?}') def parseTileInfo(infoFile, encoding): result = {'_TILES' : []} @@ -53,7 +53,7 @@ def parseTileInfo(infoFile, encoding): if sEndTiles.match(line): break else: - (count, val, face) = line.split(None, 3) + (count, val, face) = line.split(None, 2) result['_TILES'].append((count, val, face)) elif sBeginTiles.match(line): inTiles = True From ad4542b4ac89041f7b14af507ab1df4e28036b1f Mon Sep 17 00:00:00 2001 From: Eric House Date: Sun, 19 Jul 2020 17:31:50 -0700 Subject: [PATCH 20/27] add pref to set color of board lines --- .../main/java/org/eehouse/android/xw4/BoardCanvas.java | 10 +++++++--- .../java/org/eehouse/android/xw4/PrefsDelegate.java | 1 + .../java/org/eehouse/android/xw4/jni/CommonPrefs.java | 4 +++- .../android/app/src/main/res/values/common_rsrc.xml | 1 + xwords4/android/app/src/main/res/values/strings.xml | 2 ++ xwords4/android/app/src/main/res/xml/xwprefs.xml | 6 ++++++ 6 files changed, 20 insertions(+), 4 deletions(-) diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardCanvas.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardCanvas.java index fa8a5d67d..b747182f3 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardCanvas.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardCanvas.java @@ -49,7 +49,7 @@ public class BoardCanvas extends Canvas implements DrawCtx { private static final String TAG = BoardCanvas.class.getSimpleName(); private static final int BLACK = 0xFF000000; private static final int WHITE = 0xFFFFFFFF; - private static final int FRAME_GREY = 0xFF101010; + private static final int LINE_PCT = 3; private static final int SCORE_HT_DROP = 2; private static final boolean DEBUG_DRAWFRAMES = false; private static final int NOT_TURN_ALPHA = 0x3FFFFFFF; @@ -442,7 +442,10 @@ public class BoardCanvas extends Canvas implements DrawCtx { } // frame the cell - m_strokePaint.setColor( adjustColor(FRAME_GREY) ); + int frameColor = m_otherColors[CommonPrefs.COLOR_CELLLINE]; + m_strokePaint.setColor( adjustColor(frameColor) ); + int width = Math.max(1, (rect.width() * LINE_PCT) / 100); + m_strokePaint.setStrokeWidth( width ); drawRect( rect, m_strokePaint ); drawCrosshairs( rect, flags ); @@ -559,7 +562,8 @@ public class BoardCanvas extends Canvas implements DrawCtx { // the board (without scrolling), the right-most cells // don't draw their right borders due to clipping, so draw // for them. - m_strokePaint.setColor( adjustColor(FRAME_GREY) ); + int frameColor = m_otherColors[CommonPrefs.COLOR_CELLLINE]; + m_strokePaint.setColor( adjustColor(frameColor) ); int xx = rect.left + rect.width() - 1; drawLine( xx, rect.top, xx, rect.top + rect.height(), m_strokePaint ); diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/PrefsDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/PrefsDelegate.java index 9abb91d43..65919a3a8 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/PrefsDelegate.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/PrefsDelegate.java @@ -102,6 +102,7 @@ public class PrefsDelegate extends DelegateBase R.string.key_empty, R.string.key_background, R.string.key_clr_bonushint, + R.string.key_cellline, }; for ( int colorKey : colorKeys ) { editor.remove( getString(colorKey) ); diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/CommonPrefs.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/CommonPrefs.java index c1014ab3a..52b986855 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/CommonPrefs.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/CommonPrefs.java @@ -40,7 +40,8 @@ public class CommonPrefs extends XWPrefs { public static final int COLOR_FOCUS = 2; public static final int COLOR_BACKGRND = 3; public static final int COLOR_BONUSHINT = 4; - public static final int COLOR_LAST = 5; + public static final int COLOR_CELLLINE = 5; + public static final int COLOR_LAST = 6; private static CommonPrefs s_cp = null; @@ -108,6 +109,7 @@ public class CommonPrefs extends XWPrefs { R.string.key_clr_crosshairs, R.string.key_background, R.string.key_clr_bonushint, + R.string.key_cellline, }; for ( int ii = 0; ii < idsOther.length; ++ii ) { otherColors[ii] = prefToColor( context, sp, idsOther[ii] ); diff --git a/xwords4/android/app/src/main/res/values/common_rsrc.xml b/xwords4/android/app/src/main/res/values/common_rsrc.xml index 6b89e703d..45fdb86e9 100644 --- a/xwords4/android/app/src/main/res/values/common_rsrc.xml +++ b/xwords4/android/app/src/main/res/values/common_rsrc.xml @@ -31,6 +31,7 @@ key_clr_tile_back key_clr_empty key_clr_background + key_cellline key_clr_crosshairs key_clr_bonushint diff --git a/xwords4/android/app/src/main/res/values/strings.xml b/xwords4/android/app/src/main/res/values/strings.xml index 40a1f58a0..a311ed0c7 100644 --- a/xwords4/android/app/src/main/res/values/strings.xml +++ b/xwords4/android/app/src/main/res/values/strings.xml @@ -889,6 +889,8 @@ In-square bonus hint + + Board lines Keep board screen on 10 mins + + + Cell line thickness (percent, limit 1 to 25) + + + + + From e8127a22fba408371ae33c05079b8db4f5eebf29 Mon Sep 17 00:00:00 2001 From: Eric House Date: Mon, 20 Jul 2020 08:08:54 -0700 Subject: [PATCH 25/27] cleanup and update version strings commented out more of variable line-thickness since the ability to set has been removed. --- xwords4/android/app/build.gradle | 4 ++-- xwords4/android/app/src/main/assets/changes.html | 3 ++- .../java/org/eehouse/android/xw4/BoardCanvas.java | 12 +++++++----- .../main/java/org/eehouse/android/xw4/XWPrefs.java | 1 - 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/xwords4/android/app/build.gradle b/xwords4/android/app/build.gradle index 1bd74364b..d7356d9e1 100644 --- a/xwords4/android/app/build.gradle +++ b/xwords4/android/app/build.gradle @@ -1,6 +1,6 @@ def INITIAL_CLIENT_VERS = 9 -def VERSION_CODE_BASE = 156 -def VERSION_NAME = '4.4.160' +def VERSION_CODE_BASE = 157 +def VERSION_NAME = '4.4.161' def FABRIC_API_KEY = System.getenv("FABRIC_API_KEY") def BUILD_INFO_NAME = "build-info.txt" diff --git a/xwords4/android/app/src/main/assets/changes.html b/xwords4/android/app/src/main/assets/changes.html index f4c1eadb1..f8726bef1 100644 --- a/xwords4/android/app/src/main/assets/changes.html +++ b/xwords4/android/app/src/main/assets/changes.html @@ -27,8 +27,8 @@

    New with this release

    (The full changelog @@ -36,6 +36,7 @@

    Coming soon