Merge branch 'android_branch' into send_in_background

Conflicts:
	xwords4/common/comms.c
This commit is contained in:
Andy2 2011-09-20 06:21:54 -07:00
commit 92614370ce
32 changed files with 586 additions and 267 deletions

View file

@ -65,7 +65,7 @@
android:screenOrientation="sensor"
android:configChanges="keyboardHidden|orientation"
>
<intent-filter android:label="@string/resolve_edit">
<intent-filter>
<action android:name="android.intent.action.EDIT" />
</intent-filter>
</activity>

View file

@ -1255,6 +1255,23 @@ Java_org_eehouse_android_xw4_jni_XwJNI_server_1endGame
XWJNI_END();
}
JNIEXPORT jstring JNICALL
Java_org_eehouse_android_xw4_jni_XwJNI_server_1listWordsPlayed
( JNIEnv* env, jclass C, jint gamePtr, jint nMoves )
{
jstring result;
XWJNI_START_GLOBALS();
XP_ASSERT( !!state->game.server );
XWStreamCtxt* stream = and_empty_stream( MPPARM(mpool) globals );
server_listWordsPlayed( state->game.server, stream, nMoves );
result = streamToJString( MPPARM(mpool) env, stream );
(*env)->DeleteLocalRef( env, result );
stream_destroy( stream );
XWJNI_END();
return result;
}
JNIEXPORT void JNICALL
Java_org_eehouse_android_xw4_jni_XwJNI_server_1sendChat
( JNIEnv* env, jclass C, jint gamePtr, jstring jmsg )

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ListView android:id="@+id/words"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:drawSelectorOnTop="false"
android:layout_marginLeft="30dip"
android:layout_marginRight="30dip"
/>
</LinearLayout>

View file

