first checkin

This commit is contained in:
ehouse 2003-11-01 17:53:41 +00:00
parent bb3cb3e27b
commit 23bf1ba67c
27 changed files with 5367 additions and 0 deletions

87
dawg/pbitm2bin.pl Executable file
View file

@ -0,0 +1,87 @@
#!/usr/bin/perl
#
# Copyright 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.
#
#
# Given a pbitm on stdin, a text bitmap file where '#' indicates a set
# bit and '-' indicates a clear bit, convert into binary form (on
# stdout) where there's one bit per bit plus a byte each for the width
# and height. Nothing for bitdepth at this point. And no padding: if
# the number of bits in a row isn't a multiple of 8 then one byte will
# hold the last bits of one row and the first of another.
use strict;
my $nRows = 0;
my $nCols = 0;
my $bits = ""; # save the chars in a single string to start
# first gather information and sanity-check the data
while (<>) {
chomp;
my $len = length();
if ( $nCols == 0 ) {
$nCols = $len;
} else {
die "line of inconsistent length" if $nCols != $len ;
}
if ( $nCols == 0 ) {
last;
}
$bits .= $_;
++$nRows;
}
my $len = length($bits);
print pack( "C", $nCols );
# if we've been given an empty file, print out a single null byte and
# be done. That'll be the convention for "non-existant bitmap".
if ( $len == 0 ) {
exit 0;
}
print pack( "C", $nRows );
printf STDERR "emitting %dx%d bitmap\n", $nCols, $nRows;
my @charlist = split( //,$bits);
my $byte = 0;
for ( my $count = 0; ; ++$count ) {
my $ch = $charlist[$count];
my $bitindex = $count % 8;
$ch == '-' || $ch == '#' || die "unknown char $ch";
my $bit = ($ch eq '#')? 1:0;
$byte |= $bit << (7 - $bitindex);
my $lastPass = $count + 1 == $len;
if ( $bitindex == 7 || $lastPass ) {
print pack( "C", $byte );
if ( $lastPass ) {
last;
}
$byte = 0;
}
} # for loop

View file

@ -0,0 +1,45 @@
/*
* Copyright 1997 - 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.
*/
/*
* For faking out franklin compiler for now.
*/
enum {
STRD_REMAINING_TILES_ADD,
STRD_UNUSED_TILES_SUB,
STR_COMMIT_CONFIRM,
STR_BONUS_ALL,
STRD_TURN_SCORE,
STR_NONLOCAL_NAME,
STRD_TIME_PENALTY_SUB,
STRD_CUMULATIVE_SCORE,
STRS_TRAY_AT_START,
STRS_MOVE_DOWN,
STRS_MOVE_ACROSS,
STRS_NEW_TILES,
STRSS_TRADED_FOR,
STR_PASS,
STR_PHONY_REJECTED,
STRD_ROBOT_TRADED,
STR_ROBOT_MOVED,
STR_REMOTE_MOVED,
STR_LAST
};

159
franklin/Makefile Normal file
View file

@ -0,0 +1,159 @@
# ©2001 Franklin Electronic Publishers, Inc. Burlington, NJ.
# File: gui/test/Makefile
#
PLATFORM = franklin
COMMON = ../common
XW_DEFINES = -DPLATFORM_EBOOK -DPOINTER_SUPPORT -DKEY_SUPPORT -DSHOW_PROGRESS -DXWFEATURE_STANDALONE_ONLY -D__LITTLE_ENDIAN
include ../common/config.mk
APPNAME = xwords4
# Define the list of source files
SRCS_CPP = frankdraw.cpp \
frankmain.cpp \
franksavedgames.cpp \
frankask.cpp \
frankgamesdb.cpp \
frankpasswd.cpp \
frankshowtext.cpp \
frankdict.cpp \
frankletter.cpp \
frankplayer.cpp \
frankdlist.cpp
SRCS_C =
SRCS_S =
# Program parameters (ebo_locate needs 12K of stack)
#HEAPSPACE = 98304
HEAPSPACE = 409600 # 0x64000
MAINSTACKSPACE = 16384
TIMERSTACKSPACE = 4096
# Environment: Use "yes" or "no"
GUI_LOCAL_COPY = no
OS_LOCAL_COPY = no
LANG_LOCAL_COPY = no
GUI_LANGUAGE = GUI_Amr.pkg
OS_BASEDIR = ../../../os
GUI_BASEDIR = ../source
#To prevent warnings from stopping the compilation, change the following line
#to "ERROR=" or start the make using "make ERROR=".
ERROR = -Werror
OBJS = ${COMMONOBJ}
# Include the standard Makefile targets
ifeq (x$(EBSDK_LIBS)x,xx)
# Normal: binary release version
include ${EBOOKMAN_SDK}/ebsdk.uses
include ${ESDK_TARGET_INC}/Makefile.GUI
else
# Special: building the SDK
include ${EBSDK_LIBS}/ebookman_libs.uses
include ../source/Makefile.GUI
endif
#
# At this point in the Makefile, you can put overrides for variables that
# were set in "Makefile.GUI".
#
#Create linkable version of VoiceAge file
#${OBJDIR}/objects.link: welcome.voiceage
#welcome.voiceage: welcome.seb
# tail -c+4097 <welcome.seb >welcome.voiceage
#CLEANLIST += welcome.voiceage
#Need this for an os1 link of a program that uses floating-point
#GCC_LIB = ${ESDK_LIBGCC_INSTALL_LIBFILE_FLOAT}
INCFLAGS += -I$(COMMON) -I./
CFLAGS += ${XW_DEFINES} -DCPLUS
CFL_NOCPLUS = $(subst -DCPLUS,,${CFLAGS})
CLEANLIST += ${COMMONOBJ}
# dependencies for image generation
BMPS = ./bmps
frankmain.cpp: bmps_includes.h
$(BMPS)/%.cpp: $(BMPS)/%.pbitm
./pbitm2frank.pl $< $* > $@
GENIMGS = $(BMPS)/flip.cpp \
$(BMPS)/lightbulb.cpp \
$(BMPS)/valuebutton.cpp \
$(BMPS)/undo.cpp \
# listing the .cpp files here as dependencies should be all that's
# needed to get them generated.
bmps_includes.h: $(GENIMGS)
@echo "/* This file generated in Makefile; do not edit!!! */" > $@
for f in $^; do echo "#include \"$$f\"" >> $@; done
#
# Generic rules for invoking the compiler and assembler. Stolen from
# Makefile.GUI
#
${COMMONOBJDIR}/%.s :: ${COMMON}/%.c
${ESDK_GCC32_EXE} -b sneak32 -g $(CFL_NOCPLUS) -mclist -S -o $@ -c $<
${COMMONOBJDIR}/%.i :: ${COMMON}/%.c
${ESDK_GCC32_EXE} -b sneak32 -g $(CFL_NOCPLUS) -mclist -E -o $@ -c $<
${COMMONOBJDIR}/%.i :: ${COMMON}/%.cpp
${ESDK_GXX32_EXE} -b sneak32 -g $(CFLAGS) -mclist -E -o $@ -c $<
${COMMONOBJDIR}/%.s :: ${COMMON}/%.cpp
${ESDK_GXX32_EXE} -b sneak32 -g $(CFLAGS) -mclist -S -o $@ -c $<
${COMMONOBJDIR}/%.o :: ${COMMON}/%.cpp
${ESDK_GXX32_EXE} -b sneak32 -g $(CFLAGS) -o $@ -c $<
${COMMONOBJDIR}/%.o :: ${COMMON}/%.c
${ESDK_GCC32_EXE} -b sneak32 -g $(CFL_NOCPLUS) -o $@ -c $<
${COMMONOBJDIR}/%.o :: ${COMMONOBJDIR}/%.s
${ESDK_ASM32_EXE} -case ${INCFLAGS} -po ${COMMONOBJDIR} -o $<
# Targets to allow build without copying lots of files in. First has
# hack to force directory creation
os.link os.def standalone.link:
mkdir -p ../common/franklin
ln -s $$(find $${EBOOKMAN_SDK} -follow -name $@ | grep gui) $@
# get rid of the welcome crap
libraries.link:
cat $$(find $${EBOOKMAN_SDK} -follow -name $@ | grep gui) | \
grep -v Welcome > $@
#
# The following targets are usable only during SDK creation. They are for
# copying this directory to samples/gui/test.
#
build: os sa
configure:
do_install_out: build
mkdir -p ${ELIB_GUI_INSTALL_SAMPLE_TESTDIR}
(tar cf - . | (cd ${ELIB_GUI_INSTALL_SAMPLE_TESTDIR} && tar xf -))
memdebug:
$(MAKE) "XW_DEFINES = ${XW_DEFINES} -DMEM_DEBUG -DDEBUG"
test:
echo ${OBJS}

108
franklin/frankask.cpp Normal file
View file

@ -0,0 +1,108 @@
// -*-mode: C; fill-column: 78; 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.
*/
#if 0
#include <assert.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "sys.h"
#include "gui.h"
#include "OpenDatabases.h"
#include "ebm_object.h"
extern "C" {
#include "xptypes.h"
#include "board.h"
#include "model.h"
}
#include "frankids.h"
#include "frankask.h"
#define FIRST_BUTTON_ID 2000
CAskDialog::CAskDialog( U16* resultP, char* question, U16 numButtons, ... )
: CWindow( ASK_WINDOW_ID, 2, 50, 196, 80, "Question..." )
{
U16 i;
va_list ap;
this->resultP = resultP;
this->question = question;
this->drawInProgress = FALSE;
U16 horSpacing = 196 / (numButtons+1);
va_start(ap, numButtons);
for ( i = 0; i < numButtons; ++i ) {
char* buttName = va_arg( ap, char*);
XP_DEBUGF( "button %d's title is %s\n", i, buttName );
CButton* button = new CButton( i+FIRST_BUTTON_ID, 0, 0, buttName );
U16 width = button->GetWidth();
U16 bx = horSpacing * (i+1);
this->AddChild( button, bx - (width/2), 40 );
}
va_end(ap);
this->textY = 10;
this->textX = 5;
} // CAskDialog::CAskDialog
void
CAskDialog::Draw()
{
if ( !this->drawInProgress ) {
this->drawInProgress = TRUE;
CWindow::Draw(); // buttons, etc.
this->DrawText( this->question, this->textX, this->textY );
this->drawInProgress = FALSE;
}
} // CAskDialog::Draw
S32
CAskDialog::MsgHandler( MSG_TYPE type, CViewable *object, S32 data )
{
S32 result = 0;
S16 id;
switch (type) {
case MSG_BUTTON_SELECT:
id = object->GetID();
*this->resultP = id - FIRST_BUTTON_ID;
this->Close();
result = 1;
default:
break;
}
if ( result == 0 ) {
result = CWindow::MsgHandler( type, object, data );
}
return result;
} // CGamesBrowserWindow::MsgHandler
#endif /* 0 */

40
franklin/frankask.h Normal file
View file

@ -0,0 +1,40 @@
// -*-mode: C; fill-column: 78; c-basic-offset: 4; -*-
/*
* Copyright 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.
*/
#if 0
#ifndef _FRANKASK_H_
#define _FRANKASK_H_
class CAskDialog : public CWindow {
private:
U16* resultP;
U16 textY;
U16 textX;
char* question;
BOOL drawInProgress;
public:
CAskDialog( U16* resultP, char* question, U16 numButtons, ...);
void Draw();
S32 MsgHandler( MSG_TYPE type, CViewable *object, S32 data );
};
#endif
#endif /* 0 */

422
franklin/frankdict.cpp Normal file
View file

@ -0,0 +1,422 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4;-*- */
/*
* Copyright 1997-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 <ebm_object.h>
#include "dictnryp.h"
#include "frankdict.h"
#include "frankids.h"
#ifdef CPLUS
extern "C" {
#endif
typedef struct FrankDictionaryCtxt {
DictionaryCtxt super;
void* base;
size_t dictSize;
BOOL isMMC; /* means the base must be free()d */
} FrankDictionaryCtxt;
static void frank_dictionary_destroy( DictionaryCtxt* dict );
static void loadSpecialData( FrankDictionaryCtxt* ctxt, U8** ptr );
static U16 countSpecials( FrankDictionaryCtxt* ctxt );
static int tryLoadMMCFile( MPFORMAL XP_UCHAR* dictName, U8** ptrP,
size_t* size );
static U32 ntohl_noalign(U8* n);
static U16 ntohs_noalign(U8** n);
U16
GetDictFlags( ebo_enumerator_t* eboe, FileLoc loc )
{
U16 flags = FRANK_DICT_FLAGS_ERROR;
U16 tmp;
if ( loc == IN_RAM ) {
ebo_name_t* name = &eboe->name;
size_t size = EBO_BLK_SIZE;
U8* ptr = (U8*)OS_availaddr + FLAGS_CHECK_OFFSET;
#ifdef DEBUG
int result =
#endif
ebo_mapin( name, 0, (void*)ptr, &size, 0 );
XP_ASSERT( result >= 0 );
tmp = *(U16*)ptr;
(void)ebo_unmap( ptr, size );
} else if ( loc == ON_MMC ) {
#ifdef DEBUG
long read =
#endif
ebo_iread( eboe->index, &tmp, 0, sizeof(tmp) );
XP_ASSERT( read == sizeof(tmp) );
}
XP_DEBUGF( "raw value: 0x%x", tmp );
#if BYTE_ORDER==LITTLE_ENDIAN
((char*)&flags)[0] = ((char*)&tmp)[1];
((char*)&flags)[1] = ((char*)&tmp)[0];
#else
flags = tmp;
#endif
XP_DEBUGF( "GetDictFlags returning 0x%x", flags );
return flags;
} /* GetDictFlags */
DictionaryCtxt*
frank_dictionary_make( MPFORMAL XP_UCHAR* dictName )
{
FrankDictionaryCtxt* ctxt = (FrankDictionaryCtxt*)NULL;
ctxt = (FrankDictionaryCtxt*)XP_MALLOC(mpool, sizeof(*ctxt));
XP_MEMSET( ctxt, 0, sizeof(*ctxt) );
MPASSIGN( ctxt->super.mpool, mpool );
if ( !!dictName ) {
ebo_enumerator_t eboe;
XP_MEMSET( &eboe.name, 0, sizeof(eboe.name) );
U8* ptr = (U8*)OS_availaddr + DICT_OFFSET;
size_t size = EBO_BLK_SIZE * 75; /* PENDING(ehouse) how to find size
of file */
strcpy( (char*)eboe.name.name, (char*)dictName );
strcpy( eboe.name.publisher, PUB_ERICHOUSE );
strcpy( eboe.name.extension, EXT_XWORDSDICT );
XP_DEBUGF( "makedict: looking for %s.%s\n", dictName,
&eboe.name.extension );
int result = ebo_mapin( &eboe.name, 0, (void*)ptr, &size, 0 );
XP_DEBUGF( "ebo_mapin returned %d; size=%d\n", result, size );
if ( result >= 0 ) {
if ( GetDictFlags( &eboe, IN_RAM ) != FRANK_DICT_VERSION_1 ) {
result = -1;
}
}
if ( result < 0 ) {
result = tryLoadMMCFile( MPPARM(mpool) dictName, &ptr, &size );
if ( result >= 0 ) {
ctxt->isMMC = true;
}
}
if ( result >= 0 ) {
XP_U16 numFaces;
XP_U16 facesSize;
/* save for later */
ctxt->base = (void*)ptr;
ctxt->dictSize = size;
ctxt->super.destructor = frank_dictionary_destroy;
#ifdef DEBUG
U16 flags =
#endif
ntohs_noalign( &ptr );
XP_ASSERT( flags == FRANK_DICT_VERSION_1 );
ctxt->super.nFaces = numFaces = *ptr++;
XP_DEBUGF( "read %d faces from dict\n", numFaces );
facesSize = numFaces * sizeof(ctxt->super.faces16[0]);
ctxt->super.faces16 = (XP_U16*)XP_MALLOC( mpool, facesSize );
XP_MEMSET( ctxt->super.faces16, 0, facesSize );
for ( XP_U16 i = 0; i < numFaces; ++i ) {
ctxt->super.faces16[i] = *ptr++;
}
ctxt->super.countsAndValues =
(XP_U8*)XP_MALLOC(mpool, numFaces*2);
ptr += 2; /* skip xloc header */
for ( U16 i = 0; i < numFaces*2; i += 2 ) {
ctxt->super.countsAndValues[i] = *ptr++;
ctxt->super.countsAndValues[i+1] = *ptr++;
}
loadSpecialData( ctxt, &ptr );
U32 topOffset = ntohl_noalign( ptr );
ptr += sizeof(topOffset);
XP_DEBUGF( "incremented ptr by startOffset: %ld", topOffset );
ctxt->super.topEdge = ptr + topOffset;
ctxt->super.base = ptr;
#ifdef DEBUG
XP_U32 dictLength = size - (ptr - ((U8*)ctxt->base));
/* Can't do this because size is a multiple of 0x1000 created
during the memory-mapping process. Need to figure out how to
get the actual size if it ever matter. */
/* XP_ASSERT( (dictLength % 3) == 0 ); */
ctxt->super.numEdges = dictLength / 3;
#endif
}
setBlankTile( (DictionaryCtxt*)ctxt );
ctxt->super.name = frankCopyStr(MPPARM(mpool) dictName);
}
return (DictionaryCtxt*)ctxt;
} // frank_dictionary_make
static int
tryLoadMMCFile( MPFORMAL XP_UCHAR* dictName, U8** ptrP, size_t* size )
{
int result;
ebo_enumerator_t eboe;
for ( result = ebo_first_xobject( &eboe );
result == EBO_OK;
result = ebo_next_xobject( &eboe ) ) {
if ( strcmp( eboe.name.publisher, PUB_ERICHOUSE ) == 0
&& strcmp( eboe.name.extension, EXT_XWORDSDICT ) == 0
&& strcmp( eboe.name.name, (char*)dictName ) == 0
&& GetDictFlags(&eboe, ON_MMC) == FRANK_DICT_VERSION_1 ) {
XP_DEBUGF( "looking to allocate %ld bytes", eboe.size );
void* buf = (void*)XP_MALLOC( mpool, eboe.size );
long read = ebo_iread (eboe.index, buf, 0, eboe.size );
if ( read != (long)eboe.size ) {
XP_FREE( mpool, buf );
result = -1;
} else {
*ptrP = (U8*)buf;
*size = eboe.size;
}
break;
}
}
return result;
} /* tryLoadMMCFile */
static U32
ntohl_noalign( U8* np )
{
union {
U32 num;
unsigned char aschars[4];
} u;
S16 i;
#if BYTE_ORDER==LITTLE_ENDIAN
for ( i = 3; i >= 0; --i ) {
u.aschars[i] = *np++;
}
#else
for ( i = 0; i < 4; ++i ) {
u.aschars[i] = *np++;
}
#endif
XP_DEBUGF( "ntohl_noalign returning %ld", u.num );
return u.num;
} /* ntohl_noalign */
static U16
ntohs_noalign( U8** p )
{
U8* np = *p;
union {
U16 num;
unsigned char aschars[2];
} u;
S16 i;
#if BYTE_ORDER==LITTLE_ENDIAN
for ( i = 1; i >= 0; --i ) {
u.aschars[i] = *np++;
}
#else
for ( i = 0; i < 2; ++i ) {
u.aschars[i] = *np++;
}
#endif
XP_DEBUGF( "ntohl_noalign returning %ld", u.num );
*p = np;
return u.num;
} /* */
static U16
countSpecials( FrankDictionaryCtxt* ctxt )
{
U16 result = 0;
for ( U16 i = 0; i < ctxt->super.nFaces; ++i ) {
if ( IS_SPECIAL(ctxt->super.faces16[i] ) ) {
++result;
}
}
return result;
} /* countSpecials */
static XP_Bitmap*
makeBitmap( FrankDictionaryCtxt* ctxt, U8** ptrp )
{
U8* ptr = *ptrp;
IMAGE* bitmap = (IMAGE*)NULL;
U8 nCols = *ptr++;
if ( nCols > 0 ) {
U8 nRows = *ptr++;
U16 rowBytes = (nCols+7) / 8;
bitmap = (IMAGE*)XP_MALLOC( ctxt->super.mpool,
sizeof(IMAGE) + (nRows * rowBytes) );
bitmap->img_width = nCols;
bitmap->img_height = nRows;
bitmap->img_rowbytes = rowBytes;
bitmap->img_colmode = COLOR_MODE_MONO;
bitmap->img_palette = (COLOR*)NULL;
U8* dest = ((U8*)&bitmap->img_buffer) + sizeof(bitmap->img_buffer);
bitmap->img_buffer = dest;
U8 srcByte = 0, destByte = 0;
U8 nBits = nRows*nCols;
for ( U16 i = 0; i < nBits; ++i ) {
U8 srcBitIndex = i % 8;
U8 destBitIndex = (i % nCols) % 8;
if ( srcBitIndex == 0 ) {
srcByte = *ptr++;
}
U8 srcMask = 1 << (7 - srcBitIndex);
U8 bit = (srcByte & srcMask) != 0;
destByte |= bit << (7 - destBitIndex);
/* we need to put the byte if we've filled it or if we're done
with the row */
if ( (destBitIndex==7) || ((i%nCols) == (nCols-1)) ) {
*dest++ = destByte;
destByte = 0;
}
}
}
*ptrp = ptr;
return (XP_Bitmap*)bitmap;
} /* makeBitmap */
static void
loadSpecialData( FrankDictionaryCtxt* ctxt, U8** ptrp )
{
U16 nSpecials = countSpecials( ctxt );
U8* ptr = *ptrp;
XP_DEBUGF( "loadSpecialData: there are %d specials\n", nSpecials );
XP_UCHAR** texts = (XP_UCHAR**)XP_MALLOC( ctxt->super.mpool,
nSpecials * sizeof(*texts) );
SpecialBitmaps* bitmaps = (SpecialBitmaps*)
XP_MALLOC( ctxt->super.mpool, nSpecials * sizeof(*bitmaps) );
for ( Tile i = 0; i < ctxt->super.nFaces; ++i ) {
XP_UCHAR face = ctxt->super.faces16[(short)i];
if ( IS_SPECIAL(face) ) {
/* get the string */
U8 txtlen = *ptr++;
XP_UCHAR* text = (XP_UCHAR*)XP_MALLOC(ctxt->super.mpool, txtlen+1);
XP_MEMCPY( text, ptr, txtlen );
ptr += txtlen;
text[txtlen] = '\0';
XP_ASSERT( face < nSpecials );
texts[face] = text;
XP_DEBUGF( "making bitmaps for %s", texts[face] );
bitmaps[face].largeBM = makeBitmap( ctxt, &ptr );
bitmaps[face].smallBM = makeBitmap( ctxt, &ptr );
}
}
ctxt->super.chars = texts;
ctxt->super.bitmaps = bitmaps;
XP_DEBUGF( "loadSpecialData consumed %ld bytes",
ptr - *ptrp );
*ptrp = ptr;
} /* loadSpecialData */
#if 0
char*
frank_dictionary_getName(DictionaryCtxt* dict )
{
FrankDictionaryCtxt* ctxt = (FrankDictionaryCtxt*)dict;
return ctxt->name;
} /* frank_dictionary_getName */
#endif
static void
frank_dictionary_destroy( DictionaryCtxt* dict )
{
FrankDictionaryCtxt* ctxt = (FrankDictionaryCtxt*)dict;
U16 nSpecials = countSpecials( ctxt );
U16 i;
if ( !!dict->chars ) {
for ( i = 0; i < nSpecials; ++i ) {
XP_UCHAR* text = dict->chars[i];
if ( !!text ) {
XP_FREE( dict->mpool, text );
}
}
XP_FREE( dict->mpool, dict->chars );
}
if ( !!dict->countsAndValues ) {
XP_FREE( dict->mpool, dict->countsAndValues );
}
if ( !!ctxt->super.faces16 ) {
XP_FREE( dict->mpool, ctxt->super.faces16 );
}
if ( !!ctxt->super.bitmaps ) {
for ( i = 0; i < nSpecials; ++i ) {
XP_Bitmap bmp = ctxt->super.bitmaps[i].largeBM;
if ( !!bmp ) {
XP_FREE( ctxt->super.mpool, bmp );
}
bmp = ctxt->super.bitmaps[i].smallBM;
if ( !!bmp ) {
XP_FREE( ctxt->super.mpool, bmp );
}
}
XP_FREE( ctxt->super.mpool, ctxt->super.bitmaps );
}
if ( ctxt->isMMC ) {
XP_FREE( ctxt->super.mpool, ctxt->base );
} else {
(void)ebo_unmap( ctxt->base, ctxt->dictSize );
}
XP_FREE( ctxt->super.mpool, ctxt );
} // frank_dictionary_destroy
#ifdef CPLUS
}
#endif

