|
|
//
// dap.cpp
//
// ITfDisplayAttributeProvider implementation.
//
#include "globals.h"
#include "mark.h"
static const TCHAR c_szAttributeInfoKey[] = TEXT("Software\\Mark Text Service"); static const TCHAR c_szAttributeInfoValueName[] = TEXT("DisplayAttr");
// this text service has only a single display attribute so we'll use
// a single static object.
class CDisplayAttributeInfo : public ITfDisplayAttributeInfo { public: // IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj); STDMETHODIMP_(ULONG) AddRef(void) { return DllAddRef(); } STDMETHODIMP_(ULONG) Release(void) { return DllRelease(); }
// ITfDisplayAttributeInfo
STDMETHODIMP GetGUID(GUID *pguid); STDMETHODIMP GetDescription(BSTR *pbstrDesc); STDMETHODIMP GetAttributeInfo(TF_DISPLAYATTRIBUTE *ptfDisplayAttr); STDMETHODIMP SetAttributeInfo(const TF_DISPLAYATTRIBUTE *ptfDisplayAttr); STDMETHODIMP Reset();
private: static const TF_DISPLAYATTRIBUTE _c_DefaultDisplayAttribute; } g_DisplayAttributeInfo;
const TF_DISPLAYATTRIBUTE CDisplayAttributeInfo::_c_DefaultDisplayAttribute = { { TF_CT_COLORREF, RGB(255, 0, 0) }, // text color
{ TF_CT_NONE, 0 }, // background color (TF_CT_NONE => app default)
TF_LS_SOLID, // underline style
FALSE, // underline boldness
{ TF_CT_COLORREF, RGB(255, 0, 0) }, // underline color
TF_ATTR_INPUT // attribute info
};
//+---------------------------------------------------------------------------
//
// QueryInterface
//
//----------------------------------------------------------------------------
STDAPI CDisplayAttributeInfo::QueryInterface(REFIID riid, void **ppvObj) { if (ppvObj == NULL) return E_INVALIDARG;
*ppvObj = NULL;
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfDisplayAttributeInfo)) { *ppvObj = (ITfDisplayAttributeInfo *)this; }
if (*ppvObj) { AddRef(); return S_OK; }
return E_NOINTERFACE; }
//+---------------------------------------------------------------------------
//
// GetGUID
//
//----------------------------------------------------------------------------
STDAPI CDisplayAttributeInfo::GetGUID(GUID *pguid) { if (pguid == NULL) return E_INVALIDARG;
*pguid = c_guidMarkDisplayAttribute;
return S_OK; }
//+---------------------------------------------------------------------------
//
// GetDescription
//
//----------------------------------------------------------------------------
STDAPI CDisplayAttributeInfo::GetDescription(BSTR *pbstrDesc) { BSTR bstrDesc;
if (pbstrDesc == NULL) return E_INVALIDARG;
*pbstrDesc = NULL;
if ((bstrDesc = SysAllocString(L"Mark Display Attribute")) == NULL) return E_OUTOFMEMORY;
*pbstrDesc = bstrDesc;
return S_OK; }
//+---------------------------------------------------------------------------
//
// GetAttributeInfo
//
//----------------------------------------------------------------------------
STDAPI CDisplayAttributeInfo::GetAttributeInfo(TF_DISPLAYATTRIBUTE *ptfDisplayAttr) { HKEY hKeyAttributeInfo; LONG lResult; DWORD cbData;
if (ptfDisplayAttr == NULL) return E_INVALIDARG;
lResult = E_FAIL;
if (RegOpenKeyEx(HKEY_CURRENT_USER, c_szAttributeInfoKey, 0, KEY_READ, &hKeyAttributeInfo) == ERROR_SUCCESS) { cbData = sizeof(*ptfDisplayAttr);
lResult = RegQueryValueEx(hKeyAttributeInfo, c_szAttributeInfoValueName, NULL, NULL, (LPBYTE)ptfDisplayAttr, &cbData);
RegCloseKey(hKeyAttributeInfo); }
if (lResult != ERROR_SUCCESS || cbData != sizeof(*ptfDisplayAttr)) { // go with the defaults
*ptfDisplayAttr = _c_DefaultDisplayAttribute; }
return S_OK; }
//+---------------------------------------------------------------------------
//
// SetAttributeInfo
//
//----------------------------------------------------------------------------
STDAPI CDisplayAttributeInfo::SetAttributeInfo(const TF_DISPLAYATTRIBUTE *ptfDisplayAttr) { HKEY hKeyAttributeInfo; LONG lResult;
lResult = RegCreateKeyEx(HKEY_CURRENT_USER, c_szAttributeInfoKey, 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKeyAttributeInfo, NULL);
if (lResult != ERROR_SUCCESS) return E_FAIL;
lResult = RegSetValueEx(hKeyAttributeInfo, c_szAttributeInfoValueName, 0, REG_BINARY, (const BYTE *)ptfDisplayAttr, sizeof(*ptfDisplayAttr));
RegCloseKey(hKeyAttributeInfo);
return (lResult == ERROR_SUCCESS) ? S_OK : E_FAIL; }
//+---------------------------------------------------------------------------
//
// Reset
//
//----------------------------------------------------------------------------
STDAPI CDisplayAttributeInfo::Reset() { return SetAttributeInfo(&_c_DefaultDisplayAttribute); }
class CEnumDisplayAttributeInfo : public IEnumTfDisplayAttributeInfo { public: CEnumDisplayAttributeInfo(); ~CEnumDisplayAttributeInfo();
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj); STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void);
// IEnumTfDisplayAttributeInfo
STDMETHODIMP Clone(IEnumTfDisplayAttributeInfo **ppEnum); STDMETHODIMP Next(ULONG ulCount, ITfDisplayAttributeInfo **rgInfo, ULONG *pcFetched); STDMETHODIMP Reset(); STDMETHODIMP Skip(ULONG ulCount);
private: LONG _iIndex; // next display attribute to enum
LONG _cRef; // COM ref count
};
//+---------------------------------------------------------------------------
//
// ctor
//
//----------------------------------------------------------------------------
CEnumDisplayAttributeInfo::CEnumDisplayAttributeInfo() { DllAddRef();
_iIndex = 0; _cRef = 1; }
//+---------------------------------------------------------------------------
//
// dtor
//
//----------------------------------------------------------------------------
CEnumDisplayAttributeInfo::~CEnumDisplayAttributeInfo() { DllRelease(); }
//+---------------------------------------------------------------------------
//
// QueryInterface
//
//----------------------------------------------------------------------------
STDAPI CEnumDisplayAttributeInfo::QueryInterface(REFIID riid, void **ppvObj) { if (ppvObj == NULL) return E_INVALIDARG;
*ppvObj = NULL;
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IEnumTfDisplayAttributeInfo)) { *ppvObj = (IEnumTfDisplayAttributeInfo *)this; }
if (*ppvObj) { AddRef(); return S_OK; }
return E_NOINTERFACE; }
//+---------------------------------------------------------------------------
//
// AddRef
//
//----------------------------------------------------------------------------
STDAPI_(ULONG) CEnumDisplayAttributeInfo::AddRef() { return ++_cRef; }
//+---------------------------------------------------------------------------
//
// Release
//
//----------------------------------------------------------------------------
STDAPI_(ULONG) CEnumDisplayAttributeInfo::Release() { LONG cr = --_cRef;
assert(_cRef >= 0);
if (_cRef == 0) { delete this; }
return cr; }
//+---------------------------------------------------------------------------
//
// Clone
//
// Returns a copy of the object.
//----------------------------------------------------------------------------
STDAPI CEnumDisplayAttributeInfo::Clone(IEnumTfDisplayAttributeInfo **ppEnum) { CEnumDisplayAttributeInfo *pClone;
if (ppEnum == NULL) return E_INVALIDARG;
*ppEnum = NULL;
if ((pClone = new CEnumDisplayAttributeInfo) == NULL) return E_OUTOFMEMORY;
// the clone should match this object's state
pClone->_iIndex = _iIndex;
*ppEnum = pClone;
return S_OK; }
//+---------------------------------------------------------------------------
//
// Next
//
// Returns an array of display attribute info objects supported by this service.
//----------------------------------------------------------------------------
STDAPI CEnumDisplayAttributeInfo::Next(ULONG ulCount, ITfDisplayAttributeInfo **rgInfo, ULONG *pcFetched) { ULONG cFetched;
if (pcFetched == NULL) { // technically this is only legal if ulCount == 1, but we won't check
pcFetched = &cFetched; }
*pcFetched = 0;
if (ulCount == 0) return S_OK;
// we only have a single display attribute to enum, so this is trivial
if (_iIndex == 0) { *rgInfo = &g_DisplayAttributeInfo; (*rgInfo)->AddRef(); *pcFetched = 1; _iIndex++; }
return (*pcFetched == ulCount) ? S_OK : S_FALSE; }
//+---------------------------------------------------------------------------
//
// Reset
//
// Resets the enumeration.
//----------------------------------------------------------------------------
STDAPI CEnumDisplayAttributeInfo::Reset() { _iIndex = 0; return S_OK; }
//+---------------------------------------------------------------------------
//
// Skip
//
// Skips past objects in the enumeration.
//----------------------------------------------------------------------------
STDAPI CEnumDisplayAttributeInfo::Skip(ULONG ulCount) { // we have only a single item to enum
// so we can just skip it and avoid any overflow errors
if (ulCount > 0 && _iIndex == 0) { _iIndex++; } return S_OK; }
//+---------------------------------------------------------------------------
//
// EnumDisplayAttributeInfo
//
//----------------------------------------------------------------------------
STDAPI CMarkTextService::EnumDisplayAttributeInfo(IEnumTfDisplayAttributeInfo **ppEnum) { CEnumDisplayAttributeInfo *pAttributeEnum;
if (ppEnum == NULL) return E_INVALIDARG;
*ppEnum = NULL;
if ((pAttributeEnum = new CEnumDisplayAttributeInfo) == NULL) return E_OUTOFMEMORY;
*ppEnum = pAttributeEnum;
return S_OK; }
//+---------------------------------------------------------------------------
//
// GetDisplayAttributeInfo
//
//----------------------------------------------------------------------------
STDAPI CMarkTextService::GetDisplayAttributeInfo(REFGUID guidInfo, ITfDisplayAttributeInfo **ppInfo) { if (ppInfo == NULL) return E_INVALIDARG;
*ppInfo = NULL;
// unsupported GUID?
if (!IsEqualGUID(guidInfo, c_guidMarkDisplayAttribute)) return E_INVALIDARG;
*ppInfo = &g_DisplayAttributeInfo; (*ppInfo)->AddRef();
return S_OK; }
|