2025-11-28 00:35:46 +09:00

350 lines
12 KiB
C++

/**************************************************************************
THIS CODE AND INFORMATION IS PROVIDED 'AS IS' WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright 2001 Microsoft Corporation. All Rights Reserved.
**************************************************************************/
/**************************************************************************
File: Persist.cpp
Description: CTSFEditWnd::_Save() and _Load() implementation
**************************************************************************/
/**************************************************************************
#include statements
**************************************************************************/
#include "TSFEdit.h"
#include "PropLdr.h"
/**************************************************************************
global variables and definitions
**************************************************************************/
/**************************************************************************
local function prototypes
**************************************************************************/
#define BLOCK_SIZE 256
void CTSFEditWnd::_SaveToFile(LPTSTR pszFile)
{
if(pszFile)
{
HANDLE hFile;
hFile = CreateFile( pszFile,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(INVALID_HANDLE_VALUE != hFile)
{
IStream *pStream;
//create a stream on global memory
if(SUCCEEDED(CreateStreamOnHGlobal(NULL, TRUE, &pStream)))
{
LARGE_INTEGER li;
_Save(pStream);
//initialize the file
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
SetEndOfFile(hFile);
//set the stream pointer to the start of the stream
li.QuadPart = 0;
pStream->Seek(li, STREAM_SEEK_SET, NULL);
//write the contents of the stream to the file
BYTE buffer[BLOCK_SIZE];
ULONG uRead;
HRESULT hr;
uRead = 0;
hr = pStream->Read(buffer, BLOCK_SIZE, &uRead);
while(uRead > 0)
{
DWORD dwWritten;
WriteFile(hFile, buffer, uRead, &dwWritten, NULL);
uRead = 0;
hr = pStream->Read(buffer, BLOCK_SIZE, &uRead);
}
pStream->Release();
}
CloseHandle(hFile);
}
}
}
/**************************************************************************
CTSFEditWnd::_Save()
**************************************************************************/
void CTSFEditWnd::_Save(IStream *pStream)
{
if(pStream)
{
HRESULT hr;
//write the plain UNICODE text into the stream
LPWSTR pwsz;
LONG cch;
ULONG uWritten;
LARGE_INTEGER li;
ULONG uSize;
//set the stream pointer to the start of the stream
li.QuadPart = 0;
pStream->Seek(li, STREAM_SEEK_SET, NULL);
//get the text
if(SUCCEEDED(_GetText(&pwsz, &cch)))
{
TF_PERSISTENT_PROPERTY_HEADER_ACP PropHeader;
//write the size, in BYTES, of the text
uSize = cch * sizeof(WCHAR);
hr = pStream->Write(&uSize, sizeof(ULONG), &uWritten);
//write the text, including the NULL_terminator, into the stream
hr = pStream->Write(pwsz, uSize, &uWritten);
//free the memory allocated by _GetText
GlobalFree(pwsz);
//enumerate the properties in the context
IEnumTfProperties *pEnumProps;
hr = m_pContext->EnumProperties(&pEnumProps);
if(SUCCEEDED(hr))
{
ITfProperty *pProp;
ULONG uFetched;
while(SUCCEEDED(pEnumProps->Next(1, &pProp, &uFetched)) && uFetched)
{
//enumerate all the ranges that contain the property
IEnumTfRanges *pEnumRanges;
hr = pProp->EnumRanges(m_EditCookie, &pEnumRanges, NULL);
if(SUCCEEDED(hr))
{
IStream *pTempStream;
//create a temporary stream to write the property data to
hr = CreateStreamOnHGlobal(NULL, TRUE, &pTempStream);
if(SUCCEEDED(hr))
{
ITfRange *pRange;
while(SUCCEEDED(pEnumRanges->Next(1, &pRange, &uFetched)) && uFetched)
{
//reset the temporary stream's pointer
li.QuadPart = 0;
pTempStream->Seek(li, STREAM_SEEK_SET, NULL);
//get the property header and data for the range
hr = m_pServices->Serialize(pProp, pRange, &PropHeader, pTempStream);
/*
Write the property header into the primary stream.
The header also contains the size of the property
data.
*/
hr = pStream->Write(&PropHeader, sizeof(TF_PERSISTENT_PROPERTY_HEADER_ACP), &uWritten);
//reset the temporary stream's pointer
li.QuadPart = 0;
pTempStream->Seek(li, STREAM_SEEK_SET, NULL);
//copy the property data from the temporary stream into the primary stream
ULARGE_INTEGER uli;
uli.QuadPart = PropHeader.cb;
hr = pTempStream->CopyTo(pStream, uli, NULL, NULL);
pRange->Release();
}
pTempStream->Release();
}
pEnumRanges->Release();
}
pProp->Release();
}
pEnumProps->Release();
}
//write a property header with zero size and guid into the stream as a terminator
ZeroMemory(&PropHeader, sizeof(TF_PERSISTENT_PROPERTY_HEADER_ACP));
hr = pStream->Write(&PropHeader, sizeof(TF_PERSISTENT_PROPERTY_HEADER_ACP), &uWritten);
}
}
}
/**************************************************************************
CTSFEditWnd::_LoadFromFile()
**************************************************************************/
void CTSFEditWnd::_LoadFromFile(LPTSTR pszFile)
{
if(pszFile)
{
HANDLE hFile;
hFile = CreateFile( pszFile,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(INVALID_HANDLE_VALUE != hFile)
{
IStream *pStream;
//create a stream on global memory
if(SUCCEEDED(CreateStreamOnHGlobal(NULL, TRUE, &pStream)))
{
//read the contents of the file into the stream
LARGE_INTEGER li;
//set the stream pointer to the start of the stream
li.QuadPart = 0;
pStream->Seek(li, STREAM_SEEK_SET, NULL);
//write the contents of the stream to the file
BYTE buffer[BLOCK_SIZE];
ULONG uRead;
HRESULT hr;
uRead = 0;
ReadFile(hFile, buffer, BLOCK_SIZE, &uRead, NULL);
while(uRead > 0)
{
ULONG uWritten;
hr = pStream->Write(buffer, uRead, &uWritten);
uRead = 0;
ReadFile(hFile, buffer, BLOCK_SIZE, &uRead, NULL);
}
_Load(pStream);
pStream->Release();
}
CloseHandle(hFile);
}
}
}
/**************************************************************************
CTSFEditWnd::_Load()
**************************************************************************/
void CTSFEditWnd::_Load(IStream *pStream)
{
if(NULL == pStream)
{
return;
}
//can't do this if someone has a lock
if(_IsLocked(TS_LF_READ))
{
return;
}
_ClearText();
HRESULT hr;
ULONG uRead;
LARGE_INTEGER li;
ULONG uSize;
//set the stream pointer to the start of the stream
li.QuadPart = 0;
pStream->Seek(li, STREAM_SEEK_SET, NULL);
//get the size of the text, in BYTES. This is the first ULONG in the stream
hr = pStream->Read(&uSize, sizeof(ULONG), &uRead);
if(SUCCEEDED(hr) && (sizeof(ULONG) == uRead))
{
LPWSTR pwsz;
//allocate a buffer for the text plus one NULL character
pwsz = (LPWSTR)GlobalAlloc(GPTR, uSize + sizeof(WCHAR));
if(NULL != pwsz)
{
//get the plain UNICODE text from the stream
hr = pStream->Read(pwsz, uSize, &uRead);
if(SUCCEEDED(hr) && (uSize == uRead))
{
TF_PERSISTENT_PROPERTY_HEADER_ACP PropHeader;
//put the text into the edit control, but don't send a change notification
BOOL fOldNotify = m_fNotify;
m_fNotify = FALSE;
SetWindowTextW(m_hwndEdit, pwsz);
m_fNotify = fOldNotify;
/*
Read each property header and property data from the stream. The
list of properties is terminated by a TF_PERSISTENT_PROPERTY_HEADER_ACP
structure with a cb member of zero.
*/
hr = pStream->Read(&PropHeader, sizeof(TF_PERSISTENT_PROPERTY_HEADER_ACP), &uRead);
while( SUCCEEDED(hr) &&
(sizeof(TF_PERSISTENT_PROPERTY_HEADER_ACP) == uRead) &&
(0 != PropHeader.cb))
{
ITfProperty *pProp;
hr = m_pContext->GetProperty(PropHeader.guidType, &pProp);
if(SUCCEEDED(hr))
{
/*
Have TSF read the property data from the stream. This call
will request a read lock, so make sure it can be granted
or else this method will fail.
*/
CTSFPersistentPropertyLoader *pLoader = new CTSFPersistentPropertyLoader(&PropHeader, pStream);
hr = m_pServices->Unserialize(pProp, &PropHeader, NULL, pLoader);
pProp->Release();
}
hr = pStream->Read(&PropHeader, sizeof(TF_PERSISTENT_PROPERTY_HEADER_ACP), &uRead);
}
}
GlobalFree(pwsz);
}
}
}