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

367 lines
10 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 © Microsoft Corporation. All rights reserved
/******************************************************************************
* LMAdapt.cpp
* Language Model adaptation routines
******************************************************************************/
#include "stdafx.h"
#include <commdlg.h>
/****************************************************************************
* CRecoDlgClass::GetTextFile *
*----------------------------*
*
* Description: Load the content of a text file into a buffer. The
* buffer is converted into Unicode using the default
* engine codepage if it isn't already in Unicode.
*
* Return: Buffer and character count
* HRESULT hr;
*
****************************************************************************/
HRESULT CRecoDlgClass::GetTextFile(
__deref_out_ecount_opt(*pcch) WCHAR ** ppwszCoMem,
__out ULONG * pcch)
{
TCHAR pszFileName[_MAX_PATH];
OPENFILENAME ofn;
HRESULT hr = S_OK;
HANDLE hf = INVALID_HANDLE_VALUE;
DWORD cBytes;
BOOL fUnicodeFile = FALSE;
USHORT uTemp;
WCHAR * pwszCoMem = 0;
ULONG cch = 0;
DWORD dwRead;
size_t ofnsize = (BYTE*)&ofn.lpTemplateName + sizeof(ofn.lpTemplateName) - (BYTE*)&ofn;
if (SUCCEEDED(hr))
{
pszFileName[0] = 0;
ofn.lStructSize = (DWORD)ofnsize;
ofn.hwndOwner = m_hDlg;
ofn.hInstance = m_hInstance;
ofn.lpstrFilter = _T("Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0\0");
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 0;
ofn.lpstrFile = pszFileName;
ofn.nMaxFile = _MAX_PATH;
ofn.nMaxFileTitle = _MAX_PATH;
ofn.lpstrFileTitle = NULL;
ofn.lpstrInitialDir = NULL;
ofn.lpstrTitle = NULL;
ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
ofn.lpstrDefExt = _T("txt");
hr = GetOpenFileName(&ofn) ? S_OK : E_FAIL;
}
if (SUCCEEDED(hr))
{
hf = CreateFile(pszFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
hr = (hf != INVALID_HANDLE_VALUE) ? S_OK : HRESULT_FROM_WIN32(CommDlgExtendedError());
}
if (SUCCEEDED(hr))
{
cBytes = GetFileSize(hf, NULL); // 64K limit
hr = (cBytes != -1) ? S_OK : HRESULT_FROM_WIN32(GetLastError());
}
if (SUCCEEDED(hr))
{
hr = ReadFile(hf, &uTemp, 2, &dwRead, NULL) ? S_OK : HRESULT_FROM_WIN32(GetLastError());
}
if (SUCCEEDED(hr))
{
fUnicodeFile = uTemp == 0xfeff;
if (fUnicodeFile)
{
cBytes -= 2;
pwszCoMem = (WCHAR *)CoTaskMemAlloc(cBytes);
if (pwszCoMem)
{
hr = ReadFile(hf, pwszCoMem, cBytes, &dwRead, NULL) ? S_OK : HRESULT_FROM_WIN32(GetLastError());
cch = cBytes / sizeof(WCHAR);
}
else
{
hr = E_OUTOFMEMORY;
}
}
else
{
UINT uiCodePage = SpCodePageFromLcid(MAKELCID(m_langid, SORT_DEFAULT));
char * pszBuffer = (char *)malloc(cBytes);
hr = pszBuffer ? S_OK : E_OUTOFMEMORY;
if (SUCCEEDED(hr))
{
SetFilePointer(hf, 0, NULL, FILE_BEGIN); // rewind
hr = ReadFile(hf, pszBuffer, cBytes, &dwRead, NULL) ? S_OK : HRESULT_FROM_WIN32(GetLastError());
}
if (SUCCEEDED(hr))
{
cch = MultiByteToWideChar(uiCodePage, 0, pszBuffer, cBytes, NULL, NULL);
if (cch)
{
pwszCoMem = (WCHAR *)CoTaskMemAlloc(sizeof(WCHAR) * cch);
}
else
{
hr = E_FAIL;
}
}
if (SUCCEEDED(hr))
{
MultiByteToWideChar(uiCodePage, 0, pszBuffer, cBytes, pwszCoMem, cch);
}
if (pszBuffer)
{
free(pszBuffer);
}
}
}
if (INVALID_HANDLE_VALUE != hf)
{
CloseHandle(hf);
}
*ppwszCoMem = pwszCoMem;
*pcch = cch;
return hr;
}
/***************************************************************************************
* CRecoDlgClass::FeedDocumentFromFile *
*-------------------------------------*
* Description: Open a text file and feed its content to the SR engine.
* Return:
* S_OK
* E_FAIL if no client window or if unsuccessful at obtaining the file name
****************************************************************************************/
HRESULT CRecoDlgClass::FeedDocumentFromFile()
{
WCHAR * pwszCoMem = 0;
ULONG cch = 0;
HRESULT hr = GetTextFile(&pwszCoMem, &cch);
if (SUCCEEDED(hr))
{
hr = FeedDocument(pwszCoMem, cch);
}
return hr;
}
/***************************************************************************************
* CRecoDlgClass::FeedDocumentFromClipboard *
*------------------------------------------*
* Description: Take text from the clipboard and feed its content to the SR engine.
* Return:
* S_OK
* E_FAIL if neither CF_TEXT or CF_UNICODETEXT was available on the clipboard
****************************************************************************************/
HRESULT CRecoDlgClass::FeedDocumentFromClipboard()
{
HRESULT hr;
UINT uFormat;
HANDLE hData;
BOOL fClipboardOpened = FALSE;
WCHAR * pwszCoMem;
SIZE_T cch;
if (IsClipboardFormatAvailable(CF_UNICODETEXT))
{
uFormat = CF_UNICODETEXT;
}
else if (IsClipboardFormatAvailable(CF_TEXT))
{
uFormat = CF_TEXT;
}
else
{
uFormat = 0;
}
if (uFormat)
{
hr = OpenClipboard(m_hDlg) ? S_OK : HRESULT_FROM_WIN32(GetLastError());
}
else
{
hr = E_FAIL;
}
if (SUCCEEDED(hr))
{
fClipboardOpened = TRUE;
hData = GetClipboardData(uFormat);
hr = hData ? S_OK : HRESULT_FROM_WIN32(GetLastError());
}
if (SUCCEEDED(hr))
{
VOID * pData = 0;
SIZE_T cBytes;
if (CF_UNICODETEXT == uFormat)
{
cBytes = GlobalSize(hData);
pwszCoMem = (WCHAR *)CoTaskMemAlloc(cBytes);
if (pwszCoMem)
{
pData = GlobalLock(hData);
hr = pData ? S_OK : HRESULT_FROM_WIN32(GetLastError());
}
else
{
hr = E_OUTOFMEMORY;
}
if (SUCCEEDED(hr))
{
memcpy(pwszCoMem, pData, cBytes);
cch = cBytes / sizeof(WCHAR);
}
}
else
{
UINT uiCodePage = SpCodePageFromLcid(MAKELCID(m_langid, SORT_DEFAULT));
cBytes = GlobalSize(hData);
pData = GlobalLock(hData);
hr = pData ? S_OK : HRESULT_FROM_WIN32(GetLastError());
if (SUCCEEDED(hr))
{
cch = MultiByteToWideChar(uiCodePage, 0, (char *)pData, (int) cBytes, NULL, NULL);
hr = cch ? S_OK : HRESULT_FROM_WIN32(GetLastError());
}
if (SUCCEEDED(hr))
{
pwszCoMem = (WCHAR *)CoTaskMemAlloc(cch * sizeof(WCHAR));
hr = pwszCoMem ? S_OK : E_OUTOFMEMORY;
}
if (SUCCEEDED(hr))
{
MultiByteToWideChar(uiCodePage, 0, (char *)pData, (int) cBytes, pwszCoMem, (int) cch);
}
}
if (pData)
{
GlobalUnlock(hData);
}
}
if (SUCCEEDED(hr))
{
hr = FeedDocument(pwszCoMem, cch);
}
if (fClipboardOpened)
{
CloseClipboard();
}
return hr;
}
/***************************************************************************************
* CRecoDlgClass::FeedDocument *
*-----------------------------*
* Description: Common code for FeedDocumentFromFile and FeedDocumentFromClipboard.
* Feed the text buffer to the SR engine.
* Return:
* S_OK
* E_* if error in SR engine
****************************************************************************************/
HRESULT CRecoDlgClass::FeedDocument(const WCHAR * pszCoMem, const SIZE_T cch)
{
HRESULT hr = S_OK;
//
// NOTE: This function limits the size of the adaptation data to a maximum of 16K
// characters (32K bytes). This sample does NOT demonstrate the proper use
// of this method. Applcations that use SetAdaptationData should break the
// data into small (1K or less) blocks, call SetAdaptationData, and then wait
// for a SPEI_ADAPTATION event before sending the next small block of data.
// Note that calling SetAdapataionData with buffers larger than 32K can result
// in unpredictable results. Do NOT call this method with large buffers.
//
if (cch <= 16000)
{
hr = m_cpRecoCtxt->SetAdaptationData(pszCoMem, (ULONG) cch);
}
CoTaskMemFree((void *)pszCoMem);
return hr;
}
/***************************************************************************************
* CRecoDlgClass::TrainFromFile *
*------------------------------*
* Description: Load a text file, and launch the User Training wizard using this text.
*
* Return:
* S_OK
* E_* if error in SR engine
****************************************************************************************/
HRESULT CRecoDlgClass::TrainFromFile()
{
WCHAR * pwszCoMem = 0;
ULONG cch = 0;
HRESULT hr = GetTextFile(&pwszCoMem, &cch);
if (SUCCEEDED(hr))
{
hr = m_cpRecognizer->DisplayUI(m_hDlg, NULL, SPDUI_UserTraining, (void *)pwszCoMem, cch * sizeof(WCHAR));
CoTaskMemFree(pwszCoMem);
}
return hr;
}