369 lines
11 KiB
C
369 lines
11 KiB
C
/*
|
|
* COMMDLG - File Dialogs
|
|
*
|
|
* Copyright 1994 Martin Ayotte
|
|
* Copyright 1996 Albrecht Kleine
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* 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
|
|
*/
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "windef.h"
|
|
#include "winbase.h"
|
|
#include "wingdi.h"
|
|
#include "winnls.h"
|
|
#include "wine/winbase16.h"
|
|
#include "wine/winuser16.h"
|
|
#include "wine/unicode.h"
|
|
#include "winuser.h"
|
|
#include "commdlg.h"
|
|
#include "wine/debug.h"
|
|
#include "cderr.h"
|
|
#include "winreg.h"
|
|
#include "winternl.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
|
|
|
|
#include "cdlg.h"
|
|
#include "filedlg.h"
|
|
|
|
/***********************************************************************
|
|
* FILEDLG_CallWindowProc16 [internal]
|
|
*
|
|
* Call the appropriate hook
|
|
*/
|
|
static BOOL FILEDLG_CallWindowProc16(LFSPRIVATE lfs, UINT wMsg, WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
if (lfs->ofn16)
|
|
{
|
|
return (BOOL16) CallWindowProc16(
|
|
(WNDPROC16)lfs->ofn16->lpfnHook, HWND_16(lfs->hwnd),
|
|
(UINT16)wMsg, (WPARAM16)wParam, lParam);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* FILEDLG_WMInitDialog16 [internal]
|
|
* The is a duplicate of the 32bit FILEDLG_WMInitDialog function
|
|
* The only differnce is that it calls FILEDLG_CallWindowProc16
|
|
* for a 16 bit Window Proc.
|
|
*/
|
|
|
|
static LONG FILEDLG_WMInitDialog16(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
int i, n;
|
|
WCHAR tmpstr[BUFFILE];
|
|
LPWSTR pstr, old_pstr;
|
|
LPOPENFILENAMEW ofn;
|
|
LFSPRIVATE lfs = (LFSPRIVATE) lParam;
|
|
|
|
if (!lfs) return FALSE;
|
|
SetPropA(hWnd, OFN_PROP, (HANDLE)lfs);
|
|
lfs->hwnd = hWnd;
|
|
ofn = lfs->ofnW;
|
|
|
|
TRACE("flags=%lx initialdir=%s\n", ofn->Flags, debugstr_w(ofn->lpstrInitialDir));
|
|
|
|
SetWindowTextW( hWnd, ofn->lpstrTitle );
|
|
/* read custom filter information */
|
|
if (ofn->lpstrCustomFilter)
|
|
{
|
|
pstr = ofn->lpstrCustomFilter;
|
|
n = 0;
|
|
TRACE("lpstrCustomFilter = %p\n", pstr);
|
|
while(*pstr)
|
|
{
|
|
old_pstr = pstr;
|
|
i = SendDlgItemMessageW(hWnd, cmb1, CB_ADDSTRING, 0,
|
|
(LPARAM)(ofn->lpstrCustomFilter) + n );
|
|
n += lstrlenW(pstr) + 1;
|
|
pstr += lstrlenW(pstr) + 1;
|
|
TRACE("add str=%s associated to %s\n",
|
|
debugstr_w(old_pstr), debugstr_w(pstr));
|
|
SendDlgItemMessageW(hWnd, cmb1, CB_SETITEMDATA, i, (LPARAM)pstr);
|
|
n += lstrlenW(pstr) + 1;
|
|
pstr += lstrlenW(pstr) + 1;
|
|
}
|
|
}
|
|
/* read filter information */
|
|
if (ofn->lpstrFilter) {
|
|
pstr = (LPWSTR) ofn->lpstrFilter;
|
|
n = 0;
|
|
while(*pstr) {
|
|
old_pstr = pstr;
|
|
i = SendDlgItemMessageW(hWnd, cmb1, CB_ADDSTRING, 0,
|
|
(LPARAM)(ofn->lpstrFilter + n) );
|
|
n += lstrlenW(pstr) + 1;
|
|
pstr += lstrlenW(pstr) + 1;
|
|
TRACE("add str=%s associated to %s\n",
|
|
debugstr_w(old_pstr), debugstr_w(pstr));
|
|
SendDlgItemMessageW(hWnd, cmb1, CB_SETITEMDATA, i, (LPARAM)pstr);
|
|
n += lstrlenW(pstr) + 1;
|
|
pstr += lstrlenW(pstr) + 1;
|
|
}
|
|
}
|
|
/* set default filter */
|
|
if (ofn->nFilterIndex == 0 && ofn->lpstrCustomFilter == NULL)
|
|
ofn->nFilterIndex = 1;
|
|
SendDlgItemMessageW(hWnd, cmb1, CB_SETCURSEL, ofn->nFilterIndex - 1, 0);
|
|
lstrcpynW(tmpstr, FILEDLG_GetFileType(ofn->lpstrCustomFilter,
|
|
(LPWSTR)ofn->lpstrFilter, ofn->nFilterIndex - 1),BUFFILE);
|
|
TRACE("nFilterIndex = %ld, SetText of edt1 to %s\n",
|
|
ofn->nFilterIndex, debugstr_w(tmpstr));
|
|
SetDlgItemTextW( hWnd, edt1, tmpstr );
|
|
/* get drive list */
|
|
*tmpstr = 0;
|
|
DlgDirListComboBoxW(hWnd, tmpstr, cmb2, 0, DDL_DRIVES | DDL_EXCLUSIVE);
|
|
/* read initial directory */
|
|
/* FIXME: Note that this is now very version-specific (See MSDN description of
|
|
* the OPENFILENAME structure). For example under 2000/XP any path in the
|
|
* lpstrFile overrides the lpstrInitialDir, but not under 95/98/ME
|
|
*/
|
|
if (ofn->lpstrInitialDir != NULL)
|
|
{
|
|
int len;
|
|
lstrcpynW(tmpstr, ofn->lpstrInitialDir, 511);
|
|
len = lstrlenW(tmpstr);
|
|
if (len > 0 && tmpstr[len-1] != '\\' && tmpstr[len-1] != ':') {
|
|
tmpstr[len]='\\';
|
|
tmpstr[len+1]='\0';
|
|
}
|
|
}
|
|
else
|
|
*tmpstr = 0;
|
|
if (!FILEDLG_ScanDir(hWnd, tmpstr)) {
|
|
*tmpstr = 0;
|
|
if (!FILEDLG_ScanDir(hWnd, tmpstr))
|
|
WARN("Couldn't read initial directory %s!\n", debugstr_w(tmpstr));
|
|
}
|
|
/* select current drive in combo 2, omit missing drives */
|
|
{
|
|
char dir[MAX_PATH];
|
|
char str[4] = "a:\\";
|
|
GetCurrentDirectoryA( sizeof(dir), dir );
|
|
for(i = 0, n = -1; i < 26; i++)
|
|
{
|
|
str[0] = 'a' + i;
|
|
if (GetDriveTypeA(str) > DRIVE_NO_ROOT_DIR) n++;
|
|
if (toupper(str[0]) == toupper(dir[0])) break;
|
|
}
|
|
}
|
|
SendDlgItemMessageW(hWnd, cmb2, CB_SETCURSEL, n, 0);
|
|
if (!(ofn->Flags & OFN_SHOWHELP))
|
|
ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
|
|
if (ofn->Flags & OFN_HIDEREADONLY)
|
|
ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE);
|
|
if (lfs->hook)
|
|
return (BOOL) FILEDLG_CallWindowProc16(lfs, WM_INITDIALOG, wParam, lfs->lParam);
|
|
return TRUE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* FILEDLG_WMMeasureItem16 [internal]
|
|
*/
|
|
static LONG FILEDLG_WMMeasureItem16(HWND16 hWnd, WPARAM16 wParam, LPARAM lParam)
|
|
{
|
|
LPMEASUREITEMSTRUCT16 lpmeasure;
|
|
|
|
lpmeasure = MapSL(lParam);
|
|
lpmeasure->itemHeight = fldrHeight;
|
|
return TRUE;
|
|
}
|
|
|
|
/* ------------------ Dialog procedures ---------------------- */
|
|
|
|
/***********************************************************************
|
|
* FileOpenDlgProc (COMMDLG.6)
|
|
*/
|
|
BOOL16 CALLBACK FileOpenDlgProc16(HWND16 hWnd16, UINT16 wMsg, WPARAM16 wParam,
|
|
LPARAM lParam)
|
|
{
|
|
HWND hWnd = HWND_32(hWnd16);
|
|
LFSPRIVATE lfs = (LFSPRIVATE)GetPropA(hWnd,OFN_PROP);
|
|
DRAWITEMSTRUCT dis;
|
|
|
|
TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);
|
|
if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)
|
|
{
|
|
LRESULT lRet = (BOOL16)FILEDLG_CallWindowProc16(lfs, wMsg, wParam, lParam);
|
|
if (lRet)
|
|
return lRet; /* else continue message processing */
|
|
}
|
|
switch (wMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
return FILEDLG_WMInitDialog16(hWnd, wParam, lParam);
|
|
|
|
case WM_MEASUREITEM:
|
|
return FILEDLG_WMMeasureItem16(hWnd16, wParam, lParam);
|
|
|
|
case WM_DRAWITEM:
|
|
FILEDLG_MapDrawItemStruct(MapSL(lParam), &dis);
|
|
return FILEDLG_WMDrawItem(hWnd, wParam, lParam, FALSE, &dis);
|
|
|
|
case WM_COMMAND:
|
|
return FILEDLG_WMCommand(hWnd, lParam, HIWORD(lParam),wParam, lfs);
|
|
#if 0
|
|
case WM_CTLCOLOR:
|
|
SetBkColor((HDC16)wParam, 0x00C0C0C0);
|
|
switch (HIWORD(lParam))
|
|
{
|
|
case CTLCOLOR_BTN:
|
|
SetTextColor((HDC16)wParam, 0x00000000);
|
|
return hGRAYBrush;
|
|
case CTLCOLOR_STATIC:
|
|
SetTextColor((HDC16)wParam, 0x00000000);
|
|
return hGRAYBrush;
|
|
}
|
|
break;
|
|
#endif
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* FileSaveDlgProc (COMMDLG.7)
|
|
*/
|
|
BOOL16 CALLBACK FileSaveDlgProc16(HWND16 hWnd16, UINT16 wMsg, WPARAM16 wParam,
|
|
LPARAM lParam)
|
|
{
|
|
HWND hWnd = HWND_32(hWnd16);
|
|
LFSPRIVATE lfs = (LFSPRIVATE)GetPropA(hWnd,OFN_PROP);
|
|
DRAWITEMSTRUCT dis;
|
|
|
|
TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);
|
|
if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)
|
|
{
|
|
LRESULT lRet;
|
|
lRet = (BOOL16)FILEDLG_CallWindowProc16(lfs, wMsg, wParam, lParam);
|
|
if (lRet)
|
|
return lRet; /* else continue message processing */
|
|
}
|
|
switch (wMsg) {
|
|
case WM_INITDIALOG:
|
|
return FILEDLG_WMInitDialog16(hWnd, wParam, lParam);
|
|
|
|
case WM_MEASUREITEM:
|
|
return FILEDLG_WMMeasureItem16(hWnd16, wParam, lParam);
|
|
|
|
case WM_DRAWITEM:
|
|
FILEDLG_MapDrawItemStruct(MapSL(lParam), &dis);
|
|
return FILEDLG_WMDrawItem(hWnd, wParam, lParam, TRUE, &dis);
|
|
|
|
case WM_COMMAND:
|
|
return FILEDLG_WMCommand(hWnd, lParam, HIWORD(lParam), wParam, lfs);
|
|
}
|
|
|
|
/*
|
|
case WM_CTLCOLOR:
|
|
SetBkColor((HDC16)wParam, 0x00C0C0C0);
|
|
switch (HIWORD(lParam))
|
|
{
|
|
case CTLCOLOR_BTN:
|
|
SetTextColor((HDC16)wParam, 0x00000000);
|
|
return hGRAYBrush;
|
|
case CTLCOLOR_STATIC:
|
|
SetTextColor((HDC16)wParam, 0x00000000);
|
|
return hGRAYBrush;
|
|
}
|
|
return FALSE;
|
|
|
|
*/
|
|
return FALSE;
|
|
}
|
|
|
|
/* ------------------ APIs ---------------------- */
|
|
|
|
/***********************************************************************
|
|
* GetOpenFileName (COMMDLG.1)
|
|
*
|
|
* Creates a dialog box for the user to select a file to open.
|
|
*
|
|
* RETURNS
|
|
* TRUE on success: user selected a valid file
|
|
* FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
|
|
*
|
|
* BUGS
|
|
* unknown, there are some FIXME's left.
|
|
*/
|
|
BOOL16 WINAPI GetOpenFileName16(
|
|
SEGPTR ofn /* [in/out] address of structure with data*/
|
|
)
|
|
{
|
|
HINSTANCE16 hInst;
|
|
BOOL bRet = FALSE;
|
|
LPOPENFILENAME16 lpofn = MapSL(ofn);
|
|
LFSPRIVATE lfs;
|
|
FARPROC16 ptr;
|
|
|
|
if (!lpofn || !FileDlg_Init()) return FALSE;
|
|
|
|
lfs = FILEDLG_AllocPrivate((LPARAM) ofn, LFS16, OPEN_DIALOG);
|
|
if (lfs)
|
|
{
|
|
hInst = GetWindowWord( HWND_32(lpofn->hwndOwner), GWL_HINSTANCE );
|
|
ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 6);
|
|
bRet = DialogBoxIndirectParam16( hInst, lfs->hDlgTmpl16, lpofn->hwndOwner,
|
|
(DLGPROC16) ptr, (LPARAM) lfs);
|
|
FILEDLG_DestroyPrivate(lfs);
|
|
}
|
|
|
|
TRACE("return lpstrFile='%s' !\n", (char *)MapSL(lpofn->lpstrFile));
|
|
return bRet;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* GetSaveFileName (COMMDLG.2)
|
|
*
|
|
* Creates a dialog box for the user to select a file to save.
|
|
*
|
|
* RETURNS
|
|
* TRUE on success: user enters a valid file
|
|
* FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
|
|
*
|
|
* BUGS
|
|
* unknown. There are some FIXME's left.
|
|
*/
|
|
BOOL16 WINAPI GetSaveFileName16(
|
|
SEGPTR ofn /* [in/out] addess of structure with data*/
|
|
)
|
|
{
|
|
HINSTANCE16 hInst;
|
|
BOOL bRet = FALSE;
|
|
LPOPENFILENAME16 lpofn = MapSL(ofn);
|
|
LFSPRIVATE lfs;
|
|
FARPROC16 ptr;
|
|
|
|
if (!lpofn || !FileDlg_Init()) return FALSE;
|
|
|
|
lfs = FILEDLG_AllocPrivate((LPARAM) ofn, LFS16, SAVE_DIALOG);
|
|
if (lfs)
|
|
{
|
|
hInst = GetWindowWord( HWND_32(lpofn->hwndOwner), GWL_HINSTANCE );
|
|
ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 7);
|
|
bRet = DialogBoxIndirectParam16( hInst, lfs->hDlgTmpl16, lpofn->hwndOwner,
|
|
(DLGPROC16) ptr, (LPARAM) lfs);
|
|
FILEDLG_DestroyPrivate(lfs);
|
|
}
|
|
|
|
TRACE("return lpstrFile='%s' !\n", (char *)MapSL(lpofn->lpstrFile));
|
|
return bRet;
|
|
}
|