@ -18,29 +18,17 @@
<string name="button_new_game">Afegeix una partida</string>
<string name="list_item_config">Configura</string>
<string name="list_item_hide">Amaga</string>
<string name="list_item_delete">Suprimeix</string>
<string name="list_item_copy">Copia</string>
<string name="list_item_reset">Reinicialitza</string>
<string name="list_item_new_from">Nova</string>
<string name="list_item_move_up">Mou amunt</string>
<string name="list_item_move_down">Mou avall</string>
<string name="list_item_move_to_top">Mou amunt de tot</string>
<string name="list_item_move_to_bottom">Mou avall de tot</string>
<string name="resolve_edit">Edita la nota</string>
<string name="play">Partida</string>
<string name="title_games_list">Crosswords</string>
<string name="title_game">Partida</string>
<string name="title_dicts_list">Diccionaris del Crosswords</string>
<string name="title_game_configf">Configura el %s</string>
<string name="title_prefs">Configuració del Crosswords</string>
<string name="app_name">Crosswords</string>
<string name="button_ok">D\'acord</string>
<string name="button_cancel">Cancel·la</string>
<string name="button_yes"></string>
@ -84,7 +72,6 @@
<string name="strs_values_header">%s quantitat/valors:\n</string>
<string name="strd_remaining_tiles_add">+ %d [fitxes romanents]</string>
<string name="strd_unused_tiles_sub">- %d [fitxes al faristol]</string>
<string name="str_remote_moved">El jugador remot ha fet aquest moviment:</string>
<string name="strd_time_penalty_sub"></string>
<string name="str_pass"> - %d [temps]</string>
<string name="strs_move_across">mou (des de %s horitzontal)</string>
@ -119,7 +106,6 @@
<string name="remote_label">Jugador remot (s\'ignora)</string>
<string name="robot_label">Jugador robot</string>
<string name="password_label">Contrasenya (s\'ignora)</string>
<string name="robot_name">(robot)</string>
<string name="robot_namef">%s (robot)</string>
<string name="guest_name">(jugador visitant)</string>
<string name="player_edit_title">Jugador</string>
@ -132,8 +118,6 @@
<string name="dicts_item_select">Estableix com a predeterminat</string>
<string name="dicts_item_details">Detalls</string>
<string name="configure_role">Configura la connexió</string>
<string name="configure_rolef">Configura la connexió %s</string>
<string name="settings_label">Paràmetres de la partida</string>
<string name="minutes_label">Minuts a la partida</string>
@ -145,8 +129,6 @@
<string name="hints_allowed">Permet pistes</string>
<string name="use_timer">Habilita el temps</string>
<string name="color_tiles">Fitxes de colors</string>
<string name="color_tiles_summary">Les fitxes es mostren amb el color del jugador que les juga</string>
<string name="show_arrow">Mostra la fletxa al tauler</string>
<string name="show_arrow_summary">Les fitxes del faristol es col·locaran sobre la fletxa</string>
<string name="explain_robot">Explica les jugades del robot</string>
@ -199,7 +181,6 @@
<string name="bonus_l3x_summary">3L</string>
<string name="bonus_w3x_summary">3P</string>
<string name="pts">pts</string>
<string name="trading_text">Canvi de fitxes. Pitgeu\n\'Fet\' quan hagueu acabat.</string>
<string name="tile_back">Fons de la fitxa</string>
<string name="empty">Cel·la buida/fons</string>
<string name="clr_crosshairs">Creu d\'ubicació</string>
@ -209,11 +190,6 @@
<string name="dict_host">URL de baixada de diccionaris</string>
<string name="relay_port">Port del repetidor</string>
<string name="key_player">key_player</string>
<string name="tab_relay">Internet/Repetidor</string>
<string name="tab_sms">SMS (en desenvolupament)</string>
<string name="tab_bluetooth">Bluetooth (en desenvolupament)</string>
<string name="msg_relay_waiting">Esteu connectat al repetidor. S\'està esperant a %d jugador/s.</string>
<string name="relay_alert">Error en la connexió</string>
@ -232,8 +208,6 @@
<string name="force_title">Jugador/s remot/s</string>
<string name="force_expl">Un amfitrió ha de tenir com a mínim un jugador remot.</string>
<string name="summary_fmt_relay">%1$s via repetidor, sala
\"%2$s\"</string>
<string name="gameOver">Final de partida</string>
<string name="movesf">%d torns jugats</string>

View file

@ -18,29 +18,17 @@
<string name="button_new_game">Přidat hru</string>
<string name="list_item_config">Konfigurovat</string>
<string name="list_item_hide">Skrýt</string>
<string name="list_item_delete">Vymazat</string>
<string name="list_item_copy">Kopírovat</string>
<string name="list_item_reset">Vynulovat</string>
<string name="list_item_new_from">Nová hra podle vzoru</string>
<string name="list_item_move_up">Přesunout výš</string>
<string name="list_item_move_down">Přesunout níž</string>
<string name="list_item_move_to_top">Přesunout nahoru</string>
<string name="list_item_move_to_bottom">Přesunout dolů</string>
<string name="resolve_edit">Upravit poznámku</string>
<string name="play">Hrát hru</string>
<string name="title_games_list">Crosswords</string>
<string name="title_dicts_list">Slovníky Crosswords</string>
<string name="title_game">Hra</string>
<string name="title_game_configf">Konfigurovat %s</string>
<string name="title_prefs">Předvolby Crosswords</string>
<string name="app_name">Crosswords</string>
<string name="button_ok">OK</string>
<string name="button_cancel">Zrušit</string>
<string name="button_yes">Ano</string>
@ -83,7 +71,6 @@
<string name="strs_values_header">%s počet/hodnota:\n</string>
<string name="strd_remaining_tiles_add">+ %d [všechny zbývající kameny]</string>
<string name="strd_unused_tiles_sub">- %d [nepoužité kameny]</string>
<string name="str_remote_moved">Vzdálený hráč provedl tento tah:</string>
<string name="strd_time_penalty_sub"></string>
<string name="str_pass"> - %d [čas]</string>
<string name="strs_move_across">tah (od %s napříč)</string>
@ -117,7 +104,6 @@
<string name="remote_label">Hráč klient</string>
<string name="robot_label">Hráč robot</string>
<string name="robot_name">(robot)</string>
<string name="robot_namef">%s (robot)</string>
<string name="guest_name">(hráč klient)</string>
<string name="password_label">Heslo</string>
@ -131,8 +117,6 @@
<string name="dicts_item_select">Nastavit jako výchozí</string>
<string name="dicts_item_details">Podrobnosti</string>
<string name="configure_role">Konfigurovat připojení</string>
<string name="configure_rolef">Konfigurovat %s připojení</string>
<string name="settings_label">Nastavení hry</string>
<string name="minutes_label">Minut ve hře</string>
@ -146,8 +130,6 @@
<string name="hints_allowed">Povolit nápovědu</string>
<string name="use_timer">Povolit časovač</string>
<string name="color_tiles">Barvy kamenů</string>
<string name="color_tiles_summary">Obarvit kameny barvou hráče, který s nimi hrál</string>
<string name="show_arrow">Ukázat šipku</string>
<string name="show_arrow_summary">Slovo se začne psát ve směru šipky a od jejího umístění</string>
<string name="explain_robot">Vysvětlit tahy robota</string>
@ -178,7 +160,6 @@
<string name="bonus_l3x">Trojitá hodnota písmene</string>
<string name="bonus_w2x">Dvojitá hodnota slova</string>
<string name="bonus_w3x">Trojitá hodnota slova</string>
<string name="trading_text">Výměna kamenů. Zvolte\n\'Ukončit tah\' až budete hotovi.</string>
<string name="tile_back">Pozadí kamenů</string>
<string name="empty">Prázdné pole/pozadí</string>
<string name="advanced">Rozšířené</string>
@ -187,11 +168,6 @@
<string name="dict_host">URL adresa pro nahrávání slovníků</string>
<string name="relay_port">Relay port</string>
<string name="key_player">key_player</string>
<string name="tab_relay">Internet/Relay</string>
<string name="tab_sms">SMS (nefunkční)</string>
<string name="tab_bluetooth">Bluetooth (připravuje se)</string>
<string name="msg_relay_waiting">Připojen na relay. Čekám na %d hráče.</string>
<string name="relay_alert">Chyba připojení</string>
@ -211,7 +187,6 @@
<string name="force_expl">Jako Server vyberte jedoho nebo více hráčů kteří se budou moct
připojit jako Klient.</string>
<string name="summary_fmt_relay">%1$s přes Relay, místnost \"%2$s\"</string>
<string name="gameOver">Hra skončena</string>
<string name="movesf">Bylo zahráno %d tahů</string>

View file

@ -17,29 +17,17 @@
<string name="button_new_game">Pridať hru</string>
<string name="list_item_config">Konfigurovať</string>
<string name="list_item_hide">Skryť</string>
<string name="list_item_delete">Vymazať</string>
<string name="list_item_copy">Kopírovať</string>
<string name="list_item_reset">Vynulovať</string>
<string name="list_item_new_from">Nová hra podľa vzoru</string>
<string name="list_item_move_up">Presunúť vyššie</string>
<string name="list_item_move_down">Presunúť nižšie</string>
<string name="list_item_move_to_top">Presunúť nahor</string>
<string name="list_item_move_to_bottom">Presunúť nadol</string>
<string name="resolve_edit">Upraviť poznámku</string>
<string name="play">Hrať hru</string>
<string name="title_games_list">Crosswords</string>
<string name="title_dicts_list">Slovníky Crosswords</string>
<string name="title_game">Hra</string>
<string name="title_game_configf">Konfigurovať %s</string>
<string name="title_prefs">Predvoľby Crosswords</string>
<string name="app_name">Crosswords</string>
<string name="button_ok">OK</string>
<string name="button_cancel">Zrušiť</string>
<string name="button_yes">Áno</string>
@ -82,7 +70,6 @@
<string name="strs_values_header">%s počet/hodnota:\n</string>
<string name="strd_remaining_tiles_add">+ %d [všetky zostávajúce kamene]</string>
<string name="strd_unused_tiles_sub">- %d [nepoužité kamene]</string>
<string name="str_remote_moved">Vzdialený hráč uskutočnil tento ťah:</string>
<string name="strd_time_penalty_sub"/>
<string name="str_pass"> - %d [čas]</string>
<string name="strs_move_across">ťah (od %s naprieč)</string>
@ -116,7 +103,6 @@
<string name="remote_label">Hráč klient</string>
<string name="robot_label">Hráč robot</string>
<string name="robot_name">(robot)</string>
<string name="robot_namef">%s (robot)</string>
<string name="guest_name">(hráč klient)</string>
<string name="password_label">Heslo</string>
@ -130,8 +116,6 @@
<string name="dicts_item_select">Nastaviť ako východzí</string>
<string name="dicts_item_details">Podrobnosti</string>
<string name="configure_role">Konfigurovať pripojenie</string>
<string name="configure_rolef">Konfigurovať %s pripojenie</string>
<string name="settings_label">Nastavenie hry</string>
<string name="minutes_label">Minút v hre</string>
@ -145,8 +129,6 @@
<string name="hints_allowed">Povoliť nápovedu</string>
<string name="use_timer">Povoliť časovač</string>
<string name="color_tiles">Farby kameňov</string>
<string name="color_tiles_summary">Zafarbiť kamene farbou hráča, ktorý s nimi hral</string>
<string name="show_arrow">Ukázať šipku</string>
<string name="show_arrow_summary">Slovo sa začne písať v smere šipky a od jejho umiestenia</string>
<string name="explain_robot">Vysvetliť ťahy robota</string>
@ -176,7 +158,6 @@
<string name="bonus_l3x">Trojitá hodnota písmena</string>
<string name="bonus_w2x">Dvojitá hodnota slova</string>
<string name="bonus_w3x">Trojitá hodnota slova</string>
<string name="trading_text">Výmena kameňov. Zvoľte\n\'Ukončiť ťah\' až budete hotový.</string>
<string name="tile_back">Pozadie kamenňov</string>
<string name="empty">Prázdne pole/pozadie</string>
<string name="advanced">Rozšírené</string>
@ -185,11 +166,6 @@
<string name="dict_host">URL adresa pre nahrávanie slovníkov</string>
<string name="relay_port">Relay port</string>
<string name="key_player">key_player</string>
<string name="tab_relay">Internet/Relay</string>
<string name="tab_sms">SMS (nefunkčné)</string>
<string name="tab_bluetooth">Bluetooth (pripravuje sa)</string>
<string name="msg_relay_waiting">Pripojený na relay. Čakám na %d
hráčov.</string>
@ -210,7 +186,6 @@
<string name="force_expl">Ako Server vyberte jedného alebo viacerých hráčov ktorí sa budú mocť
pripojiť ako Klient.</string>
<string name="summary_fmt_relay">%1$s cez Relay, miestnosť \"%2$s\"</string>
<string name="gameOver">Hra skončená</string>
<string name="movesf">Bolo zahraných %d ťahov</string>

View file

@ -73,13 +73,19 @@
<string name="key_notagain_newfrom">key_notagain_newfrom</string>
<string name="key_notagain_trading">key_notagain_trading</string>
<!-- Name is not localized -->
<string name="app_name">Crosswords</string>
<!-- other -->
<string name="default_host">eehouse.org</string>
<!-- <string name="default_host">10.0.2.2</string> -->
<string name="dict_url">http://eehouse.org/and_wordlists</string>
<string name="app_version">4.4 beta 34</string>
<string name="game_url_pathf">//%1$s/redir.php</string>
<string name="game_url_pathf">//%1$s/newgame.php</string>
<!-- <string name="word_lookupf">http://dictionary.com/browse/%s</string> -->
<string name="word_lookupf">http://%1$s.thefreedictionary.com/_/dict.aspx?word=%2$s</string>
<!-- Debugging stuff. No point in localizing it. -->
<string name="advanced">For debugging</string>

View file

@ -12,12 +12,28 @@
############################################################
-->
<!-- window title -->
<string name="title_games_list">Crosswords</string>
<string name="title_games_list">Crosswords</string>
<!-- These two messages appear at the top of the list of games
(unless the hide_intro preferences checkbox is checked.)-->
<string name="empty_games_list">Use the button below to create a
game. Tap an existing game to play it or long-tap it for other
options.</string>
<string name="empty_games_list2">You can hide this and the button
below in the Appearance section of Settings (accessed via your
device\'s menu key).</string>
<!-- Text of button at bottom of main games-list screen and of
menuitem in main games-list screen's menu -->
menuitem in main games-list screen's menu. (The botton can
be hidden in the same way as the above text.) -->
<string name="button_new_game">Add game</string>
<!-- When the game list is empty and the above messages and button
are hidden via preferences, this text is shown -->
<string name="empty_list_msg">Use the menu key to add a
game.</string>
<!-- Used to format game name plus some other information as the
one-line summary for each game in the main screen. The name
of the game is substituted for %1$s. Something else
@ -94,6 +110,15 @@
any is downloaded. -->
<string name="gamel_menu_checkmoves">Check relay</string>
<!-- Text of progress indicator shown while check is being conducted -->
<string name="msgs_progress">Checking relay for moves
etc...</string>
<!-- If you choose the above option and have no networked games
you get this error message -->
<string name="no_games_to_refresh">No games found that connect via
the relay.</string>
<!-- Deletes all games on the device (after confirmation) -->
<string name="gamel_menu_delete_all">Delete all</string>
@ -131,6 +156,13 @@
<string name="list_item_copy">Copy</string>
<!-- Title of dialog for renaming game (triggered by selecting
list_item_rename) -->
<!-- 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
ready-to-play copy with all the same settings.</string>
<string name="game_rename_title">Rename game</string>
<!-- text within rename dialog (triggered by selecting
list_item_rename) -->
@ -183,6 +215,13 @@
it saves files it downloads. -->
<string name="loc_downloads">Downloads</string>
<!-- If you tap the download_dicts button and Android fails to
find and launch an app that's registered to handle http
downloads a Toast is posted with this message. -->
<string name="no_download_warning">Unable to download. Do you have
a web browser installed?</string>
<!--
############################################################
# :Menus:
@ -331,6 +370,20 @@
<!-- title for popup of public rooms found on server -->
<string name="room_public_prompt">Select public room</string>
<!-- If you check the join_room checkbox Crosswords queries the
relay. This is the text of the progress indicator displayed what
that's going on. (It's often visible for only a very short
time.)-->
<string name="public_names_progress">Fetching public rooms for
%1$d-player games in %2$s.</string>
<!-- If the query returns no rooms, this message is displayed,
with the number of players in the game and its language
substituted. -->
<string name="no_name_found_f">No public rooms found for
%1$d-player games in %2$s. Try refreshing or creating your
own.</string>
<!-- text of separator marking out other-setting area of the dialog -->
<string name="settings_label">Other settings</string>
@ -389,6 +442,9 @@
<!-- title of above confirmation dialog -->
<string name="confirm_save_title">Confirm save</string>
<!-- Text of button at bottom. Press it and you exit this
configure screen and open the game into the Board screen -->
<string name="play">Play game</string>
<!--
############################################################
@ -476,6 +532,10 @@
<string name="button_trade_commit">Commit exchange</string>
<string name="button_trade_cancel">Cancel exchange</string>
<string name="entering_trade">Tap to select tiles...</string>
<!-- Bonus value hint that's displayed in gray text in the colored
bonus square. Double-letter -->
<string name="bonus_l2x_summary">2L</string>
@ -837,7 +897,7 @@
e.g., if the option is "Game Language", "English" in the
listing "Game 2 (English)"
The following strings beginning with "game_summary_field" are
The following strings beginning with "game_summary_field_" are
possible values -->
<string name="summary_field">Include in game listing</string>
@ -1134,7 +1194,7 @@
<string name="invite_htmf">\u003ca href=\"%1$s\"\u003ETap here to
accept\u003c/a\u003E my invitation and join this
game.\u003cbr\u003E \u003ca
href=\"http://eehouse.org/market.php\"\u003E
href=\"http://eehouse.org/market_redir.php\"\u003E
Tap here to install Crosswords\u003c/a\u003E if you haven\'t
already.</string>
@ -1143,7 +1203,7 @@
substituted for "%1$s".-->
<string name="invite_txtf">Accept my invitation and join this
game: %1$s . (But install Crosswords first:
http://eehouse.org/market.php ).</string>
http://eehouse.org/market_redir.php ).</string>
<!-- When I've created the invitation, in text or html, I ask
Android to launch an app that can send it, typically an email
@ -1194,6 +1254,55 @@
transmitted. -->
<string name="chat_menu_clear">Clear history</string>
<!-- ############################################################
# :Screens:
# RelayGameActivity screen
#
# This screen is a simple alternative to the Game Configure
# screen. You'll get it when you choose the list_item_config
# on certain unconfigured simple relay games (currently simple
# means they have 2 players. These days about the only way to
# get this screen is to create a relay game manually and to
# abort after making the room name empty. That is, this is
# left over from an older way of helping people connect, from
# before invitations.
# The dialog has a list of instructions, two text fields for
# room name and local player name, and two buttons.
############################################################
-->
<!-- This is the heading above the list of steps. The default
language is substituted for %s. -->
<string name="relay_game_explainf">To start a basic networked two-player
game in %s:</string>
<!-- These four strings are displayed as step-by-step
instructions-->
<string name="explain_b1">• Agree on a room name with the other
player.</string>
<string name="explain_b2">• Enter the room name in the first box
below. The room names on your two phones must be
identical.</string>
<string name="explain_b3">• Optionally, enter player names in the
second box (one per phone)</string>
<string name="explain_b4">• Press the \"Play game\" button on both
phones to start the game.</string>
<!-- This is the "hint" printed in light text in the empty player
name field -->
<string name="local_name_hint">Player name</string>
<!-- This button takes you to the normal Game Configure screen -->
<string name="advanced_config">Advanced game settings</string>
<!-- If you click on the Play button without having entered a room
name you get an alert with this error message. -->
<string name="no_empty_rooms">This game cannot connect without a
room name.</string>
<!--
error messages
-->
@ -1281,104 +1390,93 @@
<string name="about_web">For a manual or sourcecode see:
http://xwords.sf.net. To report bugs, suggest features, offer to
help, etc., please email: eehouse@eehouse.org.</string>
<!-- fill this in other than in English -->
<string name="xlator"></string>
<string name="about_credits">Toolbar icons by Sarah Chu; other
credits pending permission.</string>
<string name="downloading_dictf">Downloading Crosswords
wordlist %s...</string>
<string name="no_dict_title">Wordlist not found</string>
<string name="button_download">Download</string>
<string name="subst_dict_title">Substitute wordlist (wordcount)</string>
<string name="button_substdict">Substitute</string>
<string name="button_close_game">Close game</string>
<!--
############################################################
# :Dialogs:
# Missing wordlist alert
#
# This alert is displayed when you try to open a game whose
# wordlist cannot be found.
############################################################
-->
<!-- title of alert -->
<string name="no_dict_title">Wordlist not found</string>
<!-- If the wordlist disappears mid-game there are no choices,
just an explanation and this button, after which the game
closes. -->
<string name="no_dict_finish">A wordlist this game is using has
disappeared. (Usually this means it\'s on an external card that
is no longer available.)</string>
<!-- The only button available when the above message is displayed -->
<string name="button_close_game">Close game</string>
<!-- If the missing wordlist is discovered when trying to open the
game, we have more options. If there's another wordlist in
the same language, we can offer to substitute without needing
to download. Otherwise the user must choose between
downloading and not opening the game. This first message
takes wordlist name and language substituted in for %1$ and
%2$ -->
<string name="no_dictf">Unable to open game \"%1$s\" because no
%2$s wordlist found. (It may have been deleted, or stored on
an external card that is no longer available.)</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_substf">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.) You can
download a replacement or substitute another %3$s
wordlist.</string>
<!-- Text of button displayed when downloading is an option -->
<string name="button_download">Download</string>
<!-- Text of button allowing user to choose to open with a
different (but same-language wordlist) -->
<string name="button_substdict">Substitute</string>
<!-- If substituting an existing same-language wordlist by
choosing button_substdict user gets to choose from a list of
wordlists. This is the title of that list. -->
<string name="subst_dict_title">Substitute wordlist (wordcount)</string>
<!--
############################################################
# :Dialogs:
# Password dialog
#
# This alert is displayed when a local player has set a
# password and is trying to see his tiles
############################################################
-->
<!-- Text of dialog. Player name is substituted -->
<string name="msg_ask_password">Password for \"%s\":</string>
<!-- used to create default names of games (when user has not
named them.) -->
<string name="gamef">Game %d</string>
<!-- used to create default player names -->
<!-- used to create default player names. Number between 1 and 4
is substituted -->
<string name="playerf">Player %d</string>
<string name="public_names_progress">Fetching public rooms for
%1$d-player games in %2$s.</string>
<string name="no_name_found_f">No public rooms found for
%1$d-player games in %2$s. Try refreshing or creating your
own.</string>
<!-- When a move is fetched from the relay a Notification is
posted. These are its title, which appears in the top bar of the
device, and the body that appears when you pull the notifications
down. -->
<string name="notify_title">Moves made</string>
<string name="notify_body">New game moves have arrived</string>
<string name="no_copy_network">Games that have already connected
to the relay cannot be copied. Use \"New from\" for a
ready-to-play copy with all the same settings.</string>
<string name="no_games_to_refresh">No games found that connect via
the relay.</string>
<string name="msgs_progress">Checking relay for moves
etc...</string>
<string name="not_again_trading">You are entering tile-exchange
mode. Tap tiles to add/remove them from the set to be
exchanged. Use the buttons to commit your turn or exit exchange
mode.</string>
<string name="entering_trade">Tap to select tiles...</string>
<string name="relay_game_explainf">To start a basic networked two-player
game in %s:</string>
<string name="explain_b1">• Agree on a room name with the other
player.</string>
<string name="explain_b2">• Enter the room name in the first box
below. The room names on your two phones must be
identical.</string>
<string name="explain_b3">• Optionally, enter player names in the
second box (one per phone)</string>
<string name="explain_b4">• Press the \"Play game\" button on both
phones to start the game.</string>
<string name="advanced_config">Advanced game settings</string>
<string name="local_name_hint">Player name</string>
<string name="no_empty_rooms">This game cannot connect without a
room name.</string>
<string name="empty_games_list">Use the button below to create a
game. Tap an existing game to play it or long-tap it for other
options.</string>
<string name="empty_games_list2">You can hide this and the button
below in the Appearance section of Settings (accessed via your
device\'s menu key).</string>
<string name="empty_list_msg">Use the menu key to add a
game.</string>
<string name="no_download_warning">Unable to download. Do you have
a web browser installed?</string>
<!--
############################################################
# Dialogs
@ -1488,6 +1586,12 @@
and sync. (In a later release these moves will be downloaded in
the background.)</string>
<!-- Shown when the user chooses the "board_menu_trade" menu -->
<string name="not_again_trading">You are entering tile-exchange
mode. Tap tiles to add/remove them from the set to be
exchanged. Use the buttons to commit your turn or exit exchange
mode.</string>
<!-- Currently not used -->
<!-- <string name="not_again_newgame">The new game you have created has -->
<!-- two players. Player 1 is a robot; Player 2 is you. Tap the game -->
@ -1631,11 +1735,28 @@
-->
<!-- String giving version info, which is substituted in. -->
<string name="about_versf">Crosswords for Android, Version %1$s,
rev %2$s.</string>
rev %2$s.</string>
<!-- copyright info -->
<string name="about_copyright">Copyright (C) 1998-2011 by Eric
House. This free/open source software is released under the GNU Public
License.</string>
House. This free/open source software is released under the GNU Public
License.</string>
<!-- Another paragraph in the about dialog -->
<string name="about_web">For a manual or sourcecode see:
http://xwords.sf.net. To report bugs, suggest features, offer to
help, etc., please email: eehouse@eehouse.org.</string>
<!-- Empty in English, this should contain the name of the
translator/creator of the strings.xml file for this
language-->
<string name="xlator"></string>
<!-- Another paragraph giving credit for work done other than by
Eric House and translators -->
<string name="about_credits">Toolbar icons by Sarah Chu; other
credits pending permission.</string>
<!-- text of dialog showing the set of changes made since the last
release -->
<string name="changes_title">Recent changes</string>
@ -1643,4 +1764,10 @@
dialog -->
<string name="changes_button">Recent changes</string>
<string name="button_lookup">Lookup word</string>
<string name="title_lookup">Tap to lookup</string>
<string name="button_done">Done</string>
</resources>

View file

@ -22,6 +22,7 @@ package org.eehouse.android.xw4;
import android.app.Activity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
@ -39,15 +40,20 @@ import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import junit.framework.Assert;
import android.content.res.Configuration;
import android.content.pm.ActivityInfo;
import android.net.Uri;
import org.eehouse.android.xw4.jni.*;
import org.eehouse.android.xw4.jni.JNIThread.*;
@ -70,6 +76,8 @@ public class BoardActivity extends XWActivity
private static final int QUERY_ENDGAME = DLG_OKONLY + 7;
private static final int DLG_DELETED = DLG_OKONLY + 8;
private static final int DLG_INVITE = DLG_OKONLY + 9;
private static final int DLG_SCORES_BLK = DLG_OKONLY + 10;
private static final int DLG_WORDPICK = DLG_OKONLY + 11;
private static final int CHAT_REQUEST = 1;
private static final int SCREEN_ON_TIME = 10 * 60 * 1000; // 10 mins
@ -93,6 +101,7 @@ public class BoardActivity extends XWActivity
private static final String DLG_BYTES = "DLG_BYTES";
private static final String ROOM = "ROOM";
private static final String TOASTSTR = "TOASTSTR";
private static final String WORDS = "WORDS";
private BoardView m_view;
private int m_jniGamePtr;
@ -133,6 +142,7 @@ public class BoardActivity extends XWActivity
private String m_room;
private String m_toastStr;
private String[] m_words;
private int m_missing;
private boolean m_haveInvited = false;
@ -208,6 +218,7 @@ public class BoardActivity extends XWActivity
case QUERY_REQUEST_BLK:
case QUERY_INFORM_BLK:
case DLG_SCORES_BLK:
ab = new AlertDialog.Builder( this )
.setMessage( m_dlgBytes );
if ( 0 != m_dlgTitle ) {
@ -230,6 +241,16 @@ public class BoardActivity extends XWActivity
}
};
ab.setNegativeButton( R.string.button_no, lstnr );
} else if ( DLG_SCORES_BLK == id ) {
if ( curLangSupported() ) {
lstnr = new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dialog,
int whichButton ) {
m_jniThread.handle( JNICmd.CMD_WORDS );
}
};
ab.setNegativeButton( R.string.button_lookup, lstnr );
}
}
dialog = ab.create();
@ -300,6 +321,31 @@ public class BoardActivity extends XWActivity
.create();
}
break;
case DLG_WORDPICK:
LinearLayout layout =
(LinearLayout)Utils.inflate( this, R.layout.wordlist_view );
ListView list = (ListView)layout.findViewById( R.id.words );
ArrayAdapter<String> adapter =
new ArrayAdapter<String>( this,
//android.R.layout.select_dialog_item,
android.R.layout.simple_list_item_1,
m_words ) ;
list.setAdapter( adapter );
OnItemClickListener oicl = new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent,
View view,
int position, long id ) {
lookupWord( m_words[position] );
}
};
list.setOnItemClickListener( oicl );
dialog = new AlertDialog.Builder( this )
.setTitle( R.string.title_lookup )
.setView( layout )
.setNegativeButton( R.string.button_done, null )
.create();
Utils.setRemoveOnDismiss( this, dialog, id );
break;
default:
// just drop it; super.onCreateDialog likely failed
break;
@ -387,6 +433,7 @@ public class BoardActivity extends XWActivity
outState.putString( DLG_BYTES, m_dlgBytes );
outState.putString( ROOM, m_room );
outState.putString( TOASTSTR, m_toastStr );
outState.putStringArray( WORDS, m_words );
}
private void getBundledData( Bundle bundle )
@ -397,6 +444,7 @@ public class BoardActivity extends XWActivity
m_dlgBytes = bundle.getString( DLG_BYTES );
m_room = bundle.getString( ROOM );
m_toastStr = bundle.getString( TOASTSTR );
m_words = bundle.getStringArray( WORDS );
}
}
@ -1032,7 +1080,8 @@ public class BoardActivity extends XWActivity
case UtilCtxt.QUERY_ROBOT_TRADE:
m_dlgBytes = query;
m_dlgTitle = R.string.info_title;
waitBlockingDialog( QUERY_INFORM_BLK, 0 );
waitBlockingDialog( QUERY_ROBOT_MOVE == id ?
DLG_SCORES_BLK : QUERY_INFORM_BLK, 0 );
result = true;
break;
@ -1230,6 +1279,17 @@ public class BoardActivity extends XWActivity
adjustTradeVisibility();
}
break;
case JNIThread.GOT_WORDS:
m_words =
TextUtils.split( (String)msg.obj, "\n" );
if ( 0 == m_words.length ) {
// drop it
} else if ( 1 == m_words.length ) {
lookupWord( m_words[0] );
} else {
showDialog( DLG_WORDPICK );
}
break;
}
}
};
@ -1501,4 +1561,40 @@ public class BoardActivity extends XWActivity
which );
}
}
private void lookupWord( String word )
{
String fmt = getString( R.string.word_lookupf );
String dict_url = String.format( fmt, curLangCode(), word );
Uri uri = Uri.parse( dict_url );
Intent intent = new Intent( Intent.ACTION_VIEW, uri );
intent.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK );
try {
startActivity( intent );
} catch ( android.content.ActivityNotFoundException anfe ) {
Utils.logf( "%s", anfe.toString() );
}
}
private String curLangCode()
{
// from string-array name="language_names" in common_rsrc.xml
switch( m_gi.dictLang ) {
case 1:
return "en";
case 2:
return "fr";
case 3:
return "de";
default:
return null;
}
}
private boolean curLangSupported()
{
return null != curLangCode();
}
} // class BoardActivity

