checked in from personal archive

This commit is contained in:
ehouse 2003-11-16 19:23:48 +00:00
parent b3d53f1bd8
commit 7f17376766
13 changed files with 2739 additions and 0 deletions

226
palm/Makefile Normal file
View file

@ -0,0 +1,226 @@
# -*- mode: Makefile; -*-
# Copyright 2002 by Eric House (fixin@peak.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.
PLATFORM=palm
LANG=en_US
TARGET=$(PLATFORM)/xwords4.prc
ROOTNAME = Crosswords
BITMAPS = ./bmps
NAME = "Crosswords"
TYPE = appl
ICONTEXT = "Crosswords"
APPID = Xwr4
MLPREFIX = /usr
DICT = $(shell echo $$BASENG_PATH)
#OWNERNAME = "Eric House"
NO_REG_REQUIRED = -DNO_REG_REQUIRED
PALM_TOOLS_PREFIX = $(shell echo $$PALM_TOOLS_PREFIX)
ifeq (x$(PALM_TOOLS_PREFIX)x, xx)
PALM_TOOLS_PREFIX = m68k-palmos-
endif
#PALM_TOOLS_PREFIX=m68k-palmos-coff-
CC = $(PALM_TOOLS_PREFIX)gcc
AR = $(PALM_TOOLS_PREFIX)ar
MULTILINK = $(PALM_TOOLS_PREFIX)multilink
PAR = par
PILRC = pilrc
MULTILINK_OPTIONS = -basename $(ROOTNAME) -segmentsize 27k -g \
-deadstrip -verbose -gdb-script app.gdb
ifneq (x$(OWNERNAME)x,xx)
HASHDEF = -DOWNER_HASH=$$(./namehash $(OWNERNAME))
endif
MYDEFINES = -DXW_FEATURE_UTILS -DPOINTER_SUPPORT -DKEY_SUPPORT \
-DOVERRIDE_EDGE_FOR_INDEX -DDIRECT_PALMOS_CALLS -DCOLOR_SUPPORT \
-DSHOW_PROGRESS \
$(HASHDEF) $(NO_REG_REQUIRED)
# turn on letting users pick tiles "face-up"
# MYDEFINES += -DFEATURE_TRAY_EDIT
MYDEFINES += -DBEYOND_IR
ifdef XWFEATURE_STANDALONE_ONLY
MYDEFINES += -DXWFEATURE_STANDALONE_ONLY
else
MYDEFINES += -DIR_SUPPORT -DIR_EXCHMGR
endif
# -DEIGHT_TILES
# -DSUPPORT_SONY_JOGDIAL
# HS_DUO_SUPPORT = 1
DEFINES += -DPLATFORM_PALM -D__BIG_ENDIAN $(MYDEFINES)
BITMAP_RSRCS = \
$(BITMAPS)/rightarrow.pbitm \
$(BITMAPS)/downarrow.pbitm \
$(BITMAPS)/flipbutton.pbitm \
$(BITMAPS)/valuebutton.pbitm \
$(BITMAPS)/lightbulb.pbitm \
$(BITMAPS)/traybuttons.pbitm \
$(BITMAPS)/showtray.pbitm \
$(BITMAPS)/xwords4.pbitm \
$(BITMAPS)/xwcoloricon.ppm \
$(BITMAPS)/xwords4small.pbitm \
INCLUDES += -I/usr/local/share/palmdev/sdk-4.0/Extensions/ExpansionMgr
ifneq (x$(HS_DUO_SUPPORT)x, xx)
INCLUDES += -I/usr/local/share/palmdev/duoIncs
INCLUDES += -I/usr/local/share/palmdev/duoIncs/68K
INCLUDES += -I/usr/local/share/palmdev/duoIncs/68K/System
INCLUDES += -I/usr/local/share/palmdev/duoIncs/Common/System
MYDEFINES += -DHS_DUO_SUPPORT
FNAVS = ./fnav03e9.bin
endif
CSFLAGS = -O2 -g -S -Wall -DAPPID=\'$(APPID)\' $(DEFINES) $(INCLUDES)
#CFLAGS = -O2 -g -Wall -DAPPID=\'$(APPID)\' $(DEFINES) $(INCLUDES) -palmos3.5
CFLAGS = -O2 -g -Wall -DAPPID=\'$(APPID)\' $(DEFINES) $(INCLUDES)
# In the non-debug mode (for which DONT_OMIT is undefined) build without
# the frame pointer.
ifneq ($(DONT_OMIT), true)
CSFLAGS += -fomit-frame-pointer
CFLAGS += -fomit-frame-pointer
endif
include ../common/config.mk
OBJS = $(PLATFORM)/palmmain.o \
$(PLATFORM)/palmsavg.o \
$(PLATFORM)/gameutil.o \
$(PLATFORM)/newgame.o \
$(PLATFORM)/palmdict.o \
$(PLATFORM)/palmdraw.o \
$(PLATFORM)/palmutil.o \
$(PLATFORM)/dictui.o \
$(PLATFORM)/dictlist.o \
$(PLATFORM)/palmir.o \
$(PLATFORM)/prefsdlg.o \
$(PLATFORM)/connsdlg.o \
$(COMMONOBJ)
include ../common/rules.mk
$(TARGET): $(PLATFORM)/objs.prc $(PLATFORM)/res.prc
$(PAR) -c -a 'resource|backup' $@ $(NAME) $(TYPE) $(APPID) $^
if [ x$(shell echo $$XW_UPLOAD_DIR) != x ]; then \
zip -j xw4.zip $@; \
mv xw4.zip $(shell echo $$XW_UPLOAD_DIR); \
cp $@ $(shell echo $$XW_UPLOAD_DIR); \
fi
solo:
$(MAKE) XWFEATURE_STANDALONE_ONLY=1
debug:
$(MAKE) MYDEFINES="$(MYDEFINES) -DDEBUG" DONT_OMIT=true
memdebug:
$(MAKE) MYDEFINES="$(MYDEFINES) -DDEBUG -DMEM_DEBUG" DONT_OMIT=true
gremlins:
$(MAKE) MYDEFINES="$(MYDEFINES) -DDEBUG -DMEM_DEBUG -DFOR_GREMLINS" DONT_OMIT=true
#
REL=405
REL_PATH=public_html/xwords/4.0.5
ship-all:
make clean; make; \
make; (cd xwconfig && make); \
for l in fr_FR en_US es_ES es_CT sv_SE de_DE ; do \
make clean; \
make LANG=$$l; \
zip -j xw$(REL)_$$l.zip xwconfig/xwconfig.prc $(TARGET); \
done
.S.o:
$(CC) $(TARGETFLAGS) -c $<
.c.s:
$(CC) $(CSFLAGS) $<
$(BITMAPS)/%.pbitm: $(BITMAPS)/%.bmp
bmtoa $< > $@
$(PLATFORM)/objs.prc: LocalizedStrIncludes.h $(OBJS) gdbload
@rm -f *.grc *.bin
$(MULTILINK) $(MULTILINK_OPTIONS) $(OBJS)
$(PAR) -c -a resource $(PLATFORM)/objs.prc Code rsrc rsrc *.grc
@rm -f *.grc *.bin
$(PLATFORM)/res.prc: xwords4.rcp $(HEADERS) $(CODESEG) StrL03e8.bin $(FNAVS)
$(PILRC) $< >/dev/null
$(PAR) -c -a 'resource' $@ Rsrc rsrc rsrc *.bin
rm -f $< *.bin
xwords4.rcp: l10n/xwords4_$(LANG).rcp.pre xwords4defines.h $(BITMAP_RSRCS)
gcc -x c -E -P $(INCLUDES) $(MYDEFINES) \
-DICONTEXT=\"$(ICONTEXT)\" $< > $@
LocalizedStrIncludes.h StrL03e8.bin: ./l10n/StrRes_$(LANG).pre ./l10n/mkstrsres.c
gcc $(CFLAGS) $(FORMATDEFINES) \
-DLANGSTRFILE=\"$<\" ./l10n/mkstrsres.c \
-o mkstrsres
./mkstrsres StrL03e8.bin LocalizedStrIncludes.h
rm -f mkstrsres
namehash: namehash.c ownerhash.h
fnavgen: fnavgen.c
gcc $< -o $@
$(FNAVS): ./fnavgen
./$<
# GDB seems confused by relative paths these days. So generate the
# file rather than trying to keep in in cvs.
gdbload:
echo "source app.gdb" > $@
echo "load-segments" >> $@
echo "dir $(shell pwd)" >> $@
echo "dir $(shell pwd)/../common" >> $@
clean:
cd ../common && $(MAKE) PLATFORM=$(PLATFORM) $@
rm -rf $(PLATFORM)/*.[oa] xwords4 *.bin *.stamp *.[pg]rc \
xwords4.rcp *.btxt $(PLATFORM)/* $(CODESEG) \
LocalizedStrIncludes.h gdbload
#cmod03E8.bin: palmdraw.c Makefile
# $(CC) -O2 -nostartfiles $(INCLUDES) $(MYDEFINES) -o tmp $<
# $(OBJRES) tmp
# mv code0001.tmp.grc $@ ; rm *.tmp.grc
help:
@echo make memdebug OR
@echo make LANG=en_US OR
@echo make ship-all OR
@echo make gremlins OR
@echo make clean

21
palm/callback.h Normal file
View file

@ -0,0 +1,21 @@
/* copied from _Palm Programming_ p. 79*/
#ifndef __CALLBACK__
#define __CALLBACK__
#ifdef MW_COMPILER
/* these are no-ops for MW as I understand it */
# define CALLBACK_PROLOGUE()
# define CALLBACK_EPILOGUE()
#else
register void *reg_a4 asm("%a4");
#define CALLBACK_PROLOGUE() \
{ void* __save_a4 = reg_a4; asm("move.l %%a5,%%a4; sub.l #edata,%%a4" : :);
#define CALLBACK_EPILOGUE() reg_a4 = __save_a4;}
#endif /* MW_COMPILER */
#endif

320
palm/connsdlg.c Normal file
View file

@ -0,0 +1,320 @@
/* -*-mode: C; fill-column: 77; c-basic-offset: 4; -*- */
/*
* Copyright 2003 by Eric House (fixin@peak.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.
*/
#ifdef BEYOND_IR
#include <NetMgr.h>
#include "callback.h"
#include "connsdlg.h"
#include "palmmain.h"
#include "palmutil.h"
#include "palmir.h"
/* When user pops up via Host gadget, we want to get the port to listen on.
* When pops up via the Guest gadget, we want to get the port and IP address
* of the host AS WELL AS the local port that we'll tell it we're listening
* on. We need local state for both, since user can switch between them and
* expect state to live as long as the parent dialog isn't exited.
*/
typedef struct ConnsDlgState {
ListPtr connTypesList;
XP_U16 serverRole;
XP_Bool isNewGame;
ConnDlgAddrs* addrState;
XP_UCHAR localIPStr[16];
} ConnsDlgState;
static void
fieldFromStr( XP_U16 id, XP_UCHAR* buf, XP_Bool editable )
{
FieldPtr field = getActiveObjectPtr( id );
UInt16 len = FldGetTextLength( field );
FldSetSelection( field, 0, len );
FldInsert( field, buf, XP_STRLEN(buf) );
setFieldEditable( field, editable );
} /* fieldFromStr */
static void
strFromField( XP_U16 id, XP_UCHAR* buf, XP_U16 max )
{
FieldPtr field = getActiveObjectPtr( id );
XP_UCHAR* str = FldGetTextPtr( field );
XP_U16 len = FldGetTextLength( field );
if ( len > max-1 ) {
len = max - 1;
}
XP_MEMCPY( buf, str, len );
buf[len] = '\0';
} /* strFromField */
#if 0
static void
stateFromGlobals( PalmAppGlobals* globals, ConnsDlgState* state )
{
comms_getAddr( globals->game.comms, &state->targetAddr,
&state->myPort );
state->isNewGame = globals->isNewGame;
} /* stateFromGlobals */
static void
globalsFromState( PalmAppGlobals* globals, ConnsDlgState* state )
{
comms_setAddr( globals->game.comms, &state->targetAddr,
state->myPort );
} /* globalsFromState */
#endif
static void
ctlsFromState( PalmAppGlobals* globals, FormPtr form, ConnsDlgState* state )
{
XP_Bool isNewGame = state->isNewGame;
XP_UCHAR buf[16];
ConnDlgAddrs* addrState = state->addrState;
NetLibAddrINToA( globals->nlStuff.netLibRef,
addrState->remoteIP, buf );
fieldFromStr( XW_CONNS_TARGET_FIELD_ID, buf, isNewGame );
StrPrintF( buf, "%d", addrState->remotePort );
fieldFromStr( XW_CONNS_TPORT_FIELD_ID, buf, isNewGame );
StrPrintF( buf, "%d", addrState->localPort );
fieldFromStr( XW_CONNS_MYPORT_FIELD_ID, buf, isNewGame );
fieldFromStr( XW_CONNS_HOSTIP_FIELD_ID, state->localIPStr, XP_FALSE );
} /* ctlsFromState */
static XP_Bool
stateFromCtls( PalmAppGlobals* globals, ConnsDlgState* state )
{
XP_Bool ok = XP_TRUE;
XP_UCHAR buf[16];
XP_U32 tmpAddr;
ConnDlgAddrs* addrState = state->addrState;
XP_Bool rejectBadIP = addrState->conType == COMMS_CONN_IP;
strFromField( XW_CONNS_TARGET_FIELD_ID, buf, sizeof(buf) );
tmpAddr = NetLibAddrAToIN( globals->nlStuff.netLibRef, buf );
if ( tmpAddr != -1L ) {
addrState->remoteIP = tmpAddr;
} else if ( rejectBadIP ) {
NetLibAddrINToA( globals->nlStuff.netLibRef, addrState->remoteIP,
buf );
fieldFromStr( XW_CONNS_TARGET_FIELD_ID, buf, state->isNewGame );
ok = XP_FALSE;
}
strFromField( XW_CONNS_TPORT_FIELD_ID, buf, sizeof(buf) );
addrState->remotePort = StrAToI( buf );
strFromField( XW_CONNS_MYPORT_FIELD_ID, buf, sizeof(buf) );
addrState->localPort = StrAToI( buf );
return ok;
} /* stateFromCtls */
/* Adjust the set of visible form controls based on state. There are two
* variables here: whether we're showing for a Host or a Guest, and whether
* the connection method is IR or IP. Currently IR means no controls needed,
* either way. IP means on set if launched from host button, another if
* launched from Guest.
*/
static void
updateFormCtls( FormPtr form, ConnsDlgState* state )
{
const XP_U16 ipCtlsBoth[] = {
XW_CONNS_MYPORT_LABEL_ID,
XW_CONNS_MYPORT_FIELD_ID,
XW_CONNS_HOSTIP_LABEL_ID,
XW_CONNS_HOSTIP_FIELD_ID,
0
};
const XP_U16 ipCtlsGuest[] = {
XW_CONNS_TARGET_LABEL_ID,
XW_CONNS_TARGET_FIELD_ID,
XW_CONNS_TPORT_LABEL_ID,
XW_CONNS_TPORT_FIELD_ID,
0
};
if ( state->addrState->conType == COMMS_CONN_IR ) {
disOrEnableSet( form, ipCtlsBoth, XP_FALSE );
disOrEnableSet( form, ipCtlsGuest, XP_FALSE );
} else {
disOrEnableSet( form, ipCtlsBoth, XP_TRUE );
disOrEnableSet( form, ipCtlsGuest,
state->serverRole == SERVER_ISCLIENT );
setFieldEditable( getActiveObjectPtr(XW_CONNS_HOSTIP_FIELD_ID),
XP_FALSE );
}
} /* updateFormCtls */
static void
cleanupExit( PalmAppGlobals* globals )
{
XP_FREE( globals->mpool, globals->connState );
globals->connState = NULL;
FrmReturnToForm( 0 );
} /* cleanupExit */
static XP_U32
figureLocalIP( PalmAppGlobals* globals, XP_UCHAR* buf )
{
Err err;
XP_U32 ipAddr = 0L;
XP_U16 netLibRef = globals->nlStuff.netLibRef;
XP_U16 index;
for ( index = 0; ; ++index ) {
UInt32 creator;
UInt16 instance;
err = NetLibIFGet( netLibRef, index,
&creator, &instance );
/* Docs say to iterate until get netErrInvalidInterface, but I'm
never getting that, getting netErrInterfaceNotFound instead */
if ( (err == netErrInvalidInterface) ||
(err == netErrInterfaceNotFound) ) {
break; /* we're done */
} else if ( err == errNone ) {
XP_U8 up;
UInt16 siz = sizeof(up);
err = NetLibIFSettingGet( netLibRef, creator, instance,
netIFSettingUp, &up, &siz );
if ( (err == errNone) && (up != 0) ) {
siz = sizeof(ipAddr);
/* use this interface?? */
err = NetLibIFSettingGet( netLibRef, creator, instance,
netIFSettingReqIPAddr,
&ipAddr, &siz );
XP_ASSERT( siz == 4 );
}
}
}
if ( !!buf ) {
NetLibAddrINToA( globals->nlStuff.netLibRef, ipAddr, buf );
XP_LOGF( "got local addr: %s", buf );
}
return ipAddr;
} /* figureLocalIP */
Boolean
ConnsFormHandleEvent( EventPtr event )
{
Boolean result;
PalmAppGlobals* globals;
ConnsDlgState* state;
FormPtr form;
XP_S16 chosen;
CALLBACK_PROLOGUE();
globals = getFormRefcon();
state = globals->connState;
if ( !state ) {
state = globals->connState = XP_MALLOC( globals->mpool,
sizeof(*state) );
XP_MEMSET( state, 0, sizeof(*state) );
}
form = FrmGetActiveForm();
switch ( event->eType ) {
case frmOpenEvent:
if ( !openNetLibIfNot( globals ) ) {
beep();
cleanupExit( globals );
result = true;
break;
}
state->serverRole =
(Connectedness)globals->dlgParams[CONNS_PARAM_ROLE_INDEX];
state->addrState =
(ConnDlgAddrs*)globals->dlgParams[CONNS_PARAM_ADDR_INDEX];
state->isNewGame = globals->isNewGame;
(void)figureLocalIP( globals, state->localIPStr );
/* setup connection popup */
state->connTypesList = getActiveObjectPtr( XW_CONNS_TYPE_LIST_ID );
XP_ASSERT( state->addrState->conType == COMMS_CONN_IR
|| state->addrState->conType == COMMS_CONN_IP );
setSelectorFromList( XW_CONNS_TYPE_TRIGGER_ID, state->connTypesList,
state->addrState->conType == COMMS_CONN_IR? 0:1 );
ctlsFromState( globals, form, state );
updateFormCtls( form, state );
case frmUpdateEvent:
FrmDrawForm( form );
result = true;
break;
case ctlSelectEvent:
result = true;
switch ( event->data.ctlSelect.controlID ) {
case XW_CONNS_TYPE_TRIGGER_ID:
if ( state->isNewGame ) {
chosen = LstPopupList( state->connTypesList );
if ( chosen >= 0 ) {
setSelectorFromList( XW_CONNS_TYPE_TRIGGER_ID,
state->connTypesList, chosen );
state->addrState->conType =
chosen == 0? COMMS_CONN_IR : COMMS_CONN_IP;
updateFormCtls( form, state );
}
}
break;
case XW_CONNS_OK_BUTTON_ID:
if ( !state->isNewGame ) {
/* do nothing; same as cancel */
} else if ( !stateFromCtls( globals, state ) ) {
beep();
break;
} else {
EventType eventToPost;
eventToPost.eType = connsSettingChgEvent;
EvtAddEventToQueue( &eventToPost );
}
case XW_CONNS_CANCEL_BUTTON_ID:
cleanupExit( globals );
break;
}
break;
default:
result = false;
}
CALLBACK_EPILOGUE();
return result;
} /* ConnsFormHandleEvent */
#endif /* BEYOND_IR */

37
palm/connsdlg.h Normal file
View file

@ -0,0 +1,37 @@
/* -*-mode: C; fill-column: 77; c-basic-offset: 4; -*- */
/*
* Copyright 2003 by Eric House (fixin@peak.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.
*/
#ifndef _CONNSDLG_H_
#define _CONNSDLG_H_
#include <Event.h>
Boolean ConnsFormHandleEvent( EventPtr event );
#define CONNS_PARAM_ROLE_INDEX 0
#define CONNS_PARAM_ADDR_INDEX 1
#define PopupConnsForm( g, h, addrP ) { \
(g)->dlgParams[CONNS_PARAM_ROLE_INDEX] = (XP_U32)(h); \
(g)->dlgParams[CONNS_PARAM_ADDR_INDEX] = (XP_U32)(addrP); \
FrmPopupForm( XW_CONNS_FORM ); \
}
#endif

346
palm/dictlist.c Normal file
View file

@ -0,0 +1,346 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
/****************************************************************************
* *
* Copyright 1999 - 2003 by Eric House (fixin@peak.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.
* *
****************************************************************************/
#include <PalmTypes.h>
#include <Form.h>
#include <VFSMgr.h>
#include <FeatureMgr.h>
#include "callback.h"
#include "dictlist.h"
#include "palmmain.h"
#include "palmutil.h"
#include "palmdict.h"
#include "strutils.h"
#include "xwords4defines.h"
#define TYPE_DAWG 'DAWG'
#define TYPE_XWR3 'Xwr3'
//////////////////////////////////////////////////////////////////////////////
// typedef and #defines
//////////////////////////////////////////////////////////////////////////////
struct PalmDictList {
XP_U16 nDicts;
DictListEntry dictArray[1];
};
//////////////////////////////////////////////////////////////////////////////
// Prototypes
//////////////////////////////////////////////////////////////////////////////
XP_Bool
getNthDict( const PalmDictList* dl, short n, DictListEntry** dle )
{
XP_Bool exists = !!dl && (dl->nDicts > n);
if ( exists ) {
*dle = (DictListEntry*)&dl->dictArray[n];
}
return exists;
} /* getNthDict */
XP_Bool
getDictWithName( const PalmDictList* dl, XP_UCHAR* name,
DictListEntry** dlep )
{
XP_Bool result = XP_FALSE;
if ( !!dl ) {
XP_U16 i;
XP_UCHAR* extName;
XP_UCHAR oldChName = '\0'; /* shut compiler up */
DictListEntry* dle = (DictListEntry*)dl->dictArray;
extName = (XP_UCHAR*)StrStr((const char*)name,
(const char*)".pdb" );
if ( !!extName ) {
oldChName = *extName;
*extName = '\0';
}
for ( i = 0; !result && i < dl->nDicts; ++i ) {
XP_UCHAR* extCand;
XP_UCHAR oldChCand = '\0';
extCand = (XP_UCHAR*)StrStr((const char*)dle->baseName, ".pdb" );
if ( !!extCand ) {
oldChCand = *extCand;
*extCand = '\0';
}
if ( 0 == XP_STRCMP( (const char*)name,
(const char*)dle->baseName ) ) {
*dlep = dle;
result = XP_TRUE;
}
if ( !!extCand ) {
*extCand = oldChCand;
}
++dle;
}
if ( !!extName ) {
*extName = oldChName;
}
}
return result;
} /* getDictWithName */
void
cacheDictForName( PalmDictList* dl, XP_UCHAR* dictName,
DictionaryCtxt* dict )
{
DictListEntry* dle;
(void)getDictWithName(dl, dictName, &dle );
XP_ASSERT( getDictWithName(dl, dictName, &dle ) );
XP_ASSERT( !dle->dict );
dle->dict = dict;
} /* cacheDictForName */
void
removeFromDictCache( PalmDictList* dl, XP_UCHAR* dictName,
DictionaryCtxt* dict )
{
DictListEntry* dle;
(void)getDictWithName( dl, dictName, &dle );
XP_ASSERT( getDictWithName( dl, dictName, &dle ) );
XP_ASSERT( !!dle->dict );
XP_ASSERT( dle->dict == dict );
dle->dict = NULL;
} /* removeFromDictCache */
static void
addEntry( MPFORMAL PalmDictList** dlp, DictListEntry* dle )
{
PalmDictList* dl = *dlp;
DictListEntry* ignore;
if ( !dl ) {
dl = (PalmDictList*)XP_MALLOC( mpool, sizeof(*dl) );
XP_MEMSET( dl, 0, sizeof(*dl) );
}
if ( !getDictWithName( dl, dle->baseName, &ignore ) ) {
XP_U16 size = sizeof(*dl);
size += dl->nDicts * sizeof( dl->dictArray[0] );
dl = (PalmDictList*)XP_REALLOC( mpool, (XP_U8*)dl, size );
dle->dict = NULL;
XP_MEMCPY( &dl->dictArray[dl->nDicts++], dle,
sizeof( dl->dictArray[0] ) );
}
*dlp = dl;
} /* addEntry */
static void
searchDir( MPFORMAL PalmDictList** dlp, UInt16 volNum, unsigned char separator,
unsigned char* path, XP_U16 pathSize )
{
Err err;
FileRef dirRef;
XP_U16 pathLen = XP_STRLEN( (const char*)path );
err = VFSFileOpen( volNum, (const char*)path, vfsModeRead, &dirRef );
if ( err == errNone ) {
UInt32 dEnum = vfsIteratorStart;
FileInfoType fit;
fit.nameP = (char*)path + pathLen;
while ( dEnum != vfsIteratorStop ) {
XP_UCHAR* ext;
fit.nameBufLen = pathSize - pathLen;
err = VFSDirEntryEnumerate( dirRef, &dEnum, &fit );
if ( err != errNone ) {
break;
}
if ( (fit.attributes & vfsFileAttrDirectory) != 0 ) {
XP_U16 len = XP_STRLEN((const char*)path);
path[len] = separator;
path[len+1] = '\0';
searchDir( MPPARM(mpool) dlp, volNum, separator,
path, pathSize );
} else if ( (ext = (XP_UCHAR*)StrStr( (const char*)path, ".pdb" ))
!= NULL ) {
/* find out if it's a crosswords dict. */
FileRef fileRef;
UInt32 type, creator;
err = VFSFileOpen( volNum, (const char*)path, vfsModeRead,
&fileRef );
if ( err == errNone ) {
err = VFSFileDBInfo( fileRef, NULL, /* name */
NULL, /* attributes */
NULL, /* versionP */
NULL, /* crDateP */
NULL, NULL, /*UInt32 *modDateP, UInt32 *bckUpDateP,*/
NULL, NULL, /*UInt32 *modNumP, MemHandle *appInfoHP,*/
NULL, /*MemHandle *sortInfoHP, */
&type, &creator,
NULL ); /* nRecords */
VFSFileClose( fileRef );
if ( (err == errNone) && (type == TYPE_DAWG) &&
(creator == TYPE_XWR3) ) {
DictListEntry dl;
dl.path = copyString( MPPARM(mpool) path );
dl.location = DL_VFS;
dl.u.vfsData.volNum = volNum;
dl.baseName = dl.path + pathLen;
addEntry( MPPARM(mpool) dlp, &dl );
}
}
}
}
path[pathLen] = '\0';
VFSFileClose( dirRef );
}
} /* searchDir */
static void
tryVFSSearch( MPFORMAL PalmDictList** dlp )
{
Err err;
UInt16 volNum;
UInt32 vEnum;
vEnum = vfsIteratorStart;
while ( vEnum != vfsIteratorStop ) {
unsigned char pathStr[265];
UInt16 bufLen;
err = VFSVolumeEnumerate( &volNum, &vEnum );
if ( err != errNone ) {
break;
}
bufLen = sizeof(pathStr);
err = VFSGetDefaultDirectory( volNum, ".pdb", (char*)pathStr,
&bufLen );
if ( err == errNone ) {
pathStr[1] = '\0';
searchDir( MPPARM(mpool) dlp, volNum, pathStr[0],
pathStr, sizeof(pathStr) );
}
}
} /* tryVFSSearch */
/* if we've allocated extra space in the array as an optimization now's when
* we pull back */
static void
cleanList( PalmDictList** dl )
{
} /* cleanList */
PalmDictList*
DictListMake( MPFORMAL_NOCOMMA )
{
Err err;
DmSearchStateType stateType;
UInt32 vers;
PalmDictList* dl = NULL;
UInt16 cardNo;
LocalID dbID;
Boolean newSearch = true;
XP_Bool found = false;
/* first the DM case */
while ( !found ) {
err = DmGetNextDatabaseByTypeCreator( newSearch, &stateType, TYPE_DAWG,
TYPE_XWR3/* APPID */,
false,// onlyLatestVers,
&cardNo, &dbID );
if ( err != 0 ) {
break;
} else {
XP_UCHAR nameBuf[33];
XP_U16 nameLen;
DictListEntry dle;
err = DmDatabaseInfo( cardNo, dbID, (char*)nameBuf, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL );
nameLen = XP_STRLEN( (const char*)nameBuf ) + 1;
dle.location = DL_STORAGE;
dle.u.dmData.cardNo = cardNo;
dle.u.dmData.dbID = dbID;
dle.path = dle.baseName = XP_MALLOC( mpool, nameLen );
XP_MEMCPY( dle.path, nameBuf, nameLen );
addEntry( MPPARM(mpool) &dl, &dle );
}
newSearch = false;
}
/* then the VFS case */
err = FtrGet( sysFileCVFSMgr, vfsFtrIDVersion, &vers );
if ( err == errNone ) {
tryVFSSearch( MPPARM(mpool) &dl );
}
cleanList( &dl );
return dl;
} /* DictListMake */
void
DictListFree( MPFORMAL PalmDictList* dl )
{
if ( !!dl ) {
DictListEntry* dle = dl->dictArray;
XP_U16 i;
for ( i = 0; i < dl->nDicts; ++i, ++dle ) {
XP_FREE( mpool, dle->path );
}
XP_FREE( mpool, dl );
}
} /* dictListFree */
XP_U16
DictListCount( PalmDictList* dl )
{
if ( !dl ) {
return 0;
} else {
return dl->nDicts;
}
} /* dictListCount */

