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

1864 lines
43 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. ps.c
  5. Abstract:
  6. This file handles Postscript specific UI options
  7. Environment:
  8. Win32 subsystem, DriverUI module, user mode
  9. Revision History:
  10. 02/25/97 -davidx-
  11. Finish PS-specific items.
  12. 02/04/97 -davidx-
  13. Reorganize driver UI to separate ps and uni DLLs.
  14. 12/17/96 -amandan-
  15. Created it.
  16. --*/
  17. #include "precomp.h"
  18. #include <ntverp.h>
  19. BOOL BSearchConstraintList(PUIINFO, DWORD, DWORD, DWORD);
  20. static CONST WORD ScaleItemInfo[] =
  21. {
  22. IDS_CPSUI_SCALING, TVITEM_LEVEL1, DMPUB_SCALE,
  23. SCALE_ITEM, HELP_INDEX_SCALE,
  24. 2, TVOT_UDARROW,
  25. IDS_CPSUI_PERCENT, IDI_CPSUI_SCALING,
  26. 0, MIN_SCALE,
  27. ITEM_INFO_SIGNATURE
  28. };
  29. BOOL
  30. _BPackItemScale(
  31. PUIDATA pUiData
  32. )
  33. /*++
  34. Routine Description:
  35. Pack scaling option.
  36. Arguments:
  37. pUiData - Points to UIDATA structure
  38. Return Value:
  39. TRUE if successful, FALSE if there is an error.
  40. --*/
  41. {
  42. return BPackUDArrowItemTemplate(
  43. pUiData,
  44. ScaleItemInfo,
  45. pUiData->ci.pdm->dmScale,
  46. pUiData->ci.pUIInfo->dwMaxScale,
  47. NULL);
  48. }
  49. DWORD
  50. _DwEnumPersonalities(
  51. PCOMMONINFO pci,
  52. PWSTR pwstrOutput
  53. )
  54. /*++
  55. Routine Description:
  56. Enumerate the list of supported printer description languages
  57. Arguments:
  58. pci - Points to common printer info
  59. pwstrOutput - Points to output buffer
  60. Return Value:
  61. Number of personalities supported
  62. GDI_ERROR if there is an error
  63. --*/
  64. {
  65. if (pwstrOutput)
  66. CopyString(pwstrOutput, TEXT("PostScript"), CCHLANGNAME);
  67. return 1;
  68. }
  69. DWORD
  70. _DwGetOrientationAngle(
  71. PUIINFO pUIInfo,
  72. PDEVMODE pdm
  73. )
  74. /*++
  75. Routine Description:
  76. Get the orienation angle requested by DrvDeviceCapabilities(DC_ORIENTATION)
  77. Arguments:
  78. pUIInfo - Pointer to UIINFO
  79. pdm - Pointer to DEVMODE
  80. Return Value:
  81. The angle (90 or 270 or landscape rotation)
  82. --*/
  83. {
  84. DWORD dwRet;
  85. PPSDRVEXTRA pdmPrivate;
  86. pdmPrivate = (PPSDRVEXTRA) GET_DRIVER_PRIVATE_DEVMODE(pdm);
  87. //
  88. // Normal landscape rotates counterclockwise
  89. // Rotated landscape rotates clockwise
  90. //
  91. if (pUIInfo->dwFlags & FLAG_ROTATE90)
  92. dwRet = (pdmPrivate->dwFlags & PSDEVMODE_LSROTATE) ? 270 : 90;
  93. else
  94. dwRet = (pdmPrivate->dwFlags & PSDEVMODE_LSROTATE) ? 90 : 270;
  95. return dwRet;
  96. }
  97. static CONST WORD PSOrientItemInfo[] =
  98. {
  99. IDS_CPSUI_ORIENTATION, TVITEM_LEVEL1, DMPUB_ORIENTATION,
  100. ORIENTATION_ITEM, HELP_INDEX_ORIENTATION,
  101. 3, TVOT_3STATES,
  102. IDS_CPSUI_PORTRAIT, IDI_CPSUI_PORTRAIT,
  103. IDS_CPSUI_LANDSCAPE, IDI_CPSUI_LANDSCAPE,
  104. IDS_CPSUI_ROT_LAND, IDI_CPSUI_ROT_LAND,
  105. ITEM_INFO_SIGNATURE
  106. };
  107. BOOL
  108. _BPackOrientationItem(
  109. IN OUT PUIDATA pUiData
  110. )
  111. /*++
  112. Routine Description:
  113. Synthesize the orientation feature for Doc property sheet
  114. Arguments:
  115. pUiData - Points to UIDATA structure
  116. Return Value:
  117. TRUE for success and FALSE for failure
  118. Note:
  119. Always synthesize orienation for PostScript
  120. --*/
  121. {
  122. PFEATURE pFeature;
  123. DWORD dwSelection;
  124. //
  125. // If there is no predefined orientation feature, we displays it ourselves.
  126. //
  127. if ((pUiData->ci.pdm->dmFields & DM_ORIENTATION) &&
  128. (pUiData->ci.pdm->dmOrientation == DMORIENT_LANDSCAPE))
  129. {
  130. PPSDRVEXTRA pdmPrivate;
  131. pdmPrivate = (PPSDRVEXTRA) GET_DRIVER_PRIVATE_DEVMODE(pUiData->ci.pdm);
  132. dwSelection = pdmPrivate->dwFlags & PSDEVMODE_LSROTATE ? 2 : 1;
  133. }
  134. else
  135. dwSelection = 0;
  136. //
  137. // Synthesize the feature ourselves
  138. //
  139. return BPackOptItemTemplate(pUiData, PSOrientItemInfo, dwSelection, NULL);
  140. }
  141. static CONST WORD PSOutputOptionItemInfo[] =
  142. {
  143. IDS_PSOUTPUT_OPTION, TVITEM_LEVEL2, DMPUB_NONE,
  144. PSOUTPUT_OPTION_ITEM, HELP_INDEX_PSOUTPUT_OPTION,
  145. 4, TVOT_LISTBOX,
  146. IDS_PSOPT_SPEED, IDI_PSOPT_SPEED,
  147. IDS_PSOPT_PORTABILITY, IDI_PSOPT_PORTABILITY,
  148. IDS_PSOPT_EPS, IDI_PSOPT_EPS,
  149. IDS_PSOPT_ARCHIVE, IDI_PSOPT_ARCHIVE,
  150. ITEM_INFO_SIGNATURE
  151. };
  152. BOOL
  153. BPackItemPSOutputOption(
  154. PUIDATA pUiData,
  155. PPSDRVEXTRA pdmPrivate
  156. )
  157. /*++
  158. Routine Description:
  159. Pack PostScript output option item
  160. Arguments:
  161. pUiData - Points to UIDATA structure
  162. pdmPrivate - Points to pscript private devmode
  163. Return Value:
  164. TRUE if successful, FALSE if there is an error
  165. --*/
  166. {
  167. DWORD dwSel;
  168. switch (pdmPrivate->iDialect)
  169. {
  170. case PORTABILITY:
  171. dwSel = 1;
  172. break;
  173. case EPS:
  174. dwSel = 2;
  175. break;
  176. case ARCHIVE:
  177. dwSel = 3;
  178. break;
  179. case SPEED:
  180. default:
  181. dwSel = 0;
  182. break;
  183. }
  184. return BPackOptItemTemplate(pUiData, PSOutputOptionItemInfo, dwSel, NULL);
  185. }
  186. static CONST WORD PSTTDLFormatItemInfo[] =
  187. {
  188. IDS_PSTT_DLFORMAT, TVITEM_LEVEL2, DMPUB_NONE,
  189. PSTT_DLFORMAT_ITEM, HELP_INDEX_PSTT_DLFORMAT,
  190. 4, TVOT_LISTBOX,
  191. IDS_TTDL_DEFAULT, IDI_PSTT_DLFORMAT,
  192. IDS_TTDL_TYPE1, IDI_PSTT_DLFORMAT,
  193. IDS_TTDL_TYPE3, IDI_PSTT_DLFORMAT,
  194. IDS_TTDL_TYPE42, IDI_PSTT_DLFORMAT,
  195. ITEM_INFO_SIGNATURE
  196. };
  197. BOOL
  198. BPackItemTTDownloadFormat(
  199. PUIDATA pUiData,
  200. PPSDRVEXTRA pdmPrivate
  201. )
  202. /*++
  203. Routine Description:
  204. Pack PostScript TrueType download option item
  205. Arguments:
  206. pUiData - Points to UIDATA structure
  207. pdmPrivate - Points to pscript private devmode
  208. Return Value:
  209. TRUE if successful, FALSE if there is an error
  210. --*/
  211. {
  212. DWORD dwSel;
  213. BOOL bSupportType42;
  214. POPTTYPE pOptType = pUiData->pOptType;
  215. bSupportType42 = (pUiData->ci.pUIInfo->dwTTRasterizer == TTRAS_TYPE42);
  216. switch (pdmPrivate->iTTDLFmt)
  217. {
  218. case TYPE_1:
  219. dwSel = 1;
  220. break;
  221. case TYPE_3:
  222. dwSel = 2;
  223. break;
  224. case TYPE_42:
  225. dwSel = bSupportType42 ? 3 : 0;
  226. break;
  227. case TT_DEFAULT:
  228. default:
  229. dwSel = 0;
  230. break;
  231. }
  232. if (! BPackOptItemTemplate(pUiData, PSTTDLFormatItemInfo, dwSel, NULL))
  233. return FALSE;
  234. //
  235. // if printer doesn't support Type42, hide Type42 option
  236. //
  237. if (pOptType && !bSupportType42)
  238. pOptType->pOptParam[3].Flags |= OPTPF_HIDE;
  239. return TRUE;
  240. }
  241. static CONST WORD PSLevelItemInfo[] =
  242. {
  243. IDS_PSLEVEL, TVITEM_LEVEL2, DMPUB_NONE,
  244. PSLEVEL_ITEM, HELP_INDEX_SCALE,
  245. 2, TVOT_UDARROW,
  246. 0, IDI_PSLEVEL,
  247. 0,
  248. //
  249. // Adobe doesn't want to support level 1
  250. //
  251. #ifdef ADOBE
  252. 2,
  253. #else
  254. 1,
  255. #endif
  256. ITEM_INFO_SIGNATURE
  257. };
  258. BOOL
  259. BPackItemPSLevel(
  260. PUIDATA pUiData,
  261. PPSDRVEXTRA pdmPrivate
  262. )
  263. /*++
  264. Routine Description:
  265. Pack PostScript output option item
  266. Arguments:
  267. pUiData - Points to UIDATA structure
  268. pdmPrivate - Points to pscript private devmode
  269. Return Value:
  270. TRUE if successful, FALSE if there is an error
  271. --*/
  272. {
  273. DWORD dwSel = pdmPrivate->iPSLevel;
  274. DWORD dwLangLevel = pUiData->ci.pUIInfo->dwLangLevel;
  275. //
  276. // we don't expect language level to be higher than 4
  277. //
  278. if (dwLangLevel <= 1)
  279. return TRUE;
  280. if (dwLangLevel > 4)
  281. dwLangLevel = 4;
  282. //
  283. // make sure the current selection is sensible
  284. //
  285. if (dwSel == 0 || dwSel > dwLangLevel)
  286. dwSel = dwLangLevel;
  287. return BPackUDArrowItemTemplate(pUiData, PSLevelItemInfo, dwSel, dwLangLevel, NULL);
  288. }
  289. static CONST WORD EHandlerItemInfo[] =
  290. {
  291. IDS_PSERROR_HANDLER, TVITEM_LEVEL2, DMPUB_NONE,
  292. PSERROR_HANDLER_ITEM, HELP_INDEX_PSERROR_HANDLER,
  293. 2, TVOT_2STATES,
  294. IDS_CPSUI_YES, IDI_CPSUI_YES,
  295. IDS_CPSUI_NO, IDI_CPSUI_NO,
  296. ITEM_INFO_SIGNATURE
  297. };
  298. static CONST WORD MirrorItemInfo[] =
  299. {
  300. IDS_MIRROR, TVITEM_LEVEL2, DMPUB_NONE,
  301. MIRROR_ITEM, HELP_INDEX_MIRROR,
  302. 2, TVOT_2STATES,
  303. IDS_CPSUI_YES, IDI_CPSUI_YES,
  304. IDS_CPSUI_NO, IDI_CPSUI_NO,
  305. ITEM_INFO_SIGNATURE
  306. };
  307. static CONST WORD NegativeItemInfo[] =
  308. {
  309. IDS_NEGATIVE_PRINT, TVITEM_LEVEL2, DMPUB_NONE,
  310. NEGATIVE_ITEM, HELP_INDEX_NEGATIVE,
  311. 2, TVOT_2STATES,
  312. IDS_CPSUI_YES, IDI_CPSUI_YES,
  313. IDS_CPSUI_NO, IDI_CPSUI_NO,
  314. ITEM_INFO_SIGNATURE
  315. };
  316. static CONST WORD CompressBmpItemInfo[] =
  317. {
  318. IDS_COMPRESSBMP, TVITEM_LEVEL2, DMPUB_NONE,
  319. COMPRESSBMP_ITEM, HELP_INDEX_COMPRESSBMP,
  320. 2, TVOT_2STATES,
  321. IDS_CPSUI_YES, IDI_CPSUI_YES,
  322. IDS_CPSUI_NO, IDI_CPSUI_NO,
  323. ITEM_INFO_SIGNATURE
  324. };
  325. BOOL
  326. _BPackDocumentOptions(
  327. IN OUT PUIDATA pUiData
  328. )
  329. /*++
  330. Routine Description:
  331. Pack PostScript specific options such as Job Control etc.
  332. Arguments:
  333. pUiData - Points to UIDATA structure
  334. Return Value:
  335. TRUE for success and FALSE for failure
  336. --*/
  337. {
  338. POPTITEM pOptItem;
  339. PPSDRVEXTRA pdmPrivate;
  340. DWORD dwFlags;
  341. pdmPrivate = pUiData->ci.pdmPrivate;
  342. dwFlags = pdmPrivate->dwFlags;
  343. pOptItem = pUiData->pOptItem;
  344. VPackOptItemGroupHeader(pUiData,
  345. IDS_PSOPTIONS,
  346. IDI_CPSUI_POSTSCRIPT,
  347. HELP_INDEX_PSOPTIONS);
  348. if (pOptItem)
  349. pOptItem->Flags |= OPTIF_COLLAPSE;
  350. return BPackItemPSOutputOption(pUiData, pdmPrivate) &&
  351. BPackItemTTDownloadFormat(pUiData, pdmPrivate) &&
  352. BPackItemPSLevel(pUiData, pdmPrivate) &&
  353. BPackOptItemTemplate(
  354. pUiData,
  355. EHandlerItemInfo,
  356. (dwFlags & PSDEVMODE_EHANDLER) ? 0 : 1, NULL) &&
  357. (pUiData->ci.pUIInfo->dwLangLevel > 1 ||
  358. BPackOptItemTemplate(
  359. pUiData,
  360. CompressBmpItemInfo,
  361. (dwFlags & PSDEVMODE_COMPRESSBMP) ? 0 : 1, NULL)) &&
  362. BPackOptItemTemplate(
  363. pUiData,
  364. MirrorItemInfo,
  365. (dwFlags & PSDEVMODE_MIRROR) ? 0 : 1, NULL) &&
  366. (IS_COLOR_DEVICE(pUiData->ci.pUIInfo) ||
  367. BPackOptItemTemplate(
  368. pUiData,
  369. NegativeItemInfo,
  370. (dwFlags & PSDEVMODE_NEG) ? 0 : 1, NULL));
  371. }
  372. VOID
  373. _VUnpackDocumentOptions(
  374. POPTITEM pOptItem,
  375. PDEVMODE pdm
  376. )
  377. /*++
  378. Routine Description:
  379. Extract Postscript devmode information from an OPTITEM
  380. Stored it back into Postscript devmode.
  381. Arguments:
  382. pOptItem - Pointer to an OPTITEM
  383. pdm - Pointer to Postscript DEVMODE structure
  384. Return Value:
  385. None
  386. --*/
  387. {
  388. PPSDRVEXTRA pdmPrivate;
  389. pdmPrivate = (PPSDRVEXTRA) GET_DRIVER_PRIVATE_DEVMODE(pdm);
  390. switch (GETUSERDATAITEM(pOptItem->UserData))
  391. {
  392. case ORIENTATION_ITEM:
  393. pdm->dmFields |= DM_ORIENTATION;
  394. pdm->dmOrientation = (pOptItem->Sel == 0) ?
  395. DMORIENT_PORTRAIT :
  396. DMORIENT_LANDSCAPE;
  397. if (pOptItem->Sel != 2)
  398. pdmPrivate->dwFlags &= ~PSDEVMODE_LSROTATE;
  399. else
  400. pdmPrivate->dwFlags |= PSDEVMODE_LSROTATE;
  401. break;
  402. case PSOUTPUT_OPTION_ITEM:
  403. switch (pOptItem->Sel)
  404. {
  405. case 1:
  406. pdmPrivate->iDialect = PORTABILITY;
  407. break;
  408. case 2:
  409. pdmPrivate->iDialect = EPS;
  410. break;
  411. case 3:
  412. pdmPrivate->iDialect = ARCHIVE;
  413. break;
  414. case 0:
  415. default:
  416. pdmPrivate->iDialect = SPEED;
  417. break;
  418. }
  419. break;
  420. case PSTT_DLFORMAT_ITEM:
  421. switch (pOptItem->Sel)
  422. {
  423. case 1:
  424. pdmPrivate->iTTDLFmt = TYPE_1;
  425. break;
  426. case 2:
  427. pdmPrivate->iTTDLFmt = TYPE_3;
  428. break;
  429. case 3:
  430. pdmPrivate->iTTDLFmt = TYPE_42;
  431. break;
  432. case 0:
  433. default:
  434. pdmPrivate->iTTDLFmt = TT_DEFAULT;
  435. break;
  436. }
  437. break;
  438. case PSLEVEL_ITEM:
  439. pdmPrivate->iPSLevel = pOptItem->Sel;
  440. break;
  441. case PSERROR_HANDLER_ITEM:
  442. if (pOptItem->Sel == 0)
  443. pdmPrivate->dwFlags |= PSDEVMODE_EHANDLER;
  444. else
  445. pdmPrivate->dwFlags &= ~PSDEVMODE_EHANDLER;
  446. break;
  447. case PSHALFTONE_FREQ_ITEM:
  448. case PSHALFTONE_ANGLE_ITEM:
  449. // DCR - not implemented yet
  450. break;
  451. case MIRROR_ITEM:
  452. if (pOptItem->Sel == 0)
  453. pdmPrivate->dwFlags |= PSDEVMODE_MIRROR;
  454. else
  455. pdmPrivate->dwFlags &= ~PSDEVMODE_MIRROR;
  456. break;
  457. case NEGATIVE_ITEM:
  458. if (pOptItem->Sel == 0)
  459. pdmPrivate->dwFlags |= PSDEVMODE_NEG;
  460. else
  461. pdmPrivate->dwFlags &= ~PSDEVMODE_NEG;
  462. break;
  463. case COMPRESSBMP_ITEM:
  464. if (pOptItem->Sel == 0)
  465. pdmPrivate->dwFlags |= PSDEVMODE_COMPRESSBMP;
  466. else
  467. pdmPrivate->dwFlags &= ~PSDEVMODE_COMPRESSBMP;
  468. break;
  469. }
  470. }
  471. static CONST WORD IgnoreDevFontItemInfo[] =
  472. {
  473. IDS_USE_DEVFONTS, TVITEM_LEVEL1, DMPUB_NONE,
  474. IGNORE_DEVFONT_ITEM, HELP_INDEX_IGNORE_DEVFONT,
  475. 2, TVOT_2STATES,
  476. IDS_CPSUI_YES, IDI_CPSUI_YES,
  477. IDS_CPSUI_NO, IDI_CPSUI_NO,
  478. ITEM_INFO_SIGNATURE
  479. };
  480. BOOL
  481. _BPackFontSubstItems(
  482. IN OUT PUIDATA pUiData
  483. )
  484. /*++
  485. Routine Description:
  486. Pack font substitution related items (printer-sticky)
  487. Arguments:
  488. pUiData - Points to UIDATA structure
  489. Return Value:
  490. TRUE if successful, FALSE if there is an error
  491. --*/
  492. {
  493. BOOL bNoDeviceFont;
  494. bNoDeviceFont = (pUiData->ci.pPrinterData->dwFlags & PFLAGS_IGNORE_DEVFONT);
  495. //
  496. // On non-1252 code page systems, gives user the option
  497. // to disable all device fonts
  498. //
  499. // Note: On non-1252 CodePage systems (Cs-Ct-Ja-Ko & Cyr-Grk-Tur, etc),
  500. // PScript NT4 had difficulty mapping printer font Encodings to GDI strings.
  501. // AdobePS5/PScript5 is supposed to handle these correctly. So Adobe wants
  502. // this choice to be suppressed on all code pages.
  503. //
  504. // Fix MS bug #121883, Adobe bug #235417
  505. //
  506. if (FALSE && GetACP() != 1252 &&
  507. !BPackOptItemTemplate(pUiData, IgnoreDevFontItemInfo, bNoDeviceFont ? 1 : 0, NULL))
  508. {
  509. return FALSE;
  510. }
  511. //
  512. // Don't display the font substitution table if device font is disabled
  513. //
  514. if (bNoDeviceFont)
  515. return TRUE;
  516. return BPackItemFontSubstTable(pUiData);
  517. }
  518. static CONST WORD ProtocolItemInfo[] =
  519. {
  520. IDS_PSPROTOCOL, TVITEM_LEVEL1, DMPUB_NONE,
  521. PSPROTOCOL_ITEM, HELP_INDEX_PSPROTOCOL,
  522. 4, TVOT_LISTBOX,
  523. IDS_PSPROTOCOL_ASCII, IDI_PSPROTOCOL,
  524. IDS_PSPROTOCOL_BCP, IDI_PSPROTOCOL,
  525. IDS_PSPROTOCOL_TBCP, IDI_PSPROTOCOL,
  526. IDS_PSPROTOCOL_BINARY, IDI_PSPROTOCOL,
  527. ITEM_INFO_SIGNATURE
  528. };
  529. BOOL
  530. BPackPSProtocolItem(
  531. IN OUT PUIDATA pUiData
  532. )
  533. /*++
  534. Routine Description:
  535. Pack PostScript communication protocol item
  536. Arguments:
  537. pUiData - Points to UIDATA structure
  538. Return Value:
  539. TRUE if successful, FALSE if there is an error
  540. --*/
  541. {
  542. DWORD dwSel;
  543. POPTITEM pOptItem;
  544. POPTPARAM pOptParam;
  545. PUIINFO pUIInfo;
  546. pOptItem = pUiData->pOptItem;
  547. if (! BPackOptItemTemplate(pUiData, ProtocolItemInfo, 0, NULL))
  548. return FALSE;
  549. if (pOptItem)
  550. {
  551. //
  552. // Hide those selections which are not supported on the printer
  553. //
  554. pOptParam = pOptItem->pOptType->pOptParam;
  555. pUIInfo = pUiData->ci.pUIInfo;
  556. if (! (pUIInfo->dwProtocols & PROTOCOL_BCP))
  557. pOptParam[1].Flags |= OPTPF_HIDE;
  558. if (! (pUIInfo->dwProtocols & PROTOCOL_TBCP))
  559. pOptParam[2].Flags |= OPTPF_HIDE;
  560. if (! (pUIInfo->dwProtocols & PROTOCOL_BINARY))
  561. pOptParam[3].Flags |= OPTPF_HIDE;
  562. switch (pUiData->ci.pPrinterData->wProtocol)
  563. {
  564. case PROTOCOL_BCP:
  565. dwSel = 1;
  566. break;
  567. case PROTOCOL_TBCP:
  568. dwSel = 2;
  569. break;
  570. case PROTOCOL_BINARY:
  571. dwSel = 3;
  572. break;
  573. default:
  574. dwSel = 0;
  575. break;
  576. }
  577. if (pOptParam[dwSel].Flags & OPTPF_HIDE)
  578. pOptItem->Sel = 0;
  579. else
  580. pOptItem->Sel = dwSel;
  581. }
  582. return TRUE;
  583. }
  584. //
  585. // We will use different lower limit for Printer VM
  586. // based on printer level. The 10th element of this
  587. // ItemInfo must be filled with correct lower limit
  588. // number before begin used.
  589. //
  590. static WORD PrinterVMItemInfo[] =
  591. {
  592. IDS_POSTSCRIPT_VM, TVITEM_LEVEL1, DMPUB_NONE,
  593. PRINTER_VM_ITEM, HELP_INDEX_PRINTER_VM,
  594. 2, TVOT_UDARROW,
  595. IDS_KBYTES, IDI_CPSUI_MEM,
  596. 0, 0,
  597. ITEM_INFO_SIGNATURE
  598. };
  599. static CONST WORD JobTimeoutItemInfo[] =
  600. {
  601. IDS_JOBTIMEOUT, TVITEM_LEVEL1, DMPUB_NONE,
  602. JOB_TIMEOUT_ITEM, HELP_INDEX_JOB_TIMEOUT,
  603. 2, TVOT_UDARROW,
  604. IDS_SECONDS, IDI_USE_DEFAULT,
  605. 0, 0,
  606. ITEM_INFO_SIGNATURE
  607. };
  608. static CONST WORD WaitTimeoutItemInfo[] =
  609. {
  610. IDS_WAITTIMEOUT, TVITEM_LEVEL1, DMPUB_NONE,
  611. WAIT_TIMEOUT_ITEM, HELP_INDEX_WAIT_TIMEOUT,
  612. 2, TVOT_UDARROW,
  613. IDS_SECONDS, IDI_USE_DEFAULT,
  614. 0, 0,
  615. ITEM_INFO_SIGNATURE
  616. };
  617. static CONST WORD CtrlDBeforeItemInfo[] =
  618. {
  619. IDS_CTRLD_BEFORE, TVITEM_LEVEL1, DMPUB_NONE,
  620. CTRLD_BEFORE_ITEM, HELP_INDEX_CTRLD_BEFORE,
  621. 2, TVOT_2STATES,
  622. IDS_CPSUI_YES, IDI_CPSUI_YES,
  623. IDS_CPSUI_NO, IDI_CPSUI_NO,
  624. ITEM_INFO_SIGNATURE
  625. };
  626. static CONST WORD CtrlDAfterItemInfo[] =
  627. {
  628. IDS_CTRLD_AFTER, TVITEM_LEVEL1, DMPUB_NONE,
  629. CTRLD_AFTER_ITEM, HELP_INDEX_CTRLD_AFTER,
  630. 2, TVOT_2STATES,
  631. IDS_CPSUI_YES, IDI_CPSUI_YES,
  632. IDS_CPSUI_NO, IDI_CPSUI_NO,
  633. ITEM_INFO_SIGNATURE
  634. };
  635. static CONST WORD TrueGrayTextItemInfo[] =
  636. {
  637. IDS_TRUE_GRAY_TEXT, TVITEM_LEVEL1, DMPUB_NONE,
  638. TRUE_GRAY_TEXT_ITEM, HELP_INDEX_TRUE_GRAY_TEXT,
  639. 2, TVOT_2STATES,
  640. IDS_CPSUI_YES, IDI_CPSUI_YES,
  641. IDS_CPSUI_NO, IDI_CPSUI_NO,
  642. ITEM_INFO_SIGNATURE
  643. };
  644. static CONST WORD TrueGrayGraphItemInfo[] =
  645. {
  646. IDS_TRUE_GRAY_GRAPH, TVITEM_LEVEL1, DMPUB_NONE,
  647. TRUE_GRAY_GRAPH_ITEM, HELP_INDEX_TRUE_GRAY_GRAPH,
  648. 2, TVOT_2STATES,
  649. IDS_CPSUI_YES, IDI_CPSUI_YES,
  650. IDS_CPSUI_NO, IDI_CPSUI_NO,
  651. ITEM_INFO_SIGNATURE
  652. };
  653. static CONST WORD AddEuroItemInfo[] =
  654. {
  655. IDS_ADD_EURO, TVITEM_LEVEL1, DMPUB_NONE,
  656. ADD_EURO_ITEM, HELP_INDEX_ADD_EURO,
  657. 2, TVOT_2STATES,
  658. IDS_CPSUI_YES, IDI_CPSUI_YES,
  659. IDS_CPSUI_NO, IDI_CPSUI_NO,
  660. ITEM_INFO_SIGNATURE
  661. };
  662. static CONST WORD MinOutlineItemInfo[] =
  663. {
  664. IDS_PSMINOUTLINE, TVITEM_LEVEL1, DMPUB_NONE,
  665. PSMINOUTLINE_ITEM, HELP_INDEX_PSMINOUTLINE,
  666. 2, TVOT_UDARROW,
  667. IDS_PIXELS, IDI_USE_DEFAULT,
  668. 0, 0,
  669. ITEM_INFO_SIGNATURE
  670. };
  671. static CONST WORD MaxBitmapItemInfo[] =
  672. {
  673. IDS_PSMAXBITMAP, TVITEM_LEVEL1, DMPUB_NONE,
  674. PSMAXBITMAP_ITEM, HELP_INDEX_PSMAXBITMAP,
  675. 2, TVOT_UDARROW,
  676. IDS_PIXELS, IDI_USE_DEFAULT,
  677. 0, 0,
  678. ITEM_INFO_SIGNATURE
  679. };
  680. BOOL
  681. _BPackPrinterOptions(
  682. IN OUT PUIDATA pUiData
  683. )
  684. /*++
  685. Routine Description:
  686. Pack driver-specific options (printer-sticky)
  687. Arguments:
  688. pUiData - Points to a UIDATA structure
  689. Return Value:
  690. TRUE for success and FALSE for failure
  691. --*/
  692. {
  693. PPRINTERDATA pPrinterData = pUiData->ci.pPrinterData;
  694. BOOL rc;
  695. //
  696. // Fill in the lower limit number of PrinterVMItemInfo
  697. // based on printer level.
  698. //
  699. PrinterVMItemInfo[10] = (pUiData->ci.pUIInfo->dwLangLevel <= 1 ? MIN_FREEMEM_L1 : MIN_FREEMEM_L2) / KBYTES;
  700. rc = BPackUDArrowItemTemplate(
  701. pUiData,
  702. PrinterVMItemInfo,
  703. pPrinterData->dwFreeMem / KBYTES,
  704. 0x7fff, NULL) &&
  705. BPackPSProtocolItem(pUiData) &&
  706. BPackOptItemTemplate(
  707. pUiData,
  708. CtrlDBeforeItemInfo,
  709. (pPrinterData->dwFlags & PFLAGS_CTRLD_BEFORE) ? 0 : 1, NULL) &&
  710. BPackOptItemTemplate(
  711. pUiData,
  712. CtrlDAfterItemInfo,
  713. (pPrinterData->dwFlags & PFLAGS_CTRLD_AFTER) ? 0 : 1, NULL) &&
  714. BPackOptItemTemplate(
  715. pUiData,
  716. TrueGrayTextItemInfo,
  717. (pPrinterData->dwFlags & PFLAGS_TRUE_GRAY_TEXT) ? 0 : 1, NULL) &&
  718. BPackOptItemTemplate(
  719. pUiData,
  720. TrueGrayGraphItemInfo,
  721. (pPrinterData->dwFlags & PFLAGS_TRUE_GRAY_GRAPH) ? 0 : 1, NULL);
  722. if (!rc)
  723. return FALSE;
  724. if (pUiData->ci.pUIInfo->dwLangLevel > 1)
  725. {
  726. rc = BPackOptItemTemplate(
  727. pUiData,
  728. AddEuroItemInfo,
  729. (pPrinterData->dwFlags & PFLAGS_ADD_EURO) ? 0 : 1, NULL);
  730. if (!rc)
  731. return FALSE;
  732. }
  733. return BPackUDArrowItemTemplate(
  734. pUiData,
  735. JobTimeoutItemInfo,
  736. pPrinterData->dwJobTimeout,
  737. 0x7fff, NULL) &&
  738. BPackUDArrowItemTemplate(
  739. pUiData,
  740. WaitTimeoutItemInfo,
  741. pPrinterData->dwWaitTimeout,
  742. 0x7fff, NULL) &&
  743. BPackUDArrowItemTemplate(
  744. pUiData,
  745. MinOutlineItemInfo,
  746. pPrinterData->wMinoutlinePPEM,
  747. 0x7fff, NULL) &&
  748. BPackUDArrowItemTemplate(
  749. pUiData,
  750. MaxBitmapItemInfo,
  751. pPrinterData->wMaxbitmapPPEM,
  752. 0x7fff, NULL);
  753. }
  754. VOID
  755. _VUnpackDriverPrnPropItem(
  756. PUIDATA pUiData,
  757. POPTITEM pOptItem
  758. )
  759. /*++
  760. Routine Description:
  761. Unpack driver-specific printer property items
  762. Arguments:
  763. pUiData - Points to our UIDATA structure
  764. pOptItem - Specifies the OPTITEM to be unpacked
  765. Return Value:
  766. NONE
  767. --*/
  768. {
  769. PPRINTERDATA pPrinterData = pUiData->ci.pPrinterData;
  770. switch (GETUSERDATAITEM(pOptItem->UserData))
  771. {
  772. case PRINTER_VM_ITEM:
  773. if (pUiData->ci.dwFlags & FLAG_USER_CHANGED_FREEMEM)
  774. {
  775. pPrinterData->dwFreeMem = pOptItem->Sel * KBYTES;
  776. }
  777. break;
  778. case PSPROTOCOL_ITEM:
  779. switch (pOptItem->Sel)
  780. {
  781. case 1:
  782. pPrinterData->wProtocol = PROTOCOL_BCP;
  783. break;
  784. case 2:
  785. pPrinterData->wProtocol = PROTOCOL_TBCP;
  786. break;
  787. case 3:
  788. pPrinterData->wProtocol = PROTOCOL_BINARY;
  789. break;
  790. default:
  791. pPrinterData->wProtocol = PROTOCOL_ASCII;
  792. break;
  793. }
  794. break;
  795. case CTRLD_BEFORE_ITEM:
  796. if (pOptItem->Sel == 0)
  797. pPrinterData->dwFlags |= PFLAGS_CTRLD_BEFORE;
  798. else
  799. pPrinterData->dwFlags &= ~PFLAGS_CTRLD_BEFORE;
  800. break;
  801. case CTRLD_AFTER_ITEM:
  802. if (pOptItem->Sel == 0)
  803. pPrinterData->dwFlags |= PFLAGS_CTRLD_AFTER;
  804. else
  805. pPrinterData->dwFlags &= ~PFLAGS_CTRLD_AFTER;
  806. break;
  807. case TRUE_GRAY_TEXT_ITEM:
  808. if (pOptItem->Sel == 0)
  809. pPrinterData->dwFlags |= PFLAGS_TRUE_GRAY_TEXT;
  810. else
  811. pPrinterData->dwFlags &= ~PFLAGS_TRUE_GRAY_TEXT;
  812. break;
  813. case TRUE_GRAY_GRAPH_ITEM:
  814. if (pOptItem->Sel == 0)
  815. pPrinterData->dwFlags |= PFLAGS_TRUE_GRAY_GRAPH;
  816. else
  817. pPrinterData->dwFlags &= ~PFLAGS_TRUE_GRAY_GRAPH;
  818. break;
  819. case ADD_EURO_ITEM:
  820. if (pOptItem->Sel == 0)
  821. pPrinterData->dwFlags |= PFLAGS_ADD_EURO;
  822. else
  823. pPrinterData->dwFlags &= ~PFLAGS_ADD_EURO;
  824. pPrinterData->dwFlags |= PFLAGS_EURO_SET;
  825. break;
  826. case PSMINOUTLINE_ITEM:
  827. pPrinterData->wMinoutlinePPEM = (WORD) pOptItem->Sel;
  828. break;
  829. case PSMAXBITMAP_ITEM:
  830. pPrinterData->wMaxbitmapPPEM = (WORD) pOptItem->Sel;
  831. break;
  832. }
  833. }
  834. BOOL
  835. BUpdateModelNtfFilename(
  836. PCOMMONINFO pci
  837. )
  838. /*++
  839. Routine Description:
  840. Save model-specific NTF filename under PrinterDriverData registry key
  841. for compatibility with the new NT4 driver.
  842. Arguments:
  843. pci - Points to basic printer information
  844. Return Value:
  845. TRUE if successful, FALSE if there is an error
  846. --*/
  847. {
  848. //
  849. // Get the list of driver dependent files and
  850. // save it in registry for NT4 compatibility
  851. //
  852. PTSTR ptstr, ptstrNext, ptstrDependentFiles, ptstrCopy, ptstrFileNamesWithoutPath;
  853. DWORD dwCharCount = 0;
  854. BOOL bResult;
  855. if ((ptstrDependentFiles = pci->pDriverInfo3->pDependentFiles) == NULL)
  856. {
  857. return BSetPrinterDataString(pci->hPrinter,
  858. REGVAL_DEPFILES,
  859. ptstrDependentFiles,
  860. REG_MULTI_SZ);
  861. }
  862. //
  863. // First pass of the MULTI_SZ string to get file names char count
  864. //
  865. while (*ptstrDependentFiles != NUL)
  866. {
  867. //
  868. // Go the end of current string
  869. //
  870. ptstr = ptstrDependentFiles + _tcslen(ptstrDependentFiles);
  871. ptstrNext = ptstr + 1;
  872. dwCharCount++; // for the NUL char of current string
  873. //
  874. // Search backward for '\' path separator
  875. //
  876. while (--ptstr >= ptstrDependentFiles)
  877. {
  878. if (*ptstr == TEXT(PATH_SEPARATOR))
  879. {
  880. break;
  881. }
  882. dwCharCount++;
  883. }
  884. ptstrDependentFiles = ptstrNext;
  885. }
  886. dwCharCount++; // for the last NUL of the MULTI_SZ string
  887. if ((ptstrFileNamesWithoutPath = MemAllocZ(dwCharCount * sizeof(TCHAR))) == NULL)
  888. {
  889. ERR(("Memory allocation failed\n"));
  890. return FALSE;
  891. }
  892. //
  893. // Second pass of the MULTI_SZ string to copy the file names
  894. //
  895. ptstrDependentFiles = pci->pDriverInfo3->pDependentFiles;
  896. ptstrCopy = ptstrFileNamesWithoutPath;
  897. while (*ptstrDependentFiles != NUL)
  898. {
  899. INT iNameLen;
  900. //
  901. // Go the end of current string
  902. //
  903. ptstr = ptstrDependentFiles + _tcslen(ptstrDependentFiles);
  904. ptstrNext = ptstr + 1;
  905. //
  906. // Search backward for '\' path separator
  907. //
  908. while (--ptstr >= ptstrDependentFiles)
  909. {
  910. if (*ptstr == TEXT(PATH_SEPARATOR))
  911. {
  912. break;
  913. }
  914. }
  915. ptstr++; // point to the char after '\'
  916. iNameLen = _tcslen(ptstr);
  917. CopyMemory(ptstrCopy, ptstr, iNameLen * sizeof(TCHAR));
  918. ptstrCopy += iNameLen + 1;
  919. ptstrDependentFiles = ptstrNext;
  920. }
  921. bResult = BSetPrinterDataString(pci->hPrinter,
  922. REGVAL_DEPFILES,
  923. ptstrFileNamesWithoutPath,
  924. REG_MULTI_SZ);
  925. MemFree(ptstrFileNamesWithoutPath);
  926. return bResult;
  927. }
  928. #ifdef WINNT_40
  929. BOOL
  930. BUpdateVMErrorMessageID(
  931. PCOMMONINFO pci
  932. )
  933. /*++
  934. Routine Description:
  935. Save the VM Error message ID calculated from the current user's locale
  936. under PrinterDriverData registry key.
  937. Arguments:
  938. pci - Points to basic printer information
  939. Return Value:
  940. TRUE if successful, FALSE if there is an error
  941. --*/
  942. {
  943. DWORD dwVMErrorMessageID = DWGetVMErrorMessageID();
  944. return BSetPrinterDataDWord(pci->hPrinter,
  945. REGVAL_VMERRORMESSAGEID,
  946. dwVMErrorMessageID);
  947. }
  948. #endif // WINNT_40
  949. INT
  950. _IListDevFontNames(
  951. HDC hdc,
  952. PWSTR pwstrBuf,
  953. INT iSize
  954. )
  955. {
  956. DWORD dwParam = QUERY_FAMILYNAME;
  957. //
  958. // Ask the driver graphics module for the list of permanant device fonts
  959. //
  960. return ExtEscape(hdc,
  961. DRIVERESC_QUERY_DEVFONTS,
  962. sizeof(dwParam),
  963. (PCSTR) &dwParam,
  964. iSize,
  965. (PSTR) pwstrBuf);
  966. }
  967. INT_PTR CALLBACK
  968. _AboutDlgProc(
  969. HWND hDlg,
  970. UINT message,
  971. WPARAM wParam,
  972. LPARAM lParam
  973. )
  974. /*++
  975. Routine Description:
  976. Procedure for handling "Printer Properties" proerty sheet page
  977. Arguments:
  978. hDlg - Identifies the property sheet page
  979. message - Specifies the message
  980. wParam - Specifies additional message-specific information
  981. lParam - Specifies additional message-specific information
  982. Return Value:
  983. Depends on the value of message parameter
  984. --*/
  985. {
  986. PUIDATA pUiData;
  987. PWSTR pPpdFilename;
  988. CHAR achBuf[64] = {0};
  989. CHAR achMsg[136] = {0};
  990. PPDDATA *pPpdData;
  991. switch (message)
  992. {
  993. case WM_INITDIALOG:
  994. //
  995. // Initialize the About dialog box
  996. //
  997. pUiData = (PUIDATA) lParam;
  998. ASSERT(VALIDUIDATA(pUiData));
  999. if (LoadStringA(ghInstance, IDS_PS_VERSION, achBuf, sizeof(achBuf) - 1))
  1000. {
  1001. #ifdef WINNT_40
  1002. if (FAILED(StringCchPrintfA(achMsg,
  1003. CCHOF(achMsg),
  1004. "%s (" VER_54DRIVERVERSION_STR ")",
  1005. achBuf)))
  1006. #else // WINNT_40
  1007. if (FAILED(StringCchPrintfA(achMsg,
  1008. CCHOF(achMsg),
  1009. "%s (" VER_PRODUCTVERSION_STR ")",
  1010. achBuf)))
  1011. #endif // WINNT_40
  1012. {
  1013. WARNING(("Device Settings About box version string truncated.\n"));
  1014. }
  1015. }
  1016. else
  1017. {
  1018. WARNING(("Device Setting About box attempt to load version string failed.\n"));
  1019. }
  1020. SetDlgItemTextA(hDlg, IDC_WINNT_VER, achMsg);
  1021. SetDlgItemText(hDlg, IDC_MODELNAME, pUiData->ci.pDriverInfo3->pName);
  1022. if (pPpdFilename = pUiData->ci.pDriverInfo3->pDataFile)
  1023. {
  1024. if (pPpdFilename = wcsrchr(pPpdFilename, TEXT(PATH_SEPARATOR)))
  1025. pPpdFilename++;
  1026. else
  1027. pPpdFilename = pUiData->ci.pDriverInfo3->pDataFile;
  1028. SetDlgItemText(hDlg, IDC_PPD_FILENAME, pPpdFilename);
  1029. pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER(pUiData->ci.pInfoHeader);
  1030. ASSERT(pPpdData != NULL);
  1031. StringCchPrintfA(achBuf,
  1032. CCHOF(achBuf),
  1033. "%d.%d",
  1034. HIWORD(pPpdData->dwPpdFilever), LOWORD(pPpdData->dwPpdFilever));
  1035. SetDlgItemTextA(hDlg, IDC_PPD_FILEVER, achBuf);
  1036. }
  1037. return TRUE;
  1038. case WM_COMMAND:
  1039. switch (LOWORD(wParam))
  1040. {
  1041. case IDOK:
  1042. case IDCANCEL:
  1043. EndDialog(hDlg, LOWORD(wParam));
  1044. return TRUE;
  1045. }
  1046. break;
  1047. }
  1048. return FALSE;
  1049. }
  1050. //
  1051. // Determine whether the printer supports stapling
  1052. //
  1053. BOOL
  1054. _BSupportStapling(
  1055. PCOMMONINFO pci
  1056. )
  1057. {
  1058. PFEATURE pFeature, pFeatureY;
  1059. DWORD dwIndex;
  1060. BOOL bStapleFeatureExist = FALSE;
  1061. //
  1062. // Except for *StapleOrientation (whose None option doesn't mean stapling off),
  1063. // if any of following stapling keywords appear in the PPD file, we check if that
  1064. // feature is supported with current installable option selections.
  1065. //
  1066. // *StapleLocation
  1067. // *StapleX
  1068. // *StapleY
  1069. // *StapleWhen
  1070. //
  1071. // PPD spec says that a PPD file can contain either *StapleLocation or
  1072. // *StapleX and *StapleY but not both.
  1073. //
  1074. if (pFeature = PGetNamedFeature(pci->pUIInfo, "StapleLocation", &dwIndex))
  1075. {
  1076. bStapleFeatureExist = TRUE;
  1077. if (!_BSupportFeature(pci, GID_UNKNOWN, pFeature))
  1078. {
  1079. return FALSE;
  1080. }
  1081. }
  1082. else if ( (pFeature = PGetNamedFeature(pci->pUIInfo, "StapleX", &dwIndex)) &&
  1083. (pFeatureY = PGetNamedFeature(pci->pUIInfo, "StapleY", &dwIndex)) )
  1084. {
  1085. bStapleFeatureExist = TRUE;
  1086. if (!_BSupportFeature(pci, GID_UNKNOWN, pFeature) ||
  1087. !_BSupportFeature(pci, GID_UNKNOWN, pFeatureY))
  1088. {
  1089. return FALSE;
  1090. }
  1091. }
  1092. if (pFeature = PGetNamedFeature(pci->pUIInfo, "StapleWhen", &dwIndex))
  1093. {
  1094. bStapleFeatureExist = TRUE;
  1095. if (!_BSupportFeature(pci, GID_UNKNOWN, pFeature))
  1096. {
  1097. return FALSE;
  1098. }
  1099. }
  1100. //
  1101. // We didn't find any constraints on the stapling features caused by installable options,
  1102. // so we will assume the printer can support stapling if any of the standard PPD stapling
  1103. // keywords are present.
  1104. //
  1105. return bStapleFeatureExist ||
  1106. PGetNamedFeature(pci->pUIInfo, "StapleOrientation", &dwIndex) != NULL;
  1107. }
  1108. BOOL
  1109. BFeatureIsConstrained(
  1110. PUIINFO pUIInfo,
  1111. PFEATURE pFeature,
  1112. DWORD dwFeatureIndex,
  1113. DWORD dwOptionCount,
  1114. DWORD dwConstraintList,
  1115. PBYTE aubConstrainedOption,
  1116. DWORD dwGid
  1117. )
  1118. /*++
  1119. Routine Description:
  1120. Determine whether the particular constraint list constrains feature options.
  1121. Arguments:
  1122. pUIInfo - Points to a UIINFO structure
  1123. pFeature - Points to feature structure to be checked whether constraint or not
  1124. dwFeatureIndex - index for the feature
  1125. dwOptionCount - number of options for the feature
  1126. dwConstraintList - Specifies the constraint list to be searched
  1127. aubConstrainedOption - Byte array of option constrained flag
  1128. dwGid - GID_DUPLEX, GID_COLLATE or GID_UNKNOWN to allow feature specific don't cares
  1129. Return Value:
  1130. TRUE if the feature is constrained by the constraint list, FALSE otherwise.
  1131. --*/
  1132. {
  1133. POPTION pOption;
  1134. DWORD dwOptionIndex;
  1135. ASSERT(dwOptionCount < MAX_PRINTER_OPTIONS);
  1136. if (dwConstraintList == NULL_CONSTRAINT)
  1137. return FALSE;
  1138. for (dwOptionIndex = 0; dwOptionIndex < dwOptionCount; dwOptionIndex++)
  1139. {
  1140. pOption = PGetIndexedOption(pUIInfo, pFeature, dwOptionIndex);
  1141. ASSERT(pOption != NULL);
  1142. switch(dwGid)
  1143. {
  1144. case GID_COLLATE:
  1145. //
  1146. // don't care about constraints for no-collate
  1147. //
  1148. if (((PCOLLATE) pOption)->dwCollateID == DMCOLLATE_FALSE)
  1149. continue;
  1150. break;
  1151. case GID_DUPLEX:
  1152. //
  1153. // don't care about constraints for non-duplex
  1154. //
  1155. if (((PDUPLEX) pOption)->dwDuplexID == DMDUP_SIMPLEX)
  1156. continue;
  1157. break;
  1158. case GID_UNKNOWN:
  1159. default:
  1160. //
  1161. // skip the check for None/False option
  1162. //
  1163. if (pFeature->dwNoneFalseOptIndex == dwOptionIndex)
  1164. continue;
  1165. break;
  1166. }
  1167. if (BSearchConstraintList(pUIInfo, dwConstraintList,
  1168. dwFeatureIndex, dwOptionIndex))
  1169. {
  1170. aubConstrainedOption[dwOptionIndex] = 1;
  1171. }
  1172. //
  1173. // If one option is unconstrained, the feature is not constrained by the
  1174. // constraint list
  1175. //
  1176. if (!aubConstrainedOption[dwOptionIndex])
  1177. return FALSE;
  1178. }
  1179. return TRUE;
  1180. }
  1181. BOOL
  1182. _BSupportFeature(
  1183. PCOMMONINFO pci,
  1184. DWORD dwGid,
  1185. PFEATURE pFeatureIn
  1186. )
  1187. /*++
  1188. Routine Description:
  1189. Determine whether the printer supports a feature based on current printer-sticky
  1190. feature selections.
  1191. Arguments:
  1192. pci - Points to basic printer information
  1193. dwGid - the GID of the feature to check for constraints. (currently only GID_COLLATE or GID_DUPLEX
  1194. if pFeatureIn is NULL)
  1195. pFeatureIn - pointer to the feature structure if the feature doesn't have predefined GID_xxx value
  1196. Return Value:
  1197. TRUE if feature can be supported, FALSE otherwise.
  1198. --*/
  1199. {
  1200. POPTSELECT pCombinedOptions = pci->pCombinedOptions;
  1201. PUIINFO pUIInfo = pci->pUIInfo;
  1202. PFEATURE pCheckFeature, pFeature;
  1203. POPTION pOption;
  1204. BYTE aubConstrainedOption[MAX_PRINTER_OPTIONS];
  1205. DWORD dwCheckFeatureIndex, dwCheckOptionCount;
  1206. DWORD dwFeatureIndex;
  1207. BYTE ubCurOptIndex, ubNext;
  1208. if (!pCombinedOptions)
  1209. return FALSE;
  1210. if (pFeatureIn)
  1211. {
  1212. //
  1213. // If the input feature pointer is provided, dwGid should be GID_UNKNOWN.
  1214. //
  1215. ASSERT(dwGid == GID_UNKNOWN);
  1216. pCheckFeature = pFeatureIn;
  1217. }
  1218. else
  1219. {
  1220. //
  1221. // If no input feature pointer, use dwGid to find the feature. dwGid should be
  1222. // either GID_DUPLEX or GID_COLLATE.
  1223. //
  1224. ASSERT((dwGid == GID_DUPLEX) || (dwGid == GID_COLLATE));
  1225. if (!(pCheckFeature = GET_PREDEFINED_FEATURE(pUIInfo, dwGid)))
  1226. return FALSE;
  1227. }
  1228. dwCheckFeatureIndex = GET_INDEX_FROM_FEATURE(pUIInfo, pCheckFeature);
  1229. dwCheckOptionCount = pCheckFeature->Options.dwCount;
  1230. //
  1231. // Mark all options of the checked feature as non-constrained.
  1232. //
  1233. memset(aubConstrainedOption, 0, sizeof(aubConstrainedOption));
  1234. //
  1235. // Scan the feature list to check if it will be constrained by current selections
  1236. //
  1237. if (!(pFeature = OFFSET_TO_POINTER(pUIInfo->pInfoHeader, pUIInfo->loFeatureList)))
  1238. return FALSE;
  1239. //
  1240. // We only care about printer-sticky features
  1241. //
  1242. pFeature += pUIInfo->dwDocumentFeatures;
  1243. for (dwFeatureIndex = pUIInfo->dwDocumentFeatures;
  1244. dwFeatureIndex < pUIInfo->dwDocumentFeatures + pUIInfo->dwPrinterFeatures;
  1245. dwFeatureIndex++, pFeature++)
  1246. {
  1247. //
  1248. // If the feature's current selection is not None/False, it may constrain the checked feature
  1249. //
  1250. if ((DWORD)pCombinedOptions[dwFeatureIndex].ubCurOptIndex != pFeature->dwNoneFalseOptIndex)
  1251. {
  1252. if (BFeatureIsConstrained(pUIInfo, pCheckFeature, dwCheckFeatureIndex, dwCheckOptionCount,
  1253. pFeature->dwUIConstraintList, aubConstrainedOption, dwGid))
  1254. return FALSE;
  1255. }
  1256. ubNext = (BYTE)dwFeatureIndex;
  1257. while (1)
  1258. {
  1259. ubCurOptIndex = pCombinedOptions[ubNext].ubCurOptIndex;
  1260. pOption = PGetIndexedOption(pUIInfo, pFeature, ubCurOptIndex == OPTION_INDEX_ANY ? 0 : ubCurOptIndex);
  1261. if (pOption && BFeatureIsConstrained(pUIInfo, pCheckFeature, dwCheckFeatureIndex, dwCheckOptionCount,
  1262. pOption->dwUIConstraintList, aubConstrainedOption, dwGid))
  1263. return FALSE;
  1264. if ((ubNext = pCombinedOptions[ubNext].ubNext) == NULL_OPTSELECT)
  1265. break;
  1266. }
  1267. }
  1268. //
  1269. // No constraints found, so the feature can be supported.
  1270. //
  1271. return TRUE;
  1272. }
  1273. VOID
  1274. VSyncRevPrintAndOutputOrder(
  1275. PUIDATA pUiData,
  1276. POPTITEM pCurItem
  1277. )
  1278. /*++
  1279. Routine Description:
  1280. For PostScript driver, PPD could have "*OpenUI *OutputOrder", which enables user to
  1281. select "Normal" or "Reverse" output order. In order to avoid spooler performing reverse
  1282. printing simulation, we will ssync up option selections between REVPRINT_ITEM and
  1283. "OutputOrder".
  1284. Arguments:
  1285. pUiData - Pointer to UIDATA structure
  1286. pCurItem - Pointer to currently selected option item. It will be non-NULL for
  1287. REVPRINT_ITEM, and will be NULL otherwise.
  1288. Return Value:
  1289. None.
  1290. --*/
  1291. {
  1292. PUIINFO pUIInfo;
  1293. PPPDDATA pPpdData;
  1294. PFEATURE pFeature;
  1295. POPTION pOption;
  1296. PCSTR pstrKeywordName;
  1297. POPTITEM pRevPrintItem, pOutputOrderItem;
  1298. BOOL bReverse;
  1299. ASSERT(VALIDUIDATA(pUiData));
  1300. pUIInfo = pUiData->ci.pUIInfo;
  1301. pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER((PINFOHEADER)pUiData->ci.pRawData);
  1302. ASSERT(pPpdData != NULL);
  1303. if (pPpdData->dwOutputOrderIndex != INVALID_FEATURE_INDEX &&
  1304. (pOutputOrderItem = PFindOptItemWithKeyword(pUiData, "OutputOrder")) &&
  1305. pOutputOrderItem->Sel < 2 &&
  1306. (pFeature = PGetIndexedFeature(pUIInfo, pPpdData->dwOutputOrderIndex)) &&
  1307. (pOption = PGetIndexedOption(pUIInfo, pFeature, pOutputOrderItem->Sel)) &&
  1308. (pstrKeywordName = OFFSET_TO_POINTER(pUIInfo->pubResourceData, pOption->loKeywordName)))
  1309. {
  1310. //
  1311. // "OutputOrder" feature is available.
  1312. //
  1313. if (strcmp(pstrKeywordName, "Reverse") == EQUAL_STRING)
  1314. bReverse = TRUE;
  1315. else
  1316. bReverse = FALSE;
  1317. if (pCurItem)
  1318. {
  1319. //
  1320. // Currently selected item is REVPRINT_ITEM. We should change "OutputOrder" option
  1321. // if needed to match the requested output order.
  1322. //
  1323. if ((pCurItem->Sel == 0 && bReverse) || (pCurItem->Sel == 1 && !bReverse))
  1324. {
  1325. pOutputOrderItem->Sel = 1 - pOutputOrderItem->Sel;
  1326. pOutputOrderItem->Flags |= OPTIF_CHANGED;
  1327. //
  1328. // Save the new settings in the options array
  1329. //
  1330. VUnpackDocumentPropertiesItems(pUiData, pOutputOrderItem, 1);
  1331. //
  1332. // The change could trigger constraints.
  1333. //
  1334. if (ICheckConstraintsDlg(pUiData, pOutputOrderItem, 1, FALSE) == CONFLICT_CANCEL)
  1335. {
  1336. //
  1337. // If there is a conflict and the user clicked CANCEL,
  1338. // we need to restore the origianl selection.
  1339. //
  1340. pCurItem->Sel = 1 - pCurItem->Sel;
  1341. pCurItem->Flags |= OPTIF_CHANGED;
  1342. VUnpackDocumentPropertiesItems(pUiData, pCurItem, 1);
  1343. pOutputOrderItem->Sel = 1 - pOutputOrderItem->Sel;
  1344. pOutputOrderItem->Flags |= OPTIF_CHANGED;
  1345. VUnpackDocumentPropertiesItems(pUiData, pOutputOrderItem, 1);
  1346. }
  1347. }
  1348. }
  1349. else
  1350. {
  1351. //
  1352. // Sync up REVPRINT_ITEM selection based on "OutputOrder" selection.
  1353. //
  1354. if ((pRevPrintItem = PFindOptItemWithUserData(pUiData, REVPRINT_ITEM)) &&
  1355. ((pRevPrintItem->Sel == 0 && bReverse) || (pRevPrintItem->Sel == 1 && !bReverse)))
  1356. {
  1357. pRevPrintItem->Sel = 1 - pRevPrintItem->Sel;
  1358. pRevPrintItem->Flags |= OPTIF_CHANGED;
  1359. //
  1360. // Save the new settings in the options array
  1361. //
  1362. VUnpackDocumentPropertiesItems(pUiData, pRevPrintItem, 1);
  1363. }
  1364. }
  1365. }
  1366. }