|
|
/*++
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, _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->dmFields & DM_COLOR) && (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
|