Mods to saved games dialog: allow to rename the current game; after

renaming or duplicating a game, make that new name the one initially
selected in the listbox; remove sorting code relying on OS to sort
when CBS_SORT set.
This commit is contained in:
ehouse 2008-12-06 20:28:01 +00:00
parent 6da758b5fa
commit 57197f8b2c
4 changed files with 116 additions and 72 deletions

View file

@ -1623,23 +1623,26 @@ static void
ceChooseAndOpen( CEAppGlobals* globals ) ceChooseAndOpen( CEAppGlobals* globals )
{ {
// Save in case we'll be duplicating it // Save in case we'll be duplicating it
again:
if ( ceSaveCurGame( globals, XP_FALSE ) if ( ceSaveCurGame( globals, XP_FALSE )
|| queryBoxChar( globals, "Do you really want to " || queryBoxChar( globals, "Do you really want to "
"overwrite the current game?" ) ) { "overwrite the current game?" ) ) {
wchar_t path[256]; SavedGamesResult choice;
path[0] = 0; wchar_t newName[256];
newName[0] = 0;
ceSetTitleFromName( globals ); /* in case we named it above */ ceSetTitleFromName( globals ); /* in case we named it above */
if ( ceSavedGamesDlg( globals, globals->curGameName, choice = ceSavedGamesDlg( globals, globals->curGameName, newName,
path, VSIZE(path) )) { VSIZE(newName) );
if ( CE_SVGAME_CANCEL != choice ) {
XP_UCHAR* name; XP_UCHAR* name;
XP_U16 len; XP_U16 len;
len = wcslen(path); len = wcslen(newName);
name = XP_MALLOC( globals->mpool, len + 1 ); name = XP_MALLOC( globals->mpool, len + 1 );
WideCharToMultiByte( CP_ACP, 0, path, len + 1, WideCharToMultiByte( CP_ACP, 0, newName, len + 1,
name, len + 1, NULL, NULL ); name, len + 1, NULL, NULL );
if ( globals->curGameName != NULL if ( globals->curGameName != NULL
@ -1660,10 +1663,19 @@ ceChooseAndOpen( CEAppGlobals* globals )
globals->curGameName = NULL; /* prevent being destroyed */ globals->curGameName = NULL; /* prevent being destroyed */
closeGame( globals ); closeGame( globals );
if ( CE_SVGAME_RENAME == choice ) {
XP_U16 len = 1 + XP_STRLEN( oldName );
wchar_t widebuf[len];
MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, oldName, len,
widebuf, len );
(void)MoveFile( widebuf, newName );
}
globals->curGameName = name; globals->curGameName = name;
if ( ceLoadSavedGame( globals ) ) { if ( ceLoadSavedGame( globals ) ) {
XP_FREE( globals->mpool, oldName ); XP_FREE( globals->mpool, oldName );
} else { } else {
XP_ASSERT( CE_SVGAME_RENAME != choice );
XP_LOGF( "failed to open chosen game" ); XP_LOGF( "failed to open chosen game" );
XP_FREE( globals->mpool, globals->curGameName ); XP_FREE( globals->mpool, globals->curGameName );
globals->curGameName = oldName; globals->curGameName = oldName;
@ -1672,6 +1684,9 @@ ceChooseAndOpen( CEAppGlobals* globals )
} }
} }
ceInitAndStartBoard( globals, XP_FALSE, NULL ); ceInitAndStartBoard( globals, XP_FALSE, NULL );
if ( CE_SVGAME_RENAME == choice ) {
goto again;
}
} }
} else { } else {
XP_LOGF( "GetOpenFileName() failed" ); XP_LOGF( "GetOpenFileName() failed" );

View file

@ -168,17 +168,39 @@ typedef struct CeSavedGamesState {
CeDlgHdr dlgHdr; CeDlgHdr dlgHdr;
wchar_t* buf; wchar_t* buf;
XP_U16 buflen; XP_U16 buflen;
XP_S16 sel; XP_S16 sel; /* index of game name currently selected */
XP_U16 openGameIndex; XP_U16 openGameIndex; /* index of game that's open */
wchar_t curNameW[128]; wchar_t openNameW[128];
wchar_t newNameW[MAX_PATH];
XP_U16 nItems; XP_U16 nItems;
XP_U16 gameListId; XP_U16 gameListId;
XP_Bool opened;
XP_Bool inited; XP_Bool inited;
XP_Bool relaunch; XP_Bool relaunch;
SavedGamesResult result;
} CeSavedGamesState; } CeSavedGamesState;
static void
ceBasename( wchar_t* buf, const wchar_t* path )
{
const wchar_t* ptr = path + wcslen(path);
const wchar_t* dot = NULL;
for ( ; ; ) {
if ( ptr == path ) {
break;
} else if ( *ptr == L'\\' ) {
++ptr;
break;
} else if ( !dot && *ptr == L'.' ) {
dot = ptr;
}
--ptr;
}
lstrcpy( buf, ptr );
buf[dot-ptr] = 0; /* nuke extension */
} /* ceBasename */
/* Probably belongs as a utility */ /* Probably belongs as a utility */
static void static void
getComboText( CeSavedGamesState* state, wchar_t* buf, XP_U16* lenp ) getComboText( CeSavedGamesState* state, wchar_t* buf, XP_U16* lenp )
@ -220,7 +242,7 @@ setButtons( CeSavedGamesState* state )
ceEnOrDisable( hDlg, IDC_SVGM_OPEN, haveItem && !curSelected ); ceEnOrDisable( hDlg, IDC_SVGM_OPEN, haveItem && !curSelected );
ceEnOrDisable( hDlg, IDC_SVGM_DUP, haveItem ); ceEnOrDisable( hDlg, IDC_SVGM_DUP, haveItem );
ceEnOrDisable( hDlg, IDC_SVGM_DEL, haveItem && !curSelected ); ceEnOrDisable( hDlg, IDC_SVGM_DEL, haveItem && !curSelected );
ceEnOrDisable( hDlg, IDC_SVGM_CHANGE, haveItem && !curSelected ); ceEnOrDisable( hDlg, IDC_SVGM_CHANGE, haveItem );
} }
static void static void
@ -231,7 +253,7 @@ initSavedGamesData( CeSavedGamesState* state )
CEAppGlobals* globals = state->dlgHdr.globals; CEAppGlobals* globals = state->dlgHdr.globals;
WIN32_FIND_DATA data; WIN32_FIND_DATA data;
wchar_t path[CE_MAX_PATH_LEN]; wchar_t path[CE_MAX_PATH_LEN];
XP_S16 curSel = -1; XP_S16 sel;
XP_U16 ii; XP_U16 ii;
XP_U16 nItems = 0; XP_U16 nItems = 0;
@ -242,40 +264,13 @@ initSavedGamesData( CeSavedGamesState* state )
fileH = FindFirstFile( path, &data ); fileH = FindFirstFile( path, &data );
for ( ii = 0; fileH != INVALID_HANDLE_VALUE; ++ii ) { for ( ii = 0; fileH != INVALID_HANDLE_VALUE; ++ii ) {
XP_U16 len = wcslen( data.cFileName ); XP_U16 len = wcslen( data.cFileName );
XP_U16 item;
XP_Bool isCurGame = 0 == wcscmp( state->curNameW, data.cFileName );
XP_ASSERT( data.cFileName[len-4] == '.'); XP_ASSERT( data.cFileName[len-4] == L'.');
data.cFileName[len-4] = 0; 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,
GETLBTEXT(globals), item,
(LPARAM)buf );
/* Does the current item belong above the one we're inserting? */
if ( 0 <= wcscmp( buf, data.cFileName ) ) {
break;
}
}
(void)SendDlgItemMessage( hDlg, state->gameListId, (void)SendDlgItemMessage( hDlg, state->gameListId,
INSERTSTRING(globals), ADDSTRING(globals),
item, (LPARAM)data.cFileName ); 0, (LPARAM)data.cFileName );
/* Remember which entry matches the currently opened game, and adjust
if it's changed. We may be incrementing an uninitialized curSel,
but that's ok as isCurGame is guaranteed to be true exactly once
through. */
if ( isCurGame ) {
curSel = item;
} else if ( curSel >= item ) {
++curSel; /* since we've moved it up */
}
++nItems; ++nItems;
if ( !FindNextFile( fileH, &data ) ) { if ( !FindNextFile( fileH, &data ) ) {
@ -283,29 +278,51 @@ initSavedGamesData( CeSavedGamesState* state )
break; break;
} }
} }
state->nItems = nItems; state->nItems = nItems;
state->openGameIndex = curSel;
SendDlgItemMessage( hDlg, state->gameListId, /* Now locate the open game and game we should select (which may
SETCURSEL(globals), curSel, 0 ); differ) */
state->sel = curSel; sel = SendDlgItemMessage( hDlg, state->gameListId, FINDSTRINGEXACT(globals),
-1, (LPARAM)state->openNameW );
XP_ASSERT( sel >= 0 ); /* should always have this */
state->openGameIndex = sel;
sel = SendDlgItemMessage( hDlg,state->gameListId, FINDSTRINGEXACT(globals),
-1, (LPARAM)state->newNameW );
if ( sel < 0 ) {
sel = state->openGameIndex;
}
SendDlgItemMessage( hDlg, state->gameListId, SETCURSEL(globals), sel, 0 );
state->sel = sel;
setButtons( state ); setButtons( state );
LOG_RETURN_VOID();
} /* initSavedGamesData */ } /* initSavedGamesData */
static XP_Bool static XP_Bool
renameSelected( CeSavedGamesState* state ) renameSelected( CeSavedGamesState* state )
{ {
wchar_t path[MAX_PATH]; wchar_t newPath[MAX_PATH];
XP_Bool confirmed = ceConfirmUniqueName( state->dlgHdr.globals, IDS_RENAME, XP_Bool confirmed = ceConfirmUniqueName( state->dlgHdr.globals, IDS_RENAME,
path, VSIZE(path) ); newPath, VSIZE(newPath) );
if ( confirmed ) { if ( confirmed ) {
wchar_t curPath[MAX_PATH]; /* If we're renaming the current game, we have to exit and let
getFullSelPath( state, curPath, VSIZE(curPath) ); calling code handle it. If we're renaming any other game, we can
confirmed = MoveFile( curPath, path ); do it here. */
if ( state->openGameIndex == state->sel ) {
swprintf( state->buf, L"%s", newPath );
state->result = CE_SVGAME_RENAME;
} else {
wchar_t curPath[MAX_PATH];
getFullSelPath( state, curPath, VSIZE(curPath) );
confirmed = MoveFile( curPath, newPath );
}
}
if ( confirmed ) {
ceBasename( state->newNameW, newPath );
} else {
state->newNameW[0] = 0;
} }
return confirmed; return confirmed;
} /* renameSelected */ } /* renameSelected */
@ -323,6 +340,13 @@ duplicateSelected( CeSavedGamesState* state )
getFullSelPath( state, curPath, VSIZE(curPath) ); getFullSelPath( state, curPath, VSIZE(curPath) );
confirmed = CopyFile( curPath, newPath, TRUE ); /* TRUE is what??? */ confirmed = CopyFile( curPath, newPath, TRUE ); /* TRUE is what??? */
} }
if ( confirmed ) {
ceBasename( state->newNameW, newPath );
} else {
state->newNameW[0] = 0;
}
return confirmed; return confirmed;
} /* duplicateSelected */ } /* duplicateSelected */
@ -415,11 +439,12 @@ SavedGamesDlg( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
wchar_t buf[128]; wchar_t buf[128];
XP_U16 len = VSIZE(buf); XP_U16 len = VSIZE(buf);
getComboText( state, buf, &len ); getComboText( state, buf, &len );
len = ceGetPath( state->dlgHdr.globals, DEFAULT_DIR_PATH_L, len = ceGetPath( state->dlgHdr.globals,
state->buf, state->buflen ); DEFAULT_DIR_PATH_L, state->buf,
state->buflen );
swprintf( &state->buf[len], L"%s.xwg", buf ); swprintf( &state->buf[len], L"%s.xwg", buf );
XP_LOGW( "returning", state->buf ); XP_LOGW( "returning", state->buf );
state->opened = XP_TRUE; state->result = CE_SVGAME_OPEN;
} }
/* fallthrough */ /* fallthrough */
case IDOK: /* Done button */ case IDOK: /* Done button */
@ -440,7 +465,7 @@ SavedGamesDlg( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
return result; return result;
} /* SavedGamesDlg */ } /* SavedGamesDlg */
XP_Bool SavedGamesResult
ceSavedGamesDlg( CEAppGlobals* globals, const XP_UCHAR* curPath, ceSavedGamesDlg( CEAppGlobals* globals, const XP_UCHAR* curPath,
wchar_t* buf, XP_U16 buflen ) wchar_t* buf, XP_U16 buflen )
{ {
@ -455,30 +480,27 @@ ceSavedGamesDlg( CEAppGlobals* globals, const XP_UCHAR* curPath,
state.sel = -1; state.sel = -1;
if ( !!curPath ) { if ( !!curPath ) {
wchar_t shortName[128]; wchar_t widebuf[MAX_PATH];
XP_U16 len; XP_U16 len;
XP_U16 dirLen;
dirLen = ceGetPath( globals, DEFAULT_DIR_PATH_L, shortName,
VSIZE(shortName) );
len = (XP_U16)XP_STRLEN( curPath ); len = (XP_U16)XP_STRLEN( curPath );
MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, curPath, len + 1, MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, curPath, len + 1,
shortName, len + 1 ); widebuf, len + 1 );
lstrcpy( state.curNameW, shortName+dirLen ); ceBasename( state.openNameW, widebuf );
} }
for ( ; ; ) { for ( ; ; ) {
state.relaunch = XP_FALSE;
state.result = CE_SVGAME_CANCEL;
(void)DialogBoxParam( globals->hInst, (LPCTSTR)IDD_SAVEDGAMESDLG, (void)DialogBoxParam( globals->hInst, (LPCTSTR)IDD_SAVEDGAMESDLG,
globals->hWnd, globals->hWnd,
(DLGPROC)SavedGamesDlg, (long)&state ); (DLGPROC)SavedGamesDlg, (long)&state );
if ( !state.relaunch ) { if ( !state.relaunch || (state.result == CE_SVGAME_RENAME) ) {
break; break;
} }
state.relaunch = XP_FALSE;
} }
XP_LOGW( __func__, buf ); XP_LOGW( __func__, buf );
return state.opened; return state.result;
} /* ceSavedGamesDlg */ } /* ceSavedGamesDlg */

