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.
 
 
 
 
 
 

1864 lines
43 KiB

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
ps.c
Abstract:
This file handles Postscript specific UI options
Environment:
Win32 subsystem, DriverUI module, user mode
Revision History:
02/25/97 -davidx-
Finish PS-specific items.
02/04/97 -davidx-
Reorganize driver UI to separate ps and uni DLLs.
12/17/96 -amandan-
Created it.
--*/
#include "precomp.h"
#include <ntverp.h>
BOOL BSearchConstraintList(PUIINFO, DWORD, DWORD, DWORD);
static CONST WORD ScaleItemInfo[] =
{
IDS_CPSUI_SCALING, TVITEM_LEVEL1, DMPUB_SCALE,
SCALE_ITEM, HELP_INDEX_SCALE,
2, TVOT_UDARROW,
IDS_CPSUI_PERCENT, IDI_CPSUI_SCALING,
0, MIN_SCALE,
ITEM_INFO_SIGNATURE
};
BOOL
_BPackItemScale(
PUIDATA pUiData
)
/*++
Routine Description:
Pack scaling option.
Arguments:
pUiData - Points to UIDATA structure
Return Value:
TRUE if successful, FALSE if there is an error.
--*/
{
return BPackUDArrowItemTemplate(
pUiData,
ScaleItemInfo,
pUiData->ci.pdm->dmScale,
pUiData->ci.pUIInfo->dwMaxScale,
NULL);
}
DWORD
_DwEnumPersonalities(
PCOMMONINFO pci,
PWSTR pwstrOutput
)
/*++
Routine Description:
Enumerate the list of supported printer description languages
Arguments:
pci - Points to common printer info
pwstrOutput - Points to output buffer
Return Value:
Number of personalities supported
GDI_ERROR if there is an error
--*/
{
if (pwstrOutput)
CopyString(pwstrOutput, TEXT("PostScript"), CCHLANGNAME);
return 1;
}
DWORD
_DwGetOrientationAngle(
PUIINFO pUIInfo,
PDEVMODE pdm
)
/*++
Routine Description:
Get the orienation angle requested by DrvDeviceCapabilities(DC_ORIENTATION)
Arguments:
pUIInfo - Pointer to UIINFO
pdm - Pointer to DEVMODE
Return Value:
The angle (90 or 270 or landscape rotation)
--*/
{
DWORD dwRet;
PPSDRVEXTRA pdmPrivate;
pdmPrivate = (PPSDRVEXTRA) GET_DRIVER_PRIVATE_DEVMODE(pdm);
//
// Normal landscape rotates counterclockwise
// Rotated landscape rotates clockwise
//
if (pUIInfo->dwFlags & FLAG_ROTATE90)
dwRet = (pdmPrivate->dwFlags & PSDEVMODE_LSROTATE) ? 270 : 90;
else
dwRet = (pdmPrivate->dwFlags & PSDEVMODE_LSROTATE) ? 90 : 270;
return dwRet;
}
static CONST WORD PSOrientItemInfo[] =
{
IDS_CPSUI_ORIENTATION, TVITEM_LEVEL1, DMPUB_ORIENTATION,
ORIENTATION_ITEM, HELP_INDEX_ORIENTATION,
3, TVOT_3STATES,
IDS_CPSUI_PORTRAIT, IDI_CPSUI_PORTRAIT,
IDS_CPSUI_LANDSCAPE, IDI_CPSUI_LANDSCAPE,
IDS_CPSUI_ROT_LAND, IDI_CPSUI_ROT_LAND,
ITEM_INFO_SIGNATURE
};
BOOL
_BPackOrientationItem(
IN OUT PUIDATA pUiData
)
/*++
Routine Description:
Synthesize the orientation feature for Doc property sheet
Arguments:
pUiData - Points to UIDATA structure
Return Value:
TRUE for success and FALSE for failure
Note:
Always synthesize orienation for PostScript
--*/
{
PFEATURE pFeature;
DWORD dwSelection;
//
// If there is no predefined orientation feature, we displays it ourselves.
//
if ((pUiData->ci.pdm->dmFields & DM_ORIENTATION) &&
(pUiData->ci.pdm->dmOrientation == DMORIENT_LANDSCAPE))
{
PPSDRVEXTRA pdmPrivate;
pdmPrivate = (PPSDRVEXTRA) GET_DRIVER_PRIVATE_DEVMODE(pUiData->ci.pdm);
dwSelection = pdmPrivate->dwFlags & PSDEVMODE_LSROTATE ? 2 : 1;
}
else
dwSelection = 0;
//
// Synthesize the feature ourselves
//
return BPackOptItemTemplate(pUiData, PSOrientItemInfo, dwSelection, NULL);
}
static CONST WORD PSOutputOptionItemInfo[] =
{
IDS_PSOUTPUT_OPTION, TVITEM_LEVEL2, DMPUB_NONE,
PSOUTPUT_OPTION_ITEM, HELP_INDEX_PSOUTPUT_OPTION,
4, TVOT_LISTBOX,
IDS_PSOPT_SPEED, IDI_PSOPT_SPEED,
IDS_PSOPT_PORTABILITY, IDI_PSOPT_PORTABILITY,
IDS_PSOPT_EPS, IDI_PSOPT_EPS,
IDS_PSOPT_ARCHIVE, IDI_PSOPT_ARCHIVE,
ITEM_INFO_SIGNATURE
};
BOOL
BPackItemPSOutputOption(
PUIDATA pUiData,
PPSDRVEXTRA pdmPrivate
)
/*++
Routine Description:
Pack PostScript output option item
Arguments:
pUiData - Points to UIDATA structure
pdmPrivate - Points to pscript private devmode
Return Value:
TRUE if successful, FALSE if there is an error
--*/
{
DWORD dwSel;
switch (pdmPrivate->iDialect)
{
case PORTABILITY:
dwSel = 1;
break;
case EPS:
dwSel = 2;
break;
case ARCHIVE:
dwSel = 3;
break;
case SPEED:
default:
dwSel = 0;
break;
}
return BPackOptItemTemplate(pUiData, PSOutputOptionItemInfo, dwSel, NULL);
}
static CONST WORD PSTTDLFormatItemInfo[] =
{
IDS_PSTT_DLFORMAT, TVITEM_LEVEL2, DMPUB_NONE,
PSTT_DLFORMAT_ITEM, HELP_INDEX_PSTT_DLFORMAT,
4, TVOT_LISTBOX,
IDS_TTDL_DEFAULT, IDI_PSTT_DLFORMAT,
IDS_TTDL_TYPE1, IDI_PSTT_DLFORMAT,
IDS_TTDL_TYPE3, IDI_PSTT_DLFORMAT,
IDS_TTDL_TYPE42, IDI_PSTT_DLFORMAT,
ITEM_INFO_SIGNATURE
};
BOOL
BPackItemTTDownloadFormat(
PUIDATA pUiData,
PPSDRVEXTRA pdmPrivate
)
/*++
Routine Description:
Pack PostScript TrueType download option item
Arguments:
pUiData - Points to UIDATA structure
pdmPrivate - Points to pscript private devmode
Return Value:
TRUE if successful, FALSE if there is an error
--*/
{
DWORD dwSel;
BOOL bSupportType42;
POPTTYPE pOptType = pUiData->pOptType;
bSupportType42 = (pUiData->ci.pUIInfo->dwTTRasterizer == TTRAS_TYPE42);
switch (pdmPrivate->iTTDLFmt)
{
case TYPE_1:
dwSel = 1;
break;
case TYPE_3:
dwSel = 2;
break;
case TYPE_42:
dwSel = bSupportType42 ? 3 : 0;
break;
case TT_DEFAULT:
default:
dwSel = 0;
break;
}
if (! BPackOptItemTemplate(pUiData, PSTTDLFormatItemInfo, dwSel, NULL))
return FALSE;
//
// if printer doesn't support Type42, hide Type42 option
//
if (pOptType && !bSupportType42)
pOptType->pOptParam[3].Flags |= OPTPF_HIDE;
return TRUE;
}
static CONST WORD PSLevelItemInfo[] =
{
IDS_PSLEVEL, TVITEM_LEVEL2, DMPUB_NONE,
PSLEVEL_ITEM, HELP_INDEX_SCALE,
2, TVOT_UDARROW,
0, IDI_PSLEVEL,
0,
//
// Adobe doesn't want to support level 1
//
#ifdef ADOBE
2,
#else
1,
#endif
ITEM_INFO_SIGNATURE
};
BOOL
BPackItemPSLevel(
PUIDATA pUiData,
PPSDRVEXTRA pdmPrivate
)
/*++
Routine Description:
Pack PostScript output option item
Arguments:
pUiData - Points to UIDATA structure
pdmPrivate - Points to pscript private devmode
Return Value:
TRUE if successful, FALSE if there is an error
--*/
{
DWORD dwSel = pdmPrivate->iPSLevel;
DWORD dwLangLevel = pUiData->ci.pUIInfo->dwLangLevel;
//
// we don't expect language level to be higher than 4
//
if (dwLangLevel <= 1)
return TRUE;
if (dwLangLevel > 4)
dwLangLevel = 4;
//
// make sure the current selection is sensible
//
if (dwSel == 0 || dwSel > dwLangLevel)
dwSel = dwLangLevel;
return BPackUDArrowItemTemplate(pUiData, PSLevelItemInfo, dwSel, dwLangLevel, NULL);
}
static CONST WORD EHandlerItemInfo[] =
{
IDS_PSERROR_HANDLER, TVITEM_LEVEL2, DMPUB_NONE,
PSERROR_HANDLER_ITEM, HELP_INDEX_PSERROR_HANDLER,
2, TVOT_2STATES,
IDS_CPSUI_YES, IDI_CPSUI_YES,
IDS_CPSUI_NO, IDI_CPSUI_NO,
ITEM_INFO_SIGNATURE
};
static CONST WORD MirrorItemInfo[] =
{
IDS_MIRROR, TVITEM_LEVEL2, DMPUB_NONE,
MIRROR_ITEM, HELP_INDEX_MIRROR,
2, TVOT_2STATES,
IDS_CPSUI_YES, IDI_CPSUI_YES,
IDS_CPSUI_NO, IDI_CPSUI_NO,
ITEM_INFO_SIGNATURE
};
static CONST WORD NegativeItemInfo[] =
{
IDS_NEGATIVE_PRINT, TVITEM_LEVEL2, DMPUB_NONE,
NEGATIVE_ITEM, HELP_INDEX_NEGATIVE,
2, TVOT_2STATES,
IDS_CPSUI_YES, IDI_CPSUI_YES,
IDS_CPSUI_NO, IDI_CPSUI_NO,
ITEM_INFO_SIGNATURE
};
static CONST WORD CompressBmpItemInfo[] =
{
IDS_COMPRESSBMP, TVITEM_LEVEL2, DMPUB_NONE,
COMPRESSBMP_ITEM, HELP_INDEX_COMPRESSBMP,
2, TVOT_2STATES,
IDS_CPSUI_YES, IDI_CPSUI_YES,
IDS_CPSUI_NO, IDI_CPSUI_NO,
ITEM_INFO_SIGNATURE
};
BOOL
_BPackDocumentOptions(
IN OUT PUIDATA pUiData
)
/*++
Routine Description:
Pack PostScript specific options such as Job Control etc.
Arguments:
pUiData - Points to UIDATA structure
Return Value:
TRUE for success and FALSE for failure
--*/
{
POPTITEM pOptItem;
PPSDRVEXTRA pdmPrivate;
DWORD dwFlags;
pdmPrivate = pUiData->ci.pdmPrivate;
dwFlags = pdmPrivate->dwFlags;
pOptItem = pUiData->pOptItem;
VPackOptItemGroupHeader(pUiData,
IDS_PSOPTIONS,
IDI_CPSUI_POSTSCRIPT,
HELP_INDEX_PSOPTIONS);
if (pOptItem)
pOptItem->Flags |= OPTIF_COLLAPSE;
return BPackItemPSOutputOption(pUiData, pdmPrivate) &&
BPackItemTTDownloadFormat(pUiData, pdmPrivate) &&
BPackItemPSLevel(pUiData, pdmPrivate) &&
BPackOptItemTemplate(
pUiData,
EHandlerItemInfo,
(dwFlags & PSDEVMODE_EHANDLER) ? 0 : 1, NULL) &&
(pUiData->ci.pUIInfo->dwLangLevel > 1 ||
BPackOptItemTemplate(
pUiData,
CompressBmpItemInfo,
(dwFlags & PSDEVMODE_COMPRESSBMP) ? 0 : 1, NULL)) &&
BPackOptItemTemplate(
pUiData,
MirrorItemInfo,
(dwFlags & PSDEVMODE_MIRROR) ? 0 : 1, NULL) &&
(IS_COLOR_DEVICE(pUiData->ci.pUIInfo) ||
BPackOptItemTemplate(
pUiData,
NegativeItemInfo,
(dwFlags & PSDEVMODE_NEG) ? 0 : 1, NULL));
}
VOID
_VUnpackDocumentOptions(
POPTITEM pOptItem,
PDEVMODE pdm
)
/*++
Routine Description:
Extract Postscript devmode information from an OPTITEM
Stored it back into Postscript devmode.
Arguments:
pOptItem - Pointer to an OPTITEM
pdm - Pointer to Postscript DEVMODE structure
Return Value:
None
--*/
{
PPSDRVEXTRA pdmPrivate;
pdmPrivate = (PPSDRVEXTRA) GET_DRIVER_PRIVATE_DEVMODE(pdm);
switch (GETUSERDATAITEM(pOptItem->UserData))
{
case ORIENTATION_ITEM:
pdm->dmFields |= DM_ORIENTATION;
pdm->dmOrientation = (pOptItem->Sel == 0) ?
DMORIENT_PORTRAIT :
DMORIENT_LANDSCAPE;
if (pOptItem->Sel != 2)
pdmPrivate->dwFlags &= ~PSDEVMODE_LSROTATE;
else
pdmPrivate->dwFlags |= PSDEVMODE_LSROTATE;
break;
case PSOUTPUT_OPTION_ITEM:
switch (pOptItem->Sel)
{
case 1:
pdmPrivate->iDialect = PORTABILITY;
break;
case 2:
pdmPrivate->iDialect = EPS;
break;
case 3:
pdmPrivate->iDialect = ARCHIVE;
break;
case 0:
default:
pdmPrivate->iDialect = SPEED;
break;
}
break;
case PSTT_DLFORMAT_ITEM:
switch (pOptItem->Sel)
{
case 1:
pdmPrivate->iTTDLFmt = TYPE_1;
break;
case 2:
pdmPrivate->iTTDLFmt = TYPE_3;
break;
case 3:
pdmPrivate->iTTDLFmt = TYPE_42;
break;
case 0:
default:
pdmPrivate->iTTDLFmt = TT_DEFAULT;
break;
}
break;
case PSLEVEL_ITEM:
pdmPrivate->iPSLevel = pOptItem->Sel;
break;
case PSERROR_HANDLER_ITEM:
if (pOptItem->Sel == 0)
pdmPrivate->dwFlags |= PSDEVMODE_EHANDLER;
else
pdmPrivate->dwFlags &= ~PSDEVMODE_EHANDLER;
break;
case PSHALFTONE_FREQ_ITEM:
case PSHALFTONE_ANGLE_ITEM:
// DCR - not implemented yet
break;
case MIRROR_ITEM:
if (pOptItem->Sel == 0)
pdmPrivate->dwFlags |= PSDEVMODE_MIRROR;
else
pdmPrivate->dwFlags &= ~PSDEVMODE_MIRROR;
break;
case NEGATIVE_ITEM:
if (pOptItem->Sel == 0)
pdmPrivate->dwFlags |= PSDEVMODE_NEG;
else
pdmPrivate->dwFlags &= ~PSDEVMODE_NEG;
break;
case COMPRESSBMP_ITEM:
if (pOptItem->Sel == 0)
pdmPrivate->dwFlags |= PSDEVMODE_COMPRESSBMP;
else
pdmPrivate->dwFlags &= ~PSDEVMODE_COMPRESSBMP;
break;
}
}
static CONST WORD IgnoreDevFontItemInfo[] =
{
IDS_USE_DEVFONTS, TVITEM_LEVEL1, DMPUB_NONE,
IGNORE_DEVFONT_ITEM, HELP_INDEX_IGNORE_DEVFONT,
2, TVOT_2STATES,
IDS_CPSUI_YES, IDI_CPSUI_YES,
IDS_CPSUI_NO, IDI_CPSUI_NO,
ITEM_INFO_SIGNATURE
};
BOOL
_BPackFontSubstItems(
IN OUT PUIDATA pUiData
)
/*++
Routine Description:
Pack font substitution related items (printer-sticky)
Arguments:
pUiData - Points to UIDATA structure
Return Value:
TRUE if successful, FALSE if there is an error
--*/
{
BOOL bNoDeviceFont;
bNoDeviceFont = (pUiData->ci.pPrinterData->dwFlags & PFLAGS_IGNORE_DEVFONT);
//
// On non-1252 code page systems, gives user the option
// to disable all device fonts
//
// Note: On non-1252 CodePage systems (Cs-Ct-Ja-Ko & Cyr-Grk-Tur, etc),
// PScript NT4 had difficulty mapping printer font Encodings to GDI strings.
// AdobePS5/PScript5 is supposed to handle these correctly. So Adobe wants
// this choice to be suppressed on all code pages.
//
// Fix MS bug #121883, Adobe bug #235417
//
if (FALSE && GetACP() != 1252 &&
!BPackOptItemTemplate(pUiData, IgnoreDevFontItemInfo, bNoDeviceFont ? 1 : 0, NULL))
{
return FALSE;
}
//
// Don't display the font substitution table if device font is disabled
//
if (bNoDeviceFont)
return TRUE;
return BPackItemFontSubstTable(pUiData);
}
static CONST WORD ProtocolItemInfo[] =
{
IDS_PSPROTOCOL, TVITEM_LEVEL1, DMPUB_NONE,
PSPROTOCOL_ITEM, HELP_INDEX_PSPROTOCOL,
4, TVOT_LISTBOX,
IDS_PSPROTOCOL_ASCII, IDI_PSPROTOCOL,
IDS_PSPROTOCOL_BCP, IDI_PSPROTOCOL,
IDS_PSPROTOCOL_TBCP, IDI_PSPROTOCOL,
IDS_PSPROTOCOL_BINARY, IDI_PSPROTOCOL,
ITEM_INFO_SIGNATURE
};
BOOL
BPackPSProtocolItem(
IN OUT PUIDATA pUiData
)
/*++
Routine Description:
Pack PostScript communication protocol item
Arguments:
pUiData - Points to UIDATA structure
Return Value:
TRUE if successful, FALSE if there is an error
--*/
{
DWORD dwSel;
POPTITEM pOptItem;
POPTPARAM pOptParam;
PUIINFO pUIInfo;
pOptItem = pUiData->pOptItem;
if (! BPackOptItemTemplate(pUiData, ProtocolItemInfo, 0, NULL))
return FALSE;
if (pOptItem)
{
//
// Hide those selections which are not supported on the printer
//
pOptParam = pOptItem->pOptType->pOptParam;
pUIInfo = pUiData->ci.pUIInfo;
if (! (pUIInfo->dwProtocols & PROTOCOL_BCP))
pOptParam[1].Flags |= OPTPF_HIDE;
if (! (pUIInfo->dwProtocols & PROTOCOL_TBCP))
pOptParam[2].Flags |= OPTPF_HIDE;
if (! (pUIInfo->dwProtocols & PROTOCOL_BINARY))
pOptParam[3].Flags |= OPTPF_HIDE;
switch (pUiData->ci.pPrinterData->wProtocol)
{
case PROTOCOL_BCP:
dwSel = 1;
break;
case PROTOCOL_TBCP:
dwSel = 2;
break;
case PROTOCOL_BINARY:
dwSel = 3;
break;
default:
dwSel = 0;
break;
}
if (pOptParam[dwSel].Flags & OPTPF_HIDE)
pOptItem->Sel = 0;
else
pOptItem->Sel = dwSel;
}
return TRUE;
}
//
// We will use different lower limit for Printer VM
// based on printer level. The 10th element of this
// ItemInfo must be filled with correct lower limit
// number before begin used.
//
static WORD PrinterVMItemInfo[] =
{
IDS_POSTSCRIPT_VM, TVITEM_LEVEL1, DMPUB_NONE,
PRINTER_VM_ITEM, HELP_INDEX_PRINTER_VM,
2, TVOT_UDARROW,
IDS_KBYTES, IDI_CPSUI_MEM,
0, 0,
ITEM_INFO_SIGNATURE
};
static CONST WORD JobTimeoutItemInfo[] =
{
IDS_JOBTIMEOUT, TVITEM_LEVEL1, DMPUB_NONE,
JOB_TIMEOUT_ITEM, HELP_INDEX_JOB_TIMEOUT,
2, TVOT_UDARROW,
IDS_SECONDS, IDI_USE_DEFAULT,
0, 0,
ITEM_INFO_SIGNATURE
};
static CONST WORD WaitTimeoutItemInfo[] =
{
IDS_WAITTIMEOUT, TVITEM_LEVEL1, DMPUB_NONE,
WAIT_TIMEOUT_ITEM, HELP_INDEX_WAIT_TIMEOUT,
2, TVOT_UDARROW,
IDS_SECONDS, IDI_USE_DEFAULT,
0, 0,
ITEM_INFO_SIGNATURE
};
static CONST WORD CtrlDBeforeItemInfo[] =
{
IDS_CTRLD_BEFORE, TVITEM_LEVEL1, DMPUB_NONE,
CTRLD_BEFORE_ITEM, HELP_INDEX_CTRLD_BEFORE,
2, TVOT_2STATES,
IDS_CPSUI_YES, IDI_CPSUI_YES,
IDS_CPSUI_NO, IDI_CPSUI_NO,
ITEM_INFO_SIGNATURE
};
static CONST WORD CtrlDAfterItemInfo[] =
{
IDS_CTRLD_AFTER, TVITEM_LEVEL1, DMPUB_NONE,
CTRLD_AFTER_ITEM, HELP_INDEX_CTRLD_AFTER,
2, TVOT_2STATES,
IDS_CPSUI_YES, IDI_CPSUI_YES,
IDS_CPSUI_NO, IDI_CPSUI_NO,
ITEM_INFO_SIGNATURE
};
static CONST WORD TrueGrayTextItemInfo[] =
{
IDS_TRUE_GRAY_TEXT, TVITEM_LEVEL1, DMPUB_NONE,
TRUE_GRAY_TEXT_ITEM, HELP_INDEX_TRUE_GRAY_TEXT,
2, TVOT_2STATES,
IDS_CPSUI_YES, IDI_CPSUI_YES,
IDS_CPSUI_NO, IDI_CPSUI_NO,
ITEM_INFO_SIGNATURE
};
static CONST WORD TrueGrayGraphItemInfo[] =
{
IDS_TRUE_GRAY_GRAPH, TVITEM_LEVEL1, DMPUB_NONE,
TRUE_GRAY_GRAPH_ITEM, HELP_INDEX_TRUE_GRAY_GRAPH,
2, TVOT_2STATES,
IDS_CPSUI_YES, IDI_CPSUI_YES,
IDS_CPSUI_NO, IDI_CPSUI_NO,
ITEM_INFO_SIGNATURE
};
static CONST WORD AddEuroItemInfo[] =
{
IDS_ADD_EURO, TVITEM_LEVEL1, DMPUB_NONE,
ADD_EURO_ITEM, HELP_INDEX_ADD_EURO,
2, TVOT_2STATES,
IDS_CPSUI_YES, IDI_CPSUI_YES,
IDS_CPSUI_NO, IDI_CPSUI_NO,
ITEM_INFO_SIGNATURE
};
static CONST WORD MinOutlineItemInfo[] =
{
IDS_PSMINOUTLINE, TVITEM_LEVEL1, DMPUB_NONE,
PSMINOUTLINE_ITEM, HELP_INDEX_PSMINOUTLINE,
2, TVOT_UDARROW,
IDS_PIXELS, IDI_USE_DEFAULT,
0, 0,
ITEM_INFO_SIGNATURE
};
static CONST WORD MaxBitmapItemInfo[] =
{
IDS_PSMAXBITMAP, TVITEM_LEVEL1, DMPUB_NONE,
PSMAXBITMAP_ITEM, HELP_INDEX_PSMAXBITMAP,
2, TVOT_UDARROW,
IDS_PIXELS, IDI_USE_DEFAULT,
0, 0,
ITEM_INFO_SIGNATURE
};
BOOL
_BPackPrinterOptions(
IN OUT PUIDATA pUiData
)
/*++
Routine Description:
Pack driver-specific options (printer-sticky)
Arguments:
pUiData - Points to a UIDATA structure
Return Value:
TRUE for success and FALSE for failure
--*/
{
PPRINTERDATA pPrinterData = pUiData->ci.pPrinterData;
BOOL rc;
//
// Fill in the lower limit number of PrinterVMItemInfo
// based on printer level.
//
PrinterVMItemInfo[10] = (pUiData->ci.pUIInfo->dwLangLevel <= 1 ? MIN_FREEMEM_L1 : MIN_FREEMEM_L2) / KBYTES;
rc = BPackUDArrowItemTemplate(
pUiData,
PrinterVMItemInfo,
pPrinterData->dwFreeMem / KBYTES,
0x7fff, NULL) &&
BPackPSProtocolItem(pUiData) &&
BPackOptItemTemplate(
pUiData,
CtrlDBeforeItemInfo,
(pPrinterData->dwFlags & PFLAGS_CTRLD_BEFORE) ? 0 : 1, NULL) &&
BPackOptItemTemplate(
pUiData,
CtrlDAfterItemInfo,
(pPrinterData->dwFlags & PFLAGS_CTRLD_AFTER) ? 0 : 1, NULL) &&
BPackOptItemTemplate(
pUiData,
TrueGrayTextItemInfo,
(pPrinterData->dwFlags & PFLAGS_TRUE_GRAY_TEXT) ? 0 : 1, NULL) &&
BPackOptItemTemplate(
pUiData,
TrueGrayGraphItemInfo,
(pPrinterData->dwFlags & PFLAGS_TRUE_GRAY_GRAPH) ? 0 : 1, NULL);
if (!rc)
return FALSE;
if (pUiData->ci.pUIInfo->dwLangLevel > 1)
{
rc = BPackOptItemTemplate(
pUiData,
AddEuroItemInfo,
(pPrinterData->dwFlags & PFLAGS_ADD_EURO) ? 0 : 1, NULL);
if (!rc)
return FALSE;
}
return BPackUDArrowItemTemplate(
pUiData,
JobTimeoutItemInfo,
pPrinterData->dwJobTimeout,
0x7fff, NULL) &&
BPackUDArrowItemTemplate(
pUiData,
WaitTimeoutItemInfo,
pPrinterData->dwWaitTimeout,
0x7fff, NULL) &&
BPackUDArrowItemTemplate(
pUiData,
MinOutlineItemInfo,
pPrinterData->wMinoutlinePPEM,
0x7fff, NULL) &&
BPackUDArrowItemTemplate(
pUiData,
MaxBitmapItemInfo,
pPrinterData->wMaxbitmapPPEM,
0x7fff, NULL);
}
VOID
_VUnpackDriverPrnPropItem(
PUIDATA pUiData,
POPTITEM pOptItem
)
/*++
Routine Description:
Unpack driver-specific printer property items
Arguments:
pUiData - Points to our UIDATA structure
pOptItem - Specifies the OPTITEM to be unpacked
Return Value:
NONE
--*/
{
PPRINTERDATA pPrinterData = pUiData->ci.pPrinterData;
switch (GETUSERDATAITEM(pOptItem->UserData))
{
case PRINTER_VM_ITEM:
if (pUiData->ci.dwFlags & FLAG_USER_CHANGED_FREEMEM)
{
pPrinterData->dwFreeMem = pOptItem->Sel * KBYTES;
}
break;
case PSPROTOCOL_ITEM:
switch (pOptItem->Sel)
{
case 1:
pPrinterData->wProtocol = PROTOCOL_BCP;
break;
case 2:
pPrinterData->wProtocol = PROTOCOL_TBCP;
break;
case 3:
pPrinterData->wProtocol = PROTOCOL_BINARY;
break;
default:
pPrinterData->wProtocol = PROTOCOL_ASCII;
break;
}
break;
case CTRLD_BEFORE_ITEM:
if (pOptItem->Sel == 0)
pPrinterData->dwFlags |= PFLAGS_CTRLD_BEFORE;
else
pPrinterData->dwFlags &= ~PFLAGS_CTRLD_BEFORE;
break;
case CTRLD_AFTER_ITEM:
if (pOptItem->Sel == 0)
pPrinterData->dwFlags |= PFLAGS_CTRLD_AFTER;
else
pPrinterData->dwFlags &= ~PFLAGS_CTRLD_AFTER;
break;
case TRUE_GRAY_TEXT_ITEM:
if (pOptItem->Sel == 0)
pPrinterData->dwFlags |= PFLAGS_TRUE_GRAY_TEXT;
else
pPrinterData->dwFlags &= ~PFLAGS_TRUE_GRAY_TEXT;
break;
case TRUE_GRAY_GRAPH_ITEM:
if (pOptItem->Sel == 0)
pPrinterData->dwFlags |= PFLAGS_TRUE_GRAY_GRAPH;
else
pPrinterData->dwFlags &= ~PFLAGS_TRUE_GRAY_GRAPH;
break;
case ADD_EURO_ITEM:
if (pOptItem->Sel == 0)
pPrinterData->dwFlags |= PFLAGS_ADD_EURO;
else
pPrinterData->dwFlags &= ~PFLAGS_ADD_EURO;
pPrinterData->dwFlags |= PFLAGS_EURO_SET;
break;
case PSMINOUTLINE_ITEM:
pPrinterData->wMinoutlinePPEM = (WORD) pOptItem->Sel;
break;
case PSMAXBITMAP_ITEM:
pPrinterData->wMaxbitmapPPEM = (WORD) pOptItem->Sel;
break;
}
}
BOOL
BUpdateModelNtfFilename(
PCOMMONINFO pci
)
/*++
Routine Description:
Save model-specific NTF filename under PrinterDriverData registry key
for compatibility with the new NT4 driver.
Arguments:
pci - Points to basic printer information
Return Value:
TRUE if successful, FALSE if there is an error
--*/
{
//
// Get the list of driver dependent files and
// save it in registry for NT4 compatibility
//
PTSTR ptstr, ptstrNext, ptstrDependentFiles, ptstrCopy, ptstrFileNamesWithoutPath;
DWORD dwCharCount = 0;
BOOL bResult;
if ((ptstrDependentFiles = pci->pDriverInfo3->pDependentFiles) == NULL)
{
return BSetPrinterDataString(pci->hPrinter,
REGVAL_DEPFILES,
ptstrDependentFiles,
REG_MULTI_SZ);
}
//
// First pass of the MULTI_SZ string to get file names char count
//
while (*ptstrDependentFiles != NUL)
{
//
// Go the end of current string
//
ptstr = ptstrDependentFiles + _tcslen(ptstrDependentFiles);
ptstrNext = ptstr + 1;
dwCharCount++; // for the NUL char of current string
//
// Search backward for '\' path separator
//
while (--ptstr >= ptstrDependentFiles)
{
if (*ptstr == TEXT(PATH_SEPARATOR))
{
break;
}
dwCharCount++;
}
ptstrDependentFiles = ptstrNext;
}
dwCharCount++; // for the last NUL of the MULTI_SZ string
if ((ptstrFileNamesWithoutPath = MemAllocZ(dwCharCount * sizeof(TCHAR))) == NULL)
{
ERR(("Memory allocation failed\n"));
return FALSE;
}
//
// Second pass of the MULTI_SZ string to copy the file names
//
ptstrDependentFiles = pci->pDriverInfo3->pDependentFiles;
ptstrCopy = ptstrFileNamesWithoutPath;
while (*ptstrDependentFiles != NUL)
{
INT iNameLen;
//
// Go the end of current string
//
ptstr = ptstrDependentFiles + _tcslen(ptstrDependentFiles);
ptstrNext = ptstr + 1;
//
// Search backward for '\' path separator
//
while (--ptstr >= ptstrDependentFiles)
{
if (*ptstr == TEXT(PATH_SEPARATOR))
{
break;
}
}
ptstr++; // point to the char after '\'
iNameLen = _tcslen(ptstr);
CopyMemory(ptstrCopy, ptstr, iNameLen * sizeof(TCHAR));
ptstrCopy += iNameLen + 1;
ptstrDependentFiles = ptstrNext;
}
bResult = BSetPrinterDataString(pci->hPrinter,
REGVAL_DEPFILES,
ptstrFileNamesWithoutPath,
REG_MULTI_SZ);
MemFree(ptstrFileNamesWithoutPath);
return bResult;
}
#ifdef WINNT_40
BOOL
BUpdateVMErrorMessageID(
PCOMMONINFO pci
)
/*++
Routine Description:
Save the VM Error message ID calculated from the current user's locale
under PrinterDriverData registry key.
Arguments:
pci - Points to basic printer information
Return Value:
TRUE if successful, FALSE if there is an error
--*/
{
DWORD dwVMErrorMessageID = DWGetVMErrorMessageID();
return BSetPrinterDataDWord(pci->hPrinter,
REGVAL_VMERRORMESSAGEID,
dwVMErrorMessageID);
}
#endif // WINNT_40
INT
_IListDevFontNames(
HDC hdc,
PWSTR pwstrBuf,
INT iSize
)
{
DWORD dwParam = QUERY_FAMILYNAME;
//
// Ask the driver graphics module for the list of permanant device fonts
//
return ExtEscape(hdc,
DRIVERESC_QUERY_DEVFONTS,
sizeof(dwParam),
(PCSTR) &dwParam,
iSize,
(PSTR) pwstrBuf);
}
INT_PTR CALLBACK
_AboutDlgProc(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam
)
/*++
Routine Description:
Procedure for handling "Printer Properties" proerty sheet page
Arguments:
hDlg - Identifies the property sheet page
message - Specifies the message
wParam - Specifies additional message-specific information
lParam - Specifies additional message-specific information
Return Value:
Depends on the value of message parameter
--*/
{
PUIDATA pUiData;
PWSTR pPpdFilename;
CHAR achBuf[64] = {0};
CHAR achMsg[136] = {0};
PPDDATA *pPpdData;
switch (message)
{
case WM_INITDIALOG:
//
// Initialize the About dialog box
//
pUiData = (PUIDATA) lParam;
ASSERT(VALIDUIDATA(pUiData));
if (LoadStringA(ghInstance, IDS_PS_VERSION, achBuf, sizeof(achBuf) - 1))
{
#ifdef WINNT_40
if (FAILED(StringCchPrintfA(achMsg,
CCHOF(achMsg),
"%s (" VER_54DRIVERVERSION_STR ")",
achBuf)))
#else // WINNT_40
if (FAILED(StringCchPrintfA(achMsg,
CCHOF(achMsg),
"%s (" VER_PRODUCTVERSION_STR ")",
achBuf)))
#endif // WINNT_40
{
WARNING(("Device Settings About box version string truncated.\n"));
}
}
else
{
WARNING(("Device Setting About box attempt to load version string failed.\n"));
}
SetDlgItemTextA(hDlg, IDC_WINNT_VER, achMsg);
SetDlgItemText(hDlg, IDC_MODELNAME, pUiData->ci.pDriverInfo3->pName);
if (pPpdFilename = pUiData->ci.pDriverInfo3->pDataFile)
{
if (pPpdFilename = wcsrchr(pPpdFilename, TEXT(PATH_SEPARATOR)))
pPpdFilename++;
else
pPpdFilename = pUiData->ci.pDriverInfo3->pDataFile;
SetDlgItemText(hDlg, IDC_PPD_FILENAME, pPpdFilename);
pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER(pUiData->ci.pInfoHeader);
ASSERT(pPpdData != NULL);
StringCchPrintfA(achBuf,
CCHOF(achBuf),
"%d.%d",
HIWORD(pPpdData->dwPpdFilever), LOWORD(pPpdData->dwPpdFilever));
SetDlgItemTextA(hDlg, IDC_PPD_FILEVER, achBuf);
}
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
//
// Determine whether the printer supports stapling
//
BOOL
_BSupportStapling(
PCOMMONINFO pci
)
{
PFEATURE pFeature, pFeatureY;
DWORD dwIndex;
BOOL bStapleFeatureExist = FALSE;
//
// Except for *StapleOrientation (whose None option doesn't mean stapling off),
// if any of following stapling keywords appear in the PPD file, we check if that
// feature is supported with current installable option selections.
//
// *StapleLocation
// *StapleX
// *StapleY
// *StapleWhen
//
// PPD spec says that a PPD file can contain either *StapleLocation or
// *StapleX and *StapleY but not both.
//
if (pFeature = PGetNamedFeature(pci->pUIInfo, "StapleLocation", &dwIndex))
{
bStapleFeatureExist = TRUE;
if (!_BSupportFeature(pci, GID_UNKNOWN, pFeature))
{
return FALSE;
}
}
else if ( (pFeature = PGetNamedFeature(pci->pUIInfo, "StapleX", &dwIndex)) &&
(pFeatureY = PGetNamedFeature(pci->pUIInfo, "StapleY", &dwIndex)) )
{
bStapleFeatureExist = TRUE;
if (!_BSupportFeature(pci, GID_UNKNOWN, pFeature) ||
!_BSupportFeature(pci, GID_UNKNOWN, pFeatureY))
{
return FALSE;
}
}
if (pFeature = PGetNamedFeature(pci->pUIInfo, "StapleWhen", &dwIndex))
{
bStapleFeatureExist = TRUE;
if (!_BSupportFeature(pci, GID_UNKNOWN, pFeature))
{
return FALSE;
}
}
//
// We didn't find any constraints on the stapling features caused by installable options,
// so we will assume the printer can support stapling if any of the standard PPD stapling
// keywords are present.
//
return bStapleFeatureExist ||
PGetNamedFeature(pci->pUIInfo, "StapleOrientation", &dwIndex) != NULL;
}
BOOL
BFeatureIsConstrained(
PUIINFO pUIInfo,
PFEATURE pFeature,
DWORD dwFeatureIndex,
DWORD dwOptionCount,
DWORD dwConstraintList,
PBYTE aubConstrainedOption,
DWORD dwGid
)
/*++
Routine Description:
Determine whether the particular constraint list constrains feature options.
Arguments:
pUIInfo - Points to a UIINFO structure
pFeature - Points to feature structure to be checked whether constraint or not
dwFeatureIndex - index for the feature
dwOptionCount - number of options for the feature
dwConstraintList - Specifies the constraint list to be searched
aubConstrainedOption - Byte array of option constrained flag
dwGid - GID_DUPLEX, GID_COLLATE or GID_UNKNOWN to allow feature specific don't cares
Return Value:
TRUE if the feature is constrained by the constraint list, FALSE otherwise.
--*/
{
POPTION pOption;
DWORD dwOptionIndex;
ASSERT(dwOptionCount < MAX_PRINTER_OPTIONS);
if (dwConstraintList == NULL_CONSTRAINT)
return FALSE;
for (dwOptionIndex = 0; dwOptionIndex < dwOptionCount; dwOptionIndex++)
{
pOption = PGetIndexedOption(pUIInfo, pFeature, dwOptionIndex);
ASSERT(pOption != NULL);
switch(dwGid)
{
case GID_COLLATE:
//
// don't care about constraints for no-collate
//
if (((PCOLLATE) pOption)->dwCollateID == DMCOLLATE_FALSE)
continue;
break;
case GID_DUPLEX:
//
// don't care about constraints for non-duplex
//
if (((PDUPLEX) pOption)->dwDuplexID == DMDUP_SIMPLEX)
continue;
break;
case GID_UNKNOWN:
default:
//
// skip the check for None/False option
//
if (pFeature->dwNoneFalseOptIndex == dwOptionIndex)
continue;
break;
}
if (BSearchConstraintList(pUIInfo, dwConstraintList,
dwFeatureIndex, dwOptionIndex))
{
aubConstrainedOption[dwOptionIndex] = 1;
}
//
// If one option is unconstrained, the feature is not constrained by the
// constraint list
//
if (!aubConstrainedOption[dwOptionIndex])
return FALSE;
}
return TRUE;
}
BOOL
_BSupportFeature(
PCOMMONINFO pci,
DWORD dwGid,
PFEATURE pFeatureIn
)
/*++
Routine Description:
Determine whether the printer supports a feature based on current printer-sticky
feature selections.
Arguments:
pci - Points to basic printer information
dwGid - the GID of the feature to check for constraints. (currently only GID_COLLATE or GID_DUPLEX
if pFeatureIn is NULL)
pFeatureIn - pointer to the feature structure if the feature doesn't have predefined GID_xxx value
Return Value:
TRUE if feature can be supported, FALSE otherwise.
--*/
{
POPTSELECT pCombinedOptions = pci->pCombinedOptions;
PUIINFO pUIInfo = pci->pUIInfo;
PFEATURE pCheckFeature, pFeature;
POPTION pOption;
BYTE aubConstrainedOption[MAX_PRINTER_OPTIONS];
DWORD dwCheckFeatureIndex, dwCheckOptionCount;
DWORD dwFeatureIndex;
BYTE ubCurOptIndex, ubNext;
if (!pCombinedOptions)
return FALSE;
if (pFeatureIn)
{
//
// If the input feature pointer is provided, dwGid should be GID_UNKNOWN.
//
ASSERT(dwGid == GID_UNKNOWN);
pCheckFeature = pFeatureIn;
}
else
{
//
// If no input feature pointer, use dwGid to find the feature. dwGid should be
// either GID_DUPLEX or GID_COLLATE.
//
ASSERT((dwGid == GID_DUPLEX) || (dwGid == GID_COLLATE));
if (!(pCheckFeature = GET_PREDEFINED_FEATURE(pUIInfo, dwGid)))
return FALSE;
}
dwCheckFeatureIndex = GET_INDEX_FROM_FEATURE(pUIInfo, pCheckFeature);
dwCheckOptionCount = pCheckFeature->Options.dwCount;
//
// Mark all options of the checked feature as non-constrained.
//
memset(aubConstrainedOption, 0, sizeof(aubConstrainedOption));
//
// Scan the feature list to check if it will be constrained by current selections
//
if (!(pFeature = OFFSET_TO_POINTER(pUIInfo->pInfoHeader, pUIInfo->loFeatureList)))
return FALSE;
//
// We only care about printer-sticky features
//
pFeature += pUIInfo->dwDocumentFeatures;
for (dwFeatureIndex = pUIInfo->dwDocumentFeatures;
dwFeatureIndex < pUIInfo->dwDocumentFeatures + pUIInfo->dwPrinterFeatures;
dwFeatureIndex++, pFeature++)
{
//
// If the feature's current selection is not None/False, it may constrain the checked feature
//
if ((DWORD)pCombinedOptions[dwFeatureIndex].ubCurOptIndex != pFeature->dwNoneFalseOptIndex)
{
if (BFeatureIsConstrained(pUIInfo, pCheckFeature, dwCheckFeatureIndex, dwCheckOptionCount,
pFeature->dwUIConstraintList, aubConstrainedOption, dwGid))
return FALSE;
}
ubNext = (BYTE)dwFeatureIndex;
while (1)
{
ubCurOptIndex = pCombinedOptions[ubNext].ubCurOptIndex;
pOption = PGetIndexedOption(pUIInfo, pFeature, ubCurOptIndex == OPTION_INDEX_ANY ? 0 : ubCurOptIndex);
if (pOption && BFeatureIsConstrained(pUIInfo, pCheckFeature, dwCheckFeatureIndex, dwCheckOptionCount,
pOption->dwUIConstraintList, aubConstrainedOption, dwGid))
return FALSE;
if ((ubNext = pCombinedOptions[ubNext].ubNext) == NULL_OPTSELECT)
break;
}
}
//
// No constraints found, so the feature can be supported.
//
return TRUE;
}
VOID
VSyncRevPrintAndOutputOrder(
PUIDATA pUiData,
POPTITEM pCurItem
)
/*++
Routine Description:
For PostScript driver, PPD could have "*OpenUI *OutputOrder", which enables user to
select "Normal" or "Reverse" output order. In order to avoid spooler performing reverse
printing simulation, we will ssync up option selections between REVPRINT_ITEM and
"OutputOrder".
Arguments:
pUiData - Pointer to UIDATA structure
pCurItem - Pointer to currently selected option item. It will be non-NULL for
REVPRINT_ITEM, and will be NULL otherwise.
Return Value:
None.
--*/
{
PUIINFO pUIInfo;
PPPDDATA pPpdData;
PFEATURE pFeature;
POPTION pOption;
PCSTR pstrKeywordName;
POPTITEM pRevPrintItem, pOutputOrderItem;
BOOL bReverse;
ASSERT(VALIDUIDATA(pUiData));
pUIInfo = pUiData->ci.pUIInfo;
pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER((PINFOHEADER)pUiData->ci.pRawData);
ASSERT(pPpdData != NULL);
if (pPpdData->dwOutputOrderIndex != INVALID_FEATURE_INDEX &&
(pOutputOrderItem = PFindOptItemWithKeyword(pUiData, "OutputOrder")) &&
pOutputOrderItem->Sel < 2 &&
(pFeature = PGetIndexedFeature(pUIInfo, pPpdData->dwOutputOrderIndex)) &&
(pOption = PGetIndexedOption(pUIInfo, pFeature, pOutputOrderItem->Sel)) &&
(pstrKeywordName = OFFSET_TO_POINTER(pUIInfo->pubResourceData, pOption->loKeywordName)))
{
//
// "OutputOrder" feature is available.
//
if (strcmp(pstrKeywordName, "Reverse") == EQUAL_STRING)
bReverse = TRUE;
else
bReverse = FALSE;
if (pCurItem)
{
//
// Currently selected item is REVPRINT_ITEM. We should change "OutputOrder" option
// if needed to match the requested output order.
//
if ((pCurItem->Sel == 0 && bReverse) || (pCurItem->Sel == 1 && !bReverse))
{
pOutputOrderItem->Sel = 1 - pOutputOrderItem->Sel;
pOutputOrderItem->Flags |= OPTIF_CHANGED;
//
// Save the new settings in the options array
//
VUnpackDocumentPropertiesItems(pUiData, pOutputOrderItem, 1);
//
// The change could trigger constraints.
//
if (ICheckConstraintsDlg(pUiData, pOutputOrderItem, 1, FALSE) == CONFLICT_CANCEL)
{
//
// If there is a conflict and the user clicked CANCEL,
// we need to restore the origianl selection.
//
pCurItem->Sel = 1 - pCurItem->Sel;
pCurItem->Flags |= OPTIF_CHANGED;
VUnpackDocumentPropertiesItems(pUiData, pCurItem, 1);
pOutputOrderItem->Sel = 1 - pOutputOrderItem->Sel;
pOutputOrderItem->Flags |= OPTIF_CHANGED;
VUnpackDocumentPropertiesItems(pUiData, pOutputOrderItem, 1);
}
}
}
else
{
//
// Sync up REVPRINT_ITEM selection based on "OutputOrder" selection.
//
if ((pRevPrintItem = PFindOptItemWithUserData(pUiData, REVPRINT_ITEM)) &&
((pRevPrintItem->Sel == 0 && bReverse) || (pRevPrintItem->Sel == 1 && !bReverse)))
{
pRevPrintItem->Sel = 1 - pRevPrintItem->Sel;
pRevPrintItem->Flags |= OPTIF_CHANGED;
//
// Save the new settings in the options array
//
VUnpackDocumentPropertiesItems(pUiData, pRevPrintItem, 1);
}
}
}
}