Use new relay status callback, and similar callback added to socket

read/writer, to provide connection status beside scoreboard (in area
outside that managed by code in common/).  Simple letters now, it'll
be icons eventually.
This commit is contained in:
ehouse 2009-09-15 13:04:34 +00:00
parent d5d20293ce
commit 4ce9a87be5
6 changed files with 143 additions and 23 deletions

View file

@ -1904,6 +1904,19 @@ ce_draw_focus( CEDrawCtx* dctx, const RECT* invalR )
drawColoredRect( dctx, invalR, CE_FOCUS_COLOR );
}
void
ce_draw_status( CEDrawCtx* dctx, const RECT* rect, wchar_t stateCh )
{
CEAppGlobals* globals = dctx->globals;
FillRect( globals->hdc, rect, dctx->brushes[CE_BKG_COLOR] );
DrawText( globals->hdc, &stateCh, 1, (RECT*)rect,
dctx->scoreIsVertical?
DT_CENTER | DT_BOTTOM :
DT_VCENTER | DT_RIGHT );
}
#ifndef _WIN32_WCE
HBRUSH
ce_draw_getFocusBrush( const CEDrawCtx* dctx )

View file

@ -28,6 +28,8 @@ CEDrawCtx* ce_drawctxt_make( MPFORMAL HWND mainWin, CEAppGlobals* globals );
void ce_draw_update( CEDrawCtx* dctx );
void ce_draw_erase( CEDrawCtx* dctx, const RECT* invalR );
void ce_draw_focus( CEDrawCtx* dctx, const RECT* invalR );
void ce_draw_status( CEDrawCtx* dctx, const RECT* invalR, wchar_t stateCh );
#ifndef _WIN32_WCE
HBRUSH ce_draw_getFocusBrush( const CEDrawCtx* dctx );
#endif

View file

