// // Include Files. // #include "input.h" #include #include #include #include #include #include #include #include "inputdlg.h" #include "msctf.h" #include "msctfp.h" #include "ctffunc.h" #include "util.h" #include "inputhlp.h" #include "external.h" #define IMAGEID_KEYBOARD 0 #define IMAGEID_SPEECH 1 #define IMAGEID_PEN 2 #define IMAGEID_TIPITEMS 3 #define IMAGEID_EXTERNAL 4 #define IMAGEID_SMARTTAG 5 #define TV_ITEM_TYPE_LANG 0x0001 #define TV_ITEM_TYPE_GROUP 0x0002 #define TV_ITEM_TYPE_KBD 0x0010 #define TV_ITEM_TYPE_SPEECH 0x0020 #define TV_ITEM_TYPE_PEN 0x0040 #define TV_ITEM_TYPE_TIP 0x0100 #define TV_ITEM_TYPE_EXTERNAL 0x0200 #define TV_ITEM_TYPE_SMARTTAG 0x0400 #define INPUT_TYPE_KBD TV_ITEM_TYPE_KBD #define INPUT_TYPE_PEN TV_ITEM_TYPE_PEN #define INPUT_TYPE_SPEECH TV_ITEM_TYPE_SPEECH #define INPUT_TYPE_TIP TV_ITEM_TYPE_TIP #define INPUT_TYPE_EXTERNAL TV_ITEM_TYPE_EXTERNAL #define INPUT_TYPE_SMARTTAG TV_ITEM_TYPE_SMARTTAG #define MAX_DUPLICATED_HKL 64 // // Context Help Ids. // static int aInputHelpIds[] = { IDC_GROUPBOX1, IDH_COMM_GROUPBOX, IDC_LOCALE_DEFAULT_TEXT, IDH_INPUT_DEFAULT_LOCALE, IDC_LOCALE_DEFAULT, IDH_INPUT_DEFAULT_LOCALE, IDC_GROUPBOX2, IDH_COMM_GROUPBOX, IDC_INPUT_LIST_TEXT, IDH_INPUT_LIST, IDC_INPUT_LIST, IDH_INPUT_LIST, IDC_KBDL_ADD, IDH_INPUT_ADD, IDC_KBDL_DELETE, IDH_INPUT_DELETE, IDC_KBDL_EDIT, IDH_INPUT_EDIT, IDC_GROUPBOX3, IDH_COMM_GROUPBOX, IDC_TB_SETTING, IDH_INPUT_TOOLBAR_SETTINGS, IDC_HOTKEY_SETTING, IDH_INPUT_KEY_SETTINGS, 0, 0 }; static int aToolbarSettingsHelpIds[] = { IDC_GROUPBOX1, IDH_COMM_GROUPBOX, IDC_TB_SHOWLANGBAR, IDH_INPUT_SHOWLANGBAR, IDC_TB_HIGHTRANS, IDH_INPUT_HIGH_TRANS, IDC_TB_EXTRAICON, IDH_INPUT_EXTRAICON, IDC_TB_TEXTLABELS, IDH_INPUT_TEXT_LABELS, 0, 0 }; static int aLocaleKeysSettingsHelpIds[] = { IDC_KBDL_CAPSLOCK_FRAME, IDH_COMM_GROUPBOX, IDC_KBDL_CAPSLOCK, IDH_INPUT_SETTINGS_CAPSLOCK, IDC_KBDL_SHIFTLOCK, IDH_INPUT_SETTINGS_CAPSLOCK, IDC_KBDL_HOTKEY_FRAME, IDH_COMM_GROUPBOX, IDC_KBDL_HOTKEY, IDH_INPUT_SETTINGS_HOTKEY, IDC_KBDL_HOTKEY_SEQUENCE, IDH_INPUT_SETTINGS_HOTKEY, IDC_KBDL_HOTKEY_LIST, IDH_INPUT_SETTINGS_HOTKEY_LIST, IDC_KBDL_CHANGE_HOTKEY, IDH_INPUT_SETTINGS_HOTKEY, 0, 0 }; static int aLocaleAddHelpIds[] = { IDC_KBDLA_LOCALE_TEXT, IDH_INPUT_ADD_LOCALE, IDC_KBDLA_LOCALE, IDH_INPUT_ADD_LOCALE, IDC_KBDLA_LAYOUT_TEXT, IDH_INPUT_ADD_LAYOUT, IDC_KBDLA_LAYOUT, IDH_INPUT_ADD_LAYOUT, IDC_PEN_TEXT, IDH_INPUT_ADD_PEN, IDC_PEN_TIP, IDH_INPUT_ADD_PEN, IDC_SPEECH_TEXT, IDH_INPUT_ADD_SPEECH, IDC_SPEECH_TIP, IDH_INPUT_ADD_SPEECH, 0, 0 }; static int aLocaleHotkeyHelpIds[] = { IDC_GROUPBOX1, IDH_COMM_GROUPBOX, IDC_KBDLH_LANGHOTKEY, IDH_INPUT_LANG_HOTKEY_CHANGE, IDC_KBDLH_SHIFT, IDH_INPUT_LANG_HOTKEY_CHANGE, IDC_KBDLH_PLUS, IDH_INPUT_LANG_HOTKEY_CHANGE, IDC_KBDLH_CTRL, IDH_INPUT_LANG_HOTKEY_CHANGE, IDC_KBDLH_L_ALT, IDH_INPUT_LANG_HOTKEY_CHANGE, IDC_KBDLH_LAYOUTHOTKEY, IDH_INPUT_LANG_HOTKEY_CHANGE, IDC_KBDLH_SHIFT2, IDH_INPUT_LANG_HOTKEY_CHANGE, IDC_KBDLH_PLUS2, IDH_INPUT_LANG_HOTKEY_CHANGE, IDC_KBDLH_CTRL2, IDH_INPUT_LANG_HOTKEY_CHANGE, IDC_KBDLH_L_ALT2, IDH_INPUT_LANG_HOTKEY_CHANGE, IDC_KBDLH_GRAVE, IDH_INPUT_LANG_HOTKEY_CHANGE, 0, 0 }; static int aLayoutHotkeyHelpIds[] = { IDC_KBDLH_LAYOUT_TEXT, IDH_INPUT_LAYOUT_HOTKEY_CHANGE, IDC_KBDLH_LANGHOTKEY, IDH_INPUT_LAYOUT_HOTKEY_CHANGE, IDC_KBDLH_SHIFT, IDH_INPUT_LAYOUT_HOTKEY_CHANGE, IDC_KBDLH_CTRL, IDH_INPUT_LAYOUT_HOTKEY_CHANGE, IDC_KBDLH_L_ALT, IDH_INPUT_LAYOUT_HOTKEY_CHANGE, IDC_KBDLH_KEY_COMBO, IDH_INPUT_LAYOUT_HOTKEY_CHANGE, 0, 0 }; // // Global Variables. // HWND g_hDlg; HWND g_hwndTV; HTREEITEM g_hTVRoot; HIMAGELIST g_hImageList; UINT g_cTVItemSize = 0; BOOL g_OSNT4 = FALSE; BOOL g_OSNT5 = FALSE; BOOL g_OSWIN95 = FALSE; BOOL g_bAdvChanged = FALSE; static BOOL g_bGetSwitchLangHotKey = TRUE; static BOOL g_bCoInit = FALSE; static DWORD g_dwPrimLangID = 0; static UINT g_iThaiLayout = 0; static BOOL g_bPenOrSapiTip = FALSE; static BOOL g_bExtraTip = FALSE; UINT g_iInputs = 0; UINT g_iOrgInputs = 0; WNDPROC g_lpfnTVWndProc = NULL; TCHAR szPropHwnd[] = TEXT("PROP_HWND"); TCHAR szPropIdx[] = TEXT("PROP_IDX"); TCHAR szDefault[DESC_MAX]; TCHAR szInputTypeKbd[DESC_MAX]; TCHAR szInputTypePen[DESC_MAX]; TCHAR szInputTypeSpeech[DESC_MAX]; TCHAR szInputTypeExternal[DESC_MAX]; HINSTANCE g_hShlwapi = NULL; FARPROC pfnSHLoadRegUIString = NULL; // // External Routines. // extern HWND g_hwndAdvanced; extern void Region_RebootTheSystem(); extern BOOL Region_OpenIntlInfFile(HINF *phInf); extern BOOL Region_CloseInfFile(HINF *phInf); extern BOOL Region_ReadDefaultLayoutFromInf( LPTSTR pszLocale, LPDWORD pdwLocale, LPDWORD pdwLayout, LPDWORD pdwLocale2, LPDWORD pdwLayout2, HINF hIntlInf); // For (_WIN32_WINNT >= 0x0500 from winuser.h #define KLF_SHIFTLOCK 0x00010000 #define KLF_RESET 0x40000000 #define SM_IMMENABLED 82 //////////////////////////////////////////////////////////////////////////// // // MarkSptipRemoved // // TRUE - mark the reg value as "removed", FALSE - delete the reg value // //////////////////////////////////////////////////////////////////////////// BOOL MarkSptipRemoved(BOOL bRemoved) { // // SPTIP's private regentries for the use of detecting // whether user has removed profile // const TCHAR c_szProfileRemoved[] = TEXT("ProfileRemoved"); const TCHAR c_szSapilayrKey[] = TEXT("SOFTWARE\\Microsoft\\CTF\\Sapilayr\\"); HKEY hkey; long lRet = ERROR_SUCCESS; DWORD dw = bRemoved ? 1 : 0; if (ERROR_SUCCESS == RegCreateKey(HKEY_CURRENT_USER, c_szSapilayrKey, &hkey)) { lRet = RegSetValueEx(hkey, c_szProfileRemoved, 0, REG_DWORD, (LPBYTE)&dw, sizeof(DWORD)); RegCloseKey(hkey); } return lRet; } //////////////////////////////////////////////////////////////////////////// // // CompareStringTIP // //////////////////////////////////////////////////////////////////////////// int CompareStringTIP(LPTSTR lpStr1, LPTSTR lpStr2) { if (g_bCHSystem) { TCHAR szTemp[MAX_PATH]; UINT uSize1 = lstrlen(lpStr1); UINT uSize2 = lstrlen(lpStr2); UINT uSizeDef = lstrlen(szDefault); if (uSize1 == uSize2) return lstrcmp(lpStr1, lpStr2); if (uSize1 > uSizeDef) { if (lstrcmp(lpStr1 + uSize1 - uSizeDef, szDefault) == 0) { StringCchCopy(szTemp, ARRAYSIZE(szTemp), lpStr1); *(szTemp + uSize1 - uSizeDef) = TEXT('\0'); return lstrcmp(szTemp, lpStr2); } } if (uSize2 > uSizeDef) { if (lstrcmp(lpStr2 + uSize2 - uSizeDef, szDefault) == 0) { StringCchCopy(szTemp, ARRAYSIZE(szTemp), lpStr2); *(szTemp + uSize2 - uSizeDef) = TEXT('\0'); return lstrcmp(szTemp, lpStr1); } } } return lstrcmp(lpStr1, lpStr2); } //////////////////////////////////////////////////////////////////////////// // // Locale_ErrorMsg // // Sound a beep and put up the given error message. // //////////////////////////////////////////////////////////////////////////// void Locale_ErrorMsg( HWND hwnd, UINT iErr, LPTSTR lpValue) { TCHAR sz[DESC_MAX]; TCHAR szString[DESC_MAX]; // // Sound a beep. // MessageBeep(MB_OK); // // Put up the appropriate error message box. // if (LoadString(hInstance, iErr, sz, ARRAYSIZE(sz))) { // // If the caller wants to display a message with a caller supplied // value string, do it. // if (lpValue) { StringCchPrintf(szString, ARRAYSIZE(szString), sz, lpValue); MessageBox(hwnd, szString, NULL, MB_OK_OOPS); } else { MessageBox(hwnd, sz, NULL, MB_OK_OOPS); } } } //////////////////////////////////////////////////////////////////////////// // // IsFELangID // //////////////////////////////////////////////////////////////////////////// BOOL IsFELangID(DWORD dwLangID) { if ((dwLangID == 0x0404) || (dwLangID == 0x0411) || (dwLangID == 0x0412) || (dwLangID == 0x0804)) { return TRUE; } return FALSE; } //////////////////////////////////////////////////////////////////////////// // // IsUnregisteredFEDummyHKL // //////////////////////////////////////////////////////////////////////////// BOOL IsUnregisteredFEDummyHKL(HKL hkl) { HKEY hKey; BOOL bRet = FALSE; TCHAR szFEDummyHKL[10]; switch (LANGIDFROMLCID(hkl)) { case 0x411: break; case 0x412: break; case 0x404: break; case 0x804: break; default: goto Exit; } if (HIWORD((DWORD)(UINT_PTR)hkl) != LOWORD((DWORD)(UINT_PTR)hkl)) { goto Exit; } StringCchPrintf(szFEDummyHKL, ARRAYSIZE(szFEDummyHKL), TEXT("%08x"), LOWORD((DWORD)(UINT_PTR)hkl)); // // Now read all of preload hkl from the registry. // if (RegOpenKey(HKEY_CURRENT_USER, c_szKbdPreloadKey, &hKey) == ERROR_SUCCESS) { DWORD dwIndex; DWORD cchValue, cbData; LONG dwRetVal; TCHAR szValue[MAX_PATH]; // language id (number) TCHAR szData[MAX_PATH]; // language name dwIndex = 0; cchValue = sizeof(szValue) / sizeof(TCHAR); cbData = sizeof(szData); dwRetVal = RegEnumValue( hKey, dwIndex, szValue, &cchValue, NULL, NULL, (LPBYTE)szData, &cbData ); if (dwRetVal != ERROR_SUCCESS) { RegCloseKey(hKey); return (FALSE); } // // There is FE dummy hkl. we will skip this hkl if it is not loaded // from Preload registry section. // bRet = TRUE; do { if (!lstrcmp(szFEDummyHKL, szData)) { HKEY hSubKey; BOOL bSubHKL = FALSE; // // Check substitute hkl. // if (RegOpenKey(HKEY_CURRENT_USER, c_szKbdSubstKey, &hSubKey) == ERROR_SUCCESS) { if (RegQueryValueEx(hSubKey, szData, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { bSubHKL = TRUE; } RegCloseKey(hSubKey); if (bSubHKL) goto Next; } // // Found dummy hkl from preload section, so we need to display // this dummy hkl // bRet = FALSE; break; } Next: dwIndex++; cchValue = sizeof(szValue) / sizeof(TCHAR); szValue[0] = TEXT('\0'); cbData = sizeof(szData); szData[0] = TEXT('\0'); dwRetVal = RegEnumValue( hKey, dwIndex, szValue, &cchValue, NULL, NULL, (LPBYTE)szData, &cbData ); } while (dwRetVal == ERROR_SUCCESS); RegCloseKey(hKey); } Exit: return bRet; } #ifdef _WIN64 // // Issue optimization for IA64 retail version case - related bug#361062 // #pragma optimize("", off) #endif // _WIN64 //////////////////////////////////////////////////////////////////////////// // // GetSubstituteHKL // //////////////////////////////////////////////////////////////////////////// HKL GetSubstituteHKL(REFCLSID rclsid, LANGID langid, REFGUID guidProfile) { HKEY hkey; DWORD cb; HKL hkl = NULL; TCHAR szSubKeyPath[MAX_PATH]; TCHAR szSubHKL[MAX_PATH]; StringCchCopy(szSubKeyPath, ARRAYSIZE(szSubKeyPath), c_szCTFTipPath); StringFromGUID2(rclsid, (LPOLESTR) szSubKeyPath + lstrlen(szSubKeyPath), 100); StringCchCat(szSubKeyPath, ARRAYSIZE(szSubKeyPath), TEXT("\\")); StringCchCat(szSubKeyPath, ARRAYSIZE(szSubKeyPath), c_szLangProfileKey); StringCchCat(szSubKeyPath, ARRAYSIZE(szSubKeyPath), TEXT("\\")); StringCchPrintf(szSubKeyPath + lstrlen(szSubKeyPath), ARRAYSIZE(szSubKeyPath) - lstrlen(szSubKeyPath), TEXT("0x%08x"), langid); StringCchCat(szSubKeyPath, ARRAYSIZE(szSubKeyPath), TEXT("\\")); StringFromGUID2(guidProfile, (LPOLESTR) szSubKeyPath + lstrlen(szSubKeyPath), 50); if (RegOpenKey(HKEY_LOCAL_MACHINE, szSubKeyPath, &hkey) == ERROR_SUCCESS) { cb = sizeof(szSubHKL); RegQueryValueEx(hkey, c_szSubstituteLayout, NULL, NULL, (LPBYTE)szSubHKL, &cb); RegCloseKey(hkey); if ((szSubHKL[0] == '0') && ((szSubHKL[1] == 'X') || (szSubHKL[1] == 'x'))) { hkl = (HKL) IntToPtr(TransNum(szSubHKL+2)); if (LOWORD(hkl) != langid) hkl = 0; } } return hkl; } #ifdef _WIN64 #pragma optimize("", on) #endif // _WIN64 //////////////////////////////////////////////////////////////////////////// // // IsTipSubstituteHKL // //////////////////////////////////////////////////////////////////////////// BOOL IsTipSubstituteHKL(HKL hkl) { UINT ctr; // // Search substitute HKL of Tips. // for (ctr = 0; ctr < g_iTipsBuff; ctr++) { if (hkl == g_lpTips[ctr].hklSub) { return TRUE; } } return FALSE; } //////////////////////////////////////////////////////////////////////////// // // IsEnabledTipOrMultiLayouts() // //////////////////////////////////////////////////////////////////////////// BOOL IsEnabledTipOrMultiLayouts() { BOOL bRet = TRUE; if (g_iInputs < 2 && !g_iEnabledTips) { // No Tip and one layout, so diable turn off ctfmon UI. bRet = FALSE; } return bRet; } //////////////////////////////////////////////////////////////////////////// // // AddKbdLayoutOnKbdTip // //////////////////////////////////////////////////////////////////////////// void AddKbdLayoutOnKbdTip(HKL hkl, UINT iLayout) { UINT ctr; // // Search substitute HKL of Tips. // for (ctr = 0; ctr < g_iTipsBuff; ctr++) { if (hkl == g_lpTips[ctr].hklSub) { if (iLayout) g_lpTips[ctr].iLayout = iLayout; } } } //////////////////////////////////////////////////////////////////////////// // // IsAvailableTip // //////////////////////////////////////////////////////////////////////////// BOOL IsTipAvailableForAdd(DWORD dwLangID) { UINT ctr; // // Search substitute HKL of Tips. // for (ctr = 0; ctr < g_iTipsBuff; ctr++) { if ((dwLangID == g_lpTips[ctr].dwLangID) && !(g_lpTips[ctr].bEnabled)) { if (g_lpTips[ctr].uInputType & INPUT_TYPE_SPEECH) { if (!(g_lpTips[ctr].fEngineAvailable)) continue; } return TRUE; } } return FALSE; } //////////////////////////////////////////////////////////////////////////// // // CreateImageIcons // //////////////////////////////////////////////////////////////////////////// void CreateImageIcons() { HBITMAP hBmp; UINT flags = ILC_COLOR | ILC_MASK; HIMAGELIST hIml, hImlTmp; HICON hIcon = NULL; // // Create the image list // g_hImageList = ImageList_Create( GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR32 | ILC_MASK, 0, 0 ); // // Load the group icons of input type. // hIcon = LoadImage(hInstOrig, MAKEINTRESOURCE(IDI_KEYBOARD), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); ImageList_AddIcon(g_hImageList, hIcon); hIcon = LoadImage(hInstOrig, MAKEINTRESOURCE(IDI_SPEECH), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); ImageList_AddIcon(g_hImageList, hIcon); hIcon = LoadImage(hInstOrig, MAKEINTRESOURCE(IDI_PEN), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); ImageList_AddIcon(g_hImageList, hIcon); hIcon = LoadImage(GetCicResInstance(hInstOrig, IDI_TIPITEM), MAKEINTRESOURCE(IDI_TIPITEM), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); ImageList_AddIcon(g_hImageList, hIcon); hIcon = LoadImage(GetCicResInstance(hInstOrig, IDI_ICON), MAKEINTRESOURCE(IDI_ICON), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); ImageList_AddIcon(g_hImageList, hIcon); hIcon = LoadImage(GetCicResInstance(hInstOrig, IDI_SMARTTAG), MAKEINTRESOURCE(IDI_SMARTTAG), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); ImageList_AddIcon(g_hImageList, hIcon); // Associate the image list with the tree. hImlTmp = TreeView_SetImageList(g_hwndTV, g_hImageList, TVSIL_NORMAL); if (hImlTmp) ImageList_Destroy(hImlTmp); } //////////////////////////////////////////////////////////////////////////// // // CreateLangIcon // //////////////////////////////////////////////////////////////////////////// HICON CreateLangIcon( HWND hwnd, UINT langID ) { HBITMAP hbmColour; HBITMAP hbmMono; HBITMAP hbmOld; HICON hicon = NULL; ICONINFO ii; RECT rc; DWORD rgbText; DWORD rgbBk = 0; UINT i; HDC hdc; HDC hdcScreen; //HBRUSH hbr; LOGFONT lf; HFONT hfont; HFONT hfontOld; TCHAR szData[20]; // // Get the indicator by using the first 2 characters of the // abbreviated language name. // if (GetLocaleInfo(MAKELCID(langID, SORT_DEFAULT), LOCALE_SABBREVLANGNAME | LOCALE_NOUSEROVERRIDE, szData, ARRAYSIZE(szData))) { // // Make Uppercase // if (g_OSWIN95) { szData[0] -= 0x20; szData[1] -= 0x20; } // // Only use the first two characters. // szData[2] = TEXT('\0'); } else { // // Id wasn't found. Use question marks. // szData[0] = TEXT('?'); szData[1] = TEXT('?'); szData[2] = TEXT('\0'); } if(SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, 0)) { if( (hfont = CreateFontIndirect(&lf)) ) { UINT cxSmIcon = GetSystemMetrics( SM_CXSMICON ); UINT cySmIcon = GetSystemMetrics( SM_CYSMICON ); hdcScreen = GetDC(NULL); hdc = CreateCompatibleDC(hdcScreen); hbmColour = CreateCompatibleBitmap(hdcScreen, cxSmIcon, cySmIcon); ReleaseDC( NULL, hdcScreen); if (hbmColour && hdc) { hbmMono = CreateBitmap(cxSmIcon, cySmIcon, 1, 1, NULL); if (hbmMono) { hbmOld = SelectObject( hdc, hbmColour); rc.left = 0; rc.top = 0; rc.right = cxSmIcon; rc.bottom = cySmIcon; rgbBk = SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT)); rgbText = SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); ExtTextOut(hdc, rc.left, rc.top, ETO_OPAQUE, &rc, TEXT(""), 0, NULL); SelectObject( hdc, GetStockObject(DEFAULT_GUI_FONT)); hfontOld = SelectObject( hdc, hfont); DrawText(hdc, szData, 2, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE); if (g_bShowRtL) MirrorBitmapInDC(hdc, hbmColour); SelectObject( hdc, hbmMono); PatBlt(hdc, 0, 0, cxSmIcon, cySmIcon, BLACKNESS); ii.fIcon = TRUE; ii.xHotspot = 0; ii.yHotspot = 0; ii.hbmColor = hbmColour; ii.hbmMask = hbmMono; hicon = CreateIconIndirect(&ii); SelectObject(hdc, hbmOld); DeleteObject(hbmMono); SelectObject(hdc, hfontOld); } DeleteObject(hbmColour); DeleteDC(hdc); } DeleteObject(hfont); } } return hicon; } //////////////////////////////////////////////////////////////////////////// // // GetLanguageName // //////////////////////////////////////////////////////////////////////////// BOOL GetLanguageName( LCID lcid, LPTSTR lpLangName, UINT cchLangName) { BOOL bRet = TRUE; if (g_OSWIN95) { if (!GetLocaleInfo(lcid, LOCALE_SLANGUAGE, lpLangName, cchLangName)) { LoadString(hInstance, IDS_LOCALE_UNKNOWN, lpLangName, cchLangName); bRet = FALSE; } } else { WCHAR wszLangName[MAX_PATH]; if (!GetLocaleInfoW(lcid, LOCALE_SLANGUAGE, wszLangName, ARRAYSIZE(wszLangName))) { LoadString(hInstance, IDS_LOCALE_UNKNOWN, lpLangName, cchLangName); bRet = FALSE; } else { StringCchCopy(lpLangName, cchLangName, wszLangName); } } return bRet; } //////////////////////////////////////////////////////////////////////////// // // CreateTVItemNode // //////////////////////////////////////////////////////////////////////////// LPTVITEMNODE CreateTVItemNode(DWORD dwLangID) { LPTVITEMNODE pTVItemNode; HANDLE hItemNode; // // Create the new node. // if (!(pTVItemNode = (LPTVITEMNODE) LocalAlloc(LPTR, sizeof(TVITEMNODE)))) { return (NULL); } g_cTVItemSize++; // // Fill in the new node with the appropriate info. // pTVItemNode->dwLangID = dwLangID; pTVItemNode->bDefLang = FALSE; pTVItemNode->iIdxTips = -1; pTVItemNode->atmDefTipName = 0; pTVItemNode->atmTVItemName = 0; pTVItemNode->lParam = 0; // // Return the pointer to the new node. // return (pTVItemNode); } //////////////////////////////////////////////////////////////////////////// // // RemoveTVItemNode // //////////////////////////////////////////////////////////////////////////// void RemoveTVItemNode( LPTVITEMNODE pTVItemNode) { if (pTVItemNode) { if (pTVItemNode->uInputType & INPUT_TYPE_KBD) { int idxSel = -1; TCHAR szItemName[MAX_PATH * 2]; HWND hwndDefList = GetDlgItem(g_hDlg, IDC_LOCALE_DEFAULT); GetLanguageName(MAKELCID(pTVItemNode->dwLangID, SORT_DEFAULT), szItemName, ARRAYSIZE(szItemName)); StringCchCat(szItemName, ARRAYSIZE(szItemName), TEXT(" - ")); GetAtomName(pTVItemNode->atmTVItemName, szItemName + lstrlen(szItemName), MAX_PATH); idxSel = ComboBox_FindString(hwndDefList, 0, szItemName); if (idxSel != CB_ERR) { ComboBox_DeleteString(hwndDefList, idxSel); } } if (pTVItemNode->atmTVItemName) DeleteAtom(pTVItemNode->atmTVItemName); if (pTVItemNode->atmDefTipName) DeleteAtom(pTVItemNode->atmDefTipName); LocalFree(pTVItemNode); g_cTVItemSize--; } } //////////////////////////////////////////////////////////////////////////// // // Locale_AddToLinkedList // // Adds an Input Locale to the main g_lpLang array. // //////////////////////////////////////////////////////////////////////////// LPLANGNODE Locale_AddToLinkedList( UINT idx, HKL hkl) { LPINPUTLANG pInpLang = &g_lpLang[idx]; LPLANGNODE pLangNode; LPLANGNODE pTemp; HANDLE hLangNode; // // Create the new node. // if (!(hLangNode = LocalAlloc(LHND, sizeof(LANGNODE)))) { return (NULL); } pLangNode = LocalLock(hLangNode); // // Fill in the new node with the appropriate info. // pLangNode->wStatus = 0; pLangNode->iLayout = (UINT)(-1); pLangNode->hkl = hkl; pLangNode->hklUnload = hkl; pLangNode->iLang = idx; pLangNode->hLangNode = hLangNode; pLangNode->pNext = NULL; pLangNode->nIconIME = -1; // // If an hkl is given, see if it's an IME. If so, mark the status bit. // if ((hkl) && ((HIWORD(hkl) & 0xf000) == 0xe000)) { pLangNode->wStatus |= LANG_IME; } // // Put the new node in the list. // pTemp = pInpLang->pNext; if (pTemp == NULL) { pInpLang->pNext = pLangNode; } else { while (pTemp->pNext != NULL) { pTemp = pTemp->pNext; } pTemp->pNext = pLangNode; } // // Increment the count. // pInpLang->iNumCount++; // // Return the pointer to the new node. // return (pLangNode); } //////////////////////////////////////////////////////////////////////////// // // Locale_RemoveFromLinkedList // // Removes a link from the linked list. // //////////////////////////////////////////////////////////////////////////// void Locale_RemoveFromLinkedList( LPLANGNODE pLangNode) { LPINPUTLANG pInpLang; LPLANGNODE pPrev; LPLANGNODE pCur; HANDLE hCur; pInpLang = &g_lpLang[pLangNode->iLang]; // // Find the node in the list. // pPrev = NULL; pCur = pInpLang->pNext; while (pCur && (pCur != pLangNode)) { pPrev = pCur; pCur = pCur->pNext; } if (pPrev == NULL) { if (pCur == pLangNode) { pInpLang->pNext = pCur->pNext; } else { pInpLang->pNext = NULL; } } else if (pCur) { pPrev->pNext = pCur->pNext; } // // Remove the node from the list. // if (pCur) { hCur = pCur->hLangNode; LocalUnlock(hCur); LocalFree(hCur); } } //////////////////////////////////////////////////////////////////////////// // // Locale_GetImeHotKeyInfo // // Initializes array for CHS/CHT specific IME related hotkey items. // //////////////////////////////////////////////////////////////////////////// int Locale_GetImeHotKeyInfo( HWND hwnd, LPHOTKEYINFO *aImeHotKey) { HWND hwndTV = g_hwndTV; LPLANGNODE pLangNode; LANGID LangID; int ctr; BOOL fCHS, fCHT; TV_ITEM tvItem; HTREEITEM hItem; HTREEITEM hLangItem; HTREEITEM hGroupItem; fCHS = fCHT = FALSE; ctr = 0; // // Check if the CHS or CHT layouts are loaded. // tvItem.mask = TVIF_HANDLE | TVIF_PARAM; for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ; hLangItem != NULL ; hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem)) { for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem); hGroupItem != NULL; hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem)) { for (hItem = TreeView_GetChild(hwndTV, hGroupItem); hItem != NULL; hItem = TreeView_GetNextSibling(hwndTV, hItem)) { LPTVITEMNODE pTVItemNode; tvItem.hItem = hItem; if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam) { pTVItemNode = (LPTVITEMNODE) tvItem.lParam; pLangNode = (LPLANGNODE)pTVItemNode->lParam; if (pLangNode == NULL) continue; } else continue; LangID = LOWORD(g_lpLayout[pLangNode->iLayout].dwID); if ( PRIMARYLANGID(LangID) == LANG_CHINESE ) { if ( SUBLANGID(LangID) == SUBLANG_CHINESE_SIMPLIFIED) fCHS = TRUE; else if ( SUBLANGID(LangID) == SUBLANG_CHINESE_TRADITIONAL ) fCHT = TRUE; } if (fCHS && fCHT) break; } } } if ( (fCHS == TRUE) && (fCHT == TRUE) ) { // Both CHS and CHT IMEs are Loaded *aImeHotKey = g_aImeHotKeyCHxBoth; return(sizeof(g_aImeHotKeyCHxBoth) / sizeof(HOTKEYINFO) ); } else { if ( fCHS == TRUE ) { // only CHS IMEs are loaded *aImeHotKey = g_aImeHotKey0804; return (sizeof(g_aImeHotKey0804) / sizeof(HOTKEYINFO)); } if ( fCHT == TRUE ) { // Only CHT IMEs are loaded. *aImeHotKey = g_aImeHotKey0404; return (sizeof(g_aImeHotKey0404) / sizeof(HOTKEYINFO)); } } // all other cases, No Chinese IME is loaded. *aImeHotKey=NULL; return (0); } //////////////////////////////////////////////////////////////////////////// // // Locale_EnumChildWndProc // // disable all controls. //////////////////////////////////////////////////////////////////////////// BOOL CALLBACK Locale_EnumChildWndProc(HWND hwnd, LPARAM lParam) { EnableWindow(hwnd, FALSE); ShowWindow(hwnd, SW_HIDE); return TRUE; } //////////////////////////////////////////////////////////////////////////// // // Locale_EnablePane // // The controls in "iControl" are the controls that get disabled if the // pane can't come up. // //////////////////////////////////////////////////////////////////////////// void Locale_EnablePane( HWND hwnd, BOOL bEnable, UINT DisableId) { if (!bEnable) { if (DisableId == IDC_KBDL_DISABLED_2) { // // Disable all controls. // EnumChildWindows(hwnd, (WNDENUMPROC)Locale_EnumChildWndProc, 0); ShowWindow(GetDlgItem(hwnd, IDC_KBDL_DISABLED_2), SW_SHOW); EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DISABLED_2), TRUE); } else { if (!g_iEnabledTips) { // // Disable all controls. // EnumChildWindows(hwnd, (WNDENUMPROC)Locale_EnumChildWndProc, 0); ShowWindow(GetDlgItem(hwnd, IDC_KBDL_DISABLED), SW_SHOW); EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DISABLED), TRUE); } else { // // Disable Add, Property, Hotkey and default language setting controls. // EnableWindow(GetDlgItem(hwnd, IDC_LOCALE_DEFAULT), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDL_ADD), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDL_EDIT), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_HOTKEY_SETTING), FALSE); } } } return; } //////////////////////////////////////////////////////////////////////////// // // Locale_KillPaneDialog // // Processing for a WM_DESTROY message. // //////////////////////////////////////////////////////////////////////////// void Locale_KillPaneDialog( HWND hwnd) { UINT ctr, iCount; HANDLE hCur; LPLANGNODE pCur; LPHOTKEYINFO aImeHotKey; TV_ITEM tvItem; HTREEITEM hLangItem; HTREEITEM hGroupItem; HTREEITEM hItem; LPTVITEMNODE pTVItemNode; HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST); if (g_bCoInit) CoUninitialize(); // // Delete all hot key atoms and free up the hotkey arrays. // if (g_SwitchLangHotKey.atmHotKeyName) { DeleteAtom(g_SwitchLangHotKey.atmHotKeyName); } iCount = Locale_GetImeHotKeyInfo(hwnd, &aImeHotKey); for (ctr = 0; ctr < iCount; ctr++) { if (aImeHotKey[ctr].atmHotKeyName) { DeleteAtom(aImeHotKey[ctr].atmHotKeyName); } } for (ctr = 0; ctr < DSWITCH_HOTKEY_SIZE; ctr++) { if (g_aDirectSwitchHotKey[ctr].atmHotKeyName) { DeleteAtom(g_aDirectSwitchHotKey[ctr].atmHotKeyName); } } // // Delete all TreeView node. // tvItem.mask = TVIF_HANDLE | TVIF_PARAM; for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ; hLangItem != NULL ; hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem) ) { for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem); hGroupItem != NULL; hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem)) { for (hItem = TreeView_GetChild(hwndTV, hGroupItem); hItem != NULL; hItem = TreeView_GetNextSibling(hwndTV, hItem)) { tvItem.hItem = hItem; if (TreeView_GetItem(hwndTV, &tvItem)) { pTVItemNode = (LPTVITEMNODE) tvItem.lParam; RemoveTVItemNode(pTVItemNode); } } tvItem.hItem = hGroupItem; if (TreeView_GetItem(hwndTV, &tvItem)) { pTVItemNode = (LPTVITEMNODE) tvItem.lParam; if (TreeView_GetItem(hwndTV, &tvItem)) { RemoveTVItemNode(pTVItemNode); continue; } } } tvItem.hItem = hLangItem; if (TreeView_GetItem(hwndTV, &tvItem)) { pTVItemNode = (LPTVITEMNODE) tvItem.lParam; RemoveTVItemNode(pTVItemNode); } } #ifdef DEBUG if (g_cTVItemSize) { MessageBox(NULL, TEXT("Error is occurred during terminate window"), NULL, MB_OK); } #endif // // Delete all Language Name atoms and free the g_lpLang array. // for (ctr = 0; ctr < g_iLangBuff; ctr++) { if (g_lpLang[ctr].atmLanguageName) { DeleteAtom(g_lpLang[ctr].atmLanguageName); } pCur = g_lpLang[ctr].pNext; g_lpLang[ctr].pNext = NULL; while (pCur) { hCur = pCur->hLangNode; pCur = pCur->pNext; LocalUnlock(hCur); LocalFree(hCur); } } if (g_hImageList != NULL) { TreeView_SetImageList(hwndTV, NULL, TVSIL_NORMAL); ImageList_Destroy(g_hImageList); } LocalUnlock(g_hLang); LocalFree(g_hLang); // // Delete all layout text and layout file atoms and free the // g_lpLayout array. // for (ctr = 0; ctr < g_iLayoutBuff; ctr++) { if (g_lpLayout[ctr].atmLayoutText) { DeleteAtom(g_lpLayout[ctr].atmLayoutText); } if (g_lpLayout[ctr].atmLayoutFile) { DeleteAtom(g_lpLayout[ctr].atmLayoutFile); } if (g_lpLayout[ctr].atmIMEFile) { DeleteAtom(g_lpLayout[ctr].atmIMEFile); } } LocalUnlock(g_hLayout); LocalFree(g_hLayout); // // Make sure the mutex is released. // if (g_hMutex) { ReleaseMutex(g_hMutex); } } //////////////////////////////////////////////////////////////////////////// // // SelectDefaultKbdLayoutAsBold // //////////////////////////////////////////////////////////////////////////// void SelectDefaultKbdLayoutAsBold( HWND hwndTV, HTREEITEM hTVItem) { TV_ITEM tvItem; TCHAR szItemName[MAX_PATH]; TCHAR szLayoutName[MAX_PATH]; TreeView_SelectItem(hwndTV, hTVItem); tvItem.mask = TVIF_TEXT | TVIF_PARAM | TVIF_STATE; tvItem.hItem = hTVItem; tvItem.state = 0; tvItem.stateMask = TVIS_BOLD; tvItem.pszText = szItemName; tvItem.cchTextMax = sizeof(szItemName) / sizeof(TCHAR); if (TreeView_GetItem(hwndTV, &tvItem)) { LPTVITEMNODE pTVItemNode; pTVItemNode = (LPTVITEMNODE) tvItem.lParam; if (!pTVItemNode) return; if (g_bCHSystem) { GetAtomName(pTVItemNode->atmTVItemName, szLayoutName, ARRAYSIZE(szLayoutName)); StringCchCat(szLayoutName, ARRAYSIZE(szLayoutName), szDefault); tvItem.pszText = szLayoutName; } tvItem.state |= TVIS_BOLD; SendMessage(hwndTV, TVM_SETITEM, 0, (LPARAM) &tvItem); } } //////////////////////////////////////////////////////////////////////////// // // FindTVLangItem // //////////////////////////////////////////////////////////////////////////// HTREEITEM FindTVLangItem(DWORD dwLangID, LPTSTR lpLangText) { HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST); TV_ITEM tvItem; HTREEITEM hLangItem; LPTVITEMNODE pTVLangNode; TCHAR szLangName[MAX_PATH]; tvItem.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_PARAM; tvItem.pszText = szLangName; tvItem.cchTextMax = sizeof(szLangName) / sizeof(TCHAR); for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ; hLangItem != NULL ; hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem) ) { tvItem.hItem = hLangItem; if (TreeView_GetItem(hwndTV, &tvItem)) { int iSize = lstrlen(lpLangText); pTVLangNode = (LPTVITEMNODE) tvItem.lParam; if (!pTVLangNode) { continue; } *(szLangName + min(iSize, tvItem.cchTextMax)) = TEXT('\0'); if (!CompareStringTIP(szLangName, lpLangText) || (dwLangID && (pTVLangNode->dwLangID == dwLangID))) { return hLangItem; } } } return NULL; } //////////////////////////////////////////////////////////////////////////// // // AddTreeViewItems // //////////////////////////////////////////////////////////////////////////// HTREEITEM AddTreeViewItems( UINT uItemType, LPTSTR lpLangText, LPTSTR lpGroupText, LPTSTR lpTipText, LPTVITEMNODE *ppTVItemNode) { HTREEITEM hTVItem; HTREEITEM hTVItem2; HTREEITEM hItem; HTREEITEM hLangItem = NULL; HTREEITEM hGroupItem; TV_ITEM tvItem; TV_INSERTSTRUCT tvIns; HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST); HWND hwndDefList = GetDlgItem(g_hDlg, IDC_LOCALE_DEFAULT); TCHAR szDefItem[MAX_PATH]; TCHAR szLangName[ MAX_PATH ]; LPTVITEMNODE pTVLangNode; LPTVITEMNODE pTVItemNode; BOOL bFoundLang = FALSE; BOOL bFindGroup = FALSE; LPLANGNODE pLangNode; pTVItemNode = *ppTVItemNode; if (!pTVItemNode) return NULL; // We only want to add an lang item if it is not already there. // tvItem.mask = TVIF_HANDLE | TVIF_TEXT | TVIF_PARAM; tvItem.state = 0; tvItem.stateMask = 0; tvItem.pszText = szLangName; tvItem.cchTextMax = sizeof(szLangName) / sizeof(TCHAR); for (hItem = TreeView_GetChild(hwndTV, g_hTVRoot) ; hItem != NULL ; hItem = TreeView_GetNextSibling(hwndTV, hItem) ) { tvItem.hItem = hItem; if (TreeView_GetItem(hwndTV, &tvItem)) { pTVLangNode = (LPTVITEMNODE) tvItem.lParam; if (!pTVLangNode) { continue; } if (pTVLangNode->dwLangID == pTVItemNode->dwLangID) { // We found a match! // hLangItem = hItem; bFoundLang = TRUE; if (!pTVLangNode->atmDefTipName && pTVItemNode->atmDefTipName) { TCHAR szDefTip[DESC_MAX]; GetAtomName(pTVItemNode->atmDefTipName, szDefTip, ARRAYSIZE(szDefTip)); pTVLangNode->atmDefTipName = AddAtom(szDefTip); } if (!(pTVLangNode->hklSub) && pTVItemNode->hklSub) pTVLangNode->hklSub = pTVItemNode->hklSub; } } } if (bFoundLang && (uItemType & TV_ITEM_TYPE_LANG)) { RemoveTVItemNode(pTVItemNode); *ppTVItemNode = NULL; return hItem; } tvItem.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM | TVIF_STATE; tvItem.lParam = (LPARAM) pTVItemNode; if (uItemType & TV_ITEM_TYPE_LANG) { HICON hIcon = NULL; int iImage; hIcon = CreateLangIcon(hwndTV, LOWORD(pTVItemNode->dwLangID)); if (hIcon) { iImage = ImageList_AddIcon(g_hImageList, hIcon); tvItem.iImage = iImage; tvItem.iSelectedImage = iImage; } pTVItemNode->atmTVItemName = AddAtom(lpLangText); pTVItemNode->uInputType |= TV_ITEM_TYPE_LANG; tvItem.pszText = lpLangText; tvItem.cchTextMax = sizeof(szLangName) / sizeof(TCHAR); tvIns.item = tvItem; tvIns.hInsertAfter = TVI_SORT; tvIns.hParent = g_hTVRoot; hTVItem = (HTREEITEM) SendMessage(hwndTV, TVM_INSERTITEM, 0, (LPARAM)(LPTV_INSERTSTRUCT) &tvIns); return hTVItem; } if (hLangItem == NULL) return NULL; // Find the group node of input type for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem) ; hGroupItem != NULL ; hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem) ) { tvItem.hItem = hGroupItem; if (TreeView_GetItem(hwndTV, &tvItem)) { if (!lstrcmp(tvItem.pszText, lpGroupText)) { bFindGroup = TRUE; break; } } } tvItem.lParam = (LPARAM) pTVItemNode; pTVItemNode->uInputType |= uItemType; g_iInputs++; if (!bFindGroup) { LPTVITEMNODE pTVGroupNode; if (pTVItemNode->bNoAddCat) { pTVGroupNode = pTVItemNode; } else { if (!(pTVGroupNode = CreateTVItemNode(pTVItemNode->dwLangID))) return NULL; pTVGroupNode->dwLangID = pTVItemNode->dwLangID; pTVGroupNode->uInputType = pTVItemNode->uInputType | TV_ITEM_TYPE_GROUP; pTVGroupNode->atmTVItemName = AddAtom(lpTipText); tvItem.lParam = (LPARAM) pTVGroupNode; } tvItem.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM | TVIF_STATE; tvItem.state = 0; if (pTVItemNode->uInputType & TV_ITEM_TYPE_KBD) { tvItem.iImage = IMAGEID_KEYBOARD; tvItem.iSelectedImage = IMAGEID_KEYBOARD; } else if (pTVItemNode->uInputType & TV_ITEM_TYPE_PEN) { tvItem.iImage = IMAGEID_PEN; tvItem.iSelectedImage = IMAGEID_PEN; } else if (pTVItemNode->uInputType & TV_ITEM_TYPE_SPEECH) { tvItem.iImage = IMAGEID_SPEECH; tvItem.iSelectedImage = IMAGEID_SPEECH; } else if (pTVItemNode->uInputType & TV_ITEM_TYPE_SMARTTAG) { tvItem.iImage = IMAGEID_SMARTTAG; tvItem.iSelectedImage = IMAGEID_SMARTTAG; } else { tvItem.iImage = IMAGEID_EXTERNAL; tvItem.iSelectedImage = IMAGEID_EXTERNAL; } if (pTVItemNode->bNoAddCat) tvItem.pszText = lpTipText; else tvItem.pszText = lpGroupText; tvItem.cchTextMax = MAX_PATH; tvIns.item = tvItem; tvIns.hInsertAfter = TVI_SORT; tvIns.hParent = hLangItem; hGroupItem = (HTREEITEM) SendMessage(hwndTV, TVM_INSERTITEM, 0, (LPARAM)(LPTV_INSERTSTRUCT) &tvIns); hTVItem = TreeView_GetParent(hwndTV, hGroupItem); TreeView_Expand(hwndTV, hTVItem, TVE_EXPAND); } if (pTVItemNode->bNoAddCat) return hGroupItem; // // Check layout name whether it is already added on the treeview. // for (hItem = TreeView_GetChild(hwndTV, hGroupItem); hItem != NULL; hItem = TreeView_GetNextSibling(hwndTV, hItem)) { tvItem.hItem = hItem; if (TreeView_GetItem(hwndTV, &tvItem)) { if (!CompareStringTIP(tvItem.pszText, lpTipText)) { if (pTVItemNode->lParam) Locale_RemoveFromLinkedList((LPLANGNODE)pTVItemNode->lParam); RemoveTVItemNode(pTVItemNode); return NULL; } } } pTVItemNode->atmTVItemName = AddAtom(lpTipText); tvItem.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM | TVIF_STATE; tvItem.state = 0; tvItem.stateMask = TVIS_BOLD; tvItem.iImage = IMAGEID_TIPITEMS; tvItem.iSelectedImage = IMAGEID_TIPITEMS; tvItem.lParam = (LPARAM) pTVItemNode; tvItem.pszText = lpTipText; tvItem.cchTextMax = MAX_PATH; tvIns.item = tvItem; tvIns.hInsertAfter = TVI_SORT; tvIns.hParent = hGroupItem; hTVItem = (HTREEITEM) SendMessage(hwndTV, TVM_INSERTITEM, 0, (LPARAM)(LPTV_INSERTSTRUCT) &tvIns); pLangNode = (LPLANGNODE)pTVItemNode->lParam; // // Adding the available default setting languages // if ((pTVItemNode->uInputType == TV_ITEM_TYPE_KBD) || (pTVItemNode->uInputType & (TV_ITEM_TYPE_KBD|TV_ITEM_TYPE_TIP) && pTVItemNode->hklSub)) { StringCchCopy(szDefItem, ARRAYSIZE(szDefItem), lpLangText); StringCchCat(szDefItem, ARRAYSIZE(szDefItem), TEXT(" - ")); StringCchCat(szDefItem, ARRAYSIZE(szDefItem), lpTipText); if (ComboBox_FindStringExact(hwndDefList, 0, szDefItem) == CB_ERR) ComboBox_AddString(hwndDefList, szDefItem); } #if 0 if (pTVItemNode->hklSub) { TV_ITEM tvItem2; tvItem2.mask = TVIF_HANDLE | TVIF_PARAM; if (tvItem2.hItem = FindTVLangItem(pTVItemNode->dwLangID, NULL)) { if (TreeView_GetItem(hwndTV, &tvItem2) && tvItem2.lParam) { pTVItemNode = (LPTVITEMNODE) tvItem2.lParam; pLangNode = (LPLANGNODE)pTVItemNode->lParam; } } } #endif if (pLangNode && (pLangNode->wStatus & LANG_DEFAULT)) { // // Select the default layout item as bold // SelectDefaultKbdLayoutAsBold(hwndTV, hTVItem); TreeView_Expand(hwndTV, hTVItem, TVE_EXPAND); tvItem.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM | TVIF_STATE; tvItem.hItem = hLangItem; tvItem.pszText = szLangName; tvItem.cchTextMax = sizeof(szLangName) / sizeof(TCHAR); if (TreeView_GetItem(hwndTV, &tvItem)) { LPTVITEMNODE pTVLangItemNode; int idxSel = -1; StringCchCopy(szDefItem, ARRAYSIZE(szDefItem), lpLangText); StringCchCat(szDefItem, ARRAYSIZE(szDefItem), TEXT(" - ")); StringCchCat(szDefItem, ARRAYSIZE(szDefItem), lpTipText); // // Set the default locale selection. // // if ((idxSel = ComboBox_FindStringExact(hwndDefList, 0, szDefItem)) == CB_ERR) { // Simply set the current selection to be the first entry // in the list. // ComboBox_SetCurSel(hwndDefList, 0); } else ComboBox_SetCurSel(hwndDefList, idxSel); if (pTVLangItemNode = (LPTVITEMNODE) tvItem.lParam) { pTVLangItemNode->bDefLang = TRUE; pTVLangItemNode->atmDefTipName = AddAtom(lpTipText); tvItem.state |= TVIS_BOLD; } StringCchCopy(tvItem.pszText, tvItem.cchTextMax, lpLangText); // // No more adding default description // //StringCchCat(tvItem.pszText, ARRAYSIZE(tvItem.cchTextMax), szDefault); SendMessage(hwndTV, TVM_SETITEM, 0, (LPARAM) &tvItem); TreeView_SelectSetFirstVisible(hwndTV, hLangItem); } } if (hTVItem2 = TreeView_GetParent(hwndTV, hTVItem)) TreeView_Expand(hwndTV, hTVItem2, TVE_EXPAND); return hTVItem; } //////////////////////////////////////////////////////////////////////////// // // UpdateDefaultTVLangItem // //////////////////////////////////////////////////////////////////////////// BOOL UpdateDefaultTVLangItem( DWORD dwLangID, LPTSTR lpDefTip, BOOL bDefLang, BOOL bSubhkl) { HTREEITEM hItem; TV_ITEM tvItem; HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST); TCHAR szLangName[ MAX_PATH ]; LPTVITEMNODE pTVLangItemNode; tvItem.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM | TVIF_STATE; tvItem.pszText = szLangName; tvItem.cchTextMax = sizeof(szLangName) / sizeof(TCHAR); for (hItem = TreeView_GetChild(hwndTV, g_hTVRoot) ; hItem != NULL ; hItem = TreeView_GetNextSibling(hwndTV, hItem) ) { tvItem.hItem = hItem; if (TreeView_GetItem(hwndTV, &tvItem)) { pTVLangItemNode = (LPTVITEMNODE) tvItem.lParam; if (!pTVLangItemNode) { continue; } if (pTVLangItemNode->dwLangID == dwLangID) { // We found a match! // GetAtomName(pTVLangItemNode->atmTVItemName, szLangName, ARRAYSIZE(szLangName)); if (pTVLangItemNode->atmDefTipName) DeleteAtom(pTVLangItemNode->atmDefTipName); pTVLangItemNode->atmDefTipName = AddAtom(lpDefTip); if (bSubhkl && (pTVLangItemNode->lParam && pTVLangItemNode->hklSub)) { LPLANGNODE pLangNode = NULL; if (pLangNode = (LPLANGNODE)pTVLangItemNode->lParam) { if (bDefLang) pLangNode->wStatus |= (LANG_DEFAULT | LANG_DEF_CHANGE); else if (pLangNode->wStatus & LANG_DEFAULT) pLangNode->wStatus &= ~(LANG_DEFAULT | LANG_DEF_CHANGE); } } tvItem.stateMask |= TVIS_BOLD; if (bDefLang) { TreeView_SelectSetFirstVisible(hwndTV, hItem); pTVLangItemNode->bDefLang = TRUE; // // No more adding default description // //StringCchCat(szLangName, ARRAYSIZE(szLangName), szDefault); tvItem.state |= TVIS_BOLD; } else { pTVLangItemNode->bDefLang = FALSE; tvItem.state &= ~TVIS_BOLD; } tvItem.pszText = szLangName; SendMessage(hwndTV, TVM_SETITEM, 0, (LPARAM) &tvItem); return TRUE; } } } return FALSE; } //////////////////////////////////////////////////////////////////////////// // // UpdateLangKBDItemNode // //////////////////////////////////////////////////////////////////////////// BOOL UpdateLangKBDItemNode( HTREEITEM hLangItem, LPTSTR lpDefTip, BOOL bDefault) { HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST); BOOL fRet = FALSE; TV_ITEM tvItem; HTREEITEM hGroupItem; HTREEITEM hItem; LPTVITEMNODE pTVItemNode; LPLANGNODE pLangNode; TCHAR szItemName[ MAX_PATH ]; TCHAR szLayoutName[ MAX_PATH ]; tvItem.mask = TVIF_TEXT | TVIF_PARAM | TVIF_HANDLE | TVIF_STATE; tvItem.pszText = szItemName; tvItem.cchTextMax = sizeof(szItemName) / sizeof(TCHAR); for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem); hGroupItem != NULL; hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem)) { for (hItem = TreeView_GetChild(hwndTV, hGroupItem); hItem != NULL; hItem = TreeView_GetNextSibling(hwndTV, hItem)) { tvItem.hItem = hItem; if (TreeView_GetItem(hwndTV, &tvItem)) { if (!CompareStringTIP(tvItem.pszText, lpDefTip) && (pTVItemNode = (LPTVITEMNODE) tvItem.lParam)) { GetAtomName(pTVItemNode->atmTVItemName, szLayoutName, ARRAYSIZE(szLayoutName)); tvItem.stateMask |= TVIS_BOLD; if (bDefault) { pTVItemNode->bDefLang = TRUE; tvItem.state |= TVIS_BOLD; if (g_bCHSystem) StringCchCat(szLayoutName, ARRAYSIZE(szLayoutName), szDefault); } else { pTVItemNode->bDefLang = FALSE; tvItem.state &= ~TVIS_BOLD; } pLangNode = (LPLANGNODE)pTVItemNode->lParam; if (pLangNode != NULL) { if (bDefault) pLangNode->wStatus |= (LANG_DEFAULT | LANG_DEF_CHANGE); else if (pLangNode->wStatus & LANG_DEFAULT) pLangNode->wStatus &= ~(LANG_DEFAULT | LANG_DEF_CHANGE); } tvItem.pszText = szLayoutName; SendMessage(hwndTV, TVM_SETITEM, 0, (LPARAM) &tvItem); fRet = TRUE; return fRet; } } } } return fRet; } //////////////////////////////////////////////////////////////////////////// // // FindDefaultTipItem // //////////////////////////////////////////////////////////////////////////// HTREEITEM FindDefaultTipItem( DWORD dwLangID, LPTSTR lpDefTip) { HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST); TV_ITEM tvItem; HTREEITEM hLangItem; HTREEITEM hGroupItem; HTREEITEM hItem; LPTVITEMNODE pTVLangItemNode; TCHAR szLangName[MAX_PATH]; tvItem.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_PARAM; tvItem.pszText = szLangName; tvItem.cchTextMax = sizeof(szLangName) / sizeof(TCHAR); for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ; hLangItem != NULL ; hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem) ) { for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem); hGroupItem != NULL; hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem)) { for (hItem = TreeView_GetChild(hwndTV, hGroupItem); hItem != NULL; hItem = TreeView_GetNextSibling(hwndTV, hItem)) { tvItem.hItem = hItem; if (TreeView_GetItem(hwndTV, &tvItem)) { pTVLangItemNode = (LPTVITEMNODE) tvItem.lParam; if (!pTVLangItemNode) continue; if ((pTVLangItemNode->uInputType & INPUT_TYPE_KBD) && (pTVLangItemNode->dwLangID == dwLangID)) { if (!CompareStringTIP(tvItem.pszText, lpDefTip) || lpDefTip == NULL) return hItem; } } } } } return NULL; } //////////////////////////////////////////////////////////////////////////// // // SetNextDefaultLayout // //////////////////////////////////////////////////////////////////////////// void SetNextDefaultLayout( DWORD dwLangID, BOOL bDefLang, LPTSTR lpNextTip, UINT cchNextTip) { TV_ITEM tvItem; HTREEITEM hItem; LPLANGNODE pLangNode = NULL; LPTVITEMNODE pTVDefItemNode = NULL; hItem = FindDefaultTipItem(dwLangID, NULL); tvItem.hItem = hItem; tvItem.mask = TVIF_HANDLE | TVIF_PARAM; if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam) { pTVDefItemNode = (LPTVITEMNODE) tvItem.lParam; pLangNode = (LPLANGNODE)pTVDefItemNode->lParam; GetAtomName(pTVDefItemNode->atmTVItemName, lpNextTip, cchNextTip); if (bDefLang) { // // Select the default layout item as bold // SelectDefaultKbdLayoutAsBold(g_hwndTV, hItem); } if (pLangNode && bDefLang) pLangNode->wStatus |= (LANG_DEFAULT | LANG_DEF_CHANGE); } } //////////////////////////////////////////////////////////////////////////// // // EnsureDefaultKbdLayout // //////////////////////////////////////////////////////////////////////////// void EnsureDefaultKbdLayout(UINT *nLocales) { HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST); TV_ITEM tvItem; HTREEITEM hLangItem; HTREEITEM hGroupItem; HTREEITEM hItem; LPTVITEMNODE pTVItemNode; LPLANGNODE pLangNode = NULL; BOOL bDefLayout = FALSE; tvItem.mask = TVIF_HANDLE | TVIF_PARAM; for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ; hLangItem != NULL ; hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem)) { for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem); hGroupItem != NULL; hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem)) { for (hItem = TreeView_GetChild(hwndTV, hGroupItem); hItem != NULL; hItem = TreeView_GetNextSibling(hwndTV, hItem)) { (*nLocales)++; tvItem.hItem = hItem; if (TreeView_GetItem(hwndTV, &tvItem)) { pTVItemNode = (LPTVITEMNODE) tvItem.lParam; if (!pTVItemNode) continue; pLangNode = (LPLANGNODE)pTVItemNode->lParam; if (pLangNode == NULL && (pTVItemNode->uInputType & INPUT_TYPE_KBD) && pTVItemNode->hklSub) { if (tvItem.hItem = FindTVLangItem(pTVItemNode->dwLangID, NULL)) { if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam) { pTVItemNode = (LPTVITEMNODE) tvItem.lParam; pLangNode = (LPLANGNODE)pTVItemNode->lParam; } } } if (pLangNode == NULL) continue; if (!(pLangNode->wStatus & LANG_UNLOAD) && (pLangNode->wStatus & LANG_DEFAULT)) { bDefLayout = TRUE; } } } } } if (!bDefLayout) { LPTVITEMNODE pTVLangItemNode; for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ; hLangItem != NULL ; hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem)) { tvItem.hItem = hLangItem; if (TreeView_GetItem(hwndTV, &tvItem)) { pTVLangItemNode = (LPTVITEMNODE) tvItem.lParam; if (!pTVLangItemNode) continue; if (pTVLangItemNode->bDefLang) { for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem); hGroupItem != NULL; hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem)) { for (hItem = TreeView_GetChild(hwndTV, hGroupItem); hItem != NULL; hItem = TreeView_GetNextSibling(hwndTV, hItem)) { tvItem.hItem = hItem; if (TreeView_GetItem(hwndTV, &tvItem)) { pTVItemNode = (LPTVITEMNODE) tvItem.lParam; if (!pTVItemNode) continue; pLangNode = (LPLANGNODE)pTVItemNode->lParam; if (pLangNode == NULL && (pTVItemNode->uInputType & INPUT_TYPE_KBD) && pTVItemNode->hklSub) { if (tvItem.hItem = FindTVLangItem(pTVItemNode->dwLangID, NULL)) { if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam) { pTVItemNode = (LPTVITEMNODE) tvItem.lParam; pLangNode = (LPLANGNODE)pTVItemNode->lParam; } } } if (pLangNode == NULL) continue; if (!(pLangNode->wStatus & LANG_UNLOAD)) { pLangNode->wStatus |= LANG_DEFAULT; break; } } } } } } } } return; } //////////////////////////////////////////////////////////////////////////// // // FindTVItem // //////////////////////////////////////////////////////////////////////////// HTREEITEM FindTVItem(DWORD dwLangID, LPTSTR lpTipText) { HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST); TV_ITEM tvItem; HTREEITEM hItem; HTREEITEM hLangItem = NULL; HTREEITEM hGroupItem = NULL; LPTVITEMNODE pTVLangNode; TCHAR szLangName[ MAX_PATH ]; tvItem.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_PARAM; tvItem.pszText = szLangName; tvItem.cchTextMax = sizeof(szLangName) / sizeof(TCHAR); for (hItem = TreeView_GetChild(hwndTV, g_hTVRoot) ; hItem != NULL ; hItem = TreeView_GetNextSibling(hwndTV, hItem) ) { tvItem.hItem = hItem; if (TreeView_GetItem(hwndTV, &tvItem)) { pTVLangNode = (LPTVITEMNODE) tvItem.lParam; if (!pTVLangNode) { continue; } if (pTVLangNode->dwLangID == dwLangID) { hLangItem = hItem; } } } if (hLangItem && lpTipText) { for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem); hGroupItem != NULL; hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem)) { for (hItem = TreeView_GetChild(hwndTV, hGroupItem); hItem != NULL; hItem = TreeView_GetNextSibling(hwndTV, hItem)) { tvItem.hItem = hItem; if (TreeView_GetItem(hwndTV, &tvItem)) { if (!CompareStringTIP(tvItem.pszText, lpTipText)) { return hItem; } } } } } return NULL; } //////////////////////////////////////////////////////////////////////////// // // CheckButtons // //////////////////////////////////////////////////////////////////////////// void CheckButtons( HWND hwnd) { TV_ITEM tvItem; UINT uInputType; HTREEITEM hTVItem; LPTVITEMNODE pTVItemNode; LPLANGNODE pLangNode = NULL; hTVItem = TreeView_GetSelection(g_hwndTV); if (!hTVItem) return; tvItem.hItem = hTVItem; tvItem.mask = TVIF_HANDLE | TVIF_PARAM; if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam) { if (!(pTVItemNode = (LPTVITEMNODE) tvItem.lParam)) return; pLangNode = (LPLANGNODE)pTVItemNode->lParam; uInputType = pTVItemNode->uInputType; if ((uInputType & INPUT_TYPE_KBD) && (g_iInputs >= 2)) { EnableWindow(GetDlgItem(hwnd, IDC_KBDL_SET_DEFAULT), TRUE); } else { BOOL bKbdGroup = FALSE; if (uInputType & TV_ITEM_TYPE_LANG) { HTREEITEM hGroupItem; for (hGroupItem = TreeView_GetChild(g_hwndTV, hTVItem); hGroupItem != NULL; hGroupItem = TreeView_GetNextSibling(g_hwndTV, hGroupItem)) { tvItem.hItem = hGroupItem; if (TreeView_GetItem(g_hwndTV, &tvItem)) { LPTVITEMNODE pTVItemNode2; if (!(pTVItemNode2 = (LPTVITEMNODE) tvItem.lParam)) return; if (pTVItemNode2->uInputType & INPUT_TYPE_KBD) { bKbdGroup = TRUE; break; } } } } if (bKbdGroup && (g_iInputs >= 2)) EnableWindow(GetDlgItem(hwnd, IDC_KBDL_SET_DEFAULT), TRUE); else EnableWindow(GetDlgItem(hwnd, IDC_KBDL_SET_DEFAULT), FALSE); } if ((!g_bSetupCase) && ((pLangNode && (pLangNode->wStatus & LANG_IME) && (pLangNode->wStatus & LANG_ORIGACTIVE) && (uInputType == INPUT_TYPE_KBD) && (GetSystemMetrics(SM_IMMENABLED))) || ((uInputType & INPUT_TYPE_TIP) && !(uInputType & TV_ITEM_TYPE_GROUP)))) { EnableWindow(GetDlgItem(hwnd, IDC_KBDL_EDIT), TRUE); } else { EnableWindow(GetDlgItem(hwnd, IDC_KBDL_EDIT), FALSE); } if (g_iInputs == 1) { EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DELETE), FALSE); return; } else { EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DELETE), TRUE); } if (uInputType & TV_ITEM_TYPE_LANG) { if (!TreeView_GetNextSibling(g_hwndTV, hTVItem) && !TreeView_GetPrevSibling(g_hwndTV, hTVItem)) { EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DELETE), FALSE); } return; } else if (uInputType & TV_ITEM_TYPE_GROUP) { if (uInputType & TV_ITEM_TYPE_KBD) { if (!TreeView_GetNextSibling(g_hwndTV, hTVItem) && !TreeView_GetPrevSibling(g_hwndTV, hTVItem)) { hTVItem = TreeView_GetParent(g_hwndTV, hTVItem); if (!TreeView_GetNextSibling(g_hwndTV, hTVItem) && !TreeView_GetPrevSibling(g_hwndTV, hTVItem)) { EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DELETE), FALSE); } } else { EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DELETE), FALSE); } } return; } else if (uInputType & TV_ITEM_TYPE_KBD) { if (!TreeView_GetNextSibling(g_hwndTV, hTVItem) && !TreeView_GetPrevSibling(g_hwndTV, hTVItem)) { hTVItem = TreeView_GetParent(g_hwndTV, hTVItem); if (!TreeView_GetNextSibling(g_hwndTV, hTVItem) && !TreeView_GetPrevSibling(g_hwndTV, hTVItem)) { hTVItem = TreeView_GetParent(g_hwndTV, hTVItem); if (!TreeView_GetNextSibling(g_hwndTV, hTVItem) && !TreeView_GetPrevSibling(g_hwndTV, hTVItem)) { EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DELETE), FALSE); } } else { EnableWindow(GetDlgItem(hwnd, IDC_KBDL_DELETE), FALSE); } } return; } } } //////////////////////////////////////////////////////////////////////////// // // EnumCiceroTips // //////////////////////////////////////////////////////////////////////////// BOOL EnumCiceroTips() { ULONG ul; ULONG ulCnt; HRESULT hr; LPTIPS pTips; LANGID *plangid; UINT uInputType; BOOL bReturn = TRUE; BOOL bEnabledTip = FALSE; TCHAR szTipName[MAX_PATH]; TCHAR szTipTypeName[MAX_PATH]; IEnumTfLanguageProfiles *pEnum; ITfInputProcessorProfiles *pProfiles = NULL; ITfFnLangProfileUtil *pLangUtil = NULL; ITfCategoryMgr *pCategory = NULL; // // initialize COM // if (CoInitialize(NULL) == S_OK) g_bCoInit = TRUE; else g_bCoInit = FALSE; // // Check-up SAPI TIP registration. // hr = CoCreateInstance(&CLSID_SapiLayr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfFnLangProfileUtil, (LPVOID *) &pLangUtil); if (SUCCEEDED(hr)) { pLangUtil->lpVtbl->RegisterActiveProfiles(pLangUtil); } // // load Assembly list // hr = CoCreateInstance(&CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER, &IID_ITfInputProcessorProfiles, (LPVOID *) &pProfiles); if (FAILED(hr)) return FALSE; // // Create the new node. // if (!(g_hTips = (LPTIPS) LocalAlloc(LHND, ALLOCBLOCK * sizeof(TIPS)))) { return FALSE; } g_nTipsBuffSize = ALLOCBLOCK; g_iTipsBuff = 0; g_lpTips = LocalLock(g_hTips); // // Enum all available languages // if (SUCCEEDED(pProfiles->lpVtbl->EnumLanguageProfiles(pProfiles, 0, &pEnum))) { TF_LANGUAGEPROFILE tflp; CLSID clsid; GUID guidProfile; while (pEnum->lpVtbl->Next(pEnum, 1, &tflp, NULL) == S_OK) { BSTR bstr = NULL; BSTR bstr2 = NULL; LANGID langid = tflp.langid; BOOL bNoCategory = FALSE; hr = pProfiles->lpVtbl->GetLanguageProfileDescription( pProfiles, &tflp.clsid, tflp.langid, &tflp.guidProfile, &bstr); if (FAILED(hr)) continue; StringCchCopy(szTipName, ARRAYSIZE(szTipName), bstr); if (IsEqualGUID(&tflp.catid, &GUID_TFCAT_TIP_KEYBOARD)) { StringCchCopy(szTipTypeName, ARRAYSIZE(szTipTypeName), szInputTypeKbd); uInputType = INPUT_TYPE_KBD; } else if (IsEqualGUID(&tflp.catid, &GUID_TFCAT_TIP_HANDWRITING)) { StringCchCopy(szTipTypeName, ARRAYSIZE(szTipTypeName), szInputTypePen); uInputType = INPUT_TYPE_PEN; } else if (IsEqualGUID(&tflp.catid, &GUID_TFCAT_TIP_SPEECH)) { StringCchCopy(szTipTypeName, ARRAYSIZE(szTipTypeName), szInputTypeSpeech); uInputType = INPUT_TYPE_SPEECH; bNoCategory = TRUE; } else { g_bExtraTip = TRUE; uInputType = INPUT_TYPE_EXTERNAL; if (pCategory == NULL) { hr = CoCreateInstance(&CLSID_TF_CategoryMgr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfCategoryMgr, (LPVOID *) &pCategory); if (FAILED(hr)) return FALSE; } if (pCategory->lpVtbl->GetGUIDDescription(pCategory, &tflp.catid, &bstr2) == S_OK) { StringCchCopy(szTipTypeName, ARRAYSIZE(szTipTypeName), bstr2); } else { StringCchCopy(szTipTypeName, ARRAYSIZE(szTipTypeName), szInputTypeExternal); } if (IsEqualGUID(&tflp.catid, &GUID_TFCAT_TIP_SMARTTAG)) { bNoCategory = TRUE; uInputType |= INPUT_TYPE_SMARTTAG; } } uInputType |= INPUT_TYPE_TIP; if (g_iTipsBuff + 1 == g_nTipsBuffSize) { HANDLE hTemp; LocalUnlock(g_hTips); g_nTipsBuffSize += ALLOCBLOCK; hTemp = LocalReAlloc(g_hTips, g_nTipsBuffSize * sizeof(TIPS), LHND); if (hTemp == NULL) return FALSE; g_hTips = hTemp; g_lpTips = LocalLock(g_hTips); } g_lpTips[g_iTipsBuff].dwLangID = (DWORD) langid; g_lpTips[g_iTipsBuff].uInputType = uInputType; g_lpTips[g_iTipsBuff].atmTipText = AddAtom(szTipName); g_lpTips[g_iTipsBuff].clsid = tflp.clsid; g_lpTips[g_iTipsBuff].guidProfile = tflp.guidProfile; g_lpTips[g_iTipsBuff].bNoAddCat = bNoCategory; if (pProfiles->lpVtbl->GetDefaultLanguageProfile(pProfiles, langid, &tflp.catid, &clsid, &guidProfile) == S_OK) { if (IsEqualGUID(&tflp.guidProfile, &guidProfile)) g_lpTips[g_iTipsBuff].bDefault = TRUE; } if (uInputType & INPUT_TYPE_KBD) { g_lpTips[g_iTipsBuff].hklSub = GetSubstituteHKL(&tflp.clsid, tflp.langid, &tflp.guidProfile); } pProfiles->lpVtbl->IsEnabledLanguageProfile(pProfiles, &tflp.clsid, tflp.langid, &tflp.guidProfile, &bEnabledTip); // we need a special care for speech here, because: // // - speech TIP uses -1 profile with disabled status // // - when a user start a session, either this control // panel or first Cicero app, it'll fire off setting up // per user profiles based on SR engines currently // installed and available on the machine // // - speech TIP also fires off the logic when any SR // engines are added or removed // // to make this senario work, we have to check with // speech TIP's ITfFnProfileUtil interface each time // we invoke "Add Input Language" dialog box. // if (pLangUtil && (uInputType & INPUT_TYPE_SPEECH)) { BOOL fSpeechAvailable = FALSE; pLangUtil->lpVtbl->IsProfileAvailableForLang( pLangUtil, langid, &fSpeechAvailable ); g_lpTips[g_iTipsBuff].fEngineAvailable = fSpeechAvailable; } // // Enable pen and speech category adding options if user has the // installed pen or speech items. // if ((!g_bPenOrSapiTip) && ((uInputType & INPUT_TYPE_PEN) || g_lpTips[g_iTipsBuff].fEngineAvailable)) g_bPenOrSapiTip = TRUE; if (bEnabledTip && langid) { TCHAR szLangName[MAX_PATH]; LPTVITEMNODE pTVItemNode; LPTVITEMNODE pTVLangItemNode; GetLanguageName(MAKELCID(langid, SORT_DEFAULT), szLangName, ARRAYSIZE(szLangName)); if (!(pTVLangItemNode = CreateTVItemNode(langid))) { bReturn = FALSE; break; } if (pTVLangItemNode->hklSub) pTVLangItemNode->atmDefTipName = AddAtom(szTipName); AddTreeViewItems(TV_ITEM_TYPE_LANG, szLangName, NULL, NULL, &pTVLangItemNode); if (!(pTVItemNode = CreateTVItemNode(langid))) { bReturn = FALSE; break; } pTVItemNode->uInputType = uInputType; pTVItemNode->iIdxTips = g_iTipsBuff; pTVItemNode->clsid = tflp.clsid; pTVItemNode->guidProfile = tflp.guidProfile; pTVItemNode->hklSub = g_lpTips[g_iTipsBuff].hklSub; pTVItemNode->bNoAddCat = g_lpTips[g_iTipsBuff].bNoAddCat; // // Make sure the loading TIP substitute hkl // if (pTVItemNode->hklSub) { TCHAR szSubhkl[10]; HKL hklNew; StringCchPrintf(szSubhkl, ARRAYSIZE(szSubhkl), TEXT("%08x"), (DWORD)(UINT_PTR)pTVItemNode->hklSub); hklNew = LoadKeyboardLayout(szSubhkl, KLF_SUBSTITUTE_OK | KLF_REPLACELANG | KLF_NOTELLSHELL); if (hklNew != pTVItemNode->hklSub) { pTVItemNode->hklSub = 0; g_lpTips[g_iTipsBuff].hklSub = 0; } } AddTreeViewItems(uInputType, szLangName, szTipTypeName, szTipName, &pTVItemNode); g_lpTips[g_iTipsBuff].bEnabled = TRUE; g_iEnabledTips++; if (uInputType & INPUT_TYPE_KBD) g_iEnabledKbdTips++; } g_iTipsBuff++; if (bstr) SysFreeString(bstr); if (bstr2) SysFreeString(bstr2); } pEnum->lpVtbl->Release(pEnum); } if (pCategory) pCategory->lpVtbl->Release(pCategory); if (pLangUtil) pLangUtil->lpVtbl->Release(pLangUtil); if (pProfiles) pProfiles->lpVtbl->Release(pProfiles); return bReturn; } //////////////////////////////////////////////////////////////////////////// // // SaveLanguageProfileStatus // //////////////////////////////////////////////////////////////////////////// LRESULT SaveLanguageProfileStatus( BOOL bSave, int iIdxTip, HKL hklSub) { HRESULT hr; UINT idx; int iIdxDef = -1; int iIdxDefTip = -1; ITfInputProcessorProfiles *pProfiles = NULL; // // load Assembly list // hr = CoCreateInstance(&CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER, &IID_ITfInputProcessorProfiles, (LPVOID *) &pProfiles); if (FAILED(hr)) return S_FALSE; if (bSave) { ITfFnLangProfileUtil *pLangUtil = NULL; for (idx = 0; idx < g_iTipsBuff; idx++) { hr = pProfiles->lpVtbl->EnableLanguageProfile( pProfiles, &(g_lpTips[idx].clsid), (LANGID)g_lpTips[idx].dwLangID, &(g_lpTips[idx].guidProfile), g_lpTips[idx].bEnabled); if (FAILED(hr)) goto Exit; } hr = CoCreateInstance(&CLSID_SapiLayr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfFnLangProfileUtil, (LPVOID *) &pLangUtil); if (S_OK == hr) { pLangUtil->lpVtbl->RegisterActiveProfiles(pLangUtil); pLangUtil->lpVtbl->Release(pLangUtil); } } if (hklSub && iIdxTip != -1 && iIdxTip < (int)g_iTipsBuff) { BOOL bFound = FALSE; TCHAR szItem[MAX_PATH]; TCHAR szDefLayout[MAX_PATH]; HWND hwndDefList = GetDlgItem(g_hDlg, IDC_LOCALE_DEFAULT); szDefLayout[0] = L'\0'; // // Get the current selection in the input locale list. // if ((iIdxDef = ComboBox_GetCurSel(hwndDefList)) != CB_ERR) { WCHAR *pwchar; SendMessage(hwndDefList, CB_GETLBTEXT, iIdxDef, (LPARAM)szItem); pwchar = wcschr(szItem, L'-'); if (pwchar != NULL) StringCchCopy(szDefLayout, ARRAYSIZE(szDefLayout), pwchar + 2); } GetAtomName(g_lpTips[iIdxTip].atmTipText, szItem, ARRAYSIZE(szItem)); if (lstrcmp(szItem, szDefLayout) == 0) { iIdxDefTip = iIdxTip; bFound = TRUE; } else { for (idx = 0; idx < g_iTipsBuff; idx++) { if (hklSub == g_lpTips[idx].hklSub) { GetAtomName(g_lpTips[idx].atmTipText, szItem, ARRAYSIZE(szItem)); if (lstrcmp(szItem, szDefLayout) == 0) { iIdxDefTip = idx; bFound = TRUE; break; } } } } if (bFound && iIdxDefTip != -1) { pProfiles->lpVtbl->SetDefaultLanguageProfile( pProfiles, (LANGID)g_lpTips[iIdxDefTip].dwLangID, &(g_lpTips[iIdxDefTip].clsid), &(g_lpTips[iIdxDefTip].guidProfile)); } } Exit: if (pProfiles) pProfiles->lpVtbl->Release(pProfiles); return hr; } //////////////////////////////////////////////////////////////////////////// // // UpdateToolBarSetting // //////////////////////////////////////////////////////////////////////////// void UpdateToolBarSetting() { HRESULT hr; ITfLangBarMgr *pLangBar = NULL; // // load LangBar manager // hr = CoCreateInstance(&CLSID_TF_LangBarMgr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfLangBarMgr, (LPVOID *) &pLangBar); if (SUCCEEDED(hr)) pLangBar->lpVtbl->ShowFloating(pLangBar, g_dwToolBar); if (pLangBar) pLangBar->lpVtbl->Release(pLangBar); } //////////////////////////////////////////////////////////////////////////// // // Locale_ApplyError // // Put up the given error message with the language name in it. // // NOTE: This error is NOT fatal - as we could be half way through the // list before an error occurs. The registry will already have // some information and we should let them have what comes next // as well. // //////////////////////////////////////////////////////////////////////////// int Locale_ApplyError( HWND hwnd, LPLANGNODE pLangNode, UINT iErr, UINT iStyle) { UINT idxLang, idxLayout; TCHAR sz[MAX_PATH]; TCHAR szTemp[MAX_PATH]; TCHAR szLangName[MAX_PATH * 2]; LPTSTR pszLang; // // Load in the string for the given string id. // LoadString(hInstance, iErr, sz, ARRAYSIZE(sz)); // // Get the language name to fill into the above string. // if (pLangNode) { idxLang = pLangNode->iLang; idxLayout = pLangNode->iLayout; GetAtomName(g_lpLang[idxLang].atmLanguageName, szLangName, ARRAYSIZE(szLangName)); if (g_lpLang[idxLang].dwID != g_lpLayout[idxLayout].dwID) { pszLang = szLangName + lstrlen(szLangName); pszLang[0] = TEXT(' '); pszLang[1] = TEXT('-'); pszLang[2] = TEXT(' '); GetAtomName(g_lpLayout[idxLayout].atmLayoutText, pszLang + 3, ARRAYSIZE(szLangName) - (lstrlen(szLangName) + 3)); } } else { LoadString(hInstance, IDS_UNKNOWN, szLangName, ARRAYSIZE(szLangName)); } // // Put up the error message box. // StringCchPrintf(szTemp, ARRAYSIZE(szTemp), sz, szLangName); return (MessageBox(hwnd, szTemp, NULL, iStyle)); } //////////////////////////////////////////////////////////////////////////// // // Locale_FetchIndicator // // Saves the two letter indicator symbol for the given language in the // g_lpLang array. // //////////////////////////////////////////////////////////////////////////// void Locale_FetchIndicator( LPLANGNODE pLangNode) { TCHAR szData[MAX_PATH]; LPINPUTLANG pInpLang = &g_lpLang[pLangNode->iLang]; // // Get the indicator by using the first 2 characters of the // abbreviated language name. // if (GetLocaleInfo(LOWORD(pInpLang->dwID), LOCALE_SABBREVLANGNAME | LOCALE_NOUSEROVERRIDE, szData, ARRAYSIZE(szData))) { // // Save the first two characters. // pInpLang->szSymbol[0] = szData[0]; pInpLang->szSymbol[1] = szData[1]; pInpLang->szSymbol[2] = TEXT('\0'); } else { // // Id wasn't found. Return question marks. // pInpLang->szSymbol[0] = TEXT('?'); pInpLang->szSymbol[1] = TEXT('?'); pInpLang->szSymbol[2] = TEXT('\0'); } } //////////////////////////////////////////////////////////////////////////// // // Locale_SetSecondaryControls // // Sets the secondary controls to either be enabled or disabled. // When there is only 1 active TIP, then this function will be called to // disable these controls. // //////////////////////////////////////////////////////////////////////////// void Locale_SetSecondaryControls( HWND hwndMain) { if (g_iInputs >= 2) { EnableWindow(GetDlgItem(hwndMain, IDC_HOTKEY_SETTING), TRUE); } else { EnableWindow(GetDlgItem(hwndMain, IDC_HOTKEY_SETTING), FALSE); } CheckButtons(hwndMain); } //////////////////////////////////////////////////////////////////////////// // // Locale_CommandSetDefault // // Sets the new default when the Set as Default button is pressed. // //////////////////////////////////////////////////////////////////////////// void Locale_CommandSetDefault( HWND hwnd) { int iIdxDef; int idxList; LPLANGNODE pLangNode = NULL; HWND hwndTV = GetDlgItem(hwnd, IDC_INPUT_LIST); HWND hwndDefList = GetDlgItem(hwnd, IDC_LOCALE_DEFAULT); TCHAR sz[DESC_MAX]; HTREEITEM hTVCurLangItem = NULL; HTREEITEM hTVCurItem = NULL; TV_ITEM tvItem; TV_ITEM tvItem2; HTREEITEM hItem; HTREEITEM hLangItem; HTREEITEM hGroupItem; LPTVITEMNODE pCurItemNode; LPTVITEMNODE pPrevDefItemNode; TCHAR szLangText[DESC_MAX]; TCHAR szLayoutName[DESC_MAX]; TCHAR szDefItem[MAX_PATH]; LPINPUTLANG pInpLang; WCHAR *pwchar; TCHAR szDefTip[DESC_MAX]; szLayoutName[0] = L'\0'; // // Get the current selection in the input locale list. // iIdxDef = (int) SendMessage(hwndDefList, CB_GETCURSEL, 0, 0); if (iIdxDef == CB_ERR) { //iIdxDef = 0; DWORD dwLangID; for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ; hLangItem != NULL ; hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem) ) { tvItem.hItem = hLangItem; if (TreeView_GetItem(hwndTV, &tvItem) && (pCurItemNode = (LPTVITEMNODE) tvItem.lParam)) { if (pCurItemNode->bDefLang) { dwLangID = pCurItemNode->dwLangID; GetAtomName(pCurItemNode->atmTVItemName, szLangText, ARRAYSIZE(szLangText)); break; } } } } else { SendMessage(hwndDefList, CB_GETLBTEXT, iIdxDef, (LPARAM)szDefItem); pwchar = wcschr(szDefItem, L'-'); if ((pwchar != NULL) && (szDefItem < (pwchar - 1))) { *(pwchar - 1) = TEXT('\0'); StringCchCopy(szLayoutName, ARRAYSIZE(szLayoutName), pwchar + 2); } StringCchCopy(szLangText, ARRAYSIZE(szLangText), szDefItem); } hTVCurLangItem = FindTVLangItem(0, szLangText); if (hTVCurLangItem == NULL) { // // There is no default keyboard layout on the system, so try to set // the default keyboard layout with the first available item. // if (SendMessage(hwndDefList, CB_GETLBTEXT, 0, (LPARAM)szDefItem) != CB_ERR) { pwchar = wcschr(szDefItem, L'-'); if ((pwchar != NULL) && (szDefItem < (pwchar - 1))) { *(pwchar - 1) = TEXT('\0'); StringCchCopy(szLayoutName, ARRAYSIZE(szLayoutName), pwchar + 2); } StringCchCopy(szLangText, ARRAYSIZE(szLangText), szDefItem); ComboBox_SetCurSel(hwndDefList, 0); } } else { tvItem.mask = TVIF_HANDLE | TVIF_PARAM; tvItem.hItem = hTVCurLangItem; } if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam) { // // Get the pointer to the lang node from the list box // item data. // pCurItemNode = (LPTVITEMNODE) tvItem.lParam; if (hTVCurItem = FindTVItem(pCurItemNode->dwLangID, szLayoutName)) { tvItem.hItem = hTVCurItem; if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam) { TreeView_SelectItem(hwndTV, hTVCurItem); pCurItemNode = (LPTVITEMNODE) tvItem.lParam; } } } else { // // Make sure we're not removing the only entry in the list. // MessageBeep(MB_ICONEXCLAMATION); return; } // // Find the previous default Tip. // for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ; hLangItem != NULL ; hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem) ) { tvItem.hItem = hLangItem; if (TreeView_GetItem(hwndTV, &tvItem) && (pPrevDefItemNode = (LPTVITEMNODE) tvItem.lParam)) { if (pPrevDefItemNode->bDefLang) { GetAtomName(pPrevDefItemNode->atmDefTipName, szDefTip, ARRAYSIZE(szDefTip)); UpdateDefaultTVLangItem(pPrevDefItemNode->dwLangID, szDefTip, FALSE, TRUE); UpdateLangKBDItemNode(hLangItem, szDefTip, FALSE); break; } } } pCurItemNode->bDefLang = TRUE; if (pCurItemNode->atmDefTipName) GetAtomName(pCurItemNode->atmDefTipName, szDefTip, ARRAYSIZE(szDefTip)); else GetAtomName(pCurItemNode->atmTVItemName, szDefTip, ARRAYSIZE(szDefTip)); UpdateDefaultTVLangItem(pCurItemNode->dwLangID, szDefTip, TRUE, pCurItemNode->hklSub ? TRUE : FALSE); if (!UpdateLangKBDItemNode(hTVCurLangItem, szDefTip, TRUE)) { SetNextDefaultLayout(pCurItemNode->dwLangID, pCurItemNode->bDefLang, szDefTip, ARRAYSIZE(szDefTip)); } if (pCurItemNode->uInputType & TV_ITEM_TYPE_LANG) { hItem = FindDefaultTipItem(pCurItemNode->dwLangID, szDefTip); tvItem.hItem = hItem; if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam) pCurItemNode = (LPTVITEMNODE) tvItem.lParam; // // Select the default layout item as bold // SelectDefaultKbdLayoutAsBold(hwndTV, hItem); pLangNode = (LPLANGNODE)pCurItemNode->lParam; if (pLangNode) pLangNode->wStatus |= (LANG_DEFAULT | LANG_DEF_CHANGE); } // // Enable the Apply button. // g_dwChanges |= CHANGE_DEFAULT; PropSheet_Changed(GetParent(hwnd), hwnd); } void Locale_CommandSetDefaultLayout( HWND hwnd) { TV_ITEM tvItem; HTREEITEM hTVItem; HTREEITEM hLangItem; HTREEITEM hTVCurItem; TCHAR szDefTip[DESC_MAX]; TCHAR szLangText[DESC_MAX]; LPLANGNODE pLangNode = NULL; LPTVITEMNODE pCurItemNode; LPTVITEMNODE pPrevDefItemNode; HWND hwndTV = GetDlgItem(hwnd, IDC_INPUT_LIST); // // Get the current selection layout in the input layout lists. // hTVCurItem = TreeView_GetSelection(hwndTV); if (!hTVCurItem) return; tvItem.mask = TVIF_HANDLE | TVIF_PARAM; tvItem.hItem = hTVCurItem; if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam) { // // Get the pointer to the lang node from the list box // item data. // pCurItemNode = (LPTVITEMNODE) tvItem.lParam; } else { // // Make sure we're not removing the only entry in the list. // MessageBeep(MB_ICONEXCLAMATION); return; } // // Find the previous default Tip. // for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ; hLangItem != NULL ; hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem) ) { tvItem.hItem = hLangItem; if (TreeView_GetItem(hwndTV, &tvItem) && (pPrevDefItemNode = (LPTVITEMNODE) tvItem.lParam)) { if (pPrevDefItemNode->bDefLang) { if (pPrevDefItemNode->atmDefTipName) GetAtomName(pPrevDefItemNode->atmDefTipName, szDefTip, ARRAYSIZE(szDefTip)); else GetAtomName(pPrevDefItemNode->atmTVItemName, szDefTip, ARRAYSIZE(szDefTip)); UpdateDefaultTVLangItem(pPrevDefItemNode->dwLangID, szDefTip, FALSE, TRUE); UpdateLangKBDItemNode(hLangItem, szDefTip, FALSE); break; } } } if (pCurItemNode->atmDefTipName) GetAtomName(pCurItemNode->atmDefTipName, szDefTip, ARRAYSIZE(szDefTip)); else GetAtomName(pCurItemNode->atmTVItemName, szDefTip, ARRAYSIZE(szDefTip)); UpdateDefaultTVLangItem(pCurItemNode->dwLangID, szDefTip, TRUE, pCurItemNode->hklSub ? TRUE : FALSE); pCurItemNode->bDefLang = TRUE; pLangNode = (LPLANGNODE)pCurItemNode->lParam; if (pLangNode) pLangNode->wStatus |= (LANG_DEFAULT | LANG_DEF_CHANGE); if (hTVItem = FindTVLangItem(pCurItemNode->dwLangID, NULL)) { int idxSel = -1; TCHAR szDefItem[MAX_PATH]; HWND hwndDefList = GetDlgItem(g_hDlg, IDC_LOCALE_DEFAULT); tvItem.mask = TVIF_HANDLE | TVIF_PARAM; tvItem.hItem = hTVItem; if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam) { LPTVITEMNODE pTVItemNode; pTVItemNode = (LPTVITEMNODE) tvItem.lParam; GetAtomName(pTVItemNode->atmTVItemName, szLangText, ARRAYSIZE(szLangText)); } StringCchCopy(szDefItem, ARRAYSIZE(szDefItem), szLangText); StringCchCat(szDefItem, ARRAYSIZE(szDefItem), TEXT(" - ")); StringCchCat(szDefItem, ARRAYSIZE(szDefItem), szDefTip); // // Set the default locale selection. // if ((idxSel = ComboBox_FindStringExact(hwndDefList, 0, szDefItem)) != CB_ERR) ComboBox_SetCurSel(hwndDefList, idxSel); } SelectDefaultKbdLayoutAsBold(hwndTV, FindDefaultTipItem(pCurItemNode->dwLangID, szDefTip)); // // Enable the Apply button. // g_dwChanges |= CHANGE_DEFAULT; PropSheet_Changed(GetParent(hwnd), hwnd); } //////////////////////////////////////////////////////////////////////////// // // GetLanguageHotkeyFromRegistry() // //////////////////////////////////////////////////////////////////////////// BOOL GetLanguageHotkeyFromRegistry( LPTSTR lpLangKey, UINT cchLangKey, LPTSTR lpLayoutKey, UINT cchLayoutKey) { DWORD cb; HKEY hkey; lpLangKey[0] = 0; StringCchCopy(lpLayoutKey, cchLayoutKey, TEXT("3")); if (RegOpenKey(HKEY_CURRENT_USER, c_szKbdToggleKey, &hkey) == ERROR_SUCCESS) { cb = sizeof(lpLangKey); RegQueryValueEx(hkey, g_OSWIN95? NULL : c_szToggleHotKey, NULL, NULL, (LPBYTE)lpLangKey, &cb); if (g_iEnabledKbdTips) { StringCchCopy(lpLangKey, cchLangKey, TEXT("1")); RegQueryValueEx(hkey, c_szToggleLang, NULL, NULL, (LPBYTE)lpLangKey, &cb); } if (RegQueryValueEx(hkey, c_szToggleLayout, NULL, NULL, (LPBYTE)lpLayoutKey, &cb) != ERROR_SUCCESS) { if (lstrcmp(lpLangKey, TEXT("1")) == 0) { lpLayoutKey[0] = TEXT('2'); lpLayoutKey[1] = TEXT('\0'); } if (lstrcmp(lpLangKey, TEXT("2")) == 0) { lpLayoutKey[0] = TEXT('1'); lpLayoutKey[1] = TEXT('\0'); } else { lpLayoutKey[0] = TEXT('3'); lpLayoutKey[1] = TEXT('\0'); } if (GetSystemMetrics(SM_MIDEASTENABLED)) { lpLayoutKey[0] = TEXT('3'); lpLayoutKey[1] = TEXT('\0'); } } if (lstrcmp(lpLangKey, lpLayoutKey) == 0) StringCchCopy(lpLayoutKey, cchLayoutKey, TEXT("3")); RegCloseKey(hkey); return TRUE; } else return FALSE; } //////////////////////////////////////////////////////////////////////////// // // Locale_SetDefaultHotKey // // Set the default hotkey for a locale switch. // //////////////////////////////////////////////////////////////////////////// void Locale_SetDefaultHotKey( HWND hwnd, BOOL bAdd) { LPHOTKEYINFO pHotKeyNode; BOOL bReset = FALSE; // // Initialize lang hotkey value to switch between lnaguages. // if (g_bGetSwitchLangHotKey) { TCHAR szItem[DESC_MAX]; TCHAR sz[10]; TCHAR sz2[10]; g_SwitchLangHotKey.dwHotKeyID = HOTKEY_SWITCH_LANG; g_SwitchLangHotKey.fdwEnable = MOD_CONTROL | MOD_ALT | MOD_SHIFT; LoadString( hInstance, IDS_KBD_SWITCH_LOCALE, szItem, sizeof(szItem) / sizeof(TCHAR) ); g_SwitchLangHotKey.atmHotKeyName = AddAtom(szItem); if (!GetLanguageHotkeyFromRegistry(sz, ARRAYSIZE(sz), sz2, ARRAYSIZE(sz2))) { g_SwitchLangHotKey.uModifiers = 0; g_SwitchLangHotKey.uLayoutHotKey = 0; g_SwitchLangHotKey.uVKey = 0; } else { // // Set the modifiers. // if (sz[1] == 0) { switch (sz[0]) { case ( TEXT('1') ) : { g_SwitchLangHotKey.uModifiers = MOD_ALT | MOD_SHIFT; break; } case ( TEXT('2') ) : { g_SwitchLangHotKey.uModifiers = MOD_CONTROL | MOD_SHIFT; break; } case ( TEXT('3') ) : { g_SwitchLangHotKey.uModifiers = 0; break; } case ( TEXT('4') ) : { g_SwitchLangHotKey.uModifiers = 0; g_SwitchLangHotKey.uVKey = CHAR_GRAVE; break; } } } // // Get the layout hotkey from the registry // if (sz2[1] == 0) { switch (sz2[0]) { case ( TEXT('1') ) : { g_SwitchLangHotKey.uLayoutHotKey = MOD_ALT | MOD_SHIFT; break; } case ( TEXT('2') ) : { g_SwitchLangHotKey.uLayoutHotKey = MOD_CONTROL | MOD_SHIFT; break; } case ( TEXT('3') ) : { g_SwitchLangHotKey.uLayoutHotKey = 0; break; } case ( TEXT('4') ) : { g_SwitchLangHotKey.uLayoutHotKey = 0; g_SwitchLangHotKey.uVKey = CHAR_GRAVE; break; } } } } g_bGetSwitchLangHotKey = FALSE; } // // Get language switch hotkey // pHotKeyNode = (LPHOTKEYINFO) &g_SwitchLangHotKey; // // Check the current hotkey setting // if ((bAdd && g_iInputs >= 2) && (g_SwitchLangHotKey.uModifiers == 0 && g_SwitchLangHotKey.uLayoutHotKey == 0 && g_SwitchLangHotKey.uVKey == 0)) { bReset = TRUE; } if (bAdd && (g_iInputs == 2 || bReset)) { if (g_dwPrimLangID == LANG_THAI && g_iThaiLayout) { pHotKeyNode->uVKey = CHAR_GRAVE; pHotKeyNode->uModifiers &= ~(MOD_CONTROL | MOD_ALT | MOD_SHIFT); } else pHotKeyNode->uModifiers = MOD_ALT | MOD_SHIFT; if (g_bMESystem) { pHotKeyNode->uVKey = CHAR_GRAVE; pHotKeyNode->uLayoutHotKey &= ~(MOD_CONTROL | MOD_ALT | MOD_SHIFT); } else if (pHotKeyNode->uModifiers & MOD_CONTROL) pHotKeyNode->uLayoutHotKey = MOD_ALT; else pHotKeyNode->uLayoutHotKey = MOD_CONTROL; g_dwChanges |= CHANGE_LANGSWITCH; } if (!bAdd) { if (g_iInputs == 1) { // // Remove the locale hotkey, since it's no longer required. // pHotKeyNode->uVKey = 0; pHotKeyNode->uModifiers &= ~(MOD_CONTROL | MOD_ALT | MOD_SHIFT); pHotKeyNode->uLayoutHotKey &= ~(MOD_CONTROL | MOD_ALT | MOD_SHIFT); g_dwChanges |= CHANGE_LANGSWITCH; } else if ((g_dwPrimLangID == LANG_THAI && !g_iThaiLayout) && (pHotKeyNode->uVKey == CHAR_GRAVE)) { // // Reset the locale switch hotkey from Grave accent to // Left-Alt + Shift. // pHotKeyNode->uVKey = 0; if (pHotKeyNode->uLayoutHotKey & MOD_ALT) pHotKeyNode->uModifiers = MOD_CONTROL | MOD_SHIFT; else pHotKeyNode->uModifiers = MOD_ALT | MOD_SHIFT; g_dwChanges |= CHANGE_LANGSWITCH; } } } //////////////////////////////////////////////////////////////////////////// // // Locale_SetLanguageHotkey // // Set the language switch hotkey on the registry. // //////////////////////////////////////////////////////////////////////////// void Locale_SetLanguageHotkey() { UINT idx, idx2; HKEY hkeyToggle; TCHAR szTemp[10], szTemp2[10]; LPHOTKEYINFO pHotKeyNode; // // Get language switch hotkey // pHotKeyNode = (LPHOTKEYINFO) &g_SwitchLangHotKey; idx = 3; idx2 = 3; if (pHotKeyNode->uModifiers & MOD_ALT) { idx = 1; } else if (pHotKeyNode->uModifiers & MOD_CONTROL) { idx = 2; } else if (g_iThaiLayout && pHotKeyNode->uVKey == CHAR_GRAVE) { idx = 4; } if (pHotKeyNode->uLayoutHotKey & MOD_ALT) { idx2 = 1; } else if (pHotKeyNode->uLayoutHotKey & MOD_CONTROL) { idx2 = 2; } else if (g_bMESystem && pHotKeyNode->uVKey == CHAR_GRAVE) { idx2 = 4; } // // Get the toggle hotkey as a string so that it can be written // into the registry (as data). // StringCchPrintf(szTemp, ARRAYSIZE(szTemp), TEXT("%d"), idx); StringCchPrintf(szTemp2, ARRAYSIZE(szTemp2), TEXT("%d"), idx2); // // Set the new entry in the registry. It is of the form: // // HKCU\Keyboard Layout // Toggle: Hotkey = // if (RegCreateKey(HKEY_CURRENT_USER, c_szKbdToggleKey, &hkeyToggle ) == ERROR_SUCCESS) { RegSetValueEx(hkeyToggle, g_OSWIN95? NULL : c_szToggleHotKey, 0, REG_SZ, (LPBYTE)szTemp, (DWORD)(lstrlen(szTemp) + 1) * sizeof(TCHAR) ); RegSetValueEx(hkeyToggle, c_szToggleLang, 0, REG_SZ, (LPBYTE)szTemp, (DWORD)(lstrlen(szTemp) + 1) * sizeof(TCHAR) ); RegSetValueEx(hkeyToggle, c_szToggleLayout, 0, REG_SZ, (LPBYTE)szTemp2, (DWORD)(lstrlen(szTemp2) + 1) * sizeof(TCHAR) ); RegCloseKey(hkeyToggle); } // // Since we updated the registry, we should reread this next time. // g_bGetSwitchLangHotKey = TRUE; // // Call SystemParametersInfo to enable the toggle. // SystemParametersInfo(SPI_SETLANGTOGGLE, 0, NULL, 0); } //////////////////////////////////////////////////////////////////////////// // // Locale_FileExists // // Determines if the file exists and is accessible. // //////////////////////////////////////////////////////////////////////////// BOOL Locale_FileExists( LPTSTR pFileName) { WIN32_FIND_DATA FindData; HANDLE FindHandle; BOOL bRet; UINT OldMode; OldMode = SetErrorMode(SEM_FAILCRITICALERRORS); FindHandle = FindFirstFile(pFileName, &FindData); if (FindHandle == INVALID_HANDLE_VALUE) { bRet = FALSE; } else { FindClose(FindHandle); bRet = TRUE; } SetErrorMode(OldMode); return (bRet); } //////////////////////////////////////////////////////////////////////////// // // Locale_GetHotkeys // // Gets the hotkey keyboard switch value from the registry and then // sets the appropriate radio button in the dialog. // //////////////////////////////////////////////////////////////////////////// void Locale_GetHotkeys( HWND hwnd, BOOL *bHasIme) { TCHAR sz[10]; TCHAR sz2[10]; int ctr1, iLangCount, iCount; UINT iIndex; TCHAR szLanguage[DESC_MAX]; TCHAR szLayout[DESC_MAX]; TCHAR szItem[DESC_MAX]; TCHAR szAction[DESC_MAX]; LPLANGNODE pLangNode; HWND hwndTV = g_hwndTV; HWND hwndHotkey = GetDlgItem(hwnd, IDC_KBDL_HOTKEY_LIST); LPHOTKEYINFO aImeHotKey; TV_ITEM tvItem; HTREEITEM hItem; HTREEITEM hLangItem; HTREEITEM hGroupItem; // // Clear out the hot keys list box. // ListBox_ResetContent(hwndHotkey); // // Get the hotkey value to switch between locales from the registry. // if (g_bGetSwitchLangHotKey) { g_SwitchLangHotKey.dwHotKeyID = HOTKEY_SWITCH_LANG; g_SwitchLangHotKey.fdwEnable = MOD_CONTROL | MOD_ALT | MOD_SHIFT; LoadString( hInstance, IDS_KBD_SWITCH_LOCALE, szItem, sizeof(szItem) / sizeof(TCHAR) ); g_SwitchLangHotKey.atmHotKeyName = AddAtom(szItem); if (!GetLanguageHotkeyFromRegistry(sz, ARRAYSIZE(sz), sz2, ARRAYSIZE(sz2))) { g_SwitchLangHotKey.uModifiers = 0; g_SwitchLangHotKey.uLayoutHotKey = 0; g_SwitchLangHotKey.uVKey = 0; } else { // // Set the modifiers. // if (sz[1] == 0) { switch (sz[0]) { case ( TEXT('1') ) : { g_SwitchLangHotKey.uModifiers = MOD_ALT | MOD_SHIFT; break; } case ( TEXT('2') ) : { g_SwitchLangHotKey.uModifiers = MOD_CONTROL | MOD_SHIFT; break; } case ( TEXT('3') ) : { g_SwitchLangHotKey.uModifiers = 0; break; } case ( TEXT('4') ) : { g_SwitchLangHotKey.uModifiers = 0; g_SwitchLangHotKey.uVKey = CHAR_GRAVE; break; } } } // // Get the layout hotkey from the registry // if (sz2[1] == 0) { switch (sz2[0]) { case ( TEXT('1') ) : { g_SwitchLangHotKey.uLayoutHotKey = MOD_ALT | MOD_SHIFT; break; } case ( TEXT('2') ) : { g_SwitchLangHotKey.uLayoutHotKey = MOD_CONTROL | MOD_SHIFT; break; } case ( TEXT('3') ) : { g_SwitchLangHotKey.uLayoutHotKey = 0; break; } case ( TEXT('4') ) : { g_SwitchLangHotKey.uLayoutHotKey = 0; g_SwitchLangHotKey.uVKey = CHAR_GRAVE; break; } } } g_bGetSwitchLangHotKey = FALSE; } } iIndex = ListBox_InsertString(hwndHotkey, -1, szItem); ListBox_SetItemData(hwndHotkey, iIndex, (LONG_PTR)&g_SwitchLangHotKey); // // Determine the hotkey value for direct locale switch. // // Query all available direct switch hotkey IDs and put the // corresponding hkl, key, and modifiers information into the array. // for (ctr1 = 0; ctr1 < DSWITCH_HOTKEY_SIZE; ctr1++) { BOOL fRet; g_aDirectSwitchHotKey[ctr1].dwHotKeyID = IME_HOTKEY_DSWITCH_FIRST + ctr1; g_aDirectSwitchHotKey[ctr1].fdwEnable = MOD_VIRTKEY | MOD_CONTROL | MOD_ALT | MOD_SHIFT | MOD_LEFT | MOD_RIGHT; g_aDirectSwitchHotKey[ctr1].idxLayout = -1; fRet = ImmGetHotKey( g_aDirectSwitchHotKey[ctr1].dwHotKeyID, &g_aDirectSwitchHotKey[ctr1].uModifiers, &g_aDirectSwitchHotKey[ctr1].uVKey, &g_aDirectSwitchHotKey[ctr1].hkl ); if (!fRet) { g_aDirectSwitchHotKey[ctr1].uModifiers = 0; if ((g_aDirectSwitchHotKey[ctr1].fdwEnable & (MOD_LEFT | MOD_RIGHT)) == (MOD_LEFT | MOD_RIGHT)) { g_aDirectSwitchHotKey[ctr1].uModifiers |= MOD_LEFT | MOD_RIGHT; } g_aDirectSwitchHotKey[ctr1].uVKey = 0; g_aDirectSwitchHotKey[ctr1].hkl = (HKL)NULL; } } LoadString( hInstance, IDS_KBD_SWITCH_TO, szAction, sizeof(szAction) / sizeof(TCHAR) ); // // Try to find either a matching hkl or empty spot in the array // for each of the hkls in the locale list. // for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ; hLangItem != NULL ; hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem) ) { for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem); hGroupItem != NULL; hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem)) { for (hItem = TreeView_GetChild(hwndTV, hGroupItem); hItem != NULL; hItem = TreeView_GetNextSibling(hwndTV, hItem)) { int ctr2; int iEmpty = -1; int iMatch = -1; LPTVITEMNODE pTVItemNode; tvItem.hItem = hItem; tvItem.mask = TVIF_HANDLE | TVIF_PARAM; if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam) { pTVItemNode = (LPTVITEMNODE) tvItem.lParam; pLangNode = (LPLANGNODE)pTVItemNode->lParam; } else break; if (pLangNode == NULL && (pTVItemNode->uInputType & INPUT_TYPE_KBD) && pTVItemNode->hklSub) { if (tvItem.hItem = FindTVLangItem(pTVItemNode->dwLangID, NULL)) { if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam) { pTVItemNode = (LPTVITEMNODE) tvItem.lParam; pLangNode = (LPLANGNODE)pTVItemNode->lParam; } } } if (pLangNode == NULL) continue; for (ctr2 = 0; ctr2 < DSWITCH_HOTKEY_SIZE; ctr2++) { if (!g_aDirectSwitchHotKey[ctr2].hkl) { if ((iEmpty == -1) && (g_aDirectSwitchHotKey[ctr2].idxLayout == -1)) { // // Remember the first empty spot. // iEmpty = ctr2; } } else if (g_aDirectSwitchHotKey[ctr2].hkl == pLangNode->hkl) { // // We found a match. Remember it. // iMatch = ctr2; break; } } if (iMatch == -1) { if (iEmpty == -1) { // // We don't have any spots left. // continue; } else { // // New item. // iMatch = iEmpty; if (pLangNode->hkl) { g_aDirectSwitchHotKey[iMatch].hkl = pLangNode->hkl; } else { // // This must be a newly added layout. We don't have // the hkl yet. Remember the index position of this // layout - we can get the real hkl when the user // chooses to apply. // g_aDirectSwitchHotKey[iMatch].idxLayout = ctr1; } } } if (pLangNode->wStatus & LANG_IME) { *bHasIme = TRUE; } if (pLangNode->wStatus & LANG_HOTKEY) { g_aDirectSwitchHotKey[iMatch].uModifiers = pLangNode->uModifiers; g_aDirectSwitchHotKey[iMatch].uVKey = pLangNode->uVKey; } GetAtomName(g_lpLang[pLangNode->iLang].atmLanguageName, szLanguage, ARRAYSIZE(szLanguage)); GetAtomName(g_lpLayout[pLangNode->iLayout].atmLayoutText, szLayout, ARRAYSIZE(szLayout)); StringCchCat(szLanguage, ARRAYSIZE(szLanguage), TEXT(" - ")); StringCchCat(szLanguage, ARRAYSIZE(szLanguage), szLayout); StringCchPrintf(szItem, ARRAYSIZE(szItem), szAction, szLanguage); if (ListBox_FindStringExact(hwndHotkey, 0, szItem) != CB_ERR) continue; g_aDirectSwitchHotKey[iMatch].atmHotKeyName = AddAtom(szItem); iIndex = ListBox_InsertString(hwndHotkey, -1, szItem); ListBox_SetItemData(hwndHotkey, iIndex, &g_aDirectSwitchHotKey[iMatch]); } } } // // Determine IME specific hotkeys for CHS and CHT locales. // iCount = *bHasIme ? Locale_GetImeHotKeyInfo(hwnd,&aImeHotKey) : 0; for (ctr1 = 0; ctr1 < iCount; ctr1++) { BOOL bRet; LoadString( hInstance, aImeHotKey[ctr1].idHotKeyName, szItem, sizeof(szItem) / sizeof(TCHAR) ); aImeHotKey[ctr1].atmHotKeyName = AddAtom(szItem); iIndex = ListBox_InsertString(hwndHotkey, -1,szItem); ListBox_SetItemData(hwndHotkey, iIndex, &aImeHotKey[ctr1]); // // Get the hot key value. // bRet = ImmGetHotKey( aImeHotKey[ctr1].dwHotKeyID, &aImeHotKey[ctr1].uModifiers, &aImeHotKey[ctr1].uVKey, NULL ); if (!bRet) { aImeHotKey[ctr1].uModifiers = 0; if ((aImeHotKey[ctr1].fdwEnable & (MOD_LEFT | MOD_RIGHT)) == (MOD_LEFT | MOD_RIGHT)) { aImeHotKey[ctr1].uModifiers |= MOD_LEFT | MOD_RIGHT; } aImeHotKey[ctr1].uVKey = 0; aImeHotKey[ctr1].hkl = (HKL)NULL; } } ListBox_SetCurSel(hwndHotkey, 0); } //////////////////////////////////////////////////////////////////////////// // // Locale_SetImmHotkey // //////////////////////////////////////////////////////////////////////////// void Locale_SetImmHotkey( HWND hwnd, LPLANGNODE pLangNode, UINT nLangs, HKL * pLangs, BOOL *bDirectSwitch) { int ctr1; HKL hkl; BOOL bRet; UINT uVKey; UINT uModifiers; int iEmpty = -1; int iMatch = -1; LPHOTKEYINFO pHotKeyNode; if (pLangNode == NULL) return; for (ctr1 = 0; ctr1 < DSWITCH_HOTKEY_SIZE; ctr1++) { if (!g_aDirectSwitchHotKey[ctr1].hkl) { if ((iEmpty == -1) && (g_aDirectSwitchHotKey[ctr1].idxLayout == -1)) { // // Remember the first empty spot. // iEmpty = ctr1; } } else if (g_aDirectSwitchHotKey[ctr1].hkl == pLangNode->hkl) { // // We found a match. Remember it. // iMatch = ctr1; break; } } if (iMatch == -1) { if (iEmpty == -1) { // // We don't have any spots left. // return; } else { // // New item. // iMatch = iEmpty; if (pLangNode->hkl) { g_aDirectSwitchHotKey[iMatch].hkl = pLangNode->hkl; } else { // // This must be a newly added layout. We don't have // the hkl yet. Remember the index position of this // layout - we can get the real hkl when the user // chooses to apply. // g_aDirectSwitchHotKey[iMatch].idxLayout = ctr1; } } } if (iMatch == -1) return; // // Get Hotkey information for current layout. // pHotKeyNode = (LPHOTKEYINFO) &g_aDirectSwitchHotKey[iMatch]; bRet = ImmGetHotKey(pHotKeyNode->dwHotKeyID, &uModifiers, &uVKey, &hkl); if (!bRet && (!pHotKeyNode->uVKey) && ((pHotKeyNode->uModifiers & (MOD_ALT | MOD_CONTROL | MOD_SHIFT)) != (MOD_ALT | MOD_CONTROL | MOD_SHIFT))) { // // No such hotkey exists. User does not specify key and modifier // information either. We can skip this one. // return; } if ((pHotKeyNode->uModifiers == uModifiers) && (pHotKeyNode->uVKey == uVKey)) { // // No change. // if (IS_DIRECT_SWITCH_HOTKEY(pHotKeyNode->dwHotKeyID)) { *bDirectSwitch = TRUE; } return; } if (pHotKeyNode->idxLayout != -1) { // // We had this layout index remembered because at that time // we did not have a real hkl to work with. Now it is // time to get the real hkl. // pHotKeyNode->hkl = pLangNode->hkl; } if (!bRet && IS_DIRECT_SWITCH_HOTKEY(pHotKeyNode->dwHotKeyID)) { // // New direct switch hotkey ID. We need to see if the same // hkl is set at another ID. If so, set the other ID instead // of the one requested. // DWORD dwHotKeyID; // // Loop through all direct switch hotkeys. // for (dwHotKeyID = IME_HOTKEY_DSWITCH_FIRST; (dwHotKeyID <= IME_HOTKEY_DSWITCH_LAST); dwHotKeyID++) { if (dwHotKeyID == pHotKeyNode->dwHotKeyID) { // // Skip itself. // continue; } bRet = ImmGetHotKey(dwHotKeyID, &uModifiers, &uVKey, &hkl); if (!bRet) { // // Did not find the hotkey id. Skip. // continue; } if (hkl == pHotKeyNode->hkl) { // // We found the same hkl already with hotkey // settings at another ID. Set hotkey // ID equal to the one with the same hkl. So later // we will modify hotkey for the correct hkl. // pHotKeyNode->dwHotKeyID = dwHotKeyID; break; } } } // // Set the hotkey value. // bRet = ImmSetHotKey( pHotKeyNode->dwHotKeyID, pHotKeyNode->uModifiers, pHotKeyNode->uVKey, pHotKeyNode->hkl ); if (bRet) { // // Hotkey set successfully. See if user used any direct // switch hot key. We may have to load imm later. // if (IS_DIRECT_SWITCH_HOTKEY(pHotKeyNode->dwHotKeyID)) { if (pHotKeyNode->uVKey != 0) { *bDirectSwitch = TRUE; } } else { // // Must be IME related hotkey. We need to sync up the // imes so that the new hotkey is effective to all // of them. // UINT ctr2; for (ctr2 = 0; ctr2 < nLangs; ctr2++) { if (!ImmIsIME(pLangs[ctr2])) { continue; } ImmEscape( pLangs[ctr2], NULL, IME_ESC_SYNC_HOTKEY, &pHotKeyNode->dwHotKeyID ); } } } else { // // Failed to set hotkey. Maybe a duplicate. Warn user. // TCHAR szString[DESC_MAX]; GetAtomName( pHotKeyNode->atmHotKeyName, szString, sizeof(szString) / sizeof(TCHAR) ); Locale_ErrorMsg(hwnd, IDS_KBD_SET_HOTKEY_ERR, szString); } } //////////////////////////////////////////////////////////////////////////// // // Locale_SetImmCHxHotkey // //////////////////////////////////////////////////////////////////////////// void Locale_SetImmCHxHotkey( HWND hwnd, UINT nLangs, HKL * pLangs) { HKL hkl; UINT ctr1; UINT uVKey; UINT iCount; UINT uModifiers; LPHOTKEYINFO aImeHotKey; LPHOTKEYINFO pHotKeyNode; // // Determine IME specific hotkeys for CHS and CHT locales. // iCount = Locale_GetImeHotKeyInfo(hwnd, &aImeHotKey); for (ctr1 = 0; ctr1 < iCount; ctr1++) { UINT iIndex; BOOL bRet; // // Get Hotkey information for current layout. // pHotKeyNode = (LPHOTKEYINFO) &aImeHotKey[ctr1]; bRet = ImmGetHotKey(pHotKeyNode->dwHotKeyID, &uModifiers, &uVKey, &hkl); if (!bRet && (!pHotKeyNode->uVKey) && ((pHotKeyNode->uModifiers & (MOD_ALT | MOD_CONTROL | MOD_SHIFT)) != (MOD_ALT | MOD_CONTROL | MOD_SHIFT))) { // // No such hotkey exists. User does not specify key and modifier // information either. We can skip this one. // continue; } if ((pHotKeyNode->uModifiers == uModifiers) && (pHotKeyNode->uVKey == uVKey)) { // // No change. // continue; } // // Set the hotkey value. // bRet = ImmSetHotKey( pHotKeyNode->dwHotKeyID, pHotKeyNode->uModifiers, pHotKeyNode->uVKey, pHotKeyNode->hkl ); if (bRet) { // // Must be IME related hotkey. We need to sync up the // imes so that the new hotkey is effective to all // of them. // UINT ctr2; for (ctr2 = 0; ctr2 < nLangs; ctr2++) { if (!ImmIsIME(pLangs[ctr2])) { continue; } ImmEscape( pLangs[ctr2], NULL, IME_ESC_SYNC_HOTKEY, &pHotKeyNode->dwHotKeyID ); } } else { // // Failed to set hotkey. Maybe a duplicate. Warn user. // TCHAR szString[DESC_MAX]; GetAtomName( pHotKeyNode->atmHotKeyName, szString, sizeof(szString) / sizeof(TCHAR) ); Locale_ErrorMsg(hwnd, IDS_KBD_SET_HOTKEY_ERR, szString); } } } //////////////////////////////////////////////////////////////////////////// // // Locale_GetAttributes // // Gets the global layout attributes (eg: CapsLock/ShiftLock value) from // the registry and then sets the appropriate radio button in the dialog. // //////////////////////////////////////////////////////////////////////////// void Locale_GetAttributes( HWND hwnd) { DWORD cb; HKEY hkey; // // Initialize the global. // g_dwAttributes = 0; // KLF_SHIFTLOCK = 0x00010000 // // Get the Atributes value from the registry. // if (RegOpenKey(HKEY_CURRENT_USER, c_szKbdLayouts, &hkey) == ERROR_SUCCESS) { cb = sizeof(DWORD); RegQueryValueEx( hkey, c_szAttributes, NULL, NULL, (LPBYTE)&g_dwAttributes, &cb ); RegCloseKey(hkey); } // // Set the radio buttons appropriately. // CheckDlgButton( hwnd, IDC_KBDL_SHIFTLOCK, (g_dwAttributes & KLF_SHIFTLOCK) ? BST_CHECKED : BST_UNCHECKED ); CheckDlgButton( hwnd, IDC_KBDL_CAPSLOCK, (g_dwAttributes & KLF_SHIFTLOCK) ? BST_UNCHECKED : BST_CHECKED); } //////////////////////////////////////////////////////////////////////////// // // Locale_LoadLayouts // // Loads the layouts from the registry. // //////////////////////////////////////////////////////////////////////////// BOOL Locale_LoadLayouts( HWND hwnd) { HKEY hKey; HKEY hkey1; DWORD cb; DWORD dwIndex; LONG dwRetVal; DWORD dwValue; DWORD dwType; TCHAR szValue[MAX_PATH]; // language id (number) TCHAR szData[MAX_PATH]; // language name TCHAR szSystemDir[MAX_PATH * 2]; UINT SysDirLen; DWORD dwLayoutID; BOOL bLoadedLayout; // // Load shlwapi module to get the localized layout name // g_hShlwapi = LoadSystemLibrary(TEXT("shlwapi.dll")); if (g_hShlwapi) { // // Get address SHLoadRegUIStringW // pfnSHLoadRegUIString = GetProcAddress(g_hShlwapi, (LPVOID)439); } // // Now read all of the layouts from the registry. // if (RegOpenKey(HKEY_LOCAL_MACHINE, c_szLayoutPath, &hKey) != ERROR_SUCCESS) { Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED); return (FALSE); } dwIndex = 0; dwRetVal = RegEnumKey( hKey, dwIndex, szValue, sizeof(szValue) / sizeof(TCHAR) ); if (dwRetVal != ERROR_SUCCESS) { Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED); RegCloseKey(hKey); return (FALSE); } g_hLayout = LocalAlloc(LHND, ALLOCBLOCK * sizeof(LAYOUT)); g_nLayoutBuffSize = ALLOCBLOCK; g_iLayoutBuff = 0; g_iLayoutIME = 0; // number of IME layouts. g_lpLayout = LocalLock(g_hLayout); if (!g_hLayout) { Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED); RegCloseKey(hKey); return (FALSE); } // // Save the system directory string. // szSystemDir[0] = 0; if (SysDirLen = GetSystemDirectory(szSystemDir, MAX_PATH)) { if (SysDirLen > MAX_PATH) { SysDirLen = 0; szSystemDir[0] = 0; } else if (szSystemDir[SysDirLen - 1] != TEXT('\\')) { szSystemDir[SysDirLen] = TEXT('\\'); szSystemDir[SysDirLen + 1] = 0; SysDirLen++; } } do { // // New layout - get the layout id, the layout file name, and // the layout description string. // if (g_iLayoutBuff + 1 == g_nLayoutBuffSize) { HANDLE hTemp; LocalUnlock(g_hLayout); g_nLayoutBuffSize += ALLOCBLOCK; hTemp = LocalReAlloc( g_hLayout, g_nLayoutBuffSize * sizeof(LAYOUT), LHND ); if (hTemp == NULL) { break; } g_hLayout = hTemp; g_lpLayout = LocalLock(g_hLayout); } // // Get the layout id // dwLayoutID = TransNum(szValue); // // Save the layout id. // g_lpLayout[g_iLayoutBuff].dwID = dwLayoutID; StringCchCopy(szData, ARRAYSIZE(szData), c_szLayoutPath); StringCchCat(szData, ARRAYSIZE(szData), TEXT("\\")); StringCchCat(szData, ARRAYSIZE(szData), szValue); if (RegOpenKey(HKEY_LOCAL_MACHINE, szData, &hkey1) == ERROR_SUCCESS) { // // Get the name of the layout file. // szValue[0] = TEXT('\0'); cb = sizeof(szValue); if ((RegQueryValueEx( hkey1, c_szLayoutFile, NULL, NULL, (LPBYTE)szValue, &cb ) == ERROR_SUCCESS) && (cb > sizeof(TCHAR))) { g_lpLayout[g_iLayoutBuff].atmLayoutFile = AddAtom(szValue); // // See if the layout file exists already. // StringCchCopy(szSystemDir + SysDirLen, ARRAYSIZE(szSystemDir) - SysDirLen, szValue); g_lpLayout[g_iLayoutBuff].bInstalled = (Locale_FileExists(szSystemDir)); // // Get the name of the layout. // szValue[0] = TEXT('\0'); cb = sizeof(szValue); g_lpLayout[g_iLayoutBuff].iSpecialID = 0; bLoadedLayout = FALSE; if (pfnSHLoadRegUIString && pfnSHLoadRegUIString(hkey1, c_szDisplayLayoutText, szValue, ARRAYSIZE(szValue)) == S_OK) { g_lpLayout[g_iLayoutBuff].atmLayoutText = AddAtom(szValue); bLoadedLayout = TRUE; } else { // // Get the name of the layout. // szValue[0] = TEXT('\0'); cb = sizeof(szValue); if (RegQueryValueEx( hkey1, c_szLayoutText, NULL, NULL, (LPBYTE)szValue, &cb ) == ERROR_SUCCESS) { g_lpLayout[g_iLayoutBuff].atmLayoutText = AddAtom(szValue); bLoadedLayout = TRUE; } } if (bLoadedLayout) { // // See if it's an IME or a special id. // szValue[0] = TEXT('\0'); cb = sizeof(szValue); if ((HIWORD(g_lpLayout[g_iLayoutBuff].dwID) & 0xf000) == 0xe000) { // // Get the name of the IME file. // if (RegQueryValueEx( hkey1, c_szIMEFile, NULL, NULL, (LPBYTE)szValue, &cb ) == ERROR_SUCCESS) { g_lpLayout[g_iLayoutBuff].atmIMEFile = AddAtom(szValue); szValue[0] = TEXT('\0'); cb = sizeof(szValue); g_iLayoutBuff++; g_iLayoutIME++; // increment number of IME layouts. } } else { // // See if this is a special id. // if (RegQueryValueEx( hkey1, c_szLayoutID, NULL, NULL, (LPBYTE)szValue, &cb ) == ERROR_SUCCESS) { // // This may not exist. // g_lpLayout[g_iLayoutBuff].iSpecialID = (UINT)TransNum(szValue); } g_iLayoutBuff++; } } } RegCloseKey(hkey1); } dwIndex++; szValue[0] = TEXT('\0'); dwRetVal = RegEnumKey( hKey, dwIndex, szValue, sizeof(szValue) / sizeof(TCHAR) ); } while (dwRetVal == ERROR_SUCCESS); cb = sizeof(DWORD); g_dwAttributes = 0; if (RegQueryValueEx( hKey, c_szAttributes, NULL, NULL, (LPBYTE)&g_dwAttributes, &cb ) != ERROR_SUCCESS) { g_dwAttributes &= 0x00FF0000; } RegCloseKey(hKey); if (g_hShlwapi) { FreeLibrary(g_hShlwapi); g_hShlwapi = NULL; pfnSHLoadRegUIString = NULL; } return (g_iLayoutBuff); } //////////////////////////////////////////////////////////////////////////// // // Locale_LoadLocales // // Loads the locales from the registry. // //////////////////////////////////////////////////////////////////////////// BOOL Locale_LoadLocales( HWND hwnd) { HKEY hKey; DWORD cchValue, cbData; DWORD dwIndex; DWORD dwLocale, dwLayout; DWORD dwLocale2, dwLayout2; LONG dwRetVal; UINT ctr1, ctr2 = 0; TCHAR szValue[MAX_PATH]; // language id (number) TCHAR szData[MAX_PATH]; // language name HINF hIntlInf; BOOL bRet; if (!(g_hLang = LocalAlloc(LHND, ALLOCBLOCK * sizeof(INPUTLANG)))) { Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED); return (FALSE); } g_nLangBuffSize = ALLOCBLOCK; g_iLangBuff = 0; g_lpLang = LocalLock(g_hLang); // // Now read all of the locales from the registry. // if (RegOpenKey(HKEY_LOCAL_MACHINE, c_szLocaleInfo, &hKey) != ERROR_SUCCESS) { Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED); return (FALSE); } dwIndex = 0; cchValue = sizeof(szValue) / sizeof(TCHAR); cbData = sizeof(szData); dwRetVal = RegEnumValue( hKey, dwIndex, szValue, &cchValue, NULL, NULL, (LPBYTE)szData, &cbData ); if (dwRetVal != ERROR_SUCCESS) { Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED); RegCloseKey(hKey); return (FALSE); } // // Open the INF file. // bRet = Region_OpenIntlInfFile(&hIntlInf); do { // // Check for cchValue > 1 - an empty string will be enumerated, // and will come back with cchValue == 1 for the null terminator. // Also, check for cbData > 2 - an empty string will be 2, since // this is the count of bytes. // if ((cchValue > 1) && (cchValue < HKL_LEN) && (cbData > 2)) { // // New language - get the language name and the language id. // if ((g_iLangBuff + 1) == g_nLangBuffSize) { HANDLE hTemp; LocalUnlock(g_hLang); g_nLangBuffSize += ALLOCBLOCK; hTemp = LocalReAlloc( g_hLang, g_nLangBuffSize * sizeof(INPUTLANG), LHND ); if (hTemp == NULL) { break; } g_hLang = hTemp; g_lpLang = LocalLock(g_hLang); } g_lpLang[g_iLangBuff].dwID = TransNum(szValue); g_lpLang[g_iLangBuff].iUseCount = 0; g_lpLang[g_iLangBuff].iNumCount = 0; g_lpLang[g_iLangBuff].pNext = NULL; // // Get the default keyboard layout for the language. // if (bRet && Region_ReadDefaultLayoutFromInf( szValue, &dwLocale, &dwLayout, &dwLocale2, &dwLayout2, hIntlInf ) == TRUE) { // // The default layout is either the first layout in the inf file line // or it's the first layout in the line that has the same language // is the locale. g_lpLang[g_iLangBuff].dwDefaultLayout = dwLayout2?dwLayout2:dwLayout; } // // Get the full localized name of the language. // if (GetLanguageName(LOWORD(g_lpLang[g_iLangBuff].dwID), szData, ARRAYSIZE(szData))) { g_lpLang[g_iLangBuff].atmLanguageName = AddAtom(szData); g_iLangBuff++; } } dwIndex++; cchValue = sizeof(szValue) / sizeof(TCHAR); szValue[0] = TEXT('\0'); cbData = sizeof(szData); szData[0] = TEXT('\0'); dwRetVal = RegEnumValue( hKey, dwIndex, szValue, &cchValue, NULL, NULL, (LPBYTE)szData, &cbData ); } while (dwRetVal == ERROR_SUCCESS); // // If we succeeded in opening the INF file, close it. // if (bRet) { Region_CloseInfFile(&hIntlInf); } RegCloseKey(hKey); return (TRUE); } //////////////////////////////////////////////////////////////////////////// // // Locale_LoadLocalesNT4 // // Loads the locales from the registry. // //////////////////////////////////////////////////////////////////////////// BOOL Locale_LoadLocalesNT4( HWND hwnd) { HKEY hKey; DWORD cch; DWORD dwIndex; LONG dwRetVal; UINT i, j = 0; TCHAR szValue[MAX_PATH]; // language id (number) TCHAR szData[MAX_PATH]; // language name if (!(g_hLang = LocalAlloc(LHND, ALLOCBLOCK * sizeof(INPUTLANG)))) { Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED); return (FALSE); } g_nLangBuffSize = ALLOCBLOCK; g_iLangBuff = 0; g_lpLang = LocalLock(g_hLang); // // Now read all of the locales from the registry. // if (RegOpenKey(HKEY_LOCAL_MACHINE, c_szLocaleInfoNT4, &hKey) != ERROR_SUCCESS) { Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED); return (FALSE); } dwIndex = 0; cch = sizeof(szValue) / sizeof(TCHAR); dwRetVal = RegEnumValue( hKey, dwIndex, szValue, &cch, NULL, NULL, NULL, NULL ); if (dwRetVal != ERROR_SUCCESS) { Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED); RegCloseKey(hKey); return (FALSE); } do { if ((cch > 1) && (cch < HKL_LEN)) { // // Check for cch > 1: an empty string will be enumerated, // and will come back with cch == 1 for the null terminator. // // New language - get the language name, the language // description, and the language id. // if ((g_iLangBuff + 1) == g_nLangBuffSize) { HANDLE hTemp; LocalUnlock(g_hLang); g_nLangBuffSize += ALLOCBLOCK; hTemp = LocalReAlloc( g_hLang, g_nLangBuffSize * sizeof(INPUTLANG), LHND ); if (hTemp == NULL) { break; } g_hLang = hTemp; g_lpLang = LocalLock(g_hLang); } g_lpLang[g_iLangBuff].dwID = TransNum(szValue); g_lpLang[g_iLangBuff].iUseCount = 0; g_lpLang[g_iLangBuff].iNumCount = 0; g_lpLang[g_iLangBuff].pNext = NULL; // // Get the full localized name of the language. // if (GetLanguageName(LOWORD(g_lpLang[g_iLangBuff].dwID), szData, ARRAYSIZE(szData))) { g_lpLang[g_iLangBuff].atmLanguageName = AddAtom(szData); g_iLangBuff++; } } dwIndex++; cch = sizeof(szValue) / sizeof(TCHAR); szValue[0] = TEXT('\0'); dwRetVal = RegEnumValue( hKey, dwIndex, szValue, &cch, NULL, NULL, NULL, NULL ); } while (dwRetVal == ERROR_SUCCESS); RegCloseKey(hKey); return (TRUE); } //////////////////////////////////////////////////////////////////////////// // // Locale_GetActiveLocales // // Gets the active locales. // //////////////////////////////////////////////////////////////////////////// BOOL Locale_GetActiveLocales( HWND hwnd) { HKL *pLangs; UINT nLangs, ctr1, ctr2, ctr3, id; HWND hwndList = GetDlgItem(hwnd, IDC_INPUT_LIST); HKL hklSystem = 0; int idxListBox; BOOL bReturn = FALSE; BOOL bTipSubhkl = FALSE; DWORD langLay; HANDLE hLangNode; LPLANGNODE pLangNode; HICON hIcon = NULL; TCHAR szLangText[DESC_MAX]; TCHAR szLayoutName[DESC_MAX]; LPINPUTLANG pInpLang; HTREEITEM hTVItem; TV_ITEM tvItem; // // Initialize US layout option. // g_iUsLayout = -1; // // Get the active keyboard layout list from the system. // if (!SystemParametersInfo( SPI_GETDEFAULTINPUTLANG, 0, &hklSystem, 0 )) { hklSystem = GetKeyboardLayout(0); } nLangs = GetKeyboardLayoutList(0, NULL); if (nLangs == 0) { Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED); return bReturn; } pLangs = (HKL *)LocalAlloc(LPTR, sizeof(DWORD_PTR) * nLangs); if (pLangs == NULL) { Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED); return bReturn; } GetKeyboardLayoutList(nLangs, (HKL *)pLangs); // // Find the position of the US layout to use as a default. // for (ctr1 = 0; ctr1 < g_iLayoutBuff; ctr1++) { if (g_lpLayout[ctr1].dwID == US_LOCALE) { g_iUsLayout = ctr1; break; } } if (ctr1 == g_iLayoutBuff) { Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED); goto Error; } // // Get the active keyboard information and put it in the internal // language structure. // for (ctr2 = 0; ctr2 < nLangs; ctr2++) { // // Filter out TIP substitute HKL from TreeView. // bTipSubhkl = IsTipSubstituteHKL(pLangs[ctr2]); if (hklSystem != pLangs[ctr2] && IsUnregisteredFEDummyHKL(pLangs[ctr2])) { continue; } for (ctr1 = 0; ctr1 < g_iLangBuff; ctr1++) { // // See if there's a match. // if (LOWORD(pLangs[ctr2]) == LOWORD(g_lpLang[ctr1].dwID)) { LPTVITEMNODE pTVItemNode; // // Found a match. // Create a node for this language. // pLangNode = Locale_AddToLinkedList(ctr1, pLangs[ctr2]); if (!pLangNode) { Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED); goto Error; } // // Get language name to add it to treeview // pInpLang = &g_lpLang[pLangNode->iLang]; GetAtomName(pInpLang->atmLanguageName, szLangText, ARRAYSIZE(szLangText)); if ((HIWORD(pLangs[ctr2]) & 0xf000) == 0xe000) { pLangNode->wStatus |= LANG_IME; } pLangNode->wStatus |= (LANG_ORIGACTIVE | LANG_ACTIVE); pLangNode->hkl = pLangs[ctr2]; pLangNode->hklUnload = pLangs[ctr2]; Locale_FetchIndicator(pLangNode); // // Match the language to the layout. // pLangNode->iLayout = 0; langLay = (DWORD)HIWORD(pLangs[ctr2]); if ((HIWORD(pLangs[ctr2]) == 0xffff) || (HIWORD(pLangs[ctr2]) == 0xfffe)) { // // Mark default or previous error as US - this // means that the layout will be that of the basic // keyboard driver (the US one). // pLangNode->wStatus |= LANG_CHANGED; pLangNode->iLayout = g_iUsLayout; langLay = 0; } else if ((HIWORD(pLangs[ctr2]) & 0xf000) == 0xf000) { // // Layout is special, need to search for the ID // number. // id = HIWORD(pLangs[ctr2]) & 0x0fff; for (ctr3 = 0; ctr3 < g_iLayoutBuff; ctr3++) { if (id == g_lpLayout[ctr3].iSpecialID) { pLangNode->iLayout = ctr3; langLay = 0; break; } } if (langLay) { // // Didn't find the id, so reset to basic for // the language. // langLay = (DWORD)LOWORD(pLangs[ctr2]); } } if (langLay) { // // Search for the id. // for (ctr3 = 0; ctr3 < g_iLayoutBuff; ctr3++) { if (((LOWORD(langLay) & 0xf000) == 0xe000) && (g_lpLayout[ctr3].dwID) == (DWORD)((DWORD_PTR)(pLangs[ctr2]))) { pLangNode->iLayout = ctr3; break; } else { if (langLay == (DWORD)LOWORD(g_lpLayout[ctr3].dwID)) { pLangNode->iLayout = ctr3; break; } } } if (ctr3 == g_iLayoutBuff) { // // Something went wrong or didn't load from // the registry correctly. // MessageBeep(MB_ICONEXCLAMATION); pLangNode->wStatus |= LANG_CHANGED; pLangNode->iLayout = g_iUsLayout; } } // // If this is the current language, then it's the default // one. // if ((DWORD)((DWORD_PTR)pLangNode->hkl) == (DWORD)((DWORD_PTR)hklSystem)) { TCHAR sz[DESC_MAX]; pInpLang = &g_lpLang[ctr1]; // // Found the default. Set the Default input locale // text in the property sheet. // if (pLangNode->wStatus & LANG_IME) { GetAtomName(g_lpLayout[pLangNode->iLayout].atmLayoutText, sz, ARRAYSIZE(sz)); } else { GetAtomName(pInpLang->atmLanguageName, sz, ARRAYSIZE(sz)); } pLangNode->wStatus |= LANG_DEFAULT; } // Get layout name and add it to treeview GetAtomName(g_lpLayout[pLangNode->iLayout].atmLayoutText, szLayoutName, ARRAYSIZE(szLayoutName)); if (bTipSubhkl) { AddKbdLayoutOnKbdTip((HKL) ((DWORD_PTR)(pLangs[ctr2])), pLangNode->iLayout); } if (bTipSubhkl && (hTVItem = FindTVLangItem(pInpLang->dwID, NULL))) { TV_ITEM tvTipItem; HTREEITEM hGroupItem; HTREEITEM hTipItem; LPTVITEMNODE pTVTipItemNode; tvItem.mask = TVIF_HANDLE | TVIF_PARAM; tvItem.hItem = hTVItem; //GetAtomName(pTVItemNode->atmDefTipName, szLayoutName, ARRAYSIZE(szLayoutName)); tvTipItem.mask = TVIF_HANDLE | TVIF_PARAM; tvTipItem.hItem = hTVItem; // // Adding the default keyboard layout info into each TIPs. // for (hGroupItem = TreeView_GetChild(g_hwndTV, hTVItem); hGroupItem != NULL; hGroupItem = TreeView_GetNextSibling(g_hwndTV, hGroupItem)) { for (hTipItem = TreeView_GetChild(g_hwndTV, hGroupItem); hTipItem != NULL; hTipItem = TreeView_GetNextSibling(g_hwndTV, hTipItem)) { tvTipItem.hItem = hTipItem; if (TreeView_GetItem(g_hwndTV, &tvTipItem) && tvTipItem.lParam) { pTVTipItemNode = (LPTVITEMNODE) tvTipItem.lParam; if (pTVTipItemNode->hklSub == pLangNode->hkl) { pTVTipItemNode->lParam = (LPARAM) pLangNode; } } } } if (pLangNode->wStatus & LANG_DEFAULT) { UINT ctr; TCHAR szDefItem[MAX_PATH]; // // Set the default locale selection. // HWND hwndDefList = GetDlgItem(g_hDlg, IDC_LOCALE_DEFAULT); int idxSel = -1; // // Search substitute HKL of Tips. // for (ctr = 0; ctr < g_iTipsBuff; ctr++) { if (pLangs[ctr2] == g_lpTips[ctr].hklSub && g_lpTips[ctr].bDefault) { GetAtomName(g_lpTips[ctr].atmTipText, szLayoutName, ARRAYSIZE(szLayoutName)); break; } } StringCchCopy(szDefItem, ARRAYSIZE(szDefItem), szLangText); StringCchCat(szDefItem, ARRAYSIZE(szDefItem), TEXT(" - ")); StringCchCat(szDefItem, ARRAYSIZE(szDefItem), szLayoutName); if ((idxSel = ComboBox_FindStringExact(hwndDefList, 0, szDefItem)) != CB_ERR) ComboBox_SetCurSel(hwndDefList, idxSel); Locale_CommandSetDefault(hwnd); } } else { // // // if (!(pTVItemNode = CreateTVItemNode(pInpLang->dwID))) goto Error; pTVItemNode->lParam = (LPARAM)pLangNode; if (!pTVItemNode->atmDefTipName) pTVItemNode->atmDefTipName = AddAtom(szLayoutName); // // Add language node into treeview // AddTreeViewItems(TV_ITEM_TYPE_LANG, szLangText, NULL, NULL, &pTVItemNode); if (!(pTVItemNode = CreateTVItemNode(pInpLang->dwID))) goto Error; pTVItemNode->lParam = (LPARAM)pLangNode; // // Add keyboard layout item into treeview // hTVItem = AddTreeViewItems(TV_ITEM_TYPE_KBD, szLangText, szInputTypeKbd, szLayoutName, &pTVItemNode); } // // Check Thai layout. // if (g_dwPrimLangID == LANG_THAI && hTVItem) { if (PRIMARYLANGID(LOWORD(g_lpLayout[pLangNode->iLayout].dwID)) == LANG_THAI) g_iThaiLayout++; } // // Break out of inner loop - we've found it. // break; } } } bReturn = TRUE; Error: if (pLangs) LocalFree((HANDLE)pLangs); return (bReturn); } //////////////////////////////////////////////////////////////////////////// // // GetInstalledInput // //////////////////////////////////////////////////////////////////////////// BOOL GetInstalledInput(HWND hwnd) { DWORD dwLayout = 0; LANGID langID; // // Reset the installed input // g_iInputs = 0; // // Need to check language id for Thai, Chinese and Arabic. // g_dwPrimLangID = PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID())); if (g_dwPrimLangID == LANG_ARABIC || g_dwPrimLangID == LANG_HEBREW) { g_bMESystem = TRUE; } #if 0 else if (g_dwPrimLangID == LANG_CHINESE) { g_bCHSystem = TRUE; } #endif langID = GetUserDefaultUILanguage(); if (PRIMARYLANGID(langID) == LANG_ARABIC || PRIMARYLANGID(langID) == LANG_HEBREW) { g_bShowRtL = TRUE; } // // Enum new tips(speech, pen and keyboard). // If there are new tips in the system, read tip category enabling status // and add them into tree view control. // EnumCiceroTips(); // // Read all availabe keyboard layouts from system // if (g_OSNT4) { if (!Locale_LoadLocalesNT4(hwnd)) return FALSE; } else { if (!Locale_LoadLocales(hwnd)) return FALSE; } if ((!Locale_LoadLayouts(hwnd)) || (!Locale_GetActiveLocales(hwnd))) return FALSE; // // Only 1 TIP, so disable the secondary controls. // Locale_SetSecondaryControls(hwnd); // // Save the originial input layouts // g_iOrgInputs = g_iInputs; return TRUE; } //////////////////////////////////////////////////////////////////////////// // // InitPropSheet // // Processing for a WM_INITDIALOG message for the Input Locales // property sheet. // //////////////////////////////////////////////////////////////////////////// void InitPropSheet( HWND hwnd, LPPROPSHEETPAGE psp) { HKEY hKey; HANDLE hlib; HWND hwndList; LPLANGNODE pLangNode; LANGID LangID; UINT iNumLangs, ctr; TCHAR szItem[DESC_MAX]; BOOL bImeSetting = FALSE; // // See if there are any other instances of this property page. // If so, disable this page. // if (g_hMutex && (WaitForSingleObject(g_hMutex, 0) != WAIT_OBJECT_0)) { // Need to disable controls ... Locale_EnablePane(hwnd, FALSE, IDC_KBDL_DISABLED_2); return; } // // See if we're in setup mode. // if (IsSetupMode()) { // // Set the setup special case flag. // g_bSetupCase = TRUE; } // // Make sure the event is clear. // if (g_hEvent) { SetEvent(g_hEvent); } g_OSNT4 = IsOSPlatform(OS_NT4); g_OSNT5 = IsOSPlatform(OS_NT5); #ifndef _WIN64 g_OSWIN95 = IsOSPlatform(OS_WIN95); #endif // _WIN64 // // Check the Administrative privileges by the token group SID. // if (IsAdminPrivilegeUser()) { g_bAdmin_Privileges = TRUE; } else { // // The user does not have admin privileges. // g_bAdmin_Privileges = FALSE; } // // Load the strings // LoadString(hInstance, IDS_LOCALE_DEFAULT, szDefault, ARRAYSIZE(szDefault)); LoadString(hInstance, IDS_INPUT_KEYBOARD, szInputTypeKbd, ARRAYSIZE(szInputTypeKbd)); LoadString(hInstance, IDS_INPUT_PEN, szInputTypePen, ARRAYSIZE(szInputTypePen)); LoadString(hInstance, IDS_INPUT_SPEECH, szInputTypeSpeech, ARRAYSIZE(szInputTypeSpeech)); LoadString(hInstance, IDS_INPUT_EXTERNAL, szInputTypeExternal, ARRAYSIZE(szInputTypeExternal)); } //////////////////////////////////////////////////////////////////////////// // // Locale_CommandAdd // // Invokes the Add dialog. // // Returns 1 if a dialog box was invoked and the dialog returned IDOK. // Otherwise, it returns 0. // //////////////////////////////////////////////////////////////////////////// int Locale_CommandAdd( HWND hwnd) { HWND hwndList; HWND hwndTV; int idxList; UINT nList; int rc = 0; INITINFO InitInfo; LPCTSTR lpTemplateName; HINSTANCE hInstRes; HTREEITEM hTVItem; hwndTV = GetDlgItem(hwnd, IDC_INPUT_LIST); hTVItem = TreeView_GetSelection(hwndTV); if (!hTVItem) return 0; InitInfo.hwndMain = hwnd; InitInfo.pLangNode = NULL; if (g_bExtraTip) { hInstRes = GetCicResInstance(hInstance, DLG_KEYBOARD_LOCALE_ADD_EXTRA); lpTemplateName = MAKEINTRESOURCE(DLG_KEYBOARD_LOCALE_ADD_EXTRA); } else if (g_bPenOrSapiTip) { hInstRes = GetCicResInstance(hInstance, DLG_KEYBOARD_LOCALE_ADD); lpTemplateName = MAKEINTRESOURCE(DLG_KEYBOARD_LOCALE_ADD); } else { hInstRes = GetCicResInstance(hInstance, DLG_KEYBOARD_LOCALE_SIMPLE_ADD); lpTemplateName = MAKEINTRESOURCE(DLG_KEYBOARD_LOCALE_SIMPLE_ADD); } // // Bring up the appropriate dialog box. And check return value for added // items. // if ((rc = (int)DialogBoxParam(hInstRes, lpTemplateName, hwnd, KbdLocaleAddDlg, (LPARAM)(&InitInfo) )) == IDOK) { // // Turn on ApplyNow button. // PropSheet_Changed(GetParent(hwnd), hwnd); } else { // // Failure, so need to return 0. // TreeView_SelectItem(hwndTV, hTVItem); rc = 0; } return (rc); } //////////////////////////////////////////////////////////////////////////// // // Locale_CommandEdit // // Invokes the Properties dialog. // // Returns 1 if a dialog box was invoked and the dialog returned IDOK. // Otherwise, it returns 0. // //////////////////////////////////////////////////////////////////////////// void Locale_CommandEdit( HWND hwnd, LPLANGNODE pLangNode) { HWND hwndList; HWND hwndTV; int idxList; UINT nList; int rc = 0; INITINFO InitInfo; HTREEITEM hTVItem; TV_ITEM tvItem; LPTVITEMNODE pTVItemNode; hTVItem = TreeView_GetSelection(g_hwndTV); if (!hTVItem) return; tvItem.mask = TVIF_HANDLE | TVIF_PARAM; tvItem.hItem = hTVItem; if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam) { pTVItemNode = (LPTVITEMNODE) tvItem.lParam; if (pTVItemNode->uInputType & INPUT_TYPE_TIP) { HRESULT hr; ITfFnConfigure *pConfig = NULL; // // Load LangBar manager to bring the property window // hr = CoCreateInstance(&pTVItemNode->clsid, NULL, CLSCTX_INPROC_SERVER, &IID_ITfFnConfigure, (LPVOID *) &pConfig); // // Call property dialog from TIP. // if (SUCCEEDED(hr)) pConfig->lpVtbl->Show(pConfig, hwnd, (LANGID)pTVItemNode->dwLangID, &pTVItemNode->guidProfile); if (pConfig) pConfig->lpVtbl->Release(pConfig); } else { if ((pLangNode = (LPLANGNODE)pTVItemNode->lParam) && (pLangNode->wStatus & LANG_IME)) ImmConfigureIME(pLangNode->hkl, hwnd, IME_CONFIG_GENERAL, NULL); } } } //////////////////////////////////////////////////////////////////////////// // // RemoveTVSubItems // //////////////////////////////////////////////////////////////////////////// BOOL RemoveTVSubItems( HWND hwnd, HTREEITEM hTVItem, LPTVITEMNODE pTVItemNode) { TV_ITEM tvItem; BOOL bRemoveAll = TRUE; HTREEITEM hGroupItem, hItem; HWND hwndTV = GetDlgItem(g_hDlg, IDC_INPUT_LIST); // // Delete all TreeView node. // tvItem.mask = TVIF_HANDLE | TVIF_PARAM; if (pTVItemNode->uInputType & TV_ITEM_TYPE_LANG) { hGroupItem = TreeView_GetChild(hwndTV, hTVItem); } else { hGroupItem = hTVItem; bRemoveAll = FALSE; } while (hGroupItem != NULL) { BOOL bNextGroup = FALSE; LPTVITEMNODE pTVTempNode = NULL; HTREEITEM hDeletedItem = NULL; for (hItem = TreeView_GetChild(hwndTV, hGroupItem); hItem != NULL; hItem = TreeView_GetNextSibling(hwndTV, hItem)) { if (hDeletedItem) { TreeView_DeleteItem(hwndTV, hDeletedItem); hDeletedItem = NULL; } tvItem.hItem = hItem; if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam) { LPLANGNODE pLangNode = NULL; if (pTVTempNode = (LPTVITEMNODE) tvItem.lParam) pLangNode = (LPLANGNODE)pTVTempNode->lParam; else continue; if (pTVTempNode->uInputType & INPUT_TYPE_TIP) { g_lpTips[pTVTempNode->iIdxTips].bEnabled = FALSE; g_iEnabledTips--; if (pTVTempNode->uInputType & INPUT_TYPE_KBD) g_iEnabledKbdTips--; g_dwChanges |= CHANGE_TIPCHANGE; if ((pTVTempNode->uInputType & INPUT_TYPE_KBD) && pTVTempNode->hklSub) { UINT ctr; UINT uNumSubhkl = 0; for (ctr = 0; ctr < g_iTipsBuff; ctr++) { if (pTVTempNode->hklSub == g_lpTips[ctr].hklSub && g_lpTips[ctr].bEnabled) { uNumSubhkl++; } } if (!uNumSubhkl) { pLangNode = (LPLANGNODE)pTVTempNode->lParam; } else { // // Someone still use this substitute HKL. // pLangNode = NULL; } } } if ((pTVTempNode->uInputType & TV_ITEM_TYPE_KBD) && pLangNode) { if (!(pTVTempNode->uInputType & INPUT_TYPE_TIP)) pLangNode = (LPLANGNODE)pTVTempNode->lParam; if (!pLangNode) return FALSE; // // Check Thai layout. // if (g_dwPrimLangID == LANG_THAI) { if (PRIMARYLANGID(LOWORD(g_lpLayout[pLangNode->iLayout].dwID)) == LANG_THAI) g_iThaiLayout--; } pLangNode->wStatus &= ~(LANG_ACTIVE|LANG_DEFAULT); pLangNode->wStatus |= LANG_CHANGED; g_lpLang[pLangNode->iLang].iNumCount--; if (!(pLangNode->wStatus & LANG_ORIGACTIVE)) { Locale_RemoveFromLinkedList(pLangNode); } } RemoveTVItemNode(pTVTempNode); hDeletedItem = hItem; g_iInputs--; } } tvItem.hItem = hGroupItem; if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam) { pTVTempNode = (LPTVITEMNODE)tvItem.lParam; if (!pTVTempNode) continue; if (pTVTempNode->uInputType & INPUT_TYPE_SPEECH || pTVTempNode->uInputType & INPUT_TYPE_SMARTTAG) { g_lpTips[pTVTempNode->iIdxTips].bEnabled = FALSE; g_iEnabledTips--; g_dwChanges |= CHANGE_TIPCHANGE; if (pTVTempNode->uInputType & INPUT_TYPE_SPEECH) MarkSptipRemoved(TRUE); } if (pTVTempNode->uInputType & ~TV_ITEM_TYPE_LANG) { hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem); bNextGroup = TRUE; TreeView_DeleteItem(hwndTV, tvItem.hItem ); } RemoveTVItemNode(pTVTempNode); if (pTVTempNode == pTVItemNode) pTVItemNode = NULL; } if (!bNextGroup) hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem); if (!bRemoveAll) hGroupItem = NULL; } if (pTVItemNode && (pTVItemNode->uInputType & TV_ITEM_TYPE_LANG)) { int idxSel = -1; TCHAR szItemName[DESC_MAX]; HWND hwndDefList = GetDlgItem(hwnd, IDC_LOCALE_DEFAULT); GetAtomName(pTVItemNode->atmTVItemName, szItemName, ARRAYSIZE(szItemName)); idxSel = ComboBox_FindString(hwndDefList, 0, szItemName); for (; idxSel != CB_ERR; ) { ComboBox_DeleteString(hwndDefList, idxSel); idxSel = ComboBox_FindString(hwndDefList, 0, szItemName); } if (pTVItemNode->bDefLang) { ComboBox_SetCurSel(hwndDefList, 0); Locale_CommandSetDefault(hwnd); } RemoveTVItemNode(pTVItemNode); TreeView_DeleteItem(hwndTV, hTVItem ); } return TRUE; } //////////////////////////////////////////////////////////////////////////// // // GetNewRemoveItem // // Removes the currently selected input locale from the list. // //////////////////////////////////////////////////////////////////////////// HTREEITEM GetNewRemoveItem( HWND hwnd, HTREEITEM hTVItem, BOOL *bDelSameSubhkl, LPTSTR lpDelItems, UINT cchDelItems) { TV_ITEM tvItem; LPTVITEMNODE pTVItemNode; HTREEITEM hTVNewItem = hTVItem; HTREEITEM hTVLangItem = NULL; HWND hwndTV = GetDlgItem(hwnd, IDC_INPUT_LIST); tvItem.mask = TVIF_HANDLE | TVIF_PARAM; tvItem.hItem = hTVItem; if (TreeView_GetItem(hwndTV, &tvItem)) { // // Get the pointer to the lang node from the list box // item data. // pTVItemNode = (LPTVITEMNODE) tvItem.lParam; if (!pTVItemNode) goto Error; if (pTVItemNode->uInputType & TV_ITEM_TYPE_LANG) return hTVItem; if (pTVItemNode->uInputType & TV_ITEM_TYPE_GROUP) { if (!TreeView_GetNextSibling(hwndTV, hTVItem) && !TreeView_GetPrevSibling(hwndTV, hTVItem)) { if ((hTVLangItem = TreeView_GetParent(hwndTV, hTVItem)) && (TreeView_GetNextSibling(hwndTV, hTVLangItem) || TreeView_GetPrevSibling(hwndTV, hTVLangItem))) { hTVNewItem = TreeView_GetParent(hwndTV, hTVItem); } } } else { if (!TreeView_GetNextSibling(hwndTV, hTVItem) && !TreeView_GetPrevSibling(hwndTV, hTVItem)) { if (hTVNewItem = TreeView_GetParent(hwndTV, hTVItem)) { if (!TreeView_GetNextSibling(hwndTV, hTVNewItem) && !TreeView_GetPrevSibling(hwndTV, hTVNewItem)) { if ((hTVLangItem = TreeView_GetParent(hwndTV, hTVNewItem)) && (TreeView_GetNextSibling(hwndTV, hTVLangItem) || TreeView_GetPrevSibling(hwndTV, hTVLangItem))) { hTVNewItem = TreeView_GetParent(hwndTV, hTVNewItem); } } } } else { if(pTVItemNode->hklSub) { HTREEITEM hItem; HTREEITEM hTVKbdGrpItem; LPTVITEMNODE pTVTempItem; UINT uSubhklItems = 0; BOOL bFoundOther = FALSE; if (hTVKbdGrpItem = TreeView_GetParent(hwndTV, hTVItem)) { for (hItem = TreeView_GetChild(hwndTV, hTVKbdGrpItem); hItem != NULL; hItem = TreeView_GetNextSibling(hwndTV, hItem)) { tvItem.hItem = hItem; if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam) { pTVTempItem = (LPTVITEMNODE) tvItem.lParam; } else { goto Error; } if (pTVItemNode->hklSub != pTVTempItem->hklSub) { bFoundOther = TRUE; } else { TCHAR szItemName[MAX_PATH]; GetAtomName(pTVTempItem->atmTVItemName, szItemName, ARRAYSIZE(szItemName)); if (lstrlen(lpDelItems) < MAX_PATH / 2) { StringCchCat(lpDelItems, cchDelItems, TEXT("\r\n\t")); StringCchCat(lpDelItems, cchDelItems, szItemName); } else { StringCchCat(lpDelItems, cchDelItems, TEXT("...")); } uSubhklItems++; } } if (uSubhklItems >= 2) *bDelSameSubhkl = TRUE; if (!bFoundOther) { if (!TreeView_GetNextSibling(hwndTV, hTVKbdGrpItem) && !TreeView_GetPrevSibling(hwndTV, hTVKbdGrpItem)) { if ((hTVLangItem = TreeView_GetParent(hwndTV, hTVKbdGrpItem)) && (TreeView_GetNextSibling(hwndTV, hTVLangItem) || TreeView_GetPrevSibling(hwndTV, hTVLangItem))) { hTVNewItem = TreeView_GetParent(hwndTV, hTVKbdGrpItem); } } } } } } } } Error: return hTVNewItem; } //////////////////////////////////////////////////////////////////////////// // // Locale_CommandDelete // // Removes the currently selected input locale from the list. // //////////////////////////////////////////////////////////////////////////// void Locale_CommandDelete( HWND hwnd) { TV_ITEM tvItem; HTREEITEM hTVItem; LPTVITEMNODE pTVItemNode; TCHAR szDelItems[MAX_PATH]; LPLANGNODE pLangNode = NULL; BOOL bDelSameSubhkl = FALSE; BOOL bRemovedDefLayout = FALSE; DWORD dwNextLangId; HWND hwndTV = GetDlgItem(hwnd, IDC_INPUT_LIST); // // Get the current selection in the input locale list. // hTVItem = TreeView_GetSelection(hwndTV); if (!hTVItem) return; szDelItems[0] = TEXT('\0'); hTVItem = GetNewRemoveItem(hwnd, hTVItem, &bDelSameSubhkl, szDelItems, ARRAYSIZE(szDelItems)); if (bDelSameSubhkl) { TCHAR szTitle[MAX_PATH]; TCHAR szMsg[MAX_PATH]; TCHAR szMsg2[MAX_PATH*2]; CicLoadString(hInstance, IDS_DELETE_CONFIRMTITLE, szTitle, ARRAYSIZE(szTitle)); CicLoadString(hInstance, IDS_DELETE_TIP, szMsg, ARRAYSIZE(szMsg)); StringCchPrintf(szMsg2, ARRAYSIZE(szMsg2), szMsg, szDelItems); if (MessageBox(hwnd, szMsg2, szTitle, MB_YESNO|MB_ICONQUESTION ) == IDNO) { return; } } tvItem.mask = TVIF_HANDLE | TVIF_PARAM; tvItem.hItem = hTVItem; if (TreeView_GetItem(hwndTV, &tvItem)) { // // Get the pointer to the lang node from the list box // item data. // pTVItemNode = (LPTVITEMNODE) tvItem.lParam; if (!pTVItemNode) return; if ((pTVItemNode->uInputType & TV_ITEM_TYPE_LANG) || (pTVItemNode->uInputType & TV_ITEM_TYPE_GROUP)) { if (RemoveTVSubItems(hwnd, hTVItem, pTVItemNode)) goto ItemChanged; return; } if (pTVItemNode->uInputType & INPUT_TYPE_KBD) { pLangNode = (LPLANGNODE)pTVItemNode->lParam; } } else { // // Make sure we're not removing the only entry in the list. // MessageBeep(MB_ICONEXCLAMATION); return; } if (pTVItemNode->uInputType & INPUT_TYPE_TIP) { g_lpTips[pTVItemNode->iIdxTips].bEnabled = FALSE; g_iEnabledTips--; if (pTVItemNode->uInputType & INPUT_TYPE_KBD) g_iEnabledKbdTips--; if (pTVItemNode->uInputType & INPUT_TYPE_SPEECH) { // mark SPTIP's hack entry MarkSptipRemoved(TRUE); } g_dwChanges |= CHANGE_TIPCHANGE; if ((pTVItemNode->uInputType & INPUT_TYPE_KBD) && pTVItemNode->hklSub) { UINT ctr; for (ctr = 0; ctr < g_iTipsBuff; ctr++) { if (pTVItemNode->hklSub == g_lpTips[ctr].hklSub && g_lpTips[ctr].bEnabled) { HTREEITEM hDelItem; TCHAR szTipText[MAX_PATH]; g_iEnabledTips--; g_iEnabledKbdTips--; g_lpTips[ctr].bEnabled = FALSE; GetAtomName(g_lpTips[ctr].atmTipText, szTipText, ARRAYSIZE(szTipText)); // // Find the installed same keyboard TIP layout to delete it // together. // if (hDelItem = FindTVItem(g_lpTips[ctr].dwLangID, szTipText)) { tvItem.hItem = hDelItem; if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam) { RemoveTVItemNode((LPTVITEMNODE)tvItem.lParam); TreeView_DeleteItem(g_hwndTV, tvItem.hItem ); } g_iInputs--; } } } } } if (pTVItemNode->uInputType & INPUT_TYPE_KBD && pLangNode) { // // Check Thai layout. // if (g_dwPrimLangID == LANG_THAI) { if (PRIMARYLANGID(LOWORD(g_lpLayout[pLangNode->iLayout].dwID)) == LANG_THAI) g_iThaiLayout--; } if (pLangNode->wStatus & LANG_DEFAULT) { bRemovedDefLayout = TRUE; dwNextLangId = pTVItemNode->dwLangID; } // // Set the input locale to be not active and show that its state // has changed. Also, delete the string from the input locale list // in the property sheet. // // Decrement the number of nodes for this input locale. // pLangNode->wStatus &= ~(LANG_ACTIVE|LANG_DEFAULT); pLangNode->wStatus |= LANG_CHANGED; g_lpLang[pLangNode->iLang].iNumCount--; // // If it wasn't originally active, then remove it from the list. // There's nothing more to do with this node. // if (!(pLangNode->wStatus & LANG_ORIGACTIVE)) { Locale_RemoveFromLinkedList(pLangNode); } } g_iInputs--; RemoveTVItemNode(pTVItemNode); TreeView_DeleteItem(hwndTV, hTVItem); // // Set the next available default layout // if (bRemovedDefLayout) { int idxSel = -1; TCHAR szNextDefTip[MAX_PATH]; TCHAR szDefLayout[MAX_PATH * 2]; LPTVITEMNODE pTVLangItemNode = NULL; HWND hwndDefList = GetDlgItem(hwnd, IDC_LOCALE_DEFAULT); SetNextDefaultLayout(dwNextLangId, TRUE, szNextDefTip, ARRAYSIZE(szNextDefTip)); if (tvItem.hItem = FindTVLangItem(dwNextLangId, NULL)) { tvItem.mask = TVIF_HANDLE | TVIF_PARAM; if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam) { pTVLangItemNode = (LPTVITEMNODE) tvItem.lParam; if (pTVLangItemNode->atmDefTipName) DeleteAtom(pTVLangItemNode->atmDefTipName); pTVLangItemNode->atmDefTipName = AddAtom(szNextDefTip); GetAtomName(pTVLangItemNode->atmTVItemName, szDefLayout, MAX_PATH); StringCchCat(szDefLayout, ARRAYSIZE(szDefLayout), TEXT(" - ")); StringCchCat(szDefLayout, ARRAYSIZE(szDefLayout), szNextDefTip); } } idxSel = ComboBox_FindString(hwndDefList, 0, szDefLayout); if (idxSel == CB_ERR) idxSel = 0; ComboBox_SetCurSel(hwndDefList, idxSel); } // // Find keyboard group dangling node that doesn't has child keyboard // layout item. // hTVItem = TreeView_GetSelection(hwndTV); if (!hTVItem) return; tvItem.hItem = hTVItem; tvItem.mask = TVIF_HANDLE | TVIF_PARAM; if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam) { if ((pTVItemNode = (LPTVITEMNODE) tvItem.lParam)) { if ((pTVItemNode->uInputType & INPUT_TYPE_KBD) && (pTVItemNode->uInputType & TV_ITEM_TYPE_GROUP)) { if (TreeView_GetChild(hwndTV, hTVItem) == NULL) { // // Delete keyboard group dangling node // RemoveTVItemNode(pTVItemNode); TreeView_DeleteItem(hwndTV, hTVItem); } } } } ItemChanged: // // Only 1 active tip, so disable the secondary controls. // Locale_SetSecondaryControls(hwnd); // // Update the default locale switch hotkey. // Locale_SetDefaultHotKey(hwnd, FALSE); // // Move the focus to the Add button if the Remove button // is now disabled (so that we don't lose input focus) // if (!IsWindowEnabled(GetDlgItem(hwnd, IDC_KBDL_DELETE))) { SetFocus(GetDlgItem(hwnd, IDC_KBDL_ADD)); } // // Enable the Apply button. // PropSheet_Changed(GetParent(hwnd), hwnd); } //////////////////////////////////////////////////////////////////////////// // // Locale_CommandHotKeySetting // // Invokes the Change HotKey dialog. // // Returns 1 if a dialog box was invoked and the dialog returned IDOK. // Otherwise, it returns 0. // //////////////////////////////////////////////////////////////////////////// BOOL Locale_CommandHotKeySetting( HWND hwnd) { int rc = 0; INITINFO InitInfo; InitInfo.hwndMain = hwnd; if (g_OSNT5) { rc = (int)DialogBoxParam(GetCicResInstance(hInstance, DLG_KEYBOARD_LOCALE_HOTKEY), MAKEINTRESOURCE(DLG_KEYBOARD_LOCALE_HOTKEY), hwnd, KbdLocaleHotKeyDlg, (LPARAM)(&InitInfo)); } else { rc = (int)DialogBoxParam(GetCicResInstance(hInstance, DLG_KEYBOARD_HOTKEY_INPUT_LOCALE), MAKEINTRESOURCE(DLG_KEYBOARD_HOTKEY_INPUT_LOCALE), hwnd, KbdLocaleSimpleHotkey, (LPARAM)&InitInfo); } return rc; } //////////////////////////////////////////////////////////////////////////// // // Locale_CommandToolBarSetting // // Invokes the ToolBar setting dialog. // // Returns 1 if a dialog box was invoked and the dialog returned IDOK. // Otherwise, it returns 0. // //////////////////////////////////////////////////////////////////////////// BOOL Locale_CommandToolBarSetting( HWND hwnd) { int rc = 0; if ((rc = (int)DialogBoxParam(GetCicResInstance(hInstance, DLG_TOOLBAR_SETTING), MAKEINTRESOURCE(DLG_TOOLBAR_SETTING), hwnd, ToolBarSettingDlg, (LPARAM)NULL)) == IDOK) { return TRUE; } else { return FALSE; } } //////////////////////////////////////////////////////////////////////////// // // Locale_AddLanguage // // Adds the new input locale to the list in the property page. // //////////////////////////////////////////////////////////////////////////// BOOL Locale_AddLanguage( HWND hwndMain, LPLANGNODE pLangNode, int iKbdTip, int iPen, int iSpeech, int iExternal, int idxLang) { HWND hwndLang; UINT iCount, ctr; BOOL bSameHKLTip = FALSE; TCHAR szLangText[DESC_MAX]; TCHAR szLayoutName[DESC_MAX]; LPINPUTLANG pInpLang; LPTVITEMNODE pTVItemNode = NULL; HTREEITEM hTVItem; if (pLangNode && iKbdTip == -1) { // // See if the user has Admin privileges. If not, then don't allow // them to install any NEW layouts. // if ((!g_bAdmin_Privileges) && (!g_lpLayout[pLangNode->iLayout].bInstalled)) { // // The layout is not currently installed, so don't allow it // to be added. // Locale_ErrorMsg(hwndMain, IDS_KBD_LAYOUT_FAILED, NULL); return (FALSE); } // // Set the language to active. // Also, set the status to changed so that the layout will be added. // pLangNode->wStatus |= (LANG_CHANGED | LANG_ACTIVE); // // Get language name and add it to treeview // pInpLang = &g_lpLang[pLangNode->iLang]; GetAtomName(pInpLang->atmLanguageName, szLangText, ARRAYSIZE(szLangText)); if (!(pTVItemNode = CreateTVItemNode(pInpLang->dwID))) return FALSE; pTVItemNode->lParam = (LPARAM)pLangNode; AddTreeViewItems(TV_ITEM_TYPE_LANG, szLangText, NULL, NULL, &pTVItemNode); // // Get keyboard layout name and add it to treeview // GetAtomName(g_lpLayout[pLangNode->iLayout].atmLayoutText, szLayoutName, ARRAYSIZE(szLayoutName)); // // Adding the default layout name for each language // if (pTVItemNode && !pTVItemNode->atmDefTipName) pTVItemNode->atmDefTipName = AddAtom(szLayoutName); if (!(pTVItemNode = CreateTVItemNode(pInpLang->dwID))) return FALSE; pTVItemNode->lParam = (LPARAM)pLangNode; hTVItem = AddTreeViewItems(TV_ITEM_TYPE_KBD, szLangText, szInputTypeKbd, szLayoutName, &pTVItemNode); if (hTVItem) TreeView_SelectItem(g_hwndTV, hTVItem); // // Check Thai layout. // if (g_dwPrimLangID == LANG_THAI && hTVItem) { if (PRIMARYLANGID(LOWORD(g_lpLayout[pLangNode->iLayout].dwID)) == LANG_THAI) g_iThaiLayout++; } g_dwChanges |= CHANGE_NEWKBDLAYOUT; } // // Get kbd tip name and add it to treeview // if ((iKbdTip != CB_ERR) && !(g_lpTips[iKbdTip].bEnabled)) { TV_ITEM tvItem; HTREEITEM hTVLangItem; if (g_lpTips[iKbdTip].hklSub) { // // Looking for the same substitute HKL // for (ctr = 0; ctr < g_iTipsBuff; ctr++) { if (ctr == iKbdTip) continue; if (g_lpTips[ctr].hklSub == g_lpTips[iKbdTip].hklSub) { bSameHKLTip = TRUE; break; } } } // // Get TIP name description // GetAtomName(g_lpTips[iKbdTip].atmTipText, szLayoutName, ARRAYSIZE(szLayoutName)); hTVLangItem = FindTVLangItem(g_lpTips[iKbdTip].dwLangID, NULL); if (hTVLangItem) { tvItem.mask = TVIF_HANDLE | TVIF_PARAM; tvItem.hItem = hTVLangItem; if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam) { pTVItemNode = (LPTVITEMNODE) tvItem.lParam; } } else { // // Get language name and add it to treeview // if (!(pTVItemNode = CreateTVItemNode(g_lpTips[iKbdTip].dwLangID))) return FALSE; GetLanguageName(MAKELCID(g_lpTips[iKbdTip].dwLangID, SORT_DEFAULT), szLangText, ARRAYSIZE(szLangText)); AddTreeViewItems(TV_ITEM_TYPE_LANG, szLangText, NULL, NULL, &pTVItemNode); } if (pTVItemNode && g_lpTips[iKbdTip].hklSub) { // // Set the index of keyboard Tip. // pTVItemNode->iIdxTips = iKbdTip; if (!pTVItemNode->atmDefTipName) pTVItemNode->atmDefTipName = AddAtom(szLayoutName); } // // Create TIP layout // if (!(pTVItemNode = CreateTVItemNode(g_lpTips[iKbdTip].dwLangID))) return FALSE; if (pTVItemNode && g_lpTips[iKbdTip].hklSub) { // // Insert a new language node. // pLangNode = Locale_AddToLinkedList(idxLang, 0); if (pLangNode) { pLangNode->iLayout = (UINT) g_lpTips[iKbdTip].iLayout; pLangNode->wStatus |= (LANG_CHANGED | LANG_ACTIVE); pTVItemNode->lParam = (LPARAM)pLangNode; } } pTVItemNode->iIdxTips = iKbdTip; pTVItemNode->clsid = g_lpTips[iKbdTip].clsid; pTVItemNode->guidProfile = g_lpTips[iKbdTip].guidProfile; pTVItemNode->uInputType = INPUT_TYPE_TIP | INPUT_TYPE_KBD; pTVItemNode->hklSub = g_lpTips[iKbdTip].hklSub; // // Get language name from LangID. // GetLanguageName(MAKELCID(g_lpTips[iKbdTip].dwLangID, SORT_DEFAULT), szLangText, ARRAYSIZE(szLangText)); hTVItem = AddTreeViewItems(TV_ITEM_TYPE_KBD, szLangText, szInputTypeKbd, szLayoutName, &pTVItemNode); if (hTVItem) { TreeView_SelectItem(g_hwndTV, hTVItem); g_lpTips[iKbdTip].bEnabled = TRUE; g_iEnabledTips++; g_iEnabledKbdTips++; g_dwChanges |= CHANGE_TIPCHANGE; } if (bSameHKLTip) { for (ctr = 0; ctr < g_iTipsBuff; ctr++) { if (!(g_lpTips[ctr].bEnabled) && g_lpTips[ctr].hklSub == g_lpTips[iKbdTip].hklSub) { // // Create TIP layout // if (!(pTVItemNode = CreateTVItemNode(g_lpTips[ctr].dwLangID))) return FALSE; pTVItemNode->iIdxTips = ctr; pTVItemNode->clsid = g_lpTips[ctr].clsid; pTVItemNode->guidProfile = g_lpTips[ctr].guidProfile; pTVItemNode->uInputType = INPUT_TYPE_TIP | INPUT_TYPE_KBD; pTVItemNode->hklSub = g_lpTips[ctr].hklSub; if (pLangNode) pTVItemNode->lParam = (LPARAM)pLangNode; // // Get language name from LangID and layout name. // GetLanguageName(MAKELCID(g_lpTips[ctr].dwLangID, SORT_DEFAULT), szLangText, ARRAYSIZE(szLangText)); GetAtomName(g_lpTips[ctr].atmTipText, szLayoutName, ARRAYSIZE(szLayoutName)); hTVItem = AddTreeViewItems(TV_ITEM_TYPE_KBD, szLangText, szInputTypeKbd, szLayoutName, &pTVItemNode); if (hTVItem) { TreeView_SelectItem(g_hwndTV, hTVItem); g_lpTips[ctr].bEnabled = TRUE; g_iEnabledTips++; g_iEnabledKbdTips++; g_dwChanges |= CHANGE_TIPCHANGE; } } } } } // // Get pen tip name and add it to treeview // if ((iPen != CB_ERR) && !(g_lpTips[iPen].bEnabled)) { GetAtomName(g_lpTips[iPen].atmTipText, szLayoutName, ARRAYSIZE(szLayoutName)); if (!(pTVItemNode = CreateTVItemNode(g_lpTips[iPen].dwLangID))) return FALSE; pTVItemNode->iIdxTips = iPen; pTVItemNode->clsid = g_lpTips[iPen].clsid; pTVItemNode->guidProfile = g_lpTips[iPen].guidProfile; pTVItemNode->uInputType = INPUT_TYPE_TIP | INPUT_TYPE_PEN; // // Get language name from LangID. // GetLanguageName(MAKELCID(g_lpTips[iPen].dwLangID, SORT_DEFAULT), szLangText, ARRAYSIZE(szLangText)); hTVItem = AddTreeViewItems(TV_ITEM_TYPE_PEN, szLangText, szInputTypePen, szLayoutName, &pTVItemNode); if (hTVItem) { g_lpTips[iPen].bEnabled = TRUE; g_iEnabledTips++; g_dwChanges |= CHANGE_TIPCHANGE; } } // // Get speech tip name and add it to treeview // if ((iSpeech != CB_ERR) && !(g_lpTips[iSpeech].bEnabled)) { GetAtomName(g_lpTips[iSpeech].atmTipText, szLayoutName, ARRAYSIZE(szLayoutName)); if (!(pTVItemNode = CreateTVItemNode(g_lpTips[iSpeech].dwLangID))) return FALSE; pTVItemNode->iIdxTips = iSpeech; pTVItemNode->clsid = g_lpTips[iSpeech].clsid; pTVItemNode->guidProfile = g_lpTips[iSpeech].guidProfile; pTVItemNode->bNoAddCat = g_lpTips[iSpeech].bNoAddCat; pTVItemNode->uInputType = INPUT_TYPE_TIP | INPUT_TYPE_SPEECH; // // Get language name from LangID. // GetLanguageName(MAKELCID(g_lpTips[iSpeech].dwLangID, SORT_DEFAULT), szLangText, ARRAYSIZE(szLangText)); hTVItem = AddTreeViewItems(TV_ITEM_TYPE_SPEECH, szLangText, szInputTypeSpeech, szLayoutName, &pTVItemNode); if (hTVItem) { g_lpTips[iSpeech].bEnabled = TRUE; g_iEnabledTips++; g_dwChanges |= CHANGE_TIPCHANGE; MarkSptipRemoved(FALSE); } } // // Get external tip name and add it to treeview // if ((iExternal != CB_ERR) && !(g_lpTips[iExternal].bEnabled)) { BSTR bstr = NULL; TCHAR szTipTypeName[MAX_PATH]; ITfCategoryMgr *pCategory = NULL; GetAtomName(g_lpTips[iExternal].atmTipText, szLayoutName, ARRAYSIZE(szLayoutName)); if (!(pTVItemNode = CreateTVItemNode(g_lpTips[iExternal].dwLangID))) return FALSE; pTVItemNode->iIdxTips = iExternal; pTVItemNode->clsid = g_lpTips[iExternal].clsid; pTVItemNode->guidProfile = g_lpTips[iExternal].guidProfile; pTVItemNode->bNoAddCat = g_lpTips[iExternal].bNoAddCat; pTVItemNode->uInputType = INPUT_TYPE_TIP | INPUT_TYPE_EXTERNAL; if (g_lpTips[iExternal].uInputType & INPUT_TYPE_SMARTTAG) { pTVItemNode->uInputType |= INPUT_TYPE_SMARTTAG; } // // Get language name from LangID. // GetLanguageName(MAKELCID(g_lpTips[iExternal].dwLangID, SORT_DEFAULT), szLangText, ARRAYSIZE(szLangText)); if (CoCreateInstance(&CLSID_TF_CategoryMgr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfCategoryMgr, (LPVOID *) &pCategory) != S_OK) return FALSE; if (pCategory->lpVtbl->GetGUIDDescription(pCategory, &g_lpTips[iExternal].clsid, &bstr) == S_OK) { StringCchCopy(szTipTypeName, ARRAYSIZE(szTipTypeName), bstr); } else { StringCchCopy(szTipTypeName, ARRAYSIZE(szTipTypeName), szInputTypeExternal); } if (bstr) SysFreeString(bstr); if (pCategory) pCategory->lpVtbl->Release(pCategory); hTVItem = AddTreeViewItems(TV_ITEM_TYPE_EXTERNAL, szLangText, szInputTypeExternal, szLayoutName, &pTVItemNode); if (hTVItem) { g_lpTips[iExternal].bEnabled = TRUE; g_iEnabledTips++; g_dwChanges |= CHANGE_TIPCHANGE; } } // // See the secondary controls according to input layout. // Locale_SetSecondaryControls(hwndMain); // // Add the default language switch hotkey. // Locale_SetDefaultHotKey(hwndMain, TRUE); // // Return success. // return (TRUE); } //////////////////////////////////////////////////////////////////////////// // // Locale_SetupKeyboardLayouts // // Calls setup to get all of the new keyboard layout files. // //////////////////////////////////////////////////////////////////////////// BOOL Locale_SetupKeyboardLayoutsNT4( HWND hwnd) { HINF hKbdInf; HSPFILEQ FileQueue; PVOID QueueContext; UINT i; LPLANGNODE pLangNode; int count; BOOL bInitInf = FALSE; TCHAR szSection[MAX_PATH]; BOOL bRet = TRUE; HWND hwndTV = GetDlgItem(hwnd, IDC_INPUT_LIST); TV_ITEM tvItem; HTREEITEM hItem; HTREEITEM hLangItem; HTREEITEM hGroupItem; tvItem.mask = TVIF_HANDLE | TVIF_PARAM; for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ; hLangItem != NULL ; hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem) ) { for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem); hGroupItem != NULL; hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem)) { for (hItem = TreeView_GetChild(hwndTV, hGroupItem); hItem != NULL; hItem = TreeView_GetNextSibling(hwndTV, hItem)) { LPTVITEMNODE pTVItemNode; tvItem.hItem = hItem; if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam) { pTVItemNode = (LPTVITEMNODE) tvItem.lParam; pLangNode = (LPLANGNODE)pTVItemNode->lParam; if (pLangNode == NULL) continue; } else continue; if ((pLangNode->wStatus & LANG_CHANGED) && (pLangNode->wStatus & LANG_ACTIVE)) { if (!bInitInf) { // // Open the Inf file. // hKbdInf = SetupOpenInfFile(c_szKbdInf, NULL, INF_STYLE_WIN4, NULL); if (hKbdInf == INVALID_HANDLE_VALUE) { return (FALSE); } if (!SetupOpenAppendInfFile(NULL, hKbdInf, NULL)) { SetupCloseInfFile(hKbdInf); return (FALSE); } // // Create a setup file queue and initialize default setup // copy queue callback context. // FileQueue = SetupOpenFileQueue(); if ((!FileQueue) || (FileQueue == INVALID_HANDLE_VALUE)) { SetupCloseInfFile(hKbdInf); return (FALSE); } QueueContext = SetupInitDefaultQueueCallback(hwnd); if (!QueueContext) { SetupCloseFileQueue(FileQueue); SetupCloseInfFile(hKbdInf); return (FALSE); } bInitInf = TRUE; } // // Get the layout name. // StringCchPrintf(szSection, ARRAYSIZE(szSection), TEXT("%s%8.8lx"), c_szPrefixCopy, g_lpLayout[pLangNode->iLayout].dwID ); // // Enqueue the keyboard layout files so that they may be // copied. This only handles the CopyFiles entries in the // inf file. // if (!SetupInstallFilesFromInfSection( hKbdInf, NULL, FileQueue, szSection, NULL, SP_COPY_NEWER )) { // // Setup failed to find the keyboard. Make it inactive // and remove it from the list. // // This shouldn't happen - the inf file is messed up. // Locale_ErrorMsg(hwnd, IDS_KBD_SETUP_FAILED, NULL); pLangNode->wStatus &= ~(LANG_CHANGED | LANG_ACTIVE); if (pTVItemNode) { RemoveTVItemNode(pTVItemNode); } TreeView_DeleteItem(hwndTV, tvItem.hItem ); if ((g_lpLang[pLangNode->iLang].iNumCount) > 1) { (g_lpLang[pLangNode->iLang].iNumCount)--; Locale_RemoveFromLinkedList(pLangNode); } } } } } } if (bInitInf) { DWORD d; // // See if we need to install any files. // // d = 0: User wants new files or some files were missing; // Must commit queue. // // d = 1: User wants to use existing files and queue is empty; // Can skip committing queue. // // d = 2: User wants to use existing files, but del/ren queues // not empty. Must commit queue. The copy queue will // have been emptied, so only del/ren functions will be // performed. // if ((SetupScanFileQueue( FileQueue, SPQ_SCAN_FILE_VALIDITY | SPQ_SCAN_INFORM_USER, hwnd, NULL, NULL, &d )) && (d != 1)) { // // Copy the files in the queue. // if (!SetupCommitFileQueue( hwnd, FileQueue, SetupDefaultQueueCallback, QueueContext )) { // // This can happen if the user hits Cancel from within // the setup dialog. // Locale_ErrorMsg(hwnd, IDS_KBD_SETUP_FAILED, NULL); bRet = FALSE; goto Locale_SetupError; } } Locale_SetupError: // // Terminate the Queue. // SetupTermDefaultQueueCallback(QueueContext); // // Close the file queue. // SetupCloseFileQueue(FileQueue); // // Close the Inf file. // SetupCloseInfFile(hKbdInf); } // // Return success. // return (bRet); } //////////////////////////////////////////////////////////////////////////// // // Locale_ApplyInputs // // 1. make sure we have all the layout files required. // 2. write the information into the registry // 3. call Load/UnloadKeyboardLayout where relevant // // Note that this will trash the previous preload and substitutes sections, // based on what is actually loaded. Thus if something was wrong before in // the registry, it will be corrected now. // //////////////////////////////////////////////////////////////////////////// BOOL Locale_ApplyInputs( HWND hwnd) { BOOL bSetDef = FALSE; UINT iVal, idx, ctr, ctr2, nHotKeys; UINT nLocales = 0; UINT iPreload = 0; LPLANGNODE pLangNode, pTemp; LPINPUTLANG pInpLang; DWORD dwID; TCHAR sz[DESC_MAX]; // temp - build the name of the reg entry TCHAR szPreload10[10]; TCHAR szTemp[MAX_PATH]; HKEY hkeyLayouts; HKEY hkeySubst; HKEY hkeyPreload; HKEY hKeyImm; HKEY hkeyTip; HWND hwndTV = GetDlgItem(hwnd, IDC_INPUT_LIST); HKL hklDefault = 0; HKL hklLoad, hklUnload; HKL hklSub[MAX_DUPLICATED_HKL]; HCURSOR hcurSave; HKEY hkeyScanCode; DWORD cb; TCHAR szShiftL[8]; TCHAR szShiftR[8]; BOOL bHasIme = FALSE; BOOL bReplaced = FALSE; BOOL bCheckedSubhkl; BOOL bDisableCtfmon = FALSE; BOOL bRebootForCUAS = FALSE; BOOL bAlreadyLoadCtfmon = FALSE; TV_ITEM tvItem; HTREEITEM hItem; HTREEITEM hLangItem; HTREEITEM hGroupItem; // // See if the pane is disabled. If so, then there is nothing to // Apply. // if (!IsWindowEnabled(hwndTV)) { return (TRUE); } // // Put up the hour glass. // hcurSave = SetCursor(LoadCursor(NULL, IDC_WAIT)); // // Make sure there are actually changes since the last save when // OK is selected. If the user hits OK without anything to Apply, // then we should do nothing. // if (g_dwChanges == 0 && !g_bAdvChanged) { pLangNode = NULL; for (idx = 0; idx < g_iLangBuff; idx++) { pLangNode = g_lpLang[idx].pNext; while (pLangNode != NULL) { if (pLangNode->wStatus & (LANG_CHANGED | LANG_DEF_CHANGE)) { break; } pLangNode = pLangNode->pNext; } if (pLangNode != NULL) { break; } } if ((idx == g_iLangBuff) && (pLangNode == NULL)) { SetCursor(hcurSave); PropSheet_UnChanged(GetParent(hwnd), hwnd); return (TRUE); } } if (g_OSNT4) { // // Queue up the new layouts and copy the appropriate files to // disk using the setup apis. Only do this if the user has // Admin privileges. // if (g_bAdmin_Privileges && !Locale_SetupKeyboardLayoutsNT4(hwnd)) { SetCursor(hcurSave); return (FALSE); } } // // Clean up the registry. // // // For FE languages, there is a keyboard which has a different // scan code for shift keys - eg. NEC PC9801. // We have to keep information about scan codes for shift keys in // the registry under the 'toggle' sub key as named values. // szShiftL[0] = TEXT('\0'); szShiftR[0] = TEXT('\0'); if (RegOpenKey( HKEY_CURRENT_USER, c_szScanCodeKey, &hkeyScanCode ) == ERROR_SUCCESS) { cb = sizeof(szShiftL); RegQueryValueEx( hkeyScanCode, c_szValueShiftLeft, NULL, NULL, (LPBYTE)szShiftL, &cb ); cb = sizeof(szShiftR); RegQueryValueEx( hkeyScanCode, c_szValueShiftRight, NULL, NULL, (LPBYTE)szShiftR, &cb ); RegCloseKey(hkeyScanCode); } // // Delete the HKCU\Keyboard Layout key and all subkeys. // if (RegOpenKeyEx( HKEY_CURRENT_USER, c_szKbdLayouts, 0, KEY_ALL_ACCESS, &hkeyLayouts ) == ERROR_SUCCESS) { // // Delete the HKCU\Keyboard Layout\Preload, Substitutes, and Toggle // keys in the registry so that the Keyboard Layout section can be // rebuilt. // RegDeleteKey(hkeyLayouts, c_szPreloadKey); RegDeleteKey(hkeyLayouts, c_szSubstKey); RegCloseKey(hkeyLayouts); } // // Create the HKCU\Keyboard Layout key. // if (RegCreateKey( HKEY_CURRENT_USER, c_szKbdLayouts, &hkeyLayouts ) == ERROR_SUCCESS) { // // Create the HKCU\Keyboard Layout\Substitutes key. // if (RegCreateKey( hkeyLayouts, c_szSubstKey, &hkeySubst ) == ERROR_SUCCESS) { // // Create the HKCU\Keyboard Layout\Preload key. // if (RegCreateKey( hkeyLayouts, c_szPreloadKey, &hkeyPreload ) == ERROR_SUCCESS) { // // Initialize the iPreload variable to 1 to show // that the key has been created. // iPreload = 1; } else { RegCloseKey(hkeySubst); } } RegCloseKey(hkeyLayouts); } if (!iPreload) { // // Registry keys could not be created. Now what? // MessageBeep(MB_OK); SetCursor(hcurSave); return (FALSE); } // // Set all usage counts to zero in the language array. // for (idx = 0; idx < g_iLangBuff; idx++) { g_lpLang[idx].iUseCount = 0; } // // Search through the list to see if any keyboard layouts need to be // unloaded from the system. // for (idx = 0; idx < g_iLangBuff; idx++) { pLangNode = g_lpLang[idx].pNext; while (pLangNode != NULL) { if ( (pLangNode->wStatus & LANG_ORIGACTIVE) && !(pLangNode->wStatus & LANG_ACTIVE) ) { // // Before unloading the hkl, look for the corresponding // hotkey and remove it. // DWORD dwHotKeyID = 0; for (ctr = 0; ctr < DSWITCH_HOTKEY_SIZE; ctr++) { if (g_aDirectSwitchHotKey[ctr].hkl == pLangNode->hkl) { // // Found an hkl match. Remember the hotkey ID so // we can delete the hotkey entry later if the // unload of the hkl succeeds. // dwHotKeyID = g_aDirectSwitchHotKey[ctr].dwHotKeyID; break; } } // // Started off with this active, deleting it now. // Failure is not fatal. // if (!UnloadKeyboardLayout(pLangNode->hkl)) { LPLANGNODE pLangNodeNext = NULL; pLangNode->wStatus |= LANG_UNLOAD; pLangNodeNext = pLangNode->pNext; // // Don't need to check TIP case and TIP case also display // message and add the substitute hkl into the tree view. // //if (!IsTipSubstituteHKL((HKL) ((DWORD_PTR)(pLangNode->hkl)))) { Locale_ApplyError( hwnd, pLangNode, IDS_KBD_UNLOAD_KBD_FAILED, MB_OK_OOPS ); // // Failed to unload layout, put it back in the list, // and turn ON the indicator whether it needs it or not. // if (Locale_AddLanguage(hwnd, pLangNode, -1, -1, -1, -1, 0)) { Locale_SetSecondaryControls(hwnd); } } pLangNode = pLangNodeNext; } else { // // Succeeded, no longer in USER's list. // // Reset flag, this could be from ApplyInput and we'll // fail on the OK if we leave it marked as original // active. // pLangNode->wStatus &= ~(LANG_ORIGACTIVE | LANG_CHANGED); // // Remove the hotkey entry for this hkl. // if (dwHotKeyID) { ImmSetHotKey(dwHotKeyID, 0, 0, (HKL)NULL); } // // Remove the link in the language array. // // NOTE: pLangNode could be null here. // pTemp = pLangNode->pNext; Locale_RemoveFromLinkedList(pLangNode); pLangNode = pTemp; } } else { pLangNode = pLangNode->pNext; } } } // // The order in the registry is based on the order in which they // appear in the list box. // // The only exception to this is that the default will be number 1. // // If no default is found, the last one in the list will be used as // the default. // iVal = 2; ctr = 0; // // Check the default keyboard layout not to lose the default HKL. // EnsureDefaultKbdLayout(&nLocales); tvItem.mask = TVIF_HANDLE | TVIF_PARAM; for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ; hLangItem != NULL ; hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem)) { bCheckedSubhkl = FALSE; // // Clear the duplicated HKL buffer index // ctr2 = 0; for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem); hGroupItem != NULL; hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem)) { for (hItem = TreeView_GetChild(hwndTV, hGroupItem); hItem != NULL; hItem = TreeView_GetNextSibling(hwndTV, hItem)) { LPTVITEMNODE pTVItemNode; pLangNode = NULL; tvItem.hItem = hItem; if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam) { pTVItemNode = (LPTVITEMNODE) tvItem.lParam; pLangNode = (LPLANGNODE)pTVItemNode->lParam; } if (!pLangNode && !bCheckedSubhkl && (pTVItemNode->uInputType & INPUT_TYPE_KBD) && pTVItemNode->hklSub) { bCheckedSubhkl = TRUE; if (tvItem.hItem = FindTVLangItem(pTVItemNode->dwLangID, NULL)) { if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam) { LPTVITEMNODE pTVLangItemNode; pTVLangItemNode = (LPTVITEMNODE) tvItem.lParam; pLangNode = (LPLANGNODE)pTVLangItemNode->lParam; } } } if (!pLangNode) continue; if (pTVItemNode->hklSub) { UINT uHklIdx; BOOL bFoundSameHkl = FALSE; for (uHklIdx = 0; uHklIdx < ctr2; uHklIdx++) { if (pTVItemNode->hklSub == hklSub[uHklIdx]) { bFoundSameHkl = TRUE; break; } } // // This substitute HKL is already registered. Skip this HKL. // if (bFoundSameHkl) continue; hklSub[ctr2] = pTVItemNode->hklSub; ctr2++; } if (pLangNode->wStatus & LANG_UNLOAD) { pLangNode->wStatus &= ~LANG_UNLOAD; pLangNode->wStatus &= ~(LANG_CHANGED | LANG_DEF_CHANGE); nLocales--; continue; } pInpLang = &(g_lpLang[pLangNode->iLang]); // // Clear the "set hot key" field, since we will be writing to the // registry. // pLangNode->wStatus &= ~LANG_HOTKEY; // // See if it's the default input locale. // if (!bSetDef && (pLangNode->wStatus & LANG_DEFAULT)) { // // Default input locale, so the preload value should be // set to 1. // iPreload = 1; bSetDef = TRUE; if (pTVItemNode->hklSub) { TCHAR szDefTip[MAX_PATH]; if (g_lpTips && g_lpTips[pTVItemNode->iIdxTips].hklSub == pTVItemNode->hklSub) { BOOL bSave = FALSE; SaveLanguageProfileStatus(bSave, pTVItemNode->iIdxTips, pTVItemNode->hklSub); } } } else if (ctr == (nLocales - 1)) { // // We're on the last one. Make sure there was a default. // iPreload = (iVal <= nLocales) ? iVal : 1; } else { // // Set the preload value to the next value. // iPreload = iVal; iVal++; } ctr++; // // Store the preload value as a string so that it can be written // into the registry (as a value name). // StringCchPrintf(sz, ARRAYSIZE(sz), TEXT("%d"), iPreload); // // Store the locale id as a string so that it can be written // into the registry (as a value). // if ((HIWORD(g_lpLayout[pLangNode->iLayout].dwID) & 0xf000) == 0xe000) { pLangNode->wStatus |= LANG_IME; StringCchPrintf(szPreload10, ARRAYSIZE(szPreload10), TEXT("%8.8lx"), g_lpLayout[pLangNode->iLayout].dwID ); bHasIme = TRUE; } else { pLangNode->wStatus &= ~LANG_IME; dwID = pInpLang->dwID; idx = pInpLang->iUseCount; if ((idx == 0) || (idx > 0xfff)) { idx = 0; } else { dwID |= ((DWORD)(0xd000 | ((WORD)(idx - 1))) << 16); } StringCchPrintf(szPreload10, ARRAYSIZE(szPreload10), TEXT("%08.8x"), dwID); (pInpLang->iUseCount)++; } // // Set the new entry in the registry. It is of the form: // // HKCU\Keyboard Layout // Preload: 1 = // 2 = // etc... // RegSetValueEx( hkeyPreload, sz, 0, REG_SZ, (LPBYTE)szPreload10, (DWORD)(lstrlen(szPreload10) + 1) * sizeof(TCHAR) ); // // See if we need to add a substitute for this input locale. // if (((pInpLang->dwID != g_lpLayout[pLangNode->iLayout].dwID) || idx) && (!(pLangNode->wStatus & LANG_IME))) { // // Get the layout id as a string so that it can be written // into the registry (as a value). // StringCchPrintf(szTemp, ARRAYSIZE(szTemp), TEXT("%8.8lx"), g_lpLayout[pLangNode->iLayout].dwID ); // // Set the new entry in the registry. It is of the form: // // HKCU\Keyboard Layout // Substitutes: = // = // etc... // RegSetValueEx( hkeySubst, szPreload10, 0, REG_SZ, (LPBYTE)szTemp, (DWORD)(lstrlen(szTemp) + 1) * sizeof(TCHAR) ); } // // Make sure all of the changes are written to disk. // RegFlushKey(hkeySubst); RegFlushKey(hkeyPreload); RegFlushKey(HKEY_CURRENT_USER); // // See if the keyboard layout needs to be loaded. // if (pLangNode->wStatus & (LANG_CHANGED | LANG_DEF_CHANGE)) { // // Load the keyboard layout into the system. // if (pLangNode->hklUnload) { hklLoad = LoadKeyboardLayoutEx( pLangNode->hklUnload, szPreload10, KLF_SUBSTITUTE_OK | KLF_NOTELLSHELL | g_dwAttributes ); if (hklLoad != pLangNode->hklUnload) { bReplaced = TRUE; } } else { hklLoad = LoadKeyboardLayout( szPreload10, KLF_SUBSTITUTE_OK | KLF_NOTELLSHELL | g_dwAttributes ); } if (hklLoad) { pLangNode->wStatus &= ~(LANG_CHANGED | LANG_DEF_CHANGE); pLangNode->wStatus |= (LANG_ACTIVE | LANG_ORIGACTIVE); if (pLangNode->wStatus & LANG_DEFAULT) { hklDefault = hklLoad; } pLangNode->hkl = hklLoad; pLangNode->hklUnload = hklLoad; } else { Locale_ApplyError( hwnd, pLangNode, IDS_KBD_LOAD_KBD_FAILED, MB_OK_OOPS ); } } } } } // // Close the handles to the registry keys. // RegCloseKey(hkeySubst); RegCloseKey(hkeyPreload); // // If TIP setting is changed, save the enable/disable status into // registry TIP section. // if ((g_dwChanges & CHANGE_TIPCHANGE) && g_iTipsBuff) { int iIdxDefTip = -1; BOOL bSave = TRUE; SaveLanguageProfileStatus(bSave, iIdxDefTip, NULL); g_dwChanges &= ~CHANGE_TIPCHANGE; } // // Make sure the default is set properly. The layout id for the // current default input locale may have been changed. // // NOTE: This should be done before the Unloads occur in case one // of the layouts to unload is the old default layout. // if (hklDefault != 0) { if (!SystemParametersInfo( SPI_SETDEFAULTINPUTLANG, 0, (LPVOID)((LPDWORD)&hklDefault), 0 )) { // // Failure is not fatal. The old default language will // still work. // Locale_ErrorMsg(hwnd, IDS_KBD_NO_DEF_LANG2, NULL); } else { // // Try to make everything switch to the new default input locale: // if we are in setup OR // if it is the only one (but not if we just replaced the layout // within the Input Locale without changing the input locale) // if (g_bSetupCase || ((nLocales == 1) && !bReplaced)) { DWORD dwRecipients = BSM_APPLICATIONS | BSM_ALLDESKTOPS; BroadcastSystemMessage( BSF_POSTMESSAGE, &dwRecipients, WM_INPUTLANGCHANGEREQUEST, 1, // IS compatible with system font (LPARAM)hklDefault ); } } } // // Apply the advanced tab changes. // if (g_hwndAdvanced != NULL && g_bAdvChanged) { DWORD dwDisableCtfmon; BOOL bPrevDisableCUAS; BOOL bDisabledCUAS; // // Get the previous CUAS status from the registry. // bPrevDisableCUAS = IsDisableCUAS(); // // Save enable/disable CUAS info into the regitry. // if (IsDlgButtonChecked(g_hwndAdvanced, IDC_ADVANCED_CUAS_ENABLE)) { // // Enalbe Cicero Unaware Application Support. // SetDisableCUAS(FALSE); } else { // // Disable Cicero Unaware Application Support. // SetDisableCUAS(TRUE); } bDisabledCUAS = IsDisableCUAS(); if (!g_bSetupCase) { TCHAR szTitle[MAX_PATH]; TCHAR szMsg[MAX_PATH]; BOOL bPrevCtfmon; if (bPrevDisableCUAS != bDisabledCUAS) { // // CUAS option is changed, so need to require the system reboot. // bRebootForCUAS = TRUE; } // // Find language tool bar module(CTFMON.EXE) // if (FindWindow(c_szCTFMonClass, NULL) == NULL) bPrevCtfmon = FALSE; else bPrevCtfmon = TRUE; if (!bPrevCtfmon && !bRebootForCUAS && !IsDlgButtonChecked(g_hwndAdvanced, IDC_ADVANCED_CTFMON_DISABLE)) { // Turn on CTFMON.EXE CicLoadString(hInstance, IDS_TITLE_STRING, szTitle, ARRAYSIZE(szTitle)); CicLoadString(hInstance, IDS_ENABLE_CICERO, szMsg, ARRAYSIZE(szMsg)); // // Notice - Need to restart apps that are already running. // MessageBox(hwnd, szMsg, szTitle, MB_OK); } } // // Save enable/disable CTFMON info into the regitry. // if (IsDlgButtonChecked(g_hwndAdvanced, IDC_ADVANCED_CTFMON_DISABLE)) { // // Set the ctfmon disable flag // dwDisableCtfmon = 1; SetDisalbeCtfmon(dwDisableCtfmon); } else { // // Set the ctfmon enable flag // dwDisableCtfmon = 0; SetDisalbeCtfmon(dwDisableCtfmon); // // Run ctfmon.exe immediately // if (!g_bSetupCase && IsEnabledTipOrMultiLayouts() && IsInteractiveUserLogon()) { RunCtfmonProcess(); bAlreadyLoadCtfmon = TRUE; } } } // // Load the language tool bar if there is any enabled tip, otherwise // disable tool bar // bDisableCtfmon = IsDisableCtfmon(); if (!bDisableCtfmon && g_iInputs >= 2) { // // Load language bar or language icon(ctfmon.exe) // if (!bAlreadyLoadCtfmon && (g_iInputs != g_iOrgInputs)) LoadCtfmon(TRUE, 0, FALSE); if(!g_bSetupCase) EnableWindow(GetDlgItem(hwnd, IDC_TB_SETTING), TRUE); } else { if (bDisableCtfmon || !bHasIme) { LoadCtfmon(FALSE, 0, FALSE); // // Disable language bar setting option button // EnableWindow(GetDlgItem(hwnd, IDC_TB_SETTING), FALSE); } } // // Reset ctfmon change status. // g_bAdvChanged = FALSE; if (g_dwChanges & CHANGE_LANGSWITCH) { Locale_SetLanguageHotkey(); } // // Set the scan code entries in the registry. // if (RegCreateKey( HKEY_CURRENT_USER, c_szScanCodeKey, &hkeyScanCode ) == ERROR_SUCCESS) { if (szShiftL[0]) { RegSetValueEx( hkeyScanCode, c_szValueShiftLeft, 0, REG_SZ, (LPBYTE)szShiftL, (DWORD)(lstrlen(szShiftL) + 1) * sizeof(TCHAR) ); } if (szShiftR[0]) { RegSetValueEx( hkeyScanCode, c_szValueShiftRight, 0, REG_SZ, (LPBYTE)szShiftR, (DWORD)(lstrlen(szShiftR) + 1) * sizeof(TCHAR) ); } RegCloseKey(hkeyScanCode); } // // Call SystemParametersInfo to enable the toggle. // SystemParametersInfo(SPI_SETLANGTOGGLE, 0, NULL, 0); // // Turn off the hour glass. // SetCursor(hcurSave); if ((g_dwChanges & CHANGE_DIRECTSWITCH) || bHasIme || bRebootForCUAS) { g_dwChanges &= ~CHANGE_DIRECTSWITCH; if (RegOpenKey( HKEY_LOCAL_MACHINE, c_szLoadImmPath, &hKeyImm ) == ERROR_SUCCESS) { DWORD dwValue = 1; if ((g_dwChanges & CHANGE_DIRECTSWITCH) || bHasIme) { RegSetValueEx( hKeyImm, TEXT("LoadIMM"), 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD) ); } RegCloseKey(hKeyImm); if (g_bAdmin_Privileges && ((!g_bSetupCase && !GetSystemMetrics(SM_IMMENABLED) && !GetSystemMetrics(SM_DBCSENABLED)) || bRebootForCUAS)) { // // Imm was not loaded. Ask user to reboot and let // it be loaded. // TCHAR szReboot[DESC_MAX]; TCHAR szTitle[DESC_MAX]; CicLoadString(hInstance, IDS_REBOOT_STRING, szReboot, ARRAYSIZE(szReboot)); CicLoadString(hInstance, IDS_TITLE_STRING, szTitle, ARRAYSIZE(szTitle)); if (MessageBox( hwnd, szReboot, szTitle, MB_YESNO | MB_ICONQUESTION ) == IDYES) { Region_RebootTheSystem(); } } } } // // Update the originial input layouts // g_iOrgInputs = g_iInputs; // // Return success. // g_dwChanges = 0; PropSheet_UnChanged(GetParent(hwnd), hwnd); return (TRUE); } //////////////////////////////////////////////////////////////////////////// // // TVSubCVlassProc // // Ignore TreeView item expand or contractibility // //////////////////////////////////////////////////////////////////////////// LRESULT WINAPI TVSubClassProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case (WM_LBUTTONDBLCLK): { return TRUE; } case (WM_KEYDOWN): { if (wParam == VK_LEFT || wParam == VK_RIGHT) return TRUE; } default: { return CallWindowProc(g_lpfnTVWndProc, hwnd, message, wParam, lParam); } } return CallWindowProc(g_lpfnTVWndProc, hwnd, message, wParam, lParam); } //////////////////////////////////////////////////////////////////////////// // // InputLocaleDlgProc // // This is the dialog proc for the Input Locales property sheet. // //////////////////////////////////////////////////////////////////////////// INT_PTR CALLBACK InputLocaleDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { HWND hwndTV = GetDlgItem(hDlg, IDC_INPUT_LIST); switch (message) { case ( WM_DESTROY ) : { Locale_KillPaneDialog(hDlg); if (g_lpfnTVWndProc) SetWindowLongPtr(hwndTV, GWLP_WNDPROC, (LONG_PTR)g_lpfnTVWndProc); break; } case ( WM_HELP ) : { WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, c_szHelpFile, HELP_WM_HELP, (DWORD_PTR)(LPTSTR)aInputHelpIds ); break; } case ( WM_CONTEXTMENU ) : // right mouse click { WinHelp( (HWND)wParam, c_szHelpFile, HELP_CONTEXTMENU, (DWORD_PTR)(LPTSTR)aInputHelpIds ); break; } case ( WM_INITDIALOG ) : { HWND hwndDefList = GetDlgItem(hDlg, IDC_LOCALE_DEFAULT); g_hDlg = hDlg; g_hwndTV = hwndTV; InitPropSheet(hDlg, (LPPROPSHEETPAGE)lParam); // // Create image icons for Language tree view control // CreateImageIcons(); // // Reset the contents of the default locale combo box. // ComboBox_ResetContent(hwndDefList); g_hTVRoot = TreeView_GetRoot(hwndTV); // // Get all installed input information // GetInstalledInput(hDlg); // // Set subclass for treeview control to ignore treeview item expand // or contractibility by mouse or keyboard. // g_lpfnTVWndProc = (WNDPROC) SetWindowLongPtr(hwndTV, GWLP_WNDPROC, (LONG_PTR) TVSubClassProc); Locale_CommandSetDefault(hDlg); // // No longer supporting set default button. // //if (!g_bSetupCase && !g_bCHSystem) { HWND hwndDefBtn; hwndDefBtn = GetDlgItem(hDlg, IDC_KBDL_SET_DEFAULT); EnableWindow(hwndDefBtn, FALSE); ShowWindow(hwndDefBtn, SW_HIDE); } if (FindWindow(c_szCTFMonClass, NULL) == NULL || g_bSetupCase) { // // Disable language bar setting option during the setup mode, // or turned off ctfmon. // EnableWindow(GetDlgItem(hDlg, IDC_TB_SETTING), FALSE); } else { EnableWindow(GetDlgItem(hDlg, IDC_TB_SETTING), TRUE); } break; } case ( WM_NOTIFY ) : { switch (((NMHDR *)lParam)->code) { case TVN_SELCHANGED: { CheckButtons(hDlg); break; } case ( PSN_QUERYCANCEL ) : case ( PSN_KILLACTIVE ) : case ( PSN_RESET ) : break; case ( PSN_APPLY ) : { Locale_ApplyInputs(hDlg); CheckButtons(hDlg); break; } default : { return (FALSE); } } break; } case ( WM_COMMAND ) : { switch (LOWORD(wParam)) { case ( IDC_KBDL_SET_DEFAULT ) : { Locale_CommandSetDefaultLayout(hDlg); break; } case ( IDC_KBDL_ADD ) : { Locale_CommandAdd(hDlg); break; } case ( IDC_KBDL_EDIT ) : { Locale_CommandEdit(hDlg, NULL); break; } case ( IDC_KBDL_DELETE ) : { Locale_CommandDelete(hDlg); break; } case ( IDC_LOCALE_DEFAULT ) : { if (HIWORD(wParam) == CBN_SELCHANGE) { Locale_CommandSetDefault(hDlg); } break; } case ( IDC_HOTKEY_SETTING ) : { if (g_dwChanges & CHANGE_NEWKBDLAYOUT) { TCHAR szApplyMsg[MAX_PATH]; TCHAR szTitle[MAX_PATH]; CicLoadString(hInstance, IDS_KBD_APPLY_WARN, szApplyMsg, ARRAYSIZE(szApplyMsg)); CicLoadString(hInstance, IDS_TITLE_STRING, szTitle, ARRAYSIZE(szTitle)); if (MessageBox(hDlg, szApplyMsg, szTitle, MB_YESNO | MB_ICONQUESTION) == IDYES) { Locale_ApplyInputs(hDlg); } g_dwChanges &= ~CHANGE_NEWKBDLAYOUT; } Locale_CommandHotKeySetting(hDlg); break; } case ( IDC_TB_SETTING ) : { Locale_CommandToolBarSetting(hDlg); break; } case ( IDOK ) : { if (!Locale_ApplyInputs(hDlg)) { break; } // fall thru... } case ( IDCANCEL ) : { EndDialog(hDlg, TRUE); break; } default : { return (FALSE); } } break; } default : { return (FALSE); } } return (TRUE); } //////////////////////////////////////////////////////////////////////////// // // Locale_GetLayoutList // // Fills in the given listbox with the appropriate list of layouts. // //////////////////////////////////////////////////////////////////////////// void Locale_GetLayoutList( HWND hwndLayout, UINT idxLang, UINT idxLayout, BOOL *pfNoDefLayout) { UINT ctr; UINT idx; int idxSel = -1; int idxSame = -1; int idxOther = -1; int idxBase = -1; int idxUSA = -1; // last resort default TCHAR sz[DESC_MAX]; LPLANGNODE pTemp; DWORD LangID = g_lpLang[idxLang].dwID; DWORD BaseLangID = (LOWORD(LangID) & 0xff) | 0x400; // // Reset the contents of the combo box. // ComboBox_ResetContent(hwndLayout); // // Search through all of the layouts. // for (ctr = 0; ctr < g_iLayoutBuff; ctr++) { // // Filter out IME layout if it is not under native locale. // if (((HIWORD(g_lpLayout[ctr].dwID) & 0xf000) == 0xe000) && (LOWORD(g_lpLayout[ctr].dwID) != LOWORD(LangID))) { continue; } // // Make sure this layout isn't already used for this input locale. // If it is, then don't display it in the properties dialog. // if (ctr != idxLayout) { pTemp = g_lpLang[idxLang].pNext; while (pTemp) { if (pTemp->wStatus & LANG_ACTIVE) { if (ctr == pTemp->iLayout) { break; } } pTemp = pTemp->pNext; } if (pTemp && (ctr == pTemp->iLayout)) { continue; } } // // Get the layout text. If it doesn't already exist in the // combo box, then add it to the list of possible layouts. // GetAtomName(g_lpLayout[ctr].atmLayoutText, sz, ARRAYSIZE(sz)); if ((idx = ComboBox_FindStringExact(hwndLayout, 0, sz)) == CB_ERR) { // // Filter out TIP substitute HKL. // if (IsTipSubstituteHKL(IntToPtr(g_lpLayout[ctr].dwID))) { AddKbdLayoutOnKbdTip(IntToPtr(g_lpLayout[ctr].dwID), ctr); continue; } // // Add the layout string and set the item data to be the // index into the g_lpLayout array. // idx = ComboBox_AddString(hwndLayout, sz); ComboBox_SetItemData(hwndLayout, idx, MAKELONG(ctr, 0)); // // See if it's the US layout. If so, save the index. // if (g_lpLayout[ctr].dwID == US_LOCALE) { idxUSA = ctr; } } if (idxLayout == -1) { // // If the caller does not specify a layout, it must be the // Add dialog. First we want the default layout. If the // default layout is not an option (eg. it's already used), // then we want any layout that has the same id as the locale // to be the default. // if (idxSel == -1) { if (g_lpLayout[ctr].dwID == g_lpLang[idxLang].dwDefaultLayout) { idxSel = ctr; } else if (idxSame == -1) { if ((LOWORD(g_lpLayout[ctr].dwID) == LOWORD(LangID)) && (HIWORD(g_lpLayout[ctr].dwID) == 0)) { idxSame = ctr; } else if (idxOther == -1) { if (LOWORD(g_lpLayout[ctr].dwID) == LOWORD(LangID)) { idxOther = ctr; } else if ((idxBase == -1) && (LOWORD(g_lpLayout[ctr].dwID) == LOWORD(BaseLangID))) { idxBase = ctr; } } } } } else if (ctr == idxLayout) { // // For the properties dialog, we want the one ALREADY associated. // idxSel = ctr; } } // // If it's the Add dialog, do some extra checking for the layout to use. // if (idxLayout == -1) { if (idxSel == -1) { idxSel = (idxSame != -1) ? idxSame : ((idxOther != -1) ? idxOther : idxBase); } } // // If a default layout was not found, then set it to the US layout. // if (idxSel == -1) { idxSel = idxUSA; *pfNoDefLayout = TRUE; } // // Set the current selection. // if (idxSel == -1) { // // Simply set the current selection to be the first entry // in the list. // ComboBox_SetCurSel(hwndLayout, 0); } else { // // The combo box is sorted, but we need to know where // g_lpLayout[idxSel] was stored. So, get the atom again, and // search the list. // GetAtomName(g_lpLayout[idxSel].atmLayoutText, sz, ARRAYSIZE(sz)); idx = ComboBox_FindStringExact(hwndLayout, 0, sz); ComboBox_SetCurSel(hwndLayout, idx); } } //////////////////////////////////////////////////////////////////////////// // // Locale_GetTipList // //////////////////////////////////////////////////////////////////////////// void Locale_GetTipList( HWND hwnd, UINT uInxLang, BOOL bNoDefKbd) { UINT ctr; int idxDefKbd = -1; BOOL bPenOn = FALSE; BOOL bSpeechOn = FALSE; BOOL bExternalOn = FALSE; TCHAR szTipName[DESC_MAX]; TCHAR szNone[DESC_MAX]; UINT uIdx; DWORD dwLangID = g_lpLang[uInxLang].dwID; HWND hwndKbd = GetDlgItem(hwnd, IDC_KBDLA_LAYOUT); HWND hwndPen = GetDlgItem(hwnd, IDC_PEN_TIP); HWND hwndPenText = GetDlgItem(hwnd, IDC_PEN_TEXT); HWND hwndSpeech = GetDlgItem(hwnd, IDC_SPEECH_TIP); HWND hwndSpeechText = GetDlgItem(hwnd, IDC_SPEECH_TEXT); HWND hwndExternal = GetDlgItem(hwnd, IDC_EXTERNAL_TIP); HWND hwndExternalText = GetDlgItem(hwnd, IDC_EXTERNAL_TEXT); // // Reset the contents of the combo box. // ComboBox_ResetContent(hwndPen); ComboBox_ResetContent(hwndSpeech); ComboBox_ResetContent(hwndExternal); if (g_iTipsBuff == 0) { EnableWindow(hwndPen, FALSE); EnableWindow(hwndPenText, FALSE); EnableWindow(hwndSpeech, FALSE); EnableWindow(hwndSpeechText, FALSE); EnableWindow(hwndExternal, FALSE); EnableWindow(hwndExternalText, FALSE); return; } for (ctr = 0; ctr < g_iTipsBuff; ctr++) { if ((dwLangID == g_lpTips[ctr].dwLangID) && (g_lpTips[ctr].uInputType != INPUT_TYPE_KBD)) { // // Get the Tips text. // GetAtomName(g_lpTips[ctr].atmTipText, szTipName, ARRAYSIZE(szTipName)); if ((g_lpTips[ctr].uInputType & INPUT_TYPE_PEN) && !(g_lpTips[ctr].bEnabled)) { uIdx = ComboBox_AddString(hwndPen, szTipName); ComboBox_SetItemData(hwndPen, uIdx, MAKELONG(ctr, 0)); bPenOn = TRUE; } else if ((g_lpTips[ctr].uInputType & INPUT_TYPE_SPEECH) && !(g_lpTips[ctr].bEnabled) && g_lpTips[ctr].fEngineAvailable) { uIdx = ComboBox_AddString(hwndSpeech, szTipName); ComboBox_SetItemData(hwndSpeech, uIdx, MAKELONG(ctr, 0)); bSpeechOn = TRUE; } else if ((g_lpTips[ctr].uInputType & INPUT_TYPE_KBD) && !(g_lpTips[ctr].bEnabled)) { uIdx = ComboBox_AddString(hwndKbd, szTipName); ComboBox_SetItemData(hwndKbd, uIdx, MAKELONG(ctr, 1)); idxDefKbd = uIdx; } else if((g_lpTips[ctr].uInputType & INPUT_TYPE_EXTERNAL) && !(g_lpTips[ctr].bEnabled)) { uIdx = ComboBox_AddString(hwndExternal, szTipName); ComboBox_SetItemData(hwndExternal, uIdx, MAKELONG(ctr, 0)); bExternalOn = TRUE; } } } if (idxDefKbd != -1) { ComboBox_SetCurSel(hwndKbd, idxDefKbd); } EnableWindow(hwndPen, IsDlgButtonChecked(hwnd, IDC_PEN_TEXT)); EnableWindow(hwndPenText, bPenOn); ComboBox_SetCurSel(hwndPen, 0); EnableWindow(hwndSpeech, IsDlgButtonChecked(hwnd, IDC_SPEECH_TEXT)); EnableWindow(hwndSpeechText, bSpeechOn); ComboBox_SetCurSel(hwndSpeech, 0); EnableWindow(hwndExternal, IsDlgButtonChecked(hwnd, IDC_EXTERNAL_TEXT)); EnableWindow(hwndExternalText, bExternalOn); ComboBox_SetCurSel(hwndExternal, 0); } //////////////////////////////////////////////////////////////////////////// // // Locale_AddDlgInit // // Processing for a WM_INITDIALOG message for the Add dialog box. // //////////////////////////////////////////////////////////////////////////// BOOL Locale_AddDlgInit( HWND hwnd, LPARAM lParam) { UINT ctr1; UINT idx; TCHAR sz[DESC_MAX]; LPLANGNODE pLangNode; int nLocales, idxList, IMELayoutExist = 0; UINT ctr2, ListCount, DefaultIdx = 0; LRESULT LCSelectData = (LONG)-1; BOOL bNoDefLayout = FALSE; DWORD dwCurLang = 0; TV_ITEM tvItem; HTREEITEM hTVItem; HWND hwndLang = GetDlgItem(hwnd, IDC_KBDLA_LOCALE); // // Get the currently chosen input locale in the parent dialog's // treeview list box. // hTVItem = TreeView_GetSelection(g_hwndTV); if (!hTVItem) return FALSE; tvItem.mask = TVIF_HANDLE | TVIF_PARAM; tvItem.hItem = hTVItem; if (TreeView_GetItem(g_hwndTV, &tvItem)) { if ((LPTVITEMNODE) tvItem.lParam) { dwCurLang = ((LPTVITEMNODE) tvItem.lParam)->dwLangID; } } // // Go through all of the input locales. Display all of them, // since we can have multiple layouts per locale. // // Do NOT go down the links in this case. We don't want to display // the language choice multiple times. // for (ctr1 = 0; ctr1 < g_iLangBuff; ctr1++) { // // If the language does not contain an IME layout, then // compare with layout counts without IME. // for (ctr2 = 0; ctr2 < g_iLayoutBuff; ctr2++) { if ((LOWORD(g_lpLayout[ctr2].dwID) == LOWORD(g_lpLang[ctr1].dwID)) && ((HIWORD(g_lpLayout[ctr2].dwID) & 0xf000) == 0xe000)) { IMELayoutExist = 1; break; } } if ((!IMELayoutExist) && (g_lpLang[ctr1].iNumCount == (g_iLayoutBuff - g_iLayoutIME)) && (g_iTipsBuff == 0)) { // // No more layouts to be added for this language. // continue; } // // Make sure there are layouts to be added for this // input locale. // if ((g_lpLang[ctr1].iNumCount != g_iLayoutBuff) || (g_iTipsBuff != 0 && IsTipAvailableForAdd(g_lpLang[ctr1].dwID))) { // // Get the language name, add the string to the // combo box, and set the index into the g_lpLang // array as the item data. // GetAtomName(g_lpLang[ctr1].atmLanguageName, sz, ARRAYSIZE(sz)); idx = ComboBox_AddString(hwndLang, sz); ComboBox_SetItemData(hwndLang, idx, MAKELONG(ctr1, 0)); // // Save system default locale. // if (LCSelectData == -1) { if (g_lpLang[ctr1].dwID == GetSystemDefaultLCID()) { LCSelectData = MAKELONG(ctr1, 0); } } // // Save chosen input locale. // if (dwCurLang && (g_lpLang[ctr1].dwID == dwCurLang)) { LCSelectData = MAKELONG(ctr1, 0); dwCurLang = 0; } } } // // Set the current selection to the currently chosen input locale // or the default system locale entry. // if (LCSelectData != -1) { ListCount = ComboBox_GetCount(hwndLang); for (ctr1 = 0; ctr1 < ListCount; ctr1++) { if (LCSelectData == ComboBox_GetItemData(hwndLang, ctr1)) { DefaultIdx = ctr1; break; } } } ComboBox_SetCurSel(hwndLang, DefaultIdx); idx = (UINT)ComboBox_GetItemData(hwndLang, DefaultIdx); SetProp(hwnd, szPropHwnd, (HANDLE)((LPINITINFO)lParam)->hwndMain); SetProp(hwnd, szPropIdx, (HANDLE)UIntToPtr(idx)); // // Check available language. // if (idx == -1) { // // No languages // Locale_ErrorMsg(hwnd, IDS_KBD_NO_MORE_TO_ADD, NULL); return FALSE; } // // Display the keyboard layout. // Locale_GetLayoutList(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT), idx, -1, &bNoDefLayout); Locale_GetTipList(hwnd, idx, bNoDefLayout); // // Checking for keyboard layout. If user already has this language, // we want to give a choice to enable/disable keyboard layout. Otherwise, // just enable the adding keyboard layouts. // if (g_bPenOrSapiTip || g_bExtraTip) { if (FindTVLangItem(g_lpLang[idx].dwID, NULL)) { CheckDlgButton(hwnd, IDC_KBDLA_LAYOUT_TEXT, BST_UNCHECKED); EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT_TEXT), TRUE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT), FALSE); } else { CheckDlgButton(hwnd, IDC_KBDLA_LAYOUT_TEXT, BST_CHECKED); EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT_TEXT), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT), TRUE); } } // // Disable the keyboard layout if there is no available layout. // if (!ComboBox_GetCount(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT))) { EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT_TEXT), FALSE); } return TRUE; } //////////////////////////////////////////////////////////////////////////// // // Locale_AddCommandOK // // Gets the currently selected input locale from the combo box and marks // it as active in the g_lpLang list. It then gets the requested layout // and sets that in the list. It then adds the new input locale string // to the input locale list in the property sheet. // //////////////////////////////////////////////////////////////////////////// int Locale_AddCommandOK( HWND hwnd) { LPLANGNODE pLangNode = NULL; HWND hwndLang = GetDlgItem(hwnd, IDC_KBDLA_LOCALE); HWND hwndLayout = GetDlgItem(hwnd, IDC_KBDLA_LAYOUT); HWND hwndPen = GetDlgItem(hwnd, IDC_PEN_TIP); HWND hwndSpeech = GetDlgItem(hwnd, IDC_SPEECH_TIP); HWND hwndExternal = GetDlgItem(hwnd, IDC_EXTERNAL_TIP); int idxLang = ComboBox_GetCurSel(hwndLang); int idxLayout = ComboBox_GetCurSel(hwndLayout); int idxPen = ComboBox_GetCurSel(hwndPen); int idxSpeech = ComboBox_GetCurSel(hwndSpeech); int idxExternal = ComboBox_GetCurSel(hwndExternal); int iPen = -1; int iSpeech = -1; int iExternal = -1; int iKbdLayout = -1; WORD wDefault = 0; // // Get the offset for the language to add. // idxLang = (int)ComboBox_GetItemData(hwndLang, idxLang); // // Get the offset for the chosen keyboard layout. // if (IsDlgButtonChecked(hwnd, IDC_KBDLA_LAYOUT_TEXT) || !(g_bPenOrSapiTip || g_bExtraTip)) iKbdLayout = (int)ComboBox_GetItemData(hwndLayout, idxLayout); // // Get the offset for the chosen Tips. // if (hwndPen && hwndSpeech) { if (IsDlgButtonChecked(hwnd, IDC_PEN_TEXT)) iPen = (int) ComboBox_GetItemData(hwndPen, idxPen); if (IsDlgButtonChecked(hwnd, IDC_SPEECH_TEXT)) iSpeech = (int) ComboBox_GetItemData(hwndSpeech, idxSpeech); } if (hwndExternal) { if (IsDlgButtonChecked(hwnd, IDC_EXTERNAL_TEXT)) iExternal = (int) ComboBox_GetItemData(hwndExternal, idxExternal); } // // Selected no keyboard layout // if (iKbdLayout == CB_ERR) goto AddLang; if (HIWORD(iKbdLayout)) { iKbdLayout = LOWORD(iKbdLayout); } else { // // Need to check win9x system, since win9x doesn't support multiple // keyboard layout on the same language. But FE system can have multiple // IME layouts // if ((g_OSWIN95 && !IsFELangID(g_lpLang[idxLang].dwID)) && (g_lpLang[idxLang].iNumCount)) { TCHAR szTemp[DESC_MAX]; TCHAR szMsg[DESC_MAX]; TCHAR szNewLayout[DESC_MAX]; CicLoadString(hInstance, IDS_KBD_LAYOUTEDIT, szMsg, ARRAYSIZE(szMsg)); GetAtomName(g_lpLayout[iKbdLayout].atmLayoutText, szNewLayout, ARRAYSIZE(szNewLayout)); StringCchPrintf(szTemp, ARRAYSIZE(szTemp), szMsg, szNewLayout); // // Ask user whether new selected keyboard layout will be replaced // or not. // if (MessageBox(hwnd, szTemp, NULL, MB_YESNO | MB_ICONQUESTION) == IDYES) { HTREEITEM hItem; LPLANGNODE pOldLangNode = g_lpLang[idxLang].pNext; GetAtomName(g_lpLayout[pOldLangNode->iLayout].atmLayoutText, szTemp, ARRAYSIZE(szTemp)); // // Find installed keyboard layout to delete it. // if (hItem = FindTVItem(g_lpLang[idxLang].dwID, szTemp)) { TV_ITEM tvItem; tvItem.mask = TVIF_HANDLE | TVIF_PARAM; tvItem.hItem = hItem; pOldLangNode->wStatus &= ~LANG_ACTIVE; pOldLangNode->wStatus |= LANG_CHANGED; if (pOldLangNode->wStatus & LANG_DEFAULT) wDefault = LANG_DEFAULT; g_lpLang[pOldLangNode->iLang].iNumCount--; Locale_RemoveFromLinkedList(pOldLangNode); if (TreeView_GetItem(g_hwndTV, &tvItem) && tvItem.lParam) { RemoveTVItemNode((LPTVITEMNODE)tvItem.lParam); TreeView_DeleteItem(g_hwndTV, tvItem.hItem ); } g_iInputs--; } } else { // // Cancel - leave installed keyboard layout without changing. // Check if there are other tips to be installed. // iKbdLayout = -1; goto AddLang; } } // // Insert a new language node. // pLangNode = Locale_AddToLinkedList(idxLang, 0); if (!pLangNode) { return (0); } // // Get the offset for the chosen keyboard layout. // pLangNode->iLayout = (UINT) iKbdLayout; // // Set ikbdLayout as the default to distinguish keyboard tip from layouts. // iKbdLayout = -1; // // Set the default hkl after replacing the default hkl with new one. // if (g_OSWIN95) pLangNode->wStatus |= wDefault; // // See if the layout is an IME and mark the status bits accordingly. // if ((HIWORD(g_lpLayout[pLangNode->iLayout].dwID) & 0xf000) == 0xe000) { pLangNode->wStatus |= LANG_IME; } else { pLangNode->wStatus &= ~LANG_IME; } } AddLang: // // Add the new language. // if (!Locale_AddLanguage(GetProp(hwnd, szPropHwnd), pLangNode, iKbdLayout, iPen, iSpeech, iExternal, idxLang)) { // // Unable to add the language. Need to return the user back // to the Add dialog. // if (pLangNode) Locale_RemoveFromLinkedList(pLangNode); return (0); } // // Return success. // return (1); } //////////////////////////////////////////////////////////////////////////// // // KbdLocaleAddDlg // // This is the dialog proc for the Add button of the Input Locales // property sheet. // //////////////////////////////////////////////////////////////////////////// INT_PTR CALLBACK KbdLocaleAddDlg( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case ( WM_INITDIALOG ) : { if (!Locale_AddDlgInit(hwnd, lParam)) { EndDialog(hwnd, 0); } break; } case ( WM_HELP ) : { WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, c_szHelpFile, HELP_WM_HELP, (DWORD_PTR)(LPTSTR)aLocaleAddHelpIds ); break; } case ( WM_CONTEXTMENU ) : // right mouse click { WinHelp( (HWND)wParam, c_szHelpFile, HELP_CONTEXTMENU, (DWORD_PTR)(LPTSTR)aLocaleAddHelpIds ); break; } case ( WM_DESTROY ) : { RemoveProp(hwnd, szPropHwnd); RemoveProp(hwnd, szPropIdx); break; } case ( WM_COMMAND ) : { switch (LOWORD(wParam)) { case ( IDOK ) : { if (!Locale_AddCommandOK(hwnd)) { // // This means the properties dialog was cancelled. // The Add dialog should remain active. // break; } // fall thru... } case ( IDCANCEL ) : { EndDialog(hwnd, (wParam == IDOK) ? 1 : 0); break; } case ( IDC_KBDLA_LOCALE ) : { if (HIWORD(wParam) == CBN_SELCHANGE) { HWND hwndLocale = (HWND)lParam; HWND hwndLayout = GetDlgItem(hwnd, IDC_KBDLA_LAYOUT); BOOL bNoDefLayout = FALSE; int idx; // // Update the keyboard layout lists. // if ((idx = ComboBox_GetCurSel(hwndLocale)) != CB_ERR) { idx = (int)ComboBox_GetItemData(hwndLocale, idx); Locale_GetLayoutList(hwndLayout, idx, -1, &bNoDefLayout); Locale_GetTipList(hwnd, idx, bNoDefLayout); } // // Check the keyboard layout visibility // if (g_bPenOrSapiTip || g_bExtraTip) { if (FindTVLangItem(g_lpLang[idx].dwID, NULL)) { CheckDlgButton(hwnd, IDC_KBDLA_LAYOUT_TEXT, BST_UNCHECKED); EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT_TEXT), TRUE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT), FALSE); } else { // // There isn't this language in the user configuration, so // force to add a keyboard layout for this language. // CheckDlgButton(hwnd, IDC_KBDLA_LAYOUT_TEXT, BST_CHECKED); EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT_TEXT), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT), TRUE); } } // // Disable the keyboard layout if there is no available layout. // if (!ComboBox_GetCount(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT))) { EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT_TEXT), FALSE); } } break; } case (IDC_KBDLA_LAYOUT_TEXT) : { EnableWindow(GetDlgItem(hwnd, IDC_KBDLA_LAYOUT), IsDlgButtonChecked(hwnd, IDC_KBDLA_LAYOUT_TEXT)); break; } case (IDC_PEN_TEXT) : { EnableWindow(GetDlgItem(hwnd, IDC_PEN_TIP), IsDlgButtonChecked(hwnd, IDC_PEN_TEXT)); break; } case (IDC_SPEECH_TEXT) : { EnableWindow(GetDlgItem(hwnd, IDC_SPEECH_TIP), IsDlgButtonChecked(hwnd, IDC_SPEECH_TEXT)); break; } case (IDC_EXTERNAL_TEXT) : { EnableWindow(GetDlgItem(hwnd, IDC_EXTERNAL_TIP), IsDlgButtonChecked(hwnd, IDC_EXTERNAL_TEXT)); break; } default : { return (FALSE); } } break; } default : { return (FALSE); } } return (TRUE); } //////////////////////////////////////////////////////////////////////////// // // GetToolBarSetting // //////////////////////////////////////////////////////////////////////////// void GetToolBarSetting( HWND hwnd) { HRESULT hr; DWORD dwTBFlag = 0; ITfLangBarMgr *pLangBar = NULL; if (!g_OSNT5) { EnableWindow(GetDlgItem(hwnd, IDC_TB_HIGHTRANS), FALSE); } // // load LangBar manager // hr = CoCreateInstance(&CLSID_TF_LangBarMgr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfLangBarMgr, (LPVOID *) &pLangBar); if (SUCCEEDED(hr)) pLangBar->lpVtbl->GetShowFloatingStatus(pLangBar, &dwTBFlag); // // Set the language bar show/close. // CheckDlgButton(hwnd, IDC_TB_SHOWLANGBAR, !(dwTBFlag & TF_SFT_HIDDEN)); if (!(dwTBFlag & TF_SFT_SHOWNORMAL)) { // Disable langbar setting options //EnableWindow(GetDlgItem(hwnd, IDC_TB_EXTRAICON), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_TB_HIGHTRANS), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_TB_TEXTLABELS), FALSE); } // // Set language bar extra icons in case of minimized. // CheckDlgButton(hwnd, IDC_TB_EXTRAICON, dwTBFlag & TF_SFT_EXTRAICONSONMINIMIZED); // // Set the default toolbar transparency option. // CheckDlgButton(hwnd, IDC_TB_HIGHTRANS, !(dwTBFlag & TF_SFT_NOTRANSPARENCY)); // // Set the default toolbar show text option. // CheckDlgButton(hwnd, IDC_TB_TEXTLABELS, dwTBFlag & TF_SFT_LABELS); if (pLangBar) pLangBar->lpVtbl->Release(pLangBar); } //////////////////////////////////////////////////////////////////////////// // // ToolBarSettingInit // //////////////////////////////////////////////////////////////////////////// void ToolBarSettingInit( HWND hwnd) { HWND hwndCTFMon = NULL; // // Find language tool bar module(CTFMON.EXE) // hwndCTFMon = FindWindow(c_szCTFMonClass, NULL); if (hwndCTFMon) { EnableWindow(GetDlgItem(hwnd, IDC_TB_SHOWLANGBAR), TRUE); EnableWindow(GetDlgItem(hwnd, IDC_TB_EXTRAICON), TRUE); GetToolBarSetting(hwnd); } else { EnableWindow(GetDlgItem(hwnd, IDC_TB_SHOWLANGBAR), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_TB_EXTRAICON), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_TB_HIGHTRANS), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_TB_TEXTLABELS), FALSE); } } //////////////////////////////////////////////////////////////////////////// // // ToolBarSettingOK // //////////////////////////////////////////////////////////////////////////// void ToolBarSettingOK( HWND hwnd) { DWORD dwDisableCtfmon; HRESULT hr; DWORD dwTBFlag = 0; ITfLangBarMgr *pLangBar = NULL; g_dwToolBar = 0; // // Load LangBar manager and get the current status. // hr = CoCreateInstance(&CLSID_TF_LangBarMgr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfLangBarMgr, (LPVOID *) &pLangBar); if (SUCCEEDED(hr)) pLangBar->lpVtbl->GetShowFloatingStatus(pLangBar, &dwTBFlag); if (pLangBar) pLangBar->lpVtbl->Release(pLangBar); if (IsDlgButtonChecked(hwnd, IDC_TB_SHOWLANGBAR)) { if (dwTBFlag & TF_SFT_HIDDEN) { g_dwToolBar |= TF_SFT_SHOWNORMAL; } else { if (dwTBFlag & TF_SFT_SHOWNORMAL) g_dwToolBar |= TF_SFT_SHOWNORMAL; else if (dwTBFlag & TF_SFT_DOCK) g_dwToolBar |= TF_SFT_DOCK; else if (dwTBFlag & TF_SFT_MINIMIZED) g_dwToolBar |= TF_SFT_MINIMIZED; else if (dwTBFlag & TF_SFT_DESKBAND) g_dwToolBar |= TF_SFT_DESKBAND; } } else { g_dwToolBar |= TF_SFT_HIDDEN; } // // Get the extra icons // if (IsDlgButtonChecked(hwnd, IDC_TB_EXTRAICON)) g_dwToolBar |= TF_SFT_EXTRAICONSONMINIMIZED; else g_dwToolBar |= TF_SFT_NOEXTRAICONSONMINIMIZED; // // Get the transparency setting // if (IsDlgButtonChecked(hwnd, IDC_TB_HIGHTRANS)) g_dwToolBar |= TF_SFT_LOWTRANSPARENCY; else g_dwToolBar |= TF_SFT_NOTRANSPARENCY; // // Get the label setting // if (IsDlgButtonChecked(hwnd, IDC_TB_TEXTLABELS)) g_dwToolBar |= TF_SFT_LABELS; else g_dwToolBar |= TF_SFT_NOLABELS; // // Update toolbar setting on the Apply button. // UpdateToolBarSetting(); } //////////////////////////////////////////////////////////////////////////// // // ToolBarSettingDlg // // This is the dialog proc for the ToolBar Setting Dlg. // //////////////////////////////////////////////////////////////////////////// INT_PTR CALLBACK ToolBarSettingDlg( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case ( WM_INITDIALOG ) : { ToolBarSettingInit(hwnd); break; } case ( WM_HELP ) : { WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, c_szHelpFile, HELP_WM_HELP, (DWORD_PTR)(LPTSTR)aToolbarSettingsHelpIds ); break; } case ( WM_CONTEXTMENU ) : // right mouse click { WinHelp( (HWND)wParam, c_szHelpFile, HELP_CONTEXTMENU, (DWORD_PTR)(LPTSTR)aToolbarSettingsHelpIds ); break; } case ( WM_DESTROY ) : { break; } case ( WM_COMMAND ) : { switch (LOWORD(wParam)) { case ( IDOK ) : { ToolBarSettingOK(hwnd); // fall thru... } case ( IDCANCEL ) : { EndDialog(hwnd, (wParam == IDOK) ? 1 : 0); break; } case ( IDC_TB_SHOWLANGBAR ) : { BOOL bShowLangBar; bShowLangBar = IsDlgButtonChecked(hwnd, IDC_TB_SHOWLANGBAR); EnableWindow(GetDlgItem(hwnd, IDC_TB_EXTRAICON), bShowLangBar); EnableWindow(GetDlgItem(hwnd, IDC_TB_HIGHTRANS), bShowLangBar); EnableWindow(GetDlgItem(hwnd, IDC_TB_TEXTLABELS), bShowLangBar); } default : { return (FALSE); } } break; } default : { return (FALSE); } } return (TRUE); } //////////////////////////////////////////////////////////////////////////// // // Locale_TranslateHotKey // // Translates hotkey modifiers and values into key names. // //////////////////////////////////////////////////////////////////////////// void Locale_TranslateHotKey( LPTSTR lpString, UINT cchString, UINT uVKey, UINT uModifiers) { UINT ctr; TCHAR szBuffer[DESC_MAX]; BOOL bMod = FALSE; lpString[0] = 0; if (uModifiers & MOD_CONTROL) { CicLoadString(hInstance, IDS_KBD_MOD_CONTROL, szBuffer, ARRAYSIZE(szBuffer)); StringCchCat(lpString, cchString, szBuffer); bMod = TRUE; } if (uModifiers & MOD_ALT) { CicLoadString(hInstance, IDS_KBD_MOD_LEFT_ALT, szBuffer, ARRAYSIZE(szBuffer)); StringCchCat(lpString, cchString, szBuffer); bMod = TRUE; } if (uModifiers & MOD_SHIFT) { CicLoadString(hInstance, IDS_KBD_MOD_SHIFT, szBuffer, ARRAYSIZE(szBuffer)); StringCchCat(lpString, cchString, szBuffer); bMod = TRUE; } if (uVKey == 0) { if (!bMod) { GetAtomName( g_aVirtKeyDesc[0].atVirtKeyName, szBuffer, sizeof(szBuffer) / sizeof(TCHAR) ); StringCchCat(lpString, cchString, szBuffer); return; } else { // // Only modifiers, remove the "+" at the end. // lpString[lstrlen(lpString) - 1] = 0; return; } } for (ctr = 0; (ctr < sizeof(g_aVirtKeyDesc) / sizeof(VIRTKEYDESC)); ctr++) { if (g_aVirtKeyDesc[ctr].uVirtKeyValue == uVKey) { GetAtomName( g_aVirtKeyDesc[ctr].atVirtKeyName, szBuffer, sizeof(szBuffer) / sizeof(TCHAR) ); StringCchCat(lpString, cchString, szBuffer); return; } } GetAtomName( g_aVirtKeyDesc[0].atVirtKeyName, szBuffer, sizeof(szBuffer) / sizeof(TCHAR) ); StringCchCat(lpString, cchString, szBuffer); } //////////////////////////////////////////////////////////////////////////// // // Locale_HotKeyDrawItem // // Draws the hotkey list box. // //////////////////////////////////////////////////////////////////////////// void Locale_HotKeyDrawItem( HWND hWnd, LPDRAWITEMSTRUCT lpDis) { LPHOTKEYINFO pHotKeyNode; COLORREF crBk, crTxt; UINT uStrLen, uAlign; TCHAR szString[DESC_MAX]; TCHAR szHotKey[DESC_MAX]; SIZE Size; UINT iMaxChars; int iMaxWidth; if (!ListBox_GetCount(lpDis->hwndItem)) { return; } pHotKeyNode = (LPHOTKEYINFO)lpDis->itemData; crBk = SetBkColor( lpDis->hDC, (lpDis->itemState & ODS_SELECTED) ? GetSysColor(COLOR_HIGHLIGHT) : GetSysColor(COLOR_WINDOW) ); crTxt = SetTextColor( lpDis->hDC, (lpDis->itemState & ODS_SELECTED) ? GetSysColor(COLOR_HIGHLIGHTTEXT) : GetSysColor(COLOR_WINDOWTEXT) ); if (g_bMESystem && (pHotKeyNode->dwHotKeyID == HOTKEY_SWITCH_LANG)) Locale_TranslateHotKey( szHotKey, ARRAYSIZE(szHotKey), 0, pHotKeyNode->uModifiers ); else Locale_TranslateHotKey( szHotKey, ARRAYSIZE(szHotKey), pHotKeyNode->uVKey, pHotKeyNode->uModifiers ); GetTextExtentExPoint( lpDis->hDC, szHotKey, lstrlen(szHotKey), 0, NULL, NULL , &Size ); iMaxWidth = lpDis->rcItem.right - lpDis->rcItem.left - Size.cx - LIST_MARGIN * 8; uStrLen = GetAtomName( pHotKeyNode->atmHotKeyName, szString, sizeof(szString) / sizeof(TCHAR) ); GetTextExtentExPoint( lpDis->hDC, szString, uStrLen, iMaxWidth, &iMaxChars, NULL , &Size ); if (uStrLen > iMaxChars) { szString[iMaxChars-3] = TEXT('.'); szString[iMaxChars-2] = TEXT('.'); szString[iMaxChars-1] = TEXT('.'); szString[iMaxChars] = 0; } ExtTextOut( lpDis->hDC, lpDis->rcItem.left + LIST_MARGIN, lpDis->rcItem.top + (g_cyListItem - g_cyText) / 2, ETO_OPAQUE, &lpDis->rcItem, szString, iMaxChars, NULL ); uAlign = GetTextAlign(lpDis->hDC); SetTextAlign(lpDis->hDC, TA_RIGHT); ExtTextOut( lpDis->hDC, lpDis->rcItem.right - LIST_MARGIN, lpDis->rcItem.top + (g_cyListItem - g_cyText) / 2, 0, NULL, szHotKey, lstrlen(szHotKey), NULL ); SetTextAlign(lpDis->hDC, uAlign); SetBkColor(lpDis->hDC, crBk); SetTextColor(lpDis->hDC, crTxt); if (lpDis->itemState & ODS_FOCUS) { DrawFocusRect(lpDis->hDC, &lpDis->rcItem); } } //////////////////////////////////////////////////////////////////////////// // // Locale_DrawItem // // Processing for a WM_DRAWITEM message. // //////////////////////////////////////////////////////////////////////////// BOOL Locale_DrawItem( HWND hwnd, LPDRAWITEMSTRUCT lpdi) { switch (lpdi->CtlID) { case ( IDC_KBDL_HOTKEY_LIST ) : { Locale_HotKeyDrawItem(hwnd, lpdi); break; } default : { return (FALSE); } } return (TRUE); } //////////////////////////////////////////////////////////////////////////// // // Locale_MeasureItem // // Processing for a WM_MEASUREITEM message. // //////////////////////////////////////////////////////////////////////////// void Locale_MeasureItem( HWND hwnd, LPMEASUREITEMSTRUCT lpmi) { HFONT hfont; HDC hdc; TEXTMETRIC tm; switch (lpmi->CtlID) { case ( IDC_KBDL_HOTKEY_LIST ) : { hfont = (HFONT) SendMessage(hwnd, WM_GETFONT, 0, 0); hdc = GetDC(NULL); hfont = SelectObject(hdc, hfont); GetTextMetrics(hdc, &tm); SelectObject(hdc, hfont); ReleaseDC(NULL, hdc); g_cyText = tm.tmHeight; lpmi->itemHeight = g_cyListItem = MAX(g_cyText, GetSystemMetrics(SM_CYSMICON)) + 2 * LIST_MARGIN; break; } } } //////////////////////////////////////////////////////////////////////////// // // Locale_CommandChangeHotKey // // Brings up change hotkey dialog box. // //////////////////////////////////////////////////////////////////////////// void Locale_CommandChangeHotKey( HWND hwnd) { HWND hwndHotkey = GetDlgItem(hwnd, IDC_KBDL_HOTKEY_LIST); LPHOTKEYINFO pHotKeyNode; int iIndex; INITINFO InitInfo; iIndex = ListBox_GetCurSel(hwndHotkey); pHotKeyNode = (LPHOTKEYINFO)ListBox_GetItemData(hwndHotkey, iIndex); InitInfo.hwndMain = hwnd; InitInfo.pHotKeyNode = pHotKeyNode; if (pHotKeyNode->dwHotKeyID == HOTKEY_SWITCH_LANG) { if (g_iThaiLayout) DialogBoxParam(GetCicResInstance(hInstance, DLG_KEYBOARD_HOTKEY_INPUT_LOCALE_THAI), MAKEINTRESOURCE(DLG_KEYBOARD_HOTKEY_INPUT_LOCALE_THAI), hwnd, KbdLocaleChangeThaiInputLocaleHotkey, (LPARAM)&InitInfo); else if (g_bMESystem) DialogBoxParam(GetCicResInstance(hInstance, DLG_KEYBOARD_HOTKEY_INPUT_LOCALE_ME), MAKEINTRESOURCE(DLG_KEYBOARD_HOTKEY_INPUT_LOCALE_ME), hwnd, KbdLocaleChangeMEInputLocaleHotkey, (LPARAM)&InitInfo); else DialogBoxParam(GetCicResInstance(hInstance, DLG_KEYBOARD_HOTKEY_INPUT_LOCALE), MAKEINTRESOURCE(DLG_KEYBOARD_HOTKEY_INPUT_LOCALE), hwnd, KbdLocaleChangeInputLocaleHotkey, (LPARAM)&InitInfo); } else DialogBoxParam(GetCicResInstance(hInstance, DLG_KEYBOARD_HOTKEY_KEYBOARD_LAYOUT), MAKEINTRESOURCE(DLG_KEYBOARD_HOTKEY_KEYBOARD_LAYOUT), hwnd, KbdLocaleChangeKeyboardLayoutHotkey, (LPARAM)&InitInfo); } //////////////////////////////////////////////////////////////////////////// // // KbdLocaleHotKeyDlg // // This is the dialog proc for the Input Locales HotKey Setting Dlg. // //////////////////////////////////////////////////////////////////////////// INT_PTR CALLBACK KbdLocaleHotKeyDlg( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static BOOL bHasIme; switch (uMsg) { case ( WM_INITDIALOG ) : { UINT ctr; TCHAR szItem[DESC_MAX]; // // Get hotkey information. // bHasIme = FALSE; Locale_GetHotkeys(hwnd, &bHasIme); if (!ListBox_GetCount(GetDlgItem(hwnd, IDC_KBDL_HOTKEY_LIST))) { EnableWindow(GetDlgItem(hwnd, IDC_KBDL_CHANGE_HOTKEY), FALSE); } // // Get Attributes information (CapsLock/ShiftLock etc.) // Locale_GetAttributes(hwnd); // // Load virtual key description. // for (ctr = 0; (ctr < sizeof(g_aVirtKeyDesc) / sizeof(VIRTKEYDESC)); ctr++) { CicLoadString(hInstance, g_aVirtKeyDesc[ctr].idVirtKeyName, szItem, sizeof(szItem) / sizeof(TCHAR) ); g_aVirtKeyDesc[ctr].atVirtKeyName = AddAtom(szItem); } break; } case ( WM_DESTROY ) : { break; } case ( WM_HELP ) : { WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, c_szHelpFile, HELP_WM_HELP, (DWORD_PTR)(LPTSTR)aLocaleKeysSettingsHelpIds ); break; } case ( WM_CONTEXTMENU ) : // right mouse click { WinHelp( (HWND)wParam, c_szHelpFile, HELP_CONTEXTMENU, (DWORD_PTR)(LPTSTR)aLocaleKeysSettingsHelpIds ); break; } case ( WM_MEASUREITEM ) : { Locale_MeasureItem(hwnd, (LPMEASUREITEMSTRUCT)lParam); break; } case ( WM_DRAWITEM ) : { return (Locale_DrawItem(hwnd, (LPDRAWITEMSTRUCT)lParam)); } case ( WM_COMMAND ) : { switch (LOWORD(wParam)) { case ( IDC_KBDL_CAPSLOCK ) : case ( IDC_KBDL_SHIFTLOCK ) : { break; } case ( IDC_KBDL_HOTKEY_LIST ): { if (HIWORD(wParam) == LBN_DBLCLK) { // // User double clicked on a hotkey. Invoke the // change hotkey dialog. // Locale_CommandChangeHotKey(hwnd); } break; } case ( IDC_KBDL_CHANGE_HOTKEY ) : { Locale_CommandChangeHotKey(hwnd); break; } case ( IDOK ) : { DWORD dwAttributes = 0; HKEY hkeyLayouts; if (IsDlgButtonChecked(hwnd, IDC_KBDL_SHIFTLOCK)) dwAttributes |= KLF_SHIFTLOCK; else dwAttributes &= ~KLF_SHIFTLOCK; if (dwAttributes != g_dwAttributes) { DWORD cb; HKEY hkey; if (RegOpenKey(HKEY_CURRENT_USER, c_szKbdLayouts, &hkey) == ERROR_SUCCESS) { cb = sizeof(DWORD); RegSetValueEx(hkey, c_szAttributes, 0, REG_DWORD, (LPBYTE)&dwAttributes, sizeof(DWORD) ); RegCloseKey(hkey); } ActivateKeyboardLayout(GetKeyboardLayout(0), KLF_RESET | dwAttributes); } if (g_dwChanges & CHANGE_SWITCH) { UINT nLangs; HKL *pLangs = NULL; BOOL bDirectSwitch = FALSE; TV_ITEM tvItem; HTREEITEM hItem; HTREEITEM hLangItem; HTREEITEM hGroupItem; LPLANGNODE pLangNode; HWND hwndTV = g_hwndTV; Locale_SetLanguageHotkey(); // // Set Imm hotkeys. // // Get the list of the currently active keyboard layouts from // the system. We will possibly need to sync up all IMEs with new // hotkeys. // nLangs = GetKeyboardLayoutList(0, NULL); if (nLangs != 0) { pLangs = (HKL *)LocalAlloc(LPTR, sizeof(DWORD_PTR) * nLangs); if (!pLangs) return (FALSE); GetKeyboardLayoutList(nLangs, (HKL *)pLangs); } tvItem.mask = TVIF_HANDLE | TVIF_PARAM; // // Try to find either a matching hkl or empty spot in the array // for each of the hkls in the locale list. // for (hLangItem = TreeView_GetChild(hwndTV, g_hTVRoot) ; hLangItem != NULL ; hLangItem = TreeView_GetNextSibling(hwndTV, hLangItem) ) { for (hGroupItem = TreeView_GetChild(hwndTV, hLangItem); hGroupItem != NULL; hGroupItem = TreeView_GetNextSibling(hwndTV, hGroupItem)) { for (hItem = TreeView_GetChild(hwndTV, hGroupItem); hItem != NULL; hItem = TreeView_GetNextSibling(hwndTV, hItem)) { LPTVITEMNODE pTVItemNode; tvItem.hItem = hItem; if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam) { pTVItemNode = (LPTVITEMNODE) tvItem.lParam; pLangNode = (LPLANGNODE)pTVItemNode->lParam; } else break; if (pLangNode == NULL && (pTVItemNode->uInputType & INPUT_TYPE_KBD) && pTVItemNode->hklSub) { if (tvItem.hItem = FindTVLangItem(pTVItemNode->dwLangID, NULL)) { if (TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam) { pTVItemNode = (LPTVITEMNODE) tvItem.lParam; pLangNode = (LPLANGNODE)pTVItemNode->lParam; } } } if (pLangNode == NULL) continue; // // Set Imm hotkeys. // Locale_SetImmHotkey(hwnd, pLangNode, nLangs, pLangs, &bDirectSwitch); } } } if (bDirectSwitch) g_dwChanges |= CHANGE_DIRECTSWITCH; if (bHasIme) { Locale_SetImmCHxHotkey(hwnd, nLangs, pLangs); } // // Free any allocated memory. // if (pLangs != NULL) { LocalFree((HANDLE)pLangs); } g_dwChanges &= ~CHANGE_SWITCH; } EndDialog(hwnd, 1); break; } case ( IDCANCEL ) : { EndDialog(hwnd, 0); break; } default : { return (FALSE); } } break; } default : { return (FALSE); } } return (TRUE); } //////////////////////////////////////////////////////////////////////////// // // Locale_VirtKeyList // // Initializes the virtual key combo box and sets the current selection. // //////////////////////////////////////////////////////////////////////////// void Locale_VirtKeyList( HWND hwnd, UINT uVKey, BOOL bDirectSwitch) { int ctr, iStart, iEnd, iIndex; UINT iSel = 0; TCHAR szString[DESC_MAX]; HWND hwndKey = GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO); // // Look for hot keys for direct switch. // for (ctr = sizeof(g_aVirtKeyDesc) / sizeof(VIRTKEYDESC) - 1; ctr >= 0; ctr--) { if (g_aVirtKeyDesc[ctr].idVirtKeyName == IDS_VK_NONE1) { // // Found it. Remove "(None)" from hwndKey list box. // ctr++; break; } } if (ctr < 0) return; iStart = bDirectSwitch ? ctr : 0; iEnd = bDirectSwitch ? sizeof(g_aVirtKeyDesc) / sizeof(VIRTKEYDESC) : ctr; ComboBox_ResetContent(hwndKey); for (ctr = iStart; ctr < iEnd; ctr++) { GetAtomName( g_aVirtKeyDesc[ctr].atVirtKeyName, szString, sizeof(szString) / sizeof(TCHAR) ); iIndex = ComboBox_InsertString(hwndKey, -1, szString); ComboBox_SetItemData(hwndKey, iIndex, g_aVirtKeyDesc[ctr].uVirtKeyValue); if (g_aVirtKeyDesc[ctr].uVirtKeyValue == uVKey) { iSel = iIndex; } } ComboBox_SetCurSel(hwndKey, iSel); } //////////////////////////////////////////////////////////////////////////// // // Locale_ChangeHotKeyDlgInit // // Initializes the change hotkey dialog box. // //////////////////////////////////////////////////////////////////////////// void Locale_ChangeHotKeyDlgInit( HWND hwnd, LPARAM lParam) { TCHAR szHotKeyName[DESC_MAX]; LPHOTKEYINFO pHotKeyNode = ((LPINITINFO)lParam)->pHotKeyNode; BOOL bCtrl = TRUE; BOOL bAlt = TRUE; BOOL bGrave = TRUE; GetAtomName(pHotKeyNode->atmHotKeyName, szHotKeyName, ARRAYSIZE(szHotKeyName)); SetDlgItemText(hwnd, IDC_KBDLH_LAYOUT_TEXT, szHotKeyName); // // Set the language switch hotkey // if (pHotKeyNode->uModifiers & MOD_CONTROL) { CheckDlgButton(hwnd, IDC_KBDLH_CTRL, TRUE); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, FALSE); bCtrl = FALSE; } if (pHotKeyNode->uModifiers & MOD_ALT) { CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, TRUE); CheckDlgButton(hwnd, IDC_KBDLH_CTRL, FALSE); bAlt = FALSE; } if (GetDlgItem(hwnd, IDC_KBDLH_GRAVE) && (pHotKeyNode->uVKey == CHAR_GRAVE)) { CheckDlgButton(hwnd, IDC_KBDLH_GRAVE, TRUE); bGrave = FALSE; } if (bCtrl && bAlt && bGrave) { CheckDlgButton(hwnd, IDC_KBDLH_LANGHOTKEY, FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_GRAVE), FALSE); ComboBox_SetCurSel(GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO), 0); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO), FALSE); } else { CheckDlgButton(hwnd, IDC_KBDLH_LANGHOTKEY, TRUE); } // // Set the layout switch hotkey // CheckDlgButton(hwnd, IDC_KBDLH_LAYOUTHOTKEY, TRUE); if (pHotKeyNode->uLayoutHotKey & MOD_CONTROL) { CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, TRUE); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, FALSE); } else if (pHotKeyNode->uLayoutHotKey & MOD_ALT) { CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, TRUE); CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, FALSE); } else if (g_bMESystem && pHotKeyNode->uVKey == CHAR_GRAVE) { CheckDlgButton(hwnd, IDC_KBDLH_GRAVE, TRUE); } else { EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), FALSE); CheckDlgButton(hwnd, IDC_KBDLH_LAYOUTHOTKEY, FALSE); if (g_bMESystem) EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_GRAVE), FALSE); } // // There is no ctfmon.exe process during the setup, so disable layout // hotkey settings. // if (g_bSetupCase) { EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_LAYOUTHOTKEY), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_SHIFT2), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_PLUS2), FALSE); if (g_bMESystem) EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_GRAVE), FALSE); #if 0 ShowWindow(GetDlgItem(hwnd, IDC_KBDLH_LAYOUTHOTKEY), SW_HIDE); ShowWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), SW_HIDE); ShowWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), SW_HIDE); ShowWindow(GetDlgItem(hwnd, IDC_KBDLH_SHIFT2), SW_HIDE); ShowWindow(GetDlgItem(hwnd, IDC_KBDLH_PLUS2), SW_HIDE); if (g_bMESystem) ShowWindow(GetDlgItem(hwnd, IDC_KBDLH_GRAVE), SW_HIDE); #endif } if (IS_DIRECT_SWITCH_HOTKEY(pHotKeyNode->dwHotKeyID)) { Locale_VirtKeyList(hwnd, pHotKeyNode->uVKey, TRUE); } else { Locale_VirtKeyList(hwnd, pHotKeyNode->uVKey, FALSE); } SetProp(hwnd, szPropHwnd, (HANDLE)((LPINITINFO)lParam)->hwndMain); SetProp(hwnd, szPropIdx, (HANDLE)pHotKeyNode); } //////////////////////////////////////////////////////////////////////////// // // Locale_ChangeHotKeyCommandOK // // Records hotkey changes made in change hotkey dialog box. // Warns if duplicate hotkeys are selected. // //////////////////////////////////////////////////////////////////////////// BOOL Locale_ChangeHotKeyCommandOK( HWND hwnd) { LPHOTKEYINFO pHotKeyNode, pHotKeyTemp; UINT iIndex; HWND hwndHotkey, hwndMain, hwndKey; UINT uOldVKey, uOldModifiers, uOldLayoutHotKey; int ctr; int iNumMods = 0; int DialogType; pHotKeyNode = GetProp(hwnd, szPropIdx); hwndMain = GetProp(hwnd, szPropHwnd); hwndHotkey = GetDlgItem(hwndMain, IDC_KBDL_HOTKEY_LIST); hwndKey = GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO); uOldVKey = pHotKeyNode->uVKey; uOldModifiers = pHotKeyNode->uModifiers; uOldLayoutHotKey = pHotKeyNode->uLayoutHotKey; if (pHotKeyNode->dwHotKeyID == HOTKEY_SWITCH_LANG) { DialogType = DIALOG_SWITCH_INPUT_LOCALES; } else if (GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO) && (GetWindowLong( GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO), GWL_STYLE) & BS_RADIOBUTTON)) { DialogType = DIALOG_SWITCH_KEYBOARD_LAYOUT; } else { DialogType = DIALOG_SWITCH_IME; } pHotKeyNode->uModifiers &= ~(MOD_CONTROL | MOD_ALT | MOD_SHIFT); pHotKeyNode->uVKey = 0; if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY)) { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_CTRL)) { pHotKeyNode->uModifiers |= MOD_CONTROL; iNumMods++; } if (IsDlgButtonChecked(hwnd, IDC_KBDLH_L_ALT)) { pHotKeyNode->uModifiers |= MOD_ALT; iNumMods++; } if (IsDlgButtonChecked(hwnd, IDC_KBDLH_GRAVE)) { // // Assign Grave key. // pHotKeyNode->uVKey = CHAR_GRAVE; } else { // // Shift key is mandatory. // pHotKeyNode->uModifiers |= MOD_SHIFT; iNumMods++; if ((iIndex = ComboBox_GetCurSel(hwndKey)) == CB_ERR) { pHotKeyNode->uVKey = 0; } else { pHotKeyNode->uVKey = (UINT)ComboBox_GetItemData(hwndKey, iIndex); } } } // // Set the layout switch hotkey // pHotKeyNode->uLayoutHotKey = 0; if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY)) { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_CTRL2)) { pHotKeyNode->uLayoutHotKey |= MOD_CONTROL; } else if (IsDlgButtonChecked(hwnd, IDC_KBDLH_L_ALT2)) { pHotKeyNode->uLayoutHotKey |= MOD_ALT; } else if (IsDlgButtonChecked(hwnd, IDC_KBDLH_GRAVE)) { pHotKeyNode->uVKey = CHAR_GRAVE; } } // // Key sequence with only one modifier and without a key, // or without any modifier is invalid. // if (((pHotKeyNode->uVKey != 0) && (iNumMods == 0) && (DialogType != DIALOG_SWITCH_INPUT_LOCALES)) || ((pHotKeyNode->uVKey == 0) && (iNumMods != 0) && (DialogType != DIALOG_SWITCH_INPUT_LOCALES))) { TCHAR szName[DESC_MAX]; Locale_TranslateHotKey( szName, ARRAYSIZE(szName), pHotKeyNode->uVKey, pHotKeyNode->uModifiers ); Locale_ErrorMsg(hwnd, IDS_KBD_INVALID_HOTKEY, szName); pHotKeyNode->uModifiers = uOldModifiers; pHotKeyNode->uVKey = uOldVKey; return (FALSE); } // // Do not allow duplicate hot keys. // for (ctr = 0; ctr < ListBox_GetCount(hwndHotkey); ctr++) { pHotKeyTemp = (LPHOTKEYINFO)ListBox_GetItemData(hwndHotkey, ctr); if ((pHotKeyTemp != pHotKeyNode) && ((pHotKeyNode->uModifiers & (MOD_CONTROL | MOD_ALT | MOD_SHIFT)) == (pHotKeyTemp->uModifiers & (MOD_CONTROL | MOD_ALT | MOD_SHIFT))) && (pHotKeyNode->uVKey == pHotKeyTemp->uVKey) && (iNumMods || pHotKeyNode->uVKey != 0)) { TCHAR szName[DESC_MAX]; Locale_TranslateHotKey( szName, ARRAYSIZE(szName), pHotKeyNode->uVKey, pHotKeyNode->uModifiers ); Locale_ErrorMsg(hwnd, IDS_KBD_CONFLICT_HOTKEY, szName); pHotKeyNode->uModifiers = uOldModifiers; pHotKeyNode->uVKey = uOldVKey; return (FALSE); } } InvalidateRect(hwndHotkey, NULL, FALSE); if ((uOldVKey != pHotKeyNode->uVKey) || (uOldModifiers != pHotKeyNode->uModifiers) || (uOldLayoutHotKey != pHotKeyNode->uLayoutHotKey)) { g_dwChanges |= CHANGE_SWITCH; } return (TRUE); } //////////////////////////////////////////////////////////////////////////// // // KbdLocaleSimpleHotkey // // Dlgproc for hotkey on NT4 and Win9x platform // //////////////////////////////////////////////////////////////////////////// INT_PTR CALLBACK KbdLocaleSimpleHotkey( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case ( WM_INITDIALOG ) : { TCHAR szHotKey[10]; TCHAR szLayoutHotKey[10]; GetLanguageHotkeyFromRegistry(szHotKey, ARRAYSIZE(szHotKey), szLayoutHotKey, ARRAYSIZE(szLayoutHotKey)); // // Set the modifiers. // if (szHotKey[1] == 0) { CheckDlgButton(hwnd, IDC_KBDLH_LANGHOTKEY, TRUE); switch (szHotKey[0]) { case ( TEXT('1') ) : { CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, TRUE); break; } case ( TEXT('2') ) : { CheckDlgButton(hwnd, IDC_KBDLH_CTRL, TRUE); break; } default: { CheckDlgButton(hwnd, IDC_KBDLH_LANGHOTKEY, FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), FALSE); } } } else { EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), FALSE); } if (szLayoutHotKey[1] == 0) { CheckDlgButton(hwnd, IDC_KBDLH_LAYOUTHOTKEY, TRUE); switch (szLayoutHotKey[0]) { case ( TEXT('1') ) : { CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, TRUE); break; } case ( TEXT('2') ) : { CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, TRUE); break; } default: { CheckDlgButton(hwnd, IDC_KBDLH_LAYOUTHOTKEY, FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), FALSE); } } } else { EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), FALSE); } } case ( WM_HELP ) : { WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, c_szHelpFile, HELP_WM_HELP, (DWORD_PTR)(LPTSTR)aLocaleHotkeyHelpIds ); break; } case ( WM_CONTEXTMENU ) : // right mouse click { WinHelp( (HWND)wParam, c_szHelpFile, HELP_CONTEXTMENU, (DWORD_PTR)(LPTSTR)aLocaleHotkeyHelpIds ); break; } case ( WM_COMMAND ) : { switch (LOWORD(wParam)) { case ( IDOK ) : { DWORD dwLangHotKey; DWORD dwLayoutHotKey; HKEY hkeyToggle; TCHAR szTemp[10]; TCHAR szTemp2[10]; // // Language switch hotkey // if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY)) { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_L_ALT)) { dwLangHotKey = 1; } else { dwLangHotKey = 2; } } else { dwLangHotKey = 3; } // // Layout swtich hotkey // if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY)) { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_L_ALT2)) { dwLayoutHotKey = 1; } else { dwLayoutHotKey = 2; } } else { dwLayoutHotKey = 3; } // // Get the toggle hotkey as a string so that it can be written // into the registry (as data). // StringCchPrintf(szTemp, ARRAYSIZE(szTemp), TEXT("%d"), dwLangHotKey); StringCchPrintf(szTemp2, ARRAYSIZE(szTemp2), TEXT("%d"), dwLayoutHotKey); // // Create the HKCU\Keyboard Layout\Toggle key. // if (RegCreateKey(HKEY_CURRENT_USER, c_szKbdToggleKey, &hkeyToggle ) == ERROR_SUCCESS) { RegSetValueEx(hkeyToggle, g_OSNT4? c_szToggleHotKey : NULL, 0, REG_SZ, (LPBYTE)szTemp, (DWORD)(lstrlen(szTemp) + 1) * sizeof(TCHAR) ); RegSetValueEx(hkeyToggle, c_szToggleLang, 0, REG_SZ, (LPBYTE)szTemp, (DWORD)(lstrlen(szTemp) + 1) * sizeof(TCHAR) ); RegSetValueEx(hkeyToggle, c_szToggleLayout, 0, REG_SZ, (LPBYTE)szTemp2, (DWORD)(lstrlen(szTemp2) + 1) * sizeof(TCHAR) ); RegCloseKey(hkeyToggle); } EndDialog(hwnd, 1); break; } case ( IDCANCEL ) : { EndDialog(hwnd, 0); break; } case ( IDC_KBDLH_LANGHOTKEY ) : { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY)) { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY)) { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_L_ALT2)) { CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_CHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED); } else { CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED); } } else { CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED); CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED); } EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), TRUE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), TRUE); } else { CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), FALSE); } break; } case ( IDC_KBDLH_LAYOUTHOTKEY ) : { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY)) { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY)) { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_L_ALT)) { CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED); } else { CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_CHECKED); } } else { CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED); } EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), TRUE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), TRUE); } else { CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), FALSE); } break; } case ( IDC_KBDLH_CTRL ) : { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY)) { CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_CHECKED); } break; } case ( IDC_KBDLH_L_ALT ) : { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY)) { CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED); } break; } case ( IDC_KBDLH_CTRL2 ) : { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY)) { CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED); } break; } case ( IDC_KBDLH_L_ALT2 ) : { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY)) { CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_CHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED); } break; } default : { return (FALSE); } } break; } default : { return (FALSE); } } return (TRUE); } //////////////////////////////////////////////////////////////////////////// // // KbdLocaleChangeInputLocaleHotkey // // Dlgproc for changing input locale hotkey dialog box. // //////////////////////////////////////////////////////////////////////////// INT_PTR CALLBACK KbdLocaleChangeInputLocaleHotkey( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case ( WM_INITDIALOG ) : { Locale_ChangeHotKeyDlgInit(hwnd, lParam); break; } case ( WM_HELP ) : { WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, c_szHelpFile, HELP_WM_HELP, (DWORD_PTR)(LPTSTR)aLocaleHotkeyHelpIds ); break; } case ( WM_CONTEXTMENU ) : // right mouse click { WinHelp( (HWND)wParam, c_szHelpFile, HELP_CONTEXTMENU, (DWORD_PTR)(LPTSTR)aLocaleHotkeyHelpIds ); break; } case ( WM_DESTROY ) : { RemoveProp(hwnd, szPropHwnd); RemoveProp(hwnd, szPropIdx); break; } case ( WM_COMMAND ) : { LPHOTKEYINFO pHotKeyNode = GetProp(hwnd, szPropIdx); switch (LOWORD(wParam)) { case ( IDOK ) : { if (Locale_ChangeHotKeyCommandOK(hwnd)) { EndDialog(hwnd, 1); } break; } case ( IDCANCEL ) : { EndDialog(hwnd, 0); break; } case ( IDC_KBDLH_LANGHOTKEY ) : { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY)) { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY)) { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_L_ALT2)) { CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_CHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED); } else { CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED); } } else { CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED); CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED); } EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), TRUE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), TRUE); } else { CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), FALSE); } break; } case ( IDC_KBDLH_LAYOUTHOTKEY ) : { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY)) { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY)) { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_CTRL)) { CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_CHECKED); } else { CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED); } } else { CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED); } EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), TRUE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), TRUE); } else { CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), FALSE); } break; } case ( IDC_KBDLH_CTRL ) : { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY)) { CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_CHECKED); } break; } case ( IDC_KBDLH_L_ALT ) : { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY)) { CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED); } break; } case ( IDC_KBDLH_CTRL2 ) : { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY)) { CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED); } break; } case ( IDC_KBDLH_L_ALT2 ) : { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY)) { CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_CHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED); } break; } default : { return (FALSE); } } break; } default : { return (FALSE); } } return (TRUE); } //////////////////////////////////////////////////////////////////////////// // // KbdLocaleChangeThaiInputLocaleHotkey // // Dlgproc for changing Thai input locale hotkey dialog box. // //////////////////////////////////////////////////////////////////////////// INT_PTR CALLBACK KbdLocaleChangeThaiInputLocaleHotkey( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case ( WM_INITDIALOG ) : { Locale_ChangeHotKeyDlgInit(hwnd, lParam); break; } case ( WM_DESTROY ) : { RemoveProp(hwnd, szPropHwnd); RemoveProp(hwnd, szPropIdx); break; } case ( WM_HELP ) : { WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, c_szHelpFile, HELP_WM_HELP, (DWORD_PTR)(LPTSTR)aLocaleHotkeyHelpIds ); break; } case ( WM_CONTEXTMENU ) : { WinHelp( (HWND)wParam, c_szHelpFile, HELP_CONTEXTMENU, (DWORD_PTR)(LPTSTR)aLocaleHotkeyHelpIds ); break; } case ( WM_DRAWITEM ) : { if (wParam == IDC_KBDLH_VLINE) { LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam; RECT rect; HPEN hPenHilite, hPenShadow, hPenOriginal; GetClientRect(lpdis->hwndItem, &rect); hPenHilite = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNHIGHLIGHT)); hPenShadow = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW)); hPenOriginal = SelectObject(lpdis->hDC, hPenShadow); MoveToEx(lpdis->hDC, rect.right / 2, 0, NULL); LineTo(lpdis->hDC, rect.right / 2, rect.bottom); SelectObject(lpdis->hDC, hPenHilite); MoveToEx(lpdis->hDC, rect.right / 2 + 1, 0, NULL); LineTo(lpdis->hDC, rect.right / 2 + 1, rect.bottom); SelectObject(lpdis->hDC, hPenOriginal); if (hPenShadow) { DeleteObject(hPenShadow); } if (hPenHilite) { DeleteObject(hPenHilite); } return (TRUE); } return (FALSE); break; } case ( WM_COMMAND ) : { LPHOTKEYINFO pHotKeyNode = GetProp(hwnd, szPropIdx); switch (LOWORD(wParam)) { case ( IDOK ) : { if (Locale_ChangeHotKeyCommandOK(hwnd)) { EndDialog(hwnd, 1); } break; } case ( IDCANCEL ) : { EndDialog(hwnd, 0); break; } case ( IDC_KBDLH_LANGHOTKEY ) : { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY)) { CheckDlgButton(hwnd, IDC_KBDLH_GRAVE, BST_CHECKED); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), TRUE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), TRUE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_GRAVE), TRUE); } else { CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_GRAVE, BST_UNCHECKED); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_GRAVE), FALSE); } break; } case ( IDC_KBDLH_LAYOUTHOTKEY ) : { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY)) { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY)) { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_CTRL)) { CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_CHECKED); } else { CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED); } } else { CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED); } EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), TRUE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), TRUE); } else { CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), FALSE); } break; } case ( IDC_KBDLH_CTRL ) : { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY)) { CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_CHECKED); } break; } case ( IDC_KBDLH_L_ALT ) : { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY)) { CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED); } break; } case ( IDC_KBDLH_CTRL2 ) : { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY) && !IsDlgButtonChecked(hwnd, IDC_KBDLH_GRAVE)) { CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED); } break; } case ( IDC_KBDLH_L_ALT2 ) : { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY) && !IsDlgButtonChecked(hwnd, IDC_KBDLH_GRAVE)) { CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_CHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED); } break; } default : { return (FALSE); } } break; } default : { return (FALSE); } } return (TRUE); } //////////////////////////////////////////////////////////////////////////// // // KbdLocaleChangeMEInputLocaleHotkey // // Dlgproc for changing Thai input locale hotkey dialog box. // //////////////////////////////////////////////////////////////////////////// INT_PTR CALLBACK KbdLocaleChangeMEInputLocaleHotkey( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case ( WM_INITDIALOG ) : { Locale_ChangeHotKeyDlgInit(hwnd, lParam); break; } case ( WM_DESTROY ) : { RemoveProp(hwnd, szPropHwnd); RemoveProp(hwnd, szPropIdx); break; } case ( WM_HELP ) : { WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, c_szHelpFile, HELP_WM_HELP, (DWORD_PTR)(LPTSTR)aLocaleHotkeyHelpIds ); break; } case ( WM_CONTEXTMENU ) : { WinHelp( (HWND)wParam, c_szHelpFile, HELP_CONTEXTMENU, (DWORD_PTR)(LPTSTR)aLocaleHotkeyHelpIds ); break; } case ( WM_DRAWITEM ) : { if (wParam == IDC_KBDLH_VLINE) { LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam; RECT rect; HPEN hPenHilite, hPenShadow, hPenOriginal; GetClientRect(lpdis->hwndItem, &rect); hPenHilite = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNHIGHLIGHT)); hPenShadow = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW)); hPenOriginal = SelectObject(lpdis->hDC, hPenShadow); MoveToEx(lpdis->hDC, rect.right / 2, 0, NULL); LineTo(lpdis->hDC, rect.right / 2, rect.bottom); SelectObject(lpdis->hDC, hPenHilite); MoveToEx(lpdis->hDC, rect.right / 2 + 1, 0, NULL); LineTo(lpdis->hDC, rect.right / 2 + 1, rect.bottom); SelectObject(lpdis->hDC, hPenOriginal); if (hPenShadow) { DeleteObject(hPenShadow); } if (hPenHilite) { DeleteObject(hPenHilite); } return (TRUE); } return (FALSE); break; } case ( WM_COMMAND ) : { LPHOTKEYINFO pHotKeyNode = GetProp(hwnd, szPropIdx); switch (LOWORD(wParam)) { case ( IDOK ) : { if (Locale_ChangeHotKeyCommandOK(hwnd)) { EndDialog(hwnd, 1); } break; } case ( IDCANCEL ) : { EndDialog(hwnd, 0); break; } case ( IDC_KBDLH_LANGHOTKEY ) : { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY)) { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY)) { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_L_ALT2)) { CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_CHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED); } else { CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED); } } else { CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED); CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED); } EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), TRUE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), TRUE); } else { CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), FALSE); } break; } case ( IDC_KBDLH_LAYOUTHOTKEY ) : { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY)) { CheckDlgButton(hwnd, IDC_KBDLH_GRAVE, BST_CHECKED); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), TRUE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), TRUE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_GRAVE), TRUE); } else { CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_GRAVE, BST_UNCHECKED); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL2), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT2), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_GRAVE), FALSE); } break; } case ( IDC_KBDLH_CTRL ) : { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY) && !IsDlgButtonChecked(hwnd, IDC_KBDLH_GRAVE)) { CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_CHECKED); } break; } case ( IDC_KBDLH_L_ALT ) : { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LAYOUTHOTKEY) && !IsDlgButtonChecked(hwnd, IDC_KBDLH_GRAVE)) { CheckDlgButton(hwnd, IDC_KBDLH_CTRL2, BST_CHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT2, BST_UNCHECKED); } break; } case ( IDC_KBDLH_CTRL2 ) : { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY)) { CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED); } break; } case ( IDC_KBDLH_L_ALT2 ) : { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY)) { CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_CHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED); } break; } default : { return (FALSE); } } break; } default : { return (FALSE); } } return (TRUE); } //////////////////////////////////////////////////////////////////////////// // // KbdLocaleChangeKeyboardLayoutHotkey // // Dlgproc for changing direct switch keyboard layout hotkey dialog box. // //////////////////////////////////////////////////////////////////////////// INT_PTR CALLBACK KbdLocaleChangeKeyboardLayoutHotkey( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case ( WM_INITDIALOG ) : { Locale_ChangeHotKeyDlgInit(hwnd, lParam); break; } case ( WM_HELP ) : { WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, c_szHelpFile, HELP_WM_HELP, (DWORD_PTR)(LPTSTR)aLayoutHotkeyHelpIds ); break; } case ( WM_CONTEXTMENU ) : // right mouse click { WinHelp( (HWND)wParam, c_szHelpFile, HELP_CONTEXTMENU, (DWORD_PTR)(LPTSTR)aLayoutHotkeyHelpIds ); break; } case ( WM_DESTROY ) : { RemoveProp(hwnd, szPropHwnd); RemoveProp(hwnd, szPropIdx); break; } case ( WM_COMMAND ) : { HWND hwndKey = GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO); LPHOTKEYINFO pHotKeyNode = GetProp(hwnd, szPropIdx); switch (LOWORD(wParam)) { case ( IDOK ) : { if (Locale_ChangeHotKeyCommandOK(hwnd)) { EndDialog(hwnd, 1); } break; } case ( IDCANCEL ) : { EndDialog(hwnd, 0); break; } case ( IDC_KBDLH_LANGHOTKEY ) : { if (IsDlgButtonChecked(hwnd, IDC_KBDLH_LANGHOTKEY)) { CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_CHECKED); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), TRUE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), TRUE); ComboBox_SetCurSel(hwndKey, 0); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO), TRUE); } else { CheckDlgButton(hwnd, IDC_KBDLH_CTRL, BST_UNCHECKED); CheckDlgButton(hwnd, IDC_KBDLH_L_ALT, BST_UNCHECKED); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_CTRL), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_L_ALT), FALSE); ComboBox_SetCurSel(hwndKey, 0); EnableWindow(GetDlgItem(hwnd, IDC_KBDLH_KEY_COMBO), FALSE); } break; } case ( IDC_KBDLH_CTRL ) : { break; } case ( IDC_KBDLH_L_ALT ) : { break; } default : { return (FALSE); } } break; } default : { return (FALSE); } } return (TRUE); } //////////////////////////////////////////////////////////////////////////// ///////////////////////////////// END //////////////////////////////////// ////////////////////////////////////////////////////////////////////////////