48
franklin/frankdict.h Normal file
View file

@ -0,0 +1,48 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
/*
* Copyright 1999-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 _FRANKDICT_H_
#define _FRANKDICT_H_
#include <ebm_object.h>
#ifdef CPLUS
extern "C" {
#endif
typedef enum {
LOC_UNKNOWN,
IN_RAM,
ON_MMC
} FileLoc ;
#define FRANK_DICT_VERSION_1 0x0001
#define FRANK_DICT_FLAGS_ERROR 0xFFFF
U16 GetDictFlags( ebo_enumerator_t* eboe, FileLoc loc );
DictionaryCtxt* frank_dictionary_make( MPFORMAL XP_UCHAR* name );
void debugf( char* format, ... );
#ifdef CPLUS
}
#endif
#endif /* _FRANKDICT_H_ */

120
franklin/frankdlist.cpp Executable file
View file

@ -0,0 +1,120 @@
// -*-mode: C; fill-column: 78; 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.
*/
#include "frankdlist.h"
#include "frankids.h"
#include "strutils.h"
FrankDictList::FrankDictList(MPFORMAL_NOCOMMA)
{
MPASSIGN( this->mpool, mpool );
fNDicts = 0;
for ( XP_U16 i = 0; i < fNDicts; ++i ) {
fDictNames[i] = (XP_UCHAR*)NULL;
}
populateList();
} // FrankDictList::FrankDictList
FrankDictList::~FrankDictList()
{
for ( XP_U16 i = 0; i < fNDicts; ++i ) {
XP_ASSERT( !!fDictNames[i] );
XP_FREE( mpool, fDictNames[i] );
}
}
XP_S16
FrankDictList::IndexForName( XP_UCHAR* name )
{
XP_ASSERT( !!name );
for ( XP_S16 i = 0; i < fNDicts; ++i ) {
if ( 0 == XP_STRCMP( name, fDictNames[i] ) ) {
return i;
}
}
XP_ASSERT(0);
return -1;
} // FrankDictList::IndexForName
XP_S16
FrankDictList::dictListInsert( ebo_enumerator_t* eboep, FileLoc loc )
{
if ( strcmp( eboep->name.publisher, PUB_ERICHOUSE ) == 0
&& strcmp( eboep->name.extension, EXT_XWORDSDICT ) == 0
&& GetDictFlags( eboep, loc ) == FRANK_DICT_VERSION_1 ) {
XP_UCHAR* newName = (XP_UCHAR*)eboep->name.name;
XP_U16 nDicts = fNDicts;
XP_S16 pred; // predecessor
// it's a keeper. Insert in alphabetical order
for ( pred = nDicts - 1; pred >= 0; --pred ) {
XP_S16 cmps = XP_STRCMP( newName, fDictNames[pred] );
// 0 means a duplicate, e.g one on MMC and another in
// RAM. Drop the dup in favor of the RAM copy.
if ( cmps == 0 ) {
return -1;
}
if ( cmps > 0 ) {
break; // found it
}
}
/* Now move any above the new location up */
XP_S16 newLoc = pred + 1;
for ( XP_U16 j = nDicts; j > newLoc; --j ) {
fDictNames[j] = fDictNames[j-1];
}
XP_ASSERT( newLoc >= 0 );
fDictNames[newLoc] = copyString( MPPARM(mpool) newName );
fDictLocs[newLoc] = loc;
++fNDicts;
return newLoc;
} else {
return -1;
}
}
void
FrankDictList::populateList()
{
int result;
ebo_enumerator_t eboe;
for ( result = ebo_first_object( &eboe );
result == EBO_OK;
result = ebo_next_object( &eboe ) ) {
dictListInsert( &eboe, IN_RAM );
}
for ( result = ebo_first_xobject( &eboe );
result == EBO_OK;
result = ebo_next_xobject( &eboe ) ) {
dictListInsert( &eboe, ON_MMC );
}
} // FrankDictList::populateList

65
franklin/frankdlist.h Executable file
View file

@ -0,0 +1,65 @@
// -*-mode: C; fill-column: 78; 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 _FRANKDLIST_H_
#define _FRANKDLIST_H_
#include <ebm_object.h>
extern "C" {
#include "comtypes.h"
}
#include "mempool.h"
#include "frankdict.h"
#define MAX_DICTS 16
class FrankDictList {
public:
FrankDictList( MPFORMAL_NOCOMMA );
~FrankDictList();
XP_U16 GetDictCount() { return fNDicts; }
XP_UCHAR* GetNthName( XP_U16 n ) {
XP_ASSERT( n < fNDicts );
return fDictNames[n];
}
FileLoc GetNthLoc( XP_U16 n ) {
XP_ASSERT( n < fNDicts );
return fDictLocs[n];
}
XP_S16 IndexForName( XP_UCHAR* name );
private:
void populateList();
XP_S16 dictListInsert( ebo_enumerator_t* eboep, FileLoc loc );
XP_U16 fNDicts;
XP_UCHAR* fDictNames[MAX_DICTS];
FileLoc fDictLocs[MAX_DICTS];
MPSLOT
};
#endif

615
franklin/frankdraw.cpp Normal file
View file

@ -0,0 +1,615 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4;-*- */
/*
* Copyright 1997-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 <stdlib.h>
extern "C" {
#include "xptypes.h"
#include "board.h"
#include "draw.h"
#include "mempool.h"
} /* extern "C" */
#include "frankmain.h"
static void
insetRect( RECT* r, short i )
{
r->x += i;
r->y += i;
i *= 2;
r->width -= i;
r->height -= i;
} /* insetRect */
static void
eraseRect(FrankDrawCtx* dctx, RECT* rect )
{
dctx->window->DrawRectFilled( rect, COLOR_WHITE );
} /* eraseRect */
#if 0
static void
frank_draw_destroyCtxt( DrawCtx* p_dctx )
{
} /* draw_setup */
#endif
static void
frank_draw_boardBegin( DrawCtx* p_dctx, XP_Rect* rect, XP_Bool hasfocus )
{
/* FrankDrawCtx* dctx = (FrankDrawCtx*)p_dctx; */
} /* draw_finish */
static void
frank_draw_boardFinished( DrawCtx* p_dctx )
{
// GtkDrawCtx* dctx = (GtkDrawCtx*)p_dctx;
} /* draw_finished */
static void
XP_RectToRECT( RECT* d, const XP_Rect* s )
{
d->x = s->left;
d->y = s->top;
d->width = s->width;
d->height = s->height;
} /* XP_RectToRECT */
/* Called by methods that draw cells, i.e. drawCell and drawCursor, to do
* common prep of the area.
*/
static void
cellDrawPrep( FrankDrawCtx* dctx, const XP_Rect* xprect, RECT* insetRect )
{
XP_RectToRECT( insetRect, xprect );
++insetRect->height;
++insetRect->width;
eraseRect( dctx, insetRect );
} /* cellDrawPrep */
static XP_Bool
frank_draw_drawCell( DrawCtx* p_dctx, XP_Rect* xprect,
XP_UCHAR* letters, XP_Bitmap* bitmap,
XP_S16 owner, XWBonusType bonus,
XP_Bool isBlank, XP_Bool isPending, XP_Bool isStar )
{
FrankDrawCtx* dctx = (FrankDrawCtx*)p_dctx;
RECT rectInset;
XP_Bool showGrid = XP_TRUE;
cellDrawPrep( dctx, xprect, &rectInset );
if ( !!letters ) {
if ( *letters == LETTER_NONE ) {
if ( bonus != BONUS_NONE ) {
XP_ASSERT( bonus <= 4 );
RECT filledR = rectInset;
COLOR color;
insetRect( &filledR, 1 );
switch( bonus ) {
case BONUS_DOUBLE_LETTER:
color = COLOR_GRAY53;
break;
case BONUS_TRIPLE_LETTER:
color = COLOR_GRAY40;
break;
case BONUS_DOUBLE_WORD:
color = COLOR_GRAY27;
break;
case BONUS_TRIPLE_WORD:
color = COLOR_GRAY13;
break;
default:
color = COLOR_WHITE; /* make compiler happy */
XP_ASSERT(0);
}
dctx->window->DrawRectFilled( &filledR, color );
}
if ( isStar ) {
dctx->window->DrawImage( xprect->left+2, xprect->top+2,
&dctx->startMark );
}
} else {
dctx->window->DrawText( (const char*)letters, rectInset.x+2,
rectInset.y+1 );
}
} else if ( !!bitmap ) {
dctx->window->DrawImage( xprect->left+2, xprect->top+2,
(IMAGE*)bitmap );
}
if ( showGrid ) {
COLOR color = isBlank? COLOR_GRAY53:COLOR_BLACK;
dctx->window->DrawRect( &rectInset, color );
}
if ( isPending ) {
insetRect( &rectInset, 1 );
dctx->window->InvertRect( &rectInset );
}
return XP_TRUE;
} /* frank_draw_drawCell */
static void
frank_draw_invertCell( DrawCtx* p_dctx, XP_Rect* rect )
{
FrankDrawCtx* dctx = (FrankDrawCtx*)p_dctx;
RECT r;
XP_RectToRECT( &r, rect );
r.x += 3;
r.y += 3;
r.width -= 5;
r.height -= 5;
/* insetRect( &r, 2 ); */
dctx->window->InvertRect( &r );
GUI_UpdateNow();
} /* frank_draw_invertCell */
static void
frank_draw_trayBegin( DrawCtx* p_dctx, XP_Rect* rect, XP_U16 owner,
XP_Bool hasfocus )
{
/* FrankDrawCtx* dctx = (FrankDrawCtx*)p_dctx; */
/* clip? */
/* eraseRect( dctx, rect ); */
} /* frank_draw_trayBegin */
static void
frank_draw_drawTile( DrawCtx* p_dctx, XP_Rect* xprect, XP_UCHAR* letter,
XP_Bitmap* bitmap, XP_S16 val, XP_Bool highlighted )
{
FrankDrawCtx* dctx = (FrankDrawCtx*)p_dctx;
char numbuf[3];
U32 width;
XP_Rect insetR = *xprect;
RECT rect;
XP_RectToRECT( &rect, xprect );
eraseRect( dctx, &rect );
/* frame the tile */
dctx->window->DrawRect( &rect, COLOR_BLACK );
if ( !!letter ) {
if ( *letter != LETTER_NONE ) { /* blank */
dctx->window->DrawText( (char*)letter, rect.x+1, rect.y+1,
dctx->trayFont );
}
} else if ( !!bitmap ) {
dctx->window->DrawImage( rect.x+2, rect.y+3, (IMAGE*)bitmap );
}
if ( val >= 0 ) {
sprintf( (char*)numbuf, (const char*)"%d", val );
width = GUI_TextWidth( dctx->valFont, numbuf, strlen(numbuf));
U16 height = GUI_FontHeight( dctx->valFont );
dctx->window->DrawText( (char*)numbuf, rect.x+rect.width - width - 1,
rect.y + rect.height - height - 1,
dctx->valFont );
}
if ( highlighted ) {
insetRect( &rect, 1 );
dctx->window->DrawRect( &rect, COLOR_BLACK );
}
} /* frank_draw_drawTile */
static void
frank_draw_drawTileBack( DrawCtx* p_dctx, XP_Rect* xprect )
{
/* FrankDrawCtx* dctx = (FrankDrawCtx*)p_dctx; */
frank_draw_drawTile( p_dctx, xprect, (XP_UCHAR*)"?",
(XP_Bitmap*)NULL, -1, XP_FALSE );
} /* frank_draw_drawTileBack */
static void
frank_draw_drawTrayDivider( DrawCtx* p_dctx, XP_Rect* rect, XP_Bool selected )
{
FrankDrawCtx* dctx = (FrankDrawCtx*)p_dctx;
RECT winRect;
XP_RectToRECT( &winRect, rect );
eraseRect( dctx, &winRect );
++winRect.x;
winRect.width -= 2;
COLOR color;
if ( selected ) {
color = COLOR_GRAY27;
} else {
color = COLOR_BLACK;
}
dctx->window->DrawRectFilled( &winRect, color );
} /* frank_draw_drawTrayDivider */
static void
frank_draw_clearRect( DrawCtx* p_dctx, XP_Rect* rectP )
{
FrankDrawCtx* dctx = (FrankDrawCtx*)p_dctx;
RECT rect;
XP_RectToRECT( &rect, rectP );
eraseRect( dctx, &rect );
} /* frank_draw_clearRect */
static void
frank_draw_drawBoardArrow( DrawCtx* p_dctx, XP_Rect* xprect,
XWBonusType cursorBonus, XP_Bool vertical )
{
FrankDrawCtx* dctx = (FrankDrawCtx*)p_dctx;
RECT rect;
cellDrawPrep( dctx, xprect, &rect );
dctx->window->DrawImage( rect.x+3, rect.y+2,
vertical?&dctx->downcursor:&dctx->rightcursor );
/* frame the cell */
dctx->window->DrawRect( &rect, COLOR_BLACK );
} /* frank_draw_drawBoardArrow */
static void
frank_draw_scoreBegin( DrawCtx* p_dctx, XP_Rect* rect, XP_U16 numPlayers,
XP_Bool hasfocus )
{
FrankDrawCtx* dctx = (FrankDrawCtx*)p_dctx;
RECT r;
XP_RectToRECT( &r, rect );
eraseRect( dctx, &r );
} /* frank_draw_scoreBegin */
static void
frank_draw_measureRemText( DrawCtx* p_dctx, XP_Rect* r,
XP_S16 nTilesLeft,
XP_U16* width, XP_U16* height )
{
FrankDrawCtx* dctx = (FrankDrawCtx*)p_dctx;
*height = SCORE_HEIGHT;
char buf[15];
sprintf( (char*)buf, "rem:%d", nTilesLeft );
*width = GUI_TextWidth( dctx->scoreFnt, (char*)buf,
strlen(buf) );
} /* frank_draw_measureRemText */
static void
frank_draw_drawRemText( DrawCtx* p_dctx, XP_Rect* rInner,
XP_Rect* rOuter, XP_S16 nTilesLeft )
{
FrankDrawCtx* dctx = (FrankDrawCtx*)p_dctx;
char buf[15];
sprintf( (char*)buf, "rem:%d", nTilesLeft );
dctx->window->DrawText( (char*)buf, rInner->left, rInner->top,
dctx->scoreFnt );
} /* frank_draw_drawRemText */
static XP_U16
scoreWidthAndText( char* buf, const FONT* font, DrawScoreInfo* dsi )
{
char* borders = "";
if ( dsi->isTurn ) {
borders = "*";
}
sprintf( buf, "%s%.3d", borders, dsi->score );
if ( dsi->nTilesLeft >= 0 ) {
char nbuf[10];
sprintf( nbuf, ":%d", dsi->nTilesLeft );
strcat( buf, nbuf );
}
strcat( buf, borders );
S32 width = GUI_TextWidth( font, buf, strlen(buf) );
return width;
} /* scoreWidthAndText */
static void
frank_draw_measureScoreText( DrawCtx* p_dctx, XP_Rect* r,
DrawScoreInfo* dsi,
XP_U16* width, XP_U16* height )
{
FrankDrawCtx* dctx = (FrankDrawCtx*)p_dctx;
char buf[20];
const FONT* font = dsi->selected? dctx->scoreFntBold:dctx->scoreFnt;
*height = SCORE_HEIGHT;
*width = scoreWidthAndText( buf, font, dsi );
} /* frank_draw_measureScoreText */
static void
frank_draw_score_drawPlayer( DrawCtx* p_dctx,
XP_S16 playerNum, /* -1: don't use */
XP_Rect* rInner, XP_Rect* rOuter,
DrawScoreInfo* dsi )
{
FrankDrawCtx* dctx = (FrankDrawCtx*)p_dctx;
char buf[20];
XP_U16 x;
const FONT* font = dsi->selected? dctx->scoreFntBold:dctx->scoreFnt;
S32 width = scoreWidthAndText( buf, font, dsi );
x = rInner->left + ((rInner->width - width) /2);
dctx->window->DrawText( buf, x, rInner->top, font );
} /* frank_draw_score_drawPlayer */
static void
frank_draw_score_pendingScore( DrawCtx* p_dctx, XP_Rect* rect, XP_S16 score,
XP_U16 playerNum )
{
FrankDrawCtx* dctx = (FrankDrawCtx*)p_dctx;
char buf[5];
XP_U16 left;
if ( score >= 0 ) {
sprintf( buf, "%.3d", score );
} else {
strcpy( buf, "???" );
}
RECT r;
XP_RectToRECT( &r, rect );
eraseRect( dctx, &r );
left = r.x+1;
dctx->window->DrawText( "Pts:", left, r.y, dctx->valFont );
dctx->window->DrawText( buf, left, r.y+(r.height/2),
dctx->scoreFnt );
} /* frank_draw_score_pendingScore */
static void
frank_draw_scoreFinished( DrawCtx* p_dctx )
{
} /* frank_draw_scoreFinished */
static U16
frankFormatTimerText( char* buf, XP_S16 secondsLeft )
{
XP_U16 minutes, seconds;
XP_U16 nChars = 0;
if ( secondsLeft < 0 ) {
*buf++ = '-';
secondsLeft *= -1;
++nChars;
}
minutes = secondsLeft / 60;
seconds = secondsLeft % 60;
char secBuf[6];
sprintf( secBuf, "0%d", seconds );
nChars += sprintf( buf, "%d:%s", minutes,
secBuf[2] == '\0'? secBuf:&secBuf[1] );
return nChars;
} /* frankFormatTimerText */
static void
frank_draw_drawTimer( DrawCtx* p_dctx, XP_Rect* rInner, XP_Rect* rOuter,
XP_U16 player, XP_S16 secondsLeft )
{
FrankDrawCtx* dctx = (FrankDrawCtx*)p_dctx;
char buf[12];
(void)frankFormatTimerText( buf, secondsLeft );
XP_DEBUGF( "drawing timer text: %s at %d,%d", buf, rInner->left,
rInner->top );
RECT r;
XP_RectToRECT( &r, rInner );
eraseRect( dctx, &r );
dctx->window->DrawText( buf, rInner->left, rInner->top, dctx->scoreFnt );
} /* frank_draw_drawTimer */
static XP_UCHAR*
frank_draw_getMiniWText( DrawCtx* p_dctx, XWMiniTextType whichText )
{
char* str = (char*)NULL;
switch( whichText ) {
case BONUS_DOUBLE_LETTER:
str = "Double letter"; break;
case BONUS_DOUBLE_WORD:
str = "Double word"; break;
case BONUS_TRIPLE_LETTER:
str = "Triple letter"; break;
case BONUS_TRIPLE_WORD:
str = "Triple word"; break;
case INTRADE_MW_TEXT:
str = "Click D when done"; break;
default:
XP_ASSERT( XP_FALSE );
}
return (XP_UCHAR*)str;
} /* frank_draw_getMiniWText */
static void
frank_draw_measureMiniWText( DrawCtx* p_dctx, XP_UCHAR* str,
XP_U16* widthP, XP_U16* heightP )
{
FrankDrawCtx* dctx = (FrankDrawCtx*)p_dctx;
*widthP = 6 + GUI_TextWidth( dctx->scoreFnt, (const char*)str,
strlen((const char*)str) );
*heightP = 6 + GUI_FontHeight( dctx->scoreFnt );
} /* frank_draw_measureMiniWText */
static void
frank_draw_drawMiniWindow( DrawCtx* p_dctx, XP_UCHAR* text, XP_Rect* rect,
void** closureP )
{
FrankDrawCtx* dctx = (FrankDrawCtx*)p_dctx;
RECT r;
XP_RectToRECT( &r, rect );
eraseRect( dctx, &r );
--r.width;
--r.height;
++r.x;
++r.y;
dctx->window->DrawRect( &r, COLOR_BLACK );
--r.x;
--r.y;
eraseRect( dctx, &r );
dctx->window->DrawRect( &r, COLOR_BLACK );
dctx->window->DrawText( (const char*)text, r.x+2, r.y+2, dctx->scoreFnt );
} /* frank_draw_drawMiniWindow */
static void
frank_draw_eraseMiniWindow( DrawCtx* p_dctx, XP_Rect* rect, XP_Bool lastTime,
void** closure, XP_Bool* invalUnder )
{
/* FrankDrawCtx* dctx = (FrankDrawCtx*)p_dctx; */
*invalUnder = XP_TRUE;
} /* frank_draw_eraseMiniWindow */
#define SET_GDK_COLOR( c, r, g, b ) { \
c.red = (r); \
c.green = (g); \
c.blue = (b); \
}
static void
draw_doNothing( DrawCtx* dctx, ... )
{
} /* draw_doNothing */
const unsigned char downcursor_bits[] = {
0x00, 0x00,
0x10, 0x00,
0x10, 0x00,
0x10, 0x00,
0xfe, 0x00,
0x7c, 0x00,
0x38, 0x00,
0x10, 0x00,
0x00, 0x00,
};
const unsigned char rightcursor_bits[] = {
0x00, 0x00, 0x10, 0x00, 0x18, 0x00, 0x1c, 0x00, 0xfe, 0x00, 0x1c, 0x00,
0x18, 0x00, 0x10, 0x00, 0x00, 0x00
};
const unsigned char startMark_bits[] = {
0xc1, 0x80, /* ##-- ---# # */
0xe3, 0x80, /* ###- --## # */
0x77, 0x00, /* -### -### - */
0x3e, 0x00, /* --## ###- - */
0x1c, 0x00, /* ---# ##-- - */
0x3e, 0x00, /* --## ###- - */
0x77, 0x00, /* -### -### - */
0xe3, 0x80, /* ###- --## # */
0xc1, 0x80, /* ##-- ---# # */
};
DrawCtx*
frank_drawctxt_make( MPFORMAL CWindow* window )
{
FrankDrawCtx* dctx = (FrankDrawCtx*)XP_MALLOC( mpool,
sizeof(FrankDrawCtx) );
U16 i;
dctx->vtable = (DrawCtxVTable*)XP_MALLOC( mpool,
sizeof(*(((FrankDrawCtx*)dctx)->vtable)) );
for ( i = 0; i < sizeof(*dctx->vtable)/4; ++i ) {
((void**)(dctx->vtable))[i] = draw_doNothing;
}
/* SET_VTABLE_ENTRY( dctx, draw_destroyCtxt, frank_ ); */
SET_VTABLE_ENTRY( dctx->vtable, draw_boardBegin, frank );
SET_VTABLE_ENTRY( dctx->vtable, draw_drawCell, frank );
SET_VTABLE_ENTRY( dctx->vtable, draw_invertCell, frank );
SET_VTABLE_ENTRY( dctx->vtable, draw_boardFinished, frank );
SET_VTABLE_ENTRY( dctx->vtable, draw_trayBegin, frank );
SET_VTABLE_ENTRY( dctx->vtable, draw_drawTile, frank );
SET_VTABLE_ENTRY( dctx->vtable, draw_drawTileBack, frank );
SET_VTABLE_ENTRY( dctx->vtable, draw_drawTrayDivider, frank );
SET_VTABLE_ENTRY( dctx->vtable, draw_clearRect, frank );
SET_VTABLE_ENTRY( dctx->vtable, draw_drawBoardArrow, frank );
SET_VTABLE_ENTRY( dctx->vtable, draw_scoreBegin, frank );
SET_VTABLE_ENTRY( dctx->vtable, draw_measureRemText, frank );
SET_VTABLE_ENTRY( dctx->vtable, draw_drawRemText, frank );
SET_VTABLE_ENTRY( dctx->vtable, draw_measureScoreText, frank );
SET_VTABLE_ENTRY( dctx->vtable, draw_score_drawPlayer, frank );
SET_VTABLE_ENTRY( dctx->vtable, draw_score_pendingScore, frank );
SET_VTABLE_ENTRY( dctx->vtable, draw_scoreFinished, frank );
SET_VTABLE_ENTRY( dctx->vtable, draw_drawTimer, frank );
SET_VTABLE_ENTRY( dctx->vtable, draw_getMiniWText, frank );
SET_VTABLE_ENTRY( dctx->vtable, draw_measureMiniWText, frank );
SET_VTABLE_ENTRY( dctx->vtable, draw_drawMiniWindow, frank );
SET_VTABLE_ENTRY( dctx->vtable, draw_eraseMiniWindow, frank );
dctx->window = window;
dctx->valFont = GUI_GetFont( 9, CTRL_NORMAL );
dctx->scoreFnt = GUI_GetFont( 12, CTRL_NORMAL );
dctx->scoreFntBold = GUI_GetFont( 12, CTRL_BOLD );
dctx->trayFont = GUI_GetFont( 16, CTRL_NORMAL );
IMAGE downcursor = { 9, 9, 2,
COLOR_MODE_MONO, 0, (const COLOR *) 0,
(U8*)downcursor_bits };
XP_MEMCPY( (IMAGE*)&dctx->downcursor, &downcursor,
sizeof(dctx->downcursor) );
IMAGE rightcursor = { 9, 9, 2,
COLOR_MODE_MONO, 0, (const COLOR *) 0,
(U8*)rightcursor_bits };
XP_MEMCPY( (IMAGE*)&dctx->rightcursor, &rightcursor,
sizeof(dctx->rightcursor) );
IMAGE startMark = { 9, 9, 2,
COLOR_MODE_MONO, 0, (const COLOR *) 0,
(U8*)startMark_bits };
XP_MEMCPY( (IMAGE*)&dctx->startMark, &startMark,
sizeof(dctx->startMark) );
return (DrawCtx*)dctx;
} /* frank_drawctxt_make */

