diff --git a/xwords4/wince/cemain.c b/xwords4/wince/cemain.c index a917e596d..fefbdf5c5 100755 --- a/xwords4/wince/cemain.c +++ b/xwords4/wince/cemain.c @@ -1623,23 +1623,26 @@ static void ceChooseAndOpen( CEAppGlobals* globals ) { // Save in case we'll be duplicating it + again: if ( ceSaveCurGame( globals, XP_FALSE ) || queryBoxChar( globals, "Do you really want to " "overwrite the current game?" ) ) { - wchar_t path[256]; - path[0] = 0; + SavedGamesResult choice; + wchar_t newName[256]; + newName[0] = 0; ceSetTitleFromName( globals ); /* in case we named it above */ - if ( ceSavedGamesDlg( globals, globals->curGameName, - path, VSIZE(path) )) { + choice = ceSavedGamesDlg( globals, globals->curGameName, newName, + VSIZE(newName) ); + if ( CE_SVGAME_CANCEL != choice ) { XP_UCHAR* name; XP_U16 len; - len = wcslen(path); + len = wcslen(newName); 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 ); if ( globals->curGameName != NULL @@ -1660,10 +1663,19 @@ ceChooseAndOpen( CEAppGlobals* globals ) globals->curGameName = NULL; /* prevent being destroyed */ 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; if ( ceLoadSavedGame( globals ) ) { XP_FREE( globals->mpool, oldName ); } else { + XP_ASSERT( CE_SVGAME_RENAME != choice ); XP_LOGF( "failed to open chosen game" ); XP_FREE( globals->mpool, globals->curGameName ); globals->curGameName = oldName; @@ -1672,6 +1684,9 @@ ceChooseAndOpen( CEAppGlobals* globals ) } } ceInitAndStartBoard( globals, XP_FALSE, NULL ); + if ( CE_SVGAME_RENAME == choice ) { + goto again; + } } } else { XP_LOGF( "GetOpenFileName() failed" ); diff --git a/xwords4/wince/cesvdgms.c b/xwords4/wince/cesvdgms.c index d8d12387b..dbdfc0fa3 100644 --- a/xwords4/wince/cesvdgms.c +++ b/xwords4/wince/cesvdgms.c @@ -168,17 +168,39 @@ typedef struct CeSavedGamesState { CeDlgHdr dlgHdr; wchar_t* buf; XP_U16 buflen; - XP_S16 sel; - XP_U16 openGameIndex; - wchar_t curNameW[128]; + XP_S16 sel; /* index of game name currently selected */ + XP_U16 openGameIndex; /* index of game that's open */ + wchar_t openNameW[128]; + wchar_t newNameW[MAX_PATH]; XP_U16 nItems; XP_U16 gameListId; - XP_Bool opened; XP_Bool inited; XP_Bool relaunch; + SavedGamesResult result; } 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 */ static void 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_DUP, haveItem ); ceEnOrDisable( hDlg, IDC_SVGM_DEL, haveItem && !curSelected ); - ceEnOrDisable( hDlg, IDC_SVGM_CHANGE, haveItem && !curSelected ); + ceEnOrDisable( hDlg, IDC_SVGM_CHANGE, haveItem ); } static void @@ -231,7 +253,7 @@ initSavedGamesData( CeSavedGamesState* state ) CEAppGlobals* globals = state->dlgHdr.globals; WIN32_FIND_DATA data; wchar_t path[CE_MAX_PATH_LEN]; - XP_S16 curSel = -1; + XP_S16 sel; XP_U16 ii; XP_U16 nItems = 0; @@ -242,40 +264,13 @@ initSavedGamesData( CeSavedGamesState* state ) 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->curNameW, data.cFileName ); - XP_ASSERT( data.cFileName[len-4] == '.'); + XP_ASSERT( data.cFileName[len-4] == L'.'); 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, - INSERTSTRING(globals), - item, (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 */ - } - + ADDSTRING(globals), + 0, (LPARAM)data.cFileName ); ++nItems; if ( !FindNextFile( fileH, &data ) ) { @@ -283,29 +278,51 @@ initSavedGamesData( CeSavedGamesState* state ) break; } } - state->nItems = nItems; - state->openGameIndex = curSel; - SendDlgItemMessage( hDlg, state->gameListId, - SETCURSEL(globals), curSel, 0 ); - state->sel = curSel; + /* Now locate the open game and game we should select (which may + differ) */ + 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 ); - - LOG_RETURN_VOID(); } /* initSavedGamesData */ static XP_Bool renameSelected( CeSavedGamesState* state ) { - wchar_t path[MAX_PATH]; + wchar_t newPath[MAX_PATH]; XP_Bool confirmed = ceConfirmUniqueName( state->dlgHdr.globals, IDS_RENAME, - path, VSIZE(path) ); + newPath, VSIZE(newPath) ); if ( confirmed ) { - wchar_t curPath[MAX_PATH]; - getFullSelPath( state, curPath, VSIZE(curPath) ); - confirmed = MoveFile( curPath, path ); + /* If we're renaming the current game, we have to exit and let + calling code handle it. If we're renaming any other game, we can + 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; } /* renameSelected */ @@ -323,6 +340,13 @@ duplicateSelected( CeSavedGamesState* state ) getFullSelPath( state, curPath, VSIZE(curPath) ); confirmed = CopyFile( curPath, newPath, TRUE ); /* TRUE is what??? */ } + + if ( confirmed ) { + ceBasename( state->newNameW, newPath ); + } else { + state->newNameW[0] = 0; + } + return confirmed; } /* duplicateSelected */ @@ -415,11 +439,12 @@ SavedGamesDlg( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) wchar_t buf[128]; XP_U16 len = VSIZE(buf); getComboText( state, buf, &len ); - len = ceGetPath( state->dlgHdr.globals, DEFAULT_DIR_PATH_L, - state->buf, state->buflen ); + 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; + state->result = CE_SVGAME_OPEN; } /* fallthrough */ case IDOK: /* Done button */ @@ -440,7 +465,7 @@ SavedGamesDlg( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) return result; } /* SavedGamesDlg */ -XP_Bool +SavedGamesResult ceSavedGamesDlg( CEAppGlobals* globals, const XP_UCHAR* curPath, wchar_t* buf, XP_U16 buflen ) { @@ -455,30 +480,27 @@ ceSavedGamesDlg( CEAppGlobals* globals, const XP_UCHAR* curPath, state.sel = -1; if ( !!curPath ) { - wchar_t shortName[128]; + wchar_t widebuf[MAX_PATH]; XP_U16 len; - 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 ); - lstrcpy( state.curNameW, shortName+dirLen ); + widebuf, len + 1 ); + ceBasename( state.openNameW, widebuf ); } for ( ; ; ) { + state.relaunch = XP_FALSE; + state.result = CE_SVGAME_CANCEL; + (void)DialogBoxParam( globals->hInst, (LPCTSTR)IDD_SAVEDGAMESDLG, globals->hWnd, (DLGPROC)SavedGamesDlg, (long)&state ); - if ( !state.relaunch ) { + if ( !state.relaunch || (state.result == CE_SVGAME_RENAME) ) { break; } - state.relaunch = XP_FALSE; } XP_LOGW( __func__, buf ); - return state.opened; + return state.result; } /* ceSavedGamesDlg */ diff --git a/xwords4/wince/cesvdgms.h b/xwords4/wince/cesvdgms.h index 48c3aa51a..87ebb449d 100644 --- a/xwords4/wince/cesvdgms.h +++ b/xwords4/wince/cesvdgms.h @@ -23,8 +23,15 @@ #include "xptypes.h" #include "cemain.h" -XP_Bool ceSavedGamesDlg( CEAppGlobals* globals, const XP_UCHAR* curPath, - wchar_t* buf, XP_U16 buflen ); +typedef enum { + 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_U16 buflen ); #endif diff --git a/xwords4/wince/xwords4.rc b/xwords4/wince/xwords4.rc index 978f16648..2687300e2 100755 --- a/xwords4/wince/xwords4.rc +++ b/xwords4/wince/xwords4.rc @@ -439,7 +439,7 @@ BEGIN 0, 0, 0, 0 #endif 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, SVGM_LEFT_COL,SVGM_ROW_3,40,14,WS_DISABLED