Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1413 lines
43 KiB

// =================================================================================
// 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 <inetreg.h>
#include <mlang.h>
#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<len; i++)
{
n = -1;
ch = pwszColor[i];
if(ch >= 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 ;
}