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.

1226 lines
31 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. custsize.c
  5. Abstract:
  6. Display PostScript custom page size UI
  7. Environment:
  8. Windows NT PostScript driver UI
  9. Revision History:
  10. 03/31/97 -davidx-
  11. Created it.
  12. --*/
  13. #include "precomp.h"
  14. #include <windowsx.h>
  15. #include <math.h>
  16. //
  17. // PostScript custom page size context-sensitive help IDs
  18. //
  19. static const DWORD PSCustSizeHelpIDs[] = {
  20. IDC_CS_WIDTH, IDH_PSCUST_Width,
  21. IDC_CS_HEIGHT, IDH_PSCUST_Height,
  22. IDC_CS_INCH, IDH_PSCUST_Unit_Inch,
  23. IDC_CS_MM, IDH_PSCUST_Unit_Millimeter,
  24. IDC_CS_POINT, IDH_PSCUST_Unit_Point,
  25. IDC_CS_FEEDDIRECTION, IDH_PSCUST_PaperFeed_Direction,
  26. IDC_CS_CUTSHEET, IDH_PSCUST_Paper_CutSheet,
  27. IDC_CS_ROLLFED, IDH_PSCUST_Paper_RollFeed,
  28. IDC_CS_XOFFSET, IDH_PSCUST_Offset_Perpendicular,
  29. IDC_CS_YOFFSET, IDH_PSCUST_Offset_Parallel,
  30. IDOK, IDH_PSCUST_OK,
  31. IDCANCEL, IDH_PSCUST_Cancel,
  32. IDC_RESTOREDEFAULTS, IDH_PSCUST_Restore_Defaults,
  33. 0, 0
  34. };
  35. //
  36. // Display units
  37. // Note: These constants must be in the same order as dialog control IDs:
  38. // IDC_CS_INCH, IDC_CS_MM, IDC_CS_POINT
  39. //
  40. enum { CSUNIT_INCH, CSUNIT_MM, CSUNIT_POINT, CSUNIT_MAX };
  41. static const double adCSUnitData[CSUNIT_MAX] =
  42. {
  43. 25400.0, // microns per inch
  44. 1000.0, // microns per millimeter
  45. 25400.0 / 72.0, // microns per point
  46. };
  47. //
  48. // Data structure used to pass information to custom page size dialog
  49. //
  50. typedef struct _CUSTOMSIZEDLG {
  51. CUSTOMSIZEDATA csdata; // custom page size data, must be the first field
  52. PUIDATA pUiData; // pointer to UIDATA structure
  53. PPPDDATA pPpdData; // pointer to PPDDATA structure
  54. BOOL bMetric; // whether we're on metric system
  55. INT iUnit; // current display unit
  56. BOOL bSetText; // we're calling SetDlgItemText
  57. BOOL bOKPassed; // user hit OK and setting passed validation/resolution
  58. // feed direction to combo box option mapping table (round up to 4-byte boundary)
  59. BYTE aubFD2CBOptionMapping[(MAX_FEEDDIRECTION + 3) & ~3];
  60. } CUSTOMSIZEDLG, *PCUSTOMSIZEDLG;
  61. #define MAXDIGITLEN 16 // maximum number of digits for user-entered numbers
  62. #define INVALID_CBOPTION_INDEX 0xFF // invalid option index for the feeding direction combo box
  63. #define CUSTSIZE_ROUNDUP(x) (ceil((x) * 100.0) / 100.0 + 0.001)
  64. #define CUSTSIZE_ROUNDDOWN(x) (floor((x) * 100.0) / 100.0 + 0.001)
  65. VOID
  66. VUpdateCustomSizeTextField(
  67. HWND hDlg,
  68. PCUSTOMSIZEDLG pDlgData,
  69. INT iCtrlID,
  70. PCUSTOMSIZERANGE pCSRange
  71. )
  72. /*++
  73. Routine Description:
  74. Update the custom size parameter text fields:
  75. width, height, and offsets
  76. Arguments:
  77. hDlg - Handle to custom page size dialog window
  78. pDlgData - Points to custom page size dialog data
  79. iCtrlID - Specifies the interested text field control ID
  80. pCSRange - custom page size parameter ranges
  81. Return Value:
  82. NONE
  83. --*/
  84. {
  85. TCHAR tchBuf[MAX_DISPLAY_NAME];
  86. DWORD dwVal;
  87. double dMin, dMax;
  88. double dNum;
  89. switch (iCtrlID)
  90. {
  91. case IDC_CS_WIDTH:
  92. dwVal = pDlgData->csdata.dwX;
  93. pCSRange += CUSTOMPARAM_WIDTH;
  94. break;
  95. case IDC_CS_HEIGHT:
  96. dwVal = pDlgData->csdata.dwY;
  97. pCSRange += CUSTOMPARAM_HEIGHT;
  98. break;
  99. case IDC_CS_XOFFSET:
  100. dwVal = pDlgData->csdata.dwWidthOffset;
  101. pCSRange += CUSTOMPARAM_WIDTHOFFSET;
  102. break;
  103. case IDC_CS_YOFFSET:
  104. dwVal = pDlgData->csdata.dwHeightOffset;
  105. pCSRange += CUSTOMPARAM_HEIGHTOFFSET;
  106. break;
  107. }
  108. //
  109. // The dMin/dMax algorithm here must be the same as in following function
  110. // VUpdateCustomSizeRangeField.
  111. //
  112. // We only show 2 digits after the decimal point. We round the min
  113. // number up (ceil) and round the max number down (floor). Also, in
  114. // order to correct double -> DWORD conversion error we saw in some
  115. // cases (ex. 39.000 is converted to DWROD 38 since the 39.000 is actually
  116. // 38.999999...), we add the extra 0.001.
  117. //
  118. dMin = (double) pCSRange->dwMin / adCSUnitData[pDlgData->iUnit];
  119. dMin = CUSTSIZE_ROUNDUP(dMin);
  120. dMax = (double) pCSRange->dwMax / adCSUnitData[pDlgData->iUnit];
  121. dMax = CUSTSIZE_ROUNDDOWN(dMax);
  122. // Fix bug Adobe #260379. 7/25/98 jjia
  123. // _stprintf(tchBuf, TEXT("%0.2f"), (double) dwVal / adCSUnitData[pDlgData->iUnit]);
  124. //
  125. // Fix MS #23733: PostScript custom page size dialog warns in border cases.
  126. //
  127. // Round the number first (2 digits after decimal point), then add 0.001 as explained above.
  128. //
  129. dNum = (double) dwVal / adCSUnitData[pDlgData->iUnit] + 0.005;
  130. dNum = CUSTSIZE_ROUNDDOWN(dNum);
  131. //
  132. // Make sure we don't show value outside of the range. This is to take care of rounding errors.
  133. //
  134. if (dNum < dMin)
  135. {
  136. dNum = dMin;
  137. }
  138. else if (dNum > dMax)
  139. {
  140. dNum = dMax;
  141. }
  142. StringCchPrintfW(tchBuf, CCHOF(tchBuf), TEXT("%ld.%0.2lu"),
  143. (DWORD)dNum, (DWORD)((dNum - (DWORD)dNum) * 100.0));
  144. SetDlgItemText(hDlg, iCtrlID, tchBuf);
  145. }
  146. VOID
  147. VUpdateCustomSizeRangeField(
  148. HWND hDlg,
  149. PCUSTOMSIZEDLG pDlgData,
  150. INT iCtrlID,
  151. PCUSTOMSIZERANGE pCSRange
  152. )
  153. /*++
  154. Routine Description:
  155. Update the custom size parameter range fields:
  156. width, height, and offsets
  157. Arguments:
  158. hDlg - Handle to custom page size dialog window
  159. pDlgData - Points to custom page size dialog data
  160. iCtrlID - Specifies the interested range field control ID
  161. pCSRange - custom page size parameter ranges
  162. Return Value:
  163. NONE
  164. --*/
  165. {
  166. TCHAR tchBuf[MAX_DISPLAY_NAME];
  167. double dMin, dMax;
  168. switch (iCtrlID)
  169. {
  170. case IDC_CS_WIDTHRANGE:
  171. pCSRange += CUSTOMPARAM_WIDTH;
  172. break;
  173. case IDC_CS_HEIGHTRANGE:
  174. pCSRange += CUSTOMPARAM_HEIGHT;
  175. break;
  176. case IDC_CS_XOFFSETRANGE:
  177. pCSRange += CUSTOMPARAM_WIDTHOFFSET;
  178. break;
  179. case IDC_CS_YOFFSETRANGE:
  180. pCSRange += CUSTOMPARAM_HEIGHTOFFSET;
  181. break;
  182. }
  183. // Fix bug Adobe #260379. 7/25/98 jjia
  184. // If we build the driver using public MSVC, MSTOOLS and DDK,
  185. // the text string will become garbage. So, Don't use '%0.2f'
  186. // to format numbers.
  187. // _stprintf(tchBuf,
  188. // TEXT("(%0.2f, %0.2f)"),
  189. // (double) pCSRange->dwMin / adCSUnitData[pDlgData->iUnit],
  190. // (double) pCSRange->dwMax / adCSUnitData[pDlgData->iUnit]);
  191. //
  192. // Fix MS #23733: PostScript custom page size dialog warns in border cases.
  193. //
  194. // We only show 2 digits after the decimal point. We round the min
  195. // number up (ceil) and round the max number down (floor). Also, in
  196. // order to correct double -> DWORD conversion error we saw in some
  197. // cases (ex. 39.000 is converted to DWROD 38 since the 39.000 is actually
  198. // 38.999999...), we add the extra 0.001.
  199. //
  200. dMin = (double) pCSRange->dwMin / adCSUnitData[pDlgData->iUnit];
  201. dMin = CUSTSIZE_ROUNDUP(dMin);
  202. dMax = (double) pCSRange->dwMax / adCSUnitData[pDlgData->iUnit];
  203. dMax = CUSTSIZE_ROUNDDOWN(dMax);
  204. StringCchPrintfW(tchBuf, CCHOF(tchBuf),
  205. TEXT("(%ld.%0.2lu, %ld.%0.2lu)"),
  206. (DWORD)dMin, (DWORD)((dMin - (DWORD)dMin) * 100.0),
  207. (DWORD)dMax, (DWORD)((dMax - (DWORD)dMax) * 100.0));
  208. SetDlgItemText(hDlg, iCtrlID, tchBuf);
  209. }
  210. VOID
  211. VUpdateCustomSizeDlgFields(
  212. HWND hDlg,
  213. PCUSTOMSIZEDLG pDlgData,
  214. BOOL bUpdateRangeOnly
  215. )
  216. /*++
  217. Routine Description:
  218. Update the custom page size dialog controls with
  219. the current custom page size parameter values
  220. Arguments:
  221. hDlg - Handle to custom page size dialog window
  222. pDlgData - Points to custom page size dialog data
  223. bUpdateRangeOnly - Whether we need to update the range fields only
  224. Return Value:
  225. NONE
  226. --*/
  227. {
  228. CUSTOMSIZERANGE csrange[4];
  229. VGetCustomSizeParamRange(pDlgData->pUiData->ci.pRawData, &pDlgData->csdata, csrange);
  230. if (! bUpdateRangeOnly)
  231. {
  232. //
  233. // Update the text fields
  234. //
  235. pDlgData->bSetText = TRUE;
  236. VUpdateCustomSizeTextField(hDlg, pDlgData, IDC_CS_WIDTH, csrange);
  237. VUpdateCustomSizeTextField(hDlg, pDlgData, IDC_CS_HEIGHT, csrange);
  238. VUpdateCustomSizeTextField(hDlg, pDlgData, IDC_CS_XOFFSET, csrange);
  239. VUpdateCustomSizeTextField(hDlg, pDlgData, IDC_CS_YOFFSET, csrange);
  240. pDlgData->bSetText = FALSE;
  241. //
  242. // Update the paper feed direction combo box
  243. //
  244. ASSERT(pDlgData->aubFD2CBOptionMapping[pDlgData->csdata.wFeedDirection] != INVALID_CBOPTION_INDEX);
  245. if (SendDlgItemMessage(hDlg,
  246. IDC_CS_FEEDDIRECTION,
  247. CB_SETCURSEL,
  248. pDlgData->aubFD2CBOptionMapping[pDlgData->csdata.wFeedDirection],
  249. 0) == CB_ERR)
  250. {
  251. ERR(("CB_SETCURSEL failed: %d\n", GetLastError()));
  252. }
  253. //
  254. // Update cut-sheet vs. roll-fed radio buttons
  255. //
  256. CheckDlgButton(hDlg, IDC_CS_CUTSHEET, pDlgData->csdata.wCutSheet);
  257. CheckDlgButton(hDlg, IDC_CS_ROLLFED, !pDlgData->csdata.wCutSheet);
  258. }
  259. //
  260. // Update ranges for width, height, and offsets
  261. //
  262. VUpdateCustomSizeRangeField(hDlg, pDlgData, IDC_CS_WIDTHRANGE, csrange);
  263. VUpdateCustomSizeRangeField(hDlg, pDlgData, IDC_CS_HEIGHTRANGE, csrange);
  264. VUpdateCustomSizeRangeField(hDlg, pDlgData, IDC_CS_XOFFSETRANGE, csrange);
  265. VUpdateCustomSizeRangeField(hDlg, pDlgData, IDC_CS_YOFFSETRANGE, csrange);
  266. }
  267. BOOL
  268. BGetWidthHeightOffsetVal(
  269. HWND hDlg,
  270. PCUSTOMSIZEDLG pDlgData,
  271. INT iCtrlID,
  272. PDWORD pdwVal
  273. )
  274. /*++
  275. Routine Description:
  276. Get the current width/height/offset value in the specified text field
  277. Arguments:
  278. hDlg - Handle to custom page size dialog window
  279. pDlgData - Points to custom page size dialog data
  280. iCtrlID - Specifies the interested text field control ID
  281. pdwVal - Return the current value in the specified text field (in microns)
  282. Return Value:
  283. TRUE if successful, FALSE if the text field doesn't contain
  284. valid floating-point number.
  285. Note that this function doesn't perform any range check.
  286. That's done in a later step.
  287. --*/
  288. {
  289. TCHAR tchBuf[MAXDIGITLEN];
  290. double d;
  291. PTSTR ptstr;
  292. BOOL bResult = FALSE;
  293. //
  294. // Get the current value in the speicified text field
  295. //
  296. if (GetDlgItemText(hDlg, iCtrlID, tchBuf, MAXDIGITLEN) > 0)
  297. {
  298. //
  299. // Treat the string as floating-point number
  300. // Make sure there are no non-space characters left
  301. //
  302. d = _tcstod(tchBuf, &ptstr);
  303. while (*ptstr != NUL)
  304. {
  305. if (! _istspace(*ptstr))
  306. break;
  307. ptstr++;
  308. }
  309. if (bResult = (*ptstr == NUL))
  310. {
  311. //
  312. // Convert from current unit to microns
  313. //
  314. d *= adCSUnitData[pDlgData->iUnit];
  315. if (d < 0 || d > MAX_LONG)
  316. bResult = FALSE;
  317. else
  318. *pdwVal = (DWORD) d;
  319. }
  320. }
  321. if (!bResult)
  322. {
  323. //
  324. // automatically correct user's invalid input to value 0.00
  325. //
  326. SetDlgItemText(hDlg, iCtrlID, TEXT("0.00"));
  327. *pdwVal = 0;
  328. }
  329. return TRUE;
  330. }
  331. BOOL
  332. BGetFeedDirectionSel(
  333. HWND hDlg,
  334. PCUSTOMSIZEDLG pDlgData,
  335. INT iCtrlID,
  336. PDWORD pdwVal
  337. )
  338. /*++
  339. Routine Description:
  340. Get the currently selected paper direction value
  341. Arguments:
  342. hDlg - Handle to custom page size dialog window
  343. pDlgData - Points to custom page size dialog data
  344. iCtrlID - Specifies the paper feed direction combo box control ID
  345. pdwVal - Return the selected paper feed direction value
  346. Return Value:
  347. TRUE if successful, FALSE if the selected choice is constrained
  348. or if there is an error
  349. --*/
  350. {
  351. LRESULT lIndex, lVal;
  352. //
  353. // Get the currently chosen paper feed direction index
  354. //
  355. if (((lIndex = SendDlgItemMessage(hDlg, iCtrlID, CB_GETCURSEL, 0, 0)) == CB_ERR) ||
  356. ((lVal = SendDlgItemMessage(hDlg, iCtrlID, CB_GETITEMDATA, (WPARAM)lIndex, 0)) == CB_ERR))
  357. return FALSE;
  358. *pdwVal = (DWORD)lVal;
  359. return TRUE;
  360. }
  361. BOOL
  362. BChangeCustomSizeData(
  363. HWND hDlg,
  364. PCUSTOMSIZEDLG pDlgData,
  365. INT iCtrlID,
  366. DWORD dwVal
  367. )
  368. /*++
  369. Routine Description:
  370. Change the specified custom page size parameter
  371. Arguments:
  372. hDlg - Handle to custom page size dialog window
  373. pDlgData - Points to custom page size dialog data
  374. iCtrlID - Control ID indicating which parameter should be changed
  375. dwVal - New value for the specified parameter
  376. Return Value:
  377. TRUE
  378. --*/
  379. {
  380. PCUSTOMSIZEDATA pCSData;
  381. //
  382. // Update the appropriate custom page size parameter
  383. //
  384. pCSData = &pDlgData->csdata;
  385. switch (iCtrlID)
  386. {
  387. case IDC_CS_WIDTH:
  388. pCSData->dwX = dwVal;
  389. break;
  390. case IDC_CS_HEIGHT:
  391. pCSData->dwY = dwVal;
  392. break;
  393. case IDC_CS_XOFFSET:
  394. pCSData->dwWidthOffset = dwVal;
  395. break;
  396. case IDC_CS_YOFFSET:
  397. pCSData->dwHeightOffset = dwVal;
  398. break;
  399. case IDC_CS_FEEDDIRECTION:
  400. pCSData->wFeedDirection = (WORD)dwVal;
  401. break;
  402. case IDC_CS_CUTSHEET:
  403. pCSData->wCutSheet = TRUE;
  404. return TRUE;
  405. case IDC_CS_ROLLFED:
  406. pCSData->wCutSheet = FALSE;
  407. return TRUE;
  408. }
  409. VUpdateCustomSizeDlgFields(hDlg, pDlgData, TRUE);
  410. return TRUE;
  411. }
  412. VOID
  413. VInitPaperFeedDirectionList(
  414. HWND hwndList,
  415. PCUSTOMSIZEDLG pDlgData
  416. )
  417. /*++
  418. Routine Description:
  419. Initialize the paper feed direction combo box
  420. Arguments:
  421. hwndList - Window handle to the paper feed direction combo box
  422. pDlgData - Points to custom page size dialog data
  423. Return Value:
  424. NONE
  425. --*/
  426. {
  427. PUIINFO pUIInfo;
  428. PPPDDATA pPpdData;
  429. DWORD dwIndex;
  430. TCHAR tchBuf[MAX_DISPLAY_NAME];
  431. LRESULT lIndex;
  432. if (hwndList == NULL)
  433. return;
  434. ASSERT(pDlgData);
  435. pUIInfo = pDlgData->pUiData->ci.pUIInfo;
  436. pPpdData = pDlgData->pPpdData;
  437. ASSERT(pUIInfo && pPpdData);
  438. for (dwIndex=0; dwIndex < MAX_FEEDDIRECTION; dwIndex++)
  439. {
  440. //
  441. // First: initialize the mapping table
  442. //
  443. pDlgData->aubFD2CBOptionMapping[dwIndex] = INVALID_CBOPTION_INDEX;
  444. //
  445. // Don't show the feeding direction if device doesn't supported it.
  446. //
  447. if ((dwIndex == LONGEDGEFIRST || dwIndex == LONGEDGEFIRST_FLIPPED) &&
  448. !LONGEDGEFIRST_SUPPORTED(pUIInfo, pPpdData))
  449. continue;
  450. if ((dwIndex == SHORTEDGEFIRST || dwIndex == SHORTEDGEFIRST_FLIPPED) &&
  451. !SHORTEDGEFIRST_SUPPORTED(pUIInfo, pPpdData))
  452. continue;
  453. if ((dwIndex == LONGEDGEFIRST || dwIndex == SHORTEDGEFIRST) &&
  454. (MINCUSTOMPARAM_ORIENTATION(pPpdData) > 1))
  455. continue;
  456. if ((dwIndex == LONGEDGEFIRST_FLIPPED || dwIndex == SHORTEDGEFIRST_FLIPPED) &&
  457. (MAXCUSTOMPARAM_ORIENTATION(pPpdData) < 2))
  458. continue;
  459. if (LoadString(ghInstance,
  460. IDS_FEEDDIRECTION_BASE + dwIndex,
  461. tchBuf,
  462. MAX_DISPLAY_NAME))
  463. {
  464. if (((lIndex = SendMessage(hwndList, CB_ADDSTRING, 0, (LPARAM) tchBuf)) == CB_ERR) ||
  465. (SendMessage(hwndList, CB_SETITEMDATA, (WPARAM)lIndex, (LPARAM)dwIndex) == CB_ERR))
  466. {
  467. if (lIndex != CB_ERR)
  468. {
  469. SendMessage(hwndList, CB_DELETESTRING, (WPARAM)lIndex, 0);
  470. ERR(("CB_SETITEMDATA failed: %d\n", GetLastError()));
  471. }
  472. else
  473. {
  474. ERR(("CB_ADDSTRING failed: %d\n", GetLastError()));
  475. }
  476. }
  477. else
  478. {
  479. //
  480. // Record the mapping from feed direction to combo box option index.
  481. // Note that the combo box can NOT be sorted.
  482. //
  483. pDlgData->aubFD2CBOptionMapping[dwIndex] = (BYTE)lIndex;
  484. }
  485. }
  486. }
  487. }
  488. BOOL
  489. BCheckCustomSizeData(
  490. HWND hDlg,
  491. PCUSTOMSIZEDLG pDlgData
  492. )
  493. {
  494. CUSTOMSIZEDATA csdata;
  495. INT iCtrlID;
  496. //
  497. // If there is no inconsistency, return TRUE
  498. //
  499. csdata = pDlgData->csdata;
  500. if (BValidateCustomPageSizeData(pDlgData->pUiData->ci.pRawData, &csdata))
  501. return TRUE;
  502. //
  503. // Otherwise, indicate which field is invalid
  504. //
  505. if (hDlg != NULL)
  506. {
  507. if (csdata.dwX != pDlgData->csdata.dwX)
  508. iCtrlID = IDC_CS_WIDTH;
  509. else if (csdata.dwY != pDlgData->csdata.dwY)
  510. iCtrlID = IDC_CS_HEIGHT;
  511. else if (csdata.dwWidthOffset != pDlgData->csdata.dwWidthOffset)
  512. iCtrlID = IDC_CS_XOFFSET;
  513. else if (csdata.dwHeightOffset != pDlgData->csdata.dwHeightOffset)
  514. iCtrlID = IDC_CS_YOFFSET;
  515. else if (csdata.wFeedDirection != pDlgData->csdata.wFeedDirection)
  516. iCtrlID = IDC_CS_FEEDDIRECTION;
  517. else
  518. iCtrlID = IDC_CS_CUTSHEET;
  519. SetFocus(GetDlgItem(hDlg, iCtrlID));
  520. if (iCtrlID == IDC_CS_WIDTH ||
  521. iCtrlID == IDC_CS_HEIGHT ||
  522. iCtrlID == IDC_CS_XOFFSET ||
  523. iCtrlID == IDC_CS_YOFFSET)
  524. {
  525. SendDlgItemMessage(hDlg, iCtrlID, EM_SETSEL, 0, -1);
  526. }
  527. }
  528. return FALSE;
  529. }
  530. BOOL
  531. BCheckCustomSizeFeature(
  532. HWND hDlg,
  533. PCUSTOMSIZEDLG pDlgData,
  534. DWORD dwFeatureID
  535. )
  536. {
  537. PUIINFO pUIInfo;
  538. PPPDDATA pPpdData;
  539. PFEATURE pFeature;
  540. DWORD dwFeatureIndex, dwOptionIndex;
  541. CONFLICTPAIR ConflictPair;
  542. //
  543. // If the specified feature doesn't exist, simply return TRUE
  544. //
  545. pUIInfo = pDlgData->pUiData->ci.pUIInfo;
  546. if (! (pFeature = GET_PREDEFINED_FEATURE(pUIInfo, dwFeatureID)))
  547. return TRUE;
  548. dwFeatureIndex = GET_INDEX_FROM_FEATURE(pUIInfo, pFeature);
  549. pPpdData = pDlgData->pPpdData;
  550. if (dwFeatureID == GID_LEADINGEDGE)
  551. {
  552. if (SKIP_LEADINGEDGE_CHECK(pUIInfo, pPpdData))
  553. return TRUE;
  554. dwOptionIndex = (pDlgData->csdata.wFeedDirection == SHORTEDGEFIRST ||
  555. pDlgData->csdata.wFeedDirection == SHORTEDGEFIRST_FLIPPED) ?
  556. pPpdData->dwLeadingEdgeShort :
  557. pPpdData->dwLeadingEdgeLong;
  558. if (dwOptionIndex == OPTION_INDEX_ANY)
  559. {
  560. goto error;
  561. }
  562. }
  563. else // (dwFeatureID == GID_USEHWMARGINS)
  564. {
  565. dwOptionIndex = pDlgData->csdata.wCutSheet ?
  566. pPpdData->dwUseHWMarginsTrue :
  567. pPpdData->dwUseHWMarginsFalse;
  568. }
  569. //
  570. // Return TRUE if there is no conflict. This is opposite of
  571. // EnumNewPickOneUIConflict which returns TRUE if there is a conflict.
  572. //
  573. if (! EnumNewPickOneUIConflict(
  574. pDlgData->pUiData->ci.pRawData,
  575. pDlgData->pUiData->ci.pCombinedOptions,
  576. dwFeatureIndex,
  577. dwOptionIndex,
  578. &ConflictPair))
  579. {
  580. return TRUE;
  581. }
  582. error:
  583. if (hDlg != NULL)
  584. {
  585. SetFocus(GetDlgItem(hDlg,
  586. dwFeatureID == GID_LEADINGEDGE ?
  587. IDC_CS_FEEDDIRECTION :
  588. IDC_CS_CUTSHEET));
  589. }
  590. return FALSE;
  591. }
  592. BOOL
  593. BResolveCustomSizeData(
  594. HWND hDlg,
  595. PCUSTOMSIZEDLG pDlgData
  596. )
  597. {
  598. PRAWBINARYDATA pRawData;
  599. CUSTOMSIZEDATA cssave;
  600. PCUSTOMSIZEDATA pCSData;
  601. pRawData = pDlgData->pUiData->ci.pRawData;
  602. cssave = pDlgData->csdata;
  603. pCSData = &pDlgData->csdata;
  604. //
  605. // Choose alternative wCutSheet and wFeedDirection
  606. // value if the current value is constrained.
  607. //
  608. if (! BCheckCustomSizeFeature(hDlg, pDlgData, GID_USEHWMARGINS))
  609. pCSData->wCutSheet = pCSData->wCutSheet ? FALSE : TRUE;
  610. if (! BCheckCustomSizeFeature(hDlg, pDlgData, GID_LEADINGEDGE))
  611. {
  612. pCSData->wFeedDirection =
  613. (pCSData->wFeedDirection == SHORTEDGEFIRST ||
  614. pCSData->wFeedDirection == SHORTEDGEFIRST_FLIPPED) ?
  615. LONGEDGEFIRST : SHORTEDGEFIRST;
  616. }
  617. //
  618. // Check to see if the specified custom page size parameters are consistent
  619. //
  620. (VOID) BValidateCustomPageSizeData(pRawData, pCSData);
  621. if (pCSData->dwX != cssave.dwX || pCSData->dwY != cssave.dwY)
  622. {
  623. CUSTOMSIZEDATA cstemp;
  624. //
  625. // If the width or height parameter is adjusted,
  626. // try to adjust the feed direction parameter first
  627. //
  628. cstemp = *pCSData;
  629. *pCSData = cssave;
  630. pCSData->wCutSheet = cstemp.wCutSheet;
  631. pCSData->wFeedDirection =
  632. (cstemp.wFeedDirection == SHORTEDGEFIRST ||
  633. cstemp.wFeedDirection == SHORTEDGEFIRST_FLIPPED) ?
  634. LONGEDGEFIRST : SHORTEDGEFIRST;
  635. (VOID) BValidateCustomPageSizeData(pRawData, pCSData);
  636. if (pCSData->dwX != cssave.dwX ||
  637. pCSData->dwY != cssave.dwY ||
  638. !BCheckCustomSizeFeature(hDlg, pDlgData, GID_LEADINGEDGE))
  639. {
  640. *pCSData = cstemp;
  641. }
  642. }
  643. if ((hDlg != NULL) &&
  644. (!BCheckCustomSizeFeature(hDlg, pDlgData, GID_USEHWMARGINS) ||
  645. !BCheckCustomSizeFeature(hDlg, pDlgData, GID_LEADINGEDGE)))
  646. {
  647. *pCSData = cssave;
  648. return FALSE;
  649. }
  650. return TRUE;
  651. }
  652. BOOL
  653. BCheckCustomSizeDataConflicts(
  654. HWND hDlg,
  655. PCUSTOMSIZEDLG pDlgData
  656. )
  657. /*++
  658. Routine Description:
  659. Resolve any conflicts involving *LeadingEdge and *UseHWMargins
  660. and any inconsistencies between custom page size parameters
  661. Arguments:
  662. hDlg - Handle to custom page size dialog window
  663. NULL if the window is not displayed yet
  664. pDlgData - Points to custom page size dialog data
  665. Return Value:
  666. FALSE if there are any unresolved conflicts or inconsistencies,
  667. TRUE otherwise
  668. --*/
  669. {
  670. BOOL bResult;
  671. //
  672. // Check if there is any inconsistency
  673. //
  674. bResult = BCheckCustomSizeFeature(hDlg, pDlgData, GID_LEADINGEDGE) &&
  675. BCheckCustomSizeFeature(hDlg, pDlgData, GID_USEHWMARGINS) &&
  676. BCheckCustomSizeData(hDlg, pDlgData);
  677. if (! bResult)
  678. {
  679. //
  680. // Display an error message and ask the user whether he wants
  681. // to let the system automatically resolve the inconsistency.
  682. //
  683. if (hDlg == NULL ||
  684. IDisplayErrorMessageBox(hDlg,
  685. MB_OKCANCEL | MB_ICONERROR,
  686. IDS_CUSTOMSIZE_ERROR,
  687. IDS_CUSTOMSIZEPARAM_ERROR) == IDOK)
  688. {
  689. bResult = BResolveCustomSizeData(hDlg, pDlgData);
  690. if (!bResult && hDlg != NULL)
  691. {
  692. (VOID) IDisplayErrorMessageBox(
  693. hDlg,
  694. 0,
  695. IDS_CUSTOMSIZE_ERROR,
  696. IDS_CUSTOMSIZE_UNRESOLVED);
  697. }
  698. }
  699. }
  700. return bResult;
  701. }
  702. INT_PTR CALLBACK
  703. BCustomSizeDlgProc(
  704. HWND hDlg,
  705. UINT uMsg,
  706. WPARAM wParam,
  707. LPARAM lParam
  708. )
  709. /*++
  710. Routine Description:
  711. Dialog procedure for custom page size dialog
  712. Arguments:
  713. hDlg - Handle to dialog window
  714. uMsg - Message
  715. wParam, lParam - Parameters
  716. Return Value:
  717. TRUE or FALSE depending on whether message is processed
  718. --*/
  719. {
  720. PCUSTOMSIZEDLG pDlgData;
  721. INT iCmd;
  722. DWORD dwVal;
  723. switch (uMsg)
  724. {
  725. case WM_INITDIALOG:
  726. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)lParam);
  727. pDlgData = (PCUSTOMSIZEDLG) lParam;
  728. if (pDlgData == NULL)
  729. {
  730. RIP(("Dialog parameter is NULL\n"));
  731. EndDialog(hDlg, IDCANCEL);
  732. return FALSE;
  733. }
  734. SendDlgItemMessage(hDlg, IDC_CS_WIDTH, EM_SETLIMITTEXT, MAXDIGITLEN-1, 0);
  735. SendDlgItemMessage(hDlg, IDC_CS_HEIGHT, EM_SETLIMITTEXT, MAXDIGITLEN-1, 0);
  736. SendDlgItemMessage(hDlg, IDC_CS_XOFFSET, EM_SETLIMITTEXT, MAXDIGITLEN-1, 0);
  737. SendDlgItemMessage(hDlg, IDC_CS_YOFFSET, EM_SETLIMITTEXT, MAXDIGITLEN-1, 0);
  738. pDlgData->iUnit = pDlgData->bMetric ? CSUNIT_MM : CSUNIT_INCH;
  739. CheckRadioButton(hDlg, IDC_CS_INCH, IDC_CS_POINT, IDC_CS_INCH + pDlgData->iUnit);
  740. //
  741. // Determine which feed directions should be disabled
  742. //
  743. VInitPaperFeedDirectionList(GetDlgItem(hDlg, IDC_CS_FEEDDIRECTION), pDlgData);
  744. //
  745. // Set up the initial display
  746. //
  747. if (! (pDlgData->pPpdData->dwCustomSizeFlags & CUSTOMSIZE_CUTSHEET))
  748. EnableWindow(GetDlgItem(hDlg, IDC_CS_CUTSHEET), FALSE);
  749. if (! (pDlgData->pPpdData->dwCustomSizeFlags & CUSTOMSIZE_ROLLFED))
  750. EnableWindow(GetDlgItem(hDlg, IDC_CS_ROLLFED), FALSE);
  751. VUpdateCustomSizeDlgFields(hDlg, pDlgData, FALSE);
  752. ShowWindow(hDlg, SW_SHOW);
  753. break;
  754. case WM_COMMAND:
  755. pDlgData = (PCUSTOMSIZEDLG) GetWindowLongPtr(hDlg, DWLP_USER);
  756. if (pDlgData == NULL)
  757. {
  758. RIP(("Dialog parameter is NULL\n"));
  759. break;
  760. }
  761. iCmd = GET_WM_COMMAND_ID(wParam, lParam);
  762. switch (iCmd)
  763. {
  764. case IDOK:
  765. //
  766. // Check if the selected paper feed direction is constrained
  767. //
  768. if (BCheckCustomSizeDataConflicts(hDlg, pDlgData))
  769. {
  770. pDlgData->bOKPassed = TRUE;
  771. EndDialog(hDlg, IDOK);
  772. }
  773. return TRUE;
  774. case IDCANCEL:
  775. EndDialog(hDlg, IDCANCEL);
  776. return TRUE;
  777. case IDC_RESTOREDEFAULTS:
  778. //
  779. // Use default custom page size parameters
  780. //
  781. VFillDefaultCustomPageSizeData(
  782. pDlgData->pUiData->ci.pRawData,
  783. &pDlgData->csdata,
  784. pDlgData->bMetric);
  785. VUpdateCustomSizeDlgFields(hDlg, pDlgData, FALSE);
  786. return TRUE;
  787. case IDC_CS_INCH:
  788. case IDC_CS_MM:
  789. case IDC_CS_POINT:
  790. //
  791. // Change display unit
  792. //
  793. pDlgData->iUnit = (iCmd == IDC_CS_INCH) ? CSUNIT_INCH :
  794. (iCmd == IDC_CS_MM) ? CSUNIT_MM : CSUNIT_POINT;
  795. VUpdateCustomSizeDlgFields(hDlg, pDlgData, FALSE);
  796. return TRUE;
  797. case IDC_CS_WIDTH:
  798. case IDC_CS_HEIGHT:
  799. case IDC_CS_XOFFSET:
  800. case IDC_CS_YOFFSET:
  801. if (GET_WM_COMMAND_CMD(wParam, lParam) != EN_KILLFOCUS ||
  802. pDlgData->bSetText ||
  803. pDlgData->bOKPassed)
  804. {
  805. break;
  806. }
  807. if (! BGetWidthHeightOffsetVal(hDlg, pDlgData, iCmd, &dwVal) ||
  808. ! BChangeCustomSizeData(hDlg, pDlgData, iCmd, dwVal))
  809. {
  810. VUpdateCustomSizeDlgFields(hDlg, pDlgData, FALSE);
  811. SetFocus(GetDlgItem(hDlg, iCmd));
  812. SendDlgItemMessage(hDlg, iCmd, EM_SETSEL, 0, -1);
  813. }
  814. return TRUE;
  815. case IDC_CS_FEEDDIRECTION:
  816. if (GET_WM_COMMAND_CMD(wParam, lParam) != CBN_SELCHANGE)
  817. break;
  818. if (! BGetFeedDirectionSel(hDlg, pDlgData, iCmd, &dwVal) ||
  819. ! BChangeCustomSizeData(hDlg, pDlgData, iCmd, dwVal))
  820. {
  821. VUpdateCustomSizeDlgFields(hDlg, pDlgData, FALSE);
  822. SetFocus(GetDlgItem(hDlg, iCmd));
  823. }
  824. return TRUE;
  825. case IDC_CS_CUTSHEET:
  826. case IDC_CS_ROLLFED:
  827. BChangeCustomSizeData(hDlg, pDlgData, iCmd, 0);
  828. return TRUE;
  829. }
  830. break;
  831. case WM_HELP:
  832. case WM_CONTEXTMENU:
  833. //
  834. // Sanity check
  835. //
  836. pDlgData = (PCUSTOMSIZEDLG) GetWindowLongPtr(hDlg, DWLP_USER);
  837. if (pDlgData == NULL ||
  838. pDlgData->pUiData->ci.pDriverInfo3->pHelpFile == NULL)
  839. {
  840. return FALSE;
  841. }
  842. if (uMsg == WM_HELP)
  843. {
  844. WinHelp(((LPHELPINFO) lParam)->hItemHandle,
  845. pDlgData->pUiData->ci.pDriverInfo3->pHelpFile,
  846. HELP_WM_HELP,
  847. (ULONG_PTR)PSCustSizeHelpIDs);
  848. }
  849. else
  850. {
  851. WinHelp((HWND) wParam,
  852. pDlgData->pUiData->ci.pDriverInfo3->pHelpFile,
  853. HELP_CONTEXTMENU,
  854. (ULONG_PTR)PSCustSizeHelpIDs);
  855. }
  856. return TRUE;
  857. }
  858. return FALSE;
  859. }
  860. BOOL
  861. BDisplayPSCustomPageSizeDialog(
  862. PUIDATA pUiData
  863. )
  864. /*++
  865. Routine Description:
  866. Display PostScript custom page size dialog
  867. Arguments:
  868. pUiData - Points to UIDATA structure
  869. Return Value:
  870. TRUE if user pressed OK, FALSE otherwise
  871. --*/
  872. {
  873. CUSTOMSIZEDLG dlgdata;
  874. PPSDRVEXTRA pdmPrivate;
  875. ZeroMemory(&dlgdata, sizeof(dlgdata));
  876. dlgdata.pUiData = pUiData;
  877. dlgdata.pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER((PINFOHEADER) pUiData->ci.pRawData);
  878. dlgdata.bMetric = IsMetricCountry();
  879. ASSERT(SUPPORT_CUSTOMSIZE(pUiData->ci.pUIInfo) &&
  880. SUPPORT_FULL_CUSTOMSIZE_FEATURES(pUiData->ci.pUIInfo, dlgdata.pPpdData));
  881. //
  882. // Make sure the custom page size devmode fields are validated
  883. //
  884. pdmPrivate = pUiData->ci.pdmPrivate;
  885. dlgdata.csdata = pdmPrivate->csdata;
  886. (VOID) BCheckCustomSizeDataConflicts(NULL, &dlgdata);
  887. pdmPrivate->csdata = dlgdata.csdata;
  888. //
  889. // Display the custom page size dialog.
  890. // If the user pressed OK, update the devmode fields again.
  891. //
  892. if (DialogBoxParam(ghInstance,
  893. MAKEINTRESOURCE(IDD_PSCRIPT_CUSTOMSIZE),
  894. pUiData->hDlg,
  895. BCustomSizeDlgProc,
  896. (LPARAM) &dlgdata) == IDOK)
  897. {
  898. pdmPrivate->csdata = dlgdata.csdata;
  899. return TRUE;
  900. }
  901. else
  902. return FALSE;
  903. }