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.

492 lines
14 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: fontsub.cxx
  3. *
  4. * Support for the [FontSubstitutes] section of WIN.INI (new functionality
  5. * from Windows 3.1).
  6. *
  7. * Copyright (c) 1990-1999 Microsoft Corporation
  8. *
  9. \**************************************************************************/
  10. // In Windows 3.1, there is a [FontSubstitutes] section that allows
  11. // face names in LOGFONTs to match other facenames.
  12. //
  13. // For example,
  14. //
  15. // [FontSubstitutes]
  16. // Helv=MS Sans Serif
  17. //
  18. // means that a LOGFONT with a lfFacename of "Helv" will match a physical
  19. // font with a facename of either "Helv" or "MS Sans Serif". That is,
  20. // "Helv" has an alternate match (or substitute match) of "MS Sans Serif".
  21. //
  22. // In Win 3.1, the standard "Helv" and "Tms Rmn" faces have been replaced
  23. // with "MS Sans Serif" and "MS Serif", respectively. This substitution
  24. // capability provides Win 3.1 with Win 3.0 compatibility for apps that
  25. // use the old name convention.
  26. #include "precomp.hxx"
  27. #include "winuserp.h"
  28. extern "C" VOID vInitFontSubTable();
  29. extern "C" NTSTATUS QueryRegistryFontSubstituteListRoutine(
  30. PWSTR,ULONG,PVOID,ULONG,PVOID,PVOID);
  31. #pragma alloc_text(INIT, vInitFontSubTable)
  32. #pragma alloc_text(INIT, QueryRegistryFontSubstituteListRoutine)
  33. // #define DBG 1
  34. #if DBG
  35. VOID DbgPrintFontSubstitutes();
  36. #endif
  37. // This is a global reference to the font substitution table. If the table
  38. // is not initialized properly, then this is NULL and should not be
  39. // dereferenced.
  40. PFONTSUB gpfsTable = NULL;;
  41. // Set the initial as 1 for we need to hack for Notes R5
  42. COUNT gcfsTable = 0;
  43. // count of valid entries of the form face1,ch1=face2,ch2
  44. COUNT gcfsCharSetTable = 0;
  45. BOOL gbShellFontCompatible = FALSE;
  46. /******************************Public*Routine******************************\
  47. *
  48. * PWSTR pwszFindComma(PWSTR pwszInput)
  49. *
  50. *
  51. * Effects: return the pointer to the charset string which is
  52. * starting immediately after the comma or if no comma is found,
  53. * return NULL
  54. *
  55. * History:
  56. * 27-Jun-1995 -by- Bodin Dresevic [BodinD]
  57. * Wrote it.
  58. \**************************************************************************/
  59. static
  60. const WCHAR * pwszFindComma(const WCHAR * pwszInput)
  61. {
  62. const WCHAR * pwszEnd = pwszInput + LF_FACESIZE;
  63. for (; (*pwszInput != L'\0') && (pwszInput < pwszEnd); pwszInput++)
  64. {
  65. if (*pwszInput == L',')
  66. return (++pwszInput);
  67. }
  68. return NULL;
  69. }
  70. extern "C"
  71. VOID vCheckCharSet(FACE_CHARSET *pfcs, const WCHAR * pwsz); // in mapfile.c
  72. /******************************Public*Routine******************************\
  73. *
  74. * VOID vProcessEntry
  75. *
  76. *
  77. * Effects: given value name string (or value data string)
  78. * produce face name string and charset
  79. *
  80. * History:
  81. * 28-Jun-1995 -by- Bodin Dresevic [BodinD]
  82. * Wrote it.
  83. \**************************************************************************/
  84. static
  85. HRESULT vProcessEntry(const WCHAR * pwszIn, FACE_CHARSET *pfcs, WCHAR * pwszOriginal)
  86. {
  87. const WCHAR * pwszCharSet;
  88. INT cwc;
  89. // now is the time to see if this is one of the entries of the form
  90. // Face1=Face2 (old format), or if this is one of the new entries of the form:
  91. // Face1,charset1=Face2,charset2.
  92. if (pwszCharSet = pwszFindComma(pwszIn))
  93. {
  94. //Sundown: cwc is within range of LF_FASESIZE which is 32
  95. // safe to truncate
  96. cwc = (INT)(pwszCharSet - pwszIn);
  97. // now need to produce and validate charset number from the string
  98. // that follows the comma
  99. vCheckCharSet(pfcs, pwszCharSet);
  100. }
  101. else
  102. {
  103. // mark the field as being left unspecified. In mapping this means
  104. // do not replace lfCharSet in the logfont when trying the alternate
  105. // name. In enumeration this means that this field should not be
  106. // taken into account
  107. cwc = LF_FACESIZE;
  108. pfcs->jCharSet = DEFAULT_CHARSET;
  109. pfcs->fjFlags = FJ_NOTSPECIFIED;
  110. }
  111. // now write the string
  112. cCapString(pfcs->awch, pwszIn, cwc);
  113. // finally save the original facename which is not necessarrily capitalized
  114. HRESULT hr = S_OK;
  115. if (pwszOriginal)
  116. {
  117. if (pwszCharSet)
  118. {
  119. cwc--;
  120. RtlMoveMemory(pwszOriginal, pwszIn, cwc * sizeof(WCHAR));
  121. pwszOriginal[cwc] = L'\0';
  122. }
  123. else
  124. {
  125. hr = StringCchCopyW(pwszOriginal, cwc, pwszIn);
  126. }
  127. }
  128. return hr;
  129. }
  130. extern "C"
  131. NTSTATUS
  132. QueryRegistryFontSubstituteListRoutine
  133. (
  134. PWSTR ValueName,
  135. ULONG ValueType,
  136. PVOID ValueData,
  137. ULONG ValueLength,
  138. PVOID Context,
  139. PVOID EntryContext
  140. )
  141. {
  142. PBYTE pjBuffer;
  143. FONTSUB fs;
  144. if (FAILED(vProcessEntry((const WCHAR *) ValueData, &fs.fcsAltFace, NULL)) ||
  145. FAILED(vProcessEntry(ValueName, &fs.fcsFace, fs.awchOriginal)))
  146. {
  147. WARNING("Ignoring invalid font substitute entry\n");
  148. return STATUS_SUCCESS;
  149. }
  150. // the following check eliminates the garbage entries that may have possibly
  151. // been entered in win.ini in the font substitution section
  152. if
  153. (
  154. (fs.fcsFace.fjFlags == fs.fcsAltFace.fjFlags)
  155. &&
  156. (fs.fcsFace.fjFlags != FJ_GARBAGECHARSET)
  157. )
  158. {
  159. pjBuffer = (PBYTE) PALLOCMEM((gcfsTable+1) * sizeof(FONTSUB),'bsfG');
  160. if (pjBuffer)
  161. {
  162. if (gpfsTable)
  163. {
  164. RtlMoveMemory(pjBuffer,
  165. gpfsTable,
  166. gcfsTable * sizeof(FONTSUB));
  167. VFREEMEM(gpfsTable);
  168. }
  169. gpfsTable = (PFONTSUB) pjBuffer;
  170. // copy new data that we have verified to be valid
  171. gpfsTable[gcfsTable] = fs;
  172. gcfsTable++;
  173. if (!fs.fcsFace.fjFlags) // if charset is specified
  174. gcfsCharSetTable++;
  175. if (!gbShellFontCompatible &&
  176. ! _wcsicmp(fs.fcsFace.awch, L"MS Shell Dlg") &&
  177. ! _wcsicmp(fs.fcsAltFace.awch, L"Microsoft Sans Serif")
  178. )
  179. gbShellFontCompatible = TRUE;
  180. }
  181. else
  182. {
  183. // we do not have enough memory - return failiure
  184. return STATUS_NO_MEMORY;
  185. }
  186. }
  187. return STATUS_SUCCESS;
  188. }
  189. /******************************Public*Routine******************************\
  190. * vInitFontSubTable
  191. *
  192. * Initializes the font substitutes table from data in the [FontSubstitutes]
  193. * section of the WIN.INI file. No error return code is provided since, if
  194. * this is not successful, then the table simply will not exist and the
  195. * global pointer to the table will remain NULL.
  196. *
  197. \**************************************************************************/
  198. extern "C" VOID vInitFontSubTable()
  199. {
  200. RTL_QUERY_REGISTRY_TABLE QueryTable[2];
  201. NTSTATUS Status;
  202. QueryTable[0].QueryRoutine = QueryRegistryFontSubstituteListRoutine;
  203. QueryTable[0].Flags = 0;
  204. QueryTable[0].Name = NULL;
  205. QueryTable[0].EntryContext = NULL;
  206. QueryTable[0].DefaultType = REG_NONE;
  207. QueryTable[0].DefaultData = NULL;
  208. QueryTable[0].DefaultLength = 0;
  209. QueryTable[1].QueryRoutine = NULL;
  210. QueryTable[1].Flags = 0;
  211. QueryTable[1].Name = NULL;
  212. //
  213. // Initialize to an empty table
  214. //
  215. gpfsTable = (PFONTSUB) NULL;
  216. gcfsTable = 1;
  217. gcfsCharSetTable = 0;
  218. Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT,
  219. L"FontSubstitutes",
  220. &QueryTable[0],
  221. NULL,
  222. NULL);
  223. if (!NT_SUCCESS(Status))
  224. {
  225. WARNING("Failiure to get font list\n");
  226. }
  227. // by now, the substitution table should exist already, if not because there is nothing in the
  228. // registry for instance, then we allocate it now and fill the first entry.
  229. if (!gpfsTable)
  230. {
  231. gpfsTable = (PFONTSUB) PALLOCMEM(gcfsTable * sizeof(FONTSUB),'bsfG');
  232. }
  233. if (gpfsTable)
  234. {
  235. const static WCHAR Default_Sans_Serif[] = L"Default Sans Serif";
  236. const static WCHAR DEFAULT_SANS_SERIF[] = L"DEFAULT SANS SERIF";
  237. const static WCHAR MS_SANS_SERIF[] = L"MS SANS SERIF";
  238. C_ASSERT(sizeof(gpfsTable->awchOriginal) >= sizeof(Default_Sans_Serif));
  239. C_ASSERT(sizeof(gpfsTable->fcsFace.awch) >= sizeof(DEFAULT_SANS_SERIF));
  240. C_ASSERT(sizeof(gpfsTable->fcsAltFace.awch) >= sizeof(MS_SANS_SERIF));
  241. RtlCopyMemory(gpfsTable->awchOriginal, Default_Sans_Serif, sizeof(Default_Sans_Serif));
  242. RtlCopyMemory(gpfsTable->fcsFace.awch, DEFAULT_SANS_SERIF, sizeof(DEFAULT_SANS_SERIF));
  243. RtlCopyMemory(gpfsTable->fcsAltFace.awch, MS_SANS_SERIF, sizeof(MS_SANS_SERIF));
  244. gpfsTable->fcsFace.jCharSet = DEFAULT_CHARSET;
  245. gpfsTable->fcsFace.fjFlags = FJ_NOTSPECIFIED;
  246. gpfsTable->fcsAltFace.jCharSet = DEFAULT_CHARSET;
  247. gpfsTable->fcsAltFace.fjFlags = FJ_NOTSPECIFIED;
  248. }
  249. else
  250. {
  251. gcfsTable = 0;
  252. }
  253. #if 0 // don't want to do this any more
  254. DbgPrintFontSubstitutes();
  255. #endif
  256. }
  257. /******************************Public*Routine******************************\
  258. * pfsubAlternateFacename
  259. *
  260. * Search the font substitutes table for an alternative facename for the
  261. * given facename.
  262. *
  263. * Return:
  264. * Pointer to alt facename, NULL if not found.
  265. *
  266. * History:
  267. * 28-Jan-1992 -by- Gilman Wong [gilmanw]
  268. * Wrote it.
  269. \**************************************************************************/
  270. PFONTSUB pfsubAlternateFacename (
  271. const WCHAR * pwchFacename
  272. )
  273. {
  274. PFONTSUB pfs = gpfsTable;
  275. PFONTSUB pfsEnd = gpfsTable + gcfsTable;
  276. WCHAR awchCapName[LF_FACESIZE];
  277. // Want case insensitive search, so capitalize the name.
  278. cCapString(awchCapName, pwchFacename, LF_FACESIZE);
  279. // Scan through the font substitution table for the key string.
  280. for (; pfs < pfsEnd; pfs++)
  281. {
  282. if
  283. (
  284. !wcscmp(awchCapName,pfs->fcsFace.awch) &&
  285. ((pfs->fcsFace.fjFlags & FJ_NOTSPECIFIED) || (pfs->fcsFace.jCharSet == pfs->fcsAltFace.jCharSet))
  286. )
  287. {
  288. // This routine is only used in font enumeration when facename of
  289. // the fonts that are wished to be enumerated is specified as input.
  290. // We only want to enumerate the correct charsets, that is those that
  291. // are specified on the right hand side (if they are specified at all)
  292. if (pfs == gpfsTable)
  293. {
  294. // check the compatibility flag.
  295. if (GetAppCompatFlags2(VER40) & GACF2_FONTSUB)
  296. return pfs;
  297. }
  298. else
  299. return pfs;
  300. }
  301. }
  302. // Nothing found, so return NULL.
  303. return NULL;
  304. }
  305. /******************************Public*Routine******************************\
  306. *
  307. * pfsubGetFontSub
  308. *
  309. * Effects:
  310. *
  311. * Warnings:
  312. *
  313. * History:
  314. * 05-Feb-1997 -by- Bodin Dresevic [BodinD]
  315. * Wrote it.
  316. \**************************************************************************/
  317. FONTSUB * pfsubGetFontSub (
  318. const WCHAR * pwchFacename, // face name specified in logfont
  319. BYTE lfCharset // charset specified in logfont
  320. )
  321. {
  322. PFONTSUB pfs = gpfsTable;
  323. PFONTSUB pfsEnd = gpfsTable + gcfsTable;
  324. WCHAR awchCapName[LF_FACESIZE];
  325. // We will set pfsNameOnly to point to a pfsub entry if for this entry
  326. // the charset is NOT specified and the facename maches the facename
  327. // from the logfont. That is pfsNameOnly can only point to an old style
  328. // substitution of the form facename1=facename2.
  329. PFONTSUB pfsNameOnly = NULL;
  330. // We will set pfsNameAndCharset to point to a pfsub entry if for this entry
  331. // the charset IS specified and both facename and charset match.
  332. // If both pfsNameAndCharset and pfsNameOnly are nonzero after going through
  333. // the font substitution list, we will return pfsNameAndCharset from
  334. // the function. For example, font substitution table for the Russian locale
  335. // on win95 may have all three of the following entries:
  336. //
  337. // Times=Times New Roman // old style value
  338. // Times,204=Times New Roman,204
  339. // Times,0=Times New Roman,204
  340. //
  341. // Thus if the application specifies Times,0 or Times,204 in the logfont,
  342. // Times New Roman,204 will be used. If the application asks for Times,161
  343. // it will get Times New Roman,161.
  344. PFONTSUB pfsNameAndCharset = NULL;
  345. // Want case insensitive search, so capitalize the name.
  346. cCapString(awchCapName, pwchFacename, LF_FACESIZE);
  347. // Scan through the font substitution table for the key string.
  348. for (; pfs < pfsEnd; pfs++)
  349. {
  350. // Do wcscmp inline for speed:
  351. if (!wcscmp(awchCapName,pfs->fcsFace.awch))
  352. {
  353. // we found a facename match, check if we should match charset
  354. if (pfs == gpfsTable)
  355. {
  356. // check the compatibility flag.
  357. if (GetAppCompatFlags2(VER40) & GACF2_FONTSUB)
  358. {
  359. pfsNameOnly = pfs;
  360. break;
  361. }
  362. }
  363. else
  364. {
  365. if (pfs->fcsFace.fjFlags & FJ_NOTSPECIFIED)
  366. {
  367. pfsNameOnly = pfs;
  368. }
  369. else // charset is specified, now see if it matches the logfont
  370. {
  371. if (lfCharset == pfs->fcsFace.jCharSet)
  372. pfsNameAndCharset = pfs;
  373. }
  374. }
  375. }
  376. }
  377. return (pfsNameAndCharset ? pfsNameAndCharset : pfsNameOnly);
  378. }
  379. #if DBG
  380. VOID DbgPrintFontSubstitutes()
  381. {
  382. PFONTSUB pfs = gpfsTable;
  383. PFONTSUB pfsEnd = gpfsTable + gcfsTable;
  384. //
  385. // Scan through the font substitution table for the key string.
  386. //
  387. KdPrint(("[FontSubstitutes]\n"));
  388. for (; pfs < pfsEnd; pfs++)
  389. KdPrint(("\t%ws: %ws, %d, fj=0x%x = %ws, %d, fj=0x%x \n",
  390. pfs->awchOriginal,
  391. pfs->fcsFace.awch,
  392. (USHORT)pfs->fcsFace.jCharSet,
  393. (USHORT)pfs->fcsFace.fjFlags,
  394. pfs->fcsAltFace.awch,
  395. (USHORT)pfs->fcsAltFace.jCharSet,
  396. (USHORT)pfs->fcsAltFace.fjFlags
  397. ));
  398. }
  399. #endif