Merge branch 'android_branch' into android_translate

This commit is contained in:
Eric House 2020-08-12 17:02:07 -07:00
commit e1a485d23e
14 changed files with 422 additions and 373 deletions

View file

@ -13,10 +13,10 @@
</style>
</head>
<body>
<h2>CrossWords 4.4.162 release</h2>
<h2>CrossWords 4.4.163 release</h2>
<p>This minor release adds a few translations and removes a feature
that prevented building for F-Droid.</p>
<p>This release includes a major rewrite of the wordlist browser and
fixes building for F-Droid.</p>
<div id="survey">
<p>Please <a href="https://www.surveymonkey.com/s/GX3XLHR">take
@ -26,9 +26,10 @@
<h3>New with this release</h3>
<ul>
<li>Pull in translations (from Weblate)</li>
<li>Re-enable F-Droid builds by disabling the new networking
code (using MQTT -- yeah, TMI :-) </li>
<li>Add more capable filtering to the wordlist browser (Has
a <a href="https://eehouse.org/xw4/faq.html">FAQ entry</a>
even.)</li>
<li>Enable networking via MQTT for the F-droid release</li>
</ul>
<p>(The full changelog
@ -36,7 +37,6 @@
<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

View file

@ -701,10 +701,14 @@ public class DictBrowseDelegate extends DelegateBase
public void run() {
stopProgress();
if ( null != wrapper ) {
m_browseState.onFilterAccepted( m_dict, null );
initList( wrapper );
setFindPats( m_browseState.m_pats );
} else {
makeOkOnlyBuilder(R.string.alrt_bad_filter )
.show();
}
newFeatureAlert();
}
} );

View file

@ -554,7 +554,7 @@ public class MQTTUtils extends Thread implements IMqttActionListener, MqttCallba
notifyNotHere( context, from.mqtt_devID, gameID );
} else {
for ( long rowid : rowids ) {
MQTTMsgSink sink = new MQTTMsgSink( context, rowid );
MultiMsgSink sink = new MultiMsgSink( context, rowid );
helper.receiveMessage( rowid, sink, data );
}
}
@ -584,13 +584,6 @@ public class MQTTUtils extends Thread implements IMqttActionListener, MqttCallba
mReturnAddr = from;
}
@Override
protected MultiMsgSink getSink( long rowid )
{
Context context = getContext();
return new MQTTMsgSink( context, rowid );
}
@Override
void postNotification( String device, int gameID, long rowid )
{
@ -600,18 +593,10 @@ public class MQTTUtils extends Thread implements IMqttActionListener, MqttCallba
// GameUtils.postInvitedNotification( mContext, gameID, body, rowid );
}
private void receiveMessage( long rowid, MQTTMsgSink sink, byte[] msg )
private void receiveMessage( long rowid, MultiMsgSink sink, byte[] msg )
{
Log.d( TAG, "receiveMessage(rowid=%d, len=%d)", rowid, msg.length );
receiveMessage( rowid, sink, msg, mReturnAddr );
}
}
private static class MQTTMsgSink extends MultiMsgSink {
MQTTMsgSink( Context context, long rowid )
{
super( context, rowid );
}
}
}

View file

@ -381,7 +381,7 @@ public class NFCUtils {
addReplyFor( new byte[]{REPLY_NOGAME}, gameID[0] );
} else {
for ( long rowid : rowids ) {
NFCMsgSink sink = new NFCMsgSink( context, rowid );
MultiMsgSink sink = new MultiMsgSink( context, rowid );
helper.receiveMessage( rowid, sink, body );
}
}
@ -1042,13 +1042,6 @@ public class NFCUtils {
super( context );
}
@Override
protected MultiMsgSink getSink( long rowid )
{
Context context = getContext();
return new NFCMsgSink( context, rowid );
}
@Override
void postNotification( String device, int gameID, long rowid )
{
@ -1057,17 +1050,10 @@ public class NFCUtils {
GameUtils.postInvitedNotification( context, gameID, body, rowid );
}
private void receiveMessage( long rowid, NFCMsgSink sink, byte[] msg )
private void receiveMessage( long rowid, MultiMsgSink sink, byte[] msg )
{
Log.d( TAG, "receiveMessage(rowid=%d, len=%d)", rowid, msg.length );
receiveMessage( rowid, sink, msg, mAddr );
}
}
private static class NFCMsgSink extends MultiMsgSink {
NFCMsgSink( Context context, long rowid )
{
super( context, rowid );
}
}
}

View file

@ -23,13 +23,14 @@ import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TableRow;
import org.eehouse.android.xw4.jni.XwJNI.PatDesc;
public class PatTableRow extends TableRow {
private static final String TAG = PatTableRow.class.getSimpleName();
private EditWClear mEdit;
private EditText mEdit;
private CheckBox mCheck;
public PatTableRow( Context context, AttributeSet as )
@ -67,22 +68,14 @@ public class PatTableRow extends TableRow {
boolean handled = mEdit.hasFocus();
if ( handled ) {
mEdit.insertBlank( blank );
mEdit.getText().insert(mEdit.getSelectionStart(), blank );
}
return handled;
}
private void getFields()
{
for ( int ii = 0;
(null == mEdit || null == mCheck) && ii < getChildCount();
++ii ) {
View view = getChildAt( ii );
if ( view instanceof EditWClear ) {
mEdit = (EditWClear)view;
} else if ( view instanceof CheckBox ) {
mCheck = (CheckBox)view;
}
}
mEdit = (EditText)Utils.getChildInstanceOf( this, EditText.class );
mCheck = (CheckBox)Utils.getChildInstanceOf( this, CheckBox.class );
}
}

View file

