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

3337 lines
85 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. docprop.c
  5. Abstract:
  6. This file handles the DrvDocumentProperties and
  7. DrvDocumentPropertySheets spooler API
  8. Environment:
  9. Win32 subsystem, DriverUI module, user mode
  10. Revision History:
  11. 02/13/97 -davidx-
  12. Implement OEM plugin support.
  13. 02/13/97 -davidx-
  14. Working only with options array internally.
  15. 02/10/97 -davidx-
  16. Consistent handling of common printer info.
  17. 02/04/97 -davidx-
  18. Reorganize driver UI to separate ps and uni DLLs.
  19. 07/17/96 -amandan-
  20. Created it.
  21. --*/
  22. #include "precomp.h"
  23. //
  24. // Local and external function declarations
  25. //
  26. LONG LSimpleDocumentProperties( PDOCUMENTPROPERTYHEADER);
  27. CPSUICALLBACK cpcbDocumentPropertyCallback(PCPSUICBPARAM);
  28. BOOL BGetPageOrderFlag(PCOMMONINFO);
  29. VOID VUpdateEmfFeatureItems(PUIDATA, BOOL);
  30. VOID VUpdateBookletOption(PUIDATA , POPTITEM);
  31. LONG
  32. DrvDocumentPropertySheets(
  33. PPROPSHEETUI_INFO pPSUIInfo,
  34. LPARAM lParam
  35. )
  36. /*++
  37. Routine Description:
  38. This function is called to add the Document Property Page to the specified
  39. property sheets and/or to update the document properties.
  40. If pPSUIInfo is NULL, it performs the operation specified by the fMode flag of
  41. DOCUMENTPROPERTYHEADER. Specifically, if flMode is zero or pDPHdr->pdmOut
  42. is NULL, return the size of DEVMODE.
  43. If pPSUInfo is not NULL: pPSUIInf->Reason
  44. REASON_INIT- fills PCOMPROPSHEETUI with document UI items
  45. calls compstui to add the page.
  46. REASON_GET_INFO_HEADER - fills out PROPSHEETUI_INFO.
  47. REASON_SET_RESULT - saves devmode settings and copy the devmode into output buffer.
  48. REASON_DESTROY - Cleans up.
  49. Arguments:
  50. pSUIInfo - pointer to PPROPSHEETUI_INFO
  51. lParam - varies depending on the reason this function is called
  52. Return Value:
  53. > 0 success <= 0 for failure
  54. --*/
  55. {
  56. PDOCUMENTPROPERTYHEADER pDPHdr;
  57. PCOMPROPSHEETUI pCompstui;
  58. PUIDATA pUiData;
  59. PDLGPAGE pDlgPage;
  60. LONG lRet;
  61. BOOL bResult=FALSE;
  62. //
  63. // Validate input parameters
  64. //
  65. if (! (pDPHdr = (PDOCUMENTPROPERTYHEADER) (pPSUIInfo ? pPSUIInfo->lParamInit : lParam)))
  66. {
  67. RIP(("DrvDocumentPropertySheets: invalid parameters\n"));
  68. return -1;
  69. }
  70. //
  71. // pPSUIInfo = NULL, the caller is spooler so just handle the simple case,
  72. // no display is necessary.
  73. //
  74. if (pPSUIInfo == NULL)
  75. return LSimpleDocumentProperties(pDPHdr);
  76. //
  77. // Create a UIDATA structure if necessary
  78. //
  79. if (pPSUIInfo->Reason == PROPSHEETUI_REASON_INIT)
  80. {
  81. pUiData = PFillUiData(pDPHdr->hPrinter,
  82. pDPHdr->pszPrinterName,
  83. pDPHdr->pdmIn,
  84. MODE_DOCUMENT_STICKY);
  85. }
  86. else
  87. pUiData = (PUIDATA) pPSUIInfo->UserData;
  88. //
  89. // Validate pUiData
  90. //
  91. if (pUiData == NULL)
  92. {
  93. ERR(("UIDATA is NULL\n"));
  94. return -1;
  95. }
  96. ASSERT(VALIDUIDATA(pUiData));
  97. //
  98. // Handle various cases for which this function might be called
  99. //
  100. switch (pPSUIInfo->Reason)
  101. {
  102. case PROPSHEETUI_REASON_INIT:
  103. //
  104. // Allocate memory and partially fill out various data
  105. // structures required to call common UI routine.
  106. //
  107. pDlgPage = (pDPHdr->fMode & DM_ADVANCED) ?
  108. CPSUI_PDLGPAGE_ADVDOCPROP :
  109. CPSUI_PDLGPAGE_DOCPROP;
  110. pUiData->bPermission = ((pDPHdr->fMode & DM_NOPERMISSION) == 0);
  111. #ifdef PSCRIPT
  112. FOREACH_OEMPLUGIN_LOOP((&(pUiData->ci)))
  113. if (HAS_COM_INTERFACE(pOemEntry))
  114. {
  115. HRESULT hr;
  116. hr = HComOEMHideStandardUI(pOemEntry,
  117. OEMCUIP_DOCPROP);
  118. //
  119. // In the case when multiple plugins are chained, it doesn't
  120. // make sense for one plugin to hide standard UI when another
  121. // one still wants to use the standard UI. So as long as one
  122. // plugin returns S_OK here, we will hide the standard UI.
  123. //
  124. if (bResult = SUCCEEDED(hr))
  125. break;
  126. }
  127. END_OEMPLUGIN_LOOP
  128. #endif // PSCRIPT
  129. if (bResult)
  130. {
  131. //
  132. // Set the flag to indicate plugin is hiding our standard
  133. // document property sheet UI.
  134. //
  135. pUiData->dwHideFlags |= HIDEFLAG_HIDE_STD_DOCPROP;
  136. pUiData->pfnComPropSheet = pPSUIInfo->pfnComPropSheet;
  137. pUiData->hComPropSheet = pPSUIInfo->hComPropSheet;
  138. if (BAddOemPluginPages(pUiData, pDPHdr->fMode))
  139. {
  140. pPSUIInfo->UserData = (ULONG_PTR) pUiData;
  141. pPSUIInfo->Result = CPSUI_CANCEL;
  142. lRet = 1;
  143. break;
  144. }
  145. }
  146. else if (pCompstui = PPrepareDataForCommonUI(pUiData, pDlgPage))
  147. {
  148. #ifdef UNIDRV
  149. VMakeMacroSelections(pUiData, NULL);
  150. #endif
  151. pCompstui->pfnCallBack = cpcbDocumentPropertyCallback;
  152. pUiData->pfnComPropSheet = pPSUIInfo->pfnComPropSheet;
  153. pUiData->hComPropSheet = pPSUIInfo->hComPropSheet;
  154. pUiData->pCompstui = pCompstui;
  155. //
  156. // Indicate which items are constrained
  157. //
  158. VPropShowConstraints(pUiData, MODE_DOCANDPRINTER_STICKY);
  159. //
  160. // Call common UI library to add our pages
  161. //
  162. if (pUiData->pfnComPropSheet(pUiData->hComPropSheet,
  163. CPSFUNC_ADD_PCOMPROPSHEETUI,
  164. (LPARAM) pCompstui,
  165. (LPARAM) &lRet) &&
  166. BAddOemPluginPages(pUiData, pDPHdr->fMode))
  167. {
  168. pPSUIInfo->UserData = (ULONG_PTR) pUiData;
  169. pPSUIInfo->Result = CPSUI_CANCEL;
  170. lRet = 1;
  171. break;
  172. }
  173. }
  174. //
  175. // Clean up in the case of error
  176. //
  177. ERR(("Failed to initialize property sheets\n"));
  178. VFreeUiData(pUiData);
  179. return -1;
  180. case PROPSHEETUI_REASON_GET_INFO_HEADER:
  181. {
  182. PPROPSHEETUI_INFO_HEADER pPSUIHdr;
  183. DWORD dwIcon;
  184. pPSUIHdr = (PPROPSHEETUI_INFO_HEADER) lParam;
  185. pPSUIHdr->Flags = PSUIHDRF_PROPTITLE | PSUIHDRF_NOAPPLYNOW;
  186. pPSUIHdr->pTitle = pUiData->ci.pPrinterName;
  187. pPSUIHdr->hInst = ghInstance;
  188. //
  189. // Use the Icon specified in the binary data as
  190. // the printer icon.
  191. //
  192. dwIcon = pUiData->ci.pUIInfo->loPrinterIcon;
  193. if (dwIcon && (pPSUIHdr->IconID = HLoadIconFromResourceDLL(&pUiData->ci, dwIcon)))
  194. pPSUIHdr->Flags |= PSUIHDRF_USEHICON;
  195. else
  196. pPSUIHdr->IconID = _DwGetPrinterIconID();
  197. }
  198. lRet = 1;
  199. break;
  200. case PROPSHEETUI_REASON_SET_RESULT:
  201. //
  202. // Copy the new devmode back into the output buffer provided by the caller
  203. // Always return the smaller of current and input devmode
  204. //
  205. {
  206. PSETRESULT_INFO pSRInfo = (PSETRESULT_INFO) lParam;
  207. if ((pSRInfo->Result == CPSUI_OK) &&
  208. (pDPHdr->pdmOut != NULL) &&
  209. (pDPHdr->fMode & (DM_COPY | DM_UPDATE)))
  210. {
  211. PCOMMONINFO pci = (PCOMMONINFO)pUiData;
  212. //
  213. // CPSUICB_REASON_APPLYNOW may not have been called. If so, we need
  214. // to perform tasks that are usually done by CPSUICB_REASON_APPLYNOW
  215. // case in our callback function cpcbDocumentPropertyCallback.
  216. //
  217. if (!(pci->dwFlags & FLAG_APPLYNOW_CALLED))
  218. {
  219. OPTSELECT OldCombinedOptions[MAX_COMBINED_OPTIONS];
  220. //
  221. // Save a copy the pre-resolve option array
  222. //
  223. CopyMemory(OldCombinedOptions,
  224. pci->pCombinedOptions,
  225. MAX_COMBINED_OPTIONS * sizeof(OPTSELECT));
  226. //
  227. // Call the parsers to resolve any remaining conflicts.
  228. //
  229. ResolveUIConflicts(pci->pRawData,
  230. pci->pCombinedOptions,
  231. MAX_COMBINED_OPTIONS,
  232. MODE_DOCANDPRINTER_STICKY);
  233. //
  234. // Update the OPTITEM list to match the updated options array
  235. //
  236. VUpdateOptItemList(pUiData, OldCombinedOptions, pci->pCombinedOptions);
  237. //
  238. // Transfer information from options array to public devmode fields
  239. //
  240. VOptionsToDevmodeFields(&pUiData->ci, FALSE);
  241. //
  242. // Separate the doc-sticky options from the combined array
  243. // and save it back to the private devmode aOptions array
  244. //
  245. SeparateOptionArray(
  246. pci->pRawData,
  247. pci->pCombinedOptions,
  248. PGetDevmodeOptionsArray(pci->pdm),
  249. MAX_PRINTER_OPTIONS,
  250. MODE_DOCUMENT_STICKY);
  251. }
  252. BConvertDevmodeOut(pci->pdm,
  253. pDPHdr->pdmIn,
  254. pDPHdr->pdmOut);
  255. }
  256. pPSUIInfo->Result = pSRInfo->Result;
  257. }
  258. lRet = 1;
  259. break;
  260. case PROPSHEETUI_REASON_DESTROY:
  261. //
  262. // Clean up
  263. //
  264. VFreeUiData(pUiData);
  265. lRet = 1;
  266. break;
  267. default:
  268. ERR(("Unknown reason in DrvDocumentPropertySheets\n"));
  269. return -1;
  270. }
  271. return lRet;
  272. }
  273. LONG
  274. LSimpleDocumentProperties(
  275. IN OUT PDOCUMENTPROPERTYHEADER pDPHdr
  276. )
  277. /*++
  278. Routine Description:
  279. Handle simple "Document Properties" where we don't need to display
  280. a dialog and therefore don't have to have common UI library involved
  281. Mainly, devmode handling - update, merge, copy etc.
  282. Arguments:
  283. pDPHdr - Points to a DOCUMENTPROPERTYHEADER structure
  284. Return Value:
  285. > 0 if successful, <= 0 otherwise
  286. --*/
  287. {
  288. PCOMMONINFO pci;
  289. DWORD dwSize;
  290. PPRINTER_INFO_2 pPrinterInfo2;
  291. //
  292. // Load common printer info
  293. //
  294. pci = PLoadCommonInfo(pDPHdr->hPrinter, pDPHdr->pszPrinterName, 0);
  295. if (!pci || !BCalcTotalOEMDMSize(pci->hPrinter, pci->pOemPlugins, &dwSize))
  296. {
  297. VFreeCommonInfo(pci);
  298. return -1;
  299. }
  300. //
  301. // Check if the caller is interested in the size only
  302. //
  303. pDPHdr->cbOut = sizeof(DEVMODE) + gDriverDMInfo.dmDriverExtra + dwSize;
  304. if (pDPHdr->fMode == 0 || pDPHdr->pdmOut == NULL)
  305. {
  306. VFreeCommonInfo(pci);
  307. return pDPHdr->cbOut;
  308. }
  309. //
  310. // Merge the input devmode with the driver and system default devmodes
  311. //
  312. if (! (pPrinterInfo2 = MyGetPrinter(pci->hPrinter, 2)) ||
  313. ! BFillCommonInfoDevmode(pci, pPrinterInfo2->pDevMode, pDPHdr->pdmIn))
  314. {
  315. MemFree(pPrinterInfo2);
  316. VFreeCommonInfo(pci);
  317. return -1;
  318. }
  319. MemFree(pPrinterInfo2);
  320. //
  321. // Copy the devmode back into the output buffer provided by the caller
  322. // Always return the smaller of current and input devmode
  323. //
  324. if (pDPHdr->fMode & (DM_COPY | DM_UPDATE))
  325. (VOID) BConvertDevmodeOut(pci->pdm, pDPHdr->pdmIn, pDPHdr->pdmOut);
  326. //
  327. // Clean up before returning to caller
  328. //
  329. VFreeCommonInfo(pci);
  330. return 1;
  331. }
  332. VOID
  333. VRestoreDefaultFeatureSelection(
  334. IN OUT PUIDATA pUiData
  335. )
  336. /*++
  337. Routine Description:
  338. Restore the printer feature selections to their default state
  339. Arguments:
  340. pUiData - Points to our UIDATA structure
  341. Return Value:
  342. NONE
  343. --*/
  344. {
  345. POPTSELECT pOptionsArray;
  346. PFEATURE pFeature;
  347. POPTITEM pOptItem;
  348. DWORD dwCount, dwFeatureIndex, dwDefault;
  349. PUIINFO pUIInfo;
  350. //
  351. // Go through each printer feature item and check to see if
  352. // its current selection matches the default value
  353. //
  354. pUIInfo = pUiData->ci.pUIInfo;
  355. pOptionsArray = pUiData->ci.pCombinedOptions;
  356. pOptItem = pUiData->pFeatureItems;
  357. dwCount = pUiData->dwFeatureItem;
  358. for ( ; dwCount--; pOptItem++)
  359. {
  360. pFeature = (PFEATURE) GETUSERDATAITEM(pOptItem->UserData);
  361. dwFeatureIndex = GET_INDEX_FROM_FEATURE(pUIInfo, pFeature);
  362. dwDefault = pFeature->dwDefaultOptIndex;
  363. //
  364. // If the current selection doesn't match the default,
  365. // restore it to the default value.
  366. //
  367. if (pOptionsArray[dwFeatureIndex].ubCurOptIndex != dwDefault)
  368. {
  369. pOptionsArray[dwFeatureIndex].ubCurOptIndex = (BYTE) dwDefault;
  370. pOptItem->Flags |= OPTIF_CHANGED;
  371. pOptItem->Sel = (dwDefault == OPTION_INDEX_ANY) ? 0 : dwDefault;
  372. }
  373. }
  374. //
  375. // Update the display and indicate which items are constrained
  376. //
  377. VPropShowConstraints(pUiData, MODE_DOCANDPRINTER_STICKY);
  378. }
  379. VOID
  380. VOptionsToDevmodeFields(
  381. IN OUT PCOMMONINFO pci,
  382. IN BOOL bUpdateFormFields
  383. )
  384. /*++
  385. Routine Description:
  386. Convert options in pUiData->pOptionsArray into public devmode fields
  387. Arguments:
  388. pci - Points to basic printer info
  389. bUpdateFormFields - Whether or not to convert paper size option into devmode
  390. Return Value:
  391. None
  392. --*/
  393. {
  394. PFEATURE pFeature;
  395. POPTION pOption;
  396. DWORD dwGID, dwFeatureIndex, dwOptionIndex;
  397. PUIINFO pUIInfo;
  398. PDEVMODE pdm;
  399. //
  400. // Go through all predefine IDs and propage the option selection
  401. // into appropriate devmode fields
  402. //
  403. pUIInfo = pci->pUIInfo;
  404. pdm = pci->pdm;
  405. for (dwGID=0 ; dwGID < MAX_GID ; dwGID++)
  406. {
  407. //
  408. // Get the feature to get the options, and get the index
  409. // into the option array
  410. //
  411. if ((pFeature = GET_PREDEFINED_FEATURE(pUIInfo, dwGID)) == NULL)
  412. continue;
  413. dwFeatureIndex = GET_INDEX_FROM_FEATURE(pUIInfo, pFeature);
  414. dwOptionIndex = pci->pCombinedOptions[dwFeatureIndex].ubCurOptIndex;
  415. //
  416. // Get the pointer to the option array for the feature
  417. //
  418. if ((pOption = PGetIndexedOption(pUIInfo, pFeature, dwOptionIndex)) == NULL)
  419. continue;
  420. switch(dwGID)
  421. {
  422. case GID_RESOLUTION:
  423. {
  424. PRESOLUTION pRes = (PRESOLUTION)pOption;
  425. //
  426. // Get to the option selected
  427. //
  428. pdm->dmFields |= (DM_PRINTQUALITY|DM_YRESOLUTION);
  429. pdm->dmPrintQuality = GETQUALITY_X(pRes);
  430. pdm->dmYResolution = GETQUALITY_Y(pRes);
  431. }
  432. break;
  433. case GID_DUPLEX:
  434. //
  435. // Get to the option selected
  436. //
  437. pdm->dmFields |= DM_DUPLEX;
  438. pdm->dmDuplex = (SHORT) ((PDUPLEX) pOption)->dwDuplexID;
  439. break;
  440. case GID_INPUTSLOT:
  441. //
  442. // Get to the option selected
  443. //
  444. pdm->dmFields |= DM_DEFAULTSOURCE;
  445. pdm->dmDefaultSource = (SHORT) ((PINPUTSLOT) pOption)->dwPaperSourceID;
  446. break;
  447. case GID_MEDIATYPE:
  448. //
  449. // Get to the option selected
  450. //
  451. pdm->dmFields |= DM_MEDIATYPE;
  452. pdm->dmMediaType = (SHORT) ((PMEDIATYPE) pOption)->dwMediaTypeID;
  453. break;
  454. case GID_ORIENTATION:
  455. if (((PORIENTATION) pOption)->dwRotationAngle == ROTATE_NONE)
  456. pdm->dmOrientation = DMORIENT_PORTRAIT;
  457. else
  458. pdm->dmOrientation = DMORIENT_LANDSCAPE;
  459. pdm->dmFields |= DM_ORIENTATION;
  460. break;
  461. //
  462. // Fix #2822: VOptionsToDevmodeFields should be called after calling
  463. // VFixOptionsArrayWithDevmode and ResolveUIConflicts, which could
  464. // change option array to be out of sync with devmode.
  465. //
  466. case GID_COLLATE:
  467. pdm->dmFields |= DM_COLLATE;
  468. pdm->dmCollate = (SHORT) ((PCOLLATE) pOption)->dwCollateID;
  469. break;
  470. case GID_PAGESIZE:
  471. {
  472. PPAGESIZE pPageSize = (PPAGESIZE)pOption;
  473. WCHAR awchBuf[CCHPAPERNAME];
  474. //
  475. // Ignore the custom page size option. We don't add custom page size option to the
  476. // form database, see BAddOrUpgradePrinterForms(). Also see BQueryPrintForm() for
  477. // special handling of custom page size for DDI DevQueryPrintEx().
  478. //
  479. if (pPageSize->dwPaperSizeID == DMPAPER_USER ||
  480. pPageSize->dwPaperSizeID == DMPAPER_CUSTOMSIZE)
  481. {
  482. VERBOSE(("VOptionsToDevmodeFields: %d ignored\n", pPageSize->dwPaperSizeID));
  483. break;
  484. }
  485. //
  486. // bUpdateFormFields should be FALSE if we don't want to overwrite devmode form
  487. // fields with our option array's page size setting. One case of this is when
  488. // user hits the doc-setting UI's OK buttion, at that time we need to propagate
  489. // our internal devmode to app's output devmode. See cpcbDocumentPropertyCallback().
  490. // That's because in option array we could have already mapped devmode's form request
  491. // to a paper size the printer supports (example: devmode requets Legal, we map
  492. // it to the printer's form OEM_Legal). So we don't want to overwrite output devmode
  493. // form fields with our internal option.
  494. //
  495. if (!bUpdateFormFields)
  496. break;
  497. if (!LOAD_STRING_PAGESIZE_NAME(pci, pPageSize, awchBuf, CCHPAPERNAME))
  498. {
  499. ERR(("VOptionsToDevmodeFields: cannot get paper name\n"));
  500. break;
  501. }
  502. pdm->dmFields &= ~(DM_PAPERWIDTH|DM_PAPERLENGTH|DM_PAPERSIZE);
  503. pdm->dmFields |= DM_FORMNAME;
  504. CopyString(pdm->dmFormName, awchBuf, CCHFORMNAME);
  505. if (!BValidateDevmodeFormFields(
  506. pci->hPrinter,
  507. pdm,
  508. NULL,
  509. pci->pSplForms,
  510. pci->dwSplForms))
  511. {
  512. VDefaultDevmodeFormFields(pUIInfo, pdm, IsMetricCountry());
  513. }
  514. }
  515. break;
  516. }
  517. }
  518. }
  519. CPSUICALLBACK
  520. cpcbDocumentPropertyCallback(
  521. IN OUT PCPSUICBPARAM pCallbackParam
  522. )
  523. /*++
  524. Routine Description:
  525. Callback function provided to common UI DLL for handling
  526. document properties dialog.
  527. Arguments:
  528. pCallbackParam - Pointer to CPSUICBPARAM structure
  529. Return Value:
  530. CPSUICB_ACTION_NONE - no action needed
  531. CPSUICB_ACTION_OPTIF_CHANGED - items changed and should be refreshed
  532. --*/
  533. {
  534. PUIDATA pUiData;
  535. POPTITEM pCurItem, pOptItem;
  536. LONG lRet;
  537. PFEATURE pFeature;
  538. pUiData = (PUIDATA) pCallbackParam->UserData;
  539. ASSERT(pUiData != NULL);
  540. pUiData->hDlg = pCallbackParam->hDlg;
  541. pCurItem = pCallbackParam->pCurItem;
  542. lRet = CPSUICB_ACTION_NONE;
  543. //
  544. // If user has no permission to change anything, then
  545. // simply return without taking any action.
  546. //
  547. if (!HASPERMISSION(pUiData) && (pCallbackParam->Reason != CPSUICB_REASON_ABOUT))
  548. return lRet;
  549. switch (pCallbackParam->Reason)
  550. {
  551. case CPSUICB_REASON_SEL_CHANGED:
  552. case CPSUICB_REASON_ECB_CHANGED:
  553. if (! IS_DRIVER_OPTITEM(pUiData, pCurItem))
  554. break;
  555. //
  556. // Everytime the user make any changes, we update the
  557. // pOptionsArray. These settings are not saved to the devmode
  558. // until the user hit OK.
  559. //
  560. // VUnpackDocumentPropertiesItems saves the settings to pUiData->pOptionsArray
  561. // and update the private devmode flags if applicable.
  562. // ICheckConstraintsDlg check if the user has selected a constrained option
  563. //
  564. VUnpackDocumentPropertiesItems(pUiData, pCurItem, 1);
  565. #ifdef UNIDRV
  566. VSyncColorInformation(pUiData, pCurItem);
  567. //
  568. // Quality Macro support
  569. //
  570. if (GETUSERDATAITEM(pCurItem->UserData) == QUALITY_SETTINGS_ITEM ||
  571. GETUSERDATAITEM(pCurItem->UserData) == COLOR_ITEM ||
  572. GETUSERDATAITEM(pCurItem->UserData) == MEDIATYPE_ITEM ||
  573. ((pFeature = PGetFeatureFromItem(pUiData->ci.pUIInfo, pCurItem, NULL))&&
  574. pFeature->dwFlags & FEATURE_FLAG_UPDATESNAPSHOT))
  575. {
  576. VMakeMacroSelections(pUiData, pCurItem);
  577. //
  578. // Needs to update the constraints since Macro selection might have
  579. // changed the constraints
  580. //
  581. VPropShowConstraints(pUiData, MODE_DOCANDPRINTER_STICKY);
  582. VUpdateMacroSelection(pUiData, pCurItem);
  583. }
  584. else
  585. {
  586. //
  587. // Check whether the current selection invalidates the macros
  588. // and update QUALITY_SETTINGS_ITEM.
  589. VUpdateMacroSelection(pUiData, pCurItem);
  590. }
  591. #endif // UNIDRV
  592. #ifdef PSCRIPT
  593. if (GETUSERDATAITEM(pCurItem->UserData) == REVPRINT_ITEM)
  594. {
  595. VSyncRevPrintAndOutputOrder(pUiData, pCurItem);
  596. }
  597. #endif // PSCRIPT
  598. if (GETUSERDATAITEM(pCurItem->UserData) == METASPOOL_ITEM ||
  599. GETUSERDATAITEM(pCurItem->UserData) == NUP_ITEM ||
  600. GETUSERDATAITEM(pCurItem->UserData) == REVPRINT_ITEM ||
  601. GETUSERDATAITEM(pCurItem->UserData) == COPIES_COLLATE_ITEM ||
  602. ((pFeature = PGetFeatureFromItem(pUiData->ci.pUIInfo, pCurItem, NULL)) &&
  603. pFeature->dwFeatureID == GID_OUTPUTBIN))
  604. {
  605. VUpdateEmfFeatureItems(pUiData, GETUSERDATAITEM(pCurItem->UserData) != METASPOOL_ITEM);
  606. }
  607. #ifdef UNIDRV
  608. VSyncColorInformation(pUiData, pCurItem);
  609. #endif
  610. #ifdef PSCRIPT
  611. //
  612. // If the user has selected custom page size,
  613. // bring up the custom page size dialog now.
  614. //
  615. if (GETUSERDATAITEM(pCurItem->UserData) == FORMNAME_ITEM &&
  616. pCurItem->pExtPush != NULL)
  617. {
  618. if (pUiData->pwPapers[pCurItem->Sel] == DMPAPER_CUSTOMSIZE)
  619. {
  620. (VOID) BDisplayPSCustomPageSizeDialog(pUiData);
  621. pCurItem->Flags &= ~(OPTIF_EXT_HIDE | OPTIF_EXT_DISABLED);
  622. }
  623. else
  624. pCurItem->Flags |= (OPTIF_EXT_HIDE | OPTIF_EXT_DISABLED);
  625. pCurItem->Flags |= OPTIF_CHANGED;
  626. }
  627. #endif // PSCRIPT
  628. //
  629. // Update the display and indicate which items are constrained.
  630. //
  631. VPropShowConstraints(pUiData, MODE_DOCANDPRINTER_STICKY);
  632. lRet = CPSUICB_ACTION_REINIT_ITEMS;
  633. break;
  634. case CPSUICB_REASON_ITEMS_REVERTED:
  635. //
  636. // Unpack document properties treeview items
  637. //
  638. VUnpackDocumentPropertiesItems(pUiData,
  639. pUiData->pDrvOptItem,
  640. pUiData->dwDrvOptItem);
  641. //
  642. // Update the display and indicate which items are constrained
  643. //
  644. VPropShowConstraints(pUiData, MODE_DOCANDPRINTER_STICKY);
  645. lRet = CPSUICB_ACTION_OPTIF_CHANGED;
  646. break;
  647. case CPSUICB_REASON_EXTPUSH:
  648. #ifdef PSCRIPT
  649. if (GETUSERDATAITEM(pCurItem->UserData) == FORMNAME_ITEM)
  650. {
  651. //
  652. // Push button to bring up PostScript custom page size dialog
  653. //
  654. (VOID) BDisplayPSCustomPageSizeDialog(pUiData);
  655. }
  656. #endif // PSCRIPT
  657. if (pCurItem == pUiData->pFeatureHdrItem)
  658. {
  659. //
  660. // Push button for restoring all generic feature selections
  661. // to their default values
  662. //
  663. VRestoreDefaultFeatureSelection(pUiData);
  664. lRet = CPSUICB_ACTION_REINIT_ITEMS;
  665. }
  666. break;
  667. case CPSUICB_REASON_ABOUT:
  668. DialogBoxParam(ghInstance,
  669. MAKEINTRESOURCE(IDD_ABOUT),
  670. pUiData->hDlg,
  671. _AboutDlgProc,
  672. (LPARAM) pUiData);
  673. break;
  674. case CPSUICB_REASON_APPLYNOW:
  675. pUiData->ci.dwFlags |= FLAG_APPLYNOW_CALLED;
  676. //
  677. // Check if there are still any unresolved constraints left?
  678. // BOptItemSelectionsChanged returns TRUE or FALSE depending on
  679. // whether the user has made any changes to the options
  680. //
  681. if (((pUiData->ci.dwFlags & FLAG_PLUGIN_CHANGED_OPTITEM) ||
  682. BOptItemSelectionsChanged(pUiData->pDrvOptItem, pUiData->dwDrvOptItem)) &&
  683. ICheckConstraintsDlg(pUiData,
  684. pUiData->pDrvOptItem,
  685. pUiData->dwDrvOptItem,
  686. TRUE) == CONFLICT_CANCEL)
  687. {
  688. //
  689. // Conflicts found and user clicked CANCEL to
  690. // go back to the dialog without dismissing it.
  691. //
  692. lRet = CPSUICB_ACTION_NO_APPLY_EXIT;
  693. break;
  694. }
  695. //
  696. // Transfer information from options array to public devmode fields
  697. //
  698. VOptionsToDevmodeFields(&pUiData->ci, FALSE);
  699. //
  700. // Separate the doc-sticky options from the combined array
  701. // and save it back to the private devmode aOptions array
  702. //
  703. SeparateOptionArray(
  704. pUiData->ci.pRawData,
  705. pUiData->ci.pCombinedOptions,
  706. PGetDevmodeOptionsArray(pUiData->ci.pdm),
  707. MAX_PRINTER_OPTIONS,
  708. MODE_DOCUMENT_STICKY);
  709. pCallbackParam->Result = CPSUI_OK;
  710. lRet = CPSUICB_ACTION_ITEMS_APPLIED ;
  711. break;
  712. }
  713. return LInvokeOemPluginCallbacks(pUiData, pCallbackParam, lRet);
  714. }
  715. BOOL
  716. BPackItemFormName(
  717. IN OUT PUIDATA pUiData
  718. )
  719. /*++
  720. Routine Description:
  721. Pack Paper size options.
  722. Arguments:
  723. pUiData - Points to UIDATA structure
  724. Return Value:
  725. TRUE if successful, FALSE if there is an error.
  726. --*/
  727. {
  728. //
  729. // Extended push button for bringing up PostScript custom page size dialog
  730. //
  731. PFEATURE pFeature;
  732. static EXTPUSH ExtPush =
  733. {
  734. sizeof(EXTPUSH),
  735. EPF_NO_DOT_DOT_DOT,
  736. (PWSTR) IDS_EDIT_CUSTOMSIZE,
  737. NULL,
  738. 0,
  739. 0,
  740. };
  741. if (!(pFeature = GET_PREDEFINED_FEATURE(pUiData->ci.pUIInfo, GID_PAGESIZE)) ||
  742. pFeature->Options.dwCount < MIN_OPTIONS_ALLOWED ||
  743. pFeature->dwFlags & FEATURE_FLAG_NOUI)
  744. return TRUE;
  745. if (pUiData->pOptItem)
  746. {
  747. DWORD dwFormNames, dwIndex, dwSel, dwPageSizeIndex, dwOption;
  748. PWSTR pFormNames;
  749. POPTPARAM pOptParam;
  750. PUIINFO pUIInfo = pUiData->ci.pUIInfo;
  751. PFEATURE pPageSizeFeature;
  752. BOOL bSupported;
  753. dwFormNames = pUiData->dwFormNames;
  754. pFormNames = pUiData->pFormNames;
  755. //
  756. // Figure out the currently selected paper size option index
  757. //
  758. dwSel = DwFindFormNameIndex(pUiData, pUiData->ci.pdm->dmFormName, &bSupported);
  759. //
  760. // If the form is not supported on the printer, it could be the case
  761. // where the printer doesn't support a form with the same name, but
  762. // the printer can still support the requested form using exact or
  763. // closest paper size match.
  764. //
  765. // See function VFixOptionsArrayWithDevmode() and ChangeOptionsViaID().
  766. //
  767. if (!bSupported &&
  768. (pPageSizeFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_PAGESIZE)))
  769. {
  770. WCHAR awchBuf[CCHPAPERNAME];
  771. PPAGESIZE pPageSize;
  772. //
  773. // If we can't find a name match in the first DwFindFormNameIndex call,
  774. // the option array should already have the correct option index value
  775. // parser has decided to use to support the form. So now we only need
  776. // to load the option's display name and search in the form name list
  777. // again to get the paper size UI list index.
  778. //
  779. dwPageSizeIndex = GET_INDEX_FROM_FEATURE(pUIInfo, pPageSizeFeature);
  780. dwOption = pUiData->ci.pCombinedOptions[dwPageSizeIndex].ubCurOptIndex;
  781. if ((pPageSize = (PPAGESIZE)PGetIndexedOption(pUIInfo, pPageSizeFeature, dwOption)) &&
  782. LOAD_STRING_PAGESIZE_NAME(&(pUiData->ci), pPageSize, awchBuf, CCHPAPERNAME))
  783. {
  784. dwSel = DwFindFormNameIndex(pUiData, awchBuf, NULL);
  785. }
  786. }
  787. //
  788. // Fill out OPTITEM, OPTTYPE, and OPTPARAM structures
  789. //
  790. FILLOPTITEM(pUiData->pOptItem,
  791. pUiData->pOptType,
  792. ULongToPtr(IDS_CPSUI_FORMNAME),
  793. ULongToPtr(dwSel),
  794. TVITEM_LEVEL1,
  795. DMPUB_FORMNAME,
  796. FORMNAME_ITEM,
  797. HELP_INDEX_FORMNAME);
  798. pUiData->pOptType->Style = OTS_LBCB_SORT;
  799. pOptParam = PFillOutOptType(pUiData->pOptType,
  800. TVOT_LISTBOX,
  801. dwFormNames,
  802. pUiData->ci.hHeap);
  803. if (pOptParam == NULL)
  804. return FALSE;
  805. for (dwIndex=0; dwIndex < dwFormNames; dwIndex++)
  806. {
  807. pOptParam->cbSize = sizeof(OPTPARAM);
  808. pOptParam->pData = pFormNames;
  809. if (pUiData->pwPapers[dwIndex] == DMPAPER_CUSTOMSIZE)
  810. pOptParam->IconID = IDI_CUSTOM_PAGESIZE;
  811. else if (pOptParam->IconID = HLoadFormIconResource(pUiData, dwIndex))
  812. pOptParam->Flags |= OPTPF_ICONID_AS_HICON;
  813. else
  814. pOptParam->IconID = DwGuessFormIconID(pFormNames);
  815. pOptParam++;
  816. pFormNames += CCHPAPERNAME;
  817. }
  818. //
  819. // Special case for PostScript custom page size
  820. //
  821. #ifdef PSCRIPT
  822. {
  823. PPPDDATA pPpdData;
  824. pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER((PINFOHEADER) pUiData->ci.pRawData);
  825. ASSERT(pPpdData != NULL);
  826. if (SUPPORT_CUSTOMSIZE(pUIInfo) &&
  827. SUPPORT_FULL_CUSTOMSIZE_FEATURES(pUIInfo, pPpdData))
  828. {
  829. pUiData->pOptItem->Flags |= (OPTIF_EXT_IS_EXTPUSH|OPTIF_CALLBACK);
  830. pUiData->pOptItem->pExtPush = &ExtPush;
  831. //
  832. // If PostScript custom page size is selected,
  833. // select the last item of form name list.
  834. //
  835. if (pUiData->ci.pdm->dmPaperSize == DMPAPER_CUSTOMSIZE)
  836. {
  837. pUiData->pOptItem->Sel = pUiData->dwFormNames - 1;
  838. pUiData->pOptItem->Flags &= ~(OPTIF_EXT_HIDE | OPTIF_EXT_DISABLED);
  839. }
  840. else
  841. pUiData->pOptItem->Flags |= (OPTIF_EXT_HIDE | OPTIF_EXT_DISABLED);
  842. }
  843. }
  844. #endif // PSCRIPT
  845. #ifdef UNIDRV
  846. //
  847. // Supports OEM help file. If helpfile and helpindex are defined,
  848. // we will use the help id specified by the GPD. According to GPD spec,
  849. // zero loHelpFileName means no help file name specified.
  850. //
  851. if (pUIInfo->loHelpFileName &&
  852. pFeature->iHelpIndex != UNUSED_ITEM)
  853. {
  854. POIEXT pOIExt = HEAPALLOC(pUiData->ci.hHeap, sizeof(OIEXT));
  855. if (pOIExt)
  856. {
  857. pOIExt->cbSize = sizeof(OIEXT);
  858. pOIExt->Flags = 0;
  859. pOIExt->hInstCaller = NULL;
  860. pOIExt->pHelpFile = OFFSET_TO_POINTER(pUIInfo->pubResourceData,
  861. pUIInfo->loHelpFileName);
  862. pUiData->pOptItem->pOIExt = pOIExt;
  863. pUiData->pOptItem->HelpIndex = pFeature->iHelpIndex;
  864. pUiData->pOptItem->Flags |= OPTIF_HAS_POIEXT;
  865. }
  866. }
  867. #endif // UNIDRV
  868. //
  869. // Set the Keyword name for pOptItem->UserData
  870. //
  871. SETUSERDATA_KEYWORDNAME(pUiData->ci, pUiData->pOptItem, pFeature);
  872. pUiData->pOptItem++;
  873. pUiData->pOptType++;
  874. }
  875. pUiData->dwOptItem++;
  876. pUiData->dwOptType++;
  877. return TRUE;
  878. }
  879. BOOL
  880. BPackItemInputSlot(
  881. IN OUT PUIDATA pUiData
  882. )
  883. /*++
  884. Routine Description:
  885. Pack paper source option.
  886. Arguments:
  887. pUiData - Points to UIDATA structure
  888. Return Value:
  889. TRUE if successful, FALSE if there is an error.
  890. --*/
  891. {
  892. POPTTYPE pOptType;
  893. PFEATURE pFeature;
  894. PINPUTSLOT pInputSlot;
  895. pFeature = GET_PREDEFINED_FEATURE(pUiData->ci.pUIInfo, GID_INPUTSLOT);
  896. pOptType = pUiData->pOptType;
  897. if (! BPackItemPrinterFeature(
  898. pUiData,
  899. pFeature,
  900. TVITEM_LEVEL1,
  901. DMPUB_DEFSOURCE,
  902. (ULONG_PTR)INPUTSLOT_ITEM,
  903. HELP_INDEX_INPUT_SLOT))
  904. {
  905. return FALSE;
  906. }
  907. //
  908. // NOTE: if the first input slot has dwPaperSourceID == DMBIN_FORMSOURCE,
  909. // then we'll change its display name to "Automatically Select".
  910. //
  911. if (pOptType != NULL && pOptType != pUiData->pOptType)
  912. {
  913. ASSERT(pFeature != NULL);
  914. pInputSlot = PGetIndexedOption(pUiData->ci.pUIInfo, pFeature, 0);
  915. ASSERT(pInputSlot != NULL);
  916. if (pInputSlot->dwPaperSourceID == DMBIN_FORMSOURCE)
  917. pOptType->pOptParam[0].pData = (PWSTR) IDS_TRAY_FORMSOURCE;
  918. }
  919. return TRUE;
  920. }
  921. BOOL
  922. BPackItemMediaType(
  923. IN OUT PUIDATA pUiData
  924. )
  925. /*++
  926. Routine Description:
  927. Pack media type option.
  928. Arguments:
  929. pUiData - Points to UIDATA structure
  930. Return Value:
  931. TRUE if successful, FALSE if there is an error.
  932. --*/
  933. {
  934. return BPackItemPrinterFeature(
  935. pUiData,
  936. GET_PREDEFINED_FEATURE(pUiData->ci.pUIInfo, GID_MEDIATYPE),
  937. TVITEM_LEVEL1,
  938. DMPUB_MEDIATYPE,
  939. (ULONG_PTR)MEDIATYPE_ITEM,
  940. HELP_INDEX_MEDIA_TYPE);
  941. }
  942. static CONST WORD CopiesCollateItemInfo[] =
  943. {
  944. IDS_CPSUI_COPIES, TVITEM_LEVEL1, DMPUB_COPIES_COLLATE,
  945. COPIES_COLLATE_ITEM, HELP_INDEX_COPIES_COLLATE,
  946. 2, TVOT_UDARROW,
  947. 0, IDI_CPSUI_COPY,
  948. 0, MIN_COPIES,
  949. ITEM_INFO_SIGNATURE
  950. };
  951. BOOL
  952. BPackItemCopiesCollate(
  953. IN OUT PUIDATA pUiData
  954. )
  955. /*++
  956. Routine Description:
  957. Pack copies and collate option.
  958. Arguments:
  959. pUiData - Points to UIDATA structure
  960. Return Value:
  961. TRUE if successful, FALSE if there is an error.
  962. --*/
  963. {
  964. POPTITEM pOptItem = pUiData->pOptItem;
  965. PEXTCHKBOX pExtCheckbox;
  966. PFEATURE pFeature;
  967. SHORT sCopies, sMaxCopies;
  968. if ((pFeature = GET_PREDEFINED_FEATURE(pUiData->ci.pUIInfo, GID_COLLATE)) &&
  969. pFeature->dwFlags & FEATURE_FLAG_NOUI)
  970. return TRUE;
  971. if (pUiData->bEMFSpooling)
  972. {
  973. sCopies = pUiData->ci.pdm->dmCopies;
  974. sMaxCopies = max(MAX_COPIES, (SHORT)pUiData->ci.pUIInfo->dwMaxCopies);
  975. }
  976. else
  977. {
  978. sCopies = pUiData->ci.pdm->dmCopies > (SHORT)pUiData->ci.pUIInfo->dwMaxCopies ?
  979. (SHORT)pUiData->ci.pUIInfo->dwMaxCopies : pUiData->ci.pdm->dmCopies;
  980. sMaxCopies = (SHORT)pUiData->ci.pUIInfo->dwMaxCopies;
  981. }
  982. if (! BPackUDArrowItemTemplate(
  983. pUiData,
  984. CopiesCollateItemInfo,
  985. sCopies,
  986. sMaxCopies,
  987. pFeature))
  988. {
  989. return FALSE;
  990. }
  991. if (pOptItem && DRIVER_SUPPORTS_COLLATE(((PCOMMONINFO)&pUiData->ci)))
  992. {
  993. pExtCheckbox = HEAPALLOC(pUiData->ci.hHeap, sizeof(EXTCHKBOX));
  994. if (pExtCheckbox == NULL)
  995. {
  996. ERR(("Memory allocation failed\n"));
  997. return FALSE;
  998. }
  999. pExtCheckbox->cbSize = sizeof(EXTCHKBOX);
  1000. pExtCheckbox->pTitle = (PWSTR) IDS_CPSUI_COLLATE;
  1001. pExtCheckbox->pCheckedName = (PWSTR) IDS_CPSUI_COLLATED;
  1002. pExtCheckbox->IconID = IDI_CPSUI_COLLATE;
  1003. pExtCheckbox->Flags = ECBF_CHECKNAME_ONLY_ENABLED;
  1004. pExtCheckbox->pSeparator = (PWSTR)IDS_CPSUI_SLASH_SEP;
  1005. pOptItem->pExtChkBox = pExtCheckbox;
  1006. if ((pUiData->ci.pdm->dmFields & DM_COLLATE) &&
  1007. (pUiData->ci.pdm->dmCollate == DMCOLLATE_TRUE))
  1008. {
  1009. pOptItem->Flags |= OPTIF_ECB_CHECKED;
  1010. }
  1011. }
  1012. return TRUE;
  1013. }
  1014. BOOL
  1015. BPackItemResolution(
  1016. IN OUT PUIDATA pUiData
  1017. )
  1018. /*++
  1019. Routine Description:
  1020. Pack resolution option.
  1021. Arguments:
  1022. pUiData - Points to UIDATA structure
  1023. Return Value:
  1024. TRUE if successful, FALSE if there is an error.
  1025. --*/
  1026. {
  1027. return BPackItemPrinterFeature(
  1028. pUiData,
  1029. GET_PREDEFINED_FEATURE(pUiData->ci.pUIInfo, GID_RESOLUTION),
  1030. TVITEM_LEVEL1,
  1031. DMPUB_PRINTQUALITY,
  1032. (ULONG_PTR)RESOLUTION_ITEM,
  1033. HELP_INDEX_RESOLUTION);
  1034. }
  1035. static CONST WORD ColorItemInfo[] =
  1036. {
  1037. IDS_CPSUI_COLOR, TVITEM_LEVEL1, DMPUB_COLOR,
  1038. COLOR_ITEM, HELP_INDEX_COLOR,
  1039. 2, TVOT_2STATES,
  1040. IDS_CPSUI_MONOCHROME, IDI_CPSUI_MONO,
  1041. IDS_CPSUI_COLOR, IDI_CPSUI_COLOR,
  1042. ITEM_INFO_SIGNATURE
  1043. };
  1044. //
  1045. // ICM stuff is not available on NT4
  1046. //
  1047. #ifndef WINNT_40
  1048. static CONST WORD ICMMethodItemInfo[] =
  1049. {
  1050. IDS_ICMMETHOD, TVITEM_LEVEL1,
  1051. #ifdef WINNT_40
  1052. DMPUB_NONE,
  1053. #else
  1054. DMPUB_ICMMETHOD,
  1055. #endif
  1056. ICMMETHOD_ITEM, HELP_INDEX_ICMMETHOD,
  1057. #ifdef PSCRIPT
  1058. 4, TVOT_LISTBOX,
  1059. #else
  1060. 3, TVOT_LISTBOX,
  1061. #endif
  1062. IDS_ICMMETHOD_NONE, IDI_ICMMETHOD_NONE,
  1063. IDS_ICMMETHOD_SYSTEM, IDI_ICMMETHOD_SYSTEM,
  1064. IDS_ICMMETHOD_DRIVER, IDI_ICMMETHOD_DRIVER,
  1065. #ifdef PSCRIPT
  1066. IDS_ICMMETHOD_DEVICE, IDI_ICMMETHOD_DEVICE,
  1067. #endif
  1068. ITEM_INFO_SIGNATURE
  1069. };
  1070. static CONST WORD ICMIntentItemInfo[] =
  1071. {
  1072. IDS_ICMINTENT, TVITEM_LEVEL1,
  1073. #ifdef WINNT_40
  1074. DMPUB_NONE,
  1075. #else
  1076. DMPUB_ICMINTENT,
  1077. #endif
  1078. ICMINTENT_ITEM, HELP_INDEX_ICMINTENT,
  1079. 4, TVOT_LISTBOX,
  1080. IDS_ICMINTENT_SATURATE, IDI_ICMINTENT_SATURATE,
  1081. IDS_ICMINTENT_CONTRAST, IDI_ICMINTENT_CONTRAST,
  1082. IDS_ICMINTENT_COLORIMETRIC, IDI_ICMINTENT_COLORIMETRIC,
  1083. IDS_ICMINTENT_ABS_COLORIMETRIC, IDI_ICMINTENT_ABS_COLORIMETRIC,
  1084. ITEM_INFO_SIGNATURE
  1085. };
  1086. #endif // !WINNT_40
  1087. BOOL
  1088. BPackItemColor(
  1089. IN OUT PUIDATA pUiData
  1090. )
  1091. /*++
  1092. Routine Description:
  1093. Pack color mode option.
  1094. Arguments:
  1095. pUiData - Points to UIDATA structure
  1096. Return Value:
  1097. TRUE if successful, FALSE if there is an error.
  1098. --*/
  1099. {
  1100. PDEVMODE pdm;
  1101. INT dwColorSel, dwICMMethodSel, dwICMIntentSel;
  1102. //
  1103. // For Adobe driver, they want to preserve the color information
  1104. // even for b/w printers. So we always give user this choice.
  1105. //
  1106. #ifndef ADOBE
  1107. if (! IS_COLOR_DEVICE(pUiData->ci.pUIInfo))
  1108. return TRUE;
  1109. #endif // !ADOBE
  1110. //
  1111. // DCR - Some ICM methods and intents may need to be disabled
  1112. // on some non-PostScript printers.
  1113. //
  1114. pdm = pUiData->ci.pdm;
  1115. dwColorSel = dwICMMethodSel = dwICMIntentSel = 0;
  1116. if ((pdm->dmFields & DM_COLOR) && (pdm->dmColor == DMCOLOR_COLOR))
  1117. dwColorSel = 1;
  1118. if (! BPackOptItemTemplate(pUiData, ColorItemInfo, dwColorSel, NULL))
  1119. return FALSE;
  1120. //
  1121. // ICM stuff is not available on NT4
  1122. //
  1123. #ifndef WINNT_40
  1124. if (pdm->dmFields & DM_ICMMETHOD)
  1125. {
  1126. switch (pdm->dmICMMethod)
  1127. {
  1128. case DMICMMETHOD_SYSTEM:
  1129. dwICMMethodSel = 1;
  1130. break;
  1131. case DMICMMETHOD_DRIVER:
  1132. dwICMMethodSel = 2;
  1133. break;
  1134. #ifdef PSCRIPT
  1135. case DMICMMETHOD_DEVICE:
  1136. dwICMMethodSel = 3;
  1137. break;
  1138. #endif
  1139. case DMICMMETHOD_NONE:
  1140. default:
  1141. dwICMMethodSel = 0;
  1142. break;
  1143. }
  1144. }
  1145. if (pdm->dmFields & DM_ICMINTENT)
  1146. {
  1147. switch (pdm->dmICMIntent)
  1148. {
  1149. case DMICM_COLORIMETRIC:
  1150. dwICMIntentSel = 2;
  1151. break;
  1152. case DMICM_ABS_COLORIMETRIC:
  1153. dwICMIntentSel = 3;
  1154. break;
  1155. case DMICM_SATURATE:
  1156. dwICMIntentSel = 0;
  1157. break;
  1158. case DMICM_CONTRAST:
  1159. default:
  1160. dwICMIntentSel = 1;
  1161. break;
  1162. }
  1163. }
  1164. if (! BPackOptItemTemplate(pUiData, ICMMethodItemInfo, dwICMMethodSel, NULL) ||
  1165. ! BPackOptItemTemplate(pUiData, ICMIntentItemInfo, dwICMIntentSel, NULL))
  1166. {
  1167. return FALSE;
  1168. }
  1169. #endif // !WINNT_40
  1170. return TRUE;
  1171. }
  1172. BOOL
  1173. BPackItemDuplex(
  1174. IN OUT PUIDATA pUiData
  1175. )
  1176. /*++
  1177. Routine Description:
  1178. Pack duplexing option.
  1179. Arguments:
  1180. pUiData - Points to UIDATA structure
  1181. Return Value:
  1182. TRUE if successful, FALSE if there is an error.
  1183. --*/
  1184. {
  1185. POPTITEM pOptItem = pUiData->pOptItem;
  1186. PCOMMONINFO pci = &pUiData->ci;
  1187. PFEATURE pFeature = GET_PREDEFINED_FEATURE(pUiData->ci.pUIInfo, GID_DUPLEX);
  1188. BOOL bRet;
  1189. //
  1190. // Don't display the duplex feature if duplex is constrained by an
  1191. // installable feature such as duplex unit not installed
  1192. //
  1193. if (!SUPPORTS_DUPLEX(pci) ||
  1194. (pFeature && pFeature->Options.dwCount < MIN_OPTIONS_ALLOWED))
  1195. return TRUE;
  1196. bRet = BPackItemPrinterFeature(
  1197. pUiData,
  1198. pFeature,
  1199. TVITEM_LEVEL1,
  1200. DMPUB_DUPLEX,
  1201. (ULONG_PTR)DUPLEX_ITEM,
  1202. HELP_INDEX_DUPLEX);
  1203. #ifdef WINNT_40
  1204. //
  1205. // Use standard names for duplex options. Otherwise, the duplex option
  1206. // names from the PPD/GPD file may be too long to fit into the space
  1207. // on the friendly (Page Setup) tab.
  1208. //
  1209. // On NT5, this kluge is inside compstui.
  1210. //
  1211. if (bRet && pFeature && pOptItem)
  1212. {
  1213. DWORD dwIndex;
  1214. INT StrRsrcId;
  1215. PDUPLEX pDuplex;
  1216. for (dwIndex=0; dwIndex < pOptItem->pOptType->Count; dwIndex++)
  1217. {
  1218. pDuplex = (PDUPLEX) PGetIndexedOption(pUiData->ci.pUIInfo, pFeature, dwIndex);
  1219. ASSERT(pDuplex != NULL);
  1220. switch (pDuplex->dwDuplexID)
  1221. {
  1222. case DMDUP_HORIZONTAL:
  1223. StrRsrcId = IDS_CPSUI_SHORT_SIDE;
  1224. break;
  1225. case DMDUP_VERTICAL:
  1226. StrRsrcId = IDS_CPSUI_LONG_SIDE;
  1227. break;
  1228. default:
  1229. StrRsrcId = IDS_CPSUI_NONE;
  1230. break;
  1231. }
  1232. pOptItem->pOptType->pOptParam[dwIndex].pData = (PWSTR) StrRsrcId;
  1233. }
  1234. }
  1235. #endif // WINNT_40
  1236. return bRet;
  1237. }
  1238. static CONST WORD TTOptionItemInfo[] =
  1239. {
  1240. IDS_CPSUI_TTOPTION, TVITEM_LEVEL1, DMPUB_TTOPTION,
  1241. TTOPTION_ITEM, HELP_INDEX_TTOPTION,
  1242. 2, TVOT_2STATES,
  1243. IDS_CPSUI_TT_SUBDEV, IDI_CPSUI_TT_SUBDEV,
  1244. IDS_CPSUI_TT_DOWNLOADSOFT, IDI_CPSUI_TT_DOWNLOADSOFT,
  1245. ITEM_INFO_SIGNATURE
  1246. };
  1247. BOOL
  1248. BPackItemTTOptions(
  1249. IN OUT PUIDATA pUiData
  1250. )
  1251. /*++
  1252. Routine Description:
  1253. Pack TT options
  1254. Arguments:
  1255. pUiData - Points to UIDATA structure
  1256. Return Value:
  1257. TRUE if successful, FALSE if there is an error.
  1258. --*/
  1259. {
  1260. DWORD dwSel;
  1261. //
  1262. // If device fonts have been disabled or doesn't support
  1263. // font substitution , then don't
  1264. // show font substitution option
  1265. //
  1266. if (pUiData->ci.pPrinterData->dwFlags & PFLAGS_IGNORE_DEVFONT ||
  1267. pUiData->ci.pUIInfo->dwFontSubCount == 0 )
  1268. {
  1269. pUiData->ci.pdm->dmTTOption = DMTT_DOWNLOAD;
  1270. return TRUE;
  1271. }
  1272. dwSel = (pUiData->ci.pdm->dmTTOption == DMTT_SUBDEV) ? 0 : 1;
  1273. return BPackOptItemTemplate(pUiData, TTOptionItemInfo, dwSel, NULL);
  1274. }
  1275. static CONST WORD ItemInfoMFSpool[] =
  1276. {
  1277. IDS_METAFILE_SPOOLING, TVITEM_LEVEL1, DMPUB_NONE,
  1278. METASPOOL_ITEM, HELP_INDEX_METAFILE_SPOOLING,
  1279. 2, TVOT_2STATES,
  1280. IDS_ENABLED, IDI_CPSUI_ON,
  1281. IDS_DISABLED, IDI_CPSUI_OFF,
  1282. ITEM_INFO_SIGNATURE
  1283. };
  1284. static CONST WORD ItemInfoNupOption[] =
  1285. {
  1286. IDS_NUPOPTION, TVITEM_LEVEL1, NUP_DMPUB,
  1287. NUP_ITEM, HELP_INDEX_NUPOPTION,
  1288. 7, TVOT_LISTBOX,
  1289. IDS_ONE_UP, IDI_ONE_UP,
  1290. IDS_TWO_UP, IDI_TWO_UP,
  1291. IDS_FOUR_UP, IDI_FOUR_UP,
  1292. IDS_SIX_UP, IDI_SIX_UP,
  1293. IDS_NINE_UP, IDI_NINE_UP,
  1294. IDS_SIXTEEN_UP, IDI_SIXTEEN_UP,
  1295. IDS_BOOKLET , IDI_BOOKLET,
  1296. ITEM_INFO_SIGNATURE
  1297. };
  1298. static CONST WORD ItemInfoRevPrint[] =
  1299. {
  1300. IDS_PAGEORDER, TVITEM_LEVEL1, PAGEORDER_DMPUB,
  1301. REVPRINT_ITEM, HELP_INDEX_REVPRINT,
  1302. 2, TVOT_2STATES,
  1303. IDS_PAGEORDER_NORMAL, IDI_PAGEORDER_NORMAL,
  1304. IDS_PAGEORDER_REVERSE, IDI_PAGEORDER_REVERSE,
  1305. ITEM_INFO_SIGNATURE
  1306. };
  1307. BOOL
  1308. BPackItemEmfFeatures(
  1309. PUIDATA pUiData
  1310. )
  1311. /*++
  1312. Routine Description:
  1313. Pack EMF related feature items:
  1314. EMF spooling on/off
  1315. N-up
  1316. reverse-order printing
  1317. Arguments:
  1318. pUiData - Points to UIDATA structure
  1319. Return Value:
  1320. TRUE if successful, FALSE if there is an error.
  1321. --*/
  1322. {
  1323. PDRIVEREXTRA pdmExtra = pUiData->ci.pdmPrivate;
  1324. BOOL bNupOption, bReversePrint;
  1325. PCOMMONINFO pci = &pUiData->ci;
  1326. DWORD dwSel;
  1327. POPTITEM pOptItem;
  1328. //
  1329. // Check if the spooler can do N-up and reverse-order printing
  1330. // for the current printer
  1331. //
  1332. VGetSpoolerEmfCaps(pci->hPrinter, &bNupOption, &bReversePrint, 0, NULL);
  1333. //
  1334. // On Win2K and above, don't show the EMF spooling option in driver UI
  1335. // if spooler cannot do EMF.
  1336. // pUiData->bEMFSpooling is initialized at PFillUidata
  1337. // 1. Determine if Reverse Print is possible
  1338. // 2. Spooler can do EMF.
  1339. //
  1340. // On NT4, since spooler doesn't support the EMF capability query, we
  1341. // have to keep the old NT4 driver behavior of always showing the EMF
  1342. // spooling option in driver UI.
  1343. //
  1344. #ifndef WINNT_40
  1345. if (pUiData->bEMFSpooling)
  1346. {
  1347. #endif
  1348. dwSel = ISSET_MFSPOOL_FLAG(pdmExtra) ? 0 : 1;
  1349. if (!BPackOptItemTemplate(pUiData, ItemInfoMFSpool, dwSel, NULL))
  1350. return FALSE;
  1351. #ifndef WINNT_40
  1352. }
  1353. #endif
  1354. #ifdef PSCRIPT
  1355. bNupOption = TRUE;
  1356. #endif
  1357. //
  1358. // Pack N-up option item if necessary
  1359. //
  1360. if (bNupOption)
  1361. {
  1362. switch (NUPOPTION(pdmExtra))
  1363. {
  1364. case TWO_UP:
  1365. dwSel = 1;
  1366. break;
  1367. case FOUR_UP:
  1368. dwSel = 2;
  1369. break;
  1370. case SIX_UP:
  1371. dwSel = 3;
  1372. break;
  1373. case NINE_UP:
  1374. dwSel = 4;
  1375. break;
  1376. case SIXTEEN_UP:
  1377. dwSel = 5;
  1378. break;
  1379. case BOOKLET_UP:
  1380. dwSel = 6;
  1381. break;
  1382. case ONE_UP:
  1383. default:
  1384. dwSel = 0;
  1385. break;
  1386. }
  1387. pOptItem = pUiData->pOptItem;
  1388. if (!BPackOptItemTemplate(pUiData, ItemInfoNupOption, dwSel, NULL))
  1389. return FALSE;
  1390. //
  1391. // Hide booklet option if duplex is constrained by an
  1392. // installable feature such as duplex unit not installed or EMF is not
  1393. // available.
  1394. //
  1395. if ( pOptItem &&
  1396. (!pUiData->bEMFSpooling || !SUPPORTS_DUPLEX(pci)))
  1397. {
  1398. pOptItem->pOptType->pOptParam[BOOKLET_UP].Flags |= OPTPF_HIDE;
  1399. if (NUPOPTION(pdmExtra) == BOOKLET_UP)
  1400. pOptItem->Sel = 1;
  1401. }
  1402. }
  1403. else
  1404. {
  1405. NUPOPTION(pdmExtra) = ONE_UP;
  1406. }
  1407. //
  1408. // Pack Reverse-order printing option item if necessary
  1409. //
  1410. if (bReversePrint)
  1411. {
  1412. dwSel = REVPRINTOPTION(pdmExtra) ? 1 : 0;
  1413. if (!BPackOptItemTemplate(pUiData, ItemInfoRevPrint, dwSel, NULL))
  1414. return FALSE;
  1415. }
  1416. else
  1417. {
  1418. REVPRINTOPTION(pdmExtra) = FALSE;
  1419. }
  1420. if (pUiData->bEMFSpooling && pUiData->pOptItem)
  1421. VUpdateEmfFeatureItems(pUiData, FALSE);
  1422. return TRUE;
  1423. }
  1424. BOOL
  1425. BPackDocumentPropertyItems(
  1426. IN OUT PUIDATA pUiData
  1427. )
  1428. /*++
  1429. Routine Description:
  1430. Pack document property information into treeview items.
  1431. Arguments:
  1432. pUiData - Points to UIDATA structure
  1433. Return Value:
  1434. TRUE if successful, FALSE if there is an error.
  1435. --*/
  1436. {
  1437. return BPackItemFormName(pUiData) &&
  1438. BPackItemInputSlot(pUiData) &&
  1439. _BPackOrientationItem(pUiData) &&
  1440. BPackItemCopiesCollate(pUiData) &&
  1441. BPackItemResolution(pUiData) &&
  1442. BPackItemColor(pUiData) &&
  1443. _BPackItemScale(pUiData) &&
  1444. BPackItemDuplex(pUiData) &&
  1445. BPackItemMediaType(pUiData) &&
  1446. BPackItemTTOptions(pUiData) &&
  1447. BPackItemEmfFeatures(pUiData) &&
  1448. _BPackDocumentOptions(pUiData) &&
  1449. BPackItemGenericOptions(pUiData) &&
  1450. BPackOemPluginItems(pUiData);
  1451. }
  1452. VOID
  1453. VUnpackDocumentPropertiesItems(
  1454. PUIDATA pUiData,
  1455. POPTITEM pOptItem,
  1456. DWORD dwOptItem
  1457. )
  1458. /*++
  1459. Routine Description:
  1460. Extract devmode information from an OPTITEM
  1461. Stored it back into devmode.
  1462. Arguments:
  1463. pUiData - Pointer to our UIDATA structure
  1464. pOptItem - Pointer to an array of OPTITEMs
  1465. dwOptItem - Number of OPTITEMs
  1466. Return Value:
  1467. Printer feature index corresponding to the last item unpacked
  1468. --*/
  1469. {
  1470. PUIINFO pUIInfo = pUiData->ci.pUIInfo;
  1471. PDEVMODE pdm = pUiData->ci.pdm;
  1472. PDRIVEREXTRA pdmExtra = pUiData->ci.pdmPrivate;
  1473. for ( ; dwOptItem > 0; dwOptItem--, pOptItem++)
  1474. {
  1475. //
  1476. // Header items always have pOptType == NULL, see
  1477. // VPackOptItemGroupHeader
  1478. //
  1479. if (pOptItem->pOptType == NULL)
  1480. continue;
  1481. //
  1482. // To fix bug #90923, we should only allow hidden items to be processed when we are within
  1483. // the UI helper function call BUpdateUISettingForOEM issued by OEM plguin.
  1484. //
  1485. // We don't do this for other cases because there are already UI plugins that hide our
  1486. // standard items and show their own. For example, CNBJUI.DLL hides our ICMMETHOD_ITEM
  1487. // and ICMINTENT_ITEM. It uses its own as replacement items. If we change the behavior here,
  1488. // we could break those plugins when we process the hidden items and overwrite the devmode
  1489. // plugin has already set based on user selection of their replacement items.
  1490. //
  1491. if (!(pUiData->ci.dwFlags & FLAG_WITHIN_PLUGINCALL) && (pOptItem->Flags & OPTIF_HIDE))
  1492. continue;
  1493. if (ISPRINTERFEATUREITEM(pOptItem->UserData))
  1494. {
  1495. //
  1496. // Generic document-sticky printer features
  1497. //
  1498. VUpdateOptionsArrayWithSelection(pUiData, pOptItem);
  1499. }
  1500. else
  1501. {
  1502. //
  1503. // Common items in public devmode
  1504. //
  1505. switch (GETUSERDATAITEM(pOptItem->UserData))
  1506. {
  1507. case ORIENTATION_ITEM:
  1508. //
  1509. // Orientation is a special case:
  1510. // for pscript, it's handled via _VUnpackDocumentOptions
  1511. // for unidrv, it's handled as a generic feature
  1512. //
  1513. #ifdef PSCRIPT
  1514. break;
  1515. #endif
  1516. case DUPLEX_ITEM:
  1517. VUpdateOptionsArrayWithSelection(pUiData, pOptItem);
  1518. VUpdateBookletOption(pUiData, pOptItem);
  1519. break;
  1520. case RESOLUTION_ITEM:
  1521. case INPUTSLOT_ITEM:
  1522. case MEDIATYPE_ITEM:
  1523. case COLORMODE_ITEM:
  1524. case HALFTONING_ITEM:
  1525. VUpdateOptionsArrayWithSelection(pUiData, pOptItem);
  1526. break;
  1527. case SCALE_ITEM:
  1528. pdm->dmScale = (SHORT) pOptItem->Sel;
  1529. break;
  1530. case COPIES_COLLATE_ITEM:
  1531. pdm->dmCopies = (SHORT) pOptItem->Sel;
  1532. if (pOptItem->pExtChkBox)
  1533. {
  1534. pdm->dmFields |= DM_COLLATE;
  1535. pdm->dmCollate = (pOptItem->Flags & OPTIF_ECB_CHECKED) ?
  1536. DMCOLLATE_TRUE :
  1537. DMCOLLATE_FALSE;
  1538. //
  1539. // Update Collate feature option index
  1540. //
  1541. ChangeOptionsViaID(
  1542. pUiData->ci.pInfoHeader,
  1543. pUiData->ci.pCombinedOptions,
  1544. GID_COLLATE,
  1545. pdm);
  1546. }
  1547. break;
  1548. case COLOR_ITEM:
  1549. pdm->dmFields |= DM_COLOR;
  1550. pdm->dmColor = (pOptItem->Sel == 1) ?
  1551. DMCOLOR_COLOR :
  1552. DMCOLOR_MONOCHROME;
  1553. break;
  1554. case METASPOOL_ITEM:
  1555. if (pOptItem->Sel == 0)
  1556. {
  1557. SET_MFSPOOL_FLAG(pdmExtra);
  1558. }
  1559. else
  1560. {
  1561. CLEAR_MFSPOOL_FLAG(pdmExtra);
  1562. }
  1563. break;
  1564. case NUP_ITEM:
  1565. switch (pOptItem->Sel)
  1566. {
  1567. case 1:
  1568. NUPOPTION(pdmExtra) = TWO_UP;
  1569. break;
  1570. case 2:
  1571. NUPOPTION(pdmExtra) = FOUR_UP;
  1572. break;
  1573. case 3:
  1574. NUPOPTION(pdmExtra) = SIX_UP;
  1575. break;
  1576. case 4:
  1577. NUPOPTION(pdmExtra) = NINE_UP;
  1578. break;
  1579. case 5:
  1580. NUPOPTION(pdmExtra) = SIXTEEN_UP;
  1581. break;
  1582. case 6:
  1583. NUPOPTION(pdmExtra) = BOOKLET_UP;
  1584. VUpdateBookletOption(pUiData, pOptItem);
  1585. break;
  1586. case 0:
  1587. default:
  1588. NUPOPTION(pdmExtra) = ONE_UP;
  1589. break;
  1590. }
  1591. break;
  1592. case REVPRINT_ITEM:
  1593. REVPRINTOPTION(pdmExtra) = (pOptItem->Sel != 0);
  1594. break;
  1595. //
  1596. // ICM stuff is not available on NT4
  1597. //
  1598. #ifndef WINNT_40
  1599. case ICMMETHOD_ITEM:
  1600. pdm->dmFields |= DM_ICMMETHOD;
  1601. switch (pOptItem->Sel)
  1602. {
  1603. case 0:
  1604. pdm->dmICMMethod = DMICMMETHOD_NONE;
  1605. break;
  1606. case 1:
  1607. pdm->dmICMMethod = DMICMMETHOD_SYSTEM;
  1608. break;
  1609. case 2:
  1610. pdm->dmICMMethod = DMICMMETHOD_DRIVER;
  1611. break;
  1612. #ifdef PSCRIPT
  1613. case 3:
  1614. pdm->dmICMMethod = DMICMMETHOD_DEVICE;
  1615. break;
  1616. #endif
  1617. }
  1618. break;
  1619. case ICMINTENT_ITEM:
  1620. pdm->dmFields |= DM_ICMINTENT;
  1621. switch (pOptItem->Sel)
  1622. {
  1623. case 0:
  1624. pdm->dmICMIntent = DMICM_SATURATE;
  1625. break;
  1626. case 1:
  1627. pdm->dmICMIntent = DMICM_CONTRAST;
  1628. break;
  1629. case 2:
  1630. pdm->dmICMIntent = DMICM_COLORIMETRIC;
  1631. break;
  1632. case 3:
  1633. pdm->dmICMIntent = DMICM_ABS_COLORIMETRIC;
  1634. break;
  1635. }
  1636. break;
  1637. #endif // !WINNT_40
  1638. case TTOPTION_ITEM:
  1639. pdm->dmFields |= DM_TTOPTION;
  1640. if (pOptItem->Sel == 0)
  1641. pdm->dmTTOption = DMTT_SUBDEV;
  1642. else
  1643. pdm->dmTTOption = DMTT_DOWNLOAD;
  1644. break;
  1645. case FORMNAME_ITEM:
  1646. pdm->dmFields &= ~(DM_PAPERLENGTH|DM_PAPERWIDTH);
  1647. pdm->dmFields |= DM_PAPERSIZE;
  1648. pdm->dmPaperSize = pUiData->pwPapers[pOptItem->Sel];
  1649. if (pdm->dmPaperSize == DMPAPER_CUSTOMSIZE)
  1650. pdm->dmFields &= ~DM_FORMNAME;
  1651. else
  1652. pdm->dmFields |= DM_FORMNAME;
  1653. CopyString(pdm->dmFormName,
  1654. pOptItem->pOptType->pOptParam[pOptItem->Sel].pData,
  1655. CCHFORMNAME);
  1656. //
  1657. // Update PageSize feature option index
  1658. //
  1659. {
  1660. INT dwIndex;
  1661. if (PGetFeatureFromItem(pUiData->ci.pUIInfo, pOptItem, &dwIndex))
  1662. {
  1663. pUiData->ci.pCombinedOptions[dwIndex].ubCurOptIndex =
  1664. (BYTE) pUiData->pwPaperFeatures[pOptItem->Sel];
  1665. }
  1666. }
  1667. break;
  1668. }
  1669. //
  1670. // Give drivers a chance to process their private items
  1671. //
  1672. _VUnpackDocumentOptions(pOptItem, pdm);
  1673. }
  1674. }
  1675. }
  1676. VOID
  1677. VUpdateEmfFeatureItems(
  1678. PUIDATA pUiData,
  1679. BOOL bUpdateMFSpoolItem
  1680. )
  1681. /*++
  1682. Routine Description:
  1683. Handle the inter-dependency between EMF spooling, N-up, and
  1684. reverse-printing items.
  1685. Arguments:
  1686. pUiData - Points to UIDATA structure
  1687. bUpdateMFSpoolItem - Whether to update EMF spooling or the other two items
  1688. Return Value:
  1689. NONE
  1690. --*/
  1691. {
  1692. POPTITEM pMFSpoolItem, pNupItem, pRevPrintItem, pCopiesCollateItem;
  1693. pMFSpoolItem = PFindOptItemWithUserData(pUiData, METASPOOL_ITEM);
  1694. pNupItem = PFindOptItemWithUserData(pUiData, NUP_ITEM);
  1695. pRevPrintItem = PFindOptItemWithUserData(pUiData, REVPRINT_ITEM);
  1696. pCopiesCollateItem = PFindOptItemWithUserData(pUiData, COPIES_COLLATE_ITEM);
  1697. if (pMFSpoolItem == NULL)
  1698. return;
  1699. if (bUpdateMFSpoolItem)
  1700. {
  1701. //
  1702. // Force EMF spooling to be on if:
  1703. // N-up option is not ONE_UP (Unidrv only), or
  1704. // reverse-order printing is enabled or
  1705. // collate is not supported by the device or
  1706. // copies count is > than max count support by device
  1707. //
  1708. #ifdef UNIDRV
  1709. if (pNupItem && pNupItem->Sel != 0)
  1710. pMFSpoolItem->Sel = 0;
  1711. #endif // UNIDRV
  1712. if (pNupItem && pNupItem->Sel == BOOKLET_UP)
  1713. pMFSpoolItem->Sel = 0;
  1714. if (pRevPrintItem)
  1715. {
  1716. //
  1717. // Turn on EMF if the user selects "Normal" and
  1718. // the bin is "Reversed" OR user selects "Reversed"
  1719. // and the bin is "Normal"
  1720. //
  1721. BOOL bReversed = BGetPageOrderFlag(&pUiData->ci);
  1722. if ( pRevPrintItem->Sel == 0 && bReversed ||
  1723. pRevPrintItem->Sel != 0 && !bReversed )
  1724. pMFSpoolItem->Sel = 0;
  1725. }
  1726. if (pCopiesCollateItem)
  1727. {
  1728. if (((pCopiesCollateItem->Flags & OPTIF_ECB_CHECKED) &&
  1729. !PRINTER_SUPPORTS_COLLATE(((PCOMMONINFO)&pUiData->ci))) ||
  1730. (pCopiesCollateItem->Sel > (LONG)pUiData->ci.pUIInfo->dwMaxCopies))
  1731. {
  1732. pMFSpoolItem->Sel = 0;
  1733. }
  1734. }
  1735. pMFSpoolItem->Flags |= OPTIF_CHANGED;
  1736. VUnpackDocumentPropertiesItems(pUiData, pMFSpoolItem, 1);
  1737. }
  1738. else
  1739. {
  1740. //
  1741. // If EMF spooling is turned off, force:
  1742. // N-up option to be ONE_UP (Unidrv only), and
  1743. // collate to be off if the device doesn't support collation
  1744. // copies set to the max count handle by the device
  1745. //
  1746. if (pMFSpoolItem->Sel != 0)
  1747. {
  1748. #ifdef UNIDRV
  1749. if (pNupItem)
  1750. {
  1751. pNupItem->Sel = 0;
  1752. pNupItem->Flags |= OPTIF_CHANGED;
  1753. VUnpackDocumentPropertiesItems(pUiData, pNupItem, 1);
  1754. }
  1755. #endif // UNIDRV
  1756. if (pNupItem && pNupItem->Sel == BOOKLET_UP)
  1757. {
  1758. pNupItem->Sel = 0;
  1759. pNupItem->Flags |= OPTIF_CHANGED;
  1760. VUnpackDocumentPropertiesItems(pUiData, pNupItem, 1);
  1761. }
  1762. if (pCopiesCollateItem)
  1763. {
  1764. if ((pCopiesCollateItem->Flags & OPTIF_ECB_CHECKED) &&
  1765. !PRINTER_SUPPORTS_COLLATE(((PCOMMONINFO)&pUiData->ci)))
  1766. {
  1767. pCopiesCollateItem->Flags &=~OPTIF_ECB_CHECKED;
  1768. }
  1769. if (pCopiesCollateItem->Sel > (LONG)pUiData->ci.pUIInfo->dwMaxCopies)
  1770. pCopiesCollateItem->Sel = (LONG)pUiData->ci.pUIInfo->dwMaxCopies;
  1771. pCopiesCollateItem->Flags |= OPTIF_CHANGED;
  1772. VUnpackDocumentPropertiesItems(pUiData, pCopiesCollateItem, 1);
  1773. }
  1774. //
  1775. // EMF is OFF. Need to make the "Page Order" option consistent
  1776. // with the current output bin. If bin is "Reversed" and user selects
  1777. // "Normal", change it to "Reverse". If bin is "Normal" and user selects
  1778. // "Reverse", change it to "Normal"
  1779. //
  1780. if (pRevPrintItem)
  1781. {
  1782. BOOL bReversed = BGetPageOrderFlag(&pUiData->ci);
  1783. if (pRevPrintItem->Sel == 0 && bReversed )
  1784. pRevPrintItem->Sel = 1;
  1785. else if ( pRevPrintItem->Sel != 0 && !bReversed )
  1786. pRevPrintItem->Sel = 0;
  1787. pRevPrintItem->Flags |= OPTIF_CHANGED;
  1788. VUnpackDocumentPropertiesItems(pUiData, pRevPrintItem, 1);
  1789. }
  1790. }
  1791. }
  1792. }
  1793. BOOL
  1794. BGetPageOrderFlag(
  1795. PCOMMONINFO pci
  1796. )
  1797. /*++
  1798. Routine Description:
  1799. Get the page order flag for the specified output bin
  1800. Arguments:
  1801. pci - Pointer to PCOMMONINFO
  1802. Return Value:
  1803. TRUE if output bin is reverse. otherwise, FALSE
  1804. --*/
  1805. {
  1806. PUIINFO pUIInfo = pci->pUIInfo;
  1807. PFEATURE pFeature;
  1808. POUTPUTBIN pOutputBin;
  1809. DWORD dwFeatureIndex, dwOptionIndex;
  1810. BOOL bRet = FALSE;
  1811. #ifdef PSCRIPT
  1812. {
  1813. PPPDDATA pPpdData;
  1814. POPTION pOption;
  1815. PCSTR pstrKeywordName;
  1816. //
  1817. // For PostScript driver, PPD could have "*OpenUI *OutputOrder", which enables user to
  1818. // select "Normal" or "Reverse" output order. This should have higher priority than
  1819. // current output bin's output order or what *DefaultOutputOrder specifies.
  1820. //
  1821. pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER((PINFOHEADER) pci->pRawData);
  1822. ASSERT(pPpdData != NULL);
  1823. if (pPpdData->dwOutputOrderIndex != INVALID_FEATURE_INDEX)
  1824. {
  1825. //
  1826. // "OutputOrder" feature is available. Check it's current option selection.
  1827. //
  1828. pFeature = PGetIndexedFeature(pUIInfo, pPpdData->dwOutputOrderIndex);
  1829. ASSERT(pFeature != NULL);
  1830. dwOptionIndex = pci->pCombinedOptions[pPpdData->dwOutputOrderIndex].ubCurOptIndex;
  1831. if ((pOption = PGetIndexedOption(pUIInfo, pFeature, dwOptionIndex)) &&
  1832. (pstrKeywordName = OFFSET_TO_POINTER(pUIInfo->pubResourceData, pOption->loKeywordName)))
  1833. {
  1834. //
  1835. // Valid *OutputOrder option keywords are "Reverse" or "Normal".
  1836. //
  1837. if (strcmp(pstrKeywordName, "Reverse") == EQUAL_STRING)
  1838. return TRUE;
  1839. else if (strcmp(pstrKeywordName, "Normal") == EQUAL_STRING)
  1840. return FALSE;
  1841. }
  1842. //
  1843. // If we are here, the PPD must have wrong information in *OpenUI *OutputOrder.
  1844. // We just ignore "OutputOrder" feature and continue.
  1845. //
  1846. }
  1847. }
  1848. #endif // PSCRIPT
  1849. //
  1850. // If the output bin order is NORMAL or there is no output bin
  1851. // feature defined, then the page order is the user's selection.
  1852. //
  1853. if ((pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_OUTPUTBIN)))
  1854. {
  1855. dwFeatureIndex = GET_INDEX_FROM_FEATURE(pUIInfo, pFeature);
  1856. dwOptionIndex = pci->pCombinedOptions[dwFeatureIndex].ubCurOptIndex;
  1857. pOutputBin = (POUTPUTBIN)PGetIndexedOption(pUIInfo,
  1858. pFeature,
  1859. dwOptionIndex);
  1860. if (pOutputBin &&
  1861. pOutputBin->bOutputOrderReversed)
  1862. {
  1863. if (NOT_UNUSED_ITEM(pOutputBin->bOutputOrderReversed))
  1864. bRet = TRUE;
  1865. else
  1866. bRet = pUIInfo->dwFlags & FLAG_REVERSE_PRINT;
  1867. }
  1868. }
  1869. else if (pUIInfo->dwFlags & FLAG_REVERSE_PRINT)
  1870. bRet = TRUE;
  1871. return bRet;
  1872. }
  1873. DWORD
  1874. DwGetDrvCopies(
  1875. PCOMMONINFO pci
  1876. )
  1877. /*++
  1878. Routine Description:
  1879. Get the printer copy count capability. Also take into account the
  1880. collating option.
  1881. Arguments:
  1882. pci - Pointer to PCOMMONINFO
  1883. Return Value:
  1884. The number of copies the printer can do, with collating taken into consideration
  1885. --*/
  1886. {
  1887. DWORD dwRet;
  1888. if ((pci->pdm->dmFields & DM_COLLATE) &&
  1889. pci->pdm->dmCollate == DMCOLLATE_TRUE &&
  1890. !PRINTER_SUPPORTS_COLLATE(pci))
  1891. dwRet = 1;
  1892. else
  1893. dwRet = min(pci->pUIInfo->dwMaxCopies, (DWORD)pci->pdm->dmCopies);
  1894. return dwRet;
  1895. }
  1896. BOOL
  1897. DrvQueryJobAttributes(
  1898. HANDLE hPrinter,
  1899. PDEVMODE pDevMode,
  1900. DWORD dwLevel,
  1901. LPBYTE lpAttributeInfo
  1902. )
  1903. /*++
  1904. Routine Description:
  1905. Negotiate EMF printing features (such as N-up and reverse-order printing)
  1906. with the spooler
  1907. Arguments:
  1908. hPrinter - Handle to the current printer
  1909. pDevMode - Pointer to input devmode
  1910. dwLevel - Specifies the structure level for lpAttributeInfo
  1911. lpAttributeInfo - Output buffer for returning EMF printing features
  1912. Return Value:
  1913. TRUE if successful, FALSE if there is an error
  1914. --*/
  1915. {
  1916. #if !defined(WINNT_40)
  1917. PCOMMONINFO pci;
  1918. PATTRIBUTE_INFO_1 pAttrInfo1;
  1919. DWORD dwVal;
  1920. BOOL bAppDoNup, bResult = FALSE;
  1921. //
  1922. // We can only handle AttributeInfo level 1
  1923. //
  1924. if ( dwLevel != 1 && dwLevel != 2 && dwLevel != 3)
  1925. {
  1926. ERR(("Invalid level for DrvQueryJobAttributes: %d\n", dwLevel));
  1927. SetLastError(ERROR_INVALID_PARAMETER);
  1928. return bResult;
  1929. }
  1930. //
  1931. // Load basic printer information
  1932. //
  1933. if (! (pci = PLoadCommonInfo(hPrinter, NULL, 0)) ||
  1934. ! BFillCommonInfoPrinterData(pci) ||
  1935. ! BFillCommonInfoDevmode(pci, NULL, pDevMode) ||
  1936. ! BCombineCommonInfoOptionsArray(pci))
  1937. {
  1938. VFreeCommonInfo(pci);
  1939. return bResult;
  1940. }
  1941. VFixOptionsArrayWithDevmode(pci);
  1942. (VOID) ResolveUIConflicts(pci->pRawData,
  1943. pci->pCombinedOptions,
  1944. MAX_COMBINED_OPTIONS,
  1945. MODE_DOCUMENT_STICKY);
  1946. VOptionsToDevmodeFields(pci, TRUE);
  1947. if (! BUpdateUIInfo(pci))
  1948. {
  1949. VFreeCommonInfo(pci);
  1950. return bResult;
  1951. }
  1952. pAttrInfo1 = (PATTRIBUTE_INFO_1) lpAttributeInfo;
  1953. bAppDoNup = ( (pci->pdm->dmFields & DM_NUP) &&
  1954. (pci->pdm->dmNup == DMNUP_ONEUP) );
  1955. if (bAppDoNup)
  1956. {
  1957. dwVal = 1;
  1958. }
  1959. else
  1960. {
  1961. switch (NUPOPTION(pci->pdmPrivate))
  1962. {
  1963. case TWO_UP:
  1964. dwVal = 2;
  1965. break;
  1966. case FOUR_UP:
  1967. dwVal = 4;
  1968. break;
  1969. case SIX_UP:
  1970. dwVal = 6;
  1971. break;
  1972. case NINE_UP:
  1973. dwVal = 9;
  1974. break;
  1975. case SIXTEEN_UP:
  1976. dwVal = 16;
  1977. break;
  1978. case BOOKLET_UP:
  1979. dwVal = 2;
  1980. break;
  1981. case ONE_UP:
  1982. default:
  1983. dwVal = 1;
  1984. break;
  1985. }
  1986. }
  1987. pAttrInfo1->dwDrvNumberOfPagesPerSide = pAttrInfo1->dwJobNumberOfPagesPerSide = dwVal;
  1988. pAttrInfo1->dwNupBorderFlags = BORDER_PRINT;
  1989. pAttrInfo1->dwJobPageOrderFlags =
  1990. REVPRINTOPTION(pci->pdmPrivate) ? REVERSE_PRINT : NORMAL_PRINT;
  1991. pAttrInfo1->dwDrvPageOrderFlags = BGetPageOrderFlag(pci) ? REVERSE_PRINT : NORMAL_PRINT;
  1992. //
  1993. // Check for booklet
  1994. //
  1995. if ((NUPOPTION(pci->pdmPrivate) == BOOKLET_UP) && !bAppDoNup)
  1996. {
  1997. pAttrInfo1->dwJobNumberOfPagesPerSide = 2;
  1998. pAttrInfo1->dwDrvNumberOfPagesPerSide = 1;
  1999. pAttrInfo1->dwDrvPageOrderFlags |= BOOKLET_PRINT;
  2000. }
  2001. pAttrInfo1->dwJobNumberOfCopies = pci->pdm->dmCopies;
  2002. pAttrInfo1->dwDrvNumberOfCopies = DwGetDrvCopies(pci);
  2003. #ifdef UNIDRV
  2004. //
  2005. // Unidrv doesn't support N-up option.
  2006. //
  2007. pAttrInfo1->dwDrvNumberOfPagesPerSide = 1;
  2008. #endif
  2009. //
  2010. // Unidrv assumes that automatic switching to monochrome
  2011. // mode on a color printer is allowed unless disabled in GPD
  2012. //
  2013. if (dwLevel == 3)
  2014. {
  2015. #ifdef UNIDRV
  2016. SHORT dmPrintQuality, dmYResolution;
  2017. if (pci->pUIInfo->bChangeColorModeOnDoc &&
  2018. (pci->pdm->dmFields & DM_COLOR) &&
  2019. (pci->pdm->dmColor == DMCOLOR_COLOR) &&
  2020. BOkToChangeColorToMono(pci, pci->pdm, &dmPrintQuality, &dmYResolution) &&
  2021. GET_PREDEFINED_FEATURE(pci->pUIInfo, GID_COLORMODE))
  2022. {
  2023. ((PATTRIBUTE_INFO_3)pAttrInfo1)->dwColorOptimization = COLOR_OPTIMIZATION;
  2024. ((PATTRIBUTE_INFO_3)pAttrInfo1)->dmPrintQuality = dmPrintQuality;
  2025. ((PATTRIBUTE_INFO_3)pAttrInfo1)->dmYResolution = dmYResolution;
  2026. }
  2027. else
  2028. #endif
  2029. ((PATTRIBUTE_INFO_3)pAttrInfo1)->dwColorOptimization = NO_COLOR_OPTIMIZATION;
  2030. }
  2031. bResult = TRUE;
  2032. FOREACH_OEMPLUGIN_LOOP(pci)
  2033. if (HAS_COM_INTERFACE(pOemEntry))
  2034. {
  2035. HRESULT hr;
  2036. hr = HComOEMQueryJobAttributes(
  2037. pOemEntry,
  2038. hPrinter,
  2039. pDevMode,
  2040. dwLevel,
  2041. lpAttributeInfo);
  2042. if (hr == E_NOTIMPL || hr == E_NOINTERFACE)
  2043. continue;
  2044. bResult = SUCCEEDED(hr);
  2045. }
  2046. END_OEMPLUGIN_LOOP
  2047. VFreeCommonInfo(pci);
  2048. return bResult;
  2049. #else // WINNT_40
  2050. return FALSE;
  2051. #endif // WINNT_40
  2052. }
  2053. VOID
  2054. VUpdateBookletOption(
  2055. PUIDATA pUiData,
  2056. POPTITEM pCurItem
  2057. )
  2058. /*++
  2059. Routine Description:
  2060. Handle the dependencies between duplex, nup and booklet options
  2061. Arguments:
  2062. pUiData - UIDATA
  2063. pCurItem - OPTITEM to currently selected item
  2064. Return Value:
  2065. None
  2066. --*/
  2067. {
  2068. PDRIVEREXTRA pdmExtra = pUiData->ci.pdmPrivate;
  2069. DWORD dwFeatureIndex, dwOptionIndex, dwCount;
  2070. PDUPLEX pDuplexOption = NULL;
  2071. POPTITEM pDuplexItem, pNupItem;
  2072. PFEATURE pDuplexFeature = NULL;
  2073. pDuplexItem = pNupItem = NULL;
  2074. //
  2075. // 1. Booklet is enabled - turn duplex on
  2076. // 3. Duplex is simplex, disable booklet, set to 1 up.
  2077. //
  2078. pDuplexFeature = GET_PREDEFINED_FEATURE(pUiData->ci.pUIInfo, GID_DUPLEX);
  2079. pNupItem = PFindOptItemWithUserData(pUiData, NUP_ITEM);
  2080. pDuplexItem = PFindOptItemWithUserData(pUiData, DUPLEX_ITEM);
  2081. if (pDuplexFeature && pDuplexItem)
  2082. {
  2083. dwFeatureIndex = GET_INDEX_FROM_FEATURE(pUiData->ci.pUIInfo, pDuplexFeature);
  2084. dwOptionIndex = pUiData->ci.pCombinedOptions[dwFeatureIndex].ubCurOptIndex;
  2085. pDuplexOption = PGetIndexedOption(pUiData->ci.pUIInfo, pDuplexFeature, dwOptionIndex);
  2086. }
  2087. if ((GETUSERDATAITEM(pCurItem->UserData) == NUP_ITEM) &&
  2088. pCurItem->Sel == BOOKLET_UP)
  2089. {
  2090. if (pDuplexOption && pDuplexOption->dwDuplexID == DMDUP_SIMPLEX)
  2091. {
  2092. pDuplexOption = PGetIndexedOption(pUiData->ci.pUIInfo, pDuplexFeature, 0);
  2093. for (dwCount = 0 ; dwCount < pDuplexFeature->Options.dwCount; dwCount++)
  2094. {
  2095. if (pDuplexOption->dwDuplexID != DMDUP_SIMPLEX)
  2096. {
  2097. pDuplexItem->Sel = dwCount;
  2098. pDuplexItem->Flags |= OPTIF_CHANGED;
  2099. VUpdateOptionsArrayWithSelection(pUiData, pDuplexItem);
  2100. break;
  2101. }
  2102. pDuplexOption++;
  2103. }
  2104. }
  2105. }
  2106. else if ((GETUSERDATAITEM(pCurItem->UserData) == DUPLEX_ITEM) &&
  2107. pDuplexOption)
  2108. {
  2109. if (pDuplexOption->dwDuplexID == DMDUP_SIMPLEX &&
  2110. pNupItem &&
  2111. pNupItem->Sel == BOOKLET_UP)
  2112. {
  2113. pNupItem->Sel = TWO_UP;
  2114. pNupItem->Flags |= OPTIF_CHANGED;
  2115. NUPOPTION(pdmExtra) = TWO_UP;
  2116. }
  2117. }
  2118. }
  2119. #ifdef UNIDRV
  2120. VOID
  2121. VSyncColorInformation(
  2122. PUIDATA pUiData,
  2123. POPTITEM pCurItem
  2124. )
  2125. /*++
  2126. Routine Description:
  2127. Arguments:
  2128. Return Value:
  2129. --*/
  2130. {
  2131. POPTITEM pOptItem;
  2132. PFEATURE pFeature;
  2133. //
  2134. // This is a hack to work around the fact that Unidrv has
  2135. // two color options, color appearance and color mode option,
  2136. // need to update the other once one is changed
  2137. //
  2138. pOptItem = (GETUSERDATAITEM(pCurItem->UserData) == COLOR_ITEM) ?
  2139. PFindOptItemWithUserData(pUiData, COLORMODE_ITEM) :
  2140. (GETUSERDATAITEM(pCurItem->UserData) == COLORMODE_ITEM) ?
  2141. PFindOptItemWithUserData(pUiData, COLOR_ITEM) : NULL;
  2142. if ((pOptItem != NULL) &&
  2143. (pFeature = GET_PREDEFINED_FEATURE(pUiData->ci.pUIInfo, GID_COLORMODE)))
  2144. {
  2145. DWORD dwFeature = GET_INDEX_FROM_FEATURE(pUiData->ci.pUIInfo, pFeature);
  2146. //
  2147. // Find either color appearance or color mode option
  2148. //
  2149. if (GETUSERDATAITEM(pCurItem->UserData) == COLOR_ITEM)
  2150. {
  2151. ChangeOptionsViaID(
  2152. pUiData->ci.pInfoHeader,
  2153. pUiData->ci.pCombinedOptions,
  2154. GID_COLORMODE,
  2155. pUiData->ci.pdm);
  2156. pOptItem->Sel = pUiData->ci.pCombinedOptions[dwFeature].ubCurOptIndex;
  2157. pOptItem->Flags |= OPTIF_CHANGED;
  2158. }
  2159. else // COLORMODE_ITEM
  2160. {
  2161. POPTION pColorMode;
  2162. PCOLORMODEEX pColorModeEx;
  2163. pColorMode = PGetIndexedOption(
  2164. pUiData->ci.pUIInfo,
  2165. pFeature,
  2166. pCurItem->Sel);
  2167. if (pColorMode)
  2168. {
  2169. pColorModeEx = OFFSET_TO_POINTER(
  2170. pUiData->ci.pInfoHeader,
  2171. pColorMode->loRenderOffset);
  2172. if (pColorModeEx)
  2173. {
  2174. pOptItem->Sel = pColorModeEx->bColor ? 1: 0;
  2175. VUnpackDocumentPropertiesItems(pUiData, pOptItem, 1);
  2176. pOptItem->Flags |= OPTIF_CHANGED;
  2177. }
  2178. else
  2179. {
  2180. ERR(("pColorModeEx is NULL\n"));
  2181. }
  2182. }
  2183. else
  2184. {
  2185. ERR(("pColorMode is NULL\n"));
  2186. }
  2187. }
  2188. }
  2189. }
  2190. DWORD
  2191. DwGetItemFromGID(
  2192. PFEATURE pFeature
  2193. )
  2194. /*++
  2195. Routine Description:
  2196. Arguments:
  2197. Return Value:
  2198. --*/
  2199. {
  2200. DWORD dwItem = 0;
  2201. switch (pFeature->dwFeatureID)
  2202. {
  2203. case GID_PAGESIZE:
  2204. dwItem = FORMNAME_ITEM;
  2205. break;
  2206. case GID_DUPLEX:
  2207. dwItem = DUPLEX_ITEM;
  2208. break;
  2209. case GID_RESOLUTION:
  2210. dwItem = RESOLUTION_ITEM;
  2211. break;
  2212. case GID_MEDIATYPE:
  2213. dwItem = MEDIATYPE_ITEM;
  2214. break;
  2215. case GID_INPUTSLOT:
  2216. dwItem = INPUTSLOT_ITEM;
  2217. break;
  2218. case GID_COLORMODE:
  2219. dwItem = COLORMODE_ITEM;
  2220. break;
  2221. case GID_ORIENTATION:
  2222. dwItem = ORIENTATION_ITEM;
  2223. break;
  2224. case GID_PAGEPROTECTION:
  2225. dwItem = PAGE_PROTECT_ITEM;
  2226. break;
  2227. case GID_COLLATE:
  2228. dwItem = COPIES_COLLATE_ITEM;
  2229. break;
  2230. case GID_HALFTONING:
  2231. dwItem = HALFTONING_ITEM;
  2232. break;
  2233. default:
  2234. dwItem = UNKNOWN_ITEM;
  2235. break;
  2236. }
  2237. return dwItem;
  2238. }
  2239. PLISTNODE
  2240. PGetMacroList(
  2241. PUIDATA pUiData,
  2242. POPTITEM pMacroItem,
  2243. PGPDDRIVERINFO pDriverInfo
  2244. )
  2245. /*++
  2246. Routine Description:
  2247. Arguments:
  2248. Return Value:
  2249. --*/
  2250. {
  2251. PUIINFO pUIInfo = pUiData->ci.pUIInfo;
  2252. PLISTNODE pListNode = NULL;
  2253. LISTINDEX liIndex;
  2254. if (pMacroItem)
  2255. {
  2256. switch(pMacroItem->Sel)
  2257. {
  2258. case QS_BEST:
  2259. liIndex = pUIInfo->liBestQualitySettings;
  2260. break;
  2261. case QS_DRAFT:
  2262. liIndex = pUIInfo->liDraftQualitySettings;
  2263. break;
  2264. case QS_BETTER:
  2265. liIndex = pUIInfo->liBetterQualitySettings;
  2266. break;
  2267. }
  2268. pListNode = LISTNODEPTR(pDriverInfo, liIndex);
  2269. }
  2270. return pListNode;
  2271. }
  2272. VOID
  2273. VUpdateQualitySettingOptions(
  2274. PUIINFO pUIInfo,
  2275. POPTITEM pQualityItem
  2276. )
  2277. /*++
  2278. Routine Description:
  2279. Arguments:
  2280. Return Value:
  2281. --*/
  2282. {
  2283. POPTPARAM pParam;
  2284. LISTINDEX liList;
  2285. DWORD i;
  2286. pParam = pQualityItem->pOptType->pOptParam;
  2287. for (i = QS_BEST; i < QS_BEST + MAX_QUALITY_SETTINGS; i++)
  2288. {
  2289. switch(i)
  2290. {
  2291. case QS_BEST:
  2292. liList = pUIInfo->liBestQualitySettings;
  2293. break;
  2294. case QS_BETTER:
  2295. liList = pUIInfo->liBetterQualitySettings;
  2296. break;
  2297. case QS_DRAFT:
  2298. liList = pUIInfo->liDraftQualitySettings;
  2299. break;
  2300. }
  2301. if (liList == END_OF_LIST)
  2302. {
  2303. pParam->Flags |= OPTPF_DISABLED;
  2304. pParam->dwReserved[0] = TRUE;
  2305. }
  2306. else
  2307. {
  2308. pParam->Flags &= ~OPTPF_DISABLED;
  2309. pParam->dwReserved[0] = FALSE;
  2310. }
  2311. pParam++;
  2312. }
  2313. pQualityItem->Flags |= OPTIF_CHANGED;
  2314. }
  2315. VOID
  2316. VMakeMacroSelections(
  2317. PUIDATA pUiData,
  2318. POPTITEM pCurItem
  2319. )
  2320. /*++
  2321. Routine Description:
  2322. Arguments:
  2323. Return Value:
  2324. --*/
  2325. {
  2326. DWORD dwFeatureID, dwOptionID, dwItem, i;
  2327. PUIINFO pUIInfo;
  2328. POPTITEM pMacroItem, pOptItem;
  2329. PFEATURE pFeature;
  2330. PLISTNODE pListNode;
  2331. PGPDDRIVERINFO pDriverInfo;
  2332. BOOL bMatchFound = FALSE;
  2333. //
  2334. // Mark options array with the change to either
  2335. // Macro selection, media type, color
  2336. //
  2337. // Update binary data
  2338. // Make selection
  2339. //
  2340. if (pUiData->ci.pdmPrivate->dwFlags & DXF_CUSTOM_QUALITY)
  2341. return;
  2342. if (pCurItem)
  2343. VUnpackDocumentPropertiesItems(pUiData, pCurItem, 1);
  2344. pMacroItem = PFindOptItemWithUserData(pUiData, QUALITY_SETTINGS_ITEM);
  2345. //
  2346. // BUpdateUIInfo calls UpdateBinaryData to get new snapshot
  2347. // for latest optionarray
  2348. //
  2349. if (pMacroItem == NULL || !BUpdateUIInfo(&pUiData->ci) )
  2350. return;
  2351. pUIInfo = pUiData->ci.pUIInfo;
  2352. pDriverInfo = OFFSET_TO_POINTER(pUiData->ci.pInfoHeader,
  2353. pUiData->ci.pInfoHeader->loDriverOffset);
  2354. //
  2355. // Update the macro selection to reflect the current default
  2356. //
  2357. if (pCurItem && GETUSERDATAITEM(pCurItem->UserData) != QUALITY_SETTINGS_ITEM)
  2358. {
  2359. ASSERT(pUIInfo->defaultQuality != END_OF_LIST);
  2360. if (pUIInfo->defaultQuality == END_OF_LIST)
  2361. return;
  2362. pMacroItem->Sel = pUIInfo->defaultQuality;
  2363. VUnpackDocumentPropertiesItems(pUiData, pMacroItem, 1);
  2364. pMacroItem->Flags |= OPTIF_CHANGED;
  2365. }
  2366. //
  2367. // Determine which item to gray out based on the
  2368. // liBestQualitySettings, liBetterQualitySettings, liDraftQualitySettings
  2369. //
  2370. VUpdateQualitySettingOptions(pUIInfo, pMacroItem);
  2371. pListNode = PGetMacroList(pUiData, pMacroItem, pDriverInfo);
  2372. //
  2373. // Make the selction of Feature.Option
  2374. //
  2375. while (pListNode)
  2376. {
  2377. //
  2378. // Search thru our list of OPTITEM for the matching
  2379. // Feature
  2380. //
  2381. pOptItem = pUiData->pDrvOptItem;
  2382. dwFeatureID = ((PQUALNAME)(&pListNode->dwData))->wFeatureID;
  2383. dwOptionID = ((PQUALNAME)(&pListNode->dwData))->wOptionID;
  2384. pFeature = (PFEATURE)((PBYTE)pUIInfo->pInfoHeader + pUIInfo->loFeatureList) + dwFeatureID;
  2385. dwItem = DwGetItemFromGID(pFeature);
  2386. for (i = 0; i < pUiData->dwDrvOptItem; i++)
  2387. {
  2388. if (ISPRINTERFEATUREITEM(pOptItem->UserData))
  2389. {
  2390. PFEATURE pPrinterFeature = (PFEATURE)GETUSERDATAITEM(pOptItem->UserData);
  2391. if (GET_INDEX_FROM_FEATURE(pUIInfo, pPrinterFeature) == dwFeatureID)
  2392. bMatchFound = TRUE;
  2393. }
  2394. else
  2395. {
  2396. if (dwItem != UNKNOWN_ITEM &&
  2397. dwItem == GETUSERDATAITEM(pOptItem->UserData))
  2398. bMatchFound = TRUE;
  2399. }
  2400. if (bMatchFound)
  2401. {
  2402. pOptItem->Sel = dwOptionID;
  2403. pOptItem->Flags |= OPTIF_CHANGED;
  2404. VUnpackDocumentPropertiesItems(pUiData, pOptItem, 1);
  2405. bMatchFound = FALSE;
  2406. break;
  2407. }
  2408. pOptItem++;
  2409. }
  2410. pListNode = LISTNODEPTR(pDriverInfo, pListNode->dwNextItem);
  2411. }
  2412. }
  2413. VOID
  2414. VUpdateMacroSelection(
  2415. PUIDATA pUiData,
  2416. POPTITEM pCurItem
  2417. )
  2418. /*++
  2419. Routine Description:
  2420. Arguments:
  2421. Return Value:
  2422. --*/
  2423. {
  2424. DWORD dwFeatureIndex;
  2425. PFEATURE pFeature = NULL;
  2426. PLISTNODE pListNode;
  2427. POPTITEM pMacroItem;
  2428. PGPDDRIVERINFO pDriverInfo;
  2429. pMacroItem = PFindOptItemWithUserData(pUiData, QUALITY_SETTINGS_ITEM);
  2430. if (pMacroItem == NULL)
  2431. return;
  2432. pDriverInfo = OFFSET_TO_POINTER(pUiData->ci.pInfoHeader,
  2433. pUiData->ci.pInfoHeader->loDriverOffset);
  2434. if (!(pFeature = PGetFeatureFromItem(pUiData->ci.pUIInfo, pCurItem, &dwFeatureIndex)))
  2435. return;
  2436. ASSERT(pDriverInfo);
  2437. pListNode = PGetMacroList(pUiData, pMacroItem, pDriverInfo);
  2438. while (pListNode)
  2439. {
  2440. if ( ((PQUALNAME)(&pListNode->dwData))->wFeatureID == (WORD)dwFeatureIndex)
  2441. {
  2442. pMacroItem->Flags |= OPTIF_ECB_CHECKED;
  2443. _VUnpackDocumentOptions(pMacroItem, pUiData->ci.pdm);
  2444. break;
  2445. }
  2446. pListNode = LISTNODEPTR(pDriverInfo, pListNode->dwNextItem);
  2447. }
  2448. }
  2449. #endif //UNIDRV