diff --git a/xwords4/wasm/main.c b/xwords4/wasm/main.c index b85d680c1..c326add01 100644 --- a/xwords4/wasm/main.c +++ b/xwords4/wasm/main.c @@ -93,6 +93,7 @@ typedef struct _NewGameParams { bool isRobotNotRemote; bool hintsNotAllowed; + const char* lc; } NewGameParams; static void updateScreen( GameState* gs, bool doSave ); @@ -221,10 +222,19 @@ EM_JS(void, setButtons, (const char* id, const char** bstrs, setDivButtons(UTF8ToString(id), buttons, proc, closure); }); -EM_JS(void, callNewGame, (const char* msg, void* closure), { - let jsmsg = UTF8ToString(msg); - nbGetNewGame(closure, jsmsg); - }); +EM_JS(void, js_callNewGame, (const char* msg, void* closure, + char** langs, int nLangs), { + let jsmsg = UTF8ToString(msg); + + let jlangs = []; + for ( let ii = 0; ii < nLangs; ++ii ) { + const mem = HEAP32[(langs + (ii * 4)) >> 2]; + let str = UTF8ToString(mem); + console.log('pushing ' + str); + jlangs.push(str); + } + nbGetNewGame(closure, jsmsg, jlangs); + }); typedef struct _ConfirmState { Globals* globals; @@ -647,13 +657,40 @@ onPlayerNamed( void* closure, const char* name ) } } +typedef struct _NewGameState { + Globals* globals; + char* langs[16]; + int nLangs; +} NewGameState; + +static XP_Bool +onOneLang( void* closure, const XP_UCHAR* keys[] ) +{ + NewGameState* ngs = (NewGameState*)closure; + replaceStringIfDifferent( ngs->globals->mpool, &ngs->langs[ngs->nLangs], keys[1] ); + XP_LOGFF( "set langs[%d] %s", ngs->nLangs, ngs->langs[ngs->nLangs] ); + ++ngs->nLangs; + XP_ASSERT( ngs->nLangs < VSIZE(ngs->langs)); + return true; +} + +static void +callNewGame( Globals* globals ) +{ + NewGameState ngs = {.globals = globals}; + const XP_UCHAR* keys[] = {KEY_DICTS, KEY_WILDCARD, NULL}; + dutil_forEach( globals->dutil, NULL, keys, onOneLang, &ngs ); + + js_callNewGame("Configure your new game", globals, ngs.langs, ngs.nLangs); +} + static void onDeviceButton( void* closure, const char* button ) { CAST_GLOB(Globals*, globals, closure); XP_LOGFF( "(button=%s)", button ); if ( 0 == strcmp(button, BUTTON_GAME_NEW) ) { - callNewGame("Configure your new game", globals); + callNewGame(globals); } else if ( 0 == strcmp(button, BUTTON_GAME_OPEN) ) { pickGame( globals ); } else if ( 0 == strcmp(button, BUTTON_GAME_RENAME ) ) { @@ -1108,11 +1145,11 @@ onOneDict( void* closure, const XP_UCHAR* keys[] ) } static DictionaryCtxt* -loadAnyDict( Globals* globals ) +loadAnyDict( Globals* globals, const char* lc ) { FindOneState fos = {.globals = globals, }; - const XP_UCHAR* keys[] = {KEY_DICTS, KEY_WILDCARD, KEY_WILDCARD, NULL}; + const XP_UCHAR* keys[] = {KEY_DICTS, lc, KEY_WILDCARD, NULL}; dutil_forEach( globals->dutil, NULL, keys, onOneDict, &fos ); LOG_RETURNF( "%p", fos.dict ); return fos.dict; @@ -1140,7 +1177,8 @@ loadAndDraw( Globals* globals, const NetLaunchInfo* invite, } if ( !gs ) { - DictionaryCtxt* dict = loadAnyDict( globals ); + const char* lc = NULL == params ? "en" : params->lc; + DictionaryCtxt* dict = loadAnyDict( globals, lc ); if ( !!dict ) { char playerName[32]; getPlayerName( globals, playerName, sizeof(playerName) ); @@ -1734,13 +1772,14 @@ cbckBinary( BinProc proc, void* closure, int len, const uint8_t* msg ) } void -onNewGame( void* closure, bool opponentIsRobot ) +onNewGame( void* closure, bool opponentIsRobot, const char* lc ) { Globals* globals = (Globals*)closure; - XP_LOGFF( "isRobot: %d", opponentIsRobot ); + XP_LOGFF( "isRobot: %d; lc: %s", opponentIsRobot, lc ); - NewGameParams ngp = {0}; - ngp.isRobotNotRemote = opponentIsRobot; + NewGameParams ngp = { .isRobotNotRemote = opponentIsRobot, + .lc = lc, + }; loadAndDraw( globals, NULL, NULL, &ngp ); updateDeviceButtons( globals ); } diff --git a/xwords4/wasm/xwutils.js b/xwords4/wasm/xwutils.js index c3df4aafa..ab5e9213a 100644 --- a/xwords4/wasm/xwutils.js +++ b/xwords4/wasm/xwutils.js @@ -333,8 +333,12 @@ function newRadio(txt, id, proc) { return span; } -function nbGetNewGame(closure, msg) { - const dlg = newDlgWMsg('Is your opponent a robot or someone you will invite?'); +function nbGetNewGame(closure, msg, langs) { + const dlg = newDlgWMsg(msg); + + const explDiv = document.createElement('div'); + dlg.appendChild( explDiv ); + explDiv.textContent = 'Is your opponent a robot or someone you will invite?'; const radioDiv = document.createElement('div'); dlg.appendChild( radioDiv ); @@ -342,10 +346,24 @@ function nbGetNewGame(closure, msg) { radioDiv.appendChild(newRadio('Robot', 'newgame', function() {robotSet[0] = true;})); radioDiv.appendChild(newRadio('Remote player', 'newgame', function() {robotSet[0] = false;})); + let chosenLang = [langs[0]]; + if ( 1 < langs.length ) { + const langsExplDiv = document.createElement('div'); + dlg.appendChild( langsExplDiv ); + langsExplDiv.textContent = "Choose your game language"; + const langsDiv = document.createElement('div'); + dlg.appendChild( langsDiv ); + for ( let ii = 0; ii < langs.length; ++ii ) { + let langName = langs[ii]; + console.log('adding radio for ' + langName); + langsDiv.appendChild(newRadio(langName, 'lang', function() {chosenLang[0] = langName;})); + } + } + const butProc = function(indx) { if ( indx === 1 && null !== robotSet[0]) { - const types = ['number', 'boolean']; - const params = [closure, robotSet[0]]; + const types = ['number', 'boolean', 'string']; + const params = [closure, robotSet[0], chosenLang[0]]; Module.ccall('onNewGame', null, types, params); } dlg.parentNode.removeChild(dlg);