Merge branch 'android_branch' into french_xlation

Conflicts:
	xwords4/android/XWords4/res/values/strings.xml
This commit is contained in:
Andy2 2011-08-31 06:46:02 -07:00
commit cdf526c95d
28 changed files with 764 additions and 169 deletions

View file

@ -402,6 +402,7 @@ and_draw_dictChanged( DrawCtx* dctx, XP_S16 playerNum,
}
}
#ifdef XWFEATURE_MINIWIN
static const XP_UCHAR*
and_draw_getMiniWText( DrawCtx* dctx, XWMiniTextType textHint )
{
@ -448,6 +449,7 @@ and_draw_drawMiniWindow( DrawCtx* dctx, const XP_UCHAR* text,
(*env)->DeleteLocalRef( env, jstr );
}
#endif
static XP_Bool
draw_doNothing( DrawCtx* dctx, ... )
@ -496,9 +498,11 @@ makeDraw( MPFORMAL JNIEnv** envp, jobject jdraw )
SET_PROC(objFinished);
SET_PROC(dictChanged);
#ifdef XWFEATURE_MINIWIN
SET_PROC(getMiniWText);
SET_PROC(measureMiniWText);
SET_PROC(drawMiniWindow);
#endif
#undef SET_PROC
return (DrawCtx*)draw;

View file

@ -389,6 +389,34 @@ and_util_setIsServer(XW_UtilCtxt* uc, XP_Bool isServer )
UTIL_CBK_TAIL();
}
#ifndef XWFEATURE_MINIWIN
static void
and_util_setInTrade( XW_UtilCtxt* uc, XP_U16 turn, XP_Bool entering )
{
UTIL_CBK_HEADER("setInTrade", "(IZ)V" );
(*env)->CallVoidMethod( env, util->jutil, mid, turn, entering );
UTIL_CBK_TAIL();
}
static void
and_util_bonusSquareHeld( XW_UtilCtxt* uc, XWBonusType bonus )
{
UTIL_CBK_HEADER( "bonusSquareHeld", "(I)V" );
(*env)->CallVoidMethod( env, util->jutil, mid, bonus );
UTIL_CBK_TAIL();
}
static void
and_util_playerScoreHeld( XW_UtilCtxt* uc, const XP_UCHAR* txt )
{
UTIL_CBK_HEADER( "playerScoreHeld", "(Ljava/lang/String;)V" );
jstring jmsg = (*env)->NewStringUTF( env, txt );
(*env)->CallVoidMethod( env, util->jutil, mid, jmsg );
(*env)->DeleteLocalRef( env, jmsg );
UTIL_CBK_TAIL();
}
#endif
#ifndef XWFEATURE_STANDALONE_ONLY
static void
and_util_addrChange( XW_UtilCtxt* uc, const CommsAddrRec* oldAddr,
@ -473,6 +501,12 @@ makeUtil( MPFORMAL JNIEnv** envp, jobject jutil, CurGameInfo* gi,
SET_PROC(remSelected);
SET_PROC(setIsServer);
#ifndef XWFEATURE_MINIWIN
SET_PROC(setInTrade);
SET_PROC(bonusSquareHeld);
SET_PROC(playerScoreHeld);
#endif
#ifndef XWFEATURE_STANDALONE_ONLY
SET_PROC(addrChange);
#endif

View file

@ -16,6 +16,25 @@
android:longClickable="true"
android:drawSelectorOnTop="false"/>
<LinearLayout android:id="@+id/exchange_buttons"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<Button android:id="@+id/exchange_commit"
android:layout_width="fill_parent"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/button_trade_commit"
/>
<Button android:id="@+id/exchange_cancel"
android:layout_width="fill_parent"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/button_trade_cancel"
/>
</LinearLayout>
<LinearLayout android:id="@+id/toolbar_horizontal"
android:orientation="horizontal"
android:layout_width="fill_parent"

View file

@ -13,15 +13,6 @@
/>
</group>
<group android:id="@+id/group_intrade">
<item android:id="@+id/board_menu_trade_commit"
android:title="@string/board_menu_trade_commit"
/>
<item android:id="@+id/board_menu_trade_cancel"
android:title="@string/board_menu_trade_cancel"
/>
</group>
<item android:id="@+id/board_menu_undo_last"
android:title="@string/board_menu_undo_last"
android:alphabeticShortcut="U"

View file

@ -73,6 +73,7 @@
<string name="key_notagain_arrow">key_notagain_arrow</string>
<string name="key_notagain_turnchanged">key_notagain_turnchanged</string>
<string name="key_notagain_newfrom">key_notagain_newfrom</string>
<string name="key_notagain_trading">key_notagain_trading</string>
<!-- other -->
<string name="default_host">eehouse.org</string>

View file

@ -413,6 +413,12 @@
# played etc., is displayed here)
############################################################
-->
<!-- Buttons shown at bottom when board is in exchange mode,
i.e. after user has picked board_menu_trade menu item -->
<string name="button_trade_commit">Commit exchange</string>
<string name="button_trade_cancel">Cancel exchange</string>
<!-- Bonus value hint that's displayed in gray text in the colored
bonus square. Double-letter -->
<string name="bonus_l2x_summary">2L</string>
@ -1364,6 +1370,14 @@
using all the settings from this one. That is, treat this game
as a template.</string>
<string name="not_again_trading">You are entering tile-exchange
mode. Tap tiles to add/remove from the set to be exchanged, and
use the menu to commit your turn or exit exchange mode.</string>
<string name="entering_trade">Entering trade mode; use menu to
exit</string>
<string name="exiting_trade">Exiting trade mode</string>
<string name="relay_game_explainf">To start a basic networked two-player
game in %s:</string>

View file

@ -39,6 +39,7 @@ import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.EditText;
@ -54,7 +55,7 @@ import org.eehouse.android.xw4.jni.CurGameInfo.DeviceRole;
public class BoardActivity extends XWActivity
implements TransportProcs.TPMsgHandler {
implements TransportProcs.TPMsgHandler, View.OnClickListener {
public static final String INTENT_KEY_ROWID = "rowid";
public static final String INTENT_KEY_CHAT = "chat";
@ -85,6 +86,7 @@ public class BoardActivity extends XWActivity
private static final int ZOOM_ACTION = 10;
private static final int UNDO_ACTION = 11;
private static final int CHAT_ACTION = 12;
private static final int START_TRADE_ACTION = 13;
private static final String DLG_TITLE = "DLG_TITLE";
private static final String DLG_TITLESTR = "DLG_TITLESTR";
@ -102,6 +104,10 @@ public class BoardActivity extends XWActivity
private Runnable m_screenTimer;
private long m_rowid;
private Toolbar m_toolbar;
private View m_tradeButtons;
private Button m_exchCommmitButton;
private Button m_exchCancelButton;
private ArrayList<String> m_pendingChats = new ArrayList<String>();
private String m_dlgBytes = null;
@ -113,6 +119,7 @@ public class BoardActivity extends XWActivity
private boolean m_firingPrefs;
private JNIUtils m_jniu;
private boolean m_volKeysZoom;
private boolean m_inTrade; // save this in bundle?
private BoardUtilCtxt m_utils;
// call startActivityForResult synchronously
@ -338,6 +345,11 @@ public class BoardActivity extends XWActivity
m_gi = new CurGameInfo( this );
m_view = (BoardView)findViewById( R.id.board_view );
m_tradeButtons = findViewById( R.id.exchange_buttons );
m_exchCommmitButton = (Button)findViewById( R.id.exchange_commit );
m_exchCommmitButton.setOnClickListener( this );
m_exchCancelButton = (Button)findViewById( R.id.exchange_cancel );
m_exchCancelButton.setOnClickListener( this );
m_volKeysZoom = CommonPrefs.getVolKeysZoom( this );
Intent intent = getIntent();
@ -479,7 +491,6 @@ public class BoardActivity extends XWActivity
if ( null != m_gsi ) {
boolean inTrade = m_gsi.inTrade;
menu.setGroupVisible( R.id.group_intrade, inTrade ) ;
menu.setGroupVisible( R.id.group_done, !inTrade );
}
@ -507,12 +518,6 @@ public class BoardActivity extends XWActivity
case R.id.board_menu_trade:
cmd = JNIThread.JNICmd.CMD_TRADE;
break;
case R.id.board_menu_trade_commit:
cmd = JNIThread.JNICmd.CMD_COMMIT;
break;
case R.id.board_menu_trade_cancel:
cmd = JNIThread.JNICmd.CMD_CANCELTRADE;
break;
case R.id.board_menu_tray:
cmd = JNIThread.JNICmd.CMD_TOGGLE_TRAY;
@ -625,6 +630,14 @@ public class BoardActivity extends XWActivity
break;
case CHAT_ACTION:
startChatActivity();
break;
case START_TRADE_ACTION:
m_view.setInTrade( m_inTrade );
Toast.makeText( this, getString( m_inTrade?
R.string.entering_trade
: R.string.exiting_trade),
Toast.LENGTH_SHORT).show();
break;
default:
Assert.fail();
@ -632,6 +645,19 @@ public class BoardActivity extends XWActivity
}
}
//////////////////////////////////////////////////
// View.OnClickListener interface
//////////////////////////////////////////////////
@Override
public void onClick( View view )
{
if ( view == m_exchCommmitButton ) {
m_jniThread.handle( JNIThread.JNICmd.CMD_COMMIT );
} else if ( view == m_exchCancelButton ) {
m_jniThread.handle( JNIThread.JNICmd.CMD_CANCELTRADE );
}
}
//////////////////////////////////////////////////
// TransportProcs.TPMsgHandler interface
//////////////////////////////////////////////////
@ -855,7 +881,6 @@ public class BoardActivity extends XWActivity
public void setIsServer( boolean isServer )
{
Utils.logf( "setIsServer(%b)", isServer );
DeviceRole newRole = isServer? DeviceRole.SERVER_ISSERVER
: DeviceRole.SERVER_ISCLIENT;
if ( newRole != m_gi.serverRole ) {
@ -868,6 +893,70 @@ public class BoardActivity extends XWActivity
}
}
@Override
public void setInTrade( int turn, final boolean entering )
{
if ( m_inTrade != entering ) {
m_inTrade = entering;
post( new Runnable() {
public void run() {
adjustTradeVisibility();
if ( m_inTrade ) {
showNotAgainDlgThen( R.string.not_again_trading,
R.string.key_notagain_trading,
START_TRADE_ACTION );
} else {
dlgButtonClicked( START_TRADE_ACTION,
AlertDialog.BUTTON_POSITIVE );
}
}
} );
}
}
@Override
public void bonusSquareHeld( int bonus )
{
int id = 0;
switch( bonus ) {
case BONUS_DOUBLE_LETTER:
id = R.string.bonus_l2x;
break;
case BONUS_DOUBLE_WORD:
id = R.string.bonus_w2x;
break;
case BONUS_TRIPLE_LETTER:
id = R.string.bonus_l3x;
break;
case BONUS_TRIPLE_WORD:
id = R.string.bonus_w3x;
break;
default:
Assert.fail();
}
if ( 0 != id ) {
final String bonusStr = getString( id );
post( new Runnable() {
public void run() {
Toast.makeText( BoardActivity.this, bonusStr,
Toast.LENGTH_SHORT).show();
}
} );
}
}
@Override
public void playerScoreHeld( final String text )
{
post( new Runnable() {
public void run() {
Toast.makeText( BoardActivity.this, text,
Toast.LENGTH_SHORT).show();
}
} );
}
public void setTimer( int why, int when, int handle )
{
if ( null != m_timers[why] ) {
@ -1169,9 +1258,10 @@ public class BoardActivity extends XWActivity
if ( !CommonPrefs.getHideTitleBar( this ) ) {
setTitle( GameUtils.getName( this, m_rowid ) );
}
m_toolbar = new Toolbar( this );
m_toolbar = new Toolbar( this, R.id.toolbar_horizontal );
populateToolbar();
adjustTradeVisibility();
int flags = DBUtils.getMsgFlags( this, m_rowid );
if ( 0 != (GameSummary.MSG_FLAGS_CHAT & flags) ) {
@ -1353,6 +1443,12 @@ public class BoardActivity extends XWActivity
m_toolbar.update( Toolbar.BUTTON_CHAT, m_gsi.gameIsConnected );
}
private void adjustTradeVisibility()
{
m_toolbar.setVisibility( m_inTrade? View.GONE : View.VISIBLE );
m_tradeButtons.setVisibility( m_inTrade? View.VISIBLE : View.GONE );
}
private void setBackgroundColor()
{
int back = CommonPrefs.get(this)

View file

@ -41,9 +41,6 @@ import junit.framework.Assert;
public class BoardView extends View implements DrawCtx, BoardHandler,
SyncedDraw {
private static final int k_miniTextSize = 24;
private static final int k_miniPaddingH = 2;
private static final int k_miniPaddingV = 2;
private static final float MIN_FONT_DIPS = 14.0f;
private static Bitmap s_bitmap; // the board
@ -66,6 +63,7 @@ public class BoardView extends View implements DrawCtx, BoardHandler,
private Drawable m_rightArrow;
private Drawable m_downArrow;
private boolean m_blackArrow;
private boolean m_inTrade = false;
// m_backgroundUsed: alpha not set ensures inequality
private int m_backgroundUsed = 0x00000000;
private boolean m_darkOnLight;
@ -330,6 +328,12 @@ public class BoardView extends View implements DrawCtx, BoardHandler,
}
}
public void setInTrade( boolean inTrade )
{
m_inTrade = inTrade;
m_jniThread.handle( JNIThread.JNICmd.CMD_INVALALL );
}
// DrawCtxt interface implementation
public boolean scoreBegin( Rect rect, int numPlayers, int[] scores,
int remCount, int dfs )
@ -369,7 +373,7 @@ public class BoardView extends View implements DrawCtx, BoardHandler,
: CommonPrefs.COLOR_TILE_BACK;
fillRectOther( rOuter, indx );
m_fillPaint.setColor( BLACK );
m_fillPaint.setColor( adjustColor(BLACK) );
drawCentered( m_remText, rInner, null );
}
@ -421,7 +425,7 @@ public class BoardView extends View implements DrawCtx, BoardHandler,
fillRectOther( rOuter, CommonPrefs.COLOR_FOCUS );
}
String[] texts = m_scores[dsi.playerNum];
m_fillPaint.setColor( m_playerColors[dsi.playerNum] );
m_fillPaint.setColor( adjustColor(m_playerColors[dsi.playerNum]) );
Rect rect = new Rect( rOuter );
int height = rect.height() / texts.length;
@ -445,7 +449,7 @@ public class BoardView extends View implements DrawCtx, BoardHandler,
secondsLeft%60 );
fillRectOther( rect, CommonPrefs.COLOR_BACKGRND );
m_fillPaint.setColor( m_playerColors[player] );
m_fillPaint.setColor( adjustColor(m_playerColors[player]) );
Rect shorter = new Rect( rect );
shorter.inset( 0, shorter.height() / 5 );
@ -471,6 +475,9 @@ public class BoardView extends View implements DrawCtx, BoardHandler,
boolean pending = 0 != (flags & CELL_HIGHLIGHT);
String bonusStr = null;
if ( m_inTrade ) {
fillRectOther( rect, CommonPrefs.COLOR_BACKGRND );
}
if ( owner < 0 ) {
owner = 0;
@ -498,21 +505,21 @@ public class BoardView extends View implements DrawCtx, BoardHandler,
backColor = m_otherColors[CommonPrefs.COLOR_TILE_BACK];
}
fillRect( rect, backColor );
fillRect( rect, adjustColor( backColor ) );
if ( empty ) {
if ( (CELL_ISSTAR & flags) != 0 ) {
m_origin.setBounds( rect );
m_origin.draw( m_canvas );
} else if ( null != bonusStr ) {
m_fillPaint.
setColor( m_otherColors[CommonPrefs.COLOR_BONUSHINT] );
int color = m_otherColors[CommonPrefs.COLOR_BONUSHINT];
m_fillPaint.setColor( adjustColor(color) );
Rect brect = new Rect( rect );
brect.inset( 0, brect.height()/10 );
drawCentered( bonusStr, brect, m_fontDims );
}
} else {
m_fillPaint.setColor( foreColor );
m_fillPaint.setColor( adjustColor(foreColor) );
drawCentered( text, rect, m_fontDims );
}
@ -521,7 +528,7 @@ public class BoardView extends View implements DrawCtx, BoardHandler,
}
// frame the cell
m_strokePaint.setColor( FRAME_GREY );
m_strokePaint.setColor( adjustColor(FRAME_GREY) );
m_canvas.drawRect( rect, m_strokePaint );
drawCrosshairs( rect, flags );
@ -624,84 +631,6 @@ public class BoardView extends View implements DrawCtx, BoardHandler,
drawCentered( getResources().getString( R.string.pts ), rect, null );
}
public String getMiniWText ( int textHint )
{
int id = 0;
switch( textHint ) {
case BONUS_DOUBLE_LETTER:
id = R.string.bonus_l2x;
break;
case BONUS_DOUBLE_WORD:
id = R.string.bonus_w2x;
break;
case BONUS_TRIPLE_LETTER:
id = R.string.bonus_l3x;
break;
case BONUS_TRIPLE_WORD:
id = R.string.bonus_w3x;
break;
case INTRADE_MW_TEXT:
id = R.string.trading_text;
break;
default:
Assert.fail();
}
return getResources().getString( id );
}
public void measureMiniWText( String str, int[] width, int[] height )
{
m_fillPaint.setTextSize( k_miniTextSize );
FontMetricsInt fmi = m_fillPaint.getFontMetricsInt();
int lineHeight = -fmi.top + fmi.leading;
String[] lines = str.split("\n");
height[0] = (lines.length * lineHeight) + (2 * k_miniPaddingV);
int maxWidth = 0;
for ( String line : lines ) {
m_fillPaint.getTextBounds( line, 0, line.length(), m_boundsScratch );
int thisWidth = m_boundsScratch.width();
if ( maxWidth < thisWidth ) {
maxWidth = thisWidth;
}
}
width[0] = maxWidth + (k_miniPaddingH * 2);
}
public void drawMiniWindow( String text, Rect rect )
{
fillRect( rect, darkOnLight()? BLACK : WHITE );
m_fillPaint.setTextSize( k_miniTextSize );
m_fillPaint.setTextAlign( Paint.Align.CENTER );
m_fillPaint.setColor( darkOnLight()? WHITE : BLACK );
String[] lines = text.split("\n");
int lineHt = rect.height() / lines.length;
int bottom = rect.top + lineHt
- m_fillPaint.getFontMetricsInt().descent;
int center = rect.left + (rect.width() / 2);
for ( String line : lines ) {
m_canvas.drawText( line, center, bottom, m_fillPaint );
bottom += lineHt;
}
m_canvas.drawRect( rect, m_strokePaint );
// Unlike other draw methods, this one is usually called from
// outside board_draw and so doesn't benefit from the canvas
// getting moved to the board. Set that up manually. Sending
// DRAW cmd as I used to do draws *everything* and may well
// overwrite the miniwindow.
m_viewHandler.post( new Runnable() {
public void run() {
BoardView.this.invalidate();
}
} );
}
public void objFinished( /*BoardObjectType*/int typ, Rect rect, int dfs )
{
if ( DrawCtx.OBJ_SCORE == typ ) {
@ -993,4 +922,12 @@ public class BoardView extends View implements DrawCtx, BoardHandler,
}
return arrow;
}
private int adjustColor( int color )
{
if ( m_inTrade ) {
color = color & 0x3FFFFFFF;
}
return color;
}
}

