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.

2104 lines
79 KiB

  1. /*++
  2. Copyright (c) 1996-1998 Microsoft Corporation
  3. Module Name:
  4. uientry.c
  5. Abstract:
  6. This file implements functions that generate UI related GPD entries, such
  7. as *Feature, *Option, etc.
  8. Environment:
  9. User-mode, stand-alone utility tool
  10. Revision History:
  11. 10/16/96 -zhanw-
  12. Created it.
  13. 04/16/97 -zhanw-
  14. Generated Halftone and palette ColorMode options.
  15. --*/
  16. #include "gpc2gpd.h"
  17. //
  18. // the following constant definitions must match "printer5\inc\common.rc".
  19. //
  20. #define RCID_ORIENTATION 11100
  21. #define RCID_PAPERSIZE 11101
  22. #define RCID_INPUTBIN 11102
  23. #define RCID_RESOLUTION 11103
  24. #define RCID_MEDIATYPE 11104
  25. #define RCID_TEXTQUALITY 11105
  26. #define RCID_COLORMODE 11106
  27. #define RCID_MEMORY 11107
  28. #define RCID_DUPLEX 11108
  29. #define RCID_PAGEPROTECTION 11109
  30. #define RCID_HALFTONE 11110
  31. #define RCID_PORTRAIT 11025
  32. #define RCID_LANDSCAPE 11026
  33. #define RCID_MONO 11030
  34. #define RCID_COLOR 11031
  35. #define RCID_8BPP 11032
  36. #define RCID_24BPP 11033
  37. #define RCID_NONE 11040
  38. #define RCID_FLIP_ON_LONG_EDGE 11041
  39. #define RCID_FLIP_ON_SHORT_EDGE 11042
  40. #define RCID_HT_AUTO_SELECT 11050
  41. #define RCID_HT_SUPERCELL 11051
  42. #define RCID_HT_DITHER6X6 11052
  43. #define RCID_HT_DITHER8X8 11053
  44. #define RCID_ON 11090
  45. #define RCID_OFF 11091
  46. #define RCID_DOTS_PER_INCH 11400
  47. #define RCID_PAPER_SYSTEMNAME 0x7fffffff
  48. // secret value that the UI code will understand
  49. // to mean, do enumForms to determine the actual paper name
  50. void
  51. VOutputOrientation(
  52. IN OUT PCONVINFO pci)
  53. {
  54. BOOL bDocSetup;
  55. WORD wOrder;
  56. VOut(pci, "*Feature: Orientation\r\n");
  57. VOut(pci, "{\r\n");
  58. if (pci->dwStrType == STR_MACRO)
  59. VOut(pci, " *rcNameID: =ORIENTATION_DISPLAY\r\n");
  60. else if (pci->dwStrType == STR_DIRECT)
  61. VOut(pci, " *Name: \"Orientation\"\r\n");
  62. else
  63. VOut(pci, " *rcNameID: %d\r\n", RCID_ORIENTATION);
  64. VOut(pci, " *DefaultOption: PORTRAIT\r\n");
  65. VOut(pci, " *Option: PORTRAIT\r\n");
  66. VOut(pci, " {\r\n");
  67. if (pci->dwStrType == STR_MACRO)
  68. VOut(pci, " *rcNameID: =PORTRAIT_DISPLAY\r\n");
  69. else if (pci->dwStrType == STR_DIRECT)
  70. VOut(pci, " *Name: \"Portrait\"\r\n");
  71. else
  72. VOut(pci, " *rcNameID: %d\r\n", RCID_PORTRAIT);
  73. //
  74. // check if there is orientation selection commands.
  75. //
  76. bDocSetup = BInDocSetup(pci, PC_ORD_ORIENTATION, &wOrder);
  77. if (wOrder > 0 &&
  78. BBuildCmdStr(pci, CMD_PC_PORTRAIT, pci->ppc->rgocd[PC_OCD_PORTRAIT]))
  79. VOutputSelectionCmd(pci, bDocSetup, wOrder);
  80. VOut(pci, " }\r\n");
  81. //
  82. // now compose Landscape option
  83. //
  84. if (pci->pmd->fGeneral & MD_LANDSCAPE_RT90)
  85. VOut(pci, " *Option: LANDSCAPE_CC90\r\n");
  86. else
  87. VOut(pci, " *Option: LANDSCAPE_CC270\r\n");
  88. VOut(pci, " {\r\n");
  89. if (pci->dwStrType == STR_MACRO)
  90. VOut(pci, " *rcNameID: =LANDSCAPE_DISPLAY\r\n");
  91. else if (pci->dwStrType == STR_DIRECT)
  92. VOut(pci, " *Name: \"Landscape\"\r\n");
  93. else
  94. VOut(pci, " *rcNameID: %d\r\n", RCID_LANDSCAPE);
  95. if (wOrder > 0 &&
  96. BBuildCmdStr(pci, CMD_PC_LANDSCAPE, pci->ppc->rgocd[PC_OCD_LANDSCAPE]))
  97. {
  98. VOutputSelectionCmd(pci, bDocSetup, wOrder);
  99. pci->dwMode |= FM_SET_CURSOR_ORIGIN;
  100. }
  101. VOut(pci, " }\r\n"); // close Landscape option
  102. VOut(pci, "}\r\n"); // close Orientation feature
  103. }
  104. WORD
  105. WGetDefaultIndex(
  106. IN PCONVINFO pci,
  107. IN WORD wMDOI)
  108. {
  109. WORD wDefault; // 1-based option index
  110. PWORD pwDefList;
  111. WORD wOffset;
  112. //
  113. // it's guaranteed that there is at least one element in the list
  114. //
  115. if (pci->pdh->wVersion >= GPC_VERSION3 && pci->pmd->orgoiDefaults)
  116. {
  117. pwDefList = (PWORD)((PBYTE)(pci->pdh) + pci->pdh->loHeap + pci->pmd->orgoiDefaults);
  118. if (wMDOI > MD_OI_MAX)
  119. wOffset = wMDOI - MD_I_MAX; // skip over rgi[] array
  120. else
  121. wOffset = wMDOI;
  122. wDefault = pwDefList[wOffset];
  123. }
  124. else
  125. wDefault = 1;
  126. return wDefault;
  127. }
  128. void
  129. VGetOptionName(
  130. OUT PSTR pBuf, // output buffer
  131. IN short sSize, // size of output buffer
  132. IN short sID, // paper size id
  133. IN WORD wIndex, // paper size option index (1-based)
  134. IN PSTR *pstrStdName, // array of standard names indexed by id
  135. IN BOOL bUser) // whether there is a special 256 id. Only
  136. // PaperSize uses this option.
  137. {
  138. if (sID < 256)
  139. {
  140. //
  141. // standard id
  142. //
  143. StringCchPrintfA(pBuf, sSize, "%s", pstrStdName[sID-1]);
  144. }
  145. else if (sID == 256)
  146. {
  147. //
  148. // custom paper size
  149. //
  150. StringCchPrintfA(pBuf, sSize, "%s", "CUSTOMSIZE");
  151. }
  152. else
  153. {
  154. //
  155. // driver defined paper size. Use the artificial name OptionX where
  156. // X is the 1-based index of this option. It's guaranteed not to
  157. // collide with other option names.
  158. //
  159. StringCchPrintfA(pBuf, sSize, "Option%d", wIndex);
  160. }
  161. }
  162. void
  163. VOutputInputBin(
  164. IN OUT PCONVINFO pci,
  165. IN PSHORT psIndex)
  166. {
  167. WORD wDefaultOption;
  168. PPAPERSOURCE pps;
  169. WORD wCount;
  170. BOOL bDocSetup;
  171. WORD wOrder;
  172. VOut(pci, "*Feature: InputBin\r\n");
  173. VOut(pci, "{\r\n");
  174. if (pci->dwStrType == STR_MACRO)
  175. VOut(pci, " *rcNameID: =PAPER_SOURCE_DISPLAY\r\n");
  176. else if (pci->dwStrType == STR_DIRECT)
  177. VOut(pci, " *Name: \"Paper Source\"\r\n");
  178. else
  179. VOut(pci, " *rcNameID: %d\r\n", RCID_INPUTBIN);
  180. wDefaultOption = WGetDefaultIndex(pci, MD_OI_PAPERSOURCE);
  181. pps = (PPAPERSOURCE)GetTableInfo(pci->pdh, HE_PAPERSOURCE,
  182. *(psIndex + wDefaultOption - 1) - 1);
  183. //
  184. // steal pci->aubCmdBuf to hold the composed option name temporarily
  185. //
  186. VGetOptionName((PSTR)pci->aubCmdBuf,
  187. CCHOF(pci->aubCmdBuf),
  188. pps->sPaperSourceID, wDefaultOption,
  189. gpstrStdIBName, FALSE);
  190. VOut(pci, " *DefaultOption: %s\r\n", (PSTR)pci->aubCmdBuf);
  191. //
  192. // loop through index list to create one option for each element
  193. //
  194. wCount = 1;
  195. while (*psIndex)
  196. {
  197. pps = (PPAPERSOURCE)GetTableInfo(pci->pdh, HE_PAPERSOURCE, *psIndex - 1);
  198. VGetOptionName((PSTR)pci->aubCmdBuf,
  199. CCHOF(pci->aubCmdBuf),
  200. pps->sPaperSourceID, wCount,
  201. gpstrStdIBName, FALSE);
  202. //
  203. // set up info needed later
  204. //
  205. CopyStringA(pci->ppiSrc[wCount-1].aubOptName, pci->aubCmdBuf,
  206. MAX_OPTION_NAME_LENGTH);
  207. pci->ppiSrc[wCount-1].bEjectFF = pps->fGeneral & PSRC_EJECTFF;
  208. pci->ppiSrc[wCount-1].dwPaperType = (DWORD)pps->fPaperType;
  209. VOut(pci, " *Option: %s\r\n", (PSTR)pci->aubCmdBuf);
  210. VOut(pci, " {\r\n");
  211. //
  212. // for standard InputBin options, use *Name. Otherwise,
  213. // use *rcNameID.
  214. //
  215. if (pps->sPaperSourceID < DMBIN_USER)
  216. {
  217. if (pci->dwStrType == STR_MACRO)
  218. VOut(pci, " *rcNameID: =%s\r\n",
  219. gpstrStdIBDisplayNameMacro[pps->sPaperSourceID - 1]);
  220. else if (pci->dwStrType == STR_DIRECT)
  221. VOut(pci, " *Name: \"%s\"\r\n",
  222. gpstrStdIBDisplayName[pps->sPaperSourceID - 1]);
  223. else
  224. VOut(pci, " *rcNameID: %d\r\n",
  225. STD_IB_DISPLAY_NAME_ID_BASE + pps->sPaperSourceID - 1);
  226. }
  227. else // must be driver defined media type
  228. {
  229. VOut(pci, " *rcNameID: %d\r\n", pps->sPaperSourceID);
  230. if (pps->sPaperSourceID > DMBIN_USER)
  231. VOut(pci, " *OptionID: %d\r\n", pps->sPaperSourceID);
  232. }
  233. //
  234. // check for fields not used by RASDD but used by Win95 Unidrv.
  235. //
  236. if (pps->fGeneral & PSRC_MAN_PROMPT)
  237. {
  238. pci->dwErrorCode |= ERR_PSRC_MAN_PROMPT;
  239. VOut(pci, "*%% Warning: this input bin has PSRC_MAN_PROMPT set in GPC, which is ignored by GPD.\r\n");
  240. }
  241. #if 0 // move *FeedMargins into CUSTOMSIZE option
  242. //
  243. // check paper feed margins
  244. //
  245. if (pps->sTopMargin > 0 || pps->sBottomMargin > 0)
  246. VOut(pci, " *FeedMargins: PAIR(%d, %d)\r\n",
  247. pps->sTopMargin > 0 ? pps->sTopMargin : 0,
  248. pps->sBottomMargin > 0 ? pps->sBottomMargin : 0);
  249. #else
  250. if (pps->sTopMargin > 0 || pps->sBottomMargin > 0)
  251. {
  252. pci->dwMode |= FM_HAVE_SEEN_NON_ZERO_FEED_MARGINS;
  253. if (pci->pmd->fGeneral & MD_LANDSCAPE_RT90)
  254. VOut(pci, "*%% Error: this input bin has non-zero top/bottom margins which are ignored by the converter.\r\n");
  255. pci->ppiSrc[wCount-1].dwTopMargin =
  256. pps->sTopMargin > 0 ? (DWORD)pps->sTopMargin : 0;
  257. pci->ppiSrc[wCount-1].dwBottomMargin =
  258. pps->sBottomMargin > 0 ? (DWORD)pps->sBottomMargin : 0;
  259. }
  260. #endif
  261. #if 0
  262. //
  263. // bin adjustment flags have never been used on NT. Remove them.
  264. //
  265. VOut(pci, " *PaperFeed: %s_%s\r\n",
  266. gpstrPositionName[pps->sBinAdjust & 0x00FF],
  267. gpstrPositionName[pps->sBinAdjust & 0xFF00]);
  268. #endif
  269. //
  270. // check selection command.
  271. //
  272. bDocSetup = BInDocSetup(pci, PC_ORD_PAPER_SOURCE, &wOrder);
  273. if (wOrder > 0 && BBuildCmdStr(pci, CMD_PAPERSOURCE, pps->ocdSelect))
  274. VOutputSelectionCmd(pci, bDocSetup, wOrder);
  275. VOut(pci, " }\r\n"); // close the option
  276. psIndex++;
  277. wCount++;
  278. }
  279. pci->dwNumOfSrc = wCount - 1;
  280. //
  281. // for optimization: check if all feed margins happen to be
  282. // the same. If so, don't need to create dependency on
  283. // InputBin feature later on.
  284. //
  285. {
  286. BOOL bSame = TRUE;
  287. DWORD i;
  288. for (i = 1; bSame && i < pci->dwNumOfSrc; i++)
  289. bSame = bSame &&
  290. (pci->ppiSrc[i].dwTopMargin==pci->ppiSrc[0].dwTopMargin) &&
  291. (pci->ppiSrc[i].dwBottomMargin==pci->ppiSrc[0].dwBottomMargin);
  292. if (bSame)
  293. pci->dwMode |= FM_HAVE_SAME_TOP_BOTTOM_MARGINS;
  294. }
  295. VOut(pci, "}\r\n"); // close InputBin feature
  296. }
  297. void
  298. VOutputDummyInputBin(
  299. IN OUT PCONVINFO pci)
  300. {
  301. VOut(pci, "*Feature: InputBin\r\n");
  302. VOut(pci, "{\r\n");
  303. if (pci->dwStrType == STR_MACRO)
  304. VOut(pci, " *rcNameID: =PAPER_SOURCE_DISPLAY\r\n");
  305. else if (pci->dwStrType == STR_DIRECT)
  306. VOut(pci, " *Name: \"Paper Source\"\r\n");
  307. else
  308. VOut(pci, " *rcNameID: %d\r\n", RCID_INPUTBIN);
  309. VOut(pci, " *DefaultOption: AUTO\r\n");
  310. VOut(pci, " *Option: AUTO\r\n");
  311. VOut(pci, " {\r\n");
  312. if (pci->dwStrType == STR_MACRO)
  313. VOut(pci, " *rcNameID: =%s\r\n",
  314. gpstrStdIBDisplayNameMacro[6]);
  315. else if (pci->dwStrType == STR_DIRECT)
  316. VOut(pci, " *Name: \"%s\"\r\n",
  317. gpstrStdIBDisplayName[6]);
  318. else
  319. VOut(pci, " *rcNameID: 10262\r\n");
  320. VOut(pci, " }\r\n"); // Close option
  321. VOut(pci, "}\r\n"); // Close feature
  322. }
  323. void
  324. VOutputPSOthers(
  325. IN OUT PCONVINFO pci,
  326. IN POINTw * pptSize,
  327. IN BOOL bRotateSize,
  328. IN RECTw * prcMargins,
  329. IN POINTw * pptCursorOrig,
  330. IN OCD ocd,
  331. IN BOOL bL4Indentation)
  332. /*++
  333. Routine Description:
  334. This function outputs other left-over PAPERSIZE fields, i.e. printable area,
  335. printable origin, cursor origin, and selection command. The
  336. indentation is either 8 or 16 spaces if bL4Indentation is TRUE.
  337. Enforce that *PrintableArea and *PrintableOrigin are divisible by the scale
  338. of any resolution. If not, truncate *PrintableArea and/or round up
  339. *PrintableOrigin.
  340. Enforce that if the printer can rotate the logical coordinate, then
  341. *CursorOrigin are divisible by the scale of
  342. the move units. If not, round up *CursorOrigin.
  343. Arguments:
  344. pci: conversion relatedi info
  345. pptSize: 2 short's describing the physical x/y dimensions in Portrait
  346. prcMargins: 4 short's describing the margins
  347. pptCursorOrig: 2 short's describing the cursor origin in Portrait
  348. ocd: the heap offset of the command
  349. bL4Indentation: whether to use Level 4 or Level 2 indentation
  350. Return Value:
  351. None
  352. --*/
  353. {
  354. WORD x, y; // temporary variables
  355. WORD xSize, ySize; // temporary variables
  356. POINTw ptSize; // store printable area values
  357. WORD xScale, yScale;
  358. BOOL bOutputResDependency = FALSE;
  359. BOOL bOutputSwitch = TRUE;
  360. BOOL bDocSetup;
  361. WORD wOrder;
  362. WORD i;
  363. if (pptSize && prcMargins)
  364. {
  365. if (bRotateSize)
  366. {
  367. ptSize.x = pptSize->y - prcMargins->left - prcMargins->right;
  368. ptSize.y = pptSize->x - prcMargins->top - prcMargins->bottom;
  369. }
  370. else
  371. {
  372. ptSize.x = pptSize->x - prcMargins->left - prcMargins->right;
  373. ptSize.y = pptSize->y - prcMargins->top - prcMargins->bottom;
  374. }
  375. //
  376. // use the original value as the base. Generate the dependency on
  377. // Resolution only if there is at least one resolution that requires
  378. // adjustement.
  379. //
  380. VOut(pci, "%s *PrintableArea: PAIR(%d, %d)\r\n",
  381. bL4Indentation? " " : "", ptSize.x, ptSize.y);
  382. VOut(pci, "%s *PrintableOrigin: PAIR(%d, %d)\r\n",
  383. bL4Indentation? " " : "",
  384. prcMargins->left, prcMargins->top);
  385. //
  386. // ensure that the printable area and origin are divisible by the
  387. // scale of any resolution. Truncate the printable area if needed.
  388. // Round up the printable origin if needed. Also, must ensure that
  389. // the new printable area is contained within the old printable area.
  390. //
  391. for (i = 0; i < (WORD)pci->dwNumOfRes; i++)
  392. {
  393. xScale = (WORD)pci->presinfo[i].dwXScale;
  394. yScale = (WORD)pci->presinfo[i].dwYScale;
  395. xSize = (ptSize.x / xScale) * xScale;
  396. ySize = (ptSize.y / yScale) * yScale;
  397. x = ((prcMargins->left + xScale - 1) / xScale) * xScale;
  398. y = ((prcMargins->top + yScale - 1) / yScale) * yScale;
  399. //
  400. // check if the new printable area is contained within the old
  401. // printable area. If not, truncate the printable width or
  402. // length further.
  403. //
  404. if (x + xSize > prcMargins->left + ptSize.x)
  405. xSize -= xScale;
  406. if (y + ySize > prcMargins->top + ptSize.y)
  407. ySize -= yScale;
  408. if (xSize == ptSize.x && ySize == ptSize.y &&
  409. x == prcMargins->left && y == prcMargins->top)
  410. continue; // no adjustment needed for this resolution
  411. //
  412. // otherwise, some adjustment is needed.
  413. //
  414. bOutputResDependency = TRUE;
  415. if (bOutputSwitch)
  416. {
  417. VOut(pci, "%s *switch: Resolution\r\n%s {\r\n",
  418. bL4Indentation? " " : "",
  419. bL4Indentation? " " : "");
  420. bOutputSwitch = FALSE;
  421. }
  422. VOut(pci, "%s *case: %s\r\n%s {\r\n",
  423. bL4Indentation? " " : "",
  424. pci->presinfo[i].aubOptName,
  425. bL4Indentation? " " : "");
  426. if (xSize != ptSize.x || ySize != ptSize.y)
  427. {
  428. pci->dwErrorCode |= ERR_PRINTABLE_AREA_ADJUSTED;
  429. if (xSize != ptSize.x)
  430. VOut(pci,
  431. "*%% Warning: the following printable width is adjusted (%d->%d) so it is divisible by the resolution X scale.\r\n",
  432. ptSize.x, xSize);
  433. if (ySize != ptSize.y)
  434. VOut(pci,
  435. "*%% Warning: the following printable length is adjusted (%d->%d) so it is divisible by the resolution Y scale.\r\n",
  436. ptSize.y, ySize);
  437. VOut(pci, "%s *PrintableArea: PAIR(%d, %d)\r\n",
  438. bL4Indentation? " " : "",
  439. xSize, ySize);
  440. }
  441. if (x != prcMargins->left || y != prcMargins->top)
  442. {
  443. pci->dwErrorCode |= ERR_PRINTABLE_ORIGIN_ADJUSTED;
  444. if (x != prcMargins->left)
  445. VOut(pci,
  446. "*%% Warning: the following printable origin X is adjusted (%d->%d) so it is divisible by the resolution X scale.\r\n",
  447. prcMargins->left, x);
  448. if (y != prcMargins->top)
  449. VOut(pci,
  450. "*%% Warning: the following printable origin Y is adjusted (%d->%d) so it is divisible by the resolution Y scale.\r\n",
  451. prcMargins->top, y);
  452. VOut(pci, "%s *PrintableOrigin: PAIR(%d, %d)\r\n",
  453. bL4Indentation? " " : "", x, y);
  454. }
  455. //
  456. // close the *case construct
  457. //
  458. VOut(pci, "%s }\r\n", bL4Indentation? " " : "");
  459. } // end for loop
  460. if (bOutputResDependency)
  461. //
  462. // close *switch construct
  463. //
  464. VOut(pci, "%s }\r\n", bL4Indentation? " " : "");
  465. }
  466. if (pptCursorOrig) // should output *CursorOrigin entry
  467. {
  468. //
  469. // ensure that cursor origin are divisible by the scale of
  470. // move unit if the printer is not a dot-matrix printer. We are
  471. // assuming that for dot-matrix printers, the *CursorOrigin entry
  472. // is always missing. If it's not missing, then the printing offset
  473. // may be off a little. But we don't think the accuracy is so
  474. // important for dot-matrix printers.
  475. //
  476. // Round up if needed.
  477. //
  478. x = pptCursorOrig->x;
  479. y = pptCursorOrig->y;
  480. if (pci->dwMode & FM_RES_DM_GDI)
  481. {
  482. if (pci->ptMoveScale.x > 1)
  483. {
  484. x = ((x + pci->ptMoveScale.x - 1) / pci->ptMoveScale.x) *
  485. pci->ptMoveScale.x;
  486. if (x != pptCursorOrig->x)
  487. {
  488. pci->dwErrorCode |= ERR_CURSOR_ORIGIN_ADJUSTED;
  489. VOut(pci,
  490. "*%% Warning: the following *CursorOrigin X value is adjusted (%d->%d) so it is divisible by scale of X move unit.\r\n",
  491. pptCursorOrig->x, x);
  492. }
  493. }
  494. if (pci->ptMoveScale.y > 1)
  495. {
  496. y = ((y + pci->ptMoveScale.y - 1) / pci->ptMoveScale.y) *
  497. pci->ptMoveScale.y;
  498. if (y != pptCursorOrig->y)
  499. {
  500. pci->dwErrorCode |= ERR_CURSOR_ORIGIN_ADJUSTED;
  501. VOut(pci,
  502. "*%% Warning: the following *CursorOrigin Y value is adjusted (%d->%d) so it is divisible by scale of Y move unit.\r\n",
  503. pptCursorOrig->y, y);
  504. }
  505. }
  506. }
  507. VOut(pci, "%s *CursorOrigin: PAIR(%d, %d)\r\n",
  508. bL4Indentation? " " : "",
  509. x, y);
  510. }
  511. if (ocd != NOOCD)
  512. {
  513. bDocSetup = BInDocSetup(pci, PC_ORD_PAPER_SIZE, &wOrder);
  514. //
  515. // this selection command has 3-level indentation instead of 2. So
  516. // can't call VOutputSelectionCmd().
  517. //
  518. if (wOrder > 0 && BBuildCmdStr(pci, CMD_PAPERSIZE, ocd))
  519. {
  520. VOut(pci, "%s *Command: CmdSelect\r\n%s {\r\n",
  521. bL4Indentation? " " : "",
  522. bL4Indentation? " " : "");
  523. VOut(pci, "%s *Order: %s.%d\r\n",
  524. bL4Indentation? " " : "",
  525. bDocSetup? "DOC_SETUP" : "PAGE_SETUP",
  526. wOrder);
  527. if (pci->wCmdCallbackID > 0)
  528. VOut(pci, "%s *CallbackID: %d\r\n",
  529. bL4Indentation? " " : "",
  530. pci->wCmdCallbackID);
  531. else
  532. VOut(pci, "%s *Cmd: %s\r\n",
  533. bL4Indentation? " " : "",
  534. pci->aubCmdBuf);
  535. VOut(pci, "%s }\r\n",
  536. bL4Indentation? " " : "");
  537. }
  538. }
  539. }
  540. void
  541. VAdjustHMargins(
  542. PCONVINFO pci,
  543. PPAPERSIZE pps,
  544. RECTw * prcInMargins,
  545. RECTw * prcOutMargins)
  546. {
  547. DWORD dwWidth, dwHMargin, dwLeftMargin, dwRightMargin;
  548. //
  549. // handle -1 case (treated the same as 0, no margin)
  550. //
  551. prcOutMargins->top = prcInMargins->top > 0 ? prcInMargins->top : 0;
  552. prcOutMargins->bottom = prcInMargins->bottom > 0 ? prcInMargins->bottom : 0;
  553. prcOutMargins->left = prcInMargins->left > 0 ? prcInMargins->left : 0;
  554. prcOutMargins->right = prcInMargins->right > 0 ? prcInMargins->right : 0;
  555. dwWidth = (DWORD)((pps->fGeneral & PS_ROTATE) ? pps->ptSize.y : pps->ptSize.x);
  556. if (dwWidth > (DWORD)pci->pmd->ptMax.x)
  557. {
  558. dwHMargin = dwWidth - (DWORD)pci->pmd->ptMax.x;
  559. VOut(pci, "*%% Warning: this paper size exceeds the MaxWidth, imageable width is truncated . \r\n");
  560. }
  561. else
  562. dwHMargin = 0;
  563. if (pps->fGeneral & PS_CENTER)
  564. dwLeftMargin = dwHMargin / 2;
  565. else
  566. dwLeftMargin = 0;
  567. if (dwLeftMargin < (DWORD)pci->pmd->sLeftMargin)
  568. dwLeftMargin = (DWORD)pci->pmd->sLeftMargin;
  569. if ((DWORD)prcOutMargins->left < dwLeftMargin)
  570. prcOutMargins->left = (WORD)dwLeftMargin;
  571. if (dwHMargin > (DWORD)prcOutMargins->left)
  572. dwRightMargin = dwHMargin - (DWORD)prcOutMargins->left;
  573. else
  574. dwRightMargin = 0;
  575. if ((DWORD)prcOutMargins->right < dwRightMargin)
  576. prcOutMargins->right = (WORD)dwRightMargin;
  577. }
  578. void
  579. VAdjustHAndVMargins(
  580. PCONVINFO pci,
  581. PPAPERSIZE pps,
  582. RECTw * prcInMargins,
  583. DWORD dwTopMargin,
  584. DWORD dwBottomMargin,
  585. RECTw * prcOutMargins)
  586. {
  587. VAdjustHMargins(pci, pps, prcInMargins, prcOutMargins);
  588. if ((DWORD)prcOutMargins->top < dwTopMargin)
  589. prcOutMargins->top = (WORD)dwTopMargin;
  590. if ((DWORD)prcOutMargins->bottom < dwBottomMargin)
  591. prcOutMargins->bottom = (WORD)dwBottomMargin;
  592. }
  593. void
  594. VOutputPaperSize(
  595. IN OUT PCONVINFO pci,
  596. IN PSHORT psIndex)
  597. {
  598. WORD wDefaultOption, wCount;
  599. PPAPERSIZE pps;
  600. BOOL bGPC3 = pci->pdh->wVersion >= GPC_VERSION3;
  601. RECTw rcOutMargins;
  602. VOut(pci, "*Feature: PaperSize\r\n");
  603. VOut(pci, "{\r\n");
  604. if (pci->dwStrType == STR_MACRO)
  605. VOut(pci, " *rcNameID: =PAPER_SIZE_DISPLAY\r\n");
  606. else if (pci->dwStrType == STR_DIRECT)
  607. VOut(pci, " *Name: \"Paper Size\"\r\n");
  608. else
  609. VOut(pci, " *rcNameID: %d\r\n", RCID_PAPERSIZE);
  610. wDefaultOption = WGetDefaultIndex(pci, MD_OI_PAPERSIZE);
  611. pps = (PPAPERSIZE)GetTableInfo(pci->pdh, HE_PAPERSIZE,
  612. *(psIndex + wDefaultOption - 1) - 1);
  613. //
  614. // steal pci->aubCmdBuf to hold composed option name temporarily
  615. //
  616. VGetOptionName((PSTR)pci->aubCmdBuf,
  617. CCHOF(pci->aubCmdBuf),
  618. pps->sPaperSizeID, wDefaultOption,
  619. gpstrStdPSName, TRUE);
  620. VOut(pci, " *DefaultOption: %s\r\n", (PSTR)pci->aubCmdBuf);
  621. //
  622. // loop through index list to create one option for each element
  623. //
  624. wCount = 1;
  625. while (*psIndex)
  626. {
  627. pps = (PPAPERSIZE)GetTableInfo(pci->pdh, HE_PAPERSIZE, *psIndex - 1);
  628. VGetOptionName((PSTR)pci->aubCmdBuf,
  629. CCHOF(pci->aubCmdBuf),
  630. pps->sPaperSizeID, wCount,
  631. gpstrStdPSName, TRUE);
  632. //
  633. // set up info needed later
  634. //
  635. CopyStringA(pci->ppiSize[wCount-1].aubOptName, pci->aubCmdBuf,
  636. MAX_OPTION_NAME_LENGTH);
  637. pci->ppiSize[wCount-1].bEjectFF = pps->fGeneral & PS_EJECTFF;
  638. pci->ppiSize[wCount-1].dwPaperType = (DWORD)pps->fPaperType;
  639. VOut(pci, " *Option: %s\r\n", (PSTR)pci->aubCmdBuf);
  640. VOut(pci, " {\r\n");
  641. //
  642. // for standard PaperSize options, use *Name. Otherwise,
  643. // use *rcNameID.
  644. //
  645. if (pps->sPaperSizeID < DMPAPER_USER)
  646. {
  647. if (pci->bUseSystemPaperNames)
  648. VOut(pci, " *rcNameID: =RCID_DMPAPER_SYSTEM_NAME\r\n");
  649. else if (pci->dwStrType == STR_MACRO)
  650. VOut(pci, " *rcNameID: =%s\r\n",
  651. gpstrStdPSDisplayNameMacro[pps->sPaperSizeID - 1]);
  652. else if (pci->dwStrType == STR_DIRECT)
  653. VOut(pci, " *Name: \"%s\"\r\n",
  654. gpstrStdPSDisplayName[pps->sPaperSizeID - 1]);
  655. else
  656. VOut(pci, " *rcNameID: %d\r\n",
  657. STD_PS_DISPLAY_NAME_ID_BASE + pps->sPaperSizeID - 1);
  658. }
  659. else if (pps->sPaperSizeID == DMPAPER_USER)
  660. {
  661. if (pci->dwStrType == STR_MACRO)
  662. VOut(pci, " *rcNameID: =USER_DEFINED_SIZE_DISPLAY\r\n");
  663. else if (pci->dwStrType == STR_DIRECT)
  664. VOut(pci, " *Name: \"User Defined Size\"\r\n");
  665. else
  666. VOut(pci, " *rcNameID: %d\r\n",
  667. STD_PS_DISPLAY_NAME_ID_BASE + DMPAPER_USER - 1);
  668. VOut(pci, " *MinSize: PAIR(%d, %d)\r\n", pci->pmd->ptMin.x,
  669. pci->pmd->ptMin.y);
  670. VOut(pci, " *MaxSize: PAIR(%d, %d)\r\n", pci->pmd->sMaxPhysWidth,
  671. (pci->pmd->ptMax.y == NOT_USED) ? 0x7FFF : pci->pmd->ptMax.y);
  672. VOut(pci, " *MaxPrintableWidth: %d\r\n", (DWORD)pci->pmd->ptMax.x);
  673. VOut(pci, " *MinLeftMargin: %d\r\n", pci->pmd->sLeftMargin);
  674. VOut(pci, " *CenterPrintable?: %s\r\n",
  675. (pps->fGeneral & PS_CENTER)? "TRUE" : "FALSE");
  676. if ((pci->dwMode & FM_HAVE_SEEN_NON_ZERO_FEED_MARGINS) &&
  677. (pci->dwMode & FM_HAVE_SAME_TOP_BOTTOM_MARGINS))
  678. {
  679. VOut(pci, " *TopMargin: %d\r\n", pci->ppiSrc[0].dwTopMargin);
  680. VOut(pci, " *BottomMargin: %d\r\n", pci->ppiSrc[0].dwBottomMargin);
  681. }
  682. else if (pci->dwMode & FM_HAVE_SEEN_NON_ZERO_FEED_MARGINS)
  683. {
  684. DWORD i;
  685. //
  686. // need to create dependency on InputBin.
  687. //
  688. VOut(pci, " *switch: InputBin\r\n");
  689. VOut(pci, " {\r\n");
  690. for (i = 0; i < pci->dwNumOfSrc; i++)
  691. {
  692. VOut(pci, " *case: %s\r\n", pci->ppiSrc[i].aubOptName);
  693. VOut(pci, " {\r\n");
  694. VOut(pci, " *TopMargin: %d\r\n", pci->ppiSrc[i].dwTopMargin);
  695. VOut(pci, " *BottomMargin: %d\r\n", pci->ppiSrc[i].dwBottomMargin);
  696. VOut(pci, " }\r\n"); // close *case
  697. }
  698. VOut(pci, " }\r\n"); // close *switch
  699. }
  700. }
  701. else
  702. {
  703. VOut(pci, " *rcNameID: %d\r\n", pps->sPaperSizeID);
  704. VOut(pci, " *OptionID: %d\r\n", pps->sPaperSizeID);
  705. VOut(pci, " *PageDimensions: PAIR(%d, %d)\r\n", pps->ptSize.x,
  706. pps->ptSize.y);
  707. }
  708. if (pps->fGeneral & PS_ROTATE)
  709. VOut(pci, " *RotateSize? : TRUE\r\n");
  710. if (pps->fGeneral & PS_SUGGEST_LNDSCP)
  711. {
  712. pci->dwErrorCode |= ERR_PS_SUGGEST_LNDSCP;
  713. VOut(pci, "*%% Warning: this paper size has PS_SUGGEST_LNDSCP set in GPC, which is ignored by GPD. \r\n");
  714. }
  715. if (pci->pmd->fGeneral & MD_PCL_PAGEPROTECT)
  716. {
  717. VOut(pci, " *PageProtectMem: %d\r\n", GETPAGEPROMEM(pci->pdh, pps));
  718. //
  719. // check if we should synthesize a PageProtect feature later.
  720. // Note that we assume that all paper size options have the same
  721. // commands to turn on/off page protection feature. This is a bit
  722. // hacky, but it's really because GPC defined it in a awkward way.
  723. // All existing GPC minidrivers are consistent with the assumption.
  724. //
  725. if (bGPC3)
  726. {
  727. //
  728. // the first option establish the PP feature
  729. //
  730. if (wCount == 1)
  731. {
  732. if ((pci->ocdPPOn = pps->rgocd[PSZ_OCD_PAGEPROTECT_ON])
  733. != NOOCD &&
  734. (pci->ocdPPOff = pps->rgocd[PSZ_OCD_PAGEPROTECT_OFF])
  735. != NOOCD)
  736. pci->dwMode |= FM_SYN_PAGEPROTECT;
  737. }
  738. //
  739. // make sure following options are consistent with the
  740. // first option. If not, report error and don't synthesize.
  741. //
  742. else if (pci->dwMode & FM_SYN_PAGEPROTECT)
  743. {
  744. if (pps->rgocd[PSZ_OCD_PAGEPROTECT_ON] == NOOCD ||
  745. pps->rgocd[PSZ_OCD_PAGEPROTECT_OFF] == NOOCD)
  746. {
  747. pci->dwMode &= ~FM_SYN_PAGEPROTECT;
  748. pci->dwErrorCode |= ERR_INCONSISTENT_PAGEPROTECT;
  749. }
  750. }
  751. else // wCount > 1 && !(pci->dwMode & FM_SYN_PAGEPROTECT)
  752. {
  753. if (pps->rgocd[PSZ_OCD_PAGEPROTECT_ON] != NOOCD ||
  754. pps->rgocd[PSZ_OCD_PAGEPROTECT_OFF] != NOOCD)
  755. pci->dwErrorCode |= ERR_INCONSISTENT_PAGEPROTECT;
  756. }
  757. }
  758. } // end if (pci->pmd->fGeneral & MD_PCL_PAGEPROTECT)...
  759. //
  760. // Output margin related entries and selection cmd
  761. //
  762. //
  763. // check GPC version. If 3.0 or above, and if MD_LANDSCAPE_RT90 bit
  764. // if set (i.e. different margins and cursor origins might be used
  765. // for different orientations, and there are cmds to set the logical
  766. // orientation), then generate *switch/*case dependency on Orientation.
  767. // The dependency clause contains *PrintableArea, *PrintableOrigin,
  768. // *CursorOrigin and the selection command.
  769. //
  770. if (bGPC3 && (pci->pmd->fGeneral & MD_LANDSCAPE_RT90))
  771. {
  772. POINTw ptCursor;
  773. BOOL bUseCursorOrigin;
  774. bUseCursorOrigin = (pci->dwMode & FM_SET_CURSOR_ORIGIN) ||
  775. (pci->pmd->fGeneral & MD_USE_CURSOR_ORIG);
  776. //
  777. // assume that in this case there is no margins resulted from
  778. // input slot. Verify that.
  779. //
  780. if (pci->dwMode & FM_HAVE_SEEN_NON_ZERO_FEED_MARGINS)
  781. pci->dwErrorCode |= ERR_NON_ZERO_FEED_MARGINS_ON_RT90_PRINTER;
  782. VOut(pci, " *switch: Orientation\r\n");
  783. VOut(pci, " {\r\n");
  784. VOut(pci, " *case: PORTRAIT\r\n");
  785. VOut(pci, " {\r\n");
  786. //
  787. // take into account MODELDATA.sMinLeftMargin & MODELDATA.ptMax.x
  788. //
  789. if (pps->sPaperSizeID == DMPAPER_USER)
  790. {
  791. //
  792. // for use-defined size, we don't output *CursorOrigin
  793. // since it doesn't make sense.
  794. //
  795. VOutputPSOthers(pci, NULL, FALSE, NULL, NULL,
  796. pps->rgocd[PSZ_OCD_SELECTPORTRAIT], TRUE);
  797. }
  798. else
  799. {
  800. VAdjustHMargins(pci, pps, &pps->rcMargins, &rcOutMargins);
  801. if (pci->pmd->fGeneral & MD_USE_CURSOR_ORIG)
  802. {
  803. ptCursor.x = pps->ptCursorOrig.x;
  804. ptCursor.y = pps->ptCursorOrig.y;
  805. }
  806. else if (pci->dwMode & FM_SET_CURSOR_ORIGIN)
  807. {
  808. ptCursor.x = rcOutMargins.left;
  809. ptCursor.y = rcOutMargins.top;
  810. }
  811. VOutputPSOthers(pci, &pps->ptSize, pps->fGeneral & PS_ROTATE,
  812. &rcOutMargins,
  813. bUseCursorOrigin ? &ptCursor : NULL,
  814. pps->rgocd[PSZ_OCD_SELECTPORTRAIT], TRUE);
  815. }
  816. VOut(pci, " }\r\n"); // close *case: Portrait
  817. VOut(pci, " *case: LANDSCAPE_CC90\r\n");
  818. VOut(pci, " {\r\n");
  819. if (pps->sPaperSizeID == DMPAPER_USER)
  820. {
  821. VOutputPSOthers(pci, NULL, FALSE, NULL, NULL,
  822. pps->rgocd[PSZ_OCD_SELECTLANDSCAPE], TRUE);
  823. }
  824. else
  825. {
  826. VAdjustHMargins(pci, pps, &pps->rcLMargins, &rcOutMargins);
  827. //
  828. // convert ptLCursorOrig (in Landscape) to corresponding values
  829. // as in Portrait orientation.
  830. //
  831. if (pci->pmd->fGeneral & MD_USE_CURSOR_ORIG)
  832. {
  833. ptCursor.x = pps->ptLCursorOrig.y;
  834. ptCursor.y = ((pps->fGeneral & PS_ROTATE) ?
  835. pps->ptSize.x : pps->ptSize.y) -
  836. pps->ptLCursorOrig.x;
  837. }
  838. else if (pci->dwMode & FM_SET_CURSOR_ORIGIN)
  839. {
  840. ptCursor.x = rcOutMargins.left;
  841. ptCursor.y = ((pps->fGeneral & PS_ROTATE) ?
  842. pps->ptSize.x : pps->ptSize.y) -
  843. rcOutMargins.bottom;
  844. }
  845. VOutputPSOthers(pci, &pps->ptSize, pps->fGeneral & PS_ROTATE,
  846. &rcOutMargins,
  847. bUseCursorOrigin ? &ptCursor : NULL,
  848. pps->rgocd[PSZ_OCD_SELECTLANDSCAPE], TRUE);
  849. }
  850. VOut(pci, " }\r\n"); // close *case: Landscape
  851. VOut(pci, " }\r\n"); // close *switch: Orientation
  852. }
  853. else if (pps->sPaperSizeID == DMPAPER_USER)
  854. {
  855. //
  856. // output CmdSelect, if any.
  857. //
  858. VOutputPSOthers(pci, NULL, FALSE, NULL, NULL,
  859. pps->rgocd[PSZ_OCD_SELECTPORTRAIT], FALSE);
  860. }
  861. else
  862. {
  863. //
  864. // in this case, there is no separate commands to set
  865. // logical orientation.
  866. //
  867. BOOL bUseCO = pci->pmd->fGeneral & MD_USE_CURSOR_ORIG;
  868. if (pci->dwMode & FM_HAVE_SEEN_NON_ZERO_FEED_MARGINS)
  869. {
  870. DWORD i;
  871. if (pci->dwMode & FM_HAVE_SAME_TOP_BOTTOM_MARGINS)
  872. {
  873. VAdjustHAndVMargins(pci, pps, &pps->rcMargins,
  874. pci->ppiSrc[0].dwTopMargin,
  875. pci->ppiSrc[0].dwBottomMargin,
  876. &rcOutMargins);
  877. VOutputPSOthers(pci, &pps->ptSize, pps->fGeneral & PS_ROTATE,
  878. &rcOutMargins,
  879. bUseCO ? &pps->ptCursorOrig : NULL,
  880. pps->rgocd[PSZ_OCD_SELECTPORTRAIT], FALSE);
  881. }
  882. else
  883. {
  884. //
  885. // need to create dependency on InputBin. But leave
  886. // *CursorOrigin and CmdSelect out of it.
  887. //
  888. VOutputPSOthers(pci, NULL, FALSE, NULL,
  889. bUseCO ? &pps->ptCursorOrig : NULL,
  890. pps->rgocd[PSZ_OCD_SELECTPORTRAIT], FALSE);
  891. VOut(pci, " *switch: InputBin\r\n");
  892. VOut(pci, " {\r\n");
  893. for (i = 0; i < pci->dwNumOfSrc; i++)
  894. {
  895. VOut(pci, " *case: %s\r\n", pci->ppiSrc[i].aubOptName);
  896. VOut(pci, " {\r\n");
  897. VAdjustHAndVMargins(pci, pps, &pps->rcMargins,
  898. pci->ppiSrc[i].dwTopMargin,
  899. pci->ppiSrc[i].dwBottomMargin,
  900. &rcOutMargins);
  901. VOutputPSOthers(pci, &pps->ptSize, pps->fGeneral & PS_ROTATE,
  902. &rcOutMargins, NULL, NOOCD, TRUE);
  903. VOut(pci, " }\r\n"); // close *case
  904. }
  905. VOut(pci, " }\r\n");
  906. }
  907. }
  908. else
  909. {
  910. VAdjustHMargins(pci, pps, &pps->rcMargins, &rcOutMargins);
  911. VOutputPSOthers(pci, &pps->ptSize, pps->fGeneral & PS_ROTATE,
  912. &rcOutMargins,
  913. bUseCO ? &pps->ptCursorOrig : NULL,
  914. pps->rgocd[PSZ_OCD_SELECTPORTRAIT], FALSE);
  915. }
  916. }
  917. VOut(pci, " }\r\n"); // close the option
  918. psIndex++;
  919. wCount++;
  920. }
  921. pci->dwNumOfSize = wCount - 1;
  922. VOut(pci, "}\r\n");
  923. }
  924. void
  925. VOutputResolution(
  926. IN OUT PCONVINFO pci,
  927. IN PSHORT psIndex)
  928. {
  929. PGPCRESOLUTION pres;
  930. WORD wCount;
  931. WORD wDefaultOption;
  932. BOOL bDocSetup;
  933. BOOL bColor;
  934. WORD wOrder;
  935. //
  936. // check if this is a color device
  937. //
  938. bColor = *((PSHORT)((PBYTE)pci->pdh + pci->pdh->loHeap +
  939. pci->pmd->rgoi[MD_OI_COLOR])) != 0;
  940. VOut(pci, "*Feature: Resolution\r\n");
  941. VOut(pci, "{\r\n");
  942. if (pci->dwStrType == STR_MACRO)
  943. VOut(pci, " *rcNameID: =RESOLUTION_DISPLAY\r\n");
  944. else if (pci->dwStrType == STR_DIRECT)
  945. VOut(pci, " *Name: \"Resolution\"\r\n");
  946. else
  947. VOut(pci, " *rcNameID: %d\r\n", RCID_RESOLUTION);
  948. wDefaultOption = WGetDefaultIndex(pci, MD_OI_RESOLUTION);
  949. VOut(pci, " *DefaultOption: Option%d\r\n", wDefaultOption);
  950. //
  951. // loop through index list to create one option for each element
  952. //
  953. wCount = 1;
  954. while (*psIndex)
  955. {
  956. WORD wXdpi, wYdpi;
  957. pres = (PGPCRESOLUTION)GetTableInfo(pci->pdh, HE_RESOLUTION, *psIndex - 1);
  958. //
  959. // set up pci->pres for CmdSendBlockData special case in BBuildCmdStr
  960. //
  961. pci->pres = pres;
  962. wXdpi = (WORD)pci->pdh->ptMaster.x / pres->ptTextScale.x;
  963. wYdpi = (WORD)pci->pdh->ptMaster.y / pres->ptTextScale.y;
  964. //
  965. // gather information for later use
  966. //
  967. StringCchPrintfA(pci->presinfo[wCount-1].aubOptName, CCHOF(pci->presinfo[wCount-1].aubOptName), "Option%d", wCount);
  968. pci->presinfo[wCount-1].dwXScale = pres->ptTextScale.x << pres->ptScaleFac.x;
  969. pci->presinfo[wCount-1].dwYScale = pres->ptTextScale.y << pres->ptScaleFac.y;
  970. pci->presinfo[wCount-1].bColor = pres->fDump & RES_DM_COLOR;
  971. //
  972. // assume all GPCRESOLUTION structures use the same dump format.
  973. //
  974. if (wCount == 1 && (pres->fDump & RES_DM_GDI))
  975. pci->dwMode |= FM_RES_DM_GDI;
  976. VOut(pci, " *Option: Option%d\r\n", wCount);
  977. VOut(pci, " {\r\n");
  978. //
  979. // have to compose the actual display name
  980. //
  981. if (pci->dwStrType == STR_MACRO)
  982. VOut(pci, " *Name: \"%d x %d \" =DOTS_PER_INCH\r\n",
  983. wXdpi >> pres->ptScaleFac.x, wYdpi >> pres->ptScaleFac.y);
  984. else
  985. VOut(pci, " *Name: \"%d x %d dots per inch\"\r\n",
  986. wXdpi >> pres->ptScaleFac.x, wYdpi >> pres->ptScaleFac.y);
  987. VOut(pci, " *DPI: PAIR(%d, %d)\r\n",
  988. wXdpi >> pres->ptScaleFac.x, wYdpi >> pres->ptScaleFac.y);
  989. VOut(pci, " *TextDPI: PAIR(%d, %d)\r\n", wXdpi, wYdpi);
  990. if (pres->sNPins > 1)
  991. VOut(pci, " *PinsPerLogPass: %d\r\n", pres->sNPins);
  992. if (pres->sPinsPerPass > 1)
  993. VOut(pci, " *PinsPerPhysPass: %d\r\n", pres->sPinsPerPass);
  994. if (pres->sMinBlankSkip > 0)
  995. VOut(pci, " *MinStripBlankPixels: %d\r\n",
  996. pres->sMinBlankSkip);
  997. if (pres->fBlockOut & RES_BO_UNIDIR)
  998. VOut(pci, " *RequireUniDir?: TRUE\r\n");
  999. //
  1000. // Some printers (ex. LJ III) have different stripping flags for
  1001. // different resolutions.
  1002. //
  1003. if (pres->fBlockOut &
  1004. (RES_BO_LEADING_BLNKS | RES_BO_TRAILING_BLNKS | RES_BO_ENCLOSED_BLNKS))
  1005. {
  1006. pci->dwMode |= FM_VOUT_LIST;
  1007. VOut(pci, " EXTERN_GLOBAL: *StripBlanks: LIST(%s%s%s)\r\n",
  1008. (pres->fBlockOut & RES_BO_LEADING_BLNKS) ? "LEADING," : "",
  1009. (pres->fBlockOut & RES_BO_ENCLOSED_BLNKS) ? "ENCLOSED," : "",
  1010. (pres->fBlockOut & RES_BO_TRAILING_BLNKS) ? "TRAILING" : "");
  1011. pci->dwMode &= ~FM_VOUT_LIST;
  1012. }
  1013. if (pres->fBlockOut & RES_BO_MULTIPLE_ROWS)
  1014. VOut(pci, " EXTERN_GLOBAL: *SendMultipleRows?: TRUE\r\n");
  1015. //
  1016. // RES_BO_RESET_FONT is used by Win95 Unidrv but not by RASDD.
  1017. // Warn if this flag is set.
  1018. //
  1019. if (pres->fBlockOut & RES_BO_RESET_FONT)
  1020. {
  1021. pci->dwErrorCode |= ERR_RES_BO_RESET_FONT;
  1022. // set a flag to cause this to be output *ReselectFont in VoutputPrintingEntries
  1023. VOut(pci, "*%% Warning: this resolution has RES_BO_RESET_FONT set in GPC. *ReselectFont added\r\n");
  1024. }
  1025. if (pres->fBlockOut & RES_BO_OEMGRXFILTER)
  1026. {
  1027. pci->dwErrorCode |= ERR_RES_BO_OEMGRXFILTER;
  1028. VOut(pci, "*%% Error: this resolution has RES_BO_OEMGRXFILTER set in GPC. You must port over the custom code. \r\n");
  1029. }
  1030. if (pres->fBlockOut & RES_BO_NO_ADJACENT)
  1031. {
  1032. pci->dwErrorCode |= ERR_RES_BO_NO_ADJACENT;
  1033. VOut(pci, "*%% Warning: this resolution has RES_BO_NO_ADJACENT set in GPC, which is ignored by GPD. Custom code is needed.\r\n");
  1034. }
  1035. if (pres->sTextYOffset != 0)
  1036. VOut(pci, " EXTERN_GLOBAL: *TextYOffset: %d\r\n",
  1037. pres->sTextYOffset);
  1038. VOut(pci, " *SpotDiameter: %d\r\n", pres->sSpotDiameter);
  1039. //
  1040. // output printing commands that come from GPCRESOLUTION structure.
  1041. //
  1042. if (BBuildCmdStr(pci, CMD_RES_BEGINGRAPHICS, pres->rgocd[RES_OCD_BEGINGRAPHICS]))
  1043. VOutputExternCmd(pci, "CmdBeginRaster");
  1044. if (BBuildCmdStr(pci, CMD_RES_ENDGRAPHICS, pres->rgocd[RES_OCD_ENDGRAPHICS]))
  1045. VOutputExternCmd(pci, "CmdEndRaster");
  1046. if (BBuildCmdStr(pci, CMD_RES_SENDBLOCK, pres->rgocd[RES_OCD_SENDBLOCK]))
  1047. VOutputExternCmd(pci, "CmdSendBlockData");
  1048. if (BBuildCmdStr(pci, CMD_RES_ENDBLOCK, pres->rgocd[RES_OCD_ENDBLOCK]))
  1049. VOutputExternCmd(pci, "CmdEndBlockData");
  1050. //
  1051. // check selection command.
  1052. //
  1053. bDocSetup = BInDocSetup(pci, PC_ORD_RESOLUTION,&wOrder);
  1054. if (wOrder > 0 &&
  1055. BBuildCmdStr(pci, CMD_RES_SELECTRES, pres->rgocd[RES_OCD_SELECTRES]))
  1056. VOutputSelectionCmd(pci, bDocSetup, wOrder);
  1057. //
  1058. // gather info for later use
  1059. //
  1060. if (pres->fDump & RES_DM_DOWNLOAD_OUTLINE)
  1061. pci->dwMode |= FM_RES_DM_DOWNLOAD_OUTLINE;
  1062. else
  1063. pci->dwMode |= FM_NO_RES_DM_DOWNLOAD_OUTLINE;
  1064. VOut(pci, " }\r\n"); // close the option
  1065. psIndex++;
  1066. wCount++;
  1067. }
  1068. pci->dwNumOfRes = wCount - 1;
  1069. VOut(pci, "}\r\n");
  1070. }
  1071. void
  1072. VOutputMediaType(
  1073. IN OUT PCONVINFO pci,
  1074. IN PSHORT psIndex)
  1075. {
  1076. WORD wDefaultOption;
  1077. PPAPERQUALITY ppq;
  1078. WORD wCount;
  1079. BOOL bDocSetup;
  1080. WORD wOrder;
  1081. VOut(pci, "*Feature: MediaType\r\n");
  1082. VOut(pci, "{\r\n");
  1083. if (pci->dwStrType == STR_MACRO)
  1084. VOut(pci, " *rcNameID: =MEDIA_TYPE_DISPLAY\r\n");
  1085. else if (pci->dwStrType == STR_DIRECT)
  1086. VOut(pci, " *Name: \"Media Type\"\r\n");
  1087. else
  1088. VOut(pci, " *rcNameID: %d\r\n", RCID_MEDIATYPE);
  1089. wDefaultOption = WGetDefaultIndex(pci, MD_OI_PAPERQUALITY);
  1090. ppq = (PPAPERQUALITY)GetTableInfo(pci->pdh, HE_PAPERQUALITY,
  1091. *(psIndex + wDefaultOption - 1) - 1);
  1092. //
  1093. // steal pci->aubCmdBuf as temp buffer for option names
  1094. //
  1095. VGetOptionName((PSTR)pci->aubCmdBuf,
  1096. CCHOF(pci->aubCmdBuf),
  1097. ppq->sPaperQualID, wDefaultOption,
  1098. gpstrStdMTName, FALSE);
  1099. VOut(pci, " *DefaultOption: %s\r\n", (PSTR)pci->aubCmdBuf);
  1100. //
  1101. // loop through index list to create one option for each element
  1102. //
  1103. wCount = 1;
  1104. while (*psIndex)
  1105. {
  1106. ppq = (PPAPERQUALITY)GetTableInfo(pci->pdh, HE_PAPERQUALITY, *psIndex - 1);
  1107. VGetOptionName((PSTR)pci->aubCmdBuf,
  1108. CCHOF(pci->aubCmdBuf),
  1109. ppq->sPaperQualID, wCount,
  1110. gpstrStdMTName, FALSE);
  1111. VOut(pci, " *Option: %s\r\n", (PSTR)pci->aubCmdBuf);
  1112. VOut(pci, " {\r\n");
  1113. //
  1114. // for standard MediaType options, use *Name. Otherwise,
  1115. // use *rcNameID.
  1116. //
  1117. if (ppq->sPaperQualID < DMMEDIA_USER)
  1118. {
  1119. if (pci->dwStrType == STR_MACRO)
  1120. VOut(pci, " *rcNameID: =%s\r\n",
  1121. gpstrStdMTDisplayNameMacro[ppq->sPaperQualID - 1]);
  1122. else if (pci->dwStrType == STR_DIRECT)
  1123. VOut(pci, " *Name: \"%s\"\r\n",
  1124. gpstrStdMTDisplayName[ppq->sPaperQualID - 1]);
  1125. else
  1126. VOut(pci, " *rcNameID: %d\r\n",
  1127. STD_MT_DISPLAY_NAME_ID_BASE + ppq->sPaperQualID - 1);
  1128. }
  1129. else // must be driver defined media type
  1130. {
  1131. VOut(pci, " *rcNameID: %d\r\n", ppq->sPaperQualID);
  1132. if (ppq->sPaperQualID > DMMEDIA_USER)
  1133. VOut(pci, " *OptionID: %d\r\n", ppq->sPaperQualID);
  1134. }
  1135. //
  1136. // check selection command.
  1137. //
  1138. bDocSetup = BInDocSetup(pci, PC_ORD_PAPER_QUALITY, &wOrder);
  1139. if (wOrder > 0 &&
  1140. BBuildCmdStr(pci, CMD_PAPERQUALITY, ppq->ocdSelect))
  1141. VOutputSelectionCmd(pci, bDocSetup, wOrder);
  1142. VOut(pci, " }\r\n"); // close the option
  1143. psIndex++;
  1144. wCount++;
  1145. }
  1146. VOut(pci, "}\r\n");
  1147. }
  1148. void
  1149. VOutputTextQuality(
  1150. IN OUT PCONVINFO pci,
  1151. IN PSHORT psIndex)
  1152. {
  1153. WORD wDefaultOption;
  1154. PTEXTQUALITY ptq;
  1155. WORD wCount;
  1156. BOOL bDocSetup;
  1157. WORD wOrder;
  1158. VOut(pci, "*Feature: PrintQuality\r\n");
  1159. VOut(pci, "{\r\n");
  1160. if (pci->dwStrType == STR_MACRO)
  1161. VOut(pci, " *rcNameID: =TEXT_QUALITY_DISPLAY\r\n");
  1162. else if (pci->dwStrType == STR_DIRECT)
  1163. VOut(pci, " *Name: \"Print Quality\"\r\n");
  1164. else
  1165. VOut(pci, " *rcNameID: %d\r\n", RCID_TEXTQUALITY);
  1166. wDefaultOption = WGetDefaultIndex(pci, MD_OI_TEXTQUAL);
  1167. ptq = (PTEXTQUALITY)GetTableInfo(pci->pdh, HE_TEXTQUAL,
  1168. *(psIndex + wDefaultOption - 1) - 1);
  1169. //
  1170. // steal pci->aubCmdBuf as temp buffer for option names
  1171. //
  1172. VGetOptionName((PSTR)pci->aubCmdBuf,
  1173. CCHOF(pci->aubCmdBuf),
  1174. ptq->sID, wDefaultOption,
  1175. gpstrStdTQName, FALSE);
  1176. VOut(pci, " *DefaultOption: %s\r\n", (PSTR)pci->aubCmdBuf);
  1177. //
  1178. // loop through index list to create one option for each element
  1179. //
  1180. wCount = 1;
  1181. while (*psIndex)
  1182. {
  1183. ptq = (PTEXTQUALITY)GetTableInfo(pci->pdh, HE_TEXTQUAL, *psIndex - 1);
  1184. VGetOptionName((PSTR)pci->aubCmdBuf, CCHOF(pci->aubCmdBuf), ptq->sID, wCount,
  1185. gpstrStdTQName, FALSE);
  1186. VOut(pci, " *Option: %s\r\n", (PSTR)pci->aubCmdBuf);
  1187. VOut(pci, " {\r\n");
  1188. if (ptq->sID < DMTEXT_USER)
  1189. {
  1190. if (pci->dwStrType == STR_MACRO)
  1191. VOut(pci, " *rcNameID: =%s\r\n",
  1192. gpstrStdTQDisplayNameMacro[ptq->sID - 1]);
  1193. else if (pci->dwStrType == STR_DIRECT)
  1194. VOut(pci, " *Name: \"%s\"\r\n",
  1195. gpstrStdTQDisplayName[ptq->sID - 1]);
  1196. else
  1197. VOut(pci, " *rcNameID: %d\r\n",
  1198. STD_TQ_DISPLAY_NAME_ID_BASE + ptq->sID - 1);
  1199. }
  1200. else // must be driver defined text quality
  1201. VOut(pci, " *rcNameID: %d\r\n", ptq->sID);
  1202. //
  1203. // check selection command.
  1204. //
  1205. bDocSetup = BInDocSetup(pci, PC_ORD_TEXTQUALITY, &wOrder);
  1206. if (wOrder > 0 &&
  1207. BBuildCmdStr(pci, CMD_TEXTQUALITY, ptq->ocdSelect))
  1208. VOutputSelectionCmd(pci, bDocSetup, wOrder);
  1209. VOut(pci, " }\r\n"); // close the option
  1210. psIndex++;
  1211. wCount++;
  1212. }
  1213. VOut(pci, "}\r\n");
  1214. }
  1215. void
  1216. VOutputFeature(
  1217. IN OUT PCONVINFO pci,
  1218. IN FEATUREID fid,
  1219. IN PSHORT psIndex)
  1220. /*++
  1221. Routine Description:
  1222. This function outputs a generic feature in GPC. A generic feature has
  1223. only name and ocdCmdSelect for each option and there is no standard
  1224. option, i.e. all "sID" referenced in the GPC structure are really
  1225. string resource id's. The generated GPD options will be named "OptionX"
  1226. where X is 1, 2, ..., <# of options>. The default option is derived
  1227. from the GPC data. The option's display name comes from "sID".
  1228. Arguments:
  1229. fid: identification of the specific feature
  1230. psIndex: pointer to a list of structure indicies (1-based) each
  1231. corresponding to one option.
  1232. Return Value:
  1233. None
  1234. --*/
  1235. {
  1236. WORD wDefaultOption;
  1237. WORD wCount;
  1238. PWORD pwStruct;
  1239. BOOL bDocSetup;
  1240. WORD wOrder;
  1241. VOut(pci, "*Feature: %s\r\n", gpstrFeatureName[fid]);
  1242. VOut(pci, "{\r\n");
  1243. //
  1244. // display name references the corresponding value macro
  1245. //
  1246. if (pci->dwStrType == STR_MACRO)
  1247. VOut(pci, " *rcNameID: =%s\r\n", gpstrFeatureDisplayNameMacro[fid]);
  1248. else if (pci->dwStrType == STR_DIRECT)
  1249. VOut(pci, " *Name: \"%s\"\r\n", gpstrFeatureDisplayName[fid]);
  1250. else
  1251. VOut(pci, " *rcNameID: %d\r\n", gintFeatureDisplayNameID[fid]);
  1252. wDefaultOption = WGetDefaultIndex(pci, gwFeatureMDOI[fid]);
  1253. VOut(pci, " *DefaultOption: Option%d\r\n", wDefaultOption);
  1254. //
  1255. // loop through each element and output option constructs. Each option
  1256. // is named "OptionX", where X is 1, 2, ... <# of options>.
  1257. //
  1258. wCount = 1;
  1259. while (*psIndex)
  1260. {
  1261. pwStruct = (PWORD)GetTableInfo(pci->pdh, gwFeatureHE[fid], *psIndex - 1);
  1262. VOut(pci, " *Option: Option%d\r\n", wCount);
  1263. VOut(pci, " {\r\n");
  1264. //
  1265. // it's guaranteed that the 2nd WORD in a GPC structure
  1266. // is the RC string id for the name.
  1267. //
  1268. VOut(pci, " *rcNameID: %d\r\n", *(pwStruct+1));
  1269. //
  1270. // check selection command.
  1271. //
  1272. bDocSetup = BInDocSetup(pci, gwFeatureORD[fid], &wOrder);
  1273. if (wOrder > 0 &&
  1274. BBuildCmdStr(pci, gwFeatureCMD[fid],
  1275. *(pwStruct + gwFeatureOCDWordOffset[fid])))
  1276. VOutputSelectionCmd(pci, bDocSetup, wOrder);
  1277. VOut(pci, " }\r\n"); // close the option
  1278. //
  1279. // continue on to process next option
  1280. //
  1281. psIndex++;
  1282. wCount++;
  1283. }
  1284. VOut(pci, "}\r\n"); // close the feature
  1285. }
  1286. void
  1287. VOutputColorMode(
  1288. IN OUT PCONVINFO pci,
  1289. PSHORT psIndex)
  1290. /*++
  1291. Routine Description:
  1292. This function output ColorMode options including the artifical Mono mode.
  1293. The Color option is derived from GPC.
  1294. Arguments:
  1295. psIndex: pointer to list of DEVCOLOR structure indicies (1-based).
  1296. Return Value:
  1297. None
  1298. --*/
  1299. {
  1300. PDEVCOLOR pdc;
  1301. BOOL bDocSetup;
  1302. INT i;
  1303. WORD wDefaultOption, wOrder;
  1304. VOut(pci, "*Feature: ColorMode\r\n");
  1305. VOut(pci, "{\r\n");
  1306. if (pci->dwStrType == STR_MACRO)
  1307. VOut(pci, " *rcNameID: =COLOR_PRINTING_MODE_DISPLAY\r\n");
  1308. else if (pci->dwStrType == STR_DIRECT)
  1309. VOut(pci, " *Name: \"Color Printing Mode\"\r\n");
  1310. else
  1311. VOut(pci, " *rcNameID: %d\r\n", RCID_COLORMODE);
  1312. wDefaultOption = WGetDefaultIndex(pci, MD_OI_COLOR);
  1313. pdc = (PDEVCOLOR)GetTableInfo(pci->pdh, HE_COLOR,
  1314. *(psIndex + wDefaultOption - 1) - 1);
  1315. //
  1316. // 3 possibilities: planar mode, 8bpp, 24bpp
  1317. //
  1318. VOut(pci, " *DefaultOption: %s\r\n",
  1319. (pdc->sPlanes > 1 ? "Color" :
  1320. (pdc->sBitsPixel == 8 ? "8bpp" : "24bpp")));
  1321. bDocSetup = BInDocSetup(pci, PC_ORD_SETCOLORMODE, &wOrder);
  1322. //
  1323. // synthesize the Mono option.
  1324. //
  1325. VOut(pci, " *Option: Mono\r\n {\r\n");
  1326. if (pci->dwStrType == STR_MACRO)
  1327. VOut(pci, " *rcNameID: =MONO_DISPLAY\r\n");
  1328. else if (pci->dwStrType == STR_DIRECT)
  1329. VOut(pci, " *Name: \"Monochrome\"\r\n");
  1330. else
  1331. VOut(pci, " *rcNameID: %d\r\n", RCID_MONO);
  1332. VOut(pci, " *DevNumOfPlanes: 1\r\n");
  1333. VOut(pci, " *DevBPP: 1\r\n");
  1334. VOut(pci, " *Color? : FALSE\r\n");
  1335. //
  1336. // no selection command for MONO mode
  1337. //
  1338. VOut(pci, " }\r\n"); // close Mono option
  1339. //
  1340. // output color options based on GPC data
  1341. //
  1342. while (*psIndex)
  1343. {
  1344. pdc = (PDEVCOLOR)GetTableInfo(pci->pdh, HE_COLOR, *psIndex - 1);
  1345. if (!(pdc->sBitsPixel==1 && (pdc->sPlanes==3 || pdc->sPlanes==4)) &&
  1346. !(pdc->sPlanes==1 && (pdc->sBitsPixel==8 || pdc->sBitsPixel==24)))
  1347. continue; // skip this un-supported color format
  1348. VOut(pci, " *Option: %s\r\n {\r\n",
  1349. (pdc->sPlanes > 1 ? "Color" :
  1350. (pdc->sBitsPixel == 8 ? "8bpp" : "24bpp")));
  1351. if (pci->dwStrType == STR_MACRO)
  1352. VOut(pci, " *rcNameID: =%s\r\n",
  1353. (pdc->sPlanes > 1 ? "COLOR_DISPLAY" :
  1354. (pdc->sBitsPixel == 8 ? "8BPP_DISPLAY" : "24BPP_DISPLAY")));
  1355. else if (pci->dwStrType == STR_DIRECT)
  1356. VOut(pci, " *Name: \"%s\"\r\n",
  1357. (pdc->sPlanes > 1 ? "8 Color (Halftoned)" :
  1358. (pdc->sBitsPixel == 8 ? "256 Color (Halftoned)" : "True Color (24bpp)")));
  1359. else
  1360. VOut(pci, " *rcNameID: %d\r\n",
  1361. (pdc->sPlanes > 1 ? RCID_COLOR :
  1362. (pdc->sBitsPixel == 8 ? RCID_8BPP : RCID_24BPP)));
  1363. VOut(pci, " *DevNumOfPlanes: %d\r\n", pdc->sPlanes);
  1364. VOut(pci, " *DevBPP: %d\r\n", pdc->sBitsPixel);
  1365. VOut(pci, " *DrvBPP: %d\r\n",
  1366. (pdc->sPlanes > 1 ? max(pdc->sPlanes * pdc->sBitsPixel, 4) :
  1367. pdc->sBitsPixel) );
  1368. //
  1369. // output color printing attributes
  1370. //
  1371. if ((pdc->fGeneral & DC_CF_SEND_CR) &&
  1372. (pdc->fGeneral & DC_EXPLICIT_COLOR))
  1373. VOut(pci, " EXTERN_GLOBAL: *MoveToX0BeforeSetColor? : TRUE\r\n");
  1374. if ((pdc->fGeneral & DC_SEND_ALL_PLANES) ||
  1375. //
  1376. // GPC2.x and older minidrivers assume sending all color
  1377. // planes if using H_BYTE format dump. Ex. HP PaintJet.
  1378. //
  1379. (pci->pdh->wVersion < GPC_VERSION3 && (pci->dwMode & FM_RES_DM_GDI)))
  1380. VOut(pci, " EXTERN_GLOBAL: *RasterSendAllData? : TRUE\r\n");
  1381. if ((pdc->fGeneral & DC_EXPLICIT_COLOR) ||
  1382. //
  1383. // GPC1.x and GPC2.x minidrivers don'thave DC_EXPLICIT_COLOR bit
  1384. // the driver code assumes that if it's V_BYTE style dump.
  1385. //
  1386. (pci->pdh->wVersion < GPC_VERSION3 && !(pci->dwMode & FM_RES_DM_GDI)))
  1387. VOut(pci, " EXTERN_GLOBAL: *UseExpColorSelectCmd? : TRUE\r\n");
  1388. //
  1389. // warn flags that have no corresponding GPD entries
  1390. //
  1391. if (pdc->fGeneral & DC_SEND_PALETTE)
  1392. pci->dwErrorCode |= ERR_DC_SEND_PALETTE;
  1393. if (pdc->sPlanes > 1)
  1394. {
  1395. //
  1396. // figure out the color plane order
  1397. //
  1398. BYTE aubOrder[4];
  1399. OCD aocdPlanes[4];
  1400. POCD pocd;
  1401. OCD ocd;
  1402. SHORT i;
  1403. //if (!(pdc->fGeneral & DC_EXPLICIT_COLOR))
  1404. {
  1405. //
  1406. // copy color plane data cmds. May need to swap their order
  1407. //
  1408. pocd = (POCD)((PBYTE)pci->pdh + pci->pdh->loHeap + pdc->orgocdPlanes);
  1409. for (i = 0; i < pdc->sPlanes; i++)
  1410. aocdPlanes[i] = *pocd++;
  1411. }
  1412. if (pci->pdh->wVersion >= GPC_VERSION3)
  1413. *((PDWORD)aubOrder) = *((PDWORD)(pdc->rgbOrder));
  1414. else if (pdc->fGeneral & DC_PRIMARY_RGB)
  1415. *((PDWORD)aubOrder) =
  1416. (DWORD)DC_PLANE_RED |
  1417. (DWORD)DC_PLANE_GREEN << 8 |
  1418. (DWORD)DC_PLANE_BLUE << 16 |
  1419. (DWORD)DC_PLANE_NONE << 24 ;
  1420. else if (pdc->fGeneral & DC_EXTRACT_BLK)
  1421. {
  1422. //
  1423. // assume it's YMCK model (printing light color first).
  1424. // There was no DC_EXTRACT_BLK support in RES_DM_GDI path.
  1425. //
  1426. *((PDWORD)aubOrder) =
  1427. (DWORD)DC_PLANE_YELLOW |
  1428. (DWORD)DC_PLANE_MAGENTA << 8 |
  1429. (DWORD)DC_PLANE_CYAN << 16 |
  1430. (DWORD)DC_PLANE_BLACK << 24 ;
  1431. //if (!(pdc->fGeneral & DC_EXPLICIT_COLOR))
  1432. {
  1433. //
  1434. // swap cmds: 0 <-> 3; 1 <-> 3
  1435. //
  1436. ocd = aocdPlanes[0];
  1437. aocdPlanes[0] = aocdPlanes[3];
  1438. aocdPlanes[3] = ocd;
  1439. ocd = aocdPlanes[1];
  1440. aocdPlanes[1] = aocdPlanes[2];
  1441. aocdPlanes[2] = ocd;
  1442. }
  1443. }
  1444. else // YMC cases
  1445. {
  1446. //
  1447. // the data order was different for RES_DM_GDI and non RES_DM_GDI
  1448. // dump paths.
  1449. if (pci->dwMode & FM_RES_DM_GDI)
  1450. *((PDWORD)aubOrder) =
  1451. (DWORD)DC_PLANE_CYAN |
  1452. (DWORD)DC_PLANE_MAGENTA << 8 |
  1453. (DWORD)DC_PLANE_YELLOW << 16 |
  1454. (DWORD)DC_PLANE_NONE << 24 ;
  1455. else
  1456. {
  1457. *((PDWORD)aubOrder) =
  1458. (DWORD)DC_PLANE_YELLOW |
  1459. (DWORD)DC_PLANE_MAGENTA << 8 |
  1460. (DWORD)DC_PLANE_CYAN << 16 |
  1461. (DWORD)DC_PLANE_NONE << 24 ;
  1462. //if (!(pdc->fGeneral & DC_EXPLICIT_COLOR))
  1463. {
  1464. //
  1465. // swap cmds: 0 <-> 2
  1466. //
  1467. ocd = aocdPlanes[0];
  1468. aocdPlanes[0] = aocdPlanes[2];
  1469. aocdPlanes[2] = ocd;
  1470. }
  1471. }
  1472. }
  1473. if (aubOrder[3] == DC_PLANE_NONE)
  1474. VOut(pci, " *ColorPlaneOrder: LIST(%s, %s, %s)\r\n",
  1475. gpstrColorName[aubOrder[0]],
  1476. gpstrColorName[aubOrder[1]],
  1477. gpstrColorName[aubOrder[2]]);
  1478. else
  1479. VOut(pci, " *ColorPlaneOrder: LIST(%s, %s, %s, %s)\r\n",
  1480. gpstrColorName[aubOrder[0]],
  1481. gpstrColorName[aubOrder[1]],
  1482. gpstrColorName[aubOrder[2]],
  1483. gpstrColorName[aubOrder[3]]);
  1484. //
  1485. // output send-color-plane-data cmds
  1486. //
  1487. //if (!(pdc->fGeneral & DC_EXPLICIT_COLOR))
  1488. {
  1489. for (i = 0; i < pdc->sPlanes; i++)
  1490. if (BBuildCmdStr(pci, gwColorPlaneCmdID[i], aocdPlanes[i]))
  1491. VOutputExternCmd(pci, gpstrColorPlaneCmdName[aubOrder[i]]);
  1492. }
  1493. //
  1494. // output foreground (text) color selection commands
  1495. //
  1496. if (BBuildCmdStr(pci, CMD_DC_TC_BLACK, pdc->rgocd[DC_OCD_TC_BLACK]))
  1497. VOutputExternCmd(pci, "CmdSelectBlackColor");
  1498. if (BBuildCmdStr(pci, CMD_DC_TC_RED, pdc->rgocd[DC_OCD_TC_RED]))
  1499. VOutputExternCmd(pci, "CmdSelectRedColor");
  1500. if (BBuildCmdStr(pci, CMD_DC_TC_GREEN, pdc->rgocd[DC_OCD_TC_GREEN]))
  1501. VOutputExternCmd(pci, "CmdSelectGreenColor");
  1502. if (BBuildCmdStr(pci, CMD_DC_TC_YELLOW, pdc->rgocd[DC_OCD_TC_YELLOW]))
  1503. VOutputExternCmd(pci, "CmdSelectYellowColor");
  1504. if (BBuildCmdStr(pci, CMD_DC_TC_BLUE, pdc->rgocd[DC_OCD_TC_BLUE]))
  1505. VOutputExternCmd(pci, "CmdSelectBlueColor");
  1506. if (BBuildCmdStr(pci, CMD_DC_TC_MAGENTA, pdc->rgocd[DC_OCD_TC_MAGENTA]))
  1507. VOutputExternCmd(pci, "CmdSelectMagentaColor");
  1508. if (BBuildCmdStr(pci, CMD_DC_TC_CYAN, pdc->rgocd[DC_OCD_TC_CYAN]))
  1509. VOutputExternCmd(pci, "CmdSelectCyanColor");
  1510. if (BBuildCmdStr(pci, CMD_DC_TC_WHITE, pdc->rgocd[DC_OCD_TC_WHITE]))
  1511. VOutputExternCmd(pci, "CmdSelectWhiteColor");
  1512. }
  1513. else // palette color
  1514. {
  1515. VOut(pci, " *PaletteSize: 256\r\n"); // match RASDD behavior
  1516. VOut(pci, " *PaletteProgrammable? : TRUE\r\n");
  1517. //
  1518. // output palette commands
  1519. //
  1520. if (BBuildCmdStr(pci, CMD_DC_PC_START, pdc->rgocd[DC_OCD_PC_START]))
  1521. VOutputExternCmd(pci, "CmdBeginPaletteDef");
  1522. if (BBuildCmdStr(pci, CMD_DC_PC_END, pdc->rgocd[DC_OCD_PC_END]))
  1523. VOutputExternCmd(pci, "CmdEndPaletteDef");
  1524. if (BBuildCmdStr(pci, CMD_DC_PC_ENTRY, pdc->rgocd[DC_OCD_PC_ENTRY]))
  1525. VOutputExternCmd(pci, "CmdDefinePaletteEntry");
  1526. if (BBuildCmdStr(pci, CMD_DC_PC_SELECTINDEX, pdc->rgocd[DC_OCD_PC_SELECTINDEX]))
  1527. VOutputExternCmd(pci, "CmdSelectPaletteEntry");
  1528. }
  1529. //
  1530. // output the selection command
  1531. //
  1532. if (wOrder > 0 &&
  1533. BBuildCmdStr(pci, CMD_DC_SETCOLORMODE, pdc->rgocd[DC_OCD_SETCOLORMODE]))
  1534. VOutputSelectionCmd(pci, bDocSetup, wOrder);
  1535. //
  1536. // output any constraints w.r.t. Resolution
  1537. //
  1538. for (i = 0; i < (INT)pci->dwNumOfRes; i++)
  1539. {
  1540. if (!pci->presinfo[i].bColor)
  1541. VOut(pci, " *Constraints: Resolution.%s\r\n",
  1542. pci->presinfo[i].aubOptName);
  1543. }
  1544. VOut(pci, " }\r\n"); // close Color option
  1545. psIndex++;
  1546. }
  1547. VOut(pci, "}\r\n"); // close ColorMode feature
  1548. }
  1549. void
  1550. VOutputHalftone(
  1551. IN OUT PCONVINFO pci)
  1552. {
  1553. //
  1554. // Generate 4 standard options: Auto, SuperCell, 6x6, 8x8
  1555. //
  1556. VOut(pci, "*Feature: Halftone\r\n{\r\n");
  1557. if (pci->dwStrType == STR_MACRO)
  1558. VOut(pci, " *rcNameID: =HALFTONING_DISPLAY\r\n");
  1559. else if (pci->dwStrType == STR_DIRECT)
  1560. VOut(pci, " *Name: \"Halftoning\"\r\n");
  1561. else
  1562. VOut(pci, " *rcNameID: %d\r\n", RCID_HALFTONE);
  1563. VOut(pci, " *DefaultOption: HT_PATSIZE_AUTO\r\n");
  1564. VOut(pci, " *Option: HT_PATSIZE_AUTO\r\n {\r\n");
  1565. if (pci->dwStrType == STR_MACRO)
  1566. VOut(pci, " *rcNameID: =HT_AUTO_SELECT_DISPLAY\r\n }\r\n");
  1567. else if (pci->dwStrType == STR_DIRECT)
  1568. VOut(pci, " *Name: \"Auto Select\"\r\n }\r\n");
  1569. else
  1570. VOut(pci, " *rcNameID: %d\r\n }\r\n", RCID_HT_AUTO_SELECT);
  1571. VOut(pci, " *Option: HT_PATSIZE_SUPERCELL_M\r\n {\r\n");
  1572. if (pci->dwStrType == STR_MACRO)
  1573. VOut(pci, " *rcNameID: =HT_SUPERCELL_DISPLAY\r\n }\r\n");
  1574. else if (pci->dwStrType == STR_DIRECT)
  1575. VOut(pci, " *Name: \"Super Cell\"\r\n }\r\n");
  1576. else
  1577. VOut(pci, " *rcNameID: %d\r\n }\r\n", RCID_HT_SUPERCELL);
  1578. VOut(pci, " *Option: HT_PATSIZE_6x6_M\r\n {\r\n");
  1579. if (pci->dwStrType == STR_MACRO)
  1580. VOut(pci, " *rcNameID: =HT_DITHER6X6_DISPLAY\r\n }\r\n");
  1581. else if (pci->dwStrType == STR_DIRECT)
  1582. VOut(pci, " *Name: \"Dither 6x6\"\r\n }\r\n");
  1583. else
  1584. VOut(pci, " *rcNameID: %d\r\n }\r\n", RCID_HT_DITHER6X6);
  1585. VOut(pci, " *Option: HT_PATSIZE_8x8_M\r\n {\r\n");
  1586. if (pci->dwStrType == STR_MACRO)
  1587. VOut(pci, " *rcNameID: =HT_DITHER8X8_DISPLAY\r\n }\r\n");
  1588. else if (pci->dwStrType == STR_DIRECT)
  1589. VOut(pci, " *Name: \"Dither 8x8\"\r\n }\r\n");
  1590. else
  1591. VOut(pci, " *rcNameID: %d\r\n }\r\n", RCID_HT_DITHER8X8);
  1592. VOut(pci, "}\r\n"); // close Halftone feature
  1593. }
  1594. void
  1595. VOutputMemConfig(
  1596. IN OUT PCONVINFO pci,
  1597. PWORD pwMems)
  1598. {
  1599. WORD wDefaultOption;
  1600. BOOL bGPC3 = pci->pdh->wVersion >= GPC_VERSION3;
  1601. VOut(pci, "*Feature: Memory\r\n");
  1602. VOut(pci, "{\r\n");
  1603. if (pci->dwStrType == STR_MACRO)
  1604. VOut(pci, " *rcNameID: =PRINTER_MEMORY_DISPLAY\r\n");
  1605. else if (pci->dwStrType == STR_DIRECT)
  1606. VOut(pci, " *Name: \"Printer Memory\"\r\n");
  1607. else
  1608. VOut(pci, " *rcNameID: %d\r\n", RCID_MEMORY);
  1609. wDefaultOption = WGetDefaultIndex(pci, MD_OI_MEMCONFIG);
  1610. VOut(pci, " *DefaultOption: %dKB\r\n", bGPC3?
  1611. *(((PDWORD)pwMems)+ 2*(wDefaultOption-1)) :
  1612. *pwMems);
  1613. //
  1614. // loop through each index which maps to one *MemConfigKB entry
  1615. //
  1616. while (bGPC3? *((PDWORD)pwMems) : *pwMems)
  1617. {
  1618. DWORD dwInstalled, dwAvailable;
  1619. dwInstalled = (bGPC3? *((PDWORD)pwMems)++ : (DWORD)*pwMems++);
  1620. dwAvailable = (bGPC3? *((PDWORD)pwMems)++ : (DWORD)*pwMems++);
  1621. //
  1622. // have to use two temp variables. If we put the above two
  1623. // expressions directly in the VOut call, the actual values
  1624. // are reversed for some reason.
  1625. //
  1626. VOut(pci, " *Option: %dKB\r\n {\r\n", dwInstalled);
  1627. if (dwInstalled % 1024 != 0)
  1628. VOut(pci, " *Name: \"%dKB\"\r\n", dwInstalled);
  1629. else
  1630. VOut(pci, " *Name: \"%dMB\"\r\n", (dwInstalled >> 10));
  1631. VOut(pci, " *MemoryConfigKB: PAIR(%d, %d)\r\n", dwInstalled, dwAvailable);
  1632. VOut(pci, " }\r\n");
  1633. }
  1634. VOut(pci, "}\r\n"); // close Memory feature
  1635. }
  1636. void
  1637. VOutputDuplex(
  1638. IN OUT PCONVINFO pci)
  1639. {
  1640. BOOL bDocSetup;
  1641. WORD wOrder;
  1642. VOut(pci, "*Feature: Duplex\r\n");
  1643. VOut(pci, "{\r\n");
  1644. if (pci->dwStrType == STR_MACRO)
  1645. VOut(pci, " *rcNameID: =TWO_SIDED_PRINTING_DISPLAY\r\n");
  1646. else if (pci->dwStrType == STR_DIRECT)
  1647. VOut(pci, " *Name: \"Two Sided Printing\"\r\n");
  1648. else
  1649. VOut(pci, " *rcNameID: %d\r\n", RCID_DUPLEX);
  1650. VOut(pci, " *DefaultOption: NONE\r\n");
  1651. VOut(pci, " *Option: NONE\r\n {\r\n");
  1652. if (pci->dwStrType == STR_MACRO)
  1653. VOut(pci, " *rcNameID: =NONE_DISPLAY\r\n");
  1654. else if (pci->dwStrType == STR_DIRECT)
  1655. VOut(pci, " *Name: \"None\"\r\n");
  1656. else
  1657. VOut(pci, " *rcNameID: %d\r\n", RCID_NONE);
  1658. //
  1659. // output the selection command
  1660. //
  1661. bDocSetup = BInDocSetup(pci, PC_ORD_DUPLEX, &wOrder);
  1662. if (wOrder > 0 &&
  1663. BBuildCmdStr(pci, CMD_PC_DUPLEX_OFF, pci->ppc->rgocd[PC_OCD_DUPLEX_OFF]))
  1664. VOutputSelectionCmd(pci, bDocSetup, wOrder);
  1665. VOut(pci, " }\r\n"); // close NONE option
  1666. //
  1667. // assume there is no PC_OCD_DUPLEX_ON command. True for PCL printers.
  1668. //
  1669. if (pci->ppc->rgocd[PC_OCD_DUPLEX_ON] != NOOCD)
  1670. pci->dwErrorCode |= ERR_HAS_DUPLEX_ON_CMD;
  1671. VOut(pci, " *Option: VERTICAL\r\n {\r\n");
  1672. if (pci->dwStrType == STR_MACRO)
  1673. VOut(pci, " *rcNameID: =FLIP_ON_LONG_EDGE_DISPLAY\r\n");
  1674. else if (pci->dwStrType == STR_DIRECT)
  1675. VOut(pci, " *Name: \"Flip on long edge\"\r\n");
  1676. else
  1677. VOut(pci, " *rcNameID: %d\r\n", RCID_FLIP_ON_LONG_EDGE);
  1678. //
  1679. // output the selection command
  1680. //
  1681. bDocSetup = BInDocSetup(pci, PC_ORD_DUPLEX_TYPE, &wOrder);
  1682. if (wOrder > 0 &&
  1683. BBuildCmdStr(pci, CMD_PC_DUPLEX_VERT, pci->ppc->rgocd[PC_OCD_DUPLEX_VERT]))
  1684. VOutputSelectionCmd(pci, bDocSetup, wOrder);
  1685. VOut(pci, " }\r\n"); // close VERTICAL option
  1686. VOut(pci, " *Option: HORIZONTAL\r\n {\r\n");
  1687. if (pci->dwStrType == STR_MACRO)
  1688. VOut(pci, " *rcNameID: =FLIP_ON_SHORT_EDGE_DISPLAY\r\n");
  1689. else if (pci->dwStrType == STR_DIRECT)
  1690. VOut(pci, " *Name: \"Flip on short edge\"\r\n");
  1691. else
  1692. VOut(pci, " *rcNameID: %d\r\n", RCID_FLIP_ON_SHORT_EDGE);
  1693. //
  1694. // output the selection command. Same order as VERTICAL case.
  1695. //
  1696. if (wOrder > 0 &&
  1697. BBuildCmdStr(pci, CMD_PC_DUPLEX_HORZ, pci->ppc->rgocd[PC_OCD_DUPLEX_HORZ]))
  1698. VOutputSelectionCmd(pci, bDocSetup, wOrder);
  1699. VOut(pci, " }\r\n"); // close HORIZONTAL option
  1700. VOut(pci, "}\r\n"); // close Duplex feature
  1701. }
  1702. void
  1703. VOutputPageProtect(
  1704. IN OUT PCONVINFO pci)
  1705. {
  1706. BOOL bDocSetup;
  1707. WORD wOrder;
  1708. VOut(pci, "*Feature: PageProtect\r\n");
  1709. VOut(pci, "{\r\n");
  1710. if (pci->dwStrType == STR_MACRO)
  1711. VOut(pci, " *rcNameID: =PAGE_PROTECTION_DISPLAY\r\n");
  1712. else if (pci->dwStrType == STR_DIRECT)
  1713. VOut(pci, " *Name: \"Page Protection\"\r\n");
  1714. else
  1715. VOut(pci, " *rcNameID: %d\r\n", RCID_PAGEPROTECTION);
  1716. VOut(pci, " *DefaultOption: OFF\r\n");
  1717. VOut(pci, " *Option: ON\r\n {\r\n");
  1718. if (pci->dwStrType == STR_MACRO)
  1719. VOut(pci, " *rcNameID: =ON_DISPLAY\r\n");
  1720. else if (pci->dwStrType == STR_DIRECT)
  1721. VOut(pci, " *Name: \"On\"\r\n");
  1722. else
  1723. VOut(pci, " *rcNameID: %d\r\n", RCID_ON);
  1724. //
  1725. // output the selection command
  1726. //
  1727. bDocSetup = BInDocSetup(pci, PC_ORD_PAGEPROTECT, &wOrder);
  1728. if (wOrder > 0 &&
  1729. BBuildCmdStr(pci, CMD_PAGEPROTECT_ON, pci->ocdPPOn))
  1730. VOutputSelectionCmd(pci, bDocSetup, wOrder);
  1731. VOut(pci, " }\r\n"); // close ON option
  1732. VOut(pci, " *Option: OFF\r\n {\r\n");
  1733. if (pci->dwStrType == STR_MACRO)
  1734. VOut(pci, " *rcNameID: =OFF_DISPLAY\r\n");
  1735. else if (pci->dwStrType == STR_DIRECT)
  1736. VOut(pci, " *Name: \"Off\"\r\n");
  1737. else
  1738. VOut(pci, " *rcNameID: %d\r\n", RCID_OFF);
  1739. //
  1740. // output the selection command
  1741. //
  1742. if (wOrder > 0 &&
  1743. BBuildCmdStr(pci, CMD_PAGEPROTECT_OFF, pci->ocdPPOff))
  1744. VOutputSelectionCmd(pci, bDocSetup, wOrder);
  1745. VOut(pci, " }\r\n"); // close OFF option
  1746. VOut(pci, "}\r\n"); // close PageProtect feature
  1747. }
  1748. void
  1749. VOutputPaperConstraints(
  1750. IN OUT PCONVINFO pci)
  1751. {
  1752. DWORD i, j;
  1753. for (i = 0; i < pci->dwNumOfSrc; i++)
  1754. {
  1755. for (j = 0; j < pci->dwNumOfSize; j++)
  1756. {
  1757. if (!(pci->ppiSrc[i].dwPaperType & pci->ppiSize[j].dwPaperType))
  1758. VOut(pci, "*InvalidCombination: LIST(InputBin.%s, PaperSize.%s)\r\n",
  1759. pci->ppiSrc[i].aubOptName, pci->ppiSize[j].aubOptName);
  1760. }
  1761. }
  1762. }
  1763. void
  1764. VOutputUIEntries(
  1765. IN OUT PCONVINFO pci)
  1766. {
  1767. PSHORT psIndex;
  1768. BOOL bGPC3 = pci->pdh->wVersion >= GPC_VERSION3;
  1769. //
  1770. // check if this is a TTY device. If so, do not generate the Orientation
  1771. // feature.
  1772. //
  1773. if (pci->pdh->fTechnology != GPC_TECH_TTY)
  1774. VOutputOrientation(pci);
  1775. //
  1776. // check input bins. This must come before VOutputPaperSize to gather
  1777. // info about feed margins.
  1778. //
  1779. // patryan - if no PAPERSOURCE structure is found in GPC then output a dummy
  1780. // feature, containing just one option. This is to satisfy GPD parser, which
  1781. // fail if GPD contains no InputBin feature.
  1782. if (*(psIndex = DHOFFSET(pci->pdh, pci->pmd->rgoi[MD_OI_PAPERSOURCE])) != 0)
  1783. VOutputInputBin(pci, psIndex);
  1784. else
  1785. VOutputDummyInputBin(pci);
  1786. //
  1787. // check Resolution
  1788. //
  1789. if (*(psIndex = DHOFFSET(pci->pdh, pci->pmd->rgoi[MD_OI_RESOLUTION])) != 0)
  1790. VOutputResolution(pci, psIndex);
  1791. //
  1792. // set up pci->ptMoveScale for use in generating *PrintableOrigin
  1793. // and *CursorOrigin.
  1794. // Assume that all X-move cmds have the same units. Same for Y-move cmds.
  1795. //
  1796. {
  1797. PCURSORMOVE pcm;
  1798. DWORD tmp;
  1799. pcm = (PCURSORMOVE)GetTableInfo(pci->pdh, HE_CURSORMOVE,
  1800. pci->pmd->rgi[MD_I_CURSORMOVE]);
  1801. pci->ptMoveScale.x = pci->ptMoveScale.y = 1;
  1802. if (pcm && !(pcm->fYMove & CM_YM_RES_DEPENDENT))
  1803. {
  1804. if (tmp = DwCalcMoveUnit(pci, pcm, pci->pdh->ptMaster.x,
  1805. CM_OCD_XM_ABS, CM_OCD_XM_RELLEFT))
  1806. {
  1807. // Verify move scale factor is not zero. Otherwise an essential
  1808. // GPD assumption is violated.
  1809. if(!(pci->pdh->ptMaster.x / (WORD)tmp) || pci->pdh->ptMaster.x % (WORD)tmp)
  1810. pci->dwErrorCode |= ERR_MOVESCALE_NOT_FACTOR_OF_MASTERUNITS;
  1811. else
  1812. pci->ptMoveScale.x = pci->pdh->ptMaster.x / (WORD)tmp;
  1813. }
  1814. if (tmp = DwCalcMoveUnit(pci, pcm, pci->pdh->ptMaster.y,
  1815. CM_OCD_YM_ABS, CM_OCD_YM_RELUP))
  1816. {
  1817. if(!(pci->pdh->ptMaster.y / (WORD)tmp) || pci->pdh->ptMaster.y % (WORD)tmp)
  1818. pci->dwErrorCode |= ERR_MOVESCALE_NOT_FACTOR_OF_MASTERUNITS;
  1819. else
  1820. pci->ptMoveScale.y = pci->pdh->ptMaster.y / (WORD)tmp;
  1821. }
  1822. //
  1823. // Verify that the move scale factor evenly into every resolution
  1824. // scale if RES_DM_GDI is set. This is TRUE for most, if not all,
  1825. // inkjet and page printers. With this assumption, we can simplify
  1826. // checking the printable origin values later on.
  1827. //
  1828. if (pci->dwMode & FM_RES_DM_GDI)
  1829. for (tmp = 0; tmp < pci->dwNumOfRes; tmp++)
  1830. {
  1831. if ((pci->presinfo[tmp].dwXScale % pci->ptMoveScale.x != 0) ||
  1832. (pci->presinfo[tmp].dwYScale % pci->ptMoveScale.y != 0) )
  1833. {
  1834. pci->dwErrorCode |= ERR_MOVESCALE_NOT_FACTOR_INTO_SOME_RESSCALE;
  1835. break;
  1836. }
  1837. }
  1838. }
  1839. }
  1840. //
  1841. // check PAPERSIZE.
  1842. //
  1843. if (*(psIndex = DHOFFSET(pci->pdh, pci->pmd->rgoi[MD_OI_PAPERSIZE])) != 0)
  1844. VOutputPaperSize(pci, psIndex);
  1845. //
  1846. // output PaperSize & InputBin constraints, if any.
  1847. // RES_DM_COLOR is handled in VOutputResolutions.
  1848. // RES_DM_DOWNLOAD_OUTLINE is handled in VOutputPrintingEntries.
  1849. //
  1850. VOutputPaperConstraints(pci);
  1851. //
  1852. // check PaperQuality, a.k.a. MediaType
  1853. //
  1854. if (*(psIndex = DHOFFSET(pci->pdh, pci->pmd->rgoi[MD_OI_PAPERQUALITY])) != 0)
  1855. VOutputMediaType(pci, psIndex);
  1856. //
  1857. // check TextQuality (ex. "Letter Quality")
  1858. //
  1859. if (*(psIndex = DHOFFSET(pci->pdh, pci->pmd->rgoi[MD_OI_TEXTQUAL])) != 0)
  1860. VOutputTextQuality(pci, psIndex);
  1861. //
  1862. // check PaperDestination
  1863. //
  1864. if (*(psIndex = DHOFFSET(pci->pdh, pci->pmd->rgoi[MD_OI_PAPERDEST])) != 0)
  1865. VOutputFeature(pci, FID_PAPERDEST, psIndex);
  1866. //
  1867. // check ImageControl
  1868. //
  1869. if (bGPC3 &&
  1870. *(psIndex = DHOFFSET(pci->pdh, pci->pmd->rgoi2[MD_OI2_IMAGECONTROL])) != 0)
  1871. VOutputFeature(pci, FID_IMAGECONTROL, psIndex);
  1872. //
  1873. // check PrintDensity
  1874. //
  1875. if (bGPC3 &&
  1876. *(psIndex = DHOFFSET(pci->pdh, pci->pmd->rgoi2[MD_OI2_PRINTDENSITY])) != 0)
  1877. VOutputFeature(pci, FID_PRINTDENSITY, psIndex);
  1878. //
  1879. // check DEVCOLOR
  1880. //
  1881. if (*(psIndex = DHOFFSET(pci->pdh, pci->pmd->rgoi[MD_OI_COLOR])) != 0)
  1882. VOutputColorMode(pci, psIndex);
  1883. //
  1884. // synthesize Halftone feature
  1885. //
  1886. VOutputHalftone(pci);
  1887. //
  1888. // check MemConfig
  1889. //
  1890. if (*(psIndex = DHOFFSET(pci->pdh, pci->pmd->rgoi[MD_OI_MEMCONFIG])) != 0)
  1891. {
  1892. VOutputMemConfig(pci, (PWORD)psIndex);
  1893. pci->dwMode |= FM_MEMORY_FEATURE_EXIST;
  1894. }
  1895. //
  1896. // synthesize Duplex feature if necessary.
  1897. //
  1898. if (pci->pmd->fGeneral & MD_DUPLEX)
  1899. VOutputDuplex(pci);
  1900. //
  1901. // synthesize PageProtect feature if necessary
  1902. //
  1903. if ((pci->pmd->fGeneral & MD_PCL_PAGEPROTECT) &&
  1904. (pci->dwMode & FM_SYN_PAGEPROTECT))
  1905. VOutputPageProtect(pci);
  1906. }