mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-03 23:04:08 +01:00
a6ecdd0f9e
2509 2513 2514 2515 2516 2517 2518 2519 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 and 2544 from trunk with the goal of adding localization support to this branch so that it can be released before all the networking stuff on trunk is debugged.
341 lines
10 KiB
C
341 lines
10 KiB
C
/* -*- compile-command: "make -j3 TARGET_OS=wince DEBUG=TRUE RELAY_NAME_DEFAULT=localhost" -*- */
|
|
/*
|
|
* Copyright 2009 by Eric House (xwords@eehouse.org). All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include "ceresstr.h"
|
|
#include "ceutil.h"
|
|
#include "cedebug.h"
|
|
|
|
HINSTANCE
|
|
ceLoadResFile( const XP_UCHAR* file )
|
|
{
|
|
HINSTANCE hinst = NULL;
|
|
wchar_t widebuf[128];
|
|
XP_U16 len = MultiByteToWideChar( CP_ACP, 0, file, -1, widebuf, VSIZE(widebuf) );
|
|
widebuf[len] = 0;
|
|
hinst = LoadLibrary( widebuf );
|
|
return hinst;
|
|
}
|
|
|
|
void
|
|
ceCloseResFile( HINSTANCE inst )
|
|
{
|
|
XP_ASSERT( !!inst );
|
|
FreeLibrary( inst );
|
|
}
|
|
|
|
#ifdef LOADSTRING_BROKEN
|
|
typedef struct _ResStrEntry {
|
|
union {
|
|
XP_UCHAR nstr[1];
|
|
wchar_t wstr[1];
|
|
} u;
|
|
} ResStrEntry;
|
|
|
|
typedef struct _ResStrStorage {
|
|
ResStrEntry* entries[CE_LAST_RES_ID - CE_FIRST_RES_ID + 1];
|
|
} ResStrStorage;
|
|
|
|
static const ResStrEntry*
|
|
getEntry( CEAppGlobals* globals, XP_U16 resID, XP_Bool isWide )
|
|
{
|
|
ResStrStorage* storage = (ResStrStorage*)globals->resStrStorage;
|
|
ResStrEntry* entry;
|
|
XP_U16 index;
|
|
|
|
XP_ASSERT( resID >= CE_FIRST_RES_ID && resID <= CE_LAST_RES_ID );
|
|
index = CE_LAST_RES_ID - resID;
|
|
XP_ASSERT( index < VSIZE(storage->entries) );
|
|
|
|
if ( !storage ) {
|
|
storage = XP_MALLOC( globals->mpool, sizeof( *storage ) );
|
|
XP_MEMSET( storage, 0, sizeof(*storage) );
|
|
globals->resStrStorage = storage;
|
|
}
|
|
|
|
entry = storage->entries[index];
|
|
if ( !entry ) {
|
|
wchar_t wbuf[265];
|
|
XP_U16 len;
|
|
LoadString( globals->locInst, resID, wbuf, VSIZE(wbuf) );
|
|
if ( isWide ) {
|
|
len = wcslen( wbuf );
|
|
entry = (ResStrEntry*)XP_MALLOC( globals->mpool,
|
|
(len*sizeof(wchar_t))
|
|
+ sizeof(*entry) );
|
|
wcscpy( entry->u.wstr, wbuf );
|
|
} else {
|
|
XP_UCHAR nbuf[265];
|
|
(void)WideCharToMultiByte( CP_ACP, 0, wbuf, -1,
|
|
nbuf, VSIZE(nbuf), NULL, NULL );
|
|
len = XP_STRLEN( nbuf );
|
|
entry = (ResStrEntry*)XP_MALLOC( globals->mpool,
|
|
len + sizeof(*entry) );
|
|
XP_STRNCPY( entry->u.nstr, nbuf, len + 1 );
|
|
}
|
|
|
|
storage->entries[index] = entry;
|
|
}
|
|
|
|
return entry;
|
|
} /* getEntry */
|
|
#endif
|
|
|
|
const XP_UCHAR*
|
|
ceGetResString( CEAppGlobals* globals, XP_U16 resID )
|
|
{
|
|
#ifdef LOADSTRING_BROKEN
|
|
const ResStrEntry* entry = getEntry( globals, resID, XP_FALSE );
|
|
return entry->u.nstr;
|
|
#else
|
|
/* Docs say that you can call LoadString with 0 as the length and it'll
|
|
return a read-only ptr to the text within the resource, but I'm getting
|
|
a ptr to wide chars back the resource text being multibyte. I swear
|
|
I've seen it work, though, so might be a res file formatting thing or a
|
|
param to the res compiler. Need to investigate. Until I do, the above
|
|
caches local multibyte copies of the resources so the API can stay the
|
|
same. */
|
|
const XP_UCHAR* str = NULL;
|
|
LoadString( globals->locInst, resID, (LPSTR)&str, 0 );
|
|
return str;
|
|
#endif
|
|
}
|
|
|
|
const wchar_t*
|
|
ceGetResStringL( CEAppGlobals* globals, XP_U16 resID )
|
|
{
|
|
#ifdef LOADSTRING_BROKEN
|
|
const ResStrEntry* entry = getEntry( globals, resID, XP_TRUE );
|
|
return entry->u.wstr;
|
|
#else
|
|
/* Docs say that you can call LoadString with 0 as the length and it'll
|
|
return a read-only ptr to the text within the resource, but I'm getting
|
|
a ptr to wide chars back the resource text being multibyte. I swear
|
|
I've seen it work, though, so might be a res file formatting thing or a
|
|
param to the res compiler. Need to investigate. Until I do, the above
|
|
caches local multibyte copies of the resources so the API can stay the
|
|
same. */
|
|
const XP_UCHAR* str = NULL;
|
|
LoadString( globals->locInst, resID, (LPSTR)&str, 0 );
|
|
return str;
|
|
#endif
|
|
}
|
|
|
|
#ifdef LOADSTRING_BROKEN
|
|
void
|
|
ceFreeResStrings( CEAppGlobals* globals )
|
|
{
|
|
ResStrStorage* storage = (ResStrStorage*)globals->resStrStorage;
|
|
if ( !!storage ) {
|
|
XP_U16 ii;
|
|
for ( ii = 0; ii < VSIZE(storage->entries); ++ii ) {
|
|
ResStrEntry* entry = storage->entries[ii];
|
|
if ( !!entry ) {
|
|
XP_FREE( globals->mpool, entry );
|
|
}
|
|
}
|
|
|
|
XP_FREE( globals->mpool, storage );
|
|
globals->resStrStorage = NULL;
|
|
}
|
|
}
|
|
#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, LOCALES_COMBO );
|
|
|
|
ceDlgSetup( &state->dlgHdr, hDlg, DLG_STATE_NONE );
|
|
|
|
ceDlgComboShowHide( &state->dlgHdr, LOCALES_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;
|
|
}
|