31
franklin/frankdraw.h Normal file
View file

@ -0,0 +1,31 @@
// -*-mode: C; fill-column: 78; 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 <stdlib.h>
extern "C" {
#include "frankmain.h"
#include "draw.h"
#include "board.h"
} /* extern "C" */
DrawCtx* frank_drawctxt_make( MPFORMAL CWindow* win );

313
franklin/frankgamesdb.cpp Normal file
View file

@ -0,0 +1,313 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4;-*- */
/*
* Copyright 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 <ebm_object.h>
#include <string.h>
#include "frankgamesdb.h"
#include "frankids.h"
extern "C" {
# include "xptypes.h"
}
CGamesDB::CGamesDB(MPFORMAL const XP_UCHAR* fileName)
{
this->nRecordsUsed = 0;
this->nRecordsAllocated = 0;
this->lockedIndex = -1;
MPASSIGN( this->mpool, mpool );
fRecords = (DBRecord*)NULL;
// create or load file
memset( &this->xwfile, 0, sizeof(xwfile) );
strcpy( (char*)this->xwfile.name, (char*)fileName );
strcpy( this->xwfile.publisher, PUB_ERICHOUSE );
strcpy( this->xwfile.extension, EXT_XWORDSGAMES );
size_t size = EBO_BLK_SIZE;
int result = ebo_new( &this->xwfile, size, FALSE );
BOOL exists = result < 0;
XP_DEBUGF( "exists=%d", exists );
if ( exists ) {
readFromFile( &xwfile );
}
} // CGamesDBn
CGamesDB::~CGamesDB()
{
this->writeToFile();
U16 nRecords = this->nRecordsUsed;
for ( U16 i = 0; i < nRecords; ++i ) {
DBRecord* record = &fRecords[i];
XP_FREE( mpool, record->datum );
if ( !!record->name ) {
XP_FREE( mpool, record->name );
}
}
XP_FREE( mpool, fRecords );
} // ~CGamesDB
void*
CGamesDB::getNthRecord( U16 index, U16* recordLen )
{
XP_ASSERT( index < this->nRecordsUsed );
XP_ASSERT( this->lockedIndex < 0 );
this->lockedIndex = index;
*recordLen = fRecords[index].length;
XP_DEBUGF( "getNthRecord(%d) returning len=%d", index, *recordLen );
return fRecords[index].datum;
} // getNthRecord
XP_UCHAR*
CGamesDB::getNthName( U16 index )
{
XP_ASSERT( index < this->nRecordsUsed );
XP_DEBUGF( "returning %dth name: %s", index, fRecords[index].name );
return fRecords[index].name;
} /* getNthName */
void
CGamesDB::recordRelease( U16 index )
{
XP_ASSERT( this->lockedIndex == index );
this->lockedIndex = -1;
} // recordRelease
void
CGamesDB::putNthRecord( U16 index, void* ptr, U16 len )
{
XP_DEBUGF( "putNthRecord(%d,ptr,%d)", index, len );
XP_ASSERT( index <= nRecordsUsed );
if ( index == nRecordsAllocated ) { /* need a new one */
ensureSpace( nRecordsUsed+1 );
} else if ( !!fRecords[index].datum ) {
XP_FREE(mpool, fRecords[index].datum );
}
void* datap = XP_MALLOC( mpool, len );
XP_MEMCPY( datap, ptr, len );
fRecords[index].datum = datap;
fRecords[index].length = len;
if ( index == this->nRecordsUsed ) {
++this->nRecordsUsed;
}
} // putNthRecord
void
CGamesDB::putNthName( U16 index, XP_UCHAR* name )
{
XP_ASSERT( index <= this->nRecordsUsed );
if ( index == nRecordsAllocated ) { /* need a new one */
ensureSpace( nRecordsUsed+1 );
} else if ( !!fRecords[index].name ) {
XP_FREE( mpool, fRecords[index].name );
}
fRecords[index].name = frankCopyStr( MPPARM(mpool) name);
if ( index == this->nRecordsUsed ) {
++this->nRecordsUsed;
}
} /* putNthName */
void
CGamesDB::removeNthRecord( U16 index )
{
XP_ASSERT( index < this->nRecordsUsed );
if ( !!fRecords[index].datum ) {
XP_FREE( mpool, fRecords[index].datum );
if ( !!fRecords[index].name ) {
XP_FREE( mpool, fRecords[index].name );
}
}
U16 nRecords = --this->nRecordsUsed;
for ( U16 i = index; i < nRecords; ++i ) {
fRecords[i] = fRecords[i+1];
}
fRecords[nRecords].datum = NULL;
fRecords[nRecords].length = 0;
} // removeNthRecord
U16
CGamesDB::duplicateNthRecord( U16 index )
{
XP_ASSERT( index < this->nRecordsUsed );
ensureSpace( nRecordsUsed + 1 );
U16 newIndex = index + 1;
for ( U16 i = this->nRecordsUsed; i > newIndex; --i ) {
fRecords[i] = fRecords[i-1];
}
++this->nRecordsUsed;
U16 len = fRecords[newIndex].length = fRecords[index].length;
void* data = XP_MALLOC( mpool, len );
XP_MEMCPY( data, fRecords[index].datum, len );
fRecords[newIndex].datum = data;
fRecords[newIndex].name =
frankCopyStr( MPPARM(mpool) fRecords[index].name );
XP_DEBUGF( "done with duplicateNthRecord; returning %d", newIndex );
return newIndex;
} /* duplicateNthRecord */
U16
CGamesDB::countRecords()
{
return this->nRecordsUsed;
} // countRecords
void
CGamesDB::readFromFile( const ebo_name_t* xwfile )
{
size_t size = EBO_BLK_SIZE;
void* vmbase = (void*)ebo_roundup(OS_availaddr+GAMES_DB_OFFSET);
#ifdef DEBUG
int result = ebo_mapin( xwfile, 0, vmbase, &size, 1 );
XP_ASSERT( result >= 0 );
#else
(void)ebo_mapin( xwfile, 0, vmbase, &size, 1 );
#endif
XP_ASSERT( ((unsigned long)vmbase & 0x01) == 0 );
U16 nRecords;
unsigned char* ptr = (unsigned char*)vmbase;
nRecords = *((U16*)ptr)++;
XP_DEBUGF( "nRecords = %d", nRecords );
this->nRecordsUsed = this->nRecordsAllocated = nRecords;
fRecords = (DBRecord*)XP_MALLOC( mpool, nRecords * sizeof(fRecords[0]) );
for ( U16 i = 0; i < nRecords; ++i ) {
DBRecord* record = &fRecords[i];
U8 nameLen = *ptr++;
XP_UCHAR* name = (XP_UCHAR*)NULL;
if ( nameLen > 0 ) {
name = (XP_UCHAR*)XP_MALLOC(mpool, nameLen+1);
XP_MEMCPY( name, ptr, nameLen );
name[nameLen] = '\0';
ptr += nameLen;
}
record->name = name;
/* fix alignment */
while ( ((unsigned long)ptr & 0x00000001) != 0 ) {
++ptr;
}
U16 len = record->length = *((U16*)ptr)++;
XP_DEBUGF( "read len %d from offset %ld", len,
(unsigned long)ptr - (unsigned long)vmbase - 2 );
record->datum = XP_MALLOC( mpool, len );
XP_MEMCPY( record->datum, ptr, len );
ptr += len;
XP_DEBUGF( "Read %dth record", i );
XP_ASSERT( ((unsigned char*)vmbase) + size >= ptr );
}
(void)ebo_unmap( vmbase, size );
XP_DEBUGF( "read %d records from file", nRecords );
} // readFromFile
void
CGamesDB::writeToFile()
{
size_t size = EBO_BLK_SIZE;
void* vmbase = (void*)ebo_roundup(OS_availaddr+GAMES_DB_OFFSET);
#ifdef DEBUG
int result = ebo_mapin( &this->xwfile, 0, vmbase, &size, 1 );
XP_ASSERT( result >= 0 );
#else
(void)ebo_mapin( &this->xwfile, 0, vmbase, &size, 1 );
#endif
XP_ASSERT( ((unsigned long)vmbase & 0x01) == 0 );
U16 nRecords = this->nRecordsUsed;
unsigned char* ptr = (unsigned char*)vmbase;
*(U16*)ptr = nRecords;
ptr += sizeof(U16);
for ( U16 i = 0; i < nRecords; ++i ) {
XP_UCHAR* name = fRecords[i].name;
U16 slen = !!name? XP_STRLEN( name ): 0;
*ptr++ = slen;
if ( slen > 0 ) {
XP_ASSERT( slen < 0x00FF );
XP_MEMCPY( ptr, name, slen );
ptr += slen;
}
/* fix alignment */
while ( ((unsigned long)ptr & 0x00000001) != 0 ) {
++ptr;
}
U16 len = fRecords[i].length;
XP_DEBUGF( "writing len %d at offset %ld", len,
(unsigned long)ptr - (unsigned long)vmbase );
*((U16*)ptr)++ = len;
XP_MEMCPY( ptr, fRecords[i].datum, len );
ptr += len;
}
ebo_unmap( vmbase, size );
XP_WARNF( "finished writing %d recs to file", nRecords );
} // writeToFile
void
CGamesDB::ensureSpace( U16 nNeeded )
{
if ( this->nRecordsAllocated < nNeeded ) {
U16 newLen = nNeeded * sizeof(fRecords[0]);
if ( !!fRecords ) {
fRecords = (DBRecord*)XP_REALLOC( mpool, fRecords, newLen );
} else {
fRecords = (DBRecord*)XP_MALLOC( mpool, newLen );
}
U16 sizeAdded = (nNeeded - this->nRecordsAllocated) * sizeof(*fRecords);
XP_MEMSET( fRecords + this->nRecordsAllocated, 0x00, sizeAdded );
this->nRecordsAllocated = nNeeded;
XP_DEBUGF( "ensureSpace: increasing nRecordsAllocated to %d (len=%d)",
nRecordsAllocated, newLen );
}
} /* ensureSpace */