View file

@ -55,6 +55,7 @@ public class BoardView extends View implements DrawCtx, BoardHandler,
private Paint m_tileStrokePaint;
private int m_jniGamePtr;
private CurGameInfo m_gi;
private CommonPrefs m_prefs;
private int m_layoutWidth;
private int m_layoutHeight;
private Canvas m_canvas; // owns the bitmap
@ -151,10 +152,10 @@ public class BoardView extends View implements DrawCtx, BoardHandler,
m_boundsScratch = new Rect();
CommonPrefs prefs = CommonPrefs.get(context);
m_playerColors = prefs.playerColors;
m_bonusColors = prefs.bonusColors;
m_otherColors = prefs.otherColors;
m_prefs = CommonPrefs.get(context);
m_playerColors = m_prefs.playerColors;
m_bonusColors = m_prefs.bonusColors;
m_otherColors = m_prefs.otherColors;
m_bonusSummaries = new String[5];
int[] ids = { R.string.bonus_l2x_summary,
@ -427,7 +428,7 @@ public class BoardView extends View implements DrawCtx, BoardHandler,
}
String[] texts = m_scores[dsi.playerNum];
int color = m_playerColors[dsi.playerNum];
if ( !CommonPrefs.get(m_context).allowPeek ) {
if ( !m_prefs.allowPeek ) {
color = adjustColor( color );
}
m_fillPaint.setColor( color );

View file

@ -922,40 +922,40 @@ public class GameConfig extends XWActivity
return 0;
}
private int titleForDlg( int id )
{
switch( id ) {
// case ROLE_EDIT_RELAY:
// return R.string.tab_relay;
// case ROLE_EDIT_SMS:
// return R.string.tab_sms;
// case ROLE_EDIT_BT:
// return R.string.tab_bluetooth;
}
Assert.fail();
return -1;
}
// private int titleForDlg( int id )
// {
// switch( id ) {
// // case ROLE_EDIT_RELAY:
// // return R.string.tab_relay;
// // case ROLE_EDIT_SMS:
// // return R.string.tab_sms;
// // case ROLE_EDIT_BT:
// // return R.string.tab_bluetooth;
// }
// Assert.fail();
// return -1;
// }
private String[] makeXportStrings()
{
ArrayList<String> strings = new ArrayList<String>();
ArrayList<CommsAddrRec.CommsConnType> types
= new ArrayList<CommsAddrRec.CommsConnType>();
// private String[] makeXportStrings()
// {
// ArrayList<String> strings = new ArrayList<String>();
// ArrayList<CommsAddrRec.CommsConnType> types
// = new ArrayList<CommsAddrRec.CommsConnType>();
strings.add( getString(R.string.tab_relay) );
types.add( CommsAddrRec.CommsConnType.COMMS_CONN_RELAY );
// strings.add( getString(R.string.tab_relay) );
// types.add( CommsAddrRec.CommsConnType.COMMS_CONN_RELAY );
if ( m_canDoSMS ) {
strings.add( getString(R.string.tab_sms) );
types.add( CommsAddrRec.CommsConnType.COMMS_CONN_SMS );
}
if ( m_canDoBT ) {
strings.add( getString(R.string.tab_bluetooth) );
types.add( CommsAddrRec.CommsConnType.COMMS_CONN_BT );
}
m_types = types.toArray( new CommsAddrRec.CommsConnType[types.size()] );
return strings.toArray( new String[strings.size()] );
}
// if ( m_canDoSMS ) {
// strings.add( getString(R.string.tab_sms) );
// types.add( CommsAddrRec.CommsConnType.COMMS_CONN_SMS );
// }
// if ( m_canDoBT ) {
// strings.add( getString(R.string.tab_bluetooth) );
// types.add( CommsAddrRec.CommsConnType.COMMS_CONN_BT );
// }
// m_types = types.toArray( new CommsAddrRec.CommsConnType[types.size()] );
// return strings.toArray( new String[strings.size()] );
// }
private void saveChanges()
{

View file

@ -77,6 +77,7 @@ public class JNIThread extends Thread {
CMD_RESEND,
CMD_HISTORY,
CMD_FINAL,
CMD_WORDS,
CMD_ENDGAME,
CMD_POST_OVER,
CMD_SENDCHAT,
@ -88,6 +89,7 @@ public class JNIThread extends Thread {
public static final int DIALOG = 3;
public static final int QUERY_ENDGAME = 4;
public static final int TOOLBAR_STATES = 5;
public static final int GOT_WORDS = 6;
public class GameStateInfo implements Cloneable {
public int visTileCount;
@ -490,6 +492,11 @@ public class JNIThread extends Thread {
}
break;
case CMD_WORDS:
String words = XwJNI.server_listWordsPlayed( m_jniGamePtr, 1 );
Message.obtain( m_handler, GOT_WORDS, words ).sendToTarget();
break;
case CMD_ENDGAME:
XwJNI.server_endGame( m_jniGamePtr );
draw = true;

View file

@ -221,6 +221,8 @@ public class XwJNI {
public static native void server_initClientConnection( int gamePtr );
public static native void server_endGame( int gamePtr );
public static native void server_sendChat( int gamePtr, String msg );
public static native String server_listWordsPlayed( int gamePtr,
int nMoves );
// hybrid to save work
public static native boolean board_server_prefsChanged( int gamePtr,

View file

@ -22,10 +22,9 @@ list_ids() {
list_pairs() {
XML_FILE=$1
#xmlstarlet sel -t -m "//string" -v @name -o ':' -v . -n $XML_FILE | tr -d '\n' | sed 's, *, ,g'
for NAME in $(list_ids $XML_FILE); do
xmlstarlet sel -t -m "//string[@name='$NAME']" -v @name -o ':' -v . $XML_FILE \
| tr -d '\n' | sed 's, *, ,g'
xmlstarlet sel -t -m "//string[@name='$NAME']" -v @name -o ':' \
-v . $XML_FILE | tr -d '\n' | sed 's, *, ,g'
echo ""
done
}

View file

@ -2136,25 +2136,20 @@ send_via_relay( CommsCtxt* comms, XWRELAY_Cmd cmd, XWHostID destID,
XP_U8* buf;
len = stream_getSize( tmpStream );
buf = XP_MALLOC( comms->mpool, len );
if ( buf != NULL ) {
stream_getBytes( tmpStream, buf, len );
}
stream_destroy( tmpStream );
if ( buf != NULL ) {
if ( 0 < len ) {
XP_U16 result;
CommsAddrRec addr;
comms_getAddr( comms, &addr );
XP_LOGF( "%s: passing %d bytes to sendproc", __func__, len );
result = (*comms->procs.send)( buf, len, &addr,
comms->procs.closure );
result = (*comms->procs.send)( stream_getPtr(tmpStream), len,
&addr, comms->procs.closure );
success = result == len;
if ( success ) {
setHeartbeatTimer( comms );
}
}
XP_FREE( comms->mpool, buf );
stream_destroy( tmpStream );
}
return success;
} /* send_via_relay */

View file

@ -301,7 +301,7 @@ mem_stream_copyFromStream( XWStreamCtxt* p_sctx, XWStreamCtxt* src,
if ( nBytes < len ) {
len = nBytes;
}
stream_getBytes( src, buf, len );
stream_getBytes( src, buf, len );// fix to use stream_getPtr()?
stream_putBytes( p_sctx, buf, len );
nBytes -= len;
}
@ -338,6 +338,13 @@ mem_stream_getSize( const XWStreamCtxt* p_sctx )
return size;
} /* mem_stream_getSize */
static const XP_U8*
mem_stream_getPtr( const XWStreamCtxt* p_sctx )
{
MemStreamCtxt* stream = (MemStreamCtxt*)p_sctx;
return stream->buf;
} /* mem_stream_getPtr */
static XP_PlayerAddr
mem_stream_getAddress( XWStreamCtxt* p_sctx )
{
@ -451,6 +458,7 @@ make_vtable( MemStreamCtxt* stream )
SET_VTABLE_ENTRY( vtable, stream_close, mem );
SET_VTABLE_ENTRY( vtable, stream_getSize, mem );
SET_VTABLE_ENTRY( vtable, stream_getPtr, mem );
SET_VTABLE_ENTRY( vtable, stream_getAddress, mem );
SET_VTABLE_ENTRY( vtable, stream_setAddress, mem );

View file

@ -64,12 +64,12 @@ static void makeTileTrade( ModelCtxt* model, XP_S16 player,
TrayTileSet* oldTiles, TrayTileSet* newTiles );
static XP_S16 commitTurn( ModelCtxt* model, XP_S16 turn,
TrayTileSet* newTiles, XWStreamCtxt* stream,
XP_Bool useStack );
WordNotifierInfo* wni, XP_Bool useStack );
static void buildModelFromStack( ModelCtxt* model, StackCtxt* stack,
XWStreamCtxt* stream,
XP_Bool useStack, XP_U16 initial,
XWStreamCtxt* stream, WordNotifierInfo* wni,
MovePrintFuncPre mpfpr,
MovePrintFuncPost mpfpo,
void* closure );
MovePrintFuncPost mpfpo, void* closure );
static void setPendingCounts( ModelCtxt* model, XP_S16 turn );
static void loadPlayerCtxt( XWStreamCtxt* stream, XP_U16 version,
PlayerCtxt* pc );
@ -135,9 +135,9 @@ model_makeFromStream( MPFORMAL XWStreamCtxt* stream, DictionaryCtxt* dict,
stack_loadFromStream( model->vol.stack, stream );
buildModelFromStack( model, model->vol.stack, (XWStreamCtxt*)NULL,
(MovePrintFuncPre)NULL,
(MovePrintFuncPost)NULL, NULL );
buildModelFromStack( model, model->vol.stack, XP_FALSE, 0,
(XWStreamCtxt*)NULL, (WordNotifierInfo*)NULL,
(MovePrintFuncPre)NULL, (MovePrintFuncPost)NULL, NULL );
for ( i = 0; i < model->nPlayers; ++i ) {
loadPlayerCtxt( stream, version, &model->players[i] );
@ -244,19 +244,19 @@ model_destroy( ModelCtxt* model )
} /* model_destroy */
static void
buildModelFromStack( ModelCtxt* model, StackCtxt* stack,
XWStreamCtxt* stream,
MovePrintFuncPre mpf_pre, MovePrintFuncPost mpf_post,
void* closure )
buildModelFromStack( ModelCtxt* model, StackCtxt* stack, XP_Bool useStack,
XP_U16 initial, XWStreamCtxt* stream,
WordNotifierInfo* wni, MovePrintFuncPre mpf_pre,
MovePrintFuncPost mpf_post, void* closure )
{
StackEntry entry;
XP_U16 i;
XP_U16 ii;
XP_S16 moveScore = 0; /* keep compiler happy */
for ( i = 0; stack_getNthEntry( stack, i, &entry ); ++i ) {
for ( ii = initial; stack_getNthEntry( stack, ii, &entry ); ++ii ) {
if ( !!mpf_pre ) {
(*mpf_pre)( model, i, &entry, closure );
(*mpf_pre)( model, ii, &entry, closure );
}
switch ( entry.moveType ) {
@ -265,7 +265,8 @@ buildModelFromStack( ModelCtxt* model, StackCtxt* stack,
model_makeTurnFromMoveInfo( model, entry.playerNum,
&entry.u.move.moveInfo);
moveScore = commitTurn( model, entry.playerNum,
&entry.u.move.newTiles, stream, XP_FALSE);
&entry.u.move.newTiles,
stream, wni, useStack );
break;
case TRADE_TYPE:
makeTileTrade( model, entry.playerNum, &entry.u.trade.oldTiles,
@ -280,7 +281,7 @@ buildModelFromStack( ModelCtxt* model, StackCtxt* stack,
&entry.u.phony.moveInfo);
/* do something here to cause it to print */
(void)getCurrentMoveScoreIfLegal( model, entry.playerNum, stream,
&moveScore );
wni, &moveScore );
moveScore = 0;
model_resetCurrentTurn( model, entry.playerNum );
@ -290,7 +291,7 @@ buildModelFromStack( ModelCtxt* model, StackCtxt* stack,
}
if ( !!mpf_post ) {
(*mpf_post)( model, i, &entry, moveScore, closure );
(*mpf_post)( model, ii, &entry, moveScore, closure );
}
}
} /* buildModelFromStack */
@ -668,10 +669,10 @@ model_undoLatestMoves( ModelCtxt* model, PoolContext* pool,
XP_U16 turn = 0;
Tile blankTile = dict_getBlankTile( model_getDictionary(model) );
XP_Bool success = XP_TRUE;
XP_S16 moveSought = *moveNumP;
XP_S16 moveSought = !!moveNumP ? *moveNumP : -1;
XP_U16 nMovesUndone;
XP_U16 nStackEntries;
nStackEntries = stack_getNEntries( stack );
if ( nStackEntries < nMovesSought ) {
return XP_FALSE;
@ -772,10 +773,16 @@ model_undoLatestMoves( ModelCtxt* model, PoolContext* pool,
}
if ( success ) {
*turnP = turn;
*moveNumP = entry.moveNum;
if ( !!turnP ) {
*turnP = turn;
}
if ( !!moveNumP ) {
*moveNumP = entry.moveNum;
}
} else {
while ( nMovesUndone-- ) {
/* undo isn't enough here: pool's got tiles in it!! */
XP_ASSERT( 0 );
stack_redo( stack );
}
}
@ -873,11 +880,11 @@ model_makeTurnFromStream( ModelCtxt* model, XP_U16 playerNum,
void
model_makeTurnFromMoveInfo( ModelCtxt* model, XP_U16 playerNum,
MoveInfo* newMove )
const MoveInfo* newMove )
{
XP_U16 col, row, i;
XP_U16* other;
MoveInfoTile* tinfo;
const MoveInfoTile* tinfo;
Tile blank;
XP_U16 numTiles;
@ -1389,7 +1396,7 @@ putBackOtherPlayersTiles( ModelCtxt* model, XP_U16 notMyTurn,
*/
static XP_S16
commitTurn( ModelCtxt* model, XP_S16 turn, TrayTileSet* newTiles,
XWStreamCtxt* stream, XP_Bool useStack )
XWStreamCtxt* stream, WordNotifierInfo* wni, XP_Bool useStack )
{
XP_U16 ii;
PlayerCtxt* player;
@ -1403,7 +1410,7 @@ commitTurn( ModelCtxt* model, XP_S16 turn, TrayTileSet* newTiles,
#ifdef DEBUG
XP_ASSERT( getCurrentMoveScoreIfLegal( model, turn, (XWStreamCtxt*)NULL,
&score ) );
(WordNotifierInfo*)NULL, &score ) );
invalidateScore( model, turn );
#endif
@ -1450,7 +1457,7 @@ commitTurn( ModelCtxt* model, XP_S16 turn, TrayTileSet* newTiles,
++model->vol.nTilesOnBoard;
}
(void)getCurrentMoveScoreIfLegal( model, turn, stream, &score );
(void)getCurrentMoveScoreIfLegal( model, turn, stream, wni, &score );
XP_ASSERT( score >= 0 );
player->score += score;
@ -1473,7 +1480,8 @@ commitTurn( ModelCtxt* model, XP_S16 turn, TrayTileSet* newTiles,
void
model_commitTurn( ModelCtxt* model, XP_S16 turn, TrayTileSet* newTiles )
{
(void)commitTurn( model, turn, newTiles, (XWStreamCtxt*)NULL, XP_TRUE );
(void)commitTurn( model, turn, newTiles, (XWStreamCtxt*)NULL,
(WordNotifierInfo*)NULL, XP_TRUE );
} /* model_commitTurn */
/* Given a rack of new tiles and of old, remove all the old from the tray and
@ -1904,8 +1912,8 @@ makeTmpModel( ModelCtxt* model, XWStreamCtxt* stream,
model_numRows(model));
model_setNPlayers( tmpModel, model->nPlayers );
buildModelFromStack( tmpModel, model->vol.stack, stream,
mpf_pre, mpf_post, closure );
buildModelFromStack( tmpModel, model->vol.stack, XP_FALSE, 0, stream,
(WordNotifierInfo*)NULL, mpf_pre, mpf_post, closure );
return tmpModel;
} /* makeTmpModel */
@ -2025,6 +2033,59 @@ model_recentPassCountOk( ModelCtxt* model )
return count < okCount;
}
typedef struct _RecordWordsInfo {
XWStreamCtxt* stream;
XP_U16 nWords;
} RecordWordsInfo;
static XP_Bool
recordWord( const XP_UCHAR* word, XP_Bool isLegal, void* closure )
{
RecordWordsInfo* info = (RecordWordsInfo*)closure;
XWStreamCtxt* stream = info->stream;
XP_ASSERT( isLegal );
XP_LOGF( "%s(%s)", __func__, word );
if ( 0 < info->nWords++ ) {
stream_putU8( stream, '\n' );
}
stream_catString( stream, word );
return XP_TRUE;
}
XP_Bool
model_getWordsPlayed( ModelCtxt* model, PoolContext* pool,
XP_U16 nTurns, XWStreamCtxt* stream )
{
XP_ASSERT( !!stream );
StackCtxt* stack = model->vol.stack;
StackCtxt* tmpStack = stack_copy( stack );
XP_U16 nPlayers = model->nPlayers;
XP_U16 nEntries = stack_getNEntries( stack );
nEntries -= nPlayers; /* skip assignments */
if ( nTurns > nEntries ) {
nTurns = nEntries;
}
if ( model_undoLatestMoves( model, pool, nTurns, NULL, NULL ) ) {
RecordWordsInfo info = { .stream = stream, .nWords = 0 };
WordNotifierInfo notifyInfo = { .proc = recordWord,
.closure = &info,
};
/* Now push the undone moves back into the model one at a time.
recordWord() will add each played word to the stream as it's
scored */
buildModelFromStack( model, tmpStack, XP_TRUE,
nEntries - nTurns + nPlayers,/* skip assignments */
(XWStreamCtxt*)NULL, &notifyInfo,
(MovePrintFuncPre)NULL, (MovePrintFuncPost)NULL,
NULL );
}
stack_destroy( tmpStack );
return XP_TRUE;
}
XP_Bool
model_getPlayersLastScore( ModelCtxt* model, XP_S16 player,
XP_UCHAR* expl, XP_U16* explLen )

View file

@ -197,7 +197,7 @@ void model_currentMoveToStream( ModelCtxt* model, XP_S16 turn,
void model_makeTurnFromStream( ModelCtxt* model, XP_U16 playerNum,
XWStreamCtxt* stream );
void model_makeTurnFromMoveInfo( ModelCtxt* model, XP_U16 playerNum,
MoveInfo* newMove );
const MoveInfo* newMove );
void model_resetCurrentTurn( ModelCtxt* model, XP_S16 turn );
XP_S16 model_getNMoves( const ModelCtxt* model );
@ -246,11 +246,14 @@ typedef struct WordNotifierInfo {
} WordNotifierInfo;
XP_Bool getCurrentMoveScoreIfLegal( ModelCtxt* model, XP_S16 turn,
XWStreamCtxt* stream, XP_S16* score );
XWStreamCtxt* stream,
WordNotifierInfo* wni, XP_S16* score );
XP_S16 model_getPlayerScore( ModelCtxt* model, XP_S16 player );
XP_Bool model_getPlayersLastScore( ModelCtxt* model, XP_S16 player,
XP_UCHAR* expl, XP_U16* explLen );
XP_Bool model_getWordsPlayed( ModelCtxt* model, PoolContext* pool,
XP_U16 nTurns, XWStreamCtxt* stream );
/* Have there been too many passes (so game should end)? */
XP_Bool model_recentPassCountOk( ModelCtxt* model );

View file

@ -108,7 +108,7 @@ stack_loadFromStream( StackCtxt* stack, XWStreamCtxt* stream )
} /* stack_makeFromStream */
void
stack_writeToStream( StackCtxt* stack, XWStreamCtxt* stream )
stack_writeToStream( const StackCtxt* stack, XWStreamCtxt* stream )
{
XP_U16 nBytes;
XWStreamCtxt* data = stack->data;
@ -138,6 +138,21 @@ stack_writeToStream( StackCtxt* stack, XWStreamCtxt* stream )
}
} /* stack_writeToStream */
StackCtxt*
stack_copy( const StackCtxt* stack )
{
StackCtxt* newStack = NULL;
XWStreamCtxt* stream = mem_stream_make( MPPARM(stack->mpool)
stack->vtmgr, NULL, 0, NULL );
stack_writeToStream( stack, stream );
newStack = stack_make( MPPARM(stack->mpool) stack->vtmgr );
stack_loadFromStream( newStack, stream );
stack_setBitsPerTile( newStack, stack->bitsPerTile );
stream_destroy( stream );
return newStack;
}
static void
pushEntry( StackCtxt* stack, const StackEntry* entry )
{

View file

@ -72,7 +72,8 @@ void stack_init( StackCtxt* stack );
void stack_setBitsPerTile( StackCtxt* stack, XP_U16 bitsPerTile );
void stack_loadFromStream( StackCtxt* stack, XWStreamCtxt* stream );
void stack_writeToStream( StackCtxt* stack, XWStreamCtxt* stream );
void stack_writeToStream( const StackCtxt* stack, XWStreamCtxt* stream );
StackCtxt* stack_copy( const StackCtxt* stack );
void stack_addMove( StackCtxt* stack, XP_U16 turn, MoveInfo* moveInfo,
TrayTileSet* newTiles );

View file

@ -75,7 +75,8 @@ static void formatSummary( XWStreamCtxt* stream, const ModelCtxt* model,
* invalidate the score.
*/
static void
scoreCurrentMove( ModelCtxt* model, XP_S16 turn, XWStreamCtxt* stream )
scoreCurrentMove( ModelCtxt* model, XP_S16 turn, XWStreamCtxt* stream,
WordNotifierInfo* notifyInfo )
{
PlayerCtxt* player = &model->players[turn];
XP_S16 score;
@ -84,7 +85,7 @@ scoreCurrentMove( ModelCtxt* model, XP_S16 turn, XWStreamCtxt* stream )
/* recalc goes here */
score = checkScoreMove( model, turn, (EngineCtxt*)NULL, stream,
XP_TRUE, (WordNotifierInfo*)NULL );
XP_TRUE, notifyInfo );
XP_ASSERT( score >= 0 || score == ILLEGAL_MOVE_SCORE );
player->curMoveScore = score;
@ -127,11 +128,12 @@ invalidateScore( ModelCtxt* model, XP_S16 turn )
XP_Bool
getCurrentMoveScoreIfLegal( ModelCtxt* model, XP_S16 turn,
XWStreamCtxt* stream, XP_S16* score )
XWStreamCtxt* stream,
WordNotifierInfo* wni, XP_S16* score )
{
PlayerCtxt* player = &model->players[turn];
if ( !player->curMoveValid ) {
scoreCurrentMove( model, turn, stream );
scoreCurrentMove( model, turn, stream, wni );
}
*score = player->curMoveScore;

View file

@ -841,14 +841,11 @@ showPrevScore( ServerCtxt* server )
if ( !!server->nv.prevMoveStream ) {
XWStreamCtxt* prevStream = server->nv.prevMoveStream;
XP_U16 len = stream_getSize( prevStream );
XP_UCHAR* buf = XP_MALLOC( server->mpool, len );
stream_getBytes( prevStream, buf, len );
stream_destroy( prevStream );
server->nv.prevMoveStream = NULL;
stream_putBytes( stream, buf, len );
XP_FREE( server->mpool, buf );
stream_putBytes( stream, stream_getPtr( prevStream ), len );
stream_destroy( prevStream );
}
(void)util_userQuery( util, QUERY_ROBOT_MOVE, stream );
@ -2640,6 +2637,12 @@ server_formatRemainingTiles( ServerCtxt* server, XWStreamCtxt* stream,
}
} /* server_formatRemainingTiles */
void
server_listWordsPlayed( ServerCtxt* server, XWStreamCtxt* stream, XP_U16 nMoves )
{
(void)model_getWordsPlayed( server->vol.model, server->pool, nMoves, stream );
}
#define IMPOSSIBLY_LOW_SCORE -1000
void
server_writeFinalScores( ServerCtxt* server, XWStreamCtxt* stream )

View file

@ -124,6 +124,9 @@ void server_formatDictCounts( ServerCtxt* server, XWStreamCtxt* stream,
void server_formatRemainingTiles( ServerCtxt* server, XWStreamCtxt* stream,
XP_S16 player );
void server_listWordsPlayed( ServerCtxt* server, XWStreamCtxt* stream,
XP_U16 nMoves );
void server_writeFinalScores( ServerCtxt* server, XWStreamCtxt* stream );
#ifdef CPLUS

View file

@ -314,7 +314,9 @@ drawPendingScore( BoardCtxt* board, XP_Bool hasCursor )
XP_Rect lastTileR;
(void)getCurrentMoveScoreIfLegal( board->model, selPlayer,
(XWStreamCtxt*)NULL, &turnScore );
(XWStreamCtxt*)NULL,
(WordNotifierInfo*)NULL,
&turnScore );
figureTrayTileRect( board, MAX_TRAY_TILES-1, &lastTileR );
draw_score_pendingScore( board->draw, &lastTileR, turnScore,
selPlayer,

View file

@ -69,6 +69,8 @@ typedef struct StreamCtxVTable {
void (*m_stream_close)( XWStreamCtxt* dctx );
XP_U16 (*m_stream_getSize)( const XWStreamCtxt* dctx );
const XP_U8* (*m_stream_getPtr)( const XWStreamCtxt* dctx );
/* void (*m_stream_makeReturnAddr)( XWStreamCtxt* dctx, XP_PlayerAddr* addr, */
/* XP_U16* addrLen ); */
@ -143,6 +145,9 @@ struct XWStreamCtxt {
#define stream_getSize(sc) \
(sc)->vtable->m_stream_getSize((sc))
#define stream_getPtr(sc) \
(sc)->vtable->m_stream_getPtr((sc))
#define stream_makeReturnAddr(sc,addr,len) \
(sc)->vtable->m_stream_makeReturnAddr((sc),(addr),(len))

View file

@ -33,7 +33,7 @@ endif
# CC = llvm-gcc
DO_CURSES = -DPLATFORM_NCURSES
# DO_CURSES += -DUSE_GLIBLOOP
DO_CURSES += -DUSE_GLIBLOOP
ifdef CURSES_SMALL_SCREEN
DO_CURSES += -DCURSES_SMALL_SCREEN
endif

View file

@ -373,21 +373,37 @@ curses_util_engineProgressCallback( XW_UtilCtxt* XP_UNUSED(uc) )
return XP_TRUE;
} /* curses_util_engineProgressCallback */
#ifdef USE_GLIBLOOP
static gboolean
timerFired( gpointer data )
{
TimerInfo* ti = (TimerInfo*)data;
CommonGlobals* globals = ti->globals;
XWTimerReason why = ti - globals->timerInfo;
if ( linuxFireTimer( globals, why ) ) {
board_draw( globals->game.board );
}
return FALSE;
}
#endif
static void
curses_util_setTimer( XW_UtilCtxt* uc, XWTimerReason why, XP_U16 when,
XWTimerProc proc, void* closure )
{
CursesAppGlobals* globals = (CursesAppGlobals*)uc->closure;
XP_U32 nextTimer;
TimerInfo* ti = &globals->cGlobals.timerInfo[why];
globals->cGlobals.timerInfo[why].proc = proc;
globals->cGlobals.timerInfo[why].closure = closure;
ti->proc = proc;
ti->closure = closure;
nextTimer = util_getCurSeconds(uc) + when;
globals->cGlobals.timerInfo[why].when = nextTimer;
if ( globals->nextTimer > nextTimer ) {
globals->nextTimer = nextTimer;
}
#ifdef USE_GLIBLOOP
ti->globals = &globals->cGlobals;
(void)g_timeout_add_seconds( when, timerFired, ti );
#else
ti->when = util_getCurSeconds(uc) + when;
#endif
} /* curses_util_setTimer */
static void
@ -898,7 +914,7 @@ cursesListenOnSocket( CursesAppGlobals* globals, int newSock
{
#ifdef USE_GLIBLOOP
GIOChannel* channel = g_io_channel_unix_new( newSock );
guint watch = g_io_add_watch( channel, G_IO_IN | G_IO_OUT |G_IO_ERR,
guint watch = g_io_add_watch( channel, G_IO_IN | G_IO_ERR,
func, globals );
SourceData* data = g_malloc( sizeof(*data) );
@ -1649,9 +1665,7 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
#endif
#ifdef USE_GLIBLOOP
if ( params->quitAfter >= 0 ) {
cursesListenOnSocket( &g_globals, 0, handle_stdin ); /* stdin */
}
cursesListenOnSocket( &g_globals, 0, handle_stdin );
#else
cursesListenOnSocket( &g_globals, 0 ); /* stdin */

View file

@ -92,8 +92,6 @@ struct CursesAppGlobals {
struct pollfd fdArray[FD_MAX]; /* one for stdio, one for listening socket */
int timepipe[2]; /* for reading/writing "user events" */
#endif
XP_U32 nextTimer;
};
#ifdef USE_GLIBLOOP

View file

@ -1709,6 +1709,15 @@ gtk_util_playerScoreHeld( XW_UtilCtxt* uc, XP_U16 player )
GtkAppGlobals* globals = (GtkAppGlobals*)uc->closure;
#if 1
XP_USE( player );
XWStreamCtxt* stream =
mem_stream_make( MEMPOOL globals->cGlobals.params->vtMgr, globals,
CHANNEL_NONE, catOnClose );
server_listWordsPlayed( globals->cGlobals.game.server, stream, 1000 );
stream_destroy( stream );
#else
XP_UCHAR scoreExpl[48];
XP_U16 explLen = sizeof(scoreExpl);
@ -1716,6 +1725,7 @@ gtk_util_playerScoreHeld( XW_UtilCtxt* uc, XP_U16 player )
player, scoreExpl, &explLen ) ) {
XP_LOGF( "got: %s", scoreExpl );
}
#endif
}
#endif

View file

@ -138,7 +138,11 @@ typedef struct LinSMSData LinSMSData;
typedef struct _TimerInfo {
XWTimerProc proc;
void* closure;
#ifdef USE_GLIBLOOP
struct CommonGlobals* globals;
#else
XP_U32 when; /* used only for ncurses */
#endif
} TimerInfo;
struct CommonGlobals {