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.

618 lines
13 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. fontsub.c
  5. Abstract:
  6. Function for handling TrueType font substitution dialog
  7. [Environment:]
  8. Win32 subsystem, PostScript driver UI
  9. [Notes:]
  10. Revision History:
  11. 02/10/97 -davidx-
  12. Consistent handling of common printer info.
  13. 09/18/96 - amandan-
  14. Modified for common binary data and UI
  15. 08/29/95 -davidx-
  16. Created it.
  17. --*/
  18. #include "precomp.h"
  19. VOID
  20. VSetupTrueTypeFontMappings(
  21. IN PUIDATA pUiData
  22. )
  23. /*++
  24. Routine Description:
  25. Initialize the font substitution items with the settings from
  26. current font substitution table.
  27. Arguments:
  28. pUiData - Points to UIDATA structure
  29. Return Value:
  30. NONE
  31. --*/
  32. {
  33. POPTITEM pOptItem;
  34. POPTPARAM pOptParam;
  35. DWORD dwOptItem;
  36. PWSTR pTTSubstTable;
  37. //
  38. // Get the current font substitution table
  39. //
  40. if ((pTTSubstTable = PGetTTSubstTable(pUiData->ci.hPrinter, NULL)) == NULL &&
  41. (pTTSubstTable = GET_DEFAULT_FONTSUB_TABLE(&pUiData->ci, pUiData->ci.pUIInfo)) == NULL)
  42. {
  43. WARNING(("Font substitution table is not available\n"));
  44. return;
  45. }
  46. //
  47. // For each TrueType font, check if there is a device font mapped to it.
  48. // If there is, find the index of the device font in the selection list.
  49. //
  50. pOptItem = pUiData->pTTFontItems;
  51. dwOptItem = pUiData->dwTTFontItem;
  52. while (dwOptItem--)
  53. {
  54. DWORD dwOptParam, dwIndex;
  55. LPCTSTR pDevFontName;
  56. ASSERT(ISFONTSUBSTITEM(pOptItem->UserData));
  57. pOptItem->Sel = 0;
  58. pDevFontName = PtstrSearchTTSubstTable(pTTSubstTable, pOptItem->pName);
  59. //
  60. // Check if we found a match
  61. //
  62. if (pDevFontName != NULL && *pDevFontName != NUL)
  63. {
  64. //
  65. // Get the total substitution font list
  66. //
  67. dwOptParam = pOptItem->pOptType->Count;
  68. pOptParam = pOptItem->pOptType->pOptParam;
  69. //
  70. // Skip the first device font name in the list
  71. // which should always be "Download as Soft Font".
  72. //
  73. for (dwIndex=1; dwIndex < dwOptParam; dwIndex++)
  74. {
  75. if (_wcsicmp(pDevFontName, pOptParam[dwIndex].pData) == EQUAL_STRING)
  76. {
  77. pOptItem->Sel = dwIndex;
  78. break;
  79. }
  80. }
  81. }
  82. pOptItem++;
  83. }
  84. //
  85. // Remember to free the memory occupied by the substitution
  86. // table after we're done with it.
  87. //
  88. FREE_DEFAULT_FONTSUB_TABLE(pTTSubstTable);
  89. }
  90. int __cdecl
  91. ICompareOptParam(
  92. const void *p1,
  93. const void *p2
  94. )
  95. {
  96. return _wcsicmp(((POPTPARAM) p1)->pData, ((POPTPARAM) p2)->pData);
  97. }
  98. POPTTYPE
  99. PFillDevFontOptType(
  100. IN PUIDATA pUiData
  101. )
  102. /*++
  103. Routine Description:
  104. Initialize an OPTTYPE structure to hold information
  105. about the list of device fonts supported by a printer
  106. Arguments:
  107. pUiData - Pointer to UIDATA structure
  108. Return Value:
  109. Pointer to an OPTTYPE structure
  110. NULL if there is an error
  111. --*/
  112. {
  113. POPTTYPE pOptType;
  114. POPTPARAM pOptParam;
  115. HDC hdc;
  116. DWORD dwCount, dwIndex;
  117. INT iSize;
  118. PWSTR pwstrFontNames, pwstr;
  119. //
  120. // Get the list of printer device font names
  121. //
  122. dwCount = 0;
  123. if ((hdc = CreateIC(NULL, pUiData->ci.pPrinterName, NULL, NULL)) &&
  124. (iSize = _IListDevFontNames(hdc, NULL, 0)) > 0 &&
  125. (pwstrFontNames = HEAPALLOC(pUiData->ci.hHeap, iSize)) &&
  126. (iSize == _IListDevFontNames(hdc, pwstrFontNames, iSize)))
  127. {
  128. //
  129. // Count the number of device font names
  130. //
  131. for (pwstr=pwstrFontNames; *pwstr; pwstr += wcslen(pwstr)+1)
  132. dwCount++;
  133. }
  134. else
  135. {
  136. ERR(("Couldn't enumerate printer device fonts\n"));
  137. }
  138. if (hdc)
  139. DeleteDC(hdc);
  140. //
  141. // Generate an OPTTYPE structure for device font list
  142. //
  143. pOptType = HEAPALLOC(pUiData->ci.hHeap, sizeof(OPTTYPE));
  144. pOptParam = HEAPALLOC(pUiData->ci.hHeap, sizeof(OPTPARAM) * (dwCount+1));
  145. if (pOptType == NULL || pOptParam == NULL)
  146. {
  147. ERR(("Memory allocation failed\n"));
  148. return NULL;
  149. }
  150. pOptType->cbSize = sizeof(OPTTYPE);
  151. pOptType->Count = (WORD) (dwCount+1);
  152. pOptType->Type = TVOT_LISTBOX;
  153. pOptType->pOptParam = pOptParam;
  154. //
  155. // Initialize OPTPARAM structures.
  156. // The first item is always "Download as Soft Font".
  157. //
  158. for (dwIndex=0; dwIndex <= dwCount; dwIndex++)
  159. pOptParam[dwIndex].cbSize = sizeof(OPTPARAM);
  160. pOptParam->pData = (PWSTR) IDS_DOWNLOAD_AS_SOFTFONT;
  161. pOptParam++;
  162. // hack to get around a compiler bug
  163. dwCount++;
  164. dwCount--;
  165. for (dwIndex=0, pwstr=pwstrFontNames; dwIndex < dwCount; dwIndex++)
  166. {
  167. pOptParam[dwIndex].pData = pwstr;
  168. pwstr += wcslen(pwstr) + 1;
  169. }
  170. //
  171. // Sort device font names into alphabetical order;
  172. // Hide any duplicate device font names as well.
  173. //
  174. qsort(pOptParam, dwCount, sizeof(OPTPARAM), ICompareOptParam);
  175. for (dwIndex=1; dwIndex < dwCount; dwIndex++)
  176. {
  177. if (_wcsicmp(pOptParam[dwIndex].pData, pOptParam[dwIndex-1].pData) == EQUAL_STRING)
  178. pOptParam[dwIndex].Flags |= OPTPF_HIDE;
  179. }
  180. return pOptType;
  181. }
  182. //
  183. // Data structures and functions for enumerating printer device fonts
  184. //
  185. typedef struct _ENUMTTFONT {
  186. DWORD dwCount;
  187. POPTITEM pOptItem;
  188. POPTTYPE pOptType;
  189. HANDLE hHeap;
  190. WCHAR awchLastFontName[LF_FACESIZE];
  191. } ENUMTTFONT, *PENUMTTFONT;
  192. INT CALLBACK
  193. EnumTTFontProc(
  194. ENUMLOGFONT *pelf,
  195. NEWTEXTMETRIC *pntm,
  196. INT FontType,
  197. LPARAM lParam
  198. )
  199. {
  200. PENUMTTFONT pEnumData;
  201. PTSTR pFontName;
  202. PTSTR pFamilyName;
  203. //
  204. // We only care about the TrueType fonts.
  205. //
  206. if (! (FontType & TRUETYPE_FONTTYPE))
  207. return 1;
  208. pEnumData = (PENUMTTFONT) lParam;
  209. pFamilyName = pelf->elfLogFont.lfFaceName;
  210. if (_tcscmp(pFamilyName, pEnumData->awchLastFontName) == EQUAL_STRING)
  211. return 1;
  212. CopyString(pEnumData->awchLastFontName, pFamilyName, LF_FACESIZE);
  213. pEnumData->dwCount++;
  214. if (pEnumData->pOptItem)
  215. {
  216. pFontName = PtstrDuplicateStringFromHeap(pFamilyName, pEnumData->hHeap);
  217. if (pFontName == NULL)
  218. return 0;
  219. FILLOPTITEM(pEnumData->pOptItem,
  220. pEnumData->pOptType,
  221. pFontName,
  222. 0,
  223. TVITEM_LEVEL2,
  224. DMPUB_NONE,
  225. FONT_SUBST_ITEM,
  226. HELP_INDEX_TTTODEV);
  227. pEnumData->pOptItem++;
  228. }
  229. return 1;
  230. }
  231. int __cdecl
  232. ICompareOptItem(
  233. const void *p1,
  234. const void *p2
  235. )
  236. {
  237. return _wcsicmp(((POPTITEM) p1)->pName, ((POPTITEM) p2)->pName);
  238. }
  239. BOOL
  240. BPackItemFontSubstTable(
  241. IN OUT PUIDATA pUiData
  242. )
  243. /*++
  244. Routine Description:
  245. Pack Font Substitution options
  246. Arguments:
  247. pUiData - Points to UIDATA structure
  248. Return Value:
  249. TRUE if successful, FALSE if there is an error.
  250. --*/
  251. {
  252. ENUMTTFONT EnumData;
  253. POPTITEM pOptItem;
  254. HDC hdc;
  255. INT iResult;
  256. //
  257. // If the printer doesn't support font-substitution,
  258. // then simply return success here.
  259. //
  260. if (pUiData->ci.pUIInfo->dwFontSubCount == 0)
  261. return TRUE;
  262. //
  263. // Create a screen IC
  264. //
  265. if ((hdc = CreateIC(TEXT("DISPLAY"), NULL, NULL, NULL)) == NULL)
  266. {
  267. ERR(("Cannot create screen IC\n"));
  268. return FALSE;
  269. }
  270. //
  271. // Font substitution table
  272. // TrueType font <-> Device font
  273. // ....
  274. //
  275. // Group Header for Font Substitution Table
  276. //
  277. pOptItem = pUiData->pOptItem;
  278. VPackOptItemGroupHeader(
  279. pUiData,
  280. IDS_FONTSUB_TABLE,
  281. IDI_CPSUI_FONTSUB,
  282. HELP_INDEX_FONTSUB_TABLE);
  283. ZeroMemory(&EnumData, sizeof(EnumData));
  284. EnumData.hHeap = pUiData->ci.hHeap;
  285. if (pOptItem == NULL)
  286. {
  287. //
  288. // Count the number of TrueType fonts
  289. //
  290. iResult = EnumFontFamilies(hdc,
  291. NULL,
  292. (FONTENUMPROC) EnumTTFontProc,
  293. (LPARAM) &EnumData);
  294. }
  295. else
  296. {
  297. //
  298. // Collapse the group header
  299. //
  300. pOptItem->Flags |= OPTIF_COLLAPSE;
  301. pUiData->pTTFontItems = pUiData->pOptItem;
  302. EnumData.pOptItem = pUiData->pOptItem;
  303. //
  304. // Get the list of printer device fonts
  305. //
  306. EnumData.pOptType = PFillDevFontOptType(pUiData);
  307. if (EnumData.pOptType == NULL)
  308. {
  309. ERR(("PFillDevFontOptType failed\n"));
  310. iResult = 0;
  311. }
  312. else
  313. {
  314. //
  315. // Enumerate the list of TrueType fonts
  316. //
  317. iResult = EnumFontFamilies(hdc,
  318. NULL,
  319. (FONTENUMPROC) EnumTTFontProc,
  320. (LPARAM) &EnumData);
  321. if (iResult == 0 || EnumData.dwCount != pUiData->dwTTFontItem)
  322. {
  323. ERR(("Inconsistent number of TrueType fonts\n"));
  324. iResult = 0;
  325. }
  326. else
  327. {
  328. //
  329. // Sort the TrueType font items alphabetically
  330. //
  331. qsort(pUiData->pTTFontItems,
  332. pUiData->dwTTFontItem,
  333. sizeof(OPTITEM),
  334. ICompareOptItem);
  335. }
  336. }
  337. }
  338. DeleteDC(hdc);
  339. if (iResult == 0)
  340. {
  341. ERR(("Failed to enumerate TrueType fonts\n"));
  342. return FALSE;
  343. }
  344. pUiData->dwTTFontItem = EnumData.dwCount;
  345. pUiData->dwOptItem += pUiData->dwTTFontItem;
  346. if (pUiData->pOptItem)
  347. {
  348. pUiData->pOptItem += pUiData->dwTTFontItem;
  349. VSetupTrueTypeFontMappings(pUiData);
  350. }
  351. return TRUE;
  352. }
  353. DWORD
  354. DwCollectTrueTypeMappings(
  355. IN POPTITEM pOptItem,
  356. IN DWORD dwOptItem,
  357. OUT PWSTR pwstrTable
  358. )
  359. /*++
  360. Routine Description:
  361. Assemble TrueType to device font mappings into a table
  362. Arguments:
  363. pOptItem - Pointer to an array of OPTITEMs
  364. cOptItem - Number of OPTITEMs
  365. pwstrTable - Pointer to memory buffer for storing the table.
  366. NULL if we're only interested in table size.
  367. Return Value:
  368. Size of the table bytes, 0 if there is an error.
  369. --*/
  370. {
  371. DWORD dwChars = 0;
  372. INT iLength;
  373. POPTPARAM pOptParam;
  374. while (dwOptItem--)
  375. {
  376. ASSERT(ISFONTSUBSTITEM(pOptItem->UserData));
  377. if (pOptItem->Sel > 0)
  378. {
  379. iLength = wcslen(pOptItem->pName) + 1;
  380. dwChars += iLength;
  381. if (pwstrTable != NULL)
  382. {
  383. CopyMemory(pwstrTable, pOptItem->pName, iLength*sizeof(WCHAR));
  384. pwstrTable += iLength;
  385. }
  386. pOptParam = pOptItem->pOptType->pOptParam + pOptItem->Sel;
  387. iLength = wcslen(pOptParam->pData) + 1;
  388. dwChars += iLength;
  389. if (pwstrTable != NULL)
  390. {
  391. CopyMemory(pwstrTable, pOptParam->pData, iLength*sizeof(WCHAR));
  392. pwstrTable += iLength;
  393. }
  394. }
  395. pOptItem++;
  396. }
  397. //
  398. // Append a NUL character at the end of the table
  399. //
  400. dwChars++;
  401. if (pwstrTable != NULL)
  402. *pwstrTable = NUL;
  403. //
  404. // Return the table size in bytes
  405. //
  406. return dwChars * sizeof(WCHAR);
  407. }
  408. BOOL
  409. BUnpackItemFontSubstTable(
  410. IN PUIDATA pUiData
  411. )
  412. /*++
  413. Routine Description:
  414. Extract substitution table from treeview items
  415. Arguments:
  416. pUiData - Pointer to UIDATA structure
  417. Return Value:
  418. TRUE if successful, FALSE otherwise
  419. --*/
  420. {
  421. DWORD dwTableSize;
  422. PWSTR pwstrTable = NULL;
  423. POPTITEM pOptItem = pUiData->pTTFontItems;
  424. DWORD dwOptItem = pUiData->dwTTFontItem;
  425. //
  426. // Check if any changes were made to font-substitution items
  427. //
  428. if (! BOptItemSelectionsChanged(pOptItem, dwOptItem))
  429. return TRUE;
  430. //
  431. // Figure out how much memory we need to save the font substitution table
  432. // Assemble the font substitution table
  433. // Save the TrueType font substitution table to registry
  434. //
  435. if ((dwTableSize = DwCollectTrueTypeMappings(pOptItem, dwOptItem, NULL)) == 0 ||
  436. (pwstrTable = MemAlloc(dwTableSize)) == NULL ||
  437. (dwTableSize != DwCollectTrueTypeMappings(pOptItem, dwOptItem, pwstrTable)) ||
  438. !BSaveTTSubstTable(pUiData->ci.hPrinter, pwstrTable, dwTableSize))
  439. {
  440. ERR(("Couldn't save font substitution table\n"));
  441. MemFree(pwstrTable);
  442. return FALSE;
  443. }
  444. MemFree(pwstrTable);
  445. return TRUE;
  446. }