mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-08 05:24:39 +01:00
Merge branch 'android_branch' into android_translate
This commit is contained in:
commit
ba342c891d
54 changed files with 845 additions and 2047 deletions
4
README.md
Normal file
4
README.md
Normal file
|
@ -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. :-)
|
|
@ -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"
|
||||
|
||||
|
@ -36,10 +36,8 @@ if ( FABRIC_API_KEY && hasProperty('useCrashlytics') ) { // rm-for-fdroid
|
|||
} // rm-for-fdroid
|
||||
repositories {
|
||||
google()
|
||||
maven { url 'https://maven.fabric.io/public' } // rm-for-fdroid
|
||||
maven {
|
||||
url "https://repo.eclipse.org/content/repositories/paho-releases/"
|
||||
}
|
||||
maven { url 'https://maven.fabric.io/public' } // rm-for-fdroid
|
||||
maven { url "https://repo.eclipse.org/content/repositories/paho-releases/" } // rm-for-fdroid
|
||||
}
|
||||
|
||||
android {
|
||||
|
@ -122,6 +120,7 @@ android {
|
|||
resValue "string", "nfc_aid", "$NFC_AID_XW4"
|
||||
externalNativeBuild.ndkBuild.cFlags += ['-DVARIANT_xw4fdroid']
|
||||
externalNativeBuild.ndkBuild.arguments += ['XW_BT_UUID=' + XW_UUID]
|
||||
buildConfigField "boolean", "OFFER_MQTT", "false"
|
||||
}
|
||||
|
||||
xw4d {
|
||||
|
@ -337,7 +336,7 @@ dependencies {
|
|||
|
||||
implementation 'com.github.eehouse:nbsproxy:v0.2.2'
|
||||
|
||||
implementation "org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.+"
|
||||
implementation "org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.+" // rm-for-fdroid
|
||||
}
|
||||
|
||||
task mkImages(type: Exec) {
|
||||
|
|
|
@ -13,10 +13,10 @@
|
|||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h2>CrossWords 4.4.160 release</h2>
|
||||
<h2>CrossWords 4.4.161 release</h2>
|
||||
|
||||
<p>This release improves play via the internet by adding a second
|
||||
(and redundant) type of server.</p>
|
||||
<p>This minor release removes an under-construction image I added
|
||||
recently. It made friends think they were being hacked.</p>
|
||||
|
||||
<div id="survey">
|
||||
<p>Please <a href="https://www.surveymonkey.com/s/GX3XLHR">take
|
||||
|
@ -26,17 +26,17 @@
|
|||
|
||||
<h3>New with this release</h3>
|
||||
<ul>
|
||||
<li>Improve internet/relay play by adding a second server type (MQTT)</li>
|
||||
<li>Add "under construction" icon for when thumbnail isn't available</li>
|
||||
<li>Enable new "block phonies" option that won't let you use a word not in the wordlist</li>
|
||||
<li>Add new Japanese translations (via Weblate)</li>
|
||||
<li>Remove under-construction image that flashed by as a thumbnail was loading</li>
|
||||
<li>Make color of line separating board tiles configurable</li>
|
||||
<li>Change how dialogs are handled internally. You should NOT notice!</li>
|
||||
</ul>
|
||||
|
||||
<p>(The full changelog
|
||||
is <a href="http://xwords.sf.net/and_changes.php">here</a>.)</p>
|
||||
|
||||
<h3>Next up</h3>
|
||||
<h3>Coming soon</h3>
|
||||
<ul>
|
||||
<li>Add filtering to the wordlist browser</li>
|
||||
<li>Improve move-via-NFC</li>
|
||||
<li>Support duplicate-style play (popular in France)</li>
|
||||
<li>Improve play-by-data-sms workaround
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
@ -96,7 +97,7 @@ public class BTInviteDelegate extends InviteDelegate {
|
|||
for ( Iterator<TwoStringPair> iter = pairs.iterator();
|
||||
iter.hasNext(); ) {
|
||||
TwoStringPair pair = iter.next();
|
||||
if ( pair.str2.equals( dev ) ) {
|
||||
if ( TextUtils.equals( pair.str2, dev ) ) {
|
||||
iter.remove();
|
||||
break;
|
||||
}
|
||||
|
@ -104,6 +105,18 @@ public class BTInviteDelegate extends InviteDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
private void removeNulls()
|
||||
{
|
||||
for ( Iterator<TwoStringPair> 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()
|
||||
|
@ -315,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 ) {
|
||||
|
|
|
@ -49,7 +49,6 @@ 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 SCORE_HT_DROP = 2;
|
||||
private static final boolean DEBUG_DRAWFRAMES = false;
|
||||
private static final int NOT_TURN_ALPHA = 0x3FFFFFFF;
|
||||
|
@ -442,7 +441,15 @@ 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) );
|
||||
if ( false ) {
|
||||
// PENDING: fetch/calculate this a lot less frequently!!
|
||||
int linePct = XWPrefs.getPrefsInt( m_activity, R.string.key_board_line_pct, 1 );
|
||||
linePct = Math.min( 25, linePct );
|
||||
int width = Math.max(1, (rect.width() * linePct) / 100);
|
||||
m_strokePaint.setStrokeWidth( width );
|
||||
}
|
||||
drawRect( rect, m_strokePaint );
|
||||
|
||||
drawCrosshairs( rect, flags );
|
||||
|
@ -559,7 +566,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 );
|
||||
|
|
|
@ -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 ) {
|
||||
|
@ -2488,7 +2489,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,
|
||||
|
@ -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:
|
||||
|
|
|
@ -1,59 +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.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 {
|
||||
|
||||
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 );
|
||||
|
||||
builder.setTitle( state.m_titleId == 0 ? R.string.query_title : state.m_titleId )
|
||||
.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 ) );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
@ -485,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;
|
||||
|
@ -521,33 +515,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 +572,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 +716,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();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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 {
|
||||
|
@ -154,139 +150,169 @@ 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
|
||||
.setAction( Action.SKIP_CALLBACK )
|
||||
;
|
||||
}
|
||||
|
||||
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.setPrefsNAKey( keyID );
|
||||
return this;
|
||||
}
|
||||
|
||||
public DlgDelegateBuilder setActionPair( Action actn, int id )
|
||||
{ return setActionPair( new ActionPair( actn, id ) ); }
|
||||
|
||||
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 )
|
||||
.setTitle( R.string.newbie_title )
|
||||
;
|
||||
}
|
||||
|
||||
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 +335,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 +362,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 +373,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 )
|
||||
{
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
@ -89,6 +116,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 );
|
||||
|
@ -131,9 +162,6 @@ abstract 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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 )
|
||||
|
@ -56,7 +55,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; }
|
||||
|
@ -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 );
|
||||
|
@ -168,7 +172,7 @@ public class DlgState implements Parcelable {
|
|||
|
||||
private void testCanParcelize()
|
||||
{
|
||||
if (BuildConfig.DEBUG) {
|
||||
if ( BuildConfig.DEBUG ) {
|
||||
Parcel parcel = Parcel.obtain();
|
||||
writeToParcel(parcel, 0);
|
||||
|
||||
|
@ -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();
|
||||
|
@ -203,8 +205,7 @@ public class DlgState implements Parcelable {
|
|||
.setPosButton( posButton )
|
||||
.setNegButton( negButton )
|
||||
.setAction( action )
|
||||
.setPrefsKey( prefsKey )
|
||||
.setOnNA( onNA )
|
||||
.setPrefsNAKey( prefsKey )
|
||||
.setTitle(titleId)
|
||||
.setParams(params)
|
||||
.setActionPair(pair)
|
||||
|
|
|
@ -462,6 +462,7 @@ public class GameListItem extends LinearLayout
|
|||
}
|
||||
long m_rowid;
|
||||
GameListItem m_item;
|
||||
int m_nTries = 0;
|
||||
}
|
||||
private static LinkedBlockingQueue<ThumbQueueElem> s_queue
|
||||
= new LinkedBlockingQueue<>();
|
||||
|
@ -489,6 +490,11 @@ public class GameListItem extends LinearLayout
|
|||
ThumbQueueElem elem;
|
||||
try {
|
||||
elem = s_queue.take();
|
||||
if ( 0 < elem.m_nTries ) {
|
||||
// This is a second pass. give whatever caused
|
||||
// failure time to go away
|
||||
Thread.sleep(200);
|
||||
}
|
||||
} catch ( InterruptedException ie ) {
|
||||
Log.w( TAG, "interrupted; killing s_thumbThread" );
|
||||
break;
|
||||
|
@ -501,16 +507,22 @@ public class GameListItem extends LinearLayout
|
|||
thumb = GameUtils.loadMakeBitmap( activity, rowid );
|
||||
}
|
||||
|
||||
final GameListItem item = elem.m_item;
|
||||
final Bitmap ft = thumb;
|
||||
activity.runOnUiThread( new Runnable() {
|
||||
public void run() {
|
||||
ImageView iview = item.m_thumb;
|
||||
if ( null != iview ) {
|
||||
iview.setImageBitmap( ft );
|
||||
if ( null == thumb ) {
|
||||
if ( ++elem.m_nTries < 3 ) {
|
||||
s_queue.add( elem );
|
||||
}
|
||||
} else {
|
||||
final GameListItem item = elem.m_item;
|
||||
final Bitmap ft = thumb;
|
||||
activity.runOnUiThread( new Runnable() {
|
||||
public void run() {
|
||||
ImageView iview = item.m_thumb;
|
||||
if ( null != iview ) {
|
||||
iview.setImageBitmap( ft );
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
@ -2001,7 +1992,7 @@ public class GamesListDelegate extends ListDelegateBase
|
|||
|
||||
// DEBUG only
|
||||
case R.id.games_game_markbad:
|
||||
Quarantine.recordOpened( selRowIDs[0] );
|
||||
Quarantine.markBad( selRowIDs[0] );
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -2438,7 +2429,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,
|
||||
|
@ -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();
|
||||
|
|
|
@ -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 ) );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,53 +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 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.setTitle( state.m_titleId == 0 ? R.string.info_title : state.m_titleId )
|
||||
.setMessage( state.m_msg )
|
||||
.setPositiveButton( android.R.string.ok, null )
|
||||
;
|
||||
|
||||
ActionPair pair = state.m_pair;
|
||||
if ( null != pair ) {
|
||||
builder.setNeutralButton( pair.buttonStr, mkCallbackClickListener( pair ) );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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) );
|
||||
|
@ -242,7 +243,9 @@ public class PrefsDelegate extends DelegateBase
|
|||
case R.string.key_mqtt_host:
|
||||
case R.string.key_mqtt_port:
|
||||
case R.string.key_mqtt_qos:
|
||||
MQTTUtils.onConfigChanged( m_activity );
|
||||
if ( BuildConfig.OFFER_MQTT ) {
|
||||
MQTTUtils.onConfigChanged( m_activity );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Assert.failDbg();
|
||||
|
|
|
@ -30,6 +30,7 @@ import java.io.Serializable;
|
|||
public class Quarantine {
|
||||
private static final String TAG = Quarantine.class.getSimpleName();
|
||||
private static final String DATA_KEY = TAG + "/key";
|
||||
private static final int BAD_COUNT = 2;
|
||||
|
||||
public static boolean safeToOpen( long rowid )
|
||||
{
|
||||
|
@ -37,7 +38,7 @@ public class Quarantine {
|
|||
synchronized ( sDataRef ) {
|
||||
count = get().getFor( rowid );
|
||||
}
|
||||
boolean result = count == 0; // Not too strict?
|
||||
boolean result = count < BAD_COUNT;
|
||||
if ( !result ) {
|
||||
Log.d( TAG, "safeToOpen(%d) => %b (count=%d)", rowid, result, count );
|
||||
}
|
||||
|
@ -70,6 +71,17 @@ public class Quarantine {
|
|||
}
|
||||
}
|
||||
|
||||
public static void markBad( long rowid )
|
||||
{
|
||||
synchronized ( sDataRef ) {
|
||||
for ( int ii = 0; ii < BAD_COUNT; ++ii ) {
|
||||
get().increment( rowid );
|
||||
}
|
||||
store();
|
||||
Log.d( TAG, "markBad(%d): %s", rowid, sDataRef[0].toString() );
|
||||
}
|
||||
}
|
||||
|
||||
private static class Data implements Serializable {
|
||||
private HashMap<Long, Integer> mCounts = new HashMap<>();
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
@ -288,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 );
|
||||
}
|
||||
|
|
|
@ -102,7 +102,9 @@ public class XWApp extends Application
|
|||
|
||||
DupeModeTimer.init( this );
|
||||
|
||||
MQTTUtils.init( this );
|
||||
if ( BuildConfig.OFFER_MQTT ) {
|
||||
MQTTUtils.init( this );
|
||||
}
|
||||
}
|
||||
|
||||
@OnLifecycleEvent(ON_ANY)
|
||||
|
|
|
@ -207,19 +207,20 @@ public class XWPrefs {
|
|||
|
||||
public static int getPrefsInt( Context context, int keyID, int defaultValue )
|
||||
{
|
||||
String key = context.getString( keyID );
|
||||
SharedPreferences sp = PreferenceManager
|
||||
.getDefaultSharedPreferences( context );
|
||||
int result;
|
||||
try {
|
||||
result = sp.getInt( key, defaultValue );
|
||||
// If it's in a pref, it'll be a string (editable) So will get CCE
|
||||
} catch ( ClassCastException cce ) {
|
||||
String asStr = sp.getString( key, String.format( "%d", defaultValue ) );
|
||||
int result = defaultValue;
|
||||
if ( null != context ) {
|
||||
String key = context.getString( keyID );
|
||||
SharedPreferences sp = PreferenceManager
|
||||
.getDefaultSharedPreferences( context );
|
||||
try {
|
||||
result = Integer.parseInt( asStr );
|
||||
} catch ( Exception ex ) {
|
||||
result = defaultValue;
|
||||
result = sp.getInt( key, defaultValue );
|
||||
// If it's in a pref, it'll be a string (editable) So will get CCE
|
||||
} catch ( ClassCastException cce ) {
|
||||
String asStr = sp.getString( key, String.format( "%d", defaultValue ) );
|
||||
try {
|
||||
result = Integer.parseInt( asStr );
|
||||
} catch ( Exception ex ) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -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] );
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
<vector android:height="96dp" android:viewportHeight="512"
|
||||
android:viewportWidth="512" android:width="96dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M440,228.246l14.06,3.515a8.005,8.005 0,0 0,5.519 -0.605l32,-16a8,8 0,0 0,3.85 -10.126l-19.113,-47.782 3.645,-36.451a7.997,7.997 0,0 0,-0.805 -4.374l-16,-32a7.999,7.999 0,0 0,-6.023 -4.342l-56,-8a8.015,8.015 0,0 0,-2.124 -0.019L344,78.938v-27.043A35.894,35.894 0,0 0,274.054 40.543l-1.046,3.136 -14.665,14.664A8.001,8.001 0,0 0,264 72h16L280,88a31.792,31.792 0,0 0,3.575 14.669l-40.012,26.675a7.998,7.998 0,0 0,-2.718 3.078l-32,64a8.005,8.005 0,0 0,-0.812 4.303l7.788,85.67 -14.373,7.739 -19.791,-19.791a8.002,8.002 0,0 0,-9.626 -1.289l-13.395,7.654a127.825,127.825 0,0 0,-59.81 76.276l-1.984,6.944a51.601,51.601 0,0 0,-13.614 2.562l-12.583,4.194a35.471,35.471 0,0 1,-27.261 -1.937l-15.807,-7.903A8,8 0,0 0,16 368L16,488a8,8 0,0 0,8 8L312,496a8.001,8.001 0,0 0,7.692 -5.802l31.657,-110.8 15.122,-22.684 9.938,29.815a8.014,8.014 0,0 0,1.249 2.348l80,104A8,8 0,0 0,464 496h24a8,8 0,0 0,7.397 -11.046L440,350.417L440,228.246ZM477.838,204.137 L455.069,215.521 425.94,208.239a8,8 0,0 0,-5.938 0.831l-24.32,14.031 -7.546,-11.319L411.793,199.044a8.006,8.006 0,0 0,3.797 -4.514l7.132,-21.396 5.813,-3.875 3.514,31.625A8.001,8.001 0,0 0,440 208h24a7.999,7.999 0,0 0,7.96 -7.204l0.908,-9.084ZM241.089,312.289L232.687,295.485l141.299,-76.084 7.808,11.712ZM270.983,213.452 L292.951,202.469L312.177,234.511l-52.108,28.058ZM294.381,114.694a31.969,31.969 0,0 0,48.8 -19.529L352,94.063L352,130.584l-30.073,12.029L294.157,114.843ZM314.343,157.657a8,8 0,0 0,8.628 1.77l40,-16A7.999,7.999 0,0 0,368 136L368,92.063l5.3,-0.663 27.207,47.613 7.167,28.666L401.414,186.46 326.28,226.917l-23.264,-38.774 -29.702,-59.404 7.266,-4.844ZM417.558,141.247 L425.142,138.719 426.546,151.355 421.008,155.047ZM463.81,121.508L456.76,192h-9.6l-6.911,-62.199 15.113,-25.188ZM399.929,88.071l43.012,6.145L426.662,121.346l-14.97,4.99L390.5,89.25ZM285.657,53.657a8.007,8.007 0,0 0,1.932 -3.127l1.644,-4.927A19.894,19.894 0,0 1,328 51.895L328,56L283.313,56ZM328,72L328,88a16,16 0,0 1,-32 0L296,72ZM254.205,141.478 L259.897,137.683 285.267,188.422 264.351,198.88 234.468,180.951ZM224.173,201.542l3.119,-6.237 27.648,16.589 -13.489,60.7L231.137,278.147ZM114.212,361.38a111.911,111.911 0,0 1,52.362 -66.779l8.09,-4.623 19.679,19.68a8,8 0,0 0,9.45 1.387l14.8,-7.969 8.612,17.225 -15.203,8.771a7.999,7.999 0,0 0,-3.763 8.87l6.443,25.773L214.11,364a112.252,112.252 0,0 1,-100.646 -0.003ZM32,480L32,380.944l4.229,2.114a51.374,51.374 0,0 0,39.478 2.806l12.582,-4.194a35.804,35.804 0,0 1,28.636 2.661l44.959,24.978a35.751,35.751 0,0 1,13.278 12.844l3.047,5.078a51.603,51.603 0,0 0,51.653 24.585,35.872 35.872,0 0,1 34.763,15.542L273.052,480ZM227.599,435.976a35.635,35.635 0,0 1,-35.67 -16.978l-3.047,-5.077a51.779,51.779 0,0 0,-19.229 -18.599l-6.144,-3.414c0.09,0 0.179,0.004 0.269,0.004a128.43,128.43 0,0 0,57.487 -13.603l6.312,-3.155a7.998,7.998 0,0 0,4.184 -9.096l-6.536,-26.146L313.26,289.125l-24.779,68.141a8.036,8.036 0,0 0,-0.466 2.235l-6.52,104.32 -3.559,-5.339A51.971,51.971 0,0 0,227.599 435.976ZM337.344,371.563a8.014,8.014 0,0 0,-1.036 2.239L305.966,480h-9.45l7.396,-118.35 30.894,-84.956L424,225.237L424,275.471l-36.116,21.669a8.005,8.005 0,0 0,-2.54 2.423ZM476.055,480h-8.115l-76.776,-99.809 -13.447,-40.343 19.942,-29.914L424,294.13L424,352a8.006,8.006 0,0 0,0.603 3.046Z"/>
|
||||
</vector>
|
|
@ -66,7 +66,6 @@
|
|||
</RelativeLayout>
|
||||
|
||||
<ImageView android:id="@+id/thumbnail"
|
||||
android:src="@drawable/ic_uc"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical|center_horizontal"
|
||||
|
|
|
@ -31,8 +31,10 @@
|
|||
<string name="key_tile_back">key_clr_tile_back</string>
|
||||
<string name="key_empty">key_clr_empty</string>
|
||||
<string name="key_background">key_clr_background</string>
|
||||
<string name="key_cellline">key_cellline</string>
|
||||
<string name="key_clr_crosshairs">key_clr_crosshairs</string>
|
||||
<string name="key_clr_bonushint">key_clr_bonushint</string>
|
||||
<string name="key_board_line_pct">key_board_line_pct</string>
|
||||
|
||||
<string name="key_relay_host">key_relay_host</string>
|
||||
<string name="key_relay_port">key_relay_port2</string>
|
||||
|
|
|
@ -850,6 +850,9 @@
|
|||
<string name="keep_screenon">Keep screen on</string>
|
||||
<!-- clarification of above -->
|
||||
<string name="keep_screenon_summary">Keep board screen on 10 mins</string>
|
||||
|
||||
<!-- Preference title: cell line thickness as pct of cell width -->
|
||||
<string name="board_line_pct">Cell line thickness (percent, limit 1 to 25)</string>
|
||||
<!--
|
||||
############################################################
|
||||
# :Screens:
|
||||
|
@ -889,6 +892,8 @@
|
|||
<!-- the color of text, e.g. "2L", shown on a bonus square on the
|
||||
board -->
|
||||
<string name="key_bonushint">In-square bonus hint</string>
|
||||
<!-- The color of the lines delimiting cells on the board -->
|
||||
<string name="cellline">Board lines</string>
|
||||
<!--
|
||||
############################################################
|
||||
# :Dialogs:
|
||||
|
@ -1496,8 +1501,7 @@
|
|||
Eric House and translators -->
|
||||
<string name="about_credits">Toolbar icons by Sarah Chu. Navbar
|
||||
icons from the Noun Project: \"archive\" by Trendy; \"rematch\" by
|
||||
Becris; and \"swap\" by iconomania. \"Under Construction\" icon by
|
||||
ultimatearm from flaticon.com</string>
|
||||
Becris; and \"swap\" by iconomania.</string>
|
||||
<!-- text of dialog showing the set of changes made since the last
|
||||
release -->
|
||||
<string name="changes_title">Recent changes</string>
|
||||
|
@ -2058,7 +2062,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.</string>
|
||||
<string name="force_tablet_title">Use tablet (side-by-side) layout?</string>
|
||||
<string name="force_tablet_default">Use default for my device</string>
|
||||
|
|
|
@ -241,8 +241,21 @@
|
|||
android:title="@string/background"
|
||||
android:defaultValue="0xFFFFFF"
|
||||
/>
|
||||
|
||||
<org.eehouse.android.xw4.EditColorPreference
|
||||
android:key="@string/key_cellline"
|
||||
android:title="@string/cellline"
|
||||
android:defaultValue="0x101010"
|
||||
/>
|
||||
</PreferenceScreen>
|
||||
|
||||
<!-- <org.eehouse.android.xw4.XWEditTextPreference -->
|
||||
<!-- android:key="@string/key_board_line_pct" -->
|
||||
<!-- android:title="@string/board_line_pct" -->
|
||||
<!-- android:defaultValue="1" -->
|
||||
<!-- android:numeric="decimal" -->
|
||||
<!-- /> -->
|
||||
|
||||
</PreferenceScreen>
|
||||
|
||||
<PreferenceScreen android:title="@string/prefs_behavior"
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
../../../../../../xw4SMS/java/org/eehouse/android/xw4/MQTTUtils.java
|
|
@ -0,0 +1 @@
|
|||
../../../../../../xw4SMS/java/org/eehouse/android/xw4/MQTTUtils.java
|
|
@ -0,0 +1,81 @@
|
|||
/* -*- compile-command: "find-and-gradle.sh -PuseCrashlytics insXw4dDeb"; -*- */
|
||||
/*
|
||||
* Copyright 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.content.Context;
|
||||
|
||||
import org.eehouse.android.xw4.jni.CommsAddrRec;
|
||||
|
||||
public class MQTTUtils {
|
||||
private static final String TAG = MQTTUtils.class.getSimpleName();
|
||||
|
||||
public static void init( Context context )
|
||||
{
|
||||
logUnimpl( "init" );
|
||||
}
|
||||
|
||||
public static void onResume( Context context )
|
||||
{
|
||||
logUnimpl( "onResume" );
|
||||
}
|
||||
|
||||
public static int send( Context context, String addressee, int gameID, byte[] buf )
|
||||
{
|
||||
logUnimpl( "send" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static void handleMessage( Context context, CommsAddrRec from,
|
||||
int gameID, byte[] data )
|
||||
{
|
||||
logUnimpl( "handleMessage" );
|
||||
}
|
||||
|
||||
public static void handleGameGone( Context context, CommsAddrRec from, int gameID )
|
||||
{
|
||||
logUnimpl( "handleGameGone" );
|
||||
}
|
||||
|
||||
public static void gameDied( String devID, int gameID )
|
||||
{
|
||||
logUnimpl( "gameDied" );
|
||||
}
|
||||
|
||||
public static void timerFired( Context context )
|
||||
{
|
||||
logUnimpl( "timerFired" );
|
||||
}
|
||||
|
||||
static void onConfigChanged( Context context )
|
||||
{
|
||||
logUnimpl( "onConfigChanged" );
|
||||
}
|
||||
|
||||
public static void inviteRemote( Context context, String invitee, NetLaunchInfo nli )
|
||||
{
|
||||
logUnimpl( "inviteRemote" );
|
||||
}
|
||||
|
||||
private static void logUnimpl( String name )
|
||||
{
|
||||
Log.d( TAG, "%s(): UNIMPLEMENTED", name );
|
||||
}
|
||||
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="outline" viewBox="0 0 512 512" width="512" height="512"><path d="M440,228.24609l14.05957,3.51465a8.00478,8.00478,0,0,0,5.51855-.60547l32-16a8.00029,8.00029,0,0,0,3.84961-10.126l-19.11279-47.78223,3.645-36.45117a7.99681,7.99681,0,0,0-.80469-4.374l-16-32a7.99926,7.99926,0,0,0-6.02343-4.3418l-56-8a8.015,8.015,0,0,0-2.124-.01856L344,78.9375v-27.043A35.89421,35.89421,0,0,0,274.05371,40.543l-1.0459,3.13574-14.665,14.66406A8.00066,8.00066,0,0,0,264,72h16V88a31.79215,31.79215,0,0,0,3.57471,14.66895l-40.01221,26.6748a7.99763,7.99763,0,0,0-2.71777,3.07813l-32,64a8.00531,8.00531,0,0,0-.81153,4.30273l7.78809,85.66992-14.37305,7.73926-19.791-19.791a8.00152,8.00152,0,0,0-9.626-1.28906l-13.39453,7.6543a127.82537,127.82537,0,0,0-59.80957,76.27637l-1.98438,6.94433a51.60075,51.60075,0,0,0-13.61425,2.56152l-12.583,4.19434a35.471,35.471,0,0,1-27.26074-1.93652l-15.80665-7.90332A7.99951,7.99951,0,0,0,16,368V488a8.00039,8.00039,0,0,0,8,8H312a8.00054,8.00054,0,0,0,7.69238-5.80176l31.65723-110.7998,15.12207-22.6836,9.93848,29.81543a8.01375,8.01375,0,0,0,1.249,2.34766l80,104A8.00015,8.00015,0,0,0,464,496h24a7.99987,7.99987,0,0,0,7.39746-11.0459L440,350.417V228.24609Zm37.83789-24.10937-22.76855,11.38476-29.12891-7.28222a8.00008,8.00008,0,0,0-5.93848.83105l-24.32007,14.03076-7.54565-11.31884L411.793,199.044a8.00572,8.00572,0,0,0,3.79687-4.51368l7.13184-21.39648,5.81323-3.87549,3.51392,31.62549A8.00054,8.00054,0,0,0,440,208h24a7.99881,7.99881,0,0,0,7.96-7.2041l.90845-9.08374Zm-236.749,108.15234L232.687,295.48535l141.29932-76.084,7.80786,11.71191Zm29.89453-98.83691,21.96777-10.9834L312.17651,234.511l-52.10766,28.05786Zm23.39746-98.75806a31.9685,31.9685,0,0,0,48.80029-19.5293L352,94.0625V130.584l-30.07324,12.0293L294.15723,114.843Zm19.96191,42.96314a8.00019,8.00019,0,0,0,8.62793,1.7705l40-16A7.99873,7.99873,0,0,0,368,136V92.0625l5.3-.6626,27.20727,47.61255,7.16651,28.66626L401.41406,186.46,326.28,226.91675l-23.26441-38.77417-29.7019-59.40381,7.26636-4.84424Zm103.21485-16.41016,7.584-2.52832,1.40405,12.63623-5.53808,3.6919Zm46.252-19.73926L456.75977,192h-9.59961l-6.91065-62.199,15.11255-25.18775ZM399.92871,88.07129l43.01172,6.14453L426.66235,121.346l-14.97046,4.99023L390.49976,89.25ZM285.65723,53.65723a8.00738,8.00738,0,0,0,1.93164-3.127l1.64355-4.92675A19.89417,19.89417,0,0,1,328,51.89453V56H283.31348ZM328,72V88a16,16,0,0,1-32,0V72Zm-73.79492,69.47754,5.69189-3.79468,25.36988,50.7395-20.91626,10.458-29.88233-17.92944ZM224.17285,201.542l3.11865-6.23706,27.64795,16.58887-13.48877,60.70044L231.137,278.14746ZM114.21191,361.37988a111.91061,111.91061,0,0,1,52.36231-66.77929l8.08984-4.62305,19.67871,19.67969a8.00026,8.00026,0,0,0,9.4502,1.38672l14.80005-7.96924,8.6123,17.22461-15.20337,8.771a7.99882,7.99882,0,0,0-3.76269,8.87012l6.44336,25.77344L214.11035,364a112.2521,112.2521,0,0,1-100.64648-.00293ZM32,480V380.94434l4.22852,2.11425a51.37429,51.37429,0,0,0,39.47753,2.80567l12.582-4.19434a35.80373,35.80373,0,0,1,28.63574,2.66113l44.959,24.97754a35.751,35.751,0,0,1,13.27832,12.84375l3.04688,5.07813a51.60349,51.60349,0,0,0,51.65332,24.585,35.87241,35.87241,0,0,1,34.76269,15.542L273.05176,480Zm195.59863-44.02441a35.635,35.635,0,0,1-35.66992-16.97754l-3.04687-5.07715a51.77949,51.77949,0,0,0-19.22852-18.59863l-6.14429-3.41358c.0896.00049.17945.0044.26929.0044a128.43035,128.43035,0,0,0,57.4873-13.60254l6.31153-3.15528a7.99817,7.99817,0,0,0,4.18359-9.0957l-6.53613-26.14551L313.26,289.125l-24.77856,68.14062a8.03576,8.03576,0,0,0-.46583,2.23536l-6.52,104.32031-3.55909-5.33887A51.971,51.971,0,0,0,227.59863,435.97559ZM337.34375,371.5625a8.01379,8.01379,0,0,0-1.03613,2.23926L305.96582,480h-9.4502l7.39649-118.34961,30.89355-84.956L424,225.23657V275.4707l-36.11621,21.66895a8.00472,8.00472,0,0,0-2.54,2.42285ZM476.05469,480h-8.11524l-76.77636-99.80859-13.44727-40.34327,19.94238-29.91357L424,294.12988V352a8.00562,8.00562,0,0,0,.60254,3.0459Z"/></svg>
|
Before Width: | Height: | Size: 3.8 KiB |
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -3,6 +3,20 @@
|
|||
LANGCODE:hu_HU
|
||||
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
|
||||
|
|
|
@ -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
|
1
xwords4/dawg/Italian/Makefile
Symbolic link
1
xwords4/dawg/Italian/Makefile
Symbolic link
|
@ -0,0 +1 @@
|
|||
./Makefile.zinga
|
|
@ -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 \
|
||||
:; \
|
||||
|
|
|
@ -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)
|
||||
|
@ -187,12 +189,13 @@ $(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)
|
||||
|
||||
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 $<
|
||||
|
@ -213,11 +216,11 @@ 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
|
||||
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 +257,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
|
||||
|
@ -269,24 +272,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
|
||||
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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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()
|
||||
|
|
|
@ -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
|
|
@ -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";
|
80
xwords4/dawg/dictstats.py
Executable file
80
xwords4/dawg/dictstats.py
Executable file
|
@ -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()
|
|
@ -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`;
|
||||
}
|
||||
|
||||
|
49
xwords4/dawg/frank_mkspecials.py
Executable file
49
xwords4/dawg/frank_mkspecials.py
Executable file
|
@ -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()
|
7
xwords4/dawg/mkbyodbins.sh
Executable file
7
xwords4/dawg/mkbyodbins.sh
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/bin/sh
|
||||
|
||||
for INFO in $(ls */info.txt); do
|
||||
DIR=$(dirname $INFO)
|
||||
echo "*** processing $(basename $DIR) ***"
|
||||
(cd $DIR && make clean byodbins)
|
||||
done
|
|
@ -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
|
68
xwords4/dawg/pbitm2bin.py
Executable file
68
xwords4/dawg/pbitm2bin.py
Executable file
|
@ -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()
|
|
@ -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;
|
|
@ -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 ( <INPUT> ) {
|
||||
|
||||
chomp;
|
||||
s/\#.*$//;
|
||||
s/^\s*$//; # nuke all-white-space lines
|
||||
next if !length;
|
||||
|
||||
if ( $inTiles ) {
|
||||
if ( /<END_TILES>/ ) {
|
||||
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 ( /<BEGIN_TILES>/ ) {
|
||||
$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;
|
132
xwords4/dawg/xloc.py
Executable file
132
xwords4/dawg/xloc.py
Executable file
|
@ -0,0 +1,132 @@
|
|||
#!/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')
|
||||
|
||||
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('^(.*)#.*$')
|
||||
sVarAssign = re.compile('^(\w+):(.*)$')
|
||||
sBeginTiles = re.compile('^<BEGIN_TILES>$')
|
||||
sEndTiles = re.compile('^<END_TILES>$')
|
||||
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, 2)
|
||||
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
|
||||
|
||||
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:
|
||||
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()
|
||||
|
||||
infoFile = 'info.txt'
|
||||
if not os.path.exists(infoFile):
|
||||
errorOut('{} not found'.format(infoFile))
|
||||
xlocToken = parseTileInfo(infoFile, args.ENCODING)
|
||||
|
||||
if args.DO_TABLE or args.TABLE_FILE:
|
||||
path = args.TABLE_FILE or args.OUTFILE
|
||||
with open(path, 'wb') as outfile:
|
||||
writeMapFile(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__':
|
||||
main()
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue