Commit 7a34094e authored by Alex Henrie's avatar Alex Henrie Committed by Alexandre Julliard

comdlg32: Correctly handle filters with multiple file extensions in Save As dialogs.

parent 7d9ce823
......@@ -2533,12 +2533,12 @@ BOOL FILEDLG95_OnOpen(HWND hwnd)
/* Attach the file extension with file name*/
ext = PathFindExtensionW(lpstrPathAndFile);
if (! *ext)
if (! *ext && fodInfos->defext)
{
/* if no extension is specified with file name, then */
/* attach the extension from file filter or default one */
const WCHAR *filterExt = NULL;
WCHAR *filterExt = NULL;
LPWSTR lpstrFilter = NULL;
static const WCHAR szwDot[] = {'.',0};
int PathLength = lstrlenW(lpstrPathAndFile);
......@@ -2548,15 +2548,39 @@ BOOL FILEDLG95_OnOpen(HWND hwnd)
fodInfos->ofnInfos->nFilterIndex-1);
if (lpstrFilter != (LPWSTR)CB_ERR) /* control is not empty */
filterExt = PathFindExtensionW(lpstrFilter);
{
WCHAR* filterAtSemicolon;
filterExt = HeapAlloc(GetProcessHeap(), 0, lstrlenW(lpstrFilter) * sizeof(WCHAR) + sizeof(WCHAR));
strcpyW(filterExt, lpstrFilter);
/* if a semicolon-separated list of file extensions was given, do not include the
semicolon or anything after it in the extension.
example: if filterExt was "*.abc;*.def", it will become "*.abc" */
filterAtSemicolon = strchrW(filterExt, ';');
if (filterAtSemicolon)
{
filterAtSemicolon[0] = '\0';
}
/* strip the * or anything else from the extension, "*.abc" becomes "abc" */
strcpyW(filterExt, PathFindExtensionW(filterExt) + 1);
/* if the extension contains a glob, ignore it */
if (strchrW(filterExt, '*') || strchrW(filterExt, '?'))
{
HeapFree(GetProcessHeap(), 0, filterExt);
filterExt = NULL;
}
}
if ( filterExt && *filterExt ) /* attach the file extension from file type filter*/
filterExt = filterExt + 1;
else if ( fodInfos->defext ) /* attach the default file extension*/
filterExt = fodInfos->defext;
if (!filterExt)
{
/* use the default file extension */
filterExt = HeapAlloc(GetProcessHeap(), 0, lstrlenW(fodInfos->defext) * sizeof(WCHAR) + sizeof(WCHAR));
strcpyW(filterExt, fodInfos->defext);
}
/* If extension contains a glob, ignore it */
if ( filterExt && !strchrW(filterExt, '*') && !strchrW(filterExt, '?') )
if (*filterExt) /* ignore filterExt="" */
{
/* Attach the dot*/
lstrcatW(lpstrPathAndFile, szwDot);
......@@ -2564,20 +2588,19 @@ BOOL FILEDLG95_OnOpen(HWND hwnd)
lstrcatW(lpstrPathAndFile, filterExt );
}
HeapFree(GetProcessHeap(), 0, filterExt);
/* In Open dialog: if file does not exist try without extension */
if (!(fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG) && !PathFileExistsW(lpstrPathAndFile))
lpstrPathAndFile[PathLength] = '\0';
}
if (fodInfos->defext) /* add default extension */
{
/* 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;
/* 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;
}
/* In Save dialog: check if the file already exists */
......
......@@ -1044,51 +1044,90 @@ static UINT_PTR WINAPI test_extension_wndproc(HWND dlg, UINT msg, WPARAM wParam,
return FALSE;
}
static const char *defext_filters[] = {
"TestFilter (*.pt*)\0*.pt*\0",
"TestFilter (*.ab?)\0*.ab?\0",
"TestFilter (*.*)\0*.*\0",
NULL /* is a test, not an endmark! */
};
#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
static void test_extension_helper(OPENFILENAME* ofn, const char *filter,
const char *expected_filename)
{
char *filename_ptr;
DWORD ret;
BOOL boolret;
strcpy(ofn->lpstrFile, "deadbeef");
ofn->lpstrFilter = filter;
boolret = GetSaveFileNameA(ofn);
ok(boolret, "%s: expected TRUE\n", filter);
ret = CommDlgExtendedError();
ok(!ret, "%s: CommDlgExtendedError returned %#x\n", filter, ret);
filename_ptr = ofn->lpstrFile + ofn->nFileOffset;
ok(strcmp(filename_ptr, expected_filename) == 0,
"%s: Filename is %s, expected %s\n", filter, filename_ptr, expected_filename);
}
static void test_extension(void)
{
OPENFILENAME ofn = { sizeof(OPENFILENAME)};
char filename[1024] = {0};
char curdir[MAX_PATH];
char *filename_ptr;
const char *test_file_name = "deadbeef";
unsigned int i;
DWORD ret;
BOOL boolret;
const char *defext_concrete_filters[] = {
"TestFilter (*.abc)\0*.abc\0",
"TestFilter (*.abc;)\0*.abc;\0",
"TestFilter (*.abc;*.def)\0*.abc;*.def\0",
};
const char *defext_wildcard_filters[] = {
"TestFilter (*.pt*)\0*.pt*\0",
"TestFilter (*.pt*;*.abc)\0*.pt*;*.abc\0",
"TestFilter (*.ab?)\0*.ab?\0",
"TestFilter (*.*)\0*.*\0",
NULL /* is a test, not an endmark! */
};
boolret = GetCurrentDirectoryA(sizeof(curdir), curdir);
ok(boolret, "Failed to get current dir err %d\n", GetLastError());
/* Ignore .* extension */
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL;
ofn.lpstrFile = filename;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER | OFN_ENABLEHOOK;
ofn.lpstrDefExt = NULL;
ofn.lpstrInitialDir = curdir;
ofn.lpfnHook = test_extension_wndproc;
ofn.nFileExtension = 0;
for (i = 0; i < ARRAY_SIZE(defext_filters); i++) {
ofn.lpstrFilter = defext_filters[i];
strcpy(filename, test_file_name);
boolret = GetSaveFileNameA(&ofn);
ok(boolret, "%u: expected true\n", i);
ret = CommDlgExtendedError();
ok(!ret, "%u: CommDlgExtendedError returned %#x\n", i, ret);
filename_ptr = ofn.lpstrFile + strlen( ofn.lpstrFile ) - strlen( test_file_name );
ok( strlen(ofn.lpstrFile) >= strlen(test_file_name), "Filename %s is too short\n", ofn.lpstrFile );
ok( strcmp(filename_ptr, test_file_name) == 0,
"Filename is %s, expected %s\n", filename_ptr, test_file_name );
ofn.lpstrDefExt = NULL;
/* Without lpstrDefExt, append no extension */
test_extension_helper(&ofn, "TestFilter (*.abc) lpstrDefExt=NULL\0*.abc\0", "deadbeef");
test_extension_helper(&ofn, "TestFilter (*.ab?) lpstrDefExt=NULL\0*.ab?\0", "deadbeef");
ofn.lpstrDefExt = "";
/* If lpstrDefExt="" and the filter has a concrete extension, append it */
test_extension_helper(&ofn, "TestFilter (*.abc) lpstrDefExt=\"\"\0*.abc\0", "deadbeef.abc");
/* If lpstrDefExt="" and the filter has a wildcard extension, do nothing */
test_extension_helper(&ofn, "TestFilter (*.ab?) lpstrDefExt=\"\"\0*.ab?\0", "deadbeef");
ofn.lpstrDefExt = "xyz";
/* Append concrete extensions from filters */
for (i = 0; i < ARRAY_SIZE(defext_concrete_filters); i++) {
test_extension_helper(&ofn, defext_concrete_filters[i], "deadbeef.abc");
}
/* Append nothing from this filter */
test_extension_helper(&ofn, "TestFilter (*.)\0*.\0", "deadbeef");
/* Ignore wildcard extensions in filters */
for (i = 0; i < ARRAY_SIZE(defext_wildcard_filters); i++) {
test_extension_helper(&ofn, defext_wildcard_filters[i], "deadbeef.xyz");
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment