// ================================================================================= // F O N T S . C P P // ================================================================================= #include "pch.hxx" #include "fonts.h" #include "multlang.h" #include "xpcomm.h" #include "strconst.h" #include "mimeole.h" #include "goptions.h" #include "error.h" #include "thormsgs.h" #include "richedit.h" #include "ibodyopt.h" #include "shlwapi.h" #include "shlwapip.h" #include "mimeutil.h" #include "optres.h" #include "demand.h" #include "menures.h" #include "multiusr.h" // this part creates a MIME COM object from MLAMG.DLL which gives us a consistent // language menu to be the same as IE browser // HMENU CreateMimeLanguageMenu(void) #include #include #include "resource.h" #define IGNORE_HR(x) (x) #define MIMEINFO_NAME_MAX 72 #define DEFAULT_FONTSIZE 2 // MLANG language menu items table static PMIMECPINFO g_pMimeCPInfo = NULL; static ULONG g_cMimeCPInfoCount = 0; static DWORD g_cRefMultiLanguage = 0; TCHAR g_szMore[32]; #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) #define BREAK_ITEM 20 #define CP_UNDEFINED UINT(-1) #define CP_AUTO 50001 // cross language detection #define CP_1252 1252 // Ansi, Western Europe #define CCPDEFAULT 2 void SendTridentOptionsChange(); typedef struct { UINT cp; ULONG ulIdx; int cUsed; } CPCACHE; class CCachedCPInfo { public: CCachedCPInfo(); static void InitCpCache (PMIMECPINFO pcp, ULONG ccp); static void SaveCodePage (UINT codepage, PMIMECPINFO pcp, ULONG ccp); BOOL fAutoSelectInstalled; BOOL fAutoSelectChecked; static UINT GetCodePage(int idx) { return idx < ARRAY_SIZE(_CpCache) ? _CpCache[idx].cp: 0; } static ULONG GetCcp() { return _ccpInfo; } static ULONG GetMenuIdx(int idx) { return idx < ARRAY_SIZE(_CpCache) ? _CpCache[idx].ulIdx: 0; } private: static ULONG _ccpInfo; static CPCACHE _CpCache[5]; }; CCachedCPInfo::CCachedCPInfo() { fAutoSelectInstalled = FALSE; fAutoSelectChecked = FALSE; } // declaration for static members ULONG CCachedCPInfo::_ccpInfo = CCPDEFAULT; CPCACHE CCachedCPInfo::_CpCache[5] = { {CP_AUTO, 0, 0}, // cross-codepage autodetect {CP_1252,0,0}, }; CCachedCPInfo g_cpcache; // useful macros... inline BOOL IsPrimaryCodePage(MIMECPINFO *pcpinfo) { return pcpinfo->uiCodePage == pcpinfo->uiFamilyCodePage; } //------------------------------------------------------------------------ // // Function: CCachedCPInfo::InitCpCache // // Initialize the cache with default codepages // which do not change through the session // //------------------------------------------------------------------------ void CCachedCPInfo::InitCpCache (PMIMECPINFO pcp, ULONG ccp) { UINT iCache, iCpInfo; if (pcp && ccp > 0) { for (iCache= 0; iCache < CCPDEFAULT; iCache++) { for (iCpInfo= 0; iCpInfo < ccp; iCpInfo++) { if ( pcp[iCpInfo].uiCodePage == _CpCache[iCache].cp ) { if(CP_AUTO == _CpCache[iCache].cp) { g_cpcache.fAutoSelectInstalled = TRUE; } _CpCache[iCache].ulIdx = iCpInfo; _CpCache[iCache].cUsed = ARRAY_SIZE(_CpCache)-1; break; } } } } } //------------------------------------------------------------------------ // // Function: CCachedCPInfo::SaveCodePage // // Cache the given codepage along with the index to // the given array of MIMECPINFO // //------------------------------------------------------------------------ void CCachedCPInfo::SaveCodePage (UINT codepage, PMIMECPINFO pcp, ULONG ccp) { int ccpSave = -1; BOOL bCached = FALSE; UINT i; // first check if we already have this cp for (i = 0; i < _ccpInfo; i++) { if (_CpCache[i].cp == codepage) { ccpSave = i; bCached = TRUE; break; } } // if cache is not full, use the current // index to an entry if (ccpSave < 0 && _ccpInfo < ARRAY_SIZE(_CpCache)) { ccpSave = _ccpInfo; } // otherwise, popout the least used entry. // the default codepages always stay // this also decriments the usage count int cMinUsed = ARRAY_SIZE(_CpCache); UINT iMinUsed = 0; for ( i = CCPDEFAULT; i < _ccpInfo; i++) { if (_CpCache[i].cUsed > 0) _CpCache[i].cUsed--; if ( ccpSave < 0 && _CpCache[i].cUsed < cMinUsed) { cMinUsed = _CpCache[i].cUsed; iMinUsed = i; } } if (ccpSave < 0) ccpSave = iMinUsed; // set initial usage count, which goes down to 0 if it doesn't get // chosen twice in a row (with current array size) _CpCache[ccpSave].cUsed = ARRAY_SIZE(_CpCache)-1; // find a matching entry from given array of // mimecpinfo if (pcp && ccp > 0) { for (i= 0; i < ccp; i++) { if ( pcp[i].uiCodePage == codepage ) { _CpCache[ccpSave].cp = codepage; _CpCache[ccpSave].ulIdx = i; if (!bCached && _ccpInfo < ARRAY_SIZE(_CpCache)) _ccpInfo++; break; } } } } // Get UI language which can shown, using System fonts LANGID OEGetUILang() { LANGID lidUI = MLGetUILanguage(); if(fIsNT5()) // Nothing for NT5 return(lidUI); if (0x0409 != lidUI) // US resource is always no need to munge { CHAR szUICP[8]; CHAR szInstallCP[8]; GetLocaleInfo(MAKELCID(lidUI, SORT_DEFAULT), LOCALE_IDEFAULTANSICODEPAGE, szUICP, ARRAYSIZE(szUICP)); GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE, szInstallCP, ARRAYSIZE(szInstallCP)); if (lstrcmpi(szUICP, szInstallCP)) // return default user language ID return(LANGIDFROMLCID(LOCALE_USER_DEFAULT)); } return (lidUI); // return lang ID from MLGetUILanguage() } BOOL CheckAutoSelect(UINT * CodePage) { if(g_cpcache.fAutoSelectChecked) { *CodePage = CP_AUTO; return(TRUE); } return(FALSE); } HRESULT _InitMultiLanguage(void) { HRESULT hr; IMultiLanguage *pMLang1=NULL; IMultiLanguage2 *pMLang2=NULL; // check if data has been initialized if (g_pMimeCPInfo) return S_OK ; Assert(g_cMimeCPInfoCount == NULL ); // create MIME COM object hr = CoCreateInstance(CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, IID_IMultiLanguage2, (void**)&pMLang2); if (FAILED(hr)) hr = CoCreateInstance(CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, IID_IMultiLanguage, (void**)&pMLang1); if (SUCCEEDED(hr)) { UINT cNum; IEnumCodePage *pEnumCodePage; if (pMLang2) { hr = pMLang2->EnumCodePages(MIMECONTF_MAILNEWS | MIMECONTF_VALID, OEGetUILang(), &pEnumCodePage); if (SUCCEEDED(hr)) pMLang2->GetNumberOfCodePageInfo(&cNum); } else { hr = pMLang1->EnumCodePages(MIMECONTF_MAILNEWS | MIMECONTF_VALID, &pEnumCodePage); if (SUCCEEDED(hr)) pMLang1->GetNumberOfCodePageInfo(&cNum); } if (SUCCEEDED(hr)) { MemAlloc((LPVOID *)&g_pMimeCPInfo, sizeof(MIMECPINFO) * cNum); if ( g_pMimeCPInfo ) { ZeroMemory(g_pMimeCPInfo, sizeof(MIMECPINFO) * cNum); hr = pEnumCodePage->Next(cNum, g_pMimeCPInfo, &g_cMimeCPInfoCount); IGNORE_HR(MemRealloc((void **)&g_pMimeCPInfo, sizeof(MIMECPINFO) * g_cMimeCPInfoCount)); } pEnumCodePage->Release(); } // Release Objects SafeRelease(pMLang1); SafeRelease(pMLang2); } // get default charset, before user make any change to View/Language if (g_hDefaultCharsetForMail == NULL) ReadSendMailDefaultCharset(); return hr; } HRESULT InitMultiLanguage(void) { // we defer the call to _InitMultiLanguage until it is necessary // add reference count g_cRefMultiLanguage++ ; return S_OK ; } void DeinitMultiLanguage(void) { // decrease reference count if ( g_cRefMultiLanguage ) g_cRefMultiLanguage--; if ( g_cRefMultiLanguage <= 0 ) { if ( g_pMimeCPInfo) { MemFree(g_pMimeCPInfo); g_pMimeCPInfo = NULL; g_cMimeCPInfoCount = 0; } WriteSendMailDefaultCharset(); } return ; } HMENU CreateMimeLanguageMenu(BOOL bMailNote, BOOL bReadNote, UINT cp) { ULONG i; HMENU hMenu = NULL; ULONG cchXlated ; UINT uCodePage ; CHAR szBuffer[MIMEINFO_NAME_MAX]; BOOL fUseSIO; BOOL fBroken = FALSE; ULONG iMenuIdx; UINT uNoteCP; if(fIsNT5()) { if(GetLocaleInfoW(OEGetUILang(), LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, (LPWSTR)(&uCodePage), sizeof(UINT)/sizeof(WCHAR) ) != sizeof(UINT)/sizeof(WCHAR)) uCodePage = GetACP(); } else uCodePage = GetACP(); if(!cp) uNoteCP = uCodePage; else uNoteCP = GetMapCP(cp, bReadNote); bMailNote = FALSE; hMenu = CreatePopupMenu(); if ( g_pMimeCPInfo == NULL) { _InitMultiLanguage(); if ( g_pMimeCPInfo == NULL) { // create an empty menu LoadString(g_hLocRes, idsEmptyStr, szBuffer, MIMEINFO_NAME_MAX); AppendMenu(hMenu, MF_DISABLED|MF_GRAYED , (UINT)-1, szBuffer); return hMenu ; } } g_cpcache.InitCpCache(g_pMimeCPInfo, g_cMimeCPInfoCount); g_cpcache.SaveCodePage(uNoteCP, g_pMimeCPInfo, g_cMimeCPInfoCount); for(i = 0; i < g_cpcache.GetCcp(); i++) { iMenuIdx = g_cpcache.GetMenuIdx(i); // cchXlated = WideCharToMultiByte(uCodePage, 0, g_pMimeCPInfo[iMenuIdx].wszDescription, -1, szBuffer, MIMEINFO_NAME_MAX, NULL, NULL); if(!fCheckEncodeMenu(g_pMimeCPInfo[iMenuIdx].uiCodePage, bReadNote)) continue ; if(i != 0) AppendMenuWrapW(hMenu, MF_ENABLED, iMenuIdx + ID_LANG_FIRST,g_pMimeCPInfo[iMenuIdx].wszDescription); // [SBAILEY]: Raid 69638: oe:ml: Autoselect doesnt work (we don't support global encoding auto-detect, therefore don't show it #if 0 else if(g_cpcache.fAutoSelectInstalled && bReadNote) { AppendMenuWrapW(hMenu, MF_ENABLED, iMenuIdx + ID_LANG_FIRST,g_pMimeCPInfo[iMenuIdx].wszDescription); AppendMenuWrapW(hMenu, MF_SEPARATOR, 0, 0); } #endif // mark the cp entry so we can skip it for submenu // this assumes we'd never use the MSB for MIMECONTF g_pMimeCPInfo[iMenuIdx].dwFlags |= 0x80000000; } // Check Params Assert(g_pMimeCPInfo); Assert(g_cMimeCPInfoCount > 0 ); // add the submenu for the rest of encodings HMENU hSubMenu = CreatePopupMenu(); UINT uiLastFamilyCp = 0; if ( g_cMimeCPInfoCount ) { // Get System CodePage if (hSubMenu) { for (i = 0; i < g_cMimeCPInfoCount ; i++) { if(!fCheckEncodeMenu(g_pMimeCPInfo[i].uiCodePage, bReadNote)) continue ; // skip codepages that are on teir1 menu if (!(g_pMimeCPInfo[i].dwFlags & 0x80000000)) { if ((g_pMimeCPInfo[i].dwFlags & MIMECONTF_VALID) || IsPrimaryCodePage(g_pMimeCPInfo+i)) { UINT uiFlags = MF_ENABLED; if (uiLastFamilyCp > 0 && uiLastFamilyCp != g_pMimeCPInfo[i].uiFamilyCodePage) { // add separater between different family unless // we will be adding the menu bar break if(i < BREAK_ITEM || fBroken) { AppendMenuWrapW(hSubMenu, MF_SEPARATOR, 0, 0); } else { uiFlags |= MF_MENUBARBREAK; fBroken = TRUE; } } // This menu gets really long. Let's break at a defined number so it all // fits on the screen /* cchXlated = WideCharToMultiByte(uCodePage, 0, g_pMimeCPInfo[i].wszDescription, -1, szBuffer, MIMEINFO_NAME_MAX , NULL , NULL); */ AppendMenuWrapW(hSubMenu, uiFlags, i+ID_LANG_FIRST, g_pMimeCPInfo[i].wszDescription); // save the family of added codepage uiLastFamilyCp = g_pMimeCPInfo[i].uiFamilyCodePage; } } else g_pMimeCPInfo[i].dwFlags &= 0x7FFFFFFF; } // add this submenu to the last of tier1 menu if (!g_szMore[0]) { LoadString(g_hLocRes, idsEncodingMore, g_szMore, ARRAY_SIZE(g_szMore)); } if (GetMenuItemCount(hSubMenu) > 0) { MENUITEMINFO mii; mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_SUBMENU; mii.hSubMenu = hSubMenu; AppendMenu(hMenu, MF_DISABLED, ID_POPUP_LANGUAGE_MORE, g_szMore); SetMenuItemInfo(hMenu, ID_POPUP_LANGUAGE_MORE, FALSE, &mii); } else { DestroyMenu(hSubMenu); } } } else { // create an empty menu LoadString(g_hLocRes, idsEmptyStr, szBuffer, MIMEINFO_NAME_MAX); AppendMenu(hMenu, MF_DISABLED|MF_GRAYED , (UINT)-1, szBuffer); } return hMenu; } HCHARSET GetMimeCharsetFromMenuID(int nIdm) { UINT idx; HCHARSET hCharset = NULL ; ULONG cchXlated ; UINT uCodePage ; CHAR szBuffer[MIMEINFO_NAME_MAX]; idx = nIdm - ID_LANG_FIRST; if((g_pMimeCPInfo[idx].uiCodePage == CP_AUTO) && g_cpcache.fAutoSelectInstalled) // Auto Select selected { g_cpcache.fAutoSelectChecked = !g_cpcache.fAutoSelectChecked; return(NULL); } if ( g_pMimeCPInfo && idx < g_cMimeCPInfoCount ) { uCodePage = GetACP(); cchXlated = WideCharToMultiByte(uCodePage, 0, g_pMimeCPInfo[idx].wszBodyCharset, -1, szBuffer, ARRAYSIZE(szBuffer), NULL, NULL); szBuffer[ARRAYSIZE(szBuffer) - 1] = '\0'; //better safe than not null-terminated // check if BodyCharset starts with '_' like "_iso-2022-JP$ESC" // if it is, use BodyCharset // otherwise, use WebCharset // BUGBUG - special case for Korean 949 use BodyCharset, fix by RTM if ( szBuffer[0] != '_' && 949 != g_pMimeCPInfo[idx].uiCodePage) { cchXlated = WideCharToMultiByte(uCodePage, 0, g_pMimeCPInfo[idx].wszWebCharset, -1, szBuffer, ARRAYSIZE(szBuffer), NULL, NULL); szBuffer[ARRAYSIZE(szBuffer) - 1] = '\0'; //better safe than not null-terminated } MimeOleFindCharset(szBuffer,&hCharset); } return hCharset ; } HCHARSET GetMimeCharsetFromCodePage(UINT uiCodePage ) { HCHARSET hCharset = NULL ; ULONG cchXlated, i ; UINT uCodePage ; CHAR szBuffer[MIMEINFO_NAME_MAX]; if ( g_pMimeCPInfo == NULL) _InitMultiLanguage(); if ( g_pMimeCPInfo ) { uCodePage = GetACP(); for (i = 0; i < g_cMimeCPInfoCount ; i++) { if (uiCodePage == g_pMimeCPInfo[i].uiCodePage) { cchXlated = WideCharToMultiByte(uCodePage, 0, g_pMimeCPInfo[i].wszBodyCharset, -1, szBuffer, ARRAYSIZE(szBuffer), NULL, NULL); szBuffer[ARRAYSIZE(szBuffer) - 1] = '\0'; //better safe than not null-terminated // check if BodyCharset starts with '_' like "_iso-2022-JP$ESC" // if it is, use BodyCharset // otherwise, use WebCharset // BUGBUG - special case for Korean 949 use BodyCharset, fix by RTM if ( szBuffer[0] != '_' && 949 != g_pMimeCPInfo[i].uiCodePage) { cchXlated = WideCharToMultiByte(uCodePage, 0, g_pMimeCPInfo[i].wszWebCharset, -1, szBuffer, ARRAYSIZE(szBuffer), NULL, NULL); szBuffer[ARRAYSIZE(szBuffer) - 1] = '\0'; //better safe than not null-terminated } MimeOleFindCharset(szBuffer,&hCharset); break ; } } } return hCharset ; } void _GetMimeCharsetLangString(BOOL bWebCharset, UINT uiCodePage, LPINT pnIdm, LPTSTR lpszString, int nSize ) { ULONG i, cchXlated ; UINT uCodePage ; if ( g_pMimeCPInfo == NULL) _InitMultiLanguage(); if ( g_cMimeCPInfoCount ) { // Get System CodePage uCodePage = GetACP(); for (i = 0; i < g_cMimeCPInfoCount ; i++) { if (uiCodePage == g_pMimeCPInfo[i].uiCodePage) { // convert WideString to MultiByteString if (lpszString) { if (bWebCharset) cchXlated = WideCharToMultiByte(uCodePage, 0, g_pMimeCPInfo[i].wszWebCharset, -1, lpszString, nSize, NULL, NULL); else cchXlated = WideCharToMultiByte(uCodePage, 0, g_pMimeCPInfo[i].wszDescription, -1, lpszString, nSize, NULL, NULL); } if ( pnIdm ) *pnIdm = i+ID_LANG_FIRST; break ; } } } return ; } int SetMimeLanguageCheckMark(UINT uiCodePage, int index) { ULONG i; if((g_pMimeCPInfo[index].uiCodePage == CP_AUTO) && g_cpcache.fAutoSelectInstalled && DwGetOption(OPT_INCOMDEFENCODE)) return (0); else if((g_pMimeCPInfo[index].uiCodePage == CP_AUTO) && g_cpcache.fAutoSelectChecked && g_cpcache.fAutoSelectInstalled) return (OLECMDF_LATCHED | OLECMDF_ENABLED); UINT iStart = g_cpcache.fAutoSelectInstalled ? 1 : 0; if (1 < g_cMimeCPInfoCount) { if(uiCodePage == g_pMimeCPInfo[index].uiCodePage) return (OLECMDF_NINCHED | OLECMDF_ENABLED); else return OLECMDF_ENABLED; } return FALSE; } INT GetFontSize(void) { DWORD cb, iFontSize = 0; cb = sizeof(iFontSize); AthUserGetValue(NULL, c_szRegValIMNFontSize, NULL, (LPBYTE)&iFontSize, &cb); if(iFontSize < 1 || iFontSize > 7) iFontSize = 2; return((INT)iFontSize); } // // GetICP() - Gets the system's *internet* codepage from the ANSI codepage // UINT GetICP(UINT acp) { HCHARSET hCharset = NULL; UINT icp = NULL; CODEPAGEINFO rCodePage; INETCSETINFO CsetInfo; HRESULT hr; ULONG i; if(!acp) acp = GetACP(); icp = acp; // Get the codepage info for acp IF_FAILEXIT(hr = MimeOleGetCodePageInfo(acp, &rCodePage)); // Use the body (internet) charset description to get the codepage id for // the body charset IF_FAILEXIT(hr = MimeOleFindCharset(rCodePage.szBodyCset, &hCharset)); IF_FAILEXIT(hr = MimeOleGetCharsetInfo(hCharset,&CsetInfo)); // Now, we need to know if MLANG understands this CP if ( g_pMimeCPInfo == NULL) _InitMultiLanguage(); if ( g_cMimeCPInfoCount ) { for (i = 0; i < g_cMimeCPInfoCount ; i++) { if (CsetInfo.cpiInternet == g_pMimeCPInfo[i].uiCodePage) { icp = CsetInfo.cpiInternet; break ; } } } exit: return icp; } void ReadSendMailDefaultCharset(void) { // Locals HKEY hTopkey; DWORD cb; CODEPAGEID cpiCodePage; // only read once, skip if it is defined if (g_hDefaultCharsetForMail == NULL) { cb = sizeof(cpiCodePage); if (ERROR_SUCCESS == AthUserGetValue(c_szRegPathMail, c_szDefaultCodePage, NULL, (LPBYTE)&cpiCodePage, &cb)) { if (cpiCodePage == 50222 || cpiCodePage == 50221) g_hDefaultCharsetForMail = GetJP_ISOControlCharset(); else g_hDefaultCharsetForMail = GetMimeCharsetFromCodePage(cpiCodePage); } } if (g_hDefaultCharsetForMail == NULL) { if(FAILED(HGetDefaultCharset(&g_hDefaultCharsetForMail))) g_hDefaultCharsetForMail = GetMimeCharsetFromCodePage(GetICP(NULL)); } return; } void WriteSendMailDefaultCharset(void) { // Locals CODEPAGEID uiCodePage; INETCSETINFO CsetInfo ; // get CodePage from HCHARSET if (g_hDefaultCharsetForMail) { MimeOleGetCharsetInfo(g_hDefaultCharsetForMail,&CsetInfo); uiCodePage = CsetInfo.cpiInternet ; AthUserSetValue(c_szRegPathMail, c_szDefaultCodePage, REG_DWORD, (LPBYTE)&uiCodePage, sizeof(uiCodePage)); } return; } INT_PTR CALLBACK CharsetChgDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { if (msg == WM_COMMAND) { int id = GET_WM_COMMAND_ID(wParam, lParam); if (id == IDOK || id == IDCANCEL || id == idcSendAsUnicode ) { EndDialog(hwndDlg, id); return TRUE; } } else if (msg == WM_INITDIALOG ) { CenterDialog(hwndDlg); } return FALSE; } static const HELPMAP g_rgCtxMapCharSetMap[] = { {idcStatic1, 35545}, {idcLangCheck, 35540}, {0, 0} }; INT_PTR CALLBACK ReadCharsetDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { CODEPAGEID cpiWindows; CODEPAGEID cpiInternet; TCHAR szCodePage[MAX_PATH]; TCHAR szBuffer[MIMEINFO_NAME_MAX] = ""; int Idm; switch (msg) { case WM_INITDIALOG: { // Open Trident\International DWORD cb = sizeof(cpiWindows); if (ERROR_SUCCESS != SHGetValue(MU_GetCurrentUserHKey(), c_szRegInternational, c_szDefaultCodePage, NULL, (LPBYTE)&cpiWindows, &cb)) cpiWindows = GetACP(); // Open the CodePage Key wnsprintf(szCodePage, ARRAYSIZE(szCodePage), TEXT("%s\\%d"), c_szRegInternational, cpiWindows); cb = sizeof(cpiInternet); if (ERROR_SUCCESS != SHGetValue(MU_GetCurrentUserHKey(), szCodePage, c_szDefaultEncoding, NULL, (LPBYTE)&cpiInternet, &cb)) cpiInternet = GetICP(cpiWindows); // Get information about current default charset _GetMimeCharsetLangString(FALSE, GetMapCP(cpiInternet, TRUE), &Idm, szBuffer, MIMEINFO_NAME_MAX - 1); // Set the String SetWindowText(GetDlgItem(hwndDlg, idcStatic1), szBuffer); // Set the Default CheckDlgButton(hwndDlg, idcLangCheck, DwGetOption(OPT_INCOMDEFENCODE) ? BST_CHECKED:BST_UNCHECKED); break ; } case WM_COMMAND: { int id = GET_WM_COMMAND_ID(wParam, lParam); if (id == IDCANCEL || id == IDOK ) { if(id == IDOK) { SetDwOption(OPT_INCOMDEFENCODE, IsDlgButtonChecked(hwndDlg, idcLangCheck), NULL, 0); #if 0 // hack: we should call these only if OpenFontsDialog tells us user has changed the font. g_lpIFontCache->OnOptionChange(); SendTridentOptionsChange(); // Re-Read Default Character Set SetDefaultCharset(NULL); // Reset g_uiCodePage DWORD dwVal = 0; DWORD dwType = 0; DWORD cb = sizeof(dwVal); if (ERROR_SUCCESS == SHGetValue(MU_GetCurrentUserHKey(), c_szRegInternational, REGSTR_VAL_DEFAULT_CODEPAGE, &dwType, &dwVal, &cb)) g_uiCodePage = (UINT)dwVal; #endif // 0 } EndDialog(hwndDlg, id); return TRUE; } break ; } case WM_HELP: case WM_CONTEXTMENU: return OnContextHelp(hwndDlg, msg, wParam, lParam, g_rgCtxMapCharSetMap); default: break ; } return FALSE; } BOOL CheckIntlCharsetMap(HCHARSET hCharset, DWORD *pdwCodePage) { INETCSETINFO CsetInfo ; LPSTR lpCharsetName, lpStr; ULONG i; UINT uiCodePage ; if ( hCharset == NULL ) return FALSE ; if (!pdwCodePage) return FALSE ; else *pdwCodePage = 0 ; // get Code page from HCHARSET MimeOleGetCharsetInfo(hCharset,&CsetInfo); *pdwCodePage = GetMapCP(CsetInfo.cpiInternet, TRUE); // This func always called for Read note (?!) return(*pdwCodePage != CsetInfo.cpiInternet); } UINT CustomGetCPFromCharset(HCHARSET hCharset, BOOL bReadNote) { INETCSETINFO CsetInfo = {0}; UINT uiCodePage = 0 ; // get CodePage from HCHARSET MimeOleGetCharsetInfo(hCharset,&CsetInfo); uiCodePage = GetMapCP(CsetInfo.cpiInternet, bReadNote); // Bug #51636 // Check that code page supported by OE if(GetMimeCharsetFromCodePage(uiCodePage) == NULL) { HCHARSET hChar = NULL; if(bReadNote) { if(SUCCEEDED(HGetDefaultCharset(&hChar))) { if(FAILED(MimeOleGetCharsetInfo(hChar, &CsetInfo))) return(0); } else return(0); } else { if(FAILED(MimeOleGetCharsetInfo(g_hDefaultCharsetForMail, &CsetInfo))) return(0); } return(GetMapCP(CsetInfo.cpiInternet, bReadNote)); } return(uiCodePage); } BOOL IntlCharsetMapDialogBox(HWND hwndDlg) { DialogBox(g_hLocRes, MAKEINTRESOURCE(iddIntlSetting), hwndDlg, ReadCharsetDlgProc) ; return TRUE ; } int IntlCharsetConflictDialogBox(void) { return (int) DialogBox(g_hLocRes, MAKEINTRESOURCE(iddCharsetConflict), g_hwndInit, CharsetChgDlgProc); } int GetIntlCharsetLanguageCount(void) { if ( g_pMimeCPInfo == NULL) _InitMultiLanguage(); return g_cMimeCPInfoCount ; } HCHARSET GetListViewCharset() { HCHARSET hCharset; if(g_uiCodePage == GetACP() || 0 == g_uiCodePage) hCharset = NULL; else hCharset = GetMimeCharsetFromCodePage(g_uiCodePage); return hCharset; } // ================================================================================= // SetListViewFont // ================================================================================= VOID SetListViewFont (HWND hwndList, HCHARSET hCharset, BOOL fUpdate) { // Locals HFONT hFont; // Check Params Assert (IsWindow (hwndList)); hFont = HGetCharSetFont(FNT_SYS_ICON,hCharset); // If we got a font, set the list view if (hFont) { // Set the list view font - Dont redraw quite yet SendMessage (hwndList, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(fUpdate, 0)); // Try to reset header back to system icon font... // Get header HWND hwndHeader = GetWindow (hwndList, GW_CHILD); // Update Header hFont = HGetSystemFont(FNT_SYS_ICON); // If font if (hFont && hwndHeader) SendMessage (hwndHeader, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(fUpdate, 0)); // Refresh if (fUpdate) { InvalidateRect (hwndList, NULL, TRUE); InvalidateRect (GetWindow(hwndList, GW_CHILD), NULL, TRUE); } } } // ================================================================================= // HGetSystemFont // ================================================================================= HFONT HGetSystemFont(FNTSYSTYPE fnttype) { HFONT hFont; Assert (g_lpIFontCache); if (g_lpIFontCache) g_lpIFontCache->GetFont(fnttype, 0, &hFont); else hFont = NULL; return hFont; } // ================================================================================= // HGetCharSetFont // ================================================================================= HFONT HGetCharSetFont(FNTSYSTYPE fnttype, HCHARSET hCharset) { HFONT hFont; Assert (g_lpIFontCache); if (g_lpIFontCache) g_lpIFontCache->GetFont(fnttype, hCharset, &hFont); else hFont = NULL; return hFont; } // ****************************************************** // HrGetComposeFontString // // Purpose: builds the compose font string based on user settings ready for execing to Trident // // the format of the string is: // // "[Bold],[Italic],[Underline],[size],[FGRed.FGGreen.FGBlue],[BGRed.BGGreen.BGBlue],[FontFace]" // // Bold, Italic, Underline are either 0/1, indicating on or off. If none specified, 0 assumed. // Size is a number between 1 and 7. If none specified, 3 assumed // [FG|BG][Red|Green|Blue] are numbers between 0 and 255. For FG, if none specified black assumed, // for BG if none specified then undefined assumed. // Font Face is a valid font name string // For example an underline, blue text color, arial setting would be: // // ,,1,,0.0.255,,Arial // // and a bold, 5 size, black, comic sans MS would be // // 1,0,0,5,,,Comic Sans MS // ****************************************************** static const TCHAR c_szOn[] = "1,", c_szOff[] = "0,"; HRESULT HrGetComposeFontString(LPSTR rgchFont, DWORD cchFont, BOOL fMail) { DWORD dw = 0, dwSize = 2; TCHAR szFontFace[LF_FACESIZE+1]; TCHAR szTmp[50]; if (rgchFont==NULL) return E_INVALIDARG; // "[Bold],[Italic],[Underline],[size],[FGRed.FGGreen.FGBlue],[BGRed.BGGreen.BGBlue],[FontFace]" *szFontFace = 0; *rgchFont=0; // bold StrCatBuff(rgchFont, DwGetOption(fMail ? OPT_MAIL_FONTBOLD : OPT_NEWS_FONTBOLD) ? c_szOn : c_szOff, cchFont); // italic StrCatBuff(rgchFont, DwGetOption(fMail ? OPT_MAIL_FONTITALIC : OPT_NEWS_FONTITALIC) ? c_szOn : c_szOff, cchFont); // underline StrCatBuff(rgchFont, DwGetOption(fMail ? OPT_MAIL_FONTUNDERLINE : OPT_NEWS_FONTUNDERLINE) ? c_szOn : c_szOff, cchFont); dw = DwGetOption(fMail ? OPT_MAIL_FONTSIZE : OPT_NEWS_FONTSIZE); // map points to HTML size dwSize = PointSizeToHTMLSize(dw); // font size wnsprintf(szTmp, ARRAYSIZE(szTmp), "%d,", dwSize); StrCatBuff(rgchFont, szTmp, cchFont); // font foregroundcolor if(fMail) dw = DwGetOption(OPT_MAIL_FONTCOLOR); else dw = DwGetOption(OPT_NEWS_FONTCOLOR); // write out RGB string wnsprintf(szTmp, ARRAYSIZE(szTmp), "%d.%d.%d,", GetRValue(dw), GetGValue(dw), GetBValue(dw)); StrCatBuff(rgchFont, szTmp, cchFont); // default background color StrCatBuff(rgchFont, ",", cchFont); GetOption(fMail ? OPT_MAIL_FONTFACE : OPT_NEWS_FONTFACE, szFontFace, LF_FACESIZE); if(*szFontFace == 0) LoadString(g_hLocRes, idsComposeFontFace, szFontFace, LF_FACESIZE); StrCatBuff(rgchFont, szFontFace, cchFont); return S_OK; } INT PointSizeToHTMLSize(INT iPointSize) { INT iHTMLSize; // 1 ----- 8 // 2 ----- 10 // 3 ----- 12 // 4 ----- 14 // 5 ----- 18 // 6 ----- 24 // 7 ----- 36 if(iPointSize>=8 && iPointSize<9) iHTMLSize = 1; else if(iPointSize>=9 && iPointSize<12) iHTMLSize = 2; else if(iPointSize>=12 && iPointSize<14) iHTMLSize = 3; else if(iPointSize>=14 && iPointSize<18) iHTMLSize = 4; else if(iPointSize>=18 && iPointSize<24) iHTMLSize = 5; else if(iPointSize>=24 && iPointSize<36) iHTMLSize = 6; else if(iPointSize>=36) iHTMLSize = 7; else iHTMLSize = DEFAULT_FONTSIZE; return iHTMLSize; } INT HTMLSizeToPointSize(INT iHTMLSize) { INT iPointSize; // 1 ----- 8 // 2 ----- 10 // 3 ----- 12 // 4 ----- 14 // 5 ----- 18 // 6 ----- 24 // 7 ----- 36 switch (iHTMLSize) { case 1: iPointSize = 8; break; case 2: iPointSize = 10; break; case 3: iPointSize = 12; break; case 4: iPointSize = 14; break; case 5: iPointSize = 18; break; case 6: iPointSize = 24; break; case 7: iPointSize = 36; break; default: iPointSize = 10; } return iPointSize; } HRESULT HrGetStringRBG(INT rgb, LPWSTR pwszColor) { HRESULT hr = S_OK; INT i; DWORD crTemp; if(NULL == pwszColor) return E_INVALIDARG; rgb = ((rgb & 0x00ff0000) >> 16 ) | (rgb & 0x0000ff00) | ((rgb & 0x000000ff) << 16); for(i = 0; i < 6; i++) { crTemp = (rgb & (0x00f00000 >> (4*i))) >> (4*(5-i)); pwszColor[i] = (WCHAR)((crTemp < 10)? (crTemp+L'0') : (crTemp+ L'a' - 10)); } pwszColor[6] = L'\0'; return hr; } HRESULT HrGetRBGFromString(INT* pRBG, LPWSTR pwszColor) { HRESULT hr = S_OK; INT i, rbg = 0, len, n; WCHAR ch; if(NULL == pRBG) return E_INVALIDARG; *pRBG = 0; len = lstrlenW(pwszColor); for(i=0; i= L'0' && ch <= L'9') n = ch - L'0'; else if(ch >= L'a' && ch <= L'f') n = ch - L'a' + 10; else if(ch >= L'A' && ch <= L'F') n = ch - L'A' + 10; if(n < 0) continue; rbg = rbg*16 + n; } *pRBG = rbg; return hr; } // *************************************************** HRESULT FontToCharformat(HFONT hFont, CHARFORMAT *pcf) { DWORD dwOldEffects; HDC hdc; LOGFONT lf; INT yPerInch; if (FAILED(GetObject(hFont, sizeof(lf), &lf))) return E_FAIL; hdc=GetDC(NULL); yPerInch=GetDeviceCaps(hdc, LOGPIXELSY); ReleaseDC(NULL, hdc); // Set Struct Size ZeroMemory(pcf, sizeof (CHARFORMAT)); pcf->cbSize = sizeof (CHARFORMAT); // Set mask pcf->dwMask = CFM_CHARSET | CFM_BOLD | CFM_FACE | CFM_ITALIC | CFM_SIZE | CFM_STRIKEOUT | CFM_UNDERLINE | CFM_COLOR; // Clear all the bits we are about to set. We restore any bits we can not get from the LOGFONT using dwOldEffects. pcf->dwEffects = CFE_AUTOCOLOR; pcf->dwEffects |= (lf.lfWeight >= 700) ? CFE_BOLD : 0; pcf->dwEffects |= (lf.lfItalic) ? CFE_ITALIC : 0; pcf->dwEffects |= (lf.lfStrikeOut) ? CFE_STRIKEOUT : 0; pcf->dwEffects |= (lf.lfUnderline) ? CFE_UNDERLINE : 0; pcf->yHeight = -(int)((1440*lf.lfHeight)/yPerInch); // I think this is he conversion? pcf->crTextColor = 0; // use autocolor pcf->bCharSet = lf.lfCharSet; pcf->bPitchAndFamily = lf.lfPitchAndFamily; StrCpyN(pcf->szFaceName, lf.lfFaceName, LF_FACESIZE - 1); return S_OK; } static const HELPMAP g_rgCtxMapSendCharSetMap[] = { {idcLangCombo, 50910}, {IDC_RTL_MSG_DIR_CHECK, 50912}, {IDC_ENGLISH_HDR_CHECK, 50915}, {0, 0} }; INT_PTR CALLBACK SetSendCharsetDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { HWND hWndCombo; ULONG i ; ULONG cchXlated ; UINT uiCodePage; CHAR szBuffer[MIMEINFO_NAME_MAX]; UINT uiACP = GetACP(); INETCSETINFO CsetInfo ; int index = 0; int SelIndex = 0; hWndCombo = GetDlgItem(hwndDlg, idcLangCombo); switch (msg) { case WM_INITDIALOG: { CenterDialog(hwndDlg); // Init global CPs structire, if it was not inited yet if ( g_pMimeCPInfo == NULL) _InitMultiLanguage(); // Get information about current default charset MimeOleGetCharsetInfo(g_hDefaultCharsetForMail,&CsetInfo); uiCodePage = CsetInfo.cpiInternet ; // Fill combo box with available charsets for Send for (i = 0; i < g_cMimeCPInfoCount ; i++) { if(!fCheckEncodeMenu(g_pMimeCPInfo[i].uiCodePage, FALSE)) continue ; cchXlated = WideCharToMultiByte(uiACP, 0, g_pMimeCPInfo[i].wszDescription, -1, szBuffer, ARRAYSIZE(szBuffer), NULL, NULL); szBuffer[ARRAYSIZE(szBuffer) - 1] = '\0'; //better safe than not null-terminated index = (int) SendMessage(hWndCombo, CB_ADDSTRING, 0, ((LPARAM) szBuffer)); if(index != CB_ERR) SendMessage(hWndCombo, CB_SETITEMDATA, index, ((LPARAM) (g_pMimeCPInfo[i].uiCodePage))); if(g_pMimeCPInfo[i].uiCodePage == uiCodePage) { EnableWindow(GetDlgItem(hwndDlg, IDC_RTL_MSG_DIR_CHECK), ((g_pMimeCPInfo[i].uiFamilyCodePage == 1255) || (g_pMimeCPInfo[i].uiFamilyCodePage == 1256) || (g_pMimeCPInfo[i].uiFamilyCodePage == 1200))); } } //Set current selection to default charset, we can't detect this in the above //loop because the combobox sorting may change the index for (i = 0; i < g_cMimeCPInfoCount ; i++) { if(uiCodePage == (UINT)SendMessage(hWndCombo, CB_GETITEMDATA, i, NULL)) { SelIndex = i; break; } } SendMessage(hWndCombo, CB_SETCURSEL, SelIndex, 0L); CheckDlgButton(hwndDlg, IDC_ENGLISH_HDR_CHECK, DwGetOption(OPT_HARDCODEDHDRS) ? BST_CHECKED:BST_UNCHECKED); CheckDlgButton(hwndDlg, IDC_RTL_MSG_DIR_CHECK, DwGetOption(OPT_RTL_MSG_DIR) ? BST_CHECKED:BST_UNCHECKED); break ; } case WM_COMMAND: { int id = GET_WM_COMMAND_ID(wParam, lParam); HCHARSET hCharset = NULL ; if ((id == idcLangCombo) && (GET_WM_COMMAND_CMD(wParam,lParam) == CBN_SELCHANGE)) { index = (int) SendMessage(hWndCombo, CB_GETCURSEL, 0, 0L); if(index != CB_ERR) { uiCodePage = (UINT) SendMessage(hWndCombo, CB_GETITEMDATA, index, 0); if(((int) uiCodePage) != CB_ERR) { for (i = 0; i < g_cMimeCPInfoCount ; i++) { if(g_pMimeCPInfo[i].uiCodePage == uiCodePage) { EnableWindow(GetDlgItem(hwndDlg, IDC_RTL_MSG_DIR_CHECK), ((g_pMimeCPInfo[i].uiFamilyCodePage == 1255) || (g_pMimeCPInfo[i].uiFamilyCodePage == 1256) || (g_pMimeCPInfo[i].uiFamilyCodePage == 1200))); } } } } } else if (id == IDCANCEL || id == IDOK ) { if (id == IDOK ) { index = (int) SendMessage(hWndCombo, CB_GETCURSEL, 0, 0L); if(index != CB_ERR) { uiCodePage = (UINT) SendMessage(hWndCombo, CB_GETITEMDATA, index, 0); if(((int) uiCodePage) != CB_ERR) { AthUserSetValue(c_szRegPathMail, c_szDefaultCodePage, REG_DWORD, (LPBYTE)&uiCodePage, sizeof(uiCodePage)); g_hDefaultCharsetForMail = GetMimeCharsetFromCodePage(uiCodePage ); WriteSendMailDefaultCharset(); } } SetDwOption(OPT_HARDCODEDHDRS, IsDlgButtonChecked(hwndDlg, IDC_ENGLISH_HDR_CHECK), NULL, 0); SetDwOption(OPT_RTL_MSG_DIR, (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_RTL_MSG_DIR_CHECK)) && IsDlgButtonChecked(hwndDlg, IDC_RTL_MSG_DIR_CHECK)), NULL, 0); } EndDialog(hwndDlg, id); return TRUE; } break ; } case WM_HELP: case WM_CONTEXTMENU: return OnContextHelp(hwndDlg, msg, wParam, lParam, g_rgCtxMapSendCharSetMap); default: break ; } return FALSE; } BOOL SetSendCharSetDlg(HWND hwndDlg) { DialogBox(g_hLocRes, MAKEINTRESOURCE(iddSendIntlSetting), hwndDlg, SetSendCharsetDlgProc) ; return TRUE ; }