View file

@ -23,8 +23,15 @@
#include "xptypes.h" #include "xptypes.h"
#include "cemain.h" #include "cemain.h"
XP_Bool ceSavedGamesDlg( CEAppGlobals* globals, const XP_UCHAR* curPath, typedef enum {
wchar_t* buf, XP_U16 buflen ); CE_SVGAME_CANCEL
,CE_SVGAME_RENAME
,CE_SVGAME_OPEN
} SavedGamesResult;
SavedGamesResult ceSavedGamesDlg( CEAppGlobals* globals,
const XP_UCHAR* curPath,
wchar_t* buf, XP_U16 buflen );
XP_Bool ceConfirmUniqueName( CEAppGlobals* globals, XP_U16 strId, wchar_t* buf, XP_Bool ceConfirmUniqueName( CEAppGlobals* globals, XP_U16 strId, wchar_t* buf,
XP_U16 buflen ); XP_U16 buflen );
#endif #endif

View file

@ -439,7 +439,7 @@ BEGIN
0, 0, 0, 0 0, 0, 0, 0
#endif #endif
COMBOBOX IDC_SVGM_GAMELIST_PPC,SVGM_LEFT_COL,SVGM_ROW_2,70,58, COMBOBOX IDC_SVGM_GAMELIST_PPC,SVGM_LEFT_COL,SVGM_ROW_2,70,58,
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP | CBS_SORT
PUSHBUTTON "Open",IDC_SVGM_OPEN, PUSHBUTTON "Open",IDC_SVGM_OPEN,
SVGM_LEFT_COL,SVGM_ROW_3,40,14,WS_DISABLED SVGM_LEFT_COL,SVGM_ROW_3,40,14,WS_DISABLED