81
franklin/frankgamesdb.h Normal file
View file

@ -0,0 +1,81 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
/*
* Copyright 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 _FRANKGAMESDB_H_
#define _FRANKGAMESDB_H_
#include <assert.h>
#include <ctype.h>
#include "sys.h"
#include "gui.h"
#include "comtypes.h"
#include "mempool.h"
/* #include "ebm_object.h" */
struct DBRecord {
U16 length;
void* datum;
XP_UCHAR* name;
};
class CGamesDB {
private:
U16 nRecordsUsed;
U16 nRecordsAllocated;
DBRecord* fRecords;
S16 lockedIndex;
ebo_name_t xwfile;
void readFromFile( const ebo_name_t* xwfile );
void writeToFile();
void ensureSpace( U16 nNeeded );
MPSLOT
public:
/* create or open if already exists */
CGamesDB(MPFORMAL const XP_UCHAR* fileName);
/* commit optimized in-memory representation to a flat "file" */
~CGamesDB();
/* Return a ptr (read-only by convention!!) to the beginning of the
record's data. The ptr's valid until recordRelease is called. */
void* getNthRecord( U16 index, U16* recordLen );
void recordRelease( U16 index );
XP_UCHAR* getNthName( U16 index );
/* put data into a record, adding a new one, replacing or appending to an
existing one */
void putNthRecord( U16 index, void* ptr, U16 len );
void appendNthRecord( U16 index, void* ptr, U16 len );
void putNthName( U16 index, XP_UCHAR* name );
U16 duplicateNthRecord( U16 index );
void removeNthRecord( U16 index );
/* how many records do I have. indices passed by getter methods that are
>= this number are illegal. setters can pass a number = to this, in
which case we create a new record. */
U16 countRecords();
};
#endif

91
franklin/frankids.h Normal file
View file

@ -0,0 +1,91 @@
// -*-mode: C; fill-column: 78; c-basic-offset: 4; -*-
/*
* Copyright 1999-2000 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 "comtypes.h"
#include "mempool.h"
#ifndef _FRANKIDS_H_
#define _FRANKIDS_H_
#define MAIN_FLIP_BUTTON_ID 101
#define MAIN_VALUE_BUTTON_ID 102
#define MAIN_HINT_BUTTON_ID 103
#define MAIN_UNDO_BUTTON_ID 104
#define MAIN_COMMIT_BUTTON_ID 105
#define MAIN_TRADE_BUTTON_ID 106
#define MAIN_JUGGLE_BUTTON_ID 107
#define MAIN_HIDE_BUTTON_ID 108
#define MAIN_WINDOW_ID 1000
#define ASK_WINDOW_ID 1001
#define ASKLETTER_WINDOW_ID 1002
#define PLAYERS_WINDOW_ID 1003
#define PASSWORD_WINDOW_ID 1004
#define SAVEDGAMES_WINDOW_ID 1005
#define FILEMENU_BUTTON_ID 1020
#define FILEMENU_NEWGAME 1021
#define FILEMENU_SAVEDGAMES 1022
#define FILEMENU_PREFS 1023
#define FILEMENU_ABOUT 1024
#define GAMEMENU_BUTTON_ID 1025
#define GAMEMENU_TVALUES 1026
#define GAMEMENU_FINALSCORES 1041
#define GAMEMENU_GAMEINFO 1027
#define GAMEMENU_HISTORY 1028
#define MOVEMENU_BUTTON_ID 1029
#define MOVEMENU_HINT 1030
#define MOVEMENU_NEXTHINT 1031
#define MOVEMENU_REVERT 1032
#define MOVEMENU_UNDO 1033
#define MOVEMENU_DONE 1034
#define MOVEMENU_JUGGLE 1035
#define MOVEMENU_TRADE 1036
#define MOVEMENU_HIDETRAY 1037
#ifdef MEM_DEBUG
# define DEBUGMENU_BUTTON_ID 1050
# define DEBUGMENU_HEAPDUMP 1051
#endif
#define FILEMENU_WINDOW_ID 1038
#define GAMEMENU_WINDOW_ID 1039
#define MOVEMENU_WINDOW_ID 1040
#define MENUBAR_WINDOW_ID 1041
const char* PUB_ERICHOUSE = "Eric_House";
const char* EXT_XWORDSDICT = "xwd";
const char* EXT_XWORDSGAMES = "xwg";
#define DICT_OFFSET 0x00000000
#define GAMES_DB_OFFSET 0x00800000
#define FLAGS_CHECK_OFFSET 0x00900000
#define MAX_NAME_LENGTH 31 /* not including null byte */
extern "C" {
XP_UCHAR* frankCopyStr( MPFORMAL const XP_UCHAR* );
}
#endif

136
franklin/frankletter.cpp Normal file
View file

@ -0,0 +1,136 @@
// -*-mode: C; fill-column: 78; c-basic-offset: 4; -*-
/*
* Copyright 1999-2000 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 <assert.h>
#include <ctype.h>
#include "sys.h"
#include "gui.h"
#include "ebm_object.h"
extern "C" {
#include "xptypes.h"
}
#include "frankletter.h"
#include "frankids.h"
#include "frankask.h"
#define LETTER_HEIGHT 12
#define LETTERS_ROW_HEIGHT LETTER_HEIGHT
#define LETTERS_ROW_WIDTH 30
#define LETTERS_NUM_VISROWS 16
class LettersList : public CList {
private:
DictionaryCtxt* fDict;
Tile blank;
public:
LettersList( DictionaryCtxt* dict, U16 numRows );
U16 GetRowHeight( S32 row ) { return LETTER_HEIGHT; }
void DrawRow( RECT *rect, S32 row );
};
LettersList::LettersList( DictionaryCtxt* dict, U16 numRows )
: CList( 1001, LETTERS_ROW_WIDTH,
LETTERS_ROW_HEIGHT * LETTERS_NUM_VISROWS,
numRows, LISTOPTION_ALWAYS_HIGHLIGHT )
{
fDict = dict;
this->blank = dict_getBlankTile( dict );
this->SetCurrentRow(0); // Select the first item so there's a default
}
void LettersList::DrawRow( RECT *rect, S32 row )
{
unsigned char buf[4];
Tile tile = row;
// We don't draw the blank, and if it's other than the highest value tile
// we need to skip it, drawing instead the next tile above.
if ( row >= this->blank ) {
++tile;
}
dict_tilesToString( fDict, &tile, 1, buf );
CWindow* window = this->GetWindow();
window->DrawText( (char*)buf, rect->x, rect->y );
} /* LettersList::DrawRow */
CAskLetterWindow::CAskLetterWindow( DictionaryCtxt* dict,
XP_UCHAR* resultP )
: CWindow( ASKLETTER_WINDOW_ID, 55, 15, 80, 220, "Blank", TRUE )
{
fDict = dict;
this->resultP = resultP;
this->blank = dict_getBlankTile( dict );
this->list = new LettersList( dict, dict_numTileFaces( dict ) - 1 );
this->AddChild( this->list, 5, 5 );
CButton* okbutton = new CButton( 1000, 0, 0, "Ok" );
this->AddChild( okbutton, 40, 70 );
} // CAskWindow
S32
CAskLetterWindow::MsgHandler( MSG_TYPE type, CViewable *object, S32 data )
{
S32 result = 0;
Tile tile;
switch (type) {
case MSG_BUTTON_SELECT: // there's only one button....
tile = this->list->GetCurrentRow();
if ( tile >= this->blank ) {
++tile;
}
dict_tilesToString( fDict, &tile, 1, this->resultP );
this->Close();
result = 1;
break;
case MSG_KEY: // allow keys to select the matching letter in the list
if ( isalpha( data ) ) {
XP_UCHAR ch = toupper(data);
Tile tile = dict_tileForString( fDict, &ch );
if ( tile != EMPTY_TILE ) {
S32 row = tile;
XP_ASSERT( tile != this->blank );
if ( tile > this->blank ) {
--row;
}
this->list->SetCurrentRow( row );
result = 1;
}
}
default:
break;
}
if ( result == 0 ) {
result = CWindow::MsgHandler( type, object, data );
}
return result;
} // CAskLetterWindow::MsgHandler

