mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-14 08:01:38 +01:00
Add dialog for choosing localization .dll; save choice in prefs and open on boot.
This commit is contained in:
parent
a7bf9f611d
commit
481e2acb92
9 changed files with 299 additions and 38 deletions
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue