280 lines
7.3 KiB
C++
280 lines
7.3 KiB
C++
//
|
|
// pstore.cpp
|
|
//
|
|
// CCustomPropertyStore implementation, ITfPropertyStore example.
|
|
//
|
|
|
|
#include "globals.h"
|
|
#include "pstore.h"
|
|
#include "mark.h"
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ctor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CCustomPropertyStore::CCustomPropertyStore()
|
|
{
|
|
// assign some arbitrary state to this object, for demonstration purposes
|
|
_dwState = GetTickCount();
|
|
|
|
DllAddRef();
|
|
_cRef = 1;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// dtor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CCustomPropertyStore::~CCustomPropertyStore()
|
|
{
|
|
DllRelease();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// QueryInterface
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCustomPropertyStore::QueryInterface(REFIID riid, void **ppvObj)
|
|
{
|
|
if (ppvObj == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
*ppvObj = NULL;
|
|
|
|
if (IsEqualIID(riid, IID_IUnknown) ||
|
|
IsEqualIID(riid, IID_ITfPropertyStore))
|
|
{
|
|
*ppvObj = (ITfPropertyStore *)this;
|
|
}
|
|
|
|
if (*ppvObj)
|
|
{
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// AddRef
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(ULONG) CCustomPropertyStore::AddRef()
|
|
{
|
|
return ++_cRef;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Release
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(ULONG) CCustomPropertyStore::Release()
|
|
{
|
|
LONG cr = --_cRef;
|
|
|
|
assert(_cRef >= 0);
|
|
|
|
if (_cRef == 0)
|
|
{
|
|
delete this;
|
|
}
|
|
|
|
return cr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetType
|
|
//
|
|
// Returns the GUID of the property this store is assigned to.
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCustomPropertyStore::GetType(GUID *pguidType)
|
|
{
|
|
*pguidType = c_guidCustomProperty;
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetDataType
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCustomPropertyStore::GetDataType(DWORD *pdwReserved)
|
|
{
|
|
// this method is reserved, pdwReserved must be set 0
|
|
*pdwReserved = 0;
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetData
|
|
//
|
|
// Returns the data held by this store.
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCustomPropertyStore::GetData(VARIANT *pvarValue)
|
|
{
|
|
pvarValue->vt = VT_I4; // dword value for this store
|
|
pvarValue->lVal = _dwState;
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnTextUpdated
|
|
//
|
|
// Called by TSF when the text covered by this store is modified.
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCustomPropertyStore::OnTextUpdated(DWORD dwFlags, ITfRange *pRangeNew, BOOL *pfAccept)
|
|
{
|
|
// we will throw away this store (give up) anytime the text is modified.
|
|
// If we did set pfAccept TRUE, the store would be maintained.
|
|
*pfAccept = FALSE;
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Shrink
|
|
//
|
|
// Called when the text covered by this store is truncated.
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCustomPropertyStore::Shrink(ITfRange *pRangeNew, BOOL *pfFree)
|
|
{
|
|
// give up and free this store
|
|
*pfFree = TRUE;
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Divide
|
|
//
|
|
// Called when text covered by the store is deleted, such that the store is
|
|
// split in two. We have the option of freeing the store, or keeping the
|
|
// store which moves to cover just pRangeThis (the leftmost text) in which
|
|
// case we must provide a new store for the rightmost text as well.
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCustomPropertyStore::Divide(ITfRange *pRangeThis, ITfRange *pRangeNew, ITfPropertyStore **ppPropertyStore)
|
|
{
|
|
// just give up
|
|
// a NULL ppPropertyStore tells TSF to release this store
|
|
*ppPropertyStore = NULL;
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Clone
|
|
//
|
|
// Return a new store with a copy of this store's state.
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCustomPropertyStore::Clone(ITfPropertyStore **ppCloneOut)
|
|
{
|
|
CCustomPropertyStore *pClone;
|
|
|
|
*ppCloneOut = NULL;
|
|
|
|
if ((pClone = new CCustomPropertyStore) == NULL)
|
|
return E_OUTOFMEMORY;
|
|
|
|
pClone->_dwState = _dwState;
|
|
|
|
*ppCloneOut = pClone;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetPropertyRangeCreator
|
|
//
|
|
// Returns the owning text service. Used by TSF during Unserialization.
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCustomPropertyStore::GetPropertyRangeCreator(CLSID *pclsid)
|
|
{
|
|
*pclsid = c_clsidMarkTextService;
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Serialize
|
|
//
|
|
// Copy this store's state to a binary stream. This stream will later be returned
|
|
// to this text service to recreate the store in a later session.
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCustomPropertyStore::Serialize(IStream *pStream, ULONG *pcb)
|
|
{
|
|
return pStream->Write(&_dwState, sizeof(_dwState), pcb);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// IsStoreSerializable
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CMarkTextService::IsStoreSerializable(REFGUID guidProperty, ITfRange *pRange, ITfPropertyStore *pPropertyStore, BOOL *pfSerializable)
|
|
{
|
|
// we don't have any complicated logic, we'll let all our custom property values be serialized
|
|
*pfSerializable = IsEqualGUID(guidProperty, c_guidCustomProperty);
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// CreatePropertyStore
|
|
//
|
|
// Unserializes a custom property.
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CMarkTextService::CreatePropertyStore(REFGUID guidProperty, ITfRange *pRange, ULONG cb, IStream *pStream, ITfPropertyStore **ppStore)
|
|
{
|
|
CCustomPropertyStore *pStore;
|
|
DWORD dwState;
|
|
|
|
*ppStore = NULL;
|
|
|
|
if (!IsEqualGUID(guidProperty, c_guidCustomProperty))
|
|
return E_INVALIDARG;
|
|
|
|
if (cb != sizeof(DWORD))
|
|
return E_INVALIDARG;
|
|
|
|
if ((pStore = new CCustomPropertyStore) == NULL)
|
|
return E_OUTOFMEMORY;
|
|
|
|
if (pStream->Read(&dwState, sizeof(DWORD), &cb) != S_OK || cb != sizeof(DWORD))
|
|
{
|
|
pStore->Release();
|
|
return E_FAIL;
|
|
}
|
|
|
|
pStore->_SetState(dwState);
|
|
*ppStore = pStore;
|
|
|
|
return S_OK;
|
|
}
|