33
franklin/frankletter.h Normal file
View file

@ -0,0 +1,33 @@
// -*-mode: C; fill-column: 78; c-basic-offset: 4; -*-
/*
* Copyright 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.
*/
extern "C" {
#include "dictnry.h"
}
class CAskLetterWindow : public CWindow {
private:
Tile blank;
DictionaryCtxt* fDict;
XP_UCHAR* resultP;
CList* list; /* my own subclass, of course */
public:
CAskLetterWindow( DictionaryCtxt* dict, XP_UCHAR* resultP );
S32 MsgHandler( MSG_TYPE type, CViewable *object, S32 data );
};

1631
franklin/frankmain.cpp Normal file

File diff suppressed because it is too large Load diff

74
franklin/frankmain.h Normal file
View file

@ -0,0 +1,74 @@
// -*-mode: C; fill-column: 78; c-basic-offset: 4; -*-
/*
* Copyright 1999-2000 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 _FRANKMAIN_H_
#define _FRANKMAIN_H_
#include <assert.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include "sys.h"
#include "gui.h"
#include "OpenDatabases.h"
/* #include "FieldMgr.h" */
#include "ebm_object.h"
#define SCREEN_WIDTH 200
#define BOARD_LEFT 2
#define SCORE_LEFT BOARD_LEFT
#define SCORE_TOP 3
#define SCORE_WIDTH SCREEN_WIDTH
#define SCORE_HEIGHT 13
#define TIMER_WIDTH 36
#define TIMER_HEIGHT SCORE_HEIGHT
#define BOARD_TOP SCORE_HEIGHT+SCORE_TOP
#define BOARD_SCALE 12
#define TRAY_LEFT BOARD_LEFT
#define MIN_TRAY_SCALE 23
#define FRANK_DIVIDER_WIDTH 5
#define VERSION_STRING " 4.0"
extern "C" {
typedef struct FrankDrawCtx {
DrawCtxVTable* vtable;
CWindow* window;
const FONT* scoreFnt;
const FONT* scoreFntBold;
const FONT* trayFont;
const FONT* valFont;
const IMAGE rightcursor;
const IMAGE downcursor;
const IMAGE startMark;
} FrankDrawCtx;
void debugf( char* format, ... );
} /* extern "C" */
#endif

112
franklin/frankpasswd.cpp Normal file
View file

@ -0,0 +1,112 @@
// -*-mode: C; fill-column: 78; c-basic-offset: 4; -*-
/*
* Copyright 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 <assert.h>
#include <ctype.h>
#include "sys.h"
#include "gui.h"
#include "ebm_object.h"
extern "C" {
#include "xptypes.h"
}
#include "frankpasswd.h"
#include "frankids.h"
#define TEXT_ID 2000
#define PASSWD_WIDTH 105
#define PASSWD_HEIGHT 12
#define LABEL_X 10
#define LABEL_Y 10
#define PASSWD_X LABEL_X
#define PASSWD_Y (LABEL_Y+15)
#define BUTTON_Y (PASSWD_Y+20)
#define OK_BUTTON_X 30
#define CANCEL_BUTTON_X 100
#define PASS_CANCEL_ID 2001
#define PASS_OK_ID 2002
#define LABEL_ID 2003
CAskPasswdWindow::CAskPasswdWindow( const XP_UCHAR* name, XP_UCHAR* buf,
XP_U16* len, XP_Bool* result )
: CWindow( PASSWORD_WINDOW_ID, 10, 120, 180, 85, "Password", TRUE )
{
fName = name;
fBuf = buf;
this->lenp = len;
this->okP = result;
snprintf( fLabelBuf, sizeof(fLabelBuf), "Password for %s:", name );
CLabel* label = new CLabel( LABEL_ID, fLabelBuf );
this->AddChild( label, LABEL_X, LABEL_Y );
this->entry = new CTextEdit( TEXT_ID, PASSWD_WIDTH, PASSWD_HEIGHT,
TEXTOPTION_PASSWORD
| TEXTOPTION_ONELINE
| TEXTOPTION_HAS_FOCUS);
this->AddChild( this->entry, PASSWD_X, PASSWD_Y );
this->SetFocus( this->entry );
CButton* button = new CButton( PASS_CANCEL_ID, 0, 0, "Cancel" );
this->AddChild( button, CANCEL_BUTTON_X, BUTTON_Y );
button = new CButton( PASS_OK_ID, 0, 0, "Ok" );
this->AddChild( button, OK_BUTTON_X, BUTTON_Y );
} // CAskWindow
S32
CAskPasswdWindow::MsgHandler( MSG_TYPE type, CViewable *object, S32 data )
{
S32 result = 0;
char* text;
XP_U16 len;
switch (type) {
case MSG_BUTTON_SELECT: // there's only one button....
switch ( object->GetID() ) {
case PASS_OK_ID:
text = this->entry->GetText();
len = this->entry->TextLength();
strncpy( (char*)fBuf, text, XP_MIN(len,*this->lenp) );
fBuf[len] = '\0';
*this->lenp = len;
*this->okP = XP_TRUE;
break;
case PASS_CANCEL_ID:
*this->okP = XP_FALSE;
break;
default:
return 0;
}
result = 1;
this->Close();
break;
default:
break;
}
return result;
} // CAskLetterWindow::MsgHandler

40
franklin/frankpasswd.h Normal file
View file

@ -0,0 +1,40 @@
// -*-mode: C; fill-column: 78; c-basic-offset: 4; -*-
/*
* Copyright 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 _FRANKPASSWD_H_
#define _FRANKPASSWD_H_
#include "comtypes.h"
class CAskPasswdWindow : public CWindow {
private:
const XP_UCHAR* fName;
XP_UCHAR* fBuf;
XP_U16* lenp;
XP_Bool* okP;
CTextEdit* entry;
char fLabelBuf[64];
public:
CAskPasswdWindow( const XP_UCHAR* name, XP_UCHAR* buf, XP_U16* len,
XP_Bool* result );
S32 MsgHandler( MSG_TYPE type, CViewable *object, S32 data );
};
#endif /* _FRANKPASSWD_H_ */

466
franklin/frankplayer.cpp Normal file
View file