@ -81,6 +81,9 @@ typedef struct FileWriteState {
static XP_S16 ce_send_proc( const XP_U8* buf, XP_U16 len,
const CommsAddrRec* addr,
void* closure );
static void ce_relay_status( void* closure,
CommsRelayState newState );
# ifdef COMMS_HEARTBEAT
static void ce_reset_proc( void* closure );
# endif
@ -524,6 +527,9 @@ typedef struct CEBoardParms {
XP_U16 trayWidth;
XP_U16 timerLeft, timerTop, timerWidth, timerHeight;
#ifndef XWFEATURE_STANDALONE_ONLY
XP_U16 netstatLeft, netstatTop, netstatWidth, netstatHeight;
#endif
XP_U16 boardLeft, trayLeft;
XP_U16 scoreWidth;
@ -638,6 +644,26 @@ figureBoardParms( CEAppGlobals* globals, const XP_U16 nRows,
}
/* XP_LOGF( "hScale=%d; vScale=%d; trayHeight=%d", hScale, vScale, trayHeight ); */
#ifndef XWFEATURE_STANDALONE_ONLY
if ( !!globals->game.comms ) {
/* If we're horizontal, steal from the right of the scoreboard. If
vertical, from the bottom. */
if ( horiz ) {
bparms->netstatWidth = hScale;
scoreWidth -= bparms->netstatWidth;
bparms->netstatLeft = scoreWidth;
bparms->netstatTop = 0;
bparms->netstatHeight = scoreHeight;
} else {
bparms->netstatLeft = 0;
bparms->netstatHeight = vScale;
scoreHeight -= bparms->netstatHeight;
bparms->netstatTop = scoreHeight;
bparms->netstatWidth = scoreWidth;
}
}
#endif
if ( globals->gameInfo.timerEnabled ) {
if ( horiz ) {
bparms->timerWidth = scoreWidth / 6; /* arbitrarily, one sixth */
@ -749,6 +775,17 @@ cePositionBoard( CEAppGlobals* globals )
figureBoardParms( globals, nCols, &bparms );
setOwnedRects( globals, nCols, &bparms );
#ifndef XWFEATURE_STANDALONE_ONLY
if ( !!globals->game.comms ) {
globals->relayStatusR.left = bparms.adjLeft + bparms.netstatLeft;
globals->relayStatusR.top = bparms.adjTop + bparms.netstatTop;
globals->relayStatusR.right = globals->relayStatusR.left
+ bparms.netstatWidth;
globals->relayStatusR.bottom = globals->relayStatusR.top
+ bparms.netstatHeight;
}
#endif
if ( globals->gameInfo.timerEnabled ) {
board_setTimerLoc( globals->game.board,
bparms.adjLeft + bparms.timerLeft,
@ -825,6 +862,7 @@ ceInitTProcs( CEAppGlobals* globals, TransportProcs* procs )
#ifdef COMMS_HEARTBEAT
procs->reset = ce_reset_proc;
#endif
procs->rstatus = ce_relay_status;
procs->closure = globals;
}
@ -1590,6 +1628,34 @@ ceDoHistory( CEAppGlobals* globals )
MB_OK | MB_ICONINFORMATION, XP_TRUE );
} /* ceDoHistory */
static wchar_t
ceStateChar( const CEAppGlobals* globals )
{
/* Idea is to give user a clue how the network connection's coming.
Relay only matters if we have a socket open. So use that first. */
CommsRelayState relayState = globals->relayState;
CeConnState socketState = globals->socketState;
wchar_t ch;
if ( socketState == CE_IPST_CONNECTED ) {
switch( relayState ) {
case COMMS_RELAYSTATE_UNCONNECTED: ch = L'x'; break;
case COMMS_RELAYSTATE_CONNECT_PENDING: ch = L'c'; break;
case COMMS_RELAYSTATE_CONNECTED: ch = L'C'; break;
case COMMS_RELAYSTATE_ALLCONNECTED: ch = L'A'; break;
}
} else {
switch( socketState ) {
case CE_IPST_START:
case CE_IPST_RESOLVINGHOST: ch = L'4'; break;
case CE_IPST_HOSTRESOLVED: ch = L'3'; break;
case CE_IPST_CONNECTING: ch = L'2'; break;
case CE_IPST_CONNECTED: ch = L'1'; break;
}
}
return ch;
}
static void
drawInsidePaint( CEAppGlobals* globals, const RECT* invalR )
{
@ -1612,6 +1678,14 @@ drawInsidePaint( CEAppGlobals* globals, const RECT* invalR )
ce_draw_erase( globals->draw, &interR );
}
}
#ifndef XWFEATURE_STANDALONE_ONLY
if ( IntersectRect( &interR, invalR, &globals->relayStatusR ) ) {
wchar_t ch = ceStateChar( globals );
ce_draw_status( globals->draw, &globals->relayStatusR, ch );
}
#endif
#ifdef _WIN32_WCE
for ( ii = 0; ii < VSIZE(globals->scrollRects); ++ii ) {
if ( IntersectRect( &interR, invalR,
@ -2950,6 +3024,14 @@ got_data_proc( XP_U8* data, XP_U16 len, void* closure )
return draw;
} /* got_data_proc */
static void
sock_state_change( void* closure, CeConnState state )
{
CEAppGlobals* globals = (CEAppGlobals*)closure;
globals->socketState = state;
InvalidateRect( globals->hWnd, &globals->relayStatusR, TRUE /* erase */ );
}
#endif
#ifdef COMMS_HEARTBEAT
@ -2961,6 +3043,14 @@ ce_reset_proc( void* XP_UNUSED_STANDALONE(closure) )
#endif
#ifndef XWFEATURE_STANDALONE_ONLY
static void
ce_relay_status( void* closure, CommsRelayState newState )
{
CEAppGlobals* globals = (CEAppGlobals*)closure;
globals->relayState = newState;
InvalidateRect( globals->hWnd, &globals->relayStatusR, TRUE /* erase */ );
}
static XP_S16
ce_send_proc( const XP_U8* buf, XP_U16 len, const CommsAddrRec* addrp,
void* closure )
@ -2983,7 +3073,9 @@ ce_send_proc( const XP_U8* buf, XP_U16 len, const CommsAddrRec* addrp,
case COMMS_CONN_RELAY:
if ( !globals->socketWrap ) {
globals->socketWrap = ce_sockwrap_new( MPPARM(globals->mpool)
got_data_proc, globals );
globals->hWnd,
got_data_proc,
sock_state_change, globals );
}
nSent = ce_sockwrap_send( globals->socketWrap, buf, len, addrp );

View file

@ -27,6 +27,7 @@
#include "game.h"
#include "util.h"
#include "mempool.h"
#include "cesockwr.h"
#define LCROSSWORDS_DIR_NODBG L"Crosswords"
#define CE_GAMEFILE_VERSION1 0x01 /* means draw gets to save/restore */
@ -168,6 +169,12 @@ typedef struct _CEAppGlobals {
XP_Bool hintPending;
XP_Bool doGlobalPrefs;
#ifndef XWFEATURE_STANDALONE_ONLY
CommsRelayState relayState;
CeConnState socketState;
RECT relayStatusR;
#endif
#ifndef _WIN32_WCE
XP_U16 dbWidth, dbHeight;
#endif

View file

@ -1,4 +1,4 @@
/* -*- compile-command: "make -j TARGET_OS=win32 DEBUG=TRUE" -*- */
/* -*- compile-command: "make -j2 TARGET_OS=win32 DEBUG=TRUE" -*- */
/*
* Copyright 2005-2009 by Eric House (xwords@eehouse.org). All rights
* reserved.
@ -42,19 +42,13 @@ enum { WRITER_THREAD,
READER_THREAD,
N_THREADS };
typedef enum {
CE_IPST_START
,CE_IPST_RESOLVINGHOST
,CE_IPST_HOSTRESOLVED
,CE_IPST_CONNECTING
,CE_IPST_CONNECTED
} CeConnState;
#define MAX_QUEUE_SIZE 6
struct CeSocketWrapper {
HWND hWnd;
DataRecvProc dataProc;
CEAppGlobals* globals;
StateChangeProc stateProc;
void* closure;
union {
HOSTENT hent;
@ -160,6 +154,8 @@ stateChanged( CeSocketWrapper* self, CeConnState newState )
XP_LOGF( "%s: %s -> %s", __func__, ConnState2Str( curState ),
ConnState2Str( newState ) );
(*self->stateProc)( self->closure, newState );
switch( newState ) {
case CE_IPST_START:
break;
@ -174,8 +170,7 @@ stateChanged( CeSocketWrapper* self, CeConnState newState )
send_packet_if( self );
break;
}
}
} /* stateChanged */
static XP_Bool
connectSocket( CeSocketWrapper* self )
@ -191,7 +186,7 @@ connectSocket( CeSocketWrapper* self )
struct sockaddr_in name = {0};
/* Put socket in non-blocking mode */
if ( 0 != WSAAsyncSelect( sock, self->globals->hWnd,
if ( 0 != WSAAsyncSelect( sock, self->hWnd,
XWWM_SOCKET_EVT,
FD_READ | FD_WRITE | FD_CONNECT ) ) {
XP_WARNF( "WSAAsyncSelect failed" );
@ -256,7 +251,7 @@ getHostAddr( CeSocketWrapper* self )
XP_LOGF( "%s: calling WSAAsyncGetHostByName(%s)",
__func__, self->addrRec.u.ip_relay.hostName );
self->getHostTask
= WSAAsyncGetHostByName( self->globals->hWnd,
= WSAAsyncGetHostByName( self->hWnd,
XWWM_HOSTNAME_ARRIVED,
self->addrRec.u.ip_relay.hostName,
(char*)&self->hostNameUnion,
@ -271,15 +266,18 @@ getHostAddr( CeSocketWrapper* self )
}
CeSocketWrapper*
ce_sockwrap_new( MPFORMAL DataRecvProc proc, CEAppGlobals* globals )
ce_sockwrap_new( MPFORMAL HWND hWnd, DataRecvProc dataCB,
StateChangeProc stateCB, void* closure )
{
CeSocketWrapper* self = NULL;
self = XP_MALLOC( mpool, sizeof(*self) );
XP_MEMSET( self, 0, sizeof(*self) );
self->dataProc = proc;
self->globals = globals;
self->hWnd = hWnd;
self->dataProc = dataCB;
self->stateProc = stateCB;
self->closure = closure;
MPASSIGN(self->mpool, mpool );
self->socket = -1;
@ -368,7 +366,7 @@ dispatch_msgs( CeSocketWrapper* self )
/* first send */
XP_LOGF( "%s: sending %d bytes to dataProc", __func__, msgLen );
draw = (*self->dataProc)( (XP_U8*)&self->in_buf[sizeof(msgLen)],
msgLen, self->globals )
msgLen, self->closure )
|| draw;
/* then move down any additional bytes */

View file

@ -23,14 +23,22 @@
#include "comms.h"
#include "mempool.h"
#include "cemain.h"
typedef enum {
CE_IPST_START
,CE_IPST_RESOLVINGHOST
,CE_IPST_HOSTRESOLVED
,CE_IPST_CONNECTING
,CE_IPST_CONNECTED
} CeConnState;
typedef struct CeSocketWrapper CeSocketWrapper; /* forward */
typedef XP_Bool (*DataRecvProc)( XP_U8* data, XP_U16 len, void* closure );
typedef void (*StateChangeProc)( void* closure, CeConnState state );
CeSocketWrapper* ce_sockwrap_new( MPFORMAL DataRecvProc proc,
CEAppGlobals* globals );
CeSocketWrapper* ce_sockwrap_new( MPFORMAL HWND hWnd, DataRecvProc dataCB,
StateChangeProc stateCB,
void* globals );
void ce_sockwrap_delete( CeSocketWrapper* self );
void ce_sockwrap_hostname( CeSocketWrapper* self, WPARAM wParam, LPARAM lParam );