*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <ctype.h>
#include <stdlib.h>
#include "winuser.h"
#include "wine/unicode.h"
#include "wine/debug.h"
-#include "cderr.h"
#include "winreg.h"
#include "winternl.h"
-#include "winuser.h"
#include "commdlg.h"
-#include "cderr.h"
-#include "winreg.h"
-#include "winternl.h"
#include "shlwapi.h"
WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
*
* Call the appropriate hook
*/
-BOOL FD31_CallWindowProc(PFD31_DATA lfs, UINT wMsg, WPARAM wParam,
+BOOL FD31_CallWindowProc(const FD31_DATA *lfs, UINT wMsg, WPARAM wParam,
LPARAM lParam)
{
- return lfs->callbacks->CWP(lfs, wMsg, wParam, lParam);
+ BOOL ret;
+
+ if (lfs->ofnA)
+ {
+ TRACE("Call hookA %p (%p, %04x, %08lx, %08lx)\n",
+ lfs->ofnA->lpfnHook, lfs->hwnd, wMsg, wParam, lParam);
+ ret = lfs->ofnA->lpfnHook(lfs->hwnd, wMsg, wParam, lParam);
+ TRACE("ret hookA %p (%p, %04x, %08lx, %08lx)\n",
+ lfs->ofnA->lpfnHook, lfs->hwnd, wMsg, wParam, lParam);
+ return ret;
+ }
+
+ TRACE("Call hookW %p (%p, %04x, %08lx, %08lx)\n",
+ lfs->ofnW->lpfnHook, lfs->hwnd, wMsg, wParam, lParam);
+ ret = lfs->ofnW->lpfnHook(lfs->hwnd, wMsg, wParam, lParam);
+ TRACE("Ret hookW %p (%p, %04x, %08lx, %08lx)\n",
+ lfs->ofnW->lpfnHook, lfs->hwnd, wMsg, wParam, lParam);
+ return ret;
+}
+
+/***********************************************************************
+ * FD31_GetFileType [internal]
+ */
+static LPCWSTR FD31_GetFileType(LPCWSTR cfptr, LPCWSTR fptr, const WORD index)
+{
+ int n, i;
+ i = 0;
+ if (cfptr)
+ for ( ;(n = lstrlenW(cfptr)) != 0; i++)
+ {
+ cfptr += n + 1;
+ if (i == index)
+ return cfptr;
+ cfptr += lstrlenW(cfptr) + 1;
+ }
+ if (fptr)
+ for ( ;(n = lstrlenW(fptr)) != 0; i++)
+ {
+ fptr += n + 1;
+ if (i == index)
+ return fptr;
+ fptr += lstrlenW(fptr) + 1;
+ }
+ return FILE_star; /* FIXME */
}
/***********************************************************************
* FD31_ScanDir [internal]
*/
-static BOOL FD31_ScanDir(HWND hWnd, LPWSTR newPath)
+static BOOL FD31_ScanDir(const OPENFILENAMEW *ofn, HWND hWnd, LPCWSTR newPath)
{
- WCHAR buffer[BUFFILE];
- HWND hdlg, hdlgDir;
- LRESULT lRet = TRUE;
- HCURSOR hCursorWait, oldCursor;
+ WCHAR buffer[BUFFILE];
+ HWND hdlg;
+ LRESULT lRet = TRUE;
+ HCURSOR hCursorWait, oldCursor;
TRACE("Trying to change to %s\n", debugstr_w(newPath));
if ( newPath[0] && !SetCurrentDirectoryW( newPath ))
return FALSE;
- lstrcpynW(buffer, newPath, sizeof(buffer)/sizeof(WCHAR));
/* get the list of spec files */
- GetDlgItemTextW(hWnd, edt1, buffer, sizeof(buffer)/sizeof(WCHAR));
+ lstrcpynW(buffer, FD31_GetFileType(ofn->lpstrCustomFilter,
+ ofn->lpstrFilter, ofn->nFilterIndex - 1), BUFFILE);
hCursorWait = LoadCursorA(0, (LPSTR)IDC_WAIT);
oldCursor = SetCursor(hCursorWait);
if (scptr) *scptr = 0;
while (*filter == ' ') filter++;
TRACE("Using file spec %s\n", debugstr_w(filter));
- if (SendMessageW(hdlg, LB_DIR, 0, (LPARAM)filter) == LB_ERR)
- return FALSE;
+ SendMessageW(hdlg, LB_DIR, 0, (LPARAM)filter);
if (scptr) *scptr = ';';
filter = (scptr) ? (scptr + 1) : 0;
}
/* list of directories */
strcpyW(buffer, FILE_star);
- if ((hdlgDir = GetDlgItem(hWnd, lst2)) != 0) {
+ if (GetDlgItem(hWnd, lst2) != 0) {
lRet = DlgDirListW(hWnd, buffer, lst2, stc1, DDL_EXCLUSIVE | DDL_DIRECTORY);
}
SetCursor(oldCursor);
return lRet;
}
-/***********************************************************************
- * FD31_GetFileType [internal]
- */
-
-static LPWSTR FD31_GetFileType(LPWSTR cfptr, LPWSTR fptr, WORD index)
-{
- int n, i;
- i = 0;
- if (cfptr)
- for ( ;(n = lstrlenW(cfptr)) != 0; i++)
- {
- cfptr += n + 1;
- if (i == index)
- return cfptr;
- cfptr += lstrlenW(cfptr) + 1;
- }
- if (fptr)
- for ( ;(n = lstrlenW(fptr)) != 0; i++)
- {
- fptr += n + 1;
- if (i == index)
- return fptr;
- fptr += lstrlenW(fptr) + 1;
- }
- return (LPWSTR) FILE_star; /* FIXME */
-}
-
/***********************************************************************
* FD31_WMDrawItem [internal]
*/
LONG FD31_WMDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam,
- int savedlg, LPDRAWITEMSTRUCT lpdis)
+ int savedlg, const DRAWITEMSTRUCT *lpdis)
{
WCHAR *str;
HICON hIcon;
SetBkColor( lpdis->hDC, oldBk );
SetTextColor( lpdis->hDC, oldText );
}
- DrawIcon(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hFolder);
+ DrawIconEx( lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hFolder, 16, 16, 0, 0, DI_NORMAL );
HeapFree(GetProcessHeap(), 0, str);
return TRUE;
}
SetBkColor( lpdis->hDC, oldBk );
SetTextColor( lpdis->hDC, oldText );
}
- DrawIcon(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hIcon);
+ DrawIconEx( lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hIcon, 16, 16, 0, 0, DI_NORMAL );
HeapFree(GetProcessHeap(), 0, str);
return TRUE;
}
* FD31_UpdateResult [internal]
* update the displayed file name (with path)
*/
-static void FD31_UpdateResult(PFD31_DATA lfs, WCHAR *tmpstr)
+static void FD31_UpdateResult(const FD31_DATA *lfs, const WCHAR *tmpstr)
{
int lenstr2;
LPOPENFILENAMEW ofnW = lfs->ofnW;
+ LPOPENFILENAMEA ofnA = lfs->ofnA;
WCHAR tmpstr2[BUFFILE];
WCHAR *p;
if (lenstr2 > 3)
tmpstr2[lenstr2++]='\\';
lstrcpynW(tmpstr2+lenstr2, tmpstr, BUFFILE-lenstr2);
- if (ofnW->lpstrFile)
- lstrcpynW(ofnW->lpstrFile, tmpstr2, ofnW->nMaxFile);
+ if (!ofnW->lpstrFile)
+ return;
+
+ lstrcpynW(ofnW->lpstrFile, tmpstr2, ofnW->nMaxFile);
/* set filename offset */
p = PathFindFileNameW(ofnW->lpstrFile);
debugstr_w(ofnW->lpstrFile), ofnW->nFileOffset, ofnW->nFileExtension);
/* update the real client structures if any */
- lfs->callbacks->UpdateResult(lfs);
+ if (ofnA)
+ {
+ LPSTR lpszTemp;
+ if (ofnW->nMaxFile &&
+ !WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFile, -1,
+ ofnA->lpstrFile, ofnA->nMaxFile, NULL, NULL ))
+ ofnA->lpstrFile[ofnA->nMaxFile-1] = 0;
+
+ /* offsets are not guaranteed to be the same in WCHAR to MULTIBYTE conversion */
+ /* set filename offset */
+ lpszTemp = PathFindFileNameA(ofnA->lpstrFile);
+ ofnA->nFileOffset = (lpszTemp - ofnA->lpstrFile);
+
+ /* set extension offset */
+ lpszTemp = PathFindExtensionA(ofnA->lpstrFile);
+ ofnA->nFileExtension = (*lpszTemp) ? (lpszTemp - ofnA->lpstrFile) + 1 : 0;
+ }
}
/***********************************************************************
* FD31_UpdateFileTitle [internal]
* update the displayed file name (without path)
*/
-static void FD31_UpdateFileTitle(PFD31_DATA lfs)
+static void FD31_UpdateFileTitle(const FD31_DATA *lfs)
{
LONG lRet;
LPOPENFILENAMEW ofnW = lfs->ofnW;
+ LPOPENFILENAMEA ofnA = lfs->ofnA;
+
if (ofnW->lpstrFileTitle != NULL)
{
lRet = SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETCURSEL, 0, 0);
SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETTEXT, lRet,
(LPARAM)ofnW->lpstrFileTitle );
- lfs->callbacks->UpdateFileTitle(lfs);
+ if (ofnA)
+ {
+ if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFileTitle, -1,
+ ofnA->lpstrFileTitle, ofnA->nMaxFileTitle, NULL, NULL ))
+ ofnA->lpstrFileTitle[ofnA->nMaxFileTitle-1] = 0;
+ }
}
}
/***********************************************************************
* FD31_DirListDblClick [internal]
*/
-static LRESULT FD31_DirListDblClick( PFD31_DATA lfs )
+static LRESULT FD31_DirListDblClick( const FD31_DATA *lfs )
{
LONG lRet;
HWND hWnd = lfs->hwnd;
}
strcatW(tmpstr, FILE_bslash);
- FD31_ScanDir(hWnd, tmpstr);
+ FD31_ScanDir(lfs->ofnW, hWnd, tmpstr);
/* notify the app */
if (lfs->hook)
{
* FD31_FileListSelect [internal]
* called when a new item is picked in the file list
*/
-static LRESULT FD31_FileListSelect( PFD31_DATA lfs )
+static LRESULT FD31_FileListSelect( const FD31_DATA *lfs )
{
LONG lRet;
HWND hWnd = lfs->hwnd;
LPWSTR pstr;
- lRet = lfs->callbacks->SendLbGetCurSel(lfs);
+ lRet = SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETCURSEL, 0, 0);
if (lRet == LB_ERR)
return TRUE;
* before accepting the file name, test if it includes wild cards
* tries to scan the directory and returns TRUE if no error.
*/
-static LRESULT FD31_TestPath( PFD31_DATA lfs, LPWSTR path )
+static LRESULT FD31_TestPath( const FD31_DATA *lfs, LPWSTR path )
{
HWND hWnd = lfs->hwnd;
LPWSTR pBeginFileName, pstr2;
TRACE("path=%s, tmpstr2=%s\n", debugstr_w(path), debugstr_w(tmpstr2));
SetDlgItemTextW( hWnd, edt1, tmpstr2 );
- FD31_ScanDir(hWnd, path);
+ FD31_ScanDir(lfs->ofnW, hWnd, path);
return (lfs->ofnW->Flags & OFN_NOVALIDATE) ? TRUE : FALSE;
}
strcatW(path, FILE_bslash);
/* if ScanDir succeeds, we have changed the directory */
- if (FD31_ScanDir(hWnd, path))
+ if (FD31_ScanDir(lfs->ofnW, hWnd, path))
return FALSE; /* and path is not a valid file name */
/* if not, this must be a filename */
lstrcpynW(tmpstr2, pBeginFileName + 1, sizeof(tmpstr2)/sizeof(WCHAR) );
/* Should we MessageBox() if this fails? */
- if (!FD31_ScanDir(hWnd, path))
+ if (!FD31_ScanDir(lfs->ofnW, hWnd, path))
{
return FALSE;
}
* FD31_Validate [internal]
* called on: click Ok button, Enter in edit, DoubleClick in file list
*/
-static LRESULT FD31_Validate( PFD31_DATA lfs, LPWSTR path, UINT control, INT itemIndex,
+static LRESULT FD31_Validate( const FD31_DATA *lfs, LPCWSTR path, UINT control, INT itemIndex,
BOOL internalUse )
{
LONG lRet;
FD31_UpdateFileTitle(lfs);
if (lfs->hook)
{
- lRet = (BOOL)FD31_CallWindowProc(lfs, lfs->fileokstring,
+ lRet = FD31_CallWindowProc(lfs, lfs->fileokstring,
0, lfs->lParam );
if (lRet)
{
{
if (ofnW->lpstrFile)
{
- LPWSTR str = (LPWSTR)ofnW->lpstrFile;
+ LPWSTR str = ofnW->lpstrFile;
LPWSTR ptr = strrchrW(str, '\\');
str[lstrlenW(str) + 1] = '\0';
*ptr = 0;
* FD31_DiskChange [internal]
* called when a new item is picked in the disk selection combo
*/
-static LRESULT FD31_DiskChange( PFD31_DATA lfs )
+static LRESULT FD31_DiskChange( const FD31_DATA *lfs )
{
LONG lRet;
HWND hWnd = lfs->hwnd;
* FD31_FileTypeChange [internal]
* called when a new item is picked in the file type combo
*/
-static LRESULT FD31_FileTypeChange( PFD31_DATA lfs )
+static LRESULT FD31_FileTypeChange( const FD31_DATA *lfs )
{
LONG lRet;
LPWSTR pstr;
return TRUE;
pstr = (LPWSTR)SendDlgItemMessageW(lfs->hwnd, cmb1, CB_GETITEMDATA, lRet, 0);
TRACE("Selected filter : %s\n", debugstr_w(pstr));
- SetDlgItemTextW( lfs->hwnd, edt1, pstr );
return FD31_Validate( lfs, NULL, cmb1, lRet, TRUE );
}
* FD31_WMCommand [internal]
*/
LRESULT FD31_WMCommand(HWND hWnd, LPARAM lParam, UINT notification,
- UINT control, PFD31_DATA lfs )
+ UINT control, const FD31_DATA *lfs )
{
switch (control)
{
/************************************************************************
* FD31_MapOfnStructA [internal]
- * map a 32 bits Ansi structure to an Unicode one
+ * map a 32 bits Ansi structure to a Unicode one
*/
-void FD31_MapOfnStructA(const LPOPENFILENAMEA ofnA, LPOPENFILENAMEW ofnW, BOOL open)
+void FD31_MapOfnStructA(const OPENFILENAMEA *ofnA, LPOPENFILENAMEW ofnW, BOOL open)
{
UNICODE_STRING usBuffer;
ofnW->lpstrTitle = usBuffer.Buffer;
} else {
WCHAR buf[16];
+ LPWSTR title_tmp;
int len;
LoadStringW(COMDLG32_hInstance, open ? IDS_OPEN_FILE : IDS_SAVE_AS,
buf, sizeof(buf)/sizeof(WCHAR));
len = lstrlenW(buf)+1;
- ofnW->lpstrTitle = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
- memcpy((void*)ofnW->lpstrTitle, buf, len*sizeof(WCHAR));
+ title_tmp = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
+ memcpy(title_tmp, buf, len * sizeof(WCHAR));
+ ofnW->lpstrTitle = title_tmp;
}
ofnW->Flags = ofnA->Flags;
ofnW->nFileOffset = ofnA->nFileOffset;
ofnW->lpstrDefExt = FD31_DupToW(ofnA->lpstrDefExt, 3);
if ((ofnA->Flags & OFN_ENABLETEMPLATE) && (ofnA->lpTemplateName))
{
- if (HIWORD(ofnA->lpTemplateName))
+ if (!IS_INTRESOURCE(ofnA->lpTemplateName))
{
RtlCreateUnicodeStringFromAsciiz (&usBuffer,ofnA->lpTemplateName);
ofnW->lpTemplateName = usBuffer.Buffer;
}
else /* numbered resource */
- ofnW->lpTemplateName = (LPWSTR) ofnA->lpTemplateName;
+ ofnW->lpTemplateName = (LPCWSTR) ofnA->lpTemplateName;
}
}
* FD31_FreeOfnW [internal]
* Undo all allocations done by FD31_MapOfnStructA
*/
-void FD31_FreeOfnW(LPOPENFILENAMEW ofnW)
+void FD31_FreeOfnW(OPENFILENAMEW *ofnW)
{
HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrFilter);
HeapFree(GetProcessHeap(), 0, ofnW->lpstrCustomFilter);
HeapFree(GetProcessHeap(), 0, ofnW->lpstrFileTitle);
HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrInitialDir);
HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrTitle);
- if ((ofnW->lpTemplateName) && (HIWORD(ofnW->lpTemplateName)))
+ if (!IS_INTRESOURCE(ofnW->lpTemplateName))
HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpTemplateName);
}
if (!lfs) return;
hwnd = lfs->hwnd;
TRACE("destroying private allocation %p\n", lfs);
- lfs->callbacks->Destroy(lfs);
+
+ /* if ofnW has been allocated, have to free everything in it */
+ if (lfs->ofnA)
+ {
+ FD31_FreeOfnW(lfs->ofnW);
+ HeapFree(GetProcessHeap(), 0, lfs->ofnW);
+ }
HeapFree(GetProcessHeap(), 0, lfs);
RemovePropA(hwnd, FD31_OFN_PROP);
}
/************************************************************************
* FD31_AllocPrivate [internal]
* allocate a private object to hold 32 bits Unicode
- * structure that will be used throughtout the calls, while
+ * structure that will be used throughout the calls, while
* keeping available the original structures and a few variables
* On entry : type = dialog procedure type (16,32A,32W)
* dlgType = dialog type (open or save)
*/
-PFD31_DATA FD31_AllocPrivate(LPARAM lParam, UINT dlgType,
- PFD31_CALLBACKS callbacks, DWORD data)
+PFD31_DATA FD31_AllocPrivate(LPARAM lParam, UINT dlgType, BOOL IsUnicode)
{
PFD31_DATA lfs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FD31_DATA));
lfs->hook = FALSE;
lfs->lParam = lParam;
lfs->open = (dlgType == OPEN_DIALOG);
- lfs->callbacks = callbacks;
- if (! lfs->callbacks->Init(lParam, lfs, data))
+
+ if (IsUnicode)
+ {
+ lfs->ofnA = NULL;
+ lfs->ofnW = (LPOPENFILENAMEW) lParam;
+ if (lfs->ofnW->Flags & OFN_ENABLEHOOK)
+ if (lfs->ofnW->lpfnHook)
+ lfs->hook = TRUE;
+ }
+ else
+ {
+ lfs->ofnA = (LPOPENFILENAMEA) lParam;
+ if (lfs->ofnA->Flags & OFN_ENABLEHOOK)
+ if (lfs->ofnA->lpfnHook)
+ lfs->hook = TRUE;
+ lfs->ofnW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*lfs->ofnW));
+ FD31_MapOfnStructA(lfs->ofnA, lfs->ofnW, lfs->open);
+ }
+
+ if (! FD32_GetTemplate(lfs))
{
FD31_DestroyPrivate(lfs);
return NULL;
PFD31_DATA lfs = (PFD31_DATA) lParam;
if (!lfs) return FALSE;
- SetPropA(hWnd, FD31_OFN_PROP, (HANDLE)lfs);
+ SetPropA(hWnd, FD31_OFN_PROP, lfs);
lfs->hwnd = hWnd;
ofn = lfs->ofnW;
- TRACE("flags=%lx initialdir=%s\n", ofn->Flags, debugstr_w(ofn->lpstrInitialDir));
+ TRACE("flags=%x initialdir=%s\n", ofn->Flags, debugstr_w(ofn->lpstrInitialDir));
SetWindowTextW( hWnd, ofn->lpstrTitle );
/* read custom filter information */
if (ofn->nFilterIndex == 0 && ofn->lpstrCustomFilter == NULL)
ofn->nFilterIndex = 1;
SendDlgItemMessageW(hWnd, cmb1, CB_SETCURSEL, ofn->nFilterIndex - 1, 0);
- lstrcpynW(tmpstr, FD31_GetFileType(ofn->lpstrCustomFilter,
- (LPWSTR)ofn->lpstrFilter, ofn->nFilterIndex - 1),BUFFILE);
- TRACE("nFilterIndex = %ld, SetText of edt1 to %s\n",
+ if (ofn->lpstrFile && ofn->lpstrFile[0])
+ {
+ TRACE( "SetText of edt1 to %s\n", debugstr_w(ofn->lpstrFile) );
+ SetDlgItemTextW( hWnd, edt1, ofn->lpstrFile );
+ }
+ else
+ {
+ lstrcpynW(tmpstr, FD31_GetFileType(ofn->lpstrCustomFilter,
+ ofn->lpstrFilter, ofn->nFilterIndex - 1),BUFFILE);
+ TRACE("nFilterIndex = %d, SetText of edt1 to %s\n",
ofn->nFilterIndex, debugstr_w(tmpstr));
- SetDlgItemTextW( hWnd, edt1, tmpstr );
+ SetDlgItemTextW( hWnd, edt1, tmpstr );
+ }
/* get drive list */
*tmpstr = 0;
DlgDirListComboBoxW(hWnd, tmpstr, cmb2, 0, DDL_DRIVES | DDL_EXCLUSIVE);
}
else
*tmpstr = 0;
- if (!FD31_ScanDir(hWnd, tmpstr)) {
+ if (!FD31_ScanDir(ofn, hWnd, tmpstr)) {
*tmpstr = 0;
- if (!FD31_ScanDir(hWnd, tmpstr))
+ if (!FD31_ScanDir(ofn, hWnd, tmpstr))
WARN("Couldn't read initial directory %s!\n", debugstr_w(tmpstr));
}
/* select current drive in combo 2, omit missing drives */
if (ofn->Flags & OFN_HIDEREADONLY)
ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE);
if (lfs->hook)
- return (BOOL) FD31_CallWindowProc(lfs, WM_INITDIALOG, wParam, lfs->lParam);
+ return FD31_CallWindowProc(lfs, WM_INITDIALOG, wParam, lfs->lParam);
return TRUE;
}