Merge branch 'android_branch' into android_browsedict

Conflicts:
	xwords4/common/dictnry.c
This commit is contained in:
Andy2 2011-10-28 21:00:01 -07:00
commit 390e7558b0
4 changed files with 205 additions and 145 deletions

View file

@ -464,7 +464,9 @@ dict_getWordCount( const DictionaryCtxt* dict )
{
XP_U32 nWords = dict->nWords;
#ifdef XWFEATURE_WALKDICT
nWords = dict_countWords( dict );
if ( 0 == nWords ) {
nWords = dict_countWords( dict );
}
#endif
return nWords;
}
@ -731,7 +733,8 @@ nextWord( const DictionaryCtxt* dict, EdgeArray* edges )
continue; /* try with longer word */
}
while ( IS_LAST_EDGE( dict, edges->edges[nTiles-1] ) && 0 < --nTiles ) {
while ( IS_LAST_EDGE( dict, edges->edges[nTiles-1] )
&& 0 < --nTiles ) {
}
if ( 0 < nTiles ) {
@ -780,7 +783,8 @@ prevWord( const DictionaryCtxt* dict, EdgeArray* edges )
while ( 0 < edges->nEdges && ! success ) {
if ( isFirstEdge( dict, edges->edges[edges->nEdges-1] ) ) {
--edges->nEdges;
success = 0 < edges->nEdges && ISACCEPTING( dict, edges->edges[edges->nEdges-1] );
success = 0 < edges->nEdges
&& ISACCEPTING( dict, edges->edges[edges->nEdges-1] );
continue;
}
edges->edges[edges->nEdges-1] -= dict->nodeSize;
@ -812,10 +816,11 @@ dict_getWord( const DictionaryCtxt* dict, DictWord* word, WordFinder finder )
}
static XP_Bool
findStartsWith( const DictionaryCtxt* dict, Tile* tiles, XP_U16 nTiles, EdgeArray* edges )
findStartsWith( const DictionaryCtxt* dict, const Tile* tiles, XP_U16 nTiles, EdgeArray* edges )
{
XP_Bool success = XP_TRUE;
array_edge* edge = dict_getTopEdge( dict );
edges->nEdges = 0;
while ( nTiles-- > 0 ) {
Tile tile = *tiles++;
@ -856,10 +861,52 @@ dict_countWords( const DictionaryCtxt* dict )
return count;
}
static DictIndex
placeWordClose( const DictionaryCtxt* dict, DictIndex position,
XP_U16 depth, const DictIndex* indices, const Tile* prefixes,
XP_U16 count, EdgeArray* result )
{
XP_S16 low = 0;
XP_S16 high = count - 1;
XP_S16 index = -1;
for ( ; ; ) {
if ( low > high ) {
break;
}
index = low + ( (high - low) / 2);
if ( position < indices[index] ) {
high = index - 1;
} else if ( indices[index+1] <= position) {
low = index + 1;
} else {
break;
}
}
/* DictIndex top = mid < count-1? indices[mid+1] : -1; */
/* XP_LOGF( "found %ld at %d, in range between %ld and %ld", position, */
/* mid, indices[mid], top ); */
/* Now we have the index immediately below the position we want. But we
may be better off starting with the next if it's closer. The last
index is a special case since we use lastWord rather than a prefix to
init */
if ( ( index + 1 < count )
&& (indices[index + 1] - position) < (position - indices[index]) ) {
++index;
}
XP_Bool success = findStartsWith( dict, &prefixes[depth*index], depth, result )
&& ( ISACCEPTING( dict, result->edges[result->nEdges-1] )
|| nextWord( dict, result ) );
XP_ASSERT( success );
return indices[index];
} /* placeWordClose */
static void
indexOne( const DictionaryCtxt* dict, XP_U16 depth, Tile* tiles,
DictIndex* indices, XP_U16* nextIndex,
XWStreamCtxt* stream, EdgeArray* prevEdges, DictIndex* prevIndex )
DictIndex* indices, Tile* prefixes, XP_U16* nextIndex,
EdgeArray* prevEdges, DictIndex* prevIndex )
{
EdgeArray curEdges = { .nEdges = 0 };
if ( findStartsWith( dict, tiles, depth, &curEdges ) ) {
@ -880,16 +927,11 @@ indexOne( const DictionaryCtxt* dict, XP_U16 depth, Tile* tiles,
}
}
}
if ( NULL != stream ) {
if ( 0 < *nextIndex ) {
stream_catString( stream, "\n" );
}
XP_UCHAR prefix[8];
(void)dict_tilesToString( dict, tiles, depth, prefix, VSIZE(prefix) );
stream_catString( stream, prefix );
indices[*nextIndex] = *prevIndex;
if ( NULL != prefixes ) {
XP_MEMCPY( prefixes + (*nextIndex * depth), tiles, depth );
}
indices[(*nextIndex)++] = *prevIndex;
++*nextIndex;
}
}
@ -897,25 +939,25 @@ static void
doOneDepth( const DictionaryCtxt* dict,
const Tile* allTiles, XP_U16 nTiles, Tile* prefix,
XP_U16 curDepth, XP_U16 maxDepth,
DictIndex* indices, XP_U16* nextEntry,
XWStreamCtxt* stream, EdgeArray* prevEdges, DictIndex* prevIndex )
DictIndex* indices, Tile* prefixes, XP_U16* nextEntry,
EdgeArray* prevEdges, DictIndex* prevIndex )
{
XP_U16 ii;
for ( ii = 0; ii < nTiles; ++ii ) {
prefix[curDepth] = allTiles[ii];
if ( curDepth + 1 == maxDepth ) {
indexOne( dict, maxDepth, prefix, indices, nextEntry,
stream, prevEdges, prevIndex );
indexOne( dict, maxDepth, prefix, indices, prefixes,
nextEntry, prevEdges, prevIndex);
} else {
doOneDepth( dict, allTiles, nTiles, prefix, curDepth+1, maxDepth,
indices, nextEntry, stream, prevEdges, prevIndex );
indices, prefixes, nextEntry, prevEdges, prevIndex );
}
}
}
XP_U16
dict_makeIndex( const DictionaryCtxt* dict, XP_U16 depth,
DictIndex* indices, XP_U16 count, XWStreamCtxt* stream )
DictIndex* indices, Tile* prefixes, XP_U16 count )
{
XP_ASSERT( depth < MAX_COLS );
XP_U16 ii, needCount, nTiles;
@ -951,12 +993,18 @@ dict_makeIndex( const DictionaryCtxt* dict, XP_U16 depth,
indicesToEdges( dict, &firstWord, &prevEdges );
doOneDepth( dict, allTiles, nFaces, prefix, 0, depth,
indices, &nextIndex, stream, &prevEdges, &prevIndex );
indices, prefixes, &nextIndex, &prevEdges, &prevIndex );
}
return nextIndex;
}
static void
initWord( const DictionaryCtxt* dict, DictWord* word )
{
word->wordCount = dict_getWordCount( dict );
}
XP_Bool
dict_firstWord( const DictionaryCtxt* dict, DictWord* word )
{
@ -966,8 +1014,7 @@ dict_firstWord( const DictionaryCtxt* dict, DictWord* word )
XP_Bool success = ISACCEPTING( dict, edges.edges[0] )
|| nextWord( dict, &edges );
if ( success ) {
word->wordCount = dict_getWordCount( dict );
initWord( dict, word );
edgesToIndices( dict, &edges, word );
word->index = 0;
}
@ -993,7 +1040,7 @@ dict_lastWord( const DictionaryCtxt* dict, DictWord* word )
XP_Bool success = lastEdges( dict, &edges );
if ( success ) {
word->wordCount = dict_getWordCount( dict );
initWord( dict, word );
edgesToIndices( dict, &edges, word );
word->index = word->wordCount - 1;
@ -1016,56 +1063,85 @@ dict_getPrevWord( const DictionaryCtxt* dict, DictWord* word )
sought. OR if we're father than necessary from what's sought, start over
at the closer end. Then move as many steps as necessary to reach it. */
XP_Bool
dict_getNthWord( const DictionaryCtxt* dict, DictWord* word, XP_U32 nn )
dict_getNthWord( const DictionaryCtxt* dict, DictWord* word, XP_U32 nn,
XP_U16 depth, DictIndex* indices, Tile* prefixes,
XP_U16 count )
{
XP_U32 wordCount;
XP_Bool validWord = 0 < word->nTiles;
XP_U32 ii;
if ( validWord ) { /* uninitialized */
wordCount = word->wordCount;
XP_ASSERT( wordCount == dict_getWordCount( dict ) );
} else {
wordCount = dict_getWordCount( dict );
}
XP_Bool success = nn < wordCount;
if ( success ) {
wordCount /= 2; /* mid-point */
/* If word's inited but farther from target than either endpoint,
better to start with an endpoint */
if ( validWord && XP_ABS( nn - word->index ) > wordCount ) {
/* XP_LOGF( "%s: clearing word: nn=%ld; word->index=%ld", */
/* __func__, nn, word->index ); */
validWord = XP_FALSE;
/* super common cases first */
success = XP_FALSE;
if ( validWord ) {
if ( word->index == nn ) {
success = XP_TRUE;
/* do nothing; we're done */
} else if ( word->index == nn + 1 ) {
success = dict_getNextWord( dict, word );
} else if ( word->index == nn - 1 ) {
success = dict_getPrevWord( dict, word );
}
}
if ( !validWord ) {
if ( nn >= wordCount ) {
dict_lastWord( dict, word );
if ( !success ) {
EdgeArray edges;
XP_U32 wordIndex;
if ( !!indices ) {
wordIndex = placeWordClose( dict, nn, depth, indices,
prefixes, count, &edges );
if ( !validWord ) {
initWord( dict, word );
}
} else {
dict_firstWord( dict, word );
}
}
wordCount /= 2; /* mid-point */
EdgeArray edges;
indicesToEdges( dict, word, &edges );
if ( word->index < nn ) {
for ( ii = nn - word->index; ii > 0; --ii ) {
if ( !nextWord( dict, &edges ) ) {
XP_ASSERT( 0 );
}
}
} else if ( word->index > nn ) {
for ( ii = word->index - nn; ii > 0; --ii ) {
if ( !prevWord( dict, &edges ) ) {
XP_ASSERT( 0 );
/* If word's inited but farther from target than either endpoint,
better to start with an endpoint */
if ( validWord && XP_ABS( nn - word->index ) > wordCount ) {
/* XP_LOGF( "%s: clearing word: nn=%ld; word->index=%ld", */
/* __func__, nn, word->index ); */
validWord = XP_FALSE;
}
if ( !validWord ) {
if ( nn >= wordCount ) {
dict_lastWord( dict, word );
} else {
dict_firstWord( dict, word );
}
}
indicesToEdges( dict, word, &edges );
wordIndex = word->index;
}
XP_U32 ii;
if ( wordIndex < nn ) {
for ( ii = nn - wordIndex; ii > 0; --ii ) {
if ( !nextWord( dict, &edges ) ) {
XP_ASSERT( 0 );
}
}
} else if ( wordIndex > nn ) {
for ( ii = wordIndex - nn; ii > 0; --ii ) {
if ( !prevWord( dict, &edges ) ) {
XP_ASSERT( 0 );
}
}
}
edgesToIndices( dict, &edges, word );
word->index = nn;
success = XP_TRUE;
}
edgesToIndices( dict, &edges, word );
word->index = nn;
}
return success;
}
} /* dict_getNthWord */
void
dict_wordToString( const DictionaryCtxt* dict, const DictWord* word,

View file

@ -210,7 +210,6 @@ void dict_splitFaces( DictionaryCtxt* dict, const XP_U8* bytes,
/* API for iterating over a dict */
typedef XP_U32 DictIndex;
#define NO_INDEX 0xFFFFFFFF
typedef struct _DictWord {
XP_U32 wordCount;
DictIndex index;
@ -220,14 +219,14 @@ typedef struct _DictWord {
XP_U32 dict_countWords( const DictionaryCtxt* dict );
XP_U16 dict_makeIndex( const DictionaryCtxt* dict, XP_U16 depth,
DictIndex* indices, XP_U16 count,
XWStreamCtxt* stream );
DictIndex* indices, Tile* prefixes, XP_U16 count );
XP_Bool dict_firstWord( const DictionaryCtxt* dict, DictWord* word );
XP_Bool dict_lastWord( const DictionaryCtxt* dict, DictWord* word );
XP_Bool dict_getNextWord( const DictionaryCtxt* dict, DictWord* word );
XP_Bool dict_getPrevWord( const DictionaryCtxt* dict, DictWord* word );
XP_Bool dict_getNthWord( const DictionaryCtxt* dict, DictWord* word,
XP_U32 nn );
XP_Bool dict_getNthWord( const DictionaryCtxt* dict, DictWord* word, XP_U32 nn,
XP_U16 depth, DictIndex* indices,
Tile* prefixes, XP_U16 count );
void dict_wordToString( const DictionaryCtxt* dict, const DictWord* word,
XP_UCHAR* buf, XP_U16 buflen );

View file

@ -1,4 +1,4 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
/* -*- compile-command: "make -j3 MEMDEBUG=TRUE"; -*- */
/*
* Copyright 2000-2009 by Eric House (xwords@eehouse.org). All rights
* reserved.
@ -24,11 +24,10 @@
#include "gtkask.h"
static void
button_event( GtkWidget* XP_UNUSED(widget), gpointer closure )
set_bool_and_quit( GtkWidget* XP_UNUSED(widget), gpointer closure )
{
XP_Bool* whichSet = (XP_Bool*)closure;
*whichSet = 1;
*whichSet = XP_TRUE;
gtk_main_quit();
} /* button_event */
@ -55,8 +54,9 @@ gtkletterask( const PickInfo* pi, const XP_UCHAR* name,
XP_S16 ii;
GtkWidget* button;
XP_UCHAR buf[64];
XP_Bool backedUp = XP_FALSE;
XP_MEMSET( results, 0, sizeof(results) );
XP_MEMSET( results, XP_FALSE, sizeof(results) );
vbox = gtk_vbox_new( FALSE, 0 );
@ -69,7 +69,7 @@ gtkletterask( const PickInfo* pi, const XP_UCHAR* name,
gtk_box_pack_start( GTK_BOX(hbox), button, FALSE, TRUE, 0 );
g_signal_connect( GTK_OBJECT(button), "clicked",
G_CALLBACK(button_event), &results[ii] );
G_CALLBACK(set_bool_and_quit), &results[ii] );
gtk_widget_show( button );
if ( ii+1 == nTiles || (ii % BUTTONS_PER_ROW == 0) ) {
@ -79,12 +79,20 @@ gtkletterask( const PickInfo* pi, const XP_UCHAR* name,
}
#ifdef FEATURE_TRAY_EDIT
button = gtk_button_new_with_label( "Just pick em!" );
hbox = gtk_hbox_new( FALSE, 0 );
button = gtk_button_new_with_label( "Just pick em!" );
g_signal_connect( GTK_OBJECT(button), "clicked",
G_CALLBACK(abort_button_event), NULL );
gtk_box_pack_start( GTK_BOX(hbox), button, FALSE, TRUE, 0 );
gtk_widget_show( button );
button = gtk_button_new_with_label( "Back up" );
g_signal_connect( GTK_OBJECT(button), "clicked",
G_CALLBACK(set_bool_and_quit), &backedUp );
gtk_box_pack_start( GTK_BOX(hbox), button, FALSE, TRUE, 0 );
gtk_widget_show( button );
gtk_widget_show( hbox );
gtk_box_pack_start( GTK_BOX(vbox), hbox, FALSE, TRUE, 0 );
#endif
@ -128,13 +136,17 @@ gtkletterask( const PickInfo* pi, const XP_UCHAR* name,
gtk_widget_destroy( dialog );
for ( ii = 0; ii < nTiles; ++ii ) {
if ( results[ii] ) {
break;
if ( backedUp ) {
ii = PICKER_BACKUP;
} else {
for ( ii = 0; ii < nTiles; ++ii ) {
if ( results[ii] ) {
break;
}
}
if ( ii == nTiles ) {
ii = PICKER_PICKALL;
}
}
if ( ii == nTiles ) {
ii = -1;
}
return ii;

View file

@ -893,34 +893,32 @@ tmp_noop_sigintterm( int XP_UNUSED(sig) )
}
#ifdef XWFEATURE_WALKDICT
#if 0
static char*
mkPrefix( const DictionaryCtxt* dict, int index, int depth, char* buf, int len )
static void
testGetNthWord( const DictionaryCtxt* dict, char** words,
XP_U16 depth, DictIndex* indices,
Tile* prefixes, XP_U16 nIndices )
{
Tile tiles[depth];
Tile blank;
XP_U16 nTiles = dict_numTileFaces( dict );
if ( dict_hasBlankTile( dict ) ) {
blank = dict_getBlankTile( dict );
--nTiles;
} else {
blank = -1;
}
int ii;
XP_U32 half = dict_getWordCount( dict ) / 2;
XP_UCHAR buf[64];
XP_U32 ii, jj;
DictWord word = {.nTiles = 0};
XP_U32 interval = 100;
for ( ii = depth-1; ii >= 0; --ii ) {
Tile tile = index % nTiles;
if ( -1 != blank && blank <= tile ) {
++tile;
for ( ii = 0, jj = half; ii < half; ii += interval, jj += interval ) {
if ( dict_getNthWord( dict, &word, ii, depth, indices, prefixes, nIndices ) ) {
dict_wordToString( dict, &word, buf, VSIZE(buf) );
XP_ASSERT( 0 == strcmp( buf, words[ii] ) );
} else {
XP_ASSERT( 0 );
}
if ( dict_getNthWord( dict, &word, jj, depth, indices, prefixes, nIndices ) ) {
dict_wordToString( dict, &word, buf, VSIZE(buf) );
XP_ASSERT( 0 == strcmp( buf, words[jj] ) );
} else {
XP_ASSERT( 0 );
}
tiles[ii] = tile;
index /= nTiles;
}
dict_tilesToString( dict, tiles, depth, buf, len );
return buf;
}
#endif
static void
walk_dict_test( const LaunchParams* params )
@ -981,64 +979,39 @@ walk_dict_test( const LaunchParams* params )
}
}
XP_ASSERT( count == jj );
fprintf( stderr, "finished comparing runs in both directions\n" );
XP_LOGF( "finished comparing runs in both directions\n" );
fprintf( stderr, "testing getNth\n" );
int ii;
for ( ii = 0 ; ii < 100; ++ii ) {
long index = XP_RANDOM() % count;
if ( dict_getNthWord( dict, &word, index ) ) {
XP_ASSERT( word.index == index );
XP_UCHAR buf[64];
dict_wordToString( dict, &word, buf, VSIZE(buf) );
XP_ASSERT( 0 == strcmp( buf, words[index] ) );
} else {
XP_ASSERT( 0 );
}
}
XP_LOGF( "testing getNth" );
testGetNthWord( dict, words, 0, NULL, NULL, 0 );
XP_U16 depth = 2;
DictIndex indices[26*26]; /* pow(26,depth) */
XWStreamCtxt* stream = mem_stream_make( MPPARM(params->util->mpool)
params->vtMgr,
NULL, CHANNEL_NONE, NULL );
XP_U16 nIndices = dict_makeIndex( dict, depth, indices, VSIZE(indices), stream );
const char* ptr = (char*)stream_getPtr( stream );
Tile prefixes[depth*26*26];
XP_U16 nIndices = dict_makeIndex( dict, depth, indices,
prefixes, VSIZE(indices) );
#if 0
for ( ii = 0; ii < nIndices; ++ii ) {
char* next = strstr( (char*)ptr, "\n" );
XP_ASSERT( !!next );
if ( next > ptr && indices[ii] != NO_INDEX ) {
if ( !dict_getNthWord( dict, &word, indices[ii] ) ) {
XP_ASSERT( 0 );
}
XP_ASSERT( word.index == indices[ii] );
XP_UCHAR buf1[64];
dict_wordToString( dict, &word, buf1, VSIZE(buf1) );
XP_UCHAR buf2[64] = {0};
if ( ii > 0 && dict_getNthWord( dict, &word, indices[ii]-1 ) ) {
dict_wordToString( dict, &word, buf2, VSIZE(buf2) );
}
char prfx[8];
snprintf( prfx, depth+1, "%s", ptr );
prfx[depth] = '\0';
fprintf( stderr,
"%d: index: %ld; prefix: %s; word: %s (prev: %s)\n",
ii, indices[ii], prfx, buf1, buf2 );
} else if ( next == ptr && indices[ii] == NO_INDEX ) {
} else {
if ( !dict_getNthWord( dict, &word, indices[ii] ) ) {
XP_ASSERT( 0 );
}
ptr = next + 1;
XP_ASSERT( word.index == indices[ii] );
XP_UCHAR buf1[64];
dict_wordToString( dict, &word, buf1, VSIZE(buf1) );
XP_UCHAR buf2[64] = {0};
if ( ii > 0 && dict_getNthWord( dict, &word, indices[ii]-1 ) ) {
dict_wordToString( dict, &word, buf2, VSIZE(buf2) );
}
char prfx[8];
dict_tilesToString( dict, &prefixes[depth*ii], depth, prfx, VSIZE(prfx) );
fprintf( stderr, "%d: index: %ld; prefix: %s; word: %s (prev: %s)\n",
ii, indices[ii], prfx, buf1, buf2 );
}
#endif
/* for ( ii = 0; ii < VSIZE(indices); ++ii ) { */
/* DictIndex index = indices[ii]; */
/* if ( NO_INDEX == index ) { */
/* continue; */
/* } */
/* catOnClose( stream, NULL ); */
stream_destroy( stream );
XP_LOGF( "testing getNth WITH INDEXING" );
testGetNthWord( dict, words, depth, indices, prefixes, nIndices );
XP_LOGF( "done" );
exit( 0 );
}
#else