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.

11536 lines
354 KiB

  1. //
  2. // Include Files.
  3. //
  4. #include "input.h"
  5. #include <shlobj.h>
  6. #include <regstr.h>
  7. #include <setupapi.h>
  8. #include <immp.h>
  9. #include <winuserp.h>
  10. #include <winbasep.h>
  11. #include <oleauto.h>
  12. #include "inputdlg.h"
  13. #include "msctf.h"
  14. #include "msctfp.h"
  15. #include "ctffunc.h"
  16. #include "util.h"
  17. #include "inputhlp.h"
  18. #include "external.h"
  19. #define IMAGEID_KEYBOARD 0
  20. #define IMAGEID_SPEECH 1
  21. #define IMAGEID_PEN 2
  22. #define IMAGEID_TIPITEMS 3
  23. #define IMAGEID_EXTERNAL 4
  24. #define IMAGEID_SMARTTAG 5
  25. #define TV_ITEM_TYPE_LANG 0x0001
  26. #define TV_ITEM_TYPE_GROUP 0x0002
  27. #define TV_ITEM_TYPE_KBD 0x0010
  28. #define TV_ITEM_TYPE_SPEECH 0x0020
  29. #define TV_ITEM_TYPE_PEN 0x0040
  30. #define TV_ITEM_TYPE_TIP 0x0100
  31. #define TV_ITEM_TYPE_EXTERNAL 0x0200
  32. #define TV_ITEM_TYPE_SMARTTAG 0x0400
  33. #define INPUT_TYPE_KBD TV_ITEM_TYPE_KBD
  34. #define INPUT_TYPE_PEN TV_ITEM_TYPE_PEN
  35. #define INPUT_TYPE_SPEECH TV_ITEM_TYPE_SPEECH
  36. #define INPUT_TYPE_TIP TV_ITEM_TYPE_TIP
  37. #define INPUT_TYPE_EXTERNAL TV_ITEM_TYPE_EXTERNAL
  38. #define INPUT_TYPE_SMARTTAG TV_ITEM_TYPE_SMARTTAG
  39. #define MAX_DUPLICATED_HKL 64
  40. //
  41. // Context Help Ids.
  42. //
  43. static int aInputHelpIds[] =
  44. {
  45. IDC_GROUPBOX1, IDH_COMM_GROUPBOX,
  46. IDC_LOCALE_DEFAULT_TEXT, IDH_INPUT_DEFAULT_LOCALE,
  47. IDC_LOCALE_DEFAULT, IDH_INPUT_DEFAULT_LOCALE,
  48. IDC_GROUPBOX2, IDH_COMM_GROUPBOX,
  49. IDC_INPUT_LIST_TEXT, IDH_INPUT_LIST,
  50. IDC_INPUT_LIST, IDH_INPUT_LIST,
  51. IDC_KBDL_ADD, IDH_INPUT_ADD,
  52. IDC_KBDL_DELETE, IDH_INPUT_DELETE,
  53. IDC_KBDL_EDIT, IDH_INPUT_EDIT,
  54. IDC_GROUPBOX3, IDH_COMM_GROUPBOX,
  55. IDC_TB_SETTING, IDH_INPUT_TOOLBAR_SETTINGS,
  56. IDC_HOTKEY_SETTING, IDH_INPUT_KEY_SETTINGS,
  57. 0, 0
  58. };
  59. static int aToolbarSettingsHelpIds[] =
  60. {
  61. IDC_GROUPBOX1, IDH_COMM_GROUPBOX,
  62. IDC_TB_SHOWLANGBAR, IDH_INPUT_SHOWLANGBAR,
  63. IDC_TB_HIGHTRANS, IDH_INPUT_HIGH_TRANS,
  64. IDC_TB_EXTRAICON, IDH_INPUT_EXTRAICON,
  65. IDC_TB_TEXTLABELS, IDH_INPUT_TEXT_LABELS,
  66. 0, 0
  67. };
  68. static int aLocaleKeysSettingsHelpIds[] =
  69. {
  70. IDC_KBDL_CAPSLOCK_FRAME, IDH_COMM_GROUPBOX,
  71. IDC_KBDL_CAPSLOCK, IDH_INPUT_SETTINGS_CAPSLOCK,
  72. IDC_KBDL_SHIFTLOCK, IDH_INPUT_SETTINGS_CAPSLOCK,
  73. IDC_KBDL_HOTKEY_FRAME, IDH_COMM_GROUPBOX,
  74. IDC_KBDL_HOTKEY, IDH_INPUT_SETTINGS_HOTKEY,
  75. IDC_KBDL_HOTKEY_SEQUENCE, IDH_INPUT_SETTINGS_HOTKEY,
  76. IDC_KBDL_HOTKEY_LIST, IDH_INPUT_SETTINGS_HOTKEY_LIST,
  77. IDC_KBDL_CHANGE_HOTKEY, IDH_INPUT_SETTINGS_HOTKEY,
  78. 0, 0
  79. };
  80. static int aLocaleAddHelpIds[] =
  81. {
  82. IDC_KBDLA_LOCALE_TEXT, IDH_INPUT_ADD_LOCALE,
  83. IDC_KBDLA_LOCALE, IDH_INPUT_ADD_LOCALE,
  84. IDC_KBDLA_LAYOUT_TEXT, IDH_INPUT_ADD_LAYOUT,
  85. IDC_KBDLA_LAYOUT, IDH_INPUT_ADD_LAYOUT,
  86. IDC_PEN_TEXT, IDH_INPUT_ADD_PEN,
  87. IDC_PEN_TIP, IDH_INPUT_ADD_PEN,
  88. IDC_SPEECH_TEXT, IDH_INPUT_ADD_SPEECH,
  89. IDC_SPEECH_TIP, IDH_INPUT_ADD_SPEECH,
  90. 0, 0
  91. };
  92. static int aLocaleHotkeyHelpIds[] =
  93. {
  94. IDC_GROUPBOX1, IDH_COMM_GROUPBOX,
  95. IDC_KBDLH_LANGHOTKEY, IDH_INPUT_LANG_HOTKEY_CHANGE,
  96. IDC_KBDLH_SHIFT, IDH_INPUT_LANG_HOTKEY_CHANGE,
  97. IDC_KBDLH_PLUS, IDH_INPUT_LANG_HOTKEY_CHANGE,
  98. IDC_KBDLH_CTRL, IDH_INPUT_LANG_HOTKEY_CHANGE,
  99. IDC_KBDLH_L_ALT, IDH_INPUT_LANG_HOTKEY_CHANGE,
  100. IDC_KBDLH_LAYOUTHOTKEY, IDH_INPUT_LANG_HOTKEY_CHANGE,
  101. IDC_KBDLH_SHIFT2, IDH_INPUT_LANG_HOTKEY_CHANGE,
  102. IDC_KBDLH_PLUS2, IDH_INPUT_LANG_HOTKEY_CHANGE,
  103. IDC_KBDLH_CTRL2, IDH_INPUT_LANG_HOTKEY_CHANGE,
  104. IDC_KBDLH_L_ALT2, IDH_INPUT_LANG_HOTKEY_CHANGE,
  105. IDC_KBDLH_GRAVE, IDH_INPUT_LANG_HOTKEY_CHANGE,
  106. 0, 0
  107. };
  108. static int aLayoutHotkeyHelpIds[] =
  109. {
  110. IDC_KBDLH_LAYOUT_TEXT, IDH_INPUT_LAYOUT_HOTKEY_CHANGE,
  111. IDC_KBDLH_LANGHOTKEY, IDH_INPUT_LAYOUT_HOTKEY_CHANGE,
  112. IDC_KBDLH_SHIFT, IDH_INPUT_LAYOUT_HOTKEY_CHANGE,
  113. IDC_KBDLH_CTRL, IDH_INPUT_LAYOUT_HOTKEY_CHANGE,
  114. IDC_KBDLH_L_ALT, IDH_INPUT_LAYOUT_HOTKEY_CHANGE,
  115. IDC_KBDLH_KEY_COMBO, IDH_INPUT_LAYOUT_HOTKEY_CHANGE,
  116. 0, 0
  117. };
  118. //
  119. // Global Variables.
  120. //
  121. HWND g_hDlg;
  122. HWND g_hwndTV;
  123. HTREEITEM g_hTVRoot;
  124. HIMAGELIST g_hImageList;
  125. UINT g_cTVItemSize = 0;
  126. BOOL g_OSNT4 = FALSE;
  127. BOOL g_OSNT5 = FALSE;
  128. BOOL g_OSWIN95 = FALSE;
  129. BOOL g_bAdvChanged = FALSE;
  130. static BOOL g_bGetSwitchLangHotKey = TRUE;
  131. static BOOL g_bCoInit = FALSE;
  132. static DWORD g_dwPrimLangID = 0;
  133. static UINT g_iThaiLayout = 0;
  134. static BOOL g_bPenOrSapiTip = FALSE;
  135. static BOOL g_bExtraTip = FALSE;
  136. UINT g_iInputs = 0;
  137. UINT g_iOrgInputs = 0;
  138. WNDPROC g_lpfnTVWndProc = NULL;
  139. TCHAR szPropHwnd[] = TEXT("PROP_HWND");
  140. TCHAR szPropIdx[] = TEXT("PROP_IDX");
  141. TCHAR szDefault[DESC_MAX];
  142. TCHAR szInputTypeKbd[DESC_MAX];
  143. TCHAR szInputTypePen[DESC_MAX];
  144. TCHAR szInputTypeSpeech[DESC_MAX];
  145. TCHAR szInputTypeExternal[DESC_MAX];
  146. HINSTANCE g_hShlwapi = NULL;
  147. FARPROC pfnSHLoadRegUIString = NULL;
  148. //
  149. // External Routines.
  150. //
  151. extern HWND g_hwndAdvanced;
  152. extern void Region_RebootTheSystem();
  153. extern BOOL Region_OpenIntlInfFile(HINF *phInf);
  154. extern BOOL Region_CloseInfFile(HINF *phInf);
  155. extern BOOL Region_ReadDefaultLayoutFromInf(
  156. LPTSTR pszLocale,
  157. LPDWORD pdwLocale,
  158. LPDWORD pdwLayout,
  159. LPDWORD pdwLocale2,
  160. LPDWORD pdwLayout2,
  161. HINF hIntlInf);
  162. // For (_WIN32_WINNT >= 0x0500 from winuser.h
  163. #define KLF_SHIFTLOCK 0x00010000
  164. #define KLF_RESET 0x40000000
  165. #define SM_IMMENABLED 82
  166. ////////////////////////////////////////////////////////////////////////////
  167. //
  168. // MarkSptipRemoved
  169. //
  170. // TRUE - mark the reg value as "removed", FALSE - delete the reg value
  171. //
  172. ////////////////////////////////////////////////////////////////////////////
  173. BOOL MarkSptipRemoved(BOOL bRemoved)
  174. {
  175. //
  176. // SPTIP's private regentries for the use of detecting
  177. // whether user has removed profile
  178. //
  179. const TCHAR c_szProfileRemoved[] = TEXT("ProfileRemoved");
  180. const TCHAR c_szSapilayrKey[] = TEXT("SOFTWARE\\Microsoft\\CTF\\Sapilayr\\");
  181. HKEY hkey;
  182. long lRet = ERROR_SUCCESS;
  183. DWORD dw = bRemoved ? 1 : 0;
  184. if (ERROR_SUCCESS ==
  185. RegCreateKey(HKEY_CURRENT_USER, c_szSapilayrKey, &hkey))
  186. {
  187. lRet = RegSetValueEx(hkey, c_szProfileRemoved, 0,
  188. REG_DWORD, (LPBYTE)&dw, sizeof(DWORD));
  189. RegCloseKey(hkey);
  190. }
  191. return lRet;
  192. }
  193. ////////////////////////////////////////////////////////////////////////////
  194. //
  195. // CompareStringTIP
  196. //
  197. ////////////////////////////////////////////////////////////////////////////
  198. int CompareStringTIP(LPTSTR lpStr1, LPTSTR lpStr2)
  199. {
  200. if (g_bCHSystem)
  201. {
  202. TCHAR szTemp[MAX_PATH];
  203. UINT uSize1 = lstrlen(lpStr1);
  204. UINT uSize2 = lstrlen(lpStr2);
  205. UINT uSizeDef = lstrlen(szDefault);
  206. if (uSize1 == uSize2)
  207. return lstrcmp(lpStr1, lpStr2);
  208. if (uSize1 > uSizeDef)
  209. {
  210. if (lstrcmp(lpStr1 + uSize1 - uSizeDef, szDefault) == 0)
  211. {
  212. StringCchCopy(szTemp, ARRAYSIZE(szTemp), lpStr1);
  213. *(szTemp + uSize1 - uSizeDef) = TEXT('\0');
  214. return lstrcmp(szTemp, lpStr2);
  215. }
  216. }
  217. if (uSize2 > uSizeDef)
  218. {
  219. if (lstrcmp(lpStr2 + uSize2 - uSizeDef, szDefault) == 0)
  220. {
  221. StringCchCopy(szTemp, ARRAYSIZE(szTemp), lpStr2);
  222. *(szTemp + uSize2 - uSizeDef) = TEXT('\0');
  223. return lstrcmp(szTemp, lpStr1);
  224. }
  225. }
  226. }
  227. return lstrcmp(lpStr1, lpStr2);
  228. }
  229. ////////////////////////////////////////////////////////////////////////////
  230. //
  231. // Locale_ErrorMsg
  232. //
  233. // Sound a beep and put up the given error message.
  234. //
  235. ////////////////////////////////////////////////////////////////////////////
  236. void Locale_ErrorMsg(
  237. HWND hwnd,
  238. UINT iErr,
  239. LPTSTR lpValue)
  240. {
  241. TCHAR sz[DESC_MAX];
  242. TCHAR szString[DESC_MAX];
  243. //
  244. // Sound a beep.
  245. //
  246. MessageBeep(MB_OK);
  247. //
  248. // Put up the appropriate error message box.
  249. //
  250. if (LoadString(hInstance, iErr, sz, ARRAYSIZE(sz)))
  251. {
  252. //
  253. // If the caller wants to display a message with a caller supplied
  254. // value string, do it.
  255. //
  256. if (lpValue)
  257. {
  258. StringCchPrintf(szString, ARRAYSIZE(szString), sz, lpValue);
  259. MessageBox(hwnd, szString, NULL, MB_OK_OOPS);
  260. }
  261. else
  262. {
  263. MessageBox(hwnd, sz, NULL, MB_OK_OOPS);
  264. }
  265. }
  266. }
  267. ////////////////////////////////////////////////////////////////////////////
  268. //
  269. // IsFELangID
  270. //
  271. ////////////////////////////////////////////////////////////////////////////
  272. BOOL IsFELangID(DWORD dwLangID)
  273. {
  274. if ((dwLangID == 0x0404) || (dwLangID == 0x0411) ||
  275. (dwLangID == 0x0412) || (dwLangID == 0x0804))
  276. {
  277. return TRUE;
  278. }
  279. return FALSE;
  280. }
  281. ////////////////////////////////////////////////////////////////////////////
  282. //
  283. // IsUnregisteredFEDummyHKL
  284. //
  285. ////////////////////////////////////////////////////////////////////////////
  286. BOOL IsUnregisteredFEDummyHKL(HKL hkl)
  287. {
  288. HKEY hKey;
  289. BOOL bRet = FALSE;
  290. TCHAR szFEDummyHKL[10];
  291. switch (LANGIDFROMLCID(hkl))
  292. {
  293. case 0x411: break;
  294. case 0x412: break;
  295. case 0x404: break;
  296. case 0x804: break;
  297. default:
  298. goto Exit;
  299. }
  300. if (HIWORD((DWORD)(UINT_PTR)hkl) != LOWORD((DWORD)(UINT_PTR)hkl))
  301. {
  302. goto Exit;
  303. }
  304. StringCchPrintf(szFEDummyHKL, ARRAYSIZE(szFEDummyHKL), TEXT("%08x"), LOWORD((DWORD)(UINT_PTR)hkl));
  305. //
  306. // Now read all of preload hkl from the registry.
  307. //
  308. if (RegOpenKey(HKEY_CURRENT_USER, c_szKbdPreloadKey, &hKey) == ERROR_SUCCESS)
  309. {
  310. DWORD dwIndex;
  311. DWORD cchValue, cbData;
  312. LONG dwRetVal;
  313. TCHAR szValue[MAX_PATH]; // language id (number)
  314. TCHAR szData[MAX_PATH]; // language name
  315. dwIndex = 0;
  316. cchValue = sizeof(szValue) / sizeof(TCHAR);
  317. cbData = sizeof(szData);
  318. dwRetVal = RegEnumValue( hKey,
  319. dwIndex,
  320. szValue,
  321. &cchValue,
  322. NULL,
  323. NULL,
  324. (LPBYTE)szData,
  325. &cbData );
  326. if (dwRetVal != ERROR_SUCCESS)
  327. {
  328. RegCloseKey(hKey);
  329. return (FALSE);
  330. }
  331. //
  332. // There is FE dummy hkl. we will skip this hkl if it is not loaded
  333. // from Preload registry section.
  334. //
  335. bRet = TRUE;
  336. do
  337. {
  338. if (!lstrcmp(szFEDummyHKL, szData))
  339. {
  340. HKEY hSubKey;
  341. BOOL bSubHKL = FALSE;
  342. //
  343. // Check substitute hkl.
  344. //
  345. if (RegOpenKey(HKEY_CURRENT_USER,
  346. c_szKbdSubstKey,
  347. &hSubKey) == ERROR_SUCCESS)
  348. {
  349. if (RegQueryValueEx(hSubKey, szData,
  350. NULL, NULL,
  351. NULL, NULL)
  352. == ERROR_SUCCESS)
  353. {
  354. bSubHKL = TRUE;
  355. }
  356. RegCloseKey(hSubKey);
  357. if (bSubHKL)
  358. goto Next;
  359. }
  360. //
  361. // Found dummy hkl from preload section, so we need to display
  362. // this dummy hkl
  363. //
  364. bRet = FALSE;
  365. break;
  366. }
  367. Next:
  368. dwIndex++;
  369. cchValue = sizeof(szValue) / sizeof(TCHAR);
  370. szValue[0] = TEXT('\0');
  371. cbData = sizeof(szData);
  372. szData[0] = TEXT('\0');
  373. dwRetVal = RegEnumValue( hKey,
  374. dwIndex,
  375. szValue,
  376. &cchValue,
  377. NULL,
  378. NULL,
  379. (LPBYTE)szData,
  380. &cbData );
  381. } while (dwRetVal == ERROR_SUCCESS);
  382. RegCloseKey(hKey);
  383. }
  384. Exit:
  385. return bRet;
  386. }
  387. #ifdef _WIN64
  388. //
  389. // Issue optimization for IA64 retail version case - related bug#361062
  390. //
  391. #pragma optimize("", off)
  392. #endif // _WIN64
  393. ////////////////////////////////////////////////////////////////////////////
  394. //
  395. // GetSubstituteHKL
  396. //
  397. ////////////////////////////////////////////////////////////////////////////
  398. HKL GetSubstituteHKL(REFCLSID rclsid, LANGID langid, REFGUID guidProfile)
  399. {
  400. HKEY hkey;
  401. DWORD cb;
  402. HKL hkl = NULL;
  403. TCHAR szSubKeyPath[MAX_PATH];
  404. TCHAR szSubHKL[MAX_PATH];
  405. StringCchCopy(szSubKeyPath, ARRAYSIZE(szSubKeyPath), c_szCTFTipPath);
  406. StringFromGUID2(rclsid, (LPOLESTR) szSubKeyPath + lstrlen(szSubKeyPath), 100);
  407. StringCchCat(szSubKeyPath, ARRAYSIZE(szSubKeyPath), TEXT("\\"));
  408. StringCchCat(szSubKeyPath, ARRAYSIZE(szSubKeyPath), c_szLangProfileKey);
  409. StringCchCat(szSubKeyPath, ARRAYSIZE(szSubKeyPath), TEXT("\\"));
  410. StringCchPrintf(szSubKeyPath + lstrlen(szSubKeyPath),
  411. ARRAYSIZE(szSubKeyPath) - lstrlen(szSubKeyPath),
  412. TEXT("0x%08x"),
  413. langid);
  414. StringCchCat(szSubKeyPath, ARRAYSIZE(szSubKeyPath), TEXT("\\"));
  415. StringFromGUID2(guidProfile, (LPOLESTR) szSubKeyPath + lstrlen(szSubKeyPath), 50);
  416. if (RegOpenKey(HKEY_LOCAL_MACHINE, szSubKeyPath, &hkey) == ERROR_SUCCESS)
  417. {
  418. cb = sizeof(szSubHKL);
  419. RegQueryValueEx(hkey, c_szSubstituteLayout, NULL, NULL, (LPBYTE)szSubHKL, &cb);
  420. RegCloseKey(hkey);
  421. if ((szSubHKL[0] == '0') && ((szSubHKL[1] == 'X') || (szSubHKL[1] == 'x')))
  422. {
  423. hkl = (HKL) IntToPtr(TransNum(szSubHKL+2));
  424. if (LOWORD(hkl) != langid)
  425. hkl = 0;
  426. }
  427. }
  428. return hkl;
  429. }
  430. #ifdef _WIN64
  431. #pragma optimize("", on)
  432. #endif // _WIN64
  433. ////////////////////////////////////////////////////////////////////////////
  434. //
  435. // IsTipSubstituteHKL
  436. //
  437. ////////////////////////////////////////////////////////////////////////////
  438. BOOL IsTipSubstituteHKL(HKL hkl)
  439. {
  440. UINT ctr;
  441. //
  442. // Search substitute HKL of Tips.
  443. //
  444. for (ctr = 0; ctr < g_iTipsBuff; ctr++)
  445. {
  446. if (hkl == g_lpTips[ctr].hklSub)
  447. {
  448. return TRUE;
  449. }
  450. }
  451. return FALSE;
  452. }
  453. ////////////////////////////////////////////////////////////////////////////
  454. //
  455. // IsEnabledTipOrMultiLayouts()
  456. //
  457. ////////////////////////////////////////////////////////////////////////////
  458. BOOL IsEnabledTipOrMultiLayouts()
  459. {
  460. BOOL bRet = TRUE;
  461. if (g_iInputs < 2 && !g_iEnabledTips)
  462. {
  463. // No Tip and one layout, so diable turn off ctfmon UI.
  464. bRet = FALSE;
  465. }
  466. return bRet;
  467. }
  468. ////////////////////////////////////////////////////////////////////////////
  469. //
  470. // AddKbdLayoutOnKbdTip
  471. //
  472. ////////////////////////////////////////////////////////////////////////////
  473. void AddKbdLayoutOnKbdTip(HKL hkl, UINT iLayout)
  474. {
  475. UINT ctr;
  476. //
  477. // Search substitute HKL of Tips.
  478. //
  479. for (ctr = 0; ctr < g_iTipsBuff; ctr++)
  480. {
  481. if (hkl == g_lpTips[ctr].hklSub)
  482. {
  483. if (iLayout)
  484. g_lpTips[ctr].iLayout = iLayout;
  485. }
  486. }
  487. }
  488. ////////////////////////////////////////////////////////////////////////////
  489. //
  490. // IsAvailableTip
  491. //
  492. ////////////////////////////////////////////////////////////////////////////
  493. BOOL IsTipAvailableForAdd(DWORD dwLangID)
  494. {
  495. UINT ctr;
  496. //
  497. // Search substitute HKL of Tips.
  498. //
  499. for (ctr = 0; ctr < g_iTipsBuff; ctr++)
  500. {
  501. if ((dwLangID == g_lpTips[ctr].dwLangID) &&
  502. !(g_lpTips[ctr].bEnabled))
  503. {
  504. if (g_lpTips[ctr].uInputType & INPUT_TYPE_SPEECH)
  505. {
  506. if (!(g_lpTips[ctr].fEngineAvailable))
  507. continue;
  508. }
  509. return TRUE;
  510. }
  511. }
  512. return FALSE;
  513. }
  514. ////////////////////////////////////////////////////////////////////////////
  515. //
  516. // CreateImageIcons
  517. //
  518. ////////////////////////////////////////////////////////////////////////////
  519. void CreateImageIcons()
  520. {
  521. HBITMAP hBmp;
  522. UINT flags = ILC_COLOR | ILC_MASK;
  523. HIMAGELIST hIml, hImlTmp;
  524. HICON hIcon = NULL;
  525. //
  526. // Create the image list
  527. //
  528. g_hImageList = ImageList_Create( GetSystemMetrics(SM_CXSMICON),
  529. GetSystemMetrics(SM_CYSMICON),
  530. ILC_COLOR32 | ILC_MASK,
  531. 0,
  532. 0 );
  533. //
  534. // Load the group icons of input type.
  535. //
  536. hIcon = LoadImage(hInstOrig,
  537. MAKEINTRESOURCE(IDI_KEYBOARD),
  538. IMAGE_ICON,
  539. 0,
  540. 0,
  541. LR_DEFAULTCOLOR);
  542. ImageList_AddIcon(g_hImageList, hIcon);
  543. hIcon = LoadImage(hInstOrig,
  544. MAKEINTRESOURCE(IDI_SPEECH),
  545. IMAGE_ICON,
  546. 0,
  547. 0,
  548. LR_DEFAULTCOLOR);
  549. ImageList_AddIcon(g_hImageList, hIcon);
  550. hIcon = LoadImage(hInstOrig,
  551. MAKEINTRESOURCE(IDI_PEN),
  552. IMAGE_ICON,
  553. 0,
  554. 0,
  555. LR_DEFAULTCOLOR);
  556. ImageList_AddIcon(g_hImageList, hIcon);
  557. hIcon = LoadImage(GetCicResInstance(hInstOrig, IDI_TIPITEM),
  558. MAKEINTRESOURCE(IDI_TIPITEM),
  559. IMAGE_ICON,
  560. 0,
  561. 0,
  562. LR_DEFAULTCOLOR);
  563. ImageList_AddIcon(g_hImageList, hIcon);
  564. hIcon = LoadImage(GetCicResInstance(hInstOrig, IDI_ICON),
  565. MAKEINTRESOURCE(IDI_ICON),
  566. IMAGE_ICON,
  567. 0,
  568. 0,
  569. LR_DEFAULTCOLOR);
  570. ImageList_AddIcon(g_hImageList, hIcon);
  571. hIcon = LoadImage(GetCicResInstance(hInstOrig, IDI_SMARTTAG),
  572. MAKEINTRESOURCE(IDI_SMARTTAG),
  573. IMAGE_ICON,
  574. 0,
  575. 0,
  576. LR_DEFAULTCOLOR);
  577. ImageList_AddIcon(g_hImageList, hIcon);
  578. // Associate the image list with the tree.
  579. hImlTmp = TreeView_SetImageList(g_hwndTV, g_hImageList, TVSIL_NORMAL);
  580. if (hImlTmp)
  581. ImageList_Destroy(hImlTmp);
  582. }
  583. ////////////////////////////////////////////////////////////////////////////
  584. //
  585. // CreateLangIcon
  586. //
  587. ////////////////////////////////////////////////////////////////////////////
  588. HICON CreateLangIcon( HWND hwnd, UINT langID )
  589. {
  590. HBITMAP hbmColour;
  591. HBITMAP hbmMono;
  592. HBITMAP hbmOld;
  593. HICON hicon = NULL;
  594. ICONINFO ii;
  595. RECT rc;
  596. DWORD rgbText;
  597. DWORD rgbBk = 0;
  598. UINT i;
  599. HDC hdc;
  600. HDC hdcScreen;
  601. //HBRUSH hbr;
  602. LOGFONT lf;
  603. HFONT hfont;
  604. HFONT hfontOld;
  605. TCHAR szData[20];
  606. //
  607. // Get the indicator by using the first 2 characters of the
  608. // abbreviated language name.
  609. //
  610. if (GetLocaleInfo(MAKELCID(langID, SORT_DEFAULT),
  611. LOCALE_SABBREVLANGNAME | LOCALE_NOUSEROVERRIDE,
  612. szData,
  613. ARRAYSIZE(szData)))
  614. {
  615. //
  616. // Make Uppercase
  617. //
  618. if (g_OSWIN95)
  619. {
  620. szData[0] -= 0x20;
  621. szData[1] -= 0x20;
  622. }
  623. //
  624. // Only use the first two characters.
  625. //
  626. szData[2] = TEXT('\0');
  627. }
  628. else
  629. {
  630. //
  631. // Id wasn't found. Use question marks.
  632. //
  633. szData[0] = TEXT('?');
  634. szData[1] = TEXT('?');
  635. szData[2] = TEXT('\0');
  636. }
  637. if(SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, 0))
  638. {
  639. if( (hfont = CreateFontIndirect(&lf)) )
  640. {
  641. UINT cxSmIcon = GetSystemMetrics( SM_CXSMICON );
  642. UINT cySmIcon = GetSystemMetrics( SM_CYSMICON );
  643. hdcScreen = GetDC(NULL);
  644. hdc = CreateCompatibleDC(hdcScreen);
  645. hbmColour = CreateCompatibleBitmap(hdcScreen, cxSmIcon, cySmIcon);
  646. ReleaseDC( NULL, hdcScreen);
  647. if (hbmColour && hdc)
  648. {
  649. hbmMono = CreateBitmap(cxSmIcon, cySmIcon, 1, 1, NULL);
  650. if (hbmMono)
  651. {
  652. hbmOld = SelectObject( hdc, hbmColour);
  653. rc.left = 0;
  654. rc.top = 0;
  655. rc.right = cxSmIcon;
  656. rc.bottom = cySmIcon;
  657. rgbBk = SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
  658. rgbText = SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
  659. ExtTextOut(hdc,
  660. rc.left,
  661. rc.top,
  662. ETO_OPAQUE,
  663. &rc,
  664. TEXT(""),
  665. 0,
  666. NULL);
  667. SelectObject( hdc, GetStockObject(DEFAULT_GUI_FONT));
  668. hfontOld = SelectObject( hdc, hfont);
  669. DrawText(hdc,
  670. szData,
  671. 2,
  672. &rc,
  673. DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  674. if (g_bShowRtL)
  675. MirrorBitmapInDC(hdc, hbmColour);
  676. SelectObject( hdc, hbmMono);
  677. PatBlt(hdc, 0, 0, cxSmIcon, cySmIcon, BLACKNESS);
  678. ii.fIcon = TRUE;
  679. ii.xHotspot = 0;
  680. ii.yHotspot = 0;
  681. ii.hbmColor = hbmColour;
  682. ii.hbmMask = hbmMono;
  683. hicon = CreateIconIndirect(&ii);
  684. SelectObject(hdc, hbmOld);
  685. DeleteObject(hbmMono);
  686. SelectObject(hdc, hfontOld);
  687. }
  688. DeleteObject(hbmColour);
  689. DeleteDC(hdc);
  690. }
  691. DeleteObject(hfont);
  692. }
  693. }
  694. return hicon;
  695. }
  696. ////////////////////////////////////////////////////////////////////////////
  697. //
  698. // GetLanguageName
  699. //
  700. ////////////////////////////////////////////////////////////////////////////
  701. BOOL GetLanguageName(
  702. LCID lcid,
  703. LPTSTR lpLangName,
  704. UINT cchLangName)
  705. {
  706. BOOL bRet = TRUE;
  707. if (g_OSWIN95)
  708. {
  709. if (!GetLocaleInfo(lcid,
  710. LOCALE_SLANGUAGE,
  711. lpLangName,
  712. cchLangName))
  713. {
  714. LoadString(hInstance, IDS_LOCALE_UNKNOWN, lpLangName, cchLangName);
  715. bRet = FALSE;
  716. }
  717. }
  718. else
  719. {
  720. WCHAR wszLangName[MAX_PATH];
  721. if (!GetLocaleInfoW(lcid,
  722. LOCALE_SLANGUAGE,
  723. wszLangName,
  724. ARRAYSIZE(wszLangName)))
  725. {
  726. LoadString(hInstance, IDS_LOCALE_UNKNOWN, lpLangName, cchLangName);
  727. bRet = FALSE;
  728. }
  729. else
  730. {
  731. StringCchCopy(lpLangName, cchLangName, wszLangName);
  732. }
  733. }
  734. return bRet;
  735. }
  736. ////////////////////////////////////////////////////////////////////////////
  737. //
  738. // CreateTVItemNode
  739. //
  740. ////////////////////////////////////////////////////////////////////////////
  741. LPTVITEMNODE CreateTVItemNode(DWORD dwLangID)
  742. {
  743. LPTVITEMNODE pTVItemNode;
  744. HANDLE hItemNode;
  745. //
  746. // Create the new node.
  747. //
  748. if (!(pTVItemNode = (LPTVITEMNODE) LocalAlloc(LPTR, sizeof(TVITEMNODE))))
  749. {
  750. return (NULL);
  751. }
  752. g_cTVItemSize++;
  753. //
  754. // Fill in the new node with the appropriate info.
  755. //
  756. pTVItemNode->dwLangID = dwLangID;
  757. pTVItemNode->bDefLang = FALSE;
  758. pTVItemNode->iIdxTips = -1;
  759. pTVItemNode->atmDefTipName = 0;
  760. pTVItemNode->atmTVItemName = 0;
  761. pTVItemNode->lParam = 0;
  762. //
  763. // Return the pointer to the new node.
  764. //
  765. return (pTVItemNode);
  766. }
  767. ////////////////////////////////////////////////////////////////////////////
  768. //
  769. // RemoveTVItemNode
  770. //
  771. ////////////////////////////////////////////////////////////////////////////
  772. void RemoveTVItemNode(
  773. LPTVITEMNODE pTVItemNode)
  774. {
  775. if (pTVItemNode)
  776. {
  777. if (pTVItemNode->uInputType & INPUT_TYPE_KBD)
  778. {
  779. int idxSel = -1;
  780. TCHAR szItemName[MAX_PATH * 2];
  781. HWND hwndDefList = GetDlgItem(g_hDlg, IDC_LOCALE_DEFAULT);
  782. GetLanguageName(MAKELCID(pTVItemNode->dwLangID, SORT_DEFAULT),
  783. szItemName,
  784. ARRAYSIZE(szItemName));
  785. StringCchCat(szItemName, ARRAYSIZE(szItemName), TEXT(" - "));
  786. GetAtomName(pTVItemNode->atmTVItemName,
  787. szItemName + lstrlen(szItemName), MAX_PATH);
  788. idxSel = ComboBox_FindString(hwndDefList, 0, szItemName);
  789. if (idxSel != CB_ERR)
  790. {
  791. ComboBox_DeleteString(hwndDefList, idxSel);
  792. }
  793. }
  794. if (pTVItemNode->atmTVItemName)
  795. DeleteAtom(pTVItemNode->atmTVItemName);
  796. if (pTVItemNode->atmDefTipName)
  797. DeleteAtom(pTVItemNode->atmDefTipName);
  798. LocalFree(pTVItemNode);
  799. g_cTVItemSize--;
  800. }
  801. }
  802. ////////////////////////////////////////////////////////////////////////////
  803. //
  804. // Locale_AddToLinkedList
  805. //
  806. // Adds an Input Locale to the main g_lpLang array.
  807. //
  808. ////////////////////////////////////////////////////////////////////////////
  809. LPLANGNODE Locale_AddToLinkedList(
  810. UINT idx,
  811. HKL hkl)
  812. {
  813. LPINPUTLANG pInpLang = &g_lpLang[idx];
  814. LPLANGNODE pLangNode;
  815. LPLANGNODE pTemp;
  816. HANDLE hLangNode;
  817. //
  818. // Create the new node.
  819. //
  820. if (!(hLangNode = LocalAlloc(LHND, sizeof(LANGNODE))))
  821. {
  822. return (NULL);
  823. }
  824. pLangNode = LocalLock(hLangNode);
  825. //
  826. // Fill in the new node with the appropriate info.
  827. //
  828. pLangNode->wStatus = 0;
  829. pLangNode->iLayout = (UINT)(-1);
  830. pLangNode->hkl = hkl;
  831. pLangNode->hklUnload = hkl;
  832. pLangNode->iLang = idx;
  833. pLangNode->hLangNode = hLangNode;
  834. pLangNode->pNext = NULL;
  835. pLangNode->nIconIME = -1;
  836. //
  837. // If an hkl is given, see if it's an IME. If so, mark the status bit.
  838. //
  839. if ((hkl) && ((HIWORD(hkl) & 0xf000) == 0xe000))
  840. {
  841. pLangNode->wStatus |= LANG_IME;
  842. }
  843. //
  844. // Put the new node in the list.
  845. //
  846. pTemp = pInpLang->pNext;
  847. if (pTemp == NULL)
  848. {
  849. pInpLang->pNext = pLangNode;
  850. }
  851. else
  852. {
  853. while (pTemp->pNext != NULL)
  854. {
  855. pTemp = pTemp->pNext;
  856. }
  857. pTemp->pNext = pLangNode;
  858. }
  859. //
  860. // Increment the count.
  861. //
  862. pInpLang->iNumCount++;
  863. //
  864. // Return the pointer to the new node.
  865. //
  866. return (pLangNode);
  867. }
  868. ////////////////////////////////////////////////////////////////////////////
  869. //
  870. // Locale_RemoveFromLinkedList
  871. //
  872. // Removes a link from the linked list.
  873. //
  874. ////////////////////////////////////////////////////////////////////////////
  875. void Locale_RemoveFromLinkedList(
  876. LPLANGNODE pLangNode)
  877. {
  878. LPINPUTLANG pInpLang;
  879. LPLANGNODE pPrev;
  880. LPLANGNODE pCur;
  881. HANDLE hCur;
  882. pInpLang = &g_lpLang[pLangNode->iLang];
  883. //
  884. // Find the node in the list.
  885. //
  886. pPrev = NULL;
  887. pCur = pInpLang->pNext;
  888. while (pCur && (pCur != pLangNode))
  889. {
  890. pPrev = pCur;
  891. pCur = pCur->pNext;
  892. }
  893. if (pPrev == NULL)
  894. {
  895. if (pCur == pLangNode)
  896. {
  897. pInpLang->pNext = pCur->pNext;
  898. }
  899. else
  900. {
  901. pInpLang->pNext = NULL;
  902. }
  903. }
  904. else if (pCur)
  905. {
  906. pPrev->pNext = pCur->pNext;
  907. }
  908. //
  909. // Remove the node from the list.
  910. //
  911. if (pCur)
  912. {
  913. hCur = pCur->hLangNode;
  914. LocalUnlock(hCur);
  915. LocalFree(hCur);
  916. }
  917. }
  918. ////////////////////////////////////////////////////////////////////////////
  919. //
  920. // Locale_GetImeHotKeyInfo
  921. //
  922. // Initializes array for CHS/CHT specific IME related hotkey items.
  923. //
  924. ////////////////////////////////////////////////////////////////////////////
  925. int Locale_GetImeHotKeyInfo(
  926. HWND hwnd,
  927. LPHOTKEYINFO *aImeHotKey)
  928. {
  929. HWND hwndTV = g_hwndTV;
  930. LPLANGNODE pLangNode;
  931. LANGID LangID;
  932. int ctr;
  933. BOOL fCHS, fCHT;
  934. TV_ITEM tvItem;
  935. HTREEITEM hItem;
  936. HTREEITEM hLangItem;
  937. HTREEITEM hGroupItem;
  938. fCHS = fCHT = FALSE;
  939. ctr = 0;
  940. //
  941. // Check if the CHS or CHT layouts are loaded.
  942. //
  943. tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
  944. for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
  945. hLangItem != NULL ;
  946. hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem))
  947. {
  948. for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem);
  949. hGroupItem != NULL;
  950. hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem))
  951. {
  952. for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
  953. hItem != NULL;
  954. hItem = TreeView_GetNextSibling(hwndTV, hItem))
  955. {
  956. LPTVITEMNODE pTVItemNode;
  957. tvItem.hItem = hItem;
  958. if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
  959. {
  960. pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
  961. pLangNode = (LPLANGNODE)pTVItemNode->lParam;
  962. if (pLangNode == NULL)
  963. continue;
  964. }
  965. else
  966. continue;
  967. LangID = LOWORD(g_lpLayout[pLangNode->iLayout].dwID);
  968. if ( PRIMARYLANGID(LangID) == LANG_CHINESE )
  969. {
  970. if ( SUBLANGID(LangID) == SUBLANG_CHINESE_SIMPLIFIED)
  971. fCHS = TRUE;
  972. else if ( SUBLANGID(LangID) == SUBLANG_CHINESE_TRADITIONAL )
  973. fCHT = TRUE;
  974. }
  975. if (fCHS && fCHT)
  976. break;
  977. }
  978. }
  979. }
  980. if ( (fCHS == TRUE) && (fCHT == TRUE) )
  981. {
  982. // Both CHS and CHT IMEs are Loaded
  983. *aImeHotKey = g_aImeHotKeyCHxBoth;
  984. return(sizeof(g_aImeHotKeyCHxBoth) / sizeof(HOTKEYINFO) );
  985. }
  986. else
  987. {
  988. if ( fCHS == TRUE )
  989. {
  990. // only CHS IMEs are loaded
  991. *aImeHotKey = g_aImeHotKey0804;
  992. return (sizeof(g_aImeHotKey0804) / sizeof(HOTKEYINFO));
  993. }
  994. if ( fCHT == TRUE )
  995. {
  996. // Only CHT IMEs are loaded.
  997. *aImeHotKey = g_aImeHotKey0404;
  998. return (sizeof(g_aImeHotKey0404) / sizeof(HOTKEYINFO));
  999. }
  1000. }
  1001. // all other cases, No Chinese IME is loaded.
  1002. *aImeHotKey=NULL;
  1003. return (0);
  1004. }
  1005. ////////////////////////////////////////////////////////////////////////////
  1006. //
  1007. // Locale_EnumChildWndProc
  1008. //
  1009. // disable all controls.
  1010. ////////////////////////////////////////////////////////////////////////////
  1011. BOOL CALLBACK Locale_EnumChildWndProc(HWND hwnd, LPARAM lParam)
  1012. {
  1013. EnableWindow(hwnd, FALSE);
  1014. ShowWindow(hwnd, SW_HIDE);
  1015. return TRUE;
  1016. }
  1017. ////////////////////////////////////////////////////////////////////////////
  1018. //
  1019. // Locale_EnablePane
  1020. //
  1021. // The controls in "iControl" are the controls that get disabled if the
  1022. // pane can't come up.
  1023. //
  1024. ////////////////////////////////////////////////////////////////////////////
  1025. void Locale_EnablePane(
  1026. HWND hwnd,
  1027. BOOL bEnable,
  1028. UINT DisableId)
  1029. {
  1030. if (!bEnable)
  1031. {
  1032. if (DisableId == IDC_KBDL_DISABLED_2)
  1033. {
  1034. //
  1035. // Disable all controls.
  1036. //
  1037. EnumChildWindows(hwnd, (WNDENUMPROC)Locale_EnumChildWndProc, 0);
  1038. ShowWindow(GetDlgItem(hwnd, IDC_KBDL_DISABLED_2), SW_SHOW);
  1039. EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DISABLED_2), TRUE);
  1040. }
  1041. else
  1042. {
  1043. if (!g_iEnabledTips)
  1044. {
  1045. //
  1046. // Disable all controls.
  1047. //
  1048. EnumChildWindows(hwnd, (WNDENUMPROC)Locale_EnumChildWndProc, 0);
  1049. ShowWindow(GetDlgItem(hwnd, IDC_KBDL_DISABLED), SW_SHOW);
  1050. EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DISABLED), TRUE);
  1051. }
  1052. else
  1053. {
  1054. //
  1055. // Disable Add, Property, Hotkey and default language setting controls.
  1056. //
  1057. EnableWindow(GetDlgItem(hwnd, IDC_LOCALE_DEFAULT), FALSE);
  1058. EnableWindow(GetDlgItem(hwnd, IDC_KBDL_ADD), FALSE);
  1059. EnableWindow(GetDlgItem(hwnd, IDC_KBDL_EDIT), FALSE);
  1060. EnableWindow(GetDlgItem(hwnd, IDC_HOTKEY_SETTING), FALSE);
  1061. }
  1062. }
  1063. }
  1064. return;
  1065. }
  1066. ////////////////////////////////////////////////////////////////////////////
  1067. //
  1068. // Locale_KillPaneDialog
  1069. //
  1070. // Processing for a WM_DESTROY message.
  1071. //
  1072. ////////////////////////////////////////////////////////////////////////////
  1073. void Locale_KillPaneDialog(
  1074. HWND hwnd)
  1075. {
  1076. UINT ctr, iCount;
  1077. HANDLE hCur;
  1078. LPLANGNODE pCur;
  1079. LPHOTKEYINFO aImeHotKey;
  1080. TV_ITEM tvItem;
  1081. HTREEITEM hLangItem;
  1082. HTREEITEM hGroupItem;
  1083. HTREEITEM hItem;
  1084. LPTVITEMNODE pTVItemNode;
  1085. HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST);
  1086. if (g_bCoInit)
  1087. CoUninitialize();
  1088. //
  1089. // Delete all hot key atoms and free up the hotkey arrays.
  1090. //
  1091. if (g_SwitchLangHotKey.atmHotKeyName)
  1092. {
  1093. DeleteAtom(g_SwitchLangHotKey.atmHotKeyName);
  1094. }
  1095. iCount = Locale_GetImeHotKeyInfo(hwnd, &aImeHotKey);
  1096. for (ctr = 0; ctr < iCount; ctr++)
  1097. {
  1098. if (aImeHotKey[ctr].atmHotKeyName)
  1099. {
  1100. DeleteAtom(aImeHotKey[ctr].atmHotKeyName);
  1101. }
  1102. }
  1103. for (ctr = 0; ctr < DSWITCH_HOTKEY_SIZE; ctr++)
  1104. {
  1105. if (g_aDirectSwitchHotKey[ctr].atmHotKeyName)
  1106. {
  1107. DeleteAtom(g_aDirectSwitchHotKey[ctr].atmHotKeyName);
  1108. }
  1109. }
  1110. //
  1111. // Delete all TreeView node.
  1112. //
  1113. tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
  1114. for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
  1115. hLangItem != NULL ;
  1116. hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem)
  1117. )
  1118. {
  1119. for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem);
  1120. hGroupItem != NULL;
  1121. hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem))
  1122. {
  1123. for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
  1124. hItem != NULL;
  1125. hItem = TreeView_GetNextSibling(hwndTV, hItem))
  1126. {
  1127. tvItem.hItem = hItem;
  1128. if (TreeView_GetItem(hwndTV, &tvItem))
  1129. {
  1130. pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
  1131. RemoveTVItemNode(pTVItemNode);
  1132. }
  1133. }
  1134. tvItem.hItem = hGroupItem;
  1135. if (TreeView_GetItem(hwndTV, &tvItem))
  1136. {
  1137. pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
  1138. if (TreeView_GetItem(hwndTV, &tvItem))
  1139. {
  1140. RemoveTVItemNode(pTVItemNode);
  1141. continue;
  1142. }
  1143. }
  1144. }
  1145. tvItem.hItem = hLangItem;
  1146. if (TreeView_GetItem(hwndTV, &tvItem))
  1147. {
  1148. pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
  1149. RemoveTVItemNode(pTVItemNode);
  1150. }
  1151. }
  1152. #ifdef DEBUG
  1153. if (g_cTVItemSize)
  1154. {
  1155. MessageBox(NULL, TEXT("Error is occurred during terminate window"), NULL, MB_OK);
  1156. }
  1157. #endif
  1158. //
  1159. // Delete all Language Name atoms and free the g_lpLang array.
  1160. //
  1161. for (ctr = 0; ctr < g_iLangBuff; ctr++)
  1162. {
  1163. if (g_lpLang[ctr].atmLanguageName)
  1164. {
  1165. DeleteAtom(g_lpLang[ctr].atmLanguageName);
  1166. }
  1167. pCur = g_lpLang[ctr].pNext;
  1168. g_lpLang[ctr].pNext = NULL;
  1169. while (pCur)
  1170. {
  1171. hCur = pCur->hLangNode;
  1172. pCur = pCur->pNext;
  1173. LocalUnlock(hCur);
  1174. LocalFree(hCur);
  1175. }
  1176. }
  1177. if (g_hImageList != NULL)
  1178. {
  1179. TreeView_SetImageList(hwndTV, NULL, TVSIL_NORMAL);
  1180. ImageList_Destroy(g_hImageList);
  1181. }
  1182. LocalUnlock(g_hLang);
  1183. LocalFree(g_hLang);
  1184. //
  1185. // Delete all layout text and layout file atoms and free the
  1186. // g_lpLayout array.
  1187. //
  1188. for (ctr = 0; ctr < g_iLayoutBuff; ctr++)
  1189. {
  1190. if (g_lpLayout[ctr].atmLayoutText)
  1191. {
  1192. DeleteAtom(g_lpLayout[ctr].atmLayoutText);
  1193. }
  1194. if (g_lpLayout[ctr].atmLayoutFile)
  1195. {
  1196. DeleteAtom(g_lpLayout[ctr].atmLayoutFile);
  1197. }
  1198. if (g_lpLayout[ctr].atmIMEFile)
  1199. {
  1200. DeleteAtom(g_lpLayout[ctr].atmIMEFile);
  1201. }
  1202. }
  1203. LocalUnlock(g_hLayout);
  1204. LocalFree(g_hLayout);
  1205. //
  1206. // Make sure the mutex is released.
  1207. //
  1208. if (g_hMutex)
  1209. {
  1210. ReleaseMutex(g_hMutex);
  1211. }
  1212. }
  1213. ////////////////////////////////////////////////////////////////////////////
  1214. //
  1215. // SelectDefaultKbdLayoutAsBold
  1216. //
  1217. ////////////////////////////////////////////////////////////////////////////
  1218. void SelectDefaultKbdLayoutAsBold(
  1219. HWND hwndTV,
  1220. HTREEITEM hTVItem)
  1221. {
  1222. TV_ITEM tvItem;
  1223. TCHAR szItemName[MAX_PATH];
  1224. TCHAR szLayoutName[MAX_PATH];
  1225. TreeView_SelectItem(hwndTV, hTVItem);
  1226. tvItem.mask = TVIF_TEXT | TVIF_PARAM | TVIF_STATE;
  1227. tvItem.hItem = hTVItem;
  1228. tvItem.state = 0;
  1229. tvItem.stateMask = TVIS_BOLD;
  1230. tvItem.pszText = szItemName;
  1231. tvItem.cchTextMax = sizeof(szItemName) / sizeof(TCHAR);
  1232. if (TreeView_GetItem(hwndTV, &tvItem))
  1233. {
  1234. LPTVITEMNODE pTVItemNode;
  1235. pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
  1236. if (!pTVItemNode)
  1237. return;
  1238. if (g_bCHSystem)
  1239. {
  1240. GetAtomName(pTVItemNode->atmTVItemName, szLayoutName, ARRAYSIZE(szLayoutName));
  1241. StringCchCat(szLayoutName, ARRAYSIZE(szLayoutName), szDefault);
  1242. tvItem.pszText = szLayoutName;
  1243. }
  1244. tvItem.state |= TVIS_BOLD;
  1245. SendMessage(hwndTV, TVM_SETITEM, 0, (LPARAM) &tvItem);
  1246. }
  1247. }
  1248. ////////////////////////////////////////////////////////////////////////////
  1249. //
  1250. // FindTVLangItem
  1251. //
  1252. ////////////////////////////////////////////////////////////////////////////
  1253. HTREEITEM
  1254. FindTVLangItem(DWORD dwLangID, LPTSTR lpLangText)
  1255. {
  1256. HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST);
  1257. TV_ITEM tvItem;
  1258. HTREEITEM hLangItem;
  1259. LPTVITEMNODE pTVLangNode;
  1260. TCHAR szLangName[MAX_PATH];
  1261. tvItem.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_PARAM;
  1262. tvItem.pszText = szLangName;
  1263. tvItem.cchTextMax = sizeof(szLangName) / sizeof(TCHAR);
  1264. for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
  1265. hLangItem != NULL ;
  1266. hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem)
  1267. )
  1268. {
  1269. tvItem.hItem = hLangItem;
  1270. if (TreeView_GetItem(hwndTV, &tvItem))
  1271. {
  1272. int iSize = lstrlen(lpLangText);
  1273. pTVLangNode = (LPTVITEMNODE) tvItem.lParam;
  1274. if (!pTVLangNode)
  1275. {
  1276. continue;
  1277. }
  1278. *(szLangName + min(iSize, tvItem.cchTextMax)) = TEXT('\0');
  1279. if (!CompareStringTIP(szLangName, lpLangText) ||
  1280. (dwLangID && (pTVLangNode->dwLangID == dwLangID)))
  1281. {
  1282. return hLangItem;
  1283. }
  1284. }
  1285. }
  1286. return NULL;
  1287. }
  1288. ////////////////////////////////////////////////////////////////////////////
  1289. //
  1290. // AddTreeViewItems
  1291. //
  1292. ////////////////////////////////////////////////////////////////////////////
  1293. HTREEITEM AddTreeViewItems(
  1294. UINT uItemType,
  1295. LPTSTR lpLangText,
  1296. LPTSTR lpGroupText,
  1297. LPTSTR lpTipText,
  1298. LPTVITEMNODE *ppTVItemNode)
  1299. {
  1300. HTREEITEM hTVItem;
  1301. HTREEITEM hTVItem2;
  1302. HTREEITEM hItem;
  1303. HTREEITEM hLangItem = NULL;
  1304. HTREEITEM hGroupItem;
  1305. TV_ITEM tvItem;
  1306. TV_INSERTSTRUCT tvIns;
  1307. HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST);
  1308. HWND hwndDefList = GetDlgItem(g_hDlg, IDC_LOCALE_DEFAULT);
  1309. TCHAR szDefItem[MAX_PATH];
  1310. TCHAR szLangName[ MAX_PATH ];
  1311. LPTVITEMNODE pTVLangNode;
  1312. LPTVITEMNODE pTVItemNode;
  1313. BOOL bFoundLang = FALSE;
  1314. BOOL bFindGroup = FALSE;
  1315. LPLANGNODE pLangNode;
  1316. pTVItemNode = *ppTVItemNode;
  1317. if (!pTVItemNode)
  1318. return NULL;
  1319. // We only want to add an lang item if it is not already there.
  1320. //
  1321. tvItem.mask = TVIF_HANDLE | TVIF_TEXT | TVIF_PARAM;
  1322. tvItem.state = 0;
  1323. tvItem.stateMask = 0;
  1324. tvItem.pszText = szLangName;
  1325. tvItem.cchTextMax = sizeof(szLangName) / sizeof(TCHAR);
  1326. for (hItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
  1327. hItem != NULL ;
  1328. hItem = TreeView_GetNextSibling(hwndTV, hItem)
  1329. )
  1330. {
  1331. tvItem.hItem = hItem;
  1332. if (TreeView_GetItem(hwndTV, &tvItem))
  1333. {
  1334. pTVLangNode = (LPTVITEMNODE) tvItem.lParam;
  1335. if (!pTVLangNode)
  1336. {
  1337. continue;
  1338. }
  1339. if (pTVLangNode->dwLangID == pTVItemNode->dwLangID)
  1340. {
  1341. // We found a match!
  1342. //
  1343. hLangItem = hItem;
  1344. bFoundLang = TRUE;
  1345. if (!pTVLangNode->atmDefTipName && pTVItemNode->atmDefTipName)
  1346. {
  1347. TCHAR szDefTip[DESC_MAX];
  1348. GetAtomName(pTVItemNode->atmDefTipName, szDefTip, ARRAYSIZE(szDefTip));
  1349. pTVLangNode->atmDefTipName = AddAtom(szDefTip);
  1350. }
  1351. if (!(pTVLangNode->hklSub) && pTVItemNode->hklSub)
  1352. pTVLangNode->hklSub = pTVItemNode->hklSub;
  1353. }
  1354. }
  1355. }
  1356. if (bFoundLang && (uItemType & TV_ITEM_TYPE_LANG))
  1357. {
  1358. RemoveTVItemNode(pTVItemNode);
  1359. *ppTVItemNode = NULL;
  1360. return hItem;
  1361. }
  1362. tvItem.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM | TVIF_STATE;
  1363. tvItem.lParam = (LPARAM) pTVItemNode;
  1364. if (uItemType & TV_ITEM_TYPE_LANG)
  1365. {
  1366. HICON hIcon = NULL;
  1367. int iImage;
  1368. hIcon = CreateLangIcon(hwndTV, LOWORD(pTVItemNode->dwLangID));
  1369. if (hIcon)
  1370. {
  1371. iImage = ImageList_AddIcon(g_hImageList, hIcon);
  1372. tvItem.iImage = iImage;
  1373. tvItem.iSelectedImage = iImage;
  1374. }
  1375. pTVItemNode->atmTVItemName = AddAtom(lpLangText);
  1376. pTVItemNode->uInputType |= TV_ITEM_TYPE_LANG;
  1377. tvItem.pszText = lpLangText;
  1378. tvItem.cchTextMax = sizeof(szLangName) / sizeof(TCHAR);
  1379. tvIns.item = tvItem;
  1380. tvIns.hInsertAfter = TVI_SORT;
  1381. tvIns.hParent = g_hTVRoot;
  1382. hTVItem = (HTREEITEM) SendMessage(hwndTV, TVM_INSERTITEM, 0, (LPARAM)(LPTV_INSERTSTRUCT) &tvIns);
  1383. return hTVItem;
  1384. }
  1385. if (hLangItem == NULL)
  1386. return NULL;
  1387. // Find the group node of input type
  1388. for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem) ;
  1389. hGroupItem != NULL ;
  1390. hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem)
  1391. )
  1392. {
  1393. tvItem.hItem = hGroupItem;
  1394. if (TreeView_GetItem(hwndTV, &tvItem))
  1395. {
  1396. if (!lstrcmp(tvItem.pszText, lpGroupText))
  1397. {
  1398. bFindGroup = TRUE;
  1399. break;
  1400. }
  1401. }
  1402. }
  1403. tvItem.lParam = (LPARAM) pTVItemNode;
  1404. pTVItemNode->uInputType |= uItemType;
  1405. g_iInputs++;
  1406. if (!bFindGroup)
  1407. {
  1408. LPTVITEMNODE pTVGroupNode;
  1409. if (pTVItemNode->bNoAddCat)
  1410. {
  1411. pTVGroupNode = pTVItemNode;
  1412. }
  1413. else
  1414. {
  1415. if (!(pTVGroupNode = CreateTVItemNode(pTVItemNode->dwLangID)))
  1416. return NULL;
  1417. pTVGroupNode->dwLangID = pTVItemNode->dwLangID;
  1418. pTVGroupNode->uInputType = pTVItemNode->uInputType | TV_ITEM_TYPE_GROUP;
  1419. pTVGroupNode->atmTVItemName = AddAtom(lpTipText);
  1420. tvItem.lParam = (LPARAM) pTVGroupNode;
  1421. }
  1422. tvItem.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM | TVIF_STATE;
  1423. tvItem.state = 0;
  1424. if (pTVItemNode->uInputType & TV_ITEM_TYPE_KBD)
  1425. {
  1426. tvItem.iImage = IMAGEID_KEYBOARD;
  1427. tvItem.iSelectedImage = IMAGEID_KEYBOARD;
  1428. }
  1429. else if (pTVItemNode->uInputType & TV_ITEM_TYPE_PEN)
  1430. {
  1431. tvItem.iImage = IMAGEID_PEN;
  1432. tvItem.iSelectedImage = IMAGEID_PEN;
  1433. }
  1434. else if (pTVItemNode->uInputType & TV_ITEM_TYPE_SPEECH)
  1435. {
  1436. tvItem.iImage = IMAGEID_SPEECH;
  1437. tvItem.iSelectedImage = IMAGEID_SPEECH;
  1438. }
  1439. else if (pTVItemNode->uInputType & TV_ITEM_TYPE_SMARTTAG)
  1440. {
  1441. tvItem.iImage = IMAGEID_SMARTTAG;
  1442. tvItem.iSelectedImage = IMAGEID_SMARTTAG;
  1443. }
  1444. else
  1445. {
  1446. tvItem.iImage = IMAGEID_EXTERNAL;
  1447. tvItem.iSelectedImage = IMAGEID_EXTERNAL;
  1448. }
  1449. if (pTVItemNode->bNoAddCat)
  1450. tvItem.pszText = lpTipText;
  1451. else
  1452. tvItem.pszText = lpGroupText;
  1453. tvItem.cchTextMax = MAX_PATH;
  1454. tvIns.item = tvItem;
  1455. tvIns.hInsertAfter = TVI_SORT;
  1456. tvIns.hParent = hLangItem;
  1457. hGroupItem = (HTREEITEM) SendMessage(hwndTV, TVM_INSERTITEM, 0, (LPARAM)(LPTV_INSERTSTRUCT) &tvIns);
  1458. hTVItem = TreeView_GetParent(hwndTV, hGroupItem);
  1459. TreeView_Expand(hwndTV, hTVItem, TVE_EXPAND);
  1460. }
  1461. if (pTVItemNode->bNoAddCat)
  1462. return hGroupItem;
  1463. //
  1464. // Check layout name whether it is already added on the treeview.
  1465. //
  1466. for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
  1467. hItem != NULL;
  1468. hItem = TreeView_GetNextSibling(hwndTV, hItem))
  1469. {
  1470. tvItem.hItem = hItem;
  1471. if (TreeView_GetItem(hwndTV, &tvItem))
  1472. {
  1473. if (!CompareStringTIP(tvItem.pszText, lpTipText))
  1474. {
  1475. if (pTVItemNode->lParam)
  1476. Locale_RemoveFromLinkedList((LPLANGNODE)pTVItemNode->lParam);
  1477. RemoveTVItemNode(pTVItemNode);
  1478. return NULL;
  1479. }
  1480. }
  1481. }
  1482. pTVItemNode->atmTVItemName = AddAtom(lpTipText);
  1483. tvItem.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM | TVIF_STATE;
  1484. tvItem.state = 0;
  1485. tvItem.stateMask = TVIS_BOLD;
  1486. tvItem.iImage = IMAGEID_TIPITEMS;
  1487. tvItem.iSelectedImage = IMAGEID_TIPITEMS;
  1488. tvItem.lParam = (LPARAM) pTVItemNode;
  1489. tvItem.pszText = lpTipText;
  1490. tvItem.cchTextMax = MAX_PATH;
  1491. tvIns.item = tvItem;
  1492. tvIns.hInsertAfter = TVI_SORT;
  1493. tvIns.hParent = hGroupItem;
  1494. hTVItem = (HTREEITEM) SendMessage(hwndTV, TVM_INSERTITEM, 0, (LPARAM)(LPTV_INSERTSTRUCT) &tvIns);
  1495. pLangNode = (LPLANGNODE)pTVItemNode->lParam;
  1496. //
  1497. // Adding the available default setting languages
  1498. //
  1499. if ((pTVItemNode->uInputType == TV_ITEM_TYPE_KBD) ||
  1500. (pTVItemNode->uInputType & (TV_ITEM_TYPE_KBD|TV_ITEM_TYPE_TIP) && pTVItemNode->hklSub))
  1501. {
  1502. StringCchCopy(szDefItem, ARRAYSIZE(szDefItem), lpLangText);
  1503. StringCchCat(szDefItem, ARRAYSIZE(szDefItem), TEXT(" - "));
  1504. StringCchCat(szDefItem, ARRAYSIZE(szDefItem), lpTipText);
  1505. if (ComboBox_FindStringExact(hwndDefList, 0, szDefItem) == CB_ERR)
  1506. ComboBox_AddString(hwndDefList, szDefItem);
  1507. }
  1508. #if 0
  1509. if (pTVItemNode->hklSub)
  1510. {
  1511. TV_ITEM tvItem2;
  1512. tvItem2.mask = TVIF_HANDLE | TVIF_PARAM;
  1513. if (tvItem2.hItem = FindTVLangItem(pTVItemNode->dwLangID, NULL))
  1514. {
  1515. if (TreeView_GetItem(hwndTV, &tvItem2) && tvItem2.lParam)
  1516. {
  1517. pTVItemNode = (LPTVITEMNODE) tvItem2.lParam;
  1518. pLangNode = (LPLANGNODE)pTVItemNode->lParam;
  1519. }
  1520. }
  1521. }
  1522. #endif
  1523. if (pLangNode && (pLangNode->wStatus & LANG_DEFAULT))
  1524. {
  1525. //
  1526. // Select the default layout item as bold
  1527. //
  1528. SelectDefaultKbdLayoutAsBold(hwndTV, hTVItem);
  1529. TreeView_Expand(hwndTV, hTVItem, TVE_EXPAND);
  1530. tvItem.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM | TVIF_STATE;
  1531. tvItem.hItem = hLangItem;
  1532. tvItem.pszText = szLangName;
  1533. tvItem.cchTextMax = sizeof(szLangName) / sizeof(TCHAR);
  1534. if (TreeView_GetItem(hwndTV, &tvItem))
  1535. {
  1536. LPTVITEMNODE pTVLangItemNode;
  1537. int idxSel = -1;
  1538. StringCchCopy(szDefItem, ARRAYSIZE(szDefItem), lpLangText);
  1539. StringCchCat(szDefItem, ARRAYSIZE(szDefItem), TEXT(" - "));
  1540. StringCchCat(szDefItem, ARRAYSIZE(szDefItem), lpTipText);
  1541. //
  1542. // Set the default locale selection.
  1543. //
  1544. //
  1545. if ((idxSel = ComboBox_FindStringExact(hwndDefList, 0, szDefItem)) == CB_ERR)
  1546. {
  1547. // Simply set the current selection to be the first entry
  1548. // in the list.
  1549. //
  1550. ComboBox_SetCurSel(hwndDefList, 0);
  1551. }
  1552. else
  1553. ComboBox_SetCurSel(hwndDefList, idxSel);
  1554. if (pTVLangItemNode = (LPTVITEMNODE) tvItem.lParam)
  1555. {
  1556. pTVLangItemNode->bDefLang = TRUE;
  1557. pTVLangItemNode->atmDefTipName = AddAtom(lpTipText);
  1558. tvItem.state |= TVIS_BOLD;
  1559. }
  1560. StringCchCopy(tvItem.pszText, tvItem.cchTextMax, lpLangText);
  1561. //
  1562. // No more adding default description
  1563. //
  1564. //StringCchCat(tvItem.pszText, ARRAYSIZE(tvItem.cchTextMax), szDefault);
  1565. SendMessage(hwndTV, TVM_SETITEM, 0, (LPARAM) &tvItem);
  1566. TreeView_SelectSetFirstVisible(hwndTV, hLangItem);
  1567. }
  1568. }
  1569. if (hTVItem2 = TreeView_GetParent(hwndTV, hTVItem))
  1570. TreeView_Expand(hwndTV, hTVItem2, TVE_EXPAND);
  1571. return hTVItem;
  1572. }
  1573. ////////////////////////////////////////////////////////////////////////////
  1574. //
  1575. // UpdateDefaultTVLangItem
  1576. //
  1577. ////////////////////////////////////////////////////////////////////////////
  1578. BOOL UpdateDefaultTVLangItem(
  1579. DWORD dwLangID,
  1580. LPTSTR lpDefTip,
  1581. BOOL bDefLang,
  1582. BOOL bSubhkl)
  1583. {
  1584. HTREEITEM hItem;
  1585. TV_ITEM tvItem;
  1586. HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST);
  1587. TCHAR szLangName[ MAX_PATH ];
  1588. LPTVITEMNODE pTVLangItemNode;
  1589. tvItem.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM | TVIF_STATE;
  1590. tvItem.pszText = szLangName;
  1591. tvItem.cchTextMax = sizeof(szLangName) / sizeof(TCHAR);
  1592. for (hItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
  1593. hItem != NULL ;
  1594. hItem = TreeView_GetNextSibling(hwndTV, hItem)
  1595. )
  1596. {
  1597. tvItem.hItem = hItem;
  1598. if (TreeView_GetItem(hwndTV, &tvItem))
  1599. {
  1600. pTVLangItemNode = (LPTVITEMNODE) tvItem.lParam;
  1601. if (!pTVLangItemNode)
  1602. {
  1603. continue;
  1604. }
  1605. if (pTVLangItemNode->dwLangID == dwLangID)
  1606. {
  1607. // We found a match!
  1608. //
  1609. GetAtomName(pTVLangItemNode->atmTVItemName, szLangName, ARRAYSIZE(szLangName));
  1610. if (pTVLangItemNode->atmDefTipName)
  1611. DeleteAtom(pTVLangItemNode->atmDefTipName);
  1612. pTVLangItemNode->atmDefTipName = AddAtom(lpDefTip);
  1613. if (bSubhkl &&
  1614. (pTVLangItemNode->lParam && pTVLangItemNode->hklSub))
  1615. {
  1616. LPLANGNODE pLangNode = NULL;
  1617. if (pLangNode = (LPLANGNODE)pTVLangItemNode->lParam)
  1618. {
  1619. if (bDefLang)
  1620. pLangNode->wStatus |= (LANG_DEFAULT | LANG_DEF_CHANGE);
  1621. else if (pLangNode->wStatus & LANG_DEFAULT)
  1622. pLangNode->wStatus &= ~(LANG_DEFAULT | LANG_DEF_CHANGE);
  1623. }
  1624. }
  1625. tvItem.stateMask |= TVIS_BOLD;
  1626. if (bDefLang)
  1627. {
  1628. TreeView_SelectSetFirstVisible(hwndTV, hItem);
  1629. pTVLangItemNode->bDefLang = TRUE;
  1630. //
  1631. // No more adding default description
  1632. //
  1633. //StringCchCat(szLangName, ARRAYSIZE(szLangName), szDefault);
  1634. tvItem.state |= TVIS_BOLD;
  1635. }
  1636. else
  1637. {
  1638. pTVLangItemNode->bDefLang = FALSE;
  1639. tvItem.state &= ~TVIS_BOLD;
  1640. }
  1641. tvItem.pszText = szLangName;
  1642. SendMessage(hwndTV, TVM_SETITEM, 0, (LPARAM) &tvItem);
  1643. return TRUE;
  1644. }
  1645. }
  1646. }
  1647. return FALSE;
  1648. }
  1649. ////////////////////////////////////////////////////////////////////////////
  1650. //
  1651. // UpdateLangKBDItemNode
  1652. //
  1653. ////////////////////////////////////////////////////////////////////////////
  1654. BOOL UpdateLangKBDItemNode(
  1655. HTREEITEM hLangItem,
  1656. LPTSTR lpDefTip,
  1657. BOOL bDefault)
  1658. {
  1659. HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST);
  1660. BOOL fRet = FALSE;
  1661. TV_ITEM tvItem;
  1662. HTREEITEM hGroupItem;
  1663. HTREEITEM hItem;
  1664. LPTVITEMNODE pTVItemNode;
  1665. LPLANGNODE pLangNode;
  1666. TCHAR szItemName[ MAX_PATH ];
  1667. TCHAR szLayoutName[ MAX_PATH ];
  1668. tvItem.mask = TVIF_TEXT | TVIF_PARAM | TVIF_HANDLE | TVIF_STATE;
  1669. tvItem.pszText = szItemName;
  1670. tvItem.cchTextMax = sizeof(szItemName) / sizeof(TCHAR);
  1671. for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem);
  1672. hGroupItem != NULL;
  1673. hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem))
  1674. {
  1675. for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
  1676. hItem != NULL;
  1677. hItem = TreeView_GetNextSibling(hwndTV, hItem))
  1678. {
  1679. tvItem.hItem = hItem;
  1680. if (TreeView_GetItem(hwndTV, &tvItem))
  1681. {
  1682. if (!CompareStringTIP(tvItem.pszText, lpDefTip) &&
  1683. (pTVItemNode = (LPTVITEMNODE) tvItem.lParam))
  1684. {
  1685. GetAtomName(pTVItemNode->atmTVItemName, szLayoutName, ARRAYSIZE(szLayoutName));
  1686. tvItem.stateMask |= TVIS_BOLD;
  1687. if (bDefault)
  1688. {
  1689. pTVItemNode->bDefLang = TRUE;
  1690. tvItem.state |= TVIS_BOLD;
  1691. if (g_bCHSystem)
  1692. StringCchCat(szLayoutName, ARRAYSIZE(szLayoutName), szDefault);
  1693. }
  1694. else
  1695. {
  1696. pTVItemNode->bDefLang = FALSE;
  1697. tvItem.state &= ~TVIS_BOLD;
  1698. }
  1699. pLangNode = (LPLANGNODE)pTVItemNode->lParam;
  1700. if (pLangNode != NULL)
  1701. {
  1702. if (bDefault)
  1703. pLangNode->wStatus |= (LANG_DEFAULT | LANG_DEF_CHANGE);
  1704. else if (pLangNode->wStatus & LANG_DEFAULT)
  1705. pLangNode->wStatus &= ~(LANG_DEFAULT | LANG_DEF_CHANGE);
  1706. }
  1707. tvItem.pszText = szLayoutName;
  1708. SendMessage(hwndTV, TVM_SETITEM, 0, (LPARAM) &tvItem);
  1709. fRet = TRUE;
  1710. return fRet;
  1711. }
  1712. }
  1713. }
  1714. }
  1715. return fRet;
  1716. }
  1717. ////////////////////////////////////////////////////////////////////////////
  1718. //
  1719. // FindDefaultTipItem
  1720. //
  1721. ////////////////////////////////////////////////////////////////////////////
  1722. HTREEITEM FindDefaultTipItem(
  1723. DWORD dwLangID,
  1724. LPTSTR lpDefTip)
  1725. {
  1726. HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST);
  1727. TV_ITEM tvItem;
  1728. HTREEITEM hLangItem;
  1729. HTREEITEM hGroupItem;
  1730. HTREEITEM hItem;
  1731. LPTVITEMNODE pTVLangItemNode;
  1732. TCHAR szLangName[MAX_PATH];
  1733. tvItem.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_PARAM;
  1734. tvItem.pszText = szLangName;
  1735. tvItem.cchTextMax = sizeof(szLangName) / sizeof(TCHAR);
  1736. for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
  1737. hLangItem != NULL ;
  1738. hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem)
  1739. )
  1740. {
  1741. for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem);
  1742. hGroupItem != NULL;
  1743. hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem))
  1744. {
  1745. for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
  1746. hItem != NULL;
  1747. hItem = TreeView_GetNextSibling(hwndTV, hItem))
  1748. {
  1749. tvItem.hItem = hItem;
  1750. if (TreeView_GetItem(hwndTV, &tvItem))
  1751. {
  1752. pTVLangItemNode = (LPTVITEMNODE) tvItem.lParam;
  1753. if (!pTVLangItemNode)
  1754. continue;
  1755. if ((pTVLangItemNode->uInputType & INPUT_TYPE_KBD) &&
  1756. (pTVLangItemNode->dwLangID == dwLangID))
  1757. {
  1758. if (!CompareStringTIP(tvItem.pszText, lpDefTip) || lpDefTip == NULL)
  1759. return hItem;
  1760. }
  1761. }
  1762. }
  1763. }
  1764. }
  1765. return NULL;
  1766. }
  1767. ////////////////////////////////////////////////////////////////////////////
  1768. //
  1769. // SetNextDefaultLayout
  1770. //
  1771. ////////////////////////////////////////////////////////////////////////////
  1772. void SetNextDefaultLayout(
  1773. DWORD dwLangID,
  1774. BOOL bDefLang,
  1775. LPTSTR lpNextTip,
  1776. UINT cchNextTip)
  1777. {
  1778. TV_ITEM tvItem;
  1779. HTREEITEM hItem;
  1780. LPLANGNODE pLangNode = NULL;
  1781. LPTVITEMNODE pTVDefItemNode = NULL;
  1782. hItem = FindDefaultTipItem(dwLangID, NULL);
  1783. tvItem.hItem = hItem;
  1784. tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
  1785. if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam)
  1786. {
  1787. pTVDefItemNode = (LPTVITEMNODE) tvItem.lParam;
  1788. pLangNode = (LPLANGNODE)pTVDefItemNode->lParam;
  1789. GetAtomName(pTVDefItemNode->atmTVItemName, lpNextTip, cchNextTip);
  1790. if (bDefLang)
  1791. {
  1792. //
  1793. // Select the default layout item as bold
  1794. //
  1795. SelectDefaultKbdLayoutAsBold(g_hwndTV, hItem);
  1796. }
  1797. if (pLangNode && bDefLang)
  1798. pLangNode->wStatus |= (LANG_DEFAULT | LANG_DEF_CHANGE);
  1799. }
  1800. }
  1801. ////////////////////////////////////////////////////////////////////////////
  1802. //
  1803. // EnsureDefaultKbdLayout
  1804. //
  1805. ////////////////////////////////////////////////////////////////////////////
  1806. void EnsureDefaultKbdLayout(UINT *nLocales)
  1807. {
  1808. HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST);
  1809. TV_ITEM tvItem;
  1810. HTREEITEM hLangItem;
  1811. HTREEITEM hGroupItem;
  1812. HTREEITEM hItem;
  1813. LPTVITEMNODE pTVItemNode;
  1814. LPLANGNODE pLangNode = NULL;
  1815. BOOL bDefLayout = FALSE;
  1816. tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
  1817. for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
  1818. hLangItem != NULL ;
  1819. hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem))
  1820. {
  1821. for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem);
  1822. hGroupItem != NULL;
  1823. hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem))
  1824. {
  1825. for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
  1826. hItem != NULL;
  1827. hItem = TreeView_GetNextSibling(hwndTV, hItem))
  1828. {
  1829. (*nLocales)++;
  1830. tvItem.hItem = hItem;
  1831. if (TreeView_GetItem(hwndTV, &tvItem))
  1832. {
  1833. pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
  1834. if (!pTVItemNode)
  1835. continue;
  1836. pLangNode = (LPLANGNODE)pTVItemNode->lParam;
  1837. if (pLangNode == NULL &&
  1838. (pTVItemNode->uInputType & INPUT_TYPE_KBD) &&
  1839. pTVItemNode->hklSub)
  1840. {
  1841. if (tvItem.hItem = FindTVLangItem(pTVItemNode->dwLangID, NULL))
  1842. {
  1843. if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
  1844. {
  1845. pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
  1846. pLangNode = (LPLANGNODE)pTVItemNode->lParam;
  1847. }
  1848. }
  1849. }
  1850. if (pLangNode == NULL)
  1851. continue;
  1852. if (!(pLangNode->wStatus & LANG_UNLOAD) &&
  1853. (pLangNode->wStatus & LANG_DEFAULT))
  1854. {
  1855. bDefLayout = TRUE;
  1856. }
  1857. }
  1858. }
  1859. }
  1860. }
  1861. if (!bDefLayout)
  1862. {
  1863. LPTVITEMNODE pTVLangItemNode;
  1864. for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
  1865. hLangItem != NULL ;
  1866. hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem))
  1867. {
  1868. tvItem.hItem = hLangItem;
  1869. if (TreeView_GetItem(hwndTV, &tvItem))
  1870. {
  1871. pTVLangItemNode = (LPTVITEMNODE) tvItem.lParam;
  1872. if (!pTVLangItemNode)
  1873. continue;
  1874. if (pTVLangItemNode->bDefLang)
  1875. {
  1876. for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem);
  1877. hGroupItem != NULL;
  1878. hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem))
  1879. {
  1880. for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
  1881. hItem != NULL;
  1882. hItem = TreeView_GetNextSibling(hwndTV, hItem))
  1883. {
  1884. tvItem.hItem = hItem;
  1885. if (TreeView_GetItem(hwndTV, &tvItem))
  1886. {
  1887. pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
  1888. if (!pTVItemNode)
  1889. continue;
  1890. pLangNode = (LPLANGNODE)pTVItemNode->lParam;
  1891. if (pLangNode == NULL &&
  1892. (pTVItemNode->uInputType & INPUT_TYPE_KBD) &&
  1893. pTVItemNode->hklSub)
  1894. {
  1895. if (tvItem.hItem = FindTVLangItem(pTVItemNode->dwLangID, NULL))
  1896. {
  1897. if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
  1898. {
  1899. pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
  1900. pLangNode = (LPLANGNODE)pTVItemNode->lParam;
  1901. }
  1902. }
  1903. }
  1904. if (pLangNode == NULL)
  1905. continue;
  1906. if (!(pLangNode->wStatus & LANG_UNLOAD))
  1907. {
  1908. pLangNode->wStatus |= LANG_DEFAULT;
  1909. break;
  1910. }
  1911. }
  1912. }
  1913. }
  1914. }
  1915. }
  1916. }
  1917. }
  1918. return;
  1919. }
  1920. ////////////////////////////////////////////////////////////////////////////
  1921. //
  1922. // FindTVItem
  1923. //
  1924. ////////////////////////////////////////////////////////////////////////////
  1925. HTREEITEM FindTVItem(DWORD dwLangID, LPTSTR lpTipText)
  1926. {
  1927. HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST);
  1928. TV_ITEM tvItem;
  1929. HTREEITEM hItem;
  1930. HTREEITEM hLangItem = NULL;
  1931. HTREEITEM hGroupItem = NULL;
  1932. LPTVITEMNODE pTVLangNode;
  1933. TCHAR szLangName[ MAX_PATH ];
  1934. tvItem.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_PARAM;
  1935. tvItem.pszText = szLangName;
  1936. tvItem.cchTextMax = sizeof(szLangName) / sizeof(TCHAR);
  1937. for (hItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
  1938. hItem != NULL ;
  1939. hItem = TreeView_GetNextSibling(hwndTV, hItem)
  1940. )
  1941. {
  1942. tvItem.hItem = hItem;
  1943. if (TreeView_GetItem(hwndTV, &tvItem))
  1944. {
  1945. pTVLangNode = (LPTVITEMNODE) tvItem.lParam;
  1946. if (!pTVLangNode)
  1947. {
  1948. continue;
  1949. }
  1950. if (pTVLangNode->dwLangID == dwLangID)
  1951. {
  1952. hLangItem = hItem;
  1953. }
  1954. }
  1955. }
  1956. if (hLangItem && lpTipText)
  1957. {
  1958. for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem);
  1959. hGroupItem != NULL;
  1960. hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem))
  1961. {
  1962. for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
  1963. hItem != NULL;
  1964. hItem = TreeView_GetNextSibling(hwndTV, hItem))
  1965. {
  1966. tvItem.hItem = hItem;
  1967. if (TreeView_GetItem(hwndTV, &tvItem))
  1968. {
  1969. if (!CompareStringTIP(tvItem.pszText, lpTipText))
  1970. {
  1971. return hItem;
  1972. }
  1973. }
  1974. }
  1975. }
  1976. }
  1977. return NULL;
  1978. }
  1979. ////////////////////////////////////////////////////////////////////////////
  1980. //
  1981. // CheckButtons
  1982. //
  1983. ////////////////////////////////////////////////////////////////////////////
  1984. void CheckButtons(
  1985. HWND hwnd)
  1986. {
  1987. TV_ITEM tvItem;
  1988. UINT uInputType;
  1989. HTREEITEM hTVItem;
  1990. LPTVITEMNODE pTVItemNode;
  1991. LPLANGNODE pLangNode = NULL;
  1992. hTVItem = TreeView_GetSelection(g_hwndTV);
  1993. if (!hTVItem)
  1994. return;
  1995. tvItem.hItem = hTVItem;
  1996. tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
  1997. if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam)
  1998. {
  1999. if (!(pTVItemNode = (LPTVITEMNODE) tvItem.lParam))
  2000. return;
  2001. pLangNode = (LPLANGNODE)pTVItemNode->lParam;
  2002. uInputType = pTVItemNode->uInputType;
  2003. if ((uInputType & INPUT_TYPE_KBD) &&
  2004. (g_iInputs >= 2))
  2005. {
  2006. EnableWindow(GetDlgItem(hwnd, IDC_KBDL_SET_DEFAULT), TRUE);
  2007. }
  2008. else
  2009. {
  2010. BOOL bKbdGroup = FALSE;
  2011. if (uInputType & TV_ITEM_TYPE_LANG)
  2012. {
  2013. HTREEITEM hGroupItem;
  2014. for (hGroupItem = TreeView_GetChild(g_hwndTV, hTVItem);
  2015. hGroupItem != NULL;
  2016. hGroupItem = TreeView_GetNextSibling(g_hwndTV, hGroupItem))
  2017. {
  2018. tvItem.hItem = hGroupItem;
  2019. if (TreeView_GetItem(g_hwndTV, &tvItem))
  2020. {
  2021. LPTVITEMNODE pTVItemNode2;
  2022. if (!(pTVItemNode2 = (LPTVITEMNODE) tvItem.lParam))
  2023. return;
  2024. if (pTVItemNode2->uInputType & INPUT_TYPE_KBD)
  2025. {
  2026. bKbdGroup = TRUE;
  2027. break;
  2028. }
  2029. }
  2030. }
  2031. }
  2032. if (bKbdGroup && (g_iInputs >= 2))
  2033. EnableWindow(GetDlgItem(hwnd, IDC_KBDL_SET_DEFAULT), TRUE);
  2034. else
  2035. EnableWindow(GetDlgItem(hwnd, IDC_KBDL_SET_DEFAULT), FALSE);
  2036. }
  2037. if ((!g_bSetupCase) &&
  2038. ((pLangNode &&
  2039. (pLangNode->wStatus & LANG_IME) &&
  2040. (pLangNode->wStatus & LANG_ORIGACTIVE) &&
  2041. (uInputType == INPUT_TYPE_KBD) &&
  2042. (GetSystemMetrics(SM_IMMENABLED))) ||
  2043. ((uInputType & INPUT_TYPE_TIP) && !(uInputType & TV_ITEM_TYPE_GROUP))))
  2044. {
  2045. EnableWindow(GetDlgItem(hwnd, IDC_KBDL_EDIT), TRUE);
  2046. }
  2047. else
  2048. {
  2049. EnableWindow(GetDlgItem(hwnd, IDC_KBDL_EDIT), FALSE);
  2050. }
  2051. if (g_iInputs == 1)
  2052. {
  2053. EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DELETE), FALSE);
  2054. return;
  2055. }
  2056. else
  2057. {
  2058. EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DELETE), TRUE);
  2059. }
  2060. if (uInputType & TV_ITEM_TYPE_LANG)
  2061. {
  2062. if (!TreeView_GetNextSibling(g_hwndTV, hTVItem) &&
  2063. !TreeView_GetPrevSibling(g_hwndTV, hTVItem))
  2064. {
  2065. EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DELETE), FALSE);
  2066. }
  2067. return;
  2068. }
  2069. else if (uInputType & TV_ITEM_TYPE_GROUP)
  2070. {
  2071. if (uInputType & TV_ITEM_TYPE_KBD)
  2072. {
  2073. if (!TreeView_GetNextSibling(g_hwndTV, hTVItem) &&
  2074. !TreeView_GetPrevSibling(g_hwndTV, hTVItem))
  2075. {
  2076. hTVItem = TreeView_GetParent(g_hwndTV, hTVItem);
  2077. if (!TreeView_GetNextSibling(g_hwndTV, hTVItem) &&
  2078. !TreeView_GetPrevSibling(g_hwndTV, hTVItem))
  2079. {
  2080. EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DELETE), FALSE);
  2081. }
  2082. }
  2083. else
  2084. {
  2085. EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DELETE), FALSE);
  2086. }
  2087. }
  2088. return;
  2089. }
  2090. else if (uInputType & TV_ITEM_TYPE_KBD)
  2091. {
  2092. if (!TreeView_GetNextSibling(g_hwndTV, hTVItem) &&
  2093. !TreeView_GetPrevSibling(g_hwndTV, hTVItem))
  2094. {
  2095. hTVItem = TreeView_GetParent(g_hwndTV, hTVItem);
  2096. if (!TreeView_GetNextSibling(g_hwndTV, hTVItem) &&
  2097. !TreeView_GetPrevSibling(g_hwndTV, hTVItem))
  2098. {
  2099. hTVItem = TreeView_GetParent(g_hwndTV, hTVItem);
  2100. if (!TreeView_GetNextSibling(g_hwndTV, hTVItem) &&
  2101. !TreeView_GetPrevSibling(g_hwndTV, hTVItem))
  2102. {
  2103. EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DELETE), FALSE);
  2104. }
  2105. }
  2106. else
  2107. {
  2108. EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DELETE), FALSE);
  2109. }
  2110. }
  2111. return;
  2112. }
  2113. }
  2114. }
  2115. ////////////////////////////////////////////////////////////////////////////
  2116. //
  2117. // EnumCiceroTips
  2118. //
  2119. ////////////////////////////////////////////////////////////////////////////
  2120. BOOL EnumCiceroTips()
  2121. {
  2122. ULONG ul;
  2123. ULONG ulCnt;
  2124. HRESULT hr;
  2125. LPTIPS pTips;
  2126. LANGID *plangid;
  2127. UINT uInputType;
  2128. BOOL bReturn = TRUE;
  2129. BOOL bEnabledTip = FALSE;
  2130. TCHAR szTipName[MAX_PATH];
  2131. TCHAR szTipTypeName[MAX_PATH];
  2132. IEnumTfLanguageProfiles *pEnum;
  2133. ITfInputProcessorProfiles *pProfiles = NULL;
  2134. ITfFnLangProfileUtil *pLangUtil = NULL;
  2135. ITfCategoryMgr *pCategory = NULL;
  2136. //
  2137. // initialize COM
  2138. //
  2139. if (CoInitialize(NULL) == S_OK)
  2140. g_bCoInit = TRUE;
  2141. else
  2142. g_bCoInit = FALSE;
  2143. //
  2144. // Check-up SAPI TIP registration.
  2145. //
  2146. hr = CoCreateInstance(&CLSID_SapiLayr,
  2147. NULL,
  2148. CLSCTX_INPROC_SERVER,
  2149. &IID_ITfFnLangProfileUtil,
  2150. (LPVOID *) &pLangUtil);
  2151. if (SUCCEEDED(hr))
  2152. {
  2153. pLangUtil->lpVtbl->RegisterActiveProfiles(pLangUtil);
  2154. }
  2155. //
  2156. // load Assembly list
  2157. //
  2158. hr = CoCreateInstance(&CLSID_TF_InputProcessorProfiles,
  2159. NULL,
  2160. CLSCTX_INPROC_SERVER,
  2161. &IID_ITfInputProcessorProfiles,
  2162. (LPVOID *) &pProfiles);
  2163. if (FAILED(hr))
  2164. return FALSE;
  2165. //
  2166. // Create the new node.
  2167. //
  2168. if (!(g_hTips = (LPTIPS) LocalAlloc(LHND, ALLOCBLOCK * sizeof(TIPS))))
  2169. {
  2170. return FALSE;
  2171. }
  2172. g_nTipsBuffSize = ALLOCBLOCK;
  2173. g_iTipsBuff = 0;
  2174. g_lpTips = LocalLock(g_hTips);
  2175. //
  2176. // Enum all available languages
  2177. //
  2178. if (SUCCEEDED(pProfiles->lpVtbl->EnumLanguageProfiles(pProfiles, 0, &pEnum)))
  2179. {
  2180. TF_LANGUAGEPROFILE tflp;
  2181. CLSID clsid;
  2182. GUID guidProfile;
  2183. while (pEnum->lpVtbl->Next(pEnum, 1, &tflp, NULL) == S_OK)
  2184. {
  2185. BSTR bstr = NULL;
  2186. BSTR bstr2 = NULL;
  2187. LANGID langid = tflp.langid;
  2188. BOOL bNoCategory = FALSE;
  2189. hr = pProfiles->lpVtbl->GetLanguageProfileDescription(
  2190. pProfiles,
  2191. &tflp.clsid,
  2192. tflp.langid,
  2193. &tflp.guidProfile,
  2194. &bstr);
  2195. if (FAILED(hr))
  2196. continue;
  2197. StringCchCopy(szTipName, ARRAYSIZE(szTipName), bstr);
  2198. if (IsEqualGUID(&tflp.catid, &GUID_TFCAT_TIP_KEYBOARD))
  2199. {
  2200. StringCchCopy(szTipTypeName, ARRAYSIZE(szTipTypeName), szInputTypeKbd);
  2201. uInputType = INPUT_TYPE_KBD;
  2202. }
  2203. else if (IsEqualGUID(&tflp.catid, &GUID_TFCAT_TIP_HANDWRITING))
  2204. {
  2205. StringCchCopy(szTipTypeName, ARRAYSIZE(szTipTypeName), szInputTypePen);
  2206. uInputType = INPUT_TYPE_PEN;
  2207. }
  2208. else if (IsEqualGUID(&tflp.catid, &GUID_TFCAT_TIP_SPEECH))
  2209. {
  2210. StringCchCopy(szTipTypeName, ARRAYSIZE(szTipTypeName), szInputTypeSpeech);
  2211. uInputType = INPUT_TYPE_SPEECH;
  2212. bNoCategory = TRUE;
  2213. }
  2214. else
  2215. {
  2216. g_bExtraTip = TRUE;
  2217. uInputType = INPUT_TYPE_EXTERNAL;
  2218. if (pCategory == NULL)
  2219. {
  2220. hr = CoCreateInstance(&CLSID_TF_CategoryMgr,
  2221. NULL,
  2222. CLSCTX_INPROC_SERVER,
  2223. &IID_ITfCategoryMgr,
  2224. (LPVOID *) &pCategory);
  2225. if (FAILED(hr))
  2226. return FALSE;
  2227. }
  2228. if (pCategory->lpVtbl->GetGUIDDescription(pCategory,
  2229. &tflp.catid,
  2230. &bstr2) == S_OK)
  2231. {
  2232. StringCchCopy(szTipTypeName, ARRAYSIZE(szTipTypeName), bstr2);
  2233. }
  2234. else
  2235. {
  2236. StringCchCopy(szTipTypeName, ARRAYSIZE(szTipTypeName), szInputTypeExternal);
  2237. }
  2238. if (IsEqualGUID(&tflp.catid, &GUID_TFCAT_TIP_SMARTTAG))
  2239. {
  2240. bNoCategory = TRUE;
  2241. uInputType |= INPUT_TYPE_SMARTTAG;
  2242. }
  2243. }
  2244. uInputType |= INPUT_TYPE_TIP;
  2245. if (g_iTipsBuff + 1 == g_nTipsBuffSize)
  2246. {
  2247. HANDLE hTemp;
  2248. LocalUnlock(g_hTips);
  2249. g_nTipsBuffSize += ALLOCBLOCK;
  2250. hTemp = LocalReAlloc(g_hTips,
  2251. g_nTipsBuffSize * sizeof(TIPS),
  2252. LHND);
  2253. if (hTemp == NULL)
  2254. return FALSE;
  2255. g_hTips = hTemp;
  2256. g_lpTips = LocalLock(g_hTips);
  2257. }
  2258. g_lpTips[g_iTipsBuff].dwLangID = (DWORD) langid;
  2259. g_lpTips[g_iTipsBuff].uInputType = uInputType;
  2260. g_lpTips[g_iTipsBuff].atmTipText = AddAtom(szTipName);
  2261. g_lpTips[g_iTipsBuff].clsid = tflp.clsid;
  2262. g_lpTips[g_iTipsBuff].guidProfile = tflp.guidProfile;
  2263. g_lpTips[g_iTipsBuff].bNoAddCat = bNoCategory;
  2264. if (pProfiles->lpVtbl->GetDefaultLanguageProfile(pProfiles,
  2265. langid,
  2266. &tflp.catid,
  2267. &clsid,
  2268. &guidProfile) == S_OK)
  2269. {
  2270. if (IsEqualGUID(&tflp.guidProfile, &guidProfile))
  2271. g_lpTips[g_iTipsBuff].bDefault = TRUE;
  2272. }
  2273. if (uInputType & INPUT_TYPE_KBD)
  2274. {
  2275. g_lpTips[g_iTipsBuff].hklSub = GetSubstituteHKL(&tflp.clsid,
  2276. tflp.langid,
  2277. &tflp.guidProfile);
  2278. }
  2279. pProfiles->lpVtbl->IsEnabledLanguageProfile(pProfiles,
  2280. &tflp.clsid,
  2281. tflp.langid,
  2282. &tflp.guidProfile,
  2283. &bEnabledTip);
  2284. // we need a special care for speech here, because:
  2285. //
  2286. // - speech TIP uses -1 profile with disabled status
  2287. //
  2288. // - when a user start a session, either this control
  2289. // panel or first Cicero app, it'll fire off setting up
  2290. // per user profiles based on SR engines currently
  2291. // installed and available on the machine
  2292. //
  2293. // - speech TIP also fires off the logic when any SR
  2294. // engines are added or removed
  2295. //
  2296. // to make this senario work, we have to check with
  2297. // speech TIP's ITfFnProfileUtil interface each time
  2298. // we invoke "Add Input Language" dialog box.
  2299. //
  2300. if (pLangUtil && (uInputType & INPUT_TYPE_SPEECH))
  2301. {
  2302. BOOL fSpeechAvailable = FALSE;
  2303. pLangUtil->lpVtbl->IsProfileAvailableForLang( pLangUtil,
  2304. langid,
  2305. &fSpeechAvailable
  2306. );
  2307. g_lpTips[g_iTipsBuff].fEngineAvailable = fSpeechAvailable;
  2308. }
  2309. //
  2310. // Enable pen and speech category adding options if user has the
  2311. // installed pen or speech items.
  2312. //
  2313. if ((!g_bPenOrSapiTip) &&
  2314. ((uInputType & INPUT_TYPE_PEN) || g_lpTips[g_iTipsBuff].fEngineAvailable))
  2315. g_bPenOrSapiTip = TRUE;
  2316. if (bEnabledTip && langid)
  2317. {
  2318. TCHAR szLangName[MAX_PATH];
  2319. LPTVITEMNODE pTVItemNode;
  2320. LPTVITEMNODE pTVLangItemNode;
  2321. GetLanguageName(MAKELCID(langid, SORT_DEFAULT),
  2322. szLangName,
  2323. ARRAYSIZE(szLangName));
  2324. if (!(pTVLangItemNode = CreateTVItemNode(langid)))
  2325. {
  2326. bReturn = FALSE;
  2327. break;
  2328. }
  2329. if (pTVLangItemNode->hklSub)
  2330. pTVLangItemNode->atmDefTipName = AddAtom(szTipName);
  2331. AddTreeViewItems(TV_ITEM_TYPE_LANG,
  2332. szLangName,
  2333. NULL,
  2334. NULL,
  2335. &pTVLangItemNode);
  2336. if (!(pTVItemNode = CreateTVItemNode(langid)))
  2337. {
  2338. bReturn = FALSE;
  2339. break;
  2340. }
  2341. pTVItemNode->uInputType = uInputType;
  2342. pTVItemNode->iIdxTips = g_iTipsBuff;
  2343. pTVItemNode->clsid = tflp.clsid;
  2344. pTVItemNode->guidProfile = tflp.guidProfile;
  2345. pTVItemNode->hklSub = g_lpTips[g_iTipsBuff].hklSub;
  2346. pTVItemNode->bNoAddCat = g_lpTips[g_iTipsBuff].bNoAddCat;
  2347. //
  2348. // Make sure the loading TIP substitute hkl
  2349. //
  2350. if (pTVItemNode->hklSub)
  2351. {
  2352. TCHAR szSubhkl[10];
  2353. HKL hklNew;
  2354. StringCchPrintf(szSubhkl, ARRAYSIZE(szSubhkl), TEXT("%08x"), (DWORD)(UINT_PTR)pTVItemNode->hklSub);
  2355. hklNew = LoadKeyboardLayout(szSubhkl,
  2356. KLF_SUBSTITUTE_OK |
  2357. KLF_REPLACELANG |
  2358. KLF_NOTELLSHELL);
  2359. if (hklNew != pTVItemNode->hklSub)
  2360. {
  2361. pTVItemNode->hklSub = 0;
  2362. g_lpTips[g_iTipsBuff].hklSub = 0;
  2363. }
  2364. }
  2365. AddTreeViewItems(uInputType,
  2366. szLangName,
  2367. szTipTypeName,
  2368. szTipName,
  2369. &pTVItemNode);
  2370. g_lpTips[g_iTipsBuff].bEnabled = TRUE;
  2371. g_iEnabledTips++;
  2372. if (uInputType & INPUT_TYPE_KBD)
  2373. g_iEnabledKbdTips++;
  2374. }
  2375. g_iTipsBuff++;
  2376. if (bstr)
  2377. SysFreeString(bstr);
  2378. if (bstr2)
  2379. SysFreeString(bstr2);
  2380. }
  2381. pEnum->lpVtbl->Release(pEnum);
  2382. }
  2383. if (pCategory)
  2384. pCategory->lpVtbl->Release(pCategory);
  2385. if (pLangUtil)
  2386. pLangUtil->lpVtbl->Release(pLangUtil);
  2387. if (pProfiles)
  2388. pProfiles->lpVtbl->Release(pProfiles);
  2389. return bReturn;
  2390. }
  2391. ////////////////////////////////////////////////////////////////////////////
  2392. //
  2393. // SaveLanguageProfileStatus
  2394. //
  2395. ////////////////////////////////////////////////////////////////////////////
  2396. LRESULT SaveLanguageProfileStatus(
  2397. BOOL bSave,
  2398. int iIdxTip,
  2399. HKL hklSub)
  2400. {
  2401. HRESULT hr;
  2402. UINT idx;
  2403. int iIdxDef = -1;
  2404. int iIdxDefTip = -1;
  2405. ITfInputProcessorProfiles *pProfiles = NULL;
  2406. //
  2407. // load Assembly list
  2408. //
  2409. hr = CoCreateInstance(&CLSID_TF_InputProcessorProfiles,
  2410. NULL,
  2411. CLSCTX_INPROC_SERVER,
  2412. &IID_ITfInputProcessorProfiles,
  2413. (LPVOID *) &pProfiles);
  2414. if (FAILED(hr))
  2415. return S_FALSE;
  2416. if (bSave)
  2417. {
  2418. ITfFnLangProfileUtil *pLangUtil = NULL;
  2419. for (idx = 0; idx < g_iTipsBuff; idx++)
  2420. {
  2421. hr = pProfiles->lpVtbl->EnableLanguageProfile(
  2422. pProfiles,
  2423. &(g_lpTips[idx].clsid),
  2424. (LANGID)g_lpTips[idx].dwLangID,
  2425. &(g_lpTips[idx].guidProfile),
  2426. g_lpTips[idx].bEnabled);
  2427. if (FAILED(hr))
  2428. goto Exit;
  2429. }
  2430. hr = CoCreateInstance(&CLSID_SapiLayr,
  2431. NULL,
  2432. CLSCTX_INPROC_SERVER,
  2433. &IID_ITfFnLangProfileUtil,
  2434. (LPVOID *) &pLangUtil);
  2435. if (S_OK == hr)
  2436. {
  2437. pLangUtil->lpVtbl->RegisterActiveProfiles(pLangUtil);
  2438. pLangUtil->lpVtbl->Release(pLangUtil);
  2439. }
  2440. }
  2441. if (hklSub && iIdxTip != -1 && iIdxTip < (int)g_iTipsBuff)
  2442. {
  2443. BOOL bFound = FALSE;
  2444. TCHAR szItem[MAX_PATH];
  2445. TCHAR szDefLayout[MAX_PATH];
  2446. HWND hwndDefList = GetDlgItem(g_hDlg, IDC_LOCALE_DEFAULT);
  2447. szDefLayout[0] = L'\0';
  2448. //
  2449. // Get the current selection in the input locale list.
  2450. //
  2451. if ((iIdxDef = ComboBox_GetCurSel(hwndDefList)) != CB_ERR)
  2452. {
  2453. WCHAR *pwchar;
  2454. SendMessage(hwndDefList, CB_GETLBTEXT, iIdxDef, (LPARAM)szItem);
  2455. pwchar = wcschr(szItem, L'-');
  2456. if (pwchar != NULL)
  2457. StringCchCopy(szDefLayout, ARRAYSIZE(szDefLayout), pwchar + 2);
  2458. }
  2459. GetAtomName(g_lpTips[iIdxTip].atmTipText, szItem, ARRAYSIZE(szItem));
  2460. if (lstrcmp(szItem, szDefLayout) == 0)
  2461. {
  2462. iIdxDefTip = iIdxTip;
  2463. bFound = TRUE;
  2464. }
  2465. else
  2466. {
  2467. for (idx = 0; idx < g_iTipsBuff; idx++)
  2468. {
  2469. if (hklSub == g_lpTips[idx].hklSub)
  2470. {
  2471. GetAtomName(g_lpTips[idx].atmTipText,
  2472. szItem,
  2473. ARRAYSIZE(szItem));
  2474. if (lstrcmp(szItem, szDefLayout) == 0)
  2475. {
  2476. iIdxDefTip = idx;
  2477. bFound = TRUE;
  2478. break;
  2479. }
  2480. }
  2481. }
  2482. }
  2483. if (bFound && iIdxDefTip != -1)
  2484. {
  2485. pProfiles->lpVtbl->SetDefaultLanguageProfile(
  2486. pProfiles,
  2487. (LANGID)g_lpTips[iIdxDefTip].dwLangID,
  2488. &(g_lpTips[iIdxDefTip].clsid),
  2489. &(g_lpTips[iIdxDefTip].guidProfile));
  2490. }
  2491. }
  2492. Exit:
  2493. if (pProfiles)
  2494. pProfiles->lpVtbl->Release(pProfiles);
  2495. return hr;
  2496. }
  2497. ////////////////////////////////////////////////////////////////////////////
  2498. //
  2499. // UpdateToolBarSetting
  2500. //
  2501. ////////////////////////////////////////////////////////////////////////////
  2502. void UpdateToolBarSetting()
  2503. {
  2504. HRESULT hr;
  2505. ITfLangBarMgr *pLangBar = NULL;
  2506. //
  2507. // load LangBar manager
  2508. //
  2509. hr = CoCreateInstance(&CLSID_TF_LangBarMgr,
  2510. NULL,
  2511. CLSCTX_INPROC_SERVER,
  2512. &IID_ITfLangBarMgr,
  2513. (LPVOID *) &pLangBar);
  2514. if (SUCCEEDED(hr))
  2515. pLangBar->lpVtbl->ShowFloating(pLangBar, g_dwToolBar);
  2516. if (pLangBar)
  2517. pLangBar->lpVtbl->Release(pLangBar);
  2518. }
  2519. ////////////////////////////////////////////////////////////////////////////
  2520. //
  2521. // Locale_ApplyError
  2522. //
  2523. // Put up the given error message with the language name in it.
  2524. //
  2525. // NOTE: This error is NOT fatal - as we could be half way through the
  2526. // list before an error occurs. The registry will already have
  2527. // some information and we should let them have what comes next
  2528. // as well.
  2529. //
  2530. ////////////////////////////////////////////////////////////////////////////
  2531. int Locale_ApplyError(
  2532. HWND hwnd,
  2533. LPLANGNODE pLangNode,
  2534. UINT iErr,
  2535. UINT iStyle)
  2536. {
  2537. UINT idxLang, idxLayout;
  2538. TCHAR sz[MAX_PATH];
  2539. TCHAR szTemp[MAX_PATH];
  2540. TCHAR szLangName[MAX_PATH * 2];
  2541. LPTSTR pszLang;
  2542. //
  2543. // Load in the string for the given string id.
  2544. //
  2545. LoadString(hInstance, iErr, sz, ARRAYSIZE(sz));
  2546. //
  2547. // Get the language name to fill into the above string.
  2548. //
  2549. if (pLangNode)
  2550. {
  2551. idxLang = pLangNode->iLang;
  2552. idxLayout = pLangNode->iLayout;
  2553. GetAtomName(g_lpLang[idxLang].atmLanguageName, szLangName, ARRAYSIZE(szLangName));
  2554. if (g_lpLang[idxLang].dwID != g_lpLayout[idxLayout].dwID)
  2555. {
  2556. pszLang = szLangName + lstrlen(szLangName);
  2557. pszLang[0] = TEXT(' ');
  2558. pszLang[1] = TEXT('-');
  2559. pszLang[2] = TEXT(' ');
  2560. GetAtomName(g_lpLayout[idxLayout].atmLayoutText,
  2561. pszLang + 3,
  2562. ARRAYSIZE(szLangName) - (lstrlen(szLangName) + 3));
  2563. }
  2564. }
  2565. else
  2566. {
  2567. LoadString(hInstance, IDS_UNKNOWN, szLangName, ARRAYSIZE(szLangName));
  2568. }
  2569. //
  2570. // Put up the error message box.
  2571. //
  2572. StringCchPrintf(szTemp, ARRAYSIZE(szTemp), sz, szLangName);
  2573. return (MessageBox(hwnd, szTemp, NULL, iStyle));
  2574. }
  2575. ////////////////////////////////////////////////////////////////////////////
  2576. //
  2577. // Locale_FetchIndicator
  2578. //
  2579. // Saves the two letter indicator symbol for the given language in the
  2580. // g_lpLang array.
  2581. //
  2582. ////////////////////////////////////////////////////////////////////////////
  2583. void Locale_FetchIndicator(
  2584. LPLANGNODE pLangNode)
  2585. {
  2586. TCHAR szData[MAX_PATH];
  2587. LPINPUTLANG pInpLang = &g_lpLang[pLangNode->iLang];
  2588. //
  2589. // Get the indicator by using the first 2 characters of the
  2590. // abbreviated language name.
  2591. //
  2592. if (GetLocaleInfo(LOWORD(pInpLang->dwID),
  2593. LOCALE_SABBREVLANGNAME | LOCALE_NOUSEROVERRIDE,
  2594. szData,
  2595. ARRAYSIZE(szData)))
  2596. {
  2597. //
  2598. // Save the first two characters.
  2599. //
  2600. pInpLang->szSymbol[0] = szData[0];
  2601. pInpLang->szSymbol[1] = szData[1];
  2602. pInpLang->szSymbol[2] = TEXT('\0');
  2603. }
  2604. else
  2605. {
  2606. //
  2607. // Id wasn't found. Return question marks.
  2608. //
  2609. pInpLang->szSymbol[0] = TEXT('?');
  2610. pInpLang->szSymbol[1] = TEXT('?');
  2611. pInpLang->szSymbol[2] = TEXT('\0');
  2612. }
  2613. }
  2614. ////////////////////////////////////////////////////////////////////////////
  2615. //
  2616. // Locale_SetSecondaryControls
  2617. //
  2618. // Sets the secondary controls to either be enabled or disabled.
  2619. // When there is only 1 active TIP, then this function will be called to
  2620. // disable these controls.
  2621. //
  2622. ////////////////////////////////////////////////////////////////////////////
  2623. void Locale_SetSecondaryControls(
  2624. HWND hwndMain)
  2625. {
  2626. if (g_iInputs >= 2)
  2627. {
  2628. EnableWindow(GetDlgItem(hwndMain, IDC_HOTKEY_SETTING), TRUE);
  2629. }
  2630. else
  2631. {
  2632. EnableWindow(GetDlgItem(hwndMain, IDC_HOTKEY_SETTING), FALSE);
  2633. }
  2634. CheckButtons(hwndMain);
  2635. }
  2636. ////////////////////////////////////////////////////////////////////////////
  2637. //
  2638. // Locale_CommandSetDefault
  2639. //
  2640. // Sets the new default when the Set as Default button is pressed.
  2641. //
  2642. ////////////////////////////////////////////////////////////////////////////
  2643. void Locale_CommandSetDefault(
  2644. HWND hwnd)
  2645. {
  2646. int iIdxDef;
  2647. int idxList;
  2648. LPLANGNODE pLangNode = NULL;
  2649. HWND hwndTV = GetDlgItem(hwnd, IDC_INPUT_LIST);
  2650. HWND hwndDefList = GetDlgItem(hwnd, IDC_LOCALE_DEFAULT);
  2651. TCHAR sz[DESC_MAX];
  2652. HTREEITEM hTVCurLangItem = NULL;
  2653. HTREEITEM hTVCurItem = NULL;
  2654. TV_ITEM tvItem;
  2655. TV_ITEM tvItem2;
  2656. HTREEITEM hItem;
  2657. HTREEITEM hLangItem;
  2658. HTREEITEM hGroupItem;
  2659. LPTVITEMNODE pCurItemNode;
  2660. LPTVITEMNODE pPrevDefItemNode;
  2661. TCHAR szLangText[DESC_MAX];
  2662. TCHAR szLayoutName[DESC_MAX];
  2663. TCHAR szDefItem[MAX_PATH];
  2664. LPINPUTLANG pInpLang;
  2665. WCHAR *pwchar;
  2666. TCHAR szDefTip[DESC_MAX];
  2667. szLayoutName[0] = L'\0';
  2668. //
  2669. // Get the current selection in the input locale list.
  2670. //
  2671. iIdxDef = (int) SendMessage(hwndDefList, CB_GETCURSEL, 0, 0);
  2672. if (iIdxDef == CB_ERR)
  2673. {
  2674. //iIdxDef = 0;
  2675. DWORD dwLangID;
  2676. for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
  2677. hLangItem != NULL ;
  2678. hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem)
  2679. )
  2680. {
  2681. tvItem.hItem = hLangItem;
  2682. if (TreeView_GetItem(hwndTV, &tvItem) &&
  2683. (pCurItemNode = (LPTVITEMNODE) tvItem.lParam))
  2684. {
  2685. if (pCurItemNode->bDefLang)
  2686. {
  2687. dwLangID = pCurItemNode->dwLangID;
  2688. GetAtomName(pCurItemNode->atmTVItemName,
  2689. szLangText,
  2690. ARRAYSIZE(szLangText));
  2691. break;
  2692. }
  2693. }
  2694. }
  2695. }
  2696. else
  2697. {
  2698. SendMessage(hwndDefList, CB_GETLBTEXT, iIdxDef, (LPARAM)szDefItem);
  2699. pwchar = wcschr(szDefItem, L'-');
  2700. if ((pwchar != NULL) && (szDefItem < (pwchar - 1)))
  2701. {
  2702. *(pwchar - 1) = TEXT('\0');
  2703. StringCchCopy(szLayoutName, ARRAYSIZE(szLayoutName), pwchar + 2);
  2704. }
  2705. StringCchCopy(szLangText, ARRAYSIZE(szLangText), szDefItem);
  2706. }
  2707. hTVCurLangItem = FindTVLangItem(0, szLangText);
  2708. if (hTVCurLangItem == NULL)
  2709. {
  2710. //
  2711. // There is no default keyboard layout on the system, so try to set
  2712. // the default keyboard layout with the first available item.
  2713. //
  2714. if (SendMessage(hwndDefList, CB_GETLBTEXT, 0, (LPARAM)szDefItem) != CB_ERR)
  2715. {
  2716. pwchar = wcschr(szDefItem, L'-');
  2717. if ((pwchar != NULL) && (szDefItem < (pwchar - 1)))
  2718. {
  2719. *(pwchar - 1) = TEXT('\0');
  2720. StringCchCopy(szLayoutName, ARRAYSIZE(szLayoutName), pwchar + 2);
  2721. }
  2722. StringCchCopy(szLangText, ARRAYSIZE(szLangText), szDefItem);
  2723. ComboBox_SetCurSel(hwndDefList, 0);
  2724. }
  2725. }
  2726. else
  2727. {
  2728. tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
  2729. tvItem.hItem = hTVCurLangItem;
  2730. }
  2731. if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
  2732. {
  2733. //
  2734. // Get the pointer to the lang node from the list box
  2735. // item data.
  2736. //
  2737. pCurItemNode = (LPTVITEMNODE) tvItem.lParam;
  2738. if (hTVCurItem = FindTVItem(pCurItemNode->dwLangID, szLayoutName))
  2739. {
  2740. tvItem.hItem = hTVCurItem;
  2741. if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
  2742. {
  2743. TreeView_SelectItem(hwndTV, hTVCurItem);
  2744. pCurItemNode = (LPTVITEMNODE) tvItem.lParam;
  2745. }
  2746. }
  2747. }
  2748. else
  2749. {
  2750. //
  2751. // Make sure we're not removing the only entry in the list.
  2752. //
  2753. MessageBeep(MB_ICONEXCLAMATION);
  2754. return;
  2755. }
  2756. //
  2757. // Find the previous default Tip.
  2758. //
  2759. for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
  2760. hLangItem != NULL ;
  2761. hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem)
  2762. )
  2763. {
  2764. tvItem.hItem = hLangItem;
  2765. if (TreeView_GetItem(hwndTV, &tvItem) &&
  2766. (pPrevDefItemNode = (LPTVITEMNODE) tvItem.lParam))
  2767. {
  2768. if (pPrevDefItemNode->bDefLang)
  2769. {
  2770. GetAtomName(pPrevDefItemNode->atmDefTipName, szDefTip, ARRAYSIZE(szDefTip));
  2771. UpdateDefaultTVLangItem(pPrevDefItemNode->dwLangID, szDefTip, FALSE, TRUE);
  2772. UpdateLangKBDItemNode(hLangItem, szDefTip, FALSE);
  2773. break;
  2774. }
  2775. }
  2776. }
  2777. pCurItemNode->bDefLang = TRUE;
  2778. if (pCurItemNode->atmDefTipName)
  2779. GetAtomName(pCurItemNode->atmDefTipName, szDefTip, ARRAYSIZE(szDefTip));
  2780. else
  2781. GetAtomName(pCurItemNode->atmTVItemName, szDefTip, ARRAYSIZE(szDefTip));
  2782. UpdateDefaultTVLangItem(pCurItemNode->dwLangID,
  2783. szDefTip,
  2784. TRUE,
  2785. pCurItemNode->hklSub ? TRUE : FALSE);
  2786. if (!UpdateLangKBDItemNode(hTVCurLangItem, szDefTip, TRUE))
  2787. {
  2788. SetNextDefaultLayout(pCurItemNode->dwLangID,
  2789. pCurItemNode->bDefLang,
  2790. szDefTip,
  2791. ARRAYSIZE(szDefTip));
  2792. }
  2793. if (pCurItemNode->uInputType & TV_ITEM_TYPE_LANG)
  2794. {
  2795. hItem = FindDefaultTipItem(pCurItemNode->dwLangID, szDefTip);
  2796. tvItem.hItem = hItem;
  2797. if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
  2798. pCurItemNode = (LPTVITEMNODE) tvItem.lParam;
  2799. //
  2800. // Select the default layout item as bold
  2801. //
  2802. SelectDefaultKbdLayoutAsBold(hwndTV, hItem);
  2803. pLangNode = (LPLANGNODE)pCurItemNode->lParam;
  2804. if (pLangNode)
  2805. pLangNode->wStatus |= (LANG_DEFAULT | LANG_DEF_CHANGE);
  2806. }
  2807. //
  2808. // Enable the Apply button.
  2809. //
  2810. g_dwChanges |= CHANGE_DEFAULT;
  2811. PropSheet_Changed(GetParent(hwnd), hwnd);
  2812. }
  2813. void Locale_CommandSetDefaultLayout(
  2814. HWND hwnd)
  2815. {
  2816. TV_ITEM tvItem;
  2817. HTREEITEM hTVItem;
  2818. HTREEITEM hLangItem;
  2819. HTREEITEM hTVCurItem;
  2820. TCHAR szDefTip[DESC_MAX];
  2821. TCHAR szLangText[DESC_MAX];
  2822. LPLANGNODE pLangNode = NULL;
  2823. LPTVITEMNODE pCurItemNode;
  2824. LPTVITEMNODE pPrevDefItemNode;
  2825. HWND hwndTV = GetDlgItem(hwnd, IDC_INPUT_LIST);
  2826. //
  2827. // Get the current selection layout in the input layout lists.
  2828. //
  2829. hTVCurItem = TreeView_GetSelection(hwndTV);
  2830. if (!hTVCurItem)
  2831. return;
  2832. tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
  2833. tvItem.hItem = hTVCurItem;
  2834. if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
  2835. {
  2836. //
  2837. // Get the pointer to the lang node from the list box
  2838. // item data.
  2839. //
  2840. pCurItemNode = (LPTVITEMNODE) tvItem.lParam;
  2841. }
  2842. else
  2843. {
  2844. //
  2845. // Make sure we're not removing the only entry in the list.
  2846. //
  2847. MessageBeep(MB_ICONEXCLAMATION);
  2848. return;
  2849. }
  2850. //
  2851. // Find the previous default Tip.
  2852. //
  2853. for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
  2854. hLangItem != NULL ;
  2855. hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem)
  2856. )
  2857. {
  2858. tvItem.hItem = hLangItem;
  2859. if (TreeView_GetItem(hwndTV, &tvItem) &&
  2860. (pPrevDefItemNode = (LPTVITEMNODE) tvItem.lParam))
  2861. {
  2862. if (pPrevDefItemNode->bDefLang)
  2863. {
  2864. if (pPrevDefItemNode->atmDefTipName)
  2865. GetAtomName(pPrevDefItemNode->atmDefTipName, szDefTip, ARRAYSIZE(szDefTip));
  2866. else
  2867. GetAtomName(pPrevDefItemNode->atmTVItemName, szDefTip, ARRAYSIZE(szDefTip));
  2868. UpdateDefaultTVLangItem(pPrevDefItemNode->dwLangID, szDefTip, FALSE, TRUE);
  2869. UpdateLangKBDItemNode(hLangItem, szDefTip, FALSE);
  2870. break;
  2871. }
  2872. }
  2873. }
  2874. if (pCurItemNode->atmDefTipName)
  2875. GetAtomName(pCurItemNode->atmDefTipName, szDefTip, ARRAYSIZE(szDefTip));
  2876. else
  2877. GetAtomName(pCurItemNode->atmTVItemName, szDefTip, ARRAYSIZE(szDefTip));
  2878. UpdateDefaultTVLangItem(pCurItemNode->dwLangID,
  2879. szDefTip,
  2880. TRUE,
  2881. pCurItemNode->hklSub ? TRUE : FALSE);
  2882. pCurItemNode->bDefLang = TRUE;
  2883. pLangNode = (LPLANGNODE)pCurItemNode->lParam;
  2884. if (pLangNode)
  2885. pLangNode->wStatus |= (LANG_DEFAULT | LANG_DEF_CHANGE);
  2886. if (hTVItem = FindTVLangItem(pCurItemNode->dwLangID, NULL))
  2887. {
  2888. int idxSel = -1;
  2889. TCHAR szDefItem[MAX_PATH];
  2890. HWND hwndDefList = GetDlgItem(g_hDlg, IDC_LOCALE_DEFAULT);
  2891. tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
  2892. tvItem.hItem = hTVItem;
  2893. if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam)
  2894. {
  2895. LPTVITEMNODE pTVItemNode;
  2896. pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
  2897. GetAtomName(pTVItemNode->atmTVItemName, szLangText, ARRAYSIZE(szLangText));
  2898. }
  2899. StringCchCopy(szDefItem, ARRAYSIZE(szDefItem), szLangText);
  2900. StringCchCat(szDefItem, ARRAYSIZE(szDefItem), TEXT(" - "));
  2901. StringCchCat(szDefItem, ARRAYSIZE(szDefItem), szDefTip);
  2902. //
  2903. // Set the default locale selection.
  2904. //
  2905. if ((idxSel = ComboBox_FindStringExact(hwndDefList, 0, szDefItem)) != CB_ERR)
  2906. ComboBox_SetCurSel(hwndDefList, idxSel);
  2907. }
  2908. SelectDefaultKbdLayoutAsBold(hwndTV, FindDefaultTipItem(pCurItemNode->dwLangID, szDefTip));
  2909. //
  2910. // Enable the Apply button.
  2911. //
  2912. g_dwChanges |= CHANGE_DEFAULT;
  2913. PropSheet_Changed(GetParent(hwnd), hwnd);
  2914. }
  2915. ////////////////////////////////////////////////////////////////////////////
  2916. //
  2917. // GetLanguageHotkeyFromRegistry()
  2918. //
  2919. ////////////////////////////////////////////////////////////////////////////
  2920. BOOL GetLanguageHotkeyFromRegistry(
  2921. LPTSTR lpLangKey,
  2922. UINT cchLangKey,
  2923. LPTSTR lpLayoutKey,
  2924. UINT cchLayoutKey)
  2925. {
  2926. DWORD cb;
  2927. HKEY hkey;
  2928. lpLangKey[0] = 0;
  2929. StringCchCopy(lpLayoutKey, cchLayoutKey, TEXT("3"));
  2930. if (RegOpenKey(HKEY_CURRENT_USER, c_szKbdToggleKey, &hkey) == ERROR_SUCCESS)
  2931. {
  2932. cb = sizeof(lpLangKey);
  2933. RegQueryValueEx(hkey, g_OSWIN95? NULL : c_szToggleHotKey, NULL, NULL, (LPBYTE)lpLangKey, &cb);
  2934. if (g_iEnabledKbdTips)
  2935. {
  2936. StringCchCopy(lpLangKey, cchLangKey, TEXT("1"));
  2937. RegQueryValueEx(hkey, c_szToggleLang, NULL, NULL, (LPBYTE)lpLangKey, &cb);
  2938. }
  2939. if (RegQueryValueEx(hkey, c_szToggleLayout, NULL, NULL, (LPBYTE)lpLayoutKey, &cb) != ERROR_SUCCESS)
  2940. {
  2941. if (lstrcmp(lpLangKey, TEXT("1")) == 0)
  2942. {
  2943. lpLayoutKey[0] = TEXT('2');
  2944. lpLayoutKey[1] = TEXT('\0');
  2945. }
  2946. if (lstrcmp(lpLangKey, TEXT("2")) == 0)
  2947. {
  2948. lpLayoutKey[0] = TEXT('1');
  2949. lpLayoutKey[1] = TEXT('\0');
  2950. }
  2951. else
  2952. {
  2953. lpLayoutKey[0] = TEXT('3');
  2954. lpLayoutKey[1] = TEXT('\0');
  2955. }
  2956. if (GetSystemMetrics(SM_MIDEASTENABLED))
  2957. {
  2958. lpLayoutKey[0] = TEXT('3');
  2959. lpLayoutKey[1] = TEXT('\0');
  2960. }
  2961. }
  2962. if (lstrcmp(lpLangKey, lpLayoutKey) == 0)
  2963. StringCchCopy(lpLayoutKey, cchLayoutKey, TEXT("3"));
  2964. RegCloseKey(hkey);
  2965. return TRUE;
  2966. }
  2967. else
  2968. return FALSE;
  2969. }
  2970. ////////////////////////////////////////////////////////////////////////////
  2971. //
  2972. // Locale_SetDefaultHotKey
  2973. //
  2974. // Set the default hotkey for a locale switch.
  2975. //
  2976. ////////////////////////////////////////////////////////////////////////////
  2977. void Locale_SetDefaultHotKey(
  2978. HWND hwnd,
  2979. BOOL bAdd)
  2980. {
  2981. LPHOTKEYINFO pHotKeyNode;
  2982. BOOL bReset = FALSE;
  2983. //
  2984. // Initialize lang hotkey value to switch between lnaguages.
  2985. //
  2986. if (g_bGetSwitchLangHotKey)
  2987. {
  2988. TCHAR szItem[DESC_MAX];
  2989. TCHAR sz[10];
  2990. TCHAR sz2[10];
  2991. g_SwitchLangHotKey.dwHotKeyID = HOTKEY_SWITCH_LANG;
  2992. g_SwitchLangHotKey.fdwEnable = MOD_CONTROL | MOD_ALT | MOD_SHIFT;
  2993. LoadString( hInstance,
  2994. IDS_KBD_SWITCH_LOCALE,
  2995. szItem,
  2996. sizeof(szItem) / sizeof(TCHAR) );
  2997. g_SwitchLangHotKey.atmHotKeyName = AddAtom(szItem);
  2998. if (!GetLanguageHotkeyFromRegistry(sz, ARRAYSIZE(sz), sz2, ARRAYSIZE(sz2)))
  2999. {
  3000. g_SwitchLangHotKey.uModifiers = 0;
  3001. g_SwitchLangHotKey.uLayoutHotKey = 0;
  3002. g_SwitchLangHotKey.uVKey = 0;
  3003. }
  3004. else
  3005. {
  3006. //
  3007. // Set the modifiers.
  3008. //
  3009. if (sz[1] == 0)
  3010. {
  3011. switch (sz[0])
  3012. {
  3013. case ( TEXT('1') ) :
  3014. {
  3015. g_SwitchLangHotKey.uModifiers = MOD_ALT | MOD_SHIFT;
  3016. break;
  3017. }
  3018. case ( TEXT('2') ) :
  3019. {
  3020. g_SwitchLangHotKey.uModifiers = MOD_CONTROL | MOD_SHIFT;
  3021. break;
  3022. }
  3023. case ( TEXT('3') ) :
  3024. {
  3025. g_SwitchLangHotKey.uModifiers = 0;
  3026. break;
  3027. }
  3028. case ( TEXT('4') ) :
  3029. {
  3030. g_SwitchLangHotKey.uModifiers = 0;
  3031. g_SwitchLangHotKey.uVKey = CHAR_GRAVE;
  3032. break;
  3033. }
  3034. }
  3035. }
  3036. //
  3037. // Get the layout hotkey from the registry
  3038. //
  3039. if (sz2[1] == 0)
  3040. {
  3041. switch (sz2[0])
  3042. {
  3043. case ( TEXT('1') ) :
  3044. {
  3045. g_SwitchLangHotKey.uLayoutHotKey = MOD_ALT | MOD_SHIFT;
  3046. break;
  3047. }
  3048. case ( TEXT('2') ) :
  3049. {
  3050. g_SwitchLangHotKey.uLayoutHotKey = MOD_CONTROL | MOD_SHIFT;
  3051. break;
  3052. }
  3053. case ( TEXT('3') ) :
  3054. {
  3055. g_SwitchLangHotKey.uLayoutHotKey = 0;
  3056. break;
  3057. }
  3058. case ( TEXT('4') ) :
  3059. {
  3060. g_SwitchLangHotKey.uLayoutHotKey = 0;
  3061. g_SwitchLangHotKey.uVKey = CHAR_GRAVE;
  3062. break;
  3063. }
  3064. }
  3065. }
  3066. }
  3067. g_bGetSwitchLangHotKey = FALSE;
  3068. }
  3069. //
  3070. // Get language switch hotkey
  3071. //
  3072. pHotKeyNode = (LPHOTKEYINFO) &g_SwitchLangHotKey;
  3073. //
  3074. // Check the current hotkey setting
  3075. //
  3076. if ((bAdd && g_iInputs >= 2) &&
  3077. (g_SwitchLangHotKey.uModifiers == 0 &&
  3078. g_SwitchLangHotKey.uLayoutHotKey == 0 &&
  3079. g_SwitchLangHotKey.uVKey == 0))
  3080. {
  3081. bReset = TRUE;
  3082. }
  3083. if (bAdd && (g_iInputs == 2 || bReset))
  3084. {
  3085. if (g_dwPrimLangID == LANG_THAI && g_iThaiLayout)
  3086. {
  3087. pHotKeyNode->uVKey = CHAR_GRAVE;
  3088. pHotKeyNode->uModifiers &= ~(MOD_CONTROL | MOD_ALT | MOD_SHIFT);
  3089. }
  3090. else
  3091. pHotKeyNode->uModifiers = MOD_ALT | MOD_SHIFT;
  3092. if (g_bMESystem)
  3093. {
  3094. pHotKeyNode->uVKey = CHAR_GRAVE;
  3095. pHotKeyNode->uLayoutHotKey &= ~(MOD_CONTROL | MOD_ALT | MOD_SHIFT);
  3096. }
  3097. else if (pHotKeyNode->uModifiers & MOD_CONTROL)
  3098. pHotKeyNode->uLayoutHotKey = MOD_ALT;
  3099. else
  3100. pHotKeyNode->uLayoutHotKey = MOD_CONTROL;
  3101. g_dwChanges |= CHANGE_LANGSWITCH;
  3102. }
  3103. if (!bAdd)
  3104. {
  3105. if (g_iInputs == 1)
  3106. {
  3107. //
  3108. // Remove the locale hotkey, since it's no longer required.
  3109. //
  3110. pHotKeyNode->uVKey = 0;
  3111. pHotKeyNode->uModifiers &= ~(MOD_CONTROL | MOD_ALT | MOD_SHIFT);
  3112. pHotKeyNode->uLayoutHotKey &= ~(MOD_CONTROL | MOD_ALT | MOD_SHIFT);
  3113. g_dwChanges |= CHANGE_LANGSWITCH;
  3114. }
  3115. else if ((g_dwPrimLangID == LANG_THAI && !g_iThaiLayout) &&
  3116. (pHotKeyNode->uVKey == CHAR_GRAVE))
  3117. {
  3118. //
  3119. // Reset the locale switch hotkey from Grave accent to
  3120. // Left-Alt + Shift.
  3121. //
  3122. pHotKeyNode->uVKey = 0;
  3123. if (pHotKeyNode->uLayoutHotKey & MOD_ALT)
  3124. pHotKeyNode->uModifiers = MOD_CONTROL | MOD_SHIFT;
  3125. else
  3126. pHotKeyNode->uModifiers = MOD_ALT | MOD_SHIFT;
  3127. g_dwChanges |= CHANGE_LANGSWITCH;
  3128. }
  3129. }
  3130. }
  3131. ////////////////////////////////////////////////////////////////////////////
  3132. //
  3133. // Locale_SetLanguageHotkey
  3134. //
  3135. // Set the language switch hotkey on the registry.
  3136. //
  3137. ////////////////////////////////////////////////////////////////////////////
  3138. void Locale_SetLanguageHotkey()
  3139. {
  3140. UINT idx, idx2;
  3141. HKEY hkeyToggle;
  3142. TCHAR szTemp[10], szTemp2[10];
  3143. LPHOTKEYINFO pHotKeyNode;
  3144. //
  3145. // Get language switch hotkey
  3146. //
  3147. pHotKeyNode = (LPHOTKEYINFO) &g_SwitchLangHotKey;
  3148. idx = 3;
  3149. idx2 = 3;
  3150. if (pHotKeyNode->uModifiers & MOD_ALT)
  3151. {
  3152. idx = 1;
  3153. }
  3154. else if (pHotKeyNode->uModifiers & MOD_CONTROL)
  3155. {
  3156. idx = 2;
  3157. }
  3158. else if (g_iThaiLayout && pHotKeyNode->uVKey == CHAR_GRAVE)
  3159. {
  3160. idx = 4;
  3161. }
  3162. if (pHotKeyNode->uLayoutHotKey & MOD_ALT)
  3163. {
  3164. idx2 = 1;
  3165. }
  3166. else if (pHotKeyNode->uLayoutHotKey & MOD_CONTROL)
  3167. {
  3168. idx2 = 2;
  3169. }
  3170. else if (g_bMESystem && pHotKeyNode->uVKey == CHAR_GRAVE)
  3171. {
  3172. idx2 = 4;
  3173. }
  3174. //
  3175. // Get the toggle hotkey as a string so that it can be written
  3176. // into the registry (as data).
  3177. //
  3178. StringCchPrintf(szTemp, ARRAYSIZE(szTemp), TEXT("%d"), idx);
  3179. StringCchPrintf(szTemp2, ARRAYSIZE(szTemp2), TEXT("%d"), idx2);
  3180. //
  3181. // Set the new entry in the registry. It is of the form:
  3182. //
  3183. // HKCU\Keyboard Layout
  3184. // Toggle: Hotkey = <hotkey number>
  3185. //
  3186. if (RegCreateKey(HKEY_CURRENT_USER,
  3187. c_szKbdToggleKey,
  3188. &hkeyToggle ) == ERROR_SUCCESS)
  3189. {
  3190. RegSetValueEx(hkeyToggle,
  3191. g_OSWIN95? NULL : c_szToggleHotKey,
  3192. 0,
  3193. REG_SZ,
  3194. (LPBYTE)szTemp,
  3195. (DWORD)(lstrlen(szTemp) + 1) * sizeof(TCHAR) );
  3196. RegSetValueEx(hkeyToggle,
  3197. c_szToggleLang,
  3198. 0,
  3199. REG_SZ,
  3200. (LPBYTE)szTemp,
  3201. (DWORD)(lstrlen(szTemp) + 1) * sizeof(TCHAR) );
  3202. RegSetValueEx(hkeyToggle,
  3203. c_szToggleLayout,
  3204. 0,
  3205. REG_SZ,
  3206. (LPBYTE)szTemp2,
  3207. (DWORD)(lstrlen(szTemp2) + 1) * sizeof(TCHAR) );
  3208. RegCloseKey(hkeyToggle);
  3209. }
  3210. //
  3211. // Since we updated the registry, we should reread this next time.
  3212. //
  3213. g_bGetSwitchLangHotKey = TRUE;
  3214. //
  3215. // Call SystemParametersInfo to enable the toggle.
  3216. //
  3217. SystemParametersInfo(SPI_SETLANGTOGGLE, 0, NULL, 0);
  3218. }
  3219. ////////////////////////////////////////////////////////////////////////////
  3220. //
  3221. // Locale_FileExists
  3222. //
  3223. // Determines if the file exists and is accessible.
  3224. //
  3225. ////////////////////////////////////////////////////////////////////////////
  3226. BOOL Locale_FileExists(
  3227. LPTSTR pFileName)
  3228. {
  3229. WIN32_FIND_DATA FindData;
  3230. HANDLE FindHandle;
  3231. BOOL bRet;
  3232. UINT OldMode;
  3233. OldMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  3234. FindHandle = FindFirstFile(pFileName, &FindData);
  3235. if (FindHandle == INVALID_HANDLE_VALUE)
  3236. {
  3237. bRet = FALSE;
  3238. }
  3239. else
  3240. {
  3241. FindClose(FindHandle);
  3242. bRet = TRUE;
  3243. }
  3244. SetErrorMode(OldMode);
  3245. return (bRet);
  3246. }
  3247. ////////////////////////////////////////////////////////////////////////////
  3248. //
  3249. // Locale_GetHotkeys
  3250. //
  3251. // Gets the hotkey keyboard switch value from the registry and then
  3252. // sets the appropriate radio button in the dialog.
  3253. //
  3254. ////////////////////////////////////////////////////////////////////////////
  3255. void Locale_GetHotkeys(
  3256. HWND hwnd,
  3257. BOOL *bHasIme)
  3258. {
  3259. TCHAR sz[10];
  3260. TCHAR sz2[10];
  3261. int ctr1, iLangCount, iCount;
  3262. UINT iIndex;
  3263. TCHAR szLanguage[DESC_MAX];
  3264. TCHAR szLayout[DESC_MAX];
  3265. TCHAR szItem[DESC_MAX];
  3266. TCHAR szAction[DESC_MAX];
  3267. LPLANGNODE pLangNode;
  3268. HWND hwndTV = g_hwndTV;
  3269. HWND hwndHotkey = GetDlgItem(hwnd, IDC_KBDL_HOTKEY_LIST);
  3270. LPHOTKEYINFO aImeHotKey;
  3271. TV_ITEM tvItem;
  3272. HTREEITEM hItem;
  3273. HTREEITEM hLangItem;
  3274. HTREEITEM hGroupItem;
  3275. //
  3276. // Clear out the hot keys list box.
  3277. //
  3278. ListBox_ResetContent(hwndHotkey);
  3279. //
  3280. // Get the hotkey value to switch between locales from the registry.
  3281. //
  3282. if (g_bGetSwitchLangHotKey)
  3283. {
  3284. g_SwitchLangHotKey.dwHotKeyID = HOTKEY_SWITCH_LANG;
  3285. g_SwitchLangHotKey.fdwEnable = MOD_CONTROL | MOD_ALT | MOD_SHIFT;
  3286. LoadString( hInstance,
  3287. IDS_KBD_SWITCH_LOCALE,
  3288. szItem,
  3289. sizeof(szItem) / sizeof(TCHAR) );
  3290. g_SwitchLangHotKey.atmHotKeyName = AddAtom(szItem);
  3291. if (!GetLanguageHotkeyFromRegistry(sz, ARRAYSIZE(sz), sz2, ARRAYSIZE(sz2)))
  3292. {
  3293. g_SwitchLangHotKey.uModifiers = 0;
  3294. g_SwitchLangHotKey.uLayoutHotKey = 0;
  3295. g_SwitchLangHotKey.uVKey = 0;
  3296. }
  3297. else
  3298. {
  3299. //
  3300. // Set the modifiers.
  3301. //
  3302. if (sz[1] == 0)
  3303. {
  3304. switch (sz[0])
  3305. {
  3306. case ( TEXT('1') ) :
  3307. {
  3308. g_SwitchLangHotKey.uModifiers = MOD_ALT | MOD_SHIFT;
  3309. break;
  3310. }
  3311. case ( TEXT('2') ) :
  3312. {
  3313. g_SwitchLangHotKey.uModifiers = MOD_CONTROL | MOD_SHIFT;
  3314. break;
  3315. }
  3316. case ( TEXT('3') ) :
  3317. {
  3318. g_SwitchLangHotKey.uModifiers = 0;
  3319. break;
  3320. }
  3321. case ( TEXT('4') ) :
  3322. {
  3323. g_SwitchLangHotKey.uModifiers = 0;
  3324. g_SwitchLangHotKey.uVKey = CHAR_GRAVE;
  3325. break;
  3326. }
  3327. }
  3328. }
  3329. //
  3330. // Get the layout hotkey from the registry
  3331. //
  3332. if (sz2[1] == 0)
  3333. {
  3334. switch (sz2[0])
  3335. {
  3336. case ( TEXT('1') ) :
  3337. {
  3338. g_SwitchLangHotKey.uLayoutHotKey = MOD_ALT | MOD_SHIFT;
  3339. break;
  3340. }
  3341. case ( TEXT('2') ) :
  3342. {
  3343. g_SwitchLangHotKey.uLayoutHotKey = MOD_CONTROL | MOD_SHIFT;
  3344. break;
  3345. }
  3346. case ( TEXT('3') ) :
  3347. {
  3348. g_SwitchLangHotKey.uLayoutHotKey = 0;
  3349. break;
  3350. }
  3351. case ( TEXT('4') ) :
  3352. {
  3353. g_SwitchLangHotKey.uLayoutHotKey = 0;
  3354. g_SwitchLangHotKey.uVKey = CHAR_GRAVE;
  3355. break;
  3356. }
  3357. }
  3358. }
  3359. g_bGetSwitchLangHotKey = FALSE;
  3360. }
  3361. }
  3362. iIndex = ListBox_InsertString(hwndHotkey, -1, szItem);
  3363. ListBox_SetItemData(hwndHotkey, iIndex, (LONG_PTR)&g_SwitchLangHotKey);
  3364. //
  3365. // Determine the hotkey value for direct locale switch.
  3366. //
  3367. // Query all available direct switch hotkey IDs and put the
  3368. // corresponding hkl, key, and modifiers information into the array.
  3369. //
  3370. for (ctr1 = 0; ctr1 < DSWITCH_HOTKEY_SIZE; ctr1++)
  3371. {
  3372. BOOL fRet;
  3373. g_aDirectSwitchHotKey[ctr1].dwHotKeyID = IME_HOTKEY_DSWITCH_FIRST + ctr1;
  3374. g_aDirectSwitchHotKey[ctr1].fdwEnable = MOD_VIRTKEY | MOD_CONTROL |
  3375. MOD_ALT | MOD_SHIFT |
  3376. MOD_LEFT | MOD_RIGHT;
  3377. g_aDirectSwitchHotKey[ctr1].idxLayout = -1;
  3378. fRet = ImmGetHotKey( g_aDirectSwitchHotKey[ctr1].dwHotKeyID,
  3379. &g_aDirectSwitchHotKey[ctr1].uModifiers,
  3380. &g_aDirectSwitchHotKey[ctr1].uVKey,
  3381. &g_aDirectSwitchHotKey[ctr1].hkl );
  3382. if (!fRet)
  3383. {
  3384. g_aDirectSwitchHotKey[ctr1].uModifiers = 0;
  3385. if ((g_aDirectSwitchHotKey[ctr1].fdwEnable & (MOD_LEFT | MOD_RIGHT)) ==
  3386. (MOD_LEFT | MOD_RIGHT))
  3387. {
  3388. g_aDirectSwitchHotKey[ctr1].uModifiers |= MOD_LEFT | MOD_RIGHT;
  3389. }
  3390. g_aDirectSwitchHotKey[ctr1].uVKey = 0;
  3391. g_aDirectSwitchHotKey[ctr1].hkl = (HKL)NULL;
  3392. }
  3393. }
  3394. LoadString( hInstance,
  3395. IDS_KBD_SWITCH_TO,
  3396. szAction,
  3397. sizeof(szAction) / sizeof(TCHAR) );
  3398. //
  3399. // Try to find either a matching hkl or empty spot in the array
  3400. // for each of the hkls in the locale list.
  3401. //
  3402. for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
  3403. hLangItem != NULL ;
  3404. hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem)
  3405. )
  3406. {
  3407. for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem);
  3408. hGroupItem != NULL;
  3409. hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem))
  3410. {
  3411. for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
  3412. hItem != NULL;
  3413. hItem = TreeView_GetNextSibling(hwndTV, hItem))
  3414. {
  3415. int ctr2;
  3416. int iEmpty = -1;
  3417. int iMatch = -1;
  3418. LPTVITEMNODE pTVItemNode;
  3419. tvItem.hItem = hItem;
  3420. tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
  3421. if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
  3422. {
  3423. pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
  3424. pLangNode = (LPLANGNODE)pTVItemNode->lParam;
  3425. }
  3426. else
  3427. break;
  3428. if (pLangNode == NULL &&
  3429. (pTVItemNode->uInputType & INPUT_TYPE_KBD) &&
  3430. pTVItemNode->hklSub)
  3431. {
  3432. if (tvItem.hItem = FindTVLangItem(pTVItemNode->dwLangID, NULL))
  3433. {
  3434. if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
  3435. {
  3436. pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
  3437. pLangNode = (LPLANGNODE)pTVItemNode->lParam;
  3438. }
  3439. }
  3440. }
  3441. if (pLangNode == NULL)
  3442. continue;
  3443. for (ctr2 = 0; ctr2 < DSWITCH_HOTKEY_SIZE; ctr2++)
  3444. {
  3445. if (!g_aDirectSwitchHotKey[ctr2].hkl)
  3446. {
  3447. if ((iEmpty == -1) &&
  3448. (g_aDirectSwitchHotKey[ctr2].idxLayout == -1))
  3449. {
  3450. //
  3451. // Remember the first empty spot.
  3452. //
  3453. iEmpty = ctr2;
  3454. }
  3455. }
  3456. else if (g_aDirectSwitchHotKey[ctr2].hkl == pLangNode->hkl)
  3457. {
  3458. //
  3459. // We found a match. Remember it.
  3460. //
  3461. iMatch = ctr2;
  3462. break;
  3463. }
  3464. }
  3465. if (iMatch == -1)
  3466. {
  3467. if (iEmpty == -1)
  3468. {
  3469. //
  3470. // We don't have any spots left.
  3471. //
  3472. continue;
  3473. }
  3474. else
  3475. {
  3476. //
  3477. // New item.
  3478. //
  3479. iMatch = iEmpty;
  3480. if (pLangNode->hkl)
  3481. {
  3482. g_aDirectSwitchHotKey[iMatch].hkl = pLangNode->hkl;
  3483. }
  3484. else
  3485. {
  3486. //
  3487. // This must be a newly added layout. We don't have
  3488. // the hkl yet. Remember the index position of this
  3489. // layout - we can get the real hkl when the user
  3490. // chooses to apply.
  3491. //
  3492. g_aDirectSwitchHotKey[iMatch].idxLayout = ctr1;
  3493. }
  3494. }
  3495. }
  3496. if (pLangNode->wStatus & LANG_IME)
  3497. {
  3498. *bHasIme = TRUE;
  3499. }
  3500. if (pLangNode->wStatus & LANG_HOTKEY)
  3501. {
  3502. g_aDirectSwitchHotKey[iMatch].uModifiers = pLangNode->uModifiers;
  3503. g_aDirectSwitchHotKey[iMatch].uVKey = pLangNode->uVKey;
  3504. }
  3505. GetAtomName(g_lpLang[pLangNode->iLang].atmLanguageName,
  3506. szLanguage,
  3507. ARRAYSIZE(szLanguage));
  3508. GetAtomName(g_lpLayout[pLangNode->iLayout].atmLayoutText,
  3509. szLayout,
  3510. ARRAYSIZE(szLayout));
  3511. StringCchCat(szLanguage, ARRAYSIZE(szLanguage), TEXT(" - "));
  3512. StringCchCat(szLanguage, ARRAYSIZE(szLanguage), szLayout);
  3513. StringCchPrintf(szItem, ARRAYSIZE(szItem), szAction, szLanguage);
  3514. if (ListBox_FindStringExact(hwndHotkey, 0, szItem) != CB_ERR)
  3515. continue;
  3516. g_aDirectSwitchHotKey[iMatch].atmHotKeyName = AddAtom(szItem);
  3517. iIndex = ListBox_InsertString(hwndHotkey, -1, szItem);
  3518. ListBox_SetItemData(hwndHotkey, iIndex, &g_aDirectSwitchHotKey[iMatch]);
  3519. }
  3520. }
  3521. }
  3522. //
  3523. // Determine IME specific hotkeys for CHS and CHT locales.
  3524. //
  3525. iCount = *bHasIme ? Locale_GetImeHotKeyInfo(hwnd,&aImeHotKey) : 0;
  3526. for (ctr1 = 0; ctr1 < iCount; ctr1++)
  3527. {
  3528. BOOL bRet;
  3529. LoadString( hInstance,
  3530. aImeHotKey[ctr1].idHotKeyName,
  3531. szItem,
  3532. sizeof(szItem) / sizeof(TCHAR) );
  3533. aImeHotKey[ctr1].atmHotKeyName = AddAtom(szItem);
  3534. iIndex = ListBox_InsertString(hwndHotkey, -1,szItem);
  3535. ListBox_SetItemData(hwndHotkey, iIndex, &aImeHotKey[ctr1]);
  3536. //
  3537. // Get the hot key value.
  3538. //
  3539. bRet = ImmGetHotKey( aImeHotKey[ctr1].dwHotKeyID,
  3540. &aImeHotKey[ctr1].uModifiers,
  3541. &aImeHotKey[ctr1].uVKey,
  3542. NULL );
  3543. if (!bRet)
  3544. {
  3545. aImeHotKey[ctr1].uModifiers = 0;
  3546. if ((aImeHotKey[ctr1].fdwEnable & (MOD_LEFT | MOD_RIGHT)) ==
  3547. (MOD_LEFT | MOD_RIGHT))
  3548. {
  3549. aImeHotKey[ctr1].uModifiers |= MOD_LEFT | MOD_RIGHT;
  3550. }
  3551. aImeHotKey[ctr1].uVKey = 0;
  3552. aImeHotKey[ctr1].hkl = (HKL)NULL;
  3553. }
  3554. }
  3555. ListBox_SetCurSel(hwndHotkey, 0);
  3556. }
  3557. ////////////////////////////////////////////////////////////////////////////
  3558. //
  3559. // Locale_SetImmHotkey
  3560. //
  3561. ////////////////////////////////////////////////////////////////////////////
  3562. void Locale_SetImmHotkey(
  3563. HWND hwnd,
  3564. LPLANGNODE pLangNode,
  3565. UINT nLangs,
  3566. HKL * pLangs,
  3567. BOOL *bDirectSwitch)
  3568. {
  3569. int ctr1;
  3570. HKL hkl;
  3571. BOOL bRet;
  3572. UINT uVKey;
  3573. UINT uModifiers;
  3574. int iEmpty = -1;
  3575. int iMatch = -1;
  3576. LPHOTKEYINFO pHotKeyNode;
  3577. if (pLangNode == NULL)
  3578. return;
  3579. for (ctr1 = 0; ctr1 < DSWITCH_HOTKEY_SIZE; ctr1++)
  3580. {
  3581. if (!g_aDirectSwitchHotKey[ctr1].hkl)
  3582. {
  3583. if ((iEmpty == -1) &&
  3584. (g_aDirectSwitchHotKey[ctr1].idxLayout == -1))
  3585. {
  3586. //
  3587. // Remember the first empty spot.
  3588. //
  3589. iEmpty = ctr1;
  3590. }
  3591. }
  3592. else if (g_aDirectSwitchHotKey[ctr1].hkl == pLangNode->hkl)
  3593. {
  3594. //
  3595. // We found a match. Remember it.
  3596. //
  3597. iMatch = ctr1;
  3598. break;
  3599. }
  3600. }
  3601. if (iMatch == -1)
  3602. {
  3603. if (iEmpty == -1)
  3604. {
  3605. //
  3606. // We don't have any spots left.
  3607. //
  3608. return;
  3609. }
  3610. else
  3611. {
  3612. //
  3613. // New item.
  3614. //
  3615. iMatch = iEmpty;
  3616. if (pLangNode->hkl)
  3617. {
  3618. g_aDirectSwitchHotKey[iMatch].hkl = pLangNode->hkl;
  3619. }
  3620. else
  3621. {
  3622. //
  3623. // This must be a newly added layout. We don't have
  3624. // the hkl yet. Remember the index position of this
  3625. // layout - we can get the real hkl when the user
  3626. // chooses to apply.
  3627. //
  3628. g_aDirectSwitchHotKey[iMatch].idxLayout = ctr1;
  3629. }
  3630. }
  3631. }
  3632. if (iMatch == -1)
  3633. return;
  3634. //
  3635. // Get Hotkey information for current layout.
  3636. //
  3637. pHotKeyNode = (LPHOTKEYINFO) &g_aDirectSwitchHotKey[iMatch];
  3638. bRet = ImmGetHotKey(pHotKeyNode->dwHotKeyID, &uModifiers, &uVKey, &hkl);
  3639. if (!bRet &&
  3640. (!pHotKeyNode->uVKey) &&
  3641. ((pHotKeyNode->uModifiers & (MOD_ALT | MOD_CONTROL | MOD_SHIFT))
  3642. != (MOD_ALT | MOD_CONTROL | MOD_SHIFT)))
  3643. {
  3644. //
  3645. // No such hotkey exists. User does not specify key and modifier
  3646. // information either. We can skip this one.
  3647. //
  3648. return;
  3649. }
  3650. if ((pHotKeyNode->uModifiers == uModifiers) &&
  3651. (pHotKeyNode->uVKey == uVKey))
  3652. {
  3653. //
  3654. // No change.
  3655. //
  3656. if (IS_DIRECT_SWITCH_HOTKEY(pHotKeyNode->dwHotKeyID))
  3657. {
  3658. *bDirectSwitch = TRUE;
  3659. }
  3660. return;
  3661. }
  3662. if (pHotKeyNode->idxLayout != -1)
  3663. {
  3664. //
  3665. // We had this layout index remembered because at that time
  3666. // we did not have a real hkl to work with. Now it is
  3667. // time to get the real hkl.
  3668. //
  3669. pHotKeyNode->hkl = pLangNode->hkl;
  3670. }
  3671. if (!bRet && IS_DIRECT_SWITCH_HOTKEY(pHotKeyNode->dwHotKeyID))
  3672. {
  3673. //
  3674. // New direct switch hotkey ID. We need to see if the same
  3675. // hkl is set at another ID. If so, set the other ID instead
  3676. // of the one requested.
  3677. //
  3678. DWORD dwHotKeyID;
  3679. //
  3680. // Loop through all direct switch hotkeys.
  3681. //
  3682. for (dwHotKeyID = IME_HOTKEY_DSWITCH_FIRST;
  3683. (dwHotKeyID <= IME_HOTKEY_DSWITCH_LAST);
  3684. dwHotKeyID++)
  3685. {
  3686. if (dwHotKeyID == pHotKeyNode->dwHotKeyID)
  3687. {
  3688. //
  3689. // Skip itself.
  3690. //
  3691. continue;
  3692. }
  3693. bRet = ImmGetHotKey(dwHotKeyID, &uModifiers, &uVKey, &hkl);
  3694. if (!bRet)
  3695. {
  3696. //
  3697. // Did not find the hotkey id. Skip.
  3698. //
  3699. continue;
  3700. }
  3701. if (hkl == pHotKeyNode->hkl)
  3702. {
  3703. //
  3704. // We found the same hkl already with hotkey
  3705. // settings at another ID. Set hotkey
  3706. // ID equal to the one with the same hkl. So later
  3707. // we will modify hotkey for the correct hkl.
  3708. //
  3709. pHotKeyNode->dwHotKeyID = dwHotKeyID;
  3710. break;
  3711. }
  3712. }
  3713. }
  3714. //
  3715. // Set the hotkey value.
  3716. //
  3717. bRet = ImmSetHotKey( pHotKeyNode->dwHotKeyID,
  3718. pHotKeyNode->uModifiers,
  3719. pHotKeyNode->uVKey,
  3720. pHotKeyNode->hkl );
  3721. if (bRet)
  3722. {
  3723. //
  3724. // Hotkey set successfully. See if user used any direct
  3725. // switch hot key. We may have to load imm later.
  3726. //
  3727. if (IS_DIRECT_SWITCH_HOTKEY(pHotKeyNode->dwHotKeyID))
  3728. {
  3729. if (pHotKeyNode->uVKey != 0)
  3730. {
  3731. *bDirectSwitch = TRUE;
  3732. }
  3733. }
  3734. else
  3735. {
  3736. //
  3737. // Must be IME related hotkey. We need to sync up the
  3738. // imes so that the new hotkey is effective to all
  3739. // of them.
  3740. //
  3741. UINT ctr2;
  3742. for (ctr2 = 0; ctr2 < nLangs; ctr2++)
  3743. {
  3744. if (!ImmIsIME(pLangs[ctr2]))
  3745. {
  3746. continue;
  3747. }
  3748. ImmEscape( pLangs[ctr2],
  3749. NULL,
  3750. IME_ESC_SYNC_HOTKEY,
  3751. &pHotKeyNode->dwHotKeyID );
  3752. }
  3753. }
  3754. }
  3755. else
  3756. {
  3757. //
  3758. // Failed to set hotkey. Maybe a duplicate. Warn user.
  3759. //
  3760. TCHAR szString[DESC_MAX];
  3761. GetAtomName( pHotKeyNode->atmHotKeyName,
  3762. szString,
  3763. sizeof(szString) / sizeof(TCHAR) );
  3764. Locale_ErrorMsg(hwnd, IDS_KBD_SET_HOTKEY_ERR, szString);
  3765. }
  3766. }
  3767. ////////////////////////////////////////////////////////////////////////////
  3768. //
  3769. // Locale_SetImmCHxHotkey
  3770. //
  3771. ////////////////////////////////////////////////////////////////////////////
  3772. void Locale_SetImmCHxHotkey(
  3773. HWND hwnd,
  3774. UINT nLangs,
  3775. HKL * pLangs)
  3776. {
  3777. HKL hkl;
  3778. UINT ctr1;
  3779. UINT uVKey;
  3780. UINT iCount;
  3781. UINT uModifiers;
  3782. LPHOTKEYINFO aImeHotKey;
  3783. LPHOTKEYINFO pHotKeyNode;
  3784. //
  3785. // Determine IME specific hotkeys for CHS and CHT locales.
  3786. //
  3787. iCount = Locale_GetImeHotKeyInfo(hwnd, &aImeHotKey);
  3788. for (ctr1 = 0; ctr1 < iCount; ctr1++)
  3789. {
  3790. UINT iIndex;
  3791. BOOL bRet;
  3792. //
  3793. // Get Hotkey information for current layout.
  3794. //
  3795. pHotKeyNode = (LPHOTKEYINFO) &aImeHotKey[ctr1];
  3796. bRet = ImmGetHotKey(pHotKeyNode->dwHotKeyID, &uModifiers, &uVKey, &hkl);
  3797. if (!bRet &&
  3798. (!pHotKeyNode->uVKey) &&
  3799. ((pHotKeyNode->uModifiers & (MOD_ALT | MOD_CONTROL | MOD_SHIFT))
  3800. != (MOD_ALT | MOD_CONTROL | MOD_SHIFT)))
  3801. {
  3802. //
  3803. // No such hotkey exists. User does not specify key and modifier
  3804. // information either. We can skip this one.
  3805. //
  3806. continue;
  3807. }
  3808. if ((pHotKeyNode->uModifiers == uModifiers) &&
  3809. (pHotKeyNode->uVKey == uVKey))
  3810. {
  3811. //
  3812. // No change.
  3813. //
  3814. continue;
  3815. }
  3816. //
  3817. // Set the hotkey value.
  3818. //
  3819. bRet = ImmSetHotKey( pHotKeyNode->dwHotKeyID,
  3820. pHotKeyNode->uModifiers,
  3821. pHotKeyNode->uVKey,
  3822. pHotKeyNode->hkl );
  3823. if (bRet)
  3824. {
  3825. //
  3826. // Must be IME related hotkey. We need to sync up the
  3827. // imes so that the new hotkey is effective to all
  3828. // of them.
  3829. //
  3830. UINT ctr2;
  3831. for (ctr2 = 0; ctr2 < nLangs; ctr2++)
  3832. {
  3833. if (!ImmIsIME(pLangs[ctr2]))
  3834. {
  3835. continue;
  3836. }
  3837. ImmEscape( pLangs[ctr2],
  3838. NULL,
  3839. IME_ESC_SYNC_HOTKEY,
  3840. &pHotKeyNode->dwHotKeyID );
  3841. }
  3842. }
  3843. else
  3844. {
  3845. //
  3846. // Failed to set hotkey. Maybe a duplicate. Warn user.
  3847. //
  3848. TCHAR szString[DESC_MAX];
  3849. GetAtomName( pHotKeyNode->atmHotKeyName,
  3850. szString,
  3851. sizeof(szString) / sizeof(TCHAR) );
  3852. Locale_ErrorMsg(hwnd, IDS_KBD_SET_HOTKEY_ERR, szString);
  3853. }
  3854. }
  3855. }
  3856. ////////////////////////////////////////////////////////////////////////////
  3857. //
  3858. // Locale_GetAttributes
  3859. //
  3860. // Gets the global layout attributes (eg: CapsLock/ShiftLock value) from
  3861. // the registry and then sets the appropriate radio button in the dialog.
  3862. //
  3863. ////////////////////////////////////////////////////////////////////////////
  3864. void Locale_GetAttributes(
  3865. HWND hwnd)
  3866. {
  3867. DWORD cb;
  3868. HKEY hkey;
  3869. //
  3870. // Initialize the global.
  3871. //
  3872. g_dwAttributes = 0; // KLF_SHIFTLOCK = 0x00010000
  3873. //
  3874. // Get the Atributes value from the registry.
  3875. //
  3876. if (RegOpenKey(HKEY_CURRENT_USER, c_szKbdLayouts, &hkey) == ERROR_SUCCESS)
  3877. {
  3878. cb = sizeof(DWORD);
  3879. RegQueryValueEx( hkey,
  3880. c_szAttributes,
  3881. NULL,
  3882. NULL,
  3883. (LPBYTE)&g_dwAttributes,
  3884. &cb );
  3885. RegCloseKey(hkey);
  3886. }
  3887. //
  3888. // Set the radio buttons appropriately.
  3889. //
  3890. CheckDlgButton( hwnd,
  3891. IDC_KBDL_SHIFTLOCK,
  3892. (g_dwAttributes & KLF_SHIFTLOCK)
  3893. ? BST_CHECKED
  3894. : BST_UNCHECKED );
  3895. CheckDlgButton( hwnd,
  3896. IDC_KBDL_CAPSLOCK,
  3897. (g_dwAttributes & KLF_SHIFTLOCK)
  3898. ? BST_UNCHECKED
  3899. : BST_CHECKED);
  3900. }
  3901. ////////////////////////////////////////////////////////////////////////////
  3902. //
  3903. // Locale_LoadLayouts
  3904. //
  3905. // Loads the layouts from the registry.
  3906. //
  3907. ////////////////////////////////////////////////////////////////////////////
  3908. BOOL Locale_LoadLayouts(
  3909. HWND hwnd)
  3910. {
  3911. HKEY hKey;
  3912. HKEY hkey1;
  3913. DWORD cb;
  3914. DWORD dwIndex;
  3915. LONG dwRetVal;
  3916. DWORD dwValue;
  3917. DWORD dwType;
  3918. TCHAR szValue[MAX_PATH]; // language id (number)
  3919. TCHAR szData[MAX_PATH]; // language name
  3920. TCHAR szSystemDir[MAX_PATH * 2];
  3921. UINT SysDirLen;
  3922. DWORD dwLayoutID;
  3923. BOOL bLoadedLayout;
  3924. //
  3925. // Load shlwapi module to get the localized layout name
  3926. //
  3927. g_hShlwapi = LoadSystemLibrary(TEXT("shlwapi.dll"));
  3928. if (g_hShlwapi)
  3929. {
  3930. //
  3931. // Get address SHLoadRegUIStringW
  3932. //
  3933. pfnSHLoadRegUIString = GetProcAddress(g_hShlwapi, (LPVOID)439);
  3934. }
  3935. //
  3936. // Now read all of the layouts from the registry.
  3937. //
  3938. if (RegOpenKey(HKEY_LOCAL_MACHINE, c_szLayoutPath, &hKey) != ERROR_SUCCESS)
  3939. {
  3940. Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
  3941. return (FALSE);
  3942. }
  3943. dwIndex = 0;
  3944. dwRetVal = RegEnumKey( hKey,
  3945. dwIndex,
  3946. szValue,
  3947. sizeof(szValue) / sizeof(TCHAR) );
  3948. if (dwRetVal != ERROR_SUCCESS)
  3949. {
  3950. Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
  3951. RegCloseKey(hKey);
  3952. return (FALSE);
  3953. }
  3954. g_hLayout = LocalAlloc(LHND, ALLOCBLOCK * sizeof(LAYOUT));
  3955. g_nLayoutBuffSize = ALLOCBLOCK;
  3956. g_iLayoutBuff = 0;
  3957. g_iLayoutIME = 0; // number of IME layouts.
  3958. g_lpLayout = LocalLock(g_hLayout);
  3959. if (!g_hLayout)
  3960. {
  3961. Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
  3962. RegCloseKey(hKey);
  3963. return (FALSE);
  3964. }
  3965. //
  3966. // Save the system directory string.
  3967. //
  3968. szSystemDir[0] = 0;
  3969. if (SysDirLen = GetSystemDirectory(szSystemDir, MAX_PATH))
  3970. {
  3971. if (SysDirLen > MAX_PATH)
  3972. {
  3973. SysDirLen = 0;
  3974. szSystemDir[0] = 0;
  3975. }
  3976. else if (szSystemDir[SysDirLen - 1] != TEXT('\\'))
  3977. {
  3978. szSystemDir[SysDirLen] = TEXT('\\');
  3979. szSystemDir[SysDirLen + 1] = 0;
  3980. SysDirLen++;
  3981. }
  3982. }
  3983. do
  3984. {
  3985. //
  3986. // New layout - get the layout id, the layout file name, and
  3987. // the layout description string.
  3988. //
  3989. if (g_iLayoutBuff + 1 == g_nLayoutBuffSize)
  3990. {
  3991. HANDLE hTemp;
  3992. LocalUnlock(g_hLayout);
  3993. g_nLayoutBuffSize += ALLOCBLOCK;
  3994. hTemp = LocalReAlloc( g_hLayout,
  3995. g_nLayoutBuffSize * sizeof(LAYOUT),
  3996. LHND );
  3997. if (hTemp == NULL)
  3998. {
  3999. break;
  4000. }
  4001. g_hLayout = hTemp;
  4002. g_lpLayout = LocalLock(g_hLayout);
  4003. }
  4004. //
  4005. // Get the layout id
  4006. //
  4007. dwLayoutID = TransNum(szValue);
  4008. //
  4009. // Save the layout id.
  4010. //
  4011. g_lpLayout[g_iLayoutBuff].dwID = dwLayoutID;
  4012. StringCchCopy(szData, ARRAYSIZE(szData), c_szLayoutPath);
  4013. StringCchCat(szData, ARRAYSIZE(szData), TEXT("\\"));
  4014. StringCchCat(szData, ARRAYSIZE(szData), szValue);
  4015. if (RegOpenKey(HKEY_LOCAL_MACHINE, szData, &hkey1) == ERROR_SUCCESS)
  4016. {
  4017. //
  4018. // Get the name of the layout file.
  4019. //
  4020. szValue[0] = TEXT('\0');
  4021. cb = sizeof(szValue);
  4022. if ((RegQueryValueEx( hkey1,
  4023. c_szLayoutFile,
  4024. NULL,
  4025. NULL,
  4026. (LPBYTE)szValue,
  4027. &cb ) == ERROR_SUCCESS) &&
  4028. (cb > sizeof(TCHAR)))
  4029. {
  4030. g_lpLayout[g_iLayoutBuff].atmLayoutFile = AddAtom(szValue);
  4031. //
  4032. // See if the layout file exists already.
  4033. //
  4034. StringCchCopy(szSystemDir + SysDirLen,
  4035. ARRAYSIZE(szSystemDir) - SysDirLen,
  4036. szValue);
  4037. g_lpLayout[g_iLayoutBuff].bInstalled = (Locale_FileExists(szSystemDir));
  4038. //
  4039. // Get the name of the layout.
  4040. //
  4041. szValue[0] = TEXT('\0');
  4042. cb = sizeof(szValue);
  4043. g_lpLayout[g_iLayoutBuff].iSpecialID = 0;
  4044. bLoadedLayout = FALSE;
  4045. if (pfnSHLoadRegUIString &&
  4046. pfnSHLoadRegUIString(hkey1,
  4047. c_szDisplayLayoutText,
  4048. szValue,
  4049. ARRAYSIZE(szValue)) == S_OK)
  4050. {
  4051. g_lpLayout[g_iLayoutBuff].atmLayoutText = AddAtom(szValue);
  4052. bLoadedLayout = TRUE;
  4053. }
  4054. else
  4055. {
  4056. //
  4057. // Get the name of the layout.
  4058. //
  4059. szValue[0] = TEXT('\0');
  4060. cb = sizeof(szValue);
  4061. if (RegQueryValueEx( hkey1,
  4062. c_szLayoutText,
  4063. NULL,
  4064. NULL,
  4065. (LPBYTE)szValue,
  4066. &cb ) == ERROR_SUCCESS)
  4067. {
  4068. g_lpLayout[g_iLayoutBuff].atmLayoutText = AddAtom(szValue);
  4069. bLoadedLayout = TRUE;
  4070. }
  4071. }
  4072. if (bLoadedLayout)
  4073. {
  4074. //
  4075. // See if it's an IME or a special id.
  4076. //
  4077. szValue[0] = TEXT('\0');
  4078. cb = sizeof(szValue);
  4079. if ((HIWORD(g_lpLayout[g_iLayoutBuff].dwID) & 0xf000) == 0xe000)
  4080. {
  4081. //
  4082. // Get the name of the IME file.
  4083. //
  4084. if (RegQueryValueEx( hkey1,
  4085. c_szIMEFile,
  4086. NULL,
  4087. NULL,
  4088. (LPBYTE)szValue,
  4089. &cb ) == ERROR_SUCCESS)
  4090. {
  4091. g_lpLayout[g_iLayoutBuff].atmIMEFile = AddAtom(szValue);
  4092. szValue[0] = TEXT('\0');
  4093. cb = sizeof(szValue);
  4094. g_iLayoutBuff++;
  4095. g_iLayoutIME++; // increment number of IME layouts.
  4096. }
  4097. }
  4098. else
  4099. {
  4100. //
  4101. // See if this is a special id.
  4102. //
  4103. if (RegQueryValueEx( hkey1,
  4104. c_szLayoutID,
  4105. NULL,
  4106. NULL,
  4107. (LPBYTE)szValue,
  4108. &cb ) == ERROR_SUCCESS)
  4109. {
  4110. //
  4111. // This may not exist.
  4112. //
  4113. g_lpLayout[g_iLayoutBuff].iSpecialID =
  4114. (UINT)TransNum(szValue);
  4115. }
  4116. g_iLayoutBuff++;
  4117. }
  4118. }
  4119. }
  4120. RegCloseKey(hkey1);
  4121. }
  4122. dwIndex++;
  4123. szValue[0] = TEXT('\0');
  4124. dwRetVal = RegEnumKey( hKey,
  4125. dwIndex,
  4126. szValue,
  4127. sizeof(szValue) / sizeof(TCHAR) );
  4128. } while (dwRetVal == ERROR_SUCCESS);
  4129. cb = sizeof(DWORD);
  4130. g_dwAttributes = 0;
  4131. if (RegQueryValueEx( hKey,
  4132. c_szAttributes,
  4133. NULL,
  4134. NULL,
  4135. (LPBYTE)&g_dwAttributes,
  4136. &cb ) != ERROR_SUCCESS)
  4137. {
  4138. g_dwAttributes &= 0x00FF0000;
  4139. }
  4140. RegCloseKey(hKey);
  4141. if (g_hShlwapi)
  4142. {
  4143. FreeLibrary(g_hShlwapi);
  4144. g_hShlwapi = NULL;
  4145. pfnSHLoadRegUIString = NULL;
  4146. }
  4147. return (g_iLayoutBuff);
  4148. }
  4149. ////////////////////////////////////////////////////////////////////////////
  4150. //
  4151. // Locale_LoadLocales
  4152. //
  4153. // Loads the locales from the registry.
  4154. //
  4155. ////////////////////////////////////////////////////////////////////////////
  4156. BOOL Locale_LoadLocales(
  4157. HWND hwnd)
  4158. {
  4159. HKEY hKey;
  4160. DWORD cchValue, cbData;
  4161. DWORD dwIndex;
  4162. DWORD dwLocale, dwLayout;
  4163. DWORD dwLocale2, dwLayout2;
  4164. LONG dwRetVal;
  4165. UINT ctr1, ctr2 = 0;
  4166. TCHAR szValue[MAX_PATH]; // language id (number)
  4167. TCHAR szData[MAX_PATH]; // language name
  4168. HINF hIntlInf;
  4169. BOOL bRet;
  4170. if (!(g_hLang = LocalAlloc(LHND, ALLOCBLOCK * sizeof(INPUTLANG))))
  4171. {
  4172. Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
  4173. return (FALSE);
  4174. }
  4175. g_nLangBuffSize = ALLOCBLOCK;
  4176. g_iLangBuff = 0;
  4177. g_lpLang = LocalLock(g_hLang);
  4178. //
  4179. // Now read all of the locales from the registry.
  4180. //
  4181. if (RegOpenKey(HKEY_LOCAL_MACHINE, c_szLocaleInfo, &hKey) != ERROR_SUCCESS)
  4182. {
  4183. Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
  4184. return (FALSE);
  4185. }
  4186. dwIndex = 0;
  4187. cchValue = sizeof(szValue) / sizeof(TCHAR);
  4188. cbData = sizeof(szData);
  4189. dwRetVal = RegEnumValue( hKey,
  4190. dwIndex,
  4191. szValue,
  4192. &cchValue,
  4193. NULL,
  4194. NULL,
  4195. (LPBYTE)szData,
  4196. &cbData );
  4197. if (dwRetVal != ERROR_SUCCESS)
  4198. {
  4199. Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
  4200. RegCloseKey(hKey);
  4201. return (FALSE);
  4202. }
  4203. //
  4204. // Open the INF file.
  4205. //
  4206. bRet = Region_OpenIntlInfFile(&hIntlInf);
  4207. do
  4208. {
  4209. //
  4210. // Check for cchValue > 1 - an empty string will be enumerated,
  4211. // and will come back with cchValue == 1 for the null terminator.
  4212. // Also, check for cbData > 2 - an empty string will be 2, since
  4213. // this is the count of bytes.
  4214. //
  4215. if ((cchValue > 1) && (cchValue < HKL_LEN) && (cbData > 2))
  4216. {
  4217. //
  4218. // New language - get the language name and the language id.
  4219. //
  4220. if ((g_iLangBuff + 1) == g_nLangBuffSize)
  4221. {
  4222. HANDLE hTemp;
  4223. LocalUnlock(g_hLang);
  4224. g_nLangBuffSize += ALLOCBLOCK;
  4225. hTemp = LocalReAlloc( g_hLang,
  4226. g_nLangBuffSize * sizeof(INPUTLANG),
  4227. LHND );
  4228. if (hTemp == NULL)
  4229. {
  4230. break;
  4231. }
  4232. g_hLang = hTemp;
  4233. g_lpLang = LocalLock(g_hLang);
  4234. }
  4235. g_lpLang[g_iLangBuff].dwID = TransNum(szValue);
  4236. g_lpLang[g_iLangBuff].iUseCount = 0;
  4237. g_lpLang[g_iLangBuff].iNumCount = 0;
  4238. g_lpLang[g_iLangBuff].pNext = NULL;
  4239. //
  4240. // Get the default keyboard layout for the language.
  4241. //
  4242. if (bRet && Region_ReadDefaultLayoutFromInf( szValue,
  4243. &dwLocale,
  4244. &dwLayout,
  4245. &dwLocale2,
  4246. &dwLayout2,
  4247. hIntlInf ) == TRUE)
  4248. {
  4249. //
  4250. // The default layout is either the first layout in the inf file line
  4251. // or it's the first layout in the line that has the same language
  4252. // is the locale.
  4253. g_lpLang[g_iLangBuff].dwDefaultLayout = dwLayout2?dwLayout2:dwLayout;
  4254. }
  4255. //
  4256. // Get the full localized name of the language.
  4257. //
  4258. if (GetLanguageName(LOWORD(g_lpLang[g_iLangBuff].dwID), szData, ARRAYSIZE(szData)))
  4259. {
  4260. g_lpLang[g_iLangBuff].atmLanguageName = AddAtom(szData);
  4261. g_iLangBuff++;
  4262. }
  4263. }
  4264. dwIndex++;
  4265. cchValue = sizeof(szValue) / sizeof(TCHAR);
  4266. szValue[0] = TEXT('\0');
  4267. cbData = sizeof(szData);
  4268. szData[0] = TEXT('\0');
  4269. dwRetVal = RegEnumValue( hKey,
  4270. dwIndex,
  4271. szValue,
  4272. &cchValue,
  4273. NULL,
  4274. NULL,
  4275. (LPBYTE)szData,
  4276. &cbData );
  4277. } while (dwRetVal == ERROR_SUCCESS);
  4278. //
  4279. // If we succeeded in opening the INF file, close it.
  4280. //
  4281. if (bRet)
  4282. {
  4283. Region_CloseInfFile(&hIntlInf);
  4284. }
  4285. RegCloseKey(hKey);
  4286. return (TRUE);
  4287. }
  4288. ////////////////////////////////////////////////////////////////////////////
  4289. //
  4290. // Locale_LoadLocalesNT4
  4291. //
  4292. // Loads the locales from the registry.
  4293. //
  4294. ////////////////////////////////////////////////////////////////////////////
  4295. BOOL Locale_LoadLocalesNT4(
  4296. HWND hwnd)
  4297. {
  4298. HKEY hKey;
  4299. DWORD cch;
  4300. DWORD dwIndex;
  4301. LONG dwRetVal;
  4302. UINT i, j = 0;
  4303. TCHAR szValue[MAX_PATH]; // language id (number)
  4304. TCHAR szData[MAX_PATH]; // language name
  4305. if (!(g_hLang = LocalAlloc(LHND, ALLOCBLOCK * sizeof(INPUTLANG))))
  4306. {
  4307. Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
  4308. return (FALSE);
  4309. }
  4310. g_nLangBuffSize = ALLOCBLOCK;
  4311. g_iLangBuff = 0;
  4312. g_lpLang = LocalLock(g_hLang);
  4313. //
  4314. // Now read all of the locales from the registry.
  4315. //
  4316. if (RegOpenKey(HKEY_LOCAL_MACHINE, c_szLocaleInfoNT4, &hKey) != ERROR_SUCCESS)
  4317. {
  4318. Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
  4319. return (FALSE);
  4320. }
  4321. dwIndex = 0;
  4322. cch = sizeof(szValue) / sizeof(TCHAR);
  4323. dwRetVal = RegEnumValue( hKey,
  4324. dwIndex,
  4325. szValue,
  4326. &cch,
  4327. NULL,
  4328. NULL,
  4329. NULL,
  4330. NULL );
  4331. if (dwRetVal != ERROR_SUCCESS)
  4332. {
  4333. Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
  4334. RegCloseKey(hKey);
  4335. return (FALSE);
  4336. }
  4337. do
  4338. {
  4339. if ((cch > 1) && (cch < HKL_LEN))
  4340. {
  4341. //
  4342. // Check for cch > 1: an empty string will be enumerated,
  4343. // and will come back with cch == 1 for the null terminator.
  4344. //
  4345. // New language - get the language name, the language
  4346. // description, and the language id.
  4347. //
  4348. if ((g_iLangBuff + 1) == g_nLangBuffSize)
  4349. {
  4350. HANDLE hTemp;
  4351. LocalUnlock(g_hLang);
  4352. g_nLangBuffSize += ALLOCBLOCK;
  4353. hTemp = LocalReAlloc( g_hLang,
  4354. g_nLangBuffSize * sizeof(INPUTLANG),
  4355. LHND );
  4356. if (hTemp == NULL)
  4357. {
  4358. break;
  4359. }
  4360. g_hLang = hTemp;
  4361. g_lpLang = LocalLock(g_hLang);
  4362. }
  4363. g_lpLang[g_iLangBuff].dwID = TransNum(szValue);
  4364. g_lpLang[g_iLangBuff].iUseCount = 0;
  4365. g_lpLang[g_iLangBuff].iNumCount = 0;
  4366. g_lpLang[g_iLangBuff].pNext = NULL;
  4367. //
  4368. // Get the full localized name of the language.
  4369. //
  4370. if (GetLanguageName(LOWORD(g_lpLang[g_iLangBuff].dwID), szData, ARRAYSIZE(szData)))
  4371. {
  4372. g_lpLang[g_iLangBuff].atmLanguageName = AddAtom(szData);
  4373. g_iLangBuff++;
  4374. }
  4375. }
  4376. dwIndex++;
  4377. cch = sizeof(szValue) / sizeof(TCHAR);
  4378. szValue[0] = TEXT('\0');
  4379. dwRetVal = RegEnumValue( hKey,
  4380. dwIndex,
  4381. szValue,
  4382. &cch,
  4383. NULL,
  4384. NULL,
  4385. NULL,
  4386. NULL );
  4387. } while (dwRetVal == ERROR_SUCCESS);
  4388. RegCloseKey(hKey);
  4389. return (TRUE);
  4390. }
  4391. ////////////////////////////////////////////////////////////////////////////
  4392. //
  4393. // Locale_GetActiveLocales
  4394. //
  4395. // Gets the active locales.
  4396. //
  4397. ////////////////////////////////////////////////////////////////////////////
  4398. BOOL Locale_GetActiveLocales(
  4399. HWND hwnd)
  4400. {
  4401. HKL *pLangs;
  4402. UINT nLangs, ctr1, ctr2, ctr3, id;
  4403. HWND hwndList = GetDlgItem(hwnd, IDC_INPUT_LIST);
  4404. HKL hklSystem = 0;
  4405. int idxListBox;
  4406. BOOL bReturn = FALSE;
  4407. BOOL bTipSubhkl = FALSE;
  4408. DWORD langLay;
  4409. HANDLE hLangNode;
  4410. LPLANGNODE pLangNode;
  4411. HICON hIcon = NULL;
  4412. TCHAR szLangText[DESC_MAX];
  4413. TCHAR szLayoutName[DESC_MAX];
  4414. LPINPUTLANG pInpLang;
  4415. HTREEITEM hTVItem;
  4416. TV_ITEM tvItem;
  4417. //
  4418. // Initialize US layout option.
  4419. //
  4420. g_iUsLayout = -1;
  4421. //
  4422. // Get the active keyboard layout list from the system.
  4423. //
  4424. if (!SystemParametersInfo( SPI_GETDEFAULTINPUTLANG,
  4425. 0,
  4426. &hklSystem,
  4427. 0 ))
  4428. {
  4429. hklSystem = GetKeyboardLayout(0);
  4430. }
  4431. nLangs = GetKeyboardLayoutList(0, NULL);
  4432. if (nLangs == 0)
  4433. {
  4434. Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
  4435. return bReturn;
  4436. }
  4437. pLangs = (HKL *)LocalAlloc(LPTR, sizeof(DWORD_PTR) * nLangs);
  4438. if (pLangs == NULL)
  4439. {
  4440. Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
  4441. return bReturn;
  4442. }
  4443. GetKeyboardLayoutList(nLangs, (HKL *)pLangs);
  4444. //
  4445. // Find the position of the US layout to use as a default.
  4446. //
  4447. for (ctr1 = 0; ctr1 < g_iLayoutBuff; ctr1++)
  4448. {
  4449. if (g_lpLayout[ctr1].dwID == US_LOCALE)
  4450. {
  4451. g_iUsLayout = ctr1;
  4452. break;
  4453. }
  4454. }
  4455. if (ctr1 == g_iLayoutBuff)
  4456. {
  4457. Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
  4458. goto Error;
  4459. }
  4460. //
  4461. // Get the active keyboard information and put it in the internal
  4462. // language structure.
  4463. //
  4464. for (ctr2 = 0; ctr2 < nLangs; ctr2++)
  4465. {
  4466. //
  4467. // Filter out TIP substitute HKL from TreeView.
  4468. //
  4469. bTipSubhkl = IsTipSubstituteHKL(pLangs[ctr2]);
  4470. if (hklSystem != pLangs[ctr2] &&
  4471. IsUnregisteredFEDummyHKL(pLangs[ctr2]))
  4472. {
  4473. continue;
  4474. }
  4475. for (ctr1 = 0; ctr1 < g_iLangBuff; ctr1++)
  4476. {
  4477. //
  4478. // See if there's a match.
  4479. //
  4480. if (LOWORD(pLangs[ctr2]) == LOWORD(g_lpLang[ctr1].dwID))
  4481. {
  4482. LPTVITEMNODE pTVItemNode;
  4483. //
  4484. // Found a match.
  4485. // Create a node for this language.
  4486. //
  4487. pLangNode = Locale_AddToLinkedList(ctr1, pLangs[ctr2]);
  4488. if (!pLangNode)
  4489. {
  4490. Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED);
  4491. goto Error;
  4492. }
  4493. //
  4494. // Get language name to add it to treeview
  4495. //
  4496. pInpLang = &g_lpLang[pLangNode->iLang];
  4497. GetAtomName(pInpLang->atmLanguageName, szLangText, ARRAYSIZE(szLangText));
  4498. if ((HIWORD(pLangs[ctr2]) & 0xf000) == 0xe000)
  4499. {
  4500. pLangNode->wStatus |= LANG_IME;
  4501. }
  4502. pLangNode->wStatus |= (LANG_ORIGACTIVE | LANG_ACTIVE);
  4503. pLangNode->hkl = pLangs[ctr2];
  4504. pLangNode->hklUnload = pLangs[ctr2];
  4505. Locale_FetchIndicator(pLangNode);
  4506. //
  4507. // Match the language to the layout.
  4508. //
  4509. pLangNode->iLayout = 0;
  4510. langLay = (DWORD)HIWORD(pLangs[ctr2]);
  4511. if ((HIWORD(pLangs[ctr2]) == 0xffff) ||
  4512. (HIWORD(pLangs[ctr2]) == 0xfffe))
  4513. {
  4514. //
  4515. // Mark default or previous error as US - this
  4516. // means that the layout will be that of the basic
  4517. // keyboard driver (the US one).
  4518. //
  4519. pLangNode->wStatus |= LANG_CHANGED;
  4520. pLangNode->iLayout = g_iUsLayout;
  4521. langLay = 0;
  4522. }
  4523. else if ((HIWORD(pLangs[ctr2]) & 0xf000) == 0xf000)
  4524. {
  4525. //
  4526. // Layout is special, need to search for the ID
  4527. // number.
  4528. //
  4529. id = HIWORD(pLangs[ctr2]) & 0x0fff;
  4530. for (ctr3 = 0; ctr3 < g_iLayoutBuff; ctr3++)
  4531. {
  4532. if (id == g_lpLayout[ctr3].iSpecialID)
  4533. {
  4534. pLangNode->iLayout = ctr3;
  4535. langLay = 0;
  4536. break;
  4537. }
  4538. }
  4539. if (langLay)
  4540. {
  4541. //
  4542. // Didn't find the id, so reset to basic for
  4543. // the language.
  4544. //
  4545. langLay = (DWORD)LOWORD(pLangs[ctr2]);
  4546. }
  4547. }
  4548. if (langLay)
  4549. {
  4550. //
  4551. // Search for the id.
  4552. //
  4553. for (ctr3 = 0; ctr3 < g_iLayoutBuff; ctr3++)
  4554. {
  4555. if (((LOWORD(langLay) & 0xf000) == 0xe000) &&
  4556. (g_lpLayout[ctr3].dwID) == (DWORD)((DWORD_PTR)(pLangs[ctr2])))
  4557. {
  4558. pLangNode->iLayout = ctr3;
  4559. break;
  4560. }
  4561. else
  4562. {
  4563. if (langLay == (DWORD)LOWORD(g_lpLayout[ctr3].dwID))
  4564. {
  4565. pLangNode->iLayout = ctr3;
  4566. break;
  4567. }
  4568. }
  4569. }
  4570. if (ctr3 == g_iLayoutBuff)
  4571. {
  4572. //
  4573. // Something went wrong or didn't load from
  4574. // the registry correctly.
  4575. //
  4576. MessageBeep(MB_ICONEXCLAMATION);
  4577. pLangNode->wStatus |= LANG_CHANGED;
  4578. pLangNode->iLayout = g_iUsLayout;
  4579. }
  4580. }
  4581. //
  4582. // If this is the current language, then it's the default
  4583. // one.
  4584. //
  4585. if ((DWORD)((DWORD_PTR)pLangNode->hkl) == (DWORD)((DWORD_PTR)hklSystem))
  4586. {
  4587. TCHAR sz[DESC_MAX];
  4588. pInpLang = &g_lpLang[ctr1];
  4589. //
  4590. // Found the default. Set the Default input locale
  4591. // text in the property sheet.
  4592. //
  4593. if (pLangNode->wStatus & LANG_IME)
  4594. {
  4595. GetAtomName(g_lpLayout[pLangNode->iLayout].atmLayoutText,
  4596. sz,
  4597. ARRAYSIZE(sz));
  4598. }
  4599. else
  4600. {
  4601. GetAtomName(pInpLang->atmLanguageName, sz, ARRAYSIZE(sz));
  4602. }
  4603. pLangNode->wStatus |= LANG_DEFAULT;
  4604. }
  4605. // Get layout name and add it to treeview
  4606. GetAtomName(g_lpLayout[pLangNode->iLayout].atmLayoutText,
  4607. szLayoutName,
  4608. ARRAYSIZE(szLayoutName));
  4609. if (bTipSubhkl)
  4610. {
  4611. AddKbdLayoutOnKbdTip((HKL) ((DWORD_PTR)(pLangs[ctr2])), pLangNode->iLayout);
  4612. }
  4613. if (bTipSubhkl &&
  4614. (hTVItem = FindTVLangItem(pInpLang->dwID, NULL)))
  4615. {
  4616. TV_ITEM tvTipItem;
  4617. HTREEITEM hGroupItem;
  4618. HTREEITEM hTipItem;
  4619. LPTVITEMNODE pTVTipItemNode;
  4620. tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
  4621. tvItem.hItem = hTVItem;
  4622. //GetAtomName(pTVItemNode->atmDefTipName, szLayoutName, ARRAYSIZE(szLayoutName));
  4623. tvTipItem.mask = TVIF_HANDLE | TVIF_PARAM;
  4624. tvTipItem.hItem = hTVItem;
  4625. //
  4626. // Adding the default keyboard layout info into each TIPs.
  4627. //
  4628. for (hGroupItem = TreeView_GetChild(g_hwndTV, hTVItem);
  4629. hGroupItem != NULL;
  4630. hGroupItem = TreeView_GetNextSibling(g_hwndTV, hGroupItem))
  4631. {
  4632. for (hTipItem = TreeView_GetChild(g_hwndTV, hGroupItem);
  4633. hTipItem != NULL;
  4634. hTipItem = TreeView_GetNextSibling(g_hwndTV, hTipItem))
  4635. {
  4636. tvTipItem.hItem = hTipItem;
  4637. if (TreeView_GetItem(g_hwndTV, &tvTipItem) && tvTipItem.lParam)
  4638. {
  4639. pTVTipItemNode = (LPTVITEMNODE) tvTipItem.lParam;
  4640. if (pTVTipItemNode->hklSub == pLangNode->hkl)
  4641. {
  4642. pTVTipItemNode->lParam = (LPARAM) pLangNode;
  4643. }
  4644. }
  4645. }
  4646. }
  4647. if (pLangNode->wStatus & LANG_DEFAULT)
  4648. {
  4649. UINT ctr;
  4650. TCHAR szDefItem[MAX_PATH];
  4651. //
  4652. // Set the default locale selection.
  4653. //
  4654. HWND hwndDefList = GetDlgItem(g_hDlg, IDC_LOCALE_DEFAULT);
  4655. int idxSel = -1;
  4656. //
  4657. // Search substitute HKL of Tips.
  4658. //
  4659. for (ctr = 0; ctr < g_iTipsBuff; ctr++)
  4660. {
  4661. if (pLangs[ctr2] == g_lpTips[ctr].hklSub &&
  4662. g_lpTips[ctr].bDefault)
  4663. {
  4664. GetAtomName(g_lpTips[ctr].atmTipText,
  4665. szLayoutName,
  4666. ARRAYSIZE(szLayoutName));
  4667. break;
  4668. }
  4669. }
  4670. StringCchCopy(szDefItem, ARRAYSIZE(szDefItem), szLangText);
  4671. StringCchCat(szDefItem, ARRAYSIZE(szDefItem), TEXT(" - "));
  4672. StringCchCat(szDefItem, ARRAYSIZE(szDefItem), szLayoutName);
  4673. if ((idxSel = ComboBox_FindStringExact(hwndDefList, 0, szDefItem)) != CB_ERR)
  4674. ComboBox_SetCurSel(hwndDefList, idxSel);
  4675. Locale_CommandSetDefault(hwnd);
  4676. }
  4677. }
  4678. else
  4679. {
  4680. //
  4681. //
  4682. //
  4683. if (!(pTVItemNode = CreateTVItemNode(pInpLang->dwID)))
  4684. goto Error;
  4685. pTVItemNode->lParam = (LPARAM)pLangNode;
  4686. if (!pTVItemNode->atmDefTipName)
  4687. pTVItemNode->atmDefTipName = AddAtom(szLayoutName);
  4688. //
  4689. // Add language node into treeview
  4690. //
  4691. AddTreeViewItems(TV_ITEM_TYPE_LANG,
  4692. szLangText, NULL, NULL, &pTVItemNode);
  4693. if (!(pTVItemNode = CreateTVItemNode(pInpLang->dwID)))
  4694. goto Error;
  4695. pTVItemNode->lParam = (LPARAM)pLangNode;
  4696. //
  4697. // Add keyboard layout item into treeview
  4698. //
  4699. hTVItem = AddTreeViewItems(TV_ITEM_TYPE_KBD,
  4700. szLangText,
  4701. szInputTypeKbd,
  4702. szLayoutName,
  4703. &pTVItemNode);
  4704. }
  4705. //
  4706. // Check Thai layout.
  4707. //
  4708. if (g_dwPrimLangID == LANG_THAI && hTVItem)
  4709. {
  4710. if (PRIMARYLANGID(LOWORD(g_lpLayout[pLangNode->iLayout].dwID)) == LANG_THAI)
  4711. g_iThaiLayout++;
  4712. }
  4713. //
  4714. // Break out of inner loop - we've found it.
  4715. //
  4716. break;
  4717. }
  4718. }
  4719. }
  4720. bReturn = TRUE;
  4721. Error:
  4722. if (pLangs)
  4723. LocalFree((HANDLE)pLangs);
  4724. return (bReturn);
  4725. }
  4726. ////////////////////////////////////////////////////////////////////////////
  4727. //
  4728. // GetInstalledInput
  4729. //
  4730. ////////////////////////////////////////////////////////////////////////////
  4731. BOOL GetInstalledInput(HWND hwnd)
  4732. {
  4733. DWORD dwLayout = 0;
  4734. LANGID langID;
  4735. //
  4736. // Reset the installed input
  4737. //
  4738. g_iInputs = 0;
  4739. //
  4740. // Need to check language id for Thai, Chinese and Arabic.
  4741. //
  4742. g_dwPrimLangID = PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID()));
  4743. if (g_dwPrimLangID == LANG_ARABIC || g_dwPrimLangID == LANG_HEBREW)
  4744. {
  4745. g_bMESystem = TRUE;
  4746. }
  4747. #if 0
  4748. else if (g_dwPrimLangID == LANG_CHINESE)
  4749. {
  4750. g_bCHSystem = TRUE;
  4751. }
  4752. #endif
  4753. langID = GetUserDefaultUILanguage();
  4754. if (PRIMARYLANGID(langID) == LANG_ARABIC || PRIMARYLANGID(langID) == LANG_HEBREW)
  4755. {
  4756. g_bShowRtL = TRUE;
  4757. }
  4758. //
  4759. // Enum new tips(speech, pen and keyboard).
  4760. // If there are new tips in the system, read tip category enabling status
  4761. // and add them into tree view control.
  4762. //
  4763. EnumCiceroTips();
  4764. //
  4765. // Read all availabe keyboard layouts from system
  4766. //
  4767. if (g_OSNT4)
  4768. {
  4769. if (!Locale_LoadLocalesNT4(hwnd))
  4770. return FALSE;
  4771. }
  4772. else
  4773. {
  4774. if (!Locale_LoadLocales(hwnd))
  4775. return FALSE;
  4776. }
  4777. if ((!Locale_LoadLayouts(hwnd)) ||
  4778. (!Locale_GetActiveLocales(hwnd)))
  4779. return FALSE;
  4780. //
  4781. // Only 1 TIP, so disable the secondary controls.
  4782. //
  4783. Locale_SetSecondaryControls(hwnd);
  4784. //
  4785. // Save the originial input layouts
  4786. //
  4787. g_iOrgInputs = g_iInputs;
  4788. return TRUE;
  4789. }
  4790. ////////////////////////////////////////////////////////////////////////////
  4791. //
  4792. // InitPropSheet
  4793. //
  4794. // Processing for a WM_INITDIALOG message for the Input Locales
  4795. // property sheet.
  4796. //
  4797. ////////////////////////////////////////////////////////////////////////////
  4798. void InitPropSheet(
  4799. HWND hwnd,
  4800. LPPROPSHEETPAGE psp)
  4801. {
  4802. HKEY hKey;
  4803. HANDLE hlib;
  4804. HWND hwndList;
  4805. LPLANGNODE pLangNode;
  4806. LANGID LangID;
  4807. UINT iNumLangs, ctr;
  4808. TCHAR szItem[DESC_MAX];
  4809. BOOL bImeSetting = FALSE;
  4810. //
  4811. // See if there are any other instances of this property page.
  4812. // If so, disable this page.
  4813. //
  4814. if (g_hMutex && (WaitForSingleObject(g_hMutex, 0) != WAIT_OBJECT_0))
  4815. {
  4816. // Need to disable controls ...
  4817. Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED_2);
  4818. return;
  4819. }
  4820. //
  4821. // See if we're in setup mode.
  4822. //
  4823. if (IsSetupMode())
  4824. {
  4825. //
  4826. // Set the setup special case flag.
  4827. //
  4828. g_bSetupCase = TRUE;
  4829. }
  4830. //
  4831. // Make sure the event is clear.
  4832. //
  4833. if (g_hEvent)
  4834. {
  4835. SetEvent(g_hEvent);
  4836. }
  4837. g_OSNT4 = IsOSPlatform(OS_NT4);
  4838. g_OSNT5 = IsOSPlatform(OS_NT5);
  4839. #ifndef _WIN64
  4840. g_OSWIN95 = IsOSPlatform(OS_WIN95);
  4841. #endif // _WIN64
  4842. //
  4843. // Check the Administrative privileges by the token group SID.
  4844. //
  4845. if (IsAdminPrivilegeUser())
  4846. {
  4847. g_bAdmin_Privileges = TRUE;
  4848. }
  4849. else
  4850. {
  4851. //
  4852. // The user does not have admin privileges.
  4853. //
  4854. g_bAdmin_Privileges = FALSE;
  4855. }
  4856. //
  4857. // Load the strings
  4858. //
  4859. LoadString(hInstance, IDS_LOCALE_DEFAULT, szDefault, ARRAYSIZE(szDefault));
  4860. LoadString(hInstance, IDS_INPUT_KEYBOARD, szInputTypeKbd, ARRAYSIZE(szInputTypeKbd));
  4861. LoadString(hInstance, IDS_INPUT_PEN, szInputTypePen, ARRAYSIZE(szInputTypePen));
  4862. LoadString(hInstance, IDS_INPUT_SPEECH, szInputTypeSpeech, ARRAYSIZE(szInputTypeSpeech));
  4863. LoadString(hInstance, IDS_INPUT_EXTERNAL, szInputTypeExternal, ARRAYSIZE(szInputTypeExternal));
  4864. }
  4865. ////////////////////////////////////////////////////////////////////////////
  4866. //
  4867. // Locale_CommandAdd
  4868. //
  4869. // Invokes the Add dialog.
  4870. //
  4871. // Returns 1 if a dialog box was invoked and the dialog returned IDOK.
  4872. // Otherwise, it returns 0.
  4873. //
  4874. ////////////////////////////////////////////////////////////////////////////
  4875. int Locale_CommandAdd(
  4876. HWND hwnd)
  4877. {
  4878. HWND hwndList;
  4879. HWND hwndTV;
  4880. int idxList;
  4881. UINT nList;
  4882. int rc = 0;
  4883. INITINFO InitInfo;
  4884. LPCTSTR lpTemplateName;
  4885. HINSTANCE hInstRes;
  4886. HTREEITEM hTVItem;
  4887. hwndTV = GetDlgItem(hwnd, IDC_INPUT_LIST);
  4888. hTVItem = TreeView_GetSelection(hwndTV);
  4889. if (!hTVItem)
  4890. return 0;
  4891. InitInfo.hwndMain = hwnd;
  4892. InitInfo.pLangNode = NULL;
  4893. if (g_bExtraTip)
  4894. {
  4895. hInstRes = GetCicResInstance(hInstance, DLG_KEYBOARD_LOCALE_ADD_EXTRA);
  4896. lpTemplateName = MAKEINTRESOURCE(DLG_KEYBOARD_LOCALE_ADD_EXTRA);
  4897. }
  4898. else if (g_bPenOrSapiTip)
  4899. {
  4900. hInstRes = GetCicResInstance(hInstance, DLG_KEYBOARD_LOCALE_ADD);
  4901. lpTemplateName = MAKEINTRESOURCE(DLG_KEYBOARD_LOCALE_ADD);
  4902. }
  4903. else
  4904. {
  4905. hInstRes = GetCicResInstance(hInstance, DLG_KEYBOARD_LOCALE_SIMPLE_ADD);
  4906. lpTemplateName = MAKEINTRESOURCE(DLG_KEYBOARD_LOCALE_SIMPLE_ADD);
  4907. }
  4908. //
  4909. // Bring up the appropriate dialog box. And check return value for added
  4910. // items.
  4911. //
  4912. if ((rc = (int)DialogBoxParam(hInstRes,
  4913. lpTemplateName,
  4914. hwnd,
  4915. KbdLocaleAddDlg,
  4916. (LPARAM)(&InitInfo) )) == IDOK)
  4917. {
  4918. //
  4919. // Turn on ApplyNow button.
  4920. //
  4921. PropSheet_Changed(GetParent(hwnd), hwnd);
  4922. }
  4923. else
  4924. {
  4925. //
  4926. // Failure, so need to return 0.
  4927. //
  4928. TreeView_SelectItem(hwndTV, hTVItem);
  4929. rc = 0;
  4930. }
  4931. return (rc);
  4932. }
  4933. ////////////////////////////////////////////////////////////////////////////
  4934. //
  4935. // Locale_CommandEdit
  4936. //
  4937. // Invokes the Properties dialog.
  4938. //
  4939. // Returns 1 if a dialog box was invoked and the dialog returned IDOK.
  4940. // Otherwise, it returns 0.
  4941. //
  4942. ////////////////////////////////////////////////////////////////////////////
  4943. void Locale_CommandEdit(
  4944. HWND hwnd,
  4945. LPLANGNODE pLangNode)
  4946. {
  4947. HWND hwndList;
  4948. HWND hwndTV;
  4949. int idxList;
  4950. UINT nList;
  4951. int rc = 0;
  4952. INITINFO InitInfo;
  4953. HTREEITEM hTVItem;
  4954. TV_ITEM tvItem;
  4955. LPTVITEMNODE pTVItemNode;
  4956. hTVItem = TreeView_GetSelection(g_hwndTV);
  4957. if (!hTVItem)
  4958. return;
  4959. tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
  4960. tvItem.hItem = hTVItem;
  4961. if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam)
  4962. {
  4963. pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
  4964. if (pTVItemNode->uInputType & INPUT_TYPE_TIP)
  4965. {
  4966. HRESULT hr;
  4967. ITfFnConfigure *pConfig = NULL;
  4968. //
  4969. // Load LangBar manager to bring the property window
  4970. //
  4971. hr = CoCreateInstance(&pTVItemNode->clsid,
  4972. NULL,
  4973. CLSCTX_INPROC_SERVER,
  4974. &IID_ITfFnConfigure,
  4975. (LPVOID *) &pConfig);
  4976. //
  4977. // Call property dialog from TIP.
  4978. //
  4979. if (SUCCEEDED(hr))
  4980. pConfig->lpVtbl->Show(pConfig,
  4981. hwnd,
  4982. (LANGID)pTVItemNode->dwLangID,
  4983. &pTVItemNode->guidProfile);
  4984. if (pConfig)
  4985. pConfig->lpVtbl->Release(pConfig);
  4986. }
  4987. else
  4988. {
  4989. if ((pLangNode = (LPLANGNODE)pTVItemNode->lParam) && (pLangNode->wStatus & LANG_IME))
  4990. ImmConfigureIME(pLangNode->hkl, hwnd, IME_CONFIG_GENERAL, NULL);
  4991. }
  4992. }
  4993. }
  4994. ////////////////////////////////////////////////////////////////////////////
  4995. //
  4996. // RemoveTVSubItems
  4997. //
  4998. ////////////////////////////////////////////////////////////////////////////
  4999. BOOL RemoveTVSubItems(
  5000. HWND hwnd,
  5001. HTREEITEM hTVItem,
  5002. LPTVITEMNODE pTVItemNode)
  5003. {
  5004. TV_ITEM tvItem;
  5005. BOOL bRemoveAll = TRUE;
  5006. HTREEITEM hGroupItem, hItem;
  5007. HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST);
  5008. //
  5009. // Delete all TreeView node.
  5010. //
  5011. tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
  5012. if (pTVItemNode->uInputType & TV_ITEM_TYPE_LANG)
  5013. {
  5014. hGroupItem = TreeView_GetChild(hwndTV, hTVItem);
  5015. }
  5016. else
  5017. {
  5018. hGroupItem = hTVItem;
  5019. bRemoveAll = FALSE;
  5020. }
  5021. while (hGroupItem != NULL)
  5022. {
  5023. BOOL bNextGroup = FALSE;
  5024. LPTVITEMNODE pTVTempNode = NULL;
  5025. HTREEITEM hDeletedItem = NULL;
  5026. for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
  5027. hItem != NULL;
  5028. hItem = TreeView_GetNextSibling(hwndTV, hItem))
  5029. {
  5030. if (hDeletedItem)
  5031. {
  5032. TreeView_DeleteItem(hwndTV, hDeletedItem);
  5033. hDeletedItem = NULL;
  5034. }
  5035. tvItem.hItem = hItem;
  5036. if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
  5037. {
  5038. LPLANGNODE pLangNode = NULL;
  5039. if (pTVTempNode = (LPTVITEMNODE) tvItem.lParam)
  5040. pLangNode = (LPLANGNODE)pTVTempNode->lParam;
  5041. else
  5042. continue;
  5043. if (pTVTempNode->uInputType & INPUT_TYPE_TIP)
  5044. {
  5045. g_lpTips[pTVTempNode->iIdxTips].bEnabled = FALSE;
  5046. g_iEnabledTips--;
  5047. if (pTVTempNode->uInputType & INPUT_TYPE_KBD)
  5048. g_iEnabledKbdTips--;
  5049. g_dwChanges |= CHANGE_TIPCHANGE;
  5050. if ((pTVTempNode->uInputType & INPUT_TYPE_KBD) && pTVTempNode->hklSub)
  5051. {
  5052. UINT ctr;
  5053. UINT uNumSubhkl = 0;
  5054. for (ctr = 0; ctr < g_iTipsBuff; ctr++)
  5055. {
  5056. if (pTVTempNode->hklSub == g_lpTips[ctr].hklSub &&
  5057. g_lpTips[ctr].bEnabled)
  5058. {
  5059. uNumSubhkl++;
  5060. }
  5061. }
  5062. if (!uNumSubhkl)
  5063. {
  5064. pLangNode = (LPLANGNODE)pTVTempNode->lParam;
  5065. }
  5066. else
  5067. {
  5068. //
  5069. // Someone still use this substitute HKL.
  5070. //
  5071. pLangNode = NULL;
  5072. }
  5073. }
  5074. }
  5075. if ((pTVTempNode->uInputType & TV_ITEM_TYPE_KBD) && pLangNode)
  5076. {
  5077. if (!(pTVTempNode->uInputType & INPUT_TYPE_TIP))
  5078. pLangNode = (LPLANGNODE)pTVTempNode->lParam;
  5079. if (!pLangNode)
  5080. return FALSE;
  5081. //
  5082. // Check Thai layout.
  5083. //
  5084. if (g_dwPrimLangID == LANG_THAI)
  5085. {
  5086. if (PRIMARYLANGID(LOWORD(g_lpLayout[pLangNode->iLayout].dwID)) == LANG_THAI)
  5087. g_iThaiLayout--;
  5088. }
  5089. pLangNode->wStatus &= ~(LANG_ACTIVE|LANG_DEFAULT);
  5090. pLangNode->wStatus |= LANG_CHANGED;
  5091. g_lpLang[pLangNode->iLang].iNumCount--;
  5092. if (!(pLangNode->wStatus & LANG_ORIGACTIVE))
  5093. {
  5094. Locale_RemoveFromLinkedList(pLangNode);
  5095. }
  5096. }
  5097. RemoveTVItemNode(pTVTempNode);
  5098. hDeletedItem = hItem;
  5099. g_iInputs--;
  5100. }
  5101. }
  5102. tvItem.hItem = hGroupItem;
  5103. if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
  5104. {
  5105. pTVTempNode = (LPTVITEMNODE)tvItem.lParam;
  5106. if (!pTVTempNode)
  5107. continue;
  5108. if (pTVTempNode->uInputType & INPUT_TYPE_SPEECH ||
  5109. pTVTempNode->uInputType & INPUT_TYPE_SMARTTAG)
  5110. {
  5111. g_lpTips[pTVTempNode->iIdxTips].bEnabled = FALSE;
  5112. g_iEnabledTips--;
  5113. g_dwChanges |= CHANGE_TIPCHANGE;
  5114. if (pTVTempNode->uInputType & INPUT_TYPE_SPEECH)
  5115. MarkSptipRemoved(TRUE);
  5116. }
  5117. if (pTVTempNode->uInputType & ~TV_ITEM_TYPE_LANG)
  5118. {
  5119. hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem);
  5120. bNextGroup = TRUE;
  5121. TreeView_DeleteItem(hwndTV, tvItem.hItem );
  5122. }
  5123. RemoveTVItemNode(pTVTempNode);
  5124. if (pTVTempNode == pTVItemNode)
  5125. pTVItemNode = NULL;
  5126. }
  5127. if (!bNextGroup)
  5128. hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem);
  5129. if (!bRemoveAll)
  5130. hGroupItem = NULL;
  5131. }
  5132. if (pTVItemNode && (pTVItemNode->uInputType & TV_ITEM_TYPE_LANG))
  5133. {
  5134. int idxSel = -1;
  5135. TCHAR szItemName[DESC_MAX];
  5136. HWND hwndDefList = GetDlgItem(hwnd, IDC_LOCALE_DEFAULT);
  5137. GetAtomName(pTVItemNode->atmTVItemName, szItemName, ARRAYSIZE(szItemName));
  5138. idxSel = ComboBox_FindString(hwndDefList, 0, szItemName);
  5139. for (; idxSel != CB_ERR; )
  5140. {
  5141. ComboBox_DeleteString(hwndDefList, idxSel);
  5142. idxSel = ComboBox_FindString(hwndDefList, 0, szItemName);
  5143. }
  5144. if (pTVItemNode->bDefLang)
  5145. {
  5146. ComboBox_SetCurSel(hwndDefList, 0);
  5147. Locale_CommandSetDefault(hwnd);
  5148. }
  5149. RemoveTVItemNode(pTVItemNode);
  5150. TreeView_DeleteItem(hwndTV, hTVItem );
  5151. }
  5152. return TRUE;
  5153. }
  5154. ////////////////////////////////////////////////////////////////////////////
  5155. //
  5156. // GetNewRemoveItem
  5157. //
  5158. // Removes the currently selected input locale from the list.
  5159. //
  5160. ////////////////////////////////////////////////////////////////////////////
  5161. HTREEITEM GetNewRemoveItem(
  5162. HWND hwnd,
  5163. HTREEITEM hTVItem,
  5164. BOOL *bDelSameSubhkl,
  5165. LPTSTR lpDelItems,
  5166. UINT cchDelItems)
  5167. {
  5168. TV_ITEM tvItem;
  5169. LPTVITEMNODE pTVItemNode;
  5170. HTREEITEM hTVNewItem = hTVItem;
  5171. HTREEITEM hTVLangItem = NULL;
  5172. HWND hwndTV = GetDlgItem(hwnd, IDC_INPUT_LIST);
  5173. tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
  5174. tvItem.hItem = hTVItem;
  5175. if (TreeView_GetItem(hwndTV, &tvItem))
  5176. {
  5177. //
  5178. // Get the pointer to the lang node from the list box
  5179. // item data.
  5180. //
  5181. pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
  5182. if (!pTVItemNode)
  5183. goto Error;
  5184. if (pTVItemNode->uInputType & TV_ITEM_TYPE_LANG)
  5185. return hTVItem;
  5186. if (pTVItemNode->uInputType & TV_ITEM_TYPE_GROUP)
  5187. {
  5188. if (!TreeView_GetNextSibling(hwndTV, hTVItem) &&
  5189. !TreeView_GetPrevSibling(hwndTV, hTVItem))
  5190. {
  5191. if ((hTVLangItem = TreeView_GetParent(hwndTV, hTVItem)) &&
  5192. (TreeView_GetNextSibling(hwndTV, hTVLangItem) ||
  5193. TreeView_GetPrevSibling(hwndTV, hTVLangItem)))
  5194. {
  5195. hTVNewItem = TreeView_GetParent(hwndTV, hTVItem);
  5196. }
  5197. }
  5198. }
  5199. else
  5200. {
  5201. if (!TreeView_GetNextSibling(hwndTV, hTVItem) &&
  5202. !TreeView_GetPrevSibling(hwndTV, hTVItem))
  5203. {
  5204. if (hTVNewItem = TreeView_GetParent(hwndTV, hTVItem))
  5205. {
  5206. if (!TreeView_GetNextSibling(hwndTV, hTVNewItem) &&
  5207. !TreeView_GetPrevSibling(hwndTV, hTVNewItem))
  5208. {
  5209. if ((hTVLangItem = TreeView_GetParent(hwndTV, hTVNewItem)) &&
  5210. (TreeView_GetNextSibling(hwndTV, hTVLangItem) ||
  5211. TreeView_GetPrevSibling(hwndTV, hTVLangItem)))
  5212. {
  5213. hTVNewItem = TreeView_GetParent(hwndTV, hTVNewItem);
  5214. }
  5215. }
  5216. }
  5217. }
  5218. else
  5219. {
  5220. if(pTVItemNode->hklSub)
  5221. {
  5222. HTREEITEM hItem;
  5223. HTREEITEM hTVKbdGrpItem;
  5224. LPTVITEMNODE pTVTempItem;
  5225. UINT uSubhklItems = 0;
  5226. BOOL bFoundOther = FALSE;
  5227. if (hTVKbdGrpItem = TreeView_GetParent(hwndTV, hTVItem))
  5228. {
  5229. for (hItem = TreeView_GetChild(hwndTV, hTVKbdGrpItem);
  5230. hItem != NULL;
  5231. hItem = TreeView_GetNextSibling(hwndTV, hItem))
  5232. {
  5233. tvItem.hItem = hItem;
  5234. if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
  5235. {
  5236. pTVTempItem = (LPTVITEMNODE) tvItem.lParam;
  5237. }
  5238. else
  5239. {
  5240. goto Error;
  5241. }
  5242. if (pTVItemNode->hklSub != pTVTempItem->hklSub)
  5243. {
  5244. bFoundOther = TRUE;
  5245. }
  5246. else
  5247. {
  5248. TCHAR szItemName[MAX_PATH];
  5249. GetAtomName(pTVTempItem->atmTVItemName,
  5250. szItemName,
  5251. ARRAYSIZE(szItemName));
  5252. if (lstrlen(lpDelItems) < MAX_PATH / 2)
  5253. {
  5254. StringCchCat(lpDelItems, cchDelItems, TEXT("\r\n\t"));
  5255. StringCchCat(lpDelItems, cchDelItems, szItemName);
  5256. }
  5257. else
  5258. {
  5259. StringCchCat(lpDelItems, cchDelItems, TEXT("..."));
  5260. }
  5261. uSubhklItems++;
  5262. }
  5263. }
  5264. if (uSubhklItems >= 2)
  5265. *bDelSameSubhkl = TRUE;
  5266. if (!bFoundOther)
  5267. {
  5268. if (!TreeView_GetNextSibling(hwndTV, hTVKbdGrpItem) &&
  5269. !TreeView_GetPrevSibling(hwndTV, hTVKbdGrpItem))
  5270. {
  5271. if ((hTVLangItem = TreeView_GetParent(hwndTV, hTVKbdGrpItem)) &&
  5272. (TreeView_GetNextSibling(hwndTV, hTVLangItem) ||
  5273. TreeView_GetPrevSibling(hwndTV, hTVLangItem)))
  5274. {
  5275. hTVNewItem = TreeView_GetParent(hwndTV, hTVKbdGrpItem);
  5276. }
  5277. }
  5278. }
  5279. }
  5280. }
  5281. }
  5282. }
  5283. }
  5284. Error:
  5285. return hTVNewItem;
  5286. }
  5287. ////////////////////////////////////////////////////////////////////////////
  5288. //
  5289. // Locale_CommandDelete
  5290. //
  5291. // Removes the currently selected input locale from the list.
  5292. //
  5293. ////////////////////////////////////////////////////////////////////////////
  5294. void Locale_CommandDelete(
  5295. HWND hwnd)
  5296. {
  5297. TV_ITEM tvItem;
  5298. HTREEITEM hTVItem;
  5299. LPTVITEMNODE pTVItemNode;
  5300. TCHAR szDelItems[MAX_PATH];
  5301. LPLANGNODE pLangNode = NULL;
  5302. BOOL bDelSameSubhkl = FALSE;
  5303. BOOL bRemovedDefLayout = FALSE;
  5304. DWORD dwNextLangId;
  5305. HWND hwndTV = GetDlgItem(hwnd, IDC_INPUT_LIST);
  5306. //
  5307. // Get the current selection in the input locale list.
  5308. //
  5309. hTVItem = TreeView_GetSelection(hwndTV);
  5310. if (!hTVItem)
  5311. return;
  5312. szDelItems[0] = TEXT('\0');
  5313. hTVItem = GetNewRemoveItem(hwnd, hTVItem, &bDelSameSubhkl, szDelItems, ARRAYSIZE(szDelItems));
  5314. if (bDelSameSubhkl)
  5315. {
  5316. TCHAR szTitle[MAX_PATH];
  5317. TCHAR szMsg[MAX_PATH];
  5318. TCHAR szMsg2[MAX_PATH*2];
  5319. CicLoadString(hInstance, IDS_DELETE_CONFIRMTITLE, szTitle, ARRAYSIZE(szTitle));
  5320. CicLoadString(hInstance, IDS_DELETE_TIP, szMsg, ARRAYSIZE(szMsg));
  5321. StringCchPrintf(szMsg2, ARRAYSIZE(szMsg2), szMsg, szDelItems);
  5322. if (MessageBox(hwnd, szMsg2, szTitle, MB_YESNO|MB_ICONQUESTION ) == IDNO)
  5323. {
  5324. return;
  5325. }
  5326. }
  5327. tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
  5328. tvItem.hItem = hTVItem;
  5329. if (TreeView_GetItem(hwndTV, &tvItem))
  5330. {
  5331. //
  5332. // Get the pointer to the lang node from the list box
  5333. // item data.
  5334. //
  5335. pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
  5336. if (!pTVItemNode)
  5337. return;
  5338. if ((pTVItemNode->uInputType & TV_ITEM_TYPE_LANG) ||
  5339. (pTVItemNode->uInputType & TV_ITEM_TYPE_GROUP))
  5340. {
  5341. if (RemoveTVSubItems(hwnd, hTVItem, pTVItemNode))
  5342. goto ItemChanged;
  5343. return;
  5344. }
  5345. if (pTVItemNode->uInputType & INPUT_TYPE_KBD)
  5346. {
  5347. pLangNode = (LPLANGNODE)pTVItemNode->lParam;
  5348. }
  5349. }
  5350. else
  5351. {
  5352. //
  5353. // Make sure we're not removing the only entry in the list.
  5354. //
  5355. MessageBeep(MB_ICONEXCLAMATION);
  5356. return;
  5357. }
  5358. if (pTVItemNode->uInputType & INPUT_TYPE_TIP)
  5359. {
  5360. g_lpTips[pTVItemNode->iIdxTips].bEnabled = FALSE;
  5361. g_iEnabledTips--;
  5362. if (pTVItemNode->uInputType & INPUT_TYPE_KBD)
  5363. g_iEnabledKbdTips--;
  5364. if (pTVItemNode->uInputType & INPUT_TYPE_SPEECH)
  5365. {
  5366. // mark SPTIP's hack entry
  5367. MarkSptipRemoved(TRUE);
  5368. }
  5369. g_dwChanges |= CHANGE_TIPCHANGE;
  5370. if ((pTVItemNode->uInputType & INPUT_TYPE_KBD) && pTVItemNode->hklSub)
  5371. {
  5372. UINT ctr;
  5373. for (ctr = 0; ctr < g_iTipsBuff; ctr++)
  5374. {
  5375. if (pTVItemNode->hklSub == g_lpTips[ctr].hklSub &&
  5376. g_lpTips[ctr].bEnabled)
  5377. {
  5378. HTREEITEM hDelItem;
  5379. TCHAR szTipText[MAX_PATH];
  5380. g_iEnabledTips--;
  5381. g_iEnabledKbdTips--;
  5382. g_lpTips[ctr].bEnabled = FALSE;
  5383. GetAtomName(g_lpTips[ctr].atmTipText,
  5384. szTipText,
  5385. ARRAYSIZE(szTipText));
  5386. //
  5387. // Find the installed same keyboard TIP layout to delete it
  5388. // together.
  5389. //
  5390. if (hDelItem = FindTVItem(g_lpTips[ctr].dwLangID,
  5391. szTipText))
  5392. {
  5393. tvItem.hItem = hDelItem;
  5394. if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam)
  5395. {
  5396. RemoveTVItemNode((LPTVITEMNODE)tvItem.lParam);
  5397. TreeView_DeleteItem(g_hwndTV, tvItem.hItem );
  5398. }
  5399. g_iInputs--;
  5400. }
  5401. }
  5402. }
  5403. }
  5404. }
  5405. if (pTVItemNode->uInputType & INPUT_TYPE_KBD && pLangNode)
  5406. {
  5407. //
  5408. // Check Thai layout.
  5409. //
  5410. if (g_dwPrimLangID == LANG_THAI)
  5411. {
  5412. if (PRIMARYLANGID(LOWORD(g_lpLayout[pLangNode->iLayout].dwID)) == LANG_THAI)
  5413. g_iThaiLayout--;
  5414. }
  5415. if (pLangNode->wStatus & LANG_DEFAULT)
  5416. {
  5417. bRemovedDefLayout = TRUE;
  5418. dwNextLangId = pTVItemNode->dwLangID;
  5419. }
  5420. //
  5421. // Set the input locale to be not active and show that its state
  5422. // has changed. Also, delete the string from the input locale list
  5423. // in the property sheet.
  5424. //
  5425. // Decrement the number of nodes for this input locale.
  5426. //
  5427. pLangNode->wStatus &= ~(LANG_ACTIVE|LANG_DEFAULT);
  5428. pLangNode->wStatus |= LANG_CHANGED;
  5429. g_lpLang[pLangNode->iLang].iNumCount--;
  5430. //
  5431. // If it wasn't originally active, then remove it from the list.
  5432. // There's nothing more to do with this node.
  5433. //
  5434. if (!(pLangNode->wStatus & LANG_ORIGACTIVE))
  5435. {
  5436. Locale_RemoveFromLinkedList(pLangNode);
  5437. }
  5438. }
  5439. g_iInputs--;
  5440. RemoveTVItemNode(pTVItemNode);
  5441. TreeView_DeleteItem(hwndTV, hTVItem);
  5442. //
  5443. // Set the next available default layout
  5444. //
  5445. if (bRemovedDefLayout)
  5446. {
  5447. int idxSel = -1;
  5448. TCHAR szNextDefTip[MAX_PATH];
  5449. TCHAR szDefLayout[MAX_PATH * 2];
  5450. LPTVITEMNODE pTVLangItemNode = NULL;
  5451. HWND hwndDefList = GetDlgItem(hwnd, IDC_LOCALE_DEFAULT);
  5452. SetNextDefaultLayout(dwNextLangId,
  5453. TRUE,
  5454. szNextDefTip,
  5455. ARRAYSIZE(szNextDefTip));
  5456. if (tvItem.hItem = FindTVLangItem(dwNextLangId, NULL))
  5457. {
  5458. tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
  5459. if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam)
  5460. {
  5461. pTVLangItemNode = (LPTVITEMNODE) tvItem.lParam;
  5462. if (pTVLangItemNode->atmDefTipName)
  5463. DeleteAtom(pTVLangItemNode->atmDefTipName);
  5464. pTVLangItemNode->atmDefTipName = AddAtom(szNextDefTip);
  5465. GetAtomName(pTVLangItemNode->atmTVItemName,
  5466. szDefLayout,
  5467. MAX_PATH);
  5468. StringCchCat(szDefLayout, ARRAYSIZE(szDefLayout), TEXT(" - "));
  5469. StringCchCat(szDefLayout, ARRAYSIZE(szDefLayout), szNextDefTip);
  5470. }
  5471. }
  5472. idxSel = ComboBox_FindString(hwndDefList, 0, szDefLayout);
  5473. if (idxSel == CB_ERR)
  5474. idxSel = 0;
  5475. ComboBox_SetCurSel(hwndDefList, idxSel);
  5476. }
  5477. //
  5478. // Find keyboard group dangling node that doesn't has child keyboard
  5479. // layout item.
  5480. //
  5481. hTVItem = TreeView_GetSelection(hwndTV);
  5482. if (!hTVItem)
  5483. return;
  5484. tvItem.hItem = hTVItem;
  5485. tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
  5486. if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam)
  5487. {
  5488. if ((pTVItemNode = (LPTVITEMNODE) tvItem.lParam))
  5489. {
  5490. if ((pTVItemNode->uInputType & INPUT_TYPE_KBD) &&
  5491. (pTVItemNode->uInputType & TV_ITEM_TYPE_GROUP))
  5492. {
  5493. if (TreeView_GetChild(hwndTV, hTVItem) == NULL)
  5494. {
  5495. //
  5496. // Delete keyboard group dangling node
  5497. //
  5498. RemoveTVItemNode(pTVItemNode);
  5499. TreeView_DeleteItem(hwndTV, hTVItem);
  5500. }
  5501. }
  5502. }
  5503. }
  5504. ItemChanged:
  5505. //
  5506. // Only 1 active tip, so disable the secondary controls.
  5507. //
  5508. Locale_SetSecondaryControls(hwnd);
  5509. //
  5510. // Update the default locale switch hotkey.
  5511. //
  5512. Locale_SetDefaultHotKey(hwnd, FALSE);
  5513. //
  5514. // Move the focus to the Add button if the Remove button
  5515. // is now disabled (so that we don't lose input focus)
  5516. //
  5517. if (!IsWindowEnabled(GetDlgItem(hwnd, IDC_KBDL_DELETE)))
  5518. {
  5519. SetFocus(GetDlgItem(hwnd, IDC_KBDL_ADD));
  5520. }
  5521. //
  5522. // Enable the Apply button.
  5523. //
  5524. PropSheet_Changed(GetParent(hwnd), hwnd);
  5525. }
  5526. ////////////////////////////////////////////////////////////////////////////
  5527. //
  5528. // Locale_CommandHotKeySetting
  5529. //
  5530. // Invokes the Change HotKey dialog.
  5531. //
  5532. // Returns 1 if a dialog box was invoked and the dialog returned IDOK.
  5533. // Otherwise, it returns 0.
  5534. //
  5535. ////////////////////////////////////////////////////////////////////////////
  5536. BOOL Locale_CommandHotKeySetting(
  5537. HWND hwnd)
  5538. {
  5539. int rc = 0;
  5540. INITINFO InitInfo;
  5541. InitInfo.hwndMain = hwnd;
  5542. if (g_OSNT5)
  5543. {
  5544. rc = (int)DialogBoxParam(GetCicResInstance(hInstance, DLG_KEYBOARD_LOCALE_HOTKEY),
  5545. MAKEINTRESOURCE(DLG_KEYBOARD_LOCALE_HOTKEY),
  5546. hwnd,
  5547. KbdLocaleHotKeyDlg,
  5548. (LPARAM)(&InitInfo));
  5549. }
  5550. else
  5551. {
  5552. rc = (int)DialogBoxParam(GetCicResInstance(hInstance, DLG_KEYBOARD_HOTKEY_INPUT_LOCALE),
  5553. MAKEINTRESOURCE(DLG_KEYBOARD_HOTKEY_INPUT_LOCALE),
  5554. hwnd,
  5555. KbdLocaleSimpleHotkey,
  5556. (LPARAM)&InitInfo);
  5557. }
  5558. return rc;
  5559. }
  5560. ////////////////////////////////////////////////////////////////////////////
  5561. //
  5562. // Locale_CommandToolBarSetting
  5563. //
  5564. // Invokes the ToolBar setting dialog.
  5565. //
  5566. // Returns 1 if a dialog box was invoked and the dialog returned IDOK.
  5567. // Otherwise, it returns 0.
  5568. //
  5569. ////////////////////////////////////////////////////////////////////////////
  5570. BOOL Locale_CommandToolBarSetting(
  5571. HWND hwnd)
  5572. {
  5573. int rc = 0;
  5574. if ((rc = (int)DialogBoxParam(GetCicResInstance(hInstance, DLG_TOOLBAR_SETTING),
  5575. MAKEINTRESOURCE(DLG_TOOLBAR_SETTING),
  5576. hwnd,
  5577. ToolBarSettingDlg,
  5578. (LPARAM)NULL)) == IDOK)
  5579. {
  5580. return TRUE;
  5581. }
  5582. else
  5583. {
  5584. return FALSE;
  5585. }
  5586. }
  5587. ////////////////////////////////////////////////////////////////////////////
  5588. //
  5589. // Locale_AddLanguage
  5590. //
  5591. // Adds the new input locale to the list in the property page.
  5592. //
  5593. ////////////////////////////////////////////////////////////////////////////
  5594. BOOL Locale_AddLanguage(
  5595. HWND hwndMain,
  5596. LPLANGNODE pLangNode,
  5597. int iKbdTip,
  5598. int iPen,
  5599. int iSpeech,
  5600. int iExternal,
  5601. int idxLang)
  5602. {
  5603. HWND hwndLang;
  5604. UINT iCount, ctr;
  5605. BOOL bSameHKLTip = FALSE;
  5606. TCHAR szLangText[DESC_MAX];
  5607. TCHAR szLayoutName[DESC_MAX];
  5608. LPINPUTLANG pInpLang;
  5609. LPTVITEMNODE pTVItemNode = NULL;
  5610. HTREEITEM hTVItem;
  5611. if (pLangNode && iKbdTip == -1)
  5612. {
  5613. //
  5614. // See if the user has Admin privileges. If not, then don't allow
  5615. // them to install any NEW layouts.
  5616. //
  5617. if ((!g_bAdmin_Privileges) &&
  5618. (!g_lpLayout[pLangNode->iLayout].bInstalled))
  5619. {
  5620. //
  5621. // The layout is not currently installed, so don't allow it
  5622. // to be added.
  5623. //
  5624. Locale_ErrorMsg(hwndMain, IDS_KBD_LAYOUT_FAILED, NULL);
  5625. return (FALSE);
  5626. }
  5627. //
  5628. // Set the language to active.
  5629. // Also, set the status to changed so that the layout will be added.
  5630. //
  5631. pLangNode->wStatus |= (LANG_CHANGED | LANG_ACTIVE);
  5632. //
  5633. // Get language name and add it to treeview
  5634. //
  5635. pInpLang = &g_lpLang[pLangNode->iLang];
  5636. GetAtomName(pInpLang->atmLanguageName, szLangText, ARRAYSIZE(szLangText));
  5637. if (!(pTVItemNode = CreateTVItemNode(pInpLang->dwID)))
  5638. return FALSE;
  5639. pTVItemNode->lParam = (LPARAM)pLangNode;
  5640. AddTreeViewItems(TV_ITEM_TYPE_LANG,
  5641. szLangText, NULL, NULL, &pTVItemNode);
  5642. //
  5643. // Get keyboard layout name and add it to treeview
  5644. //
  5645. GetAtomName(g_lpLayout[pLangNode->iLayout].atmLayoutText,
  5646. szLayoutName,
  5647. ARRAYSIZE(szLayoutName));
  5648. //
  5649. // Adding the default layout name for each language
  5650. //
  5651. if (pTVItemNode && !pTVItemNode->atmDefTipName)
  5652. pTVItemNode->atmDefTipName = AddAtom(szLayoutName);
  5653. if (!(pTVItemNode = CreateTVItemNode(pInpLang->dwID)))
  5654. return FALSE;
  5655. pTVItemNode->lParam = (LPARAM)pLangNode;
  5656. hTVItem = AddTreeViewItems(TV_ITEM_TYPE_KBD,
  5657. szLangText, szInputTypeKbd, szLayoutName, &pTVItemNode);
  5658. if (hTVItem)
  5659. TreeView_SelectItem(g_hwndTV, hTVItem);
  5660. //
  5661. // Check Thai layout.
  5662. //
  5663. if (g_dwPrimLangID == LANG_THAI && hTVItem)
  5664. {
  5665. if (PRIMARYLANGID(LOWORD(g_lpLayout[pLangNode->iLayout].dwID)) == LANG_THAI)
  5666. g_iThaiLayout++;
  5667. }
  5668. g_dwChanges |= CHANGE_NEWKBDLAYOUT;
  5669. }
  5670. //
  5671. // Get kbd tip name and add it to treeview
  5672. //
  5673. if ((iKbdTip != CB_ERR) && !(g_lpTips[iKbdTip].bEnabled))
  5674. {
  5675. TV_ITEM tvItem;
  5676. HTREEITEM hTVLangItem;
  5677. if (g_lpTips[iKbdTip].hklSub)
  5678. {
  5679. //
  5680. // Looking for the same substitute HKL
  5681. //
  5682. for (ctr = 0; ctr < g_iTipsBuff; ctr++)
  5683. {
  5684. if (ctr == iKbdTip)
  5685. continue;
  5686. if (g_lpTips[ctr].hklSub == g_lpTips[iKbdTip].hklSub)
  5687. {
  5688. bSameHKLTip = TRUE;
  5689. break;
  5690. }
  5691. }
  5692. }
  5693. //
  5694. // Get TIP name description
  5695. //
  5696. GetAtomName(g_lpTips[iKbdTip].atmTipText, szLayoutName, ARRAYSIZE(szLayoutName));
  5697. hTVLangItem = FindTVLangItem(g_lpTips[iKbdTip].dwLangID, NULL);
  5698. if (hTVLangItem)
  5699. {
  5700. tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
  5701. tvItem.hItem = hTVLangItem;
  5702. if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam)
  5703. {
  5704. pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
  5705. }
  5706. }
  5707. else
  5708. {
  5709. //
  5710. // Get language name and add it to treeview
  5711. //
  5712. if (!(pTVItemNode = CreateTVItemNode(g_lpTips[iKbdTip].dwLangID)))
  5713. return FALSE;
  5714. GetLanguageName(MAKELCID(g_lpTips[iKbdTip].dwLangID, SORT_DEFAULT),
  5715. szLangText,
  5716. ARRAYSIZE(szLangText));
  5717. AddTreeViewItems(TV_ITEM_TYPE_LANG,
  5718. szLangText, NULL, NULL, &pTVItemNode);
  5719. }
  5720. if (pTVItemNode && g_lpTips[iKbdTip].hklSub)
  5721. {
  5722. //
  5723. // Set the index of keyboard Tip.
  5724. //
  5725. pTVItemNode->iIdxTips = iKbdTip;
  5726. if (!pTVItemNode->atmDefTipName)
  5727. pTVItemNode->atmDefTipName = AddAtom(szLayoutName);
  5728. }
  5729. //
  5730. // Create TIP layout
  5731. //
  5732. if (!(pTVItemNode = CreateTVItemNode(g_lpTips[iKbdTip].dwLangID)))
  5733. return FALSE;
  5734. if (pTVItemNode && g_lpTips[iKbdTip].hklSub)
  5735. {
  5736. //
  5737. // Insert a new language node.
  5738. //
  5739. pLangNode = Locale_AddToLinkedList(idxLang, 0);
  5740. if (pLangNode)
  5741. {
  5742. pLangNode->iLayout = (UINT) g_lpTips[iKbdTip].iLayout;
  5743. pLangNode->wStatus |= (LANG_CHANGED | LANG_ACTIVE);
  5744. pTVItemNode->lParam = (LPARAM)pLangNode;
  5745. }
  5746. }
  5747. pTVItemNode->iIdxTips = iKbdTip;
  5748. pTVItemNode->clsid = g_lpTips[iKbdTip].clsid;
  5749. pTVItemNode->guidProfile = g_lpTips[iKbdTip].guidProfile;
  5750. pTVItemNode->uInputType = INPUT_TYPE_TIP | INPUT_TYPE_KBD;
  5751. pTVItemNode->hklSub = g_lpTips[iKbdTip].hklSub;
  5752. //
  5753. // Get language name from LangID.
  5754. //
  5755. GetLanguageName(MAKELCID(g_lpTips[iKbdTip].dwLangID, SORT_DEFAULT),
  5756. szLangText,
  5757. ARRAYSIZE(szLangText));
  5758. hTVItem = AddTreeViewItems(TV_ITEM_TYPE_KBD,
  5759. szLangText, szInputTypeKbd, szLayoutName, &pTVItemNode);
  5760. if (hTVItem)
  5761. {
  5762. TreeView_SelectItem(g_hwndTV, hTVItem);
  5763. g_lpTips[iKbdTip].bEnabled = TRUE;
  5764. g_iEnabledTips++;
  5765. g_iEnabledKbdTips++;
  5766. g_dwChanges |= CHANGE_TIPCHANGE;
  5767. }
  5768. if (bSameHKLTip)
  5769. {
  5770. for (ctr = 0; ctr < g_iTipsBuff; ctr++)
  5771. {
  5772. if (!(g_lpTips[ctr].bEnabled) &&
  5773. g_lpTips[ctr].hklSub == g_lpTips[iKbdTip].hklSub)
  5774. {
  5775. //
  5776. // Create TIP layout
  5777. //
  5778. if (!(pTVItemNode = CreateTVItemNode(g_lpTips[ctr].dwLangID)))
  5779. return FALSE;
  5780. pTVItemNode->iIdxTips = ctr;
  5781. pTVItemNode->clsid = g_lpTips[ctr].clsid;
  5782. pTVItemNode->guidProfile = g_lpTips[ctr].guidProfile;
  5783. pTVItemNode->uInputType = INPUT_TYPE_TIP | INPUT_TYPE_KBD;
  5784. pTVItemNode->hklSub = g_lpTips[ctr].hklSub;
  5785. if (pLangNode)
  5786. pTVItemNode->lParam = (LPARAM)pLangNode;
  5787. //
  5788. // Get language name from LangID and layout name.
  5789. //
  5790. GetLanguageName(MAKELCID(g_lpTips[ctr].dwLangID, SORT_DEFAULT),
  5791. szLangText,
  5792. ARRAYSIZE(szLangText));
  5793. GetAtomName(g_lpTips[ctr].atmTipText, szLayoutName, ARRAYSIZE(szLayoutName));
  5794. hTVItem = AddTreeViewItems(TV_ITEM_TYPE_KBD,
  5795. szLangText, szInputTypeKbd, szLayoutName, &pTVItemNode);
  5796. if (hTVItem)
  5797. {
  5798. TreeView_SelectItem(g_hwndTV, hTVItem);
  5799. g_lpTips[ctr].bEnabled = TRUE;
  5800. g_iEnabledTips++;
  5801. g_iEnabledKbdTips++;
  5802. g_dwChanges |= CHANGE_TIPCHANGE;
  5803. }
  5804. }
  5805. }
  5806. }
  5807. }
  5808. //
  5809. // Get pen tip name and add it to treeview
  5810. //
  5811. if ((iPen != CB_ERR) && !(g_lpTips[iPen].bEnabled))
  5812. {
  5813. GetAtomName(g_lpTips[iPen].atmTipText,
  5814. szLayoutName,
  5815. ARRAYSIZE(szLayoutName));
  5816. if (!(pTVItemNode = CreateTVItemNode(g_lpTips[iPen].dwLangID)))
  5817. return FALSE;
  5818. pTVItemNode->iIdxTips = iPen;
  5819. pTVItemNode->clsid = g_lpTips[iPen].clsid;
  5820. pTVItemNode->guidProfile = g_lpTips[iPen].guidProfile;
  5821. pTVItemNode->uInputType = INPUT_TYPE_TIP | INPUT_TYPE_PEN;
  5822. //
  5823. // Get language name from LangID.
  5824. //
  5825. GetLanguageName(MAKELCID(g_lpTips[iPen].dwLangID, SORT_DEFAULT),
  5826. szLangText,
  5827. ARRAYSIZE(szLangText));
  5828. hTVItem = AddTreeViewItems(TV_ITEM_TYPE_PEN,
  5829. szLangText, szInputTypePen, szLayoutName, &pTVItemNode);
  5830. if (hTVItem)
  5831. {
  5832. g_lpTips[iPen].bEnabled = TRUE;
  5833. g_iEnabledTips++;
  5834. g_dwChanges |= CHANGE_TIPCHANGE;
  5835. }
  5836. }
  5837. //
  5838. // Get speech tip name and add it to treeview
  5839. //
  5840. if ((iSpeech != CB_ERR) && !(g_lpTips[iSpeech].bEnabled))
  5841. {
  5842. GetAtomName(g_lpTips[iSpeech].atmTipText,
  5843. szLayoutName,
  5844. ARRAYSIZE(szLayoutName));
  5845. if (!(pTVItemNode = CreateTVItemNode(g_lpTips[iSpeech].dwLangID)))
  5846. return FALSE;
  5847. pTVItemNode->iIdxTips = iSpeech;
  5848. pTVItemNode->clsid = g_lpTips[iSpeech].clsid;
  5849. pTVItemNode->guidProfile = g_lpTips[iSpeech].guidProfile;
  5850. pTVItemNode->bNoAddCat = g_lpTips[iSpeech].bNoAddCat;
  5851. pTVItemNode->uInputType = INPUT_TYPE_TIP | INPUT_TYPE_SPEECH;
  5852. //
  5853. // Get language name from LangID.
  5854. //
  5855. GetLanguageName(MAKELCID(g_lpTips[iSpeech].dwLangID, SORT_DEFAULT),
  5856. szLangText,
  5857. ARRAYSIZE(szLangText));
  5858. hTVItem = AddTreeViewItems(TV_ITEM_TYPE_SPEECH,
  5859. szLangText, szInputTypeSpeech, szLayoutName, &pTVItemNode);
  5860. if (hTVItem)
  5861. {
  5862. g_lpTips[iSpeech].bEnabled = TRUE;
  5863. g_iEnabledTips++;
  5864. g_dwChanges |= CHANGE_TIPCHANGE;
  5865. MarkSptipRemoved(FALSE);
  5866. }
  5867. }
  5868. //
  5869. // Get external tip name and add it to treeview
  5870. //
  5871. if ((iExternal != CB_ERR) && !(g_lpTips[iExternal].bEnabled))
  5872. {
  5873. BSTR bstr = NULL;
  5874. TCHAR szTipTypeName[MAX_PATH];
  5875. ITfCategoryMgr *pCategory = NULL;
  5876. GetAtomName(g_lpTips[iExternal].atmTipText,
  5877. szLayoutName,
  5878. ARRAYSIZE(szLayoutName));
  5879. if (!(pTVItemNode = CreateTVItemNode(g_lpTips[iExternal].dwLangID)))
  5880. return FALSE;
  5881. pTVItemNode->iIdxTips = iExternal;
  5882. pTVItemNode->clsid = g_lpTips[iExternal].clsid;
  5883. pTVItemNode->guidProfile = g_lpTips[iExternal].guidProfile;
  5884. pTVItemNode->bNoAddCat = g_lpTips[iExternal].bNoAddCat;
  5885. pTVItemNode->uInputType = INPUT_TYPE_TIP | INPUT_TYPE_EXTERNAL;
  5886. if (g_lpTips[iExternal].uInputType & INPUT_TYPE_SMARTTAG)
  5887. {
  5888. pTVItemNode->uInputType |= INPUT_TYPE_SMARTTAG;
  5889. }
  5890. //
  5891. // Get language name from LangID.
  5892. //
  5893. GetLanguageName(MAKELCID(g_lpTips[iExternal].dwLangID, SORT_DEFAULT),
  5894. szLangText,
  5895. ARRAYSIZE(szLangText));
  5896. if (CoCreateInstance(&CLSID_TF_CategoryMgr,
  5897. NULL,
  5898. CLSCTX_INPROC_SERVER,
  5899. &IID_ITfCategoryMgr,
  5900. (LPVOID *) &pCategory) != S_OK)
  5901. return FALSE;
  5902. if (pCategory->lpVtbl->GetGUIDDescription(pCategory,
  5903. &g_lpTips[iExternal].clsid,
  5904. &bstr) == S_OK)
  5905. {
  5906. StringCchCopy(szTipTypeName, ARRAYSIZE(szTipTypeName), bstr);
  5907. }
  5908. else
  5909. {
  5910. StringCchCopy(szTipTypeName, ARRAYSIZE(szTipTypeName), szInputTypeExternal);
  5911. }
  5912. if (bstr)
  5913. SysFreeString(bstr);
  5914. if (pCategory)
  5915. pCategory->lpVtbl->Release(pCategory);
  5916. hTVItem = AddTreeViewItems(TV_ITEM_TYPE_EXTERNAL,
  5917. szLangText, szInputTypeExternal, szLayoutName, &pTVItemNode);
  5918. if (hTVItem)
  5919. {
  5920. g_lpTips[iExternal].bEnabled = TRUE;
  5921. g_iEnabledTips++;
  5922. g_dwChanges |= CHANGE_TIPCHANGE;
  5923. }
  5924. }
  5925. //
  5926. // See the secondary controls according to input layout.
  5927. //
  5928. Locale_SetSecondaryControls(hwndMain);
  5929. //
  5930. // Add the default language switch hotkey.
  5931. //
  5932. Locale_SetDefaultHotKey(hwndMain, TRUE);
  5933. //
  5934. // Return success.
  5935. //
  5936. return (TRUE);
  5937. }
  5938. ////////////////////////////////////////////////////////////////////////////
  5939. //
  5940. // Locale_SetupKeyboardLayouts
  5941. //
  5942. // Calls setup to get all of the new keyboard layout files.
  5943. //
  5944. ////////////////////////////////////////////////////////////////////////////
  5945. BOOL Locale_SetupKeyboardLayoutsNT4(
  5946. HWND hwnd)
  5947. {
  5948. HINF hKbdInf;
  5949. HSPFILEQ FileQueue;
  5950. PVOID QueueContext;
  5951. UINT i;
  5952. LPLANGNODE pLangNode;
  5953. int count;
  5954. BOOL bInitInf = FALSE;
  5955. TCHAR szSection[MAX_PATH];
  5956. BOOL bRet = TRUE;
  5957. HWND hwndTV = GetDlgItem(hwnd, IDC_INPUT_LIST);
  5958. TV_ITEM tvItem;
  5959. HTREEITEM hItem;
  5960. HTREEITEM hLangItem;
  5961. HTREEITEM hGroupItem;
  5962. tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
  5963. for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
  5964. hLangItem != NULL ;
  5965. hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem)
  5966. )
  5967. {
  5968. for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem);
  5969. hGroupItem != NULL;
  5970. hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem))
  5971. {
  5972. for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
  5973. hItem != NULL;
  5974. hItem = TreeView_GetNextSibling(hwndTV, hItem))
  5975. {
  5976. LPTVITEMNODE pTVItemNode;
  5977. tvItem.hItem = hItem;
  5978. if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
  5979. {
  5980. pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
  5981. pLangNode = (LPLANGNODE)pTVItemNode->lParam;
  5982. if (pLangNode == NULL)
  5983. continue;
  5984. }
  5985. else
  5986. continue;
  5987. if ((pLangNode->wStatus & LANG_CHANGED) &&
  5988. (pLangNode->wStatus & LANG_ACTIVE))
  5989. {
  5990. if (!bInitInf)
  5991. {
  5992. //
  5993. // Open the Inf file.
  5994. //
  5995. hKbdInf = SetupOpenInfFile(c_szKbdInf, NULL, INF_STYLE_WIN4, NULL);
  5996. if (hKbdInf == INVALID_HANDLE_VALUE)
  5997. {
  5998. return (FALSE);
  5999. }
  6000. if (!SetupOpenAppendInfFile(NULL, hKbdInf, NULL))
  6001. {
  6002. SetupCloseInfFile(hKbdInf);
  6003. return (FALSE);
  6004. }
  6005. //
  6006. // Create a setup file queue and initialize default setup
  6007. // copy queue callback context.
  6008. //
  6009. FileQueue = SetupOpenFileQueue();
  6010. if ((!FileQueue) || (FileQueue == INVALID_HANDLE_VALUE))
  6011. {
  6012. SetupCloseInfFile(hKbdInf);
  6013. return (FALSE);
  6014. }
  6015. QueueContext = SetupInitDefaultQueueCallback(hwnd);
  6016. if (!QueueContext)
  6017. {
  6018. SetupCloseFileQueue(FileQueue);
  6019. SetupCloseInfFile(hKbdInf);
  6020. return (FALSE);
  6021. }
  6022. bInitInf = TRUE;
  6023. }
  6024. //
  6025. // Get the layout name.
  6026. //
  6027. StringCchPrintf(szSection,
  6028. ARRAYSIZE(szSection),
  6029. TEXT("%s%8.8lx"),
  6030. c_szPrefixCopy,
  6031. g_lpLayout[pLangNode->iLayout].dwID );
  6032. //
  6033. // Enqueue the keyboard layout files so that they may be
  6034. // copied. This only handles the CopyFiles entries in the
  6035. // inf file.
  6036. //
  6037. if (!SetupInstallFilesFromInfSection( hKbdInf,
  6038. NULL,
  6039. FileQueue,
  6040. szSection,
  6041. NULL,
  6042. SP_COPY_NEWER ))
  6043. {
  6044. //
  6045. // Setup failed to find the keyboard. Make it inactive
  6046. // and remove it from the list.
  6047. //
  6048. // This shouldn't happen - the inf file is messed up.
  6049. //
  6050. Locale_ErrorMsg(hwnd, IDS_KBD_SETUP_FAILED, NULL);
  6051. pLangNode->wStatus &= ~(LANG_CHANGED | LANG_ACTIVE);
  6052. if (pTVItemNode)
  6053. {
  6054. RemoveTVItemNode(pTVItemNode);
  6055. }
  6056. TreeView_DeleteItem(hwndTV, tvItem.hItem );
  6057. if ((g_lpLang[pLangNode->iLang].iNumCount) > 1)
  6058. {
  6059. (g_lpLang[pLangNode->iLang].iNumCount)--;
  6060. Locale_RemoveFromLinkedList(pLangNode);
  6061. }
  6062. }
  6063. }
  6064. }
  6065. }
  6066. }
  6067. if (bInitInf)
  6068. {
  6069. DWORD d;
  6070. //
  6071. // See if we need to install any files.
  6072. //
  6073. // d = 0: User wants new files or some files were missing;
  6074. // Must commit queue.
  6075. //
  6076. // d = 1: User wants to use existing files and queue is empty;
  6077. // Can skip committing queue.
  6078. //
  6079. // d = 2: User wants to use existing files, but del/ren queues
  6080. // not empty. Must commit queue. The copy queue will
  6081. // have been emptied, so only del/ren functions will be
  6082. // performed.
  6083. //
  6084. if ((SetupScanFileQueue( FileQueue,
  6085. SPQ_SCAN_FILE_VALIDITY | SPQ_SCAN_INFORM_USER,
  6086. hwnd,
  6087. NULL,
  6088. NULL,
  6089. &d )) && (d != 1))
  6090. {
  6091. //
  6092. // Copy the files in the queue.
  6093. //
  6094. if (!SetupCommitFileQueue( hwnd,
  6095. FileQueue,
  6096. SetupDefaultQueueCallback,
  6097. QueueContext ))
  6098. {
  6099. //
  6100. // This can happen if the user hits Cancel from within
  6101. // the setup dialog.
  6102. //
  6103. Locale_ErrorMsg(hwnd, IDS_KBD_SETUP_FAILED, NULL);
  6104. bRet = FALSE;
  6105. goto Locale_SetupError;
  6106. }
  6107. }
  6108. Locale_SetupError:
  6109. //
  6110. // Terminate the Queue.
  6111. //
  6112. SetupTermDefaultQueueCallback(QueueContext);
  6113. //
  6114. // Close the file queue.
  6115. //
  6116. SetupCloseFileQueue(FileQueue);
  6117. //
  6118. // Close the Inf file.
  6119. //
  6120. SetupCloseInfFile(hKbdInf);
  6121. }
  6122. //
  6123. // Return success.
  6124. //
  6125. return (bRet);
  6126. }
  6127. ////////////////////////////////////////////////////////////////////////////
  6128. //
  6129. // Locale_ApplyInputs
  6130. //
  6131. // 1. make sure we have all the layout files required.
  6132. // 2. write the information into the registry
  6133. // 3. call Load/UnloadKeyboardLayout where relevant
  6134. //
  6135. // Note that this will trash the previous preload and substitutes sections,
  6136. // based on what is actually loaded. Thus if something was wrong before in
  6137. // the registry, it will be corrected now.
  6138. //
  6139. ////////////////////////////////////////////////////////////////////////////
  6140. BOOL Locale_ApplyInputs(
  6141. HWND hwnd)
  6142. {
  6143. BOOL bSetDef = FALSE;
  6144. UINT iVal, idx, ctr, ctr2, nHotKeys;
  6145. UINT nLocales = 0;
  6146. UINT iPreload = 0;
  6147. LPLANGNODE pLangNode, pTemp;
  6148. LPINPUTLANG pInpLang;
  6149. DWORD dwID;
  6150. TCHAR sz[DESC_MAX]; // temp - build the name of the reg entry
  6151. TCHAR szPreload10[10];
  6152. TCHAR szTemp[MAX_PATH];
  6153. HKEY hkeyLayouts;
  6154. HKEY hkeySubst;
  6155. HKEY hkeyPreload;
  6156. HKEY hKeyImm;
  6157. HKEY hkeyTip;
  6158. HWND hwndTV = GetDlgItem(hwnd, IDC_INPUT_LIST);
  6159. HKL hklDefault = 0;
  6160. HKL hklLoad, hklUnload;
  6161. HKL hklSub[MAX_DUPLICATED_HKL];
  6162. HCURSOR hcurSave;
  6163. HKEY hkeyScanCode;
  6164. DWORD cb;
  6165. TCHAR szShiftL[8];
  6166. TCHAR szShiftR[8];
  6167. BOOL bHasIme = FALSE;
  6168. BOOL bReplaced = FALSE;
  6169. BOOL bCheckedSubhkl;
  6170. BOOL bDisableCtfmon = FALSE;
  6171. BOOL bRebootForCUAS = FALSE;
  6172. BOOL bAlreadyLoadCtfmon = FALSE;
  6173. TV_ITEM tvItem;
  6174. HTREEITEM hItem;
  6175. HTREEITEM hLangItem;
  6176. HTREEITEM hGroupItem;
  6177. //
  6178. // See if the pane is disabled. If so, then there is nothing to
  6179. // Apply.
  6180. //
  6181. if (!IsWindowEnabled(hwndTV))
  6182. {
  6183. return (TRUE);
  6184. }
  6185. //
  6186. // Put up the hour glass.
  6187. //
  6188. hcurSave = SetCursor(LoadCursor(NULL, IDC_WAIT));
  6189. //
  6190. // Make sure there are actually changes since the last save when
  6191. // OK is selected. If the user hits OK without anything to Apply,
  6192. // then we should do nothing.
  6193. //
  6194. if (g_dwChanges == 0 && !g_bAdvChanged)
  6195. {
  6196. pLangNode = NULL;
  6197. for (idx = 0; idx < g_iLangBuff; idx++)
  6198. {
  6199. pLangNode = g_lpLang[idx].pNext;
  6200. while (pLangNode != NULL)
  6201. {
  6202. if (pLangNode->wStatus & (LANG_CHANGED | LANG_DEF_CHANGE))
  6203. {
  6204. break;
  6205. }
  6206. pLangNode = pLangNode->pNext;
  6207. }
  6208. if (pLangNode != NULL)
  6209. {
  6210. break;
  6211. }
  6212. }
  6213. if ((idx == g_iLangBuff) && (pLangNode == NULL))
  6214. {
  6215. SetCursor(hcurSave);
  6216. PropSheet_UnChanged(GetParent(hwnd), hwnd);
  6217. return (TRUE);
  6218. }
  6219. }
  6220. if (g_OSNT4)
  6221. {
  6222. //
  6223. // Queue up the new layouts and copy the appropriate files to
  6224. // disk using the setup apis. Only do this if the user has
  6225. // Admin privileges.
  6226. //
  6227. if (g_bAdmin_Privileges &&
  6228. !Locale_SetupKeyboardLayoutsNT4(hwnd))
  6229. {
  6230. SetCursor(hcurSave);
  6231. return (FALSE);
  6232. }
  6233. }
  6234. //
  6235. // Clean up the registry.
  6236. //
  6237. //
  6238. // For FE languages, there is a keyboard which has a different
  6239. // scan code for shift keys - eg. NEC PC9801.
  6240. // We have to keep information about scan codes for shift keys in
  6241. // the registry under the 'toggle' sub key as named values.
  6242. //
  6243. szShiftL[0] = TEXT('\0');
  6244. szShiftR[0] = TEXT('\0');
  6245. if (RegOpenKey( HKEY_CURRENT_USER,
  6246. c_szScanCodeKey,
  6247. &hkeyScanCode ) == ERROR_SUCCESS)
  6248. {
  6249. cb = sizeof(szShiftL);
  6250. RegQueryValueEx( hkeyScanCode,
  6251. c_szValueShiftLeft,
  6252. NULL,
  6253. NULL,
  6254. (LPBYTE)szShiftL,
  6255. &cb );
  6256. cb = sizeof(szShiftR);
  6257. RegQueryValueEx( hkeyScanCode,
  6258. c_szValueShiftRight,
  6259. NULL,
  6260. NULL,
  6261. (LPBYTE)szShiftR,
  6262. &cb );
  6263. RegCloseKey(hkeyScanCode);
  6264. }
  6265. //
  6266. // Delete the HKCU\Keyboard Layout key and all subkeys.
  6267. //
  6268. if (RegOpenKeyEx( HKEY_CURRENT_USER,
  6269. c_szKbdLayouts,
  6270. 0,
  6271. KEY_ALL_ACCESS,
  6272. &hkeyLayouts ) == ERROR_SUCCESS)
  6273. {
  6274. //
  6275. // Delete the HKCU\Keyboard Layout\Preload, Substitutes, and Toggle
  6276. // keys in the registry so that the Keyboard Layout section can be
  6277. // rebuilt.
  6278. //
  6279. RegDeleteKey(hkeyLayouts, c_szPreloadKey);
  6280. RegDeleteKey(hkeyLayouts, c_szSubstKey);
  6281. RegCloseKey(hkeyLayouts);
  6282. }
  6283. //
  6284. // Create the HKCU\Keyboard Layout key.
  6285. //
  6286. if (RegCreateKey( HKEY_CURRENT_USER,
  6287. c_szKbdLayouts,
  6288. &hkeyLayouts ) == ERROR_SUCCESS)
  6289. {
  6290. //
  6291. // Create the HKCU\Keyboard Layout\Substitutes key.
  6292. //
  6293. if (RegCreateKey( hkeyLayouts,
  6294. c_szSubstKey,
  6295. &hkeySubst ) == ERROR_SUCCESS)
  6296. {
  6297. //
  6298. // Create the HKCU\Keyboard Layout\Preload key.
  6299. //
  6300. if (RegCreateKey( hkeyLayouts,
  6301. c_szPreloadKey,
  6302. &hkeyPreload ) == ERROR_SUCCESS)
  6303. {
  6304. //
  6305. // Initialize the iPreload variable to 1 to show
  6306. // that the key has been created.
  6307. //
  6308. iPreload = 1;
  6309. }
  6310. else
  6311. {
  6312. RegCloseKey(hkeySubst);
  6313. }
  6314. }
  6315. RegCloseKey(hkeyLayouts);
  6316. }
  6317. if (!iPreload)
  6318. {
  6319. //
  6320. // Registry keys could not be created. Now what?
  6321. //
  6322. MessageBeep(MB_OK);
  6323. SetCursor(hcurSave);
  6324. return (FALSE);
  6325. }
  6326. //
  6327. // Set all usage counts to zero in the language array.
  6328. //
  6329. for (idx = 0; idx < g_iLangBuff; idx++)
  6330. {
  6331. g_lpLang[idx].iUseCount = 0;
  6332. }
  6333. //
  6334. // Search through the list to see if any keyboard layouts need to be
  6335. // unloaded from the system.
  6336. //
  6337. for (idx = 0; idx < g_iLangBuff; idx++)
  6338. {
  6339. pLangNode = g_lpLang[idx].pNext;
  6340. while (pLangNode != NULL)
  6341. {
  6342. if ( (pLangNode->wStatus & LANG_ORIGACTIVE) &&
  6343. !(pLangNode->wStatus & LANG_ACTIVE) )
  6344. {
  6345. //
  6346. // Before unloading the hkl, look for the corresponding
  6347. // hotkey and remove it.
  6348. //
  6349. DWORD dwHotKeyID = 0;
  6350. for (ctr = 0; ctr < DSWITCH_HOTKEY_SIZE; ctr++)
  6351. {
  6352. if (g_aDirectSwitchHotKey[ctr].hkl == pLangNode->hkl)
  6353. {
  6354. //
  6355. // Found an hkl match. Remember the hotkey ID so
  6356. // we can delete the hotkey entry later if the
  6357. // unload of the hkl succeeds.
  6358. //
  6359. dwHotKeyID = g_aDirectSwitchHotKey[ctr].dwHotKeyID;
  6360. break;
  6361. }
  6362. }
  6363. //
  6364. // Started off with this active, deleting it now.
  6365. // Failure is not fatal.
  6366. //
  6367. if (!UnloadKeyboardLayout(pLangNode->hkl))
  6368. {
  6369. LPLANGNODE pLangNodeNext = NULL;
  6370. pLangNode->wStatus |= LANG_UNLOAD;
  6371. pLangNodeNext = pLangNode->pNext;
  6372. //
  6373. // Don't need to check TIP case and TIP case also display
  6374. // message and add the substitute hkl into the tree view.
  6375. //
  6376. //if (!IsTipSubstituteHKL((HKL) ((DWORD_PTR)(pLangNode->hkl))))
  6377. {
  6378. Locale_ApplyError( hwnd,
  6379. pLangNode,
  6380. IDS_KBD_UNLOAD_KBD_FAILED,
  6381. MB_OK_OOPS );
  6382. //
  6383. // Failed to unload layout, put it back in the list,
  6384. // and turn ON the indicator whether it needs it or not.
  6385. //
  6386. if (Locale_AddLanguage(hwnd, pLangNode, -1, -1, -1, -1, 0))
  6387. {
  6388. Locale_SetSecondaryControls(hwnd);
  6389. }
  6390. }
  6391. pLangNode = pLangNodeNext;
  6392. }
  6393. else
  6394. {
  6395. //
  6396. // Succeeded, no longer in USER's list.
  6397. //
  6398. // Reset flag, this could be from ApplyInput and we'll
  6399. // fail on the OK if we leave it marked as original
  6400. // active.
  6401. //
  6402. pLangNode->wStatus &= ~(LANG_ORIGACTIVE | LANG_CHANGED);
  6403. //
  6404. // Remove the hotkey entry for this hkl.
  6405. //
  6406. if (dwHotKeyID)
  6407. {
  6408. ImmSetHotKey(dwHotKeyID, 0, 0, (HKL)NULL);
  6409. }
  6410. //
  6411. // Remove the link in the language array.
  6412. //
  6413. // NOTE: pLangNode could be null here.
  6414. //
  6415. pTemp = pLangNode->pNext;
  6416. Locale_RemoveFromLinkedList(pLangNode);
  6417. pLangNode = pTemp;
  6418. }
  6419. }
  6420. else
  6421. {
  6422. pLangNode = pLangNode->pNext;
  6423. }
  6424. }
  6425. }
  6426. //
  6427. // The order in the registry is based on the order in which they
  6428. // appear in the list box.
  6429. //
  6430. // The only exception to this is that the default will be number 1.
  6431. //
  6432. // If no default is found, the last one in the list will be used as
  6433. // the default.
  6434. //
  6435. iVal = 2;
  6436. ctr = 0;
  6437. //
  6438. // Check the default keyboard layout not to lose the default HKL.
  6439. //
  6440. EnsureDefaultKbdLayout(&nLocales);
  6441. tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
  6442. for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
  6443. hLangItem != NULL ;
  6444. hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem))
  6445. {
  6446. bCheckedSubhkl = FALSE;
  6447. //
  6448. // Clear the duplicated HKL buffer index
  6449. //
  6450. ctr2 = 0;
  6451. for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem);
  6452. hGroupItem != NULL;
  6453. hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem))
  6454. {
  6455. for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
  6456. hItem != NULL;
  6457. hItem = TreeView_GetNextSibling(hwndTV, hItem))
  6458. {
  6459. LPTVITEMNODE pTVItemNode;
  6460. pLangNode = NULL;
  6461. tvItem.hItem = hItem;
  6462. if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
  6463. {
  6464. pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
  6465. pLangNode = (LPLANGNODE)pTVItemNode->lParam;
  6466. }
  6467. if (!pLangNode && !bCheckedSubhkl &&
  6468. (pTVItemNode->uInputType & INPUT_TYPE_KBD) &&
  6469. pTVItemNode->hklSub)
  6470. {
  6471. bCheckedSubhkl = TRUE;
  6472. if (tvItem.hItem = FindTVLangItem(pTVItemNode->dwLangID, NULL))
  6473. {
  6474. if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
  6475. {
  6476. LPTVITEMNODE pTVLangItemNode;
  6477. pTVLangItemNode = (LPTVITEMNODE) tvItem.lParam;
  6478. pLangNode = (LPLANGNODE)pTVLangItemNode->lParam;
  6479. }
  6480. }
  6481. }
  6482. if (!pLangNode)
  6483. continue;
  6484. if (pTVItemNode->hklSub)
  6485. {
  6486. UINT uHklIdx;
  6487. BOOL bFoundSameHkl = FALSE;
  6488. for (uHklIdx = 0; uHklIdx < ctr2; uHklIdx++)
  6489. {
  6490. if (pTVItemNode->hklSub == hklSub[uHklIdx])
  6491. {
  6492. bFoundSameHkl = TRUE;
  6493. break;
  6494. }
  6495. }
  6496. //
  6497. // This substitute HKL is already registered. Skip this HKL.
  6498. //
  6499. if (bFoundSameHkl)
  6500. continue;
  6501. hklSub[ctr2] = pTVItemNode->hklSub;
  6502. ctr2++;
  6503. }
  6504. if (pLangNode->wStatus & LANG_UNLOAD)
  6505. {
  6506. pLangNode->wStatus &= ~LANG_UNLOAD;
  6507. pLangNode->wStatus &= ~(LANG_CHANGED | LANG_DEF_CHANGE);
  6508. nLocales--;
  6509. continue;
  6510. }
  6511. pInpLang = &(g_lpLang[pLangNode->iLang]);
  6512. //
  6513. // Clear the "set hot key" field, since we will be writing to the
  6514. // registry.
  6515. //
  6516. pLangNode->wStatus &= ~LANG_HOTKEY;
  6517. //
  6518. // See if it's the default input locale.
  6519. //
  6520. if (!bSetDef && (pLangNode->wStatus & LANG_DEFAULT))
  6521. {
  6522. //
  6523. // Default input locale, so the preload value should be
  6524. // set to 1.
  6525. //
  6526. iPreload = 1;
  6527. bSetDef = TRUE;
  6528. if (pTVItemNode->hklSub)
  6529. {
  6530. TCHAR szDefTip[MAX_PATH];
  6531. if (g_lpTips &&
  6532. g_lpTips[pTVItemNode->iIdxTips].hklSub == pTVItemNode->hklSub)
  6533. {
  6534. BOOL bSave = FALSE;
  6535. SaveLanguageProfileStatus(bSave,
  6536. pTVItemNode->iIdxTips,
  6537. pTVItemNode->hklSub);
  6538. }
  6539. }
  6540. }
  6541. else if (ctr == (nLocales - 1))
  6542. {
  6543. //
  6544. // We're on the last one. Make sure there was a default.
  6545. //
  6546. iPreload = (iVal <= nLocales) ? iVal : 1;
  6547. }
  6548. else
  6549. {
  6550. //
  6551. // Set the preload value to the next value.
  6552. //
  6553. iPreload = iVal;
  6554. iVal++;
  6555. }
  6556. ctr++;
  6557. //
  6558. // Store the preload value as a string so that it can be written
  6559. // into the registry (as a value name).
  6560. //
  6561. StringCchPrintf(sz, ARRAYSIZE(sz), TEXT("%d"), iPreload);
  6562. //
  6563. // Store the locale id as a string so that it can be written
  6564. // into the registry (as a value).
  6565. //
  6566. if ((HIWORD(g_lpLayout[pLangNode->iLayout].dwID) & 0xf000) == 0xe000)
  6567. {
  6568. pLangNode->wStatus |= LANG_IME;
  6569. StringCchPrintf(szPreload10,
  6570. ARRAYSIZE(szPreload10),
  6571. TEXT("%8.8lx"),
  6572. g_lpLayout[pLangNode->iLayout].dwID );
  6573. bHasIme = TRUE;
  6574. }
  6575. else
  6576. {
  6577. pLangNode->wStatus &= ~LANG_IME;
  6578. dwID = pInpLang->dwID;
  6579. idx = pInpLang->iUseCount;
  6580. if ((idx == 0) || (idx > 0xfff))
  6581. {
  6582. idx = 0;
  6583. }
  6584. else
  6585. {
  6586. dwID |= ((DWORD)(0xd000 | ((WORD)(idx - 1))) << 16);
  6587. }
  6588. StringCchPrintf(szPreload10, ARRAYSIZE(szPreload10), TEXT("%08.8x"), dwID);
  6589. (pInpLang->iUseCount)++;
  6590. }
  6591. //
  6592. // Set the new entry in the registry. It is of the form:
  6593. //
  6594. // HKCU\Keyboard Layout
  6595. // Preload: 1 = <locale id>
  6596. // 2 = <locale id>
  6597. // etc...
  6598. //
  6599. RegSetValueEx( hkeyPreload,
  6600. sz,
  6601. 0,
  6602. REG_SZ,
  6603. (LPBYTE)szPreload10,
  6604. (DWORD)(lstrlen(szPreload10) + 1) * sizeof(TCHAR) );
  6605. //
  6606. // See if we need to add a substitute for this input locale.
  6607. //
  6608. if (((pInpLang->dwID != g_lpLayout[pLangNode->iLayout].dwID) || idx) &&
  6609. (!(pLangNode->wStatus & LANG_IME)))
  6610. {
  6611. //
  6612. // Get the layout id as a string so that it can be written
  6613. // into the registry (as a value).
  6614. //
  6615. StringCchPrintf(szTemp,
  6616. ARRAYSIZE(szTemp),
  6617. TEXT("%8.8lx"),
  6618. g_lpLayout[pLangNode->iLayout].dwID );
  6619. //
  6620. // Set the new entry in the registry. It is of the form:
  6621. //
  6622. // HKCU\Keyboard Layout
  6623. // Substitutes: <locale id> = <layout id>
  6624. // <locale id> = <layout id>
  6625. // etc...
  6626. //
  6627. RegSetValueEx( hkeySubst,
  6628. szPreload10,
  6629. 0,
  6630. REG_SZ,
  6631. (LPBYTE)szTemp,
  6632. (DWORD)(lstrlen(szTemp) + 1) * sizeof(TCHAR) );
  6633. }
  6634. //
  6635. // Make sure all of the changes are written to disk.
  6636. //
  6637. RegFlushKey(hkeySubst);
  6638. RegFlushKey(hkeyPreload);
  6639. RegFlushKey(HKEY_CURRENT_USER);
  6640. //
  6641. // See if the keyboard layout needs to be loaded.
  6642. //
  6643. if (pLangNode->wStatus & (LANG_CHANGED | LANG_DEF_CHANGE))
  6644. {
  6645. //
  6646. // Load the keyboard layout into the system.
  6647. //
  6648. if (pLangNode->hklUnload)
  6649. {
  6650. hklLoad = LoadKeyboardLayoutEx( pLangNode->hklUnload,
  6651. szPreload10,
  6652. KLF_SUBSTITUTE_OK |
  6653. KLF_NOTELLSHELL |
  6654. g_dwAttributes );
  6655. if (hklLoad != pLangNode->hklUnload)
  6656. {
  6657. bReplaced = TRUE;
  6658. }
  6659. }
  6660. else
  6661. {
  6662. hklLoad = LoadKeyboardLayout( szPreload10,
  6663. KLF_SUBSTITUTE_OK |
  6664. KLF_NOTELLSHELL |
  6665. g_dwAttributes );
  6666. }
  6667. if (hklLoad)
  6668. {
  6669. pLangNode->wStatus &= ~(LANG_CHANGED | LANG_DEF_CHANGE);
  6670. pLangNode->wStatus |= (LANG_ACTIVE | LANG_ORIGACTIVE);
  6671. if (pLangNode->wStatus & LANG_DEFAULT)
  6672. {
  6673. hklDefault = hklLoad;
  6674. }
  6675. pLangNode->hkl = hklLoad;
  6676. pLangNode->hklUnload = hklLoad;
  6677. }
  6678. else
  6679. {
  6680. Locale_ApplyError( hwnd,
  6681. pLangNode,
  6682. IDS_KBD_LOAD_KBD_FAILED,
  6683. MB_OK_OOPS );
  6684. }
  6685. }
  6686. }
  6687. }
  6688. }
  6689. //
  6690. // Close the handles to the registry keys.
  6691. //
  6692. RegCloseKey(hkeySubst);
  6693. RegCloseKey(hkeyPreload);
  6694. //
  6695. // If TIP setting is changed, save the enable/disable status into
  6696. // registry TIP section.
  6697. //
  6698. if ((g_dwChanges & CHANGE_TIPCHANGE) && g_iTipsBuff)
  6699. {
  6700. int iIdxDefTip = -1;
  6701. BOOL bSave = TRUE;
  6702. SaveLanguageProfileStatus(bSave, iIdxDefTip, NULL);
  6703. g_dwChanges &= ~CHANGE_TIPCHANGE;
  6704. }
  6705. //
  6706. // Make sure the default is set properly. The layout id for the
  6707. // current default input locale may have been changed.
  6708. //
  6709. // NOTE: This should be done before the Unloads occur in case one
  6710. // of the layouts to unload is the old default layout.
  6711. //
  6712. if (hklDefault != 0)
  6713. {
  6714. if (!SystemParametersInfo( SPI_SETDEFAULTINPUTLANG,
  6715. 0,
  6716. (LPVOID)((LPDWORD)&hklDefault),
  6717. 0 ))
  6718. {
  6719. //
  6720. // Failure is not fatal. The old default language will
  6721. // still work.
  6722. //
  6723. Locale_ErrorMsg(hwnd, IDS_KBD_NO_DEF_LANG2, NULL);
  6724. }
  6725. else
  6726. {
  6727. //
  6728. // Try to make everything switch to the new default input locale:
  6729. // if we are in setup OR
  6730. // if it is the only one (but not if we just replaced the layout
  6731. // within the Input Locale without changing the input locale)
  6732. //
  6733. if (g_bSetupCase || ((nLocales == 1) && !bReplaced))
  6734. {
  6735. DWORD dwRecipients = BSM_APPLICATIONS | BSM_ALLDESKTOPS;
  6736. BroadcastSystemMessage( BSF_POSTMESSAGE,
  6737. &dwRecipients,
  6738. WM_INPUTLANGCHANGEREQUEST,
  6739. 1, // IS compatible with system font
  6740. (LPARAM)hklDefault );
  6741. }
  6742. }
  6743. }
  6744. //
  6745. // Apply the advanced tab changes.
  6746. //
  6747. if (g_hwndAdvanced != NULL && g_bAdvChanged)
  6748. {
  6749. DWORD dwDisableCtfmon;
  6750. BOOL bPrevDisableCUAS;
  6751. BOOL bDisabledCUAS;
  6752. //
  6753. // Get the previous CUAS status from the registry.
  6754. //
  6755. bPrevDisableCUAS = IsDisableCUAS();
  6756. //
  6757. // Save enable/disable CUAS info into the regitry.
  6758. //
  6759. if (IsDlgButtonChecked(g_hwndAdvanced, IDC_ADVANCED_CUAS_ENABLE))
  6760. {
  6761. //
  6762. // Enalbe Cicero Unaware Application Support.
  6763. //
  6764. SetDisableCUAS(FALSE);
  6765. }
  6766. else
  6767. {
  6768. //
  6769. // Disable Cicero Unaware Application Support.
  6770. //
  6771. SetDisableCUAS(TRUE);
  6772. }
  6773. bDisabledCUAS = IsDisableCUAS();
  6774. if (!g_bSetupCase)
  6775. {
  6776. TCHAR szTitle[MAX_PATH];
  6777. TCHAR szMsg[MAX_PATH];
  6778. BOOL bPrevCtfmon;
  6779. if (bPrevDisableCUAS != bDisabledCUAS)
  6780. {
  6781. //
  6782. // CUAS option is changed, so need to require the system reboot.
  6783. //
  6784. bRebootForCUAS = TRUE;
  6785. }
  6786. //
  6787. // Find language tool bar module(CTFMON.EXE)
  6788. //
  6789. if (FindWindow(c_szCTFMonClass, NULL) == NULL)
  6790. bPrevCtfmon = FALSE;
  6791. else
  6792. bPrevCtfmon = TRUE;
  6793. if (!bPrevCtfmon &&
  6794. !bRebootForCUAS &&
  6795. !IsDlgButtonChecked(g_hwndAdvanced, IDC_ADVANCED_CTFMON_DISABLE))
  6796. {
  6797. // Turn on CTFMON.EXE
  6798. CicLoadString(hInstance, IDS_TITLE_STRING, szTitle, ARRAYSIZE(szTitle));
  6799. CicLoadString(hInstance, IDS_ENABLE_CICERO, szMsg, ARRAYSIZE(szMsg));
  6800. //
  6801. // Notice - Need to restart apps that are already running.
  6802. //
  6803. MessageBox(hwnd, szMsg, szTitle, MB_OK);
  6804. }
  6805. }
  6806. //
  6807. // Save enable/disable CTFMON info into the regitry.
  6808. //
  6809. if (IsDlgButtonChecked(g_hwndAdvanced, IDC_ADVANCED_CTFMON_DISABLE))
  6810. {
  6811. //
  6812. // Set the ctfmon disable flag
  6813. //
  6814. dwDisableCtfmon = 1;
  6815. SetDisalbeCtfmon(dwDisableCtfmon);
  6816. }
  6817. else
  6818. {
  6819. //
  6820. // Set the ctfmon enable flag
  6821. //
  6822. dwDisableCtfmon = 0;
  6823. SetDisalbeCtfmon(dwDisableCtfmon);
  6824. //
  6825. // Run ctfmon.exe immediately
  6826. //
  6827. if (!g_bSetupCase &&
  6828. IsEnabledTipOrMultiLayouts() &&
  6829. IsInteractiveUserLogon())
  6830. {
  6831. RunCtfmonProcess();
  6832. bAlreadyLoadCtfmon = TRUE;
  6833. }
  6834. }
  6835. }
  6836. //
  6837. // Load the language tool bar if there is any enabled tip, otherwise
  6838. // disable tool bar
  6839. //
  6840. bDisableCtfmon = IsDisableCtfmon();
  6841. if (!bDisableCtfmon && g_iInputs >= 2)
  6842. {
  6843. //
  6844. // Load language bar or language icon(ctfmon.exe)
  6845. //
  6846. if (!bAlreadyLoadCtfmon && (g_iInputs != g_iOrgInputs))
  6847. LoadCtfmon(TRUE, 0, FALSE);
  6848. if(!g_bSetupCase)
  6849. EnableWindow(GetDlgItem(hwnd, IDC_TB_SETTING), TRUE);
  6850. }
  6851. else
  6852. {
  6853. if (bDisableCtfmon || !bHasIme)
  6854. {
  6855. LoadCtfmon(FALSE, 0, FALSE);
  6856. //
  6857. // Disable language bar setting option button
  6858. //
  6859. EnableWindow(GetDlgItem(hwnd, IDC_TB_SETTING), FALSE);
  6860. }
  6861. }
  6862. //
  6863. // Reset ctfmon change status.
  6864. //
  6865. g_bAdvChanged = FALSE;
  6866. if (g_dwChanges & CHANGE_LANGSWITCH)
  6867. {
  6868. Locale_SetLanguageHotkey();
  6869. }
  6870. //
  6871. // Set the scan code entries in the registry.
  6872. //
  6873. if (RegCreateKey( HKEY_CURRENT_USER,
  6874. c_szScanCodeKey,
  6875. &hkeyScanCode ) == ERROR_SUCCESS)
  6876. {
  6877. if (szShiftL[0])
  6878. {
  6879. RegSetValueEx( hkeyScanCode,
  6880. c_szValueShiftLeft,
  6881. 0,
  6882. REG_SZ,
  6883. (LPBYTE)szShiftL,
  6884. (DWORD)(lstrlen(szShiftL) + 1) * sizeof(TCHAR) );
  6885. }
  6886. if (szShiftR[0])
  6887. {
  6888. RegSetValueEx( hkeyScanCode,
  6889. c_szValueShiftRight,
  6890. 0,
  6891. REG_SZ,
  6892. (LPBYTE)szShiftR,
  6893. (DWORD)(lstrlen(szShiftR) + 1) * sizeof(TCHAR) );
  6894. }
  6895. RegCloseKey(hkeyScanCode);
  6896. }
  6897. //
  6898. // Call SystemParametersInfo to enable the toggle.
  6899. //
  6900. SystemParametersInfo(SPI_SETLANGTOGGLE, 0, NULL, 0);
  6901. //
  6902. // Turn off the hour glass.
  6903. //
  6904. SetCursor(hcurSave);
  6905. if ((g_dwChanges & CHANGE_DIRECTSWITCH) || bHasIme || bRebootForCUAS)
  6906. {
  6907. g_dwChanges &= ~CHANGE_DIRECTSWITCH;
  6908. if (RegOpenKey( HKEY_LOCAL_MACHINE,
  6909. c_szLoadImmPath,
  6910. &hKeyImm ) == ERROR_SUCCESS)
  6911. {
  6912. DWORD dwValue = 1;
  6913. if ((g_dwChanges & CHANGE_DIRECTSWITCH) || bHasIme)
  6914. {
  6915. RegSetValueEx( hKeyImm,
  6916. TEXT("LoadIMM"),
  6917. 0,
  6918. REG_DWORD,
  6919. (LPBYTE)&dwValue,
  6920. sizeof(DWORD) );
  6921. }
  6922. RegCloseKey(hKeyImm);
  6923. if (g_bAdmin_Privileges &&
  6924. ((!g_bSetupCase &&
  6925. !GetSystemMetrics(SM_IMMENABLED) &&
  6926. !GetSystemMetrics(SM_DBCSENABLED)) ||
  6927. bRebootForCUAS))
  6928. {
  6929. //
  6930. // Imm was not loaded. Ask user to reboot and let
  6931. // it be loaded.
  6932. //
  6933. TCHAR szReboot[DESC_MAX];
  6934. TCHAR szTitle[DESC_MAX];
  6935. CicLoadString(hInstance, IDS_REBOOT_STRING, szReboot, ARRAYSIZE(szReboot));
  6936. CicLoadString(hInstance, IDS_TITLE_STRING, szTitle, ARRAYSIZE(szTitle));
  6937. if (MessageBox( hwnd,
  6938. szReboot,
  6939. szTitle,
  6940. MB_YESNO | MB_ICONQUESTION ) == IDYES)
  6941. {
  6942. Region_RebootTheSystem();
  6943. }
  6944. }
  6945. }
  6946. }
  6947. //
  6948. // Update the originial input layouts
  6949. //
  6950. g_iOrgInputs = g_iInputs;
  6951. //
  6952. // Return success.
  6953. //
  6954. g_dwChanges = 0;
  6955. PropSheet_UnChanged(GetParent(hwnd), hwnd);
  6956. return (TRUE);
  6957. }
  6958. ////////////////////////////////////////////////////////////////////////////
  6959. //
  6960. // TVSubCVlassProc
  6961. //
  6962. // Ignore TreeView item expand or contractibility
  6963. //
  6964. ////////////////////////////////////////////////////////////////////////////
  6965. LRESULT WINAPI TVSubClassProc(
  6966. HWND hwnd,
  6967. UINT message,
  6968. WPARAM wParam,
  6969. LPARAM lParam)
  6970. {
  6971. switch (message)
  6972. {
  6973. case (WM_LBUTTONDBLCLK):
  6974. {
  6975. return TRUE;
  6976. }
  6977. case (WM_KEYDOWN):
  6978. {
  6979. if (wParam == VK_LEFT || wParam == VK_RIGHT)
  6980. return TRUE;
  6981. }
  6982. default:
  6983. {
  6984. return CallWindowProc(g_lpfnTVWndProc, hwnd, message, wParam, lParam);
  6985. }
  6986. }
  6987. return CallWindowProc(g_lpfnTVWndProc, hwnd, message, wParam, lParam);
  6988. }
  6989. ////////////////////////////////////////////////////////////////////////////
  6990. //
  6991. // InputLocaleDlgProc
  6992. //
  6993. // This is the dialog proc for the Input Locales property sheet.
  6994. //
  6995. ////////////////////////////////////////////////////////////////////////////
  6996. INT_PTR CALLBACK InputLocaleDlgProc(
  6997. HWND hDlg,
  6998. UINT message,
  6999. WPARAM wParam,
  7000. LPARAM lParam)
  7001. {
  7002. HWND hwndTV = GetDlgItem(hDlg, IDC_INPUT_LIST);
  7003. switch (message)
  7004. {
  7005. case ( WM_DESTROY ) :
  7006. {
  7007. Locale_KillPaneDialog(hDlg);
  7008. if (g_lpfnTVWndProc)
  7009. SetWindowLongPtr(hwndTV, GWLP_WNDPROC, (LONG_PTR)g_lpfnTVWndProc);
  7010. break;
  7011. }
  7012. case ( WM_HELP ) :
  7013. {
  7014. WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
  7015. c_szHelpFile,
  7016. HELP_WM_HELP,
  7017. (DWORD_PTR)(LPTSTR)aInputHelpIds );
  7018. break;
  7019. }
  7020. case ( WM_CONTEXTMENU ) : // right mouse click
  7021. {
  7022. WinHelp( (HWND)wParam,
  7023. c_szHelpFile,
  7024. HELP_CONTEXTMENU,
  7025. (DWORD_PTR)(LPTSTR)aInputHelpIds );
  7026. break;
  7027. }
  7028. case ( WM_INITDIALOG ) :
  7029. {
  7030. HWND hwndDefList = GetDlgItem(hDlg, IDC_LOCALE_DEFAULT);
  7031. g_hDlg = hDlg;
  7032. g_hwndTV = hwndTV;
  7033. InitPropSheet(hDlg, (LPPROPSHEETPAGE)lParam);
  7034. //
  7035. // Create image icons for Language tree view control
  7036. //
  7037. CreateImageIcons();
  7038. //
  7039. // Reset the contents of the default locale combo box.
  7040. //
  7041. ComboBox_ResetContent(hwndDefList);
  7042. g_hTVRoot = TreeView_GetRoot(hwndTV);
  7043. //
  7044. // Get all installed input information
  7045. //
  7046. GetInstalledInput(hDlg);
  7047. //
  7048. // Set subclass for treeview control to ignore treeview item expand
  7049. // or contractibility by mouse or keyboard.
  7050. //
  7051. g_lpfnTVWndProc = (WNDPROC) SetWindowLongPtr(hwndTV, GWLP_WNDPROC, (LONG_PTR) TVSubClassProc);
  7052. Locale_CommandSetDefault(hDlg);
  7053. //
  7054. // No longer supporting set default button.
  7055. //
  7056. //if (!g_bSetupCase && !g_bCHSystem)
  7057. {
  7058. HWND hwndDefBtn;
  7059. hwndDefBtn = GetDlgItem(hDlg, IDC_KBDL_SET_DEFAULT);
  7060. EnableWindow(hwndDefBtn, FALSE);
  7061. ShowWindow(hwndDefBtn, SW_HIDE);
  7062. }
  7063. if (FindWindow(c_szCTFMonClass, NULL) == NULL || g_bSetupCase)
  7064. {
  7065. //
  7066. // Disable language bar setting option during the setup mode,
  7067. // or turned off ctfmon.
  7068. //
  7069. EnableWindow(GetDlgItem(hDlg, IDC_TB_SETTING), FALSE);
  7070. }
  7071. else
  7072. {
  7073. EnableWindow(GetDlgItem(hDlg, IDC_TB_SETTING), TRUE);
  7074. }
  7075. break;
  7076. }
  7077. case ( WM_NOTIFY ) :
  7078. {
  7079. switch (((NMHDR *)lParam)->code)
  7080. {
  7081. case TVN_SELCHANGED:
  7082. {
  7083. CheckButtons(hDlg);
  7084. break;
  7085. }
  7086. case ( PSN_QUERYCANCEL ) :
  7087. case ( PSN_KILLACTIVE ) :
  7088. case ( PSN_RESET ) :
  7089. break;
  7090. case ( PSN_APPLY ) :
  7091. {
  7092. Locale_ApplyInputs(hDlg);
  7093. CheckButtons(hDlg);
  7094. break;
  7095. }
  7096. default :
  7097. {
  7098. return (FALSE);
  7099. }
  7100. }
  7101. break;
  7102. }
  7103. case ( WM_COMMAND ) :
  7104. {
  7105. switch (LOWORD(wParam))
  7106. {
  7107. case ( IDC_KBDL_SET_DEFAULT ) :
  7108. {
  7109. Locale_CommandSetDefaultLayout(hDlg);
  7110. break;
  7111. }
  7112. case ( IDC_KBDL_ADD ) :
  7113. {
  7114. Locale_CommandAdd(hDlg);
  7115. break;
  7116. }
  7117. case ( IDC_KBDL_EDIT ) :
  7118. {
  7119. Locale_CommandEdit(hDlg, NULL);
  7120. break;
  7121. }
  7122. case ( IDC_KBDL_DELETE ) :
  7123. {
  7124. Locale_CommandDelete(hDlg);
  7125. break;
  7126. }
  7127. case ( IDC_LOCALE_DEFAULT ) :
  7128. {
  7129. if (HIWORD(wParam) == CBN_SELCHANGE)
  7130. {
  7131. Locale_CommandSetDefault(hDlg);
  7132. }
  7133. break;
  7134. }
  7135. case ( IDC_HOTKEY_SETTING ) :
  7136. {
  7137. if (g_dwChanges & CHANGE_NEWKBDLAYOUT)
  7138. {
  7139. TCHAR szApplyMsg[MAX_PATH];
  7140. TCHAR szTitle[MAX_PATH];
  7141. CicLoadString(hInstance, IDS_KBD_APPLY_WARN, szApplyMsg, ARRAYSIZE(szApplyMsg));
  7142. CicLoadString(hInstance, IDS_TITLE_STRING, szTitle, ARRAYSIZE(szTitle));
  7143. if (MessageBox(hDlg,
  7144. szApplyMsg,
  7145. szTitle,
  7146. MB_YESNO | MB_ICONQUESTION) == IDYES)
  7147. {
  7148. Locale_ApplyInputs(hDlg);
  7149. }
  7150. g_dwChanges &= ~CHANGE_NEWKBDLAYOUT;
  7151. }
  7152. Locale_CommandHotKeySetting(hDlg);
  7153. break;
  7154. }
  7155. case ( IDC_TB_SETTING ) :
  7156. {
  7157. Locale_CommandToolBarSetting(hDlg);
  7158. break;
  7159. }
  7160. case ( IDOK ) :
  7161. {
  7162. if (!Locale_ApplyInputs(hDlg))
  7163. {
  7164. break;
  7165. }
  7166. // fall thru...
  7167. }
  7168. case ( IDCANCEL ) :
  7169. {
  7170. EndDialog(hDlg, TRUE);
  7171. break;
  7172. }
  7173. default :
  7174. {
  7175. return (FALSE);
  7176. }
  7177. }
  7178. break;
  7179. }
  7180. default :
  7181. {
  7182. return (FALSE);
  7183. }
  7184. }
  7185. return (TRUE);
  7186. }
  7187. ////////////////////////////////////////////////////////////////////////////
  7188. //
  7189. // Locale_GetLayoutList
  7190. //
  7191. // Fills in the given listbox with the appropriate list of layouts.
  7192. //
  7193. ////////////////////////////////////////////////////////////////////////////
  7194. void Locale_GetLayoutList(
  7195. HWND hwndLayout,
  7196. UINT idxLang,
  7197. UINT idxLayout,
  7198. BOOL *pfNoDefLayout)
  7199. {
  7200. UINT ctr;
  7201. UINT idx;
  7202. int idxSel = -1;
  7203. int idxSame = -1;
  7204. int idxOther = -1;
  7205. int idxBase = -1;
  7206. int idxUSA = -1; // last resort default
  7207. TCHAR sz[DESC_MAX];
  7208. LPLANGNODE pTemp;
  7209. DWORD LangID = g_lpLang[idxLang].dwID;
  7210. DWORD BaseLangID = (LOWORD(LangID) & 0xff) | 0x400;
  7211. //
  7212. // Reset the contents of the combo box.
  7213. //
  7214. ComboBox_ResetContent(hwndLayout);
  7215. //
  7216. // Search through all of the layouts.
  7217. //
  7218. for (ctr = 0; ctr < g_iLayoutBuff; ctr++)
  7219. {
  7220. //
  7221. // Filter out IME layout if it is not under native locale.
  7222. //
  7223. if (((HIWORD(g_lpLayout[ctr].dwID) & 0xf000) == 0xe000) &&
  7224. (LOWORD(g_lpLayout[ctr].dwID) != LOWORD(LangID)))
  7225. {
  7226. continue;
  7227. }
  7228. //
  7229. // Make sure this layout isn't already used for this input locale.
  7230. // If it is, then don't display it in the properties dialog.
  7231. //
  7232. if (ctr != idxLayout)
  7233. {
  7234. pTemp = g_lpLang[idxLang].pNext;
  7235. while (pTemp)
  7236. {
  7237. if (pTemp->wStatus & LANG_ACTIVE)
  7238. {
  7239. if (ctr == pTemp->iLayout)
  7240. {
  7241. break;
  7242. }
  7243. }
  7244. pTemp = pTemp->pNext;
  7245. }
  7246. if (pTemp && (ctr == pTemp->iLayout))
  7247. {
  7248. continue;
  7249. }
  7250. }
  7251. //
  7252. // Get the layout text. If it doesn't already exist in the
  7253. // combo box, then add it to the list of possible layouts.
  7254. //
  7255. GetAtomName(g_lpLayout[ctr].atmLayoutText, sz, ARRAYSIZE(sz));
  7256. if ((idx = ComboBox_FindStringExact(hwndLayout, 0, sz)) == CB_ERR)
  7257. {
  7258. //
  7259. // Filter out TIP substitute HKL.
  7260. //
  7261. if (IsTipSubstituteHKL(IntToPtr(g_lpLayout[ctr].dwID)))
  7262. {
  7263. AddKbdLayoutOnKbdTip(IntToPtr(g_lpLayout[ctr].dwID), ctr);
  7264. continue;
  7265. }
  7266. //
  7267. // Add the layout string and set the item data to be the
  7268. // index into the g_lpLayout array.
  7269. //
  7270. idx = ComboBox_AddString(hwndLayout, sz);
  7271. ComboBox_SetItemData(hwndLayout, idx, MAKELONG(ctr, 0));
  7272. //
  7273. // See if it's the US layout. If so, save the index.
  7274. //
  7275. if (g_lpLayout[ctr].dwID == US_LOCALE)
  7276. {
  7277. idxUSA = ctr;
  7278. }
  7279. }
  7280. if (idxLayout == -1)
  7281. {
  7282. //
  7283. // If the caller does not specify a layout, it must be the
  7284. // Add dialog. First we want the default layout. If the
  7285. // default layout is not an option (eg. it's already used),
  7286. // then we want any layout that has the same id as the locale
  7287. // to be the default.
  7288. //
  7289. if (idxSel == -1)
  7290. {
  7291. if (g_lpLayout[ctr].dwID == g_lpLang[idxLang].dwDefaultLayout)
  7292. {
  7293. idxSel = ctr;
  7294. }
  7295. else if (idxSame == -1)
  7296. {
  7297. if ((LOWORD(g_lpLayout[ctr].dwID) == LOWORD(LangID)) &&
  7298. (HIWORD(g_lpLayout[ctr].dwID) == 0))
  7299. {
  7300. idxSame = ctr;
  7301. }
  7302. else if (idxOther == -1)
  7303. {
  7304. if (LOWORD(g_lpLayout[ctr].dwID) == LOWORD(LangID))
  7305. {
  7306. idxOther = ctr;
  7307. }
  7308. else if ((idxBase == -1) &&
  7309. (LOWORD(g_lpLayout[ctr].dwID) == LOWORD(BaseLangID)))
  7310. {
  7311. idxBase = ctr;
  7312. }
  7313. }
  7314. }
  7315. }
  7316. }
  7317. else if (ctr == idxLayout)
  7318. {
  7319. //
  7320. // For the properties dialog, we want the one ALREADY associated.
  7321. //
  7322. idxSel = ctr;
  7323. }
  7324. }
  7325. //
  7326. // If it's the Add dialog, do some extra checking for the layout to use.
  7327. //
  7328. if (idxLayout == -1)
  7329. {
  7330. if (idxSel == -1)
  7331. {
  7332. idxSel = (idxSame != -1)
  7333. ? idxSame
  7334. : ((idxOther != -1) ? idxOther : idxBase);
  7335. }
  7336. }
  7337. //
  7338. // If a default layout was not found, then set it to the US layout.
  7339. //
  7340. if (idxSel == -1)
  7341. {
  7342. idxSel = idxUSA;
  7343. *pfNoDefLayout = TRUE;
  7344. }
  7345. //
  7346. // Set the current selection.
  7347. //
  7348. if (idxSel == -1)
  7349. {
  7350. //
  7351. // Simply set the current selection to be the first entry
  7352. // in the list.
  7353. //
  7354. ComboBox_SetCurSel(hwndLayout, 0);
  7355. }
  7356. else
  7357. {
  7358. //
  7359. // The combo box is sorted, but we need to know where
  7360. // g_lpLayout[idxSel] was stored. So, get the atom again, and
  7361. // search the list.
  7362. //
  7363. GetAtomName(g_lpLayout[idxSel].atmLayoutText, sz, ARRAYSIZE(sz));
  7364. idx = ComboBox_FindStringExact(hwndLayout, 0, sz);
  7365. ComboBox_SetCurSel(hwndLayout, idx);
  7366. }
  7367. }
  7368. ////////////////////////////////////////////////////////////////////////////
  7369. //
  7370. // Locale_GetTipList
  7371. //
  7372. ////////////////////////////////////////////////////////////////////////////
  7373. void Locale_GetTipList(
  7374. HWND hwnd,
  7375. UINT uInxLang,
  7376. BOOL bNoDefKbd)
  7377. {
  7378. UINT ctr;
  7379. int idxDefKbd = -1;
  7380. BOOL bPenOn = FALSE;
  7381. BOOL bSpeechOn = FALSE;
  7382. BOOL bExternalOn = FALSE;
  7383. TCHAR szTipName[DESC_MAX];
  7384. TCHAR szNone[DESC_MAX];
  7385. UINT uIdx;
  7386. DWORD dwLangID = g_lpLang[uInxLang].dwID;
  7387. HWND hwndKbd = GetDlgItem(hwnd, IDC_KBDLA_LAYOUT);
  7388. HWND hwndPen = GetDlgItem(hwnd, IDC_PEN_TIP);
  7389. HWND hwndPenText = GetDlgItem(hwnd, IDC_PEN_TEXT);
  7390. HWND hwndSpeech = GetDlgItem(hwnd, IDC_SPEECH_TIP);
  7391. HWND hwndSpeechText = GetDlgItem(hwnd, IDC_SPEECH_TEXT);
  7392. HWND hwndExternal = GetDlgItem(hwnd, IDC_EXTERNAL_TIP);
  7393. HWND hwndExternalText = GetDlgItem(hwnd, IDC_EXTERNAL_TEXT);
  7394. //
  7395. // Reset the contents of the combo box.
  7396. //
  7397. ComboBox_ResetContent(hwndPen);
  7398. ComboBox_ResetContent(hwndSpeech);
  7399. ComboBox_ResetContent(hwndExternal);
  7400. if (g_iTipsBuff == 0)
  7401. {
  7402. EnableWindow(hwndPen, FALSE);
  7403. EnableWindow(hwndPenText, FALSE);
  7404. EnableWindow(hwndSpeech, FALSE);
  7405. EnableWindow(hwndSpeechText, FALSE);
  7406. EnableWindow(hwndExternal, FALSE);
  7407. EnableWindow(hwndExternalText, FALSE);
  7408. return;
  7409. }
  7410. for (ctr = 0; ctr < g_iTipsBuff; ctr++)
  7411. {
  7412. if ((dwLangID == g_lpTips[ctr].dwLangID) &&
  7413. (g_lpTips[ctr].uInputType != INPUT_TYPE_KBD))
  7414. {
  7415. //
  7416. // Get the Tips text.
  7417. //
  7418. GetAtomName(g_lpTips[ctr].atmTipText, szTipName, ARRAYSIZE(szTipName));
  7419. if ((g_lpTips[ctr].uInputType & INPUT_TYPE_PEN) &&
  7420. !(g_lpTips[ctr].bEnabled))
  7421. {
  7422. uIdx = ComboBox_AddString(hwndPen, szTipName);
  7423. ComboBox_SetItemData(hwndPen, uIdx, MAKELONG(ctr, 0));
  7424. bPenOn = TRUE;
  7425. }
  7426. else if ((g_lpTips[ctr].uInputType & INPUT_TYPE_SPEECH) &&
  7427. !(g_lpTips[ctr].bEnabled) &&
  7428. g_lpTips[ctr].fEngineAvailable)
  7429. {
  7430. uIdx = ComboBox_AddString(hwndSpeech, szTipName);
  7431. ComboBox_SetItemData(hwndSpeech, uIdx, MAKELONG(ctr, 0));
  7432. bSpeechOn = TRUE;
  7433. }
  7434. else if ((g_lpTips[ctr].uInputType & INPUT_TYPE_KBD) &&
  7435. !(g_lpTips[ctr].bEnabled))
  7436. {
  7437. uIdx = ComboBox_AddString(hwndKbd, szTipName);
  7438. ComboBox_SetItemData(hwndKbd, uIdx, MAKELONG(ctr, 1));
  7439. idxDefKbd = uIdx;
  7440. }
  7441. else if((g_lpTips[ctr].uInputType & INPUT_TYPE_EXTERNAL) &&
  7442. !(g_lpTips[ctr].bEnabled))
  7443. {
  7444. uIdx = ComboBox_AddString(hwndExternal, szTipName);
  7445. ComboBox_SetItemData(hwndExternal, uIdx, MAKELONG(ctr, 0));
  7446. bExternalOn = TRUE;
  7447. }
  7448. }
  7449. }
  7450. if (idxDefKbd != -1)
  7451. {
  7452. ComboBox_SetCurSel(hwndKbd, idxDefKbd);
  7453. }
  7454. EnableWindow(hwndPen, IsDlgButtonChecked(hwnd, IDC_PEN_TEXT));
  7455. EnableWindow(hwndPenText, bPenOn);
  7456. ComboBox_SetCurSel(hwndPen, 0);
  7457. EnableWindow(hwndSpeech, IsDlgButtonChecked(hwnd, IDC_SPEECH_TEXT));
  7458. EnableWindow(hwndSpeechText, bSpeechOn);
  7459. ComboBox_SetCurSel(hwndSpeech, 0);
  7460. EnableWindow(hwndExternal, IsDlgButtonChecked(hwnd, IDC_EXTERNAL_TEXT));
  7461. EnableWindow(hwndExternalText, bExternalOn);
  7462. ComboBox_SetCurSel(hwndExternal, 0);
  7463. }
  7464. ////////////////////////////////////////////////////////////////////////////
  7465. //
  7466. // Locale_AddDlgInit
  7467. //
  7468. // Processing for a WM_INITDIALOG message for the Add dialog box.
  7469. //
  7470. ////////////////////////////////////////////////////////////////////////////
  7471. BOOL Locale_AddDlgInit(
  7472. HWND hwnd,
  7473. LPARAM lParam)
  7474. {
  7475. UINT ctr1;
  7476. UINT idx;
  7477. TCHAR sz[DESC_MAX];
  7478. LPLANGNODE pLangNode;
  7479. int nLocales, idxList, IMELayoutExist = 0;
  7480. UINT ctr2, ListCount, DefaultIdx = 0;
  7481. LRESULT LCSelectData = (LONG)-1;
  7482. BOOL bNoDefLayout = FALSE;
  7483. DWORD dwCurLang = 0;
  7484. TV_ITEM tvItem;
  7485. HTREEITEM hTVItem;
  7486. HWND hwndLang = GetDlgItem(hwnd, IDC_KBDLA_LOCALE);
  7487. //
  7488. // Get the currently chosen input locale in the parent dialog's
  7489. // treeview list box.
  7490. //
  7491. hTVItem = TreeView_GetSelection(g_hwndTV);
  7492. if (!hTVItem)
  7493. return FALSE;
  7494. tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
  7495. tvItem.hItem = hTVItem;
  7496. if (TreeView_GetItem(g_hwndTV, &tvItem))
  7497. {
  7498. if ((LPTVITEMNODE) tvItem.lParam)
  7499. {
  7500. dwCurLang = ((LPTVITEMNODE) tvItem.lParam)->dwLangID;
  7501. }
  7502. }
  7503. //
  7504. // Go through all of the input locales. Display all of them,
  7505. // since we can have multiple layouts per locale.
  7506. //
  7507. // Do NOT go down the links in this case. We don't want to display
  7508. // the language choice multiple times.
  7509. //
  7510. for (ctr1 = 0; ctr1 < g_iLangBuff; ctr1++)
  7511. {
  7512. //
  7513. // If the language does not contain an IME layout, then
  7514. // compare with layout counts without IME.
  7515. //
  7516. for (ctr2 = 0; ctr2 < g_iLayoutBuff; ctr2++)
  7517. {
  7518. if ((LOWORD(g_lpLayout[ctr2].dwID) == LOWORD(g_lpLang[ctr1].dwID)) &&
  7519. ((HIWORD(g_lpLayout[ctr2].dwID) & 0xf000) == 0xe000))
  7520. {
  7521. IMELayoutExist = 1;
  7522. break;
  7523. }
  7524. }
  7525. if ((!IMELayoutExist) &&
  7526. (g_lpLang[ctr1].iNumCount == (g_iLayoutBuff - g_iLayoutIME)) &&
  7527. (g_iTipsBuff == 0))
  7528. {
  7529. //
  7530. // No more layouts to be added for this language.
  7531. //
  7532. continue;
  7533. }
  7534. //
  7535. // Make sure there are layouts to be added for this
  7536. // input locale.
  7537. //
  7538. if ((g_lpLang[ctr1].iNumCount != g_iLayoutBuff) ||
  7539. (g_iTipsBuff != 0 && IsTipAvailableForAdd(g_lpLang[ctr1].dwID)))
  7540. {
  7541. //
  7542. // Get the language name, add the string to the
  7543. // combo box, and set the index into the g_lpLang
  7544. // array as the item data.
  7545. //
  7546. GetAtomName(g_lpLang[ctr1].atmLanguageName, sz, ARRAYSIZE(sz));
  7547. idx = ComboBox_AddString(hwndLang, sz);
  7548. ComboBox_SetItemData(hwndLang, idx, MAKELONG(ctr1, 0));
  7549. //
  7550. // Save system default locale.
  7551. //
  7552. if (LCSelectData == -1)
  7553. {
  7554. if (g_lpLang[ctr1].dwID == GetSystemDefaultLCID())
  7555. {
  7556. LCSelectData = MAKELONG(ctr1, 0);
  7557. }
  7558. }
  7559. //
  7560. // Save chosen input locale.
  7561. //
  7562. if (dwCurLang && (g_lpLang[ctr1].dwID == dwCurLang))
  7563. {
  7564. LCSelectData = MAKELONG(ctr1, 0);
  7565. dwCurLang = 0;
  7566. }
  7567. }
  7568. }
  7569. //
  7570. // Set the current selection to the currently chosen input locale
  7571. // or the default system locale entry.
  7572. //
  7573. if (LCSelectData != -1)
  7574. {
  7575. ListCount = ComboBox_GetCount(hwndLang);
  7576. for (ctr1 = 0; ctr1 < ListCount; ctr1++)
  7577. {
  7578. if (LCSelectData == ComboBox_GetItemData(hwndLang, ctr1))
  7579. {
  7580. DefaultIdx = ctr1;
  7581. break;
  7582. }
  7583. }
  7584. }
  7585. ComboBox_SetCurSel(hwndLang, DefaultIdx);
  7586. idx = (UINT)ComboBox_GetItemData(hwndLang, DefaultIdx);
  7587. SetProp(hwnd, szPropHwnd, (HANDLE)((LPINITINFO)lParam)->hwndMain);
  7588. SetProp(hwnd, szPropIdx, (HANDLE)UIntToPtr(idx));
  7589. //
  7590. // Check available language.
  7591. //
  7592. if (idx == -1)
  7593. {
  7594. //
  7595. // No languages
  7596. //
  7597. Locale_ErrorMsg(hwnd, IDS_KBD_NO_MORE_TO_ADD, NULL);
  7598. return FALSE;
  7599. }
  7600. //
  7601. // Display the keyboard layout.
  7602. //
  7603. Locale_GetLayoutList(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT), idx, -1, &bNoDefLayout);
  7604. Locale_GetTipList(hwnd, idx, bNoDefLayout);
  7605. //
  7606. // Checking for keyboard layout. If user already has this language,
  7607. // we want to give a choice to enable/disable keyboard layout. Otherwise,
  7608. // just enable the adding keyboard layouts.
  7609. //
  7610. if (g_bPenOrSapiTip || g_bExtraTip)
  7611. {
  7612. if (FindTVLangItem(g_lpLang[idx].dwID, NULL))
  7613. {
  7614. CheckDlgButton(hwnd, IDC_KBDLA_LAYOUT_TEXT, BST_UNCHECKED);
  7615. EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT_TEXT), TRUE);
  7616. EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT), FALSE);
  7617. }
  7618. else
  7619. {
  7620. CheckDlgButton(hwnd, IDC_KBDLA_LAYOUT_TEXT, BST_CHECKED);
  7621. EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT_TEXT), FALSE);
  7622. EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT), TRUE);
  7623. }
  7624. }
  7625. //
  7626. // Disable the keyboard layout if there is no available layout.
  7627. //
  7628. if (!ComboBox_GetCount(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT)))
  7629. {
  7630. EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT_TEXT), FALSE);
  7631. }
  7632. return TRUE;
  7633. }
  7634. ////////////////////////////////////////////////////////////////////////////
  7635. //
  7636. // Locale_AddCommandOK
  7637. //
  7638. // Gets the currently selected input locale from the combo box and marks
  7639. // it as active in the g_lpLang list. It then gets the requested layout
  7640. // and sets that in the list. It then adds the new input locale string
  7641. // to the input locale list in the property sheet.
  7642. //
  7643. ////////////////////////////////////////////////////////////////////////////
  7644. int Locale_AddCommandOK(
  7645. HWND hwnd)
  7646. {
  7647. LPLANGNODE pLangNode = NULL;
  7648. HWND hwndLang = GetDlgItem(hwnd, IDC_KBDLA_LOCALE);
  7649. HWND hwndLayout = GetDlgItem(hwnd, IDC_KBDLA_LAYOUT);
  7650. HWND hwndPen = GetDlgItem(hwnd, IDC_PEN_TIP);
  7651. HWND hwndSpeech = GetDlgItem(hwnd, IDC_SPEECH_TIP);
  7652. HWND hwndExternal = GetDlgItem(hwnd, IDC_EXTERNAL_TIP);
  7653. int idxLang = ComboBox_GetCurSel(hwndLang);
  7654. int idxLayout = ComboBox_GetCurSel(hwndLayout);
  7655. int idxPen = ComboBox_GetCurSel(hwndPen);
  7656. int idxSpeech = ComboBox_GetCurSel(hwndSpeech);
  7657. int idxExternal = ComboBox_GetCurSel(hwndExternal);
  7658. int iPen = -1;
  7659. int iSpeech = -1;
  7660. int iExternal = -1;
  7661. int iKbdLayout = -1;
  7662. WORD wDefault = 0;
  7663. //
  7664. // Get the offset for the language to add.
  7665. //
  7666. idxLang = (int)ComboBox_GetItemData(hwndLang, idxLang);
  7667. //
  7668. // Get the offset for the chosen keyboard layout.
  7669. //
  7670. if (IsDlgButtonChecked(hwnd, IDC_KBDLA_LAYOUT_TEXT) ||
  7671. !(g_bPenOrSapiTip || g_bExtraTip))
  7672. iKbdLayout = (int)ComboBox_GetItemData(hwndLayout, idxLayout);
  7673. //
  7674. // Get the offset for the chosen Tips.
  7675. //
  7676. if (hwndPen && hwndSpeech)
  7677. {
  7678. if (IsDlgButtonChecked(hwnd, IDC_PEN_TEXT))
  7679. iPen = (int) ComboBox_GetItemData(hwndPen, idxPen);
  7680. if (IsDlgButtonChecked(hwnd, IDC_SPEECH_TEXT))
  7681. iSpeech = (int) ComboBox_GetItemData(hwndSpeech, idxSpeech);
  7682. }
  7683. if (hwndExternal)
  7684. {
  7685. if (IsDlgButtonChecked(hwnd, IDC_EXTERNAL_TEXT))
  7686. iExternal = (int) ComboBox_GetItemData(hwndExternal, idxExternal);
  7687. }
  7688. //
  7689. // Selected no keyboard layout
  7690. //
  7691. if (iKbdLayout == CB_ERR)
  7692. goto AddLang;
  7693. if (HIWORD(iKbdLayout))
  7694. {
  7695. iKbdLayout = LOWORD(iKbdLayout);
  7696. }
  7697. else
  7698. {
  7699. //
  7700. // Need to check win9x system, since win9x doesn't support multiple
  7701. // keyboard layout on the same language. But FE system can have multiple
  7702. // IME layouts
  7703. //
  7704. if ((g_OSWIN95 && !IsFELangID(g_lpLang[idxLang].dwID)) &&
  7705. (g_lpLang[idxLang].iNumCount))
  7706. {
  7707. TCHAR szTemp[DESC_MAX];
  7708. TCHAR szMsg[DESC_MAX];
  7709. TCHAR szNewLayout[DESC_MAX];
  7710. CicLoadString(hInstance, IDS_KBD_LAYOUTEDIT, szMsg, ARRAYSIZE(szMsg));
  7711. GetAtomName(g_lpLayout[iKbdLayout].atmLayoutText, szNewLayout, ARRAYSIZE(szNewLayout));
  7712. StringCchPrintf(szTemp, ARRAYSIZE(szTemp), szMsg, szNewLayout);
  7713. //
  7714. // Ask user whether new selected keyboard layout will be replaced
  7715. // or not.
  7716. //
  7717. if (MessageBox(hwnd, szTemp, NULL, MB_YESNO | MB_ICONQUESTION) == IDYES)
  7718. {
  7719. HTREEITEM hItem;
  7720. LPLANGNODE pOldLangNode = g_lpLang[idxLang].pNext;
  7721. GetAtomName(g_lpLayout[pOldLangNode->iLayout].atmLayoutText, szTemp, ARRAYSIZE(szTemp));
  7722. //
  7723. // Find installed keyboard layout to delete it.
  7724. //
  7725. if (hItem = FindTVItem(g_lpLang[idxLang].dwID, szTemp))
  7726. {
  7727. TV_ITEM tvItem;
  7728. tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
  7729. tvItem.hItem = hItem;
  7730. pOldLangNode->wStatus &= ~LANG_ACTIVE;
  7731. pOldLangNode->wStatus |= LANG_CHANGED;
  7732. if (pOldLangNode->wStatus & LANG_DEFAULT)
  7733. wDefault = LANG_DEFAULT;
  7734. g_lpLang[pOldLangNode->iLang].iNumCount--;
  7735. Locale_RemoveFromLinkedList(pOldLangNode);
  7736. if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam)
  7737. {
  7738. RemoveTVItemNode((LPTVITEMNODE)tvItem.lParam);
  7739. TreeView_DeleteItem(g_hwndTV, tvItem.hItem );
  7740. }
  7741. g_iInputs--;
  7742. }
  7743. }
  7744. else
  7745. {
  7746. //
  7747. // Cancel - leave installed keyboard layout without changing.
  7748. // Check if there are other tips to be installed.
  7749. //
  7750. iKbdLayout = -1;
  7751. goto AddLang;
  7752. }
  7753. }
  7754. //
  7755. // Insert a new language node.
  7756. //
  7757. pLangNode = Locale_AddToLinkedList(idxLang, 0);
  7758. if (!pLangNode)
  7759. {
  7760. return (0);
  7761. }
  7762. //
  7763. // Get the offset for the chosen keyboard layout.
  7764. //
  7765. pLangNode->iLayout = (UINT) iKbdLayout;
  7766. //
  7767. // Set ikbdLayout as the default to distinguish keyboard tip from layouts.
  7768. //
  7769. iKbdLayout = -1;
  7770. //
  7771. // Set the default hkl after replacing the default hkl with new one.
  7772. //
  7773. if (g_OSWIN95)
  7774. pLangNode->wStatus |= wDefault;
  7775. //
  7776. // See if the layout is an IME and mark the status bits accordingly.
  7777. //
  7778. if ((HIWORD(g_lpLayout[pLangNode->iLayout].dwID) & 0xf000) == 0xe000)
  7779. {
  7780. pLangNode->wStatus |= LANG_IME;
  7781. }
  7782. else
  7783. {
  7784. pLangNode->wStatus &= ~LANG_IME;
  7785. }
  7786. }
  7787. AddLang:
  7788. //
  7789. // Add the new language.
  7790. //
  7791. if (!Locale_AddLanguage(GetProp(hwnd, szPropHwnd), pLangNode, iKbdLayout, iPen, iSpeech, iExternal, idxLang))
  7792. {
  7793. //
  7794. // Unable to add the language. Need to return the user back
  7795. // to the Add dialog.
  7796. //
  7797. if (pLangNode)
  7798. Locale_RemoveFromLinkedList(pLangNode);
  7799. return (0);
  7800. }
  7801. //
  7802. // Return success.
  7803. //
  7804. return (1);
  7805. }
  7806. ////////////////////////////////////////////////////////////////////////////
  7807. //
  7808. // KbdLocaleAddDlg
  7809. //
  7810. // This is the dialog proc for the Add button of the Input Locales
  7811. // property sheet.
  7812. //
  7813. ////////////////////////////////////////////////////////////////////////////
  7814. INT_PTR CALLBACK KbdLocaleAddDlg(
  7815. HWND hwnd,
  7816. UINT uMsg,
  7817. WPARAM wParam,
  7818. LPARAM lParam)
  7819. {
  7820. switch (uMsg)
  7821. {
  7822. case ( WM_INITDIALOG ) :
  7823. {
  7824. if (!Locale_AddDlgInit(hwnd, lParam))
  7825. {
  7826. EndDialog(hwnd, 0);
  7827. }
  7828. break;
  7829. }
  7830. case ( WM_HELP ) :
  7831. {
  7832. WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
  7833. c_szHelpFile,
  7834. HELP_WM_HELP,
  7835. (DWORD_PTR)(LPTSTR)aLocaleAddHelpIds );
  7836. break;
  7837. }
  7838. case ( WM_CONTEXTMENU ) : // right mouse click
  7839. {
  7840. WinHelp( (HWND)wParam,
  7841. c_szHelpFile,
  7842. HELP_CONTEXTMENU,
  7843. (DWORD_PTR)(LPTSTR)aLocaleAddHelpIds );
  7844. break;
  7845. }
  7846. case ( WM_DESTROY ) :
  7847. {
  7848. RemoveProp(hwnd, szPropHwnd);
  7849. RemoveProp(hwnd, szPropIdx);
  7850. break;
  7851. }
  7852. case ( WM_COMMAND ) :
  7853. {
  7854. switch (LOWORD(wParam))
  7855. {
  7856. case ( IDOK ) :
  7857. {
  7858. if (!Locale_AddCommandOK(hwnd))
  7859. {
  7860. //
  7861. // This means the properties dialog was cancelled.
  7862. // The Add dialog should remain active.
  7863. //
  7864. break;
  7865. }
  7866. // fall thru...
  7867. }
  7868. case ( IDCANCEL ) :
  7869. {
  7870. EndDialog(hwnd, (wParam == IDOK) ? 1 : 0);
  7871. break;
  7872. }
  7873. case ( IDC_KBDLA_LOCALE ) :
  7874. {
  7875. if (HIWORD(wParam) == CBN_SELCHANGE)
  7876. {
  7877. HWND hwndLocale = (HWND)lParam;
  7878. HWND hwndLayout = GetDlgItem(hwnd, IDC_KBDLA_LAYOUT);
  7879. BOOL bNoDefLayout = FALSE;
  7880. int idx;
  7881. //
  7882. // Update the keyboard layout lists.
  7883. //
  7884. if ((idx = ComboBox_GetCurSel(hwndLocale)) != CB_ERR)
  7885. {
  7886. idx = (int)ComboBox_GetItemData(hwndLocale, idx);
  7887. Locale_GetLayoutList(hwndLayout, idx, -1, &bNoDefLayout);
  7888. Locale_GetTipList(hwnd, idx, bNoDefLayout);
  7889. }
  7890. //
  7891. // Check the keyboard layout visibility
  7892. //
  7893. if (g_bPenOrSapiTip || g_bExtraTip)
  7894. {
  7895. if (FindTVLangItem(g_lpLang[idx].dwID, NULL))
  7896. {
  7897. CheckDlgButton(hwnd, IDC_KBDLA_LAYOUT_TEXT, BST_UNCHECKED);
  7898. EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT_TEXT), TRUE);
  7899. EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT), FALSE);
  7900. }
  7901. else
  7902. {
  7903. //
  7904. // There isn't this language in the user configuration, so
  7905. // force to add a keyboard layout for this language.
  7906. //
  7907. CheckDlgButton(hwnd, IDC_KBDLA_LAYOUT_TEXT, BST_CHECKED);
  7908. EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT_TEXT), FALSE);
  7909. EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT), TRUE);
  7910. }
  7911. }
  7912. //
  7913. // Disable the keyboard layout if there is no available layout.
  7914. //
  7915. if (!ComboBox_GetCount(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT)))
  7916. {
  7917. EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT_TEXT), FALSE);
  7918. }
  7919. }
  7920. break;
  7921. }
  7922. case (IDC_KBDLA_LAYOUT_TEXT) :
  7923. {
  7924. EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT), IsDlgButtonChecked(hwnd, IDC_KBDLA_LAYOUT_TEXT));
  7925. break;
  7926. }
  7927. case (IDC_PEN_TEXT) :
  7928. {
  7929. EnableWindow(GetDlgItem(hwnd, IDC_PEN_TIP), IsDlgButtonChecked(hwnd, IDC_PEN_TEXT));
  7930. break;
  7931. }
  7932. case (IDC_SPEECH_TEXT) :
  7933. {
  7934. EnableWindow(GetDlgItem(hwnd, IDC_SPEECH_TIP), IsDlgButtonChecked(hwnd, IDC_SPEECH_TEXT));
  7935. break;
  7936. }
  7937. case (IDC_EXTERNAL_TEXT) :
  7938. {
  7939. EnableWindow(GetDlgItem(hwnd, IDC_EXTERNAL_TIP), IsDlgButtonChecked(hwnd, IDC_EXTERNAL_TEXT));
  7940. break;
  7941. }
  7942. default :
  7943. {
  7944. return (FALSE);
  7945. }
  7946. }
  7947. break;
  7948. }
  7949. default :
  7950. {
  7951. return (FALSE);
  7952. }
  7953. }
  7954. return (TRUE);
  7955. }
  7956. ////////////////////////////////////////////////////////////////////////////
  7957. //
  7958. // GetToolBarSetting
  7959. //
  7960. ////////////////////////////////////////////////////////////////////////////
  7961. void GetToolBarSetting(
  7962. HWND hwnd)
  7963. {
  7964. HRESULT hr;
  7965. DWORD dwTBFlag = 0;
  7966. ITfLangBarMgr *pLangBar = NULL;
  7967. if (!g_OSNT5)
  7968. {
  7969. EnableWindow(GetDlgItem(hwnd, IDC_TB_HIGHTRANS), FALSE);
  7970. }
  7971. //
  7972. // load LangBar manager
  7973. //
  7974. hr = CoCreateInstance(&CLSID_TF_LangBarMgr,
  7975. NULL,
  7976. CLSCTX_INPROC_SERVER,
  7977. &IID_ITfLangBarMgr,
  7978. (LPVOID *) &pLangBar);
  7979. if (SUCCEEDED(hr))
  7980. pLangBar->lpVtbl->GetShowFloatingStatus(pLangBar, &dwTBFlag);
  7981. //
  7982. // Set the language bar show/close.
  7983. //
  7984. CheckDlgButton(hwnd, IDC_TB_SHOWLANGBAR, !(dwTBFlag & TF_SFT_HIDDEN));
  7985. if (!(dwTBFlag & TF_SFT_SHOWNORMAL))
  7986. {
  7987. // Disable langbar setting options
  7988. //EnableWindow(GetDlgItem(hwnd, IDC_TB_EXTRAICON), FALSE);
  7989. EnableWindow(GetDlgItem(hwnd, IDC_TB_HIGHTRANS), FALSE);
  7990. EnableWindow(GetDlgItem(hwnd, IDC_TB_TEXTLABELS), FALSE);
  7991. }
  7992. //
  7993. // Set language bar extra icons in case of minimized.
  7994. //
  7995. CheckDlgButton(hwnd, IDC_TB_EXTRAICON, dwTBFlag & TF_SFT_EXTRAICONSONMINIMIZED);
  7996. //
  7997. // Set the default toolbar transparency option.
  7998. //
  7999. CheckDlgButton(hwnd, IDC_TB_HIGHTRANS, !(dwTBFlag & TF_SFT_NOTRANSPARENCY));
  8000. //
  8001. // Set the default toolbar show text option.
  8002. //
  8003. CheckDlgButton(hwnd, IDC_TB_TEXTLABELS, dwTBFlag & TF_SFT_LABELS);
  8004. if (pLangBar)
  8005. pLangBar->lpVtbl->Release(pLangBar);
  8006. }
  8007. ////////////////////////////////////////////////////////////////////////////
  8008. //
  8009. // ToolBarSettingInit
  8010. //
  8011. ////////////////////////////////////////////////////////////////////////////
  8012. void ToolBarSettingInit(
  8013. HWND hwnd)
  8014. {
  8015. HWND hwndCTFMon = NULL;
  8016. //
  8017. // Find language tool bar module(CTFMON.EXE)
  8018. //
  8019. hwndCTFMon = FindWindow(c_szCTFMonClass, NULL);
  8020. if (hwndCTFMon)
  8021. {
  8022. EnableWindow(GetDlgItem(hwnd, IDC_TB_SHOWLANGBAR), TRUE);
  8023. EnableWindow(GetDlgItem(hwnd, IDC_TB_EXTRAICON), TRUE);
  8024. GetToolBarSetting(hwnd);
  8025. }
  8026. else
  8027. {
  8028. EnableWindow(GetDlgItem(hwnd, IDC_TB_SHOWLANGBAR), FALSE);
  8029. EnableWindow(GetDlgItem(hwnd, IDC_TB_EXTRAICON), FALSE);
  8030. EnableWindow(GetDlgItem(hwnd, IDC_TB_HIGHTRANS), FALSE);
  8031. EnableWindow(GetDlgItem(hwnd, IDC_TB_TEXTLABELS), FALSE);
  8032. }
  8033. }
  8034. ////////////////////////////////////////////////////////////////////////////
  8035. //
  8036. // ToolBarSettingOK
  8037. //
  8038. ////////////////////////////////////////////////////////////////////////////
  8039. void ToolBarSettingOK(
  8040. HWND hwnd)
  8041. {
  8042. DWORD dwDisableCtfmon;
  8043. HRESULT hr;
  8044. DWORD dwTBFlag = 0;
  8045. ITfLangBarMgr *pLangBar = NULL;
  8046. g_dwToolBar = 0;
  8047. //
  8048. // Load LangBar manager and get the current status.
  8049. //
  8050. hr = CoCreateInstance(&CLSID_TF_LangBarMgr,
  8051. NULL,
  8052. CLSCTX_INPROC_SERVER,
  8053. &IID_ITfLangBarMgr,
  8054. (LPVOID *) &pLangBar);
  8055. if (SUCCEEDED(hr))
  8056. pLangBar->lpVtbl->GetShowFloatingStatus(pLangBar, &dwTBFlag);
  8057. if (pLangBar)
  8058. pLangBar->lpVtbl->Release(pLangBar);
  8059. if (IsDlgButtonChecked(hwnd, IDC_TB_SHOWLANGBAR))
  8060. {
  8061. if (dwTBFlag & TF_SFT_HIDDEN)
  8062. {
  8063. g_dwToolBar |= TF_SFT_SHOWNORMAL;
  8064. }
  8065. else
  8066. {
  8067. if (dwTBFlag & TF_SFT_SHOWNORMAL)
  8068. g_dwToolBar |= TF_SFT_SHOWNORMAL;
  8069. else if (dwTBFlag & TF_SFT_DOCK)
  8070. g_dwToolBar |= TF_SFT_DOCK;
  8071. else if (dwTBFlag & TF_SFT_MINIMIZED)
  8072. g_dwToolBar |= TF_SFT_MINIMIZED;
  8073. else if (dwTBFlag & TF_SFT_DESKBAND)
  8074. g_dwToolBar |= TF_SFT_DESKBAND;
  8075. }
  8076. }
  8077. else
  8078. {
  8079. g_dwToolBar |= TF_SFT_HIDDEN;
  8080. }
  8081. //
  8082. // Get the extra icons
  8083. //
  8084. if (IsDlgButtonChecked(hwnd, IDC_TB_EXTRAICON))
  8085. g_dwToolBar |= TF_SFT_EXTRAICONSONMINIMIZED;
  8086. else
  8087. g_dwToolBar |= TF_SFT_NOEXTRAICONSONMINIMIZED;
  8088. //
  8089. // Get the transparency setting
  8090. //
  8091. if (IsDlgButtonChecked(hwnd, IDC_TB_HIGHTRANS))
  8092. g_dwToolBar |= TF_SFT_LOWTRANSPARENCY;
  8093. else
  8094. g_dwToolBar |= TF_SFT_NOTRANSPARENCY;
  8095. //
  8096. // Get the label setting
  8097. //
  8098. if (IsDlgButtonChecked(hwnd, IDC_TB_TEXTLABELS))
  8099. g_dwToolBar |= TF_SFT_LABELS;
  8100. else
  8101. g_dwToolBar |= TF_SFT_NOLABELS;
  8102. //
  8103. // Update toolbar setting on the Apply button.
  8104. //
  8105. UpdateToolBarSetting();
  8106. }
  8107. ////////////////////////////////////////////////////////////////////////////
  8108. //
  8109. // ToolBarSettingDlg
  8110. //
  8111. // This is the dialog proc for the ToolBar Setting Dlg.
  8112. //
  8113. ////////////////////////////////////////////////////////////////////////////
  8114. INT_PTR CALLBACK ToolBarSettingDlg(
  8115. HWND hwnd,
  8116. UINT uMsg,
  8117. WPARAM wParam,
  8118. LPARAM lParam)
  8119. {
  8120. switch (uMsg)
  8121. {
  8122. case ( WM_INITDIALOG ) :
  8123. {
  8124. ToolBarSettingInit(hwnd);
  8125. break;
  8126. }
  8127. case ( WM_HELP ) :
  8128. {
  8129. WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
  8130. c_szHelpFile,
  8131. HELP_WM_HELP,
  8132. (DWORD_PTR)(LPTSTR)aToolbarSettingsHelpIds );
  8133. break;
  8134. }
  8135. case ( WM_CONTEXTMENU ) : // right mouse click
  8136. {
  8137. WinHelp( (HWND)wParam,
  8138. c_szHelpFile,
  8139. HELP_CONTEXTMENU,
  8140. (DWORD_PTR)(LPTSTR)aToolbarSettingsHelpIds );
  8141. break;
  8142. }
  8143. case ( WM_DESTROY ) :
  8144. {
  8145. break;
  8146. }
  8147. case ( WM_COMMAND ) :
  8148. {
  8149. switch (LOWORD(wParam))
  8150. {
  8151. case ( IDOK ) :
  8152. {
  8153. ToolBarSettingOK(hwnd);
  8154. // fall thru...
  8155. }
  8156. case ( IDCANCEL ) :
  8157. {
  8158. EndDialog(hwnd, (wParam == IDOK) ? 1 : 0);
  8159. break;
  8160. }
  8161. case ( IDC_TB_SHOWLANGBAR ) :
  8162. {
  8163. BOOL bShowLangBar;
  8164. bShowLangBar = IsDlgButtonChecked(hwnd, IDC_TB_SHOWLANGBAR);
  8165. EnableWindow(GetDlgItem(hwnd, IDC_TB_EXTRAICON), bShowLangBar);
  8166. EnableWindow(GetDlgItem(hwnd, IDC_TB_HIGHTRANS), bShowLangBar);
  8167. EnableWindow(GetDlgItem(hwnd, IDC_TB_TEXTLABELS), bShowLangBar);
  8168. }
  8169. default :
  8170. {
  8171. return (FALSE);
  8172. }
  8173. }
  8174. break;
  8175. }
  8176. default :
  8177. {
  8178. return (FALSE);
  8179. }
  8180. }
  8181. return (TRUE);
  8182. }
  8183. ////////////////////////////////////////////////////////////////////////////
  8184. //
  8185. // Locale_TranslateHotKey
  8186. //
  8187. // Translates hotkey modifiers and values into key names.
  8188. //
  8189. ////////////////////////////////////////////////////////////////////////////
  8190. void Locale_TranslateHotKey(
  8191. LPTSTR lpString,
  8192. UINT cchString,
  8193. UINT uVKey,
  8194. UINT uModifiers)
  8195. {
  8196. UINT ctr;
  8197. TCHAR szBuffer[DESC_MAX];
  8198. BOOL bMod = FALSE;
  8199. lpString[0] = 0;
  8200. if (uModifiers & MOD_CONTROL)
  8201. {
  8202. CicLoadString(hInstance, IDS_KBD_MOD_CONTROL, szBuffer, ARRAYSIZE(szBuffer));
  8203. StringCchCat(lpString, cchString, szBuffer);
  8204. bMod = TRUE;
  8205. }
  8206. if (uModifiers & MOD_ALT)
  8207. {
  8208. CicLoadString(hInstance, IDS_KBD_MOD_LEFT_ALT, szBuffer, ARRAYSIZE(szBuffer));
  8209. StringCchCat(lpString, cchString, szBuffer);
  8210. bMod = TRUE;
  8211. }
  8212. if (uModifiers & MOD_SHIFT)
  8213. {
  8214. CicLoadString(hInstance, IDS_KBD_MOD_SHIFT, szBuffer, ARRAYSIZE(szBuffer));
  8215. StringCchCat(lpString, cchString, szBuffer);
  8216. bMod = TRUE;
  8217. }
  8218. if (uVKey == 0)
  8219. {
  8220. if (!bMod)
  8221. {
  8222. GetAtomName( g_aVirtKeyDesc[0].atVirtKeyName,
  8223. szBuffer,
  8224. sizeof(szBuffer) / sizeof(TCHAR) );
  8225. StringCchCat(lpString, cchString, szBuffer);
  8226. return;
  8227. }
  8228. else
  8229. {
  8230. //
  8231. // Only modifiers, remove the "+" at the end.
  8232. //
  8233. lpString[lstrlen(lpString) - 1] = 0;
  8234. return;
  8235. }
  8236. }
  8237. for (ctr = 0; (ctr < sizeof(g_aVirtKeyDesc) / sizeof(VIRTKEYDESC)); ctr++)
  8238. {
  8239. if (g_aVirtKeyDesc[ctr].uVirtKeyValue == uVKey)
  8240. {
  8241. GetAtomName( g_aVirtKeyDesc[ctr].atVirtKeyName,
  8242. szBuffer,
  8243. sizeof(szBuffer) / sizeof(TCHAR) );
  8244. StringCchCat(lpString, cchString, szBuffer);
  8245. return;
  8246. }
  8247. }
  8248. GetAtomName( g_aVirtKeyDesc[0].atVirtKeyName,
  8249. szBuffer,
  8250. sizeof(szBuffer) / sizeof(TCHAR) );
  8251. StringCchCat(lpString, cchString, szBuffer);
  8252. }
  8253. ////////////////////////////////////////////////////////////////////////////
  8254. //
  8255. // Locale_HotKeyDrawItem
  8256. //
  8257. // Draws the hotkey list box.
  8258. //
  8259. ////////////////////////////////////////////////////////////////////////////
  8260. void Locale_HotKeyDrawItem(
  8261. HWND hWnd,
  8262. LPDRAWITEMSTRUCT lpDis)
  8263. {
  8264. LPHOTKEYINFO pHotKeyNode;
  8265. COLORREF crBk, crTxt;
  8266. UINT uStrLen, uAlign;
  8267. TCHAR szString[DESC_MAX];
  8268. TCHAR szHotKey[DESC_MAX];
  8269. SIZE Size;
  8270. UINT iMaxChars;
  8271. int iMaxWidth;
  8272. if (!ListBox_GetCount(lpDis->hwndItem))
  8273. {
  8274. return;
  8275. }
  8276. pHotKeyNode = (LPHOTKEYINFO)lpDis->itemData;
  8277. crBk = SetBkColor( lpDis->hDC,
  8278. (lpDis->itemState & ODS_SELECTED)
  8279. ? GetSysColor(COLOR_HIGHLIGHT)
  8280. : GetSysColor(COLOR_WINDOW) );
  8281. crTxt = SetTextColor( lpDis->hDC,
  8282. (lpDis->itemState & ODS_SELECTED)
  8283. ? GetSysColor(COLOR_HIGHLIGHTTEXT)
  8284. : GetSysColor(COLOR_WINDOWTEXT) );
  8285. if (g_bMESystem && (pHotKeyNode->dwHotKeyID == HOTKEY_SWITCH_LANG))
  8286. Locale_TranslateHotKey( szHotKey,
  8287. ARRAYSIZE(szHotKey),
  8288. 0,
  8289. pHotKeyNode->uModifiers );
  8290. else
  8291. Locale_TranslateHotKey( szHotKey,
  8292. ARRAYSIZE(szHotKey),
  8293. pHotKeyNode->uVKey,
  8294. pHotKeyNode->uModifiers );
  8295. GetTextExtentExPoint( lpDis->hDC,
  8296. szHotKey,
  8297. lstrlen(szHotKey),
  8298. 0,
  8299. NULL,
  8300. NULL ,
  8301. &Size );
  8302. iMaxWidth = lpDis->rcItem.right - lpDis->rcItem.left - Size.cx - LIST_MARGIN * 8;
  8303. uStrLen = GetAtomName( pHotKeyNode->atmHotKeyName,
  8304. szString,
  8305. sizeof(szString) / sizeof(TCHAR) );
  8306. GetTextExtentExPoint( lpDis->hDC,
  8307. szString,
  8308. uStrLen,
  8309. iMaxWidth,
  8310. &iMaxChars,
  8311. NULL ,
  8312. &Size );
  8313. if (uStrLen > iMaxChars)
  8314. {
  8315. szString[iMaxChars-3] = TEXT('.');
  8316. szString[iMaxChars-2] = TEXT('.');
  8317. szString[iMaxChars-1] = TEXT('.');
  8318. szString[iMaxChars] = 0;
  8319. }
  8320. ExtTextOut( lpDis->hDC,
  8321. lpDis->rcItem.left + LIST_MARGIN,
  8322. lpDis->rcItem.top + (g_cyListItem - g_cyText) / 2,
  8323. ETO_OPAQUE,
  8324. &lpDis->rcItem,
  8325. szString,
  8326. iMaxChars,
  8327. NULL );
  8328. uAlign = GetTextAlign(lpDis->hDC);
  8329. SetTextAlign(lpDis->hDC, TA_RIGHT);
  8330. ExtTextOut( lpDis->hDC,
  8331. lpDis->rcItem.right - LIST_MARGIN,
  8332. lpDis->rcItem.top + (g_cyListItem - g_cyText) / 2,
  8333. 0,
  8334. NULL,
  8335. szHotKey,
  8336. lstrlen(szHotKey),
  8337. NULL );
  8338. SetTextAlign(lpDis->hDC, uAlign);
  8339. SetBkColor(lpDis->hDC, crBk);
  8340. SetTextColor(lpDis->hDC, crTxt);
  8341. if (lpDis->itemState & ODS_FOCUS)
  8342. {
  8343. DrawFocusRect(lpDis->hDC, &lpDis->rcItem);
  8344. }
  8345. }
  8346. ////////////////////////////////////////////////////////////////////////////
  8347. //
  8348. // Locale_DrawItem
  8349. //
  8350. // Processing for a WM_DRAWITEM message.
  8351. //
  8352. ////////////////////////////////////////////////////////////////////////////
  8353. BOOL Locale_DrawItem(
  8354. HWND hwnd,
  8355. LPDRAWITEMSTRUCT lpdi)
  8356. {
  8357. switch (lpdi->CtlID)
  8358. {
  8359. case ( IDC_KBDL_HOTKEY_LIST ) :
  8360. {
  8361. Locale_HotKeyDrawItem(hwnd, lpdi);
  8362. break;
  8363. }
  8364. default :
  8365. {
  8366. return (FALSE);
  8367. }
  8368. }
  8369. return (TRUE);
  8370. }
  8371. ////////////////////////////////////////////////////////////////////////////
  8372. //
  8373. // Locale_MeasureItem
  8374. //
  8375. // Processing for a WM_MEASUREITEM message.
  8376. //
  8377. ////////////////////////////////////////////////////////////////////////////
  8378. void Locale_MeasureItem(
  8379. HWND hwnd,
  8380. LPMEASUREITEMSTRUCT lpmi)
  8381. {
  8382. HFONT hfont;
  8383. HDC hdc;
  8384. TEXTMETRIC tm;
  8385. switch (lpmi->CtlID)
  8386. {
  8387. case ( IDC_KBDL_HOTKEY_LIST ) :
  8388. {
  8389. hfont = (HFONT) SendMessage(hwnd, WM_GETFONT, 0, 0);
  8390. hdc = GetDC(NULL);
  8391. hfont = SelectObject(hdc, hfont);
  8392. GetTextMetrics(hdc, &tm);
  8393. SelectObject(hdc, hfont);
  8394. ReleaseDC(NULL, hdc);
  8395. g_cyText = tm.tmHeight;
  8396. lpmi->itemHeight = g_cyListItem =
  8397. MAX(g_cyText, GetSystemMetrics(SM_CYSMICON)) + 2 * LIST_MARGIN;
  8398. break;
  8399. }
  8400. }
  8401. }
  8402. ////////////////////////////////////////////////////////////////////////////
  8403. //
  8404. // Locale_CommandChangeHotKey
  8405. //
  8406. // Brings up change hotkey dialog box.
  8407. //
  8408. ////////////////////////////////////////////////////////////////////////////
  8409. void Locale_CommandChangeHotKey(
  8410. HWND hwnd)
  8411. {
  8412. HWND hwndHotkey = GetDlgItem(hwnd, IDC_KBDL_HOTKEY_LIST);
  8413. LPHOTKEYINFO pHotKeyNode;
  8414. int iIndex;
  8415. INITINFO InitInfo;
  8416. iIndex = ListBox_GetCurSel(hwndHotkey);
  8417. pHotKeyNode = (LPHOTKEYINFO)ListBox_GetItemData(hwndHotkey, iIndex);
  8418. InitInfo.hwndMain = hwnd;
  8419. InitInfo.pHotKeyNode = pHotKeyNode;
  8420. if (pHotKeyNode->dwHotKeyID == HOTKEY_SWITCH_LANG)
  8421. {
  8422. if (g_iThaiLayout)
  8423. DialogBoxParam(GetCicResInstance(hInstance, DLG_KEYBOARD_HOTKEY_INPUT_LOCALE_THAI),
  8424. MAKEINTRESOURCE(DLG_KEYBOARD_HOTKEY_INPUT_LOCALE_THAI),
  8425. hwnd,
  8426. KbdLocaleChangeThaiInputLocaleHotkey,
  8427. (LPARAM)&InitInfo);
  8428. else if (g_bMESystem)
  8429. DialogBoxParam(GetCicResInstance(hInstance, DLG_KEYBOARD_HOTKEY_INPUT_LOCALE_ME),
  8430. MAKEINTRESOURCE(DLG_KEYBOARD_HOTKEY_INPUT_LOCALE_ME),
  8431. hwnd,
  8432. KbdLocaleChangeMEInputLocaleHotkey,
  8433. (LPARAM)&InitInfo);
  8434. else
  8435. DialogBoxParam(GetCicResInstance(hInstance, DLG_KEYBOARD_HOTKEY_INPUT_LOCALE),
  8436. MAKEINTRESOURCE(DLG_KEYBOARD_HOTKEY_INPUT_LOCALE),
  8437. hwnd,
  8438. KbdLocaleChangeInputLocaleHotkey,
  8439. (LPARAM)&InitInfo);
  8440. }
  8441. else
  8442. DialogBoxParam(GetCicResInstance(hInstance, DLG_KEYBOARD_HOTKEY_KEYBOARD_LAYOUT),
  8443. MAKEINTRESOURCE(DLG_KEYBOARD_HOTKEY_KEYBOARD_LAYOUT),
  8444. hwnd,
  8445. KbdLocaleChangeKeyboardLayoutHotkey,
  8446. (LPARAM)&InitInfo);
  8447. }
  8448. ////////////////////////////////////////////////////////////////////////////
  8449. //
  8450. // KbdLocaleHotKeyDlg
  8451. //
  8452. // This is the dialog proc for the Input Locales HotKey Setting Dlg.
  8453. //
  8454. ////////////////////////////////////////////////////////////////////////////
  8455. INT_PTR CALLBACK KbdLocaleHotKeyDlg(
  8456. HWND hwnd,
  8457. UINT uMsg,
  8458. WPARAM wParam,
  8459. LPARAM lParam)
  8460. {
  8461. static BOOL bHasIme;
  8462. switch (uMsg)
  8463. {
  8464. case ( WM_INITDIALOG ) :
  8465. {
  8466. UINT ctr;
  8467. TCHAR szItem[DESC_MAX];
  8468. //
  8469. // Get hotkey information.
  8470. //
  8471. bHasIme = FALSE;
  8472. Locale_GetHotkeys(hwnd, &bHasIme);
  8473. if (!ListBox_GetCount(GetDlgItem(hwnd, IDC_KBDL_HOTKEY_LIST)))
  8474. {
  8475. EnableWindow(GetDlgItem(hwnd, IDC_KBDL_CHANGE_HOTKEY), FALSE);
  8476. }
  8477. //
  8478. // Get Attributes information (CapsLock/ShiftLock etc.)
  8479. //
  8480. Locale_GetAttributes(hwnd);
  8481. //
  8482. // Load virtual key description.
  8483. //
  8484. for (ctr = 0; (ctr < sizeof(g_aVirtKeyDesc) / sizeof(VIRTKEYDESC)); ctr++)
  8485. {
  8486. CicLoadString(hInstance,
  8487. g_aVirtKeyDesc[ctr].idVirtKeyName,
  8488. szItem,
  8489. sizeof(szItem) / sizeof(TCHAR) );
  8490. g_aVirtKeyDesc[ctr].atVirtKeyName = AddAtom(szItem);
  8491. }
  8492. break;
  8493. }
  8494. case ( WM_DESTROY ) :
  8495. {
  8496. break;
  8497. }
  8498. case ( WM_HELP ) :
  8499. {
  8500. WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
  8501. c_szHelpFile,
  8502. HELP_WM_HELP,
  8503. (DWORD_PTR)(LPTSTR)aLocaleKeysSettingsHelpIds );
  8504. break;
  8505. }
  8506. case ( WM_CONTEXTMENU ) : // right mouse click
  8507. {
  8508. WinHelp( (HWND)wParam,
  8509. c_szHelpFile,
  8510. HELP_CONTEXTMENU,
  8511. (DWORD_PTR)(LPTSTR)aLocaleKeysSettingsHelpIds );
  8512. break;
  8513. }
  8514. case ( WM_MEASUREITEM ) :
  8515. {
  8516. Locale_MeasureItem(hwnd, (LPMEASUREITEMSTRUCT)lParam);
  8517. break;
  8518. }
  8519. case ( WM_DRAWITEM ) :
  8520. {
  8521. return (Locale_DrawItem(hwnd, (LPDRAWITEMSTRUCT)lParam));
  8522. }
  8523. case ( WM_COMMAND ) :
  8524. {
  8525. switch (LOWORD(wParam))
  8526. {
  8527. case ( IDC_KBDL_CAPSLOCK ) :
  8528. case ( IDC_KBDL_SHIFTLOCK ) :
  8529. {
  8530. break;
  8531. }
  8532. case ( IDC_KBDL_HOTKEY_LIST ):
  8533. {
  8534. if (HIWORD(wParam) == LBN_DBLCLK)
  8535. {
  8536. //
  8537. // User double clicked on a hotkey. Invoke the
  8538. // change hotkey dialog.
  8539. //
  8540. Locale_CommandChangeHotKey(hwnd);
  8541. }
  8542. break;
  8543. }
  8544. case ( IDC_KBDL_CHANGE_HOTKEY ) :
  8545. {
  8546. Locale_CommandChangeHotKey(hwnd);
  8547. break;
  8548. }
  8549. case ( IDOK ) :
  8550. {
  8551. DWORD dwAttributes = 0;
  8552. HKEY hkeyLayouts;
  8553. if (IsDlgButtonChecked(hwnd, IDC_KBDL_SHIFTLOCK))
  8554. dwAttributes |= KLF_SHIFTLOCK;
  8555. else
  8556. dwAttributes &= ~KLF_SHIFTLOCK;
  8557. if (dwAttributes != g_dwAttributes)
  8558. {
  8559. DWORD cb;
  8560. HKEY hkey;
  8561. if (RegOpenKey(HKEY_CURRENT_USER, c_szKbdLayouts, &hkey) == ERROR_SUCCESS)
  8562. {
  8563. cb = sizeof(DWORD);
  8564. RegSetValueEx(hkey,
  8565. c_szAttributes,
  8566. 0,
  8567. REG_DWORD,
  8568. (LPBYTE)&dwAttributes,
  8569. sizeof(DWORD) );
  8570. RegCloseKey(hkey);
  8571. }
  8572. ActivateKeyboardLayout(GetKeyboardLayout(0), KLF_RESET | dwAttributes);
  8573. }
  8574. if (g_dwChanges & CHANGE_SWITCH)
  8575. {
  8576. UINT nLangs;
  8577. HKL *pLangs = NULL;
  8578. BOOL bDirectSwitch = FALSE;
  8579. TV_ITEM tvItem;
  8580. HTREEITEM hItem;
  8581. HTREEITEM hLangItem;
  8582. HTREEITEM hGroupItem;
  8583. LPLANGNODE pLangNode;
  8584. HWND hwndTV = g_hwndTV;
  8585. Locale_SetLanguageHotkey();
  8586. //
  8587. // Set Imm hotkeys.
  8588. //
  8589. // Get the list of the currently active keyboard layouts from
  8590. // the system. We will possibly need to sync up all IMEs with new
  8591. // hotkeys.
  8592. //
  8593. nLangs = GetKeyboardLayoutList(0, NULL);
  8594. if (nLangs != 0)
  8595. {
  8596. pLangs = (HKL *)LocalAlloc(LPTR, sizeof(DWORD_PTR) * nLangs);
  8597. if (!pLangs)
  8598. return (FALSE);
  8599. GetKeyboardLayoutList(nLangs, (HKL *)pLangs);
  8600. }
  8601. tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
  8602. //
  8603. // Try to find either a matching hkl or empty spot in the array
  8604. // for each of the hkls in the locale list.
  8605. //
  8606. for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ;
  8607. hLangItem != NULL ;
  8608. hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem)
  8609. )
  8610. {
  8611. for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem);
  8612. hGroupItem != NULL;
  8613. hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem))
  8614. {
  8615. for (hItem = TreeView_GetChild(hwndTV, hGroupItem);
  8616. hItem != NULL;
  8617. hItem = TreeView_GetNextSibling(hwndTV, hItem))
  8618. {
  8619. LPTVITEMNODE pTVItemNode;
  8620. tvItem.hItem = hItem;
  8621. if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
  8622. {
  8623. pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
  8624. pLangNode = (LPLANGNODE)pTVItemNode->lParam;
  8625. }
  8626. else
  8627. break;
  8628. if (pLangNode == NULL &&
  8629. (pTVItemNode->uInputType & INPUT_TYPE_KBD) &&
  8630. pTVItemNode->hklSub)
  8631. {
  8632. if (tvItem.hItem = FindTVLangItem(pTVItemNode->dwLangID, NULL))
  8633. {
  8634. if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam)
  8635. {
  8636. pTVItemNode = (LPTVITEMNODE) tvItem.lParam;
  8637. pLangNode = (LPLANGNODE)pTVItemNode->lParam;
  8638. }
  8639. }
  8640. }
  8641. if (pLangNode == NULL)
  8642. continue;
  8643. //
  8644. // Set Imm hotkeys.
  8645. //
  8646. Locale_SetImmHotkey(hwnd, pLangNode, nLangs, pLangs, &bDirectSwitch);
  8647. }
  8648. }
  8649. }
  8650. if (bDirectSwitch)
  8651. g_dwChanges |= CHANGE_DIRECTSWITCH;
  8652. if (bHasIme)
  8653. {
  8654. Locale_SetImmCHxHotkey(hwnd, nLangs, pLangs);
  8655. }
  8656. //
  8657. // Free any allocated memory.
  8658. //
  8659. if (pLangs != NULL)
  8660. {
  8661. LocalFree((HANDLE)pLangs);
  8662. }
  8663. g_dwChanges &= ~CHANGE_SWITCH;
  8664. }
  8665. EndDialog(hwnd, 1);
  8666. break;
  8667. }
  8668. case ( IDCANCEL ) :
  8669. {
  8670. EndDialog(hwnd, 0);
  8671. break;
  8672. }
  8673. default :
  8674. {
  8675. return (FALSE);
  8676. }
  8677. }
  8678. break;
  8679. }
  8680. default :
  8681. {
  8682. return (FALSE);
  8683. }
  8684. }
  8685. return (TRUE);
  8686. }
  8687. ////////////////////////////////////////////////////////////////////////////
  8688. //
  8689. // Locale_VirtKeyList
  8690. //
  8691. // Initializes the virtual key combo box and sets the current selection.
  8692. //
  8693. ////////////////////////////////////////////////////////////////////////////
  8694. void Locale_VirtKeyList(
  8695. HWND hwnd,
  8696. UINT uVKey,
  8697. BOOL bDirectSwitch)
  8698. {
  8699. int ctr, iStart, iEnd, iIndex;
  8700. UINT iSel = 0;
  8701. TCHAR szString[DESC_MAX];
  8702. HWND hwndKey = GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO);
  8703. //
  8704. // Look for hot keys for direct switch.
  8705. //
  8706. for (ctr = sizeof(g_aVirtKeyDesc) / sizeof(VIRTKEYDESC) - 1;
  8707. ctr >= 0;
  8708. ctr--)
  8709. {
  8710. if (g_aVirtKeyDesc[ctr].idVirtKeyName == IDS_VK_NONE1)
  8711. {
  8712. //
  8713. // Found it. Remove "(None)" from hwndKey list box.
  8714. //
  8715. ctr++;
  8716. break;
  8717. }
  8718. }
  8719. if (ctr < 0) return;
  8720. iStart = bDirectSwitch ? ctr : 0;
  8721. iEnd = bDirectSwitch ? sizeof(g_aVirtKeyDesc) / sizeof(VIRTKEYDESC) : ctr;
  8722. ComboBox_ResetContent(hwndKey);
  8723. for (ctr = iStart; ctr < iEnd; ctr++)
  8724. {
  8725. GetAtomName( g_aVirtKeyDesc[ctr].atVirtKeyName,
  8726. szString,
  8727. sizeof(szString) / sizeof(TCHAR) );
  8728. iIndex = ComboBox_InsertString(hwndKey, -1, szString);
  8729. ComboBox_SetItemData(hwndKey, iIndex, g_aVirtKeyDesc[ctr].uVirtKeyValue);
  8730. if (g_aVirtKeyDesc[ctr].uVirtKeyValue == uVKey)
  8731. {
  8732. iSel = iIndex;
  8733. }
  8734. }
  8735. ComboBox_SetCurSel(hwndKey, iSel);
  8736. }
  8737. ////////////////////////////////////////////////////////////////////////////
  8738. //
  8739. // Locale_ChangeHotKeyDlgInit
  8740. //
  8741. // Initializes the change hotkey dialog box.
  8742. //
  8743. ////////////////////////////////////////////////////////////////////////////
  8744. void Locale_ChangeHotKeyDlgInit(
  8745. HWND hwnd,
  8746. LPARAM lParam)
  8747. {
  8748. TCHAR szHotKeyName[DESC_MAX];
  8749. LPHOTKEYINFO pHotKeyNode = ((LPINITINFO)lParam)->pHotKeyNode;
  8750. BOOL bCtrl = TRUE;
  8751. BOOL bAlt = TRUE;
  8752. BOOL bGrave = TRUE;
  8753. GetAtomName(pHotKeyNode->atmHotKeyName, szHotKeyName, ARRAYSIZE(szHotKeyName));
  8754. SetDlgItemText(hwnd, IDC_KBDLH_LAYOUT_TEXT, szHotKeyName);
  8755. //
  8756. // Set the language switch hotkey
  8757. //
  8758. if (pHotKeyNode->uModifiers & MOD_CONTROL)
  8759. {
  8760. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, TRUE);
  8761. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, FALSE);
  8762. bCtrl = FALSE;
  8763. }
  8764. if (pHotKeyNode->uModifiers & MOD_ALT)
  8765. {
  8766. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, TRUE);
  8767. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, FALSE);
  8768. bAlt = FALSE;
  8769. }
  8770. if (GetDlgItem(hwnd, IDC_KBDLH_GRAVE) && (pHotKeyNode->uVKey == CHAR_GRAVE))
  8771. {
  8772. CheckDlgButton(hwnd, IDC_KBDLH_GRAVE, TRUE);
  8773. bGrave = FALSE;
  8774. }
  8775. if (bCtrl && bAlt && bGrave)
  8776. {
  8777. CheckDlgButton(hwnd, IDC_KBDLH_LANGHOTKEY, FALSE);
  8778. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), FALSE);
  8779. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), FALSE);
  8780. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_GRAVE), FALSE);
  8781. ComboBox_SetCurSel(GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO), 0);
  8782. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO), FALSE);
  8783. }
  8784. else
  8785. {
  8786. CheckDlgButton(hwnd, IDC_KBDLH_LANGHOTKEY, TRUE);
  8787. }
  8788. //
  8789. // Set the layout switch hotkey
  8790. //
  8791. CheckDlgButton(hwnd, IDC_KBDLH_LAYOUTHOTKEY, TRUE);
  8792. if (pHotKeyNode->uLayoutHotKey & MOD_CONTROL)
  8793. {
  8794. CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, TRUE);
  8795. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, FALSE);
  8796. }
  8797. else if (pHotKeyNode->uLayoutHotKey & MOD_ALT)
  8798. {
  8799. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, TRUE);
  8800. CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, FALSE);
  8801. }
  8802. else if (g_bMESystem && pHotKeyNode->uVKey == CHAR_GRAVE)
  8803. {
  8804. CheckDlgButton(hwnd, IDC_KBDLH_GRAVE, TRUE);
  8805. }
  8806. else
  8807. {
  8808. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), FALSE);
  8809. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), FALSE);
  8810. CheckDlgButton(hwnd, IDC_KBDLH_LAYOUTHOTKEY, FALSE);
  8811. if (g_bMESystem)
  8812. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_GRAVE), FALSE);
  8813. }
  8814. //
  8815. // There is no ctfmon.exe process during the setup, so disable layout
  8816. // hotkey settings.
  8817. //
  8818. if (g_bSetupCase)
  8819. {
  8820. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_LAYOUTHOTKEY), FALSE);
  8821. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), FALSE);
  8822. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), FALSE);
  8823. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_SHIFT2), FALSE);
  8824. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_PLUS2), FALSE);
  8825. if (g_bMESystem)
  8826. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_GRAVE), FALSE);
  8827. #if 0
  8828. ShowWindow(GetDlgItem(hwnd, IDC_KBDLH_LAYOUTHOTKEY), SW_HIDE);
  8829. ShowWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), SW_HIDE);
  8830. ShowWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), SW_HIDE);
  8831. ShowWindow(GetDlgItem(hwnd, IDC_KBDLH_SHIFT2), SW_HIDE);
  8832. ShowWindow(GetDlgItem(hwnd, IDC_KBDLH_PLUS2), SW_HIDE);
  8833. if (g_bMESystem)
  8834. ShowWindow(GetDlgItem(hwnd, IDC_KBDLH_GRAVE), SW_HIDE);
  8835. #endif
  8836. }
  8837. if (IS_DIRECT_SWITCH_HOTKEY(pHotKeyNode->dwHotKeyID))
  8838. {
  8839. Locale_VirtKeyList(hwnd, pHotKeyNode->uVKey, TRUE);
  8840. }
  8841. else
  8842. {
  8843. Locale_VirtKeyList(hwnd, pHotKeyNode->uVKey, FALSE);
  8844. }
  8845. SetProp(hwnd, szPropHwnd, (HANDLE)((LPINITINFO)lParam)->hwndMain);
  8846. SetProp(hwnd, szPropIdx, (HANDLE)pHotKeyNode);
  8847. }
  8848. ////////////////////////////////////////////////////////////////////////////
  8849. //
  8850. // Locale_ChangeHotKeyCommandOK
  8851. //
  8852. // Records hotkey changes made in change hotkey dialog box.
  8853. // Warns if duplicate hotkeys are selected.
  8854. //
  8855. ////////////////////////////////////////////////////////////////////////////
  8856. BOOL Locale_ChangeHotKeyCommandOK(
  8857. HWND hwnd)
  8858. {
  8859. LPHOTKEYINFO pHotKeyNode, pHotKeyTemp;
  8860. UINT iIndex;
  8861. HWND hwndHotkey, hwndMain, hwndKey;
  8862. UINT uOldVKey, uOldModifiers, uOldLayoutHotKey;
  8863. int ctr;
  8864. int iNumMods = 0;
  8865. int DialogType;
  8866. pHotKeyNode = GetProp(hwnd, szPropIdx);
  8867. hwndMain = GetProp(hwnd, szPropHwnd);
  8868. hwndHotkey = GetDlgItem(hwndMain, IDC_KBDL_HOTKEY_LIST);
  8869. hwndKey = GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO);
  8870. uOldVKey = pHotKeyNode->uVKey;
  8871. uOldModifiers = pHotKeyNode->uModifiers;
  8872. uOldLayoutHotKey = pHotKeyNode->uLayoutHotKey;
  8873. if (pHotKeyNode->dwHotKeyID == HOTKEY_SWITCH_LANG)
  8874. {
  8875. DialogType = DIALOG_SWITCH_INPUT_LOCALES;
  8876. }
  8877. else if (GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO) &&
  8878. (GetWindowLong( GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO),
  8879. GWL_STYLE) & BS_RADIOBUTTON))
  8880. {
  8881. DialogType = DIALOG_SWITCH_KEYBOARD_LAYOUT;
  8882. }
  8883. else
  8884. {
  8885. DialogType = DIALOG_SWITCH_IME;
  8886. }
  8887. pHotKeyNode->uModifiers &= ~(MOD_CONTROL | MOD_ALT | MOD_SHIFT);
  8888. pHotKeyNode->uVKey = 0;
  8889. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
  8890. {
  8891. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_CTRL))
  8892. {
  8893. pHotKeyNode->uModifiers |= MOD_CONTROL;
  8894. iNumMods++;
  8895. }
  8896. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_L_ALT))
  8897. {
  8898. pHotKeyNode->uModifiers |= MOD_ALT;
  8899. iNumMods++;
  8900. }
  8901. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_GRAVE))
  8902. {
  8903. //
  8904. // Assign Grave key.
  8905. //
  8906. pHotKeyNode->uVKey = CHAR_GRAVE;
  8907. }
  8908. else
  8909. {
  8910. //
  8911. // Shift key is mandatory.
  8912. //
  8913. pHotKeyNode->uModifiers |= MOD_SHIFT;
  8914. iNumMods++;
  8915. if ((iIndex = ComboBox_GetCurSel(hwndKey)) == CB_ERR)
  8916. {
  8917. pHotKeyNode->uVKey = 0;
  8918. }
  8919. else
  8920. {
  8921. pHotKeyNode->uVKey = (UINT)ComboBox_GetItemData(hwndKey, iIndex);
  8922. }
  8923. }
  8924. }
  8925. //
  8926. // Set the layout switch hotkey
  8927. //
  8928. pHotKeyNode->uLayoutHotKey = 0;
  8929. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
  8930. {
  8931. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_CTRL2))
  8932. {
  8933. pHotKeyNode->uLayoutHotKey |= MOD_CONTROL;
  8934. }
  8935. else if (IsDlgButtonChecked(hwnd, IDC_KBDLH_L_ALT2))
  8936. {
  8937. pHotKeyNode->uLayoutHotKey |= MOD_ALT;
  8938. }
  8939. else if (IsDlgButtonChecked(hwnd, IDC_KBDLH_GRAVE))
  8940. {
  8941. pHotKeyNode->uVKey = CHAR_GRAVE;
  8942. }
  8943. }
  8944. //
  8945. // Key sequence with only one modifier and without a key,
  8946. // or without any modifier is invalid.
  8947. //
  8948. if (((pHotKeyNode->uVKey != 0) && (iNumMods == 0) &&
  8949. (DialogType != DIALOG_SWITCH_INPUT_LOCALES)) ||
  8950. ((pHotKeyNode->uVKey == 0) && (iNumMods != 0) &&
  8951. (DialogType != DIALOG_SWITCH_INPUT_LOCALES)))
  8952. {
  8953. TCHAR szName[DESC_MAX];
  8954. Locale_TranslateHotKey( szName,
  8955. ARRAYSIZE(szName),
  8956. pHotKeyNode->uVKey,
  8957. pHotKeyNode->uModifiers );
  8958. Locale_ErrorMsg(hwnd, IDS_KBD_INVALID_HOTKEY, szName);
  8959. pHotKeyNode->uModifiers = uOldModifiers;
  8960. pHotKeyNode->uVKey = uOldVKey;
  8961. return (FALSE);
  8962. }
  8963. //
  8964. // Do not allow duplicate hot keys.
  8965. //
  8966. for (ctr = 0; ctr < ListBox_GetCount(hwndHotkey); ctr++)
  8967. {
  8968. pHotKeyTemp = (LPHOTKEYINFO)ListBox_GetItemData(hwndHotkey, ctr);
  8969. if ((pHotKeyTemp != pHotKeyNode) &&
  8970. ((pHotKeyNode->uModifiers & (MOD_CONTROL | MOD_ALT | MOD_SHIFT)) ==
  8971. (pHotKeyTemp->uModifiers & (MOD_CONTROL | MOD_ALT | MOD_SHIFT))) &&
  8972. (pHotKeyNode->uVKey == pHotKeyTemp->uVKey) &&
  8973. (iNumMods || pHotKeyNode->uVKey != 0))
  8974. {
  8975. TCHAR szName[DESC_MAX];
  8976. Locale_TranslateHotKey( szName,
  8977. ARRAYSIZE(szName),
  8978. pHotKeyNode->uVKey,
  8979. pHotKeyNode->uModifiers );
  8980. Locale_ErrorMsg(hwnd, IDS_KBD_CONFLICT_HOTKEY, szName);
  8981. pHotKeyNode->uModifiers = uOldModifiers;
  8982. pHotKeyNode->uVKey = uOldVKey;
  8983. return (FALSE);
  8984. }
  8985. }
  8986. InvalidateRect(hwndHotkey, NULL, FALSE);
  8987. if ((uOldVKey != pHotKeyNode->uVKey) ||
  8988. (uOldModifiers != pHotKeyNode->uModifiers) ||
  8989. (uOldLayoutHotKey != pHotKeyNode->uLayoutHotKey))
  8990. {
  8991. g_dwChanges |= CHANGE_SWITCH;
  8992. }
  8993. return (TRUE);
  8994. }
  8995. ////////////////////////////////////////////////////////////////////////////
  8996. //
  8997. // KbdLocaleSimpleHotkey
  8998. //
  8999. // Dlgproc for hotkey on NT4 and Win9x platform
  9000. //
  9001. ////////////////////////////////////////////////////////////////////////////
  9002. INT_PTR CALLBACK KbdLocaleSimpleHotkey(
  9003. HWND hwnd,
  9004. UINT uMsg,
  9005. WPARAM wParam,
  9006. LPARAM lParam)
  9007. {
  9008. switch (uMsg)
  9009. {
  9010. case ( WM_INITDIALOG ) :
  9011. {
  9012. TCHAR szHotKey[10];
  9013. TCHAR szLayoutHotKey[10];
  9014. GetLanguageHotkeyFromRegistry(szHotKey, ARRAYSIZE(szHotKey),
  9015. szLayoutHotKey, ARRAYSIZE(szLayoutHotKey));
  9016. //
  9017. // Set the modifiers.
  9018. //
  9019. if (szHotKey[1] == 0)
  9020. {
  9021. CheckDlgButton(hwnd, IDC_KBDLH_LANGHOTKEY, TRUE);
  9022. switch (szHotKey[0])
  9023. {
  9024. case ( TEXT('1') ) :
  9025. {
  9026. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, TRUE);
  9027. break;
  9028. }
  9029. case ( TEXT('2') ) :
  9030. {
  9031. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, TRUE);
  9032. break;
  9033. }
  9034. default:
  9035. {
  9036. CheckDlgButton(hwnd, IDC_KBDLH_LANGHOTKEY, FALSE);
  9037. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), FALSE);
  9038. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), FALSE);
  9039. }
  9040. }
  9041. }
  9042. else
  9043. {
  9044. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), FALSE);
  9045. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), FALSE);
  9046. }
  9047. if (szLayoutHotKey[1] == 0)
  9048. {
  9049. CheckDlgButton(hwnd, IDC_KBDLH_LAYOUTHOTKEY, TRUE);
  9050. switch (szLayoutHotKey[0])
  9051. {
  9052. case ( TEXT('1') ) :
  9053. {
  9054. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, TRUE);
  9055. break;
  9056. }
  9057. case ( TEXT('2') ) :
  9058. {
  9059. CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, TRUE);
  9060. break;
  9061. }
  9062. default:
  9063. {
  9064. CheckDlgButton(hwnd, IDC_KBDLH_LAYOUTHOTKEY, FALSE);
  9065. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), FALSE);
  9066. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), FALSE);
  9067. }
  9068. }
  9069. }
  9070. else
  9071. {
  9072. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), FALSE);
  9073. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), FALSE);
  9074. }
  9075. }
  9076. case ( WM_HELP ) :
  9077. {
  9078. WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
  9079. c_szHelpFile,
  9080. HELP_WM_HELP,
  9081. (DWORD_PTR)(LPTSTR)aLocaleHotkeyHelpIds );
  9082. break;
  9083. }
  9084. case ( WM_CONTEXTMENU ) : // right mouse click
  9085. {
  9086. WinHelp( (HWND)wParam,
  9087. c_szHelpFile,
  9088. HELP_CONTEXTMENU,
  9089. (DWORD_PTR)(LPTSTR)aLocaleHotkeyHelpIds );
  9090. break;
  9091. }
  9092. case ( WM_COMMAND ) :
  9093. {
  9094. switch (LOWORD(wParam))
  9095. {
  9096. case ( IDOK ) :
  9097. {
  9098. DWORD dwLangHotKey;
  9099. DWORD dwLayoutHotKey;
  9100. HKEY hkeyToggle;
  9101. TCHAR szTemp[10];
  9102. TCHAR szTemp2[10];
  9103. //
  9104. // Language switch hotkey
  9105. //
  9106. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
  9107. {
  9108. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_L_ALT))
  9109. {
  9110. dwLangHotKey = 1;
  9111. }
  9112. else
  9113. {
  9114. dwLangHotKey = 2;
  9115. }
  9116. }
  9117. else
  9118. {
  9119. dwLangHotKey = 3;
  9120. }
  9121. //
  9122. // Layout swtich hotkey
  9123. //
  9124. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
  9125. {
  9126. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_L_ALT2))
  9127. {
  9128. dwLayoutHotKey = 1;
  9129. }
  9130. else
  9131. {
  9132. dwLayoutHotKey = 2;
  9133. }
  9134. }
  9135. else
  9136. {
  9137. dwLayoutHotKey = 3;
  9138. }
  9139. //
  9140. // Get the toggle hotkey as a string so that it can be written
  9141. // into the registry (as data).
  9142. //
  9143. StringCchPrintf(szTemp, ARRAYSIZE(szTemp), TEXT("%d"), dwLangHotKey);
  9144. StringCchPrintf(szTemp2, ARRAYSIZE(szTemp2), TEXT("%d"), dwLayoutHotKey);
  9145. //
  9146. // Create the HKCU\Keyboard Layout\Toggle key.
  9147. //
  9148. if (RegCreateKey(HKEY_CURRENT_USER,
  9149. c_szKbdToggleKey,
  9150. &hkeyToggle ) == ERROR_SUCCESS)
  9151. {
  9152. RegSetValueEx(hkeyToggle,
  9153. g_OSNT4? c_szToggleHotKey : NULL,
  9154. 0,
  9155. REG_SZ,
  9156. (LPBYTE)szTemp,
  9157. (DWORD)(lstrlen(szTemp) + 1) * sizeof(TCHAR) );
  9158. RegSetValueEx(hkeyToggle,
  9159. c_szToggleLang,
  9160. 0,
  9161. REG_SZ,
  9162. (LPBYTE)szTemp,
  9163. (DWORD)(lstrlen(szTemp) + 1) * sizeof(TCHAR) );
  9164. RegSetValueEx(hkeyToggle,
  9165. c_szToggleLayout,
  9166. 0,
  9167. REG_SZ,
  9168. (LPBYTE)szTemp2,
  9169. (DWORD)(lstrlen(szTemp2) + 1) * sizeof(TCHAR) );
  9170. RegCloseKey(hkeyToggle);
  9171. }
  9172. EndDialog(hwnd, 1);
  9173. break;
  9174. }
  9175. case ( IDCANCEL ) :
  9176. {
  9177. EndDialog(hwnd, 0);
  9178. break;
  9179. }
  9180. case ( IDC_KBDLH_LANGHOTKEY ) :
  9181. {
  9182. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
  9183. {
  9184. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
  9185. {
  9186. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_L_ALT2))
  9187. {
  9188. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_CHECKED);
  9189. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED);
  9190. }
  9191. else
  9192. {
  9193. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
  9194. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED);
  9195. }
  9196. }
  9197. else
  9198. {
  9199. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED);
  9200. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
  9201. }
  9202. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), TRUE);
  9203. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), TRUE);
  9204. }
  9205. else
  9206. {
  9207. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
  9208. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED);
  9209. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), FALSE);
  9210. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), FALSE);
  9211. }
  9212. break;
  9213. }
  9214. case ( IDC_KBDLH_LAYOUTHOTKEY ) :
  9215. {
  9216. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
  9217. {
  9218. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
  9219. {
  9220. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_L_ALT))
  9221. {
  9222. CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED);
  9223. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
  9224. }
  9225. else
  9226. {
  9227. CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED);
  9228. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_CHECKED);
  9229. }
  9230. }
  9231. else
  9232. {
  9233. CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED);
  9234. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
  9235. }
  9236. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), TRUE);
  9237. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), TRUE);
  9238. }
  9239. else
  9240. {
  9241. CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED);
  9242. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
  9243. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), FALSE);
  9244. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), FALSE);
  9245. }
  9246. break;
  9247. }
  9248. case ( IDC_KBDLH_CTRL ) :
  9249. {
  9250. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
  9251. {
  9252. CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED);
  9253. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_CHECKED);
  9254. }
  9255. break;
  9256. }
  9257. case ( IDC_KBDLH_L_ALT ) :
  9258. {
  9259. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
  9260. {
  9261. CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED);
  9262. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
  9263. }
  9264. break;
  9265. }
  9266. case ( IDC_KBDLH_CTRL2 ) :
  9267. {
  9268. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
  9269. {
  9270. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
  9271. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED);
  9272. }
  9273. break;
  9274. }
  9275. case ( IDC_KBDLH_L_ALT2 ) :
  9276. {
  9277. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
  9278. {
  9279. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_CHECKED);
  9280. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED);
  9281. }
  9282. break;
  9283. }
  9284. default :
  9285. {
  9286. return (FALSE);
  9287. }
  9288. }
  9289. break;
  9290. }
  9291. default :
  9292. {
  9293. return (FALSE);
  9294. }
  9295. }
  9296. return (TRUE);
  9297. }
  9298. ////////////////////////////////////////////////////////////////////////////
  9299. //
  9300. // KbdLocaleChangeInputLocaleHotkey
  9301. //
  9302. // Dlgproc for changing input locale hotkey dialog box.
  9303. //
  9304. ////////////////////////////////////////////////////////////////////////////
  9305. INT_PTR CALLBACK KbdLocaleChangeInputLocaleHotkey(
  9306. HWND hwnd,
  9307. UINT uMsg,
  9308. WPARAM wParam,
  9309. LPARAM lParam)
  9310. {
  9311. switch (uMsg)
  9312. {
  9313. case ( WM_INITDIALOG ) :
  9314. {
  9315. Locale_ChangeHotKeyDlgInit(hwnd, lParam);
  9316. break;
  9317. }
  9318. case ( WM_HELP ) :
  9319. {
  9320. WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
  9321. c_szHelpFile,
  9322. HELP_WM_HELP,
  9323. (DWORD_PTR)(LPTSTR)aLocaleHotkeyHelpIds );
  9324. break;
  9325. }
  9326. case ( WM_CONTEXTMENU ) : // right mouse click
  9327. {
  9328. WinHelp( (HWND)wParam,
  9329. c_szHelpFile,
  9330. HELP_CONTEXTMENU,
  9331. (DWORD_PTR)(LPTSTR)aLocaleHotkeyHelpIds );
  9332. break;
  9333. }
  9334. case ( WM_DESTROY ) :
  9335. {
  9336. RemoveProp(hwnd, szPropHwnd);
  9337. RemoveProp(hwnd, szPropIdx);
  9338. break;
  9339. }
  9340. case ( WM_COMMAND ) :
  9341. {
  9342. LPHOTKEYINFO pHotKeyNode = GetProp(hwnd, szPropIdx);
  9343. switch (LOWORD(wParam))
  9344. {
  9345. case ( IDOK ) :
  9346. {
  9347. if (Locale_ChangeHotKeyCommandOK(hwnd))
  9348. {
  9349. EndDialog(hwnd, 1);
  9350. }
  9351. break;
  9352. }
  9353. case ( IDCANCEL ) :
  9354. {
  9355. EndDialog(hwnd, 0);
  9356. break;
  9357. }
  9358. case ( IDC_KBDLH_LANGHOTKEY ) :
  9359. {
  9360. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
  9361. {
  9362. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
  9363. {
  9364. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_L_ALT2))
  9365. {
  9366. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_CHECKED);
  9367. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED);
  9368. }
  9369. else
  9370. {
  9371. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
  9372. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED);
  9373. }
  9374. }
  9375. else
  9376. {
  9377. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED);
  9378. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
  9379. }
  9380. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), TRUE);
  9381. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), TRUE);
  9382. }
  9383. else
  9384. {
  9385. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
  9386. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED);
  9387. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), FALSE);
  9388. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), FALSE);
  9389. }
  9390. break;
  9391. }
  9392. case ( IDC_KBDLH_LAYOUTHOTKEY ) :
  9393. {
  9394. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
  9395. {
  9396. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
  9397. {
  9398. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_CTRL))
  9399. {
  9400. CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED);
  9401. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_CHECKED);
  9402. }
  9403. else
  9404. {
  9405. CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED);
  9406. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
  9407. }
  9408. }
  9409. else
  9410. {
  9411. CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED);
  9412. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
  9413. }
  9414. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), TRUE);
  9415. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), TRUE);
  9416. }
  9417. else
  9418. {
  9419. CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED);
  9420. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
  9421. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), FALSE);
  9422. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), FALSE);
  9423. }
  9424. break;
  9425. }
  9426. case ( IDC_KBDLH_CTRL ) :
  9427. {
  9428. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
  9429. {
  9430. CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED);
  9431. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_CHECKED);
  9432. }
  9433. break;
  9434. }
  9435. case ( IDC_KBDLH_L_ALT ) :
  9436. {
  9437. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
  9438. {
  9439. CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED);
  9440. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
  9441. }
  9442. break;
  9443. }
  9444. case ( IDC_KBDLH_CTRL2 ) :
  9445. {
  9446. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
  9447. {
  9448. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
  9449. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED);
  9450. }
  9451. break;
  9452. }
  9453. case ( IDC_KBDLH_L_ALT2 ) :
  9454. {
  9455. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
  9456. {
  9457. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_CHECKED);
  9458. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED);
  9459. }
  9460. break;
  9461. }
  9462. default :
  9463. {
  9464. return (FALSE);
  9465. }
  9466. }
  9467. break;
  9468. }
  9469. default :
  9470. {
  9471. return (FALSE);
  9472. }
  9473. }
  9474. return (TRUE);
  9475. }
  9476. ////////////////////////////////////////////////////////////////////////////
  9477. //
  9478. // KbdLocaleChangeThaiInputLocaleHotkey
  9479. //
  9480. // Dlgproc for changing Thai input locale hotkey dialog box.
  9481. //
  9482. ////////////////////////////////////////////////////////////////////////////
  9483. INT_PTR CALLBACK KbdLocaleChangeThaiInputLocaleHotkey(
  9484. HWND hwnd,
  9485. UINT uMsg,
  9486. WPARAM wParam,
  9487. LPARAM lParam)
  9488. {
  9489. switch (uMsg)
  9490. {
  9491. case ( WM_INITDIALOG ) :
  9492. {
  9493. Locale_ChangeHotKeyDlgInit(hwnd, lParam);
  9494. break;
  9495. }
  9496. case ( WM_DESTROY ) :
  9497. {
  9498. RemoveProp(hwnd, szPropHwnd);
  9499. RemoveProp(hwnd, szPropIdx);
  9500. break;
  9501. }
  9502. case ( WM_HELP ) :
  9503. {
  9504. WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
  9505. c_szHelpFile,
  9506. HELP_WM_HELP,
  9507. (DWORD_PTR)(LPTSTR)aLocaleHotkeyHelpIds );
  9508. break;
  9509. }
  9510. case ( WM_CONTEXTMENU ) :
  9511. {
  9512. WinHelp( (HWND)wParam,
  9513. c_szHelpFile,
  9514. HELP_CONTEXTMENU,
  9515. (DWORD_PTR)(LPTSTR)aLocaleHotkeyHelpIds );
  9516. break;
  9517. }
  9518. case ( WM_DRAWITEM ) :
  9519. {
  9520. if (wParam == IDC_KBDLH_VLINE)
  9521. {
  9522. LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
  9523. RECT rect;
  9524. HPEN hPenHilite, hPenShadow, hPenOriginal;
  9525. GetClientRect(lpdis->hwndItem, &rect);
  9526. hPenHilite = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNHIGHLIGHT));
  9527. hPenShadow = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW));
  9528. hPenOriginal = SelectObject(lpdis->hDC, hPenShadow);
  9529. MoveToEx(lpdis->hDC, rect.right / 2, 0, NULL);
  9530. LineTo(lpdis->hDC, rect.right / 2, rect.bottom);
  9531. SelectObject(lpdis->hDC, hPenHilite);
  9532. MoveToEx(lpdis->hDC, rect.right / 2 + 1, 0, NULL);
  9533. LineTo(lpdis->hDC, rect.right / 2 + 1, rect.bottom);
  9534. SelectObject(lpdis->hDC, hPenOriginal);
  9535. if (hPenShadow)
  9536. {
  9537. DeleteObject(hPenShadow);
  9538. }
  9539. if (hPenHilite)
  9540. {
  9541. DeleteObject(hPenHilite);
  9542. }
  9543. return (TRUE);
  9544. }
  9545. return (FALSE);
  9546. break;
  9547. }
  9548. case ( WM_COMMAND ) :
  9549. {
  9550. LPHOTKEYINFO pHotKeyNode = GetProp(hwnd, szPropIdx);
  9551. switch (LOWORD(wParam))
  9552. {
  9553. case ( IDOK ) :
  9554. {
  9555. if (Locale_ChangeHotKeyCommandOK(hwnd))
  9556. {
  9557. EndDialog(hwnd, 1);
  9558. }
  9559. break;
  9560. }
  9561. case ( IDCANCEL ) :
  9562. {
  9563. EndDialog(hwnd, 0);
  9564. break;
  9565. }
  9566. case ( IDC_KBDLH_LANGHOTKEY ) :
  9567. {
  9568. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
  9569. {
  9570. CheckDlgButton(hwnd, IDC_KBDLH_GRAVE, BST_CHECKED);
  9571. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), TRUE);
  9572. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), TRUE);
  9573. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_GRAVE), TRUE);
  9574. }
  9575. else
  9576. {
  9577. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
  9578. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED);
  9579. CheckDlgButton(hwnd, IDC_KBDLH_GRAVE, BST_UNCHECKED);
  9580. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), FALSE);
  9581. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), FALSE);
  9582. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_GRAVE), FALSE);
  9583. }
  9584. break;
  9585. }
  9586. case ( IDC_KBDLH_LAYOUTHOTKEY ) :
  9587. {
  9588. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
  9589. {
  9590. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
  9591. {
  9592. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_CTRL))
  9593. {
  9594. CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED);
  9595. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_CHECKED);
  9596. }
  9597. else
  9598. {
  9599. CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED);
  9600. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
  9601. }
  9602. }
  9603. else
  9604. {
  9605. CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED);
  9606. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
  9607. }
  9608. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), TRUE);
  9609. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), TRUE);
  9610. }
  9611. else
  9612. {
  9613. CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED);
  9614. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
  9615. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), FALSE);
  9616. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), FALSE);
  9617. }
  9618. break;
  9619. }
  9620. case ( IDC_KBDLH_CTRL ) :
  9621. {
  9622. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
  9623. {
  9624. CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED);
  9625. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_CHECKED);
  9626. }
  9627. break;
  9628. }
  9629. case ( IDC_KBDLH_L_ALT ) :
  9630. {
  9631. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
  9632. {
  9633. CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED);
  9634. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
  9635. }
  9636. break;
  9637. }
  9638. case ( IDC_KBDLH_CTRL2 ) :
  9639. {
  9640. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY) &&
  9641. !IsDlgButtonChecked(hwnd, IDC_KBDLH_GRAVE))
  9642. {
  9643. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
  9644. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED);
  9645. }
  9646. break;
  9647. }
  9648. case ( IDC_KBDLH_L_ALT2 ) :
  9649. {
  9650. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY) &&
  9651. !IsDlgButtonChecked(hwnd, IDC_KBDLH_GRAVE))
  9652. {
  9653. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_CHECKED);
  9654. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED);
  9655. }
  9656. break;
  9657. }
  9658. default :
  9659. {
  9660. return (FALSE);
  9661. }
  9662. }
  9663. break;
  9664. }
  9665. default :
  9666. {
  9667. return (FALSE);
  9668. }
  9669. }
  9670. return (TRUE);
  9671. }
  9672. ////////////////////////////////////////////////////////////////////////////
  9673. //
  9674. // KbdLocaleChangeMEInputLocaleHotkey
  9675. //
  9676. // Dlgproc for changing Thai input locale hotkey dialog box.
  9677. //
  9678. ////////////////////////////////////////////////////////////////////////////
  9679. INT_PTR CALLBACK KbdLocaleChangeMEInputLocaleHotkey(
  9680. HWND hwnd,
  9681. UINT uMsg,
  9682. WPARAM wParam,
  9683. LPARAM lParam)
  9684. {
  9685. switch (uMsg)
  9686. {
  9687. case ( WM_INITDIALOG ) :
  9688. {
  9689. Locale_ChangeHotKeyDlgInit(hwnd, lParam);
  9690. break;
  9691. }
  9692. case ( WM_DESTROY ) :
  9693. {
  9694. RemoveProp(hwnd, szPropHwnd);
  9695. RemoveProp(hwnd, szPropIdx);
  9696. break;
  9697. }
  9698. case ( WM_HELP ) :
  9699. {
  9700. WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
  9701. c_szHelpFile,
  9702. HELP_WM_HELP,
  9703. (DWORD_PTR)(LPTSTR)aLocaleHotkeyHelpIds );
  9704. break;
  9705. }
  9706. case ( WM_CONTEXTMENU ) :
  9707. {
  9708. WinHelp( (HWND)wParam,
  9709. c_szHelpFile,
  9710. HELP_CONTEXTMENU,
  9711. (DWORD_PTR)(LPTSTR)aLocaleHotkeyHelpIds );
  9712. break;
  9713. }
  9714. case ( WM_DRAWITEM ) :
  9715. {
  9716. if (wParam == IDC_KBDLH_VLINE)
  9717. {
  9718. LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
  9719. RECT rect;
  9720. HPEN hPenHilite, hPenShadow, hPenOriginal;
  9721. GetClientRect(lpdis->hwndItem, &rect);
  9722. hPenHilite = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNHIGHLIGHT));
  9723. hPenShadow = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW));
  9724. hPenOriginal = SelectObject(lpdis->hDC, hPenShadow);
  9725. MoveToEx(lpdis->hDC, rect.right / 2, 0, NULL);
  9726. LineTo(lpdis->hDC, rect.right / 2, rect.bottom);
  9727. SelectObject(lpdis->hDC, hPenHilite);
  9728. MoveToEx(lpdis->hDC, rect.right / 2 + 1, 0, NULL);
  9729. LineTo(lpdis->hDC, rect.right / 2 + 1, rect.bottom);
  9730. SelectObject(lpdis->hDC, hPenOriginal);
  9731. if (hPenShadow)
  9732. {
  9733. DeleteObject(hPenShadow);
  9734. }
  9735. if (hPenHilite)
  9736. {
  9737. DeleteObject(hPenHilite);
  9738. }
  9739. return (TRUE);
  9740. }
  9741. return (FALSE);
  9742. break;
  9743. }
  9744. case ( WM_COMMAND ) :
  9745. {
  9746. LPHOTKEYINFO pHotKeyNode = GetProp(hwnd, szPropIdx);
  9747. switch (LOWORD(wParam))
  9748. {
  9749. case ( IDOK ) :
  9750. {
  9751. if (Locale_ChangeHotKeyCommandOK(hwnd))
  9752. {
  9753. EndDialog(hwnd, 1);
  9754. }
  9755. break;
  9756. }
  9757. case ( IDCANCEL ) :
  9758. {
  9759. EndDialog(hwnd, 0);
  9760. break;
  9761. }
  9762. case ( IDC_KBDLH_LANGHOTKEY ) :
  9763. {
  9764. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
  9765. {
  9766. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
  9767. {
  9768. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_L_ALT2))
  9769. {
  9770. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_CHECKED);
  9771. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED);
  9772. }
  9773. else
  9774. {
  9775. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
  9776. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED);
  9777. }
  9778. }
  9779. else
  9780. {
  9781. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED);
  9782. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
  9783. }
  9784. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), TRUE);
  9785. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), TRUE);
  9786. }
  9787. else
  9788. {
  9789. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
  9790. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED);
  9791. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), FALSE);
  9792. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), FALSE);
  9793. }
  9794. break;
  9795. }
  9796. case ( IDC_KBDLH_LAYOUTHOTKEY ) :
  9797. {
  9798. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY))
  9799. {
  9800. CheckDlgButton(hwnd, IDC_KBDLH_GRAVE, BST_CHECKED);
  9801. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), TRUE);
  9802. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), TRUE);
  9803. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_GRAVE), TRUE);
  9804. }
  9805. else
  9806. {
  9807. CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED);
  9808. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
  9809. CheckDlgButton(hwnd, IDC_KBDLH_GRAVE, BST_UNCHECKED);
  9810. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), FALSE);
  9811. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), FALSE);
  9812. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_GRAVE), FALSE);
  9813. }
  9814. break;
  9815. }
  9816. case ( IDC_KBDLH_CTRL ) :
  9817. {
  9818. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY) &&
  9819. !IsDlgButtonChecked(hwnd, IDC_KBDLH_GRAVE))
  9820. {
  9821. CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED);
  9822. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_CHECKED);
  9823. }
  9824. break;
  9825. }
  9826. case ( IDC_KBDLH_L_ALT ) :
  9827. {
  9828. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY) &&
  9829. !IsDlgButtonChecked(hwnd, IDC_KBDLH_GRAVE))
  9830. {
  9831. CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED);
  9832. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED);
  9833. }
  9834. break;
  9835. }
  9836. case ( IDC_KBDLH_CTRL2 ) :
  9837. {
  9838. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
  9839. {
  9840. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
  9841. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED);
  9842. }
  9843. break;
  9844. }
  9845. case ( IDC_KBDLH_L_ALT2 ) :
  9846. {
  9847. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
  9848. {
  9849. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_CHECKED);
  9850. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED);
  9851. }
  9852. break;
  9853. }
  9854. default :
  9855. {
  9856. return (FALSE);
  9857. }
  9858. }
  9859. break;
  9860. }
  9861. default :
  9862. {
  9863. return (FALSE);
  9864. }
  9865. }
  9866. return (TRUE);
  9867. }
  9868. ////////////////////////////////////////////////////////////////////////////
  9869. //
  9870. // KbdLocaleChangeKeyboardLayoutHotkey
  9871. //
  9872. // Dlgproc for changing direct switch keyboard layout hotkey dialog box.
  9873. //
  9874. ////////////////////////////////////////////////////////////////////////////
  9875. INT_PTR CALLBACK KbdLocaleChangeKeyboardLayoutHotkey(
  9876. HWND hwnd,
  9877. UINT uMsg,
  9878. WPARAM wParam,
  9879. LPARAM lParam)
  9880. {
  9881. switch (uMsg)
  9882. {
  9883. case ( WM_INITDIALOG ) :
  9884. {
  9885. Locale_ChangeHotKeyDlgInit(hwnd, lParam);
  9886. break;
  9887. }
  9888. case ( WM_HELP ) :
  9889. {
  9890. WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
  9891. c_szHelpFile,
  9892. HELP_WM_HELP,
  9893. (DWORD_PTR)(LPTSTR)aLayoutHotkeyHelpIds );
  9894. break;
  9895. }
  9896. case ( WM_CONTEXTMENU ) : // right mouse click
  9897. {
  9898. WinHelp( (HWND)wParam,
  9899. c_szHelpFile,
  9900. HELP_CONTEXTMENU,
  9901. (DWORD_PTR)(LPTSTR)aLayoutHotkeyHelpIds );
  9902. break;
  9903. }
  9904. case ( WM_DESTROY ) :
  9905. {
  9906. RemoveProp(hwnd, szPropHwnd);
  9907. RemoveProp(hwnd, szPropIdx);
  9908. break;
  9909. }
  9910. case ( WM_COMMAND ) :
  9911. {
  9912. HWND hwndKey = GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO);
  9913. LPHOTKEYINFO pHotKeyNode = GetProp(hwnd, szPropIdx);
  9914. switch (LOWORD(wParam))
  9915. {
  9916. case ( IDOK ) :
  9917. {
  9918. if (Locale_ChangeHotKeyCommandOK(hwnd))
  9919. {
  9920. EndDialog(hwnd, 1);
  9921. }
  9922. break;
  9923. }
  9924. case ( IDCANCEL ) :
  9925. {
  9926. EndDialog(hwnd, 0);
  9927. break;
  9928. }
  9929. case ( IDC_KBDLH_LANGHOTKEY ) :
  9930. {
  9931. if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY))
  9932. {
  9933. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
  9934. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED);
  9935. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), TRUE);
  9936. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), TRUE);
  9937. ComboBox_SetCurSel(hwndKey, 0);
  9938. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO), TRUE);
  9939. }
  9940. else
  9941. {
  9942. CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED);
  9943. CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED);
  9944. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), FALSE);
  9945. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), FALSE);
  9946. ComboBox_SetCurSel(hwndKey, 0);
  9947. EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO), FALSE);
  9948. }
  9949. break;
  9950. }
  9951. case ( IDC_KBDLH_CTRL ) :
  9952. {
  9953. break;
  9954. }
  9955. case ( IDC_KBDLH_L_ALT ) :
  9956. {
  9957. break;
  9958. }
  9959. default :
  9960. {
  9961. return (FALSE);
  9962. }
  9963. }
  9964. break;
  9965. }
  9966. default :
  9967. {
  9968. return (FALSE);
  9969. }
  9970. }
  9971. return (TRUE);
  9972. }
  9973. ////////////////////////////////////////////////////////////////////////////
  9974. ///////////////////////////////// END ////////////////////////////////////
  9975. ////////////////////////////////////////////////////////////////////////////