mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-02-05 20:45:49 +01:00
add name button and store wordlist
As a p.o.c., load the built-in wordlist into storage once, and thereafter use it from there rather than as a file. Now it can go away and a wordlist for the user's locale be downloaded and stored instead.
This commit is contained in:
parent
c829017150
commit
2ab2f5642e
7 changed files with 131 additions and 46 deletions
|
@ -62,6 +62,7 @@
|
|||
|
||||
#define KEY_LAST_GID "cur_game"
|
||||
#define KEY_PLAYER_NAME "player_name"
|
||||
#define KEY_DICTS "dicts_3"
|
||||
#define KEY_GAME "game_data"
|
||||
#define KEY_NAME "game_name"
|
||||
#define KEY_NEXT_GAME "next_game"
|
||||
|
@ -89,6 +90,7 @@
|
|||
#define BUTTON_GAME_OPEN "Open Game"
|
||||
#define BUTTON_GAME_RENAME "Rename Game"
|
||||
#define BUTTON_GAME_DELETE "Delete Game"
|
||||
#define BUTTON_NAME "My Name"
|
||||
#define MAX_BUTTONS 20 /* not sure what's safe here */
|
||||
|
||||
typedef struct _NewGameParams {
|
||||
|
@ -471,6 +473,7 @@ onGameRanamed( void* closure, const char* newName )
|
|||
if ( !!newName ) {
|
||||
CAST_GS(GameState*, gs, closure);
|
||||
nameGame( gs, newName );
|
||||
show_name( newName );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -589,6 +592,28 @@ onDeleteConfirmed( void* closure, bool confirmed )
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
getPlayerName( Globals* globals, char* playerName, size_t buflen )
|
||||
{
|
||||
XP_U32 len = buflen;
|
||||
dutil_loadPtr( globals->dutil, NULL, KEY_PLAYER_NAME, NULL,
|
||||
playerName, &len );
|
||||
XP_LOGFF( "after: len: %d", len );
|
||||
if ( 0 == len ) { /* not found? */
|
||||
strcpy( playerName, "Player 1" );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
onPlayerNamed( void* closure, const char* name )
|
||||
{
|
||||
CAST_GLOB(Globals*, globals, closure);
|
||||
if ( !!name ) {
|
||||
dutil_storePtr( globals->dutil, NULL, KEY_PLAYER_NAME,
|
||||
name, 1 + strlen(name) );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
onDeviceButton( void* closure, const char* button )
|
||||
{
|
||||
|
@ -610,6 +635,11 @@ onDeviceButton( void* closure, const char* button )
|
|||
"\nThis action cannot be undone.",
|
||||
curGS->gameName );
|
||||
call_confirm( globals, msg, onDeleteConfirmed, curGS );
|
||||
} else if ( 0 == strcmp(button, BUTTON_NAME ) ) {
|
||||
char playerName[32];
|
||||
getPlayerName( globals, playerName, sizeof(playerName)-1 );
|
||||
call_get_string( "Set your (local) player name", playerName,
|
||||
onPlayerNamed, globals );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -643,6 +673,7 @@ updateDeviceButtons( Globals* globals )
|
|||
buttons[cur++] = BUTTON_GAME_RENAME;
|
||||
buttons[cur++] = BUTTON_GAME_DELETE;
|
||||
}
|
||||
buttons[cur++] = BUTTON_NAME;
|
||||
buttons[cur++] = NULL;
|
||||
|
||||
setButtons( BUTTONS_ID_DEVICE, buttons, onDeviceButton, globals );
|
||||
|
@ -669,6 +700,46 @@ onFocussed( void* closure, const char* ignored )
|
|||
/* } */
|
||||
}
|
||||
|
||||
static DictionaryCtxt*
|
||||
playLoadingDict( Globals* globals )
|
||||
{
|
||||
/* Looking at whether the storage system can hold a dict. Let's see if
|
||||
it's stored, and if it isn't store it. They try passing a ptr for
|
||||
making the actual dict from. */
|
||||
|
||||
XP_U32 len = 0;
|
||||
dutil_loadIndxPtr( globals->dutil, NULL, KEY_DICTS, DICTNAME, NULL, &len );
|
||||
if ( 0 == len ) {
|
||||
XP_LOGFF( "not found; storing now..." );
|
||||
XP_U32 dictLen;
|
||||
uint8_t* dictBytes = wasm_dictionary_load(MPPARM(globals->mpool)
|
||||
DICTNAME, &dictLen);
|
||||
|
||||
if ( !!dictBytes ) {
|
||||
XP_LOGFF( "loaded %d bytes of dict", dictLen );
|
||||
dutil_storeIndxPtr( globals->dutil, NULL, KEY_DICTS, DICTNAME,
|
||||
dictBytes, dictLen );
|
||||
XP_FREE( globals->mpool, dictBytes );
|
||||
}
|
||||
len = dictLen;
|
||||
} else {
|
||||
XP_LOGFF( "using stored wordlist of len %d", len );
|
||||
}
|
||||
|
||||
XP_U32 oldLen = len;
|
||||
XP_LOGFF( "oldLen: %d", oldLen );
|
||||
uint8_t* bytes = XP_MALLOC( globals->mpool, len );
|
||||
dutil_loadIndxPtr( globals->dutil, NULL, KEY_DICTS, DICTNAME,
|
||||
bytes, &len );
|
||||
XP_ASSERT( len == oldLen );
|
||||
|
||||
DictionaryCtxt* dict =
|
||||
wasm_dictionary_make( MPPARM(globals->mpool) NULL,
|
||||
globals, DICTNAME, false, bytes );
|
||||
LOG_RETURNF( "%p", dict );
|
||||
return dict;
|
||||
}
|
||||
|
||||
static void
|
||||
initDeviceGlobals( Globals* globals )
|
||||
{
|
||||
|
@ -687,8 +758,8 @@ initDeviceGlobals( Globals* globals )
|
|||
globals->vtMgr = make_vtablemgr( MPPARM_NOCOMMA(globals->mpool) );
|
||||
globals->dutil = wasm_dutil_make( MPPARM(globals->mpool) globals->vtMgr, globals );
|
||||
globals->dictMgr = dmgr_make( MPPARM_NOCOMMA(globals->mpool) );
|
||||
globals->dict = wasm_dictionary_make( MPPARM(globals->mpool) NULL,
|
||||
globals, DICTNAME, true );
|
||||
|
||||
globals->dict = playLoadingDict( globals );
|
||||
|
||||
dict_ref( globals->dict, NULL );
|
||||
|
||||
|
@ -750,34 +821,6 @@ startGame( GameState* gs, const char* name )
|
|||
LOG_RETURN_VOID();
|
||||
}
|
||||
|
||||
typedef struct _AskReplaceState {
|
||||
Globals* globals;
|
||||
NetLaunchInfo invite;
|
||||
} AskReplaceState;
|
||||
|
||||
static void
|
||||
onPlayerNamed( void* closure, const char* name )
|
||||
{
|
||||
CAST_GS(GameState*, gs, closure);
|
||||
if ( !!name ) {
|
||||
dutil_storePtr( gs->globals->dutil, NULL, KEY_PLAYER_NAME,
|
||||
name, 1 + strlen(name) );
|
||||
startGame( gs, name );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
getPlayerName( Globals* globals, char* playerName, size_t buflen )
|
||||
{
|
||||
XP_U32 len = buflen;
|
||||
dutil_loadPtr( globals->dutil, NULL, KEY_PLAYER_NAME, NULL,
|
||||
playerName, &len );
|
||||
XP_LOGFF( "after: len: %d", len );
|
||||
if ( 0 == len ) { /* not found? */
|
||||
strcpy( playerName, "Player 1" );
|
||||
}
|
||||
}
|
||||
|
||||
static GameState*
|
||||
newFromInvite( Globals* globals, const NetLaunchInfo* invite )
|
||||
{
|
||||
|
@ -1051,8 +1094,6 @@ main_onGameMessage( Globals* globals, XP_U32 gameID,
|
|||
if ( game_receiveMessage( &gs->game, NULL, stream, from ) ) {
|
||||
updateScreen( gs, true );
|
||||
}
|
||||
if ( gs != getCurGame(gs->globals) ) {
|
||||
}
|
||||
} else {
|
||||
char msg[128];
|
||||
snprintf( msg, sizeof(msg), "Dropping move for deleted game (id: %X/%d)",
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
.emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
|
||||
textarea.emscripten { font-family: monospace; width: 80%; }
|
||||
body.centered { text-align: center; }
|
||||
table.centered {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
div.emscripten { text-align: center; }
|
||||
div.emscripten_border { border: 1px solid black; }
|
||||
/* the canvas *must not* have any border or padding, or mouse coords will be wrong */
|
||||
|
@ -90,8 +94,11 @@
|
|||
<hr/>
|
||||
<div class='buttonRow' id="device_buttons"></div>
|
||||
<hr/>
|
||||
<div><span>MQTT Dev ID:</span><span id="mqtt_span"></span></div>
|
||||
<div><span>MQTT Status:</span><span id="mqtt_status">Unconnected</span></div>
|
||||
<table class='centered'>
|
||||
<tr><td>MQTT Dev ID:</td><td id="mqtt_span"></td></tr>
|
||||
<tr><td>MQTT Status:</td><td id="mqtt_status">Unconnected</td></tr>
|
||||
<tr><td>Storage used:</td><td id="storage_used">0</td></tr>
|
||||
</table>
|
||||
<hr/>
|
||||
<!-- Remove until I figure out how to this works
|
||||
<div class="emscripten">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- compile-command: "cd ../wasm && make main.html -j3"; -*- */
|
||||
/* -*- compile-command: "cd ../wasm && make MEMDEBUG=TRUE install -j3"; -*- */
|
||||
/*
|
||||
* Copyright 2021 by Eric House (xwords@eehouse.org). All rights reserved.
|
||||
*
|
||||
|
@ -49,7 +49,8 @@ getShortName( const DictionaryCtxt* dict )
|
|||
}
|
||||
|
||||
static XP_Bool
|
||||
initFromDictFile( WasmDictionaryCtxt* dctx, const char* fileName )
|
||||
initFromDictFile( WasmDictionaryCtxt* dctx, const char* fileName,
|
||||
uint8_t* dictBase )
|
||||
{
|
||||
XP_Bool formatOk = XP_TRUE;
|
||||
size_t dictLength;
|
||||
|
@ -71,7 +72,9 @@ initFromDictFile( WasmDictionaryCtxt* dctx, const char* fileName )
|
|||
{
|
||||
FILE* dictF = fopen( path, "r" );
|
||||
XP_ASSERT( !!dictF );
|
||||
if ( dctx->useMMap ) {
|
||||
if ( !!dictBase ) {
|
||||
dctx->dictBase = dictBase;
|
||||
} else if ( dctx->useMMap ) {
|
||||
dctx->dictBase = mmap( NULL, dctx->dictLength, PROT_READ,
|
||||
MAP_PRIVATE, fileno(dictF), 0 );
|
||||
} else {
|
||||
|
@ -189,7 +192,8 @@ wasm_dictionary_destroy( DictionaryCtxt* dict, XWEnv xwe )
|
|||
|
||||
DictionaryCtxt*
|
||||
wasm_dictionary_make( MPFORMAL XWEnv xwe, Globals* globals,
|
||||
const char* dictFileName, bool useMMap )
|
||||
const char* dictFileName, bool useMMap,
|
||||
uint8_t* base )
|
||||
{
|
||||
WasmDictionaryCtxt* result = NULL;
|
||||
if ( !!dictFileName ) {
|
||||
|
@ -207,7 +211,7 @@ wasm_dictionary_make( MPFORMAL XWEnv xwe, Globals* globals,
|
|||
result->useMMap = useMMap;
|
||||
|
||||
if ( !!dictFileName ) {
|
||||
XP_Bool success = initFromDictFile( result, dictFileName );
|
||||
XP_Bool success = initFromDictFile( result, dictFileName, base );
|
||||
if ( success ) {
|
||||
result->super.func_dict_getShortName = getShortName;
|
||||
setBlankTile( &result->super );
|
||||
|
@ -227,6 +231,25 @@ wasm_dictionary_make( MPFORMAL XWEnv xwe, Globals* globals,
|
|||
return &result->super;
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
wasm_dictionary_load(MPFORMAL const char* dictFileName, XP_U32* len )
|
||||
{
|
||||
uint8_t* result = NULL;
|
||||
*len = 0;
|
||||
struct stat statbuf;
|
||||
if ( 0 == stat( dictFileName, &statbuf ) && 0 != statbuf.st_size ) {
|
||||
result = XP_MALLOC( mpool, statbuf.st_size );
|
||||
FILE* dictF = fopen( dictFileName, "r" );
|
||||
size_t nRead = fread( result, 1, statbuf.st_size, dictF );
|
||||
XP_ASSERT( nRead == statbuf.st_size );
|
||||
fclose( dictF );
|
||||
*len = statbuf.st_size;
|
||||
XP_LOGFF( "loaded %d bytes", statbuf.st_size );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
dict_splitFaces( DictionaryCtxt* dict, XWEnv xwe, const XP_U8* utf8,
|
||||
XP_U16 nBytes, XP_U16 nFaces )
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include "main.h"
|
||||
|
||||
DictionaryCtxt* wasm_dictionary_make( MPFORMAL XWEnv xwe, Globals* globals,
|
||||
const char* dictFileName, bool useMMap );
|
||||
const char* dictFileName, bool useMMap,
|
||||
uint8_t* base );
|
||||
uint8_t* wasm_dictionary_load(MPFORMAL const char* dictFileName, XP_U32* len );
|
||||
|
||||
#endif
|
||||
|
|
|
@ -243,27 +243,29 @@ static void
|
|||
wasm_dutil_loadPtr( XW_DUtilCtxt* duc, XWEnv xwe, const XP_UCHAR* key,
|
||||
const XP_UCHAR* keySuffix, void* data, XP_U32* lenp )
|
||||
{
|
||||
// XP_LOGFF( "(key: %s)", key );
|
||||
// XP_LOGFF( "(key: %s, len: %d)", key, *lenp );
|
||||
MAKE_PREFIX(fullKey, key);
|
||||
|
||||
size_t len;
|
||||
get_stored_value(fullKey, NULL, &len);
|
||||
|
||||
char val[len];
|
||||
char* val = XP_MALLOC( duc->mpool, len );
|
||||
if ( get_stored_value( fullKey, val, &len ) ) {
|
||||
// XP_LOGFF( "get_stored_value(%s) => %s", fullKey, val );
|
||||
len = XP_STRLEN(val);
|
||||
XP_ASSERT( (len % 2) == 0 );
|
||||
XP_U8 decodeBuf[len/2];
|
||||
len = VSIZE(decodeBuf);
|
||||
XP_U8* decodeBuf = XP_MALLOC( duc->mpool, len/2 );
|
||||
len = len/2;
|
||||
if ( len <= *lenp ) {
|
||||
base16Decode( decodeBuf, len, val );
|
||||
XP_MEMCPY( data, decodeBuf, len );
|
||||
}
|
||||
*lenp = len;
|
||||
XP_FREE( duc->mpool, decodeBuf );
|
||||
} else {
|
||||
*lenp = 0; /* signal failure */
|
||||
}
|
||||
XP_FREE( duc->mpool, val );
|
||||
// XP_LOGFF("(%s)=> len: %d", fullKey, *lenp );
|
||||
}
|
||||
|
||||
|
@ -271,10 +273,11 @@ static void
|
|||
wasm_dutil_storePtr( XW_DUtilCtxt* duc, XWEnv xwe, const XP_UCHAR* key,
|
||||
const void* data, XP_U32 len )
|
||||
{
|
||||
XP_UCHAR out[len*2+1];
|
||||
XP_UCHAR* out = XP_MALLOC( duc->mpool, len*2+1 );
|
||||
base16Encode( data, len, out, sizeof(out) );
|
||||
MAKE_PREFIX(fullKey, key);
|
||||
set_stored_value( fullKey, out );
|
||||
XP_FREE( duc->mpool, out );
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -411,7 +411,8 @@ static DictionaryCtxt*
|
|||
wasm_util_makeEmptyDict( XW_UtilCtxt* uc, XWEnv xwe )
|
||||
{
|
||||
LOG_FUNC(); /* firing */
|
||||
return wasm_dictionary_make( MPPARM(uc->mpool) NULL, uc->closure, NULL, false );
|
||||
return wasm_dictionary_make( MPPARM(uc->mpool) NULL, uc->closure,
|
||||
NULL, false, NULL );
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -136,6 +136,14 @@ function onHaveDevID(closure, devid, gitrev, now, noTabProc, focusProc) {
|
|||
onFailure: function() { alert('onFailure'); },
|
||||
});
|
||||
|
||||
// let's sum up storage
|
||||
let total = 0;
|
||||
for (let ii = 0; ii < localStorage.length; ++ii ) {
|
||||
let key = localStorage.key(ii);
|
||||
let val = localStorage.getItem(key);
|
||||
total += key.length + val.length;
|
||||
}
|
||||
document.getElementById("storage_used").textContent=total + 'b';
|
||||
}
|
||||
|
||||
function mqttSend( topic, ptr ) {
|
||||
|
|
Loading…
Add table
Reference in a new issue