windows-nt/Source/XPSP1/NT/shell/ext/mlang/mllbcons.h
2020-09-26 16:20:57 +08:00

270 lines
6.5 KiB
C++

// MLLBCons.h : Declaration of the CMLLBCons
#ifndef __MLLBCONS_H_
#define __MLLBCONS_H_
#include "mlatl.h"
class CMultiLanguage;
/////////////////////////////////////////////////////////////////////////////
// CMLLBCons
class ATL_NO_VTABLE CMLLBCons :
public CComTearOffObjectBase<CMultiLanguage>,
public IMLangLineBreakConsole
{
public:
CMLLBCons(void)
{
DllAddRef();
m_pMLStrClass = NULL;
}
~CMLLBCons(void)
{
if (m_pMLStrClass)
m_pMLStrClass->Release();
DllRelease();
}
DECLARE_NO_REGISTRY()
BEGIN_COM_MAP(CMLLBCons)
COM_INTERFACE_ENTRY(IMLangLineBreakConsole)
END_COM_MAP()
public:
// IMLangLineBreakConsole
STDMETHOD(BreakLineML)(/*[in]*/ IMLangString* pSrcMLStr, /*[in]*/ long lSrcPos, /*[in]*/ long lSrcLen, /*[in]*/ long cMinColumns, /*[in]*/ long cMaxColumns, /*[out]*/ long* plLineLen, /*[out]*/ long* plSkipLen);
STDMETHOD(BreakLineW)(/*[in]*/ LCID locale, /*[in, size_is(cchSrc)]*/ const WCHAR* pszSrc, /*[in]*/ long cchSrc, /*[in]*/ long cMaxColumns, /*[out]*/ long* pcchLine, /*[out]*/ long* pcchSkip);
STDMETHOD(BreakLineA)(/*[in]*/ LCID locale, /*[in]*/ UINT uCodePage, /*[in, size_is(cchSrc)]*/ const CHAR* pszSrc, /*[in]*/ long cchSrc, /*[in]*/ long cMaxColumns, /*[out]*/ long* pcchLine, /*[out]*/ long* pcchSkip);
protected:
template <DWORD INFOTYPE, int CACHESIZE>
class CCharType
{
public:
#ifdef ASTRIMPL
inline CCharType(void);
#else
inline CCharType(LCID locale);
#endif
inline ~CCharType(void);
inline void Flush(void);
#ifdef ASTRIMPL
WORD GetCharType(IMLangString* pMLStr, long lPos, long lLen, HRESULT* phr = NULL);
#else
WORD GetCharType(LPCWSTR psz, int cch);
#endif
protected:
LPWORD m_pwBuf;
#ifdef ASTRIMPL
IMLangStringAStr* m_pMLStrAStr;
long m_lPos;
long m_lLen;
#else
LPSTR m_pszConv;
LPCWSTR m_psz;
int m_cch;
LCID m_locale;
UINT m_uCodePage;
#endif
WORD m_wHalfWidth;
};
HRESULT PrepareMLStrClass(void)
{
if (m_pMLStrClass)
return S_OK;
else
return ::_Module.GetClassObject(CLSID_CMLangString, IID_IClassFactory, (void**)&m_pMLStrClass);
}
IClassFactory* m_pMLStrClass;
};
template <DWORD INFOTYPE, int CACHESIZE>
#ifdef ASTRIMPL
CMLLBCons::CCharType<INFOTYPE, CACHESIZE>::CCharType(void)
#else
CMLLBCons::CCharType<INFOTYPE, CACHESIZE>::CCharType(LCID locale)
#endif
{
#ifndef ASTRIMPL
TCHAR szCodePage[8];
#endif
m_pwBuf = NULL;
#ifdef ASTRIMPL
m_pMLStrAStr = NULL;
// TODO: Set m_wHaldWidth here.
m_wHalfWidth = 0;
#else
m_pszConv = NULL;
m_locale = locale;
::GetLocaleInfo(m_locale, LOCALE_IDEFAULTANSICODEPAGE, szCodePage, ARRAYSIZE(szCodePage));
m_uCodePage = _ttoi(szCodePage);
CPINFO cpi;
::GetCPInfo(m_uCodePage, &cpi);
m_wHalfWidth = (cpi.LeadByte[0]) ? 0 : C3_HALFWIDTH;
#endif
}
template <DWORD INFOTYPE, int CACHESIZE>
CMLLBCons::CCharType<INFOTYPE, CACHESIZE>::~CCharType(void)
{
if (m_pwBuf)
delete[] m_pwBuf;
#ifdef ASTRIMPL
if (m_pMLStrAStr)
m_pMLStrAStr->Release();
#else
if (m_pszConv)
delete[] m_pszConv;
#endif
}
template <DWORD INFOTYPE, int CACHESIZE>
void CMLLBCons::CCharType<INFOTYPE, CACHESIZE>::Flush(void)
{
#ifdef ASTRIMPL
m_lPos = 0;
m_lLen = 0;
#else
m_psz = NULL;
m_cch = 0;
#endif
}
template <DWORD INFOTYPE, int CACHESIZE>
#ifdef ASTRIMPL
WORD CMLLBCons::CCharType<INFOTYPE, CACHESIZE>::GetCharType(IMLangString* pMLStr, long lPos, long lLen, HRESULT* phr)
#else
WORD CMLLBCons::CCharType<INFOTYPE, CACHESIZE>::GetCharType(LPCWSTR psz, int cch)
#endif
{
#ifdef ASTRIMPL
if (lPos >= m_lPos + m_lLen || lPos + lLen <= m_lPos)
#else
if (psz < m_psz || psz >= m_psz + m_cch)
#endif
{
#ifdef ASTRIMPL
HRESULT hr;
#endif
LPWORD pwCharType;
#ifdef ASTRIMPL
WORD wCharType;
CHAR* psz;
long cch;
LCID locale;
UINT uCodePage;
if (m_pMLStrAStr)
{
m_pMLStrAStr->Release();
m_pMLStrAStr = NULL;
}
if (SUCCEEDED(hr = pMLStr->QueryInterface(IID_IMLangStringAStr, (void**)&m_pMLStrAStr)))
{
if (!m_pwBuf)
m_pwBuf = new WORD[CACHESIZE];
if (m_pwBuf)
{
pwCharType = m_pwBuf;
cch = CACHESIZE;
}
else
{
pwCharType = &wCharType;
cch = 1;
}
lLen = min(lLen, cch);
if (SUCCEEDED(hr = m_pMLStrAStr->GetLocale(lPos, lLen, &locale, NULL, &lLen)) &&
SUCCEEDED(hr = ::LocaleToCodePage(locale, &uCodePage)) &&
SUCCEEDED(hr = m_pMLStrAStr->LockAStr(lPos, lLen, MLSTR_READ, uCodePage, 0, NULL, &psz, &cch, NULL)))
{
if (!::GetStringTypeExA(locale, INFOTYPE, psz, cch, pwCharType))
hr = E_FAIL; // NLS failed
ASSIGN_IF_FAILED(hr, m_pMLStrAStr->UnlockAStr(psz, 0, NULL, NULL));
}
}
if (phr)
*phr = hr;
if (SUCCEEDED(hr))
{
m_lPos = lPos;
m_lLen = lLen;
return pwCharType[0] | m_wHalfWidth;
}
else
{
m_lPos = 0;
m_lLen = 0;
return 0 | m_wHalfWidth;
}
#else
LPSTR pszConv;
WORD wCharType = 0;
CHAR szTemp[2];
if (!m_pwBuf)
m_pwBuf = new WORD[CACHESIZE];
if (m_pwBuf)
{
pwCharType = m_pwBuf;
cch = min(cch, CACHESIZE);
}
else
{
pwCharType = &wCharType;
cch = 1;
}
if (!m_pszConv)
m_pszConv = new CHAR[CACHESIZE * 2];
if (m_pszConv)
{
pszConv = m_pszConv;
}
else
{
pszConv = szTemp;
cch = 1;
}
if (m_pwBuf && m_pszConv)
{
m_psz = psz;
m_cch = cch;
}
int cchTemp = ::WideCharToMultiByte(m_uCodePage, 0, psz, cch, pszConv, CACHESIZE * 2, NULL, NULL);
::GetStringTypeExA(m_locale, INFOTYPE, pszConv, cchTemp, pwCharType);
return pwCharType[0] | m_wHalfWidth;
#endif
}
else
{
#ifdef ASTRIMPL
return m_pwBuf[lPos - m_lPos] | m_wHalfWidth;
#else
return m_pwBuf[psz - m_psz] | m_wHalfWidth;
#endif
}
}
#endif //__MLLBCONS_H_