|
|
/*
* spell.c * * Implementation of spelling * * Owner: v-brakol * bradk@directeq.com */ #include "pch.hxx"
#define SPID
#include "richedit.h"
#include "resource.h"
#include <mshtml.h>
#include <mshtmcid.h>
#include "mshtmhst.h"
#include <docobj.h>
#include "spell.h"
#include "strconst.h"
#include <options.h>
#include <goptions.h>
#include "mailnews.h"
#include "hotlinks.h"
#include "bodyutil.h"
#include <shlwapi.h>
#include <error.h>
#include "htmlstr.h"
#include "optres.h"
#include "mlang.h"
#include "lid.h"
#include "shlwapip.h"
#include "msi.h"
#include "demand.h"
#ifdef ImageList_GetIcon
#undef ImageList_GetIcon
#endif
#include <shfusion.h>
#define cchMaxPathName (256)
#define TESTHR(hr) (FAILED(hr) || hr == HR_S_ABORT || hr == HR_S_SPELLCANCEL)
#define SPELLER_GUID "{CC29EB3F-7BC2-11D1-A921-00A0C91E2AA2}"
#define DICTIONARY_GUID "{CC29EB3D-7BC2-11D1-A921-00A0C91E2AA2}"
#ifdef DEBUG
#define SPELLER_DEBUG_GUID "{CC29EB3F-7BC2-11D1-A921-10A0C91E2AA2}"
#define DICTIONARY_DEBUG_GUID "{CC29EB3D-7BC2-11D1-A921-10A0C91E2AA2}"
#endif // DEBUG
typedef BOOL (LPFNENUMLANG)(DWORD_PTR, LPTSTR); typedef BOOL (LPFNENUMUSERDICT)(DWORD_PTR, LPTSTR);
typedef struct _FILLLANG { HWND hwndCombo; BOOL fUnknownFound; BOOL fDefaultFound; BOOL fCurrentFound; UINT lidDefault; UINT lidCurrent; } FILLLANG, * LPFILLLANG;
BOOL FDBCSEnabled(void); BOOL TestLangID(LPCTSTR szLangId); BOOL GetLangID(LPTSTR szLangID, DWORD cchLangId); WORD WGetLangID(void); BOOL SetLangID(LPTSTR szLandID); DWORD GetSpellingPaths(LPCTSTR szKey, LPTSTR szReturnBuffer, LPTSTR szMdr, UINT cchReturnBufer); VOID OpenCustomDictionary(VOID); VOID FillLanguageDropDown(HWND hwndLang); VOID EnumLanguages(DWORD_PTR, LPFNENUMLANG); BOOL FindLangCallback(DWORD_PTR dwLangId, LPTSTR lpszLang); BOOL EnumLangCallback(DWORD_PTR dwLangId, LPTSTR lpszLang); BOOL FBadSpellChecker(LPSTR rgchBufDigit); BOOL GetNewSpellerEngine(LANGID lgid, TCHAR *rgchEngine, DWORD cchEngine, TCHAR *rgchLex, DWORD cchLex, BOOL bTestAvail); HRESULT OpenDirectory(TCHAR *szDir);
////Spelling tab CS-help
const static HELPMAP g_rgCtxMapSpell[] = { {CHK_AlwaysSuggest, IDH_NEWS_SPELL_SUGGEST_REPL}, {CHK_CheckSpellingOnSend, IDH_NEWS_SPELL_CHECK_BEFORE_SEND}, {CHK_IgnoreUppercase, IDH_NEWS_SPELL_IGNORE_UPPERCASE}, {CHK_IgnoreNumbers, IDH_NEWS_SPELL_IGNORE_WITH_NUMBERS}, {CHK_IgnoreOriginalMessage, IDH_NEWS_SPELL_ORIGINAL_TEXT}, {CHK_IgnoreURL, IDH_OPTIONS_SPELLING_INTERNET_ADDRESSES}, {idcSpellLanguages, IDH_OPTIONS_SPELLING_LANGUAGE}, {idcViewDictionary, IDH_OPTIONS_SPELLING_DICTIONARY}, {CHK_CheckSpellingOnType, 0}, {idcStatic1, IDH_NEWS_COMM_GROUPBOX}, {idcStatic2, IDH_NEWS_COMM_GROUPBOX}, {idcStatic3, IDH_NEWS_COMM_GROUPBOX}, {idcStatic4, IDH_NEWS_COMM_GROUPBOX}, {idcStatic5, IDH_NEWS_COMM_GROUPBOX}, {idcStatic6, IDH_NEWS_COMM_GROUPBOX}, {IDC_SPELL_SETTINGS_ICON, IDH_NEWS_COMM_GROUPBOX}, {IDC_SPELL_IGNORE_ICON, IDH_NEWS_COMM_GROUPBOX}, {IDC_SPELL_LANGUAGE_ICON, IDH_NEWS_COMM_GROUPBOX}, {0, 0}};
ASSERTDATA
BOOL FIgnoreNumber(void) { return(DwGetOption(OPT_SPELLIGNORENUMBER)); } BOOL FIgnoreUpper(void) { return(DwGetOption(OPT_SPELLIGNOREUPPER)); } BOOL FIgnoreDBCS(void) { return(DwGetOption(OPT_SPELLIGNOREDBCS)); } BOOL FIgnoreProtect(void) { return(DwGetOption(OPT_SPELLIGNOREPROTECT)); } BOOL FAlwaysSuggest(void) { return(DwGetOption(OPT_SPELLALWAYSSUGGEST)); } BOOL FCheckOnSend(void) { return(DwGetOption(OPT_SPELLCHECKONSEND)); } BOOL FIgnoreURL(void) { return(DwGetOption(OPT_SPELLIGNOREURL)); }
typedef struct { LPTSTR pszString; DWORD cchSize; } STRING_AND_SIZE;
BOOL TestLangID(LPCTSTR szLangId) { // check for new speller
{ TCHAR rgchEngine[MAX_PATH]; int cchEngine = sizeof(rgchEngine) / sizeof(rgchEngine[0]); TCHAR rgchLex[MAX_PATH]; int cchLex = sizeof(rgchLex) / sizeof(rgchLex[0]);
if (GetNewSpellerEngine((LANGID) StrToInt(szLangId), rgchEngine, cchEngine, rgchLex, cchLex, TRUE)) return TRUE; }
// use the old code to check for an old speller
{ TCHAR rgchBufKeyTest[cchMaxPathName]; TCHAR rgchBufTest[cchMaxPathName]; TCHAR szMdr[cchMaxPathName];
wnsprintf(rgchBufKeyTest, ARRAYSIZE(rgchBufKeyTest), c_szRegSpellKeyDef, szLangId); if (GetSpellingPaths(rgchBufKeyTest, rgchBufTest, szMdr, sizeof(rgchBufTest)/sizeof(TCHAR))) return TRUE; }
return FALSE; }
BOOL SetLangID(LPTSTR szLangId) { return SetOption(OPT_SPELL_LANGID, szLangId, lstrlen(szLangId) + 1, NULL, 0); }
/*
* GetSpellLangID * * Returns the LangID that should be used as the base for all registry * operations * */ BOOL GetLangID(LPTSTR szLangId, DWORD cchLangId) { TCHAR rgchBuf[cchMaxPathName]; TCHAR rgchBufKey[cchMaxPathName]; BOOL fRet;
if (GetOption(OPT_SPELL_LANGID, szLangId, cchLangId) != 5) { // For Arabic, we should consider all sub-langs also
// since spelling checker for Aarbic uses Saudi Aarbia sub lang
LANGID langid = GetUserDefaultLangID(); if (PRIMARYLANGID(langid) == LANG_ARABIC) { langid = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA); } wnsprintf(szLangId, cchLangId, "%d", langid); Assert(lstrlen(szLangId) == 4); }
wnsprintf(rgchBufKey, ARRAYSIZE(rgchBufKey), c_szRegSpellKeyDef, szLangId); // copy c_szRegSpellProfile to buffer
StrCpyN(rgchBuf, c_szRegSpellProfile, ARRAYSIZE(rgchBuf)); // add key to buffer
StrCatBuff(rgchBuf, rgchBufKey, ARRAYSIZE(rgchBuf));
// and see if it's legit:
if(!(fRet = TestLangID(szLangId))) { STRING_AND_SIZE stringAndSize;
stringAndSize.pszString = szLangId; stringAndSize.cchSize = cchLangId;
// couldn't open it!
// check for other languages that might be installed...
szLangId[0] = 0; EnumLanguages((DWORD_PTR) &stringAndSize, FindLangCallback); if(*szLangId == 0) wnsprintf(szLangId, cchLangId, "%d", GetUserDefaultLangID()); }
fRet = (szLangId[0] != 0) && TestLangID(szLangId);
return fRet; }
WORD WGetLangID() { TCHAR rgchBufDigit[10]; GetLangID(rgchBufDigit, ARRAYSIZE(rgchBufDigit));
return (WORD) StrToInt(rgchBufDigit); }
BOOL FindLangCallback(DWORD_PTR dwLangId, LPTSTR lpszLang) { // dwLangID is long pointer to szLang ID. Copy it and return FALSE
STRING_AND_SIZE * pStringAndSize = (STRING_AND_SIZE *) dwLangId;
if (pStringAndSize && pStringAndSize->pszString) { StrCpyN(pStringAndSize->pszString, lpszLang, pStringAndSize->cchSize); } return FALSE; }
BOOL EnumOldSpellerLanguages(DWORD_PTR dwCookie, LPFNENUMLANG pfn) { DWORD iKey = 0; FILETIME ft; HKEY hkey = NULL; LONG lRet; TCHAR szLangId[cchMaxPathName]; DWORD cchLangId; BOOL fContinue = TRUE;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegSpellKeyDefRoot, 0, KEY_ENUMERATE_SUB_KEYS, &hkey) == ERROR_SUCCESS) { do { cchLangId = (cchMaxPathName - 1) * sizeof(TCHAR);
lRet = RegEnumKeyEx(hkey, iKey++, szLangId, &cchLangId, NULL, NULL, NULL, &ft);
if (lRet != ERROR_SUCCESS || lRet == ERROR_NO_MORE_ITEMS) break;
// do some quick sanity checking
if (cchLangId != 4 || !IsCharAlphaNumeric(szLangId[0]) || IsCharAlpha(szLangId[0])) { fContinue = TRUE; } else fContinue = (!TestLangID(szLangId) || (*pfn)(dwCookie, szLangId));
} while (fContinue); }
if (hkey) RegCloseKey(hkey);
return fContinue; }
BOOL EnumNewSpellerLanguages(DWORD_PTR dwCookie, LPFNENUMLANG pfn) { BOOL fContinue = TRUE; DWORD i; UINT installState; UINT componentState; TCHAR rgchQualifier[MAX_PATH]; DWORD cchQualifier;
#ifdef DEBUG
for(i=0; fContinue; i++) { cchQualifier = sizeof(rgchQualifier) / sizeof(rgchQualifier[0]); componentState = MsiEnumComponentQualifiers(DICTIONARY_DEBUG_GUID, i, rgchQualifier, &cchQualifier, NULL, NULL);
if (componentState != ERROR_SUCCESS) break;
// find the language ID
// the string is formatted as 1033\xxxxxx
// or 1042
{ TCHAR szLangId[cchMaxPathName]; TCHAR *pSlash;
StrCpyN(szLangId, rgchQualifier, ARRAYSIZE(szLangId)); pSlash = StrChr(szLangId, '\\'); if (pSlash) *pSlash = 0;
fContinue = (*pfn)(dwCookie, szLangId); } } #endif // DEBUG
for(i=0; fContinue; i++) { cchQualifier = sizeof(rgchQualifier) / sizeof(rgchQualifier[0]); componentState = MsiEnumComponentQualifiers(DICTIONARY_GUID, i, rgchQualifier, &cchQualifier, NULL, NULL);
if (componentState != ERROR_SUCCESS) break;
// find the language ID
// the string is formatted as 1033\xxxxxx
// or 1042
{ TCHAR szLangId[cchMaxPathName]; TCHAR *pSlash;
StrCpyN(szLangId, rgchQualifier, ARRAYSIZE(szLangId)); pSlash = StrChr(szLangId, '\\'); if (pSlash) *pSlash = 0;
fContinue = (*pfn)(dwCookie, szLangId); } } return fContinue; }
VOID EnumLanguages(DWORD_PTR dwCookie, LPFNENUMLANG pfn) { // enum all languages
EnumNewSpellerLanguages(dwCookie, pfn); EnumOldSpellerLanguages(dwCookie, pfn); }
/*
* GetSpellingPaths * * Purpose: * Function to get Spelling DLL names. * * Arguments: * szKey c_szRegSpellKeyDef (with correct language) * szDefault c_szRegSpellEmpty * szReturnBuffer dll filename * szMdr dictionary filename * cchReturnBufer * * Returns: * DWORD */ DWORD GetSpellingPaths(LPCTSTR szKey, LPTSTR szReturnBuffer, LPTSTR szMdr, UINT cchReturnBufer) { DWORD dwRet = 0; TCHAR rgchBuf[cchMaxPathName]; DWORD dwType, cbData; HKEY hkey = NULL; LPTSTR szValue;
szReturnBuffer[0] = 0; wnsprintf(rgchBuf, ARRAYSIZE(rgchBuf), TEXT("%s%s"), c_szRegSpellProfile, szKey);
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, rgchBuf, 0, KEY_QUERY_VALUE, &hkey)) goto err;
cbData = cchReturnBufer * sizeof(TCHAR); szValue = (LPTSTR) (szMdr ? c_szRegSpellPath : c_szRegSpellPathDict); if (ERROR_SUCCESS != SHQueryValueEx(hkey, szValue, 0L, &dwType, (BYTE *) szReturnBuffer, &cbData)) goto err;
// Parse off the main dictionary filename
if(szMdr) { szMdr[0] = 0; cbData = cchReturnBufer * sizeof(TCHAR); if (ERROR_SUCCESS != SHQueryValueEx(hkey, c_szRegSpellPathLex, 0L, &dwType, (BYTE *) szMdr, &cbData)) goto err; }
dwRet = cbData;
err: if(hkey) RegCloseKey(hkey); return dwRet; }
BOOL GetNewSpellerEngine(LANGID lgid, TCHAR *rgchEngine, DWORD cchEngine, TCHAR *rgchLex, DWORD cchLex, BOOL bTestAvail) { DWORD er; LPCSTR rgpszDictionaryTypes[] = {"Normal", "Consise", "Complete"}; int cDictTypes = sizeof(rgpszDictionaryTypes) / sizeof(LPCSTR); int i; TCHAR rgchQual[MAX_PATH]; bool fFound = FALSE; DWORD cch; INSTALLUILEVEL iuilOriginal; if (rgchEngine == NULL || rgchLex == NULL) return FALSE;
*rgchEngine = 0; *rgchLex = 0;
wnsprintf(rgchQual, ARRAYSIZE(rgchQual), "%d\\Normal", lgid); cch = cchEngine;
if (bTestAvail) { // Explicitly Turn off internal installer UI
// Eg: A feature is set to "run from CD," and CD is not present - fail silently
// OE Bug 74697
iuilOriginal = MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL); }
#ifdef DEBUG
er = MsiProvideQualifiedComponent(SPELLER_DEBUG_GUID, rgchQual, (bTestAvail ? INSTALLMODE_EXISTING : INSTALLMODE_DEFAULT), rgchEngine, &cch); if ((er != ERROR_SUCCESS) && (er != ERROR_FILE_NOT_FOUND)) { cch = cchEngine; er = MsiProvideQualifiedComponent(SPELLER_GUID, rgchQual, (bTestAvail ? INSTALLMODE_EXISTING : INSTALLMODE_DEFAULT), rgchEngine, &cch); } #else
er = MsiProvideQualifiedComponent(SPELLER_GUID, rgchQual, (bTestAvail ? INSTALLMODE_EXISTING : INSTALLMODE_DEFAULT), rgchEngine, &cch); #endif
if ((er != ERROR_SUCCESS) && (er != ERROR_FILE_NOT_FOUND)) { fFound = FALSE; goto errorExit; }
// Hebrew does not have a main lex
#ifdef OLDHEB
if (lgid != lidHebrew) { #endif // OLDHEB
for (i = 0; i < cDictTypes; i++) { wnsprintf(rgchQual, ARRAYSIZE(rgchQual), "%d\\%s", lgid, rgpszDictionaryTypes[i]); cch = cchLex; #ifdef DEBUG
er = MsiProvideQualifiedComponent(DICTIONARY_DEBUG_GUID, rgchQual, (bTestAvail ? INSTALLMODE_EXISTING : INSTALLMODE_DEFAULT), rgchLex, &cch); if ((er != ERROR_SUCCESS) && (er != ERROR_FILE_NOT_FOUND)) { cch = cchLex; er = MsiProvideQualifiedComponent(DICTIONARY_GUID, rgchQual, (bTestAvail ? INSTALLMODE_EXISTING : INSTALLMODE_DEFAULT), rgchLex, &cch); } #else // DEBUG
er = MsiProvideQualifiedComponent(DICTIONARY_GUID, rgchQual, (bTestAvail ? INSTALLMODE_EXISTING : INSTALLMODE_DEFAULT), rgchLex, &cch); #endif // DEBUG
if ((er == ERROR_SUCCESS) || (er == ERROR_FILE_NOT_FOUND)) { fFound = TRUE; break; } } #ifdef OLDHEB
} #endif //OLDDHEB
errorExit: if (bTestAvail) { // Restore original UI Level
MsiSetInternalUI(iuilOriginal, NULL); } return fFound; }
BOOL FIsNewSpellerInstaller() { LANGID langid; TCHAR rgchEngine[MAX_PATH]; int cchEngine = sizeof(rgchEngine) / sizeof(rgchEngine[0]); TCHAR rgchLex[MAX_PATH]; int cchLex = sizeof(rgchLex) / sizeof(rgchLex[0]);
// first try to load dictionaries for various languages
langid = WGetLangID(); if (!GetNewSpellerEngine(langid, rgchEngine, cchEngine, rgchLex, cchLex, TRUE)) { langid = GetSystemDefaultLangID(); if (!GetNewSpellerEngine(langid, rgchEngine, cchEngine, rgchLex, cchLex, TRUE)) { langid = 1033; // bloody cultural imperialists.
if (!GetNewSpellerEngine(langid, rgchEngine, cchEngine, rgchLex, cchLex, TRUE)) return FALSE; } }
return TRUE; }
/*
* FIsSpellingInstalled * * Purpose: * Is the spelling stuff installed * * Arguments: * none * * Returns: * BOOL Returns TRUE if spelling is installed, else FALSE. */ BOOL FIsSpellingInstalled() { TCHAR rgchBufDigit[10];
if (GetLangID(rgchBufDigit, sizeof(rgchBufDigit)/sizeof(TCHAR)) && !FBadSpellChecker(rgchBufDigit)) return true;
if (FIsNewSpellerInstaller()) return true;
return false; }
// Does a quick check to see if spelling is available; caches result.
BOOL FCheckSpellAvail(void) { static int fSpellAvailable = -1;
if (fSpellAvailable < 0) fSpellAvailable = (FIsSpellingInstalled() ? 1 : 0);
return (fSpellAvailable > 0); }
BOOL FDBCSEnabled(void) { static int fDBCS = -1;
if (fDBCS < 0) fDBCS = GetSystemMetrics(SM_DBCSENABLED);
return (fDBCS > 0); }
// Fill the options list with the available spelling languages
VOID FillLanguageDropDown(HWND hwndLang) { TCHAR rgchBuf[cchMaxPathName]; FILLLANG fl; int i;
// get the current language
GetLangID(rgchBuf, cchMaxPathName);
fl.hwndCombo = hwndLang; fl.fUnknownFound = FALSE; fl.fDefaultFound = FALSE; fl.fCurrentFound = FALSE; fl.lidDefault = WGetLangID(); fl.lidCurrent = StrToInt(rgchBuf);
EnumLanguages((DWORD_PTR) &fl, EnumLangCallback);
// this should never happen, but just in case
if (!fl.fDefaultFound) { LoadString(g_hLocRes, idsDefaultLang, rgchBuf, cchMaxPathName - 1); i = ComboBox_AddString(hwndLang, rgchBuf); ComboBox_SetItemData(hwndLang, i, fl.lidDefault); }
// select the current one, if found, else the default one.
for (i = ComboBox_GetCount(hwndLang) - 1; i >= 0; i--) { UINT lid = (UINT) ComboBox_GetItemData(hwndLang, i);
if ((fl.fCurrentFound && lid == fl.lidCurrent) || (!fl.fCurrentFound && fl.fDefaultFound && lid == fl.lidDefault)) { ComboBox_SetCurSel(hwndLang, i); break; } } }
BOOL EnumLangCallback(DWORD_PTR dw, LPTSTR lpszLang) { LPFILLLANG lpfl = (LPFILLLANG) dw; TCHAR szLang[cchMaxPathName]; LID lidLang = (LID) StrToInt(lpszLang); int i; HRESULT hr=S_OK; IMultiLanguage2 *pMLang2 = NULL; RFC1766INFO info;
// check to see if we already have the LID in the ComboBox
{ for (i = ComboBox_GetCount(lpfl->hwndCombo) - 1; i >= 0; i--) { LID lid = (UINT) ComboBox_GetItemData(lpfl->hwndCombo, i);
if (lid == lidLang) return TRUE; } } // Try to create an IMultiLanguage2 interface
hr = CoCreateInstance(CLSID_CMultiLanguage, NULL,CLSCTX_INPROC, IID_IMultiLanguage2, (LPVOID *) &pMLang2); if (SUCCEEDED(hr)) hr = pMLang2->GetRfc1766Info(MAKELCID(lidLang, SORT_DEFAULT), MLGetUILanguage(), &info);
SafeRelease(pMLang2);
if (SUCCEEDED(hr)) { if (WideCharToMultiByte (CP_ACP, 0, info.wszLocaleName, -1, szLang, sizeof(szLang), NULL, NULL)) { szLang[ARRAYSIZE(szLang) - 1] = '\0'; //better safe than not null terminated
i = ComboBox_AddString(lpfl->hwndCombo, szLang); ComboBox_SetItemData(lpfl->hwndCombo, i, lidLang);
if (lidLang == lpfl->lidDefault) lpfl->fDefaultFound = TRUE;
if (lidLang == lpfl->lidCurrent) lpfl->fCurrentFound = TRUE;
return TRUE; } }
return TRUE; // keep enumerating
}
INT_PTR CALLBACK SpellingPageProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { BOOL f; OPTINFO *pmoi;
pmoi = (OPTINFO *)GetWindowLongPtr(hwnd, DWLP_USER);
switch (message) { case WM_INITDIALOG: { UINT uCP;
Assert(pmoi == NULL); pmoi = (OPTINFO *)(((PROPSHEETPAGE *)lParam)->lParam); Assert(pmoi != NULL); SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM)pmoi);
ButtonChkFromOptInfo(hwnd, CHK_AlwaysSuggest, pmoi, OPT_SPELLALWAYSSUGGEST); ButtonChkFromOptInfo(hwnd, CHK_CheckSpellingOnSend, pmoi, OPT_SPELLCHECKONSEND); ButtonChkFromOptInfo(hwnd, CHK_CheckSpellingOnType, pmoi, OPT_SPELLCHECKONTYPE); ButtonChkFromOptInfo(hwnd, CHK_IgnoreUppercase, pmoi, OPT_SPELLIGNOREUPPER); ButtonChkFromOptInfo(hwnd, CHK_IgnoreNumbers, pmoi, OPT_SPELLIGNORENUMBER); ButtonChkFromOptInfo(hwnd, CHK_IgnoreOriginalMessage, pmoi, OPT_SPELLIGNOREPROTECT); ButtonChkFromOptInfo(hwnd, CHK_IgnoreDBCS, pmoi, OPT_SPELLIGNOREDBCS); ButtonChkFromOptInfo(hwnd, CHK_IgnoreURL, pmoi, OPT_SPELLIGNOREURL);
FillLanguageDropDown(GetDlgItem(hwnd, idcSpellLanguages));
uCP = GetACP(); // 50406: if we're not DBCS or (we're Japaneese or either Chinese) don't show
// the DBCS option.
if (!FDBCSEnabled() || ((932==uCP) || (936==uCP) || (950==uCP))) { ShowWindow(GetDlgItem(hwnd, CHK_IgnoreDBCS), SW_HIDE); EnableWindow(GetDlgItem(hwnd, CHK_IgnoreDBCS), FALSE); }
// Pictures
HICON hIcon;
hIcon = ImageList_GetIcon(pmoi->himl, ID_SPELL, ILD_TRANSPARENT); SendDlgItemMessage(hwnd, IDC_SPELL_SETTINGS_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM) hIcon); hIcon = ImageList_GetIcon(pmoi->himl, ID_SPELL_IGNORE, ILD_TRANSPARENT); SendDlgItemMessage(hwnd, IDC_SPELL_IGNORE_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM) hIcon);
hIcon = ImageList_GetIcon(pmoi->himl, ID_LANGUAGE_ICON, ILD_TRANSPARENT); SendDlgItemMessage(hwnd, IDC_SPELL_LANGUAGE_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM) hIcon);
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LPARAM)1); } return(TRUE);
case WM_HELP: case WM_CONTEXTMENU: return OnContextHelp(hwnd, message, wParam, lParam, g_rgCtxMapSpell);
case WM_COMMAND: if (1 != GetWindowLongPtr(hwnd, GWLP_USERDATA)) break;
if (HIWORD(wParam) == BN_CLICKED || HIWORD(wParam) == CBN_SELCHANGE) { if (LOWORD(wParam) == idcViewDictionary) { AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsSpellCaption), MAKEINTRESOURCEW(idsErrSpellWarnDictionary), NULL, MB_OK | MB_ICONINFORMATION); OpenCustomDictionary(); } else { PropSheet_Changed(GetParent(hwnd), hwnd); } } break;
case WM_NOTIFY: switch (((NMHDR FAR *)lParam)->code) { case PSN_APPLY: { int i; int lidNew; int lidOld; TCHAR rgchBuf[10];
// get the current language
GetLangID(rgchBuf, sizeof(rgchBuf) / sizeof(TCHAR)); lidOld = StrToInt(rgchBuf);
Assert(pmoi != NULL);
ButtonChkToOptInfo(hwnd, CHK_AlwaysSuggest, pmoi, OPT_SPELLALWAYSSUGGEST); ButtonChkToOptInfo(hwnd, CHK_CheckSpellingOnSend, pmoi, OPT_SPELLCHECKONSEND); ButtonChkToOptInfo(hwnd, CHK_CheckSpellingOnType, pmoi, OPT_SPELLCHECKONTYPE); ButtonChkToOptInfo(hwnd, CHK_IgnoreUppercase, pmoi, OPT_SPELLIGNOREUPPER); ButtonChkToOptInfo(hwnd, CHK_IgnoreNumbers, pmoi, OPT_SPELLIGNORENUMBER); ButtonChkToOptInfo(hwnd, CHK_IgnoreOriginalMessage, pmoi, OPT_SPELLIGNOREPROTECT); ButtonChkToOptInfo(hwnd, CHK_IgnoreDBCS, pmoi, OPT_SPELLIGNOREDBCS); ButtonChkToOptInfo(hwnd, CHK_IgnoreURL, pmoi, OPT_SPELLIGNOREURL);
i = ComboBox_GetCurSel(GetDlgItem(hwnd, idcSpellLanguages)); lidNew =(LID) ComboBox_GetItemData(GetDlgItem(hwnd, idcSpellLanguages), i);
if (lidNew != lidOld) { wnsprintf(rgchBuf, ARRAYSIZE(rgchBuf), "%d", lidNew); SetLangID(rgchBuf); } } break; } break;
case WM_DESTROY: FreeIcon(hwnd, IDC_SPELL_SETTINGS_ICON); FreeIcon(hwnd, IDC_SPELL_IGNORE_ICON); FreeIcon(hwnd, IDC_SPELL_LANGUAGE_ICON); break; #if 0
case WM_HELP: { NMHDR nmhdr;
nmhdr.code = PSN_HELP; SendMessage(hwnd, WM_NOTIFY, 0, (LPARAM) &nmhdr); SetWindowLong(hwnd, DWL_MSGRESULT, TRUE); return TRUE; } #endif
}
return(FALSE); }
BOOL EnumOffice9UserDictionaries(DWORD_PTR dwCookie, LPFNENUMUSERDICT pfn) { TCHAR rgchBuf[cchMaxPathName]; HKEY hkey = NULL; FILETIME ft; DWORD iKey = 0; LONG lRet; TCHAR szValue[cchMaxPathName]; DWORD cchValue; TCHAR szCustDict[cchMaxPathName]; DWORD cchCustDict; BOOL fContinue = TRUE; BOOL fFoundUserDict = FALSE; TCHAR szOffice9Proof[cchMaxPathName]={0}; // SOFTWARE\\Microsoft\\Shared Tools\\Proofing Tools\\Custom Dictionaries
StrCpyN(rgchBuf, c_szRegSpellProfile, ARRAYSIZE(rgchBuf)); StrCatBuff(rgchBuf, c_szRegSpellKeyCustom, ARRAYSIZE(rgchBuf));
if(RegOpenKeyEx(HKEY_CURRENT_USER, rgchBuf, 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS) { do { cchValue = sizeof(szValue) / sizeof(szValue[0]); cchCustDict = sizeof(szCustDict) / sizeof(szCustDict[0]);
lRet = RegEnumValue(hkey, iKey++, szValue, &cchValue, NULL, NULL, (LPBYTE)szCustDict, &cchCustDict);
if (lRet != ERROR_SUCCESS || lRet == ERROR_NO_MORE_ITEMS) break;
fFoundUserDict = TRUE;
// check to see if we have a path
if (!(StrChr(szCustDict, ':') || StrChr(szCustDict, '\\'))) { TCHAR szTemp[cchMaxPathName]; if (!strlen(szOffice9Proof)) { LPITEMIDLIST pidl;
if (S_OK == SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &pidl)) SHGetPathFromIDList(pidl, szOffice9Proof);
// if this fails then we will try the current path
}
StrCpyN(szTemp, szOffice9Proof, ARRAYSIZE(szTemp)); PathAppend(szTemp, c_szSpellOffice9ProofPath); StrCatBuff(szTemp, szCustDict, ARRAYSIZE(szTemp)); StrCpyN(szCustDict, szTemp, ARRAYSIZE(szCustDict)); } fContinue = (*pfn)(dwCookie, szCustDict);
} while (fContinue); }
if (hkey) RegCloseKey(hkey);
return fFoundUserDict; }
BOOL EnumOfficeUserDictionaries(DWORD_PTR dwCookie, LPFNENUMUSERDICT pfn) { TCHAR rgchBuf[cchMaxPathName]; HKEY hkey = NULL; FILETIME ft; DWORD iKey = 0; LONG lRet; TCHAR szValue[cchMaxPathName]; DWORD cchValue; TCHAR szCustDict[cchMaxPathName]; DWORD cchCustDict; BOOL fFoundUserDict = FALSE; BOOL fContinue = TRUE;
// SOFTWARE\\Microsoft\\Shared Tools\\Proofing Tools\\Custom Dictionaries
StrCpyN(rgchBuf, c_szRegSpellProfile, ARRAYSIZE(rgchBuf)); StrCatBuff(rgchBuf, c_szRegSpellKeyCustom, ARRAYSIZE(rgchBuf));
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, rgchBuf, 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS) { do { cchValue = sizeof(szValue) / sizeof(szValue[0]); cchCustDict = sizeof(szCustDict) / sizeof(szCustDict[0]);
lRet = RegEnumValue(hkey, iKey++, szValue, &cchValue, NULL, NULL, (LPBYTE)szCustDict, &cchCustDict);
if (lRet != ERROR_SUCCESS || lRet == ERROR_NO_MORE_ITEMS) break;
fFoundUserDict = TRUE;
fContinue = (*pfn)(dwCookie, szCustDict);
} while (fContinue); }
if (hkey) RegCloseKey(hkey);
return fFoundUserDict; }
VOID EnumUserDictionaries(DWORD_PTR dwCookie, LPFNENUMUSERDICT pfn) { // check for Office9 user dictionaries. If we find any
// we bail.
if (EnumOffice9UserDictionaries(dwCookie, pfn)) return;
EnumOfficeUserDictionaries(dwCookie, pfn); }
BOOL GetDefaultUserDictionary(TCHAR *rgchUserDict, int cchBuff) { DWORD dwType; DWORD cchUserDict; HKEY hkey = NULL; BOOL fFound = FALSE; if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegSharedTools, 0, KEY_QUERY_VALUE, &hkey)) { cchUserDict = cchBuff; if (SHQueryValueEx(hkey, c_szRegSharedToolsPath, 0L, &dwType, rgchUserDict, &cchUserDict) == ERROR_SUCCESS) { StrCatBuff(rgchUserDict, c_szRegDefCustomDict, cchBuff);
fFound = TRUE; }
RegCloseKey(hkey); }
// if we where able to create a path to the user dict store it in the regdb
if (fFound) { TCHAR rgchBuf[cchMaxPathName];
StrCpyN(rgchBuf, c_szRegSpellProfile, ARRAYSIZE(rgchBuf)); StrCatBuff(rgchBuf, c_szRegSpellKeyCustom, ARRAYSIZE(rgchBuf));
if(RegCreateKeyEx(HKEY_LOCAL_MACHINE, rgchBuf, 0, rgchBuf, REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &hkey, NULL) == ERROR_SUCCESS) { RegSetValueEx(hkey, c_szRegSpellPathDict, 0, REG_SZ, (BYTE *)rgchUserDict, (lstrlen(rgchUserDict) + 1) * sizeof(TCHAR));
RegCloseKey(hkey); } } return fFound; }
BOOL EnumUserDictCallback(DWORD_PTR dwCookie, LPTSTR lpszDict) { STRING_AND_SIZE * pStringAndSize = (STRING_AND_SIZE *) dwCookie;
if (pStringAndSize && pStringAndSize->pszString) { StrCpyN(pStringAndSize->pszString, lpszDict, pStringAndSize->cchSize); }
return FALSE; }
BOOL GetDefUserDictionaries(LPTSTR lpszDict, DWORD cchDict) { STRING_AND_SIZE stringAndSize;
stringAndSize.pszString = lpszDict; stringAndSize.cchSize = cchDict;
lpszDict[0] = 0; EnumUserDictionaries((DWORD_PTR)&stringAndSize, EnumUserDictCallback);
if (strlen(lpszDict)) return TRUE;
if (GetDefaultUserDictionary(lpszDict, cchDict)) return TRUE; return FALSE; }
VOID OpenCustomDictionary(VOID) { HKEY hkey = NULL; TCHAR rgchBuf[cchMaxPathName]; DWORD cbData = 0; DWORD dwType;
// Verify that .DIC files can be handled:
rgchBuf[0] = '\0';
if (RegOpenKeyEx(HKEY_CLASSES_ROOT, c_szRegDICHandlerKEY, 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS) { if (hkey) { SHQueryValueEx(hkey, NULL, 0L, &dwType, (BYTE *) rgchBuf, &cbData); RegCloseKey(hkey); } }
if (cbData == 0 || !rgchBuf[0]) { if (RegCreateKeyEx(HKEY_CLASSES_ROOT, c_szRegDICHandlerKEY, 0, rgchBuf, REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &hkey, NULL) == ERROR_SUCCESS) { if (hkey) { RegSetValueEx(hkey, NULL, 0L, REG_SZ, (BYTE *) c_szRegDICHandlerDefault, (lstrlen(c_szRegDICHandlerDefault) + 1) * sizeof(TCHAR)); RegCloseKey(hkey); } } }
if (GetDefUserDictionaries(rgchBuf, sizeof(rgchBuf)/sizeof(TCHAR))) { // make sure our directory exists
{ TCHAR rgchDictDir[MAX_PATH];
StrCpyN(rgchDictDir, rgchBuf, ARRAYSIZE(rgchDictDir));
PathRemoveFileSpec(rgchDictDir); OpenDirectory(rgchDictDir); }
// now make sure the file exists
// if it does not create it
{ HANDLE hFile;
hFile = CreateFile(rgchBuf, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); } { SHELLEXECUTEINFO see; ZeroMemory(&see, sizeof(SHELLEXECUTEINFO));
see.cbSize = sizeof(see); see.fMask = SEE_MASK_NOCLOSEPROCESS; see.lpFile = rgchBuf; see.nShow = SW_SHOWNORMAL;
if (ShellExecuteEx(&see)) { Assert(see.hProcess); WaitForInputIdle(see.hProcess, 20000); CloseHandle(see.hProcess); } } } }
BOOL FBadSpellChecker(LPSTR rgchBufDigit) { TCHAR rgchBufKey[cchMaxPathName]; TCHAR rgchBuf[cchMaxPathName]; TCHAR szMdr[cchMaxPathName]; LPSTR pszSpell;
wnsprintf(rgchBufKey, ARRAYSIZE(rgchBufKey), c_szRegSpellKeyDef, rgchBufDigit);
if (!GetSpellingPaths(rgchBufKey, rgchBuf, szMdr, sizeof(rgchBuf)/sizeof(TCHAR))) return TRUE;
pszSpell = PathFindFileNameA(rgchBuf); if (!pszSpell) return TRUE;
if (lstrcmpi(pszSpell, "msspell.dll")==0 || lstrcmpi(pszSpell, "mssp32.dll")==0) return TRUE;
// [email protected] - check that the dict exists (also check the spell dll
// for good measure) - 40081
// spell dll must exist
if (!PathFileExists(rgchBuf)) return TRUE;
// main dict must exist
if (!PathFileExists(szMdr)) return TRUE;
return FALSE; }
|