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.

1366 lines
38 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 2000 Microsoft Corporation
  4. *
  5. * Abstract:
  6. *
  7. * Font linking handling
  8. *
  9. * Revision History:
  10. *
  11. * 3/03/2000 Tarek Mahmoud Sayed
  12. * Created it.
  13. *
  14. \**************************************************************************/
  15. #include "precomp.hpp"
  16. static const WCHAR FontLinkKeyW[] =
  17. L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink";
  18. static const WCHAR FontSubstitutesKeyW[] =
  19. L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes";
  20. static const WCHAR EudcKeyW[]=L"EUDC\\";
  21. static const char EudcKeyA[]= "EUDC\\";
  22. static const char WinIniFontSubstitutionSectionName[] = "FontSubstitutes";
  23. /**************************************************************************\
  24. *
  25. * Function Description:
  26. * Font Linking constructor.
  27. * caches the font linking and EUDC from the registry.
  28. *
  29. *
  30. * Arguments:
  31. *
  32. * Returns:
  33. *
  34. *
  35. * History:
  36. *
  37. * 3/3/2000 Tarek Mahmoud Sayed
  38. * Created it.
  39. *
  40. \**************************************************************************/
  41. GpFontLink::GpFontLink():
  42. DefaultFamily (NULL),
  43. linkedFonts (NULL),
  44. eudcCache (NULL),
  45. privateFonts (NULL),
  46. FontSubstitutionTable (NULL),
  47. substitutionCount (0)
  48. {
  49. // Before we cache the font linking and substitution data we need to
  50. // make sure we loaded the font table data.
  51. GpFontTable *fontTable = Globals::FontCollection->GetFontTable();
  52. if (!fontTable->IsValid())
  53. return;
  54. if (!fontTable->IsFontLoaded())
  55. fontTable->LoadAllFonts();
  56. if (Globals::IsNt)
  57. {
  58. GetFontLinkingDataFromRegistryW();
  59. GetEudcDataFromTheRegistryW();
  60. CacheFontSubstitutionDataW();
  61. }
  62. else
  63. {
  64. // There is no font linking in Win9x. and we don't support the font association
  65. // because it is for Ansi support and not Unicode.
  66. // we support the font substitution under win9x.
  67. GetEudcDataFromTheRegistryA();
  68. CacheFontSubstitutionDataA();
  69. }
  70. }
  71. /**************************************************************************\
  72. *
  73. * Function Description:
  74. *
  75. * If not already cached, create the default family to be used for font
  76. * that is not linked by default.
  77. *
  78. * o Search for the subtitution font of "MS Shell Dlg"
  79. * o Use the font the "MS Shell Dlg" substitution is linked to if exist
  80. * o If no "MS Shell Dlg" found, use the final font of the first fontlink
  81. * entry found if fontlinking is supported in the system.
  82. * o If not, lookup hardcoded UI font via system default ansi codepage.
  83. *
  84. * History:
  85. *
  86. * 4/19/2001 Worachai Chaoweeraprasit
  87. * Created it.
  88. *
  89. \**************************************************************************/
  90. const AssociatedFamilies *GpFontLink::GetDefaultFamily()
  91. {
  92. if (!DefaultFamily)
  93. {
  94. AssociatedFamilies *associated = NULL;
  95. GpFontFamily *family = GetFamilySubstitution(L"MS Shell Dlg");
  96. if (family)
  97. {
  98. associated = GetLinkedFonts(family);
  99. }
  100. else
  101. {
  102. // "MS Shell Dlg" not found,
  103. // try the first linking font found if one existed
  104. if (linkedFonts)
  105. {
  106. family = linkedFonts->family;
  107. associated = linkedFonts->associatedFamilies;
  108. }
  109. else
  110. {
  111. // No fontlinking supported in this machine. This is likely a Win9x system,
  112. // lookup default UI font via ACP.
  113. typedef struct
  114. {
  115. UINT AnsiCodepage;
  116. const WCHAR* FamilyName;
  117. } AssociatedUIFonts;
  118. static const UINT MaxEastAsianCodepages = 4;
  119. static const AssociatedUIFonts uiFonts[MaxEastAsianCodepages] =
  120. {
  121. { 932, L"MS UI Gothic" }, // Japanese
  122. { 949, L"Gulim" }, // Korean
  123. { 950, L"PMingLiu" }, // Traditional Chinese
  124. { 936, L"Simsun" } // Simplified Chinese
  125. };
  126. const WCHAR *familyName = NULL;
  127. for (UINT i = 0; i < MaxEastAsianCodepages; i++)
  128. {
  129. if (uiFonts[i].AnsiCodepage == Globals::ACP)
  130. {
  131. familyName = uiFonts[i].FamilyName;
  132. break;
  133. }
  134. }
  135. if (familyName)
  136. {
  137. GpFontTable *fontTable = Globals::FontCollection->GetFontTable();
  138. if (fontTable)
  139. {
  140. family = fontTable->GetFontFamily(familyName);
  141. }
  142. }
  143. }
  144. }
  145. if (family)
  146. {
  147. DefaultFamily = &DefaultFamilyBuffer;
  148. DefaultFamily->family = family;
  149. DefaultFamily->next = associated;
  150. }
  151. else
  152. {
  153. // Nothing we could use,
  154. // let's make sure we wouldnt try to cache it again.
  155. DefaultFamily = (AssociatedFamilies *)(-1);
  156. }
  157. }
  158. ASSERT(DefaultFamily != NULL);
  159. return (DefaultFamily && DefaultFamily != (AssociatedFamilies *)(-1)) ?
  160. DefaultFamily : NULL;
  161. }
  162. /**************************************************************************\
  163. *
  164. * Function Description:
  165. * Font linking destructor. it should be called when free theGDIPLUS library
  166. * it free all allocated data.
  167. *
  168. *
  169. * Arguments:
  170. *
  171. * Returns:
  172. *
  173. *
  174. * History:
  175. *
  176. * 3/3/2000 Tarek Mahmoud Sayed
  177. * Created it.
  178. *
  179. \**************************************************************************/
  180. GpFontLink::~GpFontLink()
  181. {
  182. FontLinkingFamily *tempFontLinkingFamily = linkedFonts;
  183. AssociatedFamilies *tempAssocFonts;
  184. PrivateLoadedFonts *loadedFontsList;
  185. while (linkedFonts != NULL)
  186. {
  187. while (linkedFonts->associatedFamilies != NULL)
  188. {
  189. tempAssocFonts = linkedFonts->associatedFamilies->next;
  190. GpFree(linkedFonts->associatedFamilies);
  191. linkedFonts->associatedFamilies = tempAssocFonts;
  192. }
  193. linkedFonts = linkedFonts->next;
  194. GpFree(tempFontLinkingFamily);
  195. tempFontLinkingFamily = linkedFonts;
  196. }
  197. if (eudcCache != NULL)
  198. {
  199. EUDCMAP *tempEUDCMapList;
  200. while (eudcCache->eudcMapList != NULL)
  201. {
  202. tempEUDCMapList = eudcCache->eudcMapList->next;
  203. GpFree(eudcCache->eudcMapList);
  204. eudcCache->eudcMapList = tempEUDCMapList;
  205. }
  206. GpFree(eudcCache);
  207. }
  208. while (privateFonts != NULL)
  209. {
  210. delete privateFonts->fontCollection;
  211. loadedFontsList = privateFonts;
  212. privateFonts = privateFonts->next;
  213. GpFree(loadedFontsList);
  214. }
  215. if (FontSubstitutionTable)
  216. {
  217. GpFree(FontSubstitutionTable);
  218. }
  219. }
  220. /**************************************************************************\
  221. *
  222. * Function Description:
  223. *
  224. * Read the font linking registry data for the NT
  225. *
  226. * Arguments:
  227. *
  228. * Returns:
  229. * nothing
  230. *
  231. * History:
  232. *
  233. * 3/3/2000 Tarek Mahmoud Sayed
  234. * Created it.
  235. *
  236. \**************************************************************************/
  237. void GpFontLink::GetFontLinkingDataFromRegistryW()
  238. {
  239. // Open the key
  240. HKEY hkey;
  241. ULONG index = 0;
  242. WCHAR subKey[MAX_PATH];
  243. DWORD allocatedDataSize= 2 * MAX_PATH;
  244. unsigned char *allocatedBuffer = NULL;
  245. DWORD subKeyLength ;
  246. DWORD RegDataLength ;
  247. LONG error = RegOpenKeyExW(
  248. HKEY_LOCAL_MACHINE,
  249. FontLinkKeyW,
  250. 0,
  251. KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
  252. &hkey);
  253. if (error == ERROR_SUCCESS)
  254. {
  255. allocatedBuffer = (unsigned char *) GpMalloc(allocatedDataSize);
  256. if (allocatedBuffer == NULL)
  257. {
  258. return;
  259. }
  260. while (error != ERROR_NO_MORE_ITEMS)
  261. {
  262. subKeyLength = MAX_PATH;
  263. RegDataLength = allocatedDataSize;
  264. error = RegEnumValueW(
  265. hkey,
  266. index,
  267. subKey,
  268. &subKeyLength,
  269. NULL,
  270. NULL,
  271. allocatedBuffer,
  272. &RegDataLength);
  273. if (error == ERROR_MORE_DATA)
  274. {
  275. allocatedDataSize *= 2;
  276. GpFree(allocatedBuffer);
  277. allocatedBuffer = (unsigned char *) GpMalloc(allocatedDataSize);
  278. if (allocatedBuffer == NULL)
  279. {
  280. RegCloseKey(hkey);
  281. return;
  282. }
  283. RegDataLength = allocatedDataSize;
  284. error = RegEnumValueW(
  285. hkey,
  286. index,
  287. subKey,
  288. &subKeyLength,
  289. NULL,
  290. NULL,
  291. allocatedBuffer,
  292. &RegDataLength);
  293. }
  294. if (error != ERROR_SUCCESS)
  295. {
  296. break;
  297. }
  298. index ++;
  299. // record current node.
  300. FontLinkingFamily *tempLinkedFonts;
  301. tempLinkedFonts =
  302. (FontLinkingFamily *) GpMalloc( sizeof (FontLinkingFamily) );
  303. if (tempLinkedFonts)
  304. {
  305. AssociatedFamilies * tailAssociatedFamilies = NULL;
  306. tempLinkedFonts->family =
  307. Globals::FontCollection->GetFontTable()->GetFontFamily(subKey);
  308. if (tempLinkedFonts->family == NULL)
  309. {
  310. GpFree(tempLinkedFonts);
  311. continue;
  312. }
  313. tempLinkedFonts->associatedFamilies = NULL;
  314. tempLinkedFonts->next = NULL;
  315. DWORD i = 0;
  316. WCHAR nextFontFile[MAX_PATH];
  317. WCHAR awcPath[MAX_PATH];
  318. DWORD charIndex = 0;
  319. UINT hash ;
  320. GpFontFile* fontFile;
  321. AssociatedFamilies *tempAssocFamilies;
  322. GpFontFamily *family;
  323. BOOL hasFontFileName = FALSE;
  324. RegDataLength /= 2;
  325. while (charIndex < RegDataLength)
  326. {
  327. if (((WCHAR *)allocatedBuffer)[charIndex] == 0x002C)
  328. {
  329. i = 0;
  330. hasFontFileName = TRUE;
  331. }
  332. else
  333. if (((WCHAR *)allocatedBuffer)[charIndex] == 0x0000)
  334. {
  335. if (i > 0)
  336. {
  337. nextFontFile[i] = 0x0;
  338. i = 0;
  339. if (hasFontFileName)
  340. {
  341. family = Globals::FontCollection->GetFontTable()->GetFontFamily(nextFontFile);
  342. hasFontFileName = FALSE;
  343. }
  344. else
  345. {
  346. family = NULL;
  347. INT j =0;
  348. WCHAR charNumber;
  349. if (MakePathName(awcPath, nextFontFile))
  350. {
  351. UnicodeStringToUpper(awcPath, awcPath);
  352. fontFile = Globals::FontCollection->GetFontTable()->GetFontFile(awcPath);
  353. if (fontFile != NULL)
  354. {
  355. family = Globals::FontCollection->GetFontTable()->GetFontFamily(fontFile->GetFamilyName(0));
  356. }
  357. else
  358. {
  359. fontFile = Globals::FontCollection->GetFontTable()->AddFontFile(awcPath);
  360. if (fontFile != NULL)
  361. {
  362. family = Globals::FontCollection->GetFontTable()->GetFontFamily(fontFile->GetFamilyName(0));
  363. }
  364. }
  365. }
  366. }
  367. if (family != NULL)
  368. {
  369. tempAssocFamilies = (AssociatedFamilies *) GpMalloc( sizeof (AssociatedFamilies) );
  370. if (tempAssocFamilies != NULL)
  371. {
  372. if (!tailAssociatedFamilies)
  373. {
  374. tempAssocFamilies->family = family;
  375. tempAssocFamilies->next = tempLinkedFonts->associatedFamilies;
  376. tempLinkedFonts->associatedFamilies = tempAssocFamilies;
  377. }
  378. else
  379. {
  380. tempAssocFamilies->family = family;
  381. tempAssocFamilies->next = NULL;
  382. tailAssociatedFamilies->next = tempAssocFamilies;
  383. }
  384. tailAssociatedFamilies = tempAssocFamilies;
  385. }
  386. }
  387. }
  388. }
  389. else // ! 0
  390. {
  391. nextFontFile[i] = ((WCHAR *)allocatedBuffer)[charIndex];
  392. i++;
  393. }
  394. charIndex++;
  395. }
  396. tempLinkedFonts->next = linkedFonts;
  397. linkedFonts = tempLinkedFonts;
  398. }
  399. }
  400. if (allocatedBuffer != NULL)
  401. {
  402. GpFree(allocatedBuffer);
  403. }
  404. RegCloseKey(hkey);
  405. }
  406. return;
  407. }
  408. /**************************************************************************\
  409. *
  410. * Function Description:
  411. * return the linked list of all fonts linked to family
  412. *
  413. *
  414. * Arguments:
  415. * family[in] the original family
  416. *
  417. * Returns:
  418. * AssociatedFamilies* the linked list of the linked fonts
  419. *
  420. * History:
  421. *
  422. * 3/3/2000 Tarek Mahmoud Sayed
  423. * Created it.
  424. *
  425. \**************************************************************************/
  426. AssociatedFamilies* GpFontLink::GetLinkedFonts(const GpFontFamily *family)
  427. {
  428. GpFontFamily *linkedFamily;
  429. if (family->IsPrivate())
  430. {
  431. WCHAR name[LF_FACESIZE];
  432. if (family->GetFamilyName(name) != Ok)
  433. {
  434. return NULL;
  435. }
  436. GpInstalledFontCollection *gpFontCollection = GpInstalledFontCollection::GetGpInstalledFontCollection();
  437. if (gpFontCollection == NULL)
  438. {
  439. return NULL;
  440. }
  441. GpFontTable *fontTable = gpFontCollection->GetFontTable();
  442. if (fontTable == NULL)
  443. {
  444. return NULL;
  445. }
  446. linkedFamily = fontTable->GetFontFamily(name);
  447. if (linkedFamily == NULL)
  448. {
  449. return NULL;
  450. }
  451. }
  452. else
  453. {
  454. linkedFamily = (GpFontFamily *) family;
  455. }
  456. FontLinkingFamily *currentFontLink = linkedFonts;
  457. while (currentFontLink != NULL)
  458. {
  459. if (currentFontLink->family == linkedFamily)
  460. {
  461. return currentFontLink->associatedFamilies;
  462. }
  463. currentFontLink = currentFontLink->next;
  464. }
  465. return NULL;
  466. }
  467. /**************************************************************************\
  468. *
  469. * Function Description:
  470. * caches EUDC data from the registry
  471. *
  472. *
  473. * Arguments:
  474. *
  475. * Returns:
  476. *
  477. *
  478. * History:
  479. *
  480. * 3/3/2000 Tarek Mahmoud Sayed
  481. * Created it.
  482. *
  483. \**************************************************************************/
  484. void GpFontLink::GetEudcDataFromTheRegistryW()
  485. {
  486. eudcCache = (EUDC *) GpMalloc(sizeof(EUDC));
  487. if (eudcCache == NULL)
  488. {
  489. return;
  490. }
  491. eudcCache->defaultFamily = NULL;
  492. eudcCache->eudcMapList = NULL;
  493. WCHAR tempString[MAX_PATH];
  494. INT i = 0;
  495. while ( EudcKeyW[i] != 0x0000)
  496. {
  497. tempString[i] = EudcKeyW[i];
  498. i++;
  499. }
  500. INT j = 0;
  501. WCHAR acpString[5];
  502. UINT acp = GetACP();
  503. while (j < 5 && acp > 0)
  504. {
  505. acpString[j] = (acp % 10) + 0x0030;
  506. acp /= 10;
  507. j++;
  508. }
  509. j--;
  510. while (j>=0)
  511. {
  512. tempString[i] = acpString[j];
  513. i++;
  514. j--;
  515. }
  516. tempString[i] = 0x0;
  517. HKEY hkey = NULL;
  518. ULONG index = 0;
  519. LONG error = RegOpenKeyExW(
  520. HKEY_CURRENT_USER,
  521. tempString,
  522. 0,
  523. KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
  524. &hkey);
  525. WCHAR subKey[MAX_PATH];
  526. DWORD subKeyLength ;
  527. DWORD RegDataLength ;
  528. GpFontFamily *family;
  529. GpFontFamily *linkedfamily;
  530. EUDCMAP *eudcMap;
  531. BOOL isDefaultNotCached = TRUE;
  532. while (error == ERROR_SUCCESS)
  533. {
  534. subKeyLength = MAX_PATH;
  535. RegDataLength = MAX_PATH;
  536. error = RegEnumValueW(hkey,
  537. index,
  538. subKey,
  539. &subKeyLength,
  540. NULL,
  541. NULL,
  542. (unsigned char *) tempString,
  543. &RegDataLength);
  544. if (error == ERROR_SUCCESS)
  545. {
  546. if (isDefaultNotCached && UnicodeStringCompareCI(subKey, L"SystemDefaultEUDCFont") == 0)
  547. {
  548. isDefaultNotCached = FALSE;
  549. family = CheckAndLoadTheFile(tempString);
  550. if (family != NULL)
  551. {
  552. eudcCache->defaultFamily = family;
  553. }
  554. }
  555. else
  556. {
  557. family = Globals::FontCollection->GetFontTable()->GetFontFamily(subKey);
  558. if (family != NULL)
  559. {
  560. linkedfamily = CheckAndLoadTheFile(tempString);
  561. if (linkedfamily != NULL)
  562. {
  563. eudcMap = (EUDCMAP *) GpMalloc(sizeof(EUDCMAP));
  564. if (eudcMap != NULL)
  565. {
  566. eudcMap->inputFamily = family;
  567. eudcMap->eudcFamily = linkedfamily;
  568. if (eudcCache->eudcMapList == NULL)
  569. {
  570. eudcCache->eudcMapList = eudcMap;
  571. eudcMap->next = NULL;
  572. }
  573. else
  574. {
  575. eudcMap->next = eudcCache->eudcMapList;
  576. eudcCache->eudcMapList = eudcMap;
  577. }
  578. }
  579. }
  580. }
  581. }
  582. }
  583. index++;
  584. }
  585. if (hkey != NULL)
  586. {
  587. RegCloseKey(hkey);
  588. }
  589. return;
  590. }
  591. /**************************************************************************\
  592. *
  593. * Function Description:
  594. * caches EUDC data from the registry
  595. *
  596. *
  597. * Arguments:
  598. *
  599. * Returns:
  600. *
  601. *
  602. * History:
  603. *
  604. * 3/3/2000 Tarek Mahmoud Sayed
  605. * Created it.
  606. *
  607. \**************************************************************************/
  608. void GpFontLink::GetEudcDataFromTheRegistryA()
  609. {
  610. eudcCache = (EUDC *) GpMalloc(sizeof(EUDC));
  611. if (eudcCache == NULL)
  612. {
  613. return;
  614. }
  615. eudcCache->defaultFamily = NULL;
  616. eudcCache->eudcMapList = NULL;
  617. char tempStringA[MAX_PATH];
  618. WCHAR tempString[MAX_PATH];
  619. INT i = 0;
  620. while ( EudcKeyA[i] != 0x00)
  621. {
  622. tempStringA[i] = EudcKeyA[i];
  623. i++;
  624. }
  625. INT j = 0;
  626. char acpString[5];
  627. UINT acp = GetACP();
  628. while (j < 5 && acp > 0)
  629. {
  630. acpString[j] = (acp % 10) + 0x30;
  631. acp /= 10;
  632. j++;
  633. }
  634. j--;
  635. while (j>=0)
  636. {
  637. tempStringA[i] = acpString[j];
  638. i++;
  639. j--;
  640. }
  641. tempStringA[i] = 0x0;
  642. HKEY hkey = NULL;
  643. ULONG index = 0;
  644. LONG error = RegOpenKeyExA(
  645. HKEY_CURRENT_USER,
  646. tempStringA,
  647. 0,
  648. KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
  649. &hkey);
  650. WCHAR subKey[MAX_PATH];
  651. char subKeyA[MAX_PATH];
  652. DWORD subKeyLength ;
  653. DWORD RegDataLength ;
  654. GpFontFamily *family;
  655. GpFontFamily *linkedfamily;
  656. EUDCMAP *eudcMap;
  657. BOOL isDefaultNotCached = TRUE;
  658. while (error == ERROR_SUCCESS)
  659. {
  660. subKeyLength = MAX_PATH;
  661. RegDataLength = MAX_PATH;
  662. error = RegEnumValueA(
  663. hkey,
  664. index,
  665. subKeyA,
  666. &subKeyLength,
  667. NULL,
  668. NULL,
  669. (unsigned char *) tempStringA,
  670. &RegDataLength);
  671. if (error == ERROR_SUCCESS)
  672. {
  673. if (!AnsiToUnicodeStr(
  674. subKeyA,
  675. subKey,
  676. MAX_PATH) ||
  677. !AnsiToUnicodeStr(
  678. tempStringA,
  679. tempString,
  680. MAX_PATH))
  681. continue;
  682. if (isDefaultNotCached && UnicodeStringCompareCI(subKey, L"SystemDefaultEUDCFont") == 0)
  683. {
  684. isDefaultNotCached = FALSE;
  685. family = CheckAndLoadTheFile(tempString);
  686. if (family != NULL)
  687. {
  688. eudcCache->defaultFamily = family;
  689. }
  690. }
  691. else
  692. {
  693. family = Globals::FontCollection->GetFontTable()->GetFontFamily(subKey);
  694. if (family != NULL)
  695. {
  696. linkedfamily = CheckAndLoadTheFile(tempString);
  697. if (linkedfamily != NULL)
  698. {
  699. eudcMap = (EUDCMAP *) GpMalloc(sizeof(EUDCMAP));
  700. if (eudcMap != NULL)
  701. {
  702. eudcMap->inputFamily = family;
  703. eudcMap->eudcFamily = linkedfamily;
  704. if (eudcCache->eudcMapList == NULL)
  705. {
  706. eudcCache->eudcMapList = eudcMap;
  707. eudcMap->next = NULL;
  708. }
  709. else
  710. {
  711. eudcMap->next = eudcCache->eudcMapList;
  712. eudcCache->eudcMapList = eudcMap;
  713. }
  714. }
  715. }
  716. }
  717. }
  718. }
  719. index++;
  720. }
  721. if (hkey != NULL)
  722. {
  723. RegCloseKey(hkey);
  724. }
  725. return;
  726. }
  727. /**************************************************************************\
  728. *
  729. * Function Description:
  730. * check if the font file name is loaded,
  731. * and load it if it is not loaded before.
  732. *
  733. *
  734. * Arguments:
  735. * fileName[In] font file name
  736. *
  737. * Returns:
  738. * GpFontFamily* the family object for that font
  739. *
  740. * History:
  741. *
  742. * 3/3/2000 Tarek Mahmoud Sayed
  743. * Created it.
  744. *
  745. \**************************************************************************/
  746. GpFontFamily* GpFontLink::CheckAndLoadTheFile(WCHAR *fileName)
  747. {
  748. WCHAR awcPath[MAX_PATH];
  749. UINT hash ;
  750. GpFontFamily *family = NULL;
  751. GpFontFile *fontFile;
  752. GpFontTable *fontTable;
  753. if (MakePathName(awcPath, fileName))
  754. {
  755. PrivateLoadedFonts *currentCell = privateFonts;
  756. while (currentCell != NULL)
  757. {
  758. if ( UnicodeStringCompareCI(fileName, currentCell->FileName) == 0 )
  759. {
  760. fontTable = currentCell->fontCollection->GetFontTable();
  761. fontFile = fontTable->GetFontFile(awcPath);
  762. if (fontFile)
  763. {
  764. family = fontTable->GetFontFamily(fontFile->GetFamilyName(0));
  765. };
  766. break;
  767. }
  768. else
  769. {
  770. currentCell = currentCell->next;
  771. }
  772. }
  773. if (family == NULL)
  774. {
  775. GpPrivateFontCollection *privateFontCollection = new GpPrivateFontCollection();
  776. if (privateFontCollection != NULL)
  777. {
  778. if (privateFontCollection->AddFontFile(awcPath) == Ok)
  779. {
  780. fontTable = privateFontCollection->GetFontTable();
  781. fontFile = fontTable->GetFontFile(awcPath);
  782. if (fontFile != NULL)
  783. {
  784. family = fontTable->GetFontFamily(fontFile->GetFamilyName(0));
  785. PrivateLoadedFonts *tempLoadedFonts = (PrivateLoadedFonts *) GpMalloc(sizeof(PrivateLoadedFonts));
  786. if (tempLoadedFonts != NULL)
  787. {
  788. tempLoadedFonts->fontCollection = privateFontCollection;
  789. UnicodeStringCopy(tempLoadedFonts->FileName, fileName);
  790. tempLoadedFonts->next = privateFonts;
  791. privateFonts = tempLoadedFonts;
  792. }
  793. else
  794. {
  795. delete privateFontCollection;
  796. }
  797. }
  798. else
  799. {
  800. delete privateFontCollection;
  801. }
  802. }
  803. else
  804. {
  805. delete privateFontCollection;
  806. }
  807. }
  808. }
  809. }
  810. return family;
  811. }
  812. /**************************************************************************\
  813. *
  814. * Function Description:
  815. * return the default family used as fallback for the EUDC
  816. *
  817. *
  818. * Arguments:
  819. *
  820. * Returns:
  821. * GpFontFamily* the family of the EUDC font
  822. *
  823. * History:
  824. *
  825. * 3/3/2000 Tarek Mahmoud Sayed
  826. * Created it.
  827. *
  828. \**************************************************************************/
  829. GpFontFamily *GpFontLink::GetDefaultEUDCFamily()
  830. {
  831. if (eudcCache != NULL)
  832. {
  833. return eudcCache->defaultFamily;
  834. }
  835. return NULL;
  836. }
  837. /**************************************************************************\
  838. *
  839. * Function Description:
  840. * return the family of the EUDC font mapped from the font family
  841. *
  842. * Arguments:
  843. * family[In] original font family
  844. *
  845. * Returns:
  846. * GpFontFamily* the family of the EUDC font
  847. *
  848. * History:
  849. *
  850. * 3/3/2000 Tarek Mahmoud Sayed
  851. * Created it.
  852. *
  853. \**************************************************************************/
  854. GpFontFamily *GpFontLink::GetMappedEUDCFamily(const GpFontFamily *family)
  855. {
  856. EUDCMAP *eudcMaping;
  857. if (eudcCache != NULL)
  858. {
  859. eudcMaping = eudcCache->eudcMapList;
  860. while (eudcMaping != NULL)
  861. {
  862. if (eudcMaping->inputFamily == family)
  863. {
  864. return eudcMaping->eudcFamily;
  865. }
  866. eudcMaping = eudcMaping->next;
  867. }
  868. }
  869. return NULL;
  870. }
  871. /**************************************************************************\
  872. *
  873. * Function Description:
  874. * Read and cache the font substitution data from the registry under
  875. * Windows NT
  876. *
  877. * Arguments:
  878. *
  879. * Returns:
  880. *
  881. * History:
  882. *
  883. * 4/12/2000 Tarek Mahmoud Sayed
  884. * Created it.
  885. *
  886. \**************************************************************************/
  887. void GpFontLink::CacheFontSubstitutionDataW()
  888. {
  889. HKEY hkey;
  890. // open this key for query and enumeration.
  891. LONG error = RegOpenKeyExW(
  892. HKEY_LOCAL_MACHINE,
  893. FontSubstitutesKeyW,
  894. 0,
  895. KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
  896. &hkey);
  897. if (error != ERROR_SUCCESS)
  898. {
  899. // failed to find these data in the registry.
  900. return;
  901. }
  902. DWORD numberOfValues = 0;
  903. error = RegQueryInfoKeyW(
  904. hkey, NULL, NULL, NULL, NULL, NULL, NULL, &numberOfValues,
  905. NULL, NULL, NULL, NULL);
  906. if (error != ERROR_SUCCESS || numberOfValues==0)
  907. {
  908. RegCloseKey(hkey);
  909. return;
  910. }
  911. // Now let's allocate for data.
  912. // we allocate memory enough to hold all font substitution data but might
  913. // not use all the allocated memory. I did that to just call the GpMalloc
  914. // one time.
  915. FontSubstitutionTable = (FontSubstitutionEntry*)
  916. GpMalloc(numberOfValues*sizeof(FontSubstitutionEntry));
  917. if (FontSubstitutionTable == NULL)
  918. {
  919. // we can't support font substitution while we out of memory.
  920. RegCloseKey(hkey);
  921. return;
  922. }
  923. // Time to read the data from the registry.
  924. ULONG index = 0;
  925. WCHAR subKey[MAX_PATH];
  926. WCHAR subKeyValue[MAX_PATH];
  927. DWORD subKeyLength ;
  928. DWORD regDataLength ;
  929. while (error == ERROR_SUCCESS)
  930. {
  931. subKeyLength = MAX_PATH;
  932. regDataLength = MAX_PATH;
  933. error = RegEnumValueW(
  934. hkey, index, subKey, &subKeyLength, NULL, NULL,
  935. (unsigned char *) subKeyValue, &regDataLength);
  936. if (error != ERROR_SUCCESS)
  937. {
  938. break;
  939. }
  940. index ++;
  941. // If the font substitution mentioned the charset, then neglect the charset
  942. // and keep the family name only.
  943. for (INT i=regDataLength-1; i>=0; i--)
  944. {
  945. if (subKeyValue[i] == 0x002C) // ','
  946. {
  947. subKeyValue[i] = 0x0000;
  948. break;
  949. }
  950. }
  951. // we found one. then try to get substitution GpFontFamily
  952. GpFontFamily *family;
  953. ASSERT(Globals::FontCollection != NULL);
  954. family = Globals::FontCollection->GetFontTable()->GetFontFamily(subKeyValue);
  955. if (family != NULL)
  956. {
  957. FontSubstitutionTable[substitutionCount].family = family;
  958. DWORD j;
  959. for (j=0 ; j<subKeyLength; j++)
  960. {
  961. if (subKey[j] == 0x002C) // ','
  962. {
  963. break;
  964. }
  965. else
  966. {
  967. FontSubstitutionTable[substitutionCount].familyName[j] = subKey[j];
  968. }
  969. }
  970. FontSubstitutionTable[substitutionCount].familyName[j] = 0x0000;
  971. FontSubstitutionTable[substitutionCount].familyNameLength = j;
  972. substitutionCount++;
  973. }
  974. }
  975. RegCloseKey(hkey);
  976. return;
  977. }
  978. /**************************************************************************\
  979. *
  980. * Function Description:
  981. * Read and cache the font substitution data from win.ini under Windows 9x
  982. *
  983. * Arguments:
  984. *
  985. * Returns:
  986. *
  987. * History:
  988. *
  989. * 6/1/2000 Tarek Mahmoud Sayed
  990. * Created it.
  991. *
  992. \**************************************************************************/
  993. void GpFontLink::CacheFontSubstitutionDataA()
  994. {
  995. DWORD bufferSize = 2048; // 2K to allocate for data reading
  996. DWORD count = 2048;
  997. char *buffer = (char*) GpMalloc(bufferSize);
  998. if (!buffer)
  999. {
  1000. // OutOfMemory
  1001. return;
  1002. }
  1003. // This loop insure we did read all the requested data in the win.ini
  1004. while (bufferSize == count)
  1005. {
  1006. count = GetProfileSectionA(
  1007. WinIniFontSubstitutionSectionName,
  1008. buffer,
  1009. bufferSize);
  1010. if (count == 0)
  1011. {
  1012. // something wrong
  1013. GpFree(buffer);
  1014. return;
  1015. }
  1016. if (bufferSize-2 <= count)
  1017. {
  1018. // we didn't read all data, make the buffer bigger
  1019. GpFree(buffer);
  1020. bufferSize += 1024;
  1021. if (bufferSize > 32*1024)
  1022. {
  1023. // the upper limit for Windows 95 is 32 KB
  1024. return;
  1025. }
  1026. count = bufferSize; // to continue the loop
  1027. buffer = (char *) GpMalloc(bufferSize);
  1028. if (buffer == NULL)
  1029. {
  1030. // Out of memory
  1031. return;
  1032. }
  1033. }
  1034. }
  1035. // Now we have the filled data buffer and the count. start parsing
  1036. // first we need to know how much memory need to allocate for caching
  1037. // then we fill this cache with useful data.
  1038. DWORD i = 0;
  1039. INT entriesCount = 0;
  1040. while (i<count)
  1041. {
  1042. while (i<count && buffer[i] != 0)
  1043. {
  1044. i++;
  1045. }
  1046. entriesCount++;
  1047. i++;
  1048. }
  1049. // Now allocate for the font substitution cache according to entriesCount
  1050. FontSubstitutionTable = (FontSubstitutionEntry*)
  1051. GpMalloc(entriesCount*sizeof(FontSubstitutionEntry));
  1052. if (FontSubstitutionTable == NULL)
  1053. {
  1054. // we can't support font substitution while we out of memory.
  1055. GpFree(buffer);
  1056. return;
  1057. }
  1058. ASSERT(Globals::FontCollection != NULL);
  1059. char *fontName;
  1060. char *fontSubstitutionName;
  1061. WCHAR familyName[MAX_PATH];
  1062. GpFontFamily *family;
  1063. substitutionCount = 0;
  1064. i = 0;
  1065. while (i<count)
  1066. {
  1067. fontName = &buffer[i];
  1068. while ( i<count &&
  1069. buffer[i] != '=' &&
  1070. buffer[i] != ',')
  1071. {
  1072. i++;
  1073. }
  1074. if (i>=count-1)
  1075. {
  1076. // something wrong in the data.
  1077. break;
  1078. }
  1079. if (buffer[i] == ',')
  1080. {
  1081. buffer[i] = 0x0;
  1082. i++;
  1083. while (i<count && buffer[i] != '=')
  1084. {
  1085. i++;
  1086. }
  1087. if (i>=count-1)
  1088. {
  1089. // something wrong in the data.
  1090. break;
  1091. }
  1092. }
  1093. buffer[i] = 0x0;
  1094. i++;
  1095. fontSubstitutionName = &buffer[i];
  1096. while ( i<count &&
  1097. buffer[i] != 0x0 &&
  1098. buffer[i] != ',')
  1099. {
  1100. i++;
  1101. }
  1102. if (i>=count)
  1103. {
  1104. i++;
  1105. // last line may not have a null terminator
  1106. // we sure we have a buffer has space more than the count
  1107. buffer[i] = 0x0;
  1108. }
  1109. if (buffer[i] == ',')
  1110. {
  1111. buffer[i] = 0x0;
  1112. i++;
  1113. while (i<count && buffer[i] != 0x0)
  1114. {
  1115. i++;
  1116. }
  1117. }
  1118. i++;
  1119. if (!AnsiToUnicodeStr(
  1120. fontSubstitutionName,
  1121. familyName,
  1122. MAX_PATH))
  1123. {
  1124. continue;
  1125. }
  1126. family = Globals::FontCollection->GetFontTable()->GetFontFamily(familyName);
  1127. if (family != NULL)
  1128. {
  1129. if (!AnsiToUnicodeStr(
  1130. fontName,
  1131. FontSubstitutionTable[substitutionCount].familyName,
  1132. MAX_PATH))
  1133. {
  1134. continue;
  1135. }
  1136. FontSubstitutionTable[substitutionCount].family = family;
  1137. INT j=0;
  1138. while (FontSubstitutionTable[substitutionCount].familyName[j] != 0x0000)
  1139. {
  1140. j++;
  1141. }
  1142. FontSubstitutionTable[substitutionCount].familyNameLength = j;
  1143. substitutionCount++;
  1144. }
  1145. }
  1146. // clean up the allocated buffer
  1147. GpFree(buffer);
  1148. return;
  1149. }
  1150. /**************************************************************************\
  1151. *
  1152. * Function Description:
  1153. * Search for matched substitution font family
  1154. *
  1155. * Arguments:
  1156. * familyName [in] name of the font to be substituted
  1157. *
  1158. * Returns:
  1159. * font family in success, NULL otherwise
  1160. *
  1161. * History:
  1162. *
  1163. * 4/12/2000 Tarek Mahmoud Sayed
  1164. * Created it.
  1165. *
  1166. \**************************************************************************/
  1167. GpFontFamily *GpFontLink::GetFamilySubstitution(const WCHAR* familyName) const
  1168. {
  1169. INT nameLength = UnicodeStringLength(familyName);
  1170. for (INT i=0 ; i<substitutionCount ; i++)
  1171. {
  1172. // to speed up the search, we use the string length comparison before
  1173. // comparing the string itself.
  1174. if (nameLength == FontSubstitutionTable[i].familyNameLength &&
  1175. UnicodeStringCompareCI(FontSubstitutionTable[i].familyName,
  1176. familyName) == 0)
  1177. {
  1178. ASSERT(FontSubstitutionTable[i].family != NULL);
  1179. return FontSubstitutionTable[i].family;
  1180. }
  1181. }
  1182. // Not found;
  1183. return NULL;
  1184. }