Get rid of string constants referencing \My Documents, using instead

SHGetSpecialFolderPath.  Cache the result of calling it.  Note that
mingw SHGetSpecialFolderPath headers define SHGetSpecialFolderPath as
SHGetSpecialFolderPathW which isn't in the library; hack around that.
This commit is contained in:
ehouse 2008-10-25 18:08:36 +00:00
parent 9b17c20117
commit 3c8f9d7049
7 changed files with 173 additions and 74 deletions

View file

@ -22,7 +22,6 @@
#include "cemain.h"
#define CE_MAX_PATH_LEN 256
#define CE_MAXDICTS 0x7FFF
typedef struct CEBitmapInfo {

View file

@ -158,7 +158,7 @@ static XP_Bool ceSetDictName( const wchar_t* wPath, XP_U16 index, void* ctxt );
static int messageBoxStream( CEAppGlobals* globals, XWStreamCtxt* stream,
wchar_t* title, XP_U16 buttons );
static XP_Bool ceQueryFromStream( CEAppGlobals* globals, XWStreamCtxt* stream);
static XP_Bool isDefaultName( const XP_UCHAR* name );
static XP_Bool isDefaultName( CEAppGlobals* globals, const XP_UCHAR* name );
static void ceSetTitleFromName( CEAppGlobals* globals );
@ -779,7 +779,7 @@ ceSetTitleFromName( CEAppGlobals* globals )
colonPos = wcsstr( widebuf, L":" );
/* if default name, remove any current name */
if ( !gameName || isDefaultName( gameName ) ) {
if ( !gameName || isDefaultName( globals, gameName ) ) {
if ( NULL != colonPos ) {
*colonPos = 0;
}
@ -896,8 +896,10 @@ static void
ceSavePrefs( CEAppGlobals* globals )
{
HANDLE fileH;
wchar_t path[CE_MAX_PATH_LEN];
fileH = CreateFile( PREFSFILENAME, GENERIC_WRITE, 0, NULL,
(void)ceGetPath( globals, PREFS_FILE_PATH_L, path, VSIZE(path) );
fileH = CreateFile( path, GENERIC_WRITE, 0, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_HIDDEN, NULL );
if ( fileH != INVALID_HANDLE_VALUE ) {
XP_U32 nWritten;
@ -979,8 +981,10 @@ ceLoadPrefs( CEAppGlobals* globals )
{
XP_Bool result = XP_FALSE;
HANDLE fileH;
wchar_t path[CE_MAX_PATH_LEN];
fileH = CreateFile( PREFSFILENAME, GENERIC_READ, 0, NULL,
(void)ceGetPath( globals, PREFS_FILE_PATH_L, path, VSIZE(path) );
fileH = CreateFile( path, GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if ( fileH != INVALID_HANDLE_VALUE ) {
XP_U32 fileSize = GetFileSize( fileH, NULL );
@ -1250,6 +1254,7 @@ InitInstance(HINSTANCE hInstance, int nCmdShow)
XP_Bool oldGameLoaded;
XP_Bool prevStateExists;
XP_Bool newDone = XP_FALSE;
wchar_t path[CE_MAX_PATH_LEN];
MPSLOT;
#ifdef XWFEATURE_RELAY
@ -1270,16 +1275,15 @@ InitInstance(HINSTANCE hInstance, int nCmdShow)
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_XWORDS4, szWindowClass, MAX_LOADSTRING);
//If it is already running, then focus on the window
hWnd = FindWindow( szWindowClass, szTitle);
// If it is already running, then focus on the window. Skip title in
// search as we change title to include game name
hWnd = FindWindow( szWindowClass, NULL );
if ( hWnd ) {
SetForegroundWindow( (HWND)((ULONG) hWnd | 0x00000001) );
result = FALSE;
goto exit;
}
(void)CreateDirectory( DEFAULT_DIR_NAME, 0 );
#ifdef MEM_DEBUG
mpool = mpool_make();
#endif
@ -1289,6 +1293,9 @@ InitInstance(HINSTANCE hInstance, int nCmdShow)
XP_MEMSET( globals, 0, sizeof(*globals) );
MPASSIGN( globals->mpool, mpool );
(void)ceGetPath( globals, DEFAULT_DIR_PATH_L, path, VSIZE(path) );
(void)CreateDirectory( path, 0 );
getOSInfo( globals );
#if defined DEBUG && !defined _WIN32_WCE
@ -1735,9 +1742,11 @@ ceWriteToFile( XWStreamCtxt* stream, void* closure )
} /* ceWriteToFile */
static XP_Bool
isDefaultName( const XP_UCHAR* name )
isDefaultName( CEAppGlobals* globals, const XP_UCHAR* name )
{
return 0 == XP_STRCMP( UNSAVEDGAMEFILENAME, name );
wchar_t path[CE_MAX_PATH_LEN];
(void)ceGetPath( globals, DEFAULT_GAME_PATH, path, VSIZE(path) );
return 0 == XP_STRCMP( path, name );
} /* isDefaultName */
static XP_Bool
@ -1750,13 +1759,16 @@ ceSaveCurGame( CEAppGlobals* globals, XP_Bool autoSave )
harm in making 'em restart. Not sure how this changes when IR's
involved. */
XP_UCHAR* name = globals->curGameName;
if ( name == NULL || isDefaultName(name) ) {
if ( name == NULL || isDefaultName( globals, name ) ) {
XP_UCHAR* newName = NULL;
if ( autoSave ) {
XP_U16 len = XP_STRLEN(UNSAVEDGAMEFILENAME) + 1;
XP_U16 len;
wchar_t path[CE_MAX_PATH_LEN];
len = 1 + ceGetPath( globals, DEFAULT_GAME_PATH,
path, VSIZE(path) );
newName = XP_MALLOC( globals->mpool, len );
XP_MEMCPY( newName, UNSAVEDGAMEFILENAME, len );
XP_MEMCPY( newName, path, len );
confirmed = XP_TRUE;
} else {
@ -1861,11 +1873,12 @@ freeGlobals( CEAppGlobals* globals )
if ( !!globals->util.vtable ) {
XP_FREE( mpool, globals->util.vtable );
}
if ( !!globals->specialDir ) {
XP_FREE( mpool, globals->specialDir );
}
XP_FREE( globals->mpool, globals );
mpool_destroy( mpool );
LOG_RETURN_VOID();
} /* freeGlobals */
#ifdef _WIN32_WCE

View file

@ -160,6 +160,8 @@ typedef struct CEAppGlobals {
int dbWidth, dbHeight;
#endif
wchar_t* specialDir; /* reserved for ceGetPath() */
#ifdef XWFEATURE_SEARCHLIMIT
XP_Bool askTrayLimits;
#endif
@ -200,4 +202,5 @@ XP_Bool queryBoxChar( CEAppGlobals* globals, const XP_UCHAR* msg );
#define BACK_KEY_UP_MAYBE 0x1000
#define CE_MAX_PATH_LEN 256
#endif /* _CEMAIN_H_ */

View file

@ -41,18 +41,22 @@ typedef struct CeSaveGameNameState {
} CeSaveGameNameState;
static XP_Bool
ceFileExists( const wchar_t* name )
ceFileExists( CEAppGlobals* globals, const wchar_t* name )
{
wchar_t buf[128];
wchar_t buf[CE_MAX_PATH_LEN];
DWORD attributes;
swprintf( buf, DEFAULT_DIR_NAME L"\\%s.xwg", name );
XP_U16 len;
len = ceGetPath( globals, DEFAULT_DIR_PATH_L, buf, VSIZE(buf) );
swprintf( &buf[len], L"%s.xwg", name );
attributes = GetFileAttributes( buf );
return attributes != 0xFFFFFFFF;
}
static void
makeUniqueName( wchar_t* buf, XP_U16 XP_UNUSED_DBG(bufLen) )
makeUniqueName( CEAppGlobals* globals, wchar_t* buf,
XP_U16 XP_UNUSED_DBG(bufLen) )
{
XP_U16 ii;
for ( ii = 1; ii < 100; ++ii ) {
@ -61,7 +65,7 @@ makeUniqueName( wchar_t* buf, XP_U16 XP_UNUSED_DBG(bufLen) )
#endif
swprintf( buf, L"Untitled%d", ii );
XP_ASSERT( len < bufLen );
if ( !ceFileExists( buf ) ) {
if ( !ceFileExists( globals, buf ) ) {
break;
}
}
@ -94,6 +98,7 @@ SaveNameDlg( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
} else {
state = (CeSaveGameNameState*)GetWindowLongPtr( hDlg, GWL_USERDATA );
if ( !!state ) {
CEAppGlobals* globals = state->dlgHdr.globals;
if ( !state->inited ) {
state->inited = XP_TRUE;
(void)SetDlgItemText( hDlg, IDC_SVGN_EDIT, state->buf );
@ -109,15 +114,17 @@ SaveNameDlg( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
switch( wid ) {
case IDOK: {
wchar_t buf[128];
XP_U16 len;
(void)GetDlgItemText( hDlg, IDC_SVGN_EDIT, buf,
VSIZE(buf) );
if ( ceFileExists( buf ) ) {
messageBoxChar( state->dlgHdr.globals,
if ( ceFileExists( globals, buf ) ) {
messageBoxChar( globals,
"File exists", L"Oops!", MB_OK );
break;
}
swprintf( state->buf, DEFAULT_DIR_NAME L"\\%s.xwg",
buf );
len = ceGetPath( globals, DEFAULT_DIR_PATH_L,
state->buf, state->buflen );
swprintf( &state->buf[len], L"%s.xwg", buf );
XP_LOGW( __func__, state->buf );
/* fallthru */
state->cancelled = XP_FALSE;
@ -142,7 +149,7 @@ ceConfirmUniqueName( CEAppGlobals* globals, XP_U16 strId, wchar_t* buf,
LOG_FUNC();
makeUniqueName( buf, buflen );
makeUniqueName( globals, buf, buflen );
XP_MEMSET( &state, 0, sizeof(state) );
state.dlgHdr.globals = globals;
@ -162,7 +169,7 @@ typedef struct CeSavedGamesState {
XP_U16 buflen;
XP_S16 sel;
XP_U16 openGameIndex;
wchar_t curName[128];
wchar_t curNameW[128];
XP_U16 nItems;
XP_U16 gameListId;
@ -173,11 +180,12 @@ typedef struct CeSavedGamesState {
/* Probably belongs as a utility */
static void
getCBText( CeSavedGamesState* state, XP_U16 id, XP_U16 sel, wchar_t* buf,
XP_U16* lenp )
getComboText( CeSavedGamesState* state, wchar_t* buf, XP_U16* lenp )
{
HWND hDlg = state->dlgHdr.hDlg;
CEAppGlobals* globals = state->dlgHdr.globals;
XP_U16 id = state->gameListId;
XP_U16 sel = state->sel;
XP_U16 len;
len = SendDlgItemMessage( hDlg, id, GETLBTEXTLEN(globals), sel, 0L );
@ -189,16 +197,15 @@ getCBText( CeSavedGamesState* state, XP_U16 id, XP_U16 sel, wchar_t* buf,
XP_ASSERT( 0 );
}
*lenp = len;
} /* getCBText */
} /* getComboText */
static void
getFullSelPath( CeSavedGamesState* state, wchar_t* buf, XP_U16 buflen )
{
XP_U16 len;
lstrcpy( buf, DEFAULT_DIR_NAME L"\\" );
len = lstrlen( buf );
XP_U16 len = ceGetPath( state->dlgHdr.globals,
DEFAULT_DIR_PATH_L, buf, buflen );
buflen -= len;
getCBText( state, state->gameListId, state->sel, &buf[len], &buflen );
getComboText( state, &buf[len], &buflen );
lstrcat( buf, L".xwg" );
}
@ -222,26 +229,28 @@ initSavedGamesData( CeSavedGamesState* state )
HWND hDlg = state->dlgHdr.hDlg;
CEAppGlobals* globals = state->dlgHdr.globals;
WIN32_FIND_DATA data;
wchar_t path[256];
wchar_t path[CE_MAX_PATH_LEN];
XP_S16 curSel = -1;
XP_U16 ii;
XP_U16 nItems = 0;
XP_MEMSET( &data, 0, sizeof(data) );
lstrcpy( path, DEFAULT_DIR_NAME L"\\" );
ceGetPath( globals, DEFAULT_DIR_PATH_L, path, VSIZE(path) );
lstrcat( path, L"*.xwg" );
fileH = FindFirstFile( path, &data );
for ( ii = 0; fileH != INVALID_HANDLE_VALUE; ++ii ) {
XP_U16 len = wcslen( data.cFileName );
XP_U16 item;
XP_Bool isCurGame = 0 == wcscmp( state->curName, data.cFileName );
XP_Bool isCurGame = 0 == wcscmp( state->curNameW, data.cFileName );
XP_ASSERT( data.cFileName[len-4] == '.');
data.cFileName[len-4] = 0;
/* Insert in sorted order. This should be fast enough for reasonable
numbers of saved games. */
/* PENDING: there's supposed to be a field attribute that make sorted
order automatic */
for ( item = 0; item < nItems; ++item ) {
wchar_t buf[256];
(void)SendDlgItemMessage( hDlg, state->gameListId,
@ -319,20 +328,19 @@ duplicateSelected( CeSavedGamesState* state )
static XP_Bool
deleteSelected( CeSavedGamesState* state )
{
wchar_t buf[128];
wchar_t path[128];
XP_U16 len = VSIZE(buf);
/* confirm first!!!! */
XP_Bool confirmed = queryBoxChar( state->dlgHdr.globals,
"Are you certain you want to delete the "
"selected game? This action cannot be "
"undone.");
if ( confirmed ) {
getCBText( state, state->gameListId,
state->sel, buf, &len );
swprintf( path, DEFAULT_DIR_NAME L"\\%s.xwg", buf );
confirmed = DeleteFile( path );
wchar_t pathW[CE_MAX_PATH_LEN];
XP_U16 len = ceGetPath( state->dlgHdr.globals,
DEFAULT_DIR_PATH_L, pathW, VSIZE(pathW) );
XP_U16 remLen = VSIZE(pathW) - len;
getComboText( state, &pathW[len], &remLen );
wcscat( pathW, L".xwg" );
confirmed = DeleteFile( pathW );
if ( confirmed ) {
state->sel = -1;
}
@ -405,10 +413,10 @@ SavedGamesDlg( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
case IDC_SVGM_OPEN: {
wchar_t buf[128];
XP_U16 len = VSIZE(buf);
getCBText( state, state->gameListId, state->sel,
buf, &len );
swprintf( state->buf, DEFAULT_DIR_NAME L"\\%s.xwg",
buf );
getComboText( state, buf, &len );
len = ceGetPath( state->dlgHdr.globals, DEFAULT_DIR_PATH_L,
state->buf, state->buflen );
swprintf( &state->buf[len], L"%s.xwg", buf );
XP_LOGW( "returning", state->buf );
state->opened = XP_TRUE;
}
@ -448,14 +456,15 @@ ceSavedGamesDlg( CEAppGlobals* globals, const XP_UCHAR* curPath,
if ( !!curPath ) {
wchar_t shortName[128];
XP_U16 len;
XP_LOGF( curPath );
XP_U16 dirLen;
dirLen = ceGetPath( globals, DEFAULT_DIR_PATH_L, shortName,
VSIZE(shortName) );
len = (XP_U16)XP_STRLEN( curPath );
MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, curPath, len + 1,
shortName, len + 1 );
len = wcslen( DEFAULT_DIR_NAME L"\\" );
lstrcpy( state.curName, shortName+len );
XP_LOGW( "shortName", state.curName );
lstrcpy( state.curNameW, shortName+dirLen );
}
for ( ; ; ) {

View file

@ -23,27 +23,6 @@
#include "xptypes.h"
#include "cemain.h"
#ifdef _WIN32_WCE
# define DEFAULT_DIR_NAME L"\\My Documents\\" LCROSSWORDS_DIR
# define PREFSFILENAME L"\\My Documents\\" LCROSSWORDS_DIR L"\\xwprefs"
# define UNSAVEDGAMEFILENAME "\\My Documents\\" CROSSWORDS_DIR "\\_newgame"
#else
# define DEFAULT_DIR_NAME "\\tmp" CROSSWORDS_DIR
# define LDEFAULT_DIR_NAME L"\\tmp" LCROSSWORDS_DIR
# define PREFSFILENAME LDEFAULT_DIR_NAME L"\\xwprefs"
# define UNSAVEDGAMEFILENAME DEFAULT_DIR_NAME "\\_newgame"
#endif
#ifdef _WIN32_WCE
# define DEFAULT_DIR_NAME L"\\My Documents\\" LCROSSWORDS_DIR
/* # define PREFSFILENAME L"\\My Documents\\Crosswords\\xwprefs" */
/* # define UNSAVEDGAMEFILENAME "\\My Documents\\Crosswords\\_newgame" */
#else
/* # define DEFAULT_DIR_NAME L"." */
# define DEFAULT_DIR_NAME L"\\tmp"
#endif
XP_Bool ceSavedGamesDlg( CEAppGlobals* globals, const XP_UCHAR* curPath,
wchar_t* buf, XP_U16 buflen );
XP_Bool ceConfirmUniqueName( CEAppGlobals* globals, XP_U16 strId, wchar_t* buf,

View file

@ -19,6 +19,7 @@
#include "stdafx.h"
#include <commctrl.h>
#include <shlobj.h>
#include "ceutil.h"
#include "cedefines.h"
@ -745,3 +746,90 @@ trapBackspaceKey( HWND hDlg )
*/
}
#endif
/* cegcc headers define this to SHGetSpecialFolderPathW, but that's not
* what's in the library... */
#ifdef SHGetSpecialFolderPath
# undef SHGetSpecialFolderPath
#endif
BOOL SHGetSpecialFolderPath( HWND hwndOwner,
LPTSTR lpszPath,
int nFolder,
BOOL fCreate );
static void
lookupSpecialDir( wchar_t* bufW )
{
bufW[0] = 0;
#ifdef _WIN32_WCE
#if 0
BOOL (*mySHGetSpecialFolderPath)( HWND hwndOwner,
LPTSTR lpszPath,
int nFolder,
BOOL fCreate );
HMODULE module;
module = LoadLibrary( L"coredll" );
if ( !!module ) {
mySHGetSpecialFolderPath = GetProcAddress( module,
L"SHGetSpecialFolderPath" );
if ( !!mySHGetSpecialFolderPath ) {
HRESULT res = (*mySHGetSpecialFolderPath)( NULL, bufW,
CSIDL_PERSONAL, TRUE );
}
FreeLibrary( module );
}
#else
SHGetSpecialFolderPath( NULL, bufW, CSIDL_PERSONAL, TRUE );
#endif
if ( 0 == bufW[0] ) {
XP_WARNF( "SHGetSpecialFolderPath hack failed" );
wcscpy( bufW, L"\\My Documents" );
}
#endif
wcscat( bufW, L"\\" LCROSSWORDS_DIR L"\\" );
}
XP_U16
ceGetPath( CEAppGlobals* globals, CePathType typ,
void* bufOut, XP_U16 bufLen )
{
XP_U16 len;
wchar_t bufW[CE_MAX_PATH_LEN];
wchar_t* specialDir = globals->specialDir;
XP_Bool asAscii = XP_FALSE;
if ( !specialDir ) {
wchar_t buf[128];
XP_U16 len;
lookupSpecialDir( buf );
len = 1 + wcslen( buf );
specialDir = XP_MALLOC( globals->mpool, len * sizeof(specialDir[0]) );
wcscpy( specialDir, buf );
globals->specialDir = specialDir;
}
wcscpy( bufW, specialDir );
switch( typ ) {
case PREFS_FILE_PATH_L:
wcscat( bufW, L"xwprefs" );
break;
case DEFAULT_DIR_PATH_L:
/* nothing to do */
break;
case DEFAULT_GAME_PATH:
asAscii = XP_TRUE;
wcscat( bufW, L"_newgame" );
break;
}
len = wcslen( bufW );
if ( asAscii ) {
(void)WideCharToMultiByte( CP_ACP, 0, bufW, len,
(char*)bufOut, bufLen, NULL, NULL );
} else {
wcscpy( (wchar_t*)bufOut, bufW );
}
return len;
} /* ceGetPath */

View file

@ -43,6 +43,14 @@ void ceSetChecked( HWND hDlg, XP_U16 resID, XP_Bool check );
void ceCenterCtl( HWND hDlg, XP_U16 resID );
typedef enum {
PREFS_FILE_PATH_L
,DEFAULT_DIR_PATH_L
,DEFAULT_GAME_PATH
} CePathType;
XP_U16 ceGetPath( CEAppGlobals* globals, CePathType typ,
void* buf, XP_U16 bufLen );
/* set vHeight to 0 to turn off scrolling */
typedef enum { DLG_STATE_NONE = 0
, DLG_STATE_TRAPBACK = 1