diff --git a/xwords4/wince/cemain.c b/xwords4/wince/cemain.c index af4e64a89..d3ea47dd7 100755 --- a/xwords4/wince/cemain.c +++ b/xwords4/wince/cemain.c @@ -934,7 +934,7 @@ ceInitAndStartBoard( CEAppGlobals* globals, XP_Bool newGame, } XP_ASSERT( !!globals->game.board ); - ceSizeIfFullscreen( globals, globals->hWnd ); + (void)ceSizeIfFullscreen( globals, globals->hWnd ); (void)cePositionBoard( globals ); board_invalAll( globals->game.board ); @@ -1092,7 +1092,7 @@ ceLoadPrefs( CEAppGlobals* globals ) XP_U32 bytesRead; if ( ReadFile( fileH, &tmpPrefs, sizeof(tmpPrefs), &bytesRead, NULL ) ) { - XP_ASSERT( tmpPrefs.versionFlags == CUR_CE_PREFS_FLAGS ); + XP_ASSERT( tmpPrefs.versionFlags==CUR_CE_PREFS_FLAGS ); result = XP_TRUE; } } @@ -1455,17 +1455,30 @@ InitInstance(HINSTANCE hInstance, int nCmdShow replaceStringIfDifferent( globals->mpool, &globals->langFileName, dll ); } #endif - + HINSTANCE inst = NULL; if ( !!globals->langFileName && !globals->locInst ) { - HINSTANCE inst = ceLoadResFile( globals->langFileName ); - if ( !!inst ) { - globals->locInst = inst; - } else { + inst = ceLoadResFile( globals->langFileName ); + if ( !inst ) { /* load didn't work */ XP_FREE( globals->mpool, globals->langFileName ); globals->langFileName = NULL; } } - if ( !globals->locInst ) { + + /* Failed to load, or user hadn't chosen one */ + if ( !inst && !globals->appPrefs.resChosen ) { + XP_UCHAR buf[MAX_PATH]; + if ( ceGetOneResFile( buf, VSIZE(buf) ) ) { + inst = ceLoadResFile( buf ); + if ( !!inst ) { + replaceStringIfDifferent( globals->mpool, + &globals->langFileName, buf ); + } + } + } + + if ( !!inst ) { + globals->locInst = inst; + } else { globals->locInst = globals->hInst; } @@ -1829,6 +1842,7 @@ ceDoNewGame( CEAppGlobals* globals, GIShow showWhat ) if ( results.langChanged ) { ceWarnLangChange( globals ); + globals->appPrefs.resChosen = XP_TRUE; } #if defined XWFEATURE_RELAY || defined XWFEATURE_BLUETOOTH @@ -1951,6 +1965,7 @@ ceDoPrefsDlg( CEAppGlobals* globals ) if ( langChanged ) { ceWarnLangChange( globals ); + globals->appPrefs.resChosen = XP_TRUE; } /* need to reflect vars set in state into globals, and update/inval @@ -2433,7 +2448,7 @@ ceToggleFullScreen( CEAppGlobals* globals ) { globals->appPrefs.fullScreen = !globals->appPrefs.fullScreen; - ceSizeIfFullscreen( globals, globals->hWnd ); + (void)ceSizeIfFullscreen( globals, globals->hWnd ); (void)cePositionBoard( globals ); } /* ceToggleFullScreen */ diff --git a/xwords4/wince/cemain.h b/xwords4/wince/cemain.h index 19f96fc29..753a4a82f 100755 --- a/xwords4/wince/cemain.h +++ b/xwords4/wince/cemain.h @@ -107,6 +107,7 @@ typedef struct CEAppPrefs { COLORREF colors[CE_NUM_COLORS]; XP_Bool showColors; XP_Bool fullScreen; + XP_Bool resChosen; } CEAppPrefs; enum { OWNED_RECT_LEFT diff --git a/xwords4/wince/ceresstr.c b/xwords4/wince/ceresstr.c index 44fb3acf3..15f69c1a0 100644 --- a/xwords4/wince/ceresstr.c +++ b/xwords4/wince/ceresstr.c @@ -199,12 +199,12 @@ typedef struct _DllSelState { } DllSelState; static void -copyWideStr( CEAppGlobals* XP_UNUSED_DBG(globals), const wchar_t* str, - wchar_t** loc ) +copyWideStr( CEAppGlobals* XP_UNUSED_DBG(globals), + wchar_t** dest, const wchar_t* src ) { - XP_U16 len = 1 + wcslen( str ); - *loc = XP_MALLOC( globals->mpool, len * sizeof(**loc) ); - wcscpy( *loc, str ); + XP_U16 len = 1 + wcslen( src ); + *dest = XP_MALLOC( globals->mpool, len * sizeof(**dest) ); + wcscpy( *dest, src ); } static XP_U16 @@ -221,30 +221,21 @@ getDLLVersion( HINSTANCE hinst ) return version; } -/* Iterate through .dll files listing the name of any that has one. Pair with - * file from which it came since that's what we'll return. - */ -static void -listDlls( DllSelState* state ) -{ - HANDLE fileH; - HWND hDlg = state->dlgHdr.hDlg; - WIN32_FIND_DATA data; - CEAppGlobals* globals = state->dlgHdr.globals; - XP_U16 nItems = 0; - XP_S16 selIndex = 0; /* default to built-in */ - wchar_t name[64]; +typedef XP_Bool (*DllCbk)( const WIN32_FIND_DATA* data, const wchar_t* name, + void* closure ); - LoadString( globals->hInst, IDS_LANGUAGE_NAME, name, VSIZE(name) ); - copyWideStr( globals, name, &state->names[nItems++] ); - (void)SendDlgItemMessage( hDlg, state->dllListID, ADDSTRING(globals), - 0, (LPARAM)name ); +static void +for_each_dll( DllCbk cbk, void* closure ) +{ + wchar_t name[64]; + HANDLE fileH; + WIN32_FIND_DATA data; + XP_MEMSET( &data, 0, sizeof(data) ); wchar_t path[MAX_PATH]; ceGetExeDir( path, VSIZE(path) ); wcscat( path, L"\\xwords4*.dll" ); - XP_MEMSET( &data, 0, sizeof(data) ); fileH = FindFirstFile( path, &data ); while ( fileH != INVALID_HANDLE_VALUE ) { @@ -253,20 +244,10 @@ listDlls( DllSelState* state ) if ( CUR_DLL_VERSION != getDLLVersion( hinst ) ) { /* do nothing; wrong version (or just not our .dll) */ } else if ( LoadString( hinst, IDS_LANGUAGE_NAME, - name, VSIZE(name) ) ) { - (void)SendDlgItemMessage( hDlg, state->dllListID, - ADDSTRING(globals), - 0, (LPARAM)name ); - copyWideStr( globals, name, &state->names[nItems] ); - copyWideStr( globals, data.cFileName, &state->files[nItems] ); - - if ( !!state->curFile ) { - if ( !wcscmp( data.cFileName, state->curFile ) ) { - selIndex = nItems; - } + name, VSIZE(name) ) ) { + if ( !(*cbk)( &data, name, closure ) ) { + break; } - - ++nItems; } else { XP_LOGF( "IDS_LANGUAGE_NAME not found in %ls", data.cFileName ); @@ -277,18 +258,72 @@ listDlls( DllSelState* state ) XP_LOGF( "Unable to open" ); } - if ( nItems >= VSIZE(state->names) ) { - break; - } else if ( !FindNextFile( fileH, &data ) ) { + if ( !FindNextFile( fileH, &data ) ) { XP_ASSERT( GetLastError() == ERROR_NO_MORE_FILES ); break; } } - SendDlgItemMessage( hDlg, state->dllListID, SETCURSEL(globals), - selIndex, 0L ); +} /* for_each_dll */ - state->nItems = nItems; - state->initialSel = selIndex; +typedef struct _ListingData { + DllSelState* state; + CEAppGlobals* globals; + XP_U16 nItems; + XP_S16 selIndex; +} ListingData; + +static XP_Bool +addToListCB( const WIN32_FIND_DATA* data, const wchar_t* name, void* closure ) +{ + ListingData* ld = (ListingData*)closure; + + (void)SendDlgItemMessage( ld->state->dlgHdr.hDlg, ld->state->dllListID, + ADDSTRING(ld->globals), 0, (LPARAM)name ); + + copyWideStr( ld->globals, &ld->state->names[ld->nItems], name ); + copyWideStr( ld->globals, &ld->state->files[ld->nItems], data->cFileName ); + + if ( !!ld->state->curFile ) { + if ( !wcscmp( data->cFileName, ld->state->curFile ) ) { + ld->selIndex = ld->nItems; + } + } + + ++ld->nItems; + + XP_Bool cont = ld->nItems < VSIZE(ld->state->names); + return cont; +} + + +/* Iterate through .dll files listing the name of any that has one. Pair with + * file from which it came since that's what we'll return. + */ +static void +listDlls( DllSelState* state ) +{ + HWND hDlg = state->dlgHdr.hDlg; + CEAppGlobals* globals = state->dlgHdr.globals; + wchar_t name[64]; + + ListingData ld = { + .globals = globals, + .state = state, + .nItems = 0, + .selIndex = 0 + }; + + LoadString( globals->hInst, IDS_LANGUAGE_NAME, name, VSIZE(name) ); + copyWideStr( globals, &state->names[ld.nItems++], name ); + (void)SendDlgItemMessage( hDlg, state->dllListID, ADDSTRING(globals), + 0, (LPARAM)name ); + + for_each_dll( addToListCB, &ld ); + SendDlgItemMessage( hDlg, state->dllListID, SETCURSEL(globals), + ld.selIndex, 0L ); + + state->nItems = ld.nItems; + state->initialSel = ld.selIndex; } /* listDlls */ static void @@ -374,6 +409,39 @@ DllSelDlg( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) return result; } /* DllSelDlg */ +typedef struct _FindOneData { + XP_UCHAR* buf; + XP_U16 bufLen; + XP_Bool called; +} FindOneData; + + +static XP_Bool +findFirstCB( const WIN32_FIND_DATA* data, const wchar_t* XP_UNUSED(name), + void* closure ) +{ + FindOneData* fd = (FindOneData*)closure; + + (void)WideCharToMultiByte( CP_ACP, 0, data->cFileName, -1, + fd->buf, fd->bufLen, NULL, NULL ); + + fd->called = XP_TRUE; + return XP_FALSE; /* don't continue */ +} + +/* Pick the first .dll found, if any */ +XP_Bool +ceGetOneResFile( XP_UCHAR* buf, XP_U16 bufLen ) +{ + FindOneData fod = { + .buf = buf, + .bufLen = bufLen, + .called = XP_FALSE, + }; + for_each_dll( findFirstCB, &fod ); + return fod.called; +} + /* ceChooseResFile: List all the available .rc files and return if user * chooses one different from the one passed in. */ @@ -404,4 +472,4 @@ ceChooseResFile( HWND hwnd, CEAppGlobals* globals, const XP_UCHAR* curFileName, LOG_RETURNF( "%s", buf ); return !state.cancelled; -} +} /* ceChooseResFile */ diff --git a/xwords4/wince/ceresstr.h b/xwords4/wince/ceresstr.h index 1ae7c1e89..3349ac670 100644 --- a/xwords4/wince/ceresstr.h +++ b/xwords4/wince/ceresstr.h @@ -27,6 +27,8 @@ void ceCloseResFile( HINSTANCE inst ); XP_Bool ceChooseResFile( HWND hwnd, CEAppGlobals* globals, const XP_UCHAR* curFileName, XP_UCHAR* buf, XP_U16 bufLen ); +/* pick some random file, assuming there's only one */ +XP_Bool ceGetOneResFile( XP_UCHAR* buf, XP_U16 bufLen ); const XP_UCHAR* ceGetResString( CEAppGlobals* globals, XP_U16 resID ); const wchar_t* ceGetResStringL( CEAppGlobals* globals, XP_U16 resID );