wine/dlls/comdlg32/printdlg.c

3963 lines
126 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* COMMDLG - Print Dialog
*
* Copyright 1994 Martin Ayotte
* Copyright 1996 Albrecht Kleine
* Copyright 1999 Klaas van Gend
* Copyright 2000 Huw D M Davies
* Copyright 2010 Vitaly Perov
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <ctype.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winspool.h"
#include "winerror.h"
#include "wine/unicode.h"
#include "wine/debug.h"
#include "commdlg.h"
#include "dlgs.h"
#include "cderr.h"
#include "cdlg.h"
WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
/* Yes these constants are the same, but we're just copying win98 */
#define UPDOWN_ID 0x270f
#define MAX_COPIES 9999
/* This PRINTDLGA internal structure stores
* pointers to several throughout useful structures.
*/
typedef struct
{
LPDEVMODEA lpDevMode;
LPPRINTDLGA lpPrintDlg;
LPPRINTER_INFO_2A lpPrinterInfo;
LPDRIVER_INFO_3A lpDriverInfo;
UINT HelpMessageID;
HICON hCollateIcon; /* PrintDlg only */
HICON hNoCollateIcon; /* PrintDlg only */
HICON hPortraitIcon; /* PrintSetupDlg only */
HICON hLandscapeIcon; /* PrintSetupDlg only */
HWND hwndUpDown;
} PRINT_PTRA;
typedef struct
{
LPDEVMODEW lpDevMode;
LPPRINTDLGW lpPrintDlg;
LPPRINTER_INFO_2W lpPrinterInfo;
LPDRIVER_INFO_3W lpDriverInfo;
UINT HelpMessageID;
HICON hCollateIcon; /* PrintDlg only */
HICON hNoCollateIcon; /* PrintDlg only */
HICON hPortraitIcon; /* PrintSetupDlg only */
HICON hLandscapeIcon; /* PrintSetupDlg only */
HWND hwndUpDown;
} PRINT_PTRW;
/* Debugging info */
struct pd_flags
{
DWORD flag;
LPCSTR name;
};
static const struct pd_flags psd_flags[] = {
{PSD_MINMARGINS,"PSD_MINMARGINS"},
{PSD_MARGINS,"PSD_MARGINS"},
{PSD_INTHOUSANDTHSOFINCHES,"PSD_INTHOUSANDTHSOFINCHES"},
{PSD_INHUNDREDTHSOFMILLIMETERS,"PSD_INHUNDREDTHSOFMILLIMETERS"},
{PSD_DISABLEMARGINS,"PSD_DISABLEMARGINS"},
{PSD_DISABLEPRINTER,"PSD_DISABLEPRINTER"},
{PSD_NOWARNING,"PSD_NOWARNING"},
{PSD_DISABLEORIENTATION,"PSD_DISABLEORIENTATION"},
{PSD_RETURNDEFAULT,"PSD_RETURNDEFAULT"},
{PSD_DISABLEPAPER,"PSD_DISABLEPAPER"},
{PSD_SHOWHELP,"PSD_SHOWHELP"},
{PSD_ENABLEPAGESETUPHOOK,"PSD_ENABLEPAGESETUPHOOK"},
{PSD_ENABLEPAGESETUPTEMPLATE,"PSD_ENABLEPAGESETUPTEMPLATE"},
{PSD_ENABLEPAGESETUPTEMPLATEHANDLE,"PSD_ENABLEPAGESETUPTEMPLATEHANDLE"},
{PSD_ENABLEPAGEPAINTHOOK,"PSD_ENABLEPAGEPAINTHOOK"},
{PSD_DISABLEPAGEPAINTING,"PSD_DISABLEPAGEPAINTING"},
{-1, NULL}
};
static const struct pd_flags pd_flags[] = {
{PD_SELECTION, "PD_SELECTION "},
{PD_PAGENUMS, "PD_PAGENUMS "},
{PD_NOSELECTION, "PD_NOSELECTION "},
{PD_NOPAGENUMS, "PD_NOPAGENUMS "},
{PD_COLLATE, "PD_COLLATE "},
{PD_PRINTTOFILE, "PD_PRINTTOFILE "},
{PD_PRINTSETUP, "PD_PRINTSETUP "},
{PD_NOWARNING, "PD_NOWARNING "},
{PD_RETURNDC, "PD_RETURNDC "},
{PD_RETURNIC, "PD_RETURNIC "},
{PD_RETURNDEFAULT, "PD_RETURNDEFAULT "},
{PD_SHOWHELP, "PD_SHOWHELP "},
{PD_ENABLEPRINTHOOK, "PD_ENABLEPRINTHOOK "},
{PD_ENABLESETUPHOOK, "PD_ENABLESETUPHOOK "},
{PD_ENABLEPRINTTEMPLATE, "PD_ENABLEPRINTTEMPLATE "},
{PD_ENABLESETUPTEMPLATE, "PD_ENABLESETUPTEMPLATE "},
{PD_ENABLEPRINTTEMPLATEHANDLE, "PD_ENABLEPRINTTEMPLATEHANDLE "},
{PD_ENABLESETUPTEMPLATEHANDLE, "PD_ENABLESETUPTEMPLATEHANDLE "},
{PD_USEDEVMODECOPIES, "PD_USEDEVMODECOPIES[ANDCOLLATE] "},
{PD_DISABLEPRINTTOFILE, "PD_DISABLEPRINTTOFILE "},
{PD_HIDEPRINTTOFILE, "PD_HIDEPRINTTOFILE "},
{PD_NONETWORKBUTTON, "PD_NONETWORKBUTTON "},
{-1, NULL}
};
/* address of wndproc for subclassed Static control */
static WNDPROC lpfnStaticWndProc;
static WNDPROC edit_wndproc;
/* the text of the fake document to render for the Page Setup dialog */
static WCHAR wszFakeDocumentText[1024];
static const WCHAR pd32_collateW[] = { 'P', 'D', '3', '2', '_', 'C', 'O', 'L', 'L', 'A', 'T', 'E', 0 };
static const WCHAR pd32_nocollateW[] = { 'P', 'D', '3', '2', '_', 'N', 'O', 'C', 'O', 'L', 'L', 'A', 'T', 'E', 0 };
static const WCHAR pd32_portraitW[] = { 'P', 'D', '3', '2', '_', 'P', 'O', 'R', 'T', 'R', 'A', 'I', 'T', 0 };
static const WCHAR pd32_landscapeW[] = { 'P', 'D', '3', '2', '_', 'L', 'A', 'N', 'D', 'S', 'C', 'A', 'P', 'E', 0 };
static const WCHAR printdlg_prop[] = {'_','_','W','I','N','E','_','P','R','I','N','T','D','L','G','D','A','T','A',0};
static const WCHAR pagesetupdlg_prop[] = { '_', '_', 'W', 'I', 'N', 'E', '_', 'P', 'A', 'G', 'E',
'S', 'E', 'T', 'U', 'P', 'D', 'L', 'G', 'D', 'A', 'T', 'A', 0 };
static LPWSTR strdupW(LPCWSTR p)
{
LPWSTR ret;
DWORD len;
if(!p) return NULL;
len = (strlenW(p) + 1) * sizeof(WCHAR);
ret = HeapAlloc(GetProcessHeap(), 0, len);
memcpy(ret, p, len);
return ret;
}
/***********************************************************
* convert_to_devmodeA
*
* Creates an ansi copy of supplied devmode
*/
static DEVMODEA *convert_to_devmodeA(const DEVMODEW *dmW)
{
DEVMODEA *dmA;
DWORD size;
if (!dmW) return NULL;
size = dmW->dmSize - CCHDEVICENAME -
((dmW->dmSize > FIELD_OFFSET(DEVMODEW, dmFormName)) ? CCHFORMNAME : 0);
dmA = HeapAlloc(GetProcessHeap(), 0, size + dmW->dmDriverExtra);
if (!dmA) return NULL;
WideCharToMultiByte(CP_ACP, 0, dmW->dmDeviceName, -1,
(LPSTR)dmA->dmDeviceName, CCHDEVICENAME, NULL, NULL);
if (FIELD_OFFSET(DEVMODEW, dmFormName) >= dmW->dmSize)
{
memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion,
dmW->dmSize - FIELD_OFFSET(DEVMODEW, dmSpecVersion));
}
else
{
memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion,
FIELD_OFFSET(DEVMODEW, dmFormName) - FIELD_OFFSET(DEVMODEW, dmSpecVersion));
WideCharToMultiByte(CP_ACP, 0, dmW->dmFormName, -1,
(LPSTR)dmA->dmFormName, CCHFORMNAME, NULL, NULL);
memcpy(&dmA->dmLogPixels, &dmW->dmLogPixels, dmW->dmSize - FIELD_OFFSET(DEVMODEW, dmLogPixels));
}
dmA->dmSize = size;
memcpy((char *)dmA + dmA->dmSize, (const char *)dmW + dmW->dmSize, dmW->dmDriverExtra);
return dmA;
}
/***********************************************************************
* PRINTDLG_OpenDefaultPrinter
*
* Returns a winspool printer handle to the default printer in *hprn
* Caller must call ClosePrinter on the handle
*
* Returns TRUE on success else FALSE
*/
static BOOL PRINTDLG_OpenDefaultPrinter(HANDLE *hprn)
{
WCHAR buf[260];
DWORD dwBufLen = sizeof(buf) / sizeof(buf[0]);
BOOL res;
if(!GetDefaultPrinterW(buf, &dwBufLen))
return FALSE;
res = OpenPrinterW(buf, hprn, NULL);
if (!res)
WARN("Could not open printer %s\n", debugstr_w(buf));
return res;
}
/***********************************************************************
* PRINTDLG_SetUpPrinterListCombo
*
* Initializes printer list combox.
* hDlg: HWND of dialog
* id: Control id of combo
* name: Name of printer to select
*
* Initializes combo with list of available printers. Selects printer 'name'
* If name is NULL or does not exist select the default printer.
*
* Returns number of printers added to list.
*/
static INT PRINTDLG_SetUpPrinterListComboA(HWND hDlg, UINT id, LPCSTR name)
{
DWORD needed, num;
INT i;
LPPRINTER_INFO_2A pi;
EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
pi = HeapAlloc(GetProcessHeap(), 0, needed);
EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed,
&num);
SendDlgItemMessageA(hDlg, id, CB_RESETCONTENT, 0, 0);
for(i = 0; i < num; i++) {
SendDlgItemMessageA(hDlg, id, CB_ADDSTRING, 0,
(LPARAM)pi[i].pPrinterName );
}
HeapFree(GetProcessHeap(), 0, pi);
if(!name ||
(i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1,
(LPARAM)name)) == CB_ERR) {
char buf[260];
DWORD dwBufLen = sizeof(buf);
if (name != NULL)
WARN("Can't find %s in printer list so trying to find default\n",
debugstr_a(name));
if(!GetDefaultPrinterA(buf, &dwBufLen))
return num;
i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
if(i == CB_ERR)
FIXME("Can't find default printer in printer list\n");
}
SendDlgItemMessageA(hDlg, id, CB_SETCURSEL, i, 0);
return num;
}
static INT PRINTDLG_SetUpPrinterListComboW(HWND hDlg, UINT id, LPCWSTR name)
{
DWORD needed, num;
INT i;
LPPRINTER_INFO_2W pi;
EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
pi = HeapAlloc(GetProcessHeap(), 0, needed);
EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed,
&num);
for(i = 0; i < num; i++) {
SendDlgItemMessageW(hDlg, id, CB_ADDSTRING, 0,
(LPARAM)pi[i].pPrinterName );
}
HeapFree(GetProcessHeap(), 0, pi);
if(!name ||
(i = SendDlgItemMessageW(hDlg, id, CB_FINDSTRINGEXACT, -1,
(LPARAM)name)) == CB_ERR) {
WCHAR buf[260];
DWORD dwBufLen = sizeof(buf)/sizeof(buf[0]);
if (name != NULL)
WARN("Can't find %s in printer list so trying to find default\n",
debugstr_w(name));
if(!GetDefaultPrinterW(buf, &dwBufLen))
return num;
i = SendDlgItemMessageW(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
if(i == CB_ERR)
TRACE("Can't find default printer in printer list\n");
}
SendDlgItemMessageW(hDlg, id, CB_SETCURSEL, i, 0);
return num;
}
/***********************************************************************
* PRINTDLG_CreateDevNames [internal]
*
*
* creates a DevNames structure.
*
* (NB. when we handle unicode the offsets will be in wchars).
*/
static BOOL PRINTDLG_CreateDevNames(HGLOBAL *hmem, const char* DeviceDriverName,
const char* DeviceName, const char* OutputPort)
{
long size;
char* pDevNamesSpace;
char* pTempPtr;
LPDEVNAMES lpDevNames;
char buf[260];
DWORD dwBufLen = sizeof(buf);
size = strlen(DeviceDriverName) + 1
+ strlen(DeviceName) + 1
+ strlen(OutputPort) + 1
+ sizeof(DEVNAMES);
if(*hmem)
*hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
else
*hmem = GlobalAlloc(GMEM_MOVEABLE, size);
if (*hmem == 0)
return FALSE;
pDevNamesSpace = GlobalLock(*hmem);
lpDevNames = (LPDEVNAMES) pDevNamesSpace;
pTempPtr = pDevNamesSpace + sizeof(DEVNAMES);
strcpy(pTempPtr, DeviceDriverName);
lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
pTempPtr += strlen(DeviceDriverName) + 1;
strcpy(pTempPtr, DeviceName);
lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
pTempPtr += strlen(DeviceName) + 1;
strcpy(pTempPtr, OutputPort);
lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
GetDefaultPrinterA(buf, &dwBufLen);
lpDevNames->wDefault = (strcmp(buf, DeviceName) == 0) ? 1 : 0;
GlobalUnlock(*hmem);
return TRUE;
}
static BOOL PRINTDLG_CreateDevNamesW(HGLOBAL *hmem, LPCWSTR DeviceDriverName,
LPCWSTR DeviceName, LPCWSTR OutputPort)
{
long size;
LPWSTR pDevNamesSpace;
LPWSTR pTempPtr;
LPDEVNAMES lpDevNames;
WCHAR bufW[260];
DWORD dwBufLen = sizeof(bufW) / sizeof(WCHAR);
size = sizeof(WCHAR)*lstrlenW(DeviceDriverName) + 2
+ sizeof(WCHAR)*lstrlenW(DeviceName) + 2
+ sizeof(WCHAR)*lstrlenW(OutputPort) + 2
+ sizeof(DEVNAMES);
if(*hmem)
*hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
else
*hmem = GlobalAlloc(GMEM_MOVEABLE, size);
if (*hmem == 0)
return FALSE;
pDevNamesSpace = GlobalLock(*hmem);
lpDevNames = (LPDEVNAMES) pDevNamesSpace;
pTempPtr = (LPWSTR)((LPDEVNAMES)pDevNamesSpace + 1);
lstrcpyW(pTempPtr, DeviceDriverName);
lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
pTempPtr += lstrlenW(DeviceDriverName) + 1;
lstrcpyW(pTempPtr, DeviceName);
lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
pTempPtr += lstrlenW(DeviceName) + 1;
lstrcpyW(pTempPtr, OutputPort);
lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
GetDefaultPrinterW(bufW, &dwBufLen);
lpDevNames->wDefault = (lstrcmpW(bufW, DeviceName) == 0) ? 1 : 0;
GlobalUnlock(*hmem);
return TRUE;
}
/***********************************************************************
* PRINTDLG_UpdatePrintDlg [internal]
*
*
* updates the PrintDlg structure for return values.
*
* RETURNS
* FALSE if user is not allowed to close (i.e. wrong nTo or nFrom values)
* TRUE if successful.
*/
static BOOL PRINTDLG_UpdatePrintDlgA(HWND hDlg,
PRINT_PTRA* PrintStructures)
{
LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
PDEVMODEA lpdm = PrintStructures->lpDevMode;
LPPRINTER_INFO_2A pi = PrintStructures->lpPrinterInfo;
if(!lpdm) {
FIXME("No lpdm ptr?\n");
return FALSE;
}
if(!(lppd->Flags & PD_PRINTSETUP)) {
/* check whether nFromPage and nToPage are within range defined by
* nMinPage and nMaxPage
*/
if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
WORD nToPage;
WORD nFromPage;
BOOL translated;
nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
nToPage = GetDlgItemInt(hDlg, edt2, &translated, FALSE);
/* if no ToPage value is entered, use the FromPage value */
if(!translated) nToPage = nFromPage;
if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
WCHAR resourcestr[256];
WCHAR resultstr[256];
LoadStringW(COMDLG32_hInstance, PD32_INVALID_PAGE_RANGE, resourcestr, 255);
wsprintfW(resultstr,resourcestr, lppd->nMinPage, lppd->nMaxPage);
LoadStringW(COMDLG32_hInstance, PD32_PRINT_TITLE, resourcestr, 255);
MessageBoxW(hDlg, resultstr, resourcestr, MB_OK | MB_ICONWARNING);
return FALSE;
}
lppd->nFromPage = nFromPage;
lppd->nToPage = nToPage;
lppd->Flags |= PD_PAGENUMS;
}
else
lppd->Flags &= ~PD_PAGENUMS;
if (IsDlgButtonChecked(hDlg, rad2) == BST_CHECKED) /* Selection */
lppd->Flags |= PD_SELECTION;
else
lppd->Flags &= ~PD_SELECTION;
if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
static char file[] = "FILE:";
lppd->Flags |= PD_PRINTTOFILE;
pi->pPortName = file;
}
if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
FIXME("Collate lppd not yet implemented as output\n");
}
/* set PD_Collate and nCopies */
if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
/* The application doesn't support multiple copies or collate...
*/
lppd->Flags &= ~PD_COLLATE;
lppd->nCopies = 1;
/* if the printer driver supports it... store info there
* otherwise no collate & multiple copies !
*/
if (lpdm->dmFields & DM_COLLATE)
lpdm->dmCollate =
(IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
if (lpdm->dmFields & DM_COPIES)
lpdm->u1.s1.dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
} else {
/* Application is responsible for multiple copies */
if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
lppd->Flags |= PD_COLLATE;
else
lppd->Flags &= ~PD_COLLATE;
lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
/* multiple copies already included in the document. Driver must print only one copy */
lpdm->u1.s1.dmCopies = 1;
}
/* Print quality, PrintDlg16 */
if(GetDlgItem(hDlg, cmb1))
{
HWND hQuality = GetDlgItem(hDlg, cmb1);
int Sel = SendMessageA(hQuality, CB_GETCURSEL, 0, 0);
if(Sel != CB_ERR)
{
LONG dpi = SendMessageA(hQuality, CB_GETITEMDATA, Sel, 0);
lpdm->dmFields |= DM_PRINTQUALITY | DM_YRESOLUTION;
lpdm->u1.s1.dmPrintQuality = LOWORD(dpi);
lpdm->dmYResolution = HIWORD(dpi);
}
}
}
return TRUE;
}
static BOOL PRINTDLG_UpdatePrintDlgW(HWND hDlg,
PRINT_PTRW* PrintStructures)
{
LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
PDEVMODEW lpdm = PrintStructures->lpDevMode;
LPPRINTER_INFO_2W pi = PrintStructures->lpPrinterInfo;
if(!lpdm) {
FIXME("No lpdm ptr?\n");
return FALSE;
}
if(!(lppd->Flags & PD_PRINTSETUP)) {
/* check whether nFromPage and nToPage are within range defined by
* nMinPage and nMaxPage
*/
if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
WORD nToPage;
WORD nFromPage;
BOOL translated;
nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
nToPage = GetDlgItemInt(hDlg, edt2, &translated, FALSE);
/* if no ToPage value is entered, use the FromPage value */
if(!translated) nToPage = nFromPage;
if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
WCHAR resourcestr[256];
WCHAR resultstr[256];
LoadStringW(COMDLG32_hInstance, PD32_INVALID_PAGE_RANGE,
resourcestr, 255);
wsprintfW(resultstr,resourcestr, lppd->nMinPage, lppd->nMaxPage);
LoadStringW(COMDLG32_hInstance, PD32_PRINT_TITLE,
resourcestr, 255);
MessageBoxW(hDlg, resultstr, resourcestr,
MB_OK | MB_ICONWARNING);
return FALSE;
}
lppd->nFromPage = nFromPage;
lppd->nToPage = nToPage;
lppd->Flags |= PD_PAGENUMS;
}
else
lppd->Flags &= ~PD_PAGENUMS;
if (IsDlgButtonChecked(hDlg, rad2) == BST_CHECKED) /* Selection */
lppd->Flags |= PD_SELECTION;
else
lppd->Flags &= ~PD_SELECTION;
if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
static WCHAR file[] = {'F','I','L','E',':',0};
lppd->Flags |= PD_PRINTTOFILE;
pi->pPortName = file;
}
if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
FIXME("Collate lppd not yet implemented as output\n");
}
/* set PD_Collate and nCopies */
if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
/* The application doesn't support multiple copies or collate...
*/
lppd->Flags &= ~PD_COLLATE;
lppd->nCopies = 1;
/* if the printer driver supports it... store info there
* otherwise no collate & multiple copies !
*/
if (lpdm->dmFields & DM_COLLATE)
lpdm->dmCollate =
(IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
if (lpdm->dmFields & DM_COPIES)
lpdm->u1.s1.dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
} else {
if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
lppd->Flags |= PD_COLLATE;
else
lppd->Flags &= ~PD_COLLATE;
lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
}
}
return TRUE;
}
/************************************************************************
* PRINTDLG_SetUpPaperComboBox
*
* Initialize either the papersize or inputslot combos of the Printer Setup
* dialog. We store the associated word (eg DMPAPER_A4) as the item data.
* We also try to re-select the old selection.
*/
static BOOL PRINTDLG_SetUpPaperComboBoxA(HWND hDlg,
int nIDComboBox,
char* PrinterName,
char* PortName,
LPDEVMODEA dm)
{
int i;
int NrOfEntries;
char* Names;
WORD* Words;
DWORD Sel;
WORD oldWord = 0;
int NamesSize;
int fwCapability_Names;
int fwCapability_Words;
TRACE(" Printer: %s, Port: %s, ComboID: %d\n",PrinterName,PortName,nIDComboBox);
/* query the dialog box for the current selected value */
Sel = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
if(Sel != CB_ERR) {
/* we enter here only if a different printer is selected after
* the Print Setup dialog is opened. The current settings are
* stored into the newly selected printer.
*/
oldWord = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA,
Sel, 0);
if (dm) {
if (nIDComboBox == cmb2)
dm->u1.s1.dmPaperSize = oldWord;
else
dm->u1.s1.dmDefaultSource = oldWord;
}
}
else {
/* we enter here only when the Print setup dialog is initially
* opened. In this case the settings are restored from when
* the dialog was last closed.
*/
if (dm) {
if (nIDComboBox == cmb2)
oldWord = dm->u1.s1.dmPaperSize;
else
oldWord = dm->u1.s1.dmDefaultSource;
}
}
if (nIDComboBox == cmb2) {
NamesSize = 64;
fwCapability_Names = DC_PAPERNAMES;
fwCapability_Words = DC_PAPERS;
} else {
nIDComboBox = cmb3;
NamesSize = 24;
fwCapability_Names = DC_BINNAMES;
fwCapability_Words = DC_BINS;
}
NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
fwCapability_Names, NULL, dm);
if (NrOfEntries == 0)
WARN("no Name Entries found!\n");
else if (NrOfEntries < 0)
return FALSE;
if(DeviceCapabilitiesA(PrinterName, PortName, fwCapability_Words, NULL, dm)
!= NrOfEntries) {
ERR("Number of caps is different\n");
NrOfEntries = 0;
}
Names = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(char)*NamesSize);
Words = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WORD));
NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
fwCapability_Names, Names, dm);
NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
fwCapability_Words, (LPSTR)Words, dm);
/* reset any current content in the combobox */
SendDlgItemMessageA(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
/* store new content */
for (i = 0; i < NrOfEntries; i++) {
DWORD pos = SendDlgItemMessageA(hDlg, nIDComboBox, CB_ADDSTRING, 0,
(LPARAM)(&Names[i*NamesSize]) );
SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETITEMDATA, pos,
Words[i]);
}
/* Look for old selection - can't do this is previous loop since
item order will change as more items are added */
Sel = 0;
for (i = 0; i < NrOfEntries; i++) {
if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
oldWord) {
Sel = i;
break;
}
}
SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
HeapFree(GetProcessHeap(),0,Words);
HeapFree(GetProcessHeap(),0,Names);
return TRUE;
}
static BOOL PRINTDLG_SetUpPaperComboBoxW(HWND hDlg,
int nIDComboBox,
const WCHAR* PrinterName,
const WCHAR* PortName,
LPDEVMODEW dm)
{
int i;
int NrOfEntries;
WCHAR* Names;
WORD* Words;
DWORD Sel;
WORD oldWord = 0;
int NamesSize;
int fwCapability_Names;
int fwCapability_Words;
TRACE(" Printer: %s, Port: %s, ComboID: %d\n",debugstr_w(PrinterName),debugstr_w(PortName),nIDComboBox);
/* query the dialog box for the current selected value */
Sel = SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
if(Sel != CB_ERR) {
/* we enter here only if a different printer is selected after
* the Print Setup dialog is opened. The current settings are
* stored into the newly selected printer.
*/
oldWord = SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETITEMDATA,
Sel, 0);
if (dm) {
if (nIDComboBox == cmb2)
dm->u1.s1.dmPaperSize = oldWord;
else
dm->u1.s1.dmDefaultSource = oldWord;
}
}
else {
/* we enter here only when the Print setup dialog is initially
* opened. In this case the settings are restored from when
* the dialog was last closed.
*/
if (dm) {
if (nIDComboBox == cmb2)
oldWord = dm->u1.s1.dmPaperSize;
else
oldWord = dm->u1.s1.dmDefaultSource;
}
}
if (nIDComboBox == cmb2) {
NamesSize = 64;
fwCapability_Names = DC_PAPERNAMES;
fwCapability_Words = DC_PAPERS;
} else {
nIDComboBox = cmb3;
NamesSize = 24;
fwCapability_Names = DC_BINNAMES;
fwCapability_Words = DC_BINS;
}
NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
fwCapability_Names, NULL, dm);
if (NrOfEntries == 0)
WARN("no Name Entries found!\n");
else if (NrOfEntries < 0)
return FALSE;
if(DeviceCapabilitiesW(PrinterName, PortName, fwCapability_Words, NULL, dm)
!= NrOfEntries) {
ERR("Number of caps is different\n");
NrOfEntries = 0;
}
Names = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WCHAR)*NamesSize);
Words = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WORD));
NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
fwCapability_Names, Names, dm);
NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
fwCapability_Words, Words, dm);
/* reset any current content in the combobox */
SendDlgItemMessageW(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
/* store new content */
for (i = 0; i < NrOfEntries; i++) {
DWORD pos = SendDlgItemMessageW(hDlg, nIDComboBox, CB_ADDSTRING, 0,
(LPARAM)(&Names[i*NamesSize]) );
SendDlgItemMessageW(hDlg, nIDComboBox, CB_SETITEMDATA, pos,
Words[i]);
}
/* Look for old selection - can't do this is previous loop since
item order will change as more items are added */
Sel = 0;
for (i = 0; i < NrOfEntries; i++) {
if(SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
oldWord) {
Sel = i;
break;
}
}
SendDlgItemMessageW(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
HeapFree(GetProcessHeap(),0,Words);
HeapFree(GetProcessHeap(),0,Names);
return TRUE;
}
/***********************************************************************
* PRINTDLG_UpdatePrinterInfoTexts [internal]
*/
static void PRINTDLG_UpdatePrinterInfoTextsA(HWND hDlg, const PRINTER_INFO_2A *pi)
{
char StatusMsg[256];
char ResourceString[256];
int i;
/* Status Message */
StatusMsg[0]='\0';
/* add all status messages */
for (i = 0; i < 25; i++) {
if (pi->Status & (1<<i)) {
LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_PAUSED+i,
ResourceString, 255);
strcat(StatusMsg,ResourceString);
}
}
/* append "ready" */
/* FIXME: status==ready must only be appended if really so.
but how to detect? */
LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_READY,
ResourceString, 255);
strcat(StatusMsg,ResourceString);
SetDlgItemTextA(hDlg, stc12, StatusMsg);
/* set all other printer info texts */
SetDlgItemTextA(hDlg, stc11, pi->pDriverName);
if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
SetDlgItemTextA(hDlg, stc14, pi->pLocation);
else
SetDlgItemTextA(hDlg, stc14, pi->pPortName);
SetDlgItemTextA(hDlg, stc13, pi->pComment ? pi->pComment : "");
return;
}
static void PRINTDLG_UpdatePrinterInfoTextsW(HWND hDlg, const PRINTER_INFO_2W *pi)
{
WCHAR StatusMsg[256];
WCHAR ResourceString[256];
static const WCHAR emptyW[] = {0};
int i;
/* Status Message */
StatusMsg[0]='\0';
/* add all status messages */
for (i = 0; i < 25; i++) {
if (pi->Status & (1<<i)) {
LoadStringW(COMDLG32_hInstance, PD32_PRINTER_STATUS_PAUSED+i,
ResourceString, 255);
lstrcatW(StatusMsg,ResourceString);
}
}
/* append "ready" */
/* FIXME: status==ready must only be appended if really so.
but how to detect? */
LoadStringW(COMDLG32_hInstance, PD32_PRINTER_STATUS_READY,
ResourceString, 255);
lstrcatW(StatusMsg,ResourceString);
SetDlgItemTextW(hDlg, stc12, StatusMsg);
/* set all other printer info texts */
SetDlgItemTextW(hDlg, stc11, pi->pDriverName);
if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
SetDlgItemTextW(hDlg, stc14, pi->pLocation);
else
SetDlgItemTextW(hDlg, stc14, pi->pPortName);
SetDlgItemTextW(hDlg, stc13, pi->pComment ? pi->pComment : emptyW);
}
/*******************************************************************
*
* PRINTDLG_ChangePrinter
*
*/
static BOOL PRINTDLG_ChangePrinterA(HWND hDlg, char *name, PRINT_PTRA *PrintStructures)
{
LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
LPDEVMODEA lpdm = NULL;
LONG dmSize;
DWORD needed;
HANDLE hprn;
HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo);
if(!OpenPrinterA(name, &hprn, NULL)) {
ERR("Can't open printer %s\n", name);
return FALSE;
}
GetPrinterA(hprn, 2, NULL, 0, &needed);
PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,needed);
GetPrinterA(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
&needed);
GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
PrintStructures->lpDriverInfo = HeapAlloc(GetProcessHeap(),0,needed);
if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo,
needed, &needed)) {
ERR("GetPrinterDriverA failed for %s, fix your config!\n",PrintStructures->lpPrinterInfo->pPrinterName);
return FALSE;
}
ClosePrinter(hprn);
PRINTDLG_UpdatePrinterInfoTextsA(hDlg, PrintStructures->lpPrinterInfo);
HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
PrintStructures->lpDevMode = NULL;
dmSize = DocumentPropertiesA(0, 0, name, NULL, NULL, 0);
if(dmSize == -1) {
ERR("DocumentProperties fails on %s\n", debugstr_a(name));
return FALSE;
}
PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
dmSize = DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, NULL,
DM_OUT_BUFFER);
if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
!lstrcmpA( (LPSTR) lpdm->dmDeviceName,
(LPSTR) PrintStructures->lpDevMode->dmDeviceName)) {
/* Supplied devicemode matches current printer so try to use it */
DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, lpdm,
DM_OUT_BUFFER | DM_IN_BUFFER);
}
if(lpdm)
GlobalUnlock(lppd->hDevMode);
lpdm = PrintStructures->lpDevMode; /* use this as a shortcut */
if(!(lppd->Flags & PD_PRINTSETUP)) {
/* Print range (All/Range/Selection) */
if(lppd->nFromPage != 0xffff)
SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
if(lppd->nToPage != 0xffff)
SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
CheckRadioButton(hDlg, rad1, rad3, rad1); /* default */
if (lppd->Flags & PD_NOSELECTION)
EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
else
if (lppd->Flags & PD_SELECTION)
CheckRadioButton(hDlg, rad1, rad3, rad2);
if (lppd->Flags & PD_NOPAGENUMS) {
EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
EnableWindow(GetDlgItem(hDlg, stc2),FALSE);
EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
EnableWindow(GetDlgItem(hDlg, stc3),FALSE);
EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
} else {
if (lppd->Flags & PD_PAGENUMS)
CheckRadioButton(hDlg, rad1, rad3, rad3);
}
/* Collate pages
*
* FIXME: The ico3 is not displayed for some reason. I don't know why.
*/
if (lppd->Flags & PD_COLLATE) {
SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
(LPARAM)PrintStructures->hCollateIcon);
CheckDlgButton(hDlg, chx2, 1);
} else {
SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
(LPARAM)PrintStructures->hNoCollateIcon);
CheckDlgButton(hDlg, chx2, 0);
}
if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
/* if printer doesn't support it: no Collate */
if (!(lpdm->dmFields & DM_COLLATE)) {
EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
EnableWindow(GetDlgItem(hDlg, ico3), FALSE);
}
}
/* nCopies */
{
INT copies;
if (lppd->hDevMode == 0)
copies = lppd->nCopies;
else
copies = lpdm->u1.s1.dmCopies;
if(copies == 0) copies = 1;
else if(copies < 0) copies = MAX_COPIES;
SetDlgItemInt(hDlg, edt3, copies, FALSE);
}
if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
/* if printer doesn't support it: no nCopies */
if (!(lpdm->dmFields & DM_COPIES)) {
EnableWindow(GetDlgItem(hDlg, edt3), FALSE);
EnableWindow(GetDlgItem(hDlg, stc5), FALSE);
}
}
/* print to file */
CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
if (lppd->Flags & PD_DISABLEPRINTTOFILE)
EnableWindow(GetDlgItem(hDlg, chx1), FALSE);
if (lppd->Flags & PD_HIDEPRINTTOFILE)
ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
/* Fill print quality combo, PrintDlg16 */
if(GetDlgItem(hDlg, cmb1))
{
DWORD numResolutions = DeviceCapabilitiesA(PrintStructures->lpPrinterInfo->pPrinterName,
PrintStructures->lpPrinterInfo->pPortName,
DC_ENUMRESOLUTIONS, NULL, lpdm);
if(numResolutions != -1)
{
HWND hQuality = GetDlgItem(hDlg, cmb1);
LONG* Resolutions;
char buf[255];
DWORD i;
int dpiX, dpiY;
HDC hPrinterDC = CreateDCA(PrintStructures->lpPrinterInfo->pDriverName,
PrintStructures->lpPrinterInfo->pPrinterName,
0, lpdm);
Resolutions = HeapAlloc(GetProcessHeap(), 0, numResolutions*sizeof(LONG)*2);
DeviceCapabilitiesA(PrintStructures->lpPrinterInfo->pPrinterName,
PrintStructures->lpPrinterInfo->pPortName,
DC_ENUMRESOLUTIONS, (LPSTR)Resolutions, lpdm);
dpiX = GetDeviceCaps(hPrinterDC, LOGPIXELSX);
dpiY = GetDeviceCaps(hPrinterDC, LOGPIXELSY);
DeleteDC(hPrinterDC);
SendMessageA(hQuality, CB_RESETCONTENT, 0, 0);
for(i = 0; i < (numResolutions * 2); i += 2)
{
BOOL IsDefault = FALSE;
LRESULT Index;
if(Resolutions[i] == Resolutions[i+1])
{
if(dpiX == Resolutions[i])
IsDefault = TRUE;
sprintf(buf, "%d dpi", Resolutions[i]);
} else
{
if(dpiX == Resolutions[i] && dpiY == Resolutions[i+1])
IsDefault = TRUE;
sprintf(buf, "%d dpi x %d dpi", Resolutions[i], Resolutions[i+1]);
}
Index = SendMessageA(hQuality, CB_ADDSTRING, 0, (LPARAM)buf);
if(IsDefault)
SendMessageA(hQuality, CB_SETCURSEL, Index, 0);
SendMessageA(hQuality, CB_SETITEMDATA, Index, MAKELONG(dpiX,dpiY));
}
HeapFree(GetProcessHeap(), 0, Resolutions);
}
}
} else { /* PD_PRINTSETUP */
BOOL bPortrait = (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT);
PRINTDLG_SetUpPaperComboBoxA(hDlg, cmb2,
PrintStructures->lpPrinterInfo->pPrinterName,
PrintStructures->lpPrinterInfo->pPortName,
lpdm);
PRINTDLG_SetUpPaperComboBoxA(hDlg, cmb3,
PrintStructures->lpPrinterInfo->pPrinterName,
PrintStructures->lpPrinterInfo->pPortName,
lpdm);
CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
(LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
PrintStructures->hLandscapeIcon));
}
/* help button */
if ((lppd->Flags & PD_SHOWHELP)==0) {
/* hide if PD_SHOWHELP not specified */
ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE);
}
return TRUE;
}
static BOOL PRINTDLG_ChangePrinterW(HWND hDlg, WCHAR *name,
PRINT_PTRW *PrintStructures)
{
LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
LPDEVMODEW lpdm = NULL;
LONG dmSize;
DWORD needed;
HANDLE hprn;
HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo);
if(!OpenPrinterW(name, &hprn, NULL)) {
ERR("Can't open printer %s\n", debugstr_w(name));
return FALSE;
}
GetPrinterW(hprn, 2, NULL, 0, &needed);
PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,needed);
GetPrinterW(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
&needed);
GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
PrintStructures->lpDriverInfo = HeapAlloc(GetProcessHeap(),0,needed);
if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo,
needed, &needed)) {
ERR("GetPrinterDriverA failed for %s, fix your config!\n",debugstr_w(PrintStructures->lpPrinterInfo->pPrinterName));
return FALSE;
}
ClosePrinter(hprn);
PRINTDLG_UpdatePrinterInfoTextsW(hDlg, PrintStructures->lpPrinterInfo);
HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
PrintStructures->lpDevMode = NULL;
dmSize = DocumentPropertiesW(0, 0, name, NULL, NULL, 0);
if(dmSize == -1) {
ERR("DocumentProperties fails on %s\n", debugstr_w(name));
return FALSE;
}
PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
dmSize = DocumentPropertiesW(0, 0, name, PrintStructures->lpDevMode, NULL,
DM_OUT_BUFFER);
if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
!lstrcmpW(lpdm->dmDeviceName,
PrintStructures->lpDevMode->dmDeviceName)) {
/* Supplied devicemode matches current printer so try to use it */
DocumentPropertiesW(0, 0, name, PrintStructures->lpDevMode, lpdm,
DM_OUT_BUFFER | DM_IN_BUFFER);
}
if(lpdm)
GlobalUnlock(lppd->hDevMode);
lpdm = PrintStructures->lpDevMode; /* use this as a shortcut */
if(!(lppd->Flags & PD_PRINTSETUP)) {
/* Print range (All/Range/Selection) */
if(lppd->nFromPage != 0xffff)
SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
if(lppd->nToPage != 0xffff)
SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
CheckRadioButton(hDlg, rad1, rad3, rad1); /* default */
if (lppd->Flags & PD_NOSELECTION)
EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
else
if (lppd->Flags & PD_SELECTION)
CheckRadioButton(hDlg, rad1, rad3, rad2);
if (lppd->Flags & PD_NOPAGENUMS) {
EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
EnableWindow(GetDlgItem(hDlg, stc2),FALSE);
EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
EnableWindow(GetDlgItem(hDlg, stc3),FALSE);
EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
} else {
if (lppd->Flags & PD_PAGENUMS)
CheckRadioButton(hDlg, rad1, rad3, rad3);
}
/* Collate pages
*
* FIXME: The ico3 is not displayed for some reason. I don't know why.
*/
if (lppd->Flags & PD_COLLATE) {
SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
(LPARAM)PrintStructures->hCollateIcon);
CheckDlgButton(hDlg, chx2, 1);
} else {
SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
(LPARAM)PrintStructures->hNoCollateIcon);
CheckDlgButton(hDlg, chx2, 0);
}
if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
/* if printer doesn't support it: no Collate */
if (!(lpdm->dmFields & DM_COLLATE)) {
EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
EnableWindow(GetDlgItem(hDlg, ico3), FALSE);
}
}
/* nCopies */
{
INT copies;
if (lppd->hDevMode == 0)
copies = lppd->nCopies;
else
copies = lpdm->u1.s1.dmCopies;
if(copies == 0) copies = 1;
else if(copies < 0) copies = MAX_COPIES;
SetDlgItemInt(hDlg, edt3, copies, FALSE);
}
if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
/* if printer doesn't support it: no nCopies */
if (!(lpdm->dmFields & DM_COPIES)) {
EnableWindow(GetDlgItem(hDlg, edt3), FALSE);
EnableWindow(GetDlgItem(hDlg, stc5), FALSE);
}
}
/* print to file */
CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
if (lppd->Flags & PD_DISABLEPRINTTOFILE)
EnableWindow(GetDlgItem(hDlg, chx1), FALSE);
if (lppd->Flags & PD_HIDEPRINTTOFILE)
ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
} else { /* PD_PRINTSETUP */
BOOL bPortrait = (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT);
PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb2,
PrintStructures->lpPrinterInfo->pPrinterName,
PrintStructures->lpPrinterInfo->pPortName,
lpdm);
PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb3,
PrintStructures->lpPrinterInfo->pPrinterName,
PrintStructures->lpPrinterInfo->pPortName,
lpdm);
CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
(LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
PrintStructures->hLandscapeIcon));
}
/* help button */
if ((lppd->Flags & PD_SHOWHELP)==0) {
/* hide if PD_SHOWHELP not specified */
ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE);
}
return TRUE;
}
/***********************************************************************
* check_printer_setup [internal]
*/
static LRESULT check_printer_setup(HWND hDlg)
{
DWORD needed,num;
WCHAR resourcestr[256],resultstr[256];
EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
if(needed == 0)
{
EnumPrintersW(PRINTER_ENUM_CONNECTIONS, NULL, 2, NULL, 0, &needed, &num);
}
if(needed > 0)
return TRUE;
else
{
LoadStringW(COMDLG32_hInstance, PD32_NO_DEVICES,resultstr, 255);
LoadStringW(COMDLG32_hInstance, PD32_PRINT_TITLE,resourcestr, 255);
MessageBoxW(hDlg, resultstr, resourcestr,MB_OK | MB_ICONWARNING);
return FALSE;
}
}
/***********************************************************************
* PRINTDLG_WMInitDialog [internal]
*/
static LRESULT PRINTDLG_WMInitDialog(HWND hDlg,
PRINT_PTRA* PrintStructures)
{
LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
DEVNAMES *pdn;
DEVMODEA *pdm;
char *name = NULL;
UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
/* load Collate ICONs */
/* We load these with LoadImage because they are not a standard
size and we don't want them rescaled */
PrintStructures->hCollateIcon =
LoadImageA(COMDLG32_hInstance, "PD32_COLLATE", IMAGE_ICON, 0, 0, 0);
PrintStructures->hNoCollateIcon =
LoadImageA(COMDLG32_hInstance, "PD32_NOCOLLATE", IMAGE_ICON, 0, 0, 0);
/* These can be done with LoadIcon */
PrintStructures->hPortraitIcon =
LoadIconA(COMDLG32_hInstance, "PD32_PORTRAIT");
PrintStructures->hLandscapeIcon =
LoadIconA(COMDLG32_hInstance, "PD32_LANDSCAPE");
/* display the collate/no_collate icon */
SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
(LPARAM)PrintStructures->hNoCollateIcon);
if(PrintStructures->hCollateIcon == 0 ||
PrintStructures->hNoCollateIcon == 0 ||
PrintStructures->hPortraitIcon == 0 ||
PrintStructures->hLandscapeIcon == 0) {
ERR("no icon in resourcefile\n");
COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
EndDialog(hDlg, FALSE);
}
/*
* if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
* must be registered and the Help button must be shown.
*/
if (lppd->Flags & PD_SHOWHELP) {
if((PrintStructures->HelpMessageID =
RegisterWindowMessageA(HELPMSGSTRINGA)) == 0) {
COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
return FALSE;
}
} else
PrintStructures->HelpMessageID = 0;
if(!(lppd->Flags &PD_PRINTSETUP)) {
PrintStructures->hwndUpDown =
CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER |
UDS_NOTHOUSANDS | UDS_ARROWKEYS |
UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
hDlg, UPDOWN_ID, COMDLG32_hInstance,
GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
}
/* FIXME: I allow more freedom than either Win95 or WinNT,
* which do not agree to what errors should be thrown or not
* in case nToPage or nFromPage is out-of-range.
*/
if (lppd->nMaxPage < lppd->nMinPage)
lppd->nMaxPage = lppd->nMinPage;
if (lppd->nMinPage == lppd->nMaxPage)
lppd->Flags |= PD_NOPAGENUMS;
if (lppd->nToPage < lppd->nMinPage)
lppd->nToPage = lppd->nMinPage;
if (lppd->nToPage > lppd->nMaxPage)
lppd->nToPage = lppd->nMaxPage;
if (lppd->nFromPage < lppd->nMinPage)
lppd->nFromPage = lppd->nMinPage;
if (lppd->nFromPage > lppd->nMaxPage)
lppd->nFromPage = lppd->nMaxPage;
/* if we have the combo box, fill it */
if (GetDlgItem(hDlg,comboID)) {
/* Fill Combobox
*/
pdn = GlobalLock(lppd->hDevNames);
pdm = GlobalLock(lppd->hDevMode);
if(pdn)
name = (char*)pdn + pdn->wDeviceOffset;
else if(pdm)
name = (char*)pdm->dmDeviceName;
PRINTDLG_SetUpPrinterListComboA(hDlg, comboID, name);
if(pdm) GlobalUnlock(lppd->hDevMode);
if(pdn) GlobalUnlock(lppd->hDevNames);
/* Now find selected printer and update rest of dlg */
name = HeapAlloc(GetProcessHeap(),0,256);
if (GetDlgItemTextA(hDlg, comboID, name, 255))
PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
HeapFree(GetProcessHeap(),0,name);
} else {
/* else use default printer */
char name[200];
DWORD dwBufLen = sizeof(name);
BOOL ret = GetDefaultPrinterA(name, &dwBufLen);
if (ret)
PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
else
FIXME("No default printer found, expect problems!\n");
}
return TRUE;
}
static LRESULT PRINTDLG_WMInitDialogW(HWND hDlg,
PRINT_PTRW* PrintStructures)
{
LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
DEVNAMES *pdn;
DEVMODEW *pdm;
WCHAR *name = NULL;
UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
/* load Collate ICONs */
/* We load these with LoadImage because they are not a standard
size and we don't want them rescaled */
PrintStructures->hCollateIcon =
LoadImageW(COMDLG32_hInstance, pd32_collateW, IMAGE_ICON, 0, 0, 0);
PrintStructures->hNoCollateIcon =
LoadImageW(COMDLG32_hInstance, pd32_nocollateW, IMAGE_ICON, 0, 0, 0);
/* These can be done with LoadIcon */
PrintStructures->hPortraitIcon =
LoadIconW(COMDLG32_hInstance, pd32_portraitW);
PrintStructures->hLandscapeIcon =
LoadIconW(COMDLG32_hInstance, pd32_landscapeW);
/* display the collate/no_collate icon */
SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
(LPARAM)PrintStructures->hNoCollateIcon);
if(PrintStructures->hCollateIcon == 0 ||
PrintStructures->hNoCollateIcon == 0 ||
PrintStructures->hPortraitIcon == 0 ||
PrintStructures->hLandscapeIcon == 0) {
ERR("no icon in resourcefile\n");
COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
EndDialog(hDlg, FALSE);
}
/*
* if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
* must be registered and the Help button must be shown.
*/
if (lppd->Flags & PD_SHOWHELP) {
if((PrintStructures->HelpMessageID =
RegisterWindowMessageW(HELPMSGSTRINGW)) == 0) {
COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
return FALSE;
}
} else
PrintStructures->HelpMessageID = 0;
if(!(lppd->Flags &PD_PRINTSETUP)) {
PrintStructures->hwndUpDown =
CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER |
UDS_NOTHOUSANDS | UDS_ARROWKEYS |
UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
hDlg, UPDOWN_ID, COMDLG32_hInstance,
GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
}
/* FIXME: I allow more freedom than either Win95 or WinNT,
* which do not agree to what errors should be thrown or not
* in case nToPage or nFromPage is out-of-range.
*/
if (lppd->nMaxPage < lppd->nMinPage)
lppd->nMaxPage = lppd->nMinPage;
if (lppd->nMinPage == lppd->nMaxPage)
lppd->Flags |= PD_NOPAGENUMS;
if (lppd->nToPage < lppd->nMinPage)
lppd->nToPage = lppd->nMinPage;
if (lppd->nToPage > lppd->nMaxPage)
lppd->nToPage = lppd->nMaxPage;
if (lppd->nFromPage < lppd->nMinPage)
lppd->nFromPage = lppd->nMinPage;
if (lppd->nFromPage > lppd->nMaxPage)
lppd->nFromPage = lppd->nMaxPage;
/* if we have the combo box, fill it */
if (GetDlgItem(hDlg,comboID)) {
/* Fill Combobox
*/
pdn = GlobalLock(lppd->hDevNames);
pdm = GlobalLock(lppd->hDevMode);
if(pdn)
name = (WCHAR*)pdn + pdn->wDeviceOffset;
else if(pdm)
name = pdm->dmDeviceName;
PRINTDLG_SetUpPrinterListComboW(hDlg, comboID, name);
if(pdm) GlobalUnlock(lppd->hDevMode);
if(pdn) GlobalUnlock(lppd->hDevNames);
/* Now find selected printer and update rest of dlg */
/* ansi is ok here */
name = HeapAlloc(GetProcessHeap(),0,256*sizeof(WCHAR));
if (GetDlgItemTextW(hDlg, comboID, name, 255))
PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
HeapFree(GetProcessHeap(),0,name);
} else {
/* else use default printer */
WCHAR name[200];
DWORD dwBufLen = sizeof(name) / sizeof(WCHAR);
BOOL ret = GetDefaultPrinterW(name, &dwBufLen);
if (ret)
PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
else
FIXME("No default printer found, expect problems!\n");
}
return TRUE;
}
/***********************************************************************
* PRINTDLG_WMCommand [internal]
*/
static LRESULT PRINTDLG_WMCommandA(HWND hDlg, WPARAM wParam,
PRINT_PTRA* PrintStructures)
{
LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
LPDEVMODEA lpdm = PrintStructures->lpDevMode;
switch (LOWORD(wParam)) {
case IDOK:
TRACE(" OK button was hit\n");
if (!PRINTDLG_UpdatePrintDlgA(hDlg, PrintStructures)) {
FIXME("Update printdlg was not successful!\n");
return(FALSE);
}
EndDialog(hDlg, TRUE);
return(TRUE);
case IDCANCEL:
TRACE(" CANCEL button was hit\n");
EndDialog(hDlg, FALSE);
return(FALSE);
case pshHelp:
TRACE(" HELP button was hit\n");
SendMessageA(lppd->hwndOwner, PrintStructures->HelpMessageID,
(WPARAM) hDlg, (LPARAM) lppd);
break;
case chx2: /* collate pages checkbox */
if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
(LPARAM)PrintStructures->hCollateIcon);
else
SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
(LPARAM)PrintStructures->hNoCollateIcon);
break;
case edt1: /* from page nr editbox */
case edt2: /* to page nr editbox */
if (HIWORD(wParam)==EN_CHANGE) {
WORD nToPage;
WORD nFromPage;
nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
CheckRadioButton(hDlg, rad1, rad3, rad3);
}
break;
case edt3:
if(HIWORD(wParam) == EN_CHANGE) {
INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
if(copies <= 1)
EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
else
EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
}
break;
case psh2: /* Properties button */
{
HANDLE hPrinter;
char PrinterName[256];
GetDlgItemTextA(hDlg, PrinterComboID, PrinterName, 255);
if (!OpenPrinterA(PrinterName, &hPrinter, NULL)) {
FIXME(" Call to OpenPrinter did not succeed!\n");
break;
}
DocumentPropertiesA(hDlg, hPrinter, PrinterName,
PrintStructures->lpDevMode,
PrintStructures->lpDevMode,
DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
ClosePrinter(hPrinter);
break;
}
case rad1: /* Paperorientation */
if (lppd->Flags & PD_PRINTSETUP)
{
lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
(LPARAM)(PrintStructures->hPortraitIcon));
}
break;
case rad2: /* Paperorientation */
if (lppd->Flags & PD_PRINTSETUP)
{
lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
(LPARAM)(PrintStructures->hLandscapeIcon));
}
break;
case cmb1: /* Printer Combobox in PRINT SETUP, quality combobox in PRINT16 */
if (PrinterComboID != LOWORD(wParam)) {
break;
}
/* FALLTHROUGH */
case cmb4: /* Printer combobox */
if (HIWORD(wParam)==CBN_SELCHANGE) {
char PrinterName[256];
GetDlgItemTextA(hDlg, LOWORD(wParam), PrinterName, 255);
PRINTDLG_ChangePrinterA(hDlg, PrinterName, PrintStructures);
}
break;
case cmb2: /* Papersize */
{
DWORD Sel = SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0);
if(Sel != CB_ERR)
lpdm->u1.s1.dmPaperSize = SendDlgItemMessageA(hDlg, cmb2,
CB_GETITEMDATA,
Sel, 0);
}
break;
case cmb3: /* Bin */
{
DWORD Sel = SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0);
if(Sel != CB_ERR)
lpdm->u1.s1.dmDefaultSource = SendDlgItemMessageA(hDlg, cmb3,
CB_GETITEMDATA, Sel,
0);
}
break;
}
if(lppd->Flags & PD_PRINTSETUP) {
switch (LOWORD(wParam)) {
case rad1: /* orientation */
case rad2:
if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) {
lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE, IMAGE_ICON,
(LPARAM)PrintStructures->hPortraitIcon);
SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
(LPARAM)PrintStructures->hPortraitIcon);
}
} else {
if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) {
lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE, IMAGE_ICON,
(LPARAM)PrintStructures->hLandscapeIcon);
SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
(LPARAM)PrintStructures->hLandscapeIcon);
}
}
break;
}
}
return FALSE;
}
static LRESULT PRINTDLG_WMCommandW(HWND hDlg, WPARAM wParam,
PRINT_PTRW* PrintStructures)
{
LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
LPDEVMODEW lpdm = PrintStructures->lpDevMode;
switch (LOWORD(wParam)) {
case IDOK:
TRACE(" OK button was hit\n");
if (!PRINTDLG_UpdatePrintDlgW(hDlg, PrintStructures)) {
FIXME("Update printdlg was not successful!\n");
return(FALSE);
}
EndDialog(hDlg, TRUE);
return(TRUE);
case IDCANCEL:
TRACE(" CANCEL button was hit\n");
EndDialog(hDlg, FALSE);
return(FALSE);
case pshHelp:
TRACE(" HELP button was hit\n");
SendMessageW(lppd->hwndOwner, PrintStructures->HelpMessageID,
(WPARAM) hDlg, (LPARAM) lppd);
break;
case chx2: /* collate pages checkbox */
if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
(LPARAM)PrintStructures->hCollateIcon);
else
SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
(LPARAM)PrintStructures->hNoCollateIcon);
break;
case edt1: /* from page nr editbox */
case edt2: /* to page nr editbox */
if (HIWORD(wParam)==EN_CHANGE) {
WORD nToPage;
WORD nFromPage;
nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
CheckRadioButton(hDlg, rad1, rad3, rad3);
}
break;
case edt3:
if(HIWORD(wParam) == EN_CHANGE) {
INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
if(copies <= 1)
EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
else
EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
}
break;
case psh2: /* Properties button */
{
HANDLE hPrinter;
WCHAR PrinterName[256];
if (!GetDlgItemTextW(hDlg, PrinterComboID, PrinterName, 255)) break;
if (!OpenPrinterW(PrinterName, &hPrinter, NULL)) {
FIXME(" Call to OpenPrinter did not succeed!\n");
break;
}
DocumentPropertiesW(hDlg, hPrinter, PrinterName,
PrintStructures->lpDevMode,
PrintStructures->lpDevMode,
DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
ClosePrinter(hPrinter);
break;
}
case rad1: /* Paperorientation */
if (lppd->Flags & PD_PRINTSETUP)
{
lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
(LPARAM)(PrintStructures->hPortraitIcon));
}
break;
case rad2: /* Paperorientation */
if (lppd->Flags & PD_PRINTSETUP)
{
lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
(LPARAM)(PrintStructures->hLandscapeIcon));
}
break;
case cmb1: /* Printer Combobox in PRINT SETUP */
/* FALLTHROUGH */
case cmb4: /* Printer combobox */
if (HIWORD(wParam)==CBN_SELCHANGE) {
WCHAR PrinterName[256];
GetDlgItemTextW(hDlg, LOWORD(wParam), PrinterName, 255);
PRINTDLG_ChangePrinterW(hDlg, PrinterName, PrintStructures);
}
break;
case cmb2: /* Papersize */
{
DWORD Sel = SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0);
if(Sel != CB_ERR)
lpdm->u1.s1.dmPaperSize = SendDlgItemMessageW(hDlg, cmb2,
CB_GETITEMDATA,
Sel, 0);
}
break;
case cmb3: /* Bin */
{
DWORD Sel = SendDlgItemMessageW(hDlg, cmb3, CB_GETCURSEL, 0, 0);
if(Sel != CB_ERR)
lpdm->u1.s1.dmDefaultSource = SendDlgItemMessageW(hDlg, cmb3,
CB_GETITEMDATA, Sel,
0);
}
break;
}
if(lppd->Flags & PD_PRINTSETUP) {
switch (LOWORD(wParam)) {
case rad1: /* orientation */
case rad2:
if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) {
lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
SendDlgItemMessageW(hDlg, stc10, STM_SETIMAGE, IMAGE_ICON,
(LPARAM)PrintStructures->hPortraitIcon);
SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
(LPARAM)PrintStructures->hPortraitIcon);
}
} else {
if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) {
lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
SendDlgItemMessageW(hDlg, stc10, STM_SETIMAGE, IMAGE_ICON,
(LPARAM)PrintStructures->hLandscapeIcon);
SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
(LPARAM)PrintStructures->hLandscapeIcon);
}
}
break;
}
}
return FALSE;
}
/***********************************************************************
* PrintDlgProcA [internal]
*/
static INT_PTR CALLBACK PrintDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
PRINT_PTRA* PrintStructures;
INT_PTR res = FALSE;
if (uMsg!=WM_INITDIALOG) {
PrintStructures = GetPropW(hDlg, printdlg_prop);
if (!PrintStructures)
return FALSE;
} else {
PrintStructures = (PRINT_PTRA*) lParam;
SetPropW(hDlg, printdlg_prop, PrintStructures);
if(!check_printer_setup(hDlg))
{
EndDialog(hDlg,FALSE);
return FALSE;
}
res = PRINTDLG_WMInitDialog(hDlg, PrintStructures);
if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
res = PrintStructures->lpPrintDlg->lpfnPrintHook(
hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg
);
return res;
}
if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam,
lParam);
if(res) return res;
}
switch (uMsg) {
case WM_COMMAND:
return PRINTDLG_WMCommandA(hDlg, wParam, PrintStructures);
case WM_DESTROY:
DestroyIcon(PrintStructures->hCollateIcon);
DestroyIcon(PrintStructures->hNoCollateIcon);
DestroyIcon(PrintStructures->hPortraitIcon);
DestroyIcon(PrintStructures->hLandscapeIcon);
if(PrintStructures->hwndUpDown)
DestroyWindow(PrintStructures->hwndUpDown);
return FALSE;
}
return res;
}
static INT_PTR CALLBACK PrintDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
PRINT_PTRW* PrintStructures;
INT_PTR res = FALSE;
if (uMsg!=WM_INITDIALOG) {
PrintStructures = GetPropW(hDlg, printdlg_prop);
if (!PrintStructures)
return FALSE;
} else {
PrintStructures = (PRINT_PTRW*) lParam;
SetPropW(hDlg, printdlg_prop, PrintStructures);
if(!check_printer_setup(hDlg))
{
EndDialog(hDlg,FALSE);
return FALSE;
}
res = PRINTDLG_WMInitDialogW(hDlg, PrintStructures);
if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg);
return res;
}
if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam, lParam);
if(res) return res;
}
switch (uMsg) {
case WM_COMMAND:
return PRINTDLG_WMCommandW(hDlg, wParam, PrintStructures);
case WM_DESTROY:
DestroyIcon(PrintStructures->hCollateIcon);
DestroyIcon(PrintStructures->hNoCollateIcon);
DestroyIcon(PrintStructures->hPortraitIcon);
DestroyIcon(PrintStructures->hLandscapeIcon);
if(PrintStructures->hwndUpDown)
DestroyWindow(PrintStructures->hwndUpDown);
return FALSE;
}
return res;
}
/************************************************************
*
* PRINTDLG_GetDlgTemplate
*
*/
static HGLOBAL PRINTDLG_GetDlgTemplateA(const PRINTDLGA *lppd)
{
HRSRC hResInfo;
HGLOBAL hDlgTmpl;
if (lppd->Flags & PD_PRINTSETUP) {
if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
hDlgTmpl = lppd->hSetupTemplate;
} else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
hResInfo = FindResourceA(lppd->hInstance,
lppd->lpSetupTemplateName, (LPSTR)RT_DIALOG);
hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
} else {
hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32_SETUP",
(LPSTR)RT_DIALOG);
hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
}
} else {
if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
hDlgTmpl = lppd->hPrintTemplate;
} else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
hResInfo = FindResourceA(lppd->hInstance,
lppd->lpPrintTemplateName,
(LPSTR)RT_DIALOG);
hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
} else {
hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32",
(LPSTR)RT_DIALOG);
hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
}
}
return hDlgTmpl;
}
static HGLOBAL PRINTDLG_GetDlgTemplateW(const PRINTDLGW *lppd)
{
HRSRC hResInfo;
HGLOBAL hDlgTmpl;
static const WCHAR xpsetup[] = { 'P','R','I','N','T','3','2','_','S','E','T','U','P',0};
static const WCHAR xprint[] = { 'P','R','I','N','T','3','2',0};
if (lppd->Flags & PD_PRINTSETUP) {
if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
hDlgTmpl = lppd->hSetupTemplate;
} else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
hResInfo = FindResourceW(lppd->hInstance,
lppd->lpSetupTemplateName, (LPWSTR)RT_DIALOG);
hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
} else {
hResInfo = FindResourceW(COMDLG32_hInstance, xpsetup, (LPWSTR)RT_DIALOG);
hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
}
} else {
if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
hDlgTmpl = lppd->hPrintTemplate;
} else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
hResInfo = FindResourceW(lppd->hInstance,
lppd->lpPrintTemplateName,
(LPWSTR)RT_DIALOG);
hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
} else {
hResInfo = FindResourceW(COMDLG32_hInstance, xprint, (LPWSTR)RT_DIALOG);
hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
}
}
return hDlgTmpl;
}
/***********************************************************************
*
* PRINTDLG_CreateDC
*
*/
static BOOL PRINTDLG_CreateDCA(LPPRINTDLGA lppd)
{
DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
DEVMODEA *pdm = GlobalLock(lppd->hDevMode);
if(lppd->Flags & PD_RETURNDC) {
lppd->hDC = CreateDCA((char*)pdn + pdn->wDriverOffset,
(char*)pdn + pdn->wDeviceOffset,
(char*)pdn + pdn->wOutputOffset,
pdm );
} else if(lppd->Flags & PD_RETURNIC) {
lppd->hDC = CreateICA((char*)pdn + pdn->wDriverOffset,
(char*)pdn + pdn->wDeviceOffset,
(char*)pdn + pdn->wOutputOffset,
pdm );
}
GlobalUnlock(lppd->hDevNames);
GlobalUnlock(lppd->hDevMode);
return lppd->hDC ? TRUE : FALSE;
}
static BOOL PRINTDLG_CreateDCW(LPPRINTDLGW lppd)
{
DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
DEVMODEW *pdm = GlobalLock(lppd->hDevMode);
if(lppd->Flags & PD_RETURNDC) {
lppd->hDC = CreateDCW((WCHAR*)pdn + pdn->wDriverOffset,
(WCHAR*)pdn + pdn->wDeviceOffset,
(WCHAR*)pdn + pdn->wOutputOffset,
pdm );
} else if(lppd->Flags & PD_RETURNIC) {
lppd->hDC = CreateICW((WCHAR*)pdn + pdn->wDriverOffset,
(WCHAR*)pdn + pdn->wDeviceOffset,
(WCHAR*)pdn + pdn->wOutputOffset,
pdm );
}
GlobalUnlock(lppd->hDevNames);
GlobalUnlock(lppd->hDevMode);
return lppd->hDC ? TRUE : FALSE;
}
/***********************************************************************
* PrintDlgA (COMDLG32.@)
*
* Displays the PRINT dialog box, which enables the user to specify
* specific properties of the print job.
*
* PARAMS
* lppd [IO] ptr to PRINTDLG32 struct
*
* RETURNS
* nonzero if the user pressed the OK button
* zero if the user cancelled the window or an error occurred
*
* BUGS
* PrintDlg:
* * The Collate Icons do not display, even though they are in the code.
* * The Properties Button(s) should call DocumentPropertiesA().
*/
BOOL WINAPI PrintDlgA(LPPRINTDLGA lppd)
{
BOOL bRet = FALSE;
LPVOID ptr;
HINSTANCE hInst;
if (!lppd)
{
COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION);
return FALSE;
}
if(TRACE_ON(commdlg)) {
char flagstr[1000] = "";
const struct pd_flags *pflag = pd_flags;
for( ; pflag->name; pflag++) {
if(lppd->Flags & pflag->flag)
strcat(flagstr, pflag->name);
}
TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
"pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
"flags %08x (%s)\n",
lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
}
if(lppd->lStructSize != sizeof(PRINTDLGA)) {
WARN("structure size failure !!!\n");
COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
return FALSE;
}
if(lppd->Flags & PD_RETURNDEFAULT) {
PRINTER_INFO_2A *pbuf;
DRIVER_INFO_3A *dbuf;
HANDLE hprn;
DWORD needed;
if(lppd->hDevMode || lppd->hDevNames) {
WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
return FALSE;
}
if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
WARN("Can't find default printer\n");
COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
return FALSE;
}
GetPrinterA(hprn, 2, NULL, 0, &needed);
pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
dbuf = HeapAlloc(GetProcessHeap(),0,needed);
if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
ERR("GetPrinterDriverA failed, le %d, fix your config for printer %s!\n",
GetLastError(),pbuf->pPrinterName);
HeapFree(GetProcessHeap(), 0, dbuf);
HeapFree(GetProcessHeap(), 0, pbuf);
COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
return FALSE;
}
ClosePrinter(hprn);
PRINTDLG_CreateDevNames(&(lppd->hDevNames),
dbuf->pDriverPath,
pbuf->pPrinterName,
pbuf->pPortName);
lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
pbuf->pDevMode->dmDriverExtra);
ptr = GlobalLock(lppd->hDevMode);
memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
pbuf->pDevMode->dmDriverExtra);
GlobalUnlock(lppd->hDevMode);
HeapFree(GetProcessHeap(), 0, pbuf);
HeapFree(GetProcessHeap(), 0, dbuf);
bRet = TRUE;
} else {
HGLOBAL hDlgTmpl;
PRINT_PTRA *PrintStructures;
/* load Dialog resources,
* depending on Flags indicates Print32 or Print32_setup dialog
*/
hDlgTmpl = PRINTDLG_GetDlgTemplateA(lppd);
if (!hDlgTmpl) {
COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
return FALSE;
}
ptr = LockResource( hDlgTmpl );
if (!ptr) {
COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
return FALSE;
}
PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(PRINT_PTRA));
PrintStructures->lpPrintDlg = lppd;
/* and create & process the dialog .
* -1 is failure, 0 is broken hwnd, everything else is ok.
*/
hInst = COMDLG32_hInstance;
if (lppd->Flags & (PD_ENABLESETUPTEMPLATE | PD_ENABLEPRINTTEMPLATE)) hInst = lppd->hInstance;
bRet = (0<DialogBoxIndirectParamA(hInst, ptr, lppd->hwndOwner,
PrintDlgProcA,
(LPARAM)PrintStructures));
if(bRet) {
DEVMODEA *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
PRINTER_INFO_2A *pi = PrintStructures->lpPrinterInfo;
DRIVER_INFO_3A *di = PrintStructures->lpDriverInfo;
if (lppd->hDevMode == 0) {
TRACE(" No hDevMode yet... Need to create my own\n");
lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE,
lpdm->dmSize + lpdm->dmDriverExtra);
} else {
lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
lpdm->dmSize + lpdm->dmDriverExtra,
GMEM_MOVEABLE);
}
lpdmReturn = GlobalLock(lppd->hDevMode);
memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
PRINTDLG_CreateDevNames(&(lppd->hDevNames),
di->pDriverPath,
pi->pPrinterName,
pi->pPortName
);
GlobalUnlock(lppd->hDevMode);
}
HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
HeapFree(GetProcessHeap(), 0, PrintStructures);
}
if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
bRet = PRINTDLG_CreateDCA(lppd);
TRACE("exit! (%d)\n", bRet);
return bRet;
}
/***********************************************************************
* PrintDlgW (COMDLG32.@)
*
* See PrintDlgA.
*/
BOOL WINAPI PrintDlgW(LPPRINTDLGW lppd)
{
BOOL bRet = FALSE;
LPVOID ptr;
HINSTANCE hInst;
if (!lppd)
{
COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION);
return FALSE;
}
if(TRACE_ON(commdlg)) {
char flagstr[1000] = "";
const struct pd_flags *pflag = pd_flags;
for( ; pflag->name; pflag++) {
if(lppd->Flags & pflag->flag)
strcat(flagstr, pflag->name);
}
TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
"pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
"flags %08x (%s)\n",
lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
}
if(lppd->lStructSize != sizeof(PRINTDLGW)) {
WARN("structure size failure !!!\n");
COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
return FALSE;
}
if(lppd->Flags & PD_RETURNDEFAULT) {
PRINTER_INFO_2W *pbuf;
DRIVER_INFO_3W *dbuf;
HANDLE hprn;
DWORD needed;
if(lppd->hDevMode || lppd->hDevNames) {
WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
return FALSE;
}
if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
WARN("Can't find default printer\n");
COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
return FALSE;
}
GetPrinterW(hprn, 2, NULL, 0, &needed);
pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
GetPrinterW(hprn, 2, (LPBYTE)pbuf, needed, &needed);
GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
dbuf = HeapAlloc(GetProcessHeap(),0,needed);
if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
ERR("GetPrinterDriverA failed, le %d, fix your config for printer %s!\n",
GetLastError(),debugstr_w(pbuf->pPrinterName));
HeapFree(GetProcessHeap(), 0, dbuf);
HeapFree(GetProcessHeap(), 0, pbuf);
COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
return FALSE;
}
ClosePrinter(hprn);
PRINTDLG_CreateDevNamesW(&(lppd->hDevNames),
dbuf->pDriverPath,
pbuf->pPrinterName,
pbuf->pPortName);
lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
pbuf->pDevMode->dmDriverExtra);
ptr = GlobalLock(lppd->hDevMode);
memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
pbuf->pDevMode->dmDriverExtra);
GlobalUnlock(lppd->hDevMode);
HeapFree(GetProcessHeap(), 0, pbuf);
HeapFree(GetProcessHeap(), 0, dbuf);
bRet = TRUE;
} else {
HGLOBAL hDlgTmpl;
PRINT_PTRW *PrintStructures;
/* load Dialog resources,
* depending on Flags indicates Print32 or Print32_setup dialog
*/
hDlgTmpl = PRINTDLG_GetDlgTemplateW(lppd);
if (!hDlgTmpl) {
COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
return FALSE;
}
ptr = LockResource( hDlgTmpl );
if (!ptr) {
COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
return FALSE;
}
PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(PRINT_PTRW));
PrintStructures->lpPrintDlg = lppd;
/* and create & process the dialog .
* -1 is failure, 0 is broken hwnd, everything else is ok.
*/
hInst = COMDLG32_hInstance;
if (lppd->Flags & (PD_ENABLESETUPTEMPLATE | PD_ENABLEPRINTTEMPLATE)) hInst = lppd->hInstance;
bRet = (0<DialogBoxIndirectParamW(hInst, ptr, lppd->hwndOwner,
PrintDlgProcW,
(LPARAM)PrintStructures));
if(bRet) {
DEVMODEW *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
PRINTER_INFO_2W *pi = PrintStructures->lpPrinterInfo;
DRIVER_INFO_3W *di = PrintStructures->lpDriverInfo;
if (lppd->hDevMode == 0) {
TRACE(" No hDevMode yet... Need to create my own\n");
lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE,
lpdm->dmSize + lpdm->dmDriverExtra);
} else {
WORD locks;
if((locks = (GlobalFlags(lppd->hDevMode) & GMEM_LOCKCOUNT))) {
WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
while(locks--) {
GlobalUnlock(lppd->hDevMode);
TRACE("Now got %d locks\n", locks);
}
}
lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
lpdm->dmSize + lpdm->dmDriverExtra,
GMEM_MOVEABLE);
}
lpdmReturn = GlobalLock(lppd->hDevMode);
memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
if (lppd->hDevNames != 0) {
WORD locks;
if((locks = (GlobalFlags(lppd->hDevNames) & GMEM_LOCKCOUNT))) {
WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
while(locks--)
GlobalUnlock(lppd->hDevNames);
}
}
PRINTDLG_CreateDevNamesW(&(lppd->hDevNames),
di->pDriverPath,
pi->pPrinterName,
pi->pPortName
);
GlobalUnlock(lppd->hDevMode);
}
HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
HeapFree(GetProcessHeap(), 0, PrintStructures);
}
if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
bRet = PRINTDLG_CreateDCW(lppd);
TRACE("exit! (%d)\n", bRet);
return bRet;
}
/***********************************************************************
*
* PageSetupDlg
* rad1 - portrait
* rad2 - landscape
* cmb1 - printer select (not in standard dialog template)
* cmb2 - paper size
* cmb3 - source (tray?)
* edt4 - border left
* edt5 - border top
* edt6 - border right
* edt7 - border bottom
* psh3 - "Printer..."
*/
typedef struct
{
BOOL unicode;
union
{
LPPAGESETUPDLGA dlga;
LPPAGESETUPDLGW dlgw;
} u;
HWND hDlg; /* Page Setup dialog handle */
RECT rtDrawRect; /* Drawing rect for page */
} pagesetup_data;
static inline DWORD pagesetup_get_flags(const pagesetup_data *data)
{
return data->u.dlgw->Flags;
}
static inline BOOL is_metric(const pagesetup_data *data)
{
return pagesetup_get_flags(data) & PSD_INHUNDREDTHSOFMILLIMETERS;
}
static inline LONG tenths_mm_to_size(const pagesetup_data *data, LONG size)
{
if (is_metric(data))
return 10 * size;
else
return 10 * size * 100 / 254;
}
static inline LONG thousandths_inch_to_size(const pagesetup_data *data, LONG size)
{
if (is_metric(data))
return size * 254 / 100;
else
return size;
}
static WCHAR get_decimal_sep(void)
{
static WCHAR sep;
if(!sep)
{
WCHAR buf[2] = {'.',0};
GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, buf, sizeof(buf) / sizeof(buf[0]));
sep = buf[0];
}
return sep;
}
static void size2str(const pagesetup_data *data, DWORD size, LPWSTR strout)
{
WCHAR integer_fmt[] = {'%','d',0};
WCHAR hundredths_fmt[] = {'%','d','%','c','%','0','2','d',0};
WCHAR thousandths_fmt[] = {'%','d','%','c','%','0','3','d',0};
/* FIXME use LOCALE_SDECIMAL when the edit parsing code can cope */
if (is_metric(data))
{
if(size % 100)
wsprintfW(strout, hundredths_fmt, size / 100, get_decimal_sep(), size % 100);
else
wsprintfW(strout, integer_fmt, size / 100);
}
else
{
if(size % 1000)
wsprintfW(strout, thousandths_fmt, size / 1000, get_decimal_sep(), size % 1000);
else
wsprintfW(strout, integer_fmt, size / 1000);
}
}
static inline BOOL is_default_metric(void)
{
DWORD system;
GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IMEASURE | LOCALE_RETURN_NUMBER,
(LPWSTR)&system, sizeof(system));
return system == 0;
}
/**********************************************
* rotate_rect
* Cyclically permute the four members of rc
* If sense is TRUE l -> t -> r -> b
* otherwise l <- t <- r <- b
*/
static inline void rotate_rect(RECT *rc, BOOL sense)
{
INT tmp;
if(sense)
{
tmp = rc->bottom;
rc->bottom = rc->right;
rc->right = rc->top;
rc->top = rc->left;
rc->left = tmp;
}
else
{
tmp = rc->left;
rc->left = rc->top;
rc->top = rc->right;
rc->right = rc->bottom;
rc->bottom = tmp;
}
}
static void pagesetup_set_orientation(pagesetup_data *data, WORD orient)
{
DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
assert(orient == DMORIENT_PORTRAIT || orient == DMORIENT_LANDSCAPE);
if(data->unicode)
dm->u1.s1.dmOrientation = orient;
else
{
DEVMODEA *dmA = (DEVMODEA *)dm;
dmA->u1.s1.dmOrientation = orient;
}
GlobalUnlock(data->u.dlgw->hDevMode);
}
static WORD pagesetup_get_orientation(const pagesetup_data *data)
{
DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
WORD orient;
if(data->unicode)
orient = dm->u1.s1.dmOrientation;
else
{
DEVMODEA *dmA = (DEVMODEA *)dm;
orient = dmA->u1.s1.dmOrientation;
}
GlobalUnlock(data->u.dlgw->hDevMode);
return orient;
}
static void pagesetup_set_papersize(pagesetup_data *data, WORD paper)
{
DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
if(data->unicode)
dm->u1.s1.dmPaperSize = paper;
else
{
DEVMODEA *dmA = (DEVMODEA *)dm;
dmA->u1.s1.dmPaperSize = paper;
}
GlobalUnlock(data->u.dlgw->hDevMode);
}
static WORD pagesetup_get_papersize(const pagesetup_data *data)
{
DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
WORD paper;
if(data->unicode)
paper = dm->u1.s1.dmPaperSize;
else
{
DEVMODEA *dmA = (DEVMODEA *)dm;
paper = dmA->u1.s1.dmPaperSize;
}
GlobalUnlock(data->u.dlgw->hDevMode);
return paper;
}
static void pagesetup_set_defaultsource(pagesetup_data *data, WORD source)
{
DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
if(data->unicode)
dm->u1.s1.dmDefaultSource = source;
else
{
DEVMODEA *dmA = (DEVMODEA *)dm;
dmA->u1.s1.dmDefaultSource = source;
}
GlobalUnlock(data->u.dlgw->hDevMode);
}
typedef enum
{
devnames_driver_name,
devnames_device_name,
devnames_output_name
} devnames_name;
static inline WORD get_devname_offset(const DEVNAMES *dn, devnames_name which)
{
switch(which)
{
case devnames_driver_name: return dn->wDriverOffset;
case devnames_device_name: return dn->wDeviceOffset;
case devnames_output_name: return dn->wOutputOffset;
}
ERR("Souldn't be here\n");
return 0;
}
static WCHAR *pagesetup_get_a_devname(const pagesetup_data *data, devnames_name which)
{
DEVNAMES *dn;
WCHAR *name;
dn = GlobalLock(data->u.dlgw->hDevNames);
if(data->unicode)
name = strdupW((WCHAR *)dn + get_devname_offset(dn, which));
else
{
int len = MultiByteToWideChar(CP_ACP, 0, (char*)dn + get_devname_offset(dn, which), -1, NULL, 0);
name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, (char*)dn + get_devname_offset(dn, which), -1, name, len);
}
GlobalUnlock(data->u.dlgw->hDevNames);
return name;
}
static WCHAR *pagesetup_get_drvname(const pagesetup_data *data)
{
return pagesetup_get_a_devname(data, devnames_driver_name);
}
static WCHAR *pagesetup_get_devname(const pagesetup_data *data)
{
return pagesetup_get_a_devname(data, devnames_device_name);
}
static WCHAR *pagesetup_get_portname(const pagesetup_data *data)
{
return pagesetup_get_a_devname(data, devnames_output_name);
}
static void pagesetup_release_a_devname(const pagesetup_data *data, WCHAR *name)
{
HeapFree(GetProcessHeap(), 0, name);
}
static void pagesetup_set_devnames(pagesetup_data *data, LPCWSTR drv, LPCWSTR devname, LPCWSTR port)
{
DEVNAMES *dn;
WCHAR def[256];
DWORD len = sizeof(DEVNAMES), drv_len, dev_len, port_len;
if(data->unicode)
{
drv_len = (strlenW(drv) + 1) * sizeof(WCHAR);
dev_len = (strlenW(devname) + 1) * sizeof(WCHAR);
port_len = (strlenW(port) + 1) * sizeof(WCHAR);
}
else
{
drv_len = WideCharToMultiByte(CP_ACP, 0, drv, -1, NULL, 0, NULL, NULL);
dev_len = WideCharToMultiByte(CP_ACP, 0, devname, -1, NULL, 0, NULL, NULL);
port_len = WideCharToMultiByte(CP_ACP, 0, port, -1, NULL, 0, NULL, NULL);
}
len += drv_len + dev_len + port_len;
if(data->u.dlgw->hDevNames)
data->u.dlgw->hDevNames = GlobalReAlloc(data->u.dlgw->hDevNames, len, GMEM_MOVEABLE);
else
data->u.dlgw->hDevNames = GlobalAlloc(GMEM_MOVEABLE, len);
dn = GlobalLock(data->u.dlgw->hDevNames);
if(data->unicode)
{
WCHAR *ptr = (WCHAR *)(dn + 1);
len = sizeof(DEVNAMES) / sizeof(WCHAR);
dn->wDriverOffset = len;
strcpyW(ptr, drv);
ptr += drv_len / sizeof(WCHAR);
len += drv_len / sizeof(WCHAR);
dn->wDeviceOffset = len;
strcpyW(ptr, devname);
ptr += dev_len / sizeof(WCHAR);
len += dev_len / sizeof(WCHAR);
dn->wOutputOffset = len;
strcpyW(ptr, port);
}
else
{
char *ptr = (char *)(dn + 1);
len = sizeof(DEVNAMES);
dn->wDriverOffset = len;
WideCharToMultiByte(CP_ACP, 0, drv, -1, ptr, drv_len, NULL, NULL);
ptr += drv_len;
len += drv_len;
dn->wDeviceOffset = len;
WideCharToMultiByte(CP_ACP, 0, devname, -1, ptr, dev_len, NULL, NULL);
ptr += dev_len;
len += dev_len;
dn->wOutputOffset = len;
WideCharToMultiByte(CP_ACP, 0, port, -1, ptr, port_len, NULL, NULL);
}
dn->wDefault = 0;
len = sizeof(def) / sizeof(def[0]);
GetDefaultPrinterW(def, &len);
if(!lstrcmpW(def, devname))
dn->wDefault = 1;
GlobalUnlock(data->u.dlgw->hDevNames);
}
static DEVMODEW *pagesetup_get_devmode(const pagesetup_data *data)
{
DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
DEVMODEW *ret;
if(data->unicode)
{
/* We make a copy even in the unicode case because the ptr
may get passed back to us in pagesetup_set_devmode. */
ret = HeapAlloc(GetProcessHeap(), 0, dm->dmSize + dm->dmDriverExtra);
memcpy(ret, dm, dm->dmSize + dm->dmDriverExtra);
}
else
ret = GdiConvertToDevmodeW((DEVMODEA *)dm);
GlobalUnlock(data->u.dlgw->hDevMode);
return ret;
}
static void pagesetup_release_devmode(const pagesetup_data *data, DEVMODEW *dm)
{
HeapFree(GetProcessHeap(), 0, dm);
}
static void pagesetup_set_devmode(pagesetup_data *data, DEVMODEW *dm)
{
DEVMODEA *dmA = NULL;
void *src, *dst;
DWORD size;
if(data->unicode)
{
size = dm->dmSize + dm->dmDriverExtra;
src = dm;
}
else
{
dmA = convert_to_devmodeA(dm);
size = dmA->dmSize + dmA->dmDriverExtra;
src = dmA;
}
if(data->u.dlgw->hDevMode)
data->u.dlgw->hDevMode = GlobalReAlloc(data->u.dlgw->hDevMode, size,
GMEM_MOVEABLE);
else
data->u.dlgw->hDevMode = GlobalAlloc(GMEM_MOVEABLE, size);
dst = GlobalLock(data->u.dlgw->hDevMode);
memcpy(dst, src, size);
GlobalUnlock(data->u.dlgw->hDevMode);
HeapFree(GetProcessHeap(), 0, dmA);
}
static inline POINT *pagesetup_get_papersize_pt(const pagesetup_data *data)
{
return &data->u.dlgw->ptPaperSize;
}
static inline RECT *pagesetup_get_margin_rect(const pagesetup_data *data)
{
return &data->u.dlgw->rtMargin;
}
typedef enum
{
page_setup_hook,
page_paint_hook
} hook_type;
static inline LPPAGESETUPHOOK pagesetup_get_hook(const pagesetup_data *data, hook_type which)
{
switch(which)
{
case page_setup_hook: return data->u.dlgw->lpfnPageSetupHook;
case page_paint_hook: return data->u.dlgw->lpfnPagePaintHook;
}
return NULL;
}
/* This should only be used in calls to hook procs so we return the ptr
already cast to LPARAM */
static inline LPARAM pagesetup_get_dlg_struct(const pagesetup_data *data)
{
return (LPARAM)data->u.dlgw;
}
static inline void swap_point(POINT *pt)
{
LONG tmp = pt->x;
pt->x = pt->y;
pt->y = tmp;
}
static BOOL pagesetup_update_papersize(pagesetup_data *data)
{
DEVMODEW *dm;
LPWSTR devname, portname;
int i, num;
WORD *words = NULL, paperword;
POINT *points = NULL;
BOOL retval = FALSE;
dm = pagesetup_get_devmode(data);
devname = pagesetup_get_devname(data);
portname = pagesetup_get_portname(data);
num = DeviceCapabilitiesW(devname, portname, DC_PAPERS, NULL, dm);
if (num <= 0)
{
FIXME("No papernames found for %s/%s\n", debugstr_w(devname), debugstr_w(portname));
goto end;
}
words = HeapAlloc(GetProcessHeap(), 0, num * sizeof(WORD));
points = HeapAlloc(GetProcessHeap(), 0, num * sizeof(POINT));
if (num != DeviceCapabilitiesW(devname, portname, DC_PAPERS, (LPWSTR)words, dm))
{
FIXME("Number of returned words is not %d\n", num);
goto end;
}
if (num != DeviceCapabilitiesW(devname, portname, DC_PAPERSIZE, (LPWSTR)points, dm))
{
FIXME("Number of returned sizes is not %d\n", num);
goto end;
}
paperword = pagesetup_get_papersize(data);
for (i = 0; i < num; i++)
if (words[i] == paperword)
break;
if (i == num)
{
FIXME("Papersize %d not found in list?\n", paperword);
goto end;
}
/* this is _10ths_ of a millimeter */
pagesetup_get_papersize_pt(data)->x = tenths_mm_to_size(data, points[i].x);
pagesetup_get_papersize_pt(data)->y = tenths_mm_to_size(data, points[i].y);
if(pagesetup_get_orientation(data) == DMORIENT_LANDSCAPE)
swap_point(pagesetup_get_papersize_pt(data));
retval = TRUE;
end:
HeapFree(GetProcessHeap(), 0, words);
HeapFree(GetProcessHeap(), 0, points);
pagesetup_release_a_devname(data, portname);
pagesetup_release_a_devname(data, devname);
pagesetup_release_devmode(data, dm);
return retval;
}
/**********************************************************************************************
* pagesetup_change_printer
*
* Redefines hDevMode and hDevNames HANDLES and initialises it.
*
*/
static BOOL pagesetup_change_printer(LPWSTR name, pagesetup_data *data)
{
HANDLE hprn;
DWORD needed;
PRINTER_INFO_2W *prn_info = NULL;
DRIVER_INFO_3W *drv_info = NULL;
DEVMODEW *dm = NULL;
BOOL retval = FALSE;
if(!OpenPrinterW(name, &hprn, NULL))
{
ERR("Can't open printer %s\n", debugstr_w(name));
goto end;
}
GetPrinterW(hprn, 2, NULL, 0, &needed);
prn_info = HeapAlloc(GetProcessHeap(), 0, needed);
GetPrinterW(hprn, 2, (LPBYTE)prn_info, needed, &needed);
GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
drv_info = HeapAlloc(GetProcessHeap(), 0, needed);
if(!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)drv_info, needed, &needed))
{
ERR("GetPrinterDriverA failed for %s, fix your config!\n", debugstr_w(prn_info->pPrinterName));
goto end;
}
ClosePrinter(hprn);
needed = DocumentPropertiesW(0, 0, name, NULL, NULL, 0);
if(needed == -1)
{
ERR("DocumentProperties fails on %s\n", debugstr_w(name));
goto end;
}
dm = HeapAlloc(GetProcessHeap(), 0, needed);
DocumentPropertiesW(0, 0, name, dm, NULL, DM_OUT_BUFFER);
pagesetup_set_devmode(data, dm);
pagesetup_set_devnames(data, drv_info->pDriverPath, prn_info->pPrinterName,
prn_info->pPortName);
retval = TRUE;
end:
HeapFree(GetProcessHeap(), 0, dm);
HeapFree(GetProcessHeap(), 0, prn_info);
HeapFree(GetProcessHeap(), 0, drv_info);
return retval;
}
/****************************************************************************************
* pagesetup_init_combos
*
* Fills Printers, Paper and Source combos
*
*/
static void pagesetup_init_combos(HWND hDlg, pagesetup_data *data)
{
DEVMODEW *dm;
LPWSTR devname, portname;
dm = pagesetup_get_devmode(data);
devname = pagesetup_get_devname(data);
portname = pagesetup_get_portname(data);
PRINTDLG_SetUpPrinterListComboW(hDlg, cmb1, devname);
PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb2, devname, portname, dm);
PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb3, devname, portname, dm);
pagesetup_release_a_devname(data, portname);
pagesetup_release_a_devname(data, devname);
pagesetup_release_devmode(data, dm);
}
/****************************************************************************************
* pagesetup_change_printer_dialog
*
* Pops up another dialog that lets the user pick another printer.
*
* For now we display the PrintDlg, this should display a striped down version of it.
*/
static void pagesetup_change_printer_dialog(HWND hDlg, pagesetup_data *data)
{
PRINTDLGW prnt;
LPWSTR drvname, devname, portname;
DEVMODEW *tmp_dm, *dm;
memset(&prnt, 0, sizeof(prnt));
prnt.lStructSize = sizeof(prnt);
prnt.Flags = 0;
prnt.hwndOwner = hDlg;
drvname = pagesetup_get_drvname(data);
devname = pagesetup_get_devname(data);
portname = pagesetup_get_portname(data);
prnt.hDevNames = 0;
PRINTDLG_CreateDevNamesW(&prnt.hDevNames, drvname, devname, portname);
pagesetup_release_a_devname(data, portname);
pagesetup_release_a_devname(data, devname);
pagesetup_release_a_devname(data, drvname);
tmp_dm = pagesetup_get_devmode(data);
prnt.hDevMode = GlobalAlloc(GMEM_MOVEABLE, tmp_dm->dmSize + tmp_dm->dmDriverExtra);
dm = GlobalLock(prnt.hDevMode);
memcpy(dm, tmp_dm, tmp_dm->dmSize + tmp_dm->dmDriverExtra);
GlobalUnlock(prnt.hDevMode);
pagesetup_release_devmode(data, tmp_dm);
if (PrintDlgW(&prnt))
{
DEVMODEW *dm = GlobalLock(prnt.hDevMode);
DEVNAMES *dn = GlobalLock(prnt.hDevNames);
pagesetup_set_devnames(data, (WCHAR*)dn + dn->wDriverOffset,
(WCHAR*)dn + dn->wDeviceOffset, (WCHAR *)dn + dn->wOutputOffset);
pagesetup_set_devmode(data, dm);
GlobalUnlock(prnt.hDevNames);
GlobalUnlock(prnt.hDevMode);
pagesetup_init_combos(hDlg, data);
}
GlobalFree(prnt.hDevMode);
GlobalFree(prnt.hDevNames);
}
/******************************************************************************************
* pagesetup_change_preview
*
* Changes paper preview size / position
*
*/
static void pagesetup_change_preview(const pagesetup_data *data)
{
LONG width, height, x, y;
RECT tmp;
const int shadow = 4;
if(pagesetup_get_orientation(data) == DMORIENT_LANDSCAPE)
{
width = data->rtDrawRect.right - data->rtDrawRect.left;
height = pagesetup_get_papersize_pt(data)->y * width / pagesetup_get_papersize_pt(data)->x;
}
else
{
height = data->rtDrawRect.bottom - data->rtDrawRect.top;
width = pagesetup_get_papersize_pt(data)->x * height / pagesetup_get_papersize_pt(data)->y;
}
x = (data->rtDrawRect.right + data->rtDrawRect.left - width) / 2;
y = (data->rtDrawRect.bottom + data->rtDrawRect.top - height) / 2;
TRACE("draw rect %s x=%d, y=%d, w=%d, h=%d\n",
wine_dbgstr_rect(&data->rtDrawRect), x, y, width, height);
MoveWindow(GetDlgItem(data->hDlg, rct2), x + width, y + shadow, shadow, height, FALSE);
MoveWindow(GetDlgItem(data->hDlg, rct3), x + shadow, y + height, width, shadow, FALSE);
MoveWindow(GetDlgItem(data->hDlg, rct1), x, y, width, height, FALSE);
tmp = data->rtDrawRect;
tmp.right += shadow;
tmp.bottom += shadow;
InvalidateRect(data->hDlg, &tmp, TRUE);
}
static inline LONG *element_from_margin_id(RECT *rc, WORD id)
{
switch(id)
{
case edt4: return &rc->left;
case edt5: return &rc->top;
case edt6: return &rc->right;
case edt7: return &rc->bottom;
}
return NULL;
}
static void update_margin_edits(HWND hDlg, const pagesetup_data *data, WORD id)
{
WCHAR str[100];
WORD idx;
for(idx = edt4; idx <= edt7; idx++)
{
if(id == 0 || id == idx)
{
size2str(data, *element_from_margin_id(pagesetup_get_margin_rect(data), idx), str);
SetDlgItemTextW(hDlg, idx, str);
}
}
}
static void margin_edit_notification(HWND hDlg, const pagesetup_data *data, WORD msg, WORD id)
{
switch (msg)
{
case EN_CHANGE:
{
WCHAR buf[10];
LONG val = 0;
LONG *value = element_from_margin_id(pagesetup_get_margin_rect(data), id);
if (GetDlgItemTextW(hDlg, id, buf, sizeof(buf) / sizeof(buf[0])) != 0)
{
WCHAR *end;
WCHAR decimal = get_decimal_sep();
val = strtolW(buf, &end, 10);
if(end != buf || *end == decimal)
{
int mult = is_metric(data) ? 100 : 1000;
val *= mult;
if(*end == decimal)
{
while(mult > 1)
{
end++;
mult /= 10;
if(isdigitW(*end))
val += (*end - '0') * mult;
else
break;
}
}
}
}
*value = val;
return;
}
case EN_KILLFOCUS:
update_margin_edits(hDlg, data, id);
return;
}
}
static void set_margin_groupbox_title(HWND hDlg, const pagesetup_data *data)
{
WCHAR title[256];
if(LoadStringW(COMDLG32_hInstance, is_metric(data) ? PD32_MARGINS_IN_MILLIMETERS : PD32_MARGINS_IN_INCHES,
title, sizeof(title)/sizeof(title[0])))
SetDlgItemTextW(hDlg, grp4, title);
}
static void pagesetup_update_orientation_buttons(HWND hDlg, const pagesetup_data *data)
{
if (pagesetup_get_orientation(data) == DMORIENT_LANDSCAPE)
CheckRadioButton(hDlg, rad1, rad2, rad2);
else
CheckRadioButton(hDlg, rad1, rad2, rad1);
}
/****************************************************************************************
* pagesetup_printer_properties
*
* Handle invocation of the 'Properties' button (not present in the default template).
*/
static void pagesetup_printer_properties(HWND hDlg, pagesetup_data *data)
{
HANDLE hprn;
LPWSTR devname;
DEVMODEW *dm;
LRESULT count;
int i;
devname = pagesetup_get_devname(data);
if (!OpenPrinterW(devname, &hprn, NULL))
{
FIXME("Call to OpenPrinter did not succeed!\n");
pagesetup_release_a_devname(data, devname);
return;
}
dm = pagesetup_get_devmode(data);
DocumentPropertiesW(hDlg, hprn, devname, dm, dm, DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
pagesetup_set_devmode(data, dm);
pagesetup_release_devmode(data, dm);
pagesetup_release_a_devname(data, devname);
ClosePrinter(hprn);
/* Changing paper */
pagesetup_update_papersize(data);
pagesetup_update_orientation_buttons(hDlg, data);
/* Changing paper preview */
pagesetup_change_preview(data);
/* Selecting paper in combo */
count = SendDlgItemMessageW(hDlg, cmb2, CB_GETCOUNT, 0, 0);
if(count != CB_ERR)
{
WORD paperword = pagesetup_get_papersize(data);
for(i = 0; i < count; i++)
{
if(SendDlgItemMessageW(hDlg, cmb2, CB_GETITEMDATA, i, 0) == paperword) {
SendDlgItemMessageW(hDlg, cmb2, CB_SETCURSEL, i, 0);
break;
}
}
}
}
/********************************************************************************
* pagesetup_wm_command
* process WM_COMMAND message for PageSetupDlg
*
* PARAMS
* hDlg [in] Main dialog HANDLE
* wParam [in] WM_COMMAND wParam
* lParam [in] WM_COMMAND lParam
* pda [in/out] ptr to PageSetupDataA
*/
static BOOL pagesetup_wm_command(HWND hDlg, WPARAM wParam, LPARAM lParam, pagesetup_data *data)
{
WORD msg = HIWORD(wParam);
WORD id = LOWORD(wParam);
TRACE("loword (lparam) %d, wparam 0x%lx, lparam %08lx\n",
LOWORD(lParam),wParam,lParam);
switch (id) {
case IDOK:
EndDialog(hDlg, TRUE);
return TRUE ;
case IDCANCEL:
EndDialog(hDlg, FALSE);
return FALSE ;
case psh3: /* Printer... */
pagesetup_change_printer_dialog(hDlg, data);
return TRUE;
case rad1: /* Portrait */
case rad2: /* Landscape */
if((id == rad1 && pagesetup_get_orientation(data) == DMORIENT_LANDSCAPE) ||
(id == rad2 && pagesetup_get_orientation(data) == DMORIENT_PORTRAIT))
{
pagesetup_set_orientation(data, (id == rad1) ? DMORIENT_PORTRAIT : DMORIENT_LANDSCAPE);
pagesetup_update_papersize(data);
rotate_rect(pagesetup_get_margin_rect(data), (id == rad2));
update_margin_edits(hDlg, data, 0);
pagesetup_change_preview(data);
}
break;
case cmb1: /* Printer combo */
if(msg == CBN_SELCHANGE)
{
WCHAR name[256];
GetDlgItemTextW(hDlg, id, name, sizeof(name) / sizeof(name[0]));
pagesetup_change_printer(name, data);
pagesetup_init_combos(hDlg, data);
}
break;
case cmb2: /* Paper combo */
if(msg == CBN_SELCHANGE)
{
DWORD paperword = SendDlgItemMessageW(hDlg, cmb2, CB_GETITEMDATA,
SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0), 0);
if (paperword != CB_ERR)
{
pagesetup_set_papersize(data, paperword);
pagesetup_update_papersize(data);
pagesetup_change_preview(data);
} else
FIXME("could not get dialog text for papersize cmbbox?\n");
}
break;
case cmb3: /* Paper Source */
if(msg == CBN_SELCHANGE)
{
WORD source = SendDlgItemMessageW(hDlg, cmb3, CB_GETITEMDATA,
SendDlgItemMessageW(hDlg, cmb3, CB_GETCURSEL, 0, 0), 0);
pagesetup_set_defaultsource(data, source);
}
break;
case psh2: /* Printer Properties button */
pagesetup_printer_properties(hDlg, data);
break;
case edt4:
case edt5:
case edt6:
case edt7:
margin_edit_notification(hDlg, data, msg, id);
break;
}
InvalidateRect(GetDlgItem(hDlg, rct1), NULL, TRUE);
return FALSE;
}
/***********************************************************************
* default_page_paint_hook
* Default hook paint procedure that receives WM_PSD_* messages from the dialog box
* whenever the sample page is redrawn.
*/
static UINT_PTR default_page_paint_hook(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam,
const pagesetup_data *data)
{
LPRECT lprc = (LPRECT) lParam;
HDC hdc = (HDC) wParam;
HPEN hpen, holdpen;
LOGFONTW lf;
HFONT hfont, holdfont;
INT oldbkmode;
TRACE("uMsg: WM_USER+%d\n",uMsg-WM_USER);
/* Call user paint hook if enable */
if (pagesetup_get_flags(data) & PSD_ENABLEPAGEPAINTHOOK)
if (pagesetup_get_hook(data, page_paint_hook)(hwndDlg, uMsg, wParam, lParam))
return TRUE;
switch (uMsg) {
/* LPPAGESETUPDLG in lParam */
case WM_PSD_PAGESETUPDLG:
/* Inform about the sample page rectangle */
case WM_PSD_FULLPAGERECT:
/* Inform about the margin rectangle */
case WM_PSD_MINMARGINRECT:
return FALSE;
/* Draw dashed rectangle showing margins */
case WM_PSD_MARGINRECT:
hpen = CreatePen(PS_DASH, 1, GetSysColor(COLOR_3DSHADOW));
holdpen = SelectObject(hdc, hpen);
Rectangle(hdc, lprc->left, lprc->top, lprc->right, lprc->bottom);
DeleteObject(SelectObject(hdc, holdpen));
return TRUE;
/* Draw the fake document */
case WM_PSD_GREEKTEXTRECT:
/* select a nice scalable font, because we want the text really small */
SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0);
lf.lfHeight = 6; /* value chosen based on visual effect */
hfont = CreateFontIndirectW(&lf);
holdfont = SelectObject(hdc, hfont);
/* if text not loaded, then do so now */
if (wszFakeDocumentText[0] == '\0')
LoadStringW(COMDLG32_hInstance,
IDS_FAKEDOCTEXT,
wszFakeDocumentText,
sizeof(wszFakeDocumentText)/sizeof(wszFakeDocumentText[0]));
oldbkmode = SetBkMode(hdc, TRANSPARENT);
DrawTextW(hdc, wszFakeDocumentText, -1, lprc, DT_TOP|DT_LEFT|DT_NOPREFIX|DT_WORDBREAK);
SetBkMode(hdc, oldbkmode);
DeleteObject(SelectObject(hdc, holdfont));
return TRUE;
/* Envelope stamp */
case WM_PSD_ENVSTAMPRECT:
/* Return address */
case WM_PSD_YAFULLPAGERECT:
FIXME("envelope/stamp is not implemented\n");
return FALSE;
default:
FIXME("Unknown message %x\n",uMsg);
return FALSE;
}
return TRUE;
}
/***********************************************************************
* PagePaintProc
* The main paint procedure for the PageSetupDlg function.
* The Page Setup dialog box includes an image of a sample page that shows how
* the user's selections affect the appearance of the printed output.
* The image consists of a rectangle that represents the selected paper
* or envelope type, with a dotted-line rectangle representing
* the current margins, and partial (Greek text) characters
* to show how text looks on the printed page.
*
* The following messages in the order sends to user hook procedure:
* WM_PSD_PAGESETUPDLG Draw the contents of the sample page
* WM_PSD_FULLPAGERECT Inform about the bounding rectangle
* WM_PSD_MINMARGINRECT Inform about the margin rectangle (min margin?)
* WM_PSD_MARGINRECT Draw the margin rectangle
* WM_PSD_GREEKTEXTRECT Draw the Greek text inside the margin rectangle
* If any of first three messages returns TRUE, painting done.
*
* PARAMS:
* hWnd [in] Handle to the Page Setup dialog box
* uMsg [in] Received message
*
* TODO:
* WM_PSD_ENVSTAMPRECT Draw in the envelope-stamp rectangle (for envelopes only)
* WM_PSD_YAFULLPAGERECT Draw the return address portion (for envelopes and other paper sizes)
*
* RETURNS:
* FALSE if all done correctly
*
*/
static LRESULT CALLBACK
PRINTDLG_PagePaintProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
RECT rcClient, rcMargin;
HPEN hpen, holdpen;
HDC hdc;
HBRUSH hbrush, holdbrush;
pagesetup_data *data;
int papersize=0, orientation=0; /* FIXME: set this values for user paint hook */
double scalx, scaly;
if (uMsg != WM_PAINT)
return CallWindowProcA(lpfnStaticWndProc, hWnd, uMsg, wParam, lParam);
/* Processing WM_PAINT message */
data = GetPropW(hWnd, pagesetupdlg_prop);
if (!data) {
WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
return FALSE;
}
if (default_page_paint_hook(hWnd, WM_PSD_PAGESETUPDLG, MAKELONG(papersize, orientation),
pagesetup_get_dlg_struct(data), data))
return FALSE;
hdc = BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &rcClient);
scalx = rcClient.right / (double)pagesetup_get_papersize_pt(data)->x;
scaly = rcClient.bottom / (double)pagesetup_get_papersize_pt(data)->y;
rcMargin = rcClient;
rcMargin.left += pagesetup_get_margin_rect(data)->left * scalx;
rcMargin.top += pagesetup_get_margin_rect(data)->top * scaly;
rcMargin.right -= pagesetup_get_margin_rect(data)->right * scalx;
rcMargin.bottom -= pagesetup_get_margin_rect(data)->bottom * scaly;
/* if the space is too small then we make sure to not draw anything */
rcMargin.left = min(rcMargin.left, rcMargin.right);
rcMargin.top = min(rcMargin.top, rcMargin.bottom);
if (!default_page_paint_hook(hWnd, WM_PSD_FULLPAGERECT, (WPARAM)hdc, (LPARAM)&rcClient, data) &&
!default_page_paint_hook(hWnd, WM_PSD_MINMARGINRECT, (WPARAM)hdc, (LPARAM)&rcMargin, data) )
{
/* fill background */
hbrush = GetSysColorBrush(COLOR_3DHIGHLIGHT);
FillRect(hdc, &rcClient, hbrush);
holdbrush = SelectObject(hdc, hbrush);
hpen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
holdpen = SelectObject(hdc, hpen);
/* paint left edge */
MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
LineTo(hdc, rcClient.left, rcClient.bottom-1);
/* paint top edge */
MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
LineTo(hdc, rcClient.right, rcClient.top);
hpen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DDKSHADOW));
DeleteObject(SelectObject(hdc, hpen));
/* paint right edge */
MoveToEx(hdc, rcClient.right-1, rcClient.top, NULL);
LineTo(hdc, rcClient.right-1, rcClient.bottom);
/* paint bottom edge */
MoveToEx(hdc, rcClient.left, rcClient.bottom-1, NULL);
LineTo(hdc, rcClient.right, rcClient.bottom-1);
DeleteObject(SelectObject(hdc, holdpen));
DeleteObject(SelectObject(hdc, holdbrush));
default_page_paint_hook(hWnd, WM_PSD_MARGINRECT, (WPARAM)hdc, (LPARAM)&rcMargin, data);
/* give text a bit of a space from the frame */
rcMargin.left += 2;
rcMargin.top += 2;
rcMargin.right -= 2;
rcMargin.bottom -= 2;
/* if the space is too small then we make sure to not draw anything */
rcMargin.left = min(rcMargin.left, rcMargin.right);
rcMargin.top = min(rcMargin.top, rcMargin.bottom);
default_page_paint_hook(hWnd, WM_PSD_GREEKTEXTRECT, (WPARAM)hdc, (LPARAM)&rcMargin, data);
}
EndPaint(hWnd, &ps);
return FALSE;
}
/*******************************************************
* The margin edit controls are subclassed to filter
* anything other than numbers and the decimal separator.
*/
static LRESULT CALLBACK pagesetup_margin_editproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
if (msg == WM_CHAR)
{
WCHAR decimal = get_decimal_sep();
WCHAR wc = (WCHAR)wparam;
if(!isdigitW(wc) && wc != decimal && wc != VK_BACK) return 0;
}
return CallWindowProcW(edit_wndproc, hwnd, msg, wparam, lparam);
}
static void subclass_margin_edits(HWND hDlg)
{
int id;
WNDPROC old_proc;
for(id = edt4; id <= edt7; id++)
{
old_proc = (WNDPROC)SetWindowLongPtrW(GetDlgItem(hDlg, id),
GWLP_WNDPROC,
(ULONG_PTR)pagesetup_margin_editproc);
InterlockedCompareExchangePointer((void**)&edit_wndproc, old_proc, NULL);
}
}
/***********************************************************************
* pagesetup_dlg_proc
*
* Message handler for PageSetupDlg
*/
static INT_PTR CALLBACK pagesetup_dlg_proc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
pagesetup_data *data;
INT_PTR res = FALSE;
HWND hDrawWnd;
if (uMsg == WM_INITDIALOG) { /*Init dialog*/
data = (pagesetup_data *)lParam;
data->hDlg = hDlg;
hDrawWnd = GetDlgItem(hDlg, rct1);
TRACE("set property to %p\n", data);
SetPropW(hDlg, pagesetupdlg_prop, data);
SetPropW(hDrawWnd, pagesetupdlg_prop, data);
GetWindowRect(hDrawWnd, &data->rtDrawRect); /* Calculating rect in client coordinates where paper draws */
ScreenToClient(hDlg, (LPPOINT)&data->rtDrawRect);
ScreenToClient(hDlg, (LPPOINT)(&data->rtDrawRect.right));
lpfnStaticWndProc = (WNDPROC)SetWindowLongPtrW(
hDrawWnd,
GWLP_WNDPROC,
(ULONG_PTR)PRINTDLG_PagePaintProc);
/* FIXME: Paint hook. Must it be at begin of initialization or at end? */
res = TRUE;
if (pagesetup_get_flags(data) & PSD_ENABLEPAGESETUPHOOK)
{
if (!pagesetup_get_hook(data, page_setup_hook)(hDlg, uMsg, wParam,
pagesetup_get_dlg_struct(data)))
FIXME("Setup page hook failed?\n");
}
/* if printer button disabled */
if (pagesetup_get_flags(data) & PSD_DISABLEPRINTER)
EnableWindow(GetDlgItem(hDlg, psh3), FALSE);
/* if margin edit boxes disabled */
if (pagesetup_get_flags(data) & PSD_DISABLEMARGINS)
{
EnableWindow(GetDlgItem(hDlg, edt4), FALSE);
EnableWindow(GetDlgItem(hDlg, edt5), FALSE);
EnableWindow(GetDlgItem(hDlg, edt6), FALSE);
EnableWindow(GetDlgItem(hDlg, edt7), FALSE);
}
/* Set orientation radiobuttons properly */
pagesetup_update_orientation_buttons(hDlg, data);
/* if orientation disabled */
if (pagesetup_get_flags(data) & PSD_DISABLEORIENTATION)
{
EnableWindow(GetDlgItem(hDlg,rad1),FALSE);
EnableWindow(GetDlgItem(hDlg,rad2),FALSE);
}
/* We fill them out enabled or not */
if (!(pagesetup_get_flags(data) & PSD_MARGINS))
{
/* default is 1 inch */
LONG size = thousandths_inch_to_size(data, 1000);
SetRect(pagesetup_get_margin_rect(data), size, size, size, size);
}
update_margin_edits(hDlg, data, 0);
subclass_margin_edits(hDlg);
set_margin_groupbox_title(hDlg, data);
/* if paper disabled */
if (pagesetup_get_flags(data) & PSD_DISABLEPAPER)
{
EnableWindow(GetDlgItem(hDlg,cmb2),FALSE);
EnableWindow(GetDlgItem(hDlg,cmb3),FALSE);
}
/* filling combos: printer, paper, source. selecting current printer (from DEVMODEA) */
pagesetup_init_combos(hDlg, data);
pagesetup_update_papersize(data);
pagesetup_set_defaultsource(data, DMBIN_FORMSOURCE); /* FIXME: This is the auto select bin. Is this correct? */
/* Drawing paper prev */
pagesetup_change_preview(data);
return TRUE;
} else {
data = GetPropW(hDlg, pagesetupdlg_prop);
if (!data)
{
WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
return FALSE;
}
if (pagesetup_get_flags(data) & PSD_ENABLEPAGESETUPHOOK)
{
res = pagesetup_get_hook(data, page_setup_hook)(hDlg, uMsg, wParam, lParam);
if (res) return res;
}
}
switch (uMsg) {
case WM_COMMAND:
return pagesetup_wm_command(hDlg, wParam, lParam, data);
}
return FALSE;
}
static WCHAR *get_default_printer(void)
{
WCHAR *name = NULL;
DWORD len = 0;
GetDefaultPrinterW(NULL, &len);
if(len)
{
name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
GetDefaultPrinterW(name, &len);
}
return name;
}
static void pagesetup_dump_dlg_struct(const pagesetup_data *data)
{
if(TRACE_ON(commdlg))
{
char flagstr[1000] = "";
const struct pd_flags *pflag = psd_flags;
for( ; pflag->name; pflag++)
{
if(pagesetup_get_flags(data) & pflag->flag)
{
strcat(flagstr, pflag->name);
strcat(flagstr, "|");
}
}
TRACE("%s: (%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
"hinst %p, flags %08x (%s)\n",
data->unicode ? "unicode" : "ansi",
data->u.dlgw, data->u.dlgw->hwndOwner, data->u.dlgw->hDevMode,
data->u.dlgw->hDevNames, data->u.dlgw->hInstance,
pagesetup_get_flags(data), flagstr);
}
}
static void *pagesetup_get_template(pagesetup_data *data)
{
HRSRC res;
HGLOBAL tmpl_handle;
if(pagesetup_get_flags(data) & PSD_ENABLEPAGESETUPTEMPLATEHANDLE)
{
tmpl_handle = data->u.dlgw->hPageSetupTemplate;
}
else if(pagesetup_get_flags(data) & PSD_ENABLEPAGESETUPTEMPLATE)
{
if(data->unicode)
res = FindResourceW(data->u.dlgw->hInstance,
data->u.dlgw->lpPageSetupTemplateName, MAKEINTRESOURCEW(RT_DIALOG));
else
res = FindResourceA(data->u.dlga->hInstance,
data->u.dlga->lpPageSetupTemplateName, MAKEINTRESOURCEA(RT_DIALOG));
tmpl_handle = LoadResource(data->u.dlgw->hInstance, res);
}
else
{
res = FindResourceW(COMDLG32_hInstance, MAKEINTRESOURCEW(PAGESETUPDLGORD),
MAKEINTRESOURCEW(RT_DIALOG));
tmpl_handle = LoadResource(COMDLG32_hInstance, res);
}
return LockResource(tmpl_handle);
}
static BOOL pagesetup_common(pagesetup_data *data)
{
BOOL ret;
void *tmpl;
if(!pagesetup_get_dlg_struct(data))
{
COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION);
return FALSE;
}
pagesetup_dump_dlg_struct(data);
if(data->u.dlgw->lStructSize != sizeof(PAGESETUPDLGW))
{
COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
return FALSE;
}
if ((pagesetup_get_flags(data) & PSD_ENABLEPAGEPAINTHOOK) &&
(pagesetup_get_hook(data, page_paint_hook) == NULL))
{
COMDLG32_SetCommDlgExtendedError(CDERR_NOHOOK);
return FALSE;
}
if(!(pagesetup_get_flags(data) & (PSD_INTHOUSANDTHSOFINCHES | PSD_INHUNDREDTHSOFMILLIMETERS)))
data->u.dlgw->Flags |= is_default_metric() ?
PSD_INHUNDREDTHSOFMILLIMETERS : PSD_INTHOUSANDTHSOFINCHES;
if (!data->u.dlgw->hDevMode || !data->u.dlgw->hDevNames)
{
WCHAR *def = get_default_printer();
if(!def)
{
if (!(pagesetup_get_flags(data) & PSD_NOWARNING))
{
WCHAR errstr[256];
LoadStringW(COMDLG32_hInstance, PD32_NO_DEFAULT_PRINTER, errstr, 255);
MessageBoxW(data->u.dlgw->hwndOwner, errstr, 0, MB_OK | MB_ICONERROR);
}
COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
return FALSE;
}
pagesetup_change_printer(def, data);
HeapFree(GetProcessHeap(), 0, def);
}
if (pagesetup_get_flags(data) & PSD_RETURNDEFAULT)
{
pagesetup_update_papersize(data);
return TRUE;
}
tmpl = pagesetup_get_template(data);
ret = DialogBoxIndirectParamW(data->u.dlgw->hInstance, tmpl,
data->u.dlgw->hwndOwner,
pagesetup_dlg_proc, (LPARAM)data) > 0;
return ret;
}
/***********************************************************************
* PageSetupDlgA (COMDLG32.@)
*
* Displays the PAGE SETUP dialog box, which enables the user to specify
* specific properties of a printed page such as
* size, source, orientation and the width of the page margins.
*
* PARAMS
* setupdlg [IO] PAGESETUPDLGA struct
*
* RETURNS
* TRUE if the user pressed the OK button
* FALSE if the user cancelled the window or an error occurred
*
* NOTES
* The values of hDevMode and hDevNames are filled on output and can be
* changed in PAGESETUPDLG when they are passed in PageSetupDlg.
*
*/
BOOL WINAPI PageSetupDlgA(LPPAGESETUPDLGA setupdlg)
{
pagesetup_data data;
data.unicode = FALSE;
data.u.dlga = setupdlg;
return pagesetup_common(&data);
}
/***********************************************************************
* PageSetupDlgW (COMDLG32.@)
*
* See PageSetupDlgA.
*/
BOOL WINAPI PageSetupDlgW(LPPAGESETUPDLGW setupdlg)
{
pagesetup_data data;
data.unicode = TRUE;
data.u.dlgw = setupdlg;
return pagesetup_common(&data);
}
/***********************************************************************
* PrintDlgExA (COMDLG32.@)
*
* See PrintDlgExW.
*
* BUGS
* Only a Stub
*
*/
HRESULT WINAPI PrintDlgExA(LPPRINTDLGEXA lppd)
{
DWORD ret = E_FAIL;
LPVOID ptr;
FIXME("(%p) not fully implemented\n", lppd);
if ((lppd == NULL) || (lppd->lStructSize != sizeof(PRINTDLGEXA)))
return E_INVALIDARG;
if (!IsWindow(lppd->hwndOwner))
return E_HANDLE;
if (lppd->Flags & PD_RETURNDEFAULT)
{
PRINTER_INFO_2A *pbuf;
DRIVER_INFO_2A *dbuf;
HANDLE hprn;
DWORD needed = 1024;
BOOL bRet;
if (lppd->hDevMode || lppd->hDevNames)
{
WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
return E_INVALIDARG;
}
if (!PRINTDLG_OpenDefaultPrinter(&hprn))
{
WARN("Can't find default printer\n");
COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
return E_FAIL;
}
pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
bRet = GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
if (!bRet && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
{
HeapFree(GetProcessHeap(), 0, pbuf);
pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
bRet = GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
}
if (!bRet)
{
HeapFree(GetProcessHeap(), 0, pbuf);
ClosePrinter(hprn);
return E_FAIL;
}
needed = 1024;
dbuf = HeapAlloc(GetProcessHeap(), 0, needed);
bRet = GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed);
if (!bRet && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
{
HeapFree(GetProcessHeap(), 0, dbuf);
dbuf = HeapAlloc(GetProcessHeap(), 0, needed);
bRet = GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed);
}
if (!bRet)
{
ERR("GetPrinterDriverА failed, last error %d, fix your config for printer %s!\n",
GetLastError(), pbuf->pPrinterName);
HeapFree(GetProcessHeap(), 0, dbuf);
HeapFree(GetProcessHeap(), 0, pbuf);
COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
ClosePrinter(hprn);
return E_FAIL;
}
ClosePrinter(hprn);
PRINTDLG_CreateDevNames(&(lppd->hDevNames),
dbuf->pDriverPath,
pbuf->pPrinterName,
pbuf->pPortName);
lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
pbuf->pDevMode->dmDriverExtra);
if (lppd->hDevMode)
{
ptr = GlobalLock(lppd->hDevMode);
if (ptr)
{
memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
pbuf->pDevMode->dmDriverExtra);
GlobalUnlock(lppd->hDevMode);
ret = S_OK;
}
}
HeapFree(GetProcessHeap(), 0, pbuf);
HeapFree(GetProcessHeap(), 0, dbuf);
return ret;
}
return E_NOTIMPL;
}
/***********************************************************************
* PrintDlgExW (COMDLG32.@)
*
* Display the property sheet style PRINT dialog box
*
* PARAMS
* lppd [IO] ptr to PRINTDLGEX struct
*
* RETURNS
* Success: S_OK
* Failure: One of the following COM error codes:
* E_OUTOFMEMORY Insufficient memory.
* E_INVALIDARG One or more arguments are invalid.
* E_POINTER Invalid pointer.
* E_HANDLE Invalid handle.
* E_FAIL Unspecified error.
*
* NOTES
* This Dialog enables the user to specify specific properties of the print job.
* The property sheet can also have additional application-specific and
* driver-specific property pages.
*
* BUGS
* Not fully implemented
*
*/
HRESULT WINAPI PrintDlgExW(LPPRINTDLGEXW lppd)
{
DWORD ret = E_FAIL;
LPVOID ptr;
FIXME("(%p) not fully implemented\n", lppd);
if ((lppd == NULL) || (lppd->lStructSize != sizeof(PRINTDLGEXW))) {
return E_INVALIDARG;
}
if (!IsWindow(lppd->hwndOwner)) {
return E_HANDLE;
}
if (lppd->Flags & PD_RETURNDEFAULT) {
PRINTER_INFO_2W *pbuf;
DRIVER_INFO_2W *dbuf;
HANDLE hprn;
DWORD needed = 1024;
BOOL bRet;
if (lppd->hDevMode || lppd->hDevNames) {
WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
return E_INVALIDARG;
}
if (!PRINTDLG_OpenDefaultPrinter(&hprn)) {
WARN("Can't find default printer\n");
COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
return E_FAIL;
}
pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
bRet = GetPrinterW(hprn, 2, (LPBYTE)pbuf, needed, &needed);
if (!bRet && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
HeapFree(GetProcessHeap(), 0, pbuf);
pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
bRet = GetPrinterW(hprn, 2, (LPBYTE)pbuf, needed, &needed);
}
if (!bRet) {
HeapFree(GetProcessHeap(), 0, pbuf);
ClosePrinter(hprn);
return E_FAIL;
}
needed = 1024;
dbuf = HeapAlloc(GetProcessHeap(), 0, needed);
bRet = GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed);
if (!bRet && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
HeapFree(GetProcessHeap(), 0, dbuf);
dbuf = HeapAlloc(GetProcessHeap(), 0, needed);
bRet = GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed);
}
if (!bRet) {
ERR("GetPrinterDriverW failed, last error %d, fix your config for printer %s!\n",
GetLastError(), debugstr_w(pbuf->pPrinterName));
HeapFree(GetProcessHeap(), 0, dbuf);
HeapFree(GetProcessHeap(), 0, pbuf);
COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
ClosePrinter(hprn);
return E_FAIL;
}
ClosePrinter(hprn);
PRINTDLG_CreateDevNamesW(&(lppd->hDevNames),
dbuf->pDriverPath,
pbuf->pPrinterName,
pbuf->pPortName);
lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
pbuf->pDevMode->dmDriverExtra);
if (lppd->hDevMode) {
ptr = GlobalLock(lppd->hDevMode);
if (ptr) {
memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
pbuf->pDevMode->dmDriverExtra);
GlobalUnlock(lppd->hDevMode);
ret = S_OK;
}
}
HeapFree(GetProcessHeap(), 0, pbuf);
HeapFree(GetProcessHeap(), 0, dbuf);
return ret;
}
return E_NOTIMPL;
}