Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1516 lines
43 KiB

/*++
Copyright (c) 1990-2003 Microsoft Corporation
Module Name:
plotdm.c
Abstract:
This module contain functions which validate/set default the devmode and
extented devmode (PLOTDEVMODE)
Author:
15-Nov-1993 Mon 14:09:27 created
[Environment:]
GDI Device Driver - Plotter.
[Notes:]
Revision History:
15-Dec-1993 Wed 21:08:49 updated
Add the default FILL_TRUETYPE flag stuff
02-Feb-1994 Wed 01:04:21 updated
Change IsMetricMode() to IsA4PaperDefault(), this function right now
will call RegOpenKey(), RegQueryValueEx() and RegCloseKey() to the
control panel\International rather then using GetLocaleInfoW().
The reason is if we call GetLocaleInfoW() then the registry key will
keep opened by the API functions and since the WinSrv will never unload
the driver, then the registry key will never get close, this has bad
consquence which it never allowed user to save its updated profile at
logoff time if this driver is used.
--*/
#include "precomp.h"
#pragma hdrstop
#define DBG_PLOTFILENAME DbgDevMode
#define DBG_DEFDEVMODE 0x00000001
#define DBG_CURFORM 0x00000002
#define DBG_DEFPAPER 0x00000004
#define DBG_A4DEFAULT 0x00000008
#define DBG_ROTPAPER 0x00000010
#define DBG_INTERSECTRECTL 0x00000020
#define DBG_SHOWDEVMODE 0x00000040
DEFINE_DBGVAR(0);
//
// Depends on what we have to do what we have to do
//
#if defined(UMODE) || defined(USERMODE_DRIVER)
#define HAS_GETREGDATA 1
#else
#define HAS_GETREGDATA 0
#endif // UMODE
//
// This is our default PLOTDEVMODE, we will update following fields
//
// dmDeviceName - Real device name passed in
// dmFormName - Letter if USA and A4 if NOT USA
// dmPaperSize - DMPAPER_LETTER/DMPAPER_A4
// dmColor - COLOR printer = DMCOLOR_COLOR else DMCOLOR_MONOCHROME
//
#define A4_FORM_NAME _DefPlotDM.dm.dmDeviceName
#define A4_FORM_CX _DefPlotDM.dm.dmPelsWidth
#define A4_FORM_CY _DefPlotDM.dm.dmPelsHeight
#define DM_PAPER_CUSTOM (DM_PAPER_WL | DM_PAPERSIZE)
static const PLOTDEVMODE _DefPlotDM = {
{
TEXT("A4"), // dmDeviceName - filled later
DM_SPECVERSION, // dmSpecVersion
DRIVER_VERSION, // dmDriverVersion
sizeof(DEVMODE), // dmSize
PLOTDM_PRIV_SIZE, // dmDriverExtra
DM_ORIENTATION |
DM_PAPERSIZE |
// DM_PAPERLENGTH |
// DM_PAPERWIDTH |
DM_SCALE |
DM_COPIES |
// DM_DEFAULTSOURCE | // Reserved one, must zero
DM_PRINTQUALITY |
DM_COLOR |
// DM_DUPLEX |
// DM_YRESOLUTION |
// DM_TTOPTION |
// DM_COLLATE |
DM_FORMNAME,
DMORIENT_PORTRAIT, // dmOrientation
DMPAPER_LETTER, // dmPaperSize
2794, // dmPaperLength
2159, // dmPaperWidth
100, // dmScale
1, // dmCopies
0, // dmDefaultSource - RESERVED = 0
DMRES_HIGH, // dmPrintQuality
DMCOLOR_COLOR, // dmColor
DMDUP_SIMPLEX, // dmDuplex
0, // dmYResolution
0, // dmTTOption
DMCOLLATE_FALSE, // dmCollate
TEXT("Letter"), // dmFormName - depends on country
0, // dmUnusedPadding - DISPLAY ONLY
0, // dmBitsPerPel - DISPLAY ONLY
2100, // dmPelsWidth - DISPLAY ONLY
2970, // dmPelsHeight - DISPLAY ONLY
0, // dmDisplayFlags - DISPLAY ONLY
0 // dmDisplayFrequency- DISPLAY ONLY
},
PLOTDM_PRIV_ID, // PrivID
PLOTDM_PRIV_VER, // PrivVer
PDMF_FILL_TRUETYPE, // default advanced dialog box
{
sizeof(COLORADJUSTMENT), // caSize
0, // caFlags
ILLUMINANT_DEVICE_DEFAULT, // caIlluminantIndex
10000, // caRedGamma
10000, // caGreenGamma
10000, // caBlueGamma
REFERENCE_BLACK_MIN, // caReferenceBlack
REFERENCE_WHITE_MAX, // caReferenceWhite
0, // caContrast
0, // caBrightness
0, // caColorfulness
0 // caRedGreenTint
}
};
#define DEFAULT_COUNTRY CTRY_UNITED_STATES
#if HAS_GETREGDATA
static const WCHAR wszCountryKey[] = L"Control Panel\\International";
static const WCHAR wszCountryValue[] = L"iCountry";
#endif
BOOL
IsA4PaperDefault(
VOID
)
/*++
Routine Description:
This function determine if the machine user is using the letter or A4
paper as default based on the country code
Arguments:
NONE
Return Value:
BOOL true if the country default paper is A4, else LETTER
Author:
23-Nov-1993 Tue 17:50:25 created
02-Feb-1994 Wed 03:01:12 updated
re-written so that we do open registry for the international data
ourself, and we will make sure we close the all the keys opened by
this function, so the system can unload the registry when the user
log off.
Revision History:
--*/
{
#if HAS_GETREGDATA
HKEY hKey;
LONG CountryCode = DEFAULT_COUNTRY;
WCHAR wszStr[16];
if (RegOpenKey(HKEY_CURRENT_USER, wszCountryKey, &hKey) == ERROR_SUCCESS) {
DWORD Type = REG_SZ;
DWORD RetVal = sizeof(wszStr);
size_t cch;
if (RegQueryValueEx(hKey,
(LPTSTR)wszCountryValue,
NULL,
&Type,
(LPBYTE)wszStr,
&RetVal) == ERROR_SUCCESS) {
LPWSTR pwStop;
PLOTDBG(DBG_A4DEFAULT, ("IsA4PaperDefault: Country = %s", wszStr));
if (Type == REG_SZ && SUCCEEDED(StringCchLength(wszStr, CCHOF(wszStr), &cch)))
{
CountryCode = wcstoul(wszStr, &pwStop, 10);
}
else
{
PLOTERR(("IsA4PaperDefault: RegQueryValue '%s' FAILED", wszCountryValue));
}
} else {
PLOTERR(("IsA4PaperDefault: RegQueryValue '%s' FAILED", wszCountryValue));
}
RegCloseKey(hKey);
} else {
PLOTERR(("IsA4PaperDefault: RegOpenKey '%s' FAILED", wszCountryKey));
}
if ((CountryCode == CTRY_UNITED_STATES) ||
(CountryCode == CTRY_CANADA) ||
((CountryCode >= 50) && (CountryCode < 60)) ||
((CountryCode >= 500) && (CountryCode < 600))) {
PLOTDBG(DBG_A4DEFAULT, ("IsA4PaperDefault = No, Use 'LETTER'"));
return(FALSE);
} else {
PLOTDBG(DBG_A4DEFAULT, ("IsA4PaperDefault = Yes"));
return(TRUE);
}
#else
//
// Use letter size now
//
return(FALSE);
#endif // HAS_GETREGDATA
}
BOOL
IntersectRECTL(
PRECTL prclDest,
PRECTL prclSrc
)
/*++
Routine Description:
This function intersect two RECTL data structures which specified imageable
areas.
Arguments:
prclDest - pointer to the destination RECTL data structure, the result
is written back to here
prclSrc - pointer to the source RECTL data structure to be intersect
with the destination RECTL
Return Value:
TRUE if destination is not empty, FALSE if final destination is empty
Author:
20-Dec-1993 Mon 14:08:02 updated
Change return value's meaning as if intersection is not empty
17-Dec-1993 Fri 14:41:10 updated
Add prclDif and compare it correctly
29-Nov-1993 Mon 19:02:01 created
Revision History:
--*/
{
BOOL IsNULL = FALSE;
if (prclSrc != prclDest) {
//
// For left/top we will set to whichever is larger.
//
if (prclDest->left < prclSrc->left) {
prclDest->left = prclSrc->left;
}
if (prclDest->top < prclSrc->top) {
prclDest->top = prclSrc->top;
}
//
// For right/bottom we will set to whichever is smaller
//
if (prclDest->right > prclSrc->right) {
prclDest->right = prclSrc->right;
}
if (prclDest->bottom > prclSrc->bottom) {
prclDest->bottom = prclSrc->bottom;
}
}
PLOTDBG(DBG_INTERSECTRECTL, ("IntersectRECTL: Dest = (%ld x %ld)",
prclDest->right-prclDest->left, prclDest->bottom-prclDest->top));
return((prclDest->right > prclDest->left) &&
(prclDest->bottom > prclDest->top));
}
BOOL
RotatePaper(
PSIZEL pSize,
PRECTL pImageArea,
UINT RotateMode
)
/*++
Routine Description:
This function rotate a paper left 90 degree, right 90 degree or 180 degree
depends on the RotateMode passed
Arguments:
pSize - Pointer to the size of the paper to be rotated
pImageArea - Pointer to the RECTL of Imageable area
RotateMode - Must be one of RM_L90, RM_R90, RM_180
Return Value:
No return value, but the pSize, and pImageArea pointed to location will
be updated.
Author:
16-Dec-1993 Thu 09:18:33 created
Revision History:
--*/
{
SIZEL Size;
RECTL Margin;
//
// To be sucessfully rotate the paper to the left 90 degree we must know
// all four sides margin before we can do anything
//
Size = *pSize;
Margin.left = pImageArea->left;
Margin.top = pImageArea->top;
Margin.right = Size.cx - pImageArea->right;
Margin.bottom = Size.cy - pImageArea->bottom;
PLOTASSERT(0, "RotatePaper: cx size too small (%ld)",
(Size.cx - Margin.left - Margin.right) > 0, Size.cx);
PLOTASSERT(0, "RotatePaper: cy size too small (%ld)",
(Size.cy - Margin.top - Margin.bottom) > 0, Size.cy);
PLOTDBG(DBG_ROTPAPER,
("RotatePaper(%ld) FROM (%ld x %ld), (%ld, %ld)-(%ld, %ld)",
(LONG)RotateMode,
pSize->cx, pSize->cy,
pImageArea->left, pImageArea->top,
pImageArea->right, pImageArea->bottom));
//
// Now we can pick the right margin/corner for the rotation
//
// cx Rotate Left 90 Rotate Right 90
// +-------+
// | T | cy cy
// | | +------------+ +------------+
// c| | | R | | L |
// y| | c| | c| |
// |L R| x| | x| |
// | | |T B| |B T|
// | | | | | |
// | | | L | | R |
// | B | +------------+ +------------+
// +-------+
//
switch (RotateMode) {
case RM_L90:
pSize->cx = Size.cy;
pSize->cy = Size.cx;
pImageArea->left = Margin.top;
pImageArea->top = Margin.right;
pImageArea->right = Size.cy - Margin.bottom;
pImageArea->bottom = Size.cx - Margin.left;
break;
case RM_R90:
pSize->cx = Size.cy;
pSize->cy = Size.cx;
pImageArea->left = Margin.bottom;
pImageArea->top = Margin.left;
pImageArea->right = Size.cy - Margin.top;
pImageArea->bottom = Size.cx - Margin.right;
break;
case RM_180:
pImageArea->top = Margin.bottom;
pImageArea->bottom = Size.cy - Margin.top;
break;
default:
PLOTERR(("RotatePaper(%ld): Invalid RotateMode passed", RotateMode));
return(FALSE);
}
PLOTDBG(DBG_ROTPAPER,
("RotatePaper(%ld) - TO (%ld x %ld), (%ld, %ld)-(%ld, %ld)",
(LONG)RotateMode,
pSize->cx, pSize->cy,
pImageArea->left, pImageArea->top,
pImageArea->right, pImageArea->bottom));
return(TRUE);
}
SHORT
GetDefaultPaper(
PPAPERINFO pPaperInfo
)
/*++
Routine Description:
This function compute the default paper name, size.
Arguments:
pPaperInfo - Point to the paper info which will be fill by this function
Return Value:
It return a SHORT value which specified the standard paper index in as
DMPAPER_xxx
Author:
03-Dec-1993 Fri 13:13:42 created
Revision History:
--*/
{
SHORT dmPaperSize;
HRESULT hr;
if (pPaperInfo == NULL) {
return 0;
}
pPaperInfo->ImageArea.left =
pPaperInfo->ImageArea.top = 0;
if (IsA4PaperDefault()) {
dmPaperSize = (SHORT)DMPAPER_A4;
pPaperInfo->Size.cx =
pPaperInfo->ImageArea.right = DMTOSPL(A4_FORM_CX);
pPaperInfo->Size.cy =
pPaperInfo->ImageArea.bottom = DMTOSPL(A4_FORM_CY);
hr = StringCchCopy(pPaperInfo->Name, CCHOF(pPaperInfo->Name), A4_FORM_NAME);
PLOTDBG(DBG_DEFPAPER, ("Pick 'A4' paper as default"));
} else {
dmPaperSize = (SHORT)DMPAPER_LETTER;
pPaperInfo->Size.cx = (LONG)_DefPlotDM.dm.dmPaperWidth;
pPaperInfo->Size.cy = (LONG)_DefPlotDM.dm.dmPaperLength;
dmPaperSize = (SHORT)DMPAPER_LETTER;
pPaperInfo->Size.cx =
pPaperInfo->ImageArea.right = DMTOSPL(_DefPlotDM.dm.dmPaperWidth);
pPaperInfo->Size.cy =
pPaperInfo->ImageArea.bottom = DMTOSPL(_DefPlotDM.dm.dmPaperLength);
hr = StringCchCopy(pPaperInfo->Name, CCHOF(pPaperInfo->Name), _DefPlotDM.dm.dmFormName);
PLOTDBG(DBG_DEFPAPER, ("Pick 'Letter' paper as default"));
}
PLOTDBG(DBG_DEFPAPER, ("SetDefaultPaper: '%ls' (%ld x %ld)",
pPaperInfo->Name, pPaperInfo->Size.cx, pPaperInfo->Size.cy));
return(dmPaperSize);
}
VOID
GetDefaultPlotterForm(
PPLOTGPC pPlotGPC,
PPAPERINFO pPaperInfo
)
/*++
Routine Description:
This function set the default loaded paper on the plotter to the first
form data list in the PCD data file
Arguments:
pPlotGPC - Pointer to the GPC data
pPaperInfo - Pointer to the paper info to be returned
Return Value:
TRUE if sucessful, false if failed
Author:
03-Feb-1994 Thu 11:37:37 created
Revision History:
--*/
{
PFORMSRC pFS;
if ((pFS = (PFORMSRC)pPlotGPC->Forms.pData) &&
(pPlotGPC->Forms.Count)) {
str2Wstr(pPaperInfo->Name, CCHOF(pPaperInfo->Name), pFS->Name);
pPaperInfo->Size = pFS->Size;
pPaperInfo->ImageArea.left = pFS->Margin.left;
pPaperInfo->ImageArea.top = pFS->Margin.top;
pPaperInfo->ImageArea.right = pFS->Size.cx - pFS->Margin.right;
pPaperInfo->ImageArea.bottom = pFS->Size.cy - pFS->Margin.bottom;
} else {
PLOTERR(("GetDefaultPlotterForm: No FORM DATA in PCD, used country default"));
GetDefaultPaper(pPaperInfo);
}
}
VOID
SetDefaultDMForm(
PPLOTDEVMODE pPlotDM,
PFORMSIZE pCurForm
)
/*++
Routine Description:
This function set the default form for the PLOTDEVMODE, these includes
dmPaperSize, dmPaperWidth, dmPaperLength, dmFormName and set pCurForm
if pointer is not NULL
Arguments:
pPlotDM - Pointer to the PLOTDEVMODE data structure
pCurForm - pointer to the FORMSIZE data structure to store current
default form set by this function
Return Value:
VOID
Author:
01-Dec-1993 Wed 13:44:31 created
Revision History:
--*/
{
PAPERINFO PaperInfo;
HRESULT hr;
pPlotDM->dm.dmFields &= ~DM_PAPER_FIELDS;
pPlotDM->dm.dmFields |= (DM_FORMNAME | DM_PAPERSIZE);
pPlotDM->dm.dmPaperSize = GetDefaultPaper(&PaperInfo);
pPlotDM->dm.dmPaperWidth = SPLTODM(PaperInfo.Size.cx);
pPlotDM->dm.dmPaperLength = SPLTODM(PaperInfo.Size.cy);
hr = StringCchCopy((LPWSTR)pPlotDM->dm.dmFormName, CCHOF(pPlotDM->dm.dmFormName), PaperInfo.Name);
if (pCurForm) {
pCurForm->Size = PaperInfo.Size;
pCurForm->ImageArea = PaperInfo.ImageArea;
}
}
VOID
SetDefaultPLOTDM(
HANDLE hPrinter,
PPLOTGPC pPlotGPC,
LPWSTR pwDeviceName,
PPLOTDEVMODE pPlotDM,
PFORMSIZE pCurForm
)
/*++
Routine Description:
This function set the default devmode based on the current pPlotGPC
Arguments:
hPrinter - Handle to the printer
pPlotGPC - our loaded/verified GPC data.
pwDeviceName - the device name passed in
pPlotDM - Pointer to our ExtDevMode
pCurForm - Pointer to the FORMSIZE data structure which will be
updated if the pointer is not NULL, the final result of
the form size/imagable area selected by the user will
be written to here. the form name will be in
pPlotDM->dmFormName.
Return Value:
VOID
Author:
14-Dec-1993 Tue 20:21:48 updated
Update the dmScale based on maximum the device can support
06-Dec-1993 Mon 12:49:52 updated
make sure we turn off the DM_xxx bits if one of those is not valid or
supported in current plotter
16-Nov-1993 Tue 13:49:27 created
Revision History:
--*/
{
WCHAR *pwchDeviceName = NULL;
ULONG ulStrLen = 0;
//
// Device name including NULL terminator
// must be equal or shorter than CCHDEVICENAME.
// PREFIX doesn' take this assumption. Buffer size needs to be flexible and
// should not be on stack.
//
if (pwDeviceName) {
ulStrLen = wcslen(pwDeviceName);
//
// Allocate buffer to hold pwDeviceName including null terminator.
// Make sure that pwDeviceName has a device name.
//
if (0 == ulStrLen ||
!(pwchDeviceName = (WCHAR*)LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT, (ulStrLen + 1) * sizeof(WCHAR))))
{
PLOTERR(("SetDefaultPLOTDM: memory allocaton failed.\n"));
//
// Make sure that pPlotGPC->DeviceName has a null terminator.
//
pPlotGPC->DeviceName[0] = (BYTE)NULL;
}
else
{
_WCPYSTR(pwchDeviceName, pwDeviceName, ulStrLen + 1);
//
// Make sure the PlotGPC's device name is ssync with the pDeviceName
// passed.
// String length must be equal or shorter than CCHDEVICENAME.
// DEVMODE's device name and pPlotGPC->DeviceName can't hold a sting
// longer than CCHDEVICENAME.
//
if (ulStrLen + 1 > CCHDEVICENAME)
{
PLOTERR(("SetDefaultPLOTDM: DeviceName is longer than buffer size.\n"));
}
else
{
WStr2Str(pPlotGPC->DeviceName, CCHOF(pPlotGPC->DeviceName), pwchDeviceName);
}
}
PLOTDBG(DBG_DEFDEVMODE, ("PlotGPC DeviceName=%hs\npwDeviceName=%ls",
pPlotGPC->DeviceName, pwDeviceName));
} else {
PLOTERR(("No DeviceName passed, using GPC's '%hs'",
pPlotGPC->DeviceName));
ulStrLen = strlen(pPlotGPC->DeviceName);
//
// Allocate buffer to hold pwDeviceName including null terminator.
// Make sure that pwDeviceName has a device name.
//
if (0 == ulStrLen ||
!(pwchDeviceName = (WCHAR*)LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT, (ulStrLen + 1) * sizeof(WCHAR))))
{
PLOTERR(("SetDefaultPLOTDM: memory allocaton failed.\n"));
}
else
{
str2Wstr(pwchDeviceName, ulStrLen + 1, pPlotGPC->DeviceName);
}
}
//
// Make a default copy first then copy device name down
//
CopyMemory(pPlotDM, &_DefPlotDM, sizeof(PLOTDEVMODE));
if (pwchDeviceName)
{
WCPYFIELDNAME(pPlotDM->dm.dmDeviceName, pwchDeviceName);
LocalFree(pwchDeviceName);
}
else
{
pPlotDM->dm.dmDeviceName[0] = (WCHAR)NULL;
}
//
// We must turn off the DM_xxx bits in dmFields if we do not support it,
// look at default fields we copy down then update it
//
if (pPlotGPC->MaxScale) {
if ((WORD)pPlotDM->dm.dmScale > pPlotGPC->MaxScale) {
pPlotDM->dm.dmScale = (SHORT)pPlotGPC->MaxScale;
}
} else {
pPlotDM->dm.dmFields &= ~DM_SCALE;
}
if (pPlotGPC->MaxCopies <= 1) {
pPlotDM->dm.dmFields &= ~DM_COPIES;
}
if (!(pPlotGPC->MaxQuality)) {
pPlotDM->dm.dmFields &= ~DM_PRINTQUALITY;
}
//
// DEFAULT 50% quality for byte align plotter (DJ 600) to do ROP right
//
if (pPlotGPC->Flags & PLOTF_RASTERBYTEALIGN) {
pPlotDM->dm.dmPrintQuality = DMRES_LOW;
PLOTWARN(("SetDefaultPLOTDM: HACK Default Qaulity = DMRES_LOW"));
}
if (!(pPlotGPC->Flags & PLOTF_COLOR)) {
if (pPlotGPC->Flags & PLOTF_RASTER) {
pPlotDM->dm.dmFields &= ~DM_COLOR;
pPlotDM->dm.dmColor = DMCOLOR_MONOCHROME;
} else {
PLOTASSERT(0,
"SetDefaultPLOTDM: The Pen Ploter CANNOT be MONO.",
(pPlotGPC->Flags & PLOTF_COLOR), 0);
pPlotGPC->Flags |= PLOTF_COLOR;
}
}
//
// Set default form name based on the country
//
SetDefaultDMForm(pPlotDM, pCurForm);
}
DWORD
MergePLOTDM(
HANDLE hPrinter,
PPLOTGPC pPlotGPC,
PPLOTDEVMODE pPlotDMFrom,
PPLOTDEVMODE pPlotDMTo,
PFORMSIZE pCurForm
)
/*++
Routine Description:
This function merge and validate the pPlotDMTo from pPlotDMFrom. The
PlotDMOut must valid
Arguments:
hPrinter - Handle to the printer to be checked
pPlotGPC - The plotter's GPC data loaded from the file
pPlotDMFrom - pointer to the input PLOTDEVMODE data structure, if can
be NULL
pPlotDMTo - Pointer to the output PLOTDEVMODE data structure, if
pPlotDMFrom is NULL then a default PLOTDEVMODE is
returned
pCurForm - Pointer to the FORMSIZE data structure which will be
updated if the pointer is not NULL, the final result of
the form size/imagable area selected by the user will
be written to here. the form name will be in
pPlotDM->dmFormName.
Return Value:
the return value is a DWORD dmField error code which specified dmFields
are invalid (DM_xxxxx in wingdi.h) if the return value has any DM_INV_xxx
bits set then it should raised an error to the user.
if return value is 0 then function sucessful
Author:
25-Oct-1994 Tue 13:32:18 created
Revision History:
--*/
{
PLOTDEVMODE PlotDMIn;
ENUMFORMPARAM EFP;
DWORD dmErrFields = 0;
SIZEL PaperSize;
//
// First: set the default PLOTDEVMODE for the output then from there
// validate/settting from input devmode, if pwDeviceName passed as
// NULL then it assume that pPlotDMTo alreay set and validated
//
// If we have invalid input devmode then this it is
//
if ((!pPlotDMFrom) || (!pPlotDMTo) || (!pPlotGPC)) {
return(0);
}
//
// Do some conversion here if necessary, first, copy the output one
//
CopyMemory(&PlotDMIn, pPlotDMTo, sizeof(PLOTDEVMODE));
ConvertDevmode((PDEVMODE) pPlotDMFrom, (PDEVMODE) &PlotDMIn);
PLOTDBG(DBG_SHOWDEVMODE,
("--------------- Input DEVMODE Setting -------------------"));
PLOTDBG(DBG_SHOWDEVMODE,
("ValidateSetPLOTDM: dmDeviceName = %ls",
(DWORD_PTR)PlotDMIn.dm.dmDeviceName));
PLOTDBG(DBG_SHOWDEVMODE,
("ValidateSetPLOTDM: dmSpecVersion = %04lx",
(DWORD)PlotDMIn.dm.dmSpecVersion));
PLOTDBG(DBG_SHOWDEVMODE,
("ValidateSetPLOTDM: dmDriverVersion = %04lx",
(DWORD)PlotDMIn.dm.dmDriverVersion));
PLOTDBG(DBG_SHOWDEVMODE,
("ValidateSetPLOTDM: dmSize = %0ld (%ld)",
(DWORD)PlotDMIn.dm.dmSize, sizeof(DEVMODE)));
PLOTDBG(DBG_SHOWDEVMODE,
("ValidateSetPLOTDM: dmDriverExtra = %ld (%ld)",
(DWORD)PlotDMIn.dm.dmDriverExtra, PLOTDM_PRIV_SIZE));
PLOTDBG(DBG_SHOWDEVMODE,
("ValidateSetPLOTDM: dmFields = %08lx",
(DWORD)PlotDMIn.dm.dmFields));
PLOTDBG(DBG_SHOWDEVMODE,
("ValidateSetPLOTDM: dmOrientation = %ld (%hs)",
(DWORD)PlotDMIn.dm.dmOrientation,
(PlotDMIn.dm.dmFields & DM_ORIENTATION) ? "ON" : "OFF"));
PLOTDBG(DBG_SHOWDEVMODE,
("ValidateSetPLOTDM: dmPaperSize = %ld (%hs)",
(DWORD)PlotDMIn.dm.dmPaperSize,
(PlotDMIn.dm.dmFields & DM_PAPERSIZE) ? "ON" : "OFF"));
PLOTDBG(DBG_SHOWDEVMODE,
("ValidateSetPLOTDM: dmPaperLength = %ld (%hs)",
(DWORD)PlotDMIn.dm.dmPaperLength,
(PlotDMIn.dm.dmFields & DM_PAPERLENGTH) ? "ON" : "OFF"));
PLOTDBG(DBG_SHOWDEVMODE,
("ValidateSetPLOTDM: dmPaperWidth = %ld (%hs)",
(DWORD)PlotDMIn.dm.dmPaperWidth,
(PlotDMIn.dm.dmFields & DM_PAPERWIDTH) ? "ON" : "OFF"));
PLOTDBG(DBG_SHOWDEVMODE,
("ValidateSetPLOTDM: dmScale = %ld (%hs)",
(DWORD)PlotDMIn.dm.dmScale,
(PlotDMIn.dm.dmFields & DM_SCALE) ? "ON" : "OFF"));
PLOTDBG(DBG_SHOWDEVMODE,
("ValidateSetPLOTDM: dmCopies = %ld (%hs)",
(DWORD)PlotDMIn.dm.dmCopies,
(PlotDMIn.dm.dmFields & DM_COPIES) ? "ON" : "OFF"));
PLOTDBG(DBG_SHOWDEVMODE,
("ValidateSetPLOTDM: dmPrintQuality = %ld (%hs)",
(DWORD)PlotDMIn.dm.dmPrintQuality,
(PlotDMIn.dm.dmFields & DM_PRINTQUALITY) ? "ON" : "OFF"));
PLOTDBG(DBG_SHOWDEVMODE,
("ValidateSetPLOTDM: dmColor = %ld (%hs)",
(DWORD)PlotDMIn.dm.dmColor,
(PlotDMIn.dm.dmFields & DM_COLOR) ? "ON" : "OFF"));
PLOTDBG(DBG_SHOWDEVMODE,
("ValidateSetPLOTDM: dmFormName = %ls (%hs)",
(DWORD_PTR)PlotDMIn.dm.dmFormName,
(PlotDMIn.dm.dmFields & DM_FORMNAME) ? "ON" : "OFF"));
PLOTDBG(DBG_SHOWDEVMODE,
("ValidateSetPLOTDM: Fill Truetype Font = %hs",
(PlotDMIn.Flags & PDMF_FILL_TRUETYPE) ? "ON" : "OFF"));
PLOTDBG(DBG_SHOWDEVMODE,
("ValidateSetPLOTDM: Plot On the Fly = %hs",
(PlotDMIn.Flags & PDMF_PLOT_ON_THE_FLY) ? "ON" : "OFF"));
PLOTDBG(DBG_SHOWDEVMODE,
("---------------------------------------------------------"));
//
// Statring checking the dmFields, *** REMEMBER: The orientation must
// check before the checking the paper/form
//
if (PlotDMIn.dm.dmFields & DM_ORIENTATION) {
switch (PlotDMIn.dm.dmOrientation) {
case DMORIENT_PORTRAIT:
case DMORIENT_LANDSCAPE:
pPlotDMTo->dm.dmOrientation = PlotDMIn.dm.dmOrientation;
pPlotDMTo->dm.dmFields |= DM_ORIENTATION;
break;
default:
PLOTERR(("ValidatePLOTDM: Invalid dmOrientation = %ld",
(LONG)PlotDMIn.dm.dmOrientation));
dmErrFields |= DM_ORIENTATION;
break;
}
}
//
// Validate form name so we have correct data, assume error first
//
dmErrFields |= (DWORD)(PlotDMIn.dm.dmFields & DM_PAPER_FIELDS);
if (((PlotDMIn.dm.dmFields & DM_PAPER_CUSTOM) == DM_PAPER_CUSTOM) &&
((PlotDMIn.dm.dmPaperSize == DMPAPER_USER) ||
(PlotDMIn.dm.dmPaperSize == 0)) &&
(PaperSize.cx = DMTOSPL(PlotDMIn.dm.dmPaperWidth)) &&
(PaperSize.cy = DMTOSPL(PlotDMIn.dm.dmPaperLength)) &&
(PaperSize.cx >= MIN_SPL_FORM_CX) &&
(PaperSize.cy >= MIN_SPL_FORM_CY) &&
(((PaperSize.cx <= pPlotGPC->DeviceSize.cx) &&
(PaperSize.cy <= pPlotGPC->DeviceSize.cy)) ||
((PaperSize.cy <= pPlotGPC->DeviceSize.cx) &&
(PaperSize.cx <= pPlotGPC->DeviceSize.cy)))) {
//
// First choice, this is what the caller wants, we need to validate
// for this device, since the size may be larger then device can
// handle
//
pPlotDMTo->dm.dmPaperWidth = PlotDMIn.dm.dmPaperWidth;
pPlotDMTo->dm.dmPaperLength = PlotDMIn.dm.dmPaperLength;
pPlotDMTo->dm.dmFields &= ~DM_PAPER_FIELDS;
pPlotDMTo->dm.dmFields |= DM_PAPER_CUSTOM;
pPlotDMTo->dm.dmPaperSize = DMPAPER_USER;
pPlotDMTo->dm.dmFormName[0] = L'\0';
if (pCurForm) {
//
// This one is full imageable area as the widht/height
//
pCurForm->ImageArea.left =
pCurForm->ImageArea.top = 0;
pCurForm->Size.cx =
pCurForm->ImageArea.right = PaperSize.cx;
pCurForm->Size.cy =
pCurForm->ImageArea.bottom = PaperSize.cy;
}
dmErrFields &= ~DM_PAPER_FIELDS; // Fine, no error
PLOTDBG(DBG_CURFORM,("ValidateSetPLOTDM: FORM=USER <%ld> (%ld x %ld)",
PlotDMIn.dm.dmPaperSize, PaperSize.cx, PaperSize.cy));
} else if ((PlotDMIn.dm.dmFields & (DM_PAPERSIZE | DM_FORMNAME)) &&
(EFP.pPlotDM = pPlotDMTo) &&
(EFP.pPlotGPC = pPlotGPC) &&
(PlotEnumForms(hPrinter, NULL, &EFP))) {
FORM_INFO_1 *pFI1;
SHORT sPaperSize;
BOOL Found = FALSE;
//
// Firstable check sPaperSize index and if not found then check formname
//
if ((PlotDMIn.dm.dmFields & DM_PAPERSIZE) &&
((sPaperSize = PlotDMIn.dm.dmPaperSize) >= DMPAPER_FIRST) &&
(sPaperSize <= (SHORT)EFP.Count) &&
(pFI1 = EFP.pFI1Base + (sPaperSize - DMPAPER_FIRST)) &&
(pFI1->Flags & FI1F_VALID_SIZE)) {
//
// Whu..., this guy really pick a right index
//
Found = TRUE;
PLOTDBG(DBG_CURFORM,("ValidateSetPLOTDM: Fount dmPaperSize=%ld",
PlotDMIn.dm.dmPaperSize));
} else if (PlotDMIn.dm.dmFields & DM_FORMNAME) {
//
// Now go through all the formname trouble
//
pFI1 = EFP.pFI1Base;
sPaperSize = DMPAPER_FIRST;
while (EFP.Count--) {
if ((pFI1->Flags & FI1F_VALID_SIZE) &&
(!wcscmp(pFI1->pName, PlotDMIn.dm.dmFormName))) {
PLOTDBG(DBG_CURFORM,("ValidateSetPLOTDM: Found dmFormName=%s",
PlotDMIn.dm.dmFormName));
Found = TRUE;
break;
}
++sPaperSize;
++pFI1;
}
}
if (Found) {
pPlotDMTo->dm.dmFields &= ~DM_PAPER_FIELDS;
pPlotDMTo->dm.dmFields |= (DM_FORMNAME | DM_PAPERSIZE);
pPlotDMTo->dm.dmPaperSize = sPaperSize;
pPlotDMTo->dm.dmPaperWidth = SPLTODM(pFI1->Size.cx);
pPlotDMTo->dm.dmPaperLength = SPLTODM(pFI1->Size.cy);
WCPYFIELDNAME(pPlotDMTo->dm.dmFormName, pFI1->pName);
PLOTDBG(DBG_CURFORM,("FI1 [%ld]: (%ld x %ld), (%ld, %ld)-(%ld, %ld)",
(LONG)pPlotDMTo->dm.dmPaperSize,
pFI1->Size.cx, pFI1->Size.cy,
pFI1->ImageableArea.left, pFI1->ImageableArea.top,
pFI1->ImageableArea.right, pFI1->ImageableArea.bottom));
if (pCurForm) {
pCurForm->Size = pFI1->Size;
pCurForm->ImageArea = pFI1->ImageableArea;
}
dmErrFields &= ~DM_PAPER_FIELDS; // Fine, no error
}
//
// Free up the memory used
//
LocalFree((HLOCAL)EFP.pFI1Base);
}
if ((PlotDMIn.dm.dmFields & DM_SCALE) &&
(pPlotGPC->MaxScale)) {
if ((PlotDMIn.dm.dmScale > 0) &&
((WORD)PlotDMIn.dm.dmScale <= pPlotGPC->MaxScale)) {
pPlotDMTo->dm.dmScale = PlotDMIn.dm.dmScale;
pPlotDMTo->dm.dmFields |= DM_SCALE;
} else {
PLOTERR(("ValidatePLOTDM: Invalid dmScale = %ld [%ld]",
(LONG)PlotDMIn.dm.dmScale, (LONG)pPlotGPC->MaxScale));
dmErrFields |= DM_SCALE;
}
}
if (PlotDMIn.dm.dmFields & DM_COPIES) {
if ((PlotDMIn.dm.dmCopies > 0) &&
((LONG)PlotDMIn.dm.dmCopies <= (LONG)pPlotGPC->MaxCopies)) {
pPlotDMTo->dm.dmCopies = PlotDMIn.dm.dmCopies;
pPlotDMTo->dm.dmFields |= DM_COPIES;
} else {
PLOTERR(("ValidatePLOTDM: Invalid dmCopies = %ld [%ld]",
(LONG)PlotDMIn.dm.dmCopies, (LONG)pPlotGPC->MaxCopies));
dmErrFields |= DM_COPIES;
}
}
if (PlotDMIn.dm.dmFields & DM_PRINTQUALITY) {
dmErrFields |= DM_PRINTQUALITY; // assume error, proven otherwise
if (pPlotGPC->MaxQuality) {
switch (PlotDMIn.dm.dmPrintQuality) {
case DMRES_DRAFT:
case DMRES_LOW:
case DMRES_MEDIUM:
case DMRES_HIGH:
dmErrFields &= ~DM_PRINTQUALITY;
pPlotDMTo->dm.dmPrintQuality = PlotDMIn.dm.dmPrintQuality;
pPlotDMTo->dm.dmFields |= DM_PRINTQUALITY;
break;
}
}
if (dmErrFields & DM_PRINTQUALITY) {
PLOTERR(("ValidatePLOTDM: Invalid dmPrintQuality = %ld [%ld]",
(LONG)PlotDMIn.dm.dmPrintQuality,
(LONG)pPlotGPC->MaxQuality));
}
}
if (PlotDMIn.dm.dmFields & DM_COLOR) {
dmErrFields |= DM_COLOR; // assume error, proven otherwise
if (pPlotGPC->Flags & PLOTF_COLOR) {
switch (PlotDMIn.dm.dmColor) {
case DMCOLOR_MONOCHROME:
if (!(pPlotGPC->Flags & PLOTF_RASTER)) {
PLOTERR(("ValidatePLOTDM: Cannot Set Pen Plotter to MONO"));
break;
}
case DMCOLOR_COLOR:
pPlotDMTo->dm.dmColor = PlotDMIn.dm.dmColor;
pPlotDMTo->dm.dmFields |= DM_COLOR;
dmErrFields &= ~DM_COLOR;
break;
}
} else if (PlotDMIn.dm.dmColor == DMCOLOR_MONOCHROME) {
dmErrFields &= ~DM_COLOR;
}
if (dmErrFields & DM_COLOR) {
PLOTERR(("ValidatePLOTDM: Invalid dmColor = %ld [%hs]",
(LONG)PlotDMIn.dm.dmColor,
(pPlotGPC->Flags & PLOTF_COLOR) ? "COLOR" : "MONO"));
}
}
//
// Any other dmFields we just skip because we do not have that caps, now
// check if they have correct EXTDEVMODE stuff
//
if ((PlotDMIn.dm.dmDriverExtra == PLOTDM_PRIV_SIZE) &&
(PlotDMIn.PrivID == PLOTDM_PRIV_ID) &&
(PlotDMIn.PrivVer == PLOTDM_PRIV_VER)) {
pPlotDMTo->Flags = (DWORD)(PlotDMIn.Flags & PDMF_ALL_BITS);
pPlotDMTo->ca = PlotDMIn.ca;
if (pPlotGPC->Flags & PLOTF_RASTER) {
pPlotDMTo->Flags |= PDMF_FILL_TRUETYPE;
} else {
//
// Non raster device does not have plot on the fly mode
//
pPlotDMTo->Flags &= ~PDMF_PLOT_ON_THE_FLY;
}
if (!ValidateColorAdj(&(pPlotDMTo->ca))) {
dmErrFields |= DM_INV_PLOTPRIVATE;
PLOTERR(("ValidatePLOTDM: Invalid coloradjusment data"));
}
}
return(dmErrFields);
}
DWORD
ValidateSetPLOTDM(
HANDLE hPrinter,
PPLOTGPC pPlotGPC,
LPWSTR pwDeviceName,
PPLOTDEVMODE pPlotDMIn,
PPLOTDEVMODE pPlotDMOut,
PFORMSIZE pCurForm
)
/*++
Routine Description:
This function set and validate the pPlotDMOut from pPlotDMIn
(if not null and valid)
Arguments:
hPrinter - Handle to the printer to be checked
pPlotGPC - The plotter's GPC data loaded from the file
pwDeviceName - Device Name to be put into dmDeviceName, if NULL then
the device name is set from pPlotGPC->DeviceName
pPlotDMIn - pointer to the input PLOTDEVMODE data structure, if can
be NULL
pPlotDMOut - Pointer to the output PLOTDEVMODE data structure, if
pPlotDMIn is NULL then a default PLOTDEVMODE is returned
pCurForm - Pointer to the FORMSIZE data structure which will be
updated if the pointer is not NULL, the final result of
the form size/imagable area selected by the user will
be written to here. the form name will be in
pPlotDM->dmFormName.
Return Value:
the return value is a DWORD dmField error code which specified dmFields
are invalid (DM_xxxxx in wingdi.h) if the return value has any DM_INV_xxx
bits set then it should raised an error to the user.
if return value is 0 then function sucessful
Author:
23-Nov-1993 Tue 10:08:50 created
15-Dec-1993 Wed 21:27:52 updated
Fixed bug which compare dmPaperWidth/Length to MIN_SPL_FORM_CX
18-Dec-1993 Sat 03:57:24 updated
Fixed bug which reset dmFields when we checking DM_PAPERxxx and
DM_FORMNAME, this turn off DM_ORIENTATION fields which let the
orientation setting never stick.
Also change how this fucntion set the paper fields, this function now
only set DM_FORMNAME upon returned if the dmPaperSize getting larger
then DMPAPER_LAST, otherwise it set DM_FORMNAME | DM_PAPERSIZE
12-Apr-1994 Tue 15:07:24 updated
Make smaller spec version printable
25-Oct-1994 Tue 13:41:03 updated
Change to have default as current Printer Properties setting first,
Revision History:
--*/
{
DWORD dmErrFields = 0;
if (NULL == pPlotDMOut || NULL == pPlotGPC)
{
PLOTASSERT(1, "ValidatePLOTDM: NULL pPlotDMOut", pPlotDMOut, 0);
PLOTASSERT(1, "ValidatePLOTDM: NULL pPlotGPC", pPlotGPC, 0);
return 0xFFFFFFFF;
}
if ((pPlotDMOut) || (pPlotGPC)) {
PPRINTER_INFO_2 pPrinter2 = NULL;
DWORD cbNeed;
DWORD cbRet;
//
// First: set the default PLOTDEVMODE for the output then from there
// validate/settting from input devmode, if pwDeviceName passed
// as NULL then it assume that pPlotDMOut alreay set and
// validated
//
if (pwDeviceName) {
SetDefaultPLOTDM(hPrinter,
pPlotGPC,
pwDeviceName,
pPlotDMOut,
pCurForm);
PLOTDBG(DBG_DEFDEVMODE,
("ValidateSetPLOTDM: Set Default PLOTDM DeviceName=%ls", pwDeviceName));
}
//
// Now see if we can get the current printman devmode setting as default
//
cbNeed =
cbRet = 0;
if ((!xGetPrinter(hPrinter, 2, NULL, 0, &cbNeed)) &&
(xGetLastError() == ERROR_INSUFFICIENT_BUFFER) &&
(pPrinter2 = LocalAlloc(LMEM_FIXED, cbNeed)) &&
(xGetPrinter(hPrinter, 2, (LPBYTE)pPrinter2, cbNeed, &cbRet)) &&
(cbNeed == cbRet) &&
(pPrinter2->pDevMode)) {
PLOTDBG(DBG_DEFDEVMODE, ("ValidateSetPLOTDM: Got the PrintMan DEVMODE"));
dmErrFields = MergePLOTDM(hPrinter,
pPlotGPC,
(PPLOTDEVMODE)pPrinter2->pDevMode,
pPlotDMOut,
pCurForm);
} else {
PLOTWARN(("ValidateSetPLOTDM: CANNOT get the PrintMan's DEVMODE"));
PLOTWARN(("pPrinter2=%08lx, pDevMode=%08lx, cbNeed=%ld, cbRet=%ld, LastErr=%ld",
pPrinter2, (pPrinter2) ? pPrinter2->pDevMode : 0,
cbNeed, cbRet, xGetLastError()));
}
if (pPrinter2) {
LocalFree((HLOCAL)pPrinter2);
}
//
// Now the pPlotDMOut is validated, merge it with user's request
//
if (pPlotDMIn) {
dmErrFields = MergePLOTDM(hPrinter,
pPlotGPC,
pPlotDMIn,
pPlotDMOut,
pCurForm);
}
}
return(dmErrFields);
}