View file

@ -65,6 +65,7 @@ public class Toolbar {
};
private XWActivity m_activity;
private View m_me;
private enum ORIENTATION { ORIENT_UNKNOWN,
ORIENT_PORTRAIT,
@ -72,9 +73,15 @@ public class Toolbar {
};
private ORIENTATION m_curOrient = ORIENTATION.ORIENT_UNKNOWN;
public Toolbar( XWActivity activity )
public Toolbar( XWActivity activity, int id )
{
m_activity = activity;
m_me = activity.findViewById( id );
}
public void setVisibility( int vis )
{
m_me.setVisibility( vis );
}
public void setListener( int index, View.OnClickListener listener )

View file

@ -71,9 +71,6 @@ public interface DrawCtx {
public static final int BONUS_TRIPLE_LETTER = 3;
public static final int BONUS_TRIPLE_WORD = 4;
public static final int INTRADE_MW_TEXT = 5;
String getMiniWText ( int textHint );
void measureMiniWText( String text, int[] width, int[] height );
void drawMiniWindow( String text, Rect rect );
void objFinished( /*BoardObjectType*/int typ, Rect rect, int dfs );

View file

@ -42,6 +42,7 @@ public class JNIThread extends Thread {
public enum JNICmd { CMD_NONE,
CMD_DRAW,
CMD_INVALALL,
CMD_LAYOUT,
CMD_START,
CMD_SWITCHCLIENT,
@ -307,6 +308,11 @@ public class JNIThread extends Thread {
draw = true;
break;
case CMD_INVALALL:
XwJNI.board_invalAll( m_jniGamePtr );
draw = true;
break;
case CMD_LAYOUT:
doLayout( (BoardDims)args[0] );
draw = true;

View file

@ -47,6 +47,10 @@ public interface UtilCtxt {
void remSelected();
void setIsServer( boolean isServer );
void setInTrade( int turn, boolean entering );
void bonusSquareHeld( int bonus );
void playerScoreHeld( String text );
static final int STRD_ROBOT_TRADED = 1;
static final int STR_ROBOT_MOVED = 2;
static final int STRS_VALUES_HEADER = 3;

View file

@ -83,6 +83,18 @@ public class UtilCtxtImpl implements UtilCtxt {
subclassOverride( "setIsServer" );
}
public void setInTrade( int turn, boolean entering )
{
}
public void bonusSquareHeld( int bonus )
{
}
public void playerScoreHeld( String text )
{
}
public String getUserString( int stringCode )
{
int id = 0;

View file

@ -95,7 +95,11 @@ static void setArrowFor( BoardCtxt* board, XP_U16 player, XP_U16 col,
XP_U16 row );
static XP_Bool setArrowVisible( BoardCtxt* board, XP_Bool visible );
#ifdef XWFEATURE_MINIWIN
static void invalTradeWindow( BoardCtxt* board, XP_S16 turn, XP_Bool redraw );
#else
# define invalTradeWindow(b,t,r)
#endif
static XP_Bool invalCellsWithTiles( BoardCtxt* board );
static void setTimerIf( BoardCtxt* board );
@ -197,13 +201,23 @@ board_destroy( BoardCtxt* board )
XP_FREE( board->mpool, board );
} /* board_destroy */
static void
setTradeInProgress( BoardCtxt* board, XP_U16 turn, XP_Bool inProgress )
{
PerTurnInfo* pti = &board->pti[turn];
pti->tradeInProgress = inProgress;
#ifndef XWFEATURE_MINIWIN
util_setInTrade( board->util, turn, inProgress );
#endif
}
BoardCtxt*
board_makeFromStream( MPFORMAL XWStreamCtxt* stream, ModelCtxt* model,
ServerCtxt* server, DrawCtx* draw, XW_UtilCtxt* util,
XP_U16 nPlayers )
{
BoardCtxt* board;
XP_U16 i;
XP_U16 ii;
XP_U16 version = stream_getVersion( stream );
board = board_make( MPPARM(mpool) model, server, draw, util );
@ -233,8 +247,8 @@ board_makeFromStream( MPFORMAL XWStreamCtxt* stream, ModelCtxt* model,
XP_ASSERT( !!server );
for ( i = 0; i < nPlayers; ++i ) {
PerTurnInfo* pti = &board->pti[i];
for ( ii = 0; ii < nPlayers; ++ii ) {
PerTurnInfo* pti = &board->pti[ii];
BoardArrow* arrow = &pti->boardArrow;
arrow->col = (XP_U8)stream_getBits( stream, NUMCOLS_NBITS );
arrow->row = (XP_U8)stream_getBits( stream, NUMCOLS_NBITS );
@ -244,7 +258,7 @@ board_makeFromStream( MPFORMAL XWStreamCtxt* stream, ModelCtxt* model,
pti->dividerLoc = (XP_U8)stream_getBits( stream, NTILES_NBITS );
pti->traySelBits = (TileBit)stream_getBits( stream,
MAX_TRAY_TILES );
pti->tradeInProgress = (XP_Bool)stream_getBits( stream, 1 );
setTradeInProgress( board, ii, (XP_Bool)stream_getBits( stream, 1 ) );
if ( version >= STREAM_VERS_KEYNAV ) {
#ifdef KEYBOARD_NAV
@ -345,16 +359,16 @@ board_writeToStream( BoardCtxt* board, XWStreamCtxt* stream )
void
board_reset( BoardCtxt* board )
{
XP_U16 i;
XP_U16 ii;
XW_TrayVisState newState;
XP_ASSERT( !!board->model );
/* This is appropriate for a new game *ONLY*. reset */
for ( i = 0; i < MAX_NUM_PLAYERS; ++i ) {
PerTurnInfo* pti = &board->pti[i];
for ( ii = 0; ii < MAX_NUM_PLAYERS; ++ii ) {
PerTurnInfo* pti = &board->pti[ii];
pti->traySelBits = 0;
pti->tradeInProgress = XP_FALSE;
setTradeInProgress( board, ii, XP_FALSE );
pti->dividerLoc = 0;
XP_MEMSET( &pti->boardArrow, 0, sizeof(pti->boardArrow) );
}
@ -678,6 +692,7 @@ invalCursorCell( BoardCtxt* board )
} /* invalCursorCell */
#endif
#ifdef XWFEATURE_MINIWIN
static void
invalTradeWindow( BoardCtxt* board, XP_S16 turn, XP_Bool redraw )
{
@ -712,6 +727,7 @@ hideMiniWindow( BoardCtxt* board, XP_Bool destroy, MiniWindowType winType )
}
} /* hideMiniWindow */
#endif
#endif
static XP_Bool
warnBadWords( XP_UCHAR* word, void* closure )
@ -850,7 +866,7 @@ selectPlayerImpl( BoardCtxt* board, XP_U16 newPlayer, XP_Bool reveal,
there were plenty of tiles but now there aren't. */
if ( newInfo->tradeInProgress &&
server_countTilesInPool(board->server) < MIN_TRADE_TILES ) {
newInfo->tradeInProgress = XP_FALSE;
setTradeInProgress( board, newPlayer, XP_FALSE );
newInfo->traySelBits = 0x00; /* clear any selected */
}
@ -904,6 +920,7 @@ board_resetEngine( BoardCtxt* board )
server_resetEngine( board->server, board->selPlayer );
} /* board_resetEngine */
#ifdef XWFEATURE_MINIWIN
/* Find a rectangle either centered on the board or pinned to the point at
* which the mouse went down.
*/
@ -929,6 +946,7 @@ positionMiniWRect( BoardCtxt* board, XP_Rect* rect, XP_Bool center )
}
forceRectToBoard( board, rect );
} /*positionMiniWRect */
#endif
static XP_Bool
timerFiredForPen( BoardCtxt* board )
@ -954,7 +972,11 @@ timerFiredForPen( BoardCtxt* board )
bonus = util_getSquareBonus( board->util, board->model,
col, row );
if ( bonus != BONUS_NONE ) {
#ifdef XWFEATURE_MINIWIN
text = draw_getMiniWText( board->draw, (XWMiniTextType)bonus );
#else
util_bonusSquareHeld( board->util, bonus );
#endif
}
}
board->penTimerFired = XP_TRUE;
@ -984,14 +1006,18 @@ timerFiredForPen( BoardCtxt* board )
XP_ASSERT( XP_STRLEN(buf) + explLen < sizeof(buf) );
XP_STRCAT( buf, scoreExpl );
}
#ifdef XWFEATURE_MINIWIN
text = buf;
#else
util_playerScoreHeld( board->util, buf );
#endif
}
board->penTimerFired = XP_TRUE;
}
if ( !!text ) {
#ifdef XWFEATURE_MINIWIN
MiniWindowStuff* stuff = &board->miniWindowStuff[MINIWINDOW_VALHINT];
makeMiniWindowForText( board, text, MINIWINDOW_VALHINT );
XP_ASSERT( stuff->text == text );
@ -1002,6 +1028,7 @@ timerFiredForPen( BoardCtxt* board )
dragDropEnd( board, board->penDownX, board->penDownY, &dragged );
XP_ASSERT( !dragged );
}
#endif
}
return draw;
} /* timerFiredForPen */
@ -1123,7 +1150,9 @@ board_invalAllTiles( BoardCtxt* board )
while ( lastRow-- ) {
board->redrawFlags[lastRow] = ~0;
}
#ifdef XWFEATURE_MINIWIN
board->tradingMiniWindowInvalid = XP_TRUE;
#endif
board->needsDrawing = XP_TRUE;
} /* board_invalAllTiles */
@ -1967,6 +1996,7 @@ invalCell( BoardCtxt* board, XP_U16 col, XP_U16 row )
XP_ASSERT( col < MAX_ROWS );
XP_ASSERT( row < MAX_ROWS );
#ifdef XWFEATURE_MINIWIN
/* if the trade window is up and this cell intersects it, set up to draw
it again */
if ( (board->trayVisState != TRAY_HIDDEN) && TRADE_IN_PROGRESS(board) ) {
@ -1978,6 +2008,7 @@ invalCell( BoardCtxt* board, XP_U16 col, XP_U16 row )
}
}
}
#endif
board->needsDrawing = XP_TRUE;
} /* invalCell */
@ -2030,6 +2061,7 @@ moveTileToArrowLoc( BoardCtxt* board, XP_U8 index )
} /* moveTileToArrowLoc */
#endif
#ifdef XWFEATURE_MINIWIN
void
makeMiniWindowForText( BoardCtxt* board, const XP_UCHAR* text,
MiniWindowType winType )
@ -2044,6 +2076,7 @@ makeMiniWindowForText( BoardCtxt* board, const XP_UCHAR* text,
stuff->rect = rect;
stuff->text = text;
} /* makeMiniWindowForText */
#endif
XP_Bool
board_beginTrade( BoardCtxt* board )
@ -2059,9 +2092,13 @@ board_beginTrade( BoardCtxt* board )
} else if ( server_countTilesInPool(board->server) < MIN_TRADE_TILES){
util_userError( board->util, ERR_TOO_FEW_TILES_LEFT_TO_TRADE );
} else {
#ifdef XWFEATURE_MINIWIN
board->tradingMiniWindowInvalid = XP_TRUE;
#else
util_setInTrade( board->util, board->selPlayer, XP_TRUE );
#endif
board->needsDrawing = XP_TRUE;
board->selInfo->tradeInProgress = XP_TRUE;
setTradeInProgress( board, board->selPlayer, XP_TRUE );
setArrowVisible( board, XP_FALSE );
result = XP_TRUE;
}
@ -2076,7 +2113,7 @@ board_endTrade( BoardCtxt* board )
if ( result ) {
PerTurnInfo* pti = board->selInfo;
invalSelTradeWindow( board );
pti->tradeInProgress = XP_FALSE;
setTradeInProgress( board, board->selPlayer, XP_FALSE );
pti->traySelBits = NO_TILES;
}
return result;
@ -2084,12 +2121,16 @@ board_endTrade( BoardCtxt* board )
#if defined POINTER_SUPPORT || defined KEYBOARD_NAV
# ifdef XWFEATURE_MINIWIN
static XP_Bool
ptOnTradeWindow( BoardCtxt* board, XP_U16 x, XP_U16 y )
{
XP_Rect* windowR = &board->miniWindowStuff[MINIWINDOW_TRADING].rect;
return rectContainsPt( windowR, x, y );
} /* ptOnTradeWindow */
# else
# define ptOnTradeWindow(b,x,y) XP_FALSE
# endif
#ifdef XWFEATURE_SEARCHLIMIT
@ -2454,7 +2495,7 @@ exitTradeMode( BoardCtxt* board )
{
PerTurnInfo* pti = board->selInfo;
invalSelTradeWindow( board );
pti->tradeInProgress = XP_FALSE;
setTradeInProgress( board, board->selPlayer, XP_FALSE );
board_invalTrayTiles( board, pti->traySelBits );
pti->traySelBits = 0x00;
return XP_TRUE;
@ -2493,9 +2534,11 @@ handlePenUpInternal( BoardCtxt* board, XP_U16 xx, XP_U16 yy, XP_Bool isPen )
if ( dragged ) {
/* do nothing further */
} else if ( board->penTimerFired ) {
#ifdef XWFEATURE_MINIWIN
if ( valHintMiniWindowActive( board ) ) {
hideMiniWindow( board, XP_TRUE, MINIWINDOW_VALHINT );
}
#endif
draw = XP_TRUE; /* might have cancelled a drag */
/* Need to clean up if there's been any dragging happening */
board->penTimerFired = XP_FALSE;

View file

@ -76,7 +76,11 @@ static void scrollIfCan( BoardCtxt* board );
#ifdef KEYBOARD_NAV
static XP_Bool cellFocused( const BoardCtxt* board, XP_U16 col, XP_U16 row );
#endif
#ifdef XWFEATURE_MINIWIN
static void drawTradeWindowIf( BoardCtxt* board );
#else
# define drawTradeWindowIf( board )
#endif
#ifdef XWFEATURE_SEARCHLIMIT
@ -221,6 +225,7 @@ rectContainsRect( XP_Rect* rect1, XP_Rect* rect2 )
&& rect1->left + rect1->width >= rect2->left + rect2->width );
} /* rectContainsRect */
#ifdef XWFEATURE_MINIWIN
static void
makeMiniWindowForTrade( BoardCtxt* board )
{
@ -230,6 +235,7 @@ makeMiniWindowForTrade( BoardCtxt* board )
makeMiniWindowForText( board, text, MINIWINDOW_TRADING );
} /* makeMiniWindowForTrade */
#endif
#ifdef XWFEATURE_CROSSHAIRS
static CellFlags
@ -591,6 +597,7 @@ scrollIfCan( BoardCtxt* board )
}
} /* scrollIfCan */
#ifdef XWFEATURE_MINIWIN
static void
drawTradeWindowIf( BoardCtxt* board )
{
@ -607,6 +614,7 @@ drawTradeWindowIf( BoardCtxt* board )
board->tradingMiniWindowInvalid = XP_FALSE;
}
} /* drawTradeWindowIf */
#endif
XP_Bool
board_draw( BoardCtxt* board )

