diff --git a/xwords4/common/dictnry.c b/xwords4/common/dictnry.c index 493b01323..eb30b9469 100644 --- a/xwords4/common/dictnry.c +++ b/xwords4/common/dictnry.c @@ -459,9 +459,8 @@ make_stubbed_dict( MPFORMAL_NOCOMMA ) #endif /* STUBBED_DICT */ -#ifndef OVERRIDE_EDGE_FOR_INDEX -array_edge* -dict_edge_for_index( DictionaryCtxt* dict, XP_U32 index ) +static array_edge* +dict_super_edge_for_index( DictionaryCtxt* dict, XP_U32 index ) { array_edge* result; @@ -470,15 +469,34 @@ dict_edge_for_index( DictionaryCtxt* dict, XP_U32 index ) } else { XP_ASSERT( index < dict->numEdges ); #ifdef NODE_CAN_4 - index *= dict->nodeSize; + /* avoid long-multiplication lib call on Palm... */ + if ( dict->nodeSize == 3 ) { + index += (index << 1); + } else { + XP_ASSERT( dict->nodeSize == 4 ); + index <<= 2; + } #else - index *= 3; + index += (index << 1); #endif result = &dict->base[index]; } return result; } /* dict_edge_for_index */ -#endif + +static array_edge* +dict_super_getTopEdge( DictionaryCtxt* dict ) +{ + return dict->topEdge; +} /* dict_super_getTopEdge */ + +void +dict_super_init( DictionaryCtxt* ctxt ) +{ + /* subclass may change these later.... */ + ctxt->func_edge_for_index = dict_super_edge_for_index; + ctxt->func_dict_getTopEdge = dict_super_getTopEdge; +} /* dict_super_init */ #ifdef CPLUS } diff --git a/xwords4/common/dictnry.h b/xwords4/common/dictnry.h index 42b31519b..fb6a576b2 100644 --- a/xwords4/common/dictnry.h +++ b/xwords4/common/dictnry.h @@ -57,6 +57,10 @@ typedef struct SpecialBitmaps { struct DictionaryCtxt { void (*destructor)( DictionaryCtxt* dict ); + + array_edge* (*func_edge_for_index)( DictionaryCtxt* dict, XP_U32 index ); + array_edge* (*func_dict_getTopEdge)( DictionaryCtxt* dict ); + array_edge* topEdge; array_edge* base; /* the physical beginning of the dictionary; not necessarily the entry point for search!! */ @@ -107,6 +111,9 @@ struct DictionaryCtxt { /* #define dict_numTileFaces(dc) (dc)->vtable->m_numTileFaces(dc) */ #define dict_destroy(d) (*((d)->destructor))(d) +#define dict_edge_for_index(d, i) (*((d)->func_edge_for_index))((d), (i)) +#define dict_getTopEdge(d) (*((d)->func_dict_getTopEdge))(d) + XP_Bool dict_tilesAreSame( DictionaryCtxt* dict1, DictionaryCtxt* dict2 ); @@ -133,20 +140,14 @@ void dict_loadFromStream( DictionaryCtxt* dict, XWStreamCtxt* stream ); /* These methods get "overridden" by subclasses. That is, they must be implemented by each platform. */ -array_edge* dict_edge_for_index( DictionaryCtxt* dict, XP_U32 index ); - -#ifdef OVERRIDE_GETTOPEDGE -/* platform code will implement this */ -array_edge* dict_getTopEdge( DictionaryCtxt* dict ); -#else -# define dict_getTopEdge( dict ) ((dict)->topEdge) -#endif - - #ifdef STUBBED_DICT DictionaryCtxt* make_stubbed_dict( MPFORMAL_NOCOMMA ); #endif +/* To be called only by subclasses!!! */ +void dict_super_init( DictionaryCtxt* ctxt ); + + #ifdef CPLUS } #endif diff --git a/xwords4/palm/palmdict.c b/xwords4/palm/palmdict.c index ce99115b9..586a42c77 100644 --- a/xwords4/palm/palmdict.c +++ b/xwords4/palm/palmdict.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "dictnryp.h" #include "dawg.h" @@ -60,6 +61,8 @@ static void palm_dictionary_destroy( DictionaryCtxt* dict ); static XP_U16 countSpecials( FaceType* ptr, UInt16 nChars ); static void setupSpecials( MPFORMAL PalmDictionaryCtxt* ctxt, Xloc_specialEntry* specialStart, XP_U16 nSpecials ); +static array_edge* palm_dict_edge_for_index_multi( DictionaryCtxt* dict, + XP_U32 index ); DictionaryCtxt* palm_dictionary_make( MPFORMAL XP_UCHAR* dictName, PalmDictList* dl ) @@ -74,7 +77,7 @@ palm_dictionary_make( MPFORMAL XP_UCHAR* dictName, PalmDictList* dl ) dawg_header* headerRecP; unsigned char* charPtr; UInt16 nChars, nSpecials; - unsigned long offset = 0; + XP_U32 offset; DictListEntry* dle; Err err; XP_U16 i; @@ -83,6 +86,8 @@ palm_dictionary_make( MPFORMAL XP_UCHAR* dictName, PalmDictList* dl ) XP_U16 flags; XP_U16 nodeSize = 3; /* init to satisfy compiler */ #endif + XP_U32 totalSize; + void* dawgBase; /* check and see if there's already a dict for this name. If yes, increment its refcount and return. */ @@ -105,6 +110,8 @@ palm_dictionary_make( MPFORMAL XP_UCHAR* dictName, PalmDictList* dl ) XP_MEMSET( ctxt, 0, sizeof(*ctxt) ); MPASSIGN( ctxt->super.mpool, mpool ); + dict_super_init( (DictionaryCtxt*)ctxt ); + if ( !!dictName ) { XP_ASSERT( XP_STRLEN((const char*)dictName) > 0 ); @@ -188,6 +195,8 @@ palm_dictionary_make( MPFORMAL XP_UCHAR* dictName, PalmDictList* dl ) ctxt->super.topEdge = NULL; ctxt->nRecords = 0; } else { + MemHandle record; + XP_U16 size; short index; XP_U16 nRecords; @@ -203,34 +212,78 @@ palm_dictionary_make( MPFORMAL XP_UCHAR* dictName, PalmDictList* dl ) ctxt->super.is_4_byte = nodeSize == 4; #endif + totalSize = 0; for ( index = 0; index < nRecords; ++index ) { - MemHandle record = - DmQueryRecord( dbRef, index + headerRecP->firstEdgeRecNum); - ctxt->dictStarts[index].indexStart = offset; - - /* cast to short to avoid libc call */ - XP_ASSERT( MemHandleSize(record) < 0xFFFF ); -#ifdef NODE_CAN_4 - XP_ASSERT( 0 == ((unsigned short)(MemHandleSize(record)) - % nodeSize )); - offset += ((unsigned short)MemHandleSize(record)) - / nodeSize; -#else - XP_ASSERT( ((unsigned short)(MemHandleSize(record)) % 3 )==0); - offset += ((unsigned short)MemHandleSize(record)) / 3; -#endif - ctxt->dictStarts[index].array = - (array_edge*)MemHandleLock( record ); - XP_ASSERT( MemHandleLockCount(record) == 1 ); + record = DmQueryRecord( dbRef, index + + headerRecP->firstEdgeRecNum); + totalSize += MemHandleSize( record ); } - XP_ASSERT( index == ctxt->nRecords ); - ctxt->dictStarts[index].indexStart = 0xFFFFFFFFL; - - ctxt->super.topEdge = ctxt->dictStarts[0].array; + /* NOTE: need to use more than one feature to support having + multiple dicts open at once. */ + err = ~errNone; /* so test below will pass if nRecords == 1 */ + if ( 0 && nRecords > 1 ) { + err = FtrPtrNew( APPID, DAWG_STORE_FEATURE, totalSize, + &dawgBase ); + if ( err == errNone ) { + for ( index = 0, offset = 0; index < nRecords; ++index ) { + record = DmQueryRecord( dbRef, index + + headerRecP->firstEdgeRecNum ); + size = MemHandleSize( record ); + XP_LOGF( "size=%d", size ); + err = DmWrite( dawgBase, offset, + MemHandleLock( record ), size ); + XP_ASSERT( err == errNone ); + MemHandleUnlock( record ); + offset += size; + XP_LOGF( "offset now = %ld", offset ); #ifdef DEBUG - ctxt->super.numEdges = offset; +#ifdef NODE_CAN_4 + ctxt->super.numEdges += size / nodeSize; +#else + ctxt->super.numEdges += size / 3; #endif +#endif + } + + ctxt->super.base = dawgBase; + ctxt->super.topEdge = dawgBase; + } else { + XP_LOGF( "unable to use Ftr for dict; err=%d", err ); + } + } + + if ( err != errNone ) { + offset = 0; + for ( index = 0; index < nRecords; ++index ) { + record = DmQueryRecord( dbRef, index + headerRecP->firstEdgeRecNum ); + size = MemHandleSize( record ); + + ctxt->dictStarts[index].indexStart = offset; + + /* cast to short to avoid libc call */ + XP_ASSERT( size < 0xFFFF ); +#ifdef NODE_CAN_4 + XP_ASSERT( 0 == (size % nodeSize) ); + offset += size / nodeSize; +#else + XP_ASSERT( ((unsigned short)size % 3 )==0); + offset += ((unsigned short)size) / 3; +#endif + ctxt->dictStarts[index].array = + (array_edge*)MemHandleLock( record ); + XP_ASSERT( MemHandleLockCount(record) == 1 ); + } + + XP_ASSERT( index == ctxt->nRecords ); + ctxt->dictStarts[index].indexStart = 0xFFFFFFFFL; + + ctxt->super.topEdge = ctxt->dictStarts[0].array; +#ifdef DEBUG + ctxt->super.numEdges = offset; +#endif + ctxt->super.func_edge_for_index = palm_dict_edge_for_index_multi; + } } setBlankTile( (DictionaryCtxt*)ctxt ); @@ -330,8 +383,14 @@ palm_dictionary_destroy( DictionaryCtxt* dict ) XP_FREE( dict->mpool, ctxt->super.faces16 ); - for ( i = 0; i < ctxt->nRecords; ++i ) { - MemPtrUnlock( ctxt->dictStarts[i].array ); + /* Try first to delete the feature. */ + if ( FtrPtrFree( APPID, DAWG_STORE_FEATURE ) == ftrErrNoSuchFeature ) { + for ( i = 0; i < ctxt->nRecords; ++i ) { + XP_ASSERT( !!ctxt->dictStarts[i].array ); + MemPtrUnlock( ctxt->dictStarts[i].array ); + } + } else { + XP_ASSERT( ctxt->dictStarts[0].array == NULL ); } MemPtrUnlock( headerRecP ); @@ -359,8 +418,8 @@ palm_dictionary_destroy( DictionaryCtxt* dict ) } /* palm_dictionary_destroy */ #ifdef OVERRIDE_EDGE_FOR_INDEX -array_edge* -dict_edge_for_index( DictionaryCtxt* dict, XP_U32 index ) +static array_edge* +palm_dict_edge_for_index_multi( DictionaryCtxt* dict, XP_U32 index ) { PalmDictionaryCtxt* ctxt = (PalmDictionaryCtxt*)dict; array_edge* result; @@ -397,4 +456,5 @@ dict_edge_for_index( DictionaryCtxt* dict, XP_U32 index ) return result; } /* dict_edge_for_index */ + #endif diff --git a/xwords4/palm/palmmain.h b/xwords4/palm/palmmain.h index e48696677..80ac4ac2b 100644 --- a/xwords4/palm/palmmain.h +++ b/xwords4/palm/palmmain.h @@ -336,6 +336,7 @@ enum { , GLOBALS_FEATURE /* for passing globals to form handlers */ , FEATURE_WANTS_68K /* support for (pre-ship) ability to choose armlet or 68K */ + , DAWG_STORE_FEATURE }; enum { WANTS_68K, WANTS_ARM };