@ -0,0 +1,466 @@
// -*-mode: C; fill-column: 78; 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 <assert.h>
#include <ctype.h>
#include "sys.h"
#include "gui.h"
#include "ebm_object.h"
extern "C" {
#include "xptypes.h"
#include "strutils.h"
#include "mempool.h"
}
#include "frankids.h"
#include "frankplayer.h"
#include "frankdict.h"
#define PLAYERCOUNT_MENU_ID 2000
#define NUMPLAYERS_POPUP_ID 2001
#define NAME_LABEL_ID 2002
#define ROBOT_LABEL_ID 2003
#define PASSWORD_LABEL_ID 2004
#define OK_BUTTON_ID 2005
#define CANCEL_BUTTON_ID 2006
#define REVERT_BUTTON_ID 2007
#define COUNT_LABEL_ID 2008
#define PLAYERDICT_MENU_ID 2009
#define DICTNAMES_POPUP_ID 2010
#define DICT_LABEL_ID 2011
#define SIZE_LABEL_ID 2012
#define BOARDSIZE_MENU_ID 2013
#define BOARDSIZE_POPUP_ID 2014
#define TIMER_CHECKBOX_ID 2015
#define TIMER_FIELD_ID 2016
#define PHONIES_MENU_ID 2017
#define PHONIES_POPUP_ID 2018
#define OK_BUTTON_COL 35
#define CANCEL_BUTTON_COL 95
#define REVERT_BUTTON_COL 125
/* These must be far enough apart that derivitaves will remain unique; make it
10 for now. Also, there can't be any overlap between their ranges and
other ids!!!!*/
#define NAME_BASE 2060
#define ROBOT_BASE 2070
#define PASSWORD_BASE 2080
#define COUNTER_ROW 5
#define LABEL_ROW 20
#define FIRST_ROW (LABEL_ROW+20)
#define ROW_OFFSET 18
#define DICTMENU_ROW (FIRST_ROW + (ROW_OFFSET * MAX_NUM_PLAYERS) + 2)
#define SIZEMENU_ROW (DICTMENU_ROW + ROW_OFFSET + 1)
#define PHONIESMENU_ROW (SIZEMENU_ROW + ROW_OFFSET + 1)
#define TIMER_ROW (PHONIESMENU_ROW + ROW_OFFSET + 1)
#define BUTTON_ROW (TIMER_ROW + ROW_OFFSET + 3)
#define NAME_COL 5
#define NAME_WIDTH 105
#define NAME_HEIGHT 12
#define ROBOT_COL (NAME_COL + NAME_WIDTH + 10)
#define PASSWD_WIDTH 20
#define TIME_WIDTH 20
#define PASSWD_HEIGHT NAME_HEIGHT
#define PASSWORD_COL (ROBOT_COL + PASSWD_WIDTH + 10)
#define TIMER_FIELD_COL 120
/* Put up a window with a list for each player giving name and robotness,
* and allowing for setting/changing a password.
*/
CPlayersWindow::CPlayersWindow( MPFORMAL CurGameInfo* gi, FrankDictList* dlist,
BOOL isNew, BOOL allowCancel, BOOL* cancelledP )
: CWindow( PLAYERS_WINDOW_ID, 2, 12, 196, 226, "Game setup", !isNew,
FALSE, FALSE )
{
fLocalGI = *gi;
fGIRef = gi;
fDList = dlist;
this->resultP = cancelledP;
fIsNew = isNew;
MPASSIGN( this->mpool, mpool );
/* numplayers counter */
CLabel* label = new CLabel( COUNT_LABEL_ID, "Number of players:" );
this->AddChild( label, NAME_COL, COUNTER_ROW );
this->countMenu = new CMenu(PLAYERCOUNT_MENU_ID, 0, 0, 0, 0, 0 );
this->countMenu->SetNumRows( MAX_NUM_PLAYERS );
char* base = (char*)fNumsBuf;
for ( U16 i = 0 ; i < MAX_NUM_PLAYERS; ++i ) {
snprintf( base, 2, "%d", i+1 );
this->countMenu->SetRow( i, 2000+i, base );
base += 2;
}
CPopupTrigger *trigger = new CPopupTrigger( NUMPLAYERS_POPUP_ID, 0, 0,
this->countMenu, 0 );
trigger->SetCurrentRow( fLocalGI.nPlayers-1 );
this->AddChild( trigger, NAME_COL+130, COUNTER_ROW );
if ( !isNew ) {
DisOrEnable( NUMPLAYERS_POPUP_ID, FALSE );
}
/* Column labels */
label = new CLabel( NAME_LABEL_ID, "Name" );
this->AddChild( label, NAME_COL, LABEL_ROW );
label = new CLabel( ROBOT_LABEL_ID, "Rbt" );
this->AddChild( label, ROBOT_COL, LABEL_ROW );
label = new CLabel( PASSWORD_LABEL_ID, "Pwd" );
this->AddChild( label, PASSWORD_COL, LABEL_ROW );
/* build a row of controls for each potential player. Disable those below
the point determined by the number of players we have. */
for ( U16 i = 0; i < MAX_NUM_PLAYERS; ++i ) {
LocalPlayer* fp = &fLocalGI.players[i];
CTextEdit* name = new CTextEdit( NAME_BASE + i, NAME_WIDTH,
NAME_HEIGHT, TEXTOPTION_ONELINE );
name->SetText( (char*)fp->name );
this->AddChild( name, NAME_COL, FIRST_ROW + (ROW_OFFSET*i) );
CCheckbox *robot_check = new CCheckbox( ROBOT_BASE + i, 0, 0, "" );
robot_check->SetDownStatus( fp->isRobot );
this->AddChild( robot_check, ROBOT_COL, FIRST_ROW + (ROW_OFFSET*i) );
CTextEdit* passwd = new CTextEdit( PASSWORD_BASE + i,
PASSWD_WIDTH, PASSWD_HEIGHT,
TEXTOPTION_PASSWORD
| TEXTOPTION_ONELINE);
this->AddChild( passwd, PASSWORD_COL, FIRST_ROW + (ROW_OFFSET*i) );
const char* password = (const char*)fp->password;
if ( !!password && !!password[0] ) {
passwd->SetText( password );
}
}
this->makeDictMenu();
this->makeSizeMenu();
this->makePhoniesMenu();
/* the timer checkbox */
fTimerEnabled = new CCheckbox( TIMER_CHECKBOX_ID, 0, 0,
"Timer enabled" );
fTimerEnabled->SetDownStatus( fLocalGI.timerEnabled );
AddChild( fTimerEnabled, NAME_COL, TIMER_ROW );
if ( !isNew ) {
fTimerEnabled->Disable();
}
/* the timer field (hidden if checkbox not checked) */
fTimerField = new CTextEdit( TIMER_FIELD_ID, TIME_WIDTH,
PASSWD_HEIGHT, TEXTOPTION_ONELINE );
char buf[10];
sprintf( buf, "%d", fLocalGI.gameSeconds / 60 );
fTimerField->SetText( buf );
AddChild( fTimerField, TIMER_FIELD_COL, TIMER_ROW );
if ( !fLocalGI.timerEnabled || !isNew ) {
fTimerField->Disable();
}
/* the buttons at the bottom */
U16 okCol = OK_BUTTON_COL;
CButton* button = new CButton( OK_BUTTON_ID, 0, 0, "Ok" );
if ( !(isNew && allowCancel) ) {
U16 buttonWidth = button->GetWidth();
U16 windowWidth = this->GetWidth();
okCol = (windowWidth - buttonWidth) / 2;
}
this->AddChild( button, okCol, BUTTON_ROW );
if ( isNew && allowCancel ) {
button = new CButton( CANCEL_BUTTON_ID, 0, 0, "Cancel" );
this->AddChild( button, CANCEL_BUTTON_COL, BUTTON_ROW );
}
adjustVisibility();
XP_DEBUGF( "CPlayersWindow done" );
} // CPlayersWindow
CPlayersWindow::~CPlayersWindow()
{
delete( this->countMenu );
delete( this->dictMenu );
delete( this->sizeMenu );
} /* ~CPlayersWindow */
void
CPlayersWindow::DisOrEnable( U16 id, BOOL enable )
{
CViewable* child = this->GetChildID( id );
if ( enable ) {
XP_DEBUGF( "enabling child id=%d\n", id );
child->Enable();
} else {
XP_DEBUGF( "disabling child id=%d\n", id );
child->Disable();
}
} /* DisOrEnable */
static BOOL
checkAllDigits( CTextEdit* te )
{
char* text = te->GetText();
char ch;
while ( (ch=*text++) != '\0' ) {
if ( !isdigit(ch) ) {
return false;
}
}
return true;
} /* checkAllDigits */
S32
CPlayersWindow::MsgHandler( MSG_TYPE type, CViewable *from, S32 data )
{
S32 result = 0;
S32 id;
U16 row;
switch ( type ) {
case MSG_MENU_SELECT: /* the num-players trigger */
XP_DEBUGF( "MSG_MENU_SELECT: data=%ld\n", data );
switch ( from->GetID()) {
case NUMPLAYERS_POPUP_ID:
row = this->countMenu->GetCurrentRow();
fLocalGI.nPlayers = row + 1; /* GetCurrentRow is 0-based */
adjustVisibility();
GUI_NeedUpdate();
result = 1;
break;
/* case DICTNAMES_POPUP_ID: */
/* row = this->dictMenu->GetCurrentRow(); */
/* break; */
}
break;
case MSG_TEXT_CHANGED:
if ( (from->GetID() == TIMER_FIELD_ID)
&& !checkAllDigits( (CTextEdit*)from ) ) {
result = TEXTEDIT_PLEASE_UNDO;
}
break;
case MSG_BUTTON_SELECT:
result = 1;
id = from->GetID();
switch ( id ) {
case TIMER_CHECKBOX_ID:
DisOrEnable( TIMER_FIELD_ID, fTimerEnabled->GetDownStatus() );
break;
case OK_BUTTON_ID:
for ( U16 i = 0; i < fLocalGI.nPlayers; ++i ) {
copyIDString( NAME_BASE+i, &fLocalGI.players[i].name );
copyIDString( PASSWORD_BASE+i,
&fLocalGI.players[i].password );
}
if ( !!dictMenu ) {
fLocalGI.dictName =
copyString( MPPARM(mpool)
fDList->GetNthName(dictMenu->GetCurrentRow()));
} else {
fLocalGI.dictName = (XP_UCHAR*)NULL;
}
if ( fIsNew ) {
fLocalGI.boardSize = 15 - this->sizeMenu->GetCurrentRow();
fLocalGI.phoniesAction = fPhoniesMenu->GetCurrentRow();
}
fLocalGI.timerEnabled = fTimerEnabled->GetDownStatus();
if ( fLocalGI.timerEnabled ) {
char* text = fTimerField->GetText();
fLocalGI.gameSeconds = atoi(text) * 60;
}
*fGIRef = fLocalGI; /* copy changes to caller */
case CANCEL_BUTTON_ID:
*this->resultP = id == CANCEL_BUTTON_ID;
this->Close();
result = 1;
break;
default: /* probably one of our synthetic IDs */
if ( id >= ROBOT_BASE && id < ROBOT_BASE+MAX_NUM_PLAYERS ) {
U16 playerNum = id - ROBOT_BASE;
BOOL isRobot = ((CButton*)from)->GetDownStatus();
fLocalGI.players[playerNum].isRobot = isRobot;
adjustVisibility();
} else if (id >= NAME_BASE && id < NAME_BASE + MAX_NUM_PLAYERS ){
} else {
result = 0;
}
}
default:
break;
}
if ( result == 0 ) {
result = CWindow::MsgHandler( type, from, data );
}
return result;
} // CPlayersWindow::MsgHandler
/* This will create a dictionary of the dict listed first in the initial.mom
* file
*/
void
CPlayersWindow::makeDictMenu()
{
XP_U16 nDicts = fDList->GetDictCount();
U16 startRow;
if ( !!fLocalGI.dictName ) {
startRow = fDList->IndexForName( fLocalGI.dictName);
} else {
startRow = 0;
}
XP_ASSERT( nDicts > 0 );
CMenu* menu = new CMenu( PLAYERDICT_MENU_ID, 0, 0, 0, 0, 0 );
menu->SetNumRows( nDicts );
for ( U16 i = 0; i < nDicts; ++i ) {
menu->SetRow( i, 3000+i, (char*)fDList->GetNthName(i) );
}
CPopupTrigger *trigger = new CPopupTrigger( DICTNAMES_POPUP_ID, 0, 0,
menu, 0 );
trigger->SetCurrentRow(startRow);
menu->SetCurrentRow(startRow);
CLabel* label = new CLabel( DICT_LABEL_ID, "Dictnry:" );
this->AddChild( label, NAME_COL, DICTMENU_ROW );
U16 labelWidth = label->GetWidth();
this->AddChild( trigger, NAME_COL+labelWidth+10, DICTMENU_ROW );
if ( !fIsNew ) {
DisOrEnable( DICTNAMES_POPUP_ID, FALSE );
}
this->dictMenu = menu;
} /* CPlayersWindow::makeDictMenu */
void
CPlayersWindow::makeSizeMenu()
{
CMenu* menu = new CMenu( BOARDSIZE_MENU_ID, 0, 0, 0, 0, 0 );
menu->SetNumRows( NUM_SIZES );
for ( U16 i = 0; i < NUM_SIZES; ++i ) {
U16 siz = 15-i;
snprintf( (char*)this->sizeNames[i], sizeof(this->sizeNames[i]),
"%dx%d", siz, siz );
menu->SetRow( i, 4000+i, (char*)this->sizeNames[i] );
}
CPopupTrigger* trigger = new CPopupTrigger( BOARDSIZE_POPUP_ID, 0, 0,
menu, 0 );
U16 curSize = 15-fLocalGI.boardSize;
trigger->SetCurrentRow(curSize);
menu->SetCurrentRow(curSize);
CLabel* label = new CLabel( SIZE_LABEL_ID, "Board size:" );
this->AddChild( label, NAME_COL, SIZEMENU_ROW );
U16 labelWidth = label->GetWidth();
this->AddChild( trigger, NAME_COL+labelWidth+10, SIZEMENU_ROW );
if ( !fIsNew ) {
DisOrEnable( BOARDSIZE_POPUP_ID, FALSE );
}
this->sizeMenu = menu;
} /* CPlayersWindow::makeSizeMenu */
void
CPlayersWindow::adjustVisibility()
{
/* disable everything greater than the number of players. Before that,
disable passwords if robot */
U16 nPlayers = fLocalGI.nPlayers;
for ( U16 i = 0; i < MAX_NUM_PLAYERS; ++i ) {
XP_Bool disableAll = i >= nPlayers;
BOOL enable;
/* name */
enable = !disableAll;
DisOrEnable( NAME_BASE + i, enable );
/* robot check */
/* enable's the same as above */
DisOrEnable( ROBOT_BASE + i, enable );
/* passwd */
enable = !disableAll && !fLocalGI.players[i].isRobot;
DisOrEnable( PASSWORD_BASE + i, enable );
}
} /* adjustVisibility */
void
CPlayersWindow::makePhoniesMenu()
{
CMenu* menu = new CMenu( PHONIES_MENU_ID, 0, 0, 0, 0, 0 );
menu->SetNumRows( 3 );
menu->SetRow( 0, 5000, "Ignore" );
menu->SetRow( 1, 5001, "Warn" );
menu->SetRow( 2, 5002, "Disallow" );
CPopupTrigger* trigger = new CPopupTrigger( PHONIES_POPUP_ID, 0, 0,
menu, 0 );
XWPhoniesChoice phoniesAction = fLocalGI.phoniesAction;
trigger->SetCurrentRow(phoniesAction);
menu->SetCurrentRow(phoniesAction);
CLabel* label = new CLabel( SIZE_LABEL_ID, "Phonies:" );
this->AddChild( label, NAME_COL, PHONIESMENU_ROW );
U16 labelWidth = label->GetWidth();
this->AddChild( trigger, NAME_COL+labelWidth+10, PHONIESMENU_ROW );
fPhoniesMenu = menu;
} /* CPlayersWindow::makePhoniesMenu */
void
CPlayersWindow::copyIDString( U16 id, XP_UCHAR** where )
{
if ( *where ) {
XP_DEBUGF( "freeing string " );
XP_DEBUGF( "%s\n", *where );
XP_FREE( mpool, *where );
XP_DEBUGF( "done freeing string\n" );
}
XP_UCHAR* str = (XP_UCHAR*)NULL;
CTextEdit* te = (CTextEdit*)this->GetChildID( id );
XP_UCHAR* name = (XP_UCHAR*)te->GetText();
U16 len = te->TextLength();
if ( len > 0 ) {
str = (XP_UCHAR*)XP_MALLOC( mpool, len + 1 );
memcpy( str, name, len );
str[len] = '\0';
}
*where = str;
} /* CPlayersWindow::copyIDString */

66
franklin/frankplayer.h Normal file
View file

@ -0,0 +1,66 @@
// -*-mode: C; fill-column: 78; 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 _FRANKPLAYER_H_
#define _FRANKPLAYER_H_
extern "C" {
#include "comtypes.h"
#include "game.h"
}
#include "frankdict.h"
#include "frankdlist.h"
#define NUM_SIZES 6
class CPlayersWindow : public CWindow {
private:
CurGameInfo fLocalGI; /* local copy; discard if cancel */
BOOL* resultP; /* where to write ok-or-cancel */
CurGameInfo* fGIRef; /* copy local to here if not cancel */
CMenu* countMenu; /* need to preserve in order to delete */
CMenu* dictMenu; /* need to preserve in order to delete */
CMenu* sizeMenu;
CMenu* fPhoniesMenu;
CCheckbox* fTimerEnabled;
CTextEdit* fTimerField;
XP_UCHAR sizeNames[10][NUM_SIZES];
FrankDictList* fDList;
BOOL fIsNew;
XP_UCHAR fNumsBuf[10]; /* saves allocs and frees for menu strings */
public:
MPSLOT
public:
CPlayersWindow( MPFORMAL CurGameInfo* pi, FrankDictList* dlist, BOOL isNew,
BOOL allowCancel, BOOL* cancelledP );
~CPlayersWindow();
S32 MsgHandler( MSG_TYPE type, CViewable *object, S32 data );
private:
void DisOrEnable( U16 id, BOOL enable );
void makeDictMenu();
void makeSizeMenu();
void makePhoniesMenu();
void copyIDString( U16 id, XP_UCHAR** where );
void adjustVisibility();
};
#endif

View file

@ -0,0 +1,231 @@
// -*-mode: C; fill-column: 78; 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 <assert.h>
#include <ctype.h>
#include "sys.h"
#include "gui.h"
#include "ebm_object.h"
extern "C" {
#include "comtypes.h"
}
#include "franksavedgames.h"
#include "frankids.h"
#define RENAME_BUTTON_ID 1000
#define DUP_BUTTON_ID 1001
#define DELETE_BUTTON_ID 1002
#define DONE_BUTTON_ID 1003
#define OPEN_BUTTON_ID 1004
#define NAME_FIELD_ID 1005
#define ROW_HEIGHT 12
#define GAMES_NUM_VISROWS 6
#define GAMES_ROW_WIDTH 150
#define LIST_TOP 5
#define LIST_HEIGHT (GAMES_NUM_VISROWS*ROW_HEIGHT)
#define FIELD_TOP (LIST_TOP+LIST_HEIGHT+8)
#define LIST_LEFT 5
#define FIELD_HEIGHT 15
#define FIELD_WIDTH 100
#define BUTTON_TOP (FIELD_TOP+FIELD_HEIGHT+8)
class GamesList : public CList {
private:
CGamesDB* gamesDB;
public:
GamesList( CGamesDB* gamesDB, U16 numRows, U16 startRow );
U16 GetRowHeight( S32 row ) { return ROW_HEIGHT; }
void DrawRow( RECT *rect, S32 row );
};
GamesList::GamesList( CGamesDB* gamesDB, U16 numRows, U16 startRow )
: CList( 1001, GAMES_ROW_WIDTH, LIST_HEIGHT,
numRows, LISTOPTION_ALWAYS_HIGHLIGHT )
{
this->gamesDB = gamesDB;
this->SetCurrentRow(startRow);
}
void GamesList::DrawRow( RECT *rect, S32 row )
{
XP_UCHAR* name = this->gamesDB->getNthName( row+1 );
if ( !name ) {
name = (XP_UCHAR*)"untitled";
}
CWindow* window = this->GetWindow();
window->DrawText( (char*)name, rect->x, rect->y );
} /* GamesList::DrawRow */
/*****************************************************************************
* The class itself
****************************************************************************/
CSavedGamesWindow::CSavedGamesWindow( CGamesDB* gamesDB, U16* toOpen,
U16* curIndex )
: CWindow( SAVEDGAMES_WINDOW_ID, 2, 90, 196, 148, "Saved games", TRUE,
FALSE, FALSE /* no closebox */ )
{
this->gamesDB = gamesDB;
this->toOpenP = toOpen; /* what we'll say to open */
this->curIndexP = curIndex; /* where we'll say current's moved to */
this->curIndex = *curIndex; /* save current (move when delete/dup) */
this->displayIndex = this->curIndex; /* start display at current */
this->gamesList = (GamesList*)NULL;
CTextEdit* field = new CTextEdit( NAME_FIELD_ID, FIELD_WIDTH,
FIELD_HEIGHT, TEXTOPTION_HAS_FOCUS
| TEXTOPTION_ONELINE );
this->nameField = field;
field->SetText( (char*)gamesDB->getNthName( this->displayIndex ) );
this->AddChild( field, LIST_LEFT, FIELD_TOP );
CButton* button = new CButton( RENAME_BUTTON_ID, 0, 0, "Rename" );
U16 result = this->AddChild( button, 130, FIELD_TOP );
button = new CButton( DUP_BUTTON_ID, 0, 0, "Dup" );
result = this->AddChild( button, 5, BUTTON_TOP );
button = new CButton( DELETE_BUTTON_ID, 0, 0, "Delete" );
result = this->AddChild( button, 40, BUTTON_TOP );
this->deleteButton = button;
checkDisableDelete();
button = new CButton( OPEN_BUTTON_ID, 0, 0, "Open" );
result = this->AddChild( button, 90, BUTTON_TOP );
button = new CButton( DONE_BUTTON_ID, 0, 0, "Done" );
result = this->AddChild( button, 130, BUTTON_TOP );
reBuildGamesList();
} // CSavedGamesWindow
void
CSavedGamesWindow::reBuildGamesList()
{
if ( !!this->gamesList ) {
this->DeleteChild( this->gamesList );
delete this->gamesList;
}
U16 numRows = this->gamesDB->countRecords() - 1; /* skip prefs */
GamesList* list = new GamesList( gamesDB, numRows, this->curIndex-1 );
this->gamesList = list;
this->AddChild( list, LIST_LEFT, LIST_TOP );
list->SetCurrentRow( this->displayIndex-1 );
} /* reBuildGamesList */
void
CSavedGamesWindow::checkDisableDelete()
{
BOOL disable = this->displayIndex == this->curIndex;
CButton* button = this->deleteButton;
if ( disable != button->IsDisabled() ) {
if ( disable ) {
button->Disable();
} else {
button->Enable();
}
}
} /* checkDisableDelete */
S32
CSavedGamesWindow::MsgHandler( MSG_TYPE type, CViewable *object, S32 data )
{
S32 result = 0;
XP_UCHAR* name;
U16 newID;
switch (type) {
case MSG_BUTTON_SELECT: // there's only one button....
switch (object->GetID()) {
case RENAME_BUTTON_ID:
name = (XP_UCHAR*)this->nameField->GetText();
this->gamesDB->putNthName( this->displayIndex, name );
this->gamesList->Draw();
break;
case DUP_BUTTON_ID:
newID = this->gamesDB->duplicateNthRecord( this->displayIndex );
this->displayIndex = newID;
reBuildGamesList();
this->gamesList->Draw();
checkDisableDelete();
break;
case DELETE_BUTTON_ID:
/* disable button instead of checking here */
XP_ASSERT( this->displayIndex != this->curIndex );
if ( 1 == GUI_Alert( ALERT_OK,
"Are you sure you want to delete"
" the selected game?" ) ) {
this->gamesDB->removeNthRecord( this->displayIndex );
if ( this->displayIndex < this->curIndex ) {
--this->curIndex;
}
if ( this->displayIndex == this->gamesDB->countRecords() ) {
--this->displayIndex;
}
reBuildGamesList();
this->gamesList->Draw();
checkDisableDelete();
}
break;
case DONE_BUTTON_ID:
this->displayIndex = this->curIndex; /* restore to saved so next
line's does nothing */
/* FALLTHRU */
case OPEN_BUTTON_ID:
*this->curIndexP = this->curIndex;
*this->toOpenP = this->displayIndex;
this->Close();
break;
}
result = 1;
break;
case MSG_ROW_SELECT:
this->displayIndex = (U16)data + 1;
nameField->SetText( (char*)gamesDB->getNthName( this->displayIndex ) );
checkDisableDelete();
result = 1;
break;
default:
break;
}
if ( result == 0 ) {
result = CWindow::MsgHandler( type, object, data );
}
return result;
} // MsgHandler

View file

@ -0,0 +1,47 @@
// -*-mode: C; fill-column: 78; c-basic-offset: 4; -*-
/*
* Copyright 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 _FRANKSAVEDGAMES_H_
#define _FRANKSAVEDGAMES_H_
#include "frankgamesdb.h"
extern "C" {
}
class CSavedGamesWindow : public CWindow {
private:
CGamesDB* gamesDB;
class GamesList* gamesList;
CTextEdit* nameField;
CButton* deleteButton;
U16* toOpenP;
U16* curIndexP;
U16 curIndex;
U16 displayIndex;
void reBuildGamesList();
void checkDisableDelete();
public:
CSavedGamesWindow( CGamesDB* gamesDB, U16* toOpen, U16* curIndex );
S32 MsgHandler( MSG_TYPE type, CViewable *object, S32 data );
};
#endif

154
franklin/frankshowtext.cpp Normal file
View file

@ -0,0 +1,154 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
/*
* Copyright 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 <assert.h>
#include <ctype.h>
#include "sys.h"
#include "gui.h"
#include "ebm_object.h"
extern "C" {
#include "xptypes.h"
#include "xwstream.h"
}
#include "frankshowtext.h"
#include "frankids.h"
#define MAX_DLG_HT 200
#define SHOWTEXT_WINDOW_ID 2000
#define SHOW_TEXT_ID 2001
#define TEXT_X 5
#define TEXT_PADDING_ABOVE 5
#define TEXT_PADDING_BELOW 5
#define TEXT_Y TEXT_PADDING_ABOVE
#define TEXT_WIDTH 180
#define TEXT_HEIGHT 40
#define TEXT_PADDING (TEXT_PADDING_ABOVE+TEXT_PADDING_BELOW)
#define TITLE_BAR_HT 15
#define OK_BUTTON_ID 1000
#define CANCEL_BUTTON_ID 1001
#define OK_BUTTON_X 40
#define CANCEL_BUTTON_X 100
#define BUTTON_HEIGHT 12
#define BUTTON_PADDING 3 /* below buttons */
CShowTextWindow::CShowTextWindow( MPFORMAL XWStreamCtxt* stream,
const char* title,
XP_Bool killStream, XP_Bool showCancel,
XP_U16* resultLoc )
: CWindow( SHOWTEXT_WINDOW_ID, 5, 170, 190,
TEXT_HEIGHT + TEXT_PADDING + TITLE_BAR_HT,
title, TRUE, FALSE, !showCancel )
{
MPASSIGN( this->mpool, mpool );
CButton* okButton = (CButton*)NULL;
CButton* cancelButton = (CButton*)NULL;
fResultLoc = resultLoc;
CTextEdit* entry = new CTextEdit( SHOW_TEXT_ID, TEXT_WIDTH, TEXT_HEIGHT,
TEXTOPTION_NOEDIT |
TEXTOPTION_NOUNDERLINE);
/* copy the stream's text into the texteditor */
stream_putU8( stream, '\0' );
XP_U16 len = stream_getSize( stream );
char* textPtr = (char*)XP_MALLOC( mpool, len );
stream_getBytes( stream, textPtr, len );
XP_ASSERT( textPtr[len-1] == '\0' );
entry->SetText(textPtr);
XP_FREE( mpool, textPtr );
if ( killStream ) {
stream_destroy( stream );
}
RECT rect;
GetUsableRect( &rect );
U16 titleBarHt = rect.y - GetY();
U16 maxTextHeight = MAX_DLG_HT - TEXT_PADDING - titleBarHt;
U16 buttonHeight;
if ( showCancel ) {
okButton = new CButton( OK_BUTTON_ID, 0, 0, "Ok" );
cancelButton = new CButton( CANCEL_BUTTON_ID, 0, 0, "Cancel" );
buttonHeight = okButton->GetHeight() + BUTTON_PADDING;
maxTextHeight -= buttonHeight;
} else {
buttonHeight = 0;
}
/* FIND out how big the text wants to be. Make the window as big as
necessary, growing it upward. */
U16 curTextHeight = entry->GetMaxHeight();
if ( curTextHeight > maxTextHeight ) {
curTextHeight = maxTextHeight;
}
entry->SetHeight( curTextHeight );
U16 newDlgHeight = curTextHeight + buttonHeight + TEXT_PADDING
+ titleBarHt;
S16 diff = newDlgHeight - GetHeight();
SetY( GetY() - diff );
SetHeight( newDlgHeight );
this->AddChild( entry, TEXT_X, TEXT_Y );
if ( showCancel ) {
U16 buttonY = TEXT_Y + curTextHeight + TEXT_PADDING_BELOW;
AddChild( okButton, OK_BUTTON_X, buttonY );
AddChild( cancelButton, CANCEL_BUTTON_X, buttonY );
}
} /* CShowTextWindow */
S32
CShowTextWindow::MsgHandler( MSG_TYPE type, CViewable *object, S32 data )
{
S32 result = 0;
switch ( type ) {
case MSG_BUTTON_SELECT: /* there's only one button */
result = 1;
switch ( object->GetID() ) {
case OK_BUTTON_ID:
*fResultLoc = 1;
break;
case CANCEL_BUTTON_ID:
*fResultLoc = 0;
break;
}
break;
default:
break;
}
if ( result == 1 ) {
this->Close();
}
return result;
} /* MsgHandler */

42
franklin/frankshowtext.h Normal file
View file

@ -0,0 +1,42 @@
// -*-mode: C; fill-column: 78; c-basic-offset: 4; -*-
/*
* Copyright 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 _SHOWTEXT_H_
#define _SHOWTEXT_H_
extern "C" {
#include "comtypes.h"
#include "mempool.h"
}
class CShowTextWindow : public CWindow {
private:
XP_U16* fResultLoc;
public:
MPSLOT
public:
CShowTextWindow( MPFORMAL XWStreamCtxt* stream, const char* title,
XP_Bool killStream, XP_Bool showCancel,
XP_U16* resultLoc );
S32 MsgHandler( MSG_TYPE type, CViewable *object, S32 data );
};
#endif /* _SHOWTEXT_H_ */

110
franklin/xptypes.h Normal file
View file

@ -0,0 +1,110 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
/*
* Copyright 1999-2000 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 _XPTYPES_H_
#define _XPTYPES_H_
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gui_types.h>
#include <assert.h>
#ifdef CPLUS
extern "C" {
#endif
#define XP_TRUE ((XP_Bool)(1==1))
#define XP_FALSE ((XP_Bool)(1==0))
typedef U8 XP_U8;
typedef S8 XP_S8;
typedef unsigned char XP_UCHAR;
typedef U16 XP_U16;
typedef S16 XP_S16;
typedef U32 XP_U32;
/* typedef S32 XP_A32; */
typedef S32 XP_S32;
typedef signed short XP_FontCode; /* not sure how I'm using this yet */
typedef BOOL XP_Bool;
typedef U32 XP_Time;
#define XP_CR "\n"
void frank_insetRect( RECT* r, short byWhat );
void frank_debugf(char*, ...);
void p_ignore(char*, ...);
int frank_snprintf( XP_UCHAR* buf, XP_U16 len, XP_UCHAR* format, ... );
unsigned long frank_flipLong( unsigned long l );
unsigned short frank_flipShort(unsigned short s);
#define XP_RANDOM() rand()
#ifdef MEM_DEBUG
# define XP_PLATMALLOC(nbytes) malloc(nbytes)
# define XP_PLATREALLOC(p,s) realloc((p), (s))
# define XP_PLATFREE(p) free(p)
#else
# define XP_MALLOC(pool, nbytes) malloc(nbytes)
# define XP_REALLOC(pool, p, bytes) realloc((p), (bytes))
# define XP_FREE(pool, p) free(p)
#endif
#define XP_MEMSET(src, val, nbytes) memset( (src), (val), (nbytes) )
#define XP_MEMCPY(d,s,l) memcpy((d),(s),(l))
#define XP_MEMCMP( a1, a2, l ) memcmp((a1),(a2),(l))
#define XP_STRLEN(s) strlen((char*)(s))
#define XP_STRCMP(s1,s2) strcmp((char*)(s1),(char*)(s2))
#define XP_STRNCMP(s1,s2,l) strncmp((char*)(s1),(char*)(s2),(l))
#define XP_SNPRINTF frank_snprintf
#define XP_MIN(a,b) ((a)<(b)?(a):(b))
#define XP_MAX(a,b) ((a)>(b)?(a):(b))
#ifdef DEBUG
#define XP_ASSERT(b) assert(b)
#else
#define XP_ASSERT(b)
#endif
#define XP_STATUSF XP_DEBUGF
#define XP_WARNF XP_DEBUGF
#ifdef DEBUG
#define XP_LOGF frank_debugf
#define XP_DEBUGF frank_debugf
#else
#define XP_LOGF if(0)p_ignore
#define XP_DEBUGF if(0)p_ignore
#endif
#define XP_NTOHL(l) frank_flipLong(l)
#define XP_NTOHS(s) frank_flipShort(s)
#define XP_HTONL(l) frank_flipLong(l)
#define XP_HTONS(s) frank_flipShort(s)
#ifdef CPLUS
}
#endif
#endif