56
palm/dictlist.h Normal file
View file

@ -0,0 +1,56 @@
/* -*-mode: C; fill-column: 77; c-basic-offset: 4; -*- */
/*
* Copyright 1999 - 2001 by Eric House (fixin@peak.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.
*/
#ifndef _DICTLIST_H_
#define _DICTLIST_H_
#include "palmmain.h"
#include "palmdict.h"
enum { DL_STORAGE, DL_VFS };
typedef struct DictListEntry {
XP_UCHAR* path;
XP_UCHAR* baseName; /* points into, or ==, path */
DictionaryCtxt* dict; /* cache so can refcount */
XP_UCHAR location; /* Storage RAM or VFS */
union {
struct {
UInt16 cardNo;
LocalID dbID;
} dmData;
struct {
UInt16 volNum;
} vfsData;
} u;
} DictListEntry;
PalmDictList* DictListMake( MPFORMAL_NOCOMMA );
void DictListFree( MPFORMAL PalmDictList* dl );
XP_U16 DictListCount( PalmDictList* dl );
XP_Bool getDictWithName( const PalmDictList* dl, unsigned char* name,
DictListEntry** dle );
void cacheDictForName( PalmDictList* dl, XP_UCHAR* dictName,
DictionaryCtxt* ctxt );
void removeFromDictCache( PalmDictList* dl, XP_UCHAR* dictName,
DictionaryCtxt* dict );
XP_Bool getNthDict( const PalmDictList* dl, short n, DictListEntry** dle );
#endif

