diff --git a/xwords4/wince/cedict.c b/xwords4/wince/cedict.c index add3ee9de..ad8684f31 100755 --- a/xwords4/wince/cedict.c +++ b/xwords4/wince/cedict.c @@ -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 ); } diff --git a/xwords4/wince/cemain.c b/xwords4/wince/cemain.c index a4aa01b06..fc2f554b3 100755 --- a/xwords4/wince/cemain.c +++ b/xwords4/wince/cemain.c @@ -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; diff --git a/xwords4/wince/ceresstr.c b/xwords4/wince/ceresstr.c index 4b1d8c9e9..7121022d9 100644 --- a/xwords4/wince/ceresstr.c +++ b/xwords4/wince/ceresstr.c @@ -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; +} diff --git a/xwords4/wince/ceresstr.h b/xwords4/wince/ceresstr.h index f6285dc40..eb5e54c99 100644 --- a/xwords4/wince/ceresstr.h +++ b/xwords4/wince/ceresstr.h @@ -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 ); diff --git a/xwords4/wince/ceutil.c b/xwords4/wince/ceutil.c index 57f89ac57..61cb55133 100755 --- a/xwords4/wince/ceutil.c +++ b/xwords4/wince/ceutil.c @@ -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 */ diff --git a/xwords4/wince/ceutil.h b/xwords4/wince/ceutil.h index fa050a5af..392af319b 100755 --- a/xwords4/wince/ceutil.h +++ b/xwords4/wince/ceutil.h @@ -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 ); diff --git a/xwords4/wince/resource.h b/xwords4/wince/resource.h index 79df677ef..105fb885b 100755 --- a/xwords4/wince/resource.h +++ b/xwords4/wince/resource.h @@ -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 diff --git a/xwords4/wince/scripts/strids.c b/xwords4/wince/scripts/strids.c index 494029410..4de548e12 100644 --- a/xwords4/wince/scripts/strids.c +++ b/xwords4/wince/scripts/strids.c @@ -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" diff --git a/xwords4/wince/xwords4.rc b/xwords4/wince/xwords4.rc index 5f9ab123e..598cb4d0f 100755 --- a/xwords4/wince/xwords4.rc +++ b/xwords4/wince/xwords4.rc @@ -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