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.

1059 lines
26 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. forms.c
  5. Abstract:
  6. Functions for dealing with paper and forms.
  7. [Environment:]
  8. Win32 subsystem, PostScript driver
  9. Revision History:
  10. 02/10/97 -davidx-
  11. Consistent handling of common printer info.
  12. 07/24/96 -amandan-
  13. Modified for common binary data and common UI module
  14. 07/25/95 -davidx-
  15. Created it.
  16. --*/
  17. #include "precomp.h"
  18. BOOL
  19. BFormSupportedOnPrinter(
  20. IN PCOMMONINFO pci,
  21. IN PFORM_INFO_1 pForm,
  22. OUT PDWORD pdwOptionIndex
  23. )
  24. /*++
  25. Routine Description:
  26. Determine whether a form is supported on a printer
  27. Arguments:
  28. pci - Points to basic printer information
  29. pForm - Pointer to information about the form in question
  30. pdwOptionIndex - Returns the paper size option index corresponding
  31. to the specified form if the form is supported.
  32. Return Value:
  33. TRUE if the requested form is supported on the printer.
  34. FALSE otherwise.
  35. --*/
  36. {
  37. PRAWBINARYDATA pRawData;
  38. PUIINFO pUIInfo;
  39. PFEATURE pFeature;
  40. DWORD dwIndex;
  41. CHAR chBuf[CCHPAPERNAME];
  42. WCHAR wchBuf[CCHPAPERNAME];
  43. //
  44. // For a user-defined form, we only care about paper dimension.
  45. // Let the parser handle this case.
  46. //
  47. if (! (pForm->Flags & (FORM_BUILTIN|FORM_PRINTER)))
  48. {
  49. *pdwOptionIndex = MapToDeviceOptIndex(
  50. pci->pInfoHeader,
  51. GID_PAGESIZE,
  52. pForm->Size.cx,
  53. pForm->Size.cy,
  54. NULL);
  55. return (*pdwOptionIndex != OPTION_INDEX_ANY);
  56. }
  57. //
  58. // For predefined or driver-defined form, we need exact name and size match
  59. //
  60. chBuf[0] = NUL;
  61. *pdwOptionIndex = OPTION_INDEX_ANY;
  62. if (! (pFeature = GET_PREDEFINED_FEATURE(pci->pUIInfo, GID_PAGESIZE)))
  63. return FALSE;
  64. for (dwIndex = 0; dwIndex < pFeature->Options.dwCount; dwIndex++)
  65. {
  66. PPAGESIZE pPageSize;
  67. PWSTR pwstr;
  68. PSTR pstr;
  69. BOOL bNameMatch;
  70. LONG x, y;
  71. pPageSize = PGetIndexedOption(pci->pUIInfo, pFeature, dwIndex);
  72. ASSERT(pPageSize != NULL);
  73. //
  74. // check if the size matches
  75. //
  76. x = MASTER_UNIT_TO_MICRON(pPageSize->szPaperSize.cx,
  77. pci->pUIInfo->ptMasterUnits.x);
  78. y = MASTER_UNIT_TO_MICRON(pPageSize->szPaperSize.cy,
  79. pci->pUIInfo->ptMasterUnits.y);
  80. if (abs(x - pForm->Size.cx) > 1000 ||
  81. abs(y - pForm->Size.cy) > 1000)
  82. {
  83. continue;
  84. }
  85. //
  86. // check if the name matches
  87. //
  88. LOAD_STRING_PAGESIZE_NAME(pci, pPageSize, wchBuf, CCHPAPERNAME);
  89. bNameMatch = (_tcsicmp(wchBuf, pForm->pName) == EQUAL_STRING);
  90. if (!bNameMatch && (pForm->Flags & FORM_BUILTIN))
  91. {
  92. PSTR pstrKeyword;
  93. //
  94. // special klugy for predefined form:
  95. // if display name doesn't match, try to match the keyword string
  96. //
  97. if (chBuf[0] == NUL)
  98. {
  99. WideCharToMultiByte(1252, 0, pForm->pName, -1, chBuf, CCHPAPERNAME, NULL, NULL);
  100. chBuf[CCHPAPERNAME-1] = NUL;
  101. }
  102. pstrKeyword = OFFSET_TO_POINTER(pci->pUIInfo->pubResourceData, pPageSize->GenericOption.loKeywordName);
  103. ASSERT(pstrKeyword != NULL);
  104. bNameMatch = (_stricmp(chBuf, pstrKeyword) == EQUAL_STRING);
  105. }
  106. if (bNameMatch)
  107. {
  108. *pdwOptionIndex = dwIndex;
  109. return TRUE;
  110. }
  111. }
  112. return FALSE;
  113. }
  114. DWORD
  115. DwGuessFormIconID(
  116. PWSTR pFormName
  117. )
  118. /*++
  119. Routine Description:
  120. Figure out the icon ID corresponding to the named form
  121. Arguments:
  122. pFormName - Pointer to the form name string
  123. Return Value:
  124. Icon ID corresponding to the specified form name
  125. Note:
  126. This is very klugy but I guess it's better than using the same icon
  127. for all forms. We try to differentiate envelopes from normal forms.
  128. We assume a form name refers an envelope if it contains word Envelope or Env.
  129. --*/
  130. #define MAXENVLEN 32
  131. {
  132. static WCHAR wchPrefix[MAXENVLEN], wchEnvelope[MAXENVLEN];
  133. static INT iPrefixLen = 0, iEnvelopeLen = 0;
  134. if (iPrefixLen <= 0 || iEnvelopeLen <= 0)
  135. {
  136. iPrefixLen = LoadString(ghInstance, IDS_ENV_PREFIX, wchPrefix, MAXENVLEN);
  137. iEnvelopeLen = LoadString(ghInstance, IDS_ENVELOPE, wchEnvelope, MAXENVLEN);
  138. }
  139. if (iPrefixLen <= 0 || iEnvelopeLen <= 0)
  140. return IDI_CPSUI_STD_FORM;
  141. while (*pFormName)
  142. {
  143. //
  144. // Do we have a word matching our description?
  145. //
  146. if (_wcsnicmp(pFormName, wchPrefix, iPrefixLen) == EQUAL_STRING &&
  147. (pFormName[iPrefixLen] == L' ' ||
  148. pFormName[iPrefixLen] == NUL ||
  149. _wcsnicmp(pFormName, wchEnvelope, iEnvelopeLen) == EQUAL_STRING))
  150. {
  151. return IDI_CPSUI_ENVELOPE;
  152. }
  153. //
  154. // Move on to the next word
  155. //
  156. while (*pFormName && *pFormName != L' ')
  157. pFormName++;
  158. while (*pFormName && *pFormName == L' ')
  159. pFormName++;
  160. }
  161. return IDI_CPSUI_STD_FORM;
  162. }
  163. ULONG_PTR
  164. HLoadFormIconResource(
  165. PUIDATA pUiData,
  166. DWORD dwIndex
  167. )
  168. /*++
  169. Routine Description:
  170. Load the icon resource corresponding to the specified form
  171. Arguments:
  172. pUiData - Points to UIDATA structure
  173. dwIndex - Specifies the form index. It's used to index into
  174. pUiData->pwPaperFeatures to get the page size option index.
  175. Return Value:
  176. Icon resource handle corresponding to the specified form (casted as DWORD)
  177. 0 if the specified icon resource cannot be loaded
  178. --*/
  179. {
  180. PFEATURE pFeature;
  181. POPTION pOption;
  182. dwIndex = pUiData->pwPaperFeatures[dwIndex];
  183. if ((pFeature = GET_PREDEFINED_FEATURE(pUiData->ci.pUIInfo, GID_PAGESIZE)) &&
  184. (pOption = PGetIndexedOption(pUiData->ci.pUIInfo, pFeature, dwIndex)) &&
  185. (pOption->loResourceIcon != 0))
  186. {
  187. return HLoadIconFromResourceDLL(&pUiData->ci, pOption->loResourceIcon);
  188. }
  189. return 0;
  190. }
  191. POPTTYPE
  192. BFillFormNameOptType(
  193. IN PUIDATA pUiData
  194. )
  195. /*++
  196. Routine Description:
  197. Initialize an OPTTYPE structure to hold information
  198. about the list of forms supported by a printer
  199. Arguments:
  200. pUiData - Pointer to UIDATA structure
  201. Return Value:
  202. Pointer to an OPTTYPE structure, NULL if there is an error
  203. --*/
  204. {
  205. POPTTYPE pOptType;
  206. POPTPARAM pOptParam;
  207. DWORD dwFormName, dwIndex;
  208. PWSTR pFormName;
  209. PUIINFO pUIInfo = pUiData->ci.pUIInfo;
  210. dwFormName = pUiData->dwFormNames;
  211. //
  212. // Allocate memory to hold OPTTYPE and OPTPARAM structures
  213. //
  214. pOptType = HEAPALLOC(pUiData->ci.hHeap, sizeof(OPTTYPE));
  215. pOptParam = HEAPALLOC(pUiData->ci.hHeap, sizeof(OPTPARAM) * dwFormName);
  216. if (!pOptType || !pOptParam)
  217. {
  218. ERR(("Memory allocation failed\n"));
  219. return NULL;
  220. }
  221. //
  222. // Initialize OPTTYPE structure
  223. //
  224. pOptType->cbSize = sizeof(OPTTYPE);
  225. pOptType->Count = (WORD) dwFormName;
  226. pOptType->Type = TVOT_LISTBOX;
  227. pOptType->pOptParam = pOptParam;
  228. pOptType->Style = OTS_LBCB_SORT | OTS_LBCB_INCL_ITEM_NONE;
  229. //
  230. // Enumerate the list of supported form names
  231. //
  232. pFormName = pUiData->pFormNames;
  233. for (dwIndex=0; dwIndex < dwFormName; dwIndex++, pOptParam++)
  234. {
  235. pOptParam->cbSize = sizeof(OPTPARAM);
  236. pOptParam->pData = pFormName;
  237. if (pOptParam->IconID = HLoadFormIconResource(pUiData, dwIndex))
  238. pOptParam->Flags |= OPTPF_ICONID_AS_HICON;
  239. else
  240. pOptParam->IconID = DwGuessFormIconID(pFormName);
  241. pFormName += CCHPAPERNAME;
  242. }
  243. return pOptType;
  244. }
  245. POPTTYPE
  246. PAdjustFormNameOptType(
  247. IN PUIDATA pUiData,
  248. IN POPTTYPE pOptType,
  249. IN DWORD dwTraySelection
  250. )
  251. /*++
  252. Routine Description:
  253. Adjust the list of forms for each tray
  254. Check each form for support on printer tray
  255. Given a tray selected, go through all the forms selection
  256. and determines which one conflicts with the current tray selection
  257. Arguments:
  258. pUiData - Pointer to our UIDATA structure
  259. pOptType - Pointer to OPTTYPE
  260. dwTraySelection - Tray index
  261. Return Value:
  262. TRUE if successful, FALSE otherwise
  263. --*/
  264. {
  265. POPTPARAM pOptParam;
  266. DWORD dwOptParam, dwFormIndex;
  267. DWORD dwTrayFeatureIndex, dwFormFeatureIndex;
  268. PFEATURE pTrayFeature, pFormFeature;
  269. PUIINFO pUIInfo = pUiData->ci.pUIInfo;
  270. dwOptParam = pOptType->Count;
  271. //
  272. // Find the pointers to InputSlot and PageSize features
  273. //
  274. pTrayFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_INPUTSLOT);
  275. pFormFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_PAGESIZE);
  276. if (!pTrayFeature || !pFormFeature)
  277. return pOptType;
  278. dwTrayFeatureIndex = GET_INDEX_FROM_FEATURE(pUIInfo, pTrayFeature);
  279. dwFormFeatureIndex = GET_INDEX_FROM_FEATURE(pUIInfo, pFormFeature);
  280. //
  281. // Make a copy of the array of formname OPTPARAMs
  282. //
  283. if (dwTraySelection != 0)
  284. {
  285. POPTTYPE pNewType;
  286. pNewType = HEAPALLOC(pUiData->ci.hHeap, sizeof(OPTTYPE));
  287. pOptParam = HEAPALLOC(pUiData->ci.hHeap, sizeof(OPTPARAM) * dwOptParam);
  288. if (!pNewType || !pOptParam)
  289. {
  290. ERR(("Memory allocation failed\n"));
  291. return NULL;
  292. }
  293. CopyMemory(pNewType, pOptType, sizeof(OPTTYPE));
  294. CopyMemory(pOptParam, pOptType->pOptParam, sizeof(OPTPARAM) * dwOptParam);
  295. pNewType->pOptParam = pOptParam;
  296. pOptType = pNewType;
  297. }
  298. else
  299. pOptParam = pOptType->pOptParam;
  300. //
  301. // Go through each formname
  302. // Check whether the current form tray feature, index
  303. // conflicts with another form tray feature,index
  304. //
  305. for (dwFormIndex=0; dwFormIndex < dwOptParam; dwFormIndex++)
  306. {
  307. DWORD dwFormSelection = pUiData->pwPaperFeatures[dwFormIndex];
  308. #ifdef PSCRIPT
  309. //
  310. // Hide only the option "PostScript Custom Page Size" itself. For other
  311. // forms that are supported via PostScript Custom Page Size, we still
  312. // want to show them, same as Unidrv does.
  313. //
  314. if (pUiData->pwPapers[dwFormIndex] == DMPAPER_CUSTOMSIZE)
  315. {
  316. pOptParam[dwFormIndex].Flags |= (OPTPF_HIDE | CONSTRAINED_FLAG);
  317. continue;
  318. }
  319. #endif // PSCRIPT
  320. //
  321. // If the form conflicts with the tray, then don't display it.
  322. //
  323. if (dwFormSelection != OPTION_INDEX_ANY &&
  324. CheckFeatureOptionConflict(pUiData->ci.pRawData,
  325. dwTrayFeatureIndex,
  326. dwTraySelection,
  327. dwFormFeatureIndex,
  328. dwFormSelection))
  329. {
  330. pOptParam[dwFormIndex].Flags |= (OPTPF_HIDE | CONSTRAINED_FLAG);
  331. }
  332. else
  333. {
  334. pOptParam[dwFormIndex].Flags &= ~(OPTPF_HIDE | CONSTRAINED_FLAG);
  335. }
  336. }
  337. return pOptType;
  338. }
  339. BOOL
  340. BPackItemFormTrayTable(
  341. IN OUT PUIDATA pUiData
  342. )
  343. /*++
  344. Routine Description:
  345. Pack form-to-tray assignment information into treeview item
  346. structures so that we can call common UI library.
  347. Arguments:
  348. pUiData - Points to UIDATA structure
  349. Return Value:
  350. TRUE if successful, FALSE otherwise
  351. --*/
  352. {
  353. POPTITEM pOptItem;
  354. POPTTYPE pOptType;
  355. DWORD dwIndex, dwTrays;
  356. PWSTR pTrayName;
  357. dwTrays = pUiData->dwBinNames;
  358. if (dwTrays == 0)
  359. {
  360. WARNING(("No paper bin available\n"));
  361. return TRUE;
  362. }
  363. //
  364. // Form-to-tray assignment table
  365. // Tray <-> Form
  366. // ...
  367. VPackOptItemGroupHeader(
  368. pUiData,
  369. IDS_CPSUI_FORMTRAYASSIGN,
  370. IDI_CPSUI_FORMTRAYASSIGN,
  371. HELP_INDEX_FORMTRAYASSIGN);
  372. pUiData->dwFormTrayItem = dwTrays;
  373. pUiData->dwOptItem += dwTrays;
  374. if (pUiData->pOptItem == NULL)
  375. return TRUE;
  376. pUiData->pFormTrayItems = pUiData->pOptItem;
  377. //
  378. // Generate the list of form names
  379. // Each OPTITEM(Tray) has a OPTTYPE.
  380. //
  381. pOptType = BFillFormNameOptType(pUiData);
  382. if (pOptType == NULL)
  383. {
  384. ERR(("BFillFormNameOptType failed\n"));
  385. return FALSE;
  386. }
  387. //
  388. // Create an OPTITEM for each tray
  389. //
  390. pTrayName = pUiData->pBinNames ;
  391. pOptItem = pUiData->pOptItem;
  392. for (dwIndex=0; dwIndex < dwTrays; dwIndex++)
  393. {
  394. //
  395. // The tray items cannot share OPTTYPE and OPTPARAMs because
  396. // each tray can contain a different list of forms.
  397. //
  398. pOptType = PAdjustFormNameOptType(pUiData, pOptType, dwIndex);
  399. if (pOptType == NULL)
  400. {
  401. ERR(("PAdjustFormNameOptParam failed\n"));
  402. return FALSE;
  403. }
  404. FILLOPTITEM(pOptItem,
  405. pOptType,
  406. pTrayName,
  407. 0,
  408. TVITEM_LEVEL2,
  409. DMPUB_NONE,
  410. FORM_TRAY_ITEM,
  411. HELP_INDEX_TRAY_ITEM);
  412. //
  413. // NOTE: hide the first tray if it's AutoSelect
  414. //
  415. if (dwIndex == 0)
  416. {
  417. PFEATURE pFeature;
  418. PINPUTSLOT pInputSlot;
  419. if ((pFeature = GET_PREDEFINED_FEATURE(pUiData->ci.pUIInfo, GID_INPUTSLOT)) &&
  420. (pInputSlot = PGetIndexedOption(pUiData->ci.pUIInfo, pFeature, 0)) &&
  421. (pInputSlot->dwPaperSourceID == DMBIN_FORMSOURCE))
  422. {
  423. pOptItem->Flags |= (OPTIF_HIDE|OPTIF_DISABLED);
  424. }
  425. }
  426. pOptItem++;
  427. pTrayName += CCHBINNAME;
  428. }
  429. pUiData->pOptItem = pOptItem;
  430. return TRUE;
  431. }
  432. VOID
  433. VSetupFormTrayAssignments(
  434. IN PUIDATA pUiData
  435. )
  436. /*++
  437. Routine Description:
  438. Update the current selection of tray items based on
  439. the specified form-to-tray assignment table
  440. Arguments:
  441. pUiData - Pointer to our UIDATA structure
  442. Return Value:
  443. NONE
  444. Note:
  445. We assume the form-tray items are in their default states
  446. when this function is called.
  447. --*/
  448. {
  449. POPTITEM pOptItem;
  450. POPTPARAM pOptParam;
  451. FORM_TRAY_TABLE pFormTrayTable;
  452. FINDFORMTRAY FindData;
  453. DWORD dwTrayStartIndex, dwTrayIndex, dwFormIndex, dwTrays, dwOptParam;
  454. PCOMMONINFO pci;
  455. PFEATURE pFeature;
  456. PINPUTSLOT pInputSlot;
  457. PPAGESIZE pPageSize;
  458. if ((dwTrays = pUiData->dwFormTrayItem) == 0)
  459. return;
  460. pci = &pUiData->ci;
  461. pOptItem = pUiData->pFormTrayItems;
  462. pOptParam = pOptItem->pOptType->pOptParam;
  463. dwOptParam = pOptItem->pOptType->Count;
  464. //
  465. // Initialize the current selection for every tray to be
  466. // "Not Available"
  467. //
  468. for (dwTrayIndex=0; dwTrayIndex < dwTrays; dwTrayIndex++)
  469. pOptItem[dwTrayIndex].Sel = -1;
  470. pFormTrayTable = PGetFormTrayTable(pUiData->ci.hPrinter, NULL);
  471. //
  472. // If the form-to-tray assignment information doesn't exist,
  473. // set up the default assignments
  474. //
  475. if (pFormTrayTable == NULL)
  476. {
  477. PWSTR pwstrDefaultForm = NULL;
  478. WCHAR awchBuf[CCHPAPERNAME];
  479. BOOL bMetric = IsMetricCountry();
  480. //
  481. // Get the default formname (Letter or A4) and
  482. // convert it formname to a seleciton index.
  483. //
  484. if (bMetric && (pci->pUIInfo->dwFlags & FLAG_A4_SIZE_EXISTS))
  485. {
  486. pwstrDefaultForm = A4_FORMNAME;
  487. }
  488. else if (!bMetric && (pci->pUIInfo->dwFlags & FLAG_LETTER_SIZE_EXISTS))
  489. {
  490. pwstrDefaultForm = LETTER_FORMNAME;
  491. }
  492. else
  493. {
  494. if ((pFeature = GET_PREDEFINED_FEATURE(pci->pUIInfo, GID_PAGESIZE)) &&
  495. (pPageSize = PGetIndexedOption(pci->pUIInfo, pFeature, pFeature->dwDefaultOptIndex)) &&
  496. LOAD_STRING_PAGESIZE_NAME(pci, pPageSize, awchBuf, CCHPAPERNAME))
  497. {
  498. pwstrDefaultForm = &(awchBuf[0]);
  499. }
  500. }
  501. //
  502. // If we can't find the default form name, we have to use the first option as the default.
  503. //
  504. dwFormIndex = pwstrDefaultForm ? DwFindFormNameIndex(pUiData, pwstrDefaultForm, NULL) : 0 ;
  505. ASSERT(dwFormIndex < dwOptParam);
  506. //
  507. // Set the default formname for each enabled tray
  508. //
  509. for (dwTrayIndex=0; dwTrayIndex < dwTrays; dwTrayIndex++)
  510. {
  511. if (! (pOptItem[dwTrayIndex].Flags & OPTIF_DISABLED) &&
  512. ! IS_CONSTRAINED(&pOptItem[dwTrayIndex], dwFormIndex))
  513. {
  514. pOptItem[dwTrayIndex].Sel = dwFormIndex;
  515. }
  516. }
  517. //
  518. // Save the default form-to-tray assignment table to registry.
  519. //
  520. if (HASPERMISSION(pUiData))
  521. BUnpackItemFormTrayTable(pUiData);
  522. return;
  523. }
  524. //
  525. // We are here means that the form to tray assignment does exits.
  526. // Iterate thru the form-to-tray assignment table one entry at
  527. // a time and update the current selection of tray items.
  528. //
  529. RESET_FINDFORMTRAY(pFormTrayTable, &FindData);
  530. //
  531. // If we have synthersized the first "AutoSelect" tray, we should skip it
  532. // in following searching through the form to tray assignment table.
  533. //
  534. // (refer to the logic in previous function BPackItemFormTrayTable)
  535. //
  536. dwTrayStartIndex = 0;
  537. if ((pFeature = GET_PREDEFINED_FEATURE(pci->pUIInfo, GID_INPUTSLOT)) &&
  538. (pInputSlot = PGetIndexedOption(pci->pUIInfo, pFeature, 0)) &&
  539. (pInputSlot->dwPaperSourceID == DMBIN_FORMSOURCE))
  540. {
  541. dwTrayStartIndex = 1;
  542. }
  543. while (BSearchFormTrayTable(pFormTrayTable, NULL, NULL, &FindData))
  544. {
  545. //
  546. // Get the next entry in the form-to-tray assignment table
  547. //
  548. for (dwTrayIndex = dwTrayStartIndex; dwTrayIndex < dwTrays; dwTrayIndex++)
  549. {
  550. //
  551. // found matching tray?
  552. //
  553. if (_wcsicmp(FindData.ptstrTrayName, pOptItem[dwTrayIndex].pName) == EQUAL_STRING)
  554. {
  555. //
  556. // If the specified tray name is supported, then check
  557. // if the associated form name is supported.
  558. //
  559. for (dwFormIndex=0; dwFormIndex < dwOptParam; dwFormIndex++)
  560. {
  561. if (_wcsicmp(FindData.ptstrFormName,
  562. pOptParam[dwFormIndex].pData) == EQUAL_STRING)
  563. {
  564. break;
  565. }
  566. }
  567. if (dwFormIndex == dwOptParam)
  568. {
  569. WARNING(("Unknown form name: %ws\n", FindData.ptstrFormName));
  570. }
  571. else if ((pOptItem[dwTrayIndex].Flags & OPTIF_DISABLED) ||
  572. IS_CONSTRAINED(&pOptItem[dwTrayIndex], dwFormIndex))
  573. {
  574. WARNING(("Conflicting form-tray assignment\n"));
  575. }
  576. else
  577. {
  578. //
  579. // If the associated form name is supported,
  580. // then remember the form index.
  581. //
  582. pOptItem[dwTrayIndex].Sel = dwFormIndex;
  583. }
  584. break;
  585. }
  586. }
  587. if (dwTrayIndex == dwTrays)
  588. WARNING(("Unknown tray name: %ws\n", FindData.ptstrTrayName));
  589. }
  590. MemFree(pFormTrayTable);
  591. }
  592. DWORD
  593. DwCollectFormTrayAssignments(
  594. IN PUIDATA pUiData,
  595. OUT PWSTR pwstrTable
  596. )
  597. /*++
  598. Routine Description:
  599. Collect the form-to-tray assignment information and save it to registry.
  600. Arguments:
  601. pUiData - Pointer to our UIDATA structure
  602. pwstrTable - Pointer to memory buffer for storing the table
  603. NULL if the caller is only interested in the table size
  604. Return Value:
  605. Size of the table bytes, 0 if there is an error.
  606. --*/
  607. {
  608. DWORD dwChars = 0;
  609. INT iLength;
  610. DWORD dwIndex;
  611. POPTPARAM pOptParam;
  612. DWORD dwOptItem = pUiData->dwFormTrayItem;
  613. POPTITEM pOptItem = pUiData->pFormTrayItems;
  614. for (dwIndex=0; dwIndex < dwOptItem; dwIndex++, pOptItem++)
  615. {
  616. ASSERT(ISFORMTRAYITEM(pOptItem->UserData));
  617. if ((pOptItem->Flags & OPTIF_DISABLED))
  618. continue;
  619. //
  620. // Get the Tray name
  621. //
  622. iLength = wcslen(pOptItem->pName) + 1;
  623. dwChars += iLength;
  624. if (pwstrTable != NULL)
  625. {
  626. CopyMemory(pwstrTable, pOptItem->pName, iLength * sizeof(WCHAR));
  627. pwstrTable += iLength;
  628. }
  629. //
  630. // Form name
  631. //
  632. if (pOptItem->Sel < 0 )
  633. {
  634. dwChars++;
  635. if (pwstrTable != NULL)
  636. *pwstrTable++ = NUL;
  637. continue;
  638. }
  639. pOptParam = pOptItem->pOptType->pOptParam + pOptItem->Sel;
  640. iLength = wcslen(pOptParam->pData) + 1;
  641. dwChars += iLength;
  642. if (pwstrTable != NULL)
  643. {
  644. CopyMemory(pwstrTable, pOptParam->pData, iLength * sizeof(WCHAR));
  645. pwstrTable += iLength;
  646. }
  647. }
  648. //
  649. // Append a NUL character at the end of the table
  650. //
  651. dwChars++;
  652. if (pwstrTable != NULL)
  653. *pwstrTable = NUL;
  654. //
  655. // Return the table size in bytes
  656. //
  657. return dwChars * sizeof(WCHAR);
  658. }
  659. BOOL
  660. BUnpackItemFormTrayTable(
  661. IN PUIDATA pUiData
  662. )
  663. /*++
  664. Routine Description:
  665. Extract form-to-tray assignment information from treeview items
  666. Arguments:
  667. pUiData - Pointer to UIDATA structure
  668. Return Value:
  669. TRUE if successful, FALSE otherwise
  670. --*/
  671. {
  672. PWSTR pwstrTable = NULL;
  673. DWORD dwTableSize;
  674. //
  675. // Figure out how much memory we need to store the form-to-tray assignment table
  676. // Assemble the form-to-tray assignment table
  677. // Save the form-to-tray assignment table to registry
  678. //
  679. if ((dwTableSize = DwCollectFormTrayAssignments(pUiData, NULL)) == 0 ||
  680. (pwstrTable = MemAlloc(dwTableSize)) == NULL ||
  681. (dwTableSize != DwCollectFormTrayAssignments(pUiData, pwstrTable)) ||
  682. !BSaveFormTrayTable(pUiData->ci.hPrinter, pwstrTable, dwTableSize))
  683. {
  684. ERR(("Couldn't save form-to-tray assignment table\n"));
  685. MemFree(pwstrTable);
  686. return FALSE;
  687. }
  688. #ifndef WINNT_40
  689. //
  690. // Publish list of available forms in the directory service
  691. //
  692. VNotifyDSOfUpdate(pUiData->ci.hPrinter);
  693. #endif // !WINNT_40
  694. MemFree(pwstrTable);
  695. return TRUE;
  696. }
  697. DWORD
  698. DwFindFormNameIndex(
  699. IN PUIDATA pUiData,
  700. IN PWSTR pFormName,
  701. OUT PBOOL pbSupported
  702. )
  703. /*++
  704. Routine Description:
  705. Given a formname, find its index in the list of supported forms
  706. Arguments:
  707. pUiData - Pointer to our UIDATA structure
  708. pFormName - Formname in question
  709. pbSupported - Whether or not the form is suppported
  710. Return Value:
  711. Index of the specified formname in the list.
  712. --*/
  713. {
  714. DWORD dwIndex;
  715. PWSTR pName;
  716. FORM_INFO_1 *pForm;
  717. PFEATURE pFeature;
  718. PPAGESIZE pPageSize;
  719. WCHAR awchBuf[CCHPAPERNAME];
  720. PCOMMONINFO pci;
  721. if (pbSupported)
  722. *pbSupported = TRUE;
  723. if (IS_EMPTY_STRING(pFormName))
  724. return 0;
  725. //
  726. // Check if the name appears in the list
  727. //
  728. pName = pUiData->pFormNames;
  729. for (dwIndex=0; dwIndex < pUiData->dwFormNames; dwIndex++)
  730. {
  731. if (_wcsicmp(pFormName, pName) == EQUAL_STRING)
  732. return dwIndex;
  733. pName += CCHPAPERNAME;
  734. }
  735. //
  736. // If the name is not in the list, try to match
  737. // the form to a printer page size
  738. //
  739. pci = (PCOMMONINFO) pUiData;
  740. if ((pForm = MyGetForm(pci->hPrinter, pFormName, 1)) &&
  741. BFormSupportedOnPrinter(pci, pForm, &dwIndex) &&
  742. (pFeature = GET_PREDEFINED_FEATURE(pci->pUIInfo, GID_PAGESIZE)) &&
  743. (pPageSize = PGetIndexedOption(pci->pUIInfo, pFeature, dwIndex)) &&
  744. LOAD_STRING_PAGESIZE_NAME(pci, pPageSize, awchBuf, CCHPAPERNAME))
  745. {
  746. pName = pUiData->pFormNames;
  747. for (dwIndex = 0; dwIndex < pUiData->dwFormNames; dwIndex++)
  748. {
  749. if (_wcsicmp(awchBuf, pName) == EQUAL_STRING)
  750. {
  751. MemFree(pForm);
  752. return dwIndex;
  753. }
  754. pName += CCHPAPERNAME;
  755. }
  756. }
  757. MemFree(pForm);
  758. //
  759. // The specified form is not supported on the printer.
  760. // Select the first available form.
  761. //
  762. if (pbSupported)
  763. *pbSupported = FALSE;
  764. return 0;
  765. }