286
palm/dictui.c Normal file
View file

@ -0,0 +1,286 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
/****************************************************************************
* *
* Copyright 1999 - 2003 by Eric House (fixin@peak.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.
* *
****************************************************************************/
#include <PalmTypes.h>
#include <Form.h>
#include <VFSMgr.h>
#include <FeatureMgr.h>
#include "callback.h"
#include "dictui.h"
#include "palmmain.h"
#include "palmutil.h"
#include "palmdict.h"
#include "dictlist.h"
#include "strutils.h"
#include "xwords4defines.h"
#define TYPE_DAWG 'DAWG'
#define TYPE_XWR3 'Xwr3'
//////////////////////////////////////////////////////////////////////////////
// Prototypes
//////////////////////////////////////////////////////////////////////////////
static XP_U16 populateDictionaryList( MPFORMAL ListData* sLd,
XP_UCHAR* curDictName,
ListPtr list, Int16 triggerID,
PalmDictList* dl );
static Boolean beamDict( const PalmDictList* dl, XP_UCHAR* dictName );
/*****************************************************************************
* Handler for dictionary info form.
****************************************************************************/
#define USE_POPULATE 1
Boolean
dictFormHandleEvent( EventPtr event )
{
FormPtr form;
Boolean result;
Int16 chosen;
DictionaryCtxt* dict;
PalmAppGlobals* globals;
XP_UCHAR* dictName;
CALLBACK_PROLOGUE();
result = false;
globals = getFormRefcon();
switch ( event->eType ) {
case frmOpenEvent: {
XP_UCHAR* curName;
XP_U16 width;
RectangleType rect;
form = FrmGetActiveForm();
/* we're either a beam dlg or a dict picker; disable a button here. */
disOrEnable( form,
globals->dictuiForBeaming ?
XW_DICTINFO_DONE_BUTTON_ID:XW_DICTINFO_BEAM_BUTTON_ID,
false );
/* dictionary list setup */
globals->dictState.dictList =
getActiveObjectPtr( XW_DICTINFO_LIST_ID );
dict = !!globals->game.model?
model_getDictionary(globals->game.model) : NULL;
if ( dict ) {
curName = dict_getName( dict );
} else {
curName = NULL;
}
width = populateDictionaryList( MPPARM(globals->mpool)
&globals->dictState.sLd,
curName, globals->dictState.dictList,
XW_DICTINFO_TRIGGER_ID,
globals->dictList );
getObjectBounds( XW_DICTINFO_LIST_ID, &rect );
rect.extent.x = width;
setObjectBounds( XW_DICTINFO_LIST_ID, &rect );
FrmDrawForm( form );
break;
}
case ctlSelectEvent:
switch ( event->data.ctlEnter.controlID ) {
case XW_DICTINFO_TRIGGER_ID:
// don't let change dict except first time
if ( globals->dictuiForBeaming || globals->isNewGame ) {
chosen = LstPopupList( globals->dictState.dictList );
if ( chosen >= 0 ) {
setSelectorFromList( XW_DICTINFO_TRIGGER_ID,
globals->dictState.dictList,
chosen );
}
}
result = true;
break;
/* case XW_PHONIES_TRIGGER_ID: */
/* chosen = LstPopupList( sPhoniesList ); */
/* if ( chosen >= 0 ) { */
/* setTriggerFromList( XW_PHONIES_TRIGGER_ID, sPhoniesList, */
/* chosen ); */
/* } */
/* result = true; */
/* break; */
case XW_DICTINFO_DONE_BUTTON_ID:
case XW_DICTINFO_BEAM_BUTTON_ID:
/* discard the const */
dictName = (XP_UCHAR*)CtlGetLabel(
getActiveObjectPtr( XW_DICTINFO_TRIGGER_ID) );
if ( globals->dictuiForBeaming ) {
if ( !beamDict( globals->dictList, dictName ) ) {
break; /* don't cancel dialog yet */
}
} else {
EventType eventToPost;
XP_ASSERT( dictName != NULL );
eventToPost.eType = dictSelectedEvent;
((DictSelectedData*)&eventToPost.data.generic)->dictName
= copyString( MEMPOOL dictName );
EvtAddEventToQueue( &eventToPost );
}
case XW_DICTINFO_CANCEL_BUTTON_ID:
result = true;
freeListData( MPPARM(globals->mpool) &globals->dictState.sLd );
FrmReturnToForm( 0 );
break;
} // switch ( event->data.ctlEnter.controlID )
break;
default:
break;
} // switch
CALLBACK_EPILOGUE();
return result;
} /* dictFormHandleEvent */
/*****************************************************************************
*
****************************************************************************/
static XP_U16
populateDictionaryList( MPFORMAL ListData* sLd, XP_UCHAR* curDictName,
ListPtr list, Int16 triggerID, PalmDictList* dl )
{
XP_U16 i;
XP_U16 maxWidth = 0;
XP_U16 nDicts;
initListData( MPPARM(mpool) sLd, 16 ); /* PENDING: MAX_DICTS or count */
nDicts = DictListCount( dl );
for ( i = 0; i < nDicts; ++i ) {
DictListEntry* dle;
XP_UCHAR* name;
XP_U16 width;
getNthDict( dl, i, &dle );
name = dle->baseName;
addListTextItem( MPPARM(mpool) sLd, name );
width = FntCharsWidth( (const char*)name, XP_STRLEN((const char*)name) );
if ( width > maxWidth ) {
maxWidth = width;
}
}
sortList( sLd );
setListSelection( sLd, (char*)curDictName );
setListChoices( sLd, list, NULL );
setSelectorFromList( triggerID, list, LstGetSelection(list) );
return maxWidth + 3; /* 3: for white space */
} /* populateDictionaryList */
/***********************************************************************
* The rest of this file mostly stolen from palmos.com. I've only modified
* beamDict
************************************************************************/
static Err
WriteDBData(const void* dataP, UInt32* sizeP, void* userDataP)
{
Err err;
/* Try to send as many bytes as were requested by the caller */
*sizeP = ExgSend((ExgSocketPtr)userDataP, (void*)dataP, *sizeP, &err);
return err;
} /* WriteDBData */
Err
sendDatabase( UInt16 cardNo, LocalID dbID, XP_UCHAR* nameP,
XP_UCHAR* descriptionP )
{
ExgSocketType exgSocket;
Err err;
/* Create exgSocket structure */
XP_MEMSET( &exgSocket, 0, sizeof(exgSocket) );
exgSocket.description = (char*)descriptionP;
exgSocket.name = (char*)nameP;
/* Start an exchange put operation */
err = ExgPut(&exgSocket);
if ( !err ) {
err = ExgDBWrite( WriteDBData, &exgSocket, NULL, dbID, cardNo );
/* Disconnect Exg and pass error */
err = ExgDisconnect(&exgSocket, err);
}
return err;
} /* sendDatabase */
static Boolean
beamDict( const PalmDictList* dl, XP_UCHAR* dictName )
{
Err err;
UInt16 cardNo;
LocalID dbID;
Boolean found;
XP_Bool shouldDispose = XP_FALSE;
DictListEntry* dle;
found = getDictWithName( dl, dictName, &dle );
/* Find our app using its internal name */
XP_ASSERT( found );
if ( found ) {
if ( dle->location == DL_VFS ) {
err = VFSImportDatabaseFromFile( dle->u.vfsData.volNum,
(const char*)dle->path,
&cardNo, &dbID );
if ( err == dmErrAlreadyExists ) {
} else if ( err == errNone ) {
shouldDispose = XP_TRUE;
} else {
found = XP_FALSE;
}
} else {
cardNo = dle->u.dmData.cardNo;
dbID = dle->u.dmData.dbID;
}
}
if ( found ) { /* send it giving external name and description */
XP_UCHAR prcName[40];
XP_SNPRINTF( prcName, sizeof(prcName), (XP_UCHAR*)"%s.pdb", dictName );
err = sendDatabase( cardNo, dbID, prcName, dictName );
found = err == 0;
if ( shouldDispose ) {
DmDeleteDatabase( cardNo, dbID );
}
}
return found;
} /* beamDict */

34
palm/dictui.h Normal file
View file

@ -0,0 +1,34 @@
/* -*-mode: C; fill-column: 77; c-basic-offset: 4; -*- */
/*
* Copyright 1999 - 2001 by Eric House (fixin@peak.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.
*/
#ifndef _DICTUI_H_
#define _DICTUI_H_
#include "palmmain.h"
#include "palmdict.h"
typedef struct DictSelectedData {
MemPtr dictName;
} DictSelectedData;
Boolean dictFormHandleEvent( EventPtr event );
/* export for beamBoard */
Err sendDatabase( UInt16 cardNo, LocalID dbID, XP_UCHAR* nameP,
XP_UCHAR* descriptionP );
#endif

186
palm/fnavgen.c Normal file
View file

@ -0,0 +1,186 @@
/* -*- mode: c; -*- */
#include <stdio.h>
#include <assert.h>
#include "xwords4defines.h"
typedef struct fnavElem {
unsigned short objectID;
unsigned short objectFlags;
unsigned short objectAbove;
unsigned short objectBelow;
} fnavElem;
typedef struct fnavHeader {
unsigned short formID; /* not part of resource!!!! */
unsigned short version; /* always 1 */
unsigned short objcount;
unsigned short headerSizeInBytes; /* always 20 */
unsigned short listSizeInBytes; /* always 8 */
unsigned short navflags;
unsigned short initialHint;
unsigned short jumpToHint;
unsigned short bottomLeftHint;
} fnavHeader;
fnavHeader gamesHeader = {
XW_NEWGAMES_FORM,
0, /* fill this in */
0, /* fill this in */
0, /* fill this in */
0, /* fill this in */
0x0001, /* force obj focus mode */
0,
0,
0,
};
fnavElem gamesElems[] = {
{ XW_ROBOT_1_CHECKBOX_ID, 0, 0, XW_ROBOT_2_CHECKBOX_ID },
{ XW_ROBOT_2_CHECKBOX_ID, 0, XW_ROBOT_1_CHECKBOX_ID, XW_ROBOT_3_CHECKBOX_ID },
{ XW_ROBOT_3_CHECKBOX_ID, 0, XW_ROBOT_2_CHECKBOX_ID, XW_ROBOT_4_CHECKBOX_ID },
{ XW_ROBOT_4_CHECKBOX_ID, 0, XW_ROBOT_3_CHECKBOX_ID, XW_SOLO_GADGET_ID },
{ XW_SOLO_GADGET_ID, 0, XW_ROBOT_4_CHECKBOX_ID, XW_SERVER_GADGET_ID },
{ XW_SERVER_GADGET_ID, 0, XW_SOLO_GADGET_ID, XW_CLIENT_GADGET_ID },
{ XW_CLIENT_GADGET_ID, 0, XW_SERVER_GADGET_ID, 0 }
};
unsigned short gamesElemsShort[] = {
#ifndef XWFEATURE_STANDALONE_ONLY
XW_SOLO_GADGET_ID,
XW_SERVER_GADGET_ID,
XW_CLIENT_GADGET_ID,
#endif
XW_NPLAYERS_SELECTOR_ID,
XW_PREFS_BUTTON_ID,
XW_REMOTE_1_CHECKBOX_ID,
XW_PLAYERNAME_1_FIELD_ID,
XW_ROBOT_1_CHECKBOX_ID,
XW_PLAYERPASSWD_1_TRIGGER_ID,
XW_REMOTE_2_CHECKBOX_ID,
XW_PLAYERNAME_2_FIELD_ID,
XW_ROBOT_2_CHECKBOX_ID,
XW_PLAYERPASSWD_2_TRIGGER_ID,
XW_REMOTE_3_CHECKBOX_ID,
XW_PLAYERNAME_3_FIELD_ID,
XW_ROBOT_3_CHECKBOX_ID,
XW_PLAYERPASSWD_3_TRIGGER_ID,
XW_REMOTE_4_CHECKBOX_ID,
XW_PLAYERNAME_4_FIELD_ID,
XW_ROBOT_4_CHECKBOX_ID,
XW_PLAYERPASSWD_4_TRIGGER_ID,
XW_DICT_SELECTOR_ID,
XW_CANCEL_BUTTON_ID,
XW_OK_BUTTON_ID
};
static void
usage( char* name )
{
fprintf( stderr, "usage: %s outfile\n", name );
exit( 1 );
} /* */
static void
write_network_short( FILE* fil, unsigned short s )
{
unsigned short tmp = htons( s );
fwrite( &tmp, sizeof(tmp), 1, fil );
} /* write_network_short */
write_fnav( fnavHeader* header, unsigned short* idArray,
fnavElem* elems, int count )
{
char nameBuf[32];
FILE* fil;
int i;
assert( !idArray || !elems );
sprintf( nameBuf, "fnav%.4x.bin", header->formID );
fil = fopen( nameBuf, "w" );
fprintf( stderr, "created file %s\n", nameBuf );
write_network_short( fil, 1 );
write_network_short( fil, count );
write_network_short( fil, 20 );
write_network_short( fil, 8 );
write_network_short( fil, header->navflags );
write_network_short( fil, header->initialHint );
write_network_short( fil, header->jumpToHint );
write_network_short( fil, header->bottomLeftHint );
/* Two words of padding. Docs disagree, but Blazer's resources have
'em */
write_network_short( fil, 0 );
write_network_short( fil, 0 );
if ( !!elems ) {
for ( i = 0; i < count; ++i ) {
write_network_short( fil, elems->objectID );
write_network_short( fil, elems->objectFlags );
write_network_short( fil, elems->objectAbove );
write_network_short( fil, elems->objectBelow );
++elems;
}
} else {
unsigned short prevID = 0;
unsigned short id = *idArray++;
while ( count-- ) {
unsigned short nextID;
if ( count == 0 ) {
nextID = 0;
} else {
nextID = *idArray++;
}
write_network_short( fil, id );
write_network_short( fil, 0 );
write_network_short( fil, prevID );
write_network_short( fil, nextID );
if ( !nextID ) {
break;
}
prevID = id;
id = nextID;
}
}
fclose(fil);
} /* write_fnav */
int
main( int argc, char** argv )
{
int i;
char* outFName;
if ( argc != 1 ) {
usage( argv[0] );
}
write_fnav( &gamesHeader, gamesElemsShort, NULL,
sizeof(gamesElemsShort)/sizeof(gamesElemsShort[0]) );
/* sizeof(gamesElems)/sizeof(gamesElems[0]) ); */
} /* main */

208
palm/gameutil.c Normal file
View file

@ -0,0 +1,208 @@
/* -*-mode: C; fill-column: 77; c-basic-offset: 4; -*- */
/*
* Copyright 1999 - 2001 by Eric House (fixin@peak.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.
*/
#include <DataMgr.h>
#include <TimeMgr.h>
#include "comtypes.h"
#include "comms.h"
#include "strutils.h"
#include "gameutil.h"
#include "xwords4defines.h"
#include "xwstream.h"
#include "palmmain.h"
XP_U16
countGameRecords( PalmAppGlobals* globals )
{
LocalID id;
DmOpenRef dbP;
UInt16 numRecs;
id = DMFINDDATABASE( globals, CARD_0, XW_GAMES_DBNAME );
dbP = DMOPENDATABASE( globals, CARD_0, id, dmModeWrite );
numRecs = DmNumRecords( dbP );
DMCLOSEDATABASE( dbP );
return numRecs;
}
#if defined OWNER_HASH || defined NO_REG_REQUIRED
void
deleteGameRecord( PalmAppGlobals* globals, XP_S16 index )
{
LocalID id;
DmOpenRef dbP;
id = DMFINDDATABASE( globals, CARD_0, XW_GAMES_DBNAME );
dbP = DMOPENDATABASE( globals, CARD_0, id, dmModeWrite );
DmRemoveRecord( dbP, index );
DMCLOSEDATABASE( dbP );
} /* deleteGameRecord */
XP_S16
duplicateGameRecord( PalmAppGlobals* globals, XP_S16 fromIndex )
{
LocalID id;
DmOpenRef dbP;
MemHandle newRecord, curRecord;
XP_U16 size;
XP_S16 newIndex = fromIndex + 1;
id = DMFINDDATABASE( globals, CARD_0, XW_GAMES_DBNAME );
dbP = DMOPENDATABASE( globals, CARD_0, id, dmModeWrite );
XP_ASSERT( fromIndex < countGameRecords(globals) );
curRecord = DmQueryRecord( dbP, fromIndex );
size = MemHandleSize( curRecord );
newRecord = DmNewRecord( dbP, (XP_U16*)&newIndex, size );
DmWrite( MemHandleLock(newRecord), 0, MemHandleLock(curRecord), size );
MemHandleUnlock( curRecord );
MemHandleUnlock( newRecord );
DmReleaseRecord( dbP, newIndex, true );
DMCLOSEDATABASE( dbP );
return newIndex;
} /* duplicateGameRecord */
#endif
void
streamToGameRecord( PalmAppGlobals* globals, XWStreamCtxt* stream,
XP_S16 index )
{
LocalID id;
DmOpenRef dbP;
MemHandle handle;
MemPtr tmpPtr, ptr;
Err err;
XP_U32 size = stream_getSize( stream );
id = DMFINDDATABASE( globals, CARD_0, XW_GAMES_DBNAME );
dbP = DMOPENDATABASE( globals, CARD_0, id, dmModeWrite );
XP_ASSERT( !!dbP );
if ( index == DmNumRecords(dbP) ) {
handle = DmNewRecord( dbP, (XP_U16*)&index, size );
} else {
XP_ASSERT( index < countGameRecords(globals) );
handle = DmGetRecord( dbP, index );
MemHandleResize( handle, size );
}
tmpPtr = MemPtrNew(size);
stream_getBytes( stream, tmpPtr, size );
ptr = MemHandleLock( handle );
err = DmWrite( ptr, 0, tmpPtr, size );
XP_ASSERT( err == 0 );
MemPtrFree( tmpPtr );
MemHandleUnlock(handle);
err = DmReleaseRecord( dbP, index, true );
XP_ASSERT( err == 0 );
DMCLOSEDATABASE( dbP );
} /* streamToGameRecord */
void
writeNameToGameRecord( PalmAppGlobals* globals, XP_S16 index,
char* newName, XP_U16 len )
{
LocalID id;
DmOpenRef dbP;
MemHandle handle;
char name[MAX_GAMENAME_LENGTH];
XP_ASSERT( len == XP_STRLEN(newName) );
XP_ASSERT( len > 0 );
XP_MEMSET( name, 0, sizeof(name) );
if ( len >= MAX_GAMENAME_LENGTH ) {
len = MAX_GAMENAME_LENGTH - 1;
}
XP_MEMCPY( name, newName, len+1 );
id = DMFINDDATABASE( globals, CARD_0, XW_GAMES_DBNAME );
dbP = DMOPENDATABASE( globals, CARD_0, id, dmModeWrite );
if ( index == DmNumRecords(dbP) ) {
handle = DmNewRecord(dbP, (XP_U16*)&index, MAX_GAMENAME_LENGTH);
} else {
XP_ASSERT( index < DmNumRecords(dbP) );
handle = DmGetRecord( dbP, index );
}
XP_ASSERT( !!handle );
DmWrite( MemHandleLock(handle), 0, name, MAX_GAMENAME_LENGTH );
MemHandleUnlock( handle );
(void)DmReleaseRecord( dbP, index, true );
DMCLOSEDATABASE( dbP );
} /* writeNameToGameRecord */
void
nameFromRecord( PalmAppGlobals* globals, XP_S16 index, char* buf )
{
LocalID id;
DmOpenRef dbP;
MemHandle handle;
buf[0] = '\0'; /* init to empty string */
if ( index < countGameRecords(globals) ) {
id = DMFINDDATABASE( globals, CARD_0, XW_GAMES_DBNAME );
if ( id != 0 ) {
dbP = DMOPENDATABASE( globals, CARD_0, id, dmModeWrite );
if ( dbP != 0 ) {
handle = DmQueryRecord( dbP, index );
XP_MEMCPY( buf, MemHandleLock(handle), MAX_GAMENAME_LENGTH );
buf[MAX_GAMENAME_LENGTH-1] = '\0';
MemHandleUnlock( handle );
DMCLOSEDATABASE( dbP );
}
}
}
} /* nameFromRecord */
/*****************************************************************************
* Later this will provide a default name based on a timestamp.
*****************************************************************************/
#ifndef TIME_FORMAT
#define TIME_FORMAT tfColonAMPM
#endif
#ifndef DATE_FORMAT
#define DATE_FORMAT dfMDYLongWithComma
#endif
void
makeDefaultGameName( char* buf )
{
char timeBuf[timeStringLength+1]; /* add 1 to be safe */
char dateBuf[longDateStrLength+1];
DateTimeType timeType;
TimSecondsToDateTime( TimGetSeconds(), &timeType );
TimeToAscii( timeType.hour, timeType.minute, TIME_FORMAT, timeBuf );
DateToAscii( timeType.month, timeType.day, timeType.year,
DATE_FORMAT, dateBuf );
StrPrintF( buf, "%s, %s", dateBuf, timeBuf );
} /* makeDefaultGameName */

35
palm/gameutil.h Normal file
View file

@ -0,0 +1,35 @@
/* -*-mode: C; fill-column: 77; c-basic-offset: 4; -*- */
/*
* Copyright 1999 - 2001 by Eric House (fixin@peak.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.
*/
#ifndef _GAMEUTIL_H_
#define _GAMEUTIL_H_
#include "comtypes.h"
#include "memstream.h"
#include "palmmain.h"
XP_U16 countGameRecords( PalmAppGlobals* globals );
void deleteGameRecord( PalmAppGlobals* globals, XP_S16 index );
XP_S16 duplicateGameRecord( PalmAppGlobals* globals, XP_S16 fromIndex );
void nameFromRecord( PalmAppGlobals* globals, XP_S16 index, char* buf );
void streamToGameRecord( PalmAppGlobals* globals, XWStreamCtxt* stream,
XP_S16 index );
void makeDefaultGameName( char* buf );
#endif

952
palm/newgame.c Normal file
View file

@ -0,0 +1,952 @@
/* -*-mode: C; fill-column: 77; c-basic-offset: 4; -*- */
/*
* Copyright 1999 - 2001 by Eric House (fixin@peak.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.
*/
#include <PalmTypes.h>
#include <Form.h>
#include <List.h>
#include <Chars.h> /* for nextFieldChr */
#include <Graffiti.h> /* for GrfSetState */
#include <Event.h>
#ifdef HS_DUO_SUPPORT
# include <Hs.h>
#endif
#include "callback.h"
#include "comtypes.h"
#include "palmmain.h"
#include "comms.h"
#include "strutils.h"
#include "newgame.h"
#include "xwords4defines.h"
#include "dictui.h"
#include "palmdict.h"
#include "palmutil.h"
#include "palmir.h"
#include "prefsdlg.h"
#include "connsdlg.h"
static void handlePasswordTrigger( PalmAppGlobals* globals,
UInt16 controlID );
static void adjustVisibility( PalmAppGlobals* globals, XP_Bool canDraw );
static void setNPlayersAndAdjust( PalmAppGlobals* globals, Int16 chosen );
static void updatePlayerInfo( PalmAppGlobals* globals );
static XP_Bool tryFieldNavigationKey( XP_U16 key );
static void loadNewGameState( PalmAppGlobals* globals );
static void unloadNewGameState( PalmAppGlobals* globals );
static void setNameThatFits( PalmNewGameState* state );
#ifdef HS_DUO_SUPPORT
static XP_Bool tryDuoRockerKey( PalmAppGlobals* globals,XP_U16 key );
static XP_Bool considerGadgetFocus( PalmNewGameState* state, EventType* event );
#else
# define tryDuoRockerKey(g,key) XP_FALSE
#endif
#ifndef XWFEATURE_STANDALONE_ONLY
static Boolean checkHiliteGadget(PalmAppGlobals* globals, EventType* event,
PalmNewGameState* state );
static void drawConnectGadgets( PalmAppGlobals* globals );
static void changeGadgetHilite( PalmAppGlobals* globals, UInt16 hiliteID );
#else
# define checkHiliteGadget(globals, event, state) XP_FALSE
# define drawConnectGadgets( globals )
#endif
#define IS_SERVER_GADGET(id) \
((id) >= XW_SOLO_GADGET_ID && (id) <= XW_CLIENT_GADGET_ID)
/*****************************************************************************
*
****************************************************************************/
Boolean
newGameHandleEvent( EventPtr event )
{
Boolean result = false;
EventType eventToPost; /* used only with OK button */
PalmAppGlobals* globals;
FormPtr form;
LocalPlayer* lp;
CurGameInfo* gi;
PalmNewGameState* state;
Int16 chosen;
XP_U16 i;
XP_U16 controlID;
XP_U16 index;
Boolean on;
Boolean canEdit;
CALLBACK_PROLOGUE();
globals = getFormRefcon();
gi = &globals->gameInfo;
state = &globals->newGameState;
switch ( event->eType ) {
case frmOpenEvent:
GlobalPrefsToLocal( globals );
loadNewGameState( globals );
form = FrmGetActiveForm();
#ifndef XWFEATURE_STANDALONE_ONLY
sizeGadgetsForStrings( form,
getActiveObjectPtr( XW_SERVERTYPES_LIST_ID ),
XW_SOLO_GADGET_ID );
#endif
state->playerNumList =
getActiveObjectPtr( XW_NPLAYERS_LIST_ID );
XP_ASSERT( state->playerNumList != NULL );
setSelectorFromList( XW_NPLAYERS_SELECTOR_ID,
state->playerNumList,
gi->nPlayers - 1 );
XP_ASSERT( !!state->dictName );
setNameThatFits( state );
XP_ASSERT( !!globals->game.server );
canEdit = state->curServerHilite == SERVER_STANDALONE
|| globals->isNewGame;
/* load the fields from what we already have */
for ( lp = gi->players, i = 0; i < MAX_NUM_PLAYERS; ++lp, ++i ) {
XP_U16 offset = i * NUM_PLAYER_COLS;
ControlPtr check;
XP_UCHAR* name;
FieldPtr nameField;
#ifndef XWFEATURE_STANDALONE_ONLY
Boolean isLocal = lp->isLocal;
check = getActiveObjectPtr(XW_REMOTE_1_CHECKBOX_ID + offset);
CtlSetValue( check, !isLocal );
#endif
check = getActiveObjectPtr(XW_ROBOT_1_CHECKBOX_ID+offset);
CtlSetValue( check, lp->isRobot );
nameField = getActiveObjectPtr(XW_PLAYERNAME_1_FIELD_ID+offset);
name = lp->name;
if ( !!name && !!*name ) {
FldInsert( nameField, (const char*)name,
XP_STRLEN((const char*)name) );
}
setFieldEditable( nameField, canEdit );
/* set up the password */
if ( !!lp->password ) {
CtlSetLabel( getActiveObjectPtr(
XW_PLAYERPASSWD_1_TRIGGER_ID+offset ),
"*" );
}
}
/* form = FrmGetActiveForm(); */
FrmSetFocus(form, FrmGetObjectIndex(form, XW_PLAYERNAME_1_FIELD_ID));
case frmUpdateEvent:
adjustVisibility( globals, XP_FALSE );
GrfSetState( false, false, false );
FrmDrawForm( FrmGetActiveForm() );
drawConnectGadgets( globals );
result = true;
break;
#ifdef BEYOND_IR
case connsSettingChgEvent:
XP_ASSERT( globals->isNewGame );
state->connsSettingChanged = XP_TRUE;
break;
#endif
#ifdef HS_DUO_SUPPORT
case frmObjectFocusTakeEvent:
case frmObjectFocusLostEvent:
result = considerGadgetFocus( state, event );
break;
#endif
case penDownEvent:
result = checkHiliteGadget( globals, event, state );
break;
case keyDownEvent:
result = tryFieldNavigationKey( event->data.keyDown.chr )
|| tryDuoRockerKey( globals, event->data.keyDown.chr );
break;
case prefsChangedEvent:
state->forwardChange = true;
break;
case ctlEnterEvent:
switch ( event->data.ctlEnter.controlID ) {
#ifndef XWFEATURE_STANDALONE_ONLY
case XW_REMOTE_1_CHECKBOX_ID:
case XW_REMOTE_2_CHECKBOX_ID:
case XW_REMOTE_3_CHECKBOX_ID:
case XW_REMOTE_4_CHECKBOX_ID:
#endif
case XW_DICT_SELECTOR_ID:
case XW_NPLAYERS_SELECTOR_ID:
if ( !globals->isNewGame ) {
result = true;
beep();
}
}
break;
case ctlSelectEvent:
result = true;
controlID = event->data.ctlSelect.controlID;
on = event->data.ctlSelect.on;
switch ( controlID ) {
case XW_ROBOT_1_CHECKBOX_ID:
case XW_ROBOT_2_CHECKBOX_ID:
case XW_ROBOT_3_CHECKBOX_ID:
case XW_ROBOT_4_CHECKBOX_ID:
index = (controlID - XW_ROBOT_1_CHECKBOX_ID) / NUM_PLAYER_COLS;
state->isRobot[index] = on;
adjustVisibility( globals, XP_TRUE );
break;
#ifndef XWFEATURE_STANDALONE_ONLY
case XW_REMOTE_1_CHECKBOX_ID:
case XW_REMOTE_2_CHECKBOX_ID:
case XW_REMOTE_3_CHECKBOX_ID:
case XW_REMOTE_4_CHECKBOX_ID:
XP_ASSERT( state->curServerHilite == SERVER_ISSERVER );
index = (controlID - XW_REMOTE_1_CHECKBOX_ID) / NUM_PLAYER_COLS;
state->isLocal[index] = !on;
state->curNPlayersLocal += on? -1:1;
adjustVisibility( globals, XP_TRUE );
break;
#endif
case XW_NPLAYERS_SELECTOR_ID:
XP_ASSERT( globals->isNewGame );
chosen = LstPopupList( state->playerNumList );
if ( chosen >= 0 ) {
setSelectorFromList( XW_NPLAYERS_SELECTOR_ID,
state->playerNumList,
chosen );
++chosen; /* chosen is 0-based */
if (state->curServerHilite==SERVER_ISCLIENT) {
state->curNPlayersLocal = chosen;
XP_ASSERT( state->curNPlayersLocal <= MAX_NUM_PLAYERS );
} else {
state->curNPlayersTotal = chosen;
}
setNPlayersAndAdjust( globals, chosen );
}
break;
case XW_DICT_SELECTOR_ID:
XP_ASSERT( globals->isNewGame );
globals->dictuiForBeaming = false;
FrmPopupForm( XW_DICTINFO_FORM );
/* popup dict selection dialog -- or maybe just a list if there
are no preferences to set. The results should all be
cancellable, so don't delete the existing dictionary (if
any) until OK is chosen */
break;
case XW_OK_BUTTON_ID:
/* if we put up the prefs form from within this one and the user
clicked ok, we need to make sure the main form gets the
notification so it can make use of any changes. */
if ( globals->isNewGame ) {
updatePlayerInfo( globals );
eventToPost.eType = newGameOkEvent;
EvtAddEventToQueue( &eventToPost );
globals->postponeDraw = true;
} else if ( state->curServerHilite
== SERVER_STANDALONE ) {
updatePlayerInfo( globals );
}
if ( state->forwardChange ) {
eventToPost.eType = prefsChangedEvent;
EvtAddEventToQueue( &eventToPost );
state->forwardChange = false;
}
unloadNewGameState( globals );
FrmReturnToForm( 0 );
break;
case XW_CANCEL_BUTTON_ID:
unloadNewGameState( globals );
eventToPost.eType = newGameCancelEvent;
EvtAddEventToQueue( &eventToPost );
FrmReturnToForm( 0 );
break;
case XW_PREFS_BUTTON_ID:
/* bring up with the this-game tab selected */
XP_ASSERT( !!globals->prefsDlgState );
globals->prefsDlgState->stateTypeIsGlobal = false;
FrmPopupForm( XW_PREFS_FORM );
break;
case XW_PLAYERPASSWD_1_TRIGGER_ID:
case XW_PLAYERPASSWD_2_TRIGGER_ID:
case XW_PLAYERPASSWD_3_TRIGGER_ID:
case XW_PLAYERPASSWD_4_TRIGGER_ID:
handlePasswordTrigger( globals, controlID );
break;
default: /* one of the password selectors? */
result = false;
}
break;
case dictSelectedEvent:
/* posted by the form we raise when user clicks Dictionary selector
above. */
if ( state->dictName != NULL ) {
XP_FREE( globals->mpool, state->dictName );
}
state->dictName =
((DictSelectedData*)&event->data.generic)->dictName;
setNameThatFits( state );
break;
default:
break;
}
CALLBACK_EPILOGUE();
return result;
} /* newGameHandleEvent */
static void
setNameThatFits( PalmNewGameState* state )
{
RectangleType rect;
XP_U16 width;
XP_U16 len = XP_STRLEN( (const char*)state->dictName );
XP_MEMCPY( state->shortDictName, state->dictName, len + 1 );
/* The width available is the cancel button's left minus ours */
getObjectBounds( XW_CANCEL_BUTTON_ID, &rect );
width = rect.topLeft.x;
getObjectBounds( XW_DICT_SELECTOR_ID, &rect );
width -= (rect.topLeft.x + 6);
for ( ; FntCharsWidth( (const char*)state->dictName, len ) > width; --len ) {
/* do nothing */
}
state->shortDictName[len] = '\0';
CtlSetLabel( getActiveObjectPtr( XW_DICT_SELECTOR_ID ),
(const char*)state->shortDictName );
} /* setNameThatFits */
static XP_U16
countLocalIn( PalmNewGameState* state, XP_U16 nPlayers )
{
XP_U16 nLocal = 0;
XP_U16 i;
for ( i = 0; i < nPlayers; ++i ) {
if ( state->isLocal[i] ) {
++nLocal;
}
}
return nLocal;
} /* countLocalIn */
/* If we're in GUEST mode, only local players are visible, and so this means
* an increase in the number of local players. If we're in a different mode
* then it means a simple increase in all players. Only the first case is
* difficult, because if the number's getting larger we need to confirm that
* there's another local player to show, and if there's not we need to
* convert the first non-local player.
*/
static void
setNPlayersAndAdjust( PalmAppGlobals* globals, Int16 chosen )
{
#ifndef XWFEATURE_STANDALONE_ONLY
PalmNewGameState* state = &globals->newGameState;
if ( state->curServerHilite == SERVER_ISCLIENT ) {
XP_U16 i;
XP_S16 nRemote = 0;
XP_S16 nLocal = 0;
/* find the first non-local player */
for ( i = 0; i < MAX_NUM_PLAYERS; ++i ) {
if ( state->isLocal[i] ) {
++nLocal;
} else {
++nRemote;
}
}
/* Make as many local as necessary */
for ( i = 0; nLocal < chosen && i < MAX_NUM_PLAYERS; ++i ) {
if ( !state->isLocal[i] ) {
state->isLocal[i] = true;
setBooleanCtrl( XW_REMOTE_1_CHECKBOX_ID +
(i * NUM_PLAYER_COLS), false );
++nLocal;
--nRemote;
}
}
state->curNPlayersLocal = chosen;
XP_ASSERT( state->curNPlayersLocal <= MAX_NUM_PLAYERS );
state->curNPlayersTotal = chosen + nRemote;
XP_ASSERT( state->curNPlayersTotal <= MAX_NUM_PLAYERS );
} else {
state->curNPlayersTotal = chosen;
state->curNPlayersLocal = countLocalIn( state, chosen );
XP_ASSERT( state->curNPlayersLocal <= MAX_NUM_PLAYERS );
}
#endif
adjustVisibility( globals, XP_TRUE );
} /* setNPlayersAndAdjust */
static Boolean
tryFieldNavigationKey( XP_U16 key )
{
FormPtr form;
Int16 curFocus, nextFocus, change;
UInt16 nObjects;
if ( key == prevFieldChr ) {
change = -1;
} else if ( key == nextFieldChr ) {
change = 1;
} else {
return false;
}
form = FrmGetActiveForm();
curFocus = nextFocus = FrmGetFocus( form );
nObjects = FrmGetNumberOfObjects(form);
/* find the next (in either direction) usable field */
for ( ; ; ) {
nextFocus += change;
if ( nextFocus == nObjects ) {
nextFocus = 0;
} else if ( nextFocus < 0 ) {
nextFocus = nObjects-1;
}
if ( nextFocus == curFocus ) {
break;
} else if ( FrmGetObjectType(form, nextFocus) != frmFieldObj ) {
continue;
} else {
FieldPtr field = FrmGetObjectPtr( form, nextFocus );
FieldAttrType attrs;
FldGetAttributes( field, &attrs );
if ( attrs.usable ) {
break;
}
}
}
FrmSetFocus( form, nextFocus );
return true;
} /* tryFieldNavigationKey */
#ifdef HS_DUO_SUPPORT
#ifdef DEBUG
static XP_UCHAR*
keyToStr( XP_U16 key )
{
#define keyCase(k) case (k): return #k
switch( key ) {
keyCase(vchrRockerUp);
keyCase(vchrRockerDown);
keyCase(vchrRockerLeft);
keyCase(vchrRockerRight);
keyCase(vchrRockerCenter);
default:
return "huh?";
}
#undef keyCase
}
#endif
static XP_Bool
tryDuoRockerKey( PalmAppGlobals* globals, XP_U16 key )
{
XP_Bool result = XP_FALSE;
XP_U16 focusID;
FormPtr form;
switch( key ) {
case vchrRockerUp:
case vchrRockerDown:
case vchrRockerLeft:
case vchrRockerRight:
XP_LOGF( "got rocker key: %s", keyToStr(key) );
result = XP_FALSE;
break;
case vchrRockerCenter:
/* if one of the gadgets is focussed, "tap" it. */
XP_LOGF( "got rocker key: %s", keyToStr(key) );
form = FrmGetActiveForm();
focusID = FrmGetObjectId( form, FrmGetFocus( form ) );
if ( IS_SERVER_GADGET( focusID ) ) {
changeGadgetHilite( globals, focusID );
result = XP_TRUE;
} else {
XP_LOGF( "%d not server gadget", focusID );
}
break;
default:
break;
}
return result;
} /* tryDuoRockerKey */
#endif
static void
adjustVisibility( PalmAppGlobals* globals, XP_Bool canDraw )
{
FormPtr form = FrmGetActiveForm();
short i;
PalmNewGameState* state = &globals->newGameState;
XP_Bool isNewGame = globals->isNewGame;
Connectedness curServerHilite = state->curServerHilite;
Boolean canShowRemote = curServerHilite != SERVER_STANDALONE;
Boolean isClient = curServerHilite == SERVER_ISCLIENT;
XP_U16 nShown = 0;
Boolean canEdit = (curServerHilite == SERVER_STANDALONE) || isNewGame;
XP_U16 nToShow = (isClient && isNewGame)?
state->curNPlayersLocal:state->curNPlayersTotal;
/* It's illegal for there to be 0 players selected. So if that ever
happens, make the first player local. And beep? */
if ( nToShow == 0 ) {
XP_ASSERT( isClient ); /* the only way this can happen is if someone
sets type to SERVER_ISCLIENT when there
are no local players. */
state->isLocal[0] = true;
nToShow = state->curNPlayersLocal = 1;
setBooleanCtrl( XW_REMOTE_1_CHECKBOX_ID, false );
}
if ( canShowRemote && isClient ) {
canShowRemote = !isNewGame;
}
#ifndef XWFEATURE_STANDALONE_ONLY
disOrEnable( form, XW_LOCAL_LABEL_ID, canShowRemote );
if ( canShowRemote ) {
disOrEnable( form, XW_TOTALP_LABEL_ID, XP_TRUE );
} else {
disOrEnable( form, XW_LOCALP_LABEL_ID, XP_TRUE );
}
#endif
for ( i = 0; i < MAX_NUM_PLAYERS; ++i ) {
short offset = NUM_PLAYER_COLS * i;
Boolean lineVisible = nShown < nToShow;
Boolean isLocal;
#ifndef XWFEATURE_STANDALONE_ONLY
Boolean showRemote;
Boolean remoteChecked = !state->isLocal[i];
if ( isClient && lineVisible && remoteChecked && isNewGame ) {
lineVisible = false;
}
#endif
/* Since the user of a device can change at will whether a local
player is a robot, we don't show that attribute except when it's
for a local player; don't keep track of what's going on on the
other device. */
isLocal = lineVisible;
#ifndef XWFEATURE_STANDALONE_ONLY
showRemote = lineVisible && canShowRemote;
isLocal = isLocal &&
(curServerHilite == SERVER_STANDALONE
|| (showRemote && !remoteChecked)
|| (isClient && isNewGame) );
/* show local/remote checkbox if not standalone */
disOrEnable( form, XW_REMOTE_1_CHECKBOX_ID + offset,
lineVisible && showRemote );
#endif
/* show name no matter what (if line's showing) */
disOrEnable( form, XW_PLAYERNAME_1_FIELD_ID + offset,
lineVisible && (isLocal || !isNewGame) );
if ( lineVisible ) {
FieldPtr nameField =
getActiveObjectPtr(XW_PLAYERNAME_1_FIELD_ID + offset);
setFieldEditable( nameField, canEdit );
if ( canDraw ) {
FldDrawField( nameField );
}
}
/* show robot checkbox if player is local */
disOrEnable( form, XW_ROBOT_1_CHECKBOX_ID + offset, isLocal );
/* and show password if not a robot (and if local) */
disOrEnable( form, XW_PLAYERPASSWD_1_TRIGGER_ID + offset,
isLocal && !state->isRobot[i] );
if ( lineVisible ) {
++nShown;
}
XP_ASSERT( nShown <= MAX_NUM_PLAYERS );
}
#ifndef XWFEATURE_STANDALONE_ONLY
XP_ASSERT( nShown > 0 );
setSelectorFromList( XW_NPLAYERS_SELECTOR_ID,
state->playerNumList, nShown - 1 );
#endif
} /* adjustVisibility */
/*
* Copy the local state into global state.
*/
static void
updatePlayerInfo( PalmAppGlobals* globals )
{
UInt16 i;
CurGameInfo* gi;
LocalPlayer* lp;
PalmNewGameState* state = &globals->newGameState;
Connectedness curServerHilite = globals->newGameState.curServerHilite;
gi = &globals->gameInfo;
gi->nPlayers = curServerHilite == SERVER_ISCLIENT?
state->curNPlayersLocal: state->curNPlayersTotal;
XP_ASSERT( gi->nPlayers <= MAX_NUM_PLAYERS );
gi->boardSize = globals->prefsDlgState->curBdSize;
gi->serverRole = curServerHilite;
replaceStringIfDifferent( MPPARM(globals->mpool) &gi->dictName,
globals->newGameState.dictName );
for ( i = 0, lp = gi->players; i < MAX_NUM_PLAYERS; ++i, ++lp ) {
XP_UCHAR* name = NULL;
XP_UCHAR* passwd = NULL;
short offset = NUM_PLAYER_COLS * i;
XP_Bool isLocal = state->isLocal[i];
if ( isLocal ) {
MemPtr p = getActiveObjectPtr( offset +
XW_PLAYERNAME_1_FIELD_ID );
name = (XP_UCHAR*)FldGetTextPtr( p );
if ( name == NULL ) {
name = (XP_UCHAR*)"";
}
passwd = globals->newGameState.passwds[i];
}
lp->isRobot = state->isRobot[i];
lp->isLocal = isLocal;
replaceStringIfDifferent(MPPARM(globals->mpool) &lp->name, name);
replaceStringIfDifferent(MPPARM(globals->mpool) &lp->password, passwd);
}
#ifdef BEYOND_IR
if ( state->connsSettingChanged ) {
CommsAddrRec addr;
XP_U16 localPort;
comms_getAddr( globals->game.comms, &addr, &localPort );
addr.conType = state->connAddrs.conType;
if ( addr.conType == COMMS_CONN_IP ) {
addr.u.ip.port = state->connAddrs.remotePort;
addr.u.ip.ipAddr = state->connAddrs.remoteIP;
localPort = state->connAddrs.localPort;
}
comms_setAddr( globals->game.comms, &addr, localPort );
}
#endif
} /* updatePlayerInfo */
void
drawOneGadget( UInt16 id, char* text, Boolean hilite )
{
RectangleType divRect;
XP_U16 len = StrLen(text);
XP_U16 width = FntCharsWidth( text, len );
XP_U16 left;
getObjectBounds( id, &divRect );
WinDrawRectangleFrame( rectangleFrame, &divRect );
WinEraseRectangle( &divRect, 0 );
left = divRect.topLeft.x;
left += (divRect.extent.x - width) / 2;
WinDrawChars( text, len, left, divRect.topLeft.y );
if ( hilite ) {
WinInvertRectangle( &divRect, 0 );
}
} /* drawOneGadget */
/* Frame 'em, draw their text, and highlight the one that's selected
*/
#ifndef XWFEATURE_STANDALONE_ONLY
#ifdef HS_DUO_SUPPORT
static void
drawFocusRingOnGadget()
{
FormPtr form = FrmGetActiveForm();
XP_U16 focusID = FrmGetObjectId( form, FrmGetFocus(form) );
if ( IS_SERVER_GADGET(focusID) ) {
Err err;
RectangleType rect;
getObjectBounds( focusID, &rect );
err = HsNavDrawFocusRing( form, focusID, 0, &rect,
hsNavFocusRingStyleObjectTypeDefault,
false );
XP_ASSERT( err == errNone );
}
} /* drawFocusRingOnGadget */
#endif
static void
drawConnectGadgets( PalmAppGlobals* globals )
{
UInt16 i;
ListPtr list = getActiveObjectPtr( XW_SERVERTYPES_LIST_ID );
XP_ASSERT( !!list );
for ( i = 0; i < 3; ++i ) {
char* text = LstGetSelectionText( list, i );
Boolean hilite = i == globals->newGameState.curServerHilite;
drawOneGadget( i + XW_SOLO_GADGET_ID, text, hilite );
}
#ifdef HS_DUO_SUPPORT
drawFocusRingOnGadget();
#endif
} /* drawConnectGadgets */
#ifdef HS_DUO_SUPPORT
static XP_Bool
considerGadgetFocus( PalmNewGameState* state, EventType* event )
{
XP_Bool result = XP_FALSE;
XP_Bool isTake;
XP_U16 eType = event->eType;
FormPtr form = FrmGetActiveForm();
XP_U16 objectID;
XP_ASSERT( eType == frmObjectFocusTakeEvent
|| eType == frmObjectFocusLostEvent );
XP_ASSERT( event->data.frmObjectFocusTake.formID == FrmGetActiveFormID() );
isTake = eType == frmObjectFocusTakeEvent;
if ( isTake ) {
objectID = event->data.frmObjectFocusTake.objectID;
} else {
objectID = event->data.frmObjectFocusLost.objectID;
}
/* docs say to return HANDLED for both take and lost */
result = IS_SERVER_GADGET( objectID );
if ( result ) {
Err err;
if ( isTake ) {
FrmSetFocus(form, FrmGetObjectIndex(form, objectID));
drawFocusRingOnGadget();
result = XP_TRUE;
/* } else { */
/* err = HsNavRemoveFocusRing( form ); */
}
}
return result;
} /* considerGadgetFocus */
#endif
static void
changeGadgetHilite( PalmAppGlobals* globals, UInt16 hiliteID )
{
PalmNewGameState* state = &globals->newGameState;
XP_Bool isNewGame = globals->isNewGame;
hiliteID -= XW_SOLO_GADGET_ID;
if ( hiliteID != state->curServerHilite ) {
/* if it's not a new game, don't recognize the change */
if ( isNewGame ) {
state->curServerHilite = hiliteID;
drawConnectGadgets( globals );
adjustVisibility( globals, XP_TRUE );
} else {
beep();
}
}
#ifdef BEYOND_IR
/* Even if it didn't change, pop the connections form */
if ( hiliteID != SERVER_STANDALONE ) {
if ( isNewGame || hiliteID==globals->newGameState.curServerHilite ) {
PopupConnsForm( globals, hiliteID, &state->connAddrs );
}
}
#endif
} /* changeGadgetHilite */
static Boolean
checkHiliteGadget( PalmAppGlobals* globals, EventType* event,
PalmNewGameState* state )
{
Boolean result = false;
UInt16 selGadget;
XP_ASSERT( &globals->newGameState == state );
result = penInGadget( event, &selGadget );
if ( result ) {
changeGadgetHilite( globals, selGadget );
}
return result;
} /* checkHiliteGadget */
#endif
/* If there's currently no password set, just let 'em set one. If there is
* one set, they need to know the old before setting the new.
*/
static void
handlePasswordTrigger( PalmAppGlobals* globals, UInt16 controlID )
{
UInt16 playerNum;
PalmNewGameState* state = &globals->newGameState;
XP_UCHAR** password;
XP_UCHAR* name;
FieldPtr nameField;
XP_U16 len;
XP_UCHAR buf[32];
char* label;
playerNum = (controlID - XW_PLAYERPASSWD_1_TRIGGER_ID) / NUM_PLAYER_COLS;
XP_ASSERT( playerNum < MAX_NUM_PLAYERS );
password = &state->passwds[playerNum];
nameField = getActiveObjectPtr( XW_PLAYERNAME_1_FIELD_ID +
(NUM_PLAYER_COLS * playerNum) );
name = (XP_UCHAR*)FldGetTextPtr( nameField );
len = sizeof(buf);
if ( askPassword( globals, name, true, buf, &len ) ) {
if ( len == 0 ) {
buf[0] = '\0';
label = " ";
} else {
label = "*";
}
replaceStringIfDifferent(MPPARM(globals->mpool) password,
(unsigned char*)buf);
/* control owns the string passed in */
CtlSetLabel( getActiveObjectPtr( controlID ), label );
}
} /* handlePasswordTrigger */
static void
unloadNewGameState( PalmAppGlobals* globals )
{
XP_U16 i;
XP_UCHAR** passwd;
PalmNewGameState* state = &globals->newGameState;
for ( passwd = state->passwds, i = 0;
i < MAX_NUM_PLAYERS; ++i, ++passwd ) {
if ( !!*passwd ) {
XP_FREE( globals->mpool, *passwd );
*passwd = NULL;
}
}
/* XP_WARNF( "freeing string 0x%lx", state->dictName ); */
XP_FREE( globals->mpool, state->dictName );
state->dictName = NULL;
} /* unloadNewGameState */
static void
loadNewGameState( PalmAppGlobals* globals )
{
CurGameInfo* gi = &globals->gameInfo;
PalmNewGameState* state = &globals->newGameState;
XP_U16 i;
LocalPlayer* lp;
XP_MEMSET( state, 0, sizeof(*state) );
state->dictName = copyString( MPPARM(globals->mpool) gi->dictName );
state->curServerHilite = gi->serverRole;
for ( i = 0, lp=gi->players; i < MAX_NUM_PLAYERS; ++i, ++lp ) {
state->isLocal[i] = lp->isLocal;
state->isRobot[i] = lp->isRobot;
state->passwds[i] = copyString( MPPARM(globals->mpool)
lp->password );
}
state->curNPlayersTotal = gi->nPlayers;
state->curNPlayersLocal = countLocalIn( state, gi->nPlayers );
XP_ASSERT( state->curNPlayersLocal <= MAX_NUM_PLAYERS );
#ifdef BEYOND_IR
{
CommsAddrRec addr;
comms_getAddr( globals->game.comms, &addr,
&state->connAddrs.localPort );
state->connAddrs.remotePort = addr.u.ip.port;
state->connAddrs.remoteIP = addr.u.ip.ipAddr;
state->connAddrs.conType = addr.conType;
}
#endif
} /* loadNewGameState */

32
palm/newgame.h Normal file
View file

@ -0,0 +1,32 @@
/* -*-mode: C; fill-column: 77; c-basic-offset: 4; -*- */
/*
* Copyright 2001-2002 by Eric House (fixin@peak.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.
*/
#ifndef NEWGAME_H
#define NEWGAME_H
#include <Event.h>
#include "palmmain.h"
Boolean newGameHandleEvent( EventPtr event );
void drawOneGadget( UInt16 id, char* text, Boolean hilite );
#endif