3337 lines
81 KiB
C
3337 lines
81 KiB
C
/*++
|
||
|
||
Copyright (c) 1996 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
docprop.c
|
||
|
||
Abstract:
|
||
|
||
This file handles the DrvDocumentProperties and
|
||
DrvDocumentPropertySheets spooler API
|
||
|
||
Environment:
|
||
|
||
Win32 subsystem, DriverUI module, user mode
|
||
|
||
Revision History:
|
||
|
||
02/13/97 -davidx-
|
||
Implement OEM plugin support.
|
||
|
||
02/13/97 -davidx-
|
||
Working only with options array internally.
|
||
|
||
02/10/97 -davidx-
|
||
Consistent handling of common printer info.
|
||
|
||
02/04/97 -davidx-
|
||
Reorganize driver UI to separate ps and uni DLLs.
|
||
|
||
07/17/96 -amandan-
|
||
Created it.
|
||
|
||
--*/
|
||
|
||
#include "precomp.h"
|
||
|
||
//
|
||
// Local and external function declarations
|
||
//
|
||
|
||
LONG LSimpleDocumentProperties( PDOCUMENTPROPERTYHEADER);
|
||
CPSUICALLBACK cpcbDocumentPropertyCallback(PCPSUICBPARAM);
|
||
BOOL BGetPageOrderFlag(PCOMMONINFO);
|
||
VOID VUpdateEmfFeatureItems(PUIDATA, BOOL);
|
||
VOID VUpdateBookletOption(PUIDATA , POPTITEM);
|
||
|
||
LONG
|
||
DrvDocumentPropertySheets(
|
||
PPROPSHEETUI_INFO pPSUIInfo,
|
||
LPARAM lParam
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is called to add the Document Property Page to the specified
|
||
property sheets and/or to update the document properties.
|
||
|
||
If pPSUIInfo is NULL, it performs the operation specified by the fMode flag of
|
||
DOCUMENTPROPERTYHEADER. Specifically, if flMode is zero or pDPHdr->pdmOut
|
||
is NULL, return the size of DEVMODE.
|
||
|
||
If pPSUInfo is not NULL: pPSUIInf->Reason
|
||
|
||
REASON_INIT- fills PCOMPROPSHEETUI with document UI items
|
||
calls compstui to add the page.
|
||
|
||
REASON_GET_INFO_HEADER - fills out PROPSHEETUI_INFO.
|
||
|
||
REASON_SET_RESULT - saves devmode settings and copy the devmode into output buffer.
|
||
|
||
REASON_DESTROY - Cleans up.
|
||
|
||
Arguments:
|
||
|
||
pSUIInfo - pointer to PPROPSHEETUI_INFO
|
||
lParam - varies depending on the reason this function is called
|
||
|
||
|
||
Return Value:
|
||
|
||
> 0 success <= 0 for failure
|
||
|
||
--*/
|
||
|
||
{
|
||
PDOCUMENTPROPERTYHEADER pDPHdr;
|
||
PCOMPROPSHEETUI pCompstui;
|
||
PUIDATA pUiData;
|
||
PDLGPAGE pDlgPage;
|
||
LONG lRet;
|
||
BOOL bResult=FALSE;
|
||
|
||
//
|
||
// Validate input parameters
|
||
//
|
||
|
||
if (! (pDPHdr = (PDOCUMENTPROPERTYHEADER) (pPSUIInfo ? pPSUIInfo->lParamInit : lParam)))
|
||
{
|
||
RIP(("DrvDocumentPropertySheets: invalid parameters\n"));
|
||
return -1;
|
||
}
|
||
|
||
//
|
||
// pPSUIInfo = NULL, the caller is spooler so just handle the simple case,
|
||
// no display is necessary.
|
||
//
|
||
|
||
if (pPSUIInfo == NULL)
|
||
return LSimpleDocumentProperties(pDPHdr);
|
||
|
||
//
|
||
// Create a UIDATA structure if necessary
|
||
//
|
||
|
||
if (pPSUIInfo->Reason == PROPSHEETUI_REASON_INIT)
|
||
{
|
||
pUiData = PFillUiData(pDPHdr->hPrinter,
|
||
pDPHdr->pszPrinterName,
|
||
pDPHdr->pdmIn,
|
||
MODE_DOCUMENT_STICKY);
|
||
}
|
||
else
|
||
pUiData = (PUIDATA) pPSUIInfo->UserData;
|
||
|
||
//
|
||
// Validate pUiData
|
||
//
|
||
|
||
if (pUiData == NULL)
|
||
{
|
||
ERR(("UIDATA is NULL\n"));
|
||
return -1;
|
||
}
|
||
|
||
ASSERT(VALIDUIDATA(pUiData));
|
||
|
||
//
|
||
// Handle various cases for which this function might be called
|
||
//
|
||
|
||
switch (pPSUIInfo->Reason)
|
||
{
|
||
case PROPSHEETUI_REASON_INIT:
|
||
|
||
//
|
||
// Allocate memory and partially fill out various data
|
||
// structures required to call common UI routine.
|
||
//
|
||
|
||
pDlgPage = (pDPHdr->fMode & DM_ADVANCED) ?
|
||
CPSUI_PDLGPAGE_ADVDOCPROP :
|
||
CPSUI_PDLGPAGE_DOCPROP;
|
||
|
||
pUiData->bPermission = ((pDPHdr->fMode & DM_NOPERMISSION) == 0);
|
||
|
||
#ifdef PSCRIPT
|
||
|
||
FOREACH_OEMPLUGIN_LOOP((&(pUiData->ci)))
|
||
|
||
if (HAS_COM_INTERFACE(pOemEntry))
|
||
{
|
||
HRESULT hr;
|
||
|
||
hr = HComOEMHideStandardUI(pOemEntry,
|
||
OEMCUIP_DOCPROP);
|
||
|
||
//
|
||
// In the case when multiple plugins are chained, it doesn't
|
||
// make sense for one plugin to hide standard UI when another
|
||
// one still wants to use the standard UI. So as long as one
|
||
// plugin returns S_OK here, we will hide the standard UI.
|
||
//
|
||
|
||
if (bResult = SUCCEEDED(hr))
|
||
break;
|
||
}
|
||
|
||
END_OEMPLUGIN_LOOP
|
||
|
||
#endif // PSCRIPT
|
||
|
||
if (bResult)
|
||
{
|
||
//
|
||
// Set the flag to indicate plugin is hiding our standard
|
||
// document property sheet UI.
|
||
//
|
||
|
||
pUiData->dwHideFlags |= HIDEFLAG_HIDE_STD_DOCPROP;
|
||
|
||
pUiData->pfnComPropSheet = pPSUIInfo->pfnComPropSheet;
|
||
pUiData->hComPropSheet = pPSUIInfo->hComPropSheet;
|
||
|
||
if (BAddOemPluginPages(pUiData, pDPHdr->fMode))
|
||
{
|
||
pPSUIInfo->UserData = (ULONG_PTR) pUiData;
|
||
pPSUIInfo->Result = CPSUI_CANCEL;
|
||
lRet = 1;
|
||
break;
|
||
}
|
||
}
|
||
else if (pCompstui = PPrepareDataForCommonUI(pUiData, pDlgPage))
|
||
{
|
||
#ifdef UNIDRV
|
||
|
||
VMakeMacroSelections(pUiData, NULL);
|
||
|
||
#endif
|
||
|
||
pCompstui->pfnCallBack = cpcbDocumentPropertyCallback;
|
||
pUiData->pfnComPropSheet = pPSUIInfo->pfnComPropSheet;
|
||
pUiData->hComPropSheet = pPSUIInfo->hComPropSheet;
|
||
pUiData->pCompstui = pCompstui;
|
||
|
||
//
|
||
// Indicate which items are constrained
|
||
//
|
||
|
||
VPropShowConstraints(pUiData, MODE_DOCANDPRINTER_STICKY);
|
||
|
||
//
|
||
// Call common UI library to add our pages
|
||
//
|
||
|
||
if (pUiData->pfnComPropSheet(pUiData->hComPropSheet,
|
||
CPSFUNC_ADD_PCOMPROPSHEETUI,
|
||
(LPARAM) pCompstui,
|
||
(LPARAM) &lRet) &&
|
||
BAddOemPluginPages(pUiData, pDPHdr->fMode))
|
||
{
|
||
pPSUIInfo->UserData = (ULONG_PTR) pUiData;
|
||
pPSUIInfo->Result = CPSUI_CANCEL;
|
||
lRet = 1;
|
||
break;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Clean up in the case of error
|
||
//
|
||
|
||
ERR(("Failed to initialize property sheets\n"));
|
||
VFreeUiData(pUiData);
|
||
return -1;
|
||
|
||
case PROPSHEETUI_REASON_GET_INFO_HEADER:
|
||
{
|
||
PPROPSHEETUI_INFO_HEADER pPSUIHdr;
|
||
DWORD dwIcon;
|
||
|
||
pPSUIHdr = (PPROPSHEETUI_INFO_HEADER) lParam;
|
||
pPSUIHdr->Flags = PSUIHDRF_PROPTITLE | PSUIHDRF_NOAPPLYNOW;
|
||
pPSUIHdr->pTitle = pUiData->ci.pPrinterName;
|
||
pPSUIHdr->hInst = ghInstance;
|
||
|
||
//
|
||
// Use the Icon specified in the binary data as
|
||
// the printer icon.
|
||
//
|
||
|
||
dwIcon = pUiData->ci.pUIInfo->loPrinterIcon;
|
||
|
||
if (dwIcon && (pPSUIHdr->IconID = HLoadIconFromResourceDLL(&pUiData->ci, dwIcon)))
|
||
pPSUIHdr->Flags |= PSUIHDRF_USEHICON;
|
||
else
|
||
pPSUIHdr->IconID = _DwGetPrinterIconID();
|
||
}
|
||
|
||
lRet = 1;
|
||
break;
|
||
|
||
case PROPSHEETUI_REASON_SET_RESULT:
|
||
|
||
//
|
||
// Copy the new devmode back into the output buffer provided by the caller
|
||
// Always return the smaller of current and input devmode
|
||
//
|
||
|
||
{
|
||
PSETRESULT_INFO pSRInfo = (PSETRESULT_INFO) lParam;
|
||
|
||
if ((pSRInfo->Result == CPSUI_OK) &&
|
||
(pDPHdr->pdmOut != NULL) &&
|
||
(pDPHdr->fMode & (DM_COPY | DM_UPDATE)))
|
||
{
|
||
PCOMMONINFO pci = (PCOMMONINFO)pUiData;
|
||
|
||
//
|
||
// CPSUICB_REASON_APPLYNOW may not have been called. If so, we need
|
||
// to perform tasks that are usually done by CPSUICB_REASON_APPLYNOW
|
||
// case in our callback function cpcbDocumentPropertyCallback.
|
||
//
|
||
|
||
if (!(pci->dwFlags & FLAG_APPLYNOW_CALLED))
|
||
{
|
||
OPTSELECT OldCombinedOptions[MAX_COMBINED_OPTIONS];
|
||
|
||
//
|
||
// Save a copy the pre-resolve option array
|
||
//
|
||
|
||
CopyMemory(OldCombinedOptions,
|
||
pci->pCombinedOptions,
|
||
MAX_COMBINED_OPTIONS * sizeof(OPTSELECT));
|
||
|
||
//
|
||
// Call the parsers to resolve any remaining conflicts.
|
||
//
|
||
|
||
ResolveUIConflicts(pci->pRawData,
|
||
pci->pCombinedOptions,
|
||
MAX_COMBINED_OPTIONS,
|
||
MODE_DOCANDPRINTER_STICKY);
|
||
|
||
//
|
||
// Update the OPTITEM list to match the updated options array
|
||
//
|
||
|
||
VUpdateOptItemList(pUiData, OldCombinedOptions, pci->pCombinedOptions);
|
||
|
||
//
|
||
// Transfer information from options array to public devmode fields
|
||
//
|
||
|
||
VOptionsToDevmodeFields(&pUiData->ci, FALSE);
|
||
|
||
//
|
||
// Separate the doc-sticky options from the combined array
|
||
// and save it back to the private devmode aOptions array
|
||
//
|
||
|
||
SeparateOptionArray(
|
||
pci->pRawData,
|
||
pci->pCombinedOptions,
|
||
PGetDevmodeOptionsArray(pci->pdm),
|
||
MAX_PRINTER_OPTIONS,
|
||
MODE_DOCUMENT_STICKY);
|
||
}
|
||
|
||
BConvertDevmodeOut(pci->pdm,
|
||
pDPHdr->pdmIn,
|
||
pDPHdr->pdmOut);
|
||
}
|
||
|
||
pPSUIInfo->Result = pSRInfo->Result;
|
||
}
|
||
|
||
lRet = 1;
|
||
break;
|
||
|
||
case PROPSHEETUI_REASON_DESTROY:
|
||
|
||
//
|
||
// Clean up
|
||
//
|
||
|
||
VFreeUiData(pUiData);
|
||
lRet = 1;
|
||
|
||
break;
|
||
|
||
default:
|
||
|
||
ERR(("Unknown reason in DrvDocumentPropertySheets\n"));
|
||
return -1;
|
||
}
|
||
|
||
return lRet;
|
||
}
|
||
|
||
|
||
|
||
LONG
|
||
LSimpleDocumentProperties(
|
||
IN OUT PDOCUMENTPROPERTYHEADER pDPHdr
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Handle simple "Document Properties" where we don't need to display
|
||
a dialog and therefore don't have to have common UI library involved
|
||
Mainly, devmode handling - update, merge, copy etc.
|
||
|
||
Arguments:
|
||
|
||
pDPHdr - Points to a DOCUMENTPROPERTYHEADER structure
|
||
|
||
Return Value:
|
||
|
||
> 0 if successful, <= 0 otherwise
|
||
|
||
--*/
|
||
|
||
{
|
||
PCOMMONINFO pci;
|
||
DWORD dwSize;
|
||
PPRINTER_INFO_2 pPrinterInfo2;
|
||
|
||
//
|
||
// Load common printer info
|
||
//
|
||
|
||
pci = PLoadCommonInfo(pDPHdr->hPrinter, pDPHdr->pszPrinterName, 0);
|
||
|
||
if (!pci || !BCalcTotalOEMDMSize(pci->hPrinter, pci->pOemPlugins, &dwSize))
|
||
{
|
||
VFreeCommonInfo(pci);
|
||
return -1;
|
||
}
|
||
|
||
//
|
||
// Check if the caller is interested in the size only
|
||
//
|
||
|
||
pDPHdr->cbOut = sizeof(DEVMODE) + gDriverDMInfo.dmDriverExtra + dwSize;
|
||
|
||
if (pDPHdr->fMode == 0 || pDPHdr->pdmOut == NULL)
|
||
{
|
||
VFreeCommonInfo(pci);
|
||
return pDPHdr->cbOut;
|
||
}
|
||
|
||
//
|
||
// Merge the input devmode with the driver and system default devmodes
|
||
//
|
||
|
||
if (! (pPrinterInfo2 = MyGetPrinter(pci->hPrinter, 2)) ||
|
||
! BFillCommonInfoDevmode(pci, pPrinterInfo2->pDevMode, pDPHdr->pdmIn))
|
||
{
|
||
MemFree(pPrinterInfo2);
|
||
VFreeCommonInfo(pci);
|
||
return -1;
|
||
}
|
||
|
||
MemFree(pPrinterInfo2);
|
||
|
||
//
|
||
// Copy the devmode back into the output buffer provided by the caller
|
||
// Always return the smaller of current and input devmode
|
||
//
|
||
|
||
if (pDPHdr->fMode & (DM_COPY | DM_UPDATE))
|
||
(VOID) BConvertDevmodeOut(pci->pdm, pDPHdr->pdmIn, pDPHdr->pdmOut);
|
||
|
||
//
|
||
// Clean up before returning to caller
|
||
//
|
||
|
||
VFreeCommonInfo(pci);
|
||
return 1;
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
VRestoreDefaultFeatureSelection(
|
||
IN OUT PUIDATA pUiData
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Restore the printer feature selections to their default state
|
||
|
||
Arguments:
|
||
|
||
pUiData - Points to our UIDATA structure
|
||
|
||
Return Value:
|
||
|
||
NONE
|
||
|
||
--*/
|
||
|
||
{
|
||
POPTSELECT pOptionsArray;
|
||
PFEATURE pFeature;
|
||
POPTITEM pOptItem;
|
||
DWORD dwCount, dwFeatureIndex, dwDefault;
|
||
PUIINFO pUIInfo;
|
||
|
||
//
|
||
// Go through each printer feature item and check to see if
|
||
// its current selection matches the default value
|
||
//
|
||
|
||
pUIInfo = pUiData->ci.pUIInfo;
|
||
pOptionsArray = pUiData->ci.pCombinedOptions;
|
||
pOptItem = pUiData->pFeatureItems;
|
||
dwCount = pUiData->dwFeatureItem;
|
||
|
||
for ( ; dwCount--; pOptItem++)
|
||
{
|
||
pFeature = (PFEATURE) GETUSERDATAITEM(pOptItem->UserData);
|
||
dwFeatureIndex = GET_INDEX_FROM_FEATURE(pUIInfo, pFeature);
|
||
dwDefault = pFeature->dwDefaultOptIndex;
|
||
|
||
//
|
||
// If the current selection doesn't match the default,
|
||
// restore it to the default value.
|
||
//
|
||
|
||
if (pOptionsArray[dwFeatureIndex].ubCurOptIndex != dwDefault)
|
||
{
|
||
pOptionsArray[dwFeatureIndex].ubCurOptIndex = (BYTE) dwDefault;
|
||
pOptItem->Flags |= OPTIF_CHANGED;
|
||
pOptItem->Sel = (dwDefault == OPTION_INDEX_ANY) ? 0 : dwDefault;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Update the display and indicate which items are constrained
|
||
//
|
||
|
||
VPropShowConstraints(pUiData, MODE_DOCANDPRINTER_STICKY);
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
VOptionsToDevmodeFields(
|
||
IN OUT PCOMMONINFO pci,
|
||
IN BOOL bUpdateFormFields
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Convert options in pUiData->pOptionsArray into public devmode fields
|
||
|
||
Arguments:
|
||
|
||
pci - Points to basic printer info
|
||
bUpdateFormFields - Whether or not to convert paper size option into devmode
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
{
|
||
PFEATURE pFeature;
|
||
POPTION pOption;
|
||
DWORD dwGID, dwFeatureIndex, dwOptionIndex;
|
||
PUIINFO pUIInfo;
|
||
PDEVMODE pdm;
|
||
|
||
//
|
||
// Go through all predefine IDs and propage the option selection
|
||
// into appropriate devmode fields
|
||
//
|
||
|
||
pUIInfo = pci->pUIInfo;
|
||
pdm = pci->pdm;
|
||
|
||
for (dwGID=0 ; dwGID < MAX_GID ; dwGID++)
|
||
{
|
||
//
|
||
// Get the feature to get the options, and get the index
|
||
// into the option array
|
||
//
|
||
|
||
if ((pFeature = GET_PREDEFINED_FEATURE(pUIInfo, dwGID)) == NULL)
|
||
continue;
|
||
|
||
dwFeatureIndex = GET_INDEX_FROM_FEATURE(pUIInfo, pFeature);
|
||
dwOptionIndex = pci->pCombinedOptions[dwFeatureIndex].ubCurOptIndex;
|
||
|
||
//
|
||
// Get the pointer to the option array for the feature
|
||
//
|
||
|
||
if ((pOption = PGetIndexedOption(pUIInfo, pFeature, dwOptionIndex)) == NULL)
|
||
continue;
|
||
|
||
switch(dwGID)
|
||
{
|
||
case GID_RESOLUTION:
|
||
{
|
||
PRESOLUTION pRes = (PRESOLUTION)pOption;
|
||
|
||
//
|
||
// Get to the option selected
|
||
//
|
||
|
||
pdm->dmFields |= (DM_PRINTQUALITY|DM_YRESOLUTION);
|
||
pdm->dmPrintQuality = GETQUALITY_X(pRes);
|
||
pdm->dmYResolution = GETQUALITY_Y(pRes);
|
||
|
||
}
|
||
break;
|
||
|
||
case GID_DUPLEX:
|
||
|
||
//
|
||
// Get to the option selected
|
||
//
|
||
|
||
pdm->dmFields |= DM_DUPLEX;
|
||
pdm->dmDuplex = (SHORT) ((PDUPLEX) pOption)->dwDuplexID;
|
||
break;
|
||
|
||
case GID_INPUTSLOT:
|
||
|
||
//
|
||
// Get to the option selected
|
||
//
|
||
|
||
pdm->dmFields |= DM_DEFAULTSOURCE;
|
||
pdm->dmDefaultSource = (SHORT) ((PINPUTSLOT) pOption)->dwPaperSourceID;
|
||
break;
|
||
|
||
case GID_MEDIATYPE:
|
||
|
||
//
|
||
// Get to the option selected
|
||
//
|
||
|
||
pdm->dmFields |= DM_MEDIATYPE;
|
||
pdm->dmMediaType = (SHORT) ((PMEDIATYPE) pOption)->dwMediaTypeID;
|
||
break;
|
||
|
||
case GID_ORIENTATION:
|
||
|
||
if (((PORIENTATION) pOption)->dwRotationAngle == ROTATE_NONE)
|
||
pdm->dmOrientation = DMORIENT_PORTRAIT;
|
||
else
|
||
pdm->dmOrientation = DMORIENT_LANDSCAPE;
|
||
|
||
pdm->dmFields |= DM_ORIENTATION;
|
||
break;
|
||
|
||
//
|
||
// Fix #2822: VOptionsToDevmodeFields should be called after calling
|
||
// VFixOptionsArrayWithDevmode and ResolveUIConflicts, which could
|
||
// change option array to be out of sync with devmode.
|
||
//
|
||
|
||
case GID_COLLATE:
|
||
|
||
pdm->dmFields |= DM_COLLATE;
|
||
pdm->dmCollate = (SHORT) ((PCOLLATE) pOption)->dwCollateID;
|
||
break;
|
||
|
||
case GID_PAGESIZE:
|
||
{
|
||
PPAGESIZE pPageSize = (PPAGESIZE)pOption;
|
||
WCHAR awchBuf[CCHPAPERNAME];
|
||
|
||
//
|
||
// Ignore the custom page size option. We don't add custom page size option to the
|
||
// form database, see BAddOrUpgradePrinterForms(). Also see BQueryPrintForm() for
|
||
// special handling of custom page size for DDI DevQueryPrintEx().
|
||
//
|
||
|
||
if (pPageSize->dwPaperSizeID == DMPAPER_USER ||
|
||
pPageSize->dwPaperSizeID == DMPAPER_CUSTOMSIZE)
|
||
{
|
||
VERBOSE(("VOptionsToDevmodeFields: %d ignored\n", pPageSize->dwPaperSizeID));
|
||
break;
|
||
}
|
||
|
||
//
|
||
// bUpdateFormFields should be FALSE if we don't want to overwrite devmode form
|
||
// fields with our option array's page size setting. One case of this is when
|
||
// user hits the doc-setting UI's OK buttion, at that time we need to propagate
|
||
// our internal devmode to app's output devmode. See cpcbDocumentPropertyCallback().
|
||
// That's because in option array we could have already mapped devmode's form request
|
||
// to a paper size the printer supports (example: devmode requets Legal, we map
|
||
// it to the printer's form OEM_Legal). So we don't want to overwrite output devmode
|
||
// form fields with our internal option.
|
||
//
|
||
|
||
if (!bUpdateFormFields)
|
||
break;
|
||
|
||
if (!LOAD_STRING_PAGESIZE_NAME(pci, pPageSize, awchBuf, CCHPAPERNAME))
|
||
{
|
||
ERR(("VOptionsToDevmodeFields: cannot get paper name\n"));
|
||
break;
|
||
}
|
||
|
||
pdm->dmFields &= ~(DM_PAPERWIDTH|DM_PAPERLENGTH|DM_PAPERSIZE);
|
||
pdm->dmFields |= DM_FORMNAME;
|
||
|
||
CopyString(pdm->dmFormName, awchBuf, CCHFORMNAME);
|
||
|
||
if (!BValidateDevmodeFormFields(
|
||
pci->hPrinter,
|
||
pdm,
|
||
NULL,
|
||
pci->pSplForms,
|
||
pci->dwSplForms))
|
||
{
|
||
VDefaultDevmodeFormFields(pUIInfo, pdm, IsMetricCountry());
|
||
}
|
||
}
|
||
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
CPSUICALLBACK
|
||
cpcbDocumentPropertyCallback(
|
||
IN OUT PCPSUICBPARAM pCallbackParam
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Callback function provided to common UI DLL for handling
|
||
document properties dialog.
|
||
|
||
Arguments:
|
||
|
||
pCallbackParam - Pointer to CPSUICBPARAM structure
|
||
|
||
Return Value:
|
||
|
||
CPSUICB_ACTION_NONE - no action needed
|
||
CPSUICB_ACTION_OPTIF_CHANGED - items changed and should be refreshed
|
||
|
||
--*/
|
||
|
||
{
|
||
PUIDATA pUiData;
|
||
POPTITEM pCurItem, pOptItem;
|
||
LONG lRet;
|
||
PFEATURE pFeature;
|
||
|
||
pUiData = (PUIDATA) pCallbackParam->UserData;
|
||
ASSERT(pUiData != NULL);
|
||
|
||
pUiData->hDlg = pCallbackParam->hDlg;
|
||
pCurItem = pCallbackParam->pCurItem;
|
||
lRet = CPSUICB_ACTION_NONE;
|
||
|
||
//
|
||
// If user has no permission to change anything, then
|
||
// simply return without taking any action.
|
||
//
|
||
|
||
if (!HASPERMISSION(pUiData) && (pCallbackParam->Reason != CPSUICB_REASON_ABOUT))
|
||
return lRet;
|
||
|
||
switch (pCallbackParam->Reason)
|
||
{
|
||
case CPSUICB_REASON_SEL_CHANGED:
|
||
case CPSUICB_REASON_ECB_CHANGED:
|
||
|
||
if (! IS_DRIVER_OPTITEM(pUiData, pCurItem))
|
||
break;
|
||
|
||
//
|
||
// Everytime the user make any changes, we update the
|
||
// pOptionsArray. These settings are not saved to the devmode
|
||
// until the user hit OK.
|
||
//
|
||
// VUnpackDocumentPropertiesItems saves the settings to pUiData->pOptionsArray
|
||
// and update the private devmode flags if applicable.
|
||
// ICheckConstraintsDlg check if the user has selected a constrained option
|
||
//
|
||
|
||
VUnpackDocumentPropertiesItems(pUiData, pCurItem, 1);
|
||
|
||
#ifdef UNIDRV
|
||
|
||
VSyncColorInformation(pUiData, pCurItem);
|
||
|
||
//
|
||
// Quality Macro support
|
||
//
|
||
|
||
if (GETUSERDATAITEM(pCurItem->UserData) == QUALITY_SETTINGS_ITEM ||
|
||
GETUSERDATAITEM(pCurItem->UserData) == COLOR_ITEM ||
|
||
GETUSERDATAITEM(pCurItem->UserData) == MEDIATYPE_ITEM ||
|
||
((pFeature = PGetFeatureFromItem(pUiData->ci.pUIInfo, pCurItem, NULL))&&
|
||
pFeature->dwFlags & FEATURE_FLAG_UPDATESNAPSHOT))
|
||
{
|
||
VMakeMacroSelections(pUiData, pCurItem);
|
||
|
||
//
|
||
// Needs to update the constraints since Macro selection might have
|
||
// changed the constraints
|
||
//
|
||
|
||
VPropShowConstraints(pUiData, MODE_DOCANDPRINTER_STICKY);
|
||
VUpdateMacroSelection(pUiData, pCurItem);
|
||
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// Check whether the current selection invalidates the macros
|
||
// and update QUALITY_SETTINGS_ITEM.
|
||
|
||
VUpdateMacroSelection(pUiData, pCurItem);
|
||
}
|
||
|
||
#endif // UNIDRV
|
||
|
||
#ifdef PSCRIPT
|
||
|
||
if (GETUSERDATAITEM(pCurItem->UserData) == REVPRINT_ITEM)
|
||
{
|
||
VSyncRevPrintAndOutputOrder(pUiData, pCurItem);
|
||
}
|
||
|
||
#endif // PSCRIPT
|
||
|
||
if (GETUSERDATAITEM(pCurItem->UserData) == METASPOOL_ITEM ||
|
||
GETUSERDATAITEM(pCurItem->UserData) == NUP_ITEM ||
|
||
GETUSERDATAITEM(pCurItem->UserData) == REVPRINT_ITEM ||
|
||
GETUSERDATAITEM(pCurItem->UserData) == COPIES_COLLATE_ITEM ||
|
||
((pFeature = PGetFeatureFromItem(pUiData->ci.pUIInfo, pCurItem, NULL)) &&
|
||
pFeature->dwFeatureID == GID_OUTPUTBIN))
|
||
{
|
||
VUpdateEmfFeatureItems(pUiData, GETUSERDATAITEM(pCurItem->UserData) != METASPOOL_ITEM);
|
||
}
|
||
|
||
#ifdef UNIDRV
|
||
|
||
VSyncColorInformation(pUiData, pCurItem);
|
||
|
||
#endif
|
||
|
||
#ifdef PSCRIPT
|
||
|
||
//
|
||
// If the user has selected custom page size,
|
||
// bring up the custom page size dialog now.
|
||
//
|
||
|
||
if (GETUSERDATAITEM(pCurItem->UserData) == FORMNAME_ITEM &&
|
||
pCurItem->pExtPush != NULL)
|
||
{
|
||
if (pUiData->pwPapers[pCurItem->Sel] == DMPAPER_CUSTOMSIZE)
|
||
{
|
||
(VOID) BDisplayPSCustomPageSizeDialog(pUiData);
|
||
pCurItem->Flags &= ~(OPTIF_EXT_HIDE | OPTIF_EXT_DISABLED);
|
||
}
|
||
else
|
||
pCurItem->Flags |= (OPTIF_EXT_HIDE | OPTIF_EXT_DISABLED);
|
||
|
||
pCurItem->Flags |= OPTIF_CHANGED;
|
||
}
|
||
|
||
#endif // PSCRIPT
|
||
|
||
//
|
||
// Update the display and indicate which items are constrained.
|
||
//
|
||
|
||
VPropShowConstraints(pUiData, MODE_DOCANDPRINTER_STICKY);
|
||
|
||
lRet = CPSUICB_ACTION_REINIT_ITEMS;
|
||
|
||
|
||
break;
|
||
|
||
case CPSUICB_REASON_ITEMS_REVERTED:
|
||
|
||
//
|
||
// Unpack document properties treeview items
|
||
//
|
||
|
||
VUnpackDocumentPropertiesItems(pUiData,
|
||
pUiData->pDrvOptItem,
|
||
pUiData->dwDrvOptItem);
|
||
|
||
//
|
||
// Update the display and indicate which items are constrained
|
||
//
|
||
|
||
VPropShowConstraints(pUiData, MODE_DOCANDPRINTER_STICKY);
|
||
|
||
lRet = CPSUICB_ACTION_OPTIF_CHANGED;
|
||
break;
|
||
|
||
case CPSUICB_REASON_EXTPUSH:
|
||
|
||
#ifdef PSCRIPT
|
||
|
||
if (GETUSERDATAITEM(pCurItem->UserData) == FORMNAME_ITEM)
|
||
{
|
||
//
|
||
// Push button to bring up PostScript custom page size dialog
|
||
//
|
||
|
||
(VOID) BDisplayPSCustomPageSizeDialog(pUiData);
|
||
}
|
||
|
||
#endif // PSCRIPT
|
||
|
||
if (pCurItem == pUiData->pFeatureHdrItem)
|
||
{
|
||
//
|
||
// Push button for restoring all generic feature selections
|
||
// to their default values
|
||
//
|
||
|
||
VRestoreDefaultFeatureSelection(pUiData);
|
||
lRet = CPSUICB_ACTION_REINIT_ITEMS;
|
||
}
|
||
break;
|
||
|
||
|
||
case CPSUICB_REASON_ABOUT:
|
||
|
||
DialogBoxParam(ghInstance,
|
||
MAKEINTRESOURCE(IDD_ABOUT),
|
||
pUiData->hDlg,
|
||
(DLGPROC) _AboutDlgProc,
|
||
(LPARAM) pUiData);
|
||
break;
|
||
|
||
|
||
case CPSUICB_REASON_APPLYNOW:
|
||
|
||
pUiData->ci.dwFlags |= FLAG_APPLYNOW_CALLED;
|
||
|
||
//
|
||
// Check if there are still any unresolved constraints left?
|
||
// BOptItemSelectionsChanged returns TRUE or FALSE depending on
|
||
// whether the user has made any changes to the options
|
||
//
|
||
|
||
if (((pUiData->ci.dwFlags & FLAG_PLUGIN_CHANGED_OPTITEM) ||
|
||
BOptItemSelectionsChanged(pUiData->pDrvOptItem, pUiData->dwDrvOptItem)) &&
|
||
ICheckConstraintsDlg(pUiData,
|
||
pUiData->pDrvOptItem,
|
||
pUiData->dwDrvOptItem,
|
||
TRUE) == CONFLICT_CANCEL)
|
||
{
|
||
//
|
||
// Conflicts found and user clicked CANCEL to
|
||
// go back to the dialog without dismissing it.
|
||
//
|
||
|
||
lRet = CPSUICB_ACTION_NO_APPLY_EXIT;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Transfer information from options array to public devmode fields
|
||
//
|
||
|
||
VOptionsToDevmodeFields(&pUiData->ci, FALSE);
|
||
|
||
//
|
||
// Separate the doc-sticky options from the combined array
|
||
// and save it back to the private devmode aOptions array
|
||
//
|
||
|
||
SeparateOptionArray(
|
||
pUiData->ci.pRawData,
|
||
pUiData->ci.pCombinedOptions,
|
||
PGetDevmodeOptionsArray(pUiData->ci.pdm),
|
||
MAX_PRINTER_OPTIONS,
|
||
MODE_DOCUMENT_STICKY);
|
||
|
||
pCallbackParam->Result = CPSUI_OK;
|
||
lRet = CPSUICB_ACTION_ITEMS_APPLIED ;
|
||
break;
|
||
}
|
||
|
||
return LInvokeOemPluginCallbacks(pUiData, pCallbackParam, lRet);
|
||
}
|
||
|
||
|
||
|
||
BOOL
|
||
BPackItemFormName(
|
||
IN OUT PUIDATA pUiData
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Pack Paper size options.
|
||
|
||
Arguments:
|
||
|
||
pUiData - Points to UIDATA structure
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE if there is an error.
|
||
|
||
--*/
|
||
|
||
{
|
||
//
|
||
// Extended push button for bringing up PostScript custom page size dialog
|
||
//
|
||
|
||
PFEATURE pFeature;
|
||
|
||
static EXTPUSH ExtPush =
|
||
{
|
||
sizeof(EXTPUSH),
|
||
EPF_NO_DOT_DOT_DOT,
|
||
(PWSTR) IDS_EDIT_CUSTOMSIZE,
|
||
NULL,
|
||
0,
|
||
0,
|
||
};
|
||
|
||
if (!(pFeature = GET_PREDEFINED_FEATURE(pUiData->ci.pUIInfo, GID_PAGESIZE)) ||
|
||
pFeature->Options.dwCount < MIN_OPTIONS_ALLOWED ||
|
||
pFeature->dwFlags & FEATURE_FLAG_NOUI)
|
||
return TRUE;
|
||
|
||
if (pUiData->pOptItem)
|
||
{
|
||
DWORD dwFormNames, dwIndex, dwSel, dwPageSizeIndex, dwOption;
|
||
PWSTR pFormNames;
|
||
POPTPARAM pOptParam;
|
||
PUIINFO pUIInfo = pUiData->ci.pUIInfo;
|
||
PFEATURE pPageSizeFeature;
|
||
BOOL bSupported;
|
||
|
||
dwFormNames = pUiData->dwFormNames;
|
||
pFormNames = pUiData->pFormNames;
|
||
|
||
//
|
||
// Figure out the currently selected paper size option index
|
||
//
|
||
|
||
dwSel = DwFindFormNameIndex(pUiData, pUiData->ci.pdm->dmFormName, &bSupported);
|
||
|
||
//
|
||
// If the form is not supported on the printer, it could be the case
|
||
// where the printer doesn't support a form with the same name, but
|
||
// the printer can still support the requested form using exact or
|
||
// closest paper size match.
|
||
//
|
||
// See function VFixOptionsArrayWithDevmode() and ChangeOptionsViaID().
|
||
//
|
||
|
||
if (!bSupported &&
|
||
(pPageSizeFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_PAGESIZE)))
|
||
{
|
||
WCHAR awchBuf[CCHPAPERNAME];
|
||
PPAGESIZE pPageSize;
|
||
|
||
//
|
||
// If we can't find a name match in the first DwFindFormNameIndex call,
|
||
// the option array should already have the correct option index value
|
||
// parser has decided to use to support the form. So now we only need
|
||
// to load the option's display name and search in the form name list
|
||
// again to get the paper size UI list index.
|
||
//
|
||
|
||
dwPageSizeIndex = GET_INDEX_FROM_FEATURE(pUIInfo, pPageSizeFeature);
|
||
|
||
dwOption = pUiData->ci.pCombinedOptions[dwPageSizeIndex].ubCurOptIndex;
|
||
|
||
if ((pPageSize = (PPAGESIZE)PGetIndexedOption(pUIInfo, pPageSizeFeature, dwOption)) &&
|
||
LOAD_STRING_PAGESIZE_NAME(&(pUiData->ci), pPageSize, awchBuf, CCHPAPERNAME))
|
||
{
|
||
dwSel = DwFindFormNameIndex(pUiData, awchBuf, NULL);
|
||
}
|
||
}
|
||
|
||
//
|
||
// Fill out OPTITEM, OPTTYPE, and OPTPARAM structures
|
||
//
|
||
|
||
FILLOPTITEM(pUiData->pOptItem,
|
||
pUiData->pOptType,
|
||
ULongToPtr(IDS_CPSUI_FORMNAME),
|
||
ULongToPtr(dwSel),
|
||
TVITEM_LEVEL1,
|
||
DMPUB_FORMNAME,
|
||
FORMNAME_ITEM,
|
||
HELP_INDEX_FORMNAME);
|
||
|
||
pUiData->pOptType->Style = OTS_LBCB_SORT;
|
||
|
||
pOptParam = PFillOutOptType(pUiData->pOptType,
|
||
TVOT_LISTBOX,
|
||
dwFormNames,
|
||
pUiData->ci.hHeap);
|
||
|
||
if (pOptParam == NULL)
|
||
return FALSE;
|
||
|
||
for (dwIndex=0; dwIndex < dwFormNames; dwIndex++)
|
||
{
|
||
pOptParam->cbSize = sizeof(OPTPARAM);
|
||
pOptParam->pData = pFormNames;
|
||
|
||
if (pUiData->pwPapers[dwIndex] == DMPAPER_CUSTOMSIZE)
|
||
pOptParam->IconID = IDI_CUSTOM_PAGESIZE;
|
||
else if (pOptParam->IconID = HLoadFormIconResource(pUiData, dwIndex))
|
||
pOptParam->Flags |= OPTPF_ICONID_AS_HICON;
|
||
else
|
||
pOptParam->IconID = DwGuessFormIconID(pFormNames);
|
||
|
||
pOptParam++;
|
||
pFormNames += CCHPAPERNAME;
|
||
}
|
||
|
||
//
|
||
// Special case for PostScript custom page size
|
||
//
|
||
|
||
#ifdef PSCRIPT
|
||
|
||
{
|
||
PPPDDATA pPpdData;
|
||
|
||
pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER((PINFOHEADER) pUiData->ci.pRawData);
|
||
|
||
ASSERT(pPpdData != NULL);
|
||
|
||
if (SUPPORT_CUSTOMSIZE(pUIInfo) &&
|
||
SUPPORT_FULL_CUSTOMSIZE_FEATURES(pUIInfo, pPpdData))
|
||
{
|
||
pUiData->pOptItem->Flags |= (OPTIF_EXT_IS_EXTPUSH|OPTIF_CALLBACK);
|
||
pUiData->pOptItem->pExtPush = &ExtPush;
|
||
|
||
//
|
||
// If PostScript custom page size is selected,
|
||
// select the last item of form name list.
|
||
//
|
||
|
||
if (pUiData->ci.pdm->dmPaperSize == DMPAPER_CUSTOMSIZE)
|
||
{
|
||
pUiData->pOptItem->Sel = pUiData->dwFormNames - 1;
|
||
pUiData->pOptItem->Flags &= ~(OPTIF_EXT_HIDE | OPTIF_EXT_DISABLED);
|
||
}
|
||
else
|
||
pUiData->pOptItem->Flags |= (OPTIF_EXT_HIDE | OPTIF_EXT_DISABLED);
|
||
}
|
||
}
|
||
|
||
#endif // PSCRIPT
|
||
|
||
#ifdef UNIDRV
|
||
|
||
//
|
||
// Supports OEM help file. If helpfile and helpindex are defined,
|
||
// we will use the help id specified by the GPD. According to GPD spec,
|
||
// zero loHelpFileName means no help file name specified.
|
||
//
|
||
|
||
if (pUIInfo->loHelpFileName &&
|
||
pFeature->iHelpIndex != UNUSED_ITEM)
|
||
{
|
||
POIEXT pOIExt = HEAPALLOC(pUiData->ci.hHeap, sizeof(OIEXT));
|
||
|
||
if (pOIExt)
|
||
{
|
||
pOIExt->cbSize = sizeof(OIEXT);
|
||
pOIExt->Flags = 0;
|
||
pOIExt->hInstCaller = NULL;
|
||
pOIExt->pHelpFile = OFFSET_TO_POINTER(pUIInfo->pubResourceData,
|
||
pUIInfo->loHelpFileName);
|
||
pUiData->pOptItem->pOIExt = pOIExt;
|
||
pUiData->pOptItem->HelpIndex = pFeature->iHelpIndex;
|
||
pUiData->pOptItem->Flags |= OPTIF_HAS_POIEXT;
|
||
}
|
||
}
|
||
|
||
#endif // UNIDRV
|
||
|
||
//
|
||
// Set the Keyword name for pOptItem->UserData
|
||
//
|
||
|
||
SETUSERDATA_KEYWORDNAME(pUiData->ci, pUiData->pOptItem, pFeature);
|
||
|
||
pUiData->pOptItem++;
|
||
pUiData->pOptType++;
|
||
}
|
||
|
||
pUiData->dwOptItem++;
|
||
pUiData->dwOptType++;
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
BOOL
|
||
BPackItemInputSlot(
|
||
IN OUT PUIDATA pUiData
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Pack paper source option.
|
||
|
||
Arguments:
|
||
|
||
pUiData - Points to UIDATA structure
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE if there is an error.
|
||
|
||
--*/
|
||
|
||
{
|
||
POPTTYPE pOptType;
|
||
PFEATURE pFeature;
|
||
PINPUTSLOT pInputSlot;
|
||
|
||
pFeature = GET_PREDEFINED_FEATURE(pUiData->ci.pUIInfo, GID_INPUTSLOT);
|
||
pOptType = pUiData->pOptType;
|
||
|
||
if (! BPackItemPrinterFeature(
|
||
pUiData,
|
||
pFeature,
|
||
TVITEM_LEVEL1,
|
||
DMPUB_DEFSOURCE,
|
||
(ULONG_PTR)INPUTSLOT_ITEM,
|
||
HELP_INDEX_INPUT_SLOT))
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// NOTE: if the first input slot has dwPaperSourceID == DMBIN_FORMSOURCE,
|
||
// then we'll change its display name to "Automatically Select".
|
||
//
|
||
|
||
if (pOptType != NULL && pOptType != pUiData->pOptType)
|
||
{
|
||
ASSERT(pFeature != NULL);
|
||
|
||
pInputSlot = PGetIndexedOption(pUiData->ci.pUIInfo, pFeature, 0);
|
||
ASSERT(pInputSlot != NULL);
|
||
|
||
if (pInputSlot->dwPaperSourceID == DMBIN_FORMSOURCE)
|
||
pOptType->pOptParam[0].pData = (PWSTR) IDS_TRAY_FORMSOURCE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL
|
||
BPackItemMediaType(
|
||
IN OUT PUIDATA pUiData
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Pack media type option.
|
||
|
||
Arguments:
|
||
|
||
pUiData - Points to UIDATA structure
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE if there is an error.
|
||
|
||
--*/
|
||
|
||
{
|
||
return BPackItemPrinterFeature(
|
||
pUiData,
|
||
GET_PREDEFINED_FEATURE(pUiData->ci.pUIInfo, GID_MEDIATYPE),
|
||
TVITEM_LEVEL1,
|
||
DMPUB_MEDIATYPE,
|
||
(ULONG_PTR)MEDIATYPE_ITEM,
|
||
HELP_INDEX_MEDIA_TYPE);
|
||
}
|
||
|
||
|
||
|
||
static CONST WORD CopiesCollateItemInfo[] =
|
||
{
|
||
IDS_CPSUI_COPIES, TVITEM_LEVEL1, DMPUB_COPIES_COLLATE,
|
||
COPIES_COLLATE_ITEM, HELP_INDEX_COPIES_COLLATE,
|
||
2, TVOT_UDARROW,
|
||
0, IDI_CPSUI_COPY,
|
||
0, MIN_COPIES,
|
||
ITEM_INFO_SIGNATURE
|
||
};
|
||
|
||
|
||
BOOL
|
||
BPackItemCopiesCollate(
|
||
IN OUT PUIDATA pUiData
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Pack copies and collate option.
|
||
|
||
Arguments:
|
||
|
||
pUiData - Points to UIDATA structure
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE if there is an error.
|
||
|
||
--*/
|
||
|
||
{
|
||
POPTITEM pOptItem = pUiData->pOptItem;
|
||
PEXTCHKBOX pExtCheckbox;
|
||
PFEATURE pFeature;
|
||
SHORT sCopies, sMaxCopies;
|
||
|
||
if ((pFeature = GET_PREDEFINED_FEATURE(pUiData->ci.pUIInfo, GID_COLLATE)) &&
|
||
pFeature->dwFlags & FEATURE_FLAG_NOUI)
|
||
return TRUE;
|
||
|
||
if (pUiData->bEMFSpooling)
|
||
{
|
||
sCopies = pUiData->ci.pdm->dmCopies;
|
||
sMaxCopies = max(MAX_COPIES, (SHORT)pUiData->ci.pUIInfo->dwMaxCopies);
|
||
}
|
||
else
|
||
{
|
||
sCopies = pUiData->ci.pdm->dmCopies > (SHORT)pUiData->ci.pUIInfo->dwMaxCopies ?
|
||
(SHORT)pUiData->ci.pUIInfo->dwMaxCopies : pUiData->ci.pdm->dmCopies;
|
||
sMaxCopies = (SHORT)pUiData->ci.pUIInfo->dwMaxCopies;
|
||
|
||
}
|
||
if (! BPackUDArrowItemTemplate(
|
||
pUiData,
|
||
CopiesCollateItemInfo,
|
||
sCopies,
|
||
sMaxCopies,
|
||
pFeature))
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
if (pOptItem && DRIVER_SUPPORTS_COLLATE(((PCOMMONINFO)&pUiData->ci)))
|
||
{
|
||
pExtCheckbox = HEAPALLOC(pUiData->ci.hHeap, sizeof(EXTCHKBOX));
|
||
|
||
if (pExtCheckbox == NULL)
|
||
{
|
||
ERR(("Memory allocation failed\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
pExtCheckbox->cbSize = sizeof(EXTCHKBOX);
|
||
pExtCheckbox->pTitle = (PWSTR) IDS_CPSUI_COLLATE;
|
||
pExtCheckbox->pCheckedName = (PWSTR) IDS_CPSUI_COLLATED;
|
||
pExtCheckbox->IconID = IDI_CPSUI_COLLATE;
|
||
pExtCheckbox->Flags = ECBF_CHECKNAME_ONLY_ENABLED;
|
||
pExtCheckbox->pSeparator = (PWSTR)IDS_CPSUI_SLASH_SEP;
|
||
|
||
pOptItem->pExtChkBox = pExtCheckbox;
|
||
|
||
if ((pUiData->ci.pdm->dmFields & DM_COLLATE) &&
|
||
(pUiData->ci.pdm->dmCollate == DMCOLLATE_TRUE))
|
||
{
|
||
pOptItem->Flags |= OPTIF_ECB_CHECKED;
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
BOOL
|
||
BPackItemResolution(
|
||
IN OUT PUIDATA pUiData
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Pack resolution option.
|
||
|
||
Arguments:
|
||
|
||
pUiData - Points to UIDATA structure
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE if there is an error.
|
||
|
||
--*/
|
||
|
||
{
|
||
return BPackItemPrinterFeature(
|
||
pUiData,
|
||
GET_PREDEFINED_FEATURE(pUiData->ci.pUIInfo, GID_RESOLUTION),
|
||
TVITEM_LEVEL1,
|
||
DMPUB_PRINTQUALITY,
|
||
(ULONG_PTR)RESOLUTION_ITEM,
|
||
HELP_INDEX_RESOLUTION);
|
||
}
|
||
|
||
|
||
|
||
static CONST WORD ColorItemInfo[] =
|
||
{
|
||
IDS_CPSUI_COLOR, TVITEM_LEVEL1, DMPUB_COLOR,
|
||
COLOR_ITEM, HELP_INDEX_COLOR,
|
||
2, TVOT_2STATES,
|
||
IDS_CPSUI_MONOCHROME, IDI_CPSUI_MONO,
|
||
IDS_CPSUI_COLOR, IDI_CPSUI_COLOR,
|
||
ITEM_INFO_SIGNATURE
|
||
};
|
||
|
||
//
|
||
// ICM stuff is not available on NT4
|
||
//
|
||
|
||
#ifndef WINNT_40
|
||
|
||
static CONST WORD ICMMethodItemInfo[] =
|
||
{
|
||
IDS_ICMMETHOD, TVITEM_LEVEL1,
|
||
|
||
#ifdef WINNT_40
|
||
DMPUB_NONE,
|
||
#else
|
||
DMPUB_ICMMETHOD,
|
||
#endif
|
||
|
||
ICMMETHOD_ITEM, HELP_INDEX_ICMMETHOD,
|
||
#ifdef PSCRIPT
|
||
4, TVOT_LISTBOX,
|
||
#else
|
||
3, TVOT_LISTBOX,
|
||
#endif
|
||
IDS_ICMMETHOD_NONE, IDI_ICMMETHOD_NONE,
|
||
IDS_ICMMETHOD_SYSTEM, IDI_ICMMETHOD_SYSTEM,
|
||
IDS_ICMMETHOD_DRIVER, IDI_ICMMETHOD_DRIVER,
|
||
#ifdef PSCRIPT
|
||
IDS_ICMMETHOD_DEVICE, IDI_ICMMETHOD_DEVICE,
|
||
#endif
|
||
ITEM_INFO_SIGNATURE
|
||
};
|
||
|
||
static CONST WORD ICMIntentItemInfo[] =
|
||
{
|
||
IDS_ICMINTENT, TVITEM_LEVEL1,
|
||
|
||
#ifdef WINNT_40
|
||
DMPUB_NONE,
|
||
#else
|
||
DMPUB_ICMINTENT,
|
||
#endif
|
||
|
||
ICMINTENT_ITEM, HELP_INDEX_ICMINTENT,
|
||
4, TVOT_LISTBOX,
|
||
IDS_ICMINTENT_SATURATE, IDI_ICMINTENT_SATURATE,
|
||
IDS_ICMINTENT_CONTRAST, IDI_ICMINTENT_CONTRAST,
|
||
IDS_ICMINTENT_COLORIMETRIC, IDI_ICMINTENT_COLORIMETRIC,
|
||
IDS_ICMINTENT_ABS_COLORIMETRIC, IDI_ICMINTENT_ABS_COLORIMETRIC,
|
||
ITEM_INFO_SIGNATURE
|
||
};
|
||
|
||
#endif // !WINNT_40
|
||
|
||
|
||
BOOL
|
||
BPackItemColor(
|
||
IN OUT PUIDATA pUiData
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Pack color mode option.
|
||
|
||
Arguments:
|
||
|
||
pUiData - Points to UIDATA structure
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE if there is an error.
|
||
|
||
--*/
|
||
|
||
{
|
||
PDEVMODE pdm;
|
||
INT dwColorSel, dwICMMethodSel, dwICMIntentSel;
|
||
|
||
//
|
||
// For Adobe driver, they want to preserve the color information
|
||
// even for b/w printers. So we always give user this choice.
|
||
//
|
||
|
||
#ifndef ADOBE
|
||
|
||
if (! IS_COLOR_DEVICE(pUiData->ci.pUIInfo))
|
||
return TRUE;
|
||
|
||
#endif // !ADOBE
|
||
|
||
//
|
||
// DCR - Some ICM methods and intents may need to be disabled
|
||
// on some non-PostScript printers.
|
||
//
|
||
|
||
pdm = pUiData->ci.pdm;
|
||
dwColorSel = dwICMMethodSel = dwICMIntentSel = 0;
|
||
|
||
if ((pdm->dmFields & DM_COLOR) && (pdm->dmColor == DMCOLOR_COLOR))
|
||
dwColorSel = 1;
|
||
|
||
if (! BPackOptItemTemplate(pUiData, ColorItemInfo, dwColorSel, NULL))
|
||
return FALSE;
|
||
|
||
//
|
||
// ICM stuff is not available on NT4
|
||
//
|
||
|
||
#ifndef WINNT_40
|
||
|
||
if (pdm->dmFields & DM_ICMMETHOD)
|
||
{
|
||
switch (pdm->dmICMMethod)
|
||
{
|
||
case DMICMMETHOD_SYSTEM:
|
||
dwICMMethodSel = 1;
|
||
break;
|
||
|
||
case DMICMMETHOD_DRIVER:
|
||
dwICMMethodSel = 2;
|
||
break;
|
||
|
||
#ifdef PSCRIPT
|
||
case DMICMMETHOD_DEVICE:
|
||
dwICMMethodSel = 3;
|
||
break;
|
||
#endif
|
||
|
||
case DMICMMETHOD_NONE:
|
||
default:
|
||
dwICMMethodSel = 0;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (pdm->dmFields & DM_ICMINTENT)
|
||
{
|
||
switch (pdm->dmICMIntent)
|
||
{
|
||
case DMICM_COLORIMETRIC:
|
||
dwICMIntentSel = 2;
|
||
break;
|
||
|
||
case DMICM_ABS_COLORIMETRIC:
|
||
dwICMIntentSel = 3;
|
||
break;
|
||
|
||
case DMICM_SATURATE:
|
||
dwICMIntentSel = 0;
|
||
break;
|
||
|
||
case DMICM_CONTRAST:
|
||
default:
|
||
dwICMIntentSel = 1;
|
||
break;
|
||
|
||
|
||
}
|
||
}
|
||
|
||
if (! BPackOptItemTemplate(pUiData, ICMMethodItemInfo, dwICMMethodSel, NULL) ||
|
||
! BPackOptItemTemplate(pUiData, ICMIntentItemInfo, dwICMIntentSel, NULL))
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
#endif // !WINNT_40
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
BOOL
|
||
BPackItemDuplex(
|
||
IN OUT PUIDATA pUiData
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Pack duplexing option.
|
||
|
||
Arguments:
|
||
|
||
pUiData - Points to UIDATA structure
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE if there is an error.
|
||
|
||
--*/
|
||
|
||
{
|
||
POPTITEM pOptItem = pUiData->pOptItem;
|
||
PCOMMONINFO pci = &pUiData->ci;
|
||
PFEATURE pFeature = GET_PREDEFINED_FEATURE(pUiData->ci.pUIInfo, GID_DUPLEX);
|
||
BOOL bRet;
|
||
|
||
|
||
//
|
||
// Don't display the duplex feature if duplex is constrained by an
|
||
// installable feature such as duplex unit not installed
|
||
//
|
||
|
||
|
||
if (!SUPPORTS_DUPLEX(pci) ||
|
||
(pFeature && pFeature->Options.dwCount < MIN_OPTIONS_ALLOWED))
|
||
return TRUE;
|
||
|
||
bRet = BPackItemPrinterFeature(
|
||
pUiData,
|
||
pFeature,
|
||
TVITEM_LEVEL1,
|
||
DMPUB_DUPLEX,
|
||
(ULONG_PTR)DUPLEX_ITEM,
|
||
HELP_INDEX_DUPLEX);
|
||
|
||
#ifdef WINNT_40
|
||
|
||
//
|
||
// Use standard names for duplex options. Otherwise, the duplex option
|
||
// names from the PPD/GPD file may be too long to fit into the space
|
||
// on the friendly (Page Setup) tab.
|
||
//
|
||
// On NT5, this kluge is inside compstui.
|
||
//
|
||
|
||
if (bRet && pFeature && pOptItem)
|
||
{
|
||
DWORD dwIndex;
|
||
INT StrRsrcId;
|
||
PDUPLEX pDuplex;
|
||
|
||
for (dwIndex=0; dwIndex < pOptItem->pOptType->Count; dwIndex++)
|
||
{
|
||
pDuplex = (PDUPLEX) PGetIndexedOption(pUiData->ci.pUIInfo, pFeature, dwIndex);
|
||
ASSERT(pDuplex != NULL);
|
||
|
||
switch (pDuplex->dwDuplexID)
|
||
{
|
||
case DMDUP_HORIZONTAL:
|
||
StrRsrcId = IDS_CPSUI_SHORT_SIDE;
|
||
break;
|
||
|
||
case DMDUP_VERTICAL:
|
||
StrRsrcId = IDS_CPSUI_LONG_SIDE;
|
||
break;
|
||
|
||
default:
|
||
StrRsrcId = IDS_CPSUI_NONE;
|
||
break;
|
||
}
|
||
|
||
pOptItem->pOptType->pOptParam[dwIndex].pData = (PWSTR) StrRsrcId;
|
||
}
|
||
}
|
||
|
||
#endif // WINNT_40
|
||
|
||
return bRet;
|
||
}
|
||
|
||
|
||
|
||
static CONST WORD TTOptionItemInfo[] =
|
||
{
|
||
IDS_CPSUI_TTOPTION, TVITEM_LEVEL1, DMPUB_TTOPTION,
|
||
TTOPTION_ITEM, HELP_INDEX_TTOPTION,
|
||
2, TVOT_2STATES,
|
||
IDS_CPSUI_TT_SUBDEV, IDI_CPSUI_TT_SUBDEV,
|
||
IDS_CPSUI_TT_DOWNLOADSOFT, IDI_CPSUI_TT_DOWNLOADSOFT,
|
||
ITEM_INFO_SIGNATURE
|
||
};
|
||
|
||
|
||
BOOL
|
||
BPackItemTTOptions(
|
||
IN OUT PUIDATA pUiData
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Pack TT options
|
||
|
||
Arguments:
|
||
|
||
pUiData - Points to UIDATA structure
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE if there is an error.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD dwSel;
|
||
|
||
|
||
//
|
||
// If device fonts have been disabled or doesn't support
|
||
// font substitution , then don't
|
||
// show font substitution option
|
||
//
|
||
|
||
if (pUiData->ci.pPrinterData->dwFlags & PFLAGS_IGNORE_DEVFONT ||
|
||
pUiData->ci.pUIInfo->dwFontSubCount == 0 )
|
||
{
|
||
pUiData->ci.pdm->dmTTOption = DMTT_DOWNLOAD;
|
||
return TRUE;
|
||
}
|
||
|
||
dwSel = (pUiData->ci.pdm->dmTTOption == DMTT_SUBDEV) ? 0 : 1;
|
||
return BPackOptItemTemplate(pUiData, TTOptionItemInfo, dwSel, NULL);
|
||
}
|
||
|
||
|
||
|
||
static CONST WORD ItemInfoMFSpool[] =
|
||
{
|
||
IDS_METAFILE_SPOOLING, TVITEM_LEVEL1, DMPUB_NONE,
|
||
METASPOOL_ITEM, HELP_INDEX_METAFILE_SPOOLING,
|
||
2, TVOT_2STATES,
|
||
IDS_ENABLED, IDI_CPSUI_ON,
|
||
IDS_DISABLED, IDI_CPSUI_OFF,
|
||
ITEM_INFO_SIGNATURE
|
||
};
|
||
|
||
static CONST WORD ItemInfoNupOption[] =
|
||
{
|
||
IDS_NUPOPTION, TVITEM_LEVEL1, NUP_DMPUB,
|
||
NUP_ITEM, HELP_INDEX_NUPOPTION,
|
||
7, TVOT_LISTBOX,
|
||
IDS_ONE_UP, IDI_ONE_UP,
|
||
IDS_TWO_UP, IDI_TWO_UP,
|
||
IDS_FOUR_UP, IDI_FOUR_UP,
|
||
IDS_SIX_UP, IDI_SIX_UP,
|
||
IDS_NINE_UP, IDI_NINE_UP,
|
||
IDS_SIXTEEN_UP, IDI_SIXTEEN_UP,
|
||
IDS_BOOKLET , IDI_BOOKLET,
|
||
ITEM_INFO_SIGNATURE
|
||
};
|
||
|
||
static CONST WORD ItemInfoRevPrint[] =
|
||
{
|
||
IDS_PAGEORDER, TVITEM_LEVEL1, PAGEORDER_DMPUB,
|
||
REVPRINT_ITEM, HELP_INDEX_REVPRINT,
|
||
2, TVOT_2STATES,
|
||
IDS_PAGEORDER_NORMAL, IDI_PAGEORDER_NORMAL,
|
||
IDS_PAGEORDER_REVERSE, IDI_PAGEORDER_REVERSE,
|
||
ITEM_INFO_SIGNATURE
|
||
};
|
||
|
||
BOOL
|
||
BPackItemEmfFeatures(
|
||
PUIDATA pUiData
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Pack EMF related feature items:
|
||
EMF spooling on/off
|
||
N-up
|
||
reverse-order printing
|
||
|
||
Arguments:
|
||
|
||
pUiData - Points to UIDATA structure
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE if there is an error.
|
||
|
||
--*/
|
||
|
||
{
|
||
PDRIVEREXTRA pdmExtra = pUiData->ci.pdmPrivate;
|
||
BOOL bNupOption, bReversePrint;
|
||
PCOMMONINFO pci = &pUiData->ci;
|
||
DWORD dwSel;
|
||
POPTITEM pOptItem;
|
||
|
||
//
|
||
// Check if the spooler can do N-up and reverse-order printing
|
||
// for the current printer
|
||
//
|
||
|
||
VGetSpoolerEmfCaps(pci->hPrinter, &bNupOption, &bReversePrint, 0, NULL);
|
||
|
||
//
|
||
// On Win2K and above, don't show the EMF spooling option in driver UI
|
||
// if spooler cannot do EMF.
|
||
// pUiData->bEMFSpooling is initialized at PFillUidata
|
||
// 1. Determine if Reverse Print is possible
|
||
// 2. Spooler can do EMF.
|
||
//
|
||
// On NT4, since spooler doesn't support the EMF capability query, we
|
||
// have to keep the old NT4 driver behavior of always showing the EMF
|
||
// spooling option in driver UI.
|
||
//
|
||
|
||
#ifndef WINNT_40
|
||
if (pUiData->bEMFSpooling)
|
||
{
|
||
#endif
|
||
|
||
dwSel = ISSET_MFSPOOL_FLAG(pdmExtra) ? 0 : 1;
|
||
|
||
if (!BPackOptItemTemplate(pUiData, ItemInfoMFSpool, dwSel, NULL))
|
||
return FALSE;
|
||
|
||
#ifndef WINNT_40
|
||
}
|
||
#endif
|
||
|
||
#ifdef PSCRIPT
|
||
bNupOption = TRUE;
|
||
#endif
|
||
|
||
//
|
||
// Pack N-up option item if necessary
|
||
//
|
||
|
||
if (bNupOption)
|
||
{
|
||
switch (NUPOPTION(pdmExtra))
|
||
{
|
||
case TWO_UP:
|
||
dwSel = 1;
|
||
break;
|
||
|
||
case FOUR_UP:
|
||
dwSel = 2;
|
||
break;
|
||
|
||
case SIX_UP:
|
||
dwSel = 3;
|
||
break;
|
||
|
||
case NINE_UP:
|
||
dwSel = 4;
|
||
break;
|
||
|
||
case SIXTEEN_UP:
|
||
dwSel = 5;
|
||
break;
|
||
|
||
case BOOKLET_UP:
|
||
dwSel = 6;
|
||
break;
|
||
|
||
case ONE_UP:
|
||
default:
|
||
dwSel = 0;
|
||
break;
|
||
}
|
||
|
||
pOptItem = pUiData->pOptItem;
|
||
|
||
if (!BPackOptItemTemplate(pUiData, ItemInfoNupOption, dwSel, NULL))
|
||
return FALSE;
|
||
|
||
|
||
//
|
||
// Hide booklet option if duplex is constrained by an
|
||
// installable feature such as duplex unit not installed or EMF is not
|
||
// available.
|
||
//
|
||
|
||
if ( pOptItem &&
|
||
(!pUiData->bEMFSpooling || !SUPPORTS_DUPLEX(pci)))
|
||
{
|
||
pOptItem->pOptType->pOptParam[BOOKLET_UP].Flags |= OPTPF_HIDE;
|
||
|
||
if (NUPOPTION(pdmExtra) == BOOKLET_UP)
|
||
pOptItem->Sel = 1;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
NUPOPTION(pdmExtra) = ONE_UP;
|
||
}
|
||
|
||
//
|
||
// Pack Reverse-order printing option item if necessary
|
||
//
|
||
|
||
if (bReversePrint)
|
||
{
|
||
dwSel = REVPRINTOPTION(pdmExtra) ? 1 : 0;
|
||
|
||
if (!BPackOptItemTemplate(pUiData, ItemInfoRevPrint, dwSel, NULL))
|
||
return FALSE;
|
||
}
|
||
else
|
||
{
|
||
REVPRINTOPTION(pdmExtra) = FALSE;
|
||
}
|
||
|
||
if (pUiData->bEMFSpooling && pUiData->pOptItem)
|
||
VUpdateEmfFeatureItems(pUiData, FALSE);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
BOOL
|
||
BPackDocumentPropertyItems(
|
||
IN OUT PUIDATA pUiData
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Pack document property information into treeview items.
|
||
|
||
Arguments:
|
||
|
||
pUiData - Points to UIDATA structure
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE if there is an error.
|
||
|
||
--*/
|
||
{
|
||
return BPackItemFormName(pUiData) &&
|
||
BPackItemInputSlot(pUiData) &&
|
||
_BPackOrientationItem(pUiData) &&
|
||
BPackItemCopiesCollate(pUiData) &&
|
||
BPackItemResolution(pUiData) &&
|
||
BPackItemColor(pUiData) &&
|
||
_BPackItemScale(pUiData) &&
|
||
BPackItemDuplex(pUiData) &&
|
||
BPackItemMediaType(pUiData) &&
|
||
BPackItemTTOptions(pUiData) &&
|
||
BPackItemEmfFeatures(pUiData) &&
|
||
_BPackDocumentOptions(pUiData) &&
|
||
BPackItemGenericOptions(pUiData) &&
|
||
BPackOemPluginItems(pUiData);
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
VUnpackDocumentPropertiesItems(
|
||
PUIDATA pUiData,
|
||
POPTITEM pOptItem,
|
||
DWORD dwOptItem
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Extract devmode information from an OPTITEM
|
||
Stored it back into devmode.
|
||
|
||
Arguments:
|
||
|
||
pUiData - Pointer to our UIDATA structure
|
||
pOptItem - Pointer to an array of OPTITEMs
|
||
dwOptItem - Number of OPTITEMs
|
||
|
||
Return Value:
|
||
|
||
Printer feature index corresponding to the last item unpacked
|
||
|
||
--*/
|
||
|
||
{
|
||
PUIINFO pUIInfo = pUiData->ci.pUIInfo;
|
||
PDEVMODE pdm = pUiData->ci.pdm;
|
||
PDRIVEREXTRA pdmExtra = pUiData->ci.pdmPrivate;
|
||
|
||
for ( ; dwOptItem > 0; dwOptItem--, pOptItem++)
|
||
{
|
||
//
|
||
// Header items always have pOptType == NULL, see
|
||
// VPackOptItemGroupHeader
|
||
//
|
||
|
||
if (pOptItem->pOptType == NULL)
|
||
continue;
|
||
|
||
//
|
||
// To fix bug #90923, we should only allow hidden items to be processed when we are within
|
||
// the UI helper function call BUpdateUISettingForOEM issued by OEM plguin.
|
||
//
|
||
// We don't do this for other cases because there are already UI plugins that hide our
|
||
// standard items and show their own. For example, CNBJUI.DLL hides our ICMMETHOD_ITEM
|
||
// and ICMINTENT_ITEM. It uses its own as replacement items. If we change the behavior here,
|
||
// we could break those plugins when we process the hidden items and overwrite the devmode
|
||
// plugin has already set based on user selection of their replacement items.
|
||
//
|
||
|
||
if (!(pUiData->ci.dwFlags & FLAG_WITHIN_PLUGINCALL) && (pOptItem->Flags & OPTIF_HIDE))
|
||
continue;
|
||
|
||
if (ISPRINTERFEATUREITEM(pOptItem->UserData))
|
||
{
|
||
//
|
||
// Generic document-sticky printer features
|
||
//
|
||
|
||
VUpdateOptionsArrayWithSelection(pUiData, pOptItem);
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// Common items in public devmode
|
||
//
|
||
|
||
switch (GETUSERDATAITEM(pOptItem->UserData))
|
||
{
|
||
case ORIENTATION_ITEM:
|
||
|
||
//
|
||
// Orientation is a special case:
|
||
// for pscript, it's handled via _VUnpackDocumentOptions
|
||
// for unidrv, it's handled as a generic feature
|
||
//
|
||
|
||
#ifdef PSCRIPT
|
||
|
||
break;
|
||
|
||
#endif
|
||
|
||
case DUPLEX_ITEM:
|
||
VUpdateOptionsArrayWithSelection(pUiData, pOptItem);
|
||
VUpdateBookletOption(pUiData, pOptItem);
|
||
break;
|
||
|
||
|
||
case RESOLUTION_ITEM:
|
||
case INPUTSLOT_ITEM:
|
||
case MEDIATYPE_ITEM:
|
||
case COLORMODE_ITEM:
|
||
case HALFTONING_ITEM:
|
||
|
||
VUpdateOptionsArrayWithSelection(pUiData, pOptItem);
|
||
break;
|
||
|
||
case SCALE_ITEM:
|
||
|
||
pdm->dmScale = (SHORT) pOptItem->Sel;
|
||
break;
|
||
|
||
case COPIES_COLLATE_ITEM:
|
||
|
||
pdm->dmCopies = (SHORT) pOptItem->Sel;
|
||
|
||
if (pOptItem->pExtChkBox)
|
||
{
|
||
pdm->dmFields |= DM_COLLATE;
|
||
pdm->dmCollate = (pOptItem->Flags & OPTIF_ECB_CHECKED) ?
|
||
DMCOLLATE_TRUE :
|
||
DMCOLLATE_FALSE;
|
||
|
||
//
|
||
// Update Collate feature option index
|
||
//
|
||
|
||
ChangeOptionsViaID(
|
||
pUiData->ci.pInfoHeader,
|
||
pUiData->ci.pCombinedOptions,
|
||
GID_COLLATE,
|
||
pdm);
|
||
}
|
||
break;
|
||
|
||
case COLOR_ITEM:
|
||
|
||
pdm->dmFields |= DM_COLOR;
|
||
pdm->dmColor = (pOptItem->Sel == 1) ?
|
||
DMCOLOR_COLOR :
|
||
DMCOLOR_MONOCHROME;
|
||
break;
|
||
|
||
case METASPOOL_ITEM:
|
||
|
||
if (pOptItem->Sel == 0)
|
||
{
|
||
SET_MFSPOOL_FLAG(pdmExtra);
|
||
}
|
||
else
|
||
{
|
||
CLEAR_MFSPOOL_FLAG(pdmExtra);
|
||
}
|
||
break;
|
||
|
||
case NUP_ITEM:
|
||
|
||
switch (pOptItem->Sel)
|
||
{
|
||
case 1:
|
||
NUPOPTION(pdmExtra) = TWO_UP;
|
||
break;
|
||
|
||
case 2:
|
||
NUPOPTION(pdmExtra) = FOUR_UP;
|
||
break;
|
||
|
||
case 3:
|
||
NUPOPTION(pdmExtra) = SIX_UP;
|
||
break;
|
||
|
||
case 4:
|
||
NUPOPTION(pdmExtra) = NINE_UP;
|
||
break;
|
||
|
||
case 5:
|
||
NUPOPTION(pdmExtra) = SIXTEEN_UP;
|
||
break;
|
||
|
||
case 6:
|
||
NUPOPTION(pdmExtra) = BOOKLET_UP;
|
||
VUpdateBookletOption(pUiData, pOptItem);
|
||
break;
|
||
|
||
case 0:
|
||
default:
|
||
NUPOPTION(pdmExtra) = ONE_UP;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case REVPRINT_ITEM:
|
||
|
||
REVPRINTOPTION(pdmExtra) = (pOptItem->Sel != 0);
|
||
break;
|
||
|
||
//
|
||
// ICM stuff is not available on NT4
|
||
//
|
||
|
||
#ifndef WINNT_40
|
||
|
||
case ICMMETHOD_ITEM:
|
||
|
||
pdm->dmFields |= DM_ICMMETHOD;
|
||
|
||
switch (pOptItem->Sel)
|
||
{
|
||
case 0:
|
||
pdm->dmICMMethod = DMICMMETHOD_NONE;
|
||
break;
|
||
|
||
case 1:
|
||
pdm->dmICMMethod = DMICMMETHOD_SYSTEM;
|
||
break;
|
||
|
||
case 2:
|
||
pdm->dmICMMethod = DMICMMETHOD_DRIVER;
|
||
break;
|
||
|
||
#ifdef PSCRIPT
|
||
case 3:
|
||
pdm->dmICMMethod = DMICMMETHOD_DEVICE;
|
||
break;
|
||
#endif
|
||
}
|
||
break;
|
||
|
||
case ICMINTENT_ITEM:
|
||
|
||
pdm->dmFields |= DM_ICMINTENT;
|
||
|
||
switch (pOptItem->Sel)
|
||
{
|
||
case 0:
|
||
pdm->dmICMIntent = DMICM_SATURATE;
|
||
break;
|
||
|
||
case 1:
|
||
pdm->dmICMIntent = DMICM_CONTRAST;
|
||
break;
|
||
|
||
case 2:
|
||
pdm->dmICMIntent = DMICM_COLORIMETRIC;
|
||
break;
|
||
|
||
case 3:
|
||
pdm->dmICMIntent = DMICM_ABS_COLORIMETRIC;
|
||
break;
|
||
}
|
||
break;
|
||
|
||
#endif // !WINNT_40
|
||
|
||
case TTOPTION_ITEM:
|
||
|
||
pdm->dmFields |= DM_TTOPTION;
|
||
|
||
if (pOptItem->Sel == 0)
|
||
pdm->dmTTOption = DMTT_SUBDEV;
|
||
else
|
||
pdm->dmTTOption = DMTT_DOWNLOAD;
|
||
break;
|
||
|
||
case FORMNAME_ITEM:
|
||
|
||
pdm->dmFields &= ~(DM_PAPERLENGTH|DM_PAPERWIDTH);
|
||
pdm->dmFields |= DM_PAPERSIZE;
|
||
pdm->dmPaperSize = pUiData->pwPapers[pOptItem->Sel];
|
||
|
||
if (pdm->dmPaperSize == DMPAPER_CUSTOMSIZE)
|
||
pdm->dmFields &= ~DM_FORMNAME;
|
||
else
|
||
pdm->dmFields |= DM_FORMNAME;
|
||
|
||
CopyString(pdm->dmFormName,
|
||
pOptItem->pOptType->pOptParam[pOptItem->Sel].pData,
|
||
CCHFORMNAME);
|
||
|
||
//
|
||
// Update PageSize feature option index
|
||
//
|
||
|
||
{
|
||
INT dwIndex;
|
||
|
||
if (PGetFeatureFromItem(pUiData->ci.pUIInfo, pOptItem, &dwIndex))
|
||
{
|
||
pUiData->ci.pCombinedOptions[dwIndex].ubCurOptIndex =
|
||
(BYTE) pUiData->pwPaperFeatures[pOptItem->Sel];
|
||
}
|
||
}
|
||
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Give drivers a chance to process their private items
|
||
//
|
||
|
||
_VUnpackDocumentOptions(pOptItem, pdm);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
VUpdateEmfFeatureItems(
|
||
PUIDATA pUiData,
|
||
BOOL bUpdateMFSpoolItem
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Handle the inter-dependency between EMF spooling, N-up, and
|
||
reverse-printing items.
|
||
|
||
Arguments:
|
||
|
||
pUiData - Points to UIDATA structure
|
||
bUpdateMFSpoolItem - Whether to update EMF spooling or the other two items
|
||
|
||
Return Value:
|
||
|
||
NONE
|
||
|
||
--*/
|
||
|
||
{
|
||
POPTITEM pMFSpoolItem, pNupItem, pRevPrintItem, pCopiesCollateItem;
|
||
|
||
pMFSpoolItem = PFindOptItemWithUserData(pUiData, METASPOOL_ITEM);
|
||
pNupItem = PFindOptItemWithUserData(pUiData, NUP_ITEM);
|
||
pRevPrintItem = PFindOptItemWithUserData(pUiData, REVPRINT_ITEM);
|
||
pCopiesCollateItem = PFindOptItemWithUserData(pUiData, COPIES_COLLATE_ITEM);
|
||
|
||
if (pMFSpoolItem == NULL)
|
||
return;
|
||
|
||
if (bUpdateMFSpoolItem)
|
||
{
|
||
|
||
//
|
||
// Force EMF spooling to be on if:
|
||
// N-up option is not ONE_UP (Unidrv only), or
|
||
// reverse-order printing is enabled or
|
||
// collate is not supported by the device or
|
||
// copies count is > than max count support by device
|
||
//
|
||
|
||
#ifdef UNIDRV
|
||
|
||
if (pNupItem && pNupItem->Sel != 0)
|
||
pMFSpoolItem->Sel = 0;
|
||
|
||
#endif // UNIDRV
|
||
|
||
if (pNupItem && pNupItem->Sel == BOOKLET_UP)
|
||
pMFSpoolItem->Sel = 0;
|
||
|
||
if (pRevPrintItem)
|
||
{
|
||
//
|
||
// Turn on EMF if the user selects "Normal" and
|
||
// the bin is "Reversed" OR user selects "Reversed"
|
||
// and the bin is "Normal"
|
||
//
|
||
|
||
BOOL bReversed = BGetPageOrderFlag(&pUiData->ci);
|
||
if ( pRevPrintItem->Sel == 0 && bReversed ||
|
||
pRevPrintItem->Sel != 0 && !bReversed )
|
||
pMFSpoolItem->Sel = 0;
|
||
}
|
||
|
||
if (pCopiesCollateItem)
|
||
{
|
||
if (((pCopiesCollateItem->Flags & OPTIF_ECB_CHECKED) &&
|
||
!PRINTER_SUPPORTS_COLLATE(((PCOMMONINFO)&pUiData->ci))) ||
|
||
(pCopiesCollateItem->Sel > (LONG)pUiData->ci.pUIInfo->dwMaxCopies))
|
||
{
|
||
pMFSpoolItem->Sel = 0;
|
||
}
|
||
}
|
||
|
||
pMFSpoolItem->Flags |= OPTIF_CHANGED;
|
||
VUnpackDocumentPropertiesItems(pUiData, pMFSpoolItem, 1);
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// If EMF spooling is turned off, force:
|
||
// N-up option to be ONE_UP (Unidrv only), and
|
||
// collate to be off if the device doesn't support collation
|
||
// copies set to the max count handle by the device
|
||
//
|
||
|
||
if (pMFSpoolItem->Sel != 0)
|
||
{
|
||
#ifdef UNIDRV
|
||
if (pNupItem)
|
||
{
|
||
pNupItem->Sel = 0;
|
||
pNupItem->Flags |= OPTIF_CHANGED;
|
||
VUnpackDocumentPropertiesItems(pUiData, pNupItem, 1);
|
||
}
|
||
#endif // UNIDRV
|
||
|
||
if (pNupItem && pNupItem->Sel == BOOKLET_UP)
|
||
{
|
||
pNupItem->Sel = 0;
|
||
pNupItem->Flags |= OPTIF_CHANGED;
|
||
VUnpackDocumentPropertiesItems(pUiData, pNupItem, 1);
|
||
}
|
||
|
||
|
||
if (pCopiesCollateItem)
|
||
{
|
||
if ((pCopiesCollateItem->Flags & OPTIF_ECB_CHECKED) &&
|
||
!PRINTER_SUPPORTS_COLLATE(((PCOMMONINFO)&pUiData->ci)))
|
||
{
|
||
pCopiesCollateItem->Flags &=~OPTIF_ECB_CHECKED;
|
||
}
|
||
|
||
if (pCopiesCollateItem->Sel > (LONG)pUiData->ci.pUIInfo->dwMaxCopies)
|
||
pCopiesCollateItem->Sel = (LONG)pUiData->ci.pUIInfo->dwMaxCopies;
|
||
|
||
pCopiesCollateItem->Flags |= OPTIF_CHANGED;
|
||
VUnpackDocumentPropertiesItems(pUiData, pCopiesCollateItem, 1);
|
||
|
||
}
|
||
|
||
//
|
||
// EMF is OFF. Need to make the "Page Order" option consistent
|
||
// with the current output bin. If bin is "Reversed" and user selects
|
||
// "Normal", change it to "Reverse". If bin is "Normal" and user selects
|
||
// "Reverse", change it to "Normal"
|
||
//
|
||
|
||
if (pRevPrintItem)
|
||
{
|
||
BOOL bReversed = BGetPageOrderFlag(&pUiData->ci);
|
||
if (pRevPrintItem->Sel == 0 && bReversed )
|
||
pRevPrintItem->Sel = 1;
|
||
else if ( pRevPrintItem->Sel != 0 && !bReversed )
|
||
pRevPrintItem->Sel = 0;
|
||
|
||
pRevPrintItem->Flags |= OPTIF_CHANGED;
|
||
VUnpackDocumentPropertiesItems(pUiData, pRevPrintItem, 1);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
BOOL
|
||
BGetPageOrderFlag(
|
||
PCOMMONINFO pci
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Get the page order flag for the specified output bin
|
||
|
||
Arguments:
|
||
|
||
pci - Pointer to PCOMMONINFO
|
||
|
||
Return Value:
|
||
|
||
TRUE if output bin is reverse. otherwise, FALSE
|
||
|
||
--*/
|
||
|
||
{
|
||
PUIINFO pUIInfo = pci->pUIInfo;
|
||
PFEATURE pFeature;
|
||
POUTPUTBIN pOutputBin;
|
||
DWORD dwFeatureIndex, dwOptionIndex;
|
||
BOOL bRet = FALSE;
|
||
|
||
#ifdef PSCRIPT
|
||
|
||
{
|
||
PPPDDATA pPpdData;
|
||
POPTION pOption;
|
||
PCSTR pstrKeywordName;
|
||
|
||
//
|
||
// For PostScript driver, PPD could have "*OpenUI *OutputOrder", which enables user to
|
||
// select "Normal" or "Reverse" output order. This should have higher priority than
|
||
// current output bin's output order or what *DefaultOutputOrder specifies.
|
||
//
|
||
|
||
pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER((PINFOHEADER) pci->pRawData);
|
||
|
||
ASSERT(pPpdData != NULL);
|
||
|
||
if (pPpdData->dwOutputOrderIndex != INVALID_FEATURE_INDEX)
|
||
{
|
||
//
|
||
// "OutputOrder" feature is available. Check it's current option selection.
|
||
//
|
||
|
||
pFeature = PGetIndexedFeature(pUIInfo, pPpdData->dwOutputOrderIndex);
|
||
|
||
ASSERT(pFeature != NULL);
|
||
|
||
dwOptionIndex = pci->pCombinedOptions[pPpdData->dwOutputOrderIndex].ubCurOptIndex;
|
||
|
||
if ((pOption = PGetIndexedOption(pUIInfo, pFeature, dwOptionIndex)) &&
|
||
(pstrKeywordName = OFFSET_TO_POINTER(pUIInfo->pubResourceData, pOption->loKeywordName)))
|
||
{
|
||
//
|
||
// Valid *OutputOrder option keywords are "Reverse" or "Normal".
|
||
//
|
||
|
||
if (strcmp(pstrKeywordName, "Reverse") == EQUAL_STRING)
|
||
return TRUE;
|
||
else if (strcmp(pstrKeywordName, "Normal") == EQUAL_STRING)
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// If we are here, the PPD must have wrong information in *OpenUI *OutputOrder.
|
||
// We just ignore "OutputOrder" feature and continue.
|
||
//
|
||
}
|
||
}
|
||
|
||
#endif // PSCRIPT
|
||
|
||
//
|
||
// If the output bin order is NORMAL or there is no output bin
|
||
// feature defined, then the page order is the user's selection.
|
||
//
|
||
|
||
if ((pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_OUTPUTBIN)))
|
||
{
|
||
dwFeatureIndex = GET_INDEX_FROM_FEATURE(pUIInfo, pFeature);
|
||
dwOptionIndex = pci->pCombinedOptions[dwFeatureIndex].ubCurOptIndex;
|
||
pOutputBin = (POUTPUTBIN)PGetIndexedOption(pUIInfo,
|
||
pFeature,
|
||
dwOptionIndex);
|
||
|
||
if (pOutputBin &&
|
||
pOutputBin->bOutputOrderReversed)
|
||
{
|
||
|
||
if (NOT_UNUSED_ITEM(pOutputBin->bOutputOrderReversed))
|
||
bRet = TRUE;
|
||
else
|
||
bRet = pUIInfo->dwFlags & FLAG_REVERSE_PRINT;
|
||
}
|
||
}
|
||
else if (pUIInfo->dwFlags & FLAG_REVERSE_PRINT)
|
||
bRet = TRUE;
|
||
|
||
return bRet;
|
||
|
||
}
|
||
|
||
DWORD
|
||
DwGetDrvCopies(
|
||
PCOMMONINFO pci
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Get the printer copy count capability. Also take into account the
|
||
collating option.
|
||
|
||
Arguments:
|
||
|
||
pci - Pointer to PCOMMONINFO
|
||
|
||
Return Value:
|
||
|
||
The number of copies the printer can do, with collating taken into consideration
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD dwRet;
|
||
|
||
if ((pci->pdm->dmFields & DM_COLLATE) &&
|
||
pci->pdm->dmCollate == DMCOLLATE_TRUE &&
|
||
!PRINTER_SUPPORTS_COLLATE(pci))
|
||
dwRet = 1;
|
||
else
|
||
dwRet = min(pci->pUIInfo->dwMaxCopies, (DWORD)pci->pdm->dmCopies);
|
||
|
||
return dwRet;
|
||
|
||
}
|
||
|
||
|
||
BOOL
|
||
DrvQueryJobAttributes(
|
||
HANDLE hPrinter,
|
||
PDEVMODE pDevMode,
|
||
DWORD dwLevel,
|
||
LPBYTE lpAttributeInfo
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Negotiate EMF printing features (such as N-up and reverse-order printing)
|
||
with the spooler
|
||
|
||
Arguments:
|
||
|
||
hPrinter - Handle to the current printer
|
||
pDevMode - Pointer to input devmode
|
||
dwLevel - Specifies the structure level for lpAttributeInfo
|
||
lpAttributeInfo - Output buffer for returning EMF printing features
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE if there is an error
|
||
|
||
--*/
|
||
|
||
{
|
||
#if !defined(WINNT_40)
|
||
|
||
PCOMMONINFO pci;
|
||
PATTRIBUTE_INFO_1 pAttrInfo1;
|
||
DWORD dwVal;
|
||
BOOL bAppDoNup, bResult = FALSE;
|
||
|
||
//
|
||
// We can only handle AttributeInfo level 1
|
||
//
|
||
|
||
if ( dwLevel != 1 && dwLevel != 2 && dwLevel != 3)
|
||
{
|
||
ERR(("Invalid level for DrvQueryJobAttributes: %d\n", dwLevel));
|
||
SetLastError(ERROR_INVALID_PARAMETER);
|
||
return bResult;
|
||
}
|
||
|
||
//
|
||
// Load basic printer information
|
||
//
|
||
|
||
if (! (pci = PLoadCommonInfo(hPrinter, NULL, 0)) ||
|
||
! BFillCommonInfoPrinterData(pci) ||
|
||
! BFillCommonInfoDevmode(pci, NULL, pDevMode) ||
|
||
! BCombineCommonInfoOptionsArray(pci))
|
||
{
|
||
VFreeCommonInfo(pci);
|
||
return bResult;
|
||
}
|
||
|
||
VFixOptionsArrayWithDevmode(pci);
|
||
|
||
(VOID) ResolveUIConflicts(pci->pRawData,
|
||
pci->pCombinedOptions,
|
||
MAX_COMBINED_OPTIONS,
|
||
MODE_DOCUMENT_STICKY);
|
||
|
||
VOptionsToDevmodeFields(pci, TRUE);
|
||
|
||
if (! BUpdateUIInfo(pci))
|
||
{
|
||
VFreeCommonInfo(pci);
|
||
return bResult;
|
||
}
|
||
|
||
pAttrInfo1 = (PATTRIBUTE_INFO_1) lpAttributeInfo;
|
||
|
||
bAppDoNup = ( (pci->pdm->dmFields & DM_NUP) &&
|
||
(pci->pdm->dmNup == DMNUP_ONEUP) );
|
||
|
||
if (bAppDoNup)
|
||
{
|
||
dwVal = 1;
|
||
}
|
||
else
|
||
{
|
||
switch (NUPOPTION(pci->pdmPrivate))
|
||
{
|
||
case TWO_UP:
|
||
dwVal = 2;
|
||
break;
|
||
|
||
case FOUR_UP:
|
||
dwVal = 4;
|
||
break;
|
||
|
||
case SIX_UP:
|
||
dwVal = 6;
|
||
break;
|
||
|
||
case NINE_UP:
|
||
dwVal = 9;
|
||
break;
|
||
|
||
case SIXTEEN_UP:
|
||
dwVal = 16;
|
||
break;
|
||
|
||
case BOOKLET_UP:
|
||
dwVal = 2;
|
||
break;
|
||
|
||
case ONE_UP:
|
||
default:
|
||
dwVal = 1;
|
||
break;
|
||
}
|
||
}
|
||
pAttrInfo1->dwDrvNumberOfPagesPerSide = pAttrInfo1->dwJobNumberOfPagesPerSide = dwVal;
|
||
pAttrInfo1->dwNupBorderFlags = BORDER_PRINT;
|
||
|
||
pAttrInfo1->dwJobPageOrderFlags =
|
||
REVPRINTOPTION(pci->pdmPrivate) ? REVERSE_PRINT : NORMAL_PRINT;
|
||
pAttrInfo1->dwDrvPageOrderFlags = BGetPageOrderFlag(pci) ? REVERSE_PRINT : NORMAL_PRINT;
|
||
|
||
//
|
||
// Check for booklet
|
||
//
|
||
|
||
if ((NUPOPTION(pci->pdmPrivate) == BOOKLET_UP) && !bAppDoNup)
|
||
{
|
||
pAttrInfo1->dwJobNumberOfPagesPerSide = 2;
|
||
pAttrInfo1->dwDrvNumberOfPagesPerSide = 1;
|
||
pAttrInfo1->dwDrvPageOrderFlags |= BOOKLET_PRINT;
|
||
}
|
||
|
||
pAttrInfo1->dwJobNumberOfCopies = pci->pdm->dmCopies;
|
||
pAttrInfo1->dwDrvNumberOfCopies = DwGetDrvCopies(pci);
|
||
|
||
#ifdef UNIDRV
|
||
|
||
//
|
||
// Unidrv doesn't support N-up option.
|
||
//
|
||
|
||
pAttrInfo1->dwDrvNumberOfPagesPerSide = 1;
|
||
|
||
#endif
|
||
|
||
//
|
||
// Unidrv assumes that automatic switching to monochrome
|
||
// mode on a color printer is allowed unless disabled in GPD
|
||
//
|
||
|
||
if (dwLevel == 3)
|
||
{
|
||
#ifdef UNIDRV
|
||
|
||
SHORT dmPrintQuality, dmYResolution;
|
||
|
||
if (pci->pUIInfo->bChangeColorModeOnDoc &&
|
||
pci->pdm->dmColor == DMCOLOR_COLOR &&
|
||
BOkToChangeColorToMono(pci, pci->pdm, &dmPrintQuality, &dmYResolution) &&
|
||
GET_PREDEFINED_FEATURE(pci->pUIInfo, GID_COLORMODE))
|
||
{
|
||
((PATTRIBUTE_INFO_3)pAttrInfo1)->dwColorOptimization = COLOR_OPTIMIZATION;
|
||
((PATTRIBUTE_INFO_3)pAttrInfo1)->dmPrintQuality = dmPrintQuality;
|
||
((PATTRIBUTE_INFO_3)pAttrInfo1)->dmYResolution = dmYResolution;
|
||
|
||
}
|
||
else
|
||
#endif
|
||
((PATTRIBUTE_INFO_3)pAttrInfo1)->dwColorOptimization = NO_COLOR_OPTIMIZATION;
|
||
}
|
||
|
||
bResult = TRUE;
|
||
|
||
FOREACH_OEMPLUGIN_LOOP(pci)
|
||
|
||
if (HAS_COM_INTERFACE(pOemEntry))
|
||
{
|
||
HRESULT hr;
|
||
|
||
hr = HComOEMQueryJobAttributes(
|
||
pOemEntry,
|
||
hPrinter,
|
||
pDevMode,
|
||
dwLevel,
|
||
lpAttributeInfo);
|
||
|
||
if (hr == E_NOTIMPL || hr == E_NOINTERFACE)
|
||
continue;
|
||
|
||
bResult = SUCCEEDED(hr);
|
||
|
||
}
|
||
|
||
END_OEMPLUGIN_LOOP
|
||
|
||
VFreeCommonInfo(pci);
|
||
return bResult;
|
||
|
||
#else // WINNT_40
|
||
|
||
return FALSE;
|
||
|
||
#endif // WINNT_40
|
||
}
|
||
|
||
VOID
|
||
VUpdateBookletOption(
|
||
PUIDATA pUiData,
|
||
POPTITEM pCurItem
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Handle the dependencies between duplex, nup and booklet options
|
||
|
||
Arguments:
|
||
|
||
pUiData - UIDATA
|
||
pCurItem - OPTITEM to currently selected item
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
PDRIVEREXTRA pdmExtra = pUiData->ci.pdmPrivate;
|
||
DWORD dwFeatureIndex, dwOptionIndex, dwCount;
|
||
PDUPLEX pDuplexOption = NULL;
|
||
POPTITEM pDuplexItem, pNupItem;
|
||
PFEATURE pDuplexFeature = NULL;
|
||
|
||
pDuplexItem = pNupItem = NULL;
|
||
|
||
//
|
||
// 1. Booklet is enabled - turn duplex on
|
||
// 3. Duplex is simplex, disable booklet, set to 1 up.
|
||
//
|
||
|
||
pDuplexFeature = GET_PREDEFINED_FEATURE(pUiData->ci.pUIInfo, GID_DUPLEX);
|
||
pNupItem = PFindOptItemWithUserData(pUiData, NUP_ITEM);
|
||
pDuplexItem = PFindOptItemWithUserData(pUiData, DUPLEX_ITEM);
|
||
|
||
if (pDuplexFeature && pDuplexItem)
|
||
{
|
||
dwFeatureIndex = GET_INDEX_FROM_FEATURE(pUiData->ci.pUIInfo, pDuplexFeature);
|
||
dwOptionIndex = pUiData->ci.pCombinedOptions[dwFeatureIndex].ubCurOptIndex;
|
||
pDuplexOption = PGetIndexedOption(pUiData->ci.pUIInfo, pDuplexFeature, dwOptionIndex);
|
||
}
|
||
|
||
if ((GETUSERDATAITEM(pCurItem->UserData) == NUP_ITEM) &&
|
||
pCurItem->Sel == BOOKLET_UP)
|
||
{
|
||
if (pDuplexOption && pDuplexOption->dwDuplexID == DMDUP_SIMPLEX)
|
||
{
|
||
pDuplexOption = PGetIndexedOption(pUiData->ci.pUIInfo, pDuplexFeature, 0);
|
||
|
||
for (dwCount = 0 ; dwCount < pDuplexFeature->Options.dwCount; dwCount++)
|
||
{
|
||
if (pDuplexOption->dwDuplexID != DMDUP_SIMPLEX)
|
||
{
|
||
pDuplexItem->Sel = dwCount;
|
||
pDuplexItem->Flags |= OPTIF_CHANGED;
|
||
VUpdateOptionsArrayWithSelection(pUiData, pDuplexItem);
|
||
break;
|
||
}
|
||
pDuplexOption++;
|
||
}
|
||
|
||
}
|
||
}
|
||
else if ((GETUSERDATAITEM(pCurItem->UserData) == DUPLEX_ITEM) &&
|
||
pDuplexOption)
|
||
{
|
||
if (pDuplexOption->dwDuplexID == DMDUP_SIMPLEX &&
|
||
pNupItem &&
|
||
pNupItem->Sel == BOOKLET_UP)
|
||
{
|
||
pNupItem->Sel = TWO_UP;
|
||
pNupItem->Flags |= OPTIF_CHANGED;
|
||
NUPOPTION(pdmExtra) = TWO_UP;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
#ifdef UNIDRV
|
||
|
||
VOID
|
||
VSyncColorInformation(
|
||
PUIDATA pUiData,
|
||
POPTITEM pCurItem
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
|
||
Return Value:
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
POPTITEM pOptItem;
|
||
PFEATURE pFeature;
|
||
|
||
//
|
||
// This is a hack to work around the fact that Unidrv has
|
||
// two color options, color appearance and color mode option,
|
||
// need to update the other once one is changed
|
||
//
|
||
|
||
pOptItem = (GETUSERDATAITEM(pCurItem->UserData) == COLOR_ITEM) ?
|
||
PFindOptItemWithUserData(pUiData, COLORMODE_ITEM) :
|
||
(GETUSERDATAITEM(pCurItem->UserData) == COLORMODE_ITEM) ?
|
||
PFindOptItemWithUserData(pUiData, COLOR_ITEM) : NULL;
|
||
|
||
if ((pOptItem != NULL) &&
|
||
(pFeature = GET_PREDEFINED_FEATURE(pUiData->ci.pUIInfo, GID_COLORMODE)))
|
||
{
|
||
DWORD dwFeature = GET_INDEX_FROM_FEATURE(pUiData->ci.pUIInfo, pFeature);
|
||
|
||
//
|
||
// Find either color appearance or color mode option
|
||
//
|
||
|
||
if (GETUSERDATAITEM(pCurItem->UserData) == COLOR_ITEM)
|
||
{
|
||
ChangeOptionsViaID(
|
||
pUiData->ci.pInfoHeader,
|
||
pUiData->ci.pCombinedOptions,
|
||
GID_COLORMODE,
|
||
pUiData->ci.pdm);
|
||
|
||
pOptItem->Sel = pUiData->ci.pCombinedOptions[dwFeature].ubCurOptIndex;
|
||
pOptItem->Flags |= OPTIF_CHANGED;
|
||
}
|
||
else // COLORMODE_ITEM
|
||
{
|
||
POPTION pColorMode;
|
||
PCOLORMODEEX pColorModeEx;
|
||
|
||
pColorMode = PGetIndexedOption(
|
||
pUiData->ci.pUIInfo,
|
||
pFeature,
|
||
pCurItem->Sel);
|
||
|
||
if (pColorMode)
|
||
{
|
||
pColorModeEx = OFFSET_TO_POINTER(
|
||
pUiData->ci.pInfoHeader,
|
||
pColorMode->loRenderOffset);
|
||
|
||
if (pColorModeEx)
|
||
{
|
||
pOptItem->Sel = pColorModeEx->bColor ? 1: 0;
|
||
|
||
VUnpackDocumentPropertiesItems(pUiData, pOptItem, 1);
|
||
|
||
pOptItem->Flags |= OPTIF_CHANGED;
|
||
}
|
||
else
|
||
{
|
||
ERR(("pColorModeEx is NULL\n"));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ERR(("pColorMode is NULL\n"));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
DWORD
|
||
DwGetItemFromGID(
|
||
PFEATURE pFeature
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
|
||
Return Value:
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD dwItem = 0;
|
||
|
||
switch (pFeature->dwFeatureID)
|
||
{
|
||
case GID_PAGESIZE:
|
||
dwItem = FORMNAME_ITEM;
|
||
break;
|
||
|
||
case GID_DUPLEX:
|
||
dwItem = DUPLEX_ITEM;
|
||
break;
|
||
|
||
case GID_RESOLUTION:
|
||
dwItem = RESOLUTION_ITEM;
|
||
break;
|
||
|
||
case GID_MEDIATYPE:
|
||
dwItem = MEDIATYPE_ITEM;
|
||
break;
|
||
|
||
case GID_INPUTSLOT:
|
||
dwItem = INPUTSLOT_ITEM;
|
||
break;
|
||
|
||
case GID_COLORMODE:
|
||
dwItem = COLORMODE_ITEM;
|
||
break;
|
||
|
||
case GID_ORIENTATION:
|
||
dwItem = ORIENTATION_ITEM;
|
||
break;
|
||
|
||
case GID_PAGEPROTECTION:
|
||
dwItem = PAGE_PROTECT_ITEM;
|
||
break;
|
||
|
||
case GID_COLLATE:
|
||
dwItem = COPIES_COLLATE_ITEM;
|
||
break;
|
||
|
||
case GID_HALFTONING:
|
||
dwItem = HALFTONING_ITEM;
|
||
break;
|
||
|
||
default:
|
||
dwItem = UNKNOWN_ITEM;
|
||
break;
|
||
}
|
||
|
||
return dwItem;
|
||
}
|
||
|
||
|
||
PLISTNODE
|
||
PGetMacroList(
|
||
PUIDATA pUiData,
|
||
POPTITEM pMacroItem,
|
||
PGPDDRIVERINFO pDriverInfo
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
|
||
Return Value:
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PUIINFO pUIInfo = pUiData->ci.pUIInfo;
|
||
PLISTNODE pListNode = NULL;
|
||
LISTINDEX liIndex;
|
||
|
||
if (pMacroItem)
|
||
{
|
||
switch(pMacroItem->Sel)
|
||
{
|
||
case QS_BEST:
|
||
liIndex = pUIInfo->liBestQualitySettings;
|
||
break;
|
||
|
||
case QS_DRAFT:
|
||
liIndex = pUIInfo->liDraftQualitySettings;
|
||
break;
|
||
|
||
case QS_BETTER:
|
||
liIndex = pUIInfo->liBetterQualitySettings;
|
||
break;
|
||
}
|
||
|
||
pListNode = LISTNODEPTR(pDriverInfo, liIndex);
|
||
|
||
}
|
||
|
||
return pListNode;
|
||
|
||
}
|
||
|
||
VOID
|
||
VUpdateQualitySettingOptions(
|
||
PUIINFO pUIInfo,
|
||
POPTITEM pQualityItem
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
|
||
Return Value:
|
||
|
||
|
||
--*/
|
||
{
|
||
POPTPARAM pParam;
|
||
LISTINDEX liList;
|
||
DWORD i;
|
||
|
||
pParam = pQualityItem->pOptType->pOptParam;
|
||
|
||
for (i = QS_BEST; i < QS_BEST + MAX_QUALITY_SETTINGS; i++)
|
||
{
|
||
switch(i)
|
||
{
|
||
case QS_BEST:
|
||
liList = pUIInfo->liBestQualitySettings;
|
||
break;
|
||
|
||
case QS_BETTER:
|
||
liList = pUIInfo->liBetterQualitySettings;
|
||
break;
|
||
|
||
case QS_DRAFT:
|
||
liList = pUIInfo->liDraftQualitySettings;
|
||
break;
|
||
|
||
}
|
||
|
||
if (liList == END_OF_LIST)
|
||
{
|
||
pParam->Flags |= OPTPF_DISABLED;
|
||
pParam->dwReserved[0] = TRUE;
|
||
|
||
}
|
||
else
|
||
{
|
||
pParam->Flags &= ~OPTPF_DISABLED;
|
||
pParam->dwReserved[0] = FALSE;
|
||
|
||
}
|
||
pParam++;
|
||
}
|
||
pQualityItem->Flags |= OPTIF_CHANGED;
|
||
}
|
||
|
||
|
||
VOID
|
||
VMakeMacroSelections(
|
||
PUIDATA pUiData,
|
||
POPTITEM pCurItem
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
|
||
Return Value:
|
||
|
||
|
||
--*/
|
||
{
|
||
DWORD dwFeatureID, dwOptionID, dwItem, i;
|
||
PUIINFO pUIInfo;
|
||
POPTITEM pMacroItem, pOptItem;
|
||
PFEATURE pFeature;
|
||
PLISTNODE pListNode;
|
||
PGPDDRIVERINFO pDriverInfo;
|
||
BOOL bMatchFound = FALSE;
|
||
|
||
//
|
||
// Mark options array with the change to either
|
||
// Macro selection, media type, color
|
||
//
|
||
// Update binary data
|
||
// Make selection
|
||
//
|
||
|
||
if (pUiData->ci.pdmPrivate->dwFlags & DXF_CUSTOM_QUALITY)
|
||
return;
|
||
|
||
|
||
if (pCurItem)
|
||
VUnpackDocumentPropertiesItems(pUiData, pCurItem, 1);
|
||
|
||
pMacroItem = PFindOptItemWithUserData(pUiData, QUALITY_SETTINGS_ITEM);
|
||
|
||
//
|
||
// BUpdateUIInfo calls UpdateBinaryData to get new snapshot
|
||
// for latest optionarray
|
||
//
|
||
|
||
if (pMacroItem == NULL || !BUpdateUIInfo(&pUiData->ci) )
|
||
return;
|
||
|
||
pUIInfo = pUiData->ci.pUIInfo;
|
||
|
||
pDriverInfo = OFFSET_TO_POINTER(pUiData->ci.pInfoHeader,
|
||
pUiData->ci.pInfoHeader->loDriverOffset);
|
||
|
||
//
|
||
// Update the macro selection to reflect the current default
|
||
//
|
||
|
||
if (pCurItem && GETUSERDATAITEM(pCurItem->UserData) != QUALITY_SETTINGS_ITEM)
|
||
{
|
||
ASSERT(pUIInfo->defaultQuality != END_OF_LIST);
|
||
|
||
if (pUIInfo->defaultQuality == END_OF_LIST)
|
||
return;
|
||
|
||
pMacroItem->Sel = pUIInfo->defaultQuality;
|
||
VUnpackDocumentPropertiesItems(pUiData, pMacroItem, 1);
|
||
pMacroItem->Flags |= OPTIF_CHANGED;
|
||
|
||
}
|
||
|
||
//
|
||
// Determine which item to gray out based on the
|
||
// liBestQualitySettings, liBetterQualitySettings, liDraftQualitySettings
|
||
//
|
||
|
||
VUpdateQualitySettingOptions(pUIInfo, pMacroItem);
|
||
|
||
pListNode = PGetMacroList(pUiData, pMacroItem, pDriverInfo);
|
||
|
||
//
|
||
// Make the selction of Feature.Option
|
||
//
|
||
|
||
while (pListNode)
|
||
{
|
||
//
|
||
// Search thru our list of OPTITEM for the matching
|
||
// Feature
|
||
//
|
||
|
||
pOptItem = pUiData->pDrvOptItem;
|
||
dwFeatureID = ((PQUALNAME)(&pListNode->dwData))->wFeatureID;
|
||
dwOptionID = ((PQUALNAME)(&pListNode->dwData))->wOptionID;
|
||
|
||
pFeature = (PFEATURE)((PBYTE)pUIInfo->pInfoHeader + pUIInfo->loFeatureList) + dwFeatureID;
|
||
dwItem = DwGetItemFromGID(pFeature);
|
||
|
||
for (i = 0; i < pUiData->dwDrvOptItem; i++)
|
||
{
|
||
if (ISPRINTERFEATUREITEM(pOptItem->UserData))
|
||
{
|
||
PFEATURE pPrinterFeature = (PFEATURE)GETUSERDATAITEM(pOptItem->UserData);
|
||
|
||
if (GET_INDEX_FROM_FEATURE(pUIInfo, pPrinterFeature) == dwFeatureID)
|
||
bMatchFound = TRUE;
|
||
}
|
||
else
|
||
{
|
||
if (dwItem != UNKNOWN_ITEM &&
|
||
dwItem == GETUSERDATAITEM(pOptItem->UserData))
|
||
bMatchFound = TRUE;
|
||
}
|
||
|
||
if (bMatchFound)
|
||
{
|
||
pOptItem->Sel = dwOptionID;
|
||
pOptItem->Flags |= OPTIF_CHANGED;
|
||
VUnpackDocumentPropertiesItems(pUiData, pOptItem, 1);
|
||
bMatchFound = FALSE;
|
||
break;
|
||
}
|
||
|
||
pOptItem++;
|
||
}
|
||
|
||
pListNode = LISTNODEPTR(pDriverInfo, pListNode->dwNextItem);
|
||
}
|
||
|
||
}
|
||
|
||
VOID
|
||
VUpdateMacroSelection(
|
||
PUIDATA pUiData,
|
||
POPTITEM pCurItem
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
|
||
Return Value:
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
DWORD dwFeatureIndex;
|
||
PFEATURE pFeature = NULL;
|
||
PLISTNODE pListNode;
|
||
POPTITEM pMacroItem;
|
||
PGPDDRIVERINFO pDriverInfo;
|
||
|
||
pMacroItem = PFindOptItemWithUserData(pUiData, QUALITY_SETTINGS_ITEM);
|
||
|
||
if (pMacroItem == NULL)
|
||
return;
|
||
|
||
pDriverInfo = OFFSET_TO_POINTER(pUiData->ci.pInfoHeader,
|
||
pUiData->ci.pInfoHeader->loDriverOffset);
|
||
|
||
if (!(pFeature = PGetFeatureFromItem(pUiData->ci.pUIInfo, pCurItem, &dwFeatureIndex)))
|
||
return;
|
||
|
||
ASSERT(pDriverInfo);
|
||
|
||
pListNode = PGetMacroList(pUiData, pMacroItem, pDriverInfo);
|
||
|
||
while (pListNode)
|
||
{
|
||
if ( ((PQUALNAME)(&pListNode->dwData))->wFeatureID == (WORD)dwFeatureIndex)
|
||
{
|
||
pMacroItem->Flags |= OPTIF_ECB_CHECKED;
|
||
_VUnpackDocumentOptions(pMacroItem, pUiData->ci.pdm);
|
||
break;
|
||
}
|
||
|
||
pListNode = LISTNODEPTR(pDriverInfo, pListNode->dwNextItem);
|
||
}
|
||
}
|
||
|
||
#endif //UNIDRV
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|