mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-04 23:02:02 +01:00
5eba6f5511
processed. With this fix a complete robot-vs-robot game works between 9300 and gtk version over relay.
1336 lines
37 KiB
C++
1336 lines
37 KiB
C++
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
|
|
/*
|
|
* Copyright 2005 by Eric House (fixin@peak.org). (based on sample
|
|
* app helloworldbasic "Copyright (c) 2002, Nokia. 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.
|
|
*/
|
|
|
|
#if defined SERIES_60
|
|
# include <w32std.h>
|
|
# include <eikinfo.h>
|
|
# include "xwords_60.rsg"
|
|
#elif defined SERIES_80
|
|
# include <cknenv.h>
|
|
# include <ckninfo.h>
|
|
# include <eikcfdlg.h>
|
|
# include <eikfile.rsg>
|
|
# include "xwords_80.rsg"
|
|
#endif
|
|
|
|
#include <stringloader.h>
|
|
#include <stdlib.h> // for srand
|
|
#include <s32file.h>
|
|
|
|
#include "xwappview.h"
|
|
#include "xwappui.h"
|
|
#include "xwords.hrh"
|
|
#include "comtypes.h"
|
|
#include "symdraw.h"
|
|
#include "symaskdlg.h"
|
|
#include "symdict.h"
|
|
#include "symgamdl.h"
|
|
#include "symblnk.h"
|
|
#include "symgmdlg.h"
|
|
#include "symutil.h"
|
|
#include "symssock.h"
|
|
|
|
#include "LocalizedStrIncludes.h"
|
|
|
|
// Standard construction sequence
|
|
CXWordsAppView* CXWordsAppView::NewL(const TRect& aRect)
|
|
{
|
|
CXWordsAppView* self = CXWordsAppView::NewLC(aRect);
|
|
CleanupStack::Pop(self);
|
|
return self;
|
|
}
|
|
|
|
CXWordsAppView* CXWordsAppView::NewLC(const TRect& aRect)
|
|
{
|
|
CXWordsAppView* self = new (ELeave) CXWordsAppView;
|
|
CleanupStack::PushL(self);
|
|
self->ConstructL(aRect);
|
|
return self;
|
|
}
|
|
|
|
CXWordsAppView::CXWordsAppView()
|
|
{
|
|
#ifdef DEBUG
|
|
TInt processHandleCount, threadHandleCount;
|
|
RThread thread;
|
|
thread.HandleCount( processHandleCount, threadHandleCount );
|
|
XP_LOGF( "startup: processHandleCount: %d; threadHandleCount: %d",
|
|
processHandleCount, threadHandleCount );
|
|
#endif
|
|
|
|
iDraw = NULL;
|
|
XP_MEMSET( &iGame, 0, sizeof(iGame) );
|
|
|
|
iCurGameName.Copy( _L("") );
|
|
|
|
/* CBase derivitaves are zero'd out, they say */
|
|
XP_ASSERT( iTimerReasons[0] == 0 && iTimerReasons[1] == 0 );
|
|
}
|
|
|
|
CXWordsAppView::~CXWordsAppView()
|
|
{
|
|
DeleteGame();
|
|
|
|
if ( iDraw ) {
|
|
draw_destroyCtxt( iDraw );
|
|
}
|
|
|
|
XP_FREE( mpool, iUtil.vtable );
|
|
vtmgr_destroy( MPPARM(mpool) iVtMgr );
|
|
|
|
mpool_destroy( mpool );
|
|
|
|
delete iDictList;
|
|
delete iRequestTimer;
|
|
delete iGamesMgr;
|
|
#ifndef XWFEATURE_STANDALONE_ONLY
|
|
delete iSendSock;
|
|
delete iNewPacketQueue;
|
|
#endif
|
|
|
|
#ifdef DEBUG
|
|
TInt processHandleCount, threadHandleCount;
|
|
RThread thread;
|
|
thread.HandleCount( processHandleCount, threadHandleCount );
|
|
XP_LOGF( "shutdown: processHandleCount: %d; threadHandleCount: %d",
|
|
processHandleCount, threadHandleCount );
|
|
#endif
|
|
}
|
|
|
|
void CXWordsAppView::ConstructL(const TRect& aRect)
|
|
{
|
|
// Create a window for this application view
|
|
CreateWindowL();
|
|
|
|
// Set the windows size
|
|
SetRect(aRect);
|
|
|
|
// Indicate that the control is blank
|
|
SetBlank();
|
|
|
|
iRequestTimer = CIdle::NewL( CActive::EPriorityIdle );
|
|
iTimerRunCount = 0;
|
|
|
|
#ifndef XWFEATURE_STANDALONE_ONLY
|
|
iSendSock = CSendSocket::NewL( PacketReceived, (void*)this );
|
|
XP_LOGF( "iSendSock created" );
|
|
iNewPacketQueue = new (ELeave)CDesC8ArrayFlat(2);
|
|
#endif
|
|
|
|
// Set the control's border
|
|
// SetBorder(TGulBorder::EFlatContainer);
|
|
|
|
// Set the correct application view (Note:
|
|
// ESkinAppViewWithCbaNoToolband is the default)
|
|
|
|
#if defined SERIES_80
|
|
//CknEnv::Skin().SetAppViewType(ESkinAppViewWithCbaNoToolband);
|
|
CknEnv::Skin().SetAppViewType(ESkinAppViewNoCbaNoToolband);
|
|
#endif
|
|
|
|
// This doesn't do what I want
|
|
// SetExtentToWholeScreen();
|
|
|
|
// Activate the window, which makes it ready to be drawn
|
|
ActivateL();
|
|
|
|
// Now the xwords-specific stuff
|
|
XP_LOGF( "starting xwords initialization" );
|
|
|
|
iStartTime.HomeTime();
|
|
TDateTime tdtime = iStartTime.DateTime();
|
|
// seed random with current microseconds, or so.... whatever.
|
|
TInt seed = (((tdtime.Minute() * 60) + tdtime.Second()) * 1000 )
|
|
+ tdtime.MicroSecond();
|
|
XP_LOGF( "seeding srand with %d", seed );
|
|
srand( seed );
|
|
|
|
#ifdef MEM_DEBUG
|
|
mpool = mpool_make();
|
|
#endif
|
|
|
|
iVtMgr = make_vtablemgr( MPPARM_NOCOMMA(mpool) );
|
|
User::LeaveIfNull( iVtMgr );
|
|
|
|
iUtil.vtable = (UtilVtable*)XP_MALLOC( mpool, sizeof( UtilVtable ) );
|
|
User::LeaveIfNull( iUtil.vtable );
|
|
SetUpUtil();
|
|
|
|
TFileName basePath;
|
|
GetXwordsRWDir( &basePath, EGamesLoc );
|
|
iGamesMgr = CXWGamesMgr::NewL( MPPARM(mpool) iCoeEnv, &basePath );
|
|
|
|
iDraw = sym_drawctxt_make( MPPARM(mpool) &SystemGc(), iCoeEnv, iEikonEnv );
|
|
User::LeaveIfNull( iDraw );
|
|
|
|
if ( !FindAllDicts() ) {
|
|
UserErrorFromID( R_ALERT_NO_DICTS );
|
|
User::Leave( -1 );
|
|
}
|
|
|
|
if ( !LoadPrefs() ) {
|
|
InitPrefs();
|
|
}
|
|
MakeOrLoadGameL();
|
|
|
|
PositionBoard();
|
|
(void)server_do( iGame.server ); // get tiles assigned etc.
|
|
} // ConstructL
|
|
|
|
// Draw this application's view to the screen
|
|
void CXWordsAppView::Draw( const TRect& aRect ) const
|
|
{
|
|
// Get the standard graphics context
|
|
CWindowGc& gc = SystemGc();
|
|
gc.SetClippingRect( aRect );
|
|
gc.Clear( aRect );
|
|
|
|
if ( iGame.board ) {
|
|
XP_Rect rect;
|
|
|
|
rect.left = SC( XP_U16, aRect.iTl.iX );
|
|
rect.top = SC( XP_U16, aRect.iTl.iY );
|
|
rect.width = SC( XP_U16, aRect.Width() );
|
|
rect.height = SC( XP_U16, aRect.Height() );
|
|
|
|
board_invalRect( iGame.board, &rect );
|
|
board_draw( iGame.board );
|
|
}
|
|
|
|
DrawGameName();
|
|
} // Draw
|
|
|
|
/* static */ VTableMgr*
|
|
CXWordsAppView::sym_util_getVTManager( XW_UtilCtxt* uc )
|
|
{
|
|
CXWordsAppView* self = (CXWordsAppView*)uc->closure;
|
|
return self->iVtMgr;
|
|
} /* sym_util_getVTManager */
|
|
|
|
#ifndef XWFEATURE_STANDALONE_ONLY
|
|
/*static*/ XWStreamCtxt*
|
|
CXWordsAppView::sym_util_makeStreamFromAddr( XW_UtilCtxt* uc,
|
|
XP_U16 channelNo )
|
|
{
|
|
XP_LOGF( "sym_util_makeStreamFromAddr called" );
|
|
CXWordsAppView* self = (CXWordsAppView*)uc->closure;
|
|
XP_ASSERT( self->iGame.comms );
|
|
return self->MakeSimpleStream( self->sym_send_on_close,
|
|
channelNo );
|
|
}
|
|
#endif
|
|
|
|
#define EM BONUS_NONE
|
|
#define DL BONUS_DOUBLE_LETTER
|
|
#define DW BONUS_DOUBLE_WORD
|
|
#define TL BONUS_TRIPLE_LETTER
|
|
#define TW BONUS_TRIPLE_WORD
|
|
|
|
static XWBonusType
|
|
sym_util_getSquareBonus( XW_UtilCtxt* /*uc*/, ModelCtxt* /*model*/,
|
|
XP_U16 col, XP_U16 row )
|
|
{
|
|
XP_U16 index;
|
|
XWBonusType result;
|
|
const XP_U16 fourteen = 14;
|
|
|
|
const char defaultBoard[8*8] = {
|
|
TW,EM,EM,DL,EM,EM,EM,TW,
|
|
EM,DW,EM,EM,EM,TL,EM,EM,
|
|
|
|
EM,EM,DW,EM,EM,EM,DL,EM,
|
|
DL,EM,EM,DW,EM,EM,EM,DL,
|
|
|
|
EM,EM,EM,EM,DW,EM,EM,EM,
|
|
EM,TL,EM,EM,EM,TL,EM,EM,
|
|
|
|
EM,EM,DL,EM,EM,EM,DL,EM,
|
|
TW,EM,EM,DL,EM,EM,EM,DW,
|
|
}; /* defaultBoard */
|
|
|
|
if ( col > 7 ) col = SC(XP_U16, fourteen - col);
|
|
if ( row > 7 ) row = SC(XP_U16, fourteen - row);
|
|
index = SC(XP_U16,(row*8) + col);
|
|
if ( index >= 8*8 ) {
|
|
result = (XWBonusType)EM;
|
|
} else {
|
|
result = (XWBonusType)defaultBoard[index];
|
|
}
|
|
return result;
|
|
} // sym_util_getSquareBonus
|
|
|
|
/* static */ void
|
|
CXWordsAppView::sym_util_userError( XW_UtilCtxt* uc, UtilErrID id )
|
|
{
|
|
TInt resourceId = 0;
|
|
|
|
switch( id ) {
|
|
case ERR_TILES_NOT_IN_LINE:
|
|
resourceId = R_TILES_IN_LINE_ALERT;
|
|
break;
|
|
case ERR_NO_EMPTIES_IN_TURN:
|
|
resourceId = R_NO_EMPTIES_SEP_ALERT;
|
|
break;
|
|
case ERR_TWO_TILES_FIRST_MOVE:
|
|
resourceId = R_TWO_TILES_FIRST_MOVE_ALERT;
|
|
break;
|
|
case ERR_TILES_MUST_CONTACT:
|
|
resourceId = R_PLACED_MUST_CONTACT_ALERT;
|
|
break;
|
|
case ERR_TOO_FEW_TILES_LEFT_TO_TRADE:
|
|
resourceId = R_TOO_FEW_TO_TRADE_ALERT;
|
|
break;
|
|
case ERR_NOT_YOUR_TURN:
|
|
resourceId = R_NOT_YOUR_TURN_ALERT;
|
|
break;
|
|
case ERR_NO_PEEK_ROBOT_TILES:
|
|
resourceId = R_NO_PEEK_ALERT;
|
|
break;
|
|
#ifndef XWFEATURE_STANDALONE_ONLY
|
|
case ERR_SERVER_DICT_WINS:
|
|
case ERR_NO_PEEK_REMOTE_TILES:
|
|
case ERR_REG_UNEXPECTED_USER:
|
|
#endif
|
|
case ERR_CANT_TRADE_MID_MOVE:
|
|
resourceId = R_REMOVE_FIRST_ALERT;
|
|
break;
|
|
case ERR_CANT_UNDO_TILEASSIGN:
|
|
resourceId = R_NOTHING_TO_UNDO_ALERT;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
CXWordsAppView* self = (CXWordsAppView*)uc->closure;
|
|
self->UserErrorFromID( resourceId );
|
|
} // sym_util_userError
|
|
|
|
static XP_Bool
|
|
sym_util_userQuery( XW_UtilCtxt* uc, UtilQueryID aId,
|
|
XWStreamCtxt* aStream )
|
|
{
|
|
CXWordsAppView* self = (CXWordsAppView*)uc->closure;
|
|
return self->UserQuery( aId, aStream );
|
|
} /* sym_util_userQuery */
|
|
|
|
static XP_S16
|
|
sym_util_userPickTile( XW_UtilCtxt* /*uc*/, const PickInfo* /*pi*/,
|
|
XP_U16 /*playerNum*/,
|
|
const XP_UCHAR4* texts, XP_U16 nTiles )
|
|
{
|
|
TInt result = 0;
|
|
TRAPD( error, CXWBlankSelDlg::UsePickTileDialogL( texts, nTiles, &result ) );
|
|
XP_ASSERT( result >= 0 && result < nTiles );
|
|
return static_cast<XP_S16>(result);
|
|
} /* sym_util_userPickTile */
|
|
|
|
static XP_Bool
|
|
sym_util_askPassword( XW_UtilCtxt* /*uc*/, const XP_UCHAR* /*name*/,
|
|
XP_UCHAR* /*buf*/, XP_U16* /*len*/ )
|
|
{
|
|
return XP_TRUE;
|
|
}
|
|
|
|
static void
|
|
sym_util_trayHiddenChange(XW_UtilCtxt* /*uc*/, XW_TrayVisState /*newState*/ )
|
|
{
|
|
}
|
|
|
|
static void
|
|
sym_util_yOffsetChange(XW_UtilCtxt* /*uc*/, XP_U16 /*oldOffset*/, XP_U16 /*newOffset*/ )
|
|
{
|
|
}
|
|
|
|
/* static */ void
|
|
CXWordsAppView::sym_util_notifyGameOverL( XW_UtilCtxt* uc )
|
|
{
|
|
CXWordsAppView* self = (CXWordsAppView*)uc->closure;
|
|
self->DrawNow();
|
|
self->DisplayFinalScoresL();
|
|
}
|
|
|
|
static XP_Bool
|
|
sym_util_hiliteCell( XW_UtilCtxt* /*uc*/, XP_U16 /*col*/, XP_U16 /*row*/ )
|
|
{
|
|
return XP_TRUE; // don't exit early
|
|
}
|
|
|
|
static XP_Bool
|
|
sym_util_engineProgressCallback( XW_UtilCtxt* /*uc*/ )
|
|
{
|
|
#ifdef SHOW_PROGRESS
|
|
#endif
|
|
return XP_TRUE;
|
|
}
|
|
|
|
static void
|
|
sym_util_setTimer( XW_UtilCtxt* /*uc*/, XWTimerReason /*why*/ )
|
|
{
|
|
}
|
|
|
|
/* static */ void
|
|
CXWordsAppView::sym_util_requestTime( XW_UtilCtxt* uc )
|
|
{
|
|
CXWordsAppView* self = (CXWordsAppView*)uc->closure;
|
|
self->StartIdleTimer( EUtilRequest );
|
|
}
|
|
|
|
/* static */ XP_U32
|
|
CXWordsAppView::sym_util_getCurSeconds( XW_UtilCtxt* uc )
|
|
{
|
|
CXWordsAppView* self = (CXWordsAppView*)uc->closure;
|
|
TTime currentTime;
|
|
currentTime.HomeTime();
|
|
|
|
TTimeIntervalSeconds interval;
|
|
(void)currentTime.SecondsFrom( self->iStartTime, interval );
|
|
|
|
return (XP_U32)interval.Int();
|
|
}
|
|
|
|
/* static */ DictionaryCtxt*
|
|
CXWordsAppView::sym_util_makeEmptyDict( XW_UtilCtxt* uc )
|
|
{
|
|
CXWordsAppView* self = (CXWordsAppView*)uc->closure;
|
|
|
|
DictionaryCtxt* dict = sym_dictionary_makeL( MPPARM(self->mpool)
|
|
NULL );
|
|
return dict;
|
|
}
|
|
|
|
static XP_UCHAR*
|
|
sym_util_getUserString( XW_UtilCtxt* /*uc*/, XP_U16 stringCode )
|
|
{
|
|
// These belong in resources. But I haven't yet figured out how
|
|
// to do 8-bit strings in resources. Also, StringLoader does
|
|
// allocations when loading strings rather than just returning
|
|
// pointers into the resources as palm does. So this method will
|
|
// have to provide permanent storage for the strings, probably via
|
|
// a string table that's filled in on demand.
|
|
|
|
switch( stringCode ) {
|
|
case STRD_REMAINING_TILES_ADD:
|
|
return (XP_UCHAR*)"+ %d [all remaining tiles]";
|
|
case STRD_UNUSED_TILES_SUB:
|
|
return (XP_UCHAR*)"- %d [unused tiles]";
|
|
case STR_BONUS_ALL:
|
|
return (XP_UCHAR*)"Bonus for using all tiles: 50" XP_CR;
|
|
case STRD_TURN_SCORE:
|
|
return (XP_UCHAR*)"Score for turn: %d" XP_CR;
|
|
case STR_COMMIT_CONFIRM:
|
|
return (XP_UCHAR*)"Commit the current move?" XP_CR;
|
|
case STR_LOCAL_NAME:
|
|
return (XP_UCHAR*)"%s";
|
|
case STR_NONLOCAL_NAME:
|
|
return (XP_UCHAR*)"%s (remote)";
|
|
case STRD_TIME_PENALTY_SUB:
|
|
return (XP_UCHAR*)" - %d [time]";
|
|
|
|
case STRD_CUMULATIVE_SCORE:
|
|
return (XP_UCHAR*)"Cumulative score: %d" XP_CR;
|
|
case STRS_MOVE_ACROSS:
|
|
return (XP_UCHAR*)"move (from %s across)" XP_CR;
|
|
case STRS_MOVE_DOWN:
|
|
return (XP_UCHAR*)"move (from %s down)" XP_CR;
|
|
case STRS_TRAY_AT_START:
|
|
return (XP_UCHAR*)"Tray at start: %s" XP_CR;
|
|
|
|
case STRS_NEW_TILES:
|
|
return (XP_UCHAR*)"New tiles: %s" XP_CR;
|
|
case STRSS_TRADED_FOR:
|
|
return (XP_UCHAR*)"Traded %s for %s.";
|
|
case STR_PASS:
|
|
return (XP_UCHAR*)"pass" XP_CR;
|
|
case STR_PHONY_REJECTED:
|
|
return (XP_UCHAR*)"Illegal word in move; turn lost!" XP_CR;
|
|
|
|
case STRD_ROBOT_TRADED:
|
|
return (XP_UCHAR*)"Robot traded tiles %d this turn.";
|
|
case STR_ROBOT_MOVED:
|
|
return (XP_UCHAR*)"The robot made this move:" XP_CR;
|
|
case STR_REMOTE_MOVED:
|
|
return (XP_UCHAR*)"Remote player made this move:" XP_CR;
|
|
|
|
case STR_PASSED:
|
|
return (XP_UCHAR*)"Passed";
|
|
case STRSD_SUMMARYSCORED:
|
|
return (XP_UCHAR*)"%s:%d";
|
|
case STRD_TRADED:
|
|
return (XP_UCHAR*)"Traded %d";
|
|
case STR_LOSTTURN:
|
|
return (XP_UCHAR*)"Lost turn";
|
|
|
|
case STRS_VALUES_HEADER:
|
|
return (XP_UCHAR*)"%s counts/values:" XP_CR;
|
|
|
|
default:
|
|
XP_LOGF( "stringCode=%d", stringCode );
|
|
return (XP_UCHAR*)"unknown code";
|
|
}
|
|
} // sym_util_getUserString
|
|
|
|
static XP_Bool
|
|
sym_util_warnIllegalWord( XW_UtilCtxt* /*uc*/, BadWordInfo* /*bwi*/,
|
|
XP_U16 /*turn*/, XP_Bool /*turnLost*/ )
|
|
{
|
|
return XP_FALSE;
|
|
}
|
|
|
|
#ifdef BEYOND_IR
|
|
/*static*/void
|
|
CXWordsAppView::sym_util_listenPortChange( XW_UtilCtxt* uc, XP_U16 aPort )
|
|
{
|
|
/* CXWordsAppView* self = (CXWordsAppView*)uc->closure; */
|
|
// self->iReadSock->SetListenPort( aPort );
|
|
/* self->iSendSock->Listen(); */
|
|
}
|
|
|
|
/*static*/void
|
|
CXWordsAppView::sym_util_addrChange( XW_UtilCtxt* uc,
|
|
const CommsAddrRec* aAddr )
|
|
{
|
|
CXWordsAppView* self = (CXWordsAppView*)uc->closure;
|
|
XP_LOGF( "util_addrChange: calling connect" );
|
|
self->iSendSock->ConnectL( aAddr );
|
|
(void)self->iSendSock->Listen();
|
|
}
|
|
#endif
|
|
|
|
#ifdef XWFEATURE_SEARCHLIMIT
|
|
static XP_Bool
|
|
sym_util_getTraySearchLimits(XW_UtilCtxt* /*uc*/, XP_U16* /*min*/, XP_U16* /*max*/ )
|
|
{
|
|
return XP_FALSE;
|
|
}
|
|
#endif
|
|
|
|
|
|
void
|
|
CXWordsAppView::SetUpUtil()
|
|
{
|
|
UtilVtable* vtable = iUtil.vtable;
|
|
iUtil.closure = (void*)this;
|
|
iUtil.gameInfo = &iGi;
|
|
MPASSIGN( iUtil.mpool, mpool );
|
|
|
|
vtable->m_util_getVTManager = sym_util_getVTManager;
|
|
#ifndef XWFEATURE_STANDALONE_ONLY
|
|
vtable->m_util_makeStreamFromAddr = sym_util_makeStreamFromAddr;
|
|
#endif
|
|
vtable->m_util_getSquareBonus = sym_util_getSquareBonus;
|
|
vtable->m_util_userError = sym_util_userError;
|
|
vtable->m_util_userQuery = sym_util_userQuery;
|
|
vtable->m_util_userPickTile = sym_util_userPickTile;
|
|
vtable->m_util_askPassword = sym_util_askPassword;
|
|
vtable->m_util_trayHiddenChange = sym_util_trayHiddenChange;
|
|
vtable->m_util_yOffsetChange = sym_util_yOffsetChange;
|
|
vtable->m_util_notifyGameOver = sym_util_notifyGameOverL;
|
|
vtable->m_util_hiliteCell = sym_util_hiliteCell;
|
|
vtable->m_util_engineProgressCallback = sym_util_engineProgressCallback;
|
|
vtable->m_util_setTimer = sym_util_setTimer;
|
|
vtable->m_util_requestTime = sym_util_requestTime;
|
|
vtable->m_util_getCurSeconds = sym_util_getCurSeconds;
|
|
vtable->m_util_makeEmptyDict = sym_util_makeEmptyDict;
|
|
vtable->m_util_getUserString = sym_util_getUserString;
|
|
vtable->m_util_warnIllegalWord = sym_util_warnIllegalWord;
|
|
#ifdef BEYOND_IR
|
|
vtable->m_util_addrChange = sym_util_addrChange;
|
|
#endif
|
|
#ifdef XWFEATURE_SEARCHLIMIT
|
|
vtable->m_util_getTraySearchLimits = sym_util_getTraySearchLimits;
|
|
#endif
|
|
}
|
|
|
|
// Load the current game from prefs or else create a new one.
|
|
// Eventually this will involve putting up the new game dialog.
|
|
void
|
|
CXWordsAppView::MakeOrLoadGameL()
|
|
{
|
|
if ( iCurGameName.Length() > 0 && iGamesMgr->Exists( &iCurGameName ) ) {
|
|
LoadOneGameL( &iCurGameName );
|
|
} else {
|
|
|
|
/***************************************************************
|
|
* PENDING The code here duplicates DoNewGame. Unify the two!!!!
|
|
***************************************************************/
|
|
|
|
gi_initPlayerInfo( MPPARM(mpool) &iGi, (XP_UCHAR*)"Player %d" );
|
|
|
|
#ifndef XWFEATURE_STANDALONE_ONLY
|
|
CommsAddrRec commsAddr;
|
|
if ( iGame.comms != NULL ) {
|
|
comms_getAddr( iGame.comms, &commsAddr );
|
|
} else {
|
|
commsAddr = iCommsAddr;
|
|
}
|
|
#endif
|
|
|
|
TGameInfoBuf gib( &iGi,
|
|
#ifndef XWFEATURE_STANDALONE_ONLY
|
|
&commsAddr,
|
|
#endif
|
|
iDictList );
|
|
if ( !CXWGameInfoDlg::DoGameInfoDlgL( MPPARM(mpool) &gib, ETrue ) ) {
|
|
User::Leave(-1);
|
|
}
|
|
|
|
gib.CopyToL( MPPARM(mpool) &iGi
|
|
#ifndef XWFEATURE_STANDALONE_ONLY
|
|
, &iCommsAddr
|
|
#endif
|
|
);
|
|
|
|
DictionaryCtxt* dict = sym_dictionary_makeL( MPPARM(mpool)
|
|
iGi.dictName );
|
|
User::LeaveIfNull( dict );
|
|
|
|
XP_U16 newGameID = SC( XP_U16, sym_util_getCurSeconds( &iUtil ) );
|
|
game_makeNewGame( MPPARM(mpool) &iGame, &iGi,
|
|
&iUtil, iDraw, newGameID, &iCp,
|
|
SYM_SEND, this );
|
|
model_setDictionary( iGame.model, dict );
|
|
|
|
#ifndef XWFEATURE_STANDALONE_ONLY
|
|
if ( iGame.comms ) {
|
|
comms_setAddr( iGame.comms, &iCommsAddr );
|
|
if ( iGi.serverRole == SERVER_ISCLIENT ) {
|
|
XWStreamCtxt* stream = MakeSimpleStream( sym_send_on_close );
|
|
server_initClientConnection( iGame.server, stream );
|
|
}
|
|
}
|
|
#endif
|
|
|
|
iGamesMgr->MakeDefaultName( &iCurGameName );
|
|
StoreOneGameL( &iCurGameName );
|
|
}
|
|
} /* MakeOrLoadGameL */
|
|
|
|
void
|
|
CXWordsAppView::DeleteGame()
|
|
{
|
|
game_dispose( &iGame );
|
|
gi_disposePlayerInfo( MPPARM(mpool) &iGi );
|
|
}
|
|
|
|
void
|
|
CXWordsAppView::PositionBoard()
|
|
{
|
|
const TRect rect = Rect();
|
|
const XP_U16 boardWidth = 15 * scaleBoardH;
|
|
const XP_U16 scoreTop = 25;
|
|
const XP_U16 scoreHt = 120;
|
|
|
|
board_setPos( iGame.board, 2, 2, XP_FALSE );
|
|
board_setScale( iGame.board, scaleBoardH, scaleBoardV );
|
|
|
|
XP_U16 scoreLeft = 2 + boardWidth + 2 + 3; /* 2 for border, 3 for gap */
|
|
XP_U16 scoreRight = SC(XP_U16, rect.iBr.iX - 2 - 1); /* 2 for border */
|
|
board_setScoreboardLoc( iGame.board, scoreLeft, scoreTop,
|
|
SC( XP_U16, scoreRight - scoreLeft - 1),
|
|
scoreHt, XP_FALSE );
|
|
board_setYOffset( iGame.board, 0 );
|
|
|
|
board_setTrayLoc( iGame.board,
|
|
2 + (15 * scaleBoardH) + 5, // to right of board
|
|
// make tray bottom same as board's
|
|
2 + (15*scaleBoardV) - scaleTrayV,
|
|
scaleTrayH, scaleTrayV, // v and h scale
|
|
3 ); // divider width
|
|
board_invalAll( iGame.board );
|
|
|
|
iTitleBox.SetRect( scoreLeft, 2, scoreRight, scoreTop - 4 );
|
|
} // PositionBoard
|
|
|
|
int
|
|
CXWordsAppView::HandleCommand( TInt aCommand )
|
|
{
|
|
XP_Bool draw = XP_FALSE;
|
|
XP_Bool notDone;
|
|
|
|
switch ( aCommand ) {
|
|
|
|
case XW_NEWGAME_COMMAND:
|
|
draw = DoNewGame();
|
|
break;
|
|
|
|
case XW_SAVEDGAMES_COMMAND:
|
|
draw = DoSavedGames();
|
|
(void)server_do( iGame.server );
|
|
break;
|
|
case XW_PREFS_COMMAND:
|
|
case XW_ABOUT_COMMAND:
|
|
NotImpl();
|
|
break;
|
|
|
|
case XW_VALUES_COMMAND:
|
|
if ( iGame.server != NULL ) {
|
|
XWStreamCtxt* stream = MakeSimpleStream( NULL );
|
|
if ( stream != NULL ) {
|
|
server_formatDictCounts( iGame.server, stream, 7 ); /* 4: ncols */
|
|
CXWAskDlg::DoInfoDlg(MPPARM(mpool) stream, ETrue);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case XW_REMAIN_COMMAND:
|
|
if ( iGame.board != NULL ) {
|
|
XWStreamCtxt* stream = MakeSimpleStream( NULL );
|
|
if ( stream ) {
|
|
board_formatRemainingTiles( iGame.board, stream );
|
|
CXWAskDlg::DoInfoDlg(MPPARM(mpool) stream, ETrue);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case XW_CURINFO_COMMAND: {
|
|
NotImpl();
|
|
/* TGameInfoBuf gib( &iGi, iDictList ); */
|
|
/* CXWGameInfoDlg::DoGameInfoDlgL( MPPARM(mpool) &gib, EFalse ); */
|
|
}
|
|
break;
|
|
|
|
case XW_HISTORY_COMMAND:
|
|
if ( iGame.server ) {
|
|
XP_Bool gameOver = server_getGameIsOver( iGame.server );
|
|
XWStreamCtxt* stream = MakeSimpleStream( NULL );
|
|
|
|
model_writeGameHistory( iGame.model, stream,
|
|
iGame.server, gameOver );
|
|
if ( stream_getSize( stream ) > 0 ) {
|
|
CXWAskDlg::DoInfoDlg( MPPARM(mpool) stream, ETrue );
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case XW_FINALSCORES_COMMAND:
|
|
if ( server_getGameIsOver( iGame.server ) ) {
|
|
DisplayFinalScoresL();
|
|
} else if ( AskFromResId( R_CONFIRM_END_GAME ) ) {
|
|
server_endGame( iGame.server );
|
|
draw = ETrue;
|
|
}
|
|
break;
|
|
|
|
case XW_HINT_COMMAND:
|
|
#ifdef XWFEATURE_SEARCHLIMIT
|
|
case XW_LIMHINT_COMMAND:
|
|
#endif
|
|
break;
|
|
case XW_NEXTHINT_COMMAND:
|
|
draw = board_requestHint( iGame.board,
|
|
#ifdef XWFEATURE_SEARCHLIMIT
|
|
XP_FALSE,
|
|
#endif
|
|
|
|
¬Done );
|
|
break;
|
|
case XW_UNDOCUR_COMMAND:
|
|
draw = board_replaceTiles( iGame.board );
|
|
break;
|
|
case XW_UNDOLAST_COMMAND:
|
|
draw = server_handleUndo( iGame.server );
|
|
break;
|
|
case XW_DONE_COMMAND:
|
|
draw = board_commitTurn( iGame.board );
|
|
break;
|
|
case XW_JUGGLE_COMMAND:
|
|
draw = board_juggleTray( iGame.board );
|
|
break;
|
|
|
|
case XW_TRADE_COMMAND:
|
|
draw = board_beginTrade( iGame.board );
|
|
break;
|
|
|
|
case XW_HIDETRAY_COMMAND:
|
|
if ( TRAY_REVEALED == board_getTrayVisState( iGame.board ) ) {
|
|
draw = board_hideTray( iGame.board );
|
|
} else {
|
|
draw = board_showTray( iGame.board );
|
|
}
|
|
break;
|
|
|
|
case XW_FLIP_COMMAND:
|
|
draw = board_flip( iGame.board );
|
|
break;
|
|
case XW_TOGGLEVALS_COMMAND:
|
|
draw = board_toggle_showValues( iGame.board );
|
|
break;
|
|
|
|
#ifndef XWFEATURE_STANDALONE_ONLY
|
|
case XW_RESEND_COMMAND:
|
|
if ( iGame.comms != NULL ) {
|
|
(void)comms_resendAll( iGame.comms );
|
|
}
|
|
#endif
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
if ( draw ) {
|
|
DoImmediateDraw();
|
|
}
|
|
|
|
return 1;
|
|
} // CXWordsAppView::HandleCommand
|
|
|
|
void
|
|
CXWordsAppView::Exiting()
|
|
{
|
|
StoreOneGameL( &iCurGameName );
|
|
WritePrefs();
|
|
} /* Exiting */
|
|
|
|
TBool
|
|
CXWordsAppView::HandleKeyEvent( const TKeyEvent& aKeyEvent )
|
|
{
|
|
XP_Bool draw = XP_FALSE;
|
|
XP_Key key = XP_KEY_NONE;
|
|
TChar chr(aKeyEvent.iCode);
|
|
|
|
switch ( chr ) {
|
|
|
|
case EKeyTab: // 2 // this is probably for laptop only! :-)
|
|
key = XP_FOCUSCHANGE_KEY;
|
|
break;
|
|
|
|
case EKeyEnter:
|
|
key = XP_RETURN_KEY;
|
|
break;
|
|
case EKeyBackspace:
|
|
key = XP_CURSOR_KEY_DEL;
|
|
break;
|
|
case EKeyLeftArrow: // 14
|
|
key = XP_CURSOR_KEY_LEFT;
|
|
break;
|
|
case EKeyRightArrow: // 15
|
|
key = XP_CURSOR_KEY_RIGHT;
|
|
break;
|
|
case EKeyUpArrow: // 16
|
|
key = XP_CURSOR_KEY_UP;
|
|
break;
|
|
case EKeyDownArrow: // 17
|
|
key = XP_CURSOR_KEY_DOWN;
|
|
break;
|
|
|
|
default:
|
|
key = (XP_Key)aKeyEvent.iScanCode;
|
|
if ( key < 0x20 || key > 0x7f ) {
|
|
key = XP_KEY_NONE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if ( iGame.board != NULL ) {
|
|
if ( key != XP_KEY_NONE ) {
|
|
draw = board_handleKey( iGame.board, key );
|
|
}
|
|
}
|
|
|
|
if ( draw ) {
|
|
DoImmediateDraw();
|
|
}
|
|
|
|
// handled if it's one we recognize. This is probably too broad!!!
|
|
return key != XP_KEY_NONE;
|
|
}
|
|
|
|
/* static */ TInt
|
|
CXWordsAppView::TimerCallback( TAny* aPtr )
|
|
{
|
|
CXWordsAppView* me = (CXWordsAppView*)aPtr;
|
|
|
|
if ( 0 ) {
|
|
|
|
#ifndef XWFEATURE_STANDALONE_ONLY
|
|
/* Only do one per call. Packets are higher priority */
|
|
} else if ( me->iTimerReasons[EProcessPacket] > 0 ) {
|
|
--me->iTimerReasons[EProcessPacket];
|
|
XP_ASSERT( me->iTimerReasons[EProcessPacket] == 0 );
|
|
|
|
XP_Bool draw = XP_FALSE;
|
|
|
|
XWStreamCtxt* stream = me->MakeSimpleStream( NULL );
|
|
|
|
TPtrC8 packet = (*me->iNewPacketQueue)[0];
|
|
stream_putBytes( stream, (void*)packet.Ptr(), packet.Length() );
|
|
me->iNewPacketQueue->Delete(0);
|
|
XP_LOGF( "pulling packet off head of queue; there are %d left",
|
|
me->iNewPacketQueue->Count() );
|
|
|
|
CommsAddrRec addr;
|
|
addr.conType = COMMS_CONN_RELAY;
|
|
if ( comms_checkIncomingStream( me->iGame.comms, stream, &addr ) ) {
|
|
draw = server_receiveMessage( me->iGame.server, stream );
|
|
}
|
|
stream_destroy( stream );
|
|
sym_util_requestTime( &me->iUtil );
|
|
|
|
if ( draw ) {
|
|
me->DoImmediateDraw();
|
|
}
|
|
#endif
|
|
} else if ( me->iTimerReasons[EUtilRequest] > 0 ) {
|
|
--me->iTimerReasons[EUtilRequest];
|
|
if ( server_do( me->iGame.server ) ) {
|
|
me->DoImmediateDraw();
|
|
}
|
|
}
|
|
|
|
return --me->iTimerRunCount > 0;
|
|
}
|
|
|
|
XWStreamCtxt*
|
|
CXWordsAppView::MakeSimpleStream( MemStreamCloseCallback cb,
|
|
XP_U16 channelNo )
|
|
{
|
|
return mem_stream_make( MPPARM(mpool)
|
|
iVtMgr, (void*)this,
|
|
channelNo, cb );
|
|
} /* MakeSimpleStream */
|
|
|
|
void
|
|
CXWordsAppView::DisplayFinalScoresL()
|
|
{
|
|
XWStreamCtxt* stream = MakeSimpleStream( NULL );
|
|
User::LeaveIfNull( stream );
|
|
|
|
server_writeFinalScores( iGame.server, stream );
|
|
|
|
CXWAskDlg::DoInfoDlg( MPPARM(mpool) stream, ETrue );
|
|
} /* displayFinalScores */
|
|
|
|
TBool
|
|
CXWordsAppView::AskFromResId( TInt aResource )
|
|
{
|
|
TBuf16<128> message;
|
|
StringLoader::Load( message, aResource );
|
|
|
|
return CXWAskDlg::DoAskDlg( MPPARM(mpool) &message );
|
|
}
|
|
|
|
static void
|
|
logOneFile( TPtrC name )
|
|
{
|
|
TBuf8<128> tmpb;
|
|
tmpb.Copy( name );
|
|
XP_UCHAR buf[128];
|
|
XP_MEMCPY( buf, (void*)(tmpb.Ptr()), tmpb.Length() );
|
|
buf[tmpb.Length()] = '\0';
|
|
XP_LOGF( "found file %s", buf );
|
|
} /* logOneFile */
|
|
|
|
TBool
|
|
CXWordsAppView::FindAllDicts()
|
|
{
|
|
/* NOTE: CEikFileNameSelector might be the way to do this and the display
|
|
* of the list in the game setup dialog.
|
|
*/
|
|
TBool found = EFalse;
|
|
RFs fs = iCoeEnv->FsSession();
|
|
|
|
TFindFile file_finder( fs );
|
|
CDir* file_list;
|
|
_LIT( wildName, "*.xwd" );
|
|
|
|
TFileName dir;
|
|
GetXwordsRWDir( &dir, EDictsLoc );
|
|
|
|
TInt err = file_finder.FindWildByDir( wildName, dir, file_list );
|
|
if ( err == KErrNone ) {
|
|
|
|
CleanupStack::PushL( file_list );
|
|
iDictList = new (ELeave)CDesC16ArrayFlat( file_list->Count() );
|
|
|
|
TInt i;
|
|
for ( i = 0; i < file_list->Count(); i++ ) {
|
|
TParse fullentry;
|
|
fullentry.Set((*file_list)[i].iName,& file_finder.File(),NULL);
|
|
logOneFile( fullentry.Name() );
|
|
iDictList->AppendL( fullentry.Name() );
|
|
}
|
|
|
|
CleanupStack::PopAndDestroy( file_list );
|
|
found = ETrue;
|
|
}
|
|
|
|
return found;
|
|
} /* FindAllDicts */
|
|
|
|
void
|
|
CXWordsAppView::UserErrorFromID( TInt aResource )
|
|
{
|
|
if ( aResource != 0 ) {
|
|
_LIT(title,"Oops");
|
|
TBuf16<128> message;
|
|
StringLoader::Load( message, aResource );
|
|
#if defined SERIES_60
|
|
CEikInfoDialog::RunDlgLD( title, message );
|
|
#elif defined SERIES_80
|
|
CCknInfoDialog::RunDlgLD( title, message );
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void
|
|
CXWordsAppView::NotImpl()
|
|
{
|
|
UserErrorFromID( R_ALERT_FEATURE_PENDING );
|
|
} /* NotImpl */
|
|
|
|
void
|
|
CXWordsAppView::GetXwordsRWDir( TFileName* aPathRef, TDriveReason aWhy )
|
|
{
|
|
aPathRef->Delete( 0, aPathRef->Length() );
|
|
|
|
switch( aWhy ) {
|
|
case EGamesLoc:
|
|
aPathRef->Append( _L("C:") ); /* read-write: must be on C */
|
|
break;
|
|
case EDictsLoc:
|
|
#if defined __WINS__
|
|
aPathRef->Append( _L("Z:") );
|
|
#elif defined __MARM__
|
|
aPathRef->Append( _L("C:") );
|
|
#endif
|
|
break;
|
|
case EPrefsLoc:
|
|
break; /* don't want a drive */
|
|
}
|
|
|
|
#ifdef XWORDS_DIR
|
|
_LIT( dir,"\\system\\apps\\" XWORDS_DIR "\\" );
|
|
#else
|
|
_LIT( dir,"\\system\\apps\\xwords_80\\" );
|
|
#endif
|
|
aPathRef->Append( dir );
|
|
} /* GetXwordsRWDir */
|
|
|
|
_LIT(filename,"xwdata.dat");
|
|
TBool
|
|
CXWordsAppView::LoadPrefs()
|
|
{
|
|
RFs fs = iCoeEnv->FsSession();
|
|
|
|
TFileName nameD;
|
|
GetXwordsRWDir( &nameD, EPrefsLoc );
|
|
nameD.Append( filename );
|
|
|
|
/* Read in prefs etc. */
|
|
RFileReadStream reader;
|
|
CleanupClosePushL(reader);
|
|
TInt err = reader.Open( fs, nameD, EFileRead );
|
|
|
|
TBool found = err == KErrNone;
|
|
if ( found ) {
|
|
iCp.showBoardArrow = reader.ReadInt8L();
|
|
iCp.showRobotScores = reader.ReadInt8L();
|
|
reader >> iCurGameName;
|
|
}
|
|
CleanupStack::PopAndDestroy( &reader ); // reader
|
|
|
|
return found;
|
|
} /* LoadPrefs */
|
|
|
|
void
|
|
CXWordsAppView::WritePrefs()
|
|
{
|
|
RFs fs = iCoeEnv->FsSession();
|
|
|
|
TFileName nameD;
|
|
GetXwordsRWDir( &nameD, EPrefsLoc );
|
|
nameD.Append( filename );
|
|
|
|
RFileWriteStream writer;
|
|
CleanupClosePushL(writer);
|
|
User::LeaveIfError( writer.Replace( fs, nameD, EFileWrite ) );
|
|
|
|
writer.WriteInt8L( iCp.showBoardArrow );
|
|
writer.WriteInt8L( iCp.showRobotScores );
|
|
|
|
writer << iCurGameName;
|
|
|
|
CleanupStack::PopAndDestroy( &writer ); // writer
|
|
} /* WritePrefs */
|
|
|
|
void
|
|
CXWordsAppView::InitPrefs()
|
|
{
|
|
iCp.showBoardArrow = XP_TRUE; // default because no pen
|
|
iCp.showRobotScores = XP_FALSE;
|
|
|
|
#ifndef XWFEATURE_STANDALONE_ONLY
|
|
iGi.serverRole = SERVER_STANDALONE;
|
|
iCommsAddr.conType = COMMS_CONN_RELAY;
|
|
char* name = "aphraea.org";
|
|
XP_MEMCPY( iCommsAddr.u.ip_relay.hostName, name, XP_STRLEN(name) + 1 );
|
|
iCommsAddr.u.ip_relay.port = 10999;
|
|
#endif
|
|
}
|
|
|
|
TBool
|
|
CXWordsAppView::DoNewGame()
|
|
{
|
|
TBool draw = EFalse;
|
|
|
|
TBool save = AskSaveGame();
|
|
|
|
#ifndef XWFEATURE_STANDALONE_ONLY
|
|
CommsAddrRec commsAddr;
|
|
if ( iGame.comms != NULL ) {
|
|
comms_getAddr( iGame.comms, &commsAddr );
|
|
} else {
|
|
commsAddr = iCommsAddr;
|
|
}
|
|
#endif
|
|
|
|
TGameInfoBuf gib( &iGi,
|
|
#ifndef XWFEATURE_STANDALONE_ONLY
|
|
&commsAddr,
|
|
#endif
|
|
iDictList );
|
|
if ( CXWGameInfoDlg::DoGameInfoDlgL( MPPARM(mpool) &gib, ETrue ) ) {
|
|
|
|
if ( save ) {
|
|
StoreOneGameL( &iCurGameName );
|
|
iGamesMgr->MakeDefaultName( &iCurGameName );
|
|
}
|
|
|
|
gib.CopyToL( MPPARM(mpool) &iGi
|
|
#ifndef XWFEATURE_STANDALONE_ONLY
|
|
, &iCommsAddr
|
|
#endif
|
|
);
|
|
XP_U16 newGameID = SC( XP_U16,sym_util_getCurSeconds( &iUtil ) );
|
|
game_reset( MPPARM(mpool) &iGame, &iGi, newGameID,
|
|
&iCp, SYM_SEND, this );
|
|
|
|
DictionaryCtxt* prevDict = model_getDictionary( iGame.model );
|
|
if ( 0 != XP_STRCMP( dict_getName(prevDict), iGi.dictName ) ) {
|
|
dict_destroy( prevDict );
|
|
DictionaryCtxt* dict = sym_dictionary_makeL( MPPARM(mpool)
|
|
iGi.dictName );
|
|
model_setDictionary( iGame.model, dict );
|
|
}
|
|
#ifndef XWFEATURE_STANDALONE_ONLY
|
|
if ( iGame.comms ) {
|
|
comms_setAddr( iGame.comms, &iCommsAddr );
|
|
|
|
if ( iGi.serverRole == SERVER_ISCLIENT ) {
|
|
XWStreamCtxt* stream = MakeSimpleStream( sym_send_on_close );
|
|
// server deletes stream
|
|
server_initClientConnection( iGame.server, stream );
|
|
}
|
|
}
|
|
#endif
|
|
|
|
board_invalAll( iGame.board );
|
|
(void)server_do( iGame.server ); // get tiles assigned etc.
|
|
draw = ETrue;
|
|
}
|
|
return draw;
|
|
} /* DoNewGame */
|
|
|
|
TBool
|
|
CXWordsAppView::DoSavedGames()
|
|
{
|
|
StoreOneGameL( &iCurGameName );
|
|
|
|
TGameName openName;
|
|
TBool confirmed = CXSavedGamesDlg::DoGamesPicker( MPPARM(mpool)
|
|
this,
|
|
iGamesMgr,
|
|
&iCurGameName,
|
|
&openName );
|
|
if ( confirmed ) {
|
|
if ( 0 != iCurGameName.Compare( openName ) ) {
|
|
|
|
iCurGameName = openName;
|
|
|
|
game_dispose( &iGame );
|
|
gi_disposePlayerInfo( MPPARM(mpool) &iGi );
|
|
|
|
LoadOneGameL( &iCurGameName );
|
|
Window().Invalidate( iTitleBox );
|
|
}
|
|
}
|
|
return confirmed;
|
|
} /* DoSavedGames */
|
|
|
|
void
|
|
CXWordsAppView::LoadOneGameL( TGameName* aGameName )
|
|
{
|
|
XWStreamCtxt* stream = MakeSimpleStream( NULL );
|
|
|
|
iGamesMgr->LoadGameL( aGameName, stream );
|
|
|
|
XP_U16 len = stream_getU8( stream );
|
|
XP_UCHAR dictName[32];
|
|
stream_getBytes( stream, dictName, len );
|
|
dictName[len] = '\0';
|
|
|
|
DictionaryCtxt* dict = sym_dictionary_makeL( MPPARM(mpool) dictName );
|
|
XP_ASSERT( !!dict );
|
|
|
|
game_makeFromStream( MPPARM(mpool) stream, &iGame,
|
|
&iGi, dict, &iUtil, iDraw, &iCp,
|
|
SYM_SEND, this );
|
|
stream_destroy( stream );
|
|
|
|
PositionBoard();
|
|
}
|
|
|
|
void
|
|
CXWordsAppView::StoreOneGameL( TGameName* aGameName )
|
|
{
|
|
XWStreamCtxt* stream = MakeSimpleStream( NULL );
|
|
|
|
/* save the dict. NOTE: should be possible to do away with this! */
|
|
XP_U32 len = XP_STRLEN(iGi.dictName);
|
|
XP_ASSERT( len <= 0xFF );
|
|
stream_putU8( stream, SC(XP_U8, len) );
|
|
stream_putBytes( stream, iGi.dictName, SC(XP_U16, len) );
|
|
|
|
/* Now the game */
|
|
game_saveToStream( &iGame, &iGi, stream );
|
|
|
|
iGamesMgr->StoreGameL( aGameName, stream );
|
|
stream_destroy( stream );
|
|
}
|
|
|
|
XP_Bool
|
|
CXWordsAppView::UserQuery( UtilQueryID aId, XWStreamCtxt* aStream )
|
|
{
|
|
TInt resID = 0;
|
|
|
|
switch ( aId ) {
|
|
case QUERY_ROBOT_MOVE:
|
|
case QUERY_ROBOT_TRADE:
|
|
case QUERY_COMMIT_TURN:
|
|
XP_ASSERT( aStream );
|
|
return CXWAskDlg::DoAskDlg( MPPARM(mpool) aStream, EFalse );
|
|
case QUERY_COMMIT_TRADE:
|
|
XP_ASSERT( !aStream );
|
|
resID = R_CONFIRM_TRADE;
|
|
break;
|
|
case SYM_QUERY_CONFIRM_DELGAME:
|
|
XP_ASSERT( !aStream );
|
|
resID = R_CONFIRM_DELGAME;
|
|
break;
|
|
}
|
|
if ( resID != 0 ) {
|
|
return AskFromResId( resID );
|
|
}
|
|
XP_ASSERT( 0 );
|
|
return XP_FALSE;
|
|
} /* sym_util_userQuery */
|
|
|
|
void
|
|
CXWordsAppView::DoImmediateDraw()
|
|
{
|
|
ActivateGc();
|
|
|
|
XP_ASSERT( iGame.board != NULL );
|
|
board_draw( iGame.board );
|
|
|
|
DeactivateGc();
|
|
} /* DoImmediateDraw */
|
|
|
|
void
|
|
CXWordsAppView::DrawGameName() const
|
|
{
|
|
if ( iGi.dictName != NULL ) {
|
|
TBuf16<66> buf;
|
|
buf.Copy( TBuf8<32>(iGi.dictName) );
|
|
buf.Insert( 0, _L("::") );
|
|
buf.Insert( 0, iCurGameName );
|
|
|
|
CWindowGc& gc = SystemGc();
|
|
gc.SetPenStyle( CGraphicsContext::ESolidPen );
|
|
gc.SetPenColor( KRgbBlack );
|
|
gc.SetBrushColor( KRgbGray );
|
|
gc.SetBrushStyle( CGraphicsContext::ESolidBrush );
|
|
|
|
gc.UseFont( iCoeEnv->NormalFont() );
|
|
gc.DrawText( buf, iTitleBox, iTitleBox.Height() - 4,/*TInt aBaselineOffset*/
|
|
CGraphicsContext::ECenter );
|
|
gc.DiscardFont();
|
|
}
|
|
}
|
|
|
|
#ifndef XWFEATURE_STANDALONE_ONLY
|
|
|
|
/*static*/ void
|
|
CXWordsAppView::PacketReceived( const TDesC8* aBuf, void* aClosure )
|
|
{
|
|
CXWordsAppView* me = (CXWordsAppView*)aClosure;
|
|
|
|
TInt count = me->iNewPacketQueue->Count();
|
|
me->iNewPacketQueue->InsertL( count, *aBuf );
|
|
XP_LOGF( "inserted packet: now number %d", count );
|
|
|
|
me->StartIdleTimer( EProcessPacket );
|
|
} /* CXWordsAppView::PacketReceived */
|
|
|
|
/*static*/ XP_S16
|
|
CXWordsAppView::sym_send( XP_U8* aBuf, XP_U16 aLen, CommsAddrRec* aAddr,
|
|
void* aClosure )
|
|
{
|
|
CommsAddrRec addr;
|
|
XP_S16 result = -1;
|
|
CXWordsAppView* self = (CXWordsAppView*)aClosure;
|
|
|
|
if ( aAddr == NULL ) {
|
|
comms_getAddr( self->iGame.comms, &addr );
|
|
aAddr = &addr;
|
|
}
|
|
|
|
if ( self->iSendSock->SendL( aBuf, aLen, aAddr ) ) {
|
|
result = aLen;
|
|
}
|
|
|
|
/* Can't call listen until we've sent something.... */
|
|
self->iSendSock->Listen();
|
|
|
|
return result;
|
|
} /* sym_send */
|
|
|
|
/*static*/ void
|
|
CXWordsAppView::sym_send_on_close( XWStreamCtxt* aStream, void* aClosure )
|
|
{
|
|
XP_LOGF( "sym_send_on_close called" );
|
|
CXWordsAppView* self = (CXWordsAppView*)aClosure;
|
|
|
|
comms_send( self->iGame.comms, aStream );
|
|
}
|
|
#endif
|
|
|
|
void
|
|
CXWordsAppView::StartIdleTimer( XWTimerReason aWhy )
|
|
{
|
|
++iTimerReasons[aWhy];
|
|
|
|
if ( ++iTimerRunCount == 1 ) {
|
|
iRequestTimer->Start( TCallBack( CXWordsAppView::TimerCallback,
|
|
(TAny*)this ) );
|
|
}
|
|
}
|