@ -50,7 +50,11 @@ abstract class XWServiceHelper {
Context getContext() { return mContext; }
abstract MultiMsgSink getSink( long rowid );
MultiMsgSink getSink( long rowid )
{
return new MultiMsgSink( getContext(), rowid );
}
abstract void postNotification( String device, int gameID, long rowid );
protected ReceiveResult receiveMessage( int gameID,

View file

@ -619,9 +619,13 @@ public class XwJNI {
new Thread( new Runnable() {
@Override
public void run() {
IterWrapper wrapper = null;
long iterPtr = di_init( jniState, dictPtr, pats,
minLen, maxLen );
callback.onIterReady( new IterWrapper(iterPtr) );
if ( 0 != iterPtr ) {
wrapper = new IterWrapper(iterPtr);
}
callback.onIterReady( wrapper );
}
} ).start();
}

View file

@ -53,9 +53,11 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<View android:layout_width="5dp"
android:layout_height="5dp"
android:layout_span="2"
<TextView style="@style/pat_table_label"
android:visibility="invisible"
/>
<EditText style="@style/pat_table_edit"
android:visibility="invisible"
/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
@ -69,8 +71,7 @@
<TextView style="@style/pat_table_label"
android:text="@string/pat_starts_with"
/>
<org.eehouse.android.xw4.EditWClear
style="@style/pat_table_edit"
<EditText style="@style/pat_table_edit"
/>
<CheckBox style="@style/pat_table_check"
/>
@ -82,8 +83,7 @@
<TextView style="@style/pat_table_label"
android:text="@string/pat_contains"
/>
<org.eehouse.android.xw4.EditWClear
style="@style/pat_table_edit"
<EditText style="@style/pat_table_edit"
/>
<CheckBox style="@style/pat_table_check"
/>
@ -95,8 +95,7 @@
<TextView style="@style/pat_table_label"
android:text="@string/pat_ends_with"
/>
<org.eehouse.android.xw4.EditWClear
style="@style/pat_table_edit"
<EditText style="@style/pat_table_edit"
/>
<CheckBox style="@style/pat_table_check"
/>

View file

@ -37,21 +37,21 @@
<!-- First state: is configured to use a room but has not yet
contacted the relay and been assigned that room. -->
<string name="summary_relay_conf_fmt">Configured for room
\"%1$s\"</string>
“%1$s”</string>
<!-- Second state: has been assigned to a room on the relay
(meaning the network is working) but there are not yet as
many players as expected: the game is not complete and play
cannot happen. -->
<string name="summary_relay_wait_fmt">Waiting for players in room
\"%1$s\"</string>
“%1$s”</string>
<!-- Third state: enough devices have connected in the room to
form a complete game. We'll be in this state as long as the
game exists. -->
<string name="summary_relay_conn_fmt">Game in play in room \"%1$s\"</string>
<string name="summary_relay_conn_fmt">Game in play in room “%1$s”</string>
<!-- Final state: game is over. -->
<string name="summary_relay_gameover_fmt">Game over in room \"%1$s\"</string>
<string name="summary_relay_gameover_fmt">Game over in room “%1$s”</string>
<string name="summary_invites_out">Players invited</string>
<string name="summary_invites_out_fmt">Players invited to room \"%1$s\"</string>
<string name="summary_invites_out_fmt">Players invited to room “%1$s”</string>
<!-- Games that have ended are listed with this string -->
<string name="gameOver">Game over</string>
<!-- Otherwise they're listed with this to give some indication of
@ -131,7 +131,7 @@
<!-- If you try to copy a networked game you get this error
message. -->
<string name="no_copy_network">Games that have already connected
to the relay cannot be copied. Use \"New from\" for a
to the relay cannot be copied. Use “New from” for a
ready-to-play copy with all the same settings.</string>
<!-- -->
<string name="game_rename_title">Rename game</string>
@ -337,7 +337,7 @@
<!-- title of popup used to determine how words are handled that
are not in the wordlist used for the game (or player if using
different wordlists per player) -->
<string name="phonies_spinner_prompt">How to handle \"phonies\"
<string name="phonies_spinner_prompt">How to handle “phonies”
(words not in wordlist)</string>
<!-- These are the three choices in the popup above whose text is
phonies_spinner_prompt -->
@ -354,7 +354,7 @@
<!-- Shown when using the Game configure screen to configure a
networked game and you try to make all players local. -->
<string name="str_reg_server_sans_remote">At least one player must
be marked \"Remote\" for a game started as Host.</string>
be marked “Remote” for a game started as Host.</string>
<!-- Used as the default name for remote players displayed within
the Game configure screen -->
<string name="guest_name">(Off-device player)</string>
@ -468,11 +468,11 @@
The number of players missing is substituted for "%1$d". -->
<plurals name="invite_msg_fmt">
<item quantity="one">This game is waiting for one remote
player. Would you like to invite someone to join -- assuming you
haven\'t already?</item>
player. Would you like to invite someone to joinassuming you
havent already?</item>
<item quantity="other">This game is waiting for %1$d remote
players. Would you like to invite someone to join -- assuming
you haven\'t already?</item>
players. Would you like to invite someone to joinassuming
you havent already?</item>
</plurals>
<plurals name="invite_sent_fmt">
<item quantity="one">You have already invited a remote player to
@ -497,7 +497,7 @@
players to invite, IF the number of missing players is
greater than one this text is appended to the above. -->
<string name="invite_multiple">\u0020(You are expecting multiple
remote players. You don\'t have to invite them all at once, but
remote players. You dont have to invite them all at once, but
this alert will not be dismissed until everybody has been invited
and all invitations have been accepted.)</string>
<string name="invit_expl_sms_fmt">Invite sent via Data SMS to phone
@ -505,13 +505,13 @@
<string name="invit_expl_usrsms_fmt">Invite sent via SMS to %1$s on %2$s</string>
<!-- shown when user chooses to invite via the default SMS app -->
<string name="sms_invite_flakey">This new option launches your
default SMS app with an invitation ready to send -- when it
works. Each SMS app is different, and some won\'t
default SMS app with an invitation ready to sendwhen it
works. Each SMS app is different, and some wont
cooperate.</string>
<!-- Toast when invite-by-visible-sms fails -->
<string name="sms_invite_fail">Unable to launch SMS app</string>
<string name="invit_expl_bt_fmt">Invite sent via Bluetooth to
paired device \"%1$s\" on %2$s</string>
paired device “%1$s” on %2$s</string>
<string name="invit_expl_relay_fmt">Invite forwarded by the relay
to another device on %1$s</string>
<string name="invit_expl_notarget_fmt">Invite sent via %1$s on
@ -528,15 +528,15 @@
only once per game. -->
<plurals name="msg_relay_waiting_fmt">
<item quantity="one">Device %1$d connected to relay in
room \"%2$s\". Waiting for one player.</item>
room “%2$s”. Waiting for one player.</item>
<item quantity="other">Device %1$d connected to relay in
room \"%2$s\". Waiting for %3$d players.</item>
room “%2$s”. Waiting for %3$d players.</item>
</plurals>
<!-- Text of "toast" shown when a game is notified by the relay
that all expected players have registered. At this point
play can begin. -->
<string name="msg_relay_all_here_fmt">All players are here in room
\"%1$s\".</string>
“%1$s”.</string>
<!-- Title of dialog used to alert players to relay-related
problems with the current game. -->
<string name="relay_alert">Connection problem</string>
@ -557,7 +557,7 @@
relay. Once this happens there is no way to continue the
game so you might as well delete it (unless you're saving it
for its history etc.) -->
<string name="msg_dev_deleted_fmt">The game named \"%1$s\" has been
<string name="msg_dev_deleted_fmt">The game named “%1$s” has been
deleted on another device. You will not be able to play any
further.</string>
<!-- Partial text of alert posted when phonies_warn or
@ -943,7 +943,7 @@
<string name="peek_other">View tiles out-of-turn</string>
<!-- explanation of the above -->
<string name="peek_other_summary">Tapping on scoreboard name shows
that player\'s tiles</string>
that players tiles</string>
<!-- If this preference is checked the "crosshairs" (vertical and
horzontal lines through the cell your finger is on that help
you tell where the app thinks you're actually tapping) will
@ -1018,7 +1018,7 @@
<string name="invite_choice_data_sms">Data SMS</string>
<string name="invite_choice_email">Email</string>
<string name="invite_choice_bt">Bluetooth</string>
<string name="invite_choice_nfc">NFC (\"Android beaming\")</string>
<string name="invite_choice_nfc">NFC (“Android beaming”)</string>
<string name="invite_choice_relay">Internet/Relay</string>
<string name="invite_choice_p2p">Wifi Direct</string>
<string name="invite_choice_title">Inviting players: How?</string>
@ -1029,7 +1029,7 @@
<!-- <string name="nfc_or_email">Send invitation using NFC (Android -->
<!-- beaming &#8211; NEW) or via email?</string> -->
<!-- <string name="nfc_or_sms_or_email">Send invitation using SMS -->
<!-- (texting) or NFC (\"Android beaming\" &#8211; NEW) or via email?</string> -->
<!-- (texting) or NFC (“Android beaming” &#8211; NEW) or via email?</string> -->
<!-- When an invitation is sent, the user gets to choose between
plaintext and html formatting. These two strings are shown in the
two buttons in the dialog. -->
@ -1038,8 +1038,8 @@
<!-- <string name="button_nfc">NFC</string> -->
<!-- This is the subject line of the email/text sent to invite
someone to join a game. -->
<string name="invite_subject">Let\'s play CrossWords</string>
<string name="invite_subject_fmt">Let\'s play CrossWords (room %1$s)</string>
<string name="invite_subject">Lets play CrossWords</string>
<string name="invite_subject_fmt">Lets play CrossWords (room %1$s)</string>
<!-- This is the body of the html version of the invitation. A URL
is created with parameters describing the game and
substituted for "%1$s". (The funky \u003c and friends are
@ -1130,7 +1130,7 @@
move)</string>
<!-- Displyed when you try to commit a move and it's not your
turn. -->
<string name="str_not_your_turn">You can\'t do that; it\'s not
<string name="str_not_your_turn">You cant do that; its not
your turn!</string>
<!-- Displayed when you try to reveal a robot player's tiles,
either by tapping on its "hidden" rack (marked by "?"
@ -1138,12 +1138,12 @@
ability to reveal another players tiles this way is
controlled by the peek_other preference and is disabled by
default.)-->
<string name="str_no_peek_robot_tiles">No peeking at the robot\'s
<string name="str_no_peek_robot_tiles">No peeking at the robots
tiles!</string>
<!-- Same as above, but used when you try to show tiles belonging
to a player on another device (a remote player.) -->
<string name="str_no_peek_remote_tiles">No peeking at remote
players\' tiles!</string>
players tiles!</string>
<!-- Displayed when you try to begin a trade but there are not
seven or more tiles in the pool. The rules don't allow
trading in this case. -->
@ -1160,7 +1160,7 @@
there are no tiles on the board (no move has yet been made.)
[If I'm being clever and disabling those features in this
case there may be no way to see this.] -->
<string name="str_cant_undo_tileassign">Tile assignment can\'t be
<string name="str_cant_undo_tileassign">Tile assignment cant be
undone.</string>
<!-- Using the hint feature is cheating by some players, and it
can be disabled via the hints_allowed preference. I should
@ -1203,12 +1203,12 @@
downloading and not opening the game. This first message
takes wordlist name and language substituted in for %1$ and
%2$ -->
<string name="no_dict_fmt">Game \"%1$s\" requires a %2$s wordlist.
<string name="no_dict_fmt">Game “%1$s” requires a %2$s wordlist.
Please download one before opening.</string>
<!-- This is an alternative message presented when there's also
the option of downloading another wordlist. Game name,
wordlist name and language are substituted in. -->
<string name="no_dict_subst_fmt">Unable to open game \"%1$s\" because
<string name="no_dict_subst_fmt">Unable to open game “%1$s” because
wordlist %2$s not found. (It may have been deleted, or stored
on an external card that is no longer available.)\n\nYou can
download a replacement or substitute another %3$s
@ -1233,7 +1233,7 @@
############################################################
-->
<!-- Text of dialog. Player name is substituted -->
<string name="msg_ask_password_fmt">Password for \"%1$s\":</string>
<string name="msg_ask_password_fmt">Password for “%1$s”:</string>
<!-- used to create default names of games (when user has not
named them.) -->
<string name="game_fmt">Game %1$d</string>
@ -1327,7 +1327,7 @@
###########################################################
-->
<!-- Title of New user info dialog-->
<string name="newbie_title">Here\'s a tip</string>
<string name="newbie_title">Heres a tip</string>
<!-- Text for button in new-user-info dialog with title just
above. -->
<string name="button_notagain">Do not show again</string>
@ -1388,7 +1388,7 @@
<!-- This is shown when you choose the board_menu_done menu item.
It's to let you know that there's a shortcut that does almost
the same thing. -->
<string name="not_again_done">Tapping the \"pts\" counter that
<string name="not_again_done">Tapping the “pts” counter that
appears at the right end of the rack is the easiest way to
commit a move.</string>
<!-- Shown in the Game configure screen when the game_locked
@ -1422,7 +1422,7 @@
<!-- This is not currently shown -->
<!-- <string name="not_again_dicts">CrossWords wordlists, which are -->
<!-- just compressed lists of words plus tile information, determine -->
<!-- what language a game is played in and how \"smart\" the robot -->
<!-- what language a game is played in and how “smart” the robot -->
<!-- is. You can download different sized wordlists in many -->
<!-- languages here. Email me at eehouse@eehouse.org for information -->
<!-- on building and installing your own wordlists.</string> -->
@ -1430,19 +1430,23 @@
Board screen. The idea is that you're tapping around
figuring out how to play and when you tap an empty cell the
arrow appears. This explains it. -->
<string name="not_again_arrow">Moving tiles to the board:\nYou can
drag tiles between the rack and the board, or you can tap an
empty square to place the board arrow. Rack tiles you tap will
replace the arrow (moving it one square in the direction it
points.) Tap the arrow once to change its orientation; a second
time, to hide it. A checkbox in the Appearance section of
Settings will hide it permanently.</string>
<string name="not_again_arrow">There are two ways to move tiles to
the board.
\n\n
• You can drag them between the rack and the board.
\n\n
• Or you can tap an empty square on the board to place the “board
arrow.” Then tiles in the rack replace the arrow when you tap
them. Tap the arrow to change its direction or to hide it.
</string>
<!-- Shown when the board screen is visible and it's just become
another players turn. The idea is to give a hint about how to
find out about recent moves. -->
<string name="not_again_turnchanged">The player whose turn it is
is drawn large in the scoreboard.\n\nHold your finger on a name in
the scoreboard to get details about that player\'s most recent
the scoreboard to get details about that players most recent
move.</string>
<!-- Shown when you first pick the list_item_new_from menuitem -->
<string name="not_again_newfrom">Create a new ready-to-play game
@ -1465,7 +1469,7 @@
<!-- Welcome dialog text -->
<string name="default_name_message">Please enter your name
here. It will be used when creating new games. (You can change it
later in the \"New game default\" section of Settings.)</string>
later in the “New game default” section of Settings.)</string>
<!--
###########################################################
# :Dialogs:
@ -1493,8 +1497,8 @@
<!-- Another paragraph giving credit for work done other than by
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.</string>
icons from the Noun Project: “archive” by Trendy; “rematch” by
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>
@ -1523,9 +1527,9 @@
<string name="not_again_lookup">This button lets you look up,
online, the words just played.</string>
<string name="not_again_archive">Archiving uses a special group
called \"Archive\" to store finished games you want to keep. And,
called “Archive” to store finished games you want to keep. And,
since deleting an entire archive is easy, archiving is also a
great way to mark games for deletion if that\'s what you prefer
great way to mark games for deletion if thats what you prefer
to do.\n\n(Deleting the Archive group is safe because it will be
created anew when needed.)
</string>
@ -1555,7 +1559,7 @@
but nothing can be done because there's not focussed text
field -->
<string name="blank_button_expl">This button inserts a blank at
the active text field\'s cursor, but there is no cursor
the active text fields cursor, but there is no cursor
now.</string>
<!-- Label for first field in wordlist browser filter -->
@ -1588,7 +1592,7 @@
<string name="dict_browse_title_fmt">%1$s (%2$d words total)</string>
<!-- -->
<string name="not_again_browse">This button opens the wordlist
browser on the current player\'s wordlist.</string>
browser on the current players wordlist.</string>
<!-- -->
<string name="not_again_browseall">This button opens the wordlist
browser on the wordlist of your choice.</string>
@ -1608,6 +1612,8 @@
<!-- Shown when user tries to make a wordlist filter where max < min -->
<string name="error_min_gt_max">The minimum length value cannot be
greater than the maximum value.</string>
<!-- shown when something goes wrong building a filter -->
<string name="alrt_bad_filter">Unable to apply filter.</string>
<!-- Title of progress alert shown while wordlist is loading. For
huge lists like Polish this can take a few seconds. -->
@ -1617,11 +1623,10 @@
<!-- Text of alert shown when user first opens wordlist
browser. Shown until not-again checkbox checked. -->
<string name="new_feature_filter">This wordlist browser now has
dramatically improved filtering abilities. As an example, you can
show all words containing \"QU\" and ending in \"ING\".\n\nAccess
filtering by tapping the Expander button at the upper-right corner
of the window.\n\nRead more on the FAQ by tapping the button
<string name="new_feature_filter">You can now filter wordlists
based on what they start with, end with, and/or contain. Access
filtering by tapping the Expander Arrow at the upper-right corner
of the window.\n\nRead more in the FAQ by tapping the button
below.</string>
<string name="board_menu_file_email">Email author</string>
@ -1631,7 +1636,7 @@
<string name="email_author_chooser">Send comment via</string>
<!-- -->
<string name="email_body_rev_fmt">(If relevant, please include the
version: \"%1$s\"; and make/model of your phone or
version: “%1$s”; and make/model of your phone or
tablet.)</string>
<!-- <string name="newgame_enable_bt">Turn Bluetooth on</string> -->
<!-- In invitation dialogs, button to remove checked items -->
@ -1660,11 +1665,11 @@
<string name="new_relay_body">Tap to open the new game</string>
<!-- -->
<string name="bt_bad_proto_fmt">The version of CrossWords on
\"%1$s\" is incompatible with this one for play using
“%1$s” is incompatible with this one for play using
Bluetooth. One of you may need to upgrade before you can
continue.</string>
<string name="sms_bad_proto_fmt">The version of CrossWords on the
phone with number \"%1$s\" is incompatible with this one for play
phone with number “%1$s” is incompatible with this one for play
using Data SMS. One of you may need to upgrade before you can
continue.</string>
<!-- -->
@ -1710,15 +1715,15 @@
<!-- -->
<plurals name="invite_sms_desc_fmt">
<item quantity="one">Please check the phone number you want to
invite to your new game, then tap \"%2$s\".</item>
invite to your new game, then tap “%2$s”.</item>
<item quantity="other">Please check the %1$d phone numbers you
want to invite to your new game, then tap \"%2$s\".</item>
want to invite to your new game, then tap “%2$s”.</item>
</plurals>
<!-- Appears near top of invitation phone number picker when it's
the user-visible SMS case -->
<string name="invite_sms_desc">Your SMS messaging app will then be
launched with a message for you to send to the phone number
you\'ve selected.</string>
youve selected.</string>
<!-- Appears near top of invitation phone number picker when it's
the user-invisible Data SMS case -->
<string name="invite_nbs_desc">A data message will then be
@ -1728,28 +1733,28 @@
<!-- -->
<plurals name="invite_relay_desc_fmt">
<item quantity="one">Please check the device you want to invite
to your new game, then tap \"%2$s\".</item>
to your new game, then tap “%2$s”.</item>
<item quantity="other">Please check the %1$d devices you want to invite
to your new game, then tap \"%2$s\".</item>
to your new game, then tap “%2$s”.</item>
</plurals>
<!-- -->
<plurals name="invite_p2p_desc_fmt">
<item quantity="one">Please select the name of the
WiFiDirect device you want to invite to your new game, then tap
\"%2$s\".</item>
“%2$s”.</item>
<item quantity="other">Please select the %1$d WiFiDirect device names you
want to invite to your new game, then tap \"%2$s\".</item>
want to invite to your new game, then tap “%2$s”.</item>
</plurals>
<string name="invite_p2p_desc_extra">Only devices that are
currently available are shown. If a nearby device isn\'t showing
currently available are shown. If a nearby device isnt showing
up please make sure that WiFi is turned on, that CrossWords is
installed, and that play via WiFi Direct is enabled.</string>
<!-- -->
<string name="warn_nomobile_fmt">The number %1$s for %2$s is not
a \"mobile\" number. Import anyway?</string>
a “mobile” number. Import anyway?</string>
<!-- Shows in SMS Invite dialog when no phone numbers have been saved previously -->
<string name="empty_sms_inviter">This phone list is empty. Use the
\"Import contact\" button to add people you want to invite, the +
“Import contact” button to add people you want to invite, the +
button to enter numbers directly.</string>
<string name="empty_bt_inviter">No paired devices detected yet.</string>
<!-- Shows in WiFiDirect Invite dialog when no known peers -->
@ -1757,8 +1762,8 @@
reachable via WiFiDirect that have CrossWords installed.</string>
<!-- -->
<string name="empty_relay_inviter">This list of devices is
empty. Use the \"Scan games\" button to scan your old games
for opponents. Use the \"+\" button to enter device IDs directly.</string>
empty. Use the “Scan games” button to scan your old games
for opponents. Use the “+” button to enter device IDs directly.</string>
<!-- -->
<string name="get_sms_title">Manual entry</string>
<string name="get_sms_number">Device phone number:</string>
@ -1790,7 +1795,7 @@
<string name="summary_conn_sms_fmt">Game in play with %1$s</string>
<!-- -->
<string name="warn_unlimited">Are you certain this number is on an
account with unlimited texting? Tap \"Cancel\" if you are
account with unlimited texting? Tap “Cancel” if you are
not.</string>
<!-- -->
<string name="remote_undone">Remote device undid a turn.</string>
@ -1816,7 +1821,7 @@
<string name="summary_busy">Summary unavailable</string>
<string name="connstat_net_noaddr">This networked game has no way
to connect and cannot be played.\n\n(It was probably created from
an invitation that didn\'t specify any way of connecting that your
an invitation that didnt specify any way of connecting that your
device supports, or you may have recently removed its last way of
connecting.)</string>
<!-- -->
@ -1854,7 +1859,7 @@
<string name="confirm_sms_expl">Warning: This feature is meant for
phones with unlimited texting plans. Once you enable it dozens of
Data SMS messages will be sent (invisibly) for each game
played. If you don\'t have an unlimited plan your carrier may
played. If you dont have an unlimited plan your carrier may
charge you for each and every message!\n\nShould play via Data SMS
be enabled?</string>
<!-- -->
@ -1864,7 +1869,7 @@
<!-- -->
<string name="confirm_sms_unlimited">Yes: I have unlimited texting</string>
<!-- -->
<string name="confirm_sms_willpay">Yes: I\'ll pay all carrier charges</string>
<string name="confirm_sms_willpay">Yes: Ill pay all carrier charges</string>
<!-- -->
<string name="warn_sms_disabled">Play via Data SMS is currently
disabled. No moves will be sent via Data SMS.\n\nYou can enable
@ -1978,7 +1983,7 @@
<string name="button_archive">Archive\u200C</string>
<string name="checkbox_archive">Move to Archive</string>
<string name="group_name_archive">Archive</string>
<string name="duplicate_group_name_fmt">The group \"%1$s\" already exists.</string>
<string name="duplicate_group_name_fmt">The group “%1$s” already exists.</string>
<string name="button_reconnect">Reconnect</string>
<string name="square_tiles">Square rack tiles</string>
<string name="square_tiles_summary">Even if they can be taller</string>
@ -1987,7 +1992,7 @@
<string name="not_again_newselect">Tapping a game opens it.\n\nYou
can instead tap the icons at the left to select or deselect games,
then act on selected games, e.g. to delete them, using the menu or
\"Actionbar.\"</string>
“Actionbar.”</string>
<string name="not_again_backclears">The back button clears any
selection instead of exiting. Hit it again to exit the
app.</string>
@ -2110,14 +2115,14 @@
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
what\'s available.</string>
legal\n\nCheck the “Show downloadable” box at the top to see
whats 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>
<string name="force_tablet_tablet">Force tablet layout</string>
<string name="force_tablet_phone">Force phone layout</string>
<!-- Nagging: title of notification reminder message -->
<string name="nag_title">Reminder: It\'s your turn</string>
<string name="nag_title">Reminder: Its your turn</string>
<!-- body of warning notification reminder message. First three
are used to build a string based on the length of time that's then
inserted in the fourth. E.g "PlayerName moved more than 2 day[s],
@ -2186,7 +2191,7 @@
<item quantity="other">%1$d players</item>
</plurals>
<string name="err_dup_invite_fmt">Duplicate invitation rejected:
device \"%1$s\" has already accepted an invitation to this
device “%1$s” has already accepted an invitation to this
game.</string>
<string name="network_advanced_title">Advanced</string>
<string name="network_advanced_summary">For experienced players</string>
@ -2209,7 +2214,7 @@
<!-- Button for alert with title above -->
<string name="button_close">Close</string>
<string name="button_reinvite">Re-invite</string>
<string name="invite_stays">(This dialog will stay up until all
<string name="invite_stays">(You will see this dialog until all
remote players have connected. You can close the game if you
expect it to take a while. Remote players will still be able to
connect, and you will be notified when they do.)</string>
@ -2232,7 +2237,7 @@
<string name="disable_nags_title">Turn reminders</string>
<string name="disable_nag_title">Disable network game reminders</string>
<string name="disable_nag_summary">Do not notify me no matter
how long it\'s been my turn</string>
how long its been my turn</string>
<string name="disable_nag_solo_title">Disable solo game reminders</string>
<string name="confirm_get_locdict_fmt">Your device is set up for
%1$s. Would you like to download a wordlist so you can play
@ -2271,7 +2276,7 @@
<string name="enable_sms_toself_title">Short-circuit SMS to self</string>
<string name="enable_sms_toself_summary">Skip radio when phone numbers same</string>
<string name="force_radio_title">Pretend to have radio</string>
<string name="radio_name_real">Don\'t pretend</string>
<string name="radio_name_real">Dont pretend</string>
<string name="radio_name_tablet">Tablet/no radio</string>
<string name="radio_name_gsm">GSM</string>
<string name="radio_name_cdma">CDMA</string>
@ -2283,7 +2288,7 @@
<string name="expl_relay_url">URL for relay web API</string>
<string name="expl_mqtt_url">URL for new MQTT-based relay API</string>
<string name="got_langdict_title">Fetch default wordlist for language</string>
<string name="got_langdict_summary">Don\'t try a second time</string>
<string name="got_langdict_summary">Dont try a second time</string>
<string name="pref_group_sms_title">SMS Stuff</string>
<string name="pref_group_sms_summary">Prefs related to play-via-sms</string>
<string name="pref_group_relay_title">Relay Stuff</string>
@ -2301,11 +2306,11 @@
connect.\n\nPlease try opening the game again later after
conditions have changed.</string>
<string name="drop_relay_warning_fmt">(This game can also connect
via %1$s, so if you\'d like to play the game without a relay
via %1$s, so if youd like to play the game without a relay
connection you can.)
</string>
<string name="confirm_drop_relay">Are you sure you want to drop this
game\'s ability to communicate via the relay?</string>
games ability to communicate via the relay?</string>
<string name="wifi_warning">\u0020For example, you may need to be on
a different WiFi network.</string>
<string name="confirm_drop_relay_bt">Bluetooth only works for nearby
@ -2313,27 +2318,27 @@
<string name="confirm_drop_relay_sms">Not all carriers support play
via Data SMS.</string>
<string name="button_enable">Enable</string>
<string name="not_again_comms_relay">The \"relay\" is a server on
<string name="not_again_comms_relay">The “relay” is a server on
the internet that passes messages between devices that are running
CrossWords. It works any time you have a fully-functional internet
connection, but might have problems on restricted WiFi
networks.</string>
<string name="not_again_comms_sms">Play via Data SMS uses the
technology on which \"texting\" is built. Though the messages are
technology on which “texting” is built. Though the messages are
invisible to you, your carrier bills them as texts, so you want to
avoid this feature unless you have an unlimited texting plan (or
budget.) Note that Android only supports this feature on devices on
a GSM carrier, i.e. every carrier in the world except Verizon and
Sprint.</string>
<string name="not_again_comms_bt">Use Bluetooth to play against a
nearby device that\'s \"paired\" with yours.</string>
nearby device thats “paired” with yours.</string>
<string name="not_again_comms_p2p">Use WiFi Direct to play against a
nearby WiFi Direct-capable device with CrossWords installed.</string>
<string name="str_no_hint_found">Cannot find any moves</string>
<string name="not_again_rematch_two_only">Rematch is limited to
two-person games, at least for now, because it\'s harder with more
devices and I think it\'s rare that people play with more than
two. Let me know if I\'m wrong and I\'ll up the priority.</string>
two-person games, at least for now, because its harder with more
devices and I think its rare that people play with more than
two. Let me know if Im wrong and Ill up the priority.</string>
<string name="show_sms_title">Show SMS sends, receives</string>
<string name="show_fcm_title">Show FCM receives</string>
<!-- Shown after "resend messages" menuitem chosen -->
@ -2347,7 +2352,7 @@
<string name="clip_label">Invitation URL</string>
<!-- EXPERIMENTAL: Newbie hint next when invite_choice_clip shown
when chosen -->
<string name="not_again_clip_expl_fmt">The \"%1$s\" option copies an
<string name="not_again_clip_expl_fmt">The “%1$s” option copies an
invitation URL to the clipboard. Paste it into the app of your
choice and send it to your friend.</string>
<string name="confirm_clear_chat">Are you sure you want to delete
@ -2361,7 +2366,7 @@
<!-- Debug-only item for testing corrupt game warnings -->
<string name="list_item_markbad">Mark corrupt</string>
<string name="not_again_dfltname_fmt">You are using the default
player name \"%1$s\". Would you like to personalize with your own
player name “%1$s”. Would you like to personalize with your own
name before you create this game?</string>
<string name="no_invites">This game has sent no invitations</string>
<string name="after_restart">This change will take effect after you
@ -2382,25 +2387,25 @@
\n\n
You can read more using the button below.</string>
<string name="download_rationale">CrossWords needs access to
temporary storage to keep what you\'re about to download.
temporary storage to keep what youre about to download.
</string>
<string name="sms_invite_rationale">
CrossWords needs permission to send an invitation via Data SMS.
</string>
<string name="dicts_storage_rationale">
CrossWords can store and read wordlists in your device\'s
CrossWords can store and read wordlists in your devices
Downloads area but it needs permission to access them
there.\n\nYou can safely deny this permission if you will never
download wordlists except from inside CrossWords and have not
previously stored any there.
</string>
<string name="phone_state_rationale">
Some phones can exchange SMS \"data\" messages. CrossWords would
Some phones can exchange SMS “data” messages. CrossWords would
like to offer you this option but needs to ask your device about
itself first (to learn if it\'s a phone and if so what
type.)\n\nIf your device can\'t send data SMS (e.g. because it
isn\'t a phone) or you don\'t ever want to play via SMS
(e.g. because you pay for each message), it\'s safe to permanently
itself first (to learn if its a phone and if so what
type.)\n\nIf your device cant send data SMS (e.g. because it
isnt a phone) or you dont ever want to play via SMS
(e.g. because you pay for each message), its safe to permanently
deny permission.
</string>
<string name="phone_lookup_rationale">
@ -2416,8 +2421,8 @@
Data SMS.</string>
<string name="contacts_rationale">
CrossWords wants access to your contacts in order to put a name to
phone numbers that send you invitations via Data SMS. You\'ll
still be able to receive invitations if you don\'t grant this
phone numbers that send you invitations via Data SMS. Youll
still be able to receive invitations if you dont grant this
permission, but only the phone number of the sender will be
displayed.
</string>
@ -2440,14 +2445,14 @@
<string name="gameevent_channel_expl">In-game events</string>
<!-- Notification that the OS isn't scheduling background services -->
<string name="servicestall_channel_expl">Stalled messaging alerts</string>
<string name="not_again_emptybtscan">If a scan doesn\'t find the device you expect:\n
<string name="not_again_emptybtscan">If a scan doesnt find the device you expect:\n
• First, just Rescan\n
• Make sure Bluetooth is enabled on the other device\n
• Launch CrossWords on the other device\n
• If all else fails, reboot this device\n
</string>
<string name="title_enable_stallnotify">Show stalled network notification</string>
<string name="summary_enable_stallnotify">Notify when Android\'s
<string name="summary_enable_stallnotify">Notify when Androids
slow to process outgoing invitations and moves</string>
<string name="notify_stall_title">Message sending is stalled</string>
<string name="notify_stall_body_fmt">%1$s (and others?) could not send outbound messages
@ -2460,17 +2465,19 @@
<string name="button_more_info">Read more</string>
<string name="banned_nbs_perms">This game is set up to communicate via data SMS, but apps from the Google Play Store are no longer allowed to do so (with rare exceptions). You can still open the game, but it may not be able to send or receive moves.
\n
\nYou can remove the data SMS communication setting, or use the \"Read more\" button to check progress on the development of an alternative.</string>
\nYou can remove the data SMS communication setting, or use the “Read more” button to check progress on the development of an alternative.</string>
<string name="relay_poll_title">Check for moves how?</string>
<string name="relay_poll_name_no_fcm">Poll only: no FCM messages</string>
<string name="relay_poll_name_no_polling">FCM only: no polling</string>
<string name="relay_poll_name_both">Default: mix polling and FCM</string>
<string name="not_again_longtap_lookup">You can look up words BEFORE
they\'re committed as moves -- by long-tapping, same as committed
words.\n\nUse this feature to check the validity of words you\'re
theyre committed as moves—by long-tapping, same as committed
words.\n\nUse this feature to check the validity of words youre
thinking of playing, or to look up an unfamiliar word provided as a
hint.</string>
<string name="servicedesc">For transmitting CrossWords moves</string>
<!-- New strings for duplicate mode play -->
<!-- Checkbox in game config dialog -->
<string name="duplicate_check">Duplicate mode</string>
@ -2478,16 +2485,19 @@
<string name="dup_tag">Dup</string>
<!-- Mark game title; will produce something like "Kati vs. Eric (dup.)" -->
<string name="dupe_title_fmt">%1$s (dup.)</string>
<!-- Used instead of str_commit_confirm when in duplicate mode -->
<string name="str_submit_confirm">Submit the current move?\n</string>
<!-- In new-game preferences, do we default to dup-mode being on or off? -->
<string name="offerdupmode_title">Play in \"duplicate-mode\"</string>
<string name="offerdupmode_title">Play in “duplicate-mode”</string>
<string name="offerdupmode_sum">(Experimental!!!) Style of play
where all players have the same tiles</string>
<!-- These are temporary: debug-only preferences to unhide duplicate
mode. Will go away once it's no longer experimental. -->
<string name="unhide_dupmode_title">Unhide duplicate-mode options</string>
<string name="unhide_dupmode_summary">(It\'s too experimental right now)</string>
<string name="unhide_dupmode_summary">(Its too experimental right now)</string>
<!-- dup mode: tile assignment -->
<string name="lmi_tiles_dup">Same tiles assigned to all players</string>
<!-- dup mode: A "pass" is when nobody can score -->
@ -2542,13 +2552,13 @@
<!-- Button in pause confirm/message edit dialog -->
<string name="pause_forget_msg">Forget message</string>
<!-- Hint in message edit when pausing -->
<string name="pause_expl_hint">Why I\'m doing this</string>
<string name="pause_expl_hint">Why Im doing this</string>
<string name="pause_notify_fmt">Player %1$s has paused this game.</string>
<string name="unpause_notify_fmt">Player %1$s has un-paused this game.</string>
<string name="pause_notify_expl_fmt">Player %1$s has paused this game, with this explanation: %2$s</string>
<string name="unpause_notify_expl_fmt">Player %1$s has un-paused
this game, with this explanation: %2$s</string>
<string name="autopause_expl_fmt">The timer for game \"%1$s\" expired without
<string name="autopause_expl_fmt">The timer for game “%1$s” expired without
any moves being made, so it has been paused for you.</string>
<string name="history_unpause_fmt">Unpaused after %2$s by: %1$s.</string>
<string name="history_pause_fmt">Paused by: %1$s.</string>
@ -2583,12 +2593,12 @@
browser. Displayed below are the possible
spellings. Currently this can only happen with Hungarian
wordlists. -->
<string name="pick_tiles_title">Pick a tile \"spelling\"</string>
<string name="pick_tiles_title">Pick a tile “spelling”</string>
<!-- Shown when user types a string that contains non-tiles,
e.g. a Q alone when the langauge has only QU. First
substituted is user's string; second substitution is name of
language -->
<string name="no_tiles_exist">\"%1$s\" cannot be spelled with %2$s tiles.</string>
<string name="no_tiles_exist">“%1$s” cannot be spelled with %2$s tiles.</string>
<string name="new_feature_title">New Feature Alert</string>
@ -2597,6 +2607,6 @@
<!-- MQTT stuff. May not see the light of day -->
<string name="invite_choice_mqtt">Internet/MQTT</string>
<string name="mqtt_invite_title">MQTT Invitation</string>
<string name="not_again_comms_mqtt">I\'m experimenting with this
<string name="not_again_comms_mqtt">Im experimenting with this
as a replacement for the relay.</string>
</resources>

View file

@ -120,10 +120,12 @@
</style>
<style name="pat_table_edit" parent="edit_w_clear">
<item name="android:layout_width">200dp</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:maxLines">1</item>
<item name="android:maxLength">15</item>
<item name="android:inputType">text</item>
<item name="android:layout_weight">1</item>
</style>
<style name="pat_table_check">
@ -152,6 +154,7 @@
<item name="android:layout_width">wrap_content</item>
<item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
<item name="android:layout_weight">1</item>
<item name="android:maxLines">1</item>
</style>
<style name="config_spinner_spinner">

View file

@ -2656,34 +2656,32 @@ Java_org_eehouse_android_xw4_jni_XwJNI_di_1init
DictionaryCtxt* dict = (DictionaryCtxt*)dictPtr;
if ( !!dict ) {
DictIterData* data = XP_CALLOC( globalState->mpool, sizeof(*data) );
data->globalState = globalState;
data->dict = dict_ref( dict, env );
data->depth = 2;
#ifdef DEBUG
data->guard = GI_GUARD;
#endif
PatDesc patDescs[3];
XP_MEMSET( patDescs, 0, VSIZE(patDescs) * sizeof(patDescs[0]) );
int len = 0;
bool formatOK = true;
if ( !!jPatsArr ) {
len = (*env)->GetArrayLength( env, jPatsArr );
XP_ASSERT( len == 3 );
for ( int ii = 0; ii < len ; ++ii ) {
for ( int ii = 0; formatOK && ii < len ; ++ii ) {
jobject jdesc = (*env)->GetObjectArrayElement( env, jPatsArr, ii );
if ( !!jdesc ) {
jbyteArray jtiles;
if ( getObject( env, jdesc, "tilePat", "[B", &jtiles ) ) {
int nTiles = (*env)->GetArrayLength( env, jtiles );
if ( 0 < nTiles ) {
patDescs[ii].nTiles = nTiles;
PatDesc* pd = &patDescs[ii];
/* If user adds too many tiles, we'll see it here */
if ( nTiles <= VSIZE(pd->tiles) ) {
pd->nTiles = nTiles;
jbyte* tiles = (*env)->GetByteArrayElements( env, jtiles, NULL );
XP_MEMCPY( &patDescs[ii].tiles[0], tiles,
nTiles * sizeof(patDescs[ii].tiles[0]) );
XP_MEMCPY( &pd->tiles[0], tiles, nTiles * sizeof(pd->tiles[0]) );
(*env)->ReleaseByteArrayElements( env, jtiles, tiles, 0 );
patDescs[ii].anyOrderOk = getBool( env, jdesc, "anyOrderOk" );
pd->anyOrderOk = getBool( env, jdesc, "anyOrderOk" );
} else {
formatOK = false;
}
}
deleteLocalRef( env, jtiles );
}
@ -2692,15 +2690,28 @@ Java_org_eehouse_android_xw4_jni_XwJNI_di_1init
}
}
DictIter* iter = NULL;
if ( formatOK ) {
DIMinMax mm = { .min = minLen, .max = maxLen };
data->iter = di_makeIter( data->dict, env, &mm, NULL, 0,
iter = di_makeIter( dict, env, &mm, NULL, 0,
!!jPatsArr ? patDescs : NULL, VSIZE(patDescs) );
}
if ( !!iter ) {
DictIterData* data = XP_CALLOC( globalState->mpool, sizeof(*data) );
data->iter = iter;
data->globalState = globalState;
data->dict = dict_ref( dict, env );
data->depth = 2;
#ifdef DEBUG
data->guard = GI_GUARD;
#endif
makeIndex( data );
(void)di_firstWord( data->iter );
closure = (jlong)data;
}
}
return closure;
}

View file

@ -145,6 +145,27 @@ typedef enum { PatErrNone,
PatErrDupInSet,
} PatErr;
#ifdef DEBUG
static const XP_UCHAR*
patErrToStr( PatErr err )
{
const XP_UCHAR* result = NULL;
# define CASESTR(s) case s: result = #s; break
switch ( err ) {
CASESTR(PatErrNone);
CASESTR(PatErrMissingClose);
CASESTR(PatErrMultipleSpellings);
CASESTR(PatErrBadCountTerm);
CASESTR(PatErrNoDigit);
CASESTR(PatErrTooComplex);
CASESTR(PatErrBogusTiles);
CASESTR(PatErrDupInSet);
}
# undef CASESTR
return result;
}
#endif
typedef struct _ParseState {
const DictionaryCtxt* dict;
const XP_UCHAR* pat;
@ -264,6 +285,18 @@ onFoundTiles( void* closure, const Tile* tiles, int len )
return 1 == len && PatErrNone == data->err;
}
static PatErr
addElem( ParseState* ps, PatElem* elem )
{
PatErr err = PatErrNone;
if ( ps->elemIndex < VSIZE(ps->elems) ) {
ps->elems[ps->elemIndex++] = *elem;
} else {
err = PatErrTooComplex;
}
return err;
}
static PatErr
parseTile( ParseState* ps )
{
@ -390,9 +423,10 @@ compileParent( ParseState* ps )
return err;
}
static void
static PatErr
initPS( ParseState* ps, const DictionaryCtxt* dict )
{
PatErr result = PatErrNone;
XP_MEMSET( ps, 0, sizeof(*ps) );
XP_ASSERT( !!dict );
ps->dict = dict;
@ -407,8 +441,9 @@ initPS( ParseState* ps, const DictionaryCtxt* dict )
#ifdef WITH_START
PatElem start = { .typ = START, };
ps->elems[ps->elemIndex++] = start;
result = addElem( ps, &start );
#endif
return result;
}
static XP_Bool
@ -416,19 +451,13 @@ compilePat( ParseState* ps, const XP_UCHAR* strPat )
{
ps->pat = strPat;
ps->patIndex = 0;
// XP_ASSERT( !!iter->dict );
/* ParseState ps = { .dict = iter->dict, */
/* .pat = strPat, */
/* .blankMask = ((TileSet)1) << dict_getBlankTile( iter->dict ), */
/* }; */
PatErr err = compileParent( ps );
XP_Bool success = err == PatErrNone && 0 < ps->elemIndex;
/* if ( success ) { */
/* XP_ASSERT( ps.elemIndex < VSIZE(ps.elems) ); */
/* replacePat( iter, &ps ); */
/* } */
if ( !success ) {
XP_LOGFF( "=> %s", patErrToStr(err) );
}
return success;
}
@ -1310,22 +1339,25 @@ firstWord( DictIter* iter, XP_Bool log )
return success;
}
static void
static XP_Bool
addTilePats( ParseState* ps, const PatDesc* pd )
{
XP_Bool success = XP_TRUE;
XP_Bool anyOrderOk = pd->anyOrderOk;
PatElem elem = { .typ = CHILD,
.minMatched = 1,
.maxMatched = 1,
};
for ( int ii = 0; ii < pd->nTiles; ++ii ) {
for ( int ii = 0; success && ii < pd->nTiles; ++ii ) {
#ifdef MULTI_SET
++elem.u.child.tiles.cnts[pd->tiles[ii]];
#else
elem.u.child.tiles |= 1 << pd->tiles[ii];
#endif
if ( !anyOrderOk ) {
ps->elems[ps->elemIndex++] = elem;
success = ps->elemIndex < VSIZE(ps->elems);
if ( success ) {
success = PatErrNone == addElem( ps, &elem );
#ifdef MULTI_SET
XP_MEMSET( &elem.u.child.tiles, 0, sizeof(elem.u.child.tiles) );
#else
@ -1333,11 +1365,14 @@ addTilePats( ParseState* ps, const PatDesc* pd )
#endif
}
}
}
if ( anyOrderOk ) {
elem.u.child.flags |= FLAG_SINGLE;
elem.minMatched = elem.maxMatched = pd->nTiles;
ps->elems[ps->elemIndex++] = elem;
success = PatErrNone == addElem( ps, &elem );
}
LOG_RETURNF( "%s", boolToStr(success) );
return success;
}
static void
@ -1352,7 +1387,12 @@ addWildcard( ParseState* ps )
#else
elem.u.child.tiles = ps->blankMask;
#endif
ps->elems[ps->elemIndex++] = elem;
#ifdef DEBUG
PatErr err =
#endif
addElem( ps, &elem );
XP_ASSERT( err == PatErrNone );
}
static void
@ -1405,7 +1445,8 @@ di_makeIter( const DictionaryCtxt* dict, XWEnv xwe, const DIMinMax* minmax,
if ( ii != STARTS_WITH ) {
addWildcard( &ps );
}
addTilePats( &ps, ta );
success = addTilePats( &ps, ta );
if ( success ) {
if ( ii != ENDS_WITH ) {
addWildcard( &ps );
}
@ -1413,6 +1454,7 @@ di_makeIter( const DictionaryCtxt* dict, XWEnv xwe, const DIMinMax* minmax,
}
}
}
}
if ( success ) {
XP_LOGFF( "making iter of size %zu", sizeof(*iter) );
iter = XP_CALLOC( dict->mpool, sizeof(*iter) );

View file

@ -77,7 +77,7 @@ typedef struct DictIter DictIter;
* ends-with. The first is more powerful but I'm not sure it'll ever be part
* of a shipping UI.*/
typedef struct _PatDesc {
Tile tiles[16];
Tile tiles[MAX_COLS_DICT];
XP_U16 nTiles;
XP_Bool anyOrderOk;
} PatDesc;

View file

@ -1948,7 +1948,6 @@ tmp_noop_sigintterm( int XP_UNUSED(sig) )
exit(0);
}
typedef struct _FTD {
PatDesc* desc;
XP_Bool called;
@ -1960,9 +1959,7 @@ onFoundTiles2( void* closure, const Tile* tiles, int nTiles )
FTD* data = (FTD*)closure;
if ( data->called ) {
XP_LOGFF( "ERROR: called more than once; Hungarian case???" );
} else if ( nTiles > VSIZE(data->desc->tiles) ) {
XP_ASSERT(0);
} else {
} else if ( nTiles <= VSIZE(data->desc->tiles) ) {
data->called = XP_TRUE;
data->desc->nTiles = nTiles;
XP_MEMCPY( &data->desc->tiles[0], tiles, nTiles * sizeof(tiles[0]) );
@ -2015,6 +2012,9 @@ patsParamsToIter( const LaunchParams* params, const DictionaryCtxt* dict )
DictIter* iter = di_makeIter( dict, NULL_XWE, dimmp, strPats, nStrPats,
0 == nPatDescs ? NULL : descs, nPatDescs );
if ( !iter ) {
XP_LOGFF( "Unable to build iter" );
}
return iter;
}
@ -2025,6 +2025,7 @@ testGetNthWord( const LaunchParams* params, const DictionaryCtxt* dict,
const IndexData* data )
{
DictIter* iter = patsParamsToIter( params, dict );
if ( !!iter ) {
XP_U32 half = di_countWords( iter, NULL ) / 2;
XP_U32 interval = half / 100;
const XP_UCHAR* delim = params->dumpDelim; /* NULL is ok */
@ -2057,6 +2058,7 @@ testGetNthWord( const LaunchParams* params, const DictionaryCtxt* dict,
}
di_freeIter( iter, NULL_XWE );
}
}
typedef struct _FTData {
DictIter* iter;
@ -2109,6 +2111,7 @@ walk_dict_test( MPFORMAL const LaunchParams* params, const DictionaryCtxt* dict,
{
DictIter* iter = patsParamsToIter( params, dict );
if ( !!iter ) {
LengthsArray lens;
XP_U32 count = di_countWords( iter, &lens );
@ -2226,7 +2229,8 @@ walk_dict_test( MPFORMAL const LaunchParams* params, const DictionaryCtxt* dict,
XP_FREE( mpool, data.prefixes );
}
di_freeIter( iter, NULL_XWE );
XP_LOGF( "done" );
}
XP_LOGFF( "done" );
}
static void
@ -2253,6 +2257,7 @@ static void
dumpDict( const LaunchParams* params, DictionaryCtxt* dict )
{
DictIter* iter = patsParamsToIter( params, dict );
if ( !!iter ) {
const XP_UCHAR* delim = params->dumpDelim; /* NULL is ok */
for ( XP_Bool result = di_firstWord( iter );
result;
@ -2263,6 +2268,7 @@ dumpDict( const LaunchParams* params, DictionaryCtxt* dict )
}
di_freeIter( iter, NULL_XWE );
}
}
static void
trimDictPath( const char* input, char* buf, int bufsiz, char** path, char** dict )
@ -2662,12 +2668,14 @@ testOneString( const LaunchParams* params, GSList* testDicts )
params->useMmap );
if ( NULL != dict ) {
DictIter* iter = patsParamsToIter( params, dict );
if ( !!iter ) {
if ( ! di_stringMatches( iter, params->iterTestPatStr ) ) {
result = 1;
}
di_freeIter( iter, NULL_XWE );
}
}
}
return result;
}
#endif