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.

591 lines
15 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. dbcs.c
  5. Abstract:
  6. This module contains the code for console DBCS font dialog
  7. Author:
  8. kazum Feb-27-1995
  9. Revision History:
  10. --*/
  11. #include "shellprv.h"
  12. #pragma hdrstop
  13. #include "lnkcon.h"
  14. #ifdef DBCS
  15. // This definition shares in windows\inc\wincon.w file
  16. //
  17. #define MACHINE_REGISTRY_CONSOLE_TTFONT (L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Console\\TrueTypeFont")
  18. #define MACHINE_REGISTRY_CONSOLE_NLS (L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Console\\Nls")
  19. NTSTATUS
  20. MyRegOpenKey(
  21. IN HANDLE hKey,
  22. IN LPWSTR lpSubKey,
  23. OUT PHANDLE phResult
  24. )
  25. {
  26. OBJECT_ATTRIBUTES Obja;
  27. UNICODE_STRING SubKey;
  28. //
  29. // Convert the subkey to a counted Unicode string.
  30. //
  31. // lpSubKey is one of those #defines up there.
  32. RtlInitUnicodeString( &SubKey, lpSubKey );
  33. //
  34. // Initialize the OBJECT_ATTRIBUTES structure and open the key.
  35. //
  36. InitializeObjectAttributes(
  37. &Obja,
  38. &SubKey,
  39. OBJ_CASE_INSENSITIVE,
  40. hKey,
  41. NULL
  42. );
  43. return NtOpenKey(
  44. phResult,
  45. KEY_READ,
  46. &Obja
  47. );
  48. }
  49. NTSTATUS
  50. MyRegEnumValue(
  51. IN HANDLE hKey,
  52. IN DWORD dwIndex,
  53. OUT DWORD dwValueLength,
  54. OUT LPWSTR lpValueName,
  55. OUT DWORD dwDataLength,
  56. OUT LPBYTE lpData
  57. )
  58. {
  59. ULONG BufferLength;
  60. ULONG ResultLength;
  61. PKEY_VALUE_FULL_INFORMATION KeyValueInformation;
  62. NTSTATUS Status;
  63. //
  64. // Convert the subkey to a counted Unicode string.
  65. //
  66. BufferLength = sizeof(KEY_VALUE_FULL_INFORMATION) + dwValueLength + dwDataLength;
  67. KeyValueInformation = LocalAlloc(LPTR,BufferLength);
  68. if (KeyValueInformation == NULL)
  69. return STATUS_NO_MEMORY;
  70. Status = NtEnumerateValueKey(
  71. hKey,
  72. dwIndex,
  73. KeyValueFullInformation,
  74. KeyValueInformation,
  75. BufferLength,
  76. &ResultLength
  77. );
  78. if (NT_SUCCESS(Status)) {
  79. ASSERT(KeyValueInformation->NameLength <= dwValueLength);
  80. RtlMoveMemory(lpValueName,
  81. KeyValueInformation->Name,
  82. min(KeyValueInformation->NameLength, dwValueLength));
  83. lpValueName[ KeyValueInformation->NameLength >> 1 ] = UNICODE_NULL;
  84. ASSERT(KeyValueInformation->DataLength <= dwDataLength);
  85. RtlMoveMemory(lpData,
  86. (PBYTE)KeyValueInformation + KeyValueInformation->DataOffset,
  87. min(KeyValueInformation->DataLength, dwDataLength));
  88. if (KeyValueInformation->Type == REG_SZ ||
  89. KeyValueInformation->Type == REG_MULTI_SZ
  90. ) {
  91. if (KeyValueInformation->DataLength + sizeof(WCHAR) > dwDataLength) {
  92. KeyValueInformation->DataLength -= sizeof(WCHAR);
  93. }
  94. // WTF is this doing?
  95. if (KeyValueInformation->DataLength < dwDataLength)
  96. lpData[KeyValueInformation->DataLength++] = 0;
  97. if (KeyValueInformation->DataLength < dwDataLength)
  98. lpData[KeyValueInformation->DataLength] = 0;
  99. }
  100. }
  101. LocalFree(KeyValueInformation);
  102. return Status;
  103. }
  104. WORD
  105. ConvertStringToDec(
  106. LPWSTR lpch,
  107. LPWSTR *endptr
  108. )
  109. {
  110. WCHAR ch;
  111. WORD val = 0;
  112. while ( (ch=*lpch) != L'\0')
  113. {
  114. if (L'0' <= ch && ch <= L'9')
  115. val = (val * 10) + (ch - L'0');
  116. else
  117. break;
  118. lpch++;
  119. }
  120. if (endptr)
  121. *endptr = lpch;
  122. return val;
  123. }
  124. WORD
  125. ConvertStringToHex(
  126. LPWSTR lpch,
  127. LPWSTR *endptr
  128. )
  129. {
  130. WCHAR ch;
  131. WORD val = 0;
  132. while ( (ch=*lpch) != L'\0')
  133. {
  134. if (L'0' <= ch && ch <= L'9')
  135. val = (val << 4) + (ch - L'0');
  136. else if (L'A' <= ch && ch <= L'F')
  137. val = (val << 4) + (ch - L'A' + 10);
  138. else if (L'a' <= ch && ch <= L'f')
  139. val = (val << 4) + (ch - L'a' + 10);
  140. else
  141. break;
  142. lpch++;
  143. }
  144. if (endptr)
  145. *endptr = lpch;
  146. return val;
  147. }
  148. NTSTATUS
  149. MakeAltRasterFont(
  150. CONSOLEPROP_DATA * pcpd,
  151. UINT CodePage,
  152. COORD *AltFontSize,
  153. BYTE *AltFontFamily,
  154. ULONG *AltFontIndex,
  155. LPTSTR AltFaceName,
  156. UINT cchFaceName
  157. )
  158. {
  159. DWORD i;
  160. DWORD Find;
  161. ULONG FontIndex;
  162. COORD FontSize = pcpd->FontInfo[pcpd->DefaultFontIndex].Size;
  163. COORD FontDelta;
  164. BOOL fDbcsCharSet = IS_ANY_DBCS_CHARSET( CodePageToCharSet( CodePage ) );
  165. FontIndex = 0;
  166. Find = (DWORD)-1;
  167. for (i=0; i < pcpd->NumberOfFonts; i++)
  168. {
  169. if (!TM_IS_TT_FONT(pcpd->FontInfo[i].Family) &&
  170. IS_ANY_DBCS_CHARSET(pcpd->FontInfo[i].tmCharSet) == fDbcsCharSet
  171. )
  172. {
  173. FontDelta.X = (SHORT)abs(FontSize.X - pcpd->FontInfo[i].Size.X);
  174. FontDelta.Y = (SHORT)abs(FontSize.Y - pcpd->FontInfo[i].Size.Y);
  175. if (Find > (DWORD)(FontDelta.X + FontDelta.Y))
  176. {
  177. Find = (DWORD)(FontDelta.X + FontDelta.Y);
  178. FontIndex = i;
  179. }
  180. }
  181. }
  182. *AltFontIndex = FontIndex;
  183. StrCpyN(AltFaceName, pcpd->FontInfo[*AltFontIndex].FaceName, cchFaceName);
  184. *AltFontSize = pcpd->FontInfo[*AltFontIndex].Size;
  185. *AltFontFamily = pcpd->FontInfo[*AltFontIndex].Family;
  186. return STATUS_SUCCESS;
  187. }
  188. NTSTATUS
  189. InitializeDbcsMisc(
  190. CONSOLEPROP_DATA * pcpd
  191. )
  192. {
  193. HANDLE hkRegistry = NULL;
  194. NTSTATUS Status;
  195. WCHAR awchValue[ 512 ];
  196. WCHAR awchData[ 512 ];
  197. DWORD dwIndex;
  198. LPWSTR pwsz;
  199. pcpd->gTTFontList.Next = NULL;
  200. Status = MyRegOpenKey(NULL,
  201. MACHINE_REGISTRY_CONSOLE_TTFONT,
  202. &hkRegistry);
  203. if (NT_SUCCESS( Status )) {
  204. TTFONTLIST *pTTFontList;
  205. for( dwIndex = 0; ; dwIndex++) {
  206. Status = MyRegEnumValue(hkRegistry,
  207. dwIndex,
  208. sizeof(awchValue), (LPWSTR)&awchValue,
  209. sizeof(awchData), (PBYTE)&awchData);
  210. if (!NT_SUCCESS( Status )) {
  211. break;
  212. }
  213. pTTFontList = LocalAlloc(LPTR, sizeof(TTFONTLIST));
  214. if (pTTFontList == NULL) {
  215. break;
  216. }
  217. pTTFontList->List.Next = NULL;
  218. pTTFontList->CodePage = ConvertStringToDec(awchValue, NULL);
  219. pwsz = awchData;
  220. if (*pwsz == BOLD_MARK) {
  221. pTTFontList->fDisableBold = TRUE;
  222. pwsz++;
  223. }
  224. else
  225. pTTFontList->fDisableBold = FALSE;
  226. StrCpyN(pTTFontList->FaceName1, pwsz, ARRAYSIZE(pTTFontList->FaceName1));
  227. pwsz += lstrlenW(pwsz) + 1;
  228. if (*pwsz == BOLD_MARK)
  229. {
  230. pTTFontList->fDisableBold = TRUE;
  231. pwsz++;
  232. }
  233. StrCpyN(pTTFontList->FaceName2, pwsz, ARRAYSIZE(pTTFontList->FaceName2));
  234. PushEntryList(&pcpd->gTTFontList, &(pTTFontList->List));
  235. }
  236. NtClose(hkRegistry);
  237. }
  238. pcpd->fChangeCodePage = FALSE;
  239. pcpd->uOEMCP = GetOEMCP();
  240. return STATUS_SUCCESS;
  241. }
  242. BYTE
  243. CodePageToCharSet(
  244. UINT CodePage
  245. )
  246. {
  247. CHARSETINFO csi;
  248. if (!TranslateCharsetInfo((DWORD *)UIntToPtr( CodePage ), &csi, TCI_SRCCODEPAGE)) // Sundown: valid zero-extension of CodePage for TCI_SRCCOPAGE.
  249. csi.ciCharset = OEM_CHARSET;
  250. return (BYTE)csi.ciCharset;
  251. }
  252. TTFONTLIST *SearchTTFont(CONSOLEPROP_DATA * pcpd, LPTSTR ptszFace, BOOL fCodePage, UINT CodePage)
  253. {
  254. PSINGLE_LIST_ENTRY pTemp = pcpd->gTTFontList.Next;
  255. if (ptszFace) {
  256. while (pTemp != NULL) {
  257. TTFONTLIST *pTTFontList = (TTFONTLIST *)pTemp;
  258. if (wcscmp(ptszFace, pTTFontList->FaceName1) == 0 ||
  259. wcscmp(ptszFace, pTTFontList->FaceName2) == 0 ) {
  260. if (fCodePage)
  261. if (pTTFontList->CodePage == CodePage )
  262. return pTTFontList;
  263. else
  264. return NULL;
  265. else
  266. return pTTFontList;
  267. }
  268. pTemp = pTemp->Next;
  269. }
  270. }
  271. return NULL;
  272. }
  273. BOOL
  274. IsAvailableTTFont(
  275. CONSOLEPROP_DATA * pcpd,
  276. LPTSTR ptszFace
  277. )
  278. {
  279. if (SearchTTFont(pcpd, ptszFace, FALSE, 0))
  280. return TRUE;
  281. else
  282. return FALSE;
  283. }
  284. BOOL
  285. IsAvailableTTFontCP(
  286. CONSOLEPROP_DATA * pcpd,
  287. LPTSTR ptszFace,
  288. UINT CodePage
  289. )
  290. {
  291. if (SearchTTFont(pcpd, ptszFace, TRUE, CodePage))
  292. return TRUE;
  293. else
  294. return FALSE;
  295. }
  296. BOOL
  297. IsDisableBoldTTFont(
  298. CONSOLEPROP_DATA * pcpd,
  299. LPTSTR ptszFace
  300. )
  301. {
  302. TTFONTLIST *pTTFontList;
  303. pTTFontList = SearchTTFont(pcpd, ptszFace, FALSE, 0);
  304. if (pTTFontList != NULL)
  305. return pTTFontList->fDisableBold;
  306. else
  307. return FALSE;
  308. }
  309. LPTSTR
  310. GetAltFaceName(
  311. CONSOLEPROP_DATA * pcpd,
  312. LPTSTR ptszFace
  313. )
  314. {
  315. TTFONTLIST *pTTFontList;
  316. pTTFontList = SearchTTFont(pcpd, ptszFace, FALSE, 0);
  317. if (pTTFontList) {
  318. if (wcscmp(ptszFace, pTTFontList->FaceName1) == 0) {
  319. return pTTFontList->FaceName2;
  320. }
  321. if (wcscmp(ptszFace, pTTFontList->FaceName2) == 0) {
  322. return pTTFontList->FaceName1;
  323. }
  324. return NULL;
  325. }
  326. else
  327. return NULL;
  328. }
  329. typedef struct _LC_List {
  330. struct _LC_List* Next;
  331. BOOL FindFlag;
  332. WCHAR LC_String[9];
  333. } LC_List, *PLC_List;
  334. static PLC_List LocaleList;
  335. BOOL CALLBACK
  336. EnumProc(
  337. LPWSTR LC_String
  338. )
  339. {
  340. PLC_List TmpList;
  341. if (lstrlenW(LC_String) <= ARRAYSIZE(LocaleList->LC_String) - 1)
  342. {
  343. TmpList = (PLC_List)&LocaleList;
  344. while (TmpList->Next != NULL)
  345. TmpList = TmpList->Next;
  346. TmpList->Next = LocalAlloc(LPTR, sizeof(LC_List));
  347. if (TmpList->Next != NULL)
  348. {
  349. TmpList = TmpList->Next;
  350. StrCpyN(TmpList->LC_String, LC_String, ARRAYSIZE(TmpList->LC_String));
  351. }
  352. }
  353. return TRUE;
  354. }
  355. int
  356. LanguageListCreate(
  357. HWND hDlg,
  358. UINT CodePage
  359. )
  360. /*++
  361. Initializes the Language list by enumerating all Locale Information.
  362. Returns
  363. --*/
  364. {
  365. HWND hWndLanguageCombo;
  366. HANDLE hkRegistry = NULL;
  367. NTSTATUS Status;
  368. WCHAR awchValue[ 512 ];
  369. WCHAR awchData[ 512 ];
  370. DWORD dwIndex;
  371. PLC_List TmpList;
  372. WORD LangID;
  373. LCID Locale;
  374. int cchData;
  375. LONG lListIndex;
  376. UINT cp;
  377. ENTERCRITICAL;
  378. /*
  379. * Enumrate system locale information
  380. */
  381. EnumSystemLocalesW( EnumProc, CP_INSTALLED );
  382. /*
  383. * Enumrate registory key
  384. */
  385. Status = MyRegOpenKey(NULL,
  386. MACHINE_REGISTRY_CONSOLE_NLS,
  387. &hkRegistry);
  388. if (NT_SUCCESS( Status )) {
  389. for( dwIndex = 0; ; dwIndex++)
  390. {
  391. Status = MyRegEnumValue(hkRegistry,
  392. dwIndex,
  393. sizeof(awchValue), (LPWSTR)&awchValue,
  394. sizeof(awchData), (PBYTE)&awchData);
  395. if (!NT_SUCCESS( Status ))
  396. {
  397. break;
  398. }
  399. TmpList = (PLC_List)&LocaleList;
  400. while(TmpList->Next != NULL)
  401. {
  402. TmpList = TmpList->Next;
  403. if (lstrcmpW(awchValue, TmpList->LC_String) == 0)
  404. {
  405. TmpList->FindFlag = TRUE;
  406. break;
  407. }
  408. }
  409. }
  410. NtClose(hkRegistry);
  411. }
  412. /*
  413. * Create ComboBox items
  414. */
  415. hWndLanguageCombo = GetDlgItem(hDlg, IDC_CNSL_LANGUAGELIST);
  416. SendMessage(hWndLanguageCombo, CB_RESETCONTENT, 0, 0L);
  417. TmpList = (PLC_List)&LocaleList;
  418. while(TmpList->Next != NULL)
  419. {
  420. TmpList = TmpList->Next;
  421. if (TmpList->FindFlag)
  422. {
  423. LangID = ConvertStringToHex(TmpList->LC_String, NULL);
  424. Locale = MAKELCID( LangID, SORT_DEFAULT );
  425. awchValue[0] = L'\0';
  426. cp = 0;
  427. {
  428. #define KERNEL32 _T("KERNEL32.DLL")
  429. #ifdef UNICODE
  430. #define GETCPINFOEX "GetCPInfoExW"
  431. #else
  432. #define GETCPINFOEX "GetCPInfoExA"
  433. #endif
  434. typedef BOOL (CALLBACK *LPFNGETCPINFOEX)(UINT, DWORD, LPCPINFOEX);
  435. LPFNGETCPINFOEX lpfnGetCPInfoEx;
  436. BOOL fRet = FALSE;
  437. CPINFOEX cpinfo;
  438. HMODULE hMod;
  439. cchData = GetLocaleInfoW(Locale, LOCALE_IDEFAULTCODEPAGE,
  440. awchData, ARRAYSIZE(awchData));
  441. if (cchData)
  442. {
  443. cp = ConvertStringToDec(awchData, NULL);
  444. hMod = GetModuleHandle(KERNEL32);
  445. if (hMod) {
  446. lpfnGetCPInfoEx = (LPFNGETCPINFOEX)GetProcAddress(hMod,GETCPINFOEX);
  447. if (lpfnGetCPInfoEx)
  448. fRet = (*lpfnGetCPInfoEx)(cp, 0, &cpinfo);
  449. }
  450. if (fRet) {
  451. lListIndex = (LONG) SendMessageW(hWndLanguageCombo, CB_ADDSTRING, 0, (LPARAM)cpinfo.CodePageName);
  452. SendMessage(hWndLanguageCombo, CB_SETITEMDATA, (DWORD)lListIndex, cp);
  453. if (CodePage == cp) {
  454. SendMessage(hWndLanguageCombo, CB_SETCURSEL, lListIndex, 0L);
  455. }
  456. }
  457. }
  458. }
  459. if (CodePage == cp) {
  460. SendMessage(hWndLanguageCombo, CB_SETCURSEL, lListIndex, 0L);
  461. }
  462. }
  463. }
  464. {
  465. PLC_List Tmp;
  466. TmpList = (PLC_List)&LocaleList;
  467. while(TmpList->Next != NULL)
  468. {
  469. Tmp = TmpList;
  470. TmpList = TmpList->Next;
  471. if (Tmp != (PLC_List)&LocaleList)
  472. LocalFree(Tmp);
  473. }
  474. LocaleList = NULL;
  475. }
  476. LEAVECRITICAL;
  477. /*
  478. * Get the LocaleIndex from the currently selected item.
  479. * (i will be LB_ERR if no currently selected item).
  480. */
  481. lListIndex = (LONG) SendMessage(hWndLanguageCombo, CB_GETCURSEL, 0, 0L);
  482. return (int) SendMessage(hWndLanguageCombo, CB_GETITEMDATA, lListIndex, 0L);
  483. }
  484. #endif // DBCS