View file

@ -89,6 +89,7 @@ typedef struct _BdCursorLoc {
} BdCursorLoc;
#endif
#ifdef XWFEATURE_MINIWIN
/* We only need two of these, one for the value hint and the other for the
trading window. There's never more than of the former since it lives only
as long as the pen is down. There are, in theory, as many trading windows
@ -101,6 +102,7 @@ typedef struct _MiniWindowStuff {
enum { MINIWINDOW_VALHINT, MINIWINDOW_TRADING };
typedef XP_U16 MiniWindowType; /* one of the two above */
#endif
typedef struct _PerTurnInfo {
#ifdef KEYBOARD_NAV
@ -213,8 +215,10 @@ struct BoardCtxt {
XP_Bool scoreBoardInvalid;
DragState dragState;
#ifdef XWFEATURE_MINIWIN
MiniWindowStuff miniWindowStuff[2];
XP_Bool tradingMiniWindowInvalid;
#endif
TileBit trayInvalBits;
#ifdef KEYBOARD_NAV
@ -230,9 +234,10 @@ struct BoardCtxt {
};
#define CURSOR_LOC_REM 0
#define valHintMiniWindowActive( board ) \
#ifdef XWFEATURE_MINIWIN
# define valHintMiniWindowActive( board ) \
((XP_Bool)((board)->miniWindowStuff[MINIWINDOW_VALHINT].text != NULL))
#endif
#define MY_TURN(b) ((b)->selPlayer == server_getCurrentTurn( (b)->server ))
#define TRADE_IN_PROGRESS(b) ((b)->selInfo->tradeInProgress==XP_TRUE)
@ -274,21 +279,27 @@ void invalRow( BoardCtxt* board, XP_U16 row );
void invalTrayTilesAbove( BoardCtxt* board, XP_U16 tileIndex );
void invalTrayTilesBetween( BoardCtxt* board, XP_U16 tileIndex1,
XP_U16 tileIndex2 );
#ifdef XWFEATURE_MINIWIN
void makeMiniWindowForText( BoardCtxt* board, const XP_UCHAR* text,
MiniWindowType winType );
void hideMiniWindow( BoardCtxt* board, XP_Bool destroy,
MiniWindowType winType );
void invalSelTradeWindow( BoardCtxt* board );
#else
# define invalSelTradeWindow(b)
#endif
XP_Bool getCellRect( const BoardCtxt* board, XP_U16 col, XP_U16 row,
XP_Rect* rect);
void getDragCellRect( BoardCtxt* board, XP_U16 col, XP_U16 row,
XP_Rect* rectP );
void invalSelTradeWindow( BoardCtxt* board );
void invalCellsUnderRect( BoardCtxt* board, const XP_Rect* rect );
#ifdef XWFEATURE_SEARCHLIMIT
void invalCurHintRect( BoardCtxt* board, XP_U16 player );
#endif
void hideMiniWindow( BoardCtxt* board, XP_Bool destroy,
MiniWindowType winType );
void moveTileInTray( BoardCtxt* board, XP_U16 moveTo, XP_U16 moveFrom );
XP_Bool handleTrayDuringTrade( BoardCtxt* board, XP_S16 index );

View file

@ -217,6 +217,10 @@ typedef struct _PlayerDicts {
#define LOG_RETURN_VOID() LOG_RETURNF("%s","void")
#define XP_LOGLOC() XP_LOGF( "%s(), line %d", __func__, __LINE__ )
#ifndef XP_USE
# define XP_USE(v) v=v
#endif
#ifndef XP_UNUSED
# if defined __GNUC__
# define XP_UNUSED(x) UNUSED__ ## x __attribute__((unused))

View file

@ -566,9 +566,11 @@ dragDropContinueImpl( BoardCtxt* board, XP_U16 xx, XP_U16 yy,
/* This is the first time we've moved!!! Kill any future timers,
and if there's a window up kill it.*/
board->penTimerFired = XP_FALSE;
#ifdef XWFEATURE_MINIWIN
if ( valHintMiniWindowActive( board ) ) {
hideMiniWindow( board, XP_TRUE, MINIWINDOW_VALHINT );
}
#endif
ds->didMove = XP_TRUE;
}
}

View file

@ -197,12 +197,14 @@ typedef struct DrawCtxVTable {
XWBonusType bonus, XP_Bool vert,
HintAtts hintAtts,
CellFlags flags);
#ifdef XWFEATURE_MINIWIN
const XP_UCHAR* DRAW_VTABLE_NAME(getMiniWText) ( DrawCtx* dctx,
XWMiniTextType textHint );
void DRAW_VTABLE_NAME(measureMiniWText) ( DrawCtx* dctx, const XP_UCHAR* textP,
XP_U16* width, XP_U16* height );
void DRAW_VTABLE_NAME(drawMiniWindow)( DrawCtx* dctx, const XP_UCHAR* text,
const XP_Rect* rect, void** closure );
#endif
#ifndef DRAW_LINK_DIRECT
} DrawCtxVTable; /* */
#endif
@ -291,11 +293,13 @@ struct DrawCtx {
#define draw_drawBoardArrow( dc, r, b, v, h, f ) \
CALL_DRAW_NAME5(drawBoardArrow,(dc),(r),(b), (v), (h), (f))
#define draw_getMiniWText( dc, b ) CALL_DRAW_NAME1(getMiniWText, (dc),(b) )
#define draw_measureMiniWText( dc, t, wp, hp) \
#ifdef XWFEATURE_MINIWIN
# define draw_getMiniWText( dc, b ) CALL_DRAW_NAME1(getMiniWText, (dc),(b) )
# define draw_measureMiniWText( dc, t, wp, hp) \
CALL_DRAW_NAME3(measureMiniWText, (dc),(t), (wp), (hp) )
#define draw_drawMiniWindow( dc, t, r, c ) \
# define draw_drawMiniWindow( dc, t, r, c ) \
CALL_DRAW_NAME3(drawMiniWindow, (dc), (t), (r), (c) )
#endif
#ifdef DRAW_WITH_PRIMITIVES
# define draw_setClip( dc, rn, ro ) CALL_DRAW_NAME2(setClip, (dc), (rn), (ro))

View file

@ -1,4 +1,4 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
/*
* Copyright 1997 - 2010 by Eric House (xwords@eehouse.org). All rights
* reserved.
@ -158,6 +158,12 @@ typedef struct UtilVtable {
void (*m_util_remSelected)(XW_UtilCtxt* uc);
#ifndef XWFEATURE_MINIWIN
void (*m_util_setInTrade)( XW_UtilCtxt* uc, XP_U16 turn, XP_Bool entering );
void (*m_util_bonusSquareHeld)( XW_UtilCtxt* uc, XWBonusType bonus );
void (*m_util_playerScoreHeld)( XW_UtilCtxt* uc, const XP_UCHAR* txt );
#endif
#ifndef XWFEATURE_STANDALONE_ONLY
void (*m_util_addrChange)( XW_UtilCtxt* uc, const CommsAddrRec* oldAddr,
const CommsAddrRec* newAddr );
@ -258,6 +264,15 @@ struct XW_UtilCtxt {
#define util_remSelected( uc ) \
(uc)->vtable->m_util_remSelected((uc))
#ifndef XWFEATURE_MINIWIN
# define util_setInTrade( uc, t, e ) \
(uc)->vtable->m_util_setInTrade( (uc), (t), (e) )
# define util_bonusSquareHeld( uc, b ) \
(uc)->vtable->m_util_bonusSquareHeld( (uc), (b) )
# define util_playerScoreHeld( uc, txt ) \
(uc)->vtable->m_util_playerScoreHeld( (uc), (txt) )
#endif
#ifndef XWFEATURE_STANDALONE_ONLY
# define util_addrChange( uc, addro, addrn ) \
(uc)->vtable->m_util_addrChange((uc), (addro), (addrn))

View file

@ -0,0 +1,38 @@
# -*-mode: Makefile; coding: utf-8; -*-
# Copyright 2002-2008 by Eric House (xwords@eehouse.org). All rights reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
XWLANG=Japanese
LANGCODE=ja_JA
ENC = UTF-8
TARGET_TYPE ?= WINCE
include ../Makefile.langcommon
SOURCEDICT ?= /dev/null
$(XWLANG)Main.dict.gz: $(SOURCEDICT) Makefile
cat $< | gzip -c > $@
# Everything but creating of the Main.dict file is inherited from the
# "parent" Makefile.langcommon in the parent directory.
clean: clean_common
rm -f $(XWLANG)Main.dict.gz *.bin $(XWLANG)*.pdb $(XWLANG)*.seb
help:
@echo 'make'

View file

@ -0,0 +1,113 @@
# -*- coding: utf-8; mode: conf; -*-
# Copyright 2002-2008 by Eric House (xwords@eehouse.org). All rights reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
LANGCODE:ja_JA
CHARSET:utf-8
D2DARGS: -r -term 0 -enc UTF-8
# High bit means "official". Next 7 bits are an enum where
# Czech-ISO8859-2==0x11. Low byte is padding.
XLOC_HEADER:0x9000
# There are too many ひらがあ for the current dawg format that limits
# the number of tiles to 64. Would have to change it again, and
# Crosswords internals as well, to support Japanese. But hey, this
# could demo. And leaving out letters selectively, say the が and ぱ
# families, might make for a good-enough demo. Need a word list first
# though.
<BEGIN_TILES>
2 0 {"_"}
2 1 'あ'
2 1 'い'
2 1 'う'
2 1 'え'
2 1 'お'
2 1 'か'
2 1 'き'
2 1 'く'
2 1 'け'
2 1 'こ'
2 1 'が'
2 1 'ぎ'
2 1 'ぐ'
2 1 'げ'
2 1 'ご'
2 1 'さ'
2 1 'し'
2 1 'す'
2 1 'せ'
2 1 'そ'
2 1 'ざ'
2 1 'じ'
2 1 'ず'
2 1 'ぜ'
2 1 'ぞ'
2 1 'た'
2 1 'ち'
2 1 'つ'
2 1 'て'
2 1 'と'
2 1 'だ'
2 1 'ぢ'
2 1 'づ'
2 1 'で'
2 1 'ど'
2 1 'な'
2 1 'に'
2 1 'ぬ'
2 1 'ね'
2 1 'の'
2 1 'は'
2 1 'ひ'
2 1 'ふ'
2 1 'へ'
2 1 'ほ'
2 1 'ば'
2 1 'び'
2 1 'ぶ'
2 1 'べ'
2 1 'ぼ'
2 1 'ぱ'
2 1 'ぴ'
2 1 'ぷ'
2 1 'ぺ'
2 1 'ぽ'
<END_TILES>
# 2 1 'ま'
# 2 1 'み'
# 2 1 'む'
# 2 1 'め'
# 2 1 'も'
# 2 1 'や'
# 2 1 'ゆ'
# 2 1 'よ'
# 2 1 'ゃ'
# 2 1 'ゅ'
# 2 1 'ょ'
# 2 1 'ら'
# 2 1 'り'
# 2 1 'る'
# 2 1 'れ'
# 2 1 'ろ'
# 2 1 'わ'
# 2 1 'ゐ'
# 2 1 'ゑ'
# 2 1 'を'
# 2 1 'ん'

View file

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

View file

@ -39,20 +39,6 @@ typedef struct CursesDrawCtx {
static void curses_draw_clearRect( DrawCtx* p_dctx, const XP_Rect* rectP );
static void getTops( const XP_Rect* rect, int* toptop, int* topbot );
static void
drawRect( WINDOW* win, const XP_Rect* rect, char vert, char hor )
{
wmove( win, rect->top-1, rect->left );
whline( win, hor, rect->width );
wmove( win, rect->top+rect->height, rect->left );
whline( win, hor, rect->width );
wmove( win, rect->top, rect->left-1 );
wvline( win, vert, rect->height );
wmove( win, rect->top, rect->left+rect->width );
wvline( win, vert, rect->height );
} /* drawRect */
static void
eraseRect( CursesDrawCtx* dctx, const XP_Rect* rect )
{
@ -484,6 +470,7 @@ curses_draw_clearRect( DrawCtx* p_dctx, const XP_Rect* rectP )
eraseRect( dctx, &rect );
} /* curses_draw_clearRect */
#ifdef XWFEATURE_MINIWIN
static const XP_UCHAR*
curses_draw_getMiniWText( DrawCtx* XP_UNUSED(p_dctx),
XWMiniTextType XP_UNUSED(textHint) )
@ -499,6 +486,20 @@ curses_draw_measureMiniWText( DrawCtx* XP_UNUSED(p_dctx), const XP_UCHAR* str,
*heightP = 3;
} /* curses_draw_measureMiniWText */
static void
drawRect( WINDOW* win, const XP_Rect* rect, char vert, char hor )
{
wmove( win, rect->top-1, rect->left );
whline( win, hor, rect->width );
wmove( win, rect->top+rect->height, rect->left );
whline( win, hor, rect->width );
wmove( win, rect->top, rect->left-1 );
wvline( win, vert, rect->height );
wmove( win, rect->top, rect->left+rect->width );
wvline( win, vert, rect->height );
} /* drawRect */
static void
curses_draw_drawMiniWindow( DrawCtx* p_dctx, const XP_UCHAR* text,
const XP_Rect* rect, void** XP_UNUSED(closure) )
@ -519,6 +520,7 @@ curses_draw_drawMiniWindow( DrawCtx* p_dctx, const XP_UCHAR* text,
mvwprintw( dctx->boardWin, smallerR.top, smallerR.left, text,
strlen(text) );
} /* curses_draw_drawMiniWindow */
#endif
#if 0
static void
@ -568,9 +570,11 @@ cursesDrawCtxtMake( WINDOW* boardWin )
SET_VTABLE_ENTRY( dctx->vtable, draw_clearRect, curses );
#ifdef XWFEATURE_MINIWIN
SET_VTABLE_ENTRY( dctx->vtable, draw_drawMiniWindow, curses );
SET_VTABLE_ENTRY( dctx->vtable, draw_getMiniWText, curses );
SET_VTABLE_ENTRY( dctx->vtable, draw_measureMiniWText, curses );
#endif
dctx->boardWin = boardWin;

View file

@ -397,16 +397,35 @@ curses_util_clearTimer( XW_UtilCtxt* uc, XWTimerReason why )
globals->cGlobals.timerInfo[why].proc = NULL;
}
#ifdef USE_GLIBLOOP
static gboolean
onetime_idle( gpointer data )
{
LOG_FUNC();
CursesAppGlobals* globals = (CursesAppGlobals*)data;
if ( server_do( globals->cGlobals.game.server ) ) {
if ( !!globals->cGlobals.game.board ) {
board_draw( globals->cGlobals.game.board );
}
}
return FALSE;
}
#endif
static void
curses_util_requestTime( XW_UtilCtxt* uc )
{
CursesAppGlobals* globals = (CursesAppGlobals*)uc->closure;
#ifdef USE_GLIBLOOP
(void)g_idle_add( onetime_idle, globals );
#else
/* I've created a pipe whose read-only end is plugged into the array of
fds that my event loop polls so that I can write to it to simulate
post-event on a more familiar system. It works, so no complaints! */
CursesAppGlobals* globals = (CursesAppGlobals*)uc->closure;
if ( 1 != write( globals->timepipe[1], "!", 1 ) ) {
XP_ASSERT(0);
}
#endif
} /* curses_util_requestTime */
static void
@ -476,7 +495,11 @@ showStatus( CursesAppGlobals* globals )
static XP_Bool
handleQuit( CursesAppGlobals* globals )
{
#ifdef USE_GLIBLOOP
g_main_loop_quit( globals->loop );
#else
globals->timeToExit = XP_TRUE;
#endif
return XP_TRUE;
} /* handleQuit */
@ -867,8 +890,23 @@ SIGINTTERM_handler( int XP_UNUSED(signal) )
}
static void
cursesListenOnSocket( CursesAppGlobals* globals, int newSock )
cursesListenOnSocket( CursesAppGlobals* globals, int newSock
#ifdef USE_GLIBLOOP
, GIOFunc func
#endif
)
{
#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,
func, globals );
SourceData* data = g_malloc( sizeof(*data) );
data->channel = channel;
data->watch = watch;
globals->sources = g_list_append( globals->sources, data );
#else
XP_ASSERT( globals->fdCount+1 < FD_MAX );
XP_WARNF( "%s: setting fd[%d] to %d", __func__, globals->fdCount, newSock );
@ -878,11 +916,27 @@ cursesListenOnSocket( CursesAppGlobals* globals, int newSock )
++globals->fdCount;
XP_LOGF( "%s: there are now %d sources to poll",
__func__, globals->fdCount );
#endif
} /* cursesListenOnSocket */
static void
curses_stop_listening( CursesAppGlobals* globals, int sock )
{
#ifdef USE_GLIBLOOP
GList* sources = globals->sources;
while ( !!sources ) {
SourceData* data = sources->data;
gint fd = g_io_channel_unix_get_fd( data->channel );
if ( fd == sock ) {
g_io_channel_unref( data->channel );
g_free( data );
globals->sources = g_list_remove_link( globals->sources, sources );
break;
}
sources = sources->next;
}
#else
int count = globals->fdCount;
int i;
bool found = false;
@ -897,8 +951,72 @@ curses_stop_listening( CursesAppGlobals* globals, int sock )
assert( found );
--globals->fdCount;
#endif
} /* curses_stop_listening */
#ifdef USE_GLIBLOOP
static gboolean
data_socket_proc( GIOChannel* source, GIOCondition condition, gpointer data )
{
if ( 0 != (G_IO_IN & condition) ) {
CursesAppGlobals* globals = (CursesAppGlobals*)data;
int fd = g_io_channel_unix_get_fd( source );
unsigned char buf[256];
int nBytes;
CommsAddrRec addrRec;
CommsAddrRec* addrp = NULL;
/* It's a normal data socket */
switch ( globals->cGlobals.params->conType ) {
#ifdef XWFEATURE_RELAY
case COMMS_CONN_RELAY:
nBytes = linux_relay_receive( &globals->cGlobals, buf,
sizeof(buf) );
break;
#endif
#ifdef XWFEATURE_SMS
case COMMS_CONN_SMS:
addrp = &addrRec;
nBytes = linux_sms_receive( &globals->cGlobals, fd,
buf, sizeof(buf), addrp );
break;
#endif
#ifdef XWFEATURE_BLUETOOTH
case COMMS_CONN_BT:
nBytes = linux_bt_receive( fd, buf, sizeof(buf) );
break;
#endif
default:
XP_ASSERT( 0 ); /* fired */
}
if ( nBytes != -1 ) {
XWStreamCtxt* inboundS;
XP_Bool redraw = XP_FALSE;
inboundS = stream_from_msgbuf( &globals->cGlobals, buf, nBytes );
if ( !!inboundS ) {
if ( comms_checkIncomingStream( globals->cGlobals.game.comms,
inboundS, addrp ) ) {
redraw = server_receiveMessage( globals->cGlobals.game.server,
inboundS );
}
stream_destroy( inboundS );
}
/* if there's something to draw resulting from the
message, we need to give the main loop time to reflect
that on the screen before giving the server another
shot. So just call the idle proc. */
if ( redraw ) {
curses_util_requestTime( globals->cGlobals.params->util );
}
}
}
return TRUE;
}
#endif
static void
curses_socket_changed( void* closure, int oldSock, int newSock,
void** XP_UNUSED(storage) )
@ -908,7 +1026,11 @@ curses_socket_changed( void* closure, int oldSock, int newSock,
curses_stop_listening( globals, oldSock );
}
if ( newSock != -1 ) {
cursesListenOnSocket( globals, newSock );
cursesListenOnSocket( globals, newSock
#ifdef USE_GLIBLOOP
, data_socket_proc
#endif
);
}
#ifdef XWFEATURE_RELAY
@ -916,6 +1038,21 @@ curses_socket_changed( void* closure, int oldSock, int newSock,
#endif
} /* curses_socket_changed */
#ifdef USE_GLIBLOOP
static gboolean
fire_acceptor( GIOChannel* source, GIOCondition condition, gpointer data )
{
if ( 0 != (G_IO_IN & condition) ) {
CursesAppGlobals* globals = (CursesAppGlobals*)data;
int fd = g_io_channel_unix_get_fd( source );
XP_ASSERT( fd == globals->csInfo.server.serverSocket );
(*globals->cGlobals.acceptor)( fd, globals );
}
return TRUE;
}
#endif
static void
curses_socket_acceptor( int listener, Acceptor func, CommonGlobals* cGlobals,
void** XP_UNUSED(storage) )
@ -924,9 +1061,14 @@ curses_socket_acceptor( int listener, Acceptor func, CommonGlobals* cGlobals,
XP_ASSERT( !cGlobals->acceptor || (func == cGlobals->acceptor) );
cGlobals->acceptor = func;
globals->csInfo.server.serverSocket = listener;
cursesListenOnSocket( globals, listener );
cursesListenOnSocket( globals, listener
#ifdef USE_GLIBLOOP
, fire_acceptor
#endif
);
}
#ifndef USE_GLIBLOOP
#ifdef XWFEATURE_RELAY
static int
figureTimeout( CursesAppGlobals* globals )
@ -990,10 +1132,12 @@ fireCursesTimer( CursesAppGlobals* globals )
}
} /* fireCursesTimer */
#endif
#endif
/*
* Ok, so this doesn't block yet....
*/
#ifndef USE_GLIBLOOP
static XP_Bool
blocking_gotEvent( CursesAppGlobals* globals, int* ch )
{
@ -1122,6 +1266,7 @@ blocking_gotEvent( CursesAppGlobals* globals, int* ch )
}
return result;
} /* blocking_gotEvent */
#endif
static void
remapKey( int* kp )
@ -1438,14 +1583,44 @@ relay_error_curses( void* XP_UNUSED(closure), XWREASON XP_UNUSED_DBG(relayErr) )
#endif
}
#ifdef USE_GLIBLOOP
static gboolean
handle_stdin( GIOChannel* source, GIOCondition condition, gpointer data )
{
if ( 0 != (G_IO_IN & condition) ) {
gint fd = g_io_channel_unix_get_fd( source );
XP_ASSERT( 0 == fd );
CursesAppGlobals* globals = (CursesAppGlobals*)data;
int ch = wgetch( globals->mainWin );
remapKey( &ch );
if (
#ifdef CURSES_SMALL_SCREEN
handleKeyEvent( globals, g_rootMenuListShow, ch ) ||
#endif
handleKeyEvent( globals, globals->menuList, ch )
|| handleKeyEvent( globals, g_sharedMenuList, ch )
|| passKeyToBoard( globals, ch ) ) {
if ( g_globals.doDraw ) {
board_draw( globals->cGlobals.game.board );
globals->doDraw = XP_FALSE;
}
}
}
return TRUE;
}
#endif
void
cursesmain( XP_Bool isServer, LaunchParams* params )
{
int piperesult;
int width, height;
memset( &g_globals, 0, sizeof(g_globals) );
#ifdef USE_GLIBLOOP
g_globals.loop = g_main_loop_new( NULL, FALSE );
#endif
g_globals.amServer = isServer;
g_globals.cGlobals.params = params;
#ifdef XWFEATURE_RELAY
@ -1472,13 +1647,19 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
= params->connInfo.relay.relayName;
}
#endif
#ifdef USE_GLIBLOOP
if ( params->quitAfter >= 0 ) {
cursesListenOnSocket( &g_globals, 0, handle_stdin ); /* stdin */
}
#else
cursesListenOnSocket( &g_globals, 0 ); /* stdin */
piperesult = pipe( g_globals.timepipe );
int piperesult = pipe( g_globals.timepipe );
XP_ASSERT( piperesult == 0 );
/* reader pipe */
cursesListenOnSocket( &g_globals, g_globals.timepipe[0] );
#endif
struct sigaction act = { .sa_handler = SIGINTTERM_handler };
sigaction( SIGINT, &act, NULL );
@ -1595,6 +1776,9 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
drawMenuLargeOrSmall( &g_globals, g_boardMenuList );
board_draw( g_globals.cGlobals.game.board );
#ifdef USE_GLIBLOOP
g_main_loop_run( g_globals.loop );
#else
while ( !g_globals.timeToExit ) {
int ch = 0;
if ( blocking_gotEvent( &g_globals, &ch ) ) {
@ -1613,7 +1797,7 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
}
}
}
#endif
}
if ( !!g_globals.cGlobals.params->fileName ) {
XWStreamCtxt* outStream;

View file

@ -65,7 +65,6 @@ struct CursesAppGlobals {
WINDOW* menuWin;
WINDOW* boardWin;
XP_Bool timeToExit;
XP_Bool doDraw;
const struct MenuList* menuList;
XP_U16 nLinesMenu;
@ -84,14 +83,25 @@ struct CursesAppGlobals {
XWGameState state;
struct sockaddr_in listenerSockAddr;
#ifdef USE_GLIBLOOP
GMainLoop* loop;
GList* sources;
#else
XP_Bool timeToExit;
short fdCount;
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
typedef struct _SourceData {
GIOChannel* channel;
gint watch;
} SourceData;
#endif
DrawCtx* cursesDrawCtxtMake( WINDOW* boardWin );

View file

@ -127,14 +127,6 @@ gtkEraseRect( const GtkDrawCtx* dctx, const XP_Rect* rect )
rect->width, rect->height );
} /* gtkEraseRect */
static void
frameRect( GtkDrawCtx* dctx, const XP_Rect* rect )
{
draw_rectangle( dctx, DRAW_WHAT(dctx), dctx->drawGC,
FALSE, rect->left, rect->top,
rect->width, rect->height );
} /* frameRect */
#ifdef DRAW_WITH_PRIMITIVES
static void
@ -1149,9 +1141,18 @@ gtk_draw_drawTimer( DrawCtx* p_dctx, const XP_Rect* rInner,
&dctx->playerColors[playerNum], NULL );
} /* gtk_draw_drawTimer */
#define MINI_LINE_HT 12
#define MINI_V_PADDING 6
#define MINI_H_PADDING 8
#ifdef XWFEATURE_MINIWIN
# define MINI_LINE_HT 12
# define MINI_V_PADDING 6
# define MINI_H_PADDING 8
static void
frameRect( GtkDrawCtx* dctx, const XP_Rect* rect )
{
draw_rectangle( dctx, DRAW_WHAT(dctx), dctx->drawGC,
FALSE, rect->left, rect->top,
rect->width, rect->height );
} /* frameRect */
static const XP_UCHAR*
gtk_draw_getMiniWText( DrawCtx* XP_UNUSED(p_dctx), XWMiniTextType textHint )
@ -1221,6 +1222,7 @@ gtk_draw_drawMiniWindow( DrawCtx* p_dctx, const XP_UCHAR* text,
&localR, XP_GTK_JUST_CENTER,
&dctx->black, NULL );
} /* gtk_draw_drawMiniWindow */
#endif
#define SET_GDK_COLOR( c, r, g, b ) { \
c.red = (r); \
@ -1301,9 +1303,11 @@ gtkDrawCtxtMake( GtkWidget* drawing_area, GtkAppGlobals* globals )
SET_VTABLE_ENTRY( dctx->vtable, draw_drawTimer, gtk );
#ifdef XWFEATURE_MINIWIN
SET_VTABLE_ENTRY( dctx->vtable, draw_getMiniWText, gtk );
SET_VTABLE_ENTRY( dctx->vtable, draw_measureMiniWText, gtk );
SET_VTABLE_ENTRY( dctx->vtable, draw_drawMiniWindow, gtk );
#endif
SET_VTABLE_ENTRY( dctx->vtable, draw_destroyCtxt, gtk );
SET_VTABLE_ENTRY( dctx->vtable, draw_dictChanged, gtk );

View file

@ -1682,6 +1682,32 @@ gtk_util_getTraySearchLimits( XW_UtilCtxt* XP_UNUSED(uc),
}
#endif
#ifndef XWFEATURE_MINIWIN
static void
gtk_util_setInTrade( XW_UtilCtxt* uc, XP_U16 turn, XP_Bool entering )
{
XP_LOGF( "%s(turn=%d; entering=%d)", __func__, turn, entering );
XP_USE( uc );
XP_USE( turn );
XP_USE( entering );
}
static void
gtk_util_bonusSquareHeld( XW_UtilCtxt* uc, XWBonusType bonus )
{
LOG_FUNC();
XP_USE( uc );
XP_USE( bonus );
}
static void
gtk_util_playerScoreHeld( XW_UtilCtxt* uc, const XP_UCHAR* txt )
{
LOG_FUNC();
XP_USE( uc );
XP_USE( txt );
}
#endif
static void
gtk_util_userError( XW_UtilCtxt* uc, UtilErrID id )
@ -1901,6 +1927,12 @@ setupGtkUtilCallbacks( GtkAppGlobals* globals, XW_UtilCtxt* util )
util->vtable->m_util_getTraySearchLimits = gtk_util_getTraySearchLimits;
#endif
#ifndef XWFEATURE_MINIWIN
util->vtable->m_util_setInTrade = gtk_util_setInTrade;
util->vtable->m_util_bonusSquareHeld = gtk_util_bonusSquareHeld;
util->vtable->m_util_playerScoreHeld = gtk_util_playerScoreHeld;
#endif
util->closure = globals;
} /* setupGtkUtilCallbacks */