Add dialog for choosing localization .dll; save choice in prefs and open on boot.

This commit is contained in:
ehouse 2009-04-19 17:33:39 +00:00
parent a7bf9f611d
commit 481e2acb92
9 changed files with 299 additions and 38 deletions

View file

@ -663,32 +663,6 @@ locateOneDir( MPFORMAL wchar_t* path, OnePathCB cb, void* ctxt, XP_U16 nSought,
return done;
} /* locateOneDir */
static XP_Bool
getDictDir( wchar_t* buf, XP_U16 bufLen )
{
/* I wanted to use SHGetKnownFolderPath to search in \\Program
Files\\Crosswords, but perhaps it's better to search in the directory
in which the app is located. If I get CAB files working for
Smartphone, then that directory will be \\Program Files\\Crosswords.
But if users have to install files using the File Explorer it'll be
easier for them if all that's required is that the app and dictionaries
be in the same place. GetModuleFileName() supports both.
*/
DWORD nChars = GetModuleFileName( NULL, buf, bufLen );
XP_Bool success = nChars < bufLen;
if ( success ) {
wchar_t* lastSlash = wcsrchr( buf, '\\' );
if ( !!lastSlash ) {
*lastSlash = 0;
}
}
/* SHGetSpecialFolderPath(NULL,NULL,0,FALSE); */
return success;
} /* getDictDir */
XP_U16
ceLocateNDicts( CEAppGlobals* globals, XP_U16 nSought, OnePathCB cb,
void* ctxt )
@ -696,7 +670,7 @@ ceLocateNDicts( CEAppGlobals* globals, XP_U16 nSought, OnePathCB cb,
XP_U16 nFound = 0;
wchar_t path[CE_MAX_PATH_LEN+1];
if ( getDictDir( path, VSIZE(path) ) ) {
if ( ceGetExeDir( path, VSIZE(path) ) ) {
locateOneDir( MPPARM(globals->mpool) path, cb, ctxt, nSought, &nFound );
}

View file

@ -262,7 +262,7 @@ WinMain( HINSTANCE hInstance,
#ifndef _WIN32_WCE
XP_U16 width = 320, height = 320;
char dll[MAX_PATH];
char dll[MAX_PATH] = {0};
parseCmdLine( lpCmdLine, &width, &height, dll );
#endif
@ -1354,18 +1354,13 @@ InitInstance(HINSTANCE hInstance, int nCmdShow
#ifndef _WIN32_WCE
srand( time(NULL) );
#endif
/* Was a language file named in preferences? If so, and if none was
provided on the cmdline, load it (if it exists; if it doesn't, act as
if none set). */
#ifndef _WIN32_WCE
if ( !!dll ) {
if ( !!dll && !!dll[0] ) {
replaceStringIfDifferent( globals->mpool, &globals->langFileName, dll );
}
#else
/* This french hard-coding thing is temporary! */
replaceStringIfDifferent( globals->mpool, &globals->langFileName, "xwords4_french.dll" );
#endif
if ( !!globals->langFileName && !globals->locInst ) {
@ -1998,6 +1993,7 @@ static HWND
makeCommandBar( HWND hwnd, HINSTANCE hInst )
{
SHMENUBARINFO mbi;
HWND result = NULL;
XP_MEMSET( &mbi, 0, sizeof(mbi) );
mbi.cbSize = sizeof(mbi);
@ -2009,13 +2005,14 @@ makeCommandBar( HWND hwnd, HINSTANCE hInst )
//mbi.dwFlags = SHCMBF_HIDESIPBUTTON; /* eeh added. Why??? */
if (!SHCreateMenuBar(&mbi)) {
if ( SHCreateMenuBar(&mbi) ) {
result = mbi.hwndMB;
} else {
/* will want to use this to change menubar: SHEnableSoftkey? */
XP_LOGF( "SHCreateMenuBar failed" );
return NULL;
}
return mbi.hwndMB;
return result;
} /* makeCommandBar */
#endif
@ -2269,6 +2266,40 @@ doAbout( CEAppGlobals* globals )
MB_OK | MB_ICONINFORMATION );
}
static void
chooseChangeResFile( CEAppGlobals* globals )
{
XP_UCHAR newFile[MAX_PATH] = { 0 };
if ( ceChooseResFile( globals, newFile, VSIZE(newFile) ) ) {
if ( !globals->langFileName
|| 0 != XP_STRCMP( newFile, globals->langFileName ) ) {
if ( globals->locInst != globals->hInst ) {
ceCloseResFile( globals->locInst );
}
ceFreeResStrings( globals );
if ( 0 != newFile[0] ) {
globals->locInst = ceLoadResFile( newFile );
} else {
globals->locInst = globals->hInst;
}
replaceStringIfDifferent( globals->mpool, &globals->langFileName,
newFile );
#ifdef _WIN32_WCE
CommandBar_Destroy( globals->hwndCB );
globals->hwndCB = makeCommandBar( globals->hWnd, globals->locInst );
#else
SetMenu( globals->hWnd, LoadMenu( globals->locInst,
MAKEINTRESOURCE(IDM_MENU) ) );
#endif
/* Need to force user to restart unless we can inval everything
to force redraw */
/* board_invalAll( globals->game.board ); */
}
}
}
LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
@ -2342,6 +2373,11 @@ WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
case ID_FILE_ABOUT:
doAbout( globals );
break;
case ID_FILE_LOCALES:
chooseChangeResFile( globals );
break;
case ID_GAME_GAMEINFO: {
GameInfoState state;

View file

@ -18,6 +18,8 @@
*/
#include "ceresstr.h"
#include "ceutil.h"
#include "cedebug.h"
HINSTANCE
ceLoadResFile( const XP_UCHAR* file )
@ -27,7 +29,6 @@ ceLoadResFile( const XP_UCHAR* file )
XP_U16 len = MultiByteToWideChar( CP_ACP, 0, file, -1, widebuf, VSIZE(widebuf) );
widebuf[len] = 0;
hinst = LoadLibrary( widebuf );
XP_LOGF( "strsInst: %p", hinst );
return hinst;
}
@ -156,3 +157,187 @@ ceFreeResStrings( CEAppGlobals* globals )
}
}
#endif
typedef struct _DllSelState {
CeDlgHdr dlgHdr;
wchar_t wbuf[MAX_PATH];
wchar_t* names[8];
wchar_t* files[8];
XP_U16 nItems;
XP_U16 dllListID;
XP_Bool inited;
XP_Bool cancelled;
} DllSelState;
static void
copyWideStr( CEAppGlobals* globals, const wchar_t* str, wchar_t** loc )
{
XP_U16 len = 1 + wcslen( str );
*loc = XP_MALLOC( globals->mpool, len * sizeof(**loc) );
wcscpy( *loc, str );
}
/* 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 )
{
LOG_FUNC();
HANDLE fileH;
HWND hDlg = state->dlgHdr.hDlg;
WIN32_FIND_DATA data;
CEAppGlobals* globals = state->dlgHdr.globals;
XP_U16 nItems = 0;
wchar_t name[64];
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 );
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 ) {
HINSTANCE hinst = LoadLibrary( data.cFileName );
if ( !!hinst ) {
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] );
++nItems;
} else {
XP_LOGF( "IDS_LANGUAGE_NAME not found in %ls", data.cFileName );
}
FreeLibrary( hinst );
} else {
logLastError("LoadLibrary");
XP_LOGF( "Unable to open" );
}
if ( nItems >= VSIZE(state->names) ) {
break;
} else if ( !FindNextFile( fileH, &data ) ) {
XP_ASSERT( GetLastError() == ERROR_NO_MORE_FILES );
break;
}
}
SendDlgItemMessage( hDlg, state->dllListID, SETCURSEL(globals), 0, 0 );
state->nItems = nItems;
LOG_RETURN_VOID();
} /* listDlls */
static void
unlistDlls( DllSelState* state )
{
XP_U16 ii;
CEAppGlobals* globals = state->dlgHdr.globals;
for ( ii = 0; ii < state->nItems; ++ii ) {
XP_ASSERT( ii == 0 || !!state->files[ii] );
if ( ii > 0 ) {
XP_FREE( globals->mpool, state->files[ii] );
}
XP_FREE( globals->mpool, state->names[ii] );
}
}
static XP_Bool
getSelText( DllSelState* state )
{
XP_Bool gotIt = XP_FALSE;
HWND hDlg = state->dlgHdr.hDlg;
CEAppGlobals* globals = state->dlgHdr.globals;
XP_S16 sel = SendDlgItemMessage( hDlg, state->dllListID,
GETCURSEL(globals), 0, 0 );
if ( sel >= 0 ) {
gotIt = XP_TRUE;
if ( sel > 0 ) {
wcscpy( state->wbuf, state->files[sel] );
}
}
return gotIt;
} /* getSelText */
LRESULT CALLBACK
DllSelDlg( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{
DllSelState* state;
BOOL result = FALSE;
if ( message == WM_INITDIALOG ) {
SetWindowLongPtr( hDlg, GWL_USERDATA, lParam );
state = (DllSelState*)lParam;
state->cancelled = XP_TRUE;
state->dllListID = LB_IF_PPC( state->dlgHdr.globals, DLLS_COMBO );
ceDlgSetup( &state->dlgHdr, hDlg, DLG_STATE_NONE );
ceDlgComboShowHide( &state->dlgHdr, DLLS_COMBO );
result = TRUE;
} else {
state = (DllSelState*)GetWindowLongPtr( hDlg, GWL_USERDATA );
if ( !!state ) {
if ( !state->inited ) {
state->inited = XP_TRUE;
listDlls( state );
}
if ( ceDoDlgHandle( &state->dlgHdr, message, wParam, lParam) ) {
result = TRUE;
} else if ( (WM_COMMAND == message)
&& (BN_CLICKED == HIWORD(wParam)) ) {
switch( LOWORD(wParam) ) {
case IDOK:
state->cancelled = XP_FALSE;
getSelText( state );
/* fallthrough */
case IDCANCEL:
unlistDlls( state );
EndDialog( hDlg, LOWORD(wParam) );
result = TRUE;
break;
}
}
}
}
return result;
} /* DllSelDlg */
/* ceChooseResFile: List all the available .rc files and return if user
* chooses one.
*/
XP_Bool
ceChooseResFile( CEAppGlobals* globals, XP_UCHAR* buf, XP_U16 bufLen )
{
DllSelState state;
XP_MEMSET( &state, 0, sizeof(state) );
state.dlgHdr.globals = globals;
(void)DialogBoxParam( globals->locInst, (LPCTSTR)IDD_LOCALESDLG, globals->hWnd,
(DLGPROC)DllSelDlg, (long)&state );
if ( !state.cancelled ) {
(void)WideCharToMultiByte( CP_ACP, 0, state.wbuf, -1,
buf, bufLen, NULL, NULL );
}
LOG_RETURNF( "%s", buf );
return !state.cancelled;
}

View file

@ -24,6 +24,7 @@
HINSTANCE ceLoadResFile( const XP_UCHAR* file );
void ceCloseResFile( HINSTANCE inst );
XP_Bool ceChooseResFile( CEAppGlobals* globals, XP_UCHAR* buf, XP_U16 bufLen );
const XP_UCHAR* ceGetResString( CEAppGlobals* globals, XP_U16 resID );
const wchar_t* ceGetResStringL( CEAppGlobals* globals, XP_U16 resID );

View file

@ -918,3 +918,29 @@ ceCurDictIsUTF8( CEAppGlobals* globals )
}
return result;
} /* ceCurDictIsUTF8 */
XP_Bool
ceGetExeDir( wchar_t* buf, XP_U16 bufLen )
{
/* I wanted to use SHGetKnownFolderPath to search in \\Program
Files\\Crosswords, but perhaps it's better to search in the directory
in which the app is located. If I get CAB files working for
Smartphone, then that directory will be \\Program Files\\Crosswords.
But if users have to install files using the File Explorer it'll be
easier for them if all that's required is that the app and dictionaries
be in the same place. GetModuleFileName() supports both.
*/
DWORD nChars = GetModuleFileName( NULL, buf, bufLen );
XP_Bool success = nChars < bufLen;
if ( success ) {
wchar_t* lastSlash = wcsrchr( buf, '\\' );
if ( !!lastSlash ) {
*lastSlash = 0;
}
}
/* SHGetSpecialFolderPath(NULL,NULL,0,FALSE); */
return success;
} /* ceGetExeDir */

View file

@ -83,6 +83,7 @@ XP_Bool ceDoDlgHandle( CeDlgHdr* dlgHdr, UINT message, WPARAM wParam, LPARAM lPa
XP_Bool ceIsLandscape( CEAppGlobals* globals );
void ceSetLeftSoftkey( CEAppGlobals* globals, XP_U16 id );
XP_Bool ceGetExeDir( wchar_t* buf, XP_U16 bufLen );
#if defined _WIN32_WCE
void ceSizeIfFullscreen( CEAppGlobals* globals, HWND hWnd );

View file

@ -37,6 +37,7 @@
#ifdef ALLOW_CHOOSE_FONTS
# define IDD_FONTSSDLG 127
#endif
#define IDD_LOCALESDLG 128
#define REMOTE_CHECK1 1005
#define NAME_EDIT1 1006
@ -162,6 +163,11 @@
# define FONTSIZE_COMBO_PPC 1130
#endif
/* Dll/language picker */
#define DLLS_COMBO 1131
#define IDC_DLLSUPDOWN 1132
#define DLLS_COMBO_PPC 1133
#define IDC_CCONVIA_LAB 1106
#define IDC_COOKIE_LAB 1107
@ -208,6 +214,7 @@
#define ID_FILE_EXIT 40002
#define IDM_HELP_ABOUT 40003
#define ID_FILE_ABOUT 40004
#define ID_FILE_LOCALES 40029
#define ID_GAME_GAMEINFO 40005
#define ID_GAME_HISTORY 40006
#define ID_GAME_FINALSCORES 40007

View file

@ -10,6 +10,7 @@ static char* ids[] = {
,"IDS_ABOUT"
,"IDS_DONE"
,"IDS_LANGUAGE_NAME"
,"IDS_NEW_GAME"
,"IDS_DICTLOC"
,"IDS_SAVENAME"
,"IDS_DUPENAME"
@ -20,6 +21,10 @@ static char* ids[] = {
,"IDS_TURN_SCORE"
,"IDS_COMMIT_CONFIRM"
,"IDS_LOCAL_NAME"
,"IDS_REM"
,"IDS_IGNORE_L"
,"IDS_WARN_L"
,"IDS_DISALLOW_L"
,"IDS_NONLOCAL_NAME"
,"IDS_TIME_PENALTY_SUB"
,"IDS_CUMULATIVE_SCORE"

View file

@ -121,6 +121,7 @@ BEGIN
MENUITEM "Preferences...", ID_FILE_PREFERENCES
MENUITEM SEPARATOR
MENUITEM "About...", ID_FILE_ABOUT
MENUITEM "Locales...", ID_FILE_LOCALES
MENUITEM SEPARATOR
MENUITEM "Exit", ID_FILE_EXIT
END
@ -881,6 +882,26 @@ BEGIN
END
#endif
IDD_LOCALESDLG DIALOG DISCARDABLE 0, 0, 120, 115
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | DS_CENTER
CAPTION "Language Picker"
FONT 8, "System"
BEGIN
#ifdef _WIN32_WCE
LISTBOX DLLS_COMBO, 30,2,70,12, LISTBOX_CONTROL_FLAGS
CONTROL "", IDC_DLLSUPDOWN, UPDOWN_CLASS, SPINNER_CONTROL_FLAGS,
0, 0, 0, 0
#endif
COMBOBOX DLLS_COMBO_PPC,30,2,70,58,
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
# ifndef _WIN32_WCE
DEFPUSHBUTTON "OK",IDOK,20,100,REPOS_BUTTON_WIDTH,
REPOS_BUTTON_HT
PUSHBUTTON "Cancel",IDCANCEL,100,100,REPOS_BUTTON_WIDTH,
REPOS_BUTTON_HT
# endif
END
/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
@ -950,6 +971,7 @@ BEGIN
IDS_OK "Ok"
IDS_DONE "Done"
IDS_LANGUAGE_NAME "English"
IDS_NEW_GAME "New Game"
IDS_ABOUT "Crosswords 4.4a1 (rev " SVN_REV ") "\
"for Windows Mobile. Copyright 1998-2008 by "\
"Eric House. This software is released under the GNU "\
@ -974,6 +996,10 @@ BEGIN
IDS_COMMIT_CONFIRM
"Commit the current move?" XP_CR
IDS_LOCAL_NAME "%s"
IDS_REM "Rem"
IDS_IGNORE_L "Ignore"
IDS_WARN_L "Warn"
IDS_DISALLOW_L "Disallow"
IDS_NONLOCAL_NAME "%s (remote)"
IDS_TIME_PENALTY_SUB " - %d [time]"
IDS_CUMULATIVE_SCORE "Cumulative score: %d" XP_CR