mirror of
https://github.com/reactos/reactos.git
synced 2025-05-01 19:50:36 +00:00
[COMDLG32] GetOpen/GetSaveFileName: Improve extension handling (#5640)
- Improve GetOpenFileName and GetSaveFileName functions. - Add FILEDLG95_GetFallbackExtension and FILEDLG95_AddDotExtIfNeeded helper functions. - Modify FILEDLG95_ValidatePathAction and FILEDLG95_OnOpen functions. CORE-19148, CORE-15020
This commit is contained in:
parent
f0995dac58
commit
d55e33d0f3
3 changed files with 118 additions and 95 deletions
|
@ -199,8 +199,14 @@ HRESULT FileSaveDialog_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
|
||||||
|
|
||||||
/* Shared helper functions */
|
/* Shared helper functions */
|
||||||
void COMDLG32_GetCanonicalPath(PCIDLIST_ABSOLUTE pidlAbsCurrent, LPWSTR lpstrFile, LPWSTR lpstrPathAndFile) DECLSPEC_HIDDEN;
|
void COMDLG32_GetCanonicalPath(PCIDLIST_ABSOLUTE pidlAbsCurrent, LPWSTR lpstrFile, LPWSTR lpstrPathAndFile) DECLSPEC_HIDDEN;
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
struct FileOpenDlgInfos;
|
||||||
|
int FILEDLG95_ValidatePathAction(struct FileOpenDlgInfos *fodInfos, LPWSTR lpstrPathAndFile, IShellFolder **ppsf,
|
||||||
|
HWND hwnd, DWORD flags, BOOL isSaveDlg, int defAction) DECLSPEC_HIDDEN;
|
||||||
|
#else
|
||||||
int FILEDLG95_ValidatePathAction(LPWSTR lpstrPathAndFile, IShellFolder **ppsf,
|
int FILEDLG95_ValidatePathAction(LPWSTR lpstrPathAndFile, IShellFolder **ppsf,
|
||||||
HWND hwnd, DWORD flags, BOOL isSaveDlg, int defAction) DECLSPEC_HIDDEN;
|
HWND hwnd, DWORD flags, BOOL isSaveDlg, int defAction) DECLSPEC_HIDDEN;
|
||||||
|
#endif
|
||||||
int COMDLG32_SplitFileNames(LPWSTR lpstrEdit, UINT nStrLen, LPWSTR *lpstrFileList, UINT *sizeUsed) DECLSPEC_HIDDEN;
|
int COMDLG32_SplitFileNames(LPWSTR lpstrEdit, UINT nStrLen, LPWSTR *lpstrFileList, UINT *sizeUsed) DECLSPEC_HIDDEN;
|
||||||
void FILEDLG95_OnOpenMessage(HWND hwnd, int idCaption, int idText) DECLSPEC_HIDDEN;
|
void FILEDLG95_OnOpenMessage(HWND hwnd, int idCaption, int idText) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
|
|
@ -2826,8 +2826,98 @@ void FILEDLG95_OnOpenMessage(HWND hwnd, int idCaption, int idText)
|
||||||
MessageBoxW(hwnd,strMsgText, strMsgTitle, MB_OK | MB_ICONHAND);
|
MessageBoxW(hwnd,strMsgText, strMsgTitle, MB_OK | MB_ICONHAND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
/* The return value needs LocalFree */
|
||||||
|
static LPWSTR FILEDLG95_GetFallbackExtension(FileOpenDlgInfos *fodInfos, LPWSTR lpstrPathAndFile)
|
||||||
|
{
|
||||||
|
LPWSTR lpstrFilter, the_ext = NULL, pchDot = NULL;
|
||||||
|
|
||||||
|
/* Without lpstrDefExt, append no extension */
|
||||||
|
if (!fodInfos->defext)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Get filter extensions */
|
||||||
|
lpstrFilter = (LPWSTR)CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,
|
||||||
|
fodInfos->ofnInfos->nFilterIndex - 1);
|
||||||
|
if (lpstrFilter != (LPWSTR)CB_ERR && lpstrFilter && *lpstrFilter)
|
||||||
|
{
|
||||||
|
LPWSTR pchSemicolon = wcschr(lpstrFilter, L';');
|
||||||
|
|
||||||
|
if (pchSemicolon)
|
||||||
|
*pchSemicolon = UNICODE_NULL;
|
||||||
|
|
||||||
|
pchDot = wcschr(lpstrFilter, L'.');
|
||||||
|
|
||||||
|
if (pchDot && pchDot[1] && !wcschr(pchDot, L'*') && !wcschr(pchDot, L'?'))
|
||||||
|
the_ext = StrDupW(pchDot + 1);
|
||||||
|
|
||||||
|
if (pchSemicolon)
|
||||||
|
*pchSemicolon = L';';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!the_ext && (!pchDot || pchDot[1]))
|
||||||
|
{
|
||||||
|
/* use default extension if no extension in filter */
|
||||||
|
the_ext = StrDupW(fodInfos->defext);
|
||||||
|
}
|
||||||
|
|
||||||
|
return the_ext;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL
|
||||||
|
FILEDLG95_AddDotExtIfNeeded(FileOpenDlgInfos *fodInfos, LPWSTR lpstrPathAndFile)
|
||||||
|
{
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
LPWSTR ext = PathFindExtensionW(lpstrPathAndFile);
|
||||||
|
int PathLength = lstrlenW(lpstrPathAndFile);
|
||||||
|
LPWSTR the_ext = FILEDLG95_GetFallbackExtension(fodInfos, lpstrPathAndFile);
|
||||||
|
|
||||||
|
if (the_ext && *the_ext &&
|
||||||
|
(*ext == UNICODE_NULL || lstrcmpiW(ext + 1, the_ext) != 0))
|
||||||
|
{
|
||||||
|
if (strlenW(lpstrPathAndFile) + 1 + strlenW(the_ext) + 1 <=
|
||||||
|
fodInfos->ofnInfos->nMaxFile)
|
||||||
|
{
|
||||||
|
/* Make the extension lowercase */
|
||||||
|
CharLowerW(the_ext);
|
||||||
|
/* Append it (with dot) to the file */
|
||||||
|
lstrcatW(lpstrPathAndFile, L".");
|
||||||
|
lstrcatW(lpstrPathAndFile, the_ext);
|
||||||
|
/* update ext */
|
||||||
|
ext = PathFindExtensionW(lpstrPathAndFile);
|
||||||
|
ret = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalFree(the_ext);
|
||||||
|
|
||||||
|
/* In Open dialog: if file does not exist try without extension */
|
||||||
|
if (!(fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG) && !PathFileExistsW(lpstrPathAndFile))
|
||||||
|
{
|
||||||
|
lpstrPathAndFile[PathLength] = UNICODE_NULL;
|
||||||
|
ret = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set/clear the output OFN_EXTENSIONDIFFERENT flag */
|
||||||
|
if (*ext)
|
||||||
|
ext++;
|
||||||
|
if (!lstrcmpiW(fodInfos->defext, ext))
|
||||||
|
fodInfos->ofnInfos->Flags &= ~OFN_EXTENSIONDIFFERENT;
|
||||||
|
else
|
||||||
|
fodInfos->ofnInfos->Flags |= OFN_EXTENSIONDIFFERENT;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
int FILEDLG95_ValidatePathAction(struct FileOpenDlgInfos *fodInfos, LPWSTR lpstrPathAndFile,
|
||||||
|
IShellFolder **ppsf, HWND hwnd, DWORD flags, BOOL isSaveDlg,
|
||||||
|
int defAction)
|
||||||
|
#else
|
||||||
int FILEDLG95_ValidatePathAction(LPWSTR lpstrPathAndFile, IShellFolder **ppsf,
|
int FILEDLG95_ValidatePathAction(LPWSTR lpstrPathAndFile, IShellFolder **ppsf,
|
||||||
HWND hwnd, DWORD flags, BOOL isSaveDlg, int defAction)
|
HWND hwnd, DWORD flags, BOOL isSaveDlg, int defAction)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
int nOpenAction = defAction;
|
int nOpenAction = defAction;
|
||||||
LPWSTR lpszTemp, lpszTemp1;
|
LPWSTR lpszTemp, lpszTemp1;
|
||||||
|
@ -2924,9 +3014,18 @@ int FILEDLG95_ValidatePathAction(LPWSTR lpstrPathAndFile, IShellFolder **ppsf,
|
||||||
{
|
{
|
||||||
if( (flags & OFN_FILEMUSTEXIST) && !isSaveDlg )
|
if( (flags & OFN_FILEMUSTEXIST) && !isSaveDlg )
|
||||||
{
|
{
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
FILEDLG95_AddDotExtIfNeeded(fodInfos, lpstrPathAndFile);
|
||||||
|
if (!PathFileExistsW(lpstrPathAndFile))
|
||||||
|
{
|
||||||
FILEDLG95_OnOpenMessage(hwnd, 0, IDS_FILENOTEXISTING);
|
FILEDLG95_OnOpenMessage(hwnd, 0, IDS_FILENOTEXISTING);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
FILEDLG95_OnOpenMessage(hwnd, 0, IDS_FILENOTEXISTING);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* change to the current folder */
|
/* change to the current folder */
|
||||||
nOpenAction = ONOPEN_OPEN;
|
nOpenAction = ONOPEN_OPEN;
|
||||||
|
@ -3011,7 +3110,11 @@ BOOL FILEDLG95_OnOpen(HWND hwnd)
|
||||||
else
|
else
|
||||||
nOpenAction = ONOPEN_BROWSE;
|
nOpenAction = ONOPEN_BROWSE;
|
||||||
|
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
nOpenAction = FILEDLG95_ValidatePathAction(fodInfos, lpstrPathAndFile, &lpsf, hwnd,
|
||||||
|
#else
|
||||||
nOpenAction = FILEDLG95_ValidatePathAction(lpstrPathAndFile, &lpsf, hwnd,
|
nOpenAction = FILEDLG95_ValidatePathAction(lpstrPathAndFile, &lpsf, hwnd,
|
||||||
|
#endif
|
||||||
fodInfos->ofnInfos->Flags,
|
fodInfos->ofnInfos->Flags,
|
||||||
fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG,
|
fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG,
|
||||||
nOpenAction);
|
nOpenAction);
|
||||||
|
@ -3088,7 +3191,9 @@ BOOL FILEDLG95_OnOpen(HWND hwnd)
|
||||||
case ONOPEN_OPEN: /* fill in the return struct and close the dialog */
|
case ONOPEN_OPEN: /* fill in the return struct and close the dialog */
|
||||||
TRACE("ONOPEN_OPEN %s\n", debugstr_w(lpstrPathAndFile));
|
TRACE("ONOPEN_OPEN %s\n", debugstr_w(lpstrPathAndFile));
|
||||||
{
|
{
|
||||||
|
#ifndef __REACTOS__
|
||||||
WCHAR *ext = NULL;
|
WCHAR *ext = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* update READONLY check box flag */
|
/* update READONLY check box flag */
|
||||||
if ((SendMessageW(GetDlgItem(hwnd,IDC_OPENREADONLY),BM_GETCHECK,0,0) & 0x03) == BST_CHECKED)
|
if ((SendMessageW(GetDlgItem(hwnd,IDC_OPENREADONLY),BM_GETCHECK,0,0) & 0x03) == BST_CHECKED)
|
||||||
|
@ -3097,104 +3202,13 @@ BOOL FILEDLG95_OnOpen(HWND hwnd)
|
||||||
fodInfos->ofnInfos->Flags &= ~OFN_READONLY;
|
fodInfos->ofnInfos->Flags &= ~OFN_READONLY;
|
||||||
|
|
||||||
/* Attach the file extension with file name*/
|
/* Attach the file extension with file name*/
|
||||||
ext = PathFindExtensionW(lpstrPathAndFile);
|
|
||||||
#ifdef __REACTOS__
|
#ifdef __REACTOS__
|
||||||
if (*ext == UNICODE_NULL && fodInfos->defext)
|
/* Add extension if necessary */
|
||||||
{
|
FILEDLG95_AddDotExtIfNeeded(fodInfos, lpstrPathAndFile);
|
||||||
LPWSTR filterExt = NULL, lpstrFilter = NULL, pch, pchNext;
|
|
||||||
LPCWSTR the_ext = NULL;
|
|
||||||
static const WCHAR szwDot[] = {'.',0};
|
|
||||||
int PathLength = lstrlenW(lpstrPathAndFile);
|
|
||||||
|
|
||||||
/* get filter extensions */
|
|
||||||
lpstrFilter = (LPWSTR) CBGetItemDataPtr(fodInfos->DlgInfos.hwndFileTypeCB,
|
|
||||||
fodInfos->ofnInfos->nFilterIndex - 1);
|
|
||||||
if (lpstrFilter != (LPWSTR)CB_ERR) /* control is not empty */
|
|
||||||
{
|
|
||||||
LPWSTR filterSearchIndex, pchFirst = NULL;
|
|
||||||
filterExt = heap_alloc((lstrlenW(lpstrFilter) + 1) * sizeof(WCHAR));
|
|
||||||
if (filterExt)
|
|
||||||
{
|
|
||||||
strcpyW(filterExt, lpstrFilter);
|
|
||||||
|
|
||||||
if (ext && *ext)
|
|
||||||
{
|
|
||||||
/* find ext in filter */
|
|
||||||
for (pch = filterExt; pch && *pch; pch = pchNext)
|
|
||||||
{
|
|
||||||
filterSearchIndex = strchrW(pch, ';');
|
|
||||||
if (filterSearchIndex)
|
|
||||||
{
|
|
||||||
filterSearchIndex[0] = 0;
|
|
||||||
pchNext = filterSearchIndex + 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pchNext = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (*pch == '*' || *pch == '.' || *pch == '?')
|
|
||||||
{
|
|
||||||
++pch;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pchFirst)
|
|
||||||
pchFirst = pch;
|
|
||||||
|
|
||||||
if (lstrcmpiW(pch, &ext[1]) == 0)
|
|
||||||
{
|
|
||||||
the_ext = pch;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* use first one if not found */
|
|
||||||
if (!the_ext && pchFirst && *pchFirst)
|
|
||||||
{
|
|
||||||
the_ext = pchFirst;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!the_ext)
|
|
||||||
{
|
|
||||||
/* use default extension if no extension in filter */
|
|
||||||
the_ext = fodInfos->defext;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (the_ext && *the_ext && lstrcmpiW(&ext[1], the_ext) != 0)
|
|
||||||
{
|
|
||||||
if (strlenW(lpstrPathAndFile) + 1 + strlenW(the_ext) + 1 <=
|
|
||||||
fodInfos->ofnInfos->nMaxFile)
|
|
||||||
{
|
|
||||||
/* append the dot */
|
|
||||||
lstrcatW(lpstrPathAndFile, szwDot);
|
|
||||||
/* append the extension */
|
|
||||||
lstrcatW(lpstrPathAndFile, the_ext);
|
|
||||||
/* update ext */
|
|
||||||
ext = PathFindExtensionW(lpstrPathAndFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
heap_free(filterExt);
|
|
||||||
|
|
||||||
/* In Open dialog: if file does not exist try without extension */
|
|
||||||
if (!(fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG) && !PathFileExistsW(lpstrPathAndFile))
|
|
||||||
lpstrPathAndFile[PathLength] = 0;
|
|
||||||
|
|
||||||
/* Set/clear the output OFN_EXTENSIONDIFFERENT flag */
|
|
||||||
if (*ext)
|
|
||||||
ext++;
|
|
||||||
if (!lstrcmpiW(fodInfos->defext, ext))
|
|
||||||
fodInfos->ofnInfos->Flags &= ~OFN_EXTENSIONDIFFERENT;
|
|
||||||
else
|
|
||||||
fodInfos->ofnInfos->Flags |= OFN_EXTENSIONDIFFERENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* update dialog data */
|
/* update dialog data */
|
||||||
SetWindowTextW(fodInfos->DlgInfos.hwndFileName, PathFindFileNameW(lpstrPathAndFile));
|
SetWindowTextW(fodInfos->DlgInfos.hwndFileName, PathFindFileNameW(lpstrPathAndFile));
|
||||||
#else /* __REACTOS__ */
|
#else /* __REACTOS__ */
|
||||||
|
ext = PathFindExtensionW(lpstrPathAndFile);
|
||||||
if (! *ext && fodInfos->defext)
|
if (! *ext && fodInfos->defext)
|
||||||
{
|
{
|
||||||
/* if no extension is specified with file name, then */
|
/* if no extension is specified with file name, then */
|
||||||
|
|
|
@ -47,8 +47,11 @@
|
||||||
* Data structure
|
* Data structure
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
typedef struct FileOpenDlgInfos
|
||||||
|
#else
|
||||||
typedef struct
|
typedef struct
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
LPOPENFILENAMEW ofnInfos;
|
LPOPENFILENAMEW ofnInfos;
|
||||||
BOOL unicode;
|
BOOL unicode;
|
||||||
|
|
Loading…
Reference in a new issue