chore: settle line endings in .gitattributes (#310)
* chore: settle line endings in .gitattributes Nothing declared line endings, so each file kept whatever the contributor's core.autocrlf produced when it was added: 382 text files ended up LF and 50 CRLF. The CRLF ones are the hazard. Editing one on macOS or Linux writes LF lines into it, and clang-format rejects a file that mixes both -- which is how `quality / Workflow validation` went red on KeyStateCategory.h, where three lines out of a CRLF file had arrived as LF. #309 converted those three lines back and left the other 49 files loaded. The repository now declares LF and the working trees are renormalized to match, so the failure mode is gone rather than deferred to whichever of those files is edited next. The four binary types are declared rather than left to git's heuristic, which decides from the first 8000 bytes alone. user_dict.dat is caught by that sample today only because the 40-byte seed is almost entirely NUL. Verified: the 56 renormalized files are byte-identical to their old contents once CR is stripped, no text file in the index still carries CRLF, and scripts/format.sh --check passes. * chore: skip the line-ending renormalization in blame The commit before this one rewrote every line of 56 files without changing a character of them, which is what this file exists to hide.
This commit is contained in:
58 files changed
+17361
-17344
No files matched your search
@@ -3,3 +3,6 @@
|
||||
|
||||
# style: 用 .clang-format 重排 server / windows / ui / log
|
||||
42238a2af693fcd0dd80354b2b450c6647647dd2
|
||||
|
||||
# chore: settle line endings in .gitattributes
|
||||
6a320d5d07f29a7757f5d066fc4e142cc521a300
|
||||
@@ -0,0 +1,14 @@
|
||||
# Line endings are decided here rather than by each contributor's core.autocrlf. The repository is
|
||||
# already predominantly LF -- 382 text files against 50 -- and the stragglers are what break CI: an
|
||||
# edit made on macOS or Linux writes LF lines into one of the CRLF files, and clang-format rejects
|
||||
# the resulting mix. That is what took `quality / Workflow validation` red on KeyStateCategory.h,
|
||||
# where three lines out of a CRLF file had arrived as LF.
|
||||
* text=auto eol=lf
|
||||
|
||||
# Declared rather than left to git's binary heuristic, which only samples the first 8000 bytes.
|
||||
# user_dict.dat is a 40-byte seed that is almost entirely NUL, so the heuristic does catch it today,
|
||||
# but a larger one written later would not be caught by a sample of its head.
|
||||
*.dat binary
|
||||
*.ico binary
|
||||
*.mp3 binary
|
||||
*.png binary
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
BasedOnStyle: Microsoft
|
||||
IndentWidth: 4
|
||||
|
||||
# Do not sort headers
|
||||
SortIncludes: false
|
||||
---
|
||||
BasedOnStyle: Microsoft
|
||||
IndentWidth: 4
|
||||
|
||||
# Do not sort headers
|
||||
SortIncludes: false
|
||||
Vendored
+9
-9
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"editor.tabSize": 4,
|
||||
"editor.indentSize": "tabSize",
|
||||
"[cpp]": {
|
||||
"editor.tabSize": 4
|
||||
},
|
||||
"[json]": {
|
||||
"editor.tabSize": 2
|
||||
}
|
||||
{
|
||||
"editor.tabSize": 4,
|
||||
"editor.indentSize": "tabSize",
|
||||
"[cpp]": {
|
||||
"editor.tabSize": 4
|
||||
},
|
||||
"[json]": {
|
||||
"editor.tabSize": 2
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
# The *.txt files in this directory are UTF-16-encoded and should
|
||||
# therefore be treated as pure binary data.
|
||||
*.txt binary
|
||||
# The *.txt files in this directory are UTF-16-encoded and should
|
||||
# therefore be treated as pure binary data.
|
||||
*.txt binary
|
||||
+8258
-8258
File diff suppressed because it is too large.
Load diff
@@ -1,65 +1,65 @@
|
||||
# Generate and compile dll files
|
||||
# Default is to compile 64-bit dll, if 32-bit is specified, 32-bit dll would be compiled
|
||||
$currentDirectory = Get-Location
|
||||
$cmakeListsPath = Join-Path -Path $currentDirectory -ChildPath "CMakeLists.txt"
|
||||
|
||||
if (-not (Test-Path $cmakeListsPath))
|
||||
{
|
||||
Write-Host("No CMakeLists.txt in current directory, please check.")
|
||||
return
|
||||
}
|
||||
|
||||
Write-Host "Start generating and compiling..."
|
||||
|
||||
|
||||
$arch = $args[0]
|
||||
|
||||
if ($arch -eq "32")
|
||||
{
|
||||
$buildFolderPath = ".\build32"
|
||||
|
||||
if (-not (Test-Path $buildFolderPath))
|
||||
{
|
||||
New-Item -ItemType Directory -Path $buildFolderPath | Out-Null
|
||||
Write-Host "build32 folder created."
|
||||
}
|
||||
|
||||
cmake --preset=for32
|
||||
|
||||
if ($LASTEXITCODE -eq 0)
|
||||
{
|
||||
cmake --build ./build32/
|
||||
}
|
||||
} elseif ($arch -eq "64")
|
||||
{
|
||||
$buildFolderPath = ".\build64"
|
||||
|
||||
if (-not (Test-Path $buildFolderPath))
|
||||
{
|
||||
New-Item -ItemType Directory -Path $buildFolderPath | Out-Null
|
||||
Write-Host "build64 folder created."
|
||||
}
|
||||
|
||||
cmake --preset=for64
|
||||
|
||||
if ($LASTEXITCODE -eq 0)
|
||||
{
|
||||
cmake --build ./build64/
|
||||
}
|
||||
} else
|
||||
{ # Default is 64-bit
|
||||
$buildFolderPath = ".\build64"
|
||||
|
||||
if (-not (Test-Path $buildFolderPath))
|
||||
{
|
||||
New-Item -ItemType Directory -Path $buildFolderPath | Out-Null
|
||||
Write-Host "build64 folder created."
|
||||
}
|
||||
|
||||
cmake --preset=for64
|
||||
|
||||
if ($LASTEXITCODE -eq 0)
|
||||
{
|
||||
cmake --build ./build64/
|
||||
}
|
||||
}
|
||||
# Generate and compile dll files
|
||||
# Default is to compile 64-bit dll, if 32-bit is specified, 32-bit dll would be compiled
|
||||
$currentDirectory = Get-Location
|
||||
$cmakeListsPath = Join-Path -Path $currentDirectory -ChildPath "CMakeLists.txt"
|
||||
|
||||
if (-not (Test-Path $cmakeListsPath))
|
||||
{
|
||||
Write-Host("No CMakeLists.txt in current directory, please check.")
|
||||
return
|
||||
}
|
||||
|
||||
Write-Host "Start generating and compiling..."
|
||||
|
||||
|
||||
$arch = $args[0]
|
||||
|
||||
if ($arch -eq "32")
|
||||
{
|
||||
$buildFolderPath = ".\build32"
|
||||
|
||||
if (-not (Test-Path $buildFolderPath))
|
||||
{
|
||||
New-Item -ItemType Directory -Path $buildFolderPath | Out-Null
|
||||
Write-Host "build32 folder created."
|
||||
}
|
||||
|
||||
cmake --preset=for32
|
||||
|
||||
if ($LASTEXITCODE -eq 0)
|
||||
{
|
||||
cmake --build ./build32/
|
||||
}
|
||||
} elseif ($arch -eq "64")
|
||||
{
|
||||
$buildFolderPath = ".\build64"
|
||||
|
||||
if (-not (Test-Path $buildFolderPath))
|
||||
{
|
||||
New-Item -ItemType Directory -Path $buildFolderPath | Out-Null
|
||||
Write-Host "build64 folder created."
|
||||
}
|
||||
|
||||
cmake --preset=for64
|
||||
|
||||
if ($LASTEXITCODE -eq 0)
|
||||
{
|
||||
cmake --build ./build64/
|
||||
}
|
||||
} else
|
||||
{ # Default is 64-bit
|
||||
$buildFolderPath = ".\build64"
|
||||
|
||||
if (-not (Test-Path $buildFolderPath))
|
||||
{
|
||||
New-Item -ItemType Directory -Path $buildFolderPath | Out-Null
|
||||
Write-Host "build64 folder created."
|
||||
}
|
||||
|
||||
cmake --preset=for64
|
||||
|
||||
if ($LASTEXITCODE -eq 0)
|
||||
{
|
||||
cmake --build ./build64/
|
||||
}
|
||||
}
|
||||
@@ -1,122 +1,122 @@
|
||||
#include "Private.h"
|
||||
#include "EnumTfCandidates.h"
|
||||
|
||||
HRESULT CEnumTfCandidates::CreateInstance(_Outptr_ IEnumTfCandidates **ppEnum,
|
||||
_In_ const CMetasequoiaImeArray<ITfCandidateString *> &rgelm, UINT currentNum)
|
||||
{
|
||||
if (ppEnum == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*ppEnum = new (std::nothrow) CEnumTfCandidates(rgelm, currentNum);
|
||||
if (*ppEnum == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
(*ppEnum)->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
CEnumTfCandidates::CEnumTfCandidates(_In_ const CMetasequoiaImeArray<ITfCandidateString *> &rgelm, UINT currentNum)
|
||||
{
|
||||
_refCount = 0;
|
||||
_rgelm = rgelm;
|
||||
_currentCandidateStrIndex = currentNum;
|
||||
}
|
||||
|
||||
CEnumTfCandidates::~CEnumTfCandidates()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// IUnknown methods
|
||||
//
|
||||
STDMETHODIMP CEnumTfCandidates::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
|
||||
{
|
||||
if (ppvObj == nullptr)
|
||||
{
|
||||
return E_POINTER;
|
||||
}
|
||||
*ppvObj = nullptr;
|
||||
|
||||
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, __uuidof(IEnumTfCandidates)))
|
||||
{
|
||||
*ppvObj = (IEnumTfCandidates *)this;
|
||||
}
|
||||
|
||||
if (*ppvObj == nullptr)
|
||||
{
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) CEnumTfCandidates::AddRef()
|
||||
{
|
||||
return (ULONG)InterlockedIncrement(&_refCount);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) CEnumTfCandidates::Release()
|
||||
{
|
||||
ULONG cRef = (ULONG)InterlockedDecrement(&_refCount);
|
||||
if (0 < cRef)
|
||||
{
|
||||
return cRef;
|
||||
}
|
||||
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// IEnumTfCandidates methods
|
||||
//
|
||||
STDMETHODIMP CEnumTfCandidates::Next(ULONG ulCount, _Out_ ITfCandidateString **ppObj, _Out_ ULONG *pcFetched)
|
||||
{
|
||||
ULONG fetched = 0;
|
||||
if (ppObj == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*ppObj = nullptr;
|
||||
|
||||
while ((fetched < ulCount) && (_currentCandidateStrIndex < _rgelm.Count()))
|
||||
{
|
||||
*ppObj = *_rgelm.GetAt(_currentCandidateStrIndex);
|
||||
(*ppObj)->AddRef();
|
||||
_currentCandidateStrIndex++;
|
||||
fetched++;
|
||||
}
|
||||
|
||||
if (pcFetched)
|
||||
{
|
||||
*pcFetched = fetched;
|
||||
}
|
||||
|
||||
return (fetched == ulCount) ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
STDMETHODIMP CEnumTfCandidates::Skip(ULONG ulCount)
|
||||
{
|
||||
while ((0 < ulCount) && (_currentCandidateStrIndex < _rgelm.Count()))
|
||||
{
|
||||
_currentCandidateStrIndex++;
|
||||
ulCount--;
|
||||
}
|
||||
|
||||
return (0 < ulCount) ? S_FALSE : S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CEnumTfCandidates::Reset()
|
||||
{
|
||||
_currentCandidateStrIndex = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CEnumTfCandidates::Clone(_Out_ IEnumTfCandidates **ppEnum)
|
||||
{
|
||||
return CreateInstance(ppEnum, _rgelm, _currentCandidateStrIndex);
|
||||
}
|
||||
#include "Private.h"
|
||||
#include "EnumTfCandidates.h"
|
||||
|
||||
HRESULT CEnumTfCandidates::CreateInstance(_Outptr_ IEnumTfCandidates **ppEnum,
|
||||
_In_ const CMetasequoiaImeArray<ITfCandidateString *> &rgelm, UINT currentNum)
|
||||
{
|
||||
if (ppEnum == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*ppEnum = new (std::nothrow) CEnumTfCandidates(rgelm, currentNum);
|
||||
if (*ppEnum == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
(*ppEnum)->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
CEnumTfCandidates::CEnumTfCandidates(_In_ const CMetasequoiaImeArray<ITfCandidateString *> &rgelm, UINT currentNum)
|
||||
{
|
||||
_refCount = 0;
|
||||
_rgelm = rgelm;
|
||||
_currentCandidateStrIndex = currentNum;
|
||||
}
|
||||
|
||||
CEnumTfCandidates::~CEnumTfCandidates()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// IUnknown methods
|
||||
//
|
||||
STDMETHODIMP CEnumTfCandidates::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
|
||||
{
|
||||
if (ppvObj == nullptr)
|
||||
{
|
||||
return E_POINTER;
|
||||
}
|
||||
*ppvObj = nullptr;
|
||||
|
||||
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, __uuidof(IEnumTfCandidates)))
|
||||
{
|
||||
*ppvObj = (IEnumTfCandidates *)this;
|
||||
}
|
||||
|
||||
if (*ppvObj == nullptr)
|
||||
{
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) CEnumTfCandidates::AddRef()
|
||||
{
|
||||
return (ULONG)InterlockedIncrement(&_refCount);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) CEnumTfCandidates::Release()
|
||||
{
|
||||
ULONG cRef = (ULONG)InterlockedDecrement(&_refCount);
|
||||
if (0 < cRef)
|
||||
{
|
||||
return cRef;
|
||||
}
|
||||
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// IEnumTfCandidates methods
|
||||
//
|
||||
STDMETHODIMP CEnumTfCandidates::Next(ULONG ulCount, _Out_ ITfCandidateString **ppObj, _Out_ ULONG *pcFetched)
|
||||
{
|
||||
ULONG fetched = 0;
|
||||
if (ppObj == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*ppObj = nullptr;
|
||||
|
||||
while ((fetched < ulCount) && (_currentCandidateStrIndex < _rgelm.Count()))
|
||||
{
|
||||
*ppObj = *_rgelm.GetAt(_currentCandidateStrIndex);
|
||||
(*ppObj)->AddRef();
|
||||
_currentCandidateStrIndex++;
|
||||
fetched++;
|
||||
}
|
||||
|
||||
if (pcFetched)
|
||||
{
|
||||
*pcFetched = fetched;
|
||||
}
|
||||
|
||||
return (fetched == ulCount) ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
STDMETHODIMP CEnumTfCandidates::Skip(ULONG ulCount)
|
||||
{
|
||||
while ((0 < ulCount) && (_currentCandidateStrIndex < _rgelm.Count()))
|
||||
{
|
||||
_currentCandidateStrIndex++;
|
||||
ulCount--;
|
||||
}
|
||||
|
||||
return (0 < ulCount) ? S_FALSE : S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CEnumTfCandidates::Reset()
|
||||
{
|
||||
_currentCandidateStrIndex = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CEnumTfCandidates::Clone(_Out_ IEnumTfCandidates **ppEnum)
|
||||
{
|
||||
return CreateInstance(ppEnum, _rgelm, _currentCandidateStrIndex);
|
||||
}
|
||||
@@ -1,33 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "Globals.h"
|
||||
|
||||
class CEnumTfCandidates : public IEnumTfCandidates
|
||||
{
|
||||
protected:
|
||||
// constructor/destructor
|
||||
CEnumTfCandidates(_In_ const CMetasequoiaImeArray<ITfCandidateString *> &rgelm, UINT currentNum);
|
||||
|
||||
virtual ~CEnumTfCandidates(void);
|
||||
|
||||
public:
|
||||
// create instance
|
||||
static HRESULT CreateInstance(_Outptr_ IEnumTfCandidates **ppEnum,
|
||||
_In_ const CMetasequoiaImeArray<ITfCandidateString *> &rgelm, UINT currentNum = 0);
|
||||
|
||||
// IUnknown methods
|
||||
virtual STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj);
|
||||
virtual STDMETHODIMP_(ULONG) AddRef(void);
|
||||
virtual STDMETHODIMP_(ULONG) Release(void);
|
||||
|
||||
// IEnumTfCandidates methods
|
||||
virtual STDMETHODIMP Next(ULONG ulCount, _Out_ ITfCandidateString **ppObj, _Out_ ULONG *pcFetched);
|
||||
virtual STDMETHODIMP Skip(ULONG ulCount);
|
||||
virtual STDMETHODIMP Reset();
|
||||
virtual STDMETHODIMP Clone(_Out_ IEnumTfCandidates **ppEnum);
|
||||
|
||||
protected:
|
||||
LONG _refCount;
|
||||
CMetasequoiaImeArray<ITfCandidateString *> _rgelm;
|
||||
UINT _currentCandidateStrIndex;
|
||||
};
|
||||
#pragma once
|
||||
|
||||
#include "Globals.h"
|
||||
|
||||
class CEnumTfCandidates : public IEnumTfCandidates
|
||||
{
|
||||
protected:
|
||||
// constructor/destructor
|
||||
CEnumTfCandidates(_In_ const CMetasequoiaImeArray<ITfCandidateString *> &rgelm, UINT currentNum);
|
||||
|
||||
virtual ~CEnumTfCandidates(void);
|
||||
|
||||
public:
|
||||
// create instance
|
||||
static HRESULT CreateInstance(_Outptr_ IEnumTfCandidates **ppEnum,
|
||||
_In_ const CMetasequoiaImeArray<ITfCandidateString *> &rgelm, UINT currentNum = 0);
|
||||
|
||||
// IUnknown methods
|
||||
virtual STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj);
|
||||
virtual STDMETHODIMP_(ULONG) AddRef(void);
|
||||
virtual STDMETHODIMP_(ULONG) Release(void);
|
||||
|
||||
// IEnumTfCandidates methods
|
||||
virtual STDMETHODIMP Next(ULONG ulCount, _Out_ ITfCandidateString **ppObj, _Out_ ULONG *pcFetched);
|
||||
virtual STDMETHODIMP Skip(ULONG ulCount);
|
||||
virtual STDMETHODIMP Reset();
|
||||
virtual STDMETHODIMP Clone(_Out_ IEnumTfCandidates **ppEnum);
|
||||
|
||||
protected:
|
||||
LONG _refCount;
|
||||
CMetasequoiaImeArray<ITfCandidateString *> _rgelm;
|
||||
UINT _currentCandidateStrIndex;
|
||||
};
|
||||
@@ -1,192 +1,192 @@
|
||||
#include "Private.h"
|
||||
#include "SearchCandidateProvider.h"
|
||||
#include <new>
|
||||
#include "MetasequoiaIME.h"
|
||||
#include "CompositionProcessorEngine.h"
|
||||
#include "TipCandidateList.h"
|
||||
#include "TipCandidateString.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
|
||||
create instance of CSearchCandidateProvider
|
||||
|
||||
------------------------------------------------------------------------------*/
|
||||
HRESULT CSearchCandidateProvider::CreateInstance(_Outptr_ ITfFnSearchCandidateProvider **ppobj,
|
||||
_In_ ITfTextInputProcessorEx *ptip)
|
||||
{
|
||||
if (ppobj == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*ppobj = nullptr;
|
||||
|
||||
*ppobj = new (std::nothrow) CSearchCandidateProvider(ptip);
|
||||
if (nullptr == *ppobj)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
(*ppobj)->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
|
||||
constructor of CSearchCandidateProvider
|
||||
|
||||
------------------------------------------------------------------------------*/
|
||||
CSearchCandidateProvider::CSearchCandidateProvider(_In_ ITfTextInputProcessorEx *ptip)
|
||||
{
|
||||
assert(ptip != nullptr);
|
||||
|
||||
_pTip = ptip;
|
||||
_refCount = 0;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
|
||||
destructor of CSearchCandidateProvider
|
||||
|
||||
------------------------------------------------------------------------------*/
|
||||
CSearchCandidateProvider::~CSearchCandidateProvider(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
|
||||
query interface
|
||||
(IUnknown method)
|
||||
|
||||
------------------------------------------------------------------------------*/
|
||||
STDMETHODIMP CSearchCandidateProvider::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
|
||||
{
|
||||
if (ppvObj == nullptr)
|
||||
{
|
||||
return E_POINTER;
|
||||
}
|
||||
*ppvObj = nullptr;
|
||||
|
||||
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, __uuidof(ITfFnSearchCandidateProvider)))
|
||||
{
|
||||
*ppvObj = (ITfFnSearchCandidateProvider *)this;
|
||||
}
|
||||
else if (IsEqualIID(riid, IID_ITfFunction))
|
||||
{
|
||||
*ppvObj = (ITfFunction *)this;
|
||||
}
|
||||
|
||||
if (*ppvObj == nullptr)
|
||||
{
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
|
||||
increment reference count
|
||||
(IUnknown method)
|
||||
|
||||
------------------------------------------------------------------------------*/
|
||||
STDMETHODIMP_(ULONG) CSearchCandidateProvider::AddRef()
|
||||
{
|
||||
return (ULONG)InterlockedIncrement(&_refCount);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
|
||||
decrement reference count and release object
|
||||
(IUnknown method)
|
||||
|
||||
------------------------------------------------------------------------------*/
|
||||
STDMETHODIMP_(ULONG) CSearchCandidateProvider::Release()
|
||||
{
|
||||
ULONG ref = (ULONG)InterlockedDecrement(&_refCount);
|
||||
if (0 < ref)
|
||||
{
|
||||
return ref;
|
||||
}
|
||||
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
STDMETHODIMP CSearchCandidateProvider::GetDisplayName(_Out_ BSTR *pbstrName)
|
||||
{
|
||||
if (pbstrName == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*pbstrName = SysAllocString(L"SearchCandidateProvider");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CSearchCandidateProvider::GetSearchCandidates(BSTR bstrQuery, BSTR bstrApplicationID,
|
||||
_Outptr_result_maybenull_ ITfCandidateList **pplist)
|
||||
{
|
||||
bstrApplicationID;
|
||||
bstrQuery;
|
||||
HRESULT hr = E_FAIL;
|
||||
*pplist = nullptr;
|
||||
|
||||
if (nullptr == _pTip)
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
CCompositionProcessorEngine *pCompositionProcessorEngine =
|
||||
((CMetasequoiaIME *)_pTip)->GetCompositionProcessorEngine();
|
||||
if (nullptr == pCompositionProcessorEngine)
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
CMetasequoiaImeArray<CCandidateListItem> candidateList;
|
||||
pCompositionProcessorEngine->GetCandidateList(&candidateList, TRUE, FALSE);
|
||||
|
||||
int cCand = min(candidateList.Count(), FAKECANDIDATENUMBER);
|
||||
if (0 < cCand)
|
||||
{
|
||||
hr = CTipCandidateList::CreateInstance(pplist, cCand);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
for (int iCand = 0; iCand < cCand; iCand++)
|
||||
{
|
||||
CTipCandidateString *pCandStr = nullptr;
|
||||
hr = CTipCandidateString::CreateInstance(&pCandStr);
|
||||
if (FAILED(hr) || (pCandStr == nullptr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
pCandStr->SetIndex(iCand);
|
||||
pCandStr->SetString(candidateList.GetAt(iCand)->_ItemString.Get(),
|
||||
candidateList.GetAt(iCand)->_ItemString.GetLength());
|
||||
|
||||
((CTipCandidateList *)(*pplist))->SetCandidate(pCandStr);
|
||||
}
|
||||
}
|
||||
hr = S_OK;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
|
||||
set result
|
||||
(ITfFnSearchCandidateProvider method)
|
||||
|
||||
------------------------------------------------------------------------------*/
|
||||
STDMETHODIMP CSearchCandidateProvider::SetResult(BSTR bstrQuery, BSTR bstrApplicationID, BSTR bstrResult)
|
||||
{
|
||||
bstrQuery;
|
||||
bstrApplicationID;
|
||||
bstrResult;
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
#include "Private.h"
|
||||
#include "SearchCandidateProvider.h"
|
||||
#include <new>
|
||||
#include "MetasequoiaIME.h"
|
||||
#include "CompositionProcessorEngine.h"
|
||||
#include "TipCandidateList.h"
|
||||
#include "TipCandidateString.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
|
||||
create instance of CSearchCandidateProvider
|
||||
|
||||
------------------------------------------------------------------------------*/
|
||||
HRESULT CSearchCandidateProvider::CreateInstance(_Outptr_ ITfFnSearchCandidateProvider **ppobj,
|
||||
_In_ ITfTextInputProcessorEx *ptip)
|
||||
{
|
||||
if (ppobj == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*ppobj = nullptr;
|
||||
|
||||
*ppobj = new (std::nothrow) CSearchCandidateProvider(ptip);
|
||||
if (nullptr == *ppobj)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
(*ppobj)->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
|
||||
constructor of CSearchCandidateProvider
|
||||
|
||||
------------------------------------------------------------------------------*/
|
||||
CSearchCandidateProvider::CSearchCandidateProvider(_In_ ITfTextInputProcessorEx *ptip)
|
||||
{
|
||||
assert(ptip != nullptr);
|
||||
|
||||
_pTip = ptip;
|
||||
_refCount = 0;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
|
||||
destructor of CSearchCandidateProvider
|
||||
|
||||
------------------------------------------------------------------------------*/
|
||||
CSearchCandidateProvider::~CSearchCandidateProvider(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
|
||||
query interface
|
||||
(IUnknown method)
|
||||
|
||||
------------------------------------------------------------------------------*/
|
||||
STDMETHODIMP CSearchCandidateProvider::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
|
||||
{
|
||||
if (ppvObj == nullptr)
|
||||
{
|
||||
return E_POINTER;
|
||||
}
|
||||
*ppvObj = nullptr;
|
||||
|
||||
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, __uuidof(ITfFnSearchCandidateProvider)))
|
||||
{
|
||||
*ppvObj = (ITfFnSearchCandidateProvider *)this;
|
||||
}
|
||||
else if (IsEqualIID(riid, IID_ITfFunction))
|
||||
{
|
||||
*ppvObj = (ITfFunction *)this;
|
||||
}
|
||||
|
||||
if (*ppvObj == nullptr)
|
||||
{
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
|
||||
increment reference count
|
||||
(IUnknown method)
|
||||
|
||||
------------------------------------------------------------------------------*/
|
||||
STDMETHODIMP_(ULONG) CSearchCandidateProvider::AddRef()
|
||||
{
|
||||
return (ULONG)InterlockedIncrement(&_refCount);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
|
||||
decrement reference count and release object
|
||||
(IUnknown method)
|
||||
|
||||
------------------------------------------------------------------------------*/
|
||||
STDMETHODIMP_(ULONG) CSearchCandidateProvider::Release()
|
||||
{
|
||||
ULONG ref = (ULONG)InterlockedDecrement(&_refCount);
|
||||
if (0 < ref)
|
||||
{
|
||||
return ref;
|
||||
}
|
||||
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
STDMETHODIMP CSearchCandidateProvider::GetDisplayName(_Out_ BSTR *pbstrName)
|
||||
{
|
||||
if (pbstrName == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*pbstrName = SysAllocString(L"SearchCandidateProvider");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CSearchCandidateProvider::GetSearchCandidates(BSTR bstrQuery, BSTR bstrApplicationID,
|
||||
_Outptr_result_maybenull_ ITfCandidateList **pplist)
|
||||
{
|
||||
bstrApplicationID;
|
||||
bstrQuery;
|
||||
HRESULT hr = E_FAIL;
|
||||
*pplist = nullptr;
|
||||
|
||||
if (nullptr == _pTip)
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
CCompositionProcessorEngine *pCompositionProcessorEngine =
|
||||
((CMetasequoiaIME *)_pTip)->GetCompositionProcessorEngine();
|
||||
if (nullptr == pCompositionProcessorEngine)
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
CMetasequoiaImeArray<CCandidateListItem> candidateList;
|
||||
pCompositionProcessorEngine->GetCandidateList(&candidateList, TRUE, FALSE);
|
||||
|
||||
int cCand = min(candidateList.Count(), FAKECANDIDATENUMBER);
|
||||
if (0 < cCand)
|
||||
{
|
||||
hr = CTipCandidateList::CreateInstance(pplist, cCand);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
for (int iCand = 0; iCand < cCand; iCand++)
|
||||
{
|
||||
CTipCandidateString *pCandStr = nullptr;
|
||||
hr = CTipCandidateString::CreateInstance(&pCandStr);
|
||||
if (FAILED(hr) || (pCandStr == nullptr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
pCandStr->SetIndex(iCand);
|
||||
pCandStr->SetString(candidateList.GetAt(iCand)->_ItemString.Get(),
|
||||
candidateList.GetAt(iCand)->_ItemString.GetLength());
|
||||
|
||||
((CTipCandidateList *)(*pplist))->SetCandidate(pCandStr);
|
||||
}
|
||||
}
|
||||
hr = S_OK;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
|
||||
set result
|
||||
(ITfFnSearchCandidateProvider method)
|
||||
|
||||
------------------------------------------------------------------------------*/
|
||||
STDMETHODIMP CSearchCandidateProvider::SetResult(BSTR bstrQuery, BSTR bstrApplicationID, BSTR bstrResult)
|
||||
{
|
||||
bstrQuery;
|
||||
bstrApplicationID;
|
||||
bstrResult;
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
@@ -1,44 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include "Private.h"
|
||||
|
||||
//
|
||||
// CSearchCandidateProvider
|
||||
//
|
||||
// TfFnSearchCandidateProvider is used for search integration feature, CSearchCandidateProvider
|
||||
// implements this interface that can be called by search integration, and offer the candidate list
|
||||
// as search integration suggestion.
|
||||
//
|
||||
#define FAKECANDIDATENUMBER (16)
|
||||
class CSearchCandidateProvider : public ITfFnSearchCandidateProvider
|
||||
{
|
||||
protected:
|
||||
// constructor/destructor
|
||||
CSearchCandidateProvider(_In_ ITfTextInputProcessorEx *ptip);
|
||||
virtual ~CSearchCandidateProvider();
|
||||
|
||||
public:
|
||||
// create instance
|
||||
static HRESULT CreateInstance(_Outptr_ ITfFnSearchCandidateProvider **ppobj, _In_ ITfTextInputProcessorEx *ptip);
|
||||
|
||||
// IUnknown methods
|
||||
STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj);
|
||||
STDMETHODIMP_(ULONG) AddRef(void);
|
||||
STDMETHODIMP_(ULONG) Release(void);
|
||||
|
||||
// ITfFunction methods
|
||||
STDMETHODIMP GetDisplayName(_Out_ BSTR *pbstrName);
|
||||
|
||||
// ITfFnSearchCandidateProvider methods
|
||||
//
|
||||
// GetSearchCandidates is responsible for supporting the candidates to caller, search integration
|
||||
// SetResult is not used
|
||||
//
|
||||
STDMETHODIMP GetSearchCandidates(BSTR bstrQuery, BSTR bstrApplicationID,
|
||||
_Outptr_result_maybenull_ ITfCandidateList **pplist);
|
||||
STDMETHODIMP SetResult(BSTR bstrQuery, BSTR bstrApplicationID, BSTR bstrResult);
|
||||
|
||||
private:
|
||||
LONG _refCount;
|
||||
ITfTextInputProcessorEx *_pTip;
|
||||
};
|
||||
#pragma once
|
||||
|
||||
#include "Private.h"
|
||||
|
||||
//
|
||||
// CSearchCandidateProvider
|
||||
//
|
||||
// TfFnSearchCandidateProvider is used for search integration feature, CSearchCandidateProvider
|
||||
// implements this interface that can be called by search integration, and offer the candidate list
|
||||
// as search integration suggestion.
|
||||
//
|
||||
#define FAKECANDIDATENUMBER (16)
|
||||
class CSearchCandidateProvider : public ITfFnSearchCandidateProvider
|
||||
{
|
||||
protected:
|
||||
// constructor/destructor
|
||||
CSearchCandidateProvider(_In_ ITfTextInputProcessorEx *ptip);
|
||||
virtual ~CSearchCandidateProvider();
|
||||
|
||||
public:
|
||||
// create instance
|
||||
static HRESULT CreateInstance(_Outptr_ ITfFnSearchCandidateProvider **ppobj, _In_ ITfTextInputProcessorEx *ptip);
|
||||
|
||||
// IUnknown methods
|
||||
STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj);
|
||||
STDMETHODIMP_(ULONG) AddRef(void);
|
||||
STDMETHODIMP_(ULONG) Release(void);
|
||||
|
||||
// ITfFunction methods
|
||||
STDMETHODIMP GetDisplayName(_Out_ BSTR *pbstrName);
|
||||
|
||||
// ITfFnSearchCandidateProvider methods
|
||||
//
|
||||
// GetSearchCandidates is responsible for supporting the candidates to caller, search integration
|
||||
// SetResult is not used
|
||||
//
|
||||
STDMETHODIMP GetSearchCandidates(BSTR bstrQuery, BSTR bstrApplicationID,
|
||||
_Outptr_result_maybenull_ ITfCandidateList **pplist);
|
||||
STDMETHODIMP SetResult(BSTR bstrQuery, BSTR bstrApplicationID, BSTR bstrResult);
|
||||
|
||||
private:
|
||||
LONG _refCount;
|
||||
ITfTextInputProcessorEx *_pTip;
|
||||
};
|
||||
@@ -1,170 +1,170 @@
|
||||
#include "Private.h"
|
||||
#include "TipCandidateList.h"
|
||||
#include "EnumTfCandidates.h"
|
||||
#include "TipCandidateString.h"
|
||||
|
||||
HRESULT CTipCandidateList::CreateInstance(_Outptr_ ITfCandidateList **ppobj, size_t candStrReserveSize)
|
||||
{
|
||||
if (ppobj == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*ppobj = nullptr;
|
||||
|
||||
*ppobj = new (std::nothrow) CTipCandidateList(candStrReserveSize);
|
||||
if (*ppobj == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
(*ppobj)->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
CTipCandidateList::CTipCandidateList(size_t candStrReserveSize)
|
||||
{
|
||||
_refCount = 0;
|
||||
|
||||
if (0 < candStrReserveSize)
|
||||
{
|
||||
_tfCandStrList.reserve(candStrReserveSize);
|
||||
}
|
||||
}
|
||||
|
||||
CTipCandidateList::~CTipCandidateList()
|
||||
{
|
||||
for (UINT i = 0; i < _tfCandStrList.Count(); i++)
|
||||
{
|
||||
ITfCandidateString **ppCandStr = _tfCandStrList.GetAt(i);
|
||||
if ((ppCandStr != nullptr) && (*ppCandStr != nullptr))
|
||||
{
|
||||
(*ppCandStr)->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STDMETHODIMP CTipCandidateList::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
|
||||
{
|
||||
if (ppvObj == nullptr)
|
||||
{
|
||||
return E_POINTER;
|
||||
}
|
||||
*ppvObj = nullptr;
|
||||
|
||||
if (IsEqualIID(riid, IID_IUnknown))
|
||||
{
|
||||
*ppvObj = (ITfCandidateList *)this;
|
||||
}
|
||||
else if (IsEqualIID(riid, IID_ITfCandidateList))
|
||||
{
|
||||
*ppvObj = (ITfCandidateList *)this;
|
||||
}
|
||||
|
||||
if (*ppvObj == nullptr)
|
||||
{
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) CTipCandidateList::AddRef()
|
||||
{
|
||||
return (ULONG)InterlockedIncrement((LONG *)&_refCount);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) CTipCandidateList::Release()
|
||||
{
|
||||
ULONG cRefT = (ULONG)InterlockedDecrement((LONG *)&_refCount);
|
||||
if (0 < cRefT)
|
||||
{
|
||||
return cRefT;
|
||||
}
|
||||
|
||||
delete this;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
STDMETHODIMP CTipCandidateList::EnumCandidates(_Outptr_ IEnumTfCandidates **ppEnum)
|
||||
{
|
||||
return CEnumTfCandidates::CreateInstance(ppEnum, _tfCandStrList);
|
||||
}
|
||||
|
||||
STDMETHODIMP CTipCandidateList::GetCandidate(ULONG nIndex, _Outptr_result_maybenull_ ITfCandidateString **ppCandStr)
|
||||
{
|
||||
if (ppCandStr == nullptr)
|
||||
{
|
||||
return E_POINTER;
|
||||
}
|
||||
*ppCandStr = nullptr;
|
||||
|
||||
ULONG sizeCandStr = (ULONG)_tfCandStrList.Count();
|
||||
if (sizeCandStr <= nIndex)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
ITfCandidateString **ppCandStrCur = _tfCandStrList.GetAt(static_cast<UINT>(nIndex));
|
||||
if ((ppCandStrCur == nullptr) || (*ppCandStrCur == nullptr))
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
BSTR bstr = nullptr;
|
||||
CTipCandidateString *pTipCandidateStrCur = static_cast<CTipCandidateString *>(*ppCandStrCur);
|
||||
if (FAILED(pTipCandidateStrCur->GetString(&bstr)))
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
CTipCandidateString *pCandidateString = nullptr;
|
||||
const HRESULT hr = CTipCandidateString::CreateInstance(&pCandidateString);
|
||||
if (SUCCEEDED(hr) && (pCandidateString != nullptr))
|
||||
{
|
||||
pCandidateString->SetIndex(nIndex);
|
||||
pCandidateString->SetString((LPCWSTR)bstr, SysStringLen(bstr));
|
||||
*ppCandStr = pCandidateString;
|
||||
}
|
||||
|
||||
SysFreeString(bstr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
STDMETHODIMP CTipCandidateList::GetCandidateNum(_Out_ ULONG *pnCnt)
|
||||
{
|
||||
if (pnCnt == nullptr)
|
||||
{
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
*pnCnt = (ULONG)(_tfCandStrList.Count());
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CTipCandidateList::SetResult(ULONG nIndex, TfCandidateResult imcr)
|
||||
{
|
||||
nIndex;
|
||||
imcr;
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CTipCandidateList::SetCandidate(_In_ ITfCandidateString *pCandStr)
|
||||
{
|
||||
if (pCandStr == nullptr)
|
||||
{
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
ITfCandidateString **ppCandLast = _tfCandStrList.Append();
|
||||
if (ppCandLast)
|
||||
{
|
||||
*ppCandLast = pCandStr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
pCandStr->Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
#include "Private.h"
|
||||
#include "TipCandidateList.h"
|
||||
#include "EnumTfCandidates.h"
|
||||
#include "TipCandidateString.h"
|
||||
|
||||
HRESULT CTipCandidateList::CreateInstance(_Outptr_ ITfCandidateList **ppobj, size_t candStrReserveSize)
|
||||
{
|
||||
if (ppobj == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*ppobj = nullptr;
|
||||
|
||||
*ppobj = new (std::nothrow) CTipCandidateList(candStrReserveSize);
|
||||
if (*ppobj == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
(*ppobj)->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
CTipCandidateList::CTipCandidateList(size_t candStrReserveSize)
|
||||
{
|
||||
_refCount = 0;
|
||||
|
||||
if (0 < candStrReserveSize)
|
||||
{
|
||||
_tfCandStrList.reserve(candStrReserveSize);
|
||||
}
|
||||
}
|
||||
|
||||
CTipCandidateList::~CTipCandidateList()
|
||||
{
|
||||
for (UINT i = 0; i < _tfCandStrList.Count(); i++)
|
||||
{
|
||||
ITfCandidateString **ppCandStr = _tfCandStrList.GetAt(i);
|
||||
if ((ppCandStr != nullptr) && (*ppCandStr != nullptr))
|
||||
{
|
||||
(*ppCandStr)->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STDMETHODIMP CTipCandidateList::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
|
||||
{
|
||||
if (ppvObj == nullptr)
|
||||
{
|
||||
return E_POINTER;
|
||||
}
|
||||
*ppvObj = nullptr;
|
||||
|
||||
if (IsEqualIID(riid, IID_IUnknown))
|
||||
{
|
||||
*ppvObj = (ITfCandidateList *)this;
|
||||
}
|
||||
else if (IsEqualIID(riid, IID_ITfCandidateList))
|
||||
{
|
||||
*ppvObj = (ITfCandidateList *)this;
|
||||
}
|
||||
|
||||
if (*ppvObj == nullptr)
|
||||
{
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) CTipCandidateList::AddRef()
|
||||
{
|
||||
return (ULONG)InterlockedIncrement((LONG *)&_refCount);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) CTipCandidateList::Release()
|
||||
{
|
||||
ULONG cRefT = (ULONG)InterlockedDecrement((LONG *)&_refCount);
|
||||
if (0 < cRefT)
|
||||
{
|
||||
return cRefT;
|
||||
}
|
||||
|
||||
delete this;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
STDMETHODIMP CTipCandidateList::EnumCandidates(_Outptr_ IEnumTfCandidates **ppEnum)
|
||||
{
|
||||
return CEnumTfCandidates::CreateInstance(ppEnum, _tfCandStrList);
|
||||
}
|
||||
|
||||
STDMETHODIMP CTipCandidateList::GetCandidate(ULONG nIndex, _Outptr_result_maybenull_ ITfCandidateString **ppCandStr)
|
||||
{
|
||||
if (ppCandStr == nullptr)
|
||||
{
|
||||
return E_POINTER;
|
||||
}
|
||||
*ppCandStr = nullptr;
|
||||
|
||||
ULONG sizeCandStr = (ULONG)_tfCandStrList.Count();
|
||||
if (sizeCandStr <= nIndex)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
ITfCandidateString **ppCandStrCur = _tfCandStrList.GetAt(static_cast<UINT>(nIndex));
|
||||
if ((ppCandStrCur == nullptr) || (*ppCandStrCur == nullptr))
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
BSTR bstr = nullptr;
|
||||
CTipCandidateString *pTipCandidateStrCur = static_cast<CTipCandidateString *>(*ppCandStrCur);
|
||||
if (FAILED(pTipCandidateStrCur->GetString(&bstr)))
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
CTipCandidateString *pCandidateString = nullptr;
|
||||
const HRESULT hr = CTipCandidateString::CreateInstance(&pCandidateString);
|
||||
if (SUCCEEDED(hr) && (pCandidateString != nullptr))
|
||||
{
|
||||
pCandidateString->SetIndex(nIndex);
|
||||
pCandidateString->SetString((LPCWSTR)bstr, SysStringLen(bstr));
|
||||
*ppCandStr = pCandidateString;
|
||||
}
|
||||
|
||||
SysFreeString(bstr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
STDMETHODIMP CTipCandidateList::GetCandidateNum(_Out_ ULONG *pnCnt)
|
||||
{
|
||||
if (pnCnt == nullptr)
|
||||
{
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
*pnCnt = (ULONG)(_tfCandStrList.Count());
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CTipCandidateList::SetResult(ULONG nIndex, TfCandidateResult imcr)
|
||||
{
|
||||
nIndex;
|
||||
imcr;
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CTipCandidateList::SetCandidate(_In_ ITfCandidateString *pCandStr)
|
||||
{
|
||||
if (pCandStr == nullptr)
|
||||
{
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
ITfCandidateString **ppCandLast = _tfCandStrList.Append();
|
||||
if (ppCandLast)
|
||||
{
|
||||
*ppCandLast = pCandStr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
pCandStr->Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
@@ -1,35 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "Private.h"
|
||||
#include "MetasequoiaIMEBaseStructure.h"
|
||||
|
||||
//
|
||||
// CTipCandidateList
|
||||
//
|
||||
|
||||
class CTipCandidateList : public ITfCandidateList
|
||||
{
|
||||
protected:
|
||||
CTipCandidateList(size_t candStrReserveSize);
|
||||
virtual ~CTipCandidateList();
|
||||
|
||||
public:
|
||||
static HRESULT CreateInstance(_Outptr_ ITfCandidateList **ppobj, size_t candStrReserveSize = 0);
|
||||
|
||||
// IUnknown methods
|
||||
virtual STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj);
|
||||
virtual STDMETHODIMP_(ULONG) AddRef();
|
||||
virtual STDMETHODIMP_(ULONG) Release();
|
||||
|
||||
// ITfCandidateList methods
|
||||
virtual STDMETHODIMP EnumCandidates(_Outptr_ IEnumTfCandidates **ppEnum);
|
||||
virtual STDMETHODIMP GetCandidate(ULONG nIndex, _Outptr_result_maybenull_ ITfCandidateString **ppCandStr);
|
||||
virtual STDMETHODIMP GetCandidateNum(_Out_ ULONG *pnCnt);
|
||||
virtual STDMETHODIMP SetResult(ULONG nIndex, TfCandidateResult imcr);
|
||||
|
||||
virtual STDMETHODIMP SetCandidate(_In_ ITfCandidateString *pCandStr);
|
||||
|
||||
protected:
|
||||
long _refCount;
|
||||
CMetasequoiaImeArray<ITfCandidateString *> _tfCandStrList;
|
||||
};
|
||||
#pragma once
|
||||
|
||||
#include "Private.h"
|
||||
#include "MetasequoiaIMEBaseStructure.h"
|
||||
|
||||
//
|
||||
// CTipCandidateList
|
||||
//
|
||||
|
||||
class CTipCandidateList : public ITfCandidateList
|
||||
{
|
||||
protected:
|
||||
CTipCandidateList(size_t candStrReserveSize);
|
||||
virtual ~CTipCandidateList();
|
||||
|
||||
public:
|
||||
static HRESULT CreateInstance(_Outptr_ ITfCandidateList **ppobj, size_t candStrReserveSize = 0);
|
||||
|
||||
// IUnknown methods
|
||||
virtual STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj);
|
||||
virtual STDMETHODIMP_(ULONG) AddRef();
|
||||
virtual STDMETHODIMP_(ULONG) Release();
|
||||
|
||||
// ITfCandidateList methods
|
||||
virtual STDMETHODIMP EnumCandidates(_Outptr_ IEnumTfCandidates **ppEnum);
|
||||
virtual STDMETHODIMP GetCandidate(ULONG nIndex, _Outptr_result_maybenull_ ITfCandidateString **ppCandStr);
|
||||
virtual STDMETHODIMP GetCandidateNum(_Out_ ULONG *pnCnt);
|
||||
virtual STDMETHODIMP SetResult(ULONG nIndex, TfCandidateResult imcr);
|
||||
|
||||
virtual STDMETHODIMP SetCandidate(_In_ ITfCandidateString *pCandStr);
|
||||
|
||||
protected:
|
||||
long _refCount;
|
||||
CMetasequoiaImeArray<ITfCandidateString *> _tfCandStrList;
|
||||
};
|
||||
@@ -1,105 +1,105 @@
|
||||
#include "Private.h"
|
||||
#include "TipCandidateString.h"
|
||||
|
||||
HRESULT CTipCandidateString::CreateInstance(_Outptr_ CTipCandidateString **ppobj)
|
||||
{
|
||||
if (ppobj == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*ppobj = nullptr;
|
||||
|
||||
*ppobj = new (std::nothrow) CTipCandidateString();
|
||||
if (*ppobj == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
(*ppobj)->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
CTipCandidateString::CTipCandidateString(void)
|
||||
{
|
||||
_refCount = 0;
|
||||
_index = 0;
|
||||
}
|
||||
|
||||
CTipCandidateString::~CTipCandidateString()
|
||||
{
|
||||
}
|
||||
|
||||
// IUnknown methods
|
||||
STDMETHODIMP CTipCandidateString::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
|
||||
{
|
||||
if (ppvObj == nullptr)
|
||||
{
|
||||
return E_POINTER;
|
||||
}
|
||||
*ppvObj = nullptr;
|
||||
|
||||
if (IsEqualIID(riid, IID_IUnknown))
|
||||
{
|
||||
*ppvObj = (CTipCandidateString *)this;
|
||||
}
|
||||
else if (IsEqualIID(riid, IID_ITfCandidateString))
|
||||
{
|
||||
*ppvObj = (CTipCandidateString *)this;
|
||||
}
|
||||
|
||||
if (*ppvObj == nullptr)
|
||||
{
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) CTipCandidateString::AddRef(void)
|
||||
{
|
||||
return (ULONG)InterlockedIncrement((LONG *)&_refCount);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) CTipCandidateString::Release(void)
|
||||
{
|
||||
ULONG refT = (ULONG)InterlockedDecrement((LONG *)&_refCount);
|
||||
if (0 < refT)
|
||||
{
|
||||
return refT;
|
||||
}
|
||||
|
||||
delete this;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ITfCandidateString methods
|
||||
STDMETHODIMP CTipCandidateString::GetString(BSTR *pbstr)
|
||||
{
|
||||
*pbstr = SysAllocString(_candidateStr.c_str());
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CTipCandidateString::GetIndex(_Out_ ULONG *pnIndex)
|
||||
{
|
||||
if (pnIndex == nullptr)
|
||||
{
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
*pnIndex = _index;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CTipCandidateString::SetIndex(ULONG uIndex)
|
||||
{
|
||||
_index = uIndex;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CTipCandidateString::SetString(_In_ const WCHAR *pch, DWORD_PTR length)
|
||||
{
|
||||
_candidateStr.assign(pch, 0, length);
|
||||
return S_OK;
|
||||
}
|
||||
#include "Private.h"
|
||||
#include "TipCandidateString.h"
|
||||
|
||||
HRESULT CTipCandidateString::CreateInstance(_Outptr_ CTipCandidateString **ppobj)
|
||||
{
|
||||
if (ppobj == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*ppobj = nullptr;
|
||||
|
||||
*ppobj = new (std::nothrow) CTipCandidateString();
|
||||
if (*ppobj == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
(*ppobj)->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
CTipCandidateString::CTipCandidateString(void)
|
||||
{
|
||||
_refCount = 0;
|
||||
_index = 0;
|
||||
}
|
||||
|
||||
CTipCandidateString::~CTipCandidateString()
|
||||
{
|
||||
}
|
||||
|
||||
// IUnknown methods
|
||||
STDMETHODIMP CTipCandidateString::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
|
||||
{
|
||||
if (ppvObj == nullptr)
|
||||
{
|
||||
return E_POINTER;
|
||||
}
|
||||
*ppvObj = nullptr;
|
||||
|
||||
if (IsEqualIID(riid, IID_IUnknown))
|
||||
{
|
||||
*ppvObj = (CTipCandidateString *)this;
|
||||
}
|
||||
else if (IsEqualIID(riid, IID_ITfCandidateString))
|
||||
{
|
||||
*ppvObj = (CTipCandidateString *)this;
|
||||
}
|
||||
|
||||
if (*ppvObj == nullptr)
|
||||
{
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) CTipCandidateString::AddRef(void)
|
||||
{
|
||||
return (ULONG)InterlockedIncrement((LONG *)&_refCount);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) CTipCandidateString::Release(void)
|
||||
{
|
||||
ULONG refT = (ULONG)InterlockedDecrement((LONG *)&_refCount);
|
||||
if (0 < refT)
|
||||
{
|
||||
return refT;
|
||||
}
|
||||
|
||||
delete this;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ITfCandidateString methods
|
||||
STDMETHODIMP CTipCandidateString::GetString(BSTR *pbstr)
|
||||
{
|
||||
*pbstr = SysAllocString(_candidateStr.c_str());
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CTipCandidateString::GetIndex(_Out_ ULONG *pnIndex)
|
||||
{
|
||||
if (pnIndex == nullptr)
|
||||
{
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
*pnIndex = _index;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CTipCandidateString::SetIndex(ULONG uIndex)
|
||||
{
|
||||
_index = uIndex;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CTipCandidateString::SetString(_In_ const WCHAR *pch, DWORD_PTR length)
|
||||
{
|
||||
_candidateStr.assign(pch, 0, length);
|
||||
return S_OK;
|
||||
}
|
||||
@@ -1,31 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include "Private.h"
|
||||
#include <string>
|
||||
|
||||
class CTipCandidateString : public ITfCandidateString
|
||||
{
|
||||
protected:
|
||||
CTipCandidateString();
|
||||
virtual ~CTipCandidateString();
|
||||
|
||||
public:
|
||||
static HRESULT CreateInstance(_Outptr_ CTipCandidateString **ppobj);
|
||||
|
||||
// IUnknown methods
|
||||
virtual STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj);
|
||||
virtual STDMETHODIMP_(ULONG) AddRef();
|
||||
virtual STDMETHODIMP_(ULONG) Release();
|
||||
|
||||
// ITfCandidateString methods
|
||||
virtual STDMETHODIMP GetString(BSTR *pbstr);
|
||||
virtual STDMETHODIMP GetIndex(_Out_ ULONG *pnIndex);
|
||||
|
||||
virtual STDMETHODIMP SetIndex(ULONG uIndex);
|
||||
virtual STDMETHODIMP SetString(_In_ const WCHAR *pch, DWORD_PTR length);
|
||||
|
||||
protected:
|
||||
long _refCount;
|
||||
int _index;
|
||||
std::wstring _candidateStr;
|
||||
};
|
||||
#pragma once
|
||||
|
||||
#include "Private.h"
|
||||
#include <string>
|
||||
|
||||
class CTipCandidateString : public ITfCandidateString
|
||||
{
|
||||
protected:
|
||||
CTipCandidateString();
|
||||
virtual ~CTipCandidateString();
|
||||
|
||||
public:
|
||||
static HRESULT CreateInstance(_Outptr_ CTipCandidateString **ppobj);
|
||||
|
||||
// IUnknown methods
|
||||
virtual STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj);
|
||||
virtual STDMETHODIMP_(ULONG) AddRef();
|
||||
virtual STDMETHODIMP_(ULONG) Release();
|
||||
|
||||
// ITfCandidateString methods
|
||||
virtual STDMETHODIMP GetString(BSTR *pbstr);
|
||||
virtual STDMETHODIMP GetIndex(_Out_ ULONG *pnIndex);
|
||||
|
||||
virtual STDMETHODIMP SetIndex(ULONG uIndex);
|
||||
virtual STDMETHODIMP SetString(_In_ const WCHAR *pch, DWORD_PTR length);
|
||||
|
||||
protected:
|
||||
long _refCount;
|
||||
int _index;
|
||||
std::wstring _candidateStr;
|
||||
};
|
||||
@@ -1,363 +1,363 @@
|
||||
#include "Private.h"
|
||||
#include "Compartment.h"
|
||||
#include "Globals.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CCompartment
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
// ctor
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CCompartment::CCompartment(_In_ IUnknown *punk, TfClientId tfClientId, _In_ REFGUID guidCompartment)
|
||||
{
|
||||
_guidCompartment = guidCompartment;
|
||||
|
||||
_punk = punk;
|
||||
_punk->AddRef();
|
||||
|
||||
_tfClientId = tfClientId;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
// dtor
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CCompartment::~CCompartment()
|
||||
{
|
||||
_punk->Release();
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
// _GetCompartment
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CCompartment::_GetCompartment(_Outptr_ ITfCompartment **ppCompartment)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
ITfCompartmentMgr *pCompartmentMgr = nullptr;
|
||||
|
||||
hr = _punk->QueryInterface(IID_ITfCompartmentMgr, (void **)&pCompartmentMgr);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pCompartmentMgr->GetCompartment(_guidCompartment, ppCompartment);
|
||||
pCompartmentMgr->Release();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
// _GetCompartmentBOOL
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CCompartment::_GetCompartmentBOOL(_Out_ BOOL &flag)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
ITfCompartment *pCompartment = nullptr;
|
||||
flag = FALSE;
|
||||
|
||||
if ((hr = _GetCompartment(&pCompartment)) == S_OK)
|
||||
{
|
||||
VARIANT var;
|
||||
if ((hr = pCompartment->GetValue(&var)) == S_OK)
|
||||
{
|
||||
if (var.vt == VT_I4) // Even VT_EMPTY, GetValue() can succeed
|
||||
{
|
||||
flag = (BOOL)var.lVal;
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = S_FALSE;
|
||||
}
|
||||
}
|
||||
pCompartment->Release();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
// _SetCompartmentBOOL
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CCompartment::_SetCompartmentBOOL(_In_ BOOL flag)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
ITfCompartment *pCompartment = nullptr;
|
||||
|
||||
hr = _GetCompartment(&pCompartment);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
VARIANT var;
|
||||
var.vt = VT_I4;
|
||||
var.lVal = flag;
|
||||
hr = pCompartment->SetValue(_tfClientId, &var);
|
||||
pCompartment->Release();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
// _GetCompartmentDWORD
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CCompartment::_GetCompartmentDWORD(_Out_ DWORD &dw)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
ITfCompartment *pCompartment = nullptr;
|
||||
dw = 0;
|
||||
|
||||
hr = _GetCompartment(&pCompartment);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
VARIANT var;
|
||||
if ((hr = pCompartment->GetValue(&var)) == S_OK)
|
||||
{
|
||||
if (var.vt == VT_I4) // Even VT_EMPTY, GetValue() can succeed
|
||||
{
|
||||
dw = (DWORD)var.lVal;
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = S_FALSE;
|
||||
}
|
||||
}
|
||||
pCompartment->Release();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
// _SetCompartmentDWORD
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CCompartment::_SetCompartmentDWORD(_In_ DWORD dw)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
ITfCompartment *pCompartment = nullptr;
|
||||
|
||||
hr = _GetCompartment(&pCompartment);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
VARIANT var;
|
||||
var.vt = VT_I4;
|
||||
var.lVal = dw;
|
||||
hr = pCompartment->SetValue(_tfClientId, &var);
|
||||
pCompartment->Release();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _ClearCompartment
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CCompartment::_ClearCompartment()
|
||||
{
|
||||
if (IsEqualGUID(_guidCompartment, GUID_COMPARTMENT_KEYBOARD_OPENCLOSE))
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
ITfCompartmentMgr *pCompartmentMgr = nullptr;
|
||||
|
||||
if ((hr = _punk->QueryInterface(IID_ITfCompartmentMgr, (void **)&pCompartmentMgr)) == S_OK)
|
||||
{
|
||||
hr = pCompartmentMgr->ClearCompartment(_tfClientId, _guidCompartment);
|
||||
pCompartmentMgr->Release();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CCompartmentEventSink
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
// ctor
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CCompartmentEventSink::CCompartmentEventSink(_In_ CESCALLBACK pfnCallback, _In_ void *pv)
|
||||
{
|
||||
_pCompartment = nullptr;
|
||||
_dwCookie = TF_INVALID_COOKIE;
|
||||
_pfnCallback = pfnCallback;
|
||||
_pv = pv;
|
||||
_refCount = 1;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
// dtor
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CCompartmentEventSink::~CCompartmentEventSink()
|
||||
{
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// QueryInterface
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CCompartmentEventSink::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
|
||||
{
|
||||
if (ppvObj == nullptr)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*ppvObj = nullptr;
|
||||
|
||||
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfCompartmentEventSink))
|
||||
{
|
||||
*ppvObj = (CCompartmentEventSink *)this;
|
||||
}
|
||||
|
||||
if (*ppvObj)
|
||||
{
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// AddRef
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI_(ULONG) CCompartmentEventSink::AddRef()
|
||||
{
|
||||
return ++_refCount;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// Release
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI_(ULONG) CCompartmentEventSink::Release()
|
||||
{
|
||||
LONG cr = --_refCount;
|
||||
|
||||
assert(_refCount >= 0);
|
||||
|
||||
if (_refCount == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
return cr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// OnChange
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CCompartmentEventSink::OnChange(_In_ REFGUID guidCompartment)
|
||||
{
|
||||
return _pfnCallback(_pv, guidCompartment);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _Advise
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CCompartmentEventSink::_Advise(_In_ IUnknown *punk, _In_ REFGUID guidCompartment)
|
||||
{
|
||||
if (!punk)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
if (_pCompartment)
|
||||
{
|
||||
_Unadvise();
|
||||
}
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
ITfCompartmentMgr *pCompartmentMgr = nullptr;
|
||||
ITfSource *pSource = nullptr;
|
||||
|
||||
hr = punk->QueryInterface(IID_ITfCompartmentMgr, (void **)&pCompartmentMgr);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = pCompartmentMgr->GetCompartment(guidCompartment, &_pCompartment);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = _pCompartment->QueryInterface(IID_ITfSource, (void **)&pSource);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pSource->AdviseSink(IID_ITfCompartmentEventSink, this, &_dwCookie);
|
||||
pSource->Release();
|
||||
}
|
||||
}
|
||||
|
||||
pCompartmentMgr->Release();
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
if (_pCompartment)
|
||||
{
|
||||
_pCompartment->Release();
|
||||
_pCompartment = nullptr;
|
||||
}
|
||||
_dwCookie = TF_INVALID_COOKIE;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _Unadvise
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CCompartmentEventSink::_Unadvise()
|
||||
{
|
||||
if (!_pCompartment)
|
||||
{
|
||||
_dwCookie = TF_INVALID_COOKIE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
ITfSource *pSource = nullptr;
|
||||
|
||||
if (_dwCookie != TF_INVALID_COOKIE)
|
||||
{
|
||||
hr = _pCompartment->QueryInterface(IID_ITfSource, (void **)&pSource);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pSource->UnadviseSink(_dwCookie);
|
||||
pSource->Release();
|
||||
}
|
||||
}
|
||||
|
||||
_pCompartment->Release();
|
||||
_pCompartment = nullptr;
|
||||
_dwCookie = TF_INVALID_COOKIE;
|
||||
|
||||
return hr;
|
||||
}
|
||||
#include "Private.h"
|
||||
#include "Compartment.h"
|
||||
#include "Globals.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CCompartment
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
// ctor
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CCompartment::CCompartment(_In_ IUnknown *punk, TfClientId tfClientId, _In_ REFGUID guidCompartment)
|
||||
{
|
||||
_guidCompartment = guidCompartment;
|
||||
|
||||
_punk = punk;
|
||||
_punk->AddRef();
|
||||
|
||||
_tfClientId = tfClientId;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
// dtor
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CCompartment::~CCompartment()
|
||||
{
|
||||
_punk->Release();
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
// _GetCompartment
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CCompartment::_GetCompartment(_Outptr_ ITfCompartment **ppCompartment)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
ITfCompartmentMgr *pCompartmentMgr = nullptr;
|
||||
|
||||
hr = _punk->QueryInterface(IID_ITfCompartmentMgr, (void **)&pCompartmentMgr);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pCompartmentMgr->GetCompartment(_guidCompartment, ppCompartment);
|
||||
pCompartmentMgr->Release();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
// _GetCompartmentBOOL
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CCompartment::_GetCompartmentBOOL(_Out_ BOOL &flag)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
ITfCompartment *pCompartment = nullptr;
|
||||
flag = FALSE;
|
||||
|
||||
if ((hr = _GetCompartment(&pCompartment)) == S_OK)
|
||||
{
|
||||
VARIANT var;
|
||||
if ((hr = pCompartment->GetValue(&var)) == S_OK)
|
||||
{
|
||||
if (var.vt == VT_I4) // Even VT_EMPTY, GetValue() can succeed
|
||||
{
|
||||
flag = (BOOL)var.lVal;
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = S_FALSE;
|
||||
}
|
||||
}
|
||||
pCompartment->Release();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
// _SetCompartmentBOOL
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CCompartment::_SetCompartmentBOOL(_In_ BOOL flag)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
ITfCompartment *pCompartment = nullptr;
|
||||
|
||||
hr = _GetCompartment(&pCompartment);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
VARIANT var;
|
||||
var.vt = VT_I4;
|
||||
var.lVal = flag;
|
||||
hr = pCompartment->SetValue(_tfClientId, &var);
|
||||
pCompartment->Release();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
// _GetCompartmentDWORD
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CCompartment::_GetCompartmentDWORD(_Out_ DWORD &dw)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
ITfCompartment *pCompartment = nullptr;
|
||||
dw = 0;
|
||||
|
||||
hr = _GetCompartment(&pCompartment);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
VARIANT var;
|
||||
if ((hr = pCompartment->GetValue(&var)) == S_OK)
|
||||
{
|
||||
if (var.vt == VT_I4) // Even VT_EMPTY, GetValue() can succeed
|
||||
{
|
||||
dw = (DWORD)var.lVal;
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = S_FALSE;
|
||||
}
|
||||
}
|
||||
pCompartment->Release();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
// _SetCompartmentDWORD
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CCompartment::_SetCompartmentDWORD(_In_ DWORD dw)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
ITfCompartment *pCompartment = nullptr;
|
||||
|
||||
hr = _GetCompartment(&pCompartment);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
VARIANT var;
|
||||
var.vt = VT_I4;
|
||||
var.lVal = dw;
|
||||
hr = pCompartment->SetValue(_tfClientId, &var);
|
||||
pCompartment->Release();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _ClearCompartment
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CCompartment::_ClearCompartment()
|
||||
{
|
||||
if (IsEqualGUID(_guidCompartment, GUID_COMPARTMENT_KEYBOARD_OPENCLOSE))
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
ITfCompartmentMgr *pCompartmentMgr = nullptr;
|
||||
|
||||
if ((hr = _punk->QueryInterface(IID_ITfCompartmentMgr, (void **)&pCompartmentMgr)) == S_OK)
|
||||
{
|
||||
hr = pCompartmentMgr->ClearCompartment(_tfClientId, _guidCompartment);
|
||||
pCompartmentMgr->Release();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CCompartmentEventSink
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
// ctor
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CCompartmentEventSink::CCompartmentEventSink(_In_ CESCALLBACK pfnCallback, _In_ void *pv)
|
||||
{
|
||||
_pCompartment = nullptr;
|
||||
_dwCookie = TF_INVALID_COOKIE;
|
||||
_pfnCallback = pfnCallback;
|
||||
_pv = pv;
|
||||
_refCount = 1;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
// dtor
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CCompartmentEventSink::~CCompartmentEventSink()
|
||||
{
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// QueryInterface
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CCompartmentEventSink::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
|
||||
{
|
||||
if (ppvObj == nullptr)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*ppvObj = nullptr;
|
||||
|
||||
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfCompartmentEventSink))
|
||||
{
|
||||
*ppvObj = (CCompartmentEventSink *)this;
|
||||
}
|
||||
|
||||
if (*ppvObj)
|
||||
{
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// AddRef
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI_(ULONG) CCompartmentEventSink::AddRef()
|
||||
{
|
||||
return ++_refCount;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// Release
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI_(ULONG) CCompartmentEventSink::Release()
|
||||
{
|
||||
LONG cr = --_refCount;
|
||||
|
||||
assert(_refCount >= 0);
|
||||
|
||||
if (_refCount == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
return cr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// OnChange
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CCompartmentEventSink::OnChange(_In_ REFGUID guidCompartment)
|
||||
{
|
||||
return _pfnCallback(_pv, guidCompartment);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _Advise
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CCompartmentEventSink::_Advise(_In_ IUnknown *punk, _In_ REFGUID guidCompartment)
|
||||
{
|
||||
if (!punk)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
if (_pCompartment)
|
||||
{
|
||||
_Unadvise();
|
||||
}
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
ITfCompartmentMgr *pCompartmentMgr = nullptr;
|
||||
ITfSource *pSource = nullptr;
|
||||
|
||||
hr = punk->QueryInterface(IID_ITfCompartmentMgr, (void **)&pCompartmentMgr);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = pCompartmentMgr->GetCompartment(guidCompartment, &_pCompartment);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = _pCompartment->QueryInterface(IID_ITfSource, (void **)&pSource);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pSource->AdviseSink(IID_ITfCompartmentEventSink, this, &_dwCookie);
|
||||
pSource->Release();
|
||||
}
|
||||
}
|
||||
|
||||
pCompartmentMgr->Release();
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
if (_pCompartment)
|
||||
{
|
||||
_pCompartment->Release();
|
||||
_pCompartment = nullptr;
|
||||
}
|
||||
_dwCookie = TF_INVALID_COOKIE;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _Unadvise
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CCompartmentEventSink::_Unadvise()
|
||||
{
|
||||
if (!_pCompartment)
|
||||
{
|
||||
_dwCookie = TF_INVALID_COOKIE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
ITfSource *pSource = nullptr;
|
||||
|
||||
if (_dwCookie != TF_INVALID_COOKIE)
|
||||
{
|
||||
hr = _pCompartment->QueryInterface(IID_ITfSource, (void **)&pSource);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pSource->UnadviseSink(_dwCookie);
|
||||
pSource->Release();
|
||||
}
|
||||
}
|
||||
|
||||
_pCompartment->Release();
|
||||
_pCompartment = nullptr;
|
||||
_dwCookie = TF_INVALID_COOKIE;
|
||||
|
||||
return hr;
|
||||
}
|
||||
@@ -1,56 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include "Private.h"
|
||||
|
||||
class CCompartment
|
||||
{
|
||||
public:
|
||||
CCompartment(_In_ IUnknown *punk, TfClientId tfClientId, _In_ REFGUID guidCompartment);
|
||||
~CCompartment();
|
||||
|
||||
HRESULT _GetCompartment(_Outptr_ ITfCompartment **ppCompartment);
|
||||
HRESULT _GetCompartmentBOOL(_Out_ BOOL &flag);
|
||||
HRESULT _SetCompartmentBOOL(_In_ BOOL flag);
|
||||
HRESULT _GetCompartmentDWORD(_Out_ DWORD &dw);
|
||||
HRESULT _SetCompartmentDWORD(_In_ DWORD dw);
|
||||
HRESULT _ClearCompartment();
|
||||
|
||||
VOID _GetGUID(GUID *pguid)
|
||||
{
|
||||
*pguid = _guidCompartment;
|
||||
}
|
||||
|
||||
private:
|
||||
GUID _guidCompartment;
|
||||
IUnknown *_punk;
|
||||
TfClientId _tfClientId;
|
||||
};
|
||||
|
||||
typedef HRESULT (*CESCALLBACK)(void *pv, REFGUID guidCompartment);
|
||||
|
||||
class CCompartmentEventSink : public ITfCompartmentEventSink
|
||||
{
|
||||
public:
|
||||
CCompartmentEventSink(_In_ CESCALLBACK pfnCallback, _In_ void *pv);
|
||||
~CCompartmentEventSink();
|
||||
|
||||
// IUnknown
|
||||
STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj);
|
||||
STDMETHODIMP_(ULONG) AddRef(void);
|
||||
STDMETHODIMP_(ULONG) Release(void);
|
||||
|
||||
// ITfCompartmentEventSink
|
||||
STDMETHODIMP OnChange(_In_ REFGUID guid);
|
||||
|
||||
// function
|
||||
HRESULT _Advise(_In_ IUnknown *punk, _In_ REFGUID guidCompartment);
|
||||
HRESULT _Unadvise();
|
||||
|
||||
private:
|
||||
ITfCompartment *_pCompartment;
|
||||
DWORD _dwCookie;
|
||||
CESCALLBACK _pfnCallback;
|
||||
void *_pv;
|
||||
|
||||
LONG _refCount;
|
||||
};
|
||||
#pragma once
|
||||
|
||||
#include "Private.h"
|
||||
|
||||
class CCompartment
|
||||
{
|
||||
public:
|
||||
CCompartment(_In_ IUnknown *punk, TfClientId tfClientId, _In_ REFGUID guidCompartment);
|
||||
~CCompartment();
|
||||
|
||||
HRESULT _GetCompartment(_Outptr_ ITfCompartment **ppCompartment);
|
||||
HRESULT _GetCompartmentBOOL(_Out_ BOOL &flag);
|
||||
HRESULT _SetCompartmentBOOL(_In_ BOOL flag);
|
||||
HRESULT _GetCompartmentDWORD(_Out_ DWORD &dw);
|
||||
HRESULT _SetCompartmentDWORD(_In_ DWORD dw);
|
||||
HRESULT _ClearCompartment();
|
||||
|
||||
VOID _GetGUID(GUID *pguid)
|
||||
{
|
||||
*pguid = _guidCompartment;
|
||||
}
|
||||
|
||||
private:
|
||||
GUID _guidCompartment;
|
||||
IUnknown *_punk;
|
||||
TfClientId _tfClientId;
|
||||
};
|
||||
|
||||
typedef HRESULT (*CESCALLBACK)(void *pv, REFGUID guidCompartment);
|
||||
|
||||
class CCompartmentEventSink : public ITfCompartmentEventSink
|
||||
{
|
||||
public:
|
||||
CCompartmentEventSink(_In_ CESCALLBACK pfnCallback, _In_ void *pv);
|
||||
~CCompartmentEventSink();
|
||||
|
||||
// IUnknown
|
||||
STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj);
|
||||
STDMETHODIMP_(ULONG) AddRef(void);
|
||||
STDMETHODIMP_(ULONG) Release(void);
|
||||
|
||||
// ITfCompartmentEventSink
|
||||
STDMETHODIMP OnChange(_In_ REFGUID guid);
|
||||
|
||||
// function
|
||||
HRESULT _Advise(_In_ IUnknown *punk, _In_ REFGUID guidCompartment);
|
||||
HRESULT _Unadvise();
|
||||
|
||||
private:
|
||||
ITfCompartment *_pCompartment;
|
||||
DWORD _dwCookie;
|
||||
CESCALLBACK _pfnCallback;
|
||||
void *_pv;
|
||||
|
||||
LONG _refCount;
|
||||
};
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,290 +1,290 @@
|
||||
#pragma once
|
||||
|
||||
#include "MetasequoiaIME.h"
|
||||
#include "sal.h"
|
||||
#include "KeyHandlerEditSession.h"
|
||||
#include "MetasequoiaIMEBaseStructure.h"
|
||||
#include "Compartment.h"
|
||||
#include "define.h"
|
||||
|
||||
class CCompositionProcessorEngine
|
||||
{
|
||||
friend class CMetasequoiaIME;
|
||||
|
||||
public:
|
||||
enum class PreservedKeyAction
|
||||
{
|
||||
None,
|
||||
ToggleImeMode,
|
||||
ToggleDoubleSingleByteMode,
|
||||
TogglePunctuationMode
|
||||
};
|
||||
|
||||
explicit CCompositionProcessorEngine(_In_ CMetasequoiaIME *pTextService);
|
||||
~CCompositionProcessorEngine(void);
|
||||
|
||||
BOOL SetupLanguageProfile(LANGID langid, REFGUID guidLanguageProfile, _In_ ITfThreadMgr *pThreadMgr,
|
||||
TfClientId tfClientId, BOOL isSecureMode, BOOL isComLessMode);
|
||||
|
||||
// Get language profile.
|
||||
GUID GetLanguageProfile(LANGID *plangid)
|
||||
{
|
||||
*plangid = _langid;
|
||||
return _guidProfile;
|
||||
}
|
||||
// Get locale
|
||||
LCID GetLocale()
|
||||
{
|
||||
return MAKELCID(_langid, SORT_DEFAULT);
|
||||
}
|
||||
|
||||
BOOL IsVirtualKeyNeed(UINT uCode, _In_reads_(1) WCHAR *pwch, BOOL fComposing, CANDIDATE_MODE candidateMode,
|
||||
BOOL hasCandidateWithWildcard, _Out_opt_ _KEYSTROKE_STATE *pKeyState);
|
||||
BOOL IsVirtualKeyNeedForFreshComposition(UINT uCode, _In_reads_(1) WCHAR *pwch,
|
||||
_Out_opt_ _KEYSTROKE_STATE *pKeyState);
|
||||
|
||||
BOOL AddVirtualKey(WCHAR wch);
|
||||
void RemoveVirtualKey(DWORD_PTR dwIndex);
|
||||
BOOL RemoveVirtualKeyBeforeCaret();
|
||||
BOOL RemoveVirtualKeyAtCaret();
|
||||
void PurgeVirtualKey();
|
||||
BOOL MoveCaret(int offset);
|
||||
DWORD_PTR GetCaretPosition() const
|
||||
{
|
||||
return _caretPosition;
|
||||
}
|
||||
void SetRenderedPreedit(std::wstring preedit, size_t prefixLength);
|
||||
DWORD_PTR GetRenderedCaretPosition() const;
|
||||
|
||||
DWORD_PTR GetVirtualKeyLength()
|
||||
{
|
||||
return _keystrokeBuffer.GetLength();
|
||||
}
|
||||
CStringRange &GetKeystrokeBuffer()
|
||||
{
|
||||
return _keystrokeBuffer;
|
||||
};
|
||||
WCHAR GetVirtualKey(DWORD_PTR dwIndex);
|
||||
// Shift+U unicode input: composition buffer starts with 'U'.
|
||||
BOOL IsUnicodeModeComposition() const;
|
||||
|
||||
void GetReadingStrings( //
|
||||
_Inout_ CMetasequoiaImeArray<CStringRange> *pReadingStrings, //
|
||||
_Out_ BOOL *pIsWildcardIncluded //
|
||||
);
|
||||
void GetCandidateList( //
|
||||
_Inout_ CMetasequoiaImeArray<CCandidateListItem> *pCandidateList, //
|
||||
BOOL isIncrementalWordSearch, BOOL isWildcardSearch //
|
||||
);
|
||||
|
||||
// Preserved key handler
|
||||
BOOL IsPreservedKeyEligible(REFGUID rguid);
|
||||
PreservedKeyAction GetPreservedKeyAction(REFGUID rguid) const;
|
||||
void OnPreservedKey(ITfContext *pContext, REFGUID rguid, _Out_ BOOL *pIsEaten, _In_ ITfThreadMgr *pThreadMgr,
|
||||
TfClientId tfClientId, BOOL *pNeedToggleIMEMode, BOOL isPrevalidated = FALSE,
|
||||
BOOL notifyServer = TRUE);
|
||||
|
||||
// Toggle IME Mode
|
||||
void ToggleIMEMode(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId);
|
||||
void SetIMEMode(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId, BOOL bOpen);
|
||||
BOOL CCompositionProcessorEngine::GetIMEMode(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId);
|
||||
// Apply CN/EN compartment change deferred until after composition commit.
|
||||
// Closing KEYBOARD_OPENCLOSE before EndComposition makes CUAS/Win32 EDIT
|
||||
// finalize the same preedit twice (Chrome/TSF-only hosts are unaffected).
|
||||
void ApplyPendingImeModeAfterCompositionCommit(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId);
|
||||
void SetPunctuationMode(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId, BOOL bOpen);
|
||||
BOOL GetPunctuationMode(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId);
|
||||
void SetDoubleSingleByteMode(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId, BOOL bOpen);
|
||||
BOOL GetDoubleSingleByteMode(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId);
|
||||
|
||||
// Punctuation
|
||||
BOOL IsPunctuation(WCHAR wch);
|
||||
const WCHAR *GetPunctuation(WCHAR wch);
|
||||
// Smart punctuation (rime digit_separators-style): after ASCII letters/digits,
|
||||
// keep ',' '.' ':' as ASCII instead of mapping to Chinese punctuation.
|
||||
static BOOL IsSmartAsciiPunctuationKey(WCHAR wch);
|
||||
std::wstring ResolvePunctuation(WCHAR wch, WCHAR precedingChar);
|
||||
|
||||
BOOL IsDoubleSingleByte(WCHAR wch);
|
||||
BOOL IsWildcard()
|
||||
{
|
||||
return _isWildcard;
|
||||
}
|
||||
BOOL IsDisableWildcardAtFirst()
|
||||
{
|
||||
return _isDisableWildcardAtFirst;
|
||||
}
|
||||
BOOL IsWildcardChar(WCHAR wch)
|
||||
{
|
||||
return ((IsWildcardOneChar(wch) || IsWildcardAllChar(wch)) ? TRUE : FALSE);
|
||||
}
|
||||
BOOL IsWildcardOneChar(WCHAR wch)
|
||||
{
|
||||
return (wch == L'?' ? TRUE : FALSE);
|
||||
}
|
||||
BOOL IsWildcardAllChar(WCHAR wch)
|
||||
{
|
||||
return (wch == L'*' ? TRUE : FALSE);
|
||||
}
|
||||
BOOL IsKeystrokeSort()
|
||||
{
|
||||
return _isKeystrokeSort;
|
||||
}
|
||||
|
||||
// Language bar control
|
||||
void SetLanguageBarStatus(DWORD status, BOOL isSet);
|
||||
|
||||
void ConversionModeCompartmentUpdated(_In_ ITfThreadMgr *pThreadMgr);
|
||||
|
||||
void ShowAllLanguageBarIcons();
|
||||
void HideAllLanguageBarIcons();
|
||||
void RefreshLanguageBarIcons();
|
||||
|
||||
inline CCandidateRange *GetCandidateListIndexRange()
|
||||
{
|
||||
return &_candidateListIndexRange;
|
||||
}
|
||||
inline UINT GetCandidateListPhraseModifier()
|
||||
{
|
||||
return _candidateListPhraseModifier;
|
||||
}
|
||||
inline UINT GetCandidateWindowWidth()
|
||||
{
|
||||
return _candidateWndWidth;
|
||||
}
|
||||
|
||||
private:
|
||||
void InitKeyStrokeTable();
|
||||
BOOL InitLanguageBar(_In_ CLangBarItemButton *pLanguageBar, _In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId,
|
||||
REFGUID guidCompartment);
|
||||
|
||||
struct _KEYSTROKE;
|
||||
BOOL IsVirtualKeyKeystrokeComposition(UINT uCode, _Out_opt_ _KEYSTROKE_STATE *pKeyState,
|
||||
KEYSTROKE_FUNCTION function);
|
||||
BOOL IsVirtualKeyKeystrokeCandidate(UINT uCode, _In_ _KEYSTROKE_STATE *pKeyState, CANDIDATE_MODE candidateMode,
|
||||
_Out_ BOOL *pfRetCode, _In_ CMetasequoiaImeArray<_KEYSTROKE> *pKeystrokeMetric);
|
||||
BOOL IsKeystrokeRange(UINT uCode, _Out_ _KEYSTROKE_STATE *pKeyState, CANDIDATE_MODE candidateMode);
|
||||
|
||||
void SetupKeystroke();
|
||||
void SetupPreserved(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId);
|
||||
void SetupConfiguration();
|
||||
void SetupLanguageBar(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId, BOOL isSecureMode);
|
||||
void SetKeystrokeTable(_Inout_ CMetasequoiaImeArray<_KEYSTROKE> *pKeystroke);
|
||||
void SetupPunctuationPair();
|
||||
void CreateLanguageBarButton(DWORD dwEnable, GUID guidLangBar, _In_z_ LPCWSTR pwszDescriptionValue,
|
||||
_In_z_ LPCWSTR pwszTooltipValue, DWORD dwOnIconIndex, DWORD dwOffIconIndex,
|
||||
_Outptr_result_maybenull_ CLangBarItemButton **ppLangBarItemButton, BOOL isSecureMode);
|
||||
void SetInitialCandidateListRange();
|
||||
void SetDefaultCandidateTextFont();
|
||||
void InitializeMetasequoiaIMECompartment(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId);
|
||||
|
||||
class XPreservedKey;
|
||||
void SetPreservedKey(const CLSID clsid, TF_PRESERVEDKEY &tfPreservedKey, _In_z_ LPCWSTR pwszDescription,
|
||||
_Out_ XPreservedKey *pXPreservedKey);
|
||||
BOOL InitPreservedKey(_In_ XPreservedKey *pXPreservedKey, _In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId);
|
||||
BOOL CheckShiftKeyOnly(_In_ CMetasequoiaImeArray<TF_PRESERVEDKEY> *pTSFPreservedKeyTable);
|
||||
|
||||
static HRESULT CompartmentCallback(_In_ void *pv, REFGUID guidCompartment);
|
||||
void PrivateCompartmentsUpdated(_In_ ITfThreadMgr *pThreadMgr);
|
||||
void KeyboardOpenCompartmentUpdated(_In_ ITfThreadMgr *pThreadMgr);
|
||||
HRESULT SetKeyboardOpenCompartment(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId, BOOL isOpen);
|
||||
void SyncPunctuationWithImeMode(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId, BOOL isOpen);
|
||||
void CommitCompositionOnExternalKeyboardClose();
|
||||
void ReleaseConfiguredImeModeDefense();
|
||||
|
||||
private:
|
||||
struct _KEYSTROKE
|
||||
{
|
||||
UINT VirtualKey;
|
||||
UINT Modifiers;
|
||||
KEYSTROKE_FUNCTION Function;
|
||||
|
||||
_KEYSTROKE()
|
||||
{
|
||||
VirtualKey = 0;
|
||||
Modifiers = 0;
|
||||
Function = FUNCTION_NONE;
|
||||
}
|
||||
};
|
||||
_KEYSTROKE _keystrokeTable[26];
|
||||
|
||||
CStringRange _keystrokeBuffer;
|
||||
DWORD_PTR _caretPosition = 0;
|
||||
std::wstring _renderedPreedit;
|
||||
size_t _renderedPreeditPrefixLength = 0;
|
||||
|
||||
BOOL _hasWildcardIncludedInKeystrokeBuffer;
|
||||
|
||||
LANGID _langid;
|
||||
GUID _guidProfile;
|
||||
TfClientId _tfClientId;
|
||||
|
||||
CMetasequoiaImeArray<_KEYSTROKE> _KeystrokeComposition;
|
||||
CMetasequoiaImeArray<_KEYSTROKE> _KeystrokeCandidate;
|
||||
CMetasequoiaImeArray<_KEYSTROKE> _KeystrokeCandidateWildcard;
|
||||
CMetasequoiaImeArray<_KEYSTROKE> _KeystrokeCandidateSymbol;
|
||||
CMetasequoiaImeArray<_KEYSTROKE> _KeystrokeSymbol;
|
||||
|
||||
// Preserved key data
|
||||
class XPreservedKey
|
||||
{
|
||||
public:
|
||||
XPreservedKey();
|
||||
~XPreservedKey();
|
||||
BOOL UninitPreservedKey(_In_ ITfThreadMgr *pThreadMgr);
|
||||
|
||||
public:
|
||||
CMetasequoiaImeArray<TF_PRESERVEDKEY> TSFPreservedKeyTable;
|
||||
GUID Guid;
|
||||
LPCWSTR Description;
|
||||
};
|
||||
|
||||
XPreservedKey _PreservedKey_IMEMode;
|
||||
XPreservedKey _PreservedKey_IMEMode02;
|
||||
XPreservedKey _PreservedKey_IMEMode03;
|
||||
XPreservedKey _PreservedKey_EnglishInputMode;
|
||||
XPreservedKey _PreservedKey_DoubleSingleByte;
|
||||
XPreservedKey _PreservedKey_Punctuation;
|
||||
|
||||
// Punctuation data
|
||||
CMetasequoiaImeArray<CPunctuationPair> _PunctuationPair;
|
||||
CMetasequoiaImeArray<CPunctuationNestPair> _PunctuationNestPair;
|
||||
|
||||
// Language bar data
|
||||
CLangBarItemButton *_pLanguageBar_IMEMode;
|
||||
CLangBarItemButton *_pLanguageBar_DoubleSingleByte;
|
||||
CLangBarItemButton *_pLanguageBar_Punctuation;
|
||||
|
||||
// Compartment
|
||||
CCompartment *_pCompartmentConversion;
|
||||
CCompartmentEventSink *_pCompartmentConversionEventSink;
|
||||
CCompartmentEventSink *_pCompartmentKeyboardOpenEventSink;
|
||||
CCompartmentEventSink *_pCompartmentDoubleSingleByteEventSink;
|
||||
CCompartmentEventSink *_pCompartmentPunctuationEventSink;
|
||||
ITfThreadMgr *_pOwnerThreadMgr;
|
||||
HWND _ownerMsgWndHandle;
|
||||
CMetasequoiaIME *_pTextService;
|
||||
BOOL _keyboardOpen;
|
||||
BOOL _keyboardOpenKnown;
|
||||
BOOL _suppressKeyboardCloseCommit;
|
||||
// After Activate applies input.default_ime_mode, Chromium (and Electron)
|
||||
// often rewrites TF_CONVERSIONMODE_* (NATIVE / SYMBOL / FULLSHAPE) while
|
||||
// focus is still on the non-editable shell. ConversionModeCompartmentUpdated
|
||||
// would then mirror those bits into OPENCLOSE and the punctuation /
|
||||
// fullwidth compartments. Defend by reasserting private state until the
|
||||
// user explicitly chooses a mode (Shift / langbar / FTB / preserved key).
|
||||
BOOL _defendConfiguredImeMode;
|
||||
BOOL _hasPendingImeModeAfterCompositionCommit;
|
||||
BOOL _pendingImeModeAfterCompositionCommit;
|
||||
|
||||
// Configuration data
|
||||
BOOL _isWildcard : 1;
|
||||
BOOL _isDisableWildcardAtFirst : 1;
|
||||
BOOL _isKeystrokeSort : 1;
|
||||
BOOL _isComLessMode : 1;
|
||||
CCandidateRange _candidateListIndexRange;
|
||||
UINT _candidateListPhraseModifier;
|
||||
UINT _candidateWndWidth;
|
||||
|
||||
static const int OUT_OF_FILE_INDEX = -1;
|
||||
};
|
||||
#pragma once
|
||||
|
||||
#include "MetasequoiaIME.h"
|
||||
#include "sal.h"
|
||||
#include "KeyHandlerEditSession.h"
|
||||
#include "MetasequoiaIMEBaseStructure.h"
|
||||
#include "Compartment.h"
|
||||
#include "define.h"
|
||||
|
||||
class CCompositionProcessorEngine
|
||||
{
|
||||
friend class CMetasequoiaIME;
|
||||
|
||||
public:
|
||||
enum class PreservedKeyAction
|
||||
{
|
||||
None,
|
||||
ToggleImeMode,
|
||||
ToggleDoubleSingleByteMode,
|
||||
TogglePunctuationMode
|
||||
};
|
||||
|
||||
explicit CCompositionProcessorEngine(_In_ CMetasequoiaIME *pTextService);
|
||||
~CCompositionProcessorEngine(void);
|
||||
|
||||
BOOL SetupLanguageProfile(LANGID langid, REFGUID guidLanguageProfile, _In_ ITfThreadMgr *pThreadMgr,
|
||||
TfClientId tfClientId, BOOL isSecureMode, BOOL isComLessMode);
|
||||
|
||||
// Get language profile.
|
||||
GUID GetLanguageProfile(LANGID *plangid)
|
||||
{
|
||||
*plangid = _langid;
|
||||
return _guidProfile;
|
||||
}
|
||||
// Get locale
|
||||
LCID GetLocale()
|
||||
{
|
||||
return MAKELCID(_langid, SORT_DEFAULT);
|
||||
}
|
||||
|
||||
BOOL IsVirtualKeyNeed(UINT uCode, _In_reads_(1) WCHAR *pwch, BOOL fComposing, CANDIDATE_MODE candidateMode,
|
||||
BOOL hasCandidateWithWildcard, _Out_opt_ _KEYSTROKE_STATE *pKeyState);
|
||||
BOOL IsVirtualKeyNeedForFreshComposition(UINT uCode, _In_reads_(1) WCHAR *pwch,
|
||||
_Out_opt_ _KEYSTROKE_STATE *pKeyState);
|
||||
|
||||
BOOL AddVirtualKey(WCHAR wch);
|
||||
void RemoveVirtualKey(DWORD_PTR dwIndex);
|
||||
BOOL RemoveVirtualKeyBeforeCaret();
|
||||
BOOL RemoveVirtualKeyAtCaret();
|
||||
void PurgeVirtualKey();
|
||||
BOOL MoveCaret(int offset);
|
||||
DWORD_PTR GetCaretPosition() const
|
||||
{
|
||||
return _caretPosition;
|
||||
}
|
||||
void SetRenderedPreedit(std::wstring preedit, size_t prefixLength);
|
||||
DWORD_PTR GetRenderedCaretPosition() const;
|
||||
|
||||
DWORD_PTR GetVirtualKeyLength()
|
||||
{
|
||||
return _keystrokeBuffer.GetLength();
|
||||
}
|
||||
CStringRange &GetKeystrokeBuffer()
|
||||
{
|
||||
return _keystrokeBuffer;
|
||||
};
|
||||
WCHAR GetVirtualKey(DWORD_PTR dwIndex);
|
||||
// Shift+U unicode input: composition buffer starts with 'U'.
|
||||
BOOL IsUnicodeModeComposition() const;
|
||||
|
||||
void GetReadingStrings( //
|
||||
_Inout_ CMetasequoiaImeArray<CStringRange> *pReadingStrings, //
|
||||
_Out_ BOOL *pIsWildcardIncluded //
|
||||
);
|
||||
void GetCandidateList( //
|
||||
_Inout_ CMetasequoiaImeArray<CCandidateListItem> *pCandidateList, //
|
||||
BOOL isIncrementalWordSearch, BOOL isWildcardSearch //
|
||||
);
|
||||
|
||||
// Preserved key handler
|
||||
BOOL IsPreservedKeyEligible(REFGUID rguid);
|
||||
PreservedKeyAction GetPreservedKeyAction(REFGUID rguid) const;
|
||||
void OnPreservedKey(ITfContext *pContext, REFGUID rguid, _Out_ BOOL *pIsEaten, _In_ ITfThreadMgr *pThreadMgr,
|
||||
TfClientId tfClientId, BOOL *pNeedToggleIMEMode, BOOL isPrevalidated = FALSE,
|
||||
BOOL notifyServer = TRUE);
|
||||
|
||||
// Toggle IME Mode
|
||||
void ToggleIMEMode(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId);
|
||||
void SetIMEMode(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId, BOOL bOpen);
|
||||
BOOL CCompositionProcessorEngine::GetIMEMode(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId);
|
||||
// Apply CN/EN compartment change deferred until after composition commit.
|
||||
// Closing KEYBOARD_OPENCLOSE before EndComposition makes CUAS/Win32 EDIT
|
||||
// finalize the same preedit twice (Chrome/TSF-only hosts are unaffected).
|
||||
void ApplyPendingImeModeAfterCompositionCommit(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId);
|
||||
void SetPunctuationMode(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId, BOOL bOpen);
|
||||
BOOL GetPunctuationMode(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId);
|
||||
void SetDoubleSingleByteMode(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId, BOOL bOpen);
|
||||
BOOL GetDoubleSingleByteMode(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId);
|
||||
|
||||
// Punctuation
|
||||
BOOL IsPunctuation(WCHAR wch);
|
||||
const WCHAR *GetPunctuation(WCHAR wch);
|
||||
// Smart punctuation (rime digit_separators-style): after ASCII letters/digits,
|
||||
// keep ',' '.' ':' as ASCII instead of mapping to Chinese punctuation.
|
||||
static BOOL IsSmartAsciiPunctuationKey(WCHAR wch);
|
||||
std::wstring ResolvePunctuation(WCHAR wch, WCHAR precedingChar);
|
||||
|
||||
BOOL IsDoubleSingleByte(WCHAR wch);
|
||||
BOOL IsWildcard()
|
||||
{
|
||||
return _isWildcard;
|
||||
}
|
||||
BOOL IsDisableWildcardAtFirst()
|
||||
{
|
||||
return _isDisableWildcardAtFirst;
|
||||
}
|
||||
BOOL IsWildcardChar(WCHAR wch)
|
||||
{
|
||||
return ((IsWildcardOneChar(wch) || IsWildcardAllChar(wch)) ? TRUE : FALSE);
|
||||
}
|
||||
BOOL IsWildcardOneChar(WCHAR wch)
|
||||
{
|
||||
return (wch == L'?' ? TRUE : FALSE);
|
||||
}
|
||||
BOOL IsWildcardAllChar(WCHAR wch)
|
||||
{
|
||||
return (wch == L'*' ? TRUE : FALSE);
|
||||
}
|
||||
BOOL IsKeystrokeSort()
|
||||
{
|
||||
return _isKeystrokeSort;
|
||||
}
|
||||
|
||||
// Language bar control
|
||||
void SetLanguageBarStatus(DWORD status, BOOL isSet);
|
||||
|
||||
void ConversionModeCompartmentUpdated(_In_ ITfThreadMgr *pThreadMgr);
|
||||
|
||||
void ShowAllLanguageBarIcons();
|
||||
void HideAllLanguageBarIcons();
|
||||
void RefreshLanguageBarIcons();
|
||||
|
||||
inline CCandidateRange *GetCandidateListIndexRange()
|
||||
{
|
||||
return &_candidateListIndexRange;
|
||||
}
|
||||
inline UINT GetCandidateListPhraseModifier()
|
||||
{
|
||||
return _candidateListPhraseModifier;
|
||||
}
|
||||
inline UINT GetCandidateWindowWidth()
|
||||
{
|
||||
return _candidateWndWidth;
|
||||
}
|
||||
|
||||
private:
|
||||
void InitKeyStrokeTable();
|
||||
BOOL InitLanguageBar(_In_ CLangBarItemButton *pLanguageBar, _In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId,
|
||||
REFGUID guidCompartment);
|
||||
|
||||
struct _KEYSTROKE;
|
||||
BOOL IsVirtualKeyKeystrokeComposition(UINT uCode, _Out_opt_ _KEYSTROKE_STATE *pKeyState,
|
||||
KEYSTROKE_FUNCTION function);
|
||||
BOOL IsVirtualKeyKeystrokeCandidate(UINT uCode, _In_ _KEYSTROKE_STATE *pKeyState, CANDIDATE_MODE candidateMode,
|
||||
_Out_ BOOL *pfRetCode, _In_ CMetasequoiaImeArray<_KEYSTROKE> *pKeystrokeMetric);
|
||||
BOOL IsKeystrokeRange(UINT uCode, _Out_ _KEYSTROKE_STATE *pKeyState, CANDIDATE_MODE candidateMode);
|
||||
|
||||
void SetupKeystroke();
|
||||
void SetupPreserved(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId);
|
||||
void SetupConfiguration();
|
||||
void SetupLanguageBar(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId, BOOL isSecureMode);
|
||||
void SetKeystrokeTable(_Inout_ CMetasequoiaImeArray<_KEYSTROKE> *pKeystroke);
|
||||
void SetupPunctuationPair();
|
||||
void CreateLanguageBarButton(DWORD dwEnable, GUID guidLangBar, _In_z_ LPCWSTR pwszDescriptionValue,
|
||||
_In_z_ LPCWSTR pwszTooltipValue, DWORD dwOnIconIndex, DWORD dwOffIconIndex,
|
||||
_Outptr_result_maybenull_ CLangBarItemButton **ppLangBarItemButton, BOOL isSecureMode);
|
||||
void SetInitialCandidateListRange();
|
||||
void SetDefaultCandidateTextFont();
|
||||
void InitializeMetasequoiaIMECompartment(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId);
|
||||
|
||||
class XPreservedKey;
|
||||
void SetPreservedKey(const CLSID clsid, TF_PRESERVEDKEY &tfPreservedKey, _In_z_ LPCWSTR pwszDescription,
|
||||
_Out_ XPreservedKey *pXPreservedKey);
|
||||
BOOL InitPreservedKey(_In_ XPreservedKey *pXPreservedKey, _In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId);
|
||||
BOOL CheckShiftKeyOnly(_In_ CMetasequoiaImeArray<TF_PRESERVEDKEY> *pTSFPreservedKeyTable);
|
||||
|
||||
static HRESULT CompartmentCallback(_In_ void *pv, REFGUID guidCompartment);
|
||||
void PrivateCompartmentsUpdated(_In_ ITfThreadMgr *pThreadMgr);
|
||||
void KeyboardOpenCompartmentUpdated(_In_ ITfThreadMgr *pThreadMgr);
|
||||
HRESULT SetKeyboardOpenCompartment(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId, BOOL isOpen);
|
||||
void SyncPunctuationWithImeMode(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId, BOOL isOpen);
|
||||
void CommitCompositionOnExternalKeyboardClose();
|
||||
void ReleaseConfiguredImeModeDefense();
|
||||
|
||||
private:
|
||||
struct _KEYSTROKE
|
||||
{
|
||||
UINT VirtualKey;
|
||||
UINT Modifiers;
|
||||
KEYSTROKE_FUNCTION Function;
|
||||
|
||||
_KEYSTROKE()
|
||||
{
|
||||
VirtualKey = 0;
|
||||
Modifiers = 0;
|
||||
Function = FUNCTION_NONE;
|
||||
}
|
||||
};
|
||||
_KEYSTROKE _keystrokeTable[26];
|
||||
|
||||
CStringRange _keystrokeBuffer;
|
||||
DWORD_PTR _caretPosition = 0;
|
||||
std::wstring _renderedPreedit;
|
||||
size_t _renderedPreeditPrefixLength = 0;
|
||||
|
||||
BOOL _hasWildcardIncludedInKeystrokeBuffer;
|
||||
|
||||
LANGID _langid;
|
||||
GUID _guidProfile;
|
||||
TfClientId _tfClientId;
|
||||
|
||||
CMetasequoiaImeArray<_KEYSTROKE> _KeystrokeComposition;
|
||||
CMetasequoiaImeArray<_KEYSTROKE> _KeystrokeCandidate;
|
||||
CMetasequoiaImeArray<_KEYSTROKE> _KeystrokeCandidateWildcard;
|
||||
CMetasequoiaImeArray<_KEYSTROKE> _KeystrokeCandidateSymbol;
|
||||
CMetasequoiaImeArray<_KEYSTROKE> _KeystrokeSymbol;
|
||||
|
||||
// Preserved key data
|
||||
class XPreservedKey
|
||||
{
|
||||
public:
|
||||
XPreservedKey();
|
||||
~XPreservedKey();
|
||||
BOOL UninitPreservedKey(_In_ ITfThreadMgr *pThreadMgr);
|
||||
|
||||
public:
|
||||
CMetasequoiaImeArray<TF_PRESERVEDKEY> TSFPreservedKeyTable;
|
||||
GUID Guid;
|
||||
LPCWSTR Description;
|
||||
};
|
||||
|
||||
XPreservedKey _PreservedKey_IMEMode;
|
||||
XPreservedKey _PreservedKey_IMEMode02;
|
||||
XPreservedKey _PreservedKey_IMEMode03;
|
||||
XPreservedKey _PreservedKey_EnglishInputMode;
|
||||
XPreservedKey _PreservedKey_DoubleSingleByte;
|
||||
XPreservedKey _PreservedKey_Punctuation;
|
||||
|
||||
// Punctuation data
|
||||
CMetasequoiaImeArray<CPunctuationPair> _PunctuationPair;
|
||||
CMetasequoiaImeArray<CPunctuationNestPair> _PunctuationNestPair;
|
||||
|
||||
// Language bar data
|
||||
CLangBarItemButton *_pLanguageBar_IMEMode;
|
||||
CLangBarItemButton *_pLanguageBar_DoubleSingleByte;
|
||||
CLangBarItemButton *_pLanguageBar_Punctuation;
|
||||
|
||||
// Compartment
|
||||
CCompartment *_pCompartmentConversion;
|
||||
CCompartmentEventSink *_pCompartmentConversionEventSink;
|
||||
CCompartmentEventSink *_pCompartmentKeyboardOpenEventSink;
|
||||
CCompartmentEventSink *_pCompartmentDoubleSingleByteEventSink;
|
||||
CCompartmentEventSink *_pCompartmentPunctuationEventSink;
|
||||
ITfThreadMgr *_pOwnerThreadMgr;
|
||||
HWND _ownerMsgWndHandle;
|
||||
CMetasequoiaIME *_pTextService;
|
||||
BOOL _keyboardOpen;
|
||||
BOOL _keyboardOpenKnown;
|
||||
BOOL _suppressKeyboardCloseCommit;
|
||||
// After Activate applies input.default_ime_mode, Chromium (and Electron)
|
||||
// often rewrites TF_CONVERSIONMODE_* (NATIVE / SYMBOL / FULLSHAPE) while
|
||||
// focus is still on the non-editable shell. ConversionModeCompartmentUpdated
|
||||
// would then mirror those bits into OPENCLOSE and the punctuation /
|
||||
// fullwidth compartments. Defend by reasserting private state until the
|
||||
// user explicitly chooses a mode (Shift / langbar / FTB / preserved key).
|
||||
BOOL _defendConfiguredImeMode;
|
||||
BOOL _hasPendingImeModeAfterCompositionCommit;
|
||||
BOOL _pendingImeModeAfterCompositionCommit;
|
||||
|
||||
// Configuration data
|
||||
BOOL _isWildcard : 1;
|
||||
BOOL _isDisableWildcardAtFirst : 1;
|
||||
BOOL _isKeystrokeSort : 1;
|
||||
BOOL _isComLessMode : 1;
|
||||
CCandidateRange _candidateListIndexRange;
|
||||
UINT _candidateListPhraseModifier;
|
||||
UINT _candidateWndWidth;
|
||||
|
||||
static const int OUT_OF_FILE_INDEX = -1;
|
||||
};
|
||||
@@ -1,129 +1,129 @@
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "EditSession.h"
|
||||
#include "MetasequoiaIME.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CStartCompositinoEditSession
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class CStartCompositionEditSession : public CEditSessionBase
|
||||
{
|
||||
public:
|
||||
CStartCompositionEditSession(_In_ CMetasequoiaIME *pTextService, _In_ ITfContext *pContext)
|
||||
: CEditSessionBase(pTextService, pContext)
|
||||
{
|
||||
}
|
||||
|
||||
// ITfEditSession
|
||||
STDMETHODIMP DoEditSession(TfEditCookie ec);
|
||||
};
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfEditSession::DoEditSession
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CStartCompositionEditSession::DoEditSession(TfEditCookie ec)
|
||||
{
|
||||
ITfInsertAtSelection *pInsertAtSelection = nullptr;
|
||||
ITfRange *pRangeInsert = nullptr;
|
||||
ITfContextComposition *pContextComposition = nullptr;
|
||||
ITfComposition *pComposition = nullptr;
|
||||
|
||||
if (FAILED(_pContext->QueryInterface(IID_ITfInsertAtSelection, (void **)&pInsertAtSelection)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (FAILED(pInsertAtSelection->InsertTextAtSelection(ec, TF_IAS_QUERYONLY, NULL, 0, &pRangeInsert)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (FAILED(_pContext->QueryInterface(IID_ITfContextComposition, (void **)&pContextComposition)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(pContextComposition->StartComposition(ec, pRangeInsert, _pTextService, &pComposition)) &&
|
||||
(nullptr != pComposition))
|
||||
{
|
||||
_pTextService->_SetComposition(pComposition);
|
||||
|
||||
// set selection to the adjusted range
|
||||
TF_SELECTION tfSelection;
|
||||
tfSelection.range = pRangeInsert;
|
||||
tfSelection.style.ase = TF_AE_NONE;
|
||||
tfSelection.style.fInterimChar = FALSE;
|
||||
|
||||
_pContext->SetSelection(ec, 1, &tfSelection);
|
||||
_pTextService->_SaveCompositionContext(_pContext);
|
||||
}
|
||||
|
||||
Exit:
|
||||
if (nullptr != pContextComposition)
|
||||
{
|
||||
pContextComposition->Release();
|
||||
}
|
||||
|
||||
if (nullptr != pRangeInsert)
|
||||
{
|
||||
pRangeInsert->Release();
|
||||
}
|
||||
|
||||
if (nullptr != pInsertAtSelection)
|
||||
{
|
||||
pInsertAtSelection->Release();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CMetasequoiaIME class
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _StartComposition
|
||||
//
|
||||
// this starts the new (std::nothrow) composition at the selection of the current
|
||||
// focus context.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CMetasequoiaIME::_StartComposition(_In_ ITfContext *pContext)
|
||||
{
|
||||
CStartCompositionEditSession *pStartCompositionEditSession =
|
||||
new (std::nothrow) CStartCompositionEditSession(this, pContext);
|
||||
|
||||
if (nullptr != pStartCompositionEditSession)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
pContext->RequestEditSession(_tfClientId, pStartCompositionEditSession, TF_ES_SYNC | TF_ES_READWRITE, &hr);
|
||||
|
||||
pStartCompositionEditSession->Release();
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _SaveCompositionContext
|
||||
//
|
||||
// this saves the context _pComposition belongs to; we need this to clear
|
||||
// text attribute in case composition has not been terminated on
|
||||
// deactivation
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CMetasequoiaIME::_SaveCompositionContext(_In_ ITfContext *pContext)
|
||||
{
|
||||
assert(_pContext == nullptr);
|
||||
|
||||
pContext->AddRef();
|
||||
_pContext = pContext;
|
||||
}
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "EditSession.h"
|
||||
#include "MetasequoiaIME.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CStartCompositinoEditSession
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class CStartCompositionEditSession : public CEditSessionBase
|
||||
{
|
||||
public:
|
||||
CStartCompositionEditSession(_In_ CMetasequoiaIME *pTextService, _In_ ITfContext *pContext)
|
||||
: CEditSessionBase(pTextService, pContext)
|
||||
{
|
||||
}
|
||||
|
||||
// ITfEditSession
|
||||
STDMETHODIMP DoEditSession(TfEditCookie ec);
|
||||
};
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfEditSession::DoEditSession
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CStartCompositionEditSession::DoEditSession(TfEditCookie ec)
|
||||
{
|
||||
ITfInsertAtSelection *pInsertAtSelection = nullptr;
|
||||
ITfRange *pRangeInsert = nullptr;
|
||||
ITfContextComposition *pContextComposition = nullptr;
|
||||
ITfComposition *pComposition = nullptr;
|
||||
|
||||
if (FAILED(_pContext->QueryInterface(IID_ITfInsertAtSelection, (void **)&pInsertAtSelection)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (FAILED(pInsertAtSelection->InsertTextAtSelection(ec, TF_IAS_QUERYONLY, NULL, 0, &pRangeInsert)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (FAILED(_pContext->QueryInterface(IID_ITfContextComposition, (void **)&pContextComposition)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(pContextComposition->StartComposition(ec, pRangeInsert, _pTextService, &pComposition)) &&
|
||||
(nullptr != pComposition))
|
||||
{
|
||||
_pTextService->_SetComposition(pComposition);
|
||||
|
||||
// set selection to the adjusted range
|
||||
TF_SELECTION tfSelection;
|
||||
tfSelection.range = pRangeInsert;
|
||||
tfSelection.style.ase = TF_AE_NONE;
|
||||
tfSelection.style.fInterimChar = FALSE;
|
||||
|
||||
_pContext->SetSelection(ec, 1, &tfSelection);
|
||||
_pTextService->_SaveCompositionContext(_pContext);
|
||||
}
|
||||
|
||||
Exit:
|
||||
if (nullptr != pContextComposition)
|
||||
{
|
||||
pContextComposition->Release();
|
||||
}
|
||||
|
||||
if (nullptr != pRangeInsert)
|
||||
{
|
||||
pRangeInsert->Release();
|
||||
}
|
||||
|
||||
if (nullptr != pInsertAtSelection)
|
||||
{
|
||||
pInsertAtSelection->Release();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CMetasequoiaIME class
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _StartComposition
|
||||
//
|
||||
// this starts the new (std::nothrow) composition at the selection of the current
|
||||
// focus context.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CMetasequoiaIME::_StartComposition(_In_ ITfContext *pContext)
|
||||
{
|
||||
CStartCompositionEditSession *pStartCompositionEditSession =
|
||||
new (std::nothrow) CStartCompositionEditSession(this, pContext);
|
||||
|
||||
if (nullptr != pStartCompositionEditSession)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
pContext->RequestEditSession(_tfClientId, pStartCompositionEditSession, TF_ES_SYNC | TF_ES_READWRITE, &hr);
|
||||
|
||||
pStartCompositionEditSession->Release();
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _SaveCompositionContext
|
||||
//
|
||||
// this saves the context _pComposition belongs to; we need this to clear
|
||||
// text attribute in case composition has not been terminated on
|
||||
// deactivation
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CMetasequoiaIME::_SaveCompositionContext(_In_ ITfContext *pContext)
|
||||
{
|
||||
assert(_pContext == nullptr);
|
||||
|
||||
pContext->AddRef();
|
||||
_pContext = pContext;
|
||||
}
|
||||
@@ -1,136 +1,136 @@
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "MetasequoiaIME.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _ClearCompositionDisplayAttributes
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CMetasequoiaIME::_ClearCompositionDisplayAttributes(TfEditCookie ec, _In_ ITfContext *pContext,
|
||||
_In_opt_ ITfComposition *expectedComposition)
|
||||
{
|
||||
ITfRange *pRangeComposition = nullptr;
|
||||
ITfProperty *pDisplayAttributeProperty = nullptr;
|
||||
ITfComposition *composition = expectedComposition ? expectedComposition : _pComposition;
|
||||
if (composition == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// get the compositon range.
|
||||
if (FAILED(composition->GetRange(&pRangeComposition)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// get our the display attribute property
|
||||
if (SUCCEEDED(pContext->GetProperty(GUID_PROP_ATTRIBUTE, &pDisplayAttributeProperty)))
|
||||
{
|
||||
// clear the value over the range
|
||||
pDisplayAttributeProperty->Clear(ec, pRangeComposition);
|
||||
|
||||
pDisplayAttributeProperty->Release();
|
||||
}
|
||||
|
||||
pRangeComposition->Release();
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _SetCompositionDisplayAttributes
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CMetasequoiaIME::_SetCompositionDisplayAttributes(TfEditCookie ec, _In_ ITfContext *pContext,
|
||||
TfGuidAtom gaDisplayAttribute)
|
||||
{
|
||||
ITfRange *pRangeComposition = nullptr;
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
// we need a range and the context it lives in
|
||||
hr = _pComposition->GetRange(&pRangeComposition);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hr = E_FAIL;
|
||||
BOOL ret = _SetCompositionDisplayAttributesForRange(ec, pContext, pRangeComposition, gaDisplayAttribute);
|
||||
pRangeComposition->Release();
|
||||
return ret;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _SetCompositionDisplayAttributesForRange
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CMetasequoiaIME::_SetCompositionDisplayAttributesForRange(TfEditCookie ec, _In_ ITfContext *pContext,
|
||||
_In_ ITfRange *pRangeComposition,
|
||||
TfGuidAtom gaDisplayAttribute)
|
||||
{
|
||||
if (pRangeComposition == nullptr)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ITfProperty *pDisplayAttributeProperty = nullptr;
|
||||
HRESULT hr = E_FAIL;
|
||||
|
||||
// get our the display attribute property
|
||||
if (SUCCEEDED(pContext->GetProperty(GUID_PROP_ATTRIBUTE, &pDisplayAttributeProperty)))
|
||||
{
|
||||
VARIANT var;
|
||||
// set the value over the range
|
||||
// the application will use this guid atom to lookup the acutal rendering information
|
||||
var.vt = VT_I4; // we're going to set a TfGuidAtom
|
||||
var.lVal = gaDisplayAttribute;
|
||||
|
||||
hr = pDisplayAttributeProperty->SetValue(ec, pRangeComposition, &var);
|
||||
|
||||
pDisplayAttributeProperty->Release();
|
||||
}
|
||||
|
||||
return (hr == S_OK);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _InitDisplayAttributeGuidAtom
|
||||
//
|
||||
// Because it's expensive to map our display attribute GUID to a TSF
|
||||
// TfGuidAtom, we do it once when Activate is called.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CMetasequoiaIME::_InitDisplayAttributeGuidAtom()
|
||||
{
|
||||
ITfCategoryMgr *pCategoryMgr = nullptr;
|
||||
HRESULT hr = CoCreateInstance(CLSID_TF_CategoryMgr, nullptr, CLSCTX_INPROC_SERVER, IID_ITfCategoryMgr,
|
||||
(void **)&pCategoryMgr);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// register the display attribute for input text.
|
||||
hr = pCategoryMgr->RegisterGUID(Global::MetasequoiaIMEGuidDisplayAttributeInput, &_gaDisplayAttributeInput);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
// register the display attribute for the converted text.
|
||||
hr = pCategoryMgr->RegisterGUID(Global::MetasequoiaIMEGuidDisplayAttributeConverted, &_gaDisplayAttributeConverted);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Exit:
|
||||
pCategoryMgr->Release();
|
||||
|
||||
return (hr == S_OK);
|
||||
}
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "MetasequoiaIME.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _ClearCompositionDisplayAttributes
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CMetasequoiaIME::_ClearCompositionDisplayAttributes(TfEditCookie ec, _In_ ITfContext *pContext,
|
||||
_In_opt_ ITfComposition *expectedComposition)
|
||||
{
|
||||
ITfRange *pRangeComposition = nullptr;
|
||||
ITfProperty *pDisplayAttributeProperty = nullptr;
|
||||
ITfComposition *composition = expectedComposition ? expectedComposition : _pComposition;
|
||||
if (composition == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// get the compositon range.
|
||||
if (FAILED(composition->GetRange(&pRangeComposition)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// get our the display attribute property
|
||||
if (SUCCEEDED(pContext->GetProperty(GUID_PROP_ATTRIBUTE, &pDisplayAttributeProperty)))
|
||||
{
|
||||
// clear the value over the range
|
||||
pDisplayAttributeProperty->Clear(ec, pRangeComposition);
|
||||
|
||||
pDisplayAttributeProperty->Release();
|
||||
}
|
||||
|
||||
pRangeComposition->Release();
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _SetCompositionDisplayAttributes
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CMetasequoiaIME::_SetCompositionDisplayAttributes(TfEditCookie ec, _In_ ITfContext *pContext,
|
||||
TfGuidAtom gaDisplayAttribute)
|
||||
{
|
||||
ITfRange *pRangeComposition = nullptr;
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
// we need a range and the context it lives in
|
||||
hr = _pComposition->GetRange(&pRangeComposition);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hr = E_FAIL;
|
||||
BOOL ret = _SetCompositionDisplayAttributesForRange(ec, pContext, pRangeComposition, gaDisplayAttribute);
|
||||
pRangeComposition->Release();
|
||||
return ret;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _SetCompositionDisplayAttributesForRange
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CMetasequoiaIME::_SetCompositionDisplayAttributesForRange(TfEditCookie ec, _In_ ITfContext *pContext,
|
||||
_In_ ITfRange *pRangeComposition,
|
||||
TfGuidAtom gaDisplayAttribute)
|
||||
{
|
||||
if (pRangeComposition == nullptr)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ITfProperty *pDisplayAttributeProperty = nullptr;
|
||||
HRESULT hr = E_FAIL;
|
||||
|
||||
// get our the display attribute property
|
||||
if (SUCCEEDED(pContext->GetProperty(GUID_PROP_ATTRIBUTE, &pDisplayAttributeProperty)))
|
||||
{
|
||||
VARIANT var;
|
||||
// set the value over the range
|
||||
// the application will use this guid atom to lookup the acutal rendering information
|
||||
var.vt = VT_I4; // we're going to set a TfGuidAtom
|
||||
var.lVal = gaDisplayAttribute;
|
||||
|
||||
hr = pDisplayAttributeProperty->SetValue(ec, pRangeComposition, &var);
|
||||
|
||||
pDisplayAttributeProperty->Release();
|
||||
}
|
||||
|
||||
return (hr == S_OK);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _InitDisplayAttributeGuidAtom
|
||||
//
|
||||
// Because it's expensive to map our display attribute GUID to a TSF
|
||||
// TfGuidAtom, we do it once when Activate is called.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CMetasequoiaIME::_InitDisplayAttributeGuidAtom()
|
||||
{
|
||||
ITfCategoryMgr *pCategoryMgr = nullptr;
|
||||
HRESULT hr = CoCreateInstance(CLSID_TF_CategoryMgr, nullptr, CLSCTX_INPROC_SERVER, IID_ITfCategoryMgr,
|
||||
(void **)&pCategoryMgr);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// register the display attribute for input text.
|
||||
hr = pCategoryMgr->RegisterGUID(Global::MetasequoiaIMEGuidDisplayAttributeInput, &_gaDisplayAttributeInput);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
// register the display attribute for the converted text.
|
||||
hr = pCategoryMgr->RegisterGUID(Global::MetasequoiaIMEGuidDisplayAttributeConverted, &_gaDisplayAttributeConverted);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Exit:
|
||||
pCategoryMgr->Release();
|
||||
|
||||
return (hr == S_OK);
|
||||
}
|
||||
@@ -1,218 +1,218 @@
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "DisplayAttributeInfo.h"
|
||||
#include "TfInputProcessorProfile.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// The registry key and values
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// the registry values of the custmized display attributes
|
||||
const WCHAR CDisplayAttributeInfoInput::_s_szValueName[] = L"DisplayAttributeInput";
|
||||
const WCHAR CDisplayAttributeInfoConverted::_s_szValueName[] = L"DisplayAttributeConverted";
|
||||
|
||||
// The descriptions
|
||||
const WCHAR CDisplayAttributeInfoInput::_s_szDescription[] = L"Metasequoia IME Text Service Display Attribute Input";
|
||||
const WCHAR CDisplayAttributeInfoConverted::_s_szDescription[] =
|
||||
L"Metasequoia IME Text Service Display Attribute Converted";
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// DisplayAttribute
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
const TF_DISPLAYATTRIBUTE CDisplayAttributeInfoInput::_s_DisplayAttribute = {
|
||||
{TF_CT_NONE, 0}, // text color
|
||||
{TF_CT_NONE, 0}, // background color (TF_CT_NONE => app default)
|
||||
TF_LS_DOT, // underline style
|
||||
FALSE, // underline boldness
|
||||
{TF_CT_NONE, 0}, // underline color
|
||||
TF_ATTR_INPUT // attribute info
|
||||
};
|
||||
|
||||
const TF_DISPLAYATTRIBUTE CDisplayAttributeInfoConverted::_s_DisplayAttribute = {
|
||||
{TF_CT_NONE, 0}, // text color
|
||||
{TF_CT_NONE, 0}, // background color (TF_CT_NONE => app default)
|
||||
TF_LS_NONE, // underline style
|
||||
FALSE, // underline boldness
|
||||
{TF_CT_NONE, 0}, // underline color
|
||||
TF_ATTR_TARGET_CONVERTED // attribute info
|
||||
};
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ctor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CDisplayAttributeInfo::CDisplayAttributeInfo()
|
||||
{
|
||||
DllAddRef();
|
||||
|
||||
_pguid = nullptr;
|
||||
_pDisplayAttribute = nullptr;
|
||||
_pValueName = nullptr;
|
||||
|
||||
_refCount = 1;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// dtor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CDisplayAttributeInfo::~CDisplayAttributeInfo()
|
||||
{
|
||||
DllRelease();
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// QueryInterface
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CDisplayAttributeInfo::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
|
||||
{
|
||||
if (ppvObj == nullptr)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*ppvObj = nullptr;
|
||||
|
||||
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfDisplayAttributeInfo))
|
||||
{
|
||||
*ppvObj = (ITfDisplayAttributeInfo *)this;
|
||||
}
|
||||
|
||||
if (*ppvObj)
|
||||
{
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// AddRef
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
ULONG CDisplayAttributeInfo::AddRef(void)
|
||||
{
|
||||
return ++_refCount;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// Release
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
ULONG CDisplayAttributeInfo::Release(void)
|
||||
{
|
||||
LONG cr = --_refCount;
|
||||
|
||||
assert(_refCount >= 0);
|
||||
|
||||
if (_refCount == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
return cr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfDisplayAttributeInfo::GetGUID
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CDisplayAttributeInfo::GetGUID(_Out_ GUID *pguid)
|
||||
{
|
||||
if (pguid == nullptr)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (_pguid == nullptr)
|
||||
return E_FAIL;
|
||||
|
||||
*pguid = *_pguid;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfDisplayAttributeInfo::GetDescription
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CDisplayAttributeInfo::GetDescription(_Out_ BSTR *pbstrDesc)
|
||||
{
|
||||
BSTR tempDesc;
|
||||
|
||||
if (pbstrDesc == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*pbstrDesc = nullptr;
|
||||
|
||||
if ((tempDesc = SysAllocString(_pDescription)) == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
*pbstrDesc = tempDesc;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfDisplayAttributeInfo::GetAttributeInfo
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CDisplayAttributeInfo::GetAttributeInfo(_Out_ TF_DISPLAYATTRIBUTE *ptfDisplayAttr)
|
||||
{
|
||||
if (ptfDisplayAttr == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
// return the default display attribute.
|
||||
*ptfDisplayAttr = *_pDisplayAttribute;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfDisplayAttributeInfo::SetAttributeInfo
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CDisplayAttributeInfo::SetAttributeInfo(_In_ const TF_DISPLAYATTRIBUTE *ptfDisplayAttr)
|
||||
{
|
||||
ptfDisplayAttr;
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfDisplayAttributeInfo::Reset
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CDisplayAttributeInfo::Reset()
|
||||
{
|
||||
return SetAttributeInfo(_pDisplayAttribute);
|
||||
}
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "DisplayAttributeInfo.h"
|
||||
#include "TfInputProcessorProfile.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// The registry key and values
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// the registry values of the custmized display attributes
|
||||
const WCHAR CDisplayAttributeInfoInput::_s_szValueName[] = L"DisplayAttributeInput";
|
||||
const WCHAR CDisplayAttributeInfoConverted::_s_szValueName[] = L"DisplayAttributeConverted";
|
||||
|
||||
// The descriptions
|
||||
const WCHAR CDisplayAttributeInfoInput::_s_szDescription[] = L"Metasequoia IME Text Service Display Attribute Input";
|
||||
const WCHAR CDisplayAttributeInfoConverted::_s_szDescription[] =
|
||||
L"Metasequoia IME Text Service Display Attribute Converted";
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// DisplayAttribute
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
const TF_DISPLAYATTRIBUTE CDisplayAttributeInfoInput::_s_DisplayAttribute = {
|
||||
{TF_CT_NONE, 0}, // text color
|
||||
{TF_CT_NONE, 0}, // background color (TF_CT_NONE => app default)
|
||||
TF_LS_DOT, // underline style
|
||||
FALSE, // underline boldness
|
||||
{TF_CT_NONE, 0}, // underline color
|
||||
TF_ATTR_INPUT // attribute info
|
||||
};
|
||||
|
||||
const TF_DISPLAYATTRIBUTE CDisplayAttributeInfoConverted::_s_DisplayAttribute = {
|
||||
{TF_CT_NONE, 0}, // text color
|
||||
{TF_CT_NONE, 0}, // background color (TF_CT_NONE => app default)
|
||||
TF_LS_NONE, // underline style
|
||||
FALSE, // underline boldness
|
||||
{TF_CT_NONE, 0}, // underline color
|
||||
TF_ATTR_TARGET_CONVERTED // attribute info
|
||||
};
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ctor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CDisplayAttributeInfo::CDisplayAttributeInfo()
|
||||
{
|
||||
DllAddRef();
|
||||
|
||||
_pguid = nullptr;
|
||||
_pDisplayAttribute = nullptr;
|
||||
_pValueName = nullptr;
|
||||
|
||||
_refCount = 1;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// dtor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CDisplayAttributeInfo::~CDisplayAttributeInfo()
|
||||
{
|
||||
DllRelease();
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// QueryInterface
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CDisplayAttributeInfo::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
|
||||
{
|
||||
if (ppvObj == nullptr)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*ppvObj = nullptr;
|
||||
|
||||
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfDisplayAttributeInfo))
|
||||
{
|
||||
*ppvObj = (ITfDisplayAttributeInfo *)this;
|
||||
}
|
||||
|
||||
if (*ppvObj)
|
||||
{
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// AddRef
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
ULONG CDisplayAttributeInfo::AddRef(void)
|
||||
{
|
||||
return ++_refCount;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// Release
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
ULONG CDisplayAttributeInfo::Release(void)
|
||||
{
|
||||
LONG cr = --_refCount;
|
||||
|
||||
assert(_refCount >= 0);
|
||||
|
||||
if (_refCount == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
return cr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfDisplayAttributeInfo::GetGUID
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CDisplayAttributeInfo::GetGUID(_Out_ GUID *pguid)
|
||||
{
|
||||
if (pguid == nullptr)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (_pguid == nullptr)
|
||||
return E_FAIL;
|
||||
|
||||
*pguid = *_pguid;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfDisplayAttributeInfo::GetDescription
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CDisplayAttributeInfo::GetDescription(_Out_ BSTR *pbstrDesc)
|
||||
{
|
||||
BSTR tempDesc;
|
||||
|
||||
if (pbstrDesc == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*pbstrDesc = nullptr;
|
||||
|
||||
if ((tempDesc = SysAllocString(_pDescription)) == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
*pbstrDesc = tempDesc;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfDisplayAttributeInfo::GetAttributeInfo
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CDisplayAttributeInfo::GetAttributeInfo(_Out_ TF_DISPLAYATTRIBUTE *ptfDisplayAttr)
|
||||
{
|
||||
if (ptfDisplayAttr == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
// return the default display attribute.
|
||||
*ptfDisplayAttr = *_pDisplayAttribute;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfDisplayAttributeInfo::SetAttributeInfo
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CDisplayAttributeInfo::SetAttributeInfo(_In_ const TF_DISPLAYATTRIBUTE *ptfDisplayAttr)
|
||||
{
|
||||
ptfDisplayAttr;
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfDisplayAttributeInfo::Reset
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CDisplayAttributeInfo::Reset()
|
||||
{
|
||||
return SetAttributeInfo(_pDisplayAttribute);
|
||||
}
|
||||
@@ -1,82 +1,82 @@
|
||||
#pragma once
|
||||
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CDisplayAttributeInfo class
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class CDisplayAttributeInfo : public ITfDisplayAttributeInfo
|
||||
{
|
||||
public:
|
||||
CDisplayAttributeInfo();
|
||||
~CDisplayAttributeInfo();
|
||||
|
||||
// IUnknown
|
||||
STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj);
|
||||
STDMETHODIMP_(ULONG) AddRef(void);
|
||||
STDMETHODIMP_(ULONG) Release(void);
|
||||
|
||||
// ITfDisplayAttributeInfo
|
||||
STDMETHODIMP GetGUID(_Out_ GUID *pguid);
|
||||
STDMETHODIMP GetDescription(_Out_ BSTR *pbstrDesc);
|
||||
STDMETHODIMP GetAttributeInfo(_Out_ TF_DISPLAYATTRIBUTE *pTSFDisplayAttr);
|
||||
STDMETHODIMP SetAttributeInfo(_In_ const TF_DISPLAYATTRIBUTE *ptfDisplayAttr);
|
||||
STDMETHODIMP Reset();
|
||||
|
||||
protected:
|
||||
const GUID *_pguid;
|
||||
const TF_DISPLAYATTRIBUTE *_pDisplayAttribute;
|
||||
const WCHAR *_pDescription;
|
||||
const WCHAR *_pValueName;
|
||||
|
||||
private:
|
||||
LONG _refCount; // COM ref count
|
||||
};
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CDisplayAttributeInfoInput class
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class CDisplayAttributeInfoInput : public CDisplayAttributeInfo
|
||||
{
|
||||
public:
|
||||
CDisplayAttributeInfoInput()
|
||||
{
|
||||
_pguid = &Global::MetasequoiaIMEGuidDisplayAttributeInput;
|
||||
_pDisplayAttribute = &_s_DisplayAttribute;
|
||||
_pDescription = _s_szDescription;
|
||||
_pValueName = _s_szValueName;
|
||||
}
|
||||
|
||||
static const TF_DISPLAYATTRIBUTE _s_DisplayAttribute;
|
||||
static const WCHAR _s_szDescription[];
|
||||
static const WCHAR _s_szValueName[];
|
||||
};
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CDisplayAttributeInfoConverted class
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class CDisplayAttributeInfoConverted : public CDisplayAttributeInfo
|
||||
{
|
||||
public:
|
||||
CDisplayAttributeInfoConverted()
|
||||
{
|
||||
_pguid = &Global::MetasequoiaIMEGuidDisplayAttributeConverted;
|
||||
_pDisplayAttribute = &_s_DisplayAttribute;
|
||||
_pDescription = _s_szDescription;
|
||||
_pValueName = _s_szValueName;
|
||||
}
|
||||
|
||||
static const TF_DISPLAYATTRIBUTE _s_DisplayAttribute;
|
||||
static const WCHAR _s_szDescription[];
|
||||
static const WCHAR _s_szValueName[];
|
||||
};
|
||||
#pragma once
|
||||
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CDisplayAttributeInfo class
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class CDisplayAttributeInfo : public ITfDisplayAttributeInfo
|
||||
{
|
||||
public:
|
||||
CDisplayAttributeInfo();
|
||||
~CDisplayAttributeInfo();
|
||||
|
||||
// IUnknown
|
||||
STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj);
|
||||
STDMETHODIMP_(ULONG) AddRef(void);
|
||||
STDMETHODIMP_(ULONG) Release(void);
|
||||
|
||||
// ITfDisplayAttributeInfo
|
||||
STDMETHODIMP GetGUID(_Out_ GUID *pguid);
|
||||
STDMETHODIMP GetDescription(_Out_ BSTR *pbstrDesc);
|
||||
STDMETHODIMP GetAttributeInfo(_Out_ TF_DISPLAYATTRIBUTE *pTSFDisplayAttr);
|
||||
STDMETHODIMP SetAttributeInfo(_In_ const TF_DISPLAYATTRIBUTE *ptfDisplayAttr);
|
||||
STDMETHODIMP Reset();
|
||||
|
||||
protected:
|
||||
const GUID *_pguid;
|
||||
const TF_DISPLAYATTRIBUTE *_pDisplayAttribute;
|
||||
const WCHAR *_pDescription;
|
||||
const WCHAR *_pValueName;
|
||||
|
||||
private:
|
||||
LONG _refCount; // COM ref count
|
||||
};
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CDisplayAttributeInfoInput class
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class CDisplayAttributeInfoInput : public CDisplayAttributeInfo
|
||||
{
|
||||
public:
|
||||
CDisplayAttributeInfoInput()
|
||||
{
|
||||
_pguid = &Global::MetasequoiaIMEGuidDisplayAttributeInput;
|
||||
_pDisplayAttribute = &_s_DisplayAttribute;
|
||||
_pDescription = _s_szDescription;
|
||||
_pValueName = _s_szValueName;
|
||||
}
|
||||
|
||||
static const TF_DISPLAYATTRIBUTE _s_DisplayAttribute;
|
||||
static const WCHAR _s_szDescription[];
|
||||
static const WCHAR _s_szValueName[];
|
||||
};
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CDisplayAttributeInfoConverted class
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class CDisplayAttributeInfoConverted : public CDisplayAttributeInfo
|
||||
{
|
||||
public:
|
||||
CDisplayAttributeInfoConverted()
|
||||
{
|
||||
_pguid = &Global::MetasequoiaIMEGuidDisplayAttributeConverted;
|
||||
_pDisplayAttribute = &_s_DisplayAttribute;
|
||||
_pDescription = _s_szDescription;
|
||||
_pValueName = _s_szValueName;
|
||||
}
|
||||
|
||||
static const TF_DISPLAYATTRIBUTE _s_DisplayAttribute;
|
||||
static const WCHAR _s_szDescription[];
|
||||
static const WCHAR _s_szValueName[];
|
||||
};
|
||||
@@ -1,74 +1,74 @@
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "MetasequoiaIME.h"
|
||||
#include "DisplayAttributeInfo.h"
|
||||
#include "EnumDisplayAttributeInfo.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfDisplayAttributeProvider::EnumDisplayAttributeInfo
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CMetasequoiaIME::EnumDisplayAttributeInfo(__RPC__deref_out_opt IEnumTfDisplayAttributeInfo **ppEnum)
|
||||
{
|
||||
CEnumDisplayAttributeInfo *pAttributeEnum = nullptr;
|
||||
|
||||
if (ppEnum == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*ppEnum = nullptr;
|
||||
|
||||
pAttributeEnum = new (std::nothrow) CEnumDisplayAttributeInfo();
|
||||
if (pAttributeEnum == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
*ppEnum = pAttributeEnum;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfDisplayAttributeProvider::GetDisplayAttributeInfo
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CMetasequoiaIME::GetDisplayAttributeInfo(__RPC__in REFGUID guidInfo,
|
||||
__RPC__deref_out_opt ITfDisplayAttributeInfo **ppInfo)
|
||||
{
|
||||
if (ppInfo == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*ppInfo = nullptr;
|
||||
|
||||
// Which display attribute GUID?
|
||||
if (IsEqualGUID(guidInfo, Global::MetasequoiaIMEGuidDisplayAttributeInput))
|
||||
{
|
||||
*ppInfo = new (std::nothrow) CDisplayAttributeInfoInput();
|
||||
if ((*ppInfo) == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
}
|
||||
else if (IsEqualGUID(guidInfo, Global::MetasequoiaIMEGuidDisplayAttributeConverted))
|
||||
{
|
||||
*ppInfo = new (std::nothrow) CDisplayAttributeInfoConverted();
|
||||
if ((*ppInfo) == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "MetasequoiaIME.h"
|
||||
#include "DisplayAttributeInfo.h"
|
||||
#include "EnumDisplayAttributeInfo.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfDisplayAttributeProvider::EnumDisplayAttributeInfo
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CMetasequoiaIME::EnumDisplayAttributeInfo(__RPC__deref_out_opt IEnumTfDisplayAttributeInfo **ppEnum)
|
||||
{
|
||||
CEnumDisplayAttributeInfo *pAttributeEnum = nullptr;
|
||||
|
||||
if (ppEnum == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*ppEnum = nullptr;
|
||||
|
||||
pAttributeEnum = new (std::nothrow) CEnumDisplayAttributeInfo();
|
||||
if (pAttributeEnum == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
*ppEnum = pAttributeEnum;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfDisplayAttributeProvider::GetDisplayAttributeInfo
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CMetasequoiaIME::GetDisplayAttributeInfo(__RPC__in REFGUID guidInfo,
|
||||
__RPC__deref_out_opt ITfDisplayAttributeInfo **ppInfo)
|
||||
{
|
||||
if (ppInfo == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*ppInfo = nullptr;
|
||||
|
||||
// Which display attribute GUID?
|
||||
if (IsEqualGUID(guidInfo, Global::MetasequoiaIMEGuidDisplayAttributeInput))
|
||||
{
|
||||
*ppInfo = new (std::nothrow) CDisplayAttributeInfoInput();
|
||||
if ((*ppInfo) == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
}
|
||||
else if (IsEqualGUID(guidInfo, Global::MetasequoiaIMEGuidDisplayAttributeConverted))
|
||||
{
|
||||
*ppInfo = new (std::nothrow) CDisplayAttributeInfoConverted();
|
||||
if ((*ppInfo) == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@@ -1,218 +1,218 @@
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "MetasequoiaIME.h"
|
||||
#include "DisplayAttributeInfo.h"
|
||||
#include "EnumDisplayAttributeInfo.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ctor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CEnumDisplayAttributeInfo::CEnumDisplayAttributeInfo()
|
||||
{
|
||||
DllAddRef();
|
||||
|
||||
_index = 0;
|
||||
_refCount = 1;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// dtor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CEnumDisplayAttributeInfo::~CEnumDisplayAttributeInfo()
|
||||
{
|
||||
DllRelease();
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// QueryInterface
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CEnumDisplayAttributeInfo::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
|
||||
{
|
||||
if (ppvObj == nullptr)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*ppvObj = nullptr;
|
||||
|
||||
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 ++_refCount;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// Release
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI_(ULONG) CEnumDisplayAttributeInfo::Release()
|
||||
{
|
||||
LONG cr = --_refCount;
|
||||
|
||||
assert(_refCount >= 0);
|
||||
|
||||
if (_refCount == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
return cr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// IEnumTfDisplayAttributeInfo::Clone
|
||||
//
|
||||
// Returns a copy of the object.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CEnumDisplayAttributeInfo::Clone(_Out_ IEnumTfDisplayAttributeInfo **ppEnum)
|
||||
{
|
||||
CEnumDisplayAttributeInfo *pClone = nullptr;
|
||||
|
||||
if (ppEnum == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*ppEnum = nullptr;
|
||||
|
||||
pClone = new (std::nothrow) CEnumDisplayAttributeInfo();
|
||||
if ((pClone) == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
// the clone should match this object's state
|
||||
pClone->_index = _index;
|
||||
|
||||
*ppEnum = pClone;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// IEnumTfDisplayAttributeInfo::Next
|
||||
//
|
||||
// Returns an array of display attribute info objects supported by this service.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
const int MAX_DISPLAY_ATTRIBUTE_INFO = 2;
|
||||
|
||||
STDAPI CEnumDisplayAttributeInfo::Next(ULONG ulCount,
|
||||
__RPC__out_ecount_part(ulCount, *pcFetched) ITfDisplayAttributeInfo **rgInfo,
|
||||
__RPC__out ULONG *pcFetched)
|
||||
{
|
||||
ULONG fetched;
|
||||
|
||||
fetched = 0;
|
||||
|
||||
if (ulCount == 0)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
if (rgInfo == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*rgInfo = nullptr;
|
||||
|
||||
while (fetched < ulCount)
|
||||
{
|
||||
ITfDisplayAttributeInfo *pDisplayAttributeInfo = nullptr;
|
||||
|
||||
if (_index == 0)
|
||||
{
|
||||
pDisplayAttributeInfo = new (std::nothrow) CDisplayAttributeInfoInput();
|
||||
if ((pDisplayAttributeInfo) == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
}
|
||||
else if (_index == 1)
|
||||
{
|
||||
pDisplayAttributeInfo = new (std::nothrow) CDisplayAttributeInfoConverted();
|
||||
if ((pDisplayAttributeInfo) == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
*rgInfo = pDisplayAttributeInfo;
|
||||
rgInfo++;
|
||||
fetched++;
|
||||
_index++;
|
||||
}
|
||||
|
||||
if (pcFetched != nullptr)
|
||||
{
|
||||
// technically this is only legal if ulCount == 1, but we won't check
|
||||
*pcFetched = fetched;
|
||||
}
|
||||
|
||||
return (fetched == ulCount) ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// IEnumTfDisplayAttributeInfo::Reset
|
||||
//
|
||||
// Resets the enumeration.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CEnumDisplayAttributeInfo::Reset()
|
||||
{
|
||||
_index = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// IEnumTfDisplayAttributeInfo::Skip
|
||||
//
|
||||
// Skips past objects in the enumeration.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CEnumDisplayAttributeInfo::Skip(ULONG ulCount)
|
||||
{
|
||||
if ((ulCount + _index) > MAX_DISPLAY_ATTRIBUTE_INFO || (ulCount + _index) < ulCount)
|
||||
{
|
||||
_index = MAX_DISPLAY_ATTRIBUTE_INFO;
|
||||
return S_FALSE;
|
||||
}
|
||||
_index += ulCount;
|
||||
return S_OK;
|
||||
}
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "MetasequoiaIME.h"
|
||||
#include "DisplayAttributeInfo.h"
|
||||
#include "EnumDisplayAttributeInfo.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ctor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CEnumDisplayAttributeInfo::CEnumDisplayAttributeInfo()
|
||||
{
|
||||
DllAddRef();
|
||||
|
||||
_index = 0;
|
||||
_refCount = 1;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// dtor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CEnumDisplayAttributeInfo::~CEnumDisplayAttributeInfo()
|
||||
{
|
||||
DllRelease();
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// QueryInterface
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CEnumDisplayAttributeInfo::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
|
||||
{
|
||||
if (ppvObj == nullptr)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*ppvObj = nullptr;
|
||||
|
||||
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 ++_refCount;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// Release
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI_(ULONG) CEnumDisplayAttributeInfo::Release()
|
||||
{
|
||||
LONG cr = --_refCount;
|
||||
|
||||
assert(_refCount >= 0);
|
||||
|
||||
if (_refCount == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
return cr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// IEnumTfDisplayAttributeInfo::Clone
|
||||
//
|
||||
// Returns a copy of the object.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CEnumDisplayAttributeInfo::Clone(_Out_ IEnumTfDisplayAttributeInfo **ppEnum)
|
||||
{
|
||||
CEnumDisplayAttributeInfo *pClone = nullptr;
|
||||
|
||||
if (ppEnum == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*ppEnum = nullptr;
|
||||
|
||||
pClone = new (std::nothrow) CEnumDisplayAttributeInfo();
|
||||
if ((pClone) == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
// the clone should match this object's state
|
||||
pClone->_index = _index;
|
||||
|
||||
*ppEnum = pClone;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// IEnumTfDisplayAttributeInfo::Next
|
||||
//
|
||||
// Returns an array of display attribute info objects supported by this service.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
const int MAX_DISPLAY_ATTRIBUTE_INFO = 2;
|
||||
|
||||
STDAPI CEnumDisplayAttributeInfo::Next(ULONG ulCount,
|
||||
__RPC__out_ecount_part(ulCount, *pcFetched) ITfDisplayAttributeInfo **rgInfo,
|
||||
__RPC__out ULONG *pcFetched)
|
||||
{
|
||||
ULONG fetched;
|
||||
|
||||
fetched = 0;
|
||||
|
||||
if (ulCount == 0)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
if (rgInfo == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*rgInfo = nullptr;
|
||||
|
||||
while (fetched < ulCount)
|
||||
{
|
||||
ITfDisplayAttributeInfo *pDisplayAttributeInfo = nullptr;
|
||||
|
||||
if (_index == 0)
|
||||
{
|
||||
pDisplayAttributeInfo = new (std::nothrow) CDisplayAttributeInfoInput();
|
||||
if ((pDisplayAttributeInfo) == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
}
|
||||
else if (_index == 1)
|
||||
{
|
||||
pDisplayAttributeInfo = new (std::nothrow) CDisplayAttributeInfoConverted();
|
||||
if ((pDisplayAttributeInfo) == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
*rgInfo = pDisplayAttributeInfo;
|
||||
rgInfo++;
|
||||
fetched++;
|
||||
_index++;
|
||||
}
|
||||
|
||||
if (pcFetched != nullptr)
|
||||
{
|
||||
// technically this is only legal if ulCount == 1, but we won't check
|
||||
*pcFetched = fetched;
|
||||
}
|
||||
|
||||
return (fetched == ulCount) ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// IEnumTfDisplayAttributeInfo::Reset
|
||||
//
|
||||
// Resets the enumeration.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CEnumDisplayAttributeInfo::Reset()
|
||||
{
|
||||
_index = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// IEnumTfDisplayAttributeInfo::Skip
|
||||
//
|
||||
// Skips past objects in the enumeration.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CEnumDisplayAttributeInfo::Skip(ULONG ulCount)
|
||||
{
|
||||
if ((ulCount + _index) > MAX_DISPLAY_ATTRIBUTE_INFO || (ulCount + _index) < ulCount)
|
||||
{
|
||||
_index = MAX_DISPLAY_ATTRIBUTE_INFO;
|
||||
return S_FALSE;
|
||||
}
|
||||
_index += ulCount;
|
||||
return S_OK;
|
||||
}
|
||||
@@ -1,32 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include "Private.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CEnumDisplayAttributeInfo
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class CEnumDisplayAttributeInfo : public IEnumTfDisplayAttributeInfo
|
||||
{
|
||||
public:
|
||||
CEnumDisplayAttributeInfo();
|
||||
~CEnumDisplayAttributeInfo();
|
||||
|
||||
// IUnknown
|
||||
STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj);
|
||||
STDMETHODIMP_(ULONG) AddRef(void);
|
||||
STDMETHODIMP_(ULONG) Release(void);
|
||||
|
||||
// IEnumTfDisplayAttributeInfo
|
||||
STDMETHODIMP Clone(_Out_ IEnumTfDisplayAttributeInfo **ppEnum);
|
||||
STDMETHODIMP Next(ULONG ulCount, __RPC__out_ecount_part(ulCount, *pcFetched) ITfDisplayAttributeInfo **rgInfo,
|
||||
__RPC__out ULONG *pcFetched);
|
||||
STDMETHODIMP Reset();
|
||||
STDMETHODIMP Skip(ULONG ulCount);
|
||||
|
||||
private:
|
||||
LONG _index; // next display attribute to enum
|
||||
LONG _refCount; // COM ref count
|
||||
};
|
||||
#pragma once
|
||||
|
||||
#include "Private.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CEnumDisplayAttributeInfo
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class CEnumDisplayAttributeInfo : public IEnumTfDisplayAttributeInfo
|
||||
{
|
||||
public:
|
||||
CEnumDisplayAttributeInfo();
|
||||
~CEnumDisplayAttributeInfo();
|
||||
|
||||
// IUnknown
|
||||
STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj);
|
||||
STDMETHODIMP_(ULONG) AddRef(void);
|
||||
STDMETHODIMP_(ULONG) Release(void);
|
||||
|
||||
// IEnumTfDisplayAttributeInfo
|
||||
STDMETHODIMP Clone(_Out_ IEnumTfDisplayAttributeInfo **ppEnum);
|
||||
STDMETHODIMP Next(ULONG ulCount, __RPC__out_ecount_part(ulCount, *pcFetched) ITfDisplayAttributeInfo **rgInfo,
|
||||
__RPC__out ULONG *pcFetched);
|
||||
STDMETHODIMP Reset();
|
||||
STDMETHODIMP Skip(ULONG ulCount);
|
||||
|
||||
private:
|
||||
LONG _index; // next display attribute to enum
|
||||
LONG _refCount; // COM ref count
|
||||
};
|
||||
+43
-43
@@ -1,43 +1,43 @@
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// DllMain
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID pvReserved)
|
||||
{
|
||||
pvReserved;
|
||||
|
||||
switch (dwReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
|
||||
Global::dllInstanceHandle = hInstance;
|
||||
|
||||
if (!InitializeCriticalSectionAndSpinCount(&Global::CS, 0))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
|
||||
DeleteCriticalSection(&Global::CS);
|
||||
|
||||
break;
|
||||
|
||||
case DLL_THREAD_ATTACH:
|
||||
|
||||
break;
|
||||
|
||||
case DLL_THREAD_DETACH:
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// DllMain
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID pvReserved)
|
||||
{
|
||||
pvReserved;
|
||||
|
||||
switch (dwReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
|
||||
Global::dllInstanceHandle = hInstance;
|
||||
|
||||
if (!InitializeCriticalSectionAndSpinCount(&Global::CS, 0))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
|
||||
DeleteCriticalSection(&Global::CS);
|
||||
|
||||
break;
|
||||
|
||||
case DLL_THREAD_ATTACH:
|
||||
|
||||
break;
|
||||
|
||||
case DLL_THREAD_DETACH:
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1,91 +1,91 @@
|
||||
#include "Private.h"
|
||||
#include "EditSession.h"
|
||||
#include "MetasequoiaIME.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ctor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CEditSessionBase::CEditSessionBase(_In_ CMetasequoiaIME *pTextService, _In_ ITfContext *pContext)
|
||||
{
|
||||
_refCount = 1;
|
||||
_pContext = pContext;
|
||||
_pContext->AddRef();
|
||||
|
||||
_pTextService = pTextService;
|
||||
_pTextService->AddRef();
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// dtor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CEditSessionBase::~CEditSessionBase()
|
||||
{
|
||||
_pContext->Release();
|
||||
_pTextService->Release();
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// QueryInterface
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CEditSessionBase::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
|
||||
{
|
||||
if (ppvObj == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*ppvObj = nullptr;
|
||||
|
||||
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfEditSession))
|
||||
{
|
||||
*ppvObj = (ITfEditSession *)this;
|
||||
}
|
||||
|
||||
if (*ppvObj)
|
||||
{
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// AddRef
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI_(ULONG) CEditSessionBase::AddRef(void)
|
||||
{
|
||||
return ++_refCount;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// Release
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI_(ULONG) CEditSessionBase::Release(void)
|
||||
{
|
||||
LONG cr = --_refCount;
|
||||
|
||||
assert(_refCount >= 0);
|
||||
|
||||
if (_refCount == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
return cr;
|
||||
}
|
||||
#include "Private.h"
|
||||
#include "EditSession.h"
|
||||
#include "MetasequoiaIME.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ctor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CEditSessionBase::CEditSessionBase(_In_ CMetasequoiaIME *pTextService, _In_ ITfContext *pContext)
|
||||
{
|
||||
_refCount = 1;
|
||||
_pContext = pContext;
|
||||
_pContext->AddRef();
|
||||
|
||||
_pTextService = pTextService;
|
||||
_pTextService->AddRef();
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// dtor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CEditSessionBase::~CEditSessionBase()
|
||||
{
|
||||
_pContext->Release();
|
||||
_pTextService->Release();
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// QueryInterface
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CEditSessionBase::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
|
||||
{
|
||||
if (ppvObj == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*ppvObj = nullptr;
|
||||
|
||||
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfEditSession))
|
||||
{
|
||||
*ppvObj = (ITfEditSession *)this;
|
||||
}
|
||||
|
||||
if (*ppvObj)
|
||||
{
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// AddRef
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI_(ULONG) CEditSessionBase::AddRef(void)
|
||||
{
|
||||
return ++_refCount;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// Release
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI_(ULONG) CEditSessionBase::Release(void)
|
||||
{
|
||||
LONG cr = --_refCount;
|
||||
|
||||
assert(_refCount >= 0);
|
||||
|
||||
if (_refCount == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
return cr;
|
||||
}
|
||||
@@ -1,27 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "Private.h"
|
||||
|
||||
class CMetasequoiaIME;
|
||||
|
||||
class CEditSessionBase : public ITfEditSession
|
||||
{
|
||||
public:
|
||||
CEditSessionBase(_In_ CMetasequoiaIME *pTextService, _In_ ITfContext *pContext);
|
||||
virtual ~CEditSessionBase();
|
||||
|
||||
// IUnknown
|
||||
STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj);
|
||||
STDMETHODIMP_(ULONG) AddRef(void);
|
||||
STDMETHODIMP_(ULONG) Release(void);
|
||||
|
||||
// ITfEditSession
|
||||
virtual STDMETHODIMP DoEditSession(TfEditCookie ec) = 0;
|
||||
|
||||
protected:
|
||||
ITfContext *_pContext;
|
||||
CMetasequoiaIME *_pTextService;
|
||||
|
||||
private:
|
||||
LONG _refCount; // COM ref count
|
||||
};
|
||||
#pragma once
|
||||
|
||||
#include "Private.h"
|
||||
|
||||
class CMetasequoiaIME;
|
||||
|
||||
class CEditSessionBase : public ITfEditSession
|
||||
{
|
||||
public:
|
||||
CEditSessionBase(_In_ CMetasequoiaIME *pTextService, _In_ ITfContext *pContext);
|
||||
virtual ~CEditSessionBase();
|
||||
|
||||
// IUnknown
|
||||
STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj);
|
||||
STDMETHODIMP_(ULONG) AddRef(void);
|
||||
STDMETHODIMP_(ULONG) Release(void);
|
||||
|
||||
// ITfEditSession
|
||||
virtual STDMETHODIMP DoEditSession(TfEditCookie ec) = 0;
|
||||
|
||||
protected:
|
||||
ITfContext *_pContext;
|
||||
CMetasequoiaIME *_pTextService;
|
||||
|
||||
private:
|
||||
LONG _refCount; // COM ref count
|
||||
};
|
||||
@@ -1,83 +1,83 @@
|
||||
#include "Private.h"
|
||||
#include "EditSession.h"
|
||||
#include "GetTextExtentEditSession.h"
|
||||
#include "TfTextLayoutSink.h"
|
||||
#include "Ipc.h"
|
||||
#include "FanyDefines.h"
|
||||
#include <debugapi.h>
|
||||
#include <fmt/xchar.h>
|
||||
#include "../Utils/PerfTimer.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ctor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CGetTextExtentEditSession::CGetTextExtentEditSession(_In_ CMetasequoiaIME *pTextService, _In_ ITfContext *pContext,
|
||||
_In_ ITfContextView *pContextView,
|
||||
_In_ ITfRange *pRangeComposition,
|
||||
_In_ CTfTextLayoutSink *pTfTextLayoutSink)
|
||||
: CEditSessionBase(pTextService, pContext)
|
||||
{
|
||||
_pContextView = pContextView;
|
||||
_pRangeComposition = pRangeComposition;
|
||||
_pTfTextLayoutSink = pTfTextLayoutSink;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfEditSession::DoEditSession
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CGetTextExtentEditSession::DoEditSession(TfEditCookie ec)
|
||||
{
|
||||
PerfTimer timer;
|
||||
RECT rc = {0, 0, 0, 0};
|
||||
BOOL isClipped = TRUE;
|
||||
HRESULT hr = S_OK;
|
||||
double getTextExtElapsedMs = 0;
|
||||
double layoutChangeElapsedMs = 0;
|
||||
|
||||
PerfTimer getTextExtTimer;
|
||||
hr = _pContextView->GetTextExt(ec, _pRangeComposition, &rc, &isClipped);
|
||||
getTextExtElapsedMs = getTextExtTimer.ElapsedMs();
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Office may set isClipped with a usable rect; ignore only empty extents.
|
||||
if (isClipped && (rc.right <= rc.left || rc.bottom <= rc.top))
|
||||
{
|
||||
Global::Point[0] = 0;
|
||||
Global::Point[1] = Global::INVALID_Y;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
const POINT anchor = GetPhysicalTextAnchor(_pContextView, rc);
|
||||
Global::Point[0] = anchor.x;
|
||||
Global::Point[1] = anchor.y;
|
||||
// This is the per-keystroke caret source. Tell the sink the session now
|
||||
// has a usable anchor, so a later transient TS_E_NOLAYOUT can be answered
|
||||
// by keeping this position instead of parking the window off-screen.
|
||||
_pTfTextLayoutSink->_MarkAnchorValid();
|
||||
if (Global::current_process_name == Global::ZEN_BROWSER)
|
||||
{
|
||||
Global::firefox_like_cnt++;
|
||||
if (Global::firefox_like_cnt == 3)
|
||||
{
|
||||
PerfTimer layoutChangeTimer;
|
||||
_pTfTextLayoutSink->_LayoutChangeNotification(&rc);
|
||||
layoutChangeElapsedMs = layoutChangeTimer.ElapsedMs();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PerfTimer layoutChangeTimer;
|
||||
_pTfTextLayoutSink->_LayoutChangeNotification(&rc);
|
||||
layoutChangeElapsedMs = layoutChangeTimer.ElapsedMs();
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
#include "Private.h"
|
||||
#include "EditSession.h"
|
||||
#include "GetTextExtentEditSession.h"
|
||||
#include "TfTextLayoutSink.h"
|
||||
#include "Ipc.h"
|
||||
#include "FanyDefines.h"
|
||||
#include <debugapi.h>
|
||||
#include <fmt/xchar.h>
|
||||
#include "../Utils/PerfTimer.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ctor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CGetTextExtentEditSession::CGetTextExtentEditSession(_In_ CMetasequoiaIME *pTextService, _In_ ITfContext *pContext,
|
||||
_In_ ITfContextView *pContextView,
|
||||
_In_ ITfRange *pRangeComposition,
|
||||
_In_ CTfTextLayoutSink *pTfTextLayoutSink)
|
||||
: CEditSessionBase(pTextService, pContext)
|
||||
{
|
||||
_pContextView = pContextView;
|
||||
_pRangeComposition = pRangeComposition;
|
||||
_pTfTextLayoutSink = pTfTextLayoutSink;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfEditSession::DoEditSession
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CGetTextExtentEditSession::DoEditSession(TfEditCookie ec)
|
||||
{
|
||||
PerfTimer timer;
|
||||
RECT rc = {0, 0, 0, 0};
|
||||
BOOL isClipped = TRUE;
|
||||
HRESULT hr = S_OK;
|
||||
double getTextExtElapsedMs = 0;
|
||||
double layoutChangeElapsedMs = 0;
|
||||
|
||||
PerfTimer getTextExtTimer;
|
||||
hr = _pContextView->GetTextExt(ec, _pRangeComposition, &rc, &isClipped);
|
||||
getTextExtElapsedMs = getTextExtTimer.ElapsedMs();
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Office may set isClipped with a usable rect; ignore only empty extents.
|
||||
if (isClipped && (rc.right <= rc.left || rc.bottom <= rc.top))
|
||||
{
|
||||
Global::Point[0] = 0;
|
||||
Global::Point[1] = Global::INVALID_Y;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
const POINT anchor = GetPhysicalTextAnchor(_pContextView, rc);
|
||||
Global::Point[0] = anchor.x;
|
||||
Global::Point[1] = anchor.y;
|
||||
// This is the per-keystroke caret source. Tell the sink the session now
|
||||
// has a usable anchor, so a later transient TS_E_NOLAYOUT can be answered
|
||||
// by keeping this position instead of parking the window off-screen.
|
||||
_pTfTextLayoutSink->_MarkAnchorValid();
|
||||
if (Global::current_process_name == Global::ZEN_BROWSER)
|
||||
{
|
||||
Global::firefox_like_cnt++;
|
||||
if (Global::firefox_like_cnt == 3)
|
||||
{
|
||||
PerfTimer layoutChangeTimer;
|
||||
_pTfTextLayoutSink->_LayoutChangeNotification(&rc);
|
||||
layoutChangeElapsedMs = layoutChangeTimer.ElapsedMs();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PerfTimer layoutChangeTimer;
|
||||
_pTfTextLayoutSink->_LayoutChangeNotification(&rc);
|
||||
layoutChangeElapsedMs = layoutChangeTimer.ElapsedMs();
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@@ -1,36 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include "EditSession.h"
|
||||
|
||||
class CMetasequoiaIME;
|
||||
class CTfTextLayoutSink;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ITfEditSession
|
||||
// CEditSessionBase
|
||||
// CGetTextExtentEditSession class
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CGetTextExtentEditSession
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class CGetTextExtentEditSession : public CEditSessionBase
|
||||
{
|
||||
public:
|
||||
CGetTextExtentEditSession(_In_ CMetasequoiaIME *pTextService, _In_ ITfContext *pContext,
|
||||
_In_ ITfContextView *pContextView, _In_ ITfRange *pRangeComposition,
|
||||
_In_ CTfTextLayoutSink *pTextLayoutSink);
|
||||
|
||||
// ITfEditSession
|
||||
STDMETHODIMP DoEditSession(TfEditCookie ec);
|
||||
|
||||
private:
|
||||
ITfContextView *_pContextView;
|
||||
ITfRange *_pRangeComposition;
|
||||
CTfTextLayoutSink *_pTfTextLayoutSink;
|
||||
};
|
||||
#pragma once
|
||||
|
||||
#include "EditSession.h"
|
||||
|
||||
class CMetasequoiaIME;
|
||||
class CTfTextLayoutSink;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ITfEditSession
|
||||
// CEditSessionBase
|
||||
// CGetTextExtentEditSession class
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CGetTextExtentEditSession
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class CGetTextExtentEditSession : public CEditSessionBase
|
||||
{
|
||||
public:
|
||||
CGetTextExtentEditSession(_In_ CMetasequoiaIME *pTextService, _In_ ITfContext *pContext,
|
||||
_In_ ITfContextView *pContextView, _In_ ITfRange *pRangeComposition,
|
||||
_In_ CTfTextLayoutSink *pTextLayoutSink);
|
||||
|
||||
// ITfEditSession
|
||||
STDMETHODIMP DoEditSession(TfEditCookie ec);
|
||||
|
||||
private:
|
||||
ITfContextView *_pContextView;
|
||||
ITfRange *_pRangeComposition;
|
||||
CTfTextLayoutSink *_pTfTextLayoutSink;
|
||||
};
|
||||
+535
-535
File diff suppressed because it is too large.
Load diff
+170
-170
@@ -1,170 +1,170 @@
|
||||
#pragma once
|
||||
|
||||
#include "Private.h"
|
||||
#include "define.h"
|
||||
#include "MetasequoiaIMEBaseStructure.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <wrl.h>
|
||||
#include <unordered_set>
|
||||
|
||||
void DllAddRef();
|
||||
void DllRelease();
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
namespace Global
|
||||
{
|
||||
//---------------------------------------------------------------------
|
||||
// inline
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
inline void SafeRelease(_In_ IUnknown *punk)
|
||||
{
|
||||
if (punk != nullptr)
|
||||
{
|
||||
punk->Release();
|
||||
}
|
||||
}
|
||||
|
||||
inline void QuickVariantInit(_Inout_ VARIANT *pvar)
|
||||
{
|
||||
pvar->vt = VT_EMPTY;
|
||||
}
|
||||
|
||||
inline void QuickVariantClear(_Inout_ VARIANT *pvar)
|
||||
{
|
||||
switch (pvar->vt)
|
||||
{
|
||||
// some ovbious VTs that don't need to call VariantClear.
|
||||
case VT_EMPTY:
|
||||
case VT_NULL:
|
||||
case VT_I2:
|
||||
case VT_I4:
|
||||
case VT_R4:
|
||||
case VT_R8:
|
||||
case VT_CY:
|
||||
case VT_DATE:
|
||||
case VT_I1:
|
||||
case VT_UI1:
|
||||
case VT_UI2:
|
||||
case VT_UI4:
|
||||
case VT_I8:
|
||||
case VT_UI8:
|
||||
case VT_INT:
|
||||
case VT_UINT:
|
||||
case VT_BOOL:
|
||||
break;
|
||||
|
||||
// Call release for VT_UNKNOWN.
|
||||
case VT_UNKNOWN:
|
||||
SafeRelease(pvar->punkVal);
|
||||
break;
|
||||
|
||||
default:
|
||||
// we call OleAut32 for other VTs.
|
||||
VariantClear(pvar);
|
||||
break;
|
||||
}
|
||||
pvar->vt = VT_EMPTY;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// IsTooSimilar
|
||||
//
|
||||
// Return TRUE if the colors cr1 and cr2 are so similar that they
|
||||
// are hard to distinguish. Used for deciding to use reverse video
|
||||
// selection instead of system selection colors.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline BOOL IsTooSimilar(COLORREF cr1, COLORREF cr2)
|
||||
{
|
||||
if ((cr1 | cr2) & 0xFF000000) // One color and/or the other isn't RGB, so algorithm doesn't apply
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LONG DeltaR = abs(GetRValue(cr1) - GetRValue(cr2));
|
||||
LONG DeltaG = abs(GetGValue(cr1) - GetGValue(cr2));
|
||||
LONG DeltaB = abs(GetBValue(cr1) - GetBValue(cr2));
|
||||
|
||||
return DeltaR + DeltaG + DeltaB < 80;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// extern
|
||||
//---------------------------------------------------------------------
|
||||
extern HINSTANCE dllInstanceHandle;
|
||||
|
||||
extern LONG dllRefCount;
|
||||
|
||||
extern CRITICAL_SECTION CS;
|
||||
extern HFONT defaultlFontHandle; // Global font object we use everywhere
|
||||
|
||||
extern const CLSID MetasequoiaIMECLSID;
|
||||
extern const GUID MetasequoiaIMEGuidProfile;
|
||||
extern const GUID MetasequoiaIMEGuidImeModePreserveKey;
|
||||
extern const GUID MetasequoiaIMEGuidImeModePreserveKey02;
|
||||
extern const GUID MetasequoiaIMEGuidImeModePreserveKey03;
|
||||
extern const GUID MetasequoiaIMEGuidEnglishInputModePreserveKey;
|
||||
extern const GUID MetasequoiaIMEGuidDoubleSingleBytePreserveKey;
|
||||
extern const GUID MetasequoiaIMEGuidPunctuationPreserveKey;
|
||||
|
||||
LRESULT CALLBACK ThreadKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
|
||||
BOOL CheckModifiers(UINT uModCurrent, UINT uMod);
|
||||
BOOL UpdateModifiers(WPARAM wParam, LPARAM lParam);
|
||||
|
||||
extern thread_local USHORT ModifiersValue;
|
||||
extern thread_local BOOL IsShiftKeyDownOnly;
|
||||
extern thread_local BOOL IsControlKeyDownOnly;
|
||||
extern thread_local BOOL IsAltKeyDownOnly;
|
||||
extern thread_local BOOL PureShiftKeyDown;
|
||||
extern thread_local BOOL PureShiftKeyUp;
|
||||
|
||||
extern const GUID MetasequoiaIMEGuidCompartmentDoubleSingleByte;
|
||||
extern const GUID MetasequoiaIMEGuidCompartmentPunctuation;
|
||||
|
||||
extern const WCHAR FullWidthCharTable[];
|
||||
extern const struct _PUNCTUATION PunctuationTable[23];
|
||||
extern const std::unordered_set<WCHAR> CommitWithHighlightedCandPunc;
|
||||
|
||||
extern const GUID MetasequoiaIMEGuidLangBarIMEMode;
|
||||
extern const GUID MetasequoiaIMEGuidLangBarDoubleSingleByte;
|
||||
extern const GUID MetasequoiaIMEGuidLangBarPunctuation;
|
||||
|
||||
extern const GUID MetasequoiaIMEGuidDisplayAttributeInput;
|
||||
extern const GUID MetasequoiaIMEGuidDisplayAttributeConverted;
|
||||
|
||||
extern const GUID MetasequoiaIMEGuidCandUIElement;
|
||||
|
||||
extern const WCHAR UnicodeByteOrderMark;
|
||||
extern const WCHAR KeywordDelimiter;
|
||||
extern const WCHAR StringDelimiter;
|
||||
|
||||
extern const WCHAR ImeModeDescription[];
|
||||
extern const WCHAR ImeModeDescription02[];
|
||||
extern const WCHAR ImeModeDescription03[];
|
||||
extern const WCHAR EnglishInputModeDescription[];
|
||||
extern const int ImeModeOnIcoIndex;
|
||||
extern const int ImeModeOffIcoIndex;
|
||||
|
||||
extern const WCHAR DoubleSingleByteDescription[];
|
||||
extern const int DoubleSingleByteOnIcoIndex;
|
||||
extern const int DoubleSingleByteOffIcoIndex;
|
||||
|
||||
extern const WCHAR PunctuationDescription[];
|
||||
extern const int PunctuationOnIcoIndex;
|
||||
extern const int PunctuationOffIcoIndex;
|
||||
|
||||
extern const WCHAR LangbarImeModeDescription[];
|
||||
extern const WCHAR LangbarDoubleSingleByteDescription[];
|
||||
extern const WCHAR LangbarPunctuationDescription[];
|
||||
|
||||
inline std::vector<std::wstring> WStringCandidateList;
|
||||
inline std::wstring FindKeyCode;
|
||||
|
||||
inline POINT PointDTO = {0, 0};
|
||||
inline std::wstring CandidateWString = L"";
|
||||
} // namespace Global
|
||||
#pragma once
|
||||
|
||||
#include "Private.h"
|
||||
#include "define.h"
|
||||
#include "MetasequoiaIMEBaseStructure.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <wrl.h>
|
||||
#include <unordered_set>
|
||||
|
||||
void DllAddRef();
|
||||
void DllRelease();
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
namespace Global
|
||||
{
|
||||
//---------------------------------------------------------------------
|
||||
// inline
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
inline void SafeRelease(_In_ IUnknown *punk)
|
||||
{
|
||||
if (punk != nullptr)
|
||||
{
|
||||
punk->Release();
|
||||
}
|
||||
}
|
||||
|
||||
inline void QuickVariantInit(_Inout_ VARIANT *pvar)
|
||||
{
|
||||
pvar->vt = VT_EMPTY;
|
||||
}
|
||||
|
||||
inline void QuickVariantClear(_Inout_ VARIANT *pvar)
|
||||
{
|
||||
switch (pvar->vt)
|
||||
{
|
||||
// some ovbious VTs that don't need to call VariantClear.
|
||||
case VT_EMPTY:
|
||||
case VT_NULL:
|
||||
case VT_I2:
|
||||
case VT_I4:
|
||||
case VT_R4:
|
||||
case VT_R8:
|
||||
case VT_CY:
|
||||
case VT_DATE:
|
||||
case VT_I1:
|
||||
case VT_UI1:
|
||||
case VT_UI2:
|
||||
case VT_UI4:
|
||||
case VT_I8:
|
||||
case VT_UI8:
|
||||
case VT_INT:
|
||||
case VT_UINT:
|
||||
case VT_BOOL:
|
||||
break;
|
||||
|
||||
// Call release for VT_UNKNOWN.
|
||||
case VT_UNKNOWN:
|
||||
SafeRelease(pvar->punkVal);
|
||||
break;
|
||||
|
||||
default:
|
||||
// we call OleAut32 for other VTs.
|
||||
VariantClear(pvar);
|
||||
break;
|
||||
}
|
||||
pvar->vt = VT_EMPTY;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// IsTooSimilar
|
||||
//
|
||||
// Return TRUE if the colors cr1 and cr2 are so similar that they
|
||||
// are hard to distinguish. Used for deciding to use reverse video
|
||||
// selection instead of system selection colors.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline BOOL IsTooSimilar(COLORREF cr1, COLORREF cr2)
|
||||
{
|
||||
if ((cr1 | cr2) & 0xFF000000) // One color and/or the other isn't RGB, so algorithm doesn't apply
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LONG DeltaR = abs(GetRValue(cr1) - GetRValue(cr2));
|
||||
LONG DeltaG = abs(GetGValue(cr1) - GetGValue(cr2));
|
||||
LONG DeltaB = abs(GetBValue(cr1) - GetBValue(cr2));
|
||||
|
||||
return DeltaR + DeltaG + DeltaB < 80;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// extern
|
||||
//---------------------------------------------------------------------
|
||||
extern HINSTANCE dllInstanceHandle;
|
||||
|
||||
extern LONG dllRefCount;
|
||||
|
||||
extern CRITICAL_SECTION CS;
|
||||
extern HFONT defaultlFontHandle; // Global font object we use everywhere
|
||||
|
||||
extern const CLSID MetasequoiaIMECLSID;
|
||||
extern const GUID MetasequoiaIMEGuidProfile;
|
||||
extern const GUID MetasequoiaIMEGuidImeModePreserveKey;
|
||||
extern const GUID MetasequoiaIMEGuidImeModePreserveKey02;
|
||||
extern const GUID MetasequoiaIMEGuidImeModePreserveKey03;
|
||||
extern const GUID MetasequoiaIMEGuidEnglishInputModePreserveKey;
|
||||
extern const GUID MetasequoiaIMEGuidDoubleSingleBytePreserveKey;
|
||||
extern const GUID MetasequoiaIMEGuidPunctuationPreserveKey;
|
||||
|
||||
LRESULT CALLBACK ThreadKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
|
||||
BOOL CheckModifiers(UINT uModCurrent, UINT uMod);
|
||||
BOOL UpdateModifiers(WPARAM wParam, LPARAM lParam);
|
||||
|
||||
extern thread_local USHORT ModifiersValue;
|
||||
extern thread_local BOOL IsShiftKeyDownOnly;
|
||||
extern thread_local BOOL IsControlKeyDownOnly;
|
||||
extern thread_local BOOL IsAltKeyDownOnly;
|
||||
extern thread_local BOOL PureShiftKeyDown;
|
||||
extern thread_local BOOL PureShiftKeyUp;
|
||||
|
||||
extern const GUID MetasequoiaIMEGuidCompartmentDoubleSingleByte;
|
||||
extern const GUID MetasequoiaIMEGuidCompartmentPunctuation;
|
||||
|
||||
extern const WCHAR FullWidthCharTable[];
|
||||
extern const struct _PUNCTUATION PunctuationTable[23];
|
||||
extern const std::unordered_set<WCHAR> CommitWithHighlightedCandPunc;
|
||||
|
||||
extern const GUID MetasequoiaIMEGuidLangBarIMEMode;
|
||||
extern const GUID MetasequoiaIMEGuidLangBarDoubleSingleByte;
|
||||
extern const GUID MetasequoiaIMEGuidLangBarPunctuation;
|
||||
|
||||
extern const GUID MetasequoiaIMEGuidDisplayAttributeInput;
|
||||
extern const GUID MetasequoiaIMEGuidDisplayAttributeConverted;
|
||||
|
||||
extern const GUID MetasequoiaIMEGuidCandUIElement;
|
||||
|
||||
extern const WCHAR UnicodeByteOrderMark;
|
||||
extern const WCHAR KeywordDelimiter;
|
||||
extern const WCHAR StringDelimiter;
|
||||
|
||||
extern const WCHAR ImeModeDescription[];
|
||||
extern const WCHAR ImeModeDescription02[];
|
||||
extern const WCHAR ImeModeDescription03[];
|
||||
extern const WCHAR EnglishInputModeDescription[];
|
||||
extern const int ImeModeOnIcoIndex;
|
||||
extern const int ImeModeOffIcoIndex;
|
||||
|
||||
extern const WCHAR DoubleSingleByteDescription[];
|
||||
extern const int DoubleSingleByteOnIcoIndex;
|
||||
extern const int DoubleSingleByteOffIcoIndex;
|
||||
|
||||
extern const WCHAR PunctuationDescription[];
|
||||
extern const int PunctuationOnIcoIndex;
|
||||
extern const int PunctuationOffIcoIndex;
|
||||
|
||||
extern const WCHAR LangbarImeModeDescription[];
|
||||
extern const WCHAR LangbarDoubleSingleByteDescription[];
|
||||
extern const WCHAR LangbarPunctuationDescription[];
|
||||
|
||||
inline std::vector<std::wstring> WStringCandidateList;
|
||||
inline std::wstring FindKeyCode;
|
||||
|
||||
inline POINT PointDTO = {0, 0};
|
||||
inline std::wstring CandidateWString = L"";
|
||||
} // namespace Global
|
||||
+72
-72
@@ -1,73 +1,73 @@
|
||||
#pragma once
|
||||
#include "resource.h"
|
||||
|
||||
#define IME_NAME L"MetasequoiaImeTsf"
|
||||
|
||||
#define TEXTSERVICE_MODEL L"Apartment"
|
||||
#define TEXTSERVICE_LANGID MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)
|
||||
#define TEXTSERVICE_ICON_INDEX -IDIS_METASEQUOIAIME
|
||||
#define TEXTSERVICE_DIC L"MetasequoiaIMESimplifiedQuanPin.txt"
|
||||
#define TEXTSERVICE_DIC_DB L"cutted_flyciku_with_jp.db"
|
||||
#define FANYLOGFILE_ "fanydebug.log"
|
||||
#define FANYLOGFILE L"fanydebug_w.log"
|
||||
|
||||
#define IME_MODE_ON_ICON_INDEX IDI_IME_MODE_ON
|
||||
#define IME_MODE_OFF_ICON_INDEX IDI_IME_MODE_OFF
|
||||
#define IME_MODE_ON_DARK_ICON_INDEX IDI_IME_MODE_ON_DARK
|
||||
#define IME_MODE_OFF_DARK_ICON_INDEX IDI_IME_MODE_OFF_DARK
|
||||
#define IME_MODE_ON_JP_ICON_INDEX IDI_IME_MODE_ON_JP
|
||||
#define IME_MODE_ON_JP_DARK_ICON_INDEX IDI_IME_MODE_ON_JP_DARK
|
||||
#define IME_MODE_CAP_ICON_INDEX IDI_IME_MODE_CAP
|
||||
#define IME_MODE_CAP_DARK_ICON_INDEX IDI_IME_MODE_CAP_DARK
|
||||
#define IME_DOUBLE_ON_INDEX IDI_DOUBLE_SINGLE_BYTE_ON
|
||||
#define IME_DOUBLE_OFF_INDEX IDI_DOUBLE_SINGLE_BYTE_OFF
|
||||
#define IME_PUNCTUATION_ON_INDEX IDI_PUNCTUATION_ON
|
||||
#define IME_PUNCTUATION_OFF_INDEX IDI_PUNCTUATION_OFF
|
||||
|
||||
#define METASEQUOIAIME_FONT_DEFAULT L"Microsoft YaHei UI"
|
||||
#define METASEQUOIAIME_LOCALE_DEFAULT L"zh-CN"
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// defined max pinyin input length
|
||||
//---------------------------------------------------------------------
|
||||
#define MAX_PINYIN_LENGTH (64) // Maximum number of characters allowed in pinyin input
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// defined Candidated Window
|
||||
//---------------------------------------------------------------------
|
||||
#define CANDWND_ROW_WIDTH (30)
|
||||
#define CANDWND_BORDER_COLOR (RGB(0x00, 0x00, 0x00))
|
||||
#define CANDWND_BORDER_WIDTH (2)
|
||||
#define CANDWND_NUM_COLOR (RGB(0xB4, 0xB4, 0xB4))
|
||||
// #define CANDWND_SELECTED_ITEM_COLOR (RGB(0xFF, 0xFF, 0xFF))
|
||||
// #define CANDWND_SELECTED_BK_COLOR (RGB(0xA6, 0xA6, 0x00))
|
||||
#define CANDWND_SELECTED_ITEM_COLOR (RGB(0x00, 0x00, 0x00))
|
||||
#define CANDWND_SELECTED_BK_COLOR (RGB(0xFF, 0xFF, 0xFF))
|
||||
#define CANDWND_ITEM_COLOR (RGB(0x00, 0x00, 0x00))
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// defined Candidated List Contants
|
||||
//---------------------------------------------------------------------
|
||||
#define CANDWND_ITEM_CNT_PER_PAGE (8) // Do not exceed 9
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// defined modifier
|
||||
//---------------------------------------------------------------------
|
||||
#define _TF_MOD_ON_KEYUP_SHIFT_ONLY (0x00010000 | TF_MOD_ON_KEYUP)
|
||||
#define _TF_MOD_ON_KEYUP_CONTROL_ONLY (0x00020000 | TF_MOD_ON_KEYUP)
|
||||
#define _TF_MOD_ON_KEYUP_ALT_ONLY (0x00040000 | TF_MOD_ON_KEYUP)
|
||||
|
||||
#define CAND_WIDTH (13) // * tmMaxCharWidth
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// string length of CLSID
|
||||
//---------------------------------------------------------------------
|
||||
#define CLSID_STRLEN (38) // strlen("{xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx}")
|
||||
|
||||
//
|
||||
// Message define
|
||||
//
|
||||
// #define WM_SHOW_MAIN_WINDOW
|
||||
// #define WM_HIDE_MAIN_WINDOW
|
||||
// #define WM_MOVE_CANDIDATE_WINDOW
|
||||
#pragma once
|
||||
#include "resource.h"
|
||||
|
||||
#define IME_NAME L"MetasequoiaImeTsf"
|
||||
|
||||
#define TEXTSERVICE_MODEL L"Apartment"
|
||||
#define TEXTSERVICE_LANGID MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)
|
||||
#define TEXTSERVICE_ICON_INDEX -IDIS_METASEQUOIAIME
|
||||
#define TEXTSERVICE_DIC L"MetasequoiaIMESimplifiedQuanPin.txt"
|
||||
#define TEXTSERVICE_DIC_DB L"cutted_flyciku_with_jp.db"
|
||||
#define FANYLOGFILE_ "fanydebug.log"
|
||||
#define FANYLOGFILE L"fanydebug_w.log"
|
||||
|
||||
#define IME_MODE_ON_ICON_INDEX IDI_IME_MODE_ON
|
||||
#define IME_MODE_OFF_ICON_INDEX IDI_IME_MODE_OFF
|
||||
#define IME_MODE_ON_DARK_ICON_INDEX IDI_IME_MODE_ON_DARK
|
||||
#define IME_MODE_OFF_DARK_ICON_INDEX IDI_IME_MODE_OFF_DARK
|
||||
#define IME_MODE_ON_JP_ICON_INDEX IDI_IME_MODE_ON_JP
|
||||
#define IME_MODE_ON_JP_DARK_ICON_INDEX IDI_IME_MODE_ON_JP_DARK
|
||||
#define IME_MODE_CAP_ICON_INDEX IDI_IME_MODE_CAP
|
||||
#define IME_MODE_CAP_DARK_ICON_INDEX IDI_IME_MODE_CAP_DARK
|
||||
#define IME_DOUBLE_ON_INDEX IDI_DOUBLE_SINGLE_BYTE_ON
|
||||
#define IME_DOUBLE_OFF_INDEX IDI_DOUBLE_SINGLE_BYTE_OFF
|
||||
#define IME_PUNCTUATION_ON_INDEX IDI_PUNCTUATION_ON
|
||||
#define IME_PUNCTUATION_OFF_INDEX IDI_PUNCTUATION_OFF
|
||||
|
||||
#define METASEQUOIAIME_FONT_DEFAULT L"Microsoft YaHei UI"
|
||||
#define METASEQUOIAIME_LOCALE_DEFAULT L"zh-CN"
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// defined max pinyin input length
|
||||
//---------------------------------------------------------------------
|
||||
#define MAX_PINYIN_LENGTH (64) // Maximum number of characters allowed in pinyin input
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// defined Candidated Window
|
||||
//---------------------------------------------------------------------
|
||||
#define CANDWND_ROW_WIDTH (30)
|
||||
#define CANDWND_BORDER_COLOR (RGB(0x00, 0x00, 0x00))
|
||||
#define CANDWND_BORDER_WIDTH (2)
|
||||
#define CANDWND_NUM_COLOR (RGB(0xB4, 0xB4, 0xB4))
|
||||
// #define CANDWND_SELECTED_ITEM_COLOR (RGB(0xFF, 0xFF, 0xFF))
|
||||
// #define CANDWND_SELECTED_BK_COLOR (RGB(0xA6, 0xA6, 0x00))
|
||||
#define CANDWND_SELECTED_ITEM_COLOR (RGB(0x00, 0x00, 0x00))
|
||||
#define CANDWND_SELECTED_BK_COLOR (RGB(0xFF, 0xFF, 0xFF))
|
||||
#define CANDWND_ITEM_COLOR (RGB(0x00, 0x00, 0x00))
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// defined Candidated List Contants
|
||||
//---------------------------------------------------------------------
|
||||
#define CANDWND_ITEM_CNT_PER_PAGE (8) // Do not exceed 9
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// defined modifier
|
||||
//---------------------------------------------------------------------
|
||||
#define _TF_MOD_ON_KEYUP_SHIFT_ONLY (0x00010000 | TF_MOD_ON_KEYUP)
|
||||
#define _TF_MOD_ON_KEYUP_CONTROL_ONLY (0x00020000 | TF_MOD_ON_KEYUP)
|
||||
#define _TF_MOD_ON_KEYUP_ALT_ONLY (0x00040000 | TF_MOD_ON_KEYUP)
|
||||
|
||||
#define CAND_WIDTH (13) // * tmMaxCharWidth
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// string length of CLSID
|
||||
//---------------------------------------------------------------------
|
||||
#define CLSID_STRLEN (38) // strlen("{xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx}")
|
||||
|
||||
//
|
||||
// Message define
|
||||
//
|
||||
// #define WM_SHOW_MAIN_WINDOW
|
||||
// #define WM_HIDE_MAIN_WINDOW
|
||||
// #define WM_MOVE_CANDIDATE_WINDOW
|
||||
// #define WM_SET_PARENT_HWND
|
||||
@@ -1,15 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "sal.h"
|
||||
|
||||
#include <combaseapi.h>
|
||||
#include <olectl.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <strsafe.h>
|
||||
#include <intsafe.h>
|
||||
|
||||
#include "initguid.h"
|
||||
#include "msctf.h"
|
||||
#include "ctffunc.h"
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "sal.h"
|
||||
|
||||
#include <combaseapi.h>
|
||||
#include <olectl.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <strsafe.h>
|
||||
#include <intsafe.h>
|
||||
|
||||
#include "initguid.h"
|
||||
#include "msctf.h"
|
||||
#include "ctffunc.h"
|
||||
@@ -1,35 +1,35 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by MetasequoiaIME.rc
|
||||
//
|
||||
#define SUBLANG_ENGLISH_US 0x01
|
||||
#define LANG_ENGLISH 0x09
|
||||
#define IDIS_METASEQUOIAIME 12
|
||||
#define IDS_DEFAULT_FONT 13
|
||||
#define IDS_IME_MODE 20
|
||||
#define IDI_IME_MODE_ON 21
|
||||
#define IDI_IME_MODE_OFF 22
|
||||
#define IDS_DOUBLE_SINGLE_BYTE 23
|
||||
#define IDI_DOUBLE_SINGLE_BYTE_ON 24
|
||||
#define IDI_DOUBLE_SINGLE_BYTE_OFF 25
|
||||
#define IDS_PUNCTUATION 26
|
||||
#define IDI_PUNCTUATION_ON 27
|
||||
#define IDI_PUNCTUATION_OFF 28
|
||||
#define IDI_IME_MODE_ON_DARK 29
|
||||
#define IDI_IME_MODE_OFF_DARK 30
|
||||
#define IDI_IME_MODE_ON_JP 31
|
||||
#define IDI_IME_MODE_ON_JP_DARK 32
|
||||
#define IDI_IME_MODE_CAP 33
|
||||
#define IDI_IME_MODE_CAP_DARK 34
|
||||
#define IDR_VERSION2 107
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 108
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by MetasequoiaIME.rc
|
||||
//
|
||||
#define SUBLANG_ENGLISH_US 0x01
|
||||
#define LANG_ENGLISH 0x09
|
||||
#define IDIS_METASEQUOIAIME 12
|
||||
#define IDS_DEFAULT_FONT 13
|
||||
#define IDS_IME_MODE 20
|
||||
#define IDI_IME_MODE_ON 21
|
||||
#define IDI_IME_MODE_OFF 22
|
||||
#define IDS_DOUBLE_SINGLE_BYTE 23
|
||||
#define IDI_DOUBLE_SINGLE_BYTE_ON 24
|
||||
#define IDI_DOUBLE_SINGLE_BYTE_OFF 25
|
||||
#define IDS_PUNCTUATION 26
|
||||
#define IDI_PUNCTUATION_ON 27
|
||||
#define IDI_PUNCTUATION_OFF 28
|
||||
#define IDI_IME_MODE_ON_DARK 29
|
||||
#define IDI_IME_MODE_OFF_DARK 30
|
||||
#define IDI_IME_MODE_ON_JP 31
|
||||
#define IDI_IME_MODE_ON_JP_DARK 32
|
||||
#define IDI_IME_MODE_CAP 33
|
||||
#define IDI_IME_MODE_CAP_DARK 34
|
||||
#define IDR_VERSION2 107
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 108
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,2 +1,2 @@
|
||||
#pragma once
|
||||
#include <windows.h>
|
||||
#pragma once
|
||||
#include <windows.h>
|
||||
@@ -1,125 +1,125 @@
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "Ipc.h"
|
||||
#include "MetasequoiaIME.h"
|
||||
#include "CompositionProcessorEngine.h"
|
||||
|
||||
BOOL CMetasequoiaIME::VerifyMetasequoiaIMECLSID(_In_ REFCLSID clsid)
|
||||
{
|
||||
if (IsEqualCLSID(clsid, Global::MetasequoiaIMECLSID))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfActiveLanguageProfileNotifySink::OnActivated
|
||||
//
|
||||
// Sink called by the framework when changes activate language profile.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CMetasequoiaIME::OnActivated(_In_ REFCLSID clsid, _In_ REFGUID guidProfile, _In_ BOOL isActivated)
|
||||
{
|
||||
guidProfile;
|
||||
|
||||
if (FALSE == VerifyMetasequoiaIMECLSID(clsid))
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (isActivated)
|
||||
{
|
||||
// ActivateEx covers the first load; this callback covers later
|
||||
// profile switches in an already-running host. Use the same
|
||||
// ShellExecute-based wake path so packaged/UWP hosts do not pass
|
||||
// their package identity to the Server.
|
||||
_WakeServerIfNeeded();
|
||||
_AddTextProcessorEngine();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Profile deactivation is the earliest authoritative signal that the
|
||||
// user selected another TIP. Deactivate() sends the same idempotent
|
||||
// event again during teardown, but may run after the Main pipe has
|
||||
// already become unavailable.
|
||||
FlushNamedpipeImeDeactivation();
|
||||
}
|
||||
|
||||
if (nullptr == _pCompositionProcessorEngine)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (isActivated)
|
||||
{
|
||||
_pCompositionProcessorEngine->ShowAllLanguageBarIcons();
|
||||
|
||||
_pCompositionProcessorEngine->ConversionModeCompartmentUpdated(_pThreadMgr);
|
||||
}
|
||||
else
|
||||
{
|
||||
_DeleteCandidateList(FALSE, nullptr);
|
||||
|
||||
_pCompositionProcessorEngine->HideAllLanguageBarIcons();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _InitActiveLanguageProfileNotifySink
|
||||
//
|
||||
// Advise a active language profile notify sink.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CMetasequoiaIME::_InitActiveLanguageProfileNotifySink()
|
||||
{
|
||||
ITfSource *pSource = nullptr;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
if (_pThreadMgr->QueryInterface(IID_ITfSource, (void **)&pSource) != S_OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (pSource->AdviseSink(IID_ITfActiveLanguageProfileNotifySink, (ITfActiveLanguageProfileNotifySink *)this,
|
||||
&_activeLanguageProfileNotifySinkCookie) != S_OK)
|
||||
{
|
||||
_activeLanguageProfileNotifySinkCookie = TF_INVALID_COOKIE;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
Exit:
|
||||
pSource->Release();
|
||||
return ret;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _UninitActiveLanguageProfileNotifySink
|
||||
//
|
||||
// Unadvise a active language profile notify sink. Assumes we have advised one already.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CMetasequoiaIME::_UninitActiveLanguageProfileNotifySink()
|
||||
{
|
||||
ITfSource *pSource = nullptr;
|
||||
|
||||
if (_activeLanguageProfileNotifySinkCookie == TF_INVALID_COOKIE)
|
||||
{
|
||||
return; // never Advised
|
||||
}
|
||||
|
||||
if (_pThreadMgr->QueryInterface(IID_ITfSource, (void **)&pSource) == S_OK)
|
||||
{
|
||||
pSource->UnadviseSink(_activeLanguageProfileNotifySinkCookie);
|
||||
pSource->Release();
|
||||
}
|
||||
|
||||
_activeLanguageProfileNotifySinkCookie = TF_INVALID_COOKIE;
|
||||
}
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "Ipc.h"
|
||||
#include "MetasequoiaIME.h"
|
||||
#include "CompositionProcessorEngine.h"
|
||||
|
||||
BOOL CMetasequoiaIME::VerifyMetasequoiaIMECLSID(_In_ REFCLSID clsid)
|
||||
{
|
||||
if (IsEqualCLSID(clsid, Global::MetasequoiaIMECLSID))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfActiveLanguageProfileNotifySink::OnActivated
|
||||
//
|
||||
// Sink called by the framework when changes activate language profile.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CMetasequoiaIME::OnActivated(_In_ REFCLSID clsid, _In_ REFGUID guidProfile, _In_ BOOL isActivated)
|
||||
{
|
||||
guidProfile;
|
||||
|
||||
if (FALSE == VerifyMetasequoiaIMECLSID(clsid))
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (isActivated)
|
||||
{
|
||||
// ActivateEx covers the first load; this callback covers later
|
||||
// profile switches in an already-running host. Use the same
|
||||
// ShellExecute-based wake path so packaged/UWP hosts do not pass
|
||||
// their package identity to the Server.
|
||||
_WakeServerIfNeeded();
|
||||
_AddTextProcessorEngine();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Profile deactivation is the earliest authoritative signal that the
|
||||
// user selected another TIP. Deactivate() sends the same idempotent
|
||||
// event again during teardown, but may run after the Main pipe has
|
||||
// already become unavailable.
|
||||
FlushNamedpipeImeDeactivation();
|
||||
}
|
||||
|
||||
if (nullptr == _pCompositionProcessorEngine)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (isActivated)
|
||||
{
|
||||
_pCompositionProcessorEngine->ShowAllLanguageBarIcons();
|
||||
|
||||
_pCompositionProcessorEngine->ConversionModeCompartmentUpdated(_pThreadMgr);
|
||||
}
|
||||
else
|
||||
{
|
||||
_DeleteCandidateList(FALSE, nullptr);
|
||||
|
||||
_pCompositionProcessorEngine->HideAllLanguageBarIcons();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _InitActiveLanguageProfileNotifySink
|
||||
//
|
||||
// Advise a active language profile notify sink.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CMetasequoiaIME::_InitActiveLanguageProfileNotifySink()
|
||||
{
|
||||
ITfSource *pSource = nullptr;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
if (_pThreadMgr->QueryInterface(IID_ITfSource, (void **)&pSource) != S_OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (pSource->AdviseSink(IID_ITfActiveLanguageProfileNotifySink, (ITfActiveLanguageProfileNotifySink *)this,
|
||||
&_activeLanguageProfileNotifySinkCookie) != S_OK)
|
||||
{
|
||||
_activeLanguageProfileNotifySinkCookie = TF_INVALID_COOKIE;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
Exit:
|
||||
pSource->Release();
|
||||
return ret;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _UninitActiveLanguageProfileNotifySink
|
||||
//
|
||||
// Unadvise a active language profile notify sink. Assumes we have advised one already.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CMetasequoiaIME::_UninitActiveLanguageProfileNotifySink()
|
||||
{
|
||||
ITfSource *pSource = nullptr;
|
||||
|
||||
if (_activeLanguageProfileNotifySinkCookie == TF_INVALID_COOKIE)
|
||||
{
|
||||
return; // never Advised
|
||||
}
|
||||
|
||||
if (_pThreadMgr->QueryInterface(IID_ITfSource, (void **)&pSource) == S_OK)
|
||||
{
|
||||
pSource->UnadviseSink(_activeLanguageProfileNotifySinkCookie);
|
||||
pSource->Release();
|
||||
}
|
||||
|
||||
_activeLanguageProfileNotifySinkCookie = TF_INVALID_COOKIE;
|
||||
}
|
||||
@@ -1,55 +1,55 @@
|
||||
#include "Private.h"
|
||||
#include "MetasequoiaIME.h"
|
||||
#include "SearchCandidateProvider.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _InitFunctionProviderSink
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CMetasequoiaIME::_InitFunctionProviderSink()
|
||||
{
|
||||
ITfSourceSingle *pSourceSingle = nullptr;
|
||||
BOOL ret = FALSE;
|
||||
if (SUCCEEDED(_pThreadMgr->QueryInterface(IID_ITfSourceSingle, (void **)&pSourceSingle)))
|
||||
{
|
||||
IUnknown *punk = nullptr;
|
||||
if (SUCCEEDED(QueryInterface(IID_IUnknown, (void **)&punk)))
|
||||
{
|
||||
if (SUCCEEDED(pSourceSingle->AdviseSingleSink(_tfClientId, IID_ITfFunctionProvider, punk)))
|
||||
{
|
||||
if (SUCCEEDED(CSearchCandidateProvider::CreateInstance(&_pITfFnSearchCandidateProvider,
|
||||
(ITfTextInputProcessorEx *)this)))
|
||||
{
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
punk->Release();
|
||||
}
|
||||
pSourceSingle->Release();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _UninitFunctionProviderSink
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CMetasequoiaIME::_UninitFunctionProviderSink()
|
||||
{
|
||||
if (_pITfFnSearchCandidateProvider != nullptr)
|
||||
{
|
||||
_pITfFnSearchCandidateProvider->Release();
|
||||
_pITfFnSearchCandidateProvider = nullptr;
|
||||
}
|
||||
|
||||
ITfSourceSingle *pSourceSingle = nullptr;
|
||||
if (SUCCEEDED(_pThreadMgr->QueryInterface(IID_ITfSourceSingle, (void **)&pSourceSingle)))
|
||||
{
|
||||
pSourceSingle->UnadviseSingleSink(_tfClientId, IID_ITfFunctionProvider);
|
||||
pSourceSingle->Release();
|
||||
}
|
||||
}
|
||||
#include "Private.h"
|
||||
#include "MetasequoiaIME.h"
|
||||
#include "SearchCandidateProvider.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _InitFunctionProviderSink
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CMetasequoiaIME::_InitFunctionProviderSink()
|
||||
{
|
||||
ITfSourceSingle *pSourceSingle = nullptr;
|
||||
BOOL ret = FALSE;
|
||||
if (SUCCEEDED(_pThreadMgr->QueryInterface(IID_ITfSourceSingle, (void **)&pSourceSingle)))
|
||||
{
|
||||
IUnknown *punk = nullptr;
|
||||
if (SUCCEEDED(QueryInterface(IID_IUnknown, (void **)&punk)))
|
||||
{
|
||||
if (SUCCEEDED(pSourceSingle->AdviseSingleSink(_tfClientId, IID_ITfFunctionProvider, punk)))
|
||||
{
|
||||
if (SUCCEEDED(CSearchCandidateProvider::CreateInstance(&_pITfFnSearchCandidateProvider,
|
||||
(ITfTextInputProcessorEx *)this)))
|
||||
{
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
punk->Release();
|
||||
}
|
||||
pSourceSingle->Release();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _UninitFunctionProviderSink
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CMetasequoiaIME::_UninitFunctionProviderSink()
|
||||
{
|
||||
if (_pITfFnSearchCandidateProvider != nullptr)
|
||||
{
|
||||
_pITfFnSearchCandidateProvider->Release();
|
||||
_pITfFnSearchCandidateProvider = nullptr;
|
||||
}
|
||||
|
||||
ITfSourceSingle *pSourceSingle = nullptr;
|
||||
if (SUCCEEDED(_pThreadMgr->QueryInterface(IID_ITfSourceSingle, (void **)&pSourceSingle)))
|
||||
{
|
||||
pSourceSingle->UnadviseSingleSink(_tfClientId, IID_ITfFunctionProvider);
|
||||
pSourceSingle->Release();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
LIBRARY MetasequoiaImeTsf.dll
|
||||
|
||||
EXPORTS
|
||||
DllGetClassObject PRIVATE
|
||||
DllCanUnloadNow PRIVATE
|
||||
DllRegisterServer PRIVATE
|
||||
DllUnregisterServer PRIVATE
|
||||
LIBRARY MetasequoiaImeTsf.dll
|
||||
|
||||
EXPORTS
|
||||
DllGetClassObject PRIVATE
|
||||
DllCanUnloadNow PRIVATE
|
||||
DllRegisterServer PRIVATE
|
||||
DllUnregisterServer PRIVATE
|
||||
+607
-607
File diff suppressed because it is too large.
Load diff
+128
-128
@@ -1,128 +1,128 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (United States) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDIS_METASEQUOIAIME ICON "..\\..\\image\\msime.ico"
|
||||
IDI_IME_MODE_ON ICON "..\\..\\image\\cn-light.ico"
|
||||
IDI_IME_MODE_OFF ICON "..\\..\\image\\en-light.ico"
|
||||
IDI_IME_MODE_ON_DARK ICON "..\\..\\image\\cn-dark.ico"
|
||||
IDI_IME_MODE_OFF_DARK ICON "..\\..\\image\\en-dark.ico"
|
||||
IDI_IME_MODE_ON_JP ICON "..\\..\\image\\jp-light.ico"
|
||||
IDI_IME_MODE_ON_JP_DARK ICON "..\\..\\image\\jp-dark.ico"
|
||||
IDI_IME_MODE_CAP ICON "..\\..\\image\\cap-light.ico"
|
||||
IDI_IME_MODE_CAP_DARK ICON "..\\..\\image\\cap-dark.ico"
|
||||
IDI_DOUBLE_SINGLE_BYTE_ON ICON "..\\..\\image\\DoubleSingleByteOn.ico"
|
||||
IDI_DOUBLE_SINGLE_BYTE_OFF ICON "..\\..\\image\\DoubleSingleByteOff.ico"
|
||||
IDI_PUNCTUATION_ON ICON "..\\..\\image\\PunctuationOn.ico"
|
||||
IDI_PUNCTUATION_OFF ICON "..\\..\\image\\PunctuationOff.ico"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
IDR_VERSION2 VERSIONINFO
|
||||
FILEVERSION 0,0,17,0
|
||||
PRODUCTVERSION 0,0,17,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "MSFT"
|
||||
VALUE "FileDescription", "The Metasequoia code of Windows 11 IME"
|
||||
VALUE "FileVersion", "0.0.17.0"
|
||||
VALUE "InternalName", "MetasequoiaIM.dll"
|
||||
VALUE "LegalCopyright", "Copyright (C)"
|
||||
VALUE "OriginalFilename", "MetasequoiaIM.dll"
|
||||
VALUE "ProductName", "MetasequoiaIME"
|
||||
VALUE "ProductVersion", "0.0.17.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDIS_METASEQUOIAIME "Chinese Simplified QuanPin (version 6.0)"
|
||||
IDS_DEFAULT_FONT "Microsoft YaHei UI"
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_IME_MODE "Chinese/English input (Shift)"
|
||||
IDS_DOUBLE_SINGLE_BYTE "Double/Single byte (Shift+Space)"
|
||||
IDS_PUNCTUATION "Chinese/English punctuation (Ctrl+.)"
|
||||
END
|
||||
|
||||
#endif // English (United States) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (United States) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDIS_METASEQUOIAIME ICON "..\\..\\image\\msime.ico"
|
||||
IDI_IME_MODE_ON ICON "..\\..\\image\\cn-light.ico"
|
||||
IDI_IME_MODE_OFF ICON "..\\..\\image\\en-light.ico"
|
||||
IDI_IME_MODE_ON_DARK ICON "..\\..\\image\\cn-dark.ico"
|
||||
IDI_IME_MODE_OFF_DARK ICON "..\\..\\image\\en-dark.ico"
|
||||
IDI_IME_MODE_ON_JP ICON "..\\..\\image\\jp-light.ico"
|
||||
IDI_IME_MODE_ON_JP_DARK ICON "..\\..\\image\\jp-dark.ico"
|
||||
IDI_IME_MODE_CAP ICON "..\\..\\image\\cap-light.ico"
|
||||
IDI_IME_MODE_CAP_DARK ICON "..\\..\\image\\cap-dark.ico"
|
||||
IDI_DOUBLE_SINGLE_BYTE_ON ICON "..\\..\\image\\DoubleSingleByteOn.ico"
|
||||
IDI_DOUBLE_SINGLE_BYTE_OFF ICON "..\\..\\image\\DoubleSingleByteOff.ico"
|
||||
IDI_PUNCTUATION_ON ICON "..\\..\\image\\PunctuationOn.ico"
|
||||
IDI_PUNCTUATION_OFF ICON "..\\..\\image\\PunctuationOff.ico"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
IDR_VERSION2 VERSIONINFO
|
||||
FILEVERSION 0,0,17,0
|
||||
PRODUCTVERSION 0,0,17,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "MSFT"
|
||||
VALUE "FileDescription", "The Metasequoia code of Windows 11 IME"
|
||||
VALUE "FileVersion", "0.0.17.0"
|
||||
VALUE "InternalName", "MetasequoiaIM.dll"
|
||||
VALUE "LegalCopyright", "Copyright (C)"
|
||||
VALUE "OriginalFilename", "MetasequoiaIM.dll"
|
||||
VALUE "ProductName", "MetasequoiaIME"
|
||||
VALUE "ProductVersion", "0.0.17.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDIS_METASEQUOIAIME "Chinese Simplified QuanPin (version 6.0)"
|
||||
IDS_DEFAULT_FONT "Microsoft YaHei UI"
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_IME_MODE "Chinese/English input (Shift)"
|
||||
IDS_DOUBLE_SINGLE_BYTE "Double/Single byte (Shift+Space)"
|
||||
IDS_PUNCTUATION "Chinese/English punctuation (Ctrl+.)"
|
||||
END
|
||||
|
||||
#endif // English (United States) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
@@ -1,366 +1,366 @@
|
||||
#ifndef UNICODE
|
||||
#define UNICODE
|
||||
#endif // !UNICODE
|
||||
|
||||
#ifndef _UNICODE
|
||||
#define _UNICODE
|
||||
#endif // !UNICODE
|
||||
|
||||
#include "Globals.h"
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// CLSIDToString
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
const BYTE GuidSymbols[] = {3, 2, 1, 0, '-', 5, 4, '-', 7, 6, '-', 8, 9, '-', 10, 11, 12, 13, 14, 15};
|
||||
|
||||
const WCHAR HexDigits[] = L"0123456789ABCDEF";
|
||||
|
||||
BOOL CLSIDToString(REFGUID refGUID, _Out_writes_(39) WCHAR *pCLSIDString)
|
||||
{
|
||||
WCHAR *pTemp = pCLSIDString;
|
||||
const BYTE *pBytes = (const BYTE *)&refGUID;
|
||||
|
||||
DWORD j = 0;
|
||||
pTemp[j++] = L'{';
|
||||
for (int i = 0; i < sizeof(GuidSymbols) && j < (CLSID_STRLEN - 2); i++)
|
||||
{
|
||||
if (GuidSymbols[i] == '-')
|
||||
{
|
||||
pTemp[j++] = L'-';
|
||||
}
|
||||
else
|
||||
{
|
||||
pTemp[j++] = HexDigits[(pBytes[GuidSymbols[i]] & 0xF0) >> 4];
|
||||
pTemp[j++] = HexDigits[(pBytes[GuidSymbols[i]] & 0x0F)];
|
||||
}
|
||||
}
|
||||
|
||||
pTemp[j++] = L'}';
|
||||
pTemp[j] = L'\0';
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// SkipWhiteSpace
|
||||
//
|
||||
// dwBufLen - in character count
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
HRESULT SkipWhiteSpace(LCID locale, _In_ LPCWSTR pwszBuffer, DWORD_PTR dwBufLen, _Out_ DWORD_PTR *pdwIndex)
|
||||
{
|
||||
DWORD_PTR index = 0;
|
||||
|
||||
*pdwIndex = 0;
|
||||
while (*pwszBuffer && IsSpace(locale, *pwszBuffer) && dwBufLen)
|
||||
{
|
||||
dwBufLen--;
|
||||
pwszBuffer++;
|
||||
index++;
|
||||
}
|
||||
|
||||
if (*pwszBuffer && dwBufLen)
|
||||
{
|
||||
*pdwIndex = index;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// FindChar
|
||||
//
|
||||
// dwBufLen - in character count
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
HRESULT FindChar(WCHAR wch, _In_ LPCWSTR pwszBuffer, DWORD_PTR dwBufLen, _Out_ DWORD_PTR *pdwIndex)
|
||||
{
|
||||
DWORD_PTR index = 0;
|
||||
|
||||
*pdwIndex = 0;
|
||||
while (*pwszBuffer && (*pwszBuffer != wch) && dwBufLen)
|
||||
{
|
||||
dwBufLen--;
|
||||
pwszBuffer++;
|
||||
index++;
|
||||
}
|
||||
|
||||
if (*pwszBuffer && dwBufLen)
|
||||
{
|
||||
*pdwIndex = index;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// IsSpace
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
BOOL IsSpace(LCID locale, WCHAR wch)
|
||||
{
|
||||
WORD wCharType = 0;
|
||||
|
||||
GetStringTypeEx(locale, CT_CTYPE1, &wch, 1, &wCharType);
|
||||
return (wCharType & C1_SPACE);
|
||||
}
|
||||
|
||||
CStringRange::CStringRange()
|
||||
{
|
||||
_stringBufLen = 0;
|
||||
_pStringBuf = nullptr;
|
||||
}
|
||||
|
||||
CStringRange::CStringRange(const CStringRange &sr) : _stringBufLen(0), _pStringBuf(nullptr)
|
||||
{
|
||||
if (sr._stringBufLen > 0 && sr._pStringBuf != nullptr)
|
||||
{
|
||||
_pStringBuf = new WCHAR[sr._stringBufLen];
|
||||
_stringBufLen = sr._stringBufLen;
|
||||
std::memcpy((void *)_pStringBuf, sr._pStringBuf, sr._stringBufLen * sizeof(WCHAR));
|
||||
}
|
||||
}
|
||||
|
||||
CStringRange::~CStringRange()
|
||||
{
|
||||
}
|
||||
|
||||
const WCHAR *CStringRange::Get() const
|
||||
{
|
||||
return _pStringBuf;
|
||||
}
|
||||
|
||||
const DWORD_PTR CStringRange::GetLength() const
|
||||
{
|
||||
return _stringBufLen;
|
||||
}
|
||||
|
||||
void CStringRange::Clear()
|
||||
{
|
||||
_stringBufLen = 0;
|
||||
_pStringBuf = nullptr;
|
||||
}
|
||||
|
||||
void CStringRange::Set(const WCHAR *pwch, DWORD_PTR dwLength)
|
||||
{
|
||||
_stringBufLen = dwLength;
|
||||
_pStringBuf = pwch;
|
||||
}
|
||||
|
||||
void CStringRange::Set(CStringRange &sr)
|
||||
{
|
||||
*this = sr;
|
||||
}
|
||||
|
||||
CStringRange &CStringRange::operator=(const CStringRange &sr)
|
||||
{
|
||||
_stringBufLen = sr._stringBufLen;
|
||||
_pStringBuf = sr._pStringBuf;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void CStringRange::CharNext(_Inout_ CStringRange *pCharNext)
|
||||
{
|
||||
if (!_stringBufLen)
|
||||
{
|
||||
pCharNext->_stringBufLen = 0;
|
||||
pCharNext->_pStringBuf = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
pCharNext->_stringBufLen = _stringBufLen;
|
||||
pCharNext->_pStringBuf = _pStringBuf;
|
||||
|
||||
while (pCharNext->_stringBufLen)
|
||||
{
|
||||
BOOL isSurrogate =
|
||||
(IS_HIGH_SURROGATE(*pCharNext->_pStringBuf) || IS_LOW_SURROGATE(*pCharNext->_pStringBuf));
|
||||
pCharNext->_stringBufLen--;
|
||||
pCharNext->_pStringBuf++;
|
||||
if (!isSurrogate)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CStringRange::Compare(LCID locale, _In_ CStringRange *pString1, _In_ CStringRange *pString2)
|
||||
{
|
||||
return CompareString(locale, NORM_IGNORECASE, pString1->Get(), (DWORD)pString1->GetLength(), pString2->Get(),
|
||||
(DWORD)pString2->GetLength());
|
||||
}
|
||||
|
||||
BOOL CStringRange::WildcardCompare(LCID locale, _In_ CStringRange *stringWithWildcard, _In_ CStringRange *targetString)
|
||||
{
|
||||
if (stringWithWildcard->GetLength() == 0)
|
||||
{
|
||||
return targetString->GetLength() == 0 ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
CStringRange stringWithWildcard_next;
|
||||
CStringRange targetString_next;
|
||||
stringWithWildcard->CharNext(&stringWithWildcard_next);
|
||||
targetString->CharNext(&targetString_next);
|
||||
|
||||
if (*stringWithWildcard->Get() == L'*')
|
||||
{
|
||||
return WildcardCompare(locale, &stringWithWildcard_next, targetString) ||
|
||||
((targetString->GetLength() != 0) && WildcardCompare(locale, stringWithWildcard, &targetString_next));
|
||||
}
|
||||
if (*stringWithWildcard->Get() == L'?')
|
||||
{
|
||||
return ((targetString->GetLength() != 0) &&
|
||||
WildcardCompare(locale, &stringWithWildcard_next, &targetString_next));
|
||||
}
|
||||
|
||||
BOOL isSurrogate1 = (IS_HIGH_SURROGATE(*stringWithWildcard->Get()) || IS_LOW_SURROGATE(*stringWithWildcard->Get()));
|
||||
BOOL isSurrogate2 = (IS_HIGH_SURROGATE(*targetString->Get()) || IS_LOW_SURROGATE(*targetString->Get()));
|
||||
|
||||
return ((CompareString(locale, NORM_IGNORECASE, stringWithWildcard->Get(), (isSurrogate1 ? 2 : 1),
|
||||
targetString->Get(), (isSurrogate2 ? 2 : 1)) == CSTR_EQUAL) &&
|
||||
WildcardCompare(locale, &stringWithWildcard_next, &targetString_next));
|
||||
}
|
||||
|
||||
CCandidateRange::CCandidateRange(void)
|
||||
{
|
||||
}
|
||||
|
||||
CCandidateRange::~CCandidateRange(void)
|
||||
{
|
||||
}
|
||||
|
||||
BOOL CCandidateRange::IsRange(UINT vKey)
|
||||
{
|
||||
DWORD value = vKey - L'0';
|
||||
if (value > 0 && value < 10) // Start from 1
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
for (UINT i = 0; i < _CandidateListIndexRange.Count(); i++)
|
||||
{
|
||||
if (value == *_CandidateListIndexRange.GetAt(i))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else if ((VK_NUMPAD0 <= vKey) && (vKey <= VK_NUMPAD9))
|
||||
{
|
||||
if ((vKey - VK_NUMPAD0) == *_CandidateListIndexRange.GetAt(i))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int CCandidateRange::GetIndex(UINT vKey)
|
||||
{
|
||||
return 0; // Always return 0(First candidate item), start from 0
|
||||
|
||||
DWORD value = vKey - L'0';
|
||||
|
||||
for (UINT i = 0; i < _CandidateListIndexRange.Count(); i++)
|
||||
{
|
||||
if (value == *_CandidateListIndexRange.GetAt(i))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
else if ((VK_NUMPAD0 <= vKey) && (vKey <= VK_NUMPAD9))
|
||||
{
|
||||
if ((vKey - VK_NUMPAD0) == *_CandidateListIndexRange.GetAt(i))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
CPunctuationPair::CPunctuationPair()
|
||||
{
|
||||
_punctuation._Code = 0;
|
||||
_punctuation._Punctuation[0] = 0;
|
||||
_pairPunctuation[0] = 0;
|
||||
_isPairToggle = FALSE;
|
||||
}
|
||||
|
||||
CPunctuationPair::CPunctuationPair( //
|
||||
WCHAR code, //
|
||||
const WCHAR *punctuation, //
|
||||
const WCHAR *pair //
|
||||
)
|
||||
{
|
||||
_punctuation._Code = code;
|
||||
|
||||
wcsncpy_s(_punctuation._Punctuation, _countof(_punctuation._Punctuation), punctuation, _TRUNCATE);
|
||||
wcsncpy_s(_pairPunctuation, _countof(_pairPunctuation), pair, _TRUNCATE);
|
||||
_isPairToggle = FALSE;
|
||||
}
|
||||
|
||||
CPunctuationNestPair::CPunctuationNestPair()
|
||||
{
|
||||
_punctuation_begin._Code = 0;
|
||||
_punctuation_begin._Punctuation[0] = 0;
|
||||
_pairPunctuation_begin[0] = 0;
|
||||
|
||||
_punctuation_end._Code = 0;
|
||||
_punctuation_end._Punctuation[0] = 0;
|
||||
_pairPunctuation_end[0] = 0;
|
||||
|
||||
_nestCount = 0;
|
||||
}
|
||||
|
||||
CPunctuationNestPair::CPunctuationNestPair( //
|
||||
WCHAR codeBegin, //
|
||||
const WCHAR *punctuationBegin, //
|
||||
const WCHAR *pairBegin, //
|
||||
const WCHAR codeEnd, //
|
||||
const WCHAR *punctuationEnd, //
|
||||
const WCHAR *pairEnd //
|
||||
)
|
||||
{
|
||||
pairEnd;
|
||||
punctuationEnd;
|
||||
_punctuation_begin._Code = codeBegin;
|
||||
wcsncpy_s( //
|
||||
_punctuation_begin._Punctuation, //
|
||||
_countof(_punctuation_begin._Punctuation), //
|
||||
punctuationBegin, //
|
||||
_TRUNCATE //
|
||||
);
|
||||
wcsncpy_s( //
|
||||
_pairPunctuation_begin, //
|
||||
_countof(_pairPunctuation_begin), //
|
||||
pairBegin, //
|
||||
_TRUNCATE //
|
||||
);
|
||||
|
||||
_punctuation_end._Code = codeEnd;
|
||||
wcsncpy_s( //
|
||||
_punctuation_end._Punctuation, //
|
||||
_countof(_punctuation_end._Punctuation), //
|
||||
punctuationEnd, //
|
||||
_TRUNCATE //
|
||||
);
|
||||
wcsncpy_s( //
|
||||
_pairPunctuation_end, //
|
||||
_countof(_pairPunctuation_end), //
|
||||
pairEnd, //
|
||||
_TRUNCATE //
|
||||
);
|
||||
|
||||
_nestCount = 0;
|
||||
}
|
||||
#ifndef UNICODE
|
||||
#define UNICODE
|
||||
#endif // !UNICODE
|
||||
|
||||
#ifndef _UNICODE
|
||||
#define _UNICODE
|
||||
#endif // !UNICODE
|
||||
|
||||
#include "Globals.h"
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// CLSIDToString
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
const BYTE GuidSymbols[] = {3, 2, 1, 0, '-', 5, 4, '-', 7, 6, '-', 8, 9, '-', 10, 11, 12, 13, 14, 15};
|
||||
|
||||
const WCHAR HexDigits[] = L"0123456789ABCDEF";
|
||||
|
||||
BOOL CLSIDToString(REFGUID refGUID, _Out_writes_(39) WCHAR *pCLSIDString)
|
||||
{
|
||||
WCHAR *pTemp = pCLSIDString;
|
||||
const BYTE *pBytes = (const BYTE *)&refGUID;
|
||||
|
||||
DWORD j = 0;
|
||||
pTemp[j++] = L'{';
|
||||
for (int i = 0; i < sizeof(GuidSymbols) && j < (CLSID_STRLEN - 2); i++)
|
||||
{
|
||||
if (GuidSymbols[i] == '-')
|
||||
{
|
||||
pTemp[j++] = L'-';
|
||||
}
|
||||
else
|
||||
{
|
||||
pTemp[j++] = HexDigits[(pBytes[GuidSymbols[i]] & 0xF0) >> 4];
|
||||
pTemp[j++] = HexDigits[(pBytes[GuidSymbols[i]] & 0x0F)];
|
||||
}
|
||||
}
|
||||
|
||||
pTemp[j++] = L'}';
|
||||
pTemp[j] = L'\0';
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// SkipWhiteSpace
|
||||
//
|
||||
// dwBufLen - in character count
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
HRESULT SkipWhiteSpace(LCID locale, _In_ LPCWSTR pwszBuffer, DWORD_PTR dwBufLen, _Out_ DWORD_PTR *pdwIndex)
|
||||
{
|
||||
DWORD_PTR index = 0;
|
||||
|
||||
*pdwIndex = 0;
|
||||
while (*pwszBuffer && IsSpace(locale, *pwszBuffer) && dwBufLen)
|
||||
{
|
||||
dwBufLen--;
|
||||
pwszBuffer++;
|
||||
index++;
|
||||
}
|
||||
|
||||
if (*pwszBuffer && dwBufLen)
|
||||
{
|
||||
*pdwIndex = index;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// FindChar
|
||||
//
|
||||
// dwBufLen - in character count
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
HRESULT FindChar(WCHAR wch, _In_ LPCWSTR pwszBuffer, DWORD_PTR dwBufLen, _Out_ DWORD_PTR *pdwIndex)
|
||||
{
|
||||
DWORD_PTR index = 0;
|
||||
|
||||
*pdwIndex = 0;
|
||||
while (*pwszBuffer && (*pwszBuffer != wch) && dwBufLen)
|
||||
{
|
||||
dwBufLen--;
|
||||
pwszBuffer++;
|
||||
index++;
|
||||
}
|
||||
|
||||
if (*pwszBuffer && dwBufLen)
|
||||
{
|
||||
*pdwIndex = index;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// IsSpace
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
BOOL IsSpace(LCID locale, WCHAR wch)
|
||||
{
|
||||
WORD wCharType = 0;
|
||||
|
||||
GetStringTypeEx(locale, CT_CTYPE1, &wch, 1, &wCharType);
|
||||
return (wCharType & C1_SPACE);
|
||||
}
|
||||
|
||||
CStringRange::CStringRange()
|
||||
{
|
||||
_stringBufLen = 0;
|
||||
_pStringBuf = nullptr;
|
||||
}
|
||||
|
||||
CStringRange::CStringRange(const CStringRange &sr) : _stringBufLen(0), _pStringBuf(nullptr)
|
||||
{
|
||||
if (sr._stringBufLen > 0 && sr._pStringBuf != nullptr)
|
||||
{
|
||||
_pStringBuf = new WCHAR[sr._stringBufLen];
|
||||
_stringBufLen = sr._stringBufLen;
|
||||
std::memcpy((void *)_pStringBuf, sr._pStringBuf, sr._stringBufLen * sizeof(WCHAR));
|
||||
}
|
||||
}
|
||||
|
||||
CStringRange::~CStringRange()
|
||||
{
|
||||
}
|
||||
|
||||
const WCHAR *CStringRange::Get() const
|
||||
{
|
||||
return _pStringBuf;
|
||||
}
|
||||
|
||||
const DWORD_PTR CStringRange::GetLength() const
|
||||
{
|
||||
return _stringBufLen;
|
||||
}
|
||||
|
||||
void CStringRange::Clear()
|
||||
{
|
||||
_stringBufLen = 0;
|
||||
_pStringBuf = nullptr;
|
||||
}
|
||||
|
||||
void CStringRange::Set(const WCHAR *pwch, DWORD_PTR dwLength)
|
||||
{
|
||||
_stringBufLen = dwLength;
|
||||
_pStringBuf = pwch;
|
||||
}
|
||||
|
||||
void CStringRange::Set(CStringRange &sr)
|
||||
{
|
||||
*this = sr;
|
||||
}
|
||||
|
||||
CStringRange &CStringRange::operator=(const CStringRange &sr)
|
||||
{
|
||||
_stringBufLen = sr._stringBufLen;
|
||||
_pStringBuf = sr._pStringBuf;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void CStringRange::CharNext(_Inout_ CStringRange *pCharNext)
|
||||
{
|
||||
if (!_stringBufLen)
|
||||
{
|
||||
pCharNext->_stringBufLen = 0;
|
||||
pCharNext->_pStringBuf = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
pCharNext->_stringBufLen = _stringBufLen;
|
||||
pCharNext->_pStringBuf = _pStringBuf;
|
||||
|
||||
while (pCharNext->_stringBufLen)
|
||||
{
|
||||
BOOL isSurrogate =
|
||||
(IS_HIGH_SURROGATE(*pCharNext->_pStringBuf) || IS_LOW_SURROGATE(*pCharNext->_pStringBuf));
|
||||
pCharNext->_stringBufLen--;
|
||||
pCharNext->_pStringBuf++;
|
||||
if (!isSurrogate)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CStringRange::Compare(LCID locale, _In_ CStringRange *pString1, _In_ CStringRange *pString2)
|
||||
{
|
||||
return CompareString(locale, NORM_IGNORECASE, pString1->Get(), (DWORD)pString1->GetLength(), pString2->Get(),
|
||||
(DWORD)pString2->GetLength());
|
||||
}
|
||||
|
||||
BOOL CStringRange::WildcardCompare(LCID locale, _In_ CStringRange *stringWithWildcard, _In_ CStringRange *targetString)
|
||||
{
|
||||
if (stringWithWildcard->GetLength() == 0)
|
||||
{
|
||||
return targetString->GetLength() == 0 ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
CStringRange stringWithWildcard_next;
|
||||
CStringRange targetString_next;
|
||||
stringWithWildcard->CharNext(&stringWithWildcard_next);
|
||||
targetString->CharNext(&targetString_next);
|
||||
|
||||
if (*stringWithWildcard->Get() == L'*')
|
||||
{
|
||||
return WildcardCompare(locale, &stringWithWildcard_next, targetString) ||
|
||||
((targetString->GetLength() != 0) && WildcardCompare(locale, stringWithWildcard, &targetString_next));
|
||||
}
|
||||
if (*stringWithWildcard->Get() == L'?')
|
||||
{
|
||||
return ((targetString->GetLength() != 0) &&
|
||||
WildcardCompare(locale, &stringWithWildcard_next, &targetString_next));
|
||||
}
|
||||
|
||||
BOOL isSurrogate1 = (IS_HIGH_SURROGATE(*stringWithWildcard->Get()) || IS_LOW_SURROGATE(*stringWithWildcard->Get()));
|
||||
BOOL isSurrogate2 = (IS_HIGH_SURROGATE(*targetString->Get()) || IS_LOW_SURROGATE(*targetString->Get()));
|
||||
|
||||
return ((CompareString(locale, NORM_IGNORECASE, stringWithWildcard->Get(), (isSurrogate1 ? 2 : 1),
|
||||
targetString->Get(), (isSurrogate2 ? 2 : 1)) == CSTR_EQUAL) &&
|
||||
WildcardCompare(locale, &stringWithWildcard_next, &targetString_next));
|
||||
}
|
||||
|
||||
CCandidateRange::CCandidateRange(void)
|
||||
{
|
||||
}
|
||||
|
||||
CCandidateRange::~CCandidateRange(void)
|
||||
{
|
||||
}
|
||||
|
||||
BOOL CCandidateRange::IsRange(UINT vKey)
|
||||
{
|
||||
DWORD value = vKey - L'0';
|
||||
if (value > 0 && value < 10) // Start from 1
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
for (UINT i = 0; i < _CandidateListIndexRange.Count(); i++)
|
||||
{
|
||||
if (value == *_CandidateListIndexRange.GetAt(i))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else if ((VK_NUMPAD0 <= vKey) && (vKey <= VK_NUMPAD9))
|
||||
{
|
||||
if ((vKey - VK_NUMPAD0) == *_CandidateListIndexRange.GetAt(i))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int CCandidateRange::GetIndex(UINT vKey)
|
||||
{
|
||||
return 0; // Always return 0(First candidate item), start from 0
|
||||
|
||||
DWORD value = vKey - L'0';
|
||||
|
||||
for (UINT i = 0; i < _CandidateListIndexRange.Count(); i++)
|
||||
{
|
||||
if (value == *_CandidateListIndexRange.GetAt(i))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
else if ((VK_NUMPAD0 <= vKey) && (vKey <= VK_NUMPAD9))
|
||||
{
|
||||
if ((vKey - VK_NUMPAD0) == *_CandidateListIndexRange.GetAt(i))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
CPunctuationPair::CPunctuationPair()
|
||||
{
|
||||
_punctuation._Code = 0;
|
||||
_punctuation._Punctuation[0] = 0;
|
||||
_pairPunctuation[0] = 0;
|
||||
_isPairToggle = FALSE;
|
||||
}
|
||||
|
||||
CPunctuationPair::CPunctuationPair( //
|
||||
WCHAR code, //
|
||||
const WCHAR *punctuation, //
|
||||
const WCHAR *pair //
|
||||
)
|
||||
{
|
||||
_punctuation._Code = code;
|
||||
|
||||
wcsncpy_s(_punctuation._Punctuation, _countof(_punctuation._Punctuation), punctuation, _TRUNCATE);
|
||||
wcsncpy_s(_pairPunctuation, _countof(_pairPunctuation), pair, _TRUNCATE);
|
||||
_isPairToggle = FALSE;
|
||||
}
|
||||
|
||||
CPunctuationNestPair::CPunctuationNestPair()
|
||||
{
|
||||
_punctuation_begin._Code = 0;
|
||||
_punctuation_begin._Punctuation[0] = 0;
|
||||
_pairPunctuation_begin[0] = 0;
|
||||
|
||||
_punctuation_end._Code = 0;
|
||||
_punctuation_end._Punctuation[0] = 0;
|
||||
_pairPunctuation_end[0] = 0;
|
||||
|
||||
_nestCount = 0;
|
||||
}
|
||||
|
||||
CPunctuationNestPair::CPunctuationNestPair( //
|
||||
WCHAR codeBegin, //
|
||||
const WCHAR *punctuationBegin, //
|
||||
const WCHAR *pairBegin, //
|
||||
const WCHAR codeEnd, //
|
||||
const WCHAR *punctuationEnd, //
|
||||
const WCHAR *pairEnd //
|
||||
)
|
||||
{
|
||||
pairEnd;
|
||||
punctuationEnd;
|
||||
_punctuation_begin._Code = codeBegin;
|
||||
wcsncpy_s( //
|
||||
_punctuation_begin._Punctuation, //
|
||||
_countof(_punctuation_begin._Punctuation), //
|
||||
punctuationBegin, //
|
||||
_TRUNCATE //
|
||||
);
|
||||
wcsncpy_s( //
|
||||
_pairPunctuation_begin, //
|
||||
_countof(_pairPunctuation_begin), //
|
||||
pairBegin, //
|
||||
_TRUNCATE //
|
||||
);
|
||||
|
||||
_punctuation_end._Code = codeEnd;
|
||||
wcsncpy_s( //
|
||||
_punctuation_end._Punctuation, //
|
||||
_countof(_punctuation_end._Punctuation), //
|
||||
punctuationEnd, //
|
||||
_TRUNCATE //
|
||||
);
|
||||
wcsncpy_s( //
|
||||
_pairPunctuation_end, //
|
||||
_countof(_pairPunctuation_end), //
|
||||
pairEnd, //
|
||||
_TRUNCATE //
|
||||
);
|
||||
|
||||
_nestCount = 0;
|
||||
}
|
||||
@@ -1,284 +1,284 @@
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <vector>
|
||||
#include "assert.h"
|
||||
#include <iostream>
|
||||
|
||||
using std::endl;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// defined keyword
|
||||
//---------------------------------------------------------------------
|
||||
template <class VALUE> struct _DEFINED_KEYWORD
|
||||
{
|
||||
LPCWSTR _pwszKeyword;
|
||||
VALUE _value;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// enum
|
||||
//---------------------------------------------------------------------
|
||||
enum KEYSTROKE_CATEGORY
|
||||
{
|
||||
CATEGORY_NONE = 0,
|
||||
CATEGORY_COMPOSING,
|
||||
CATEGORY_CANDIDATE,
|
||||
CATEGORY_INVOKE_COMPOSITION_EDIT_SESSION
|
||||
};
|
||||
|
||||
enum KEYSTROKE_FUNCTION
|
||||
{
|
||||
FUNCTION_NONE = 0,
|
||||
FUNCTION_INPUT,
|
||||
|
||||
FUNCTION_CANCEL,
|
||||
FUNCTION_TOGGLE_IME_MODE, // Toggle IME mode
|
||||
FUNCTION_FINALIZE_TEXTSTORE,
|
||||
FUNCTION_FINALIZE_TEXTSTORE_AND_INPUT,
|
||||
FUNCTION_FINALIZE_CANDIDATELIST,
|
||||
FUNCTION_FINALIZE_CANDIDATELISTForVKReturn,
|
||||
FUNCTION_FINALIZE_CANDIDATELIST_AND_INPUT,
|
||||
FUNCTION_CONVERT,
|
||||
FUNCTION_CONVERT_WILDCARD,
|
||||
FUNCTION_SELECT_BY_NUMBER,
|
||||
FUNCTION_BACKSPACE,
|
||||
FUNCTION_DELETE,
|
||||
FUNCTION_MOVE_LEFT,
|
||||
FUNCTION_MOVE_RIGHT,
|
||||
FUNCTION_MOVE_UP,
|
||||
FUNCTION_MOVE_DOWN,
|
||||
FUNCTION_MOVE_PAGE_UP,
|
||||
FUNCTION_MOVE_PAGE_DOWN,
|
||||
FUNCTION_MOVE_PAGE_TOP,
|
||||
FUNCTION_MOVE_PAGE_BOTTOM,
|
||||
|
||||
// Function Double/Single byte
|
||||
FUNCTION_DOUBLE_SINGLE_BYTE,
|
||||
|
||||
// Function Punctuation
|
||||
FUNCTION_PUNCTUATION,
|
||||
|
||||
// Raw candidate navigation key; Server decides its configured behavior.
|
||||
FUNCTION_SERVER_CANDIDATE_KEY,
|
||||
|
||||
// Unsolicited insert (voice ASR via worker pipe). Append-only so existing
|
||||
// ordinals stay stable across builds.
|
||||
FUNCTION_INSERT_TEXT,
|
||||
FUNCTION_UPDATE_VOICE_COMPOSITION,
|
||||
FUNCTION_COMMIT_VOICE_COMPOSITION,
|
||||
FUNCTION_CANCEL_VOICE_COMPOSITION,
|
||||
FUNCTION_TOGGLE_CHARACTER_SET
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// candidate list
|
||||
//---------------------------------------------------------------------
|
||||
enum CANDIDATE_MODE
|
||||
{
|
||||
CANDIDATE_NONE = 0,
|
||||
CANDIDATE_ORIGINAL,
|
||||
CANDIDATE_INCREMENTAL
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// structure
|
||||
//---------------------------------------------------------------------
|
||||
struct _KEYSTROKE_STATE
|
||||
{
|
||||
KEYSTROKE_CATEGORY Category;
|
||||
KEYSTROKE_FUNCTION Function;
|
||||
};
|
||||
|
||||
struct _PUNCTUATION
|
||||
{
|
||||
WCHAR _Code;
|
||||
WCHAR _Punctuation[3];
|
||||
};
|
||||
|
||||
BOOL CLSIDToString(REFGUID refGUID, _Out_writes_(39) WCHAR *pCLSIDString);
|
||||
|
||||
HRESULT SkipWhiteSpace(LCID locale, _In_ LPCWSTR pwszBuffer, DWORD_PTR dwBufLen, _Out_ DWORD_PTR *pdwIndex);
|
||||
HRESULT FindChar(WCHAR wch, _In_ LPCWSTR pwszBuffer, DWORD_PTR dwBufLen, _Out_ DWORD_PTR *pdwIndex);
|
||||
|
||||
BOOL IsSpace(LCID locale, WCHAR wch);
|
||||
|
||||
template <class T> class CMetasequoiaImeArray
|
||||
{
|
||||
typedef typename std::vector<T> CMetasequoiaImeInnerArray;
|
||||
typedef typename std::vector<T>::iterator CMetasequoiaImeInnerIter;
|
||||
|
||||
public:
|
||||
CMetasequoiaImeArray() : _innerVect()
|
||||
{
|
||||
}
|
||||
|
||||
explicit CMetasequoiaImeArray(size_t count) : _innerVect(count)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~CMetasequoiaImeArray()
|
||||
{
|
||||
}
|
||||
|
||||
inline T *GetAt(size_t index)
|
||||
{
|
||||
assert(index >= 0);
|
||||
assert(index < _innerVect.size());
|
||||
|
||||
T &curT = _innerVect.at(index);
|
||||
|
||||
return &(curT);
|
||||
}
|
||||
|
||||
inline const T *GetAt(size_t index) const
|
||||
{
|
||||
assert(index >= 0);
|
||||
assert(index < _innerVect.size());
|
||||
|
||||
T &curT = _innerVect.at(index);
|
||||
|
||||
return &(curT);
|
||||
}
|
||||
|
||||
void RemoveAt(size_t index)
|
||||
{
|
||||
assert(index >= 0);
|
||||
assert(index < _innerVect.size());
|
||||
|
||||
CMetasequoiaImeInnerIter iter = _innerVect.begin();
|
||||
_innerVect.erase(iter + index);
|
||||
}
|
||||
|
||||
UINT Count() const
|
||||
{
|
||||
return static_cast<UINT>(_innerVect.size());
|
||||
}
|
||||
|
||||
T *Append()
|
||||
{
|
||||
T newT;
|
||||
_innerVect.push_back(newT);
|
||||
T &backT = _innerVect.back();
|
||||
|
||||
return &(backT);
|
||||
}
|
||||
|
||||
void reserve(size_t Count)
|
||||
{
|
||||
_innerVect.reserve(Count);
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
_innerVect.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
CMetasequoiaImeInnerArray _innerVect;
|
||||
};
|
||||
|
||||
class CCandidateRange
|
||||
{
|
||||
public:
|
||||
CCandidateRange(void);
|
||||
~CCandidateRange(void);
|
||||
|
||||
BOOL IsRange(UINT vKey);
|
||||
int GetIndex(UINT vKey);
|
||||
|
||||
inline int Count() const
|
||||
{
|
||||
return _CandidateListIndexRange.Count();
|
||||
}
|
||||
inline DWORD *GetAt(int index)
|
||||
{
|
||||
return _CandidateListIndexRange.GetAt(index);
|
||||
}
|
||||
inline DWORD *Append()
|
||||
{
|
||||
return _CandidateListIndexRange.Append();
|
||||
}
|
||||
|
||||
private:
|
||||
CMetasequoiaImeArray<DWORD> _CandidateListIndexRange;
|
||||
};
|
||||
|
||||
class CStringRange
|
||||
{
|
||||
public:
|
||||
CStringRange();
|
||||
CStringRange(const CStringRange &sr);
|
||||
~CStringRange();
|
||||
|
||||
const WCHAR *Get() const;
|
||||
const DWORD_PTR GetLength() const;
|
||||
void Clear();
|
||||
void Set(const WCHAR *pwch, DWORD_PTR dwLength);
|
||||
void Set(CStringRange &sr);
|
||||
CStringRange &operator=(const CStringRange &sr);
|
||||
void CharNext(_Inout_ CStringRange *pCharNext);
|
||||
static int Compare(LCID locale, _In_ CStringRange *pString1, _In_ CStringRange *pString2);
|
||||
static BOOL WildcardCompare(LCID locale, _In_ CStringRange *stringWithWildcard, _In_ CStringRange *targetString);
|
||||
std::wstring ToWString() const
|
||||
{
|
||||
if (!_pStringBuf || _stringBufLen == 0)
|
||||
return std::wstring();
|
||||
return std::wstring(_pStringBuf, _pStringBuf + _stringBufLen);
|
||||
}
|
||||
|
||||
protected:
|
||||
DWORD_PTR _stringBufLen; // Length is in character count.
|
||||
const WCHAR *_pStringBuf; // Buffer which is not add zero terminate.
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// CCandidateListItem
|
||||
// _ItemString - candidate string
|
||||
// _FindKeyCode - tailing string
|
||||
//---------------------------------------------------------------------
|
||||
struct CCandidateListItem
|
||||
{
|
||||
CStringRange _ItemString;
|
||||
CStringRange _FindKeyCode;
|
||||
|
||||
CCandidateListItem &CCandidateListItem::operator=(const CCandidateListItem &rhs)
|
||||
{
|
||||
_ItemString = rhs._ItemString; // e.g. 你好
|
||||
_FindKeyCode = rhs._FindKeyCode; // e.g. nihao
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
class CPunctuationPair
|
||||
{
|
||||
public:
|
||||
CPunctuationPair();
|
||||
CPunctuationPair(WCHAR code, const WCHAR *punctuation, const WCHAR *pair);
|
||||
|
||||
struct _PUNCTUATION _punctuation;
|
||||
WCHAR _pairPunctuation[3];
|
||||
BOOL _isPairToggle;
|
||||
};
|
||||
|
||||
class CPunctuationNestPair
|
||||
{
|
||||
public:
|
||||
CPunctuationNestPair();
|
||||
CPunctuationNestPair( //
|
||||
WCHAR codeBegin, //
|
||||
const WCHAR *punctuationBegin, //
|
||||
const WCHAR *pairBegin, //
|
||||
const WCHAR codeEnd, //
|
||||
const WCHAR *punctuationEnd, //
|
||||
const WCHAR *pairEnd //
|
||||
);
|
||||
|
||||
struct _PUNCTUATION _punctuation_begin;
|
||||
WCHAR _pairPunctuation_begin[3];
|
||||
|
||||
struct _PUNCTUATION _punctuation_end;
|
||||
WCHAR _pairPunctuation_end[3];
|
||||
|
||||
int _nestCount;
|
||||
};
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <vector>
|
||||
#include "assert.h"
|
||||
#include <iostream>
|
||||
|
||||
using std::endl;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// defined keyword
|
||||
//---------------------------------------------------------------------
|
||||
template <class VALUE> struct _DEFINED_KEYWORD
|
||||
{
|
||||
LPCWSTR _pwszKeyword;
|
||||
VALUE _value;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// enum
|
||||
//---------------------------------------------------------------------
|
||||
enum KEYSTROKE_CATEGORY
|
||||
{
|
||||
CATEGORY_NONE = 0,
|
||||
CATEGORY_COMPOSING,
|
||||
CATEGORY_CANDIDATE,
|
||||
CATEGORY_INVOKE_COMPOSITION_EDIT_SESSION
|
||||
};
|
||||
|
||||
enum KEYSTROKE_FUNCTION
|
||||
{
|
||||
FUNCTION_NONE = 0,
|
||||
FUNCTION_INPUT,
|
||||
|
||||
FUNCTION_CANCEL,
|
||||
FUNCTION_TOGGLE_IME_MODE, // Toggle IME mode
|
||||
FUNCTION_FINALIZE_TEXTSTORE,
|
||||
FUNCTION_FINALIZE_TEXTSTORE_AND_INPUT,
|
||||
FUNCTION_FINALIZE_CANDIDATELIST,
|
||||
FUNCTION_FINALIZE_CANDIDATELISTForVKReturn,
|
||||
FUNCTION_FINALIZE_CANDIDATELIST_AND_INPUT,
|
||||
FUNCTION_CONVERT,
|
||||
FUNCTION_CONVERT_WILDCARD,
|
||||
FUNCTION_SELECT_BY_NUMBER,
|
||||
FUNCTION_BACKSPACE,
|
||||
FUNCTION_DELETE,
|
||||
FUNCTION_MOVE_LEFT,
|
||||
FUNCTION_MOVE_RIGHT,
|
||||
FUNCTION_MOVE_UP,
|
||||
FUNCTION_MOVE_DOWN,
|
||||
FUNCTION_MOVE_PAGE_UP,
|
||||
FUNCTION_MOVE_PAGE_DOWN,
|
||||
FUNCTION_MOVE_PAGE_TOP,
|
||||
FUNCTION_MOVE_PAGE_BOTTOM,
|
||||
|
||||
// Function Double/Single byte
|
||||
FUNCTION_DOUBLE_SINGLE_BYTE,
|
||||
|
||||
// Function Punctuation
|
||||
FUNCTION_PUNCTUATION,
|
||||
|
||||
// Raw candidate navigation key; Server decides its configured behavior.
|
||||
FUNCTION_SERVER_CANDIDATE_KEY,
|
||||
|
||||
// Unsolicited insert (voice ASR via worker pipe). Append-only so existing
|
||||
// ordinals stay stable across builds.
|
||||
FUNCTION_INSERT_TEXT,
|
||||
FUNCTION_UPDATE_VOICE_COMPOSITION,
|
||||
FUNCTION_COMMIT_VOICE_COMPOSITION,
|
||||
FUNCTION_CANCEL_VOICE_COMPOSITION,
|
||||
FUNCTION_TOGGLE_CHARACTER_SET
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// candidate list
|
||||
//---------------------------------------------------------------------
|
||||
enum CANDIDATE_MODE
|
||||
{
|
||||
CANDIDATE_NONE = 0,
|
||||
CANDIDATE_ORIGINAL,
|
||||
CANDIDATE_INCREMENTAL
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// structure
|
||||
//---------------------------------------------------------------------
|
||||
struct _KEYSTROKE_STATE
|
||||
{
|
||||
KEYSTROKE_CATEGORY Category;
|
||||
KEYSTROKE_FUNCTION Function;
|
||||
};
|
||||
|
||||
struct _PUNCTUATION
|
||||
{
|
||||
WCHAR _Code;
|
||||
WCHAR _Punctuation[3];
|
||||
};
|
||||
|
||||
BOOL CLSIDToString(REFGUID refGUID, _Out_writes_(39) WCHAR *pCLSIDString);
|
||||
|
||||
HRESULT SkipWhiteSpace(LCID locale, _In_ LPCWSTR pwszBuffer, DWORD_PTR dwBufLen, _Out_ DWORD_PTR *pdwIndex);
|
||||
HRESULT FindChar(WCHAR wch, _In_ LPCWSTR pwszBuffer, DWORD_PTR dwBufLen, _Out_ DWORD_PTR *pdwIndex);
|
||||
|
||||
BOOL IsSpace(LCID locale, WCHAR wch);
|
||||
|
||||
template <class T> class CMetasequoiaImeArray
|
||||
{
|
||||
typedef typename std::vector<T> CMetasequoiaImeInnerArray;
|
||||
typedef typename std::vector<T>::iterator CMetasequoiaImeInnerIter;
|
||||
|
||||
public:
|
||||
CMetasequoiaImeArray() : _innerVect()
|
||||
{
|
||||
}
|
||||
|
||||
explicit CMetasequoiaImeArray(size_t count) : _innerVect(count)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~CMetasequoiaImeArray()
|
||||
{
|
||||
}
|
||||
|
||||
inline T *GetAt(size_t index)
|
||||
{
|
||||
assert(index >= 0);
|
||||
assert(index < _innerVect.size());
|
||||
|
||||
T &curT = _innerVect.at(index);
|
||||
|
||||
return &(curT);
|
||||
}
|
||||
|
||||
inline const T *GetAt(size_t index) const
|
||||
{
|
||||
assert(index >= 0);
|
||||
assert(index < _innerVect.size());
|
||||
|
||||
T &curT = _innerVect.at(index);
|
||||
|
||||
return &(curT);
|
||||
}
|
||||
|
||||
void RemoveAt(size_t index)
|
||||
{
|
||||
assert(index >= 0);
|
||||
assert(index < _innerVect.size());
|
||||
|
||||
CMetasequoiaImeInnerIter iter = _innerVect.begin();
|
||||
_innerVect.erase(iter + index);
|
||||
}
|
||||
|
||||
UINT Count() const
|
||||
{
|
||||
return static_cast<UINT>(_innerVect.size());
|
||||
}
|
||||
|
||||
T *Append()
|
||||
{
|
||||
T newT;
|
||||
_innerVect.push_back(newT);
|
||||
T &backT = _innerVect.back();
|
||||
|
||||
return &(backT);
|
||||
}
|
||||
|
||||
void reserve(size_t Count)
|
||||
{
|
||||
_innerVect.reserve(Count);
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
_innerVect.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
CMetasequoiaImeInnerArray _innerVect;
|
||||
};
|
||||
|
||||
class CCandidateRange
|
||||
{
|
||||
public:
|
||||
CCandidateRange(void);
|
||||
~CCandidateRange(void);
|
||||
|
||||
BOOL IsRange(UINT vKey);
|
||||
int GetIndex(UINT vKey);
|
||||
|
||||
inline int Count() const
|
||||
{
|
||||
return _CandidateListIndexRange.Count();
|
||||
}
|
||||
inline DWORD *GetAt(int index)
|
||||
{
|
||||
return _CandidateListIndexRange.GetAt(index);
|
||||
}
|
||||
inline DWORD *Append()
|
||||
{
|
||||
return _CandidateListIndexRange.Append();
|
||||
}
|
||||
|
||||
private:
|
||||
CMetasequoiaImeArray<DWORD> _CandidateListIndexRange;
|
||||
};
|
||||
|
||||
class CStringRange
|
||||
{
|
||||
public:
|
||||
CStringRange();
|
||||
CStringRange(const CStringRange &sr);
|
||||
~CStringRange();
|
||||
|
||||
const WCHAR *Get() const;
|
||||
const DWORD_PTR GetLength() const;
|
||||
void Clear();
|
||||
void Set(const WCHAR *pwch, DWORD_PTR dwLength);
|
||||
void Set(CStringRange &sr);
|
||||
CStringRange &operator=(const CStringRange &sr);
|
||||
void CharNext(_Inout_ CStringRange *pCharNext);
|
||||
static int Compare(LCID locale, _In_ CStringRange *pString1, _In_ CStringRange *pString2);
|
||||
static BOOL WildcardCompare(LCID locale, _In_ CStringRange *stringWithWildcard, _In_ CStringRange *targetString);
|
||||
std::wstring ToWString() const
|
||||
{
|
||||
if (!_pStringBuf || _stringBufLen == 0)
|
||||
return std::wstring();
|
||||
return std::wstring(_pStringBuf, _pStringBuf + _stringBufLen);
|
||||
}
|
||||
|
||||
protected:
|
||||
DWORD_PTR _stringBufLen; // Length is in character count.
|
||||
const WCHAR *_pStringBuf; // Buffer which is not add zero terminate.
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// CCandidateListItem
|
||||
// _ItemString - candidate string
|
||||
// _FindKeyCode - tailing string
|
||||
//---------------------------------------------------------------------
|
||||
struct CCandidateListItem
|
||||
{
|
||||
CStringRange _ItemString;
|
||||
CStringRange _FindKeyCode;
|
||||
|
||||
CCandidateListItem &CCandidateListItem::operator=(const CCandidateListItem &rhs)
|
||||
{
|
||||
_ItemString = rhs._ItemString; // e.g. 你好
|
||||
_FindKeyCode = rhs._FindKeyCode; // e.g. nihao
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
class CPunctuationPair
|
||||
{
|
||||
public:
|
||||
CPunctuationPair();
|
||||
CPunctuationPair(WCHAR code, const WCHAR *punctuation, const WCHAR *pair);
|
||||
|
||||
struct _PUNCTUATION _punctuation;
|
||||
WCHAR _pairPunctuation[3];
|
||||
BOOL _isPairToggle;
|
||||
};
|
||||
|
||||
class CPunctuationNestPair
|
||||
{
|
||||
public:
|
||||
CPunctuationNestPair();
|
||||
CPunctuationNestPair( //
|
||||
WCHAR codeBegin, //
|
||||
const WCHAR *punctuationBegin, //
|
||||
const WCHAR *pairBegin, //
|
||||
const WCHAR codeEnd, //
|
||||
const WCHAR *punctuationEnd, //
|
||||
const WCHAR *pairEnd //
|
||||
);
|
||||
|
||||
struct _PUNCTUATION _punctuation_begin;
|
||||
WCHAR _pairPunctuation_begin[3];
|
||||
|
||||
struct _PUNCTUATION _punctuation_end;
|
||||
WCHAR _pairPunctuation_end[3];
|
||||
|
||||
int _nestCount;
|
||||
};
|
||||
@@ -1,82 +1,82 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CMetasequoiaIMEMetasequoiaIMEStructureArray.h
|
||||
//
|
||||
// CMetasequoiaIMEStructureArray declaration.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
template <class T> class CMetasequoiaIMEStructureArray
|
||||
{
|
||||
typedef typename std::vector<T> value_type;
|
||||
typedef const T &CONST_REF;
|
||||
typedef typename value_type CMetasequoiaIMEArray;
|
||||
typedef typename value_type::iterator CMetasequoiaIMEIter;
|
||||
|
||||
public:
|
||||
CMetasequoiaIMEStructureArray() : _imeVector()
|
||||
{
|
||||
}
|
||||
|
||||
explicit CMetasequoiaIMEStructureArray(size_t iCount) : _imeVector(iCount)
|
||||
{
|
||||
}
|
||||
|
||||
CMetasequoiaIMEStructureArray(size_t iCount, CONST_REF tVal) : _imeVector(iCount, tVal)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~CMetasequoiaIMEStructureArray()
|
||||
{
|
||||
}
|
||||
|
||||
inline CONST_REF GetAt(size_t iIndex) const
|
||||
{
|
||||
assert(iIndex <= _imeVector.size());
|
||||
assert(_imeVector.size() > 0);
|
||||
|
||||
return _imeVector[iIndex];
|
||||
}
|
||||
|
||||
inline T &GetAt(size_t iIndex)
|
||||
{
|
||||
assert(iIndex <= _imeVector.size());
|
||||
assert(_imeVector.size() > 0);
|
||||
|
||||
return _imeVector[iIndex];
|
||||
}
|
||||
|
||||
void RemoveAt(size_t iIndex, size_t iElements)
|
||||
{
|
||||
assert(iIndex <= _imeVector.size());
|
||||
assert(_imeVector.size() > 0);
|
||||
|
||||
CMetasequoiaIMEIter beginIter = _imeVector.begin() + iIndex;
|
||||
CMetasequoiaIMEIter lastIter = beginIter + iElements - 1;
|
||||
|
||||
_imeVector.erase(beginIter, lastIter);
|
||||
}
|
||||
|
||||
size_t Count() const
|
||||
{
|
||||
return _imeVector.size();
|
||||
}
|
||||
|
||||
void Append(const T &tVal)
|
||||
{
|
||||
_imeVector.push_back(tVal);
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
_imeVector.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
CMetasequoiaIMEArray _imeVector; // the actual array of data
|
||||
CMetasequoiaIMEIter _imeIter;
|
||||
};
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CMetasequoiaIMEMetasequoiaIMEStructureArray.h
|
||||
//
|
||||
// CMetasequoiaIMEStructureArray declaration.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
template <class T> class CMetasequoiaIMEStructureArray
|
||||
{
|
||||
typedef typename std::vector<T> value_type;
|
||||
typedef const T &CONST_REF;
|
||||
typedef typename value_type CMetasequoiaIMEArray;
|
||||
typedef typename value_type::iterator CMetasequoiaIMEIter;
|
||||
|
||||
public:
|
||||
CMetasequoiaIMEStructureArray() : _imeVector()
|
||||
{
|
||||
}
|
||||
|
||||
explicit CMetasequoiaIMEStructureArray(size_t iCount) : _imeVector(iCount)
|
||||
{
|
||||
}
|
||||
|
||||
CMetasequoiaIMEStructureArray(size_t iCount, CONST_REF tVal) : _imeVector(iCount, tVal)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~CMetasequoiaIMEStructureArray()
|
||||
{
|
||||
}
|
||||
|
||||
inline CONST_REF GetAt(size_t iIndex) const
|
||||
{
|
||||
assert(iIndex <= _imeVector.size());
|
||||
assert(_imeVector.size() > 0);
|
||||
|
||||
return _imeVector[iIndex];
|
||||
}
|
||||
|
||||
inline T &GetAt(size_t iIndex)
|
||||
{
|
||||
assert(iIndex <= _imeVector.size());
|
||||
assert(_imeVector.size() > 0);
|
||||
|
||||
return _imeVector[iIndex];
|
||||
}
|
||||
|
||||
void RemoveAt(size_t iIndex, size_t iElements)
|
||||
{
|
||||
assert(iIndex <= _imeVector.size());
|
||||
assert(_imeVector.size() > 0);
|
||||
|
||||
CMetasequoiaIMEIter beginIter = _imeVector.begin() + iIndex;
|
||||
CMetasequoiaIMEIter lastIter = beginIter + iElements - 1;
|
||||
|
||||
_imeVector.erase(beginIter, lastIter);
|
||||
}
|
||||
|
||||
size_t Count() const
|
||||
{
|
||||
return _imeVector.size();
|
||||
}
|
||||
|
||||
void Append(const T &tVal)
|
||||
{
|
||||
_imeVector.push_back(tVal);
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
_imeVector.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
CMetasequoiaIMEArray _imeVector; // the actual array of data
|
||||
CMetasequoiaIMEIter _imeIter;
|
||||
};
|
||||
@@ -1,403 +1,403 @@
|
||||
#include "KeyStateCategory.h"
|
||||
#include "Globals.h"
|
||||
#include "Ipc.h"
|
||||
#include "MetasequoiaIMEBaseStructure.h"
|
||||
#include <debugapi.h>
|
||||
|
||||
thread_local CKeyStateCategoryFactory *CKeyStateCategoryFactory::_instance = nullptr;
|
||||
|
||||
CKeyStateCategoryFactory::CKeyStateCategoryFactory()
|
||||
{
|
||||
_instance = nullptr;
|
||||
}
|
||||
|
||||
CKeyStateCategoryFactory *CKeyStateCategoryFactory::Instance()
|
||||
{
|
||||
if (nullptr == _instance)
|
||||
{
|
||||
_instance = new (std::nothrow) CKeyStateCategoryFactory();
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
|
||||
CKeyStateCategory *CKeyStateCategoryFactory::MakeKeyStateCategory(KEYSTROKE_CATEGORY keyCategory,
|
||||
_In_ CMetasequoiaIME *pTextService)
|
||||
{
|
||||
CKeyStateCategory *pKeyState = nullptr;
|
||||
|
||||
switch (keyCategory)
|
||||
{
|
||||
case CATEGORY_NONE:
|
||||
pKeyState = new (std::nothrow) CKeyStateNull(pTextService);
|
||||
break;
|
||||
|
||||
case CATEGORY_COMPOSING:
|
||||
pKeyState = new (std::nothrow) CKeyStateComposing(pTextService);
|
||||
break;
|
||||
|
||||
case CATEGORY_CANDIDATE:
|
||||
pKeyState = new (std::nothrow) CKeyStateCandidate(pTextService);
|
||||
break;
|
||||
|
||||
default:
|
||||
pKeyState = new (std::nothrow) CKeyStateNull(pTextService);
|
||||
break;
|
||||
}
|
||||
return pKeyState;
|
||||
}
|
||||
|
||||
void CKeyStateCategoryFactory::Release()
|
||||
{
|
||||
if (_instance)
|
||||
{
|
||||
delete _instance;
|
||||
_instance = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
class CKeyStateCategory
|
||||
*/
|
||||
CKeyStateCategory::CKeyStateCategory(_In_ CMetasequoiaIME *pTextService)
|
||||
{
|
||||
_pTextService = pTextService;
|
||||
}
|
||||
|
||||
CKeyStateCategory::~CKeyStateCategory(void)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT CKeyStateCategory::KeyStateHandler(KEYSTROKE_FUNCTION function, KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
switch (function)
|
||||
{
|
||||
case FUNCTION_INPUT:
|
||||
return HandleKeyInput(dto);
|
||||
|
||||
case FUNCTION_FINALIZE_TEXTSTORE_AND_INPUT:
|
||||
return HandleKeyFinalizeTextStoreAndInput(dto);
|
||||
|
||||
case FUNCTION_FINALIZE_TEXTSTORE:
|
||||
return HandleKeyFinalizeTextStore(dto);
|
||||
|
||||
case FUNCTION_FINALIZE_CANDIDATELIST_AND_INPUT:
|
||||
return HandleKeyFinalizeCandidatelistAndInput(dto);
|
||||
|
||||
case FUNCTION_FINALIZE_CANDIDATELIST:
|
||||
return HandleKeyFinalizeCandidatelist(dto);
|
||||
case FUNCTION_FINALIZE_CANDIDATELISTForVKReturn:
|
||||
return HandleKeyFinalizeCandidatelistForVKReturn(dto);
|
||||
|
||||
case FUNCTION_INSERT_TEXT:
|
||||
return _pTextService->_HandleInsertText(dto.ec, dto.pContext, dto.prefetchedText);
|
||||
|
||||
case FUNCTION_UPDATE_VOICE_COMPOSITION:
|
||||
return _pTextService->_HandleUpdateVoiceComposition(dto.ec, dto.pContext, dto.prefetchedText);
|
||||
|
||||
case FUNCTION_COMMIT_VOICE_COMPOSITION:
|
||||
return _pTextService->_HandleCommitVoiceComposition(dto.ec, dto.pContext, dto.prefetchedText);
|
||||
|
||||
case FUNCTION_CANCEL_VOICE_COMPOSITION:
|
||||
return _pTextService->_HandleCancelVoiceComposition(dto.ec, dto.pContext);
|
||||
|
||||
case FUNCTION_CONVERT: {
|
||||
return HandleKeyConvert(dto);
|
||||
}
|
||||
|
||||
case FUNCTION_CONVERT_WILDCARD:
|
||||
return HandleKeyConvertWildCard(dto);
|
||||
|
||||
case FUNCTION_CANCEL:
|
||||
return HandleKeyCancel(dto);
|
||||
|
||||
case FUNCTION_TOGGLE_IME_MODE:
|
||||
return HandleKeyToogleIMEMode(dto);
|
||||
|
||||
case FUNCTION_BACKSPACE:
|
||||
return HandleKeyBackspace(dto);
|
||||
|
||||
case FUNCTION_DELETE:
|
||||
return HandleKeyDelete(dto);
|
||||
|
||||
case FUNCTION_MOVE_LEFT:
|
||||
case FUNCTION_MOVE_RIGHT:
|
||||
return HandleKeyArrow(dto);
|
||||
|
||||
case FUNCTION_MOVE_UP:
|
||||
case FUNCTION_MOVE_DOWN:
|
||||
case FUNCTION_MOVE_PAGE_UP:
|
||||
case FUNCTION_MOVE_PAGE_DOWN:
|
||||
case FUNCTION_MOVE_PAGE_TOP:
|
||||
case FUNCTION_MOVE_PAGE_BOTTOM:
|
||||
return HandleKeyArrow(dto);
|
||||
|
||||
case FUNCTION_DOUBLE_SINGLE_BYTE:
|
||||
return HandleKeyDoubleSingleByte(dto);
|
||||
|
||||
case FUNCTION_PUNCTUATION:
|
||||
return HandleKeyPunctuation(dto);
|
||||
|
||||
case FUNCTION_SELECT_BY_NUMBER:
|
||||
return HandleKeySelectByNumber(dto);
|
||||
|
||||
case FUNCTION_NONE:
|
||||
break;
|
||||
}
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
void CKeyStateCategory::Release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
// _HandleCompositionInput
|
||||
HRESULT CKeyStateCategory::HandleKeyInput(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
// HandleKeyFinalizeTextStore
|
||||
HRESULT CKeyStateCategory::HandleKeyFinalizeTextStore(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
// HandleKeyCompositionFinalizeTextStoreAndInput
|
||||
HRESULT CKeyStateCategory::HandleKeyFinalizeTextStoreAndInput(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
// HandleKeyCompositionFinalizeCandidatelistAndInput
|
||||
HRESULT CKeyStateCategory::HandleKeyFinalizeCandidatelistAndInput(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
// HandleKeyCompositionFinalizeCandidatelist
|
||||
HRESULT CKeyStateCategory::HandleKeyFinalizeCandidatelist(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
// HandleKeyCompositionFinalizeCandidatelistForVKReturn
|
||||
HRESULT CKeyStateCategory::HandleKeyFinalizeCandidatelistForVKReturn(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
// HandleKeyConvert
|
||||
HRESULT CKeyStateCategory::HandleKeyConvert(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
// HandleKeyConvertWildCard
|
||||
HRESULT CKeyStateCategory::HandleKeyConvertWildCard(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
//_HandleCancel
|
||||
HRESULT CKeyStateCategory::HandleKeyCancel(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT CKeyStateCategory::HandleKeyToogleIMEMode(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
//_HandleCompositionBackspace
|
||||
HRESULT CKeyStateCategory::HandleKeyBackspace(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
//_HandleCompositionDelete
|
||||
HRESULT CKeyStateCategory::HandleKeyDelete(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
//_HandleCompositionArrowKey
|
||||
HRESULT CKeyStateCategory::HandleKeyArrow(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
//_HandleCompositionDoubleSingleByte
|
||||
HRESULT CKeyStateCategory::HandleKeyDoubleSingleByte(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
//_HandleCompositionPunctuation
|
||||
HRESULT CKeyStateCategory::HandleKeyPunctuation(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT CKeyStateCategory::HandleKeySelectByNumber(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
/*
|
||||
class CKeyStateComposing
|
||||
*/
|
||||
CKeyStateComposing::CKeyStateComposing(_In_ CMetasequoiaIME *pTextService) : CKeyStateCategory(pTextService)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyInput(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCompositionInput(dto.ec, dto.pContext, dto.wch, dto.requestId);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyFinalizeTextStoreAndInput(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
_pTextService->_HandleCompositionFinalize(dto.ec, dto.pContext, FALSE);
|
||||
return _pTextService->_HandleCompositionInput(dto.ec, dto.pContext, dto.wch, dto.requestId);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyFinalizeTextStore(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCompositionFinalize(dto.ec, dto.pContext, FALSE);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyFinalizeCandidatelistAndInput(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
_pTextService->_HandleCompositionFinalize(dto.ec, dto.pContext, TRUE);
|
||||
return _pTextService->_HandleCompositionInput(dto.ec, dto.pContext, dto.wch, dto.requestId);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyFinalizeCandidatelist(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCompositionFinalize(dto.ec, dto.pContext, TRUE);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyConvert(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
if (dto.code == VK_SPACE)
|
||||
{
|
||||
return _pTextService->_HandleCandidateFinalize(dto.ec, dto.pContext, dto.requestId, dto.prefetchedText);
|
||||
}
|
||||
// VK_SPACE
|
||||
return _pTextService->_HandleCompositionConvert(dto.ec, dto.pContext, FALSE);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyConvertWildCard(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCompositionConvert(dto.ec, dto.pContext, TRUE);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyCancel(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCancel(dto.ec, dto.pContext);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyToogleIMEMode(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleToogleIMEMode(dto.ec, dto.pContext);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyBackspace(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCompositionBackspace(dto.ec, dto.pContext, dto.requestId);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyDelete(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCompositionDelete(dto.ec, dto.pContext, dto.requestId);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyArrow(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCompositionArrowKey(dto.ec, dto.pContext, dto.arrowKey, dto.requestId);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyDoubleSingleByte(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCompositionDoubleSingleByte(dto.ec, dto.pContext, dto.wch);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyPunctuation(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCompositionPunctuation(dto.ec, dto.pContext, dto.code, dto.wch, dto.requestId,
|
||||
dto.prefetchedText);
|
||||
}
|
||||
|
||||
/*
|
||||
class CKeyStateCandidate
|
||||
*/
|
||||
CKeyStateCandidate::CKeyStateCandidate(_In_ CMetasequoiaIME *pTextService) : CKeyStateCategory(pTextService)
|
||||
{
|
||||
}
|
||||
|
||||
// _HandleCandidateInput
|
||||
HRESULT CKeyStateCandidate::HandleKeyFinalizeCandidatelist(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCandidateFinalize(dto.ec, dto.pContext, dto.requestId, dto.prefetchedText);
|
||||
}
|
||||
|
||||
// _HandleCandidateInput
|
||||
HRESULT CKeyStateCandidate::HandleKeyFinalizeCandidatelistForVKReturn(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCandidateFinalizeForVKReturn(dto.ec, dto.pContext);
|
||||
}
|
||||
|
||||
// HandleKeyFinalizeCandidatelistAndInput
|
||||
HRESULT CKeyStateCandidate::HandleKeyFinalizeCandidatelistAndInput(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
_pTextService->_HandleCandidateFinalize(dto.ec, dto.pContext, dto.requestId, dto.prefetchedText);
|
||||
return _pTextService->_HandleCompositionInput(dto.ec, dto.pContext, dto.wch, dto.requestId);
|
||||
}
|
||||
|
||||
//_HandleCandidateConvert
|
||||
HRESULT CKeyStateCandidate::HandleKeyConvert(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
if (dto.code == VK_SPACE)
|
||||
{
|
||||
return _pTextService->_HandleCandidateFinalize(dto.ec, dto.pContext, dto.requestId, dto.prefetchedText);
|
||||
}
|
||||
// Send candidate string to client when pressing VK_SPACE
|
||||
return _pTextService->_HandleCandidateConvert(dto.ec, dto.pContext, dto.requestId, dto.prefetchedText);
|
||||
}
|
||||
|
||||
//_HandleCancel
|
||||
HRESULT CKeyStateCandidate::HandleKeyCancel(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCancel(dto.ec, dto.pContext);
|
||||
}
|
||||
|
||||
//_HandleCandidateArrowKey
|
||||
HRESULT CKeyStateCandidate::HandleKeyArrow(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCandidateArrowKey(dto.ec, dto.pContext, dto.arrowKey, dto.requestId);
|
||||
}
|
||||
|
||||
//_HandleCandidateSelectByNumber
|
||||
HRESULT CKeyStateCandidate::HandleKeySelectByNumber(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
// return _pTextService->_HandleCandidateSelectByNumber(dto.ec, dto.pContext, dto.code);
|
||||
return _pTextService->_HandleCandidateFinalize(dto.ec, dto.pContext, dto.requestId, dto.prefetchedText);
|
||||
}
|
||||
#include "KeyStateCategory.h"
|
||||
#include "Globals.h"
|
||||
#include "Ipc.h"
|
||||
#include "MetasequoiaIMEBaseStructure.h"
|
||||
#include <debugapi.h>
|
||||
|
||||
thread_local CKeyStateCategoryFactory *CKeyStateCategoryFactory::_instance = nullptr;
|
||||
|
||||
CKeyStateCategoryFactory::CKeyStateCategoryFactory()
|
||||
{
|
||||
_instance = nullptr;
|
||||
}
|
||||
|
||||
CKeyStateCategoryFactory *CKeyStateCategoryFactory::Instance()
|
||||
{
|
||||
if (nullptr == _instance)
|
||||
{
|
||||
_instance = new (std::nothrow) CKeyStateCategoryFactory();
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
|
||||
CKeyStateCategory *CKeyStateCategoryFactory::MakeKeyStateCategory(KEYSTROKE_CATEGORY keyCategory,
|
||||
_In_ CMetasequoiaIME *pTextService)
|
||||
{
|
||||
CKeyStateCategory *pKeyState = nullptr;
|
||||
|
||||
switch (keyCategory)
|
||||
{
|
||||
case CATEGORY_NONE:
|
||||
pKeyState = new (std::nothrow) CKeyStateNull(pTextService);
|
||||
break;
|
||||
|
||||
case CATEGORY_COMPOSING:
|
||||
pKeyState = new (std::nothrow) CKeyStateComposing(pTextService);
|
||||
break;
|
||||
|
||||
case CATEGORY_CANDIDATE:
|
||||
pKeyState = new (std::nothrow) CKeyStateCandidate(pTextService);
|
||||
break;
|
||||
|
||||
default:
|
||||
pKeyState = new (std::nothrow) CKeyStateNull(pTextService);
|
||||
break;
|
||||
}
|
||||
return pKeyState;
|
||||
}
|
||||
|
||||
void CKeyStateCategoryFactory::Release()
|
||||
{
|
||||
if (_instance)
|
||||
{
|
||||
delete _instance;
|
||||
_instance = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
class CKeyStateCategory
|
||||
*/
|
||||
CKeyStateCategory::CKeyStateCategory(_In_ CMetasequoiaIME *pTextService)
|
||||
{
|
||||
_pTextService = pTextService;
|
||||
}
|
||||
|
||||
CKeyStateCategory::~CKeyStateCategory(void)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT CKeyStateCategory::KeyStateHandler(KEYSTROKE_FUNCTION function, KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
switch (function)
|
||||
{
|
||||
case FUNCTION_INPUT:
|
||||
return HandleKeyInput(dto);
|
||||
|
||||
case FUNCTION_FINALIZE_TEXTSTORE_AND_INPUT:
|
||||
return HandleKeyFinalizeTextStoreAndInput(dto);
|
||||
|
||||
case FUNCTION_FINALIZE_TEXTSTORE:
|
||||
return HandleKeyFinalizeTextStore(dto);
|
||||
|
||||
case FUNCTION_FINALIZE_CANDIDATELIST_AND_INPUT:
|
||||
return HandleKeyFinalizeCandidatelistAndInput(dto);
|
||||
|
||||
case FUNCTION_FINALIZE_CANDIDATELIST:
|
||||
return HandleKeyFinalizeCandidatelist(dto);
|
||||
case FUNCTION_FINALIZE_CANDIDATELISTForVKReturn:
|
||||
return HandleKeyFinalizeCandidatelistForVKReturn(dto);
|
||||
|
||||
case FUNCTION_INSERT_TEXT:
|
||||
return _pTextService->_HandleInsertText(dto.ec, dto.pContext, dto.prefetchedText);
|
||||
|
||||
case FUNCTION_UPDATE_VOICE_COMPOSITION:
|
||||
return _pTextService->_HandleUpdateVoiceComposition(dto.ec, dto.pContext, dto.prefetchedText);
|
||||
|
||||
case FUNCTION_COMMIT_VOICE_COMPOSITION:
|
||||
return _pTextService->_HandleCommitVoiceComposition(dto.ec, dto.pContext, dto.prefetchedText);
|
||||
|
||||
case FUNCTION_CANCEL_VOICE_COMPOSITION:
|
||||
return _pTextService->_HandleCancelVoiceComposition(dto.ec, dto.pContext);
|
||||
|
||||
case FUNCTION_CONVERT: {
|
||||
return HandleKeyConvert(dto);
|
||||
}
|
||||
|
||||
case FUNCTION_CONVERT_WILDCARD:
|
||||
return HandleKeyConvertWildCard(dto);
|
||||
|
||||
case FUNCTION_CANCEL:
|
||||
return HandleKeyCancel(dto);
|
||||
|
||||
case FUNCTION_TOGGLE_IME_MODE:
|
||||
return HandleKeyToogleIMEMode(dto);
|
||||
|
||||
case FUNCTION_BACKSPACE:
|
||||
return HandleKeyBackspace(dto);
|
||||
|
||||
case FUNCTION_DELETE:
|
||||
return HandleKeyDelete(dto);
|
||||
|
||||
case FUNCTION_MOVE_LEFT:
|
||||
case FUNCTION_MOVE_RIGHT:
|
||||
return HandleKeyArrow(dto);
|
||||
|
||||
case FUNCTION_MOVE_UP:
|
||||
case FUNCTION_MOVE_DOWN:
|
||||
case FUNCTION_MOVE_PAGE_UP:
|
||||
case FUNCTION_MOVE_PAGE_DOWN:
|
||||
case FUNCTION_MOVE_PAGE_TOP:
|
||||
case FUNCTION_MOVE_PAGE_BOTTOM:
|
||||
return HandleKeyArrow(dto);
|
||||
|
||||
case FUNCTION_DOUBLE_SINGLE_BYTE:
|
||||
return HandleKeyDoubleSingleByte(dto);
|
||||
|
||||
case FUNCTION_PUNCTUATION:
|
||||
return HandleKeyPunctuation(dto);
|
||||
|
||||
case FUNCTION_SELECT_BY_NUMBER:
|
||||
return HandleKeySelectByNumber(dto);
|
||||
|
||||
case FUNCTION_NONE:
|
||||
break;
|
||||
}
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
void CKeyStateCategory::Release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
// _HandleCompositionInput
|
||||
HRESULT CKeyStateCategory::HandleKeyInput(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
// HandleKeyFinalizeTextStore
|
||||
HRESULT CKeyStateCategory::HandleKeyFinalizeTextStore(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
// HandleKeyCompositionFinalizeTextStoreAndInput
|
||||
HRESULT CKeyStateCategory::HandleKeyFinalizeTextStoreAndInput(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
// HandleKeyCompositionFinalizeCandidatelistAndInput
|
||||
HRESULT CKeyStateCategory::HandleKeyFinalizeCandidatelistAndInput(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
// HandleKeyCompositionFinalizeCandidatelist
|
||||
HRESULT CKeyStateCategory::HandleKeyFinalizeCandidatelist(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
// HandleKeyCompositionFinalizeCandidatelistForVKReturn
|
||||
HRESULT CKeyStateCategory::HandleKeyFinalizeCandidatelistForVKReturn(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
// HandleKeyConvert
|
||||
HRESULT CKeyStateCategory::HandleKeyConvert(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
// HandleKeyConvertWildCard
|
||||
HRESULT CKeyStateCategory::HandleKeyConvertWildCard(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
//_HandleCancel
|
||||
HRESULT CKeyStateCategory::HandleKeyCancel(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT CKeyStateCategory::HandleKeyToogleIMEMode(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
//_HandleCompositionBackspace
|
||||
HRESULT CKeyStateCategory::HandleKeyBackspace(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
//_HandleCompositionDelete
|
||||
HRESULT CKeyStateCategory::HandleKeyDelete(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
//_HandleCompositionArrowKey
|
||||
HRESULT CKeyStateCategory::HandleKeyArrow(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
//_HandleCompositionDoubleSingleByte
|
||||
HRESULT CKeyStateCategory::HandleKeyDoubleSingleByte(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
//_HandleCompositionPunctuation
|
||||
HRESULT CKeyStateCategory::HandleKeyPunctuation(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT CKeyStateCategory::HandleKeySelectByNumber(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
dto;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
/*
|
||||
class CKeyStateComposing
|
||||
*/
|
||||
CKeyStateComposing::CKeyStateComposing(_In_ CMetasequoiaIME *pTextService) : CKeyStateCategory(pTextService)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyInput(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCompositionInput(dto.ec, dto.pContext, dto.wch, dto.requestId);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyFinalizeTextStoreAndInput(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
_pTextService->_HandleCompositionFinalize(dto.ec, dto.pContext, FALSE);
|
||||
return _pTextService->_HandleCompositionInput(dto.ec, dto.pContext, dto.wch, dto.requestId);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyFinalizeTextStore(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCompositionFinalize(dto.ec, dto.pContext, FALSE);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyFinalizeCandidatelistAndInput(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
_pTextService->_HandleCompositionFinalize(dto.ec, dto.pContext, TRUE);
|
||||
return _pTextService->_HandleCompositionInput(dto.ec, dto.pContext, dto.wch, dto.requestId);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyFinalizeCandidatelist(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCompositionFinalize(dto.ec, dto.pContext, TRUE);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyConvert(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
if (dto.code == VK_SPACE)
|
||||
{
|
||||
return _pTextService->_HandleCandidateFinalize(dto.ec, dto.pContext, dto.requestId, dto.prefetchedText);
|
||||
}
|
||||
// VK_SPACE
|
||||
return _pTextService->_HandleCompositionConvert(dto.ec, dto.pContext, FALSE);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyConvertWildCard(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCompositionConvert(dto.ec, dto.pContext, TRUE);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyCancel(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCancel(dto.ec, dto.pContext);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyToogleIMEMode(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleToogleIMEMode(dto.ec, dto.pContext);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyBackspace(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCompositionBackspace(dto.ec, dto.pContext, dto.requestId);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyDelete(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCompositionDelete(dto.ec, dto.pContext, dto.requestId);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyArrow(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCompositionArrowKey(dto.ec, dto.pContext, dto.arrowKey, dto.requestId);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyDoubleSingleByte(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCompositionDoubleSingleByte(dto.ec, dto.pContext, dto.wch);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyPunctuation(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCompositionPunctuation(dto.ec, dto.pContext, dto.code, dto.wch, dto.requestId,
|
||||
dto.prefetchedText);
|
||||
}
|
||||
|
||||
/*
|
||||
class CKeyStateCandidate
|
||||
*/
|
||||
CKeyStateCandidate::CKeyStateCandidate(_In_ CMetasequoiaIME *pTextService) : CKeyStateCategory(pTextService)
|
||||
{
|
||||
}
|
||||
|
||||
// _HandleCandidateInput
|
||||
HRESULT CKeyStateCandidate::HandleKeyFinalizeCandidatelist(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCandidateFinalize(dto.ec, dto.pContext, dto.requestId, dto.prefetchedText);
|
||||
}
|
||||
|
||||
// _HandleCandidateInput
|
||||
HRESULT CKeyStateCandidate::HandleKeyFinalizeCandidatelistForVKReturn(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCandidateFinalizeForVKReturn(dto.ec, dto.pContext);
|
||||
}
|
||||
|
||||
// HandleKeyFinalizeCandidatelistAndInput
|
||||
HRESULT CKeyStateCandidate::HandleKeyFinalizeCandidatelistAndInput(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
_pTextService->_HandleCandidateFinalize(dto.ec, dto.pContext, dto.requestId, dto.prefetchedText);
|
||||
return _pTextService->_HandleCompositionInput(dto.ec, dto.pContext, dto.wch, dto.requestId);
|
||||
}
|
||||
|
||||
//_HandleCandidateConvert
|
||||
HRESULT CKeyStateCandidate::HandleKeyConvert(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
if (dto.code == VK_SPACE)
|
||||
{
|
||||
return _pTextService->_HandleCandidateFinalize(dto.ec, dto.pContext, dto.requestId, dto.prefetchedText);
|
||||
}
|
||||
// Send candidate string to client when pressing VK_SPACE
|
||||
return _pTextService->_HandleCandidateConvert(dto.ec, dto.pContext, dto.requestId, dto.prefetchedText);
|
||||
}
|
||||
|
||||
//_HandleCancel
|
||||
HRESULT CKeyStateCandidate::HandleKeyCancel(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCancel(dto.ec, dto.pContext);
|
||||
}
|
||||
|
||||
//_HandleCandidateArrowKey
|
||||
HRESULT CKeyStateCandidate::HandleKeyArrow(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCandidateArrowKey(dto.ec, dto.pContext, dto.arrowKey, dto.requestId);
|
||||
}
|
||||
|
||||
//_HandleCandidateSelectByNumber
|
||||
HRESULT CKeyStateCandidate::HandleKeySelectByNumber(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
// return _pTextService->_HandleCandidateSelectByNumber(dto.ec, dto.pContext, dto.code);
|
||||
return _pTextService->_HandleCandidateFinalize(dto.ec, dto.pContext, dto.requestId, dto.prefetchedText);
|
||||
}
|
||||
+274
-274
@@ -1,274 +1,274 @@
|
||||
#pragma once
|
||||
#include "Globals.h"
|
||||
#include "Private.h"
|
||||
#include "MetasequoiaIME.h"
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
class CKeyStateCategory;
|
||||
|
||||
class CKeyStateCategoryFactory
|
||||
{
|
||||
public:
|
||||
static CKeyStateCategoryFactory *Instance();
|
||||
CKeyStateCategory *MakeKeyStateCategory(KEYSTROKE_CATEGORY keyCategory, _In_ CMetasequoiaIME *pTextService);
|
||||
void Release();
|
||||
|
||||
protected:
|
||||
CKeyStateCategoryFactory();
|
||||
|
||||
private:
|
||||
static thread_local CKeyStateCategoryFactory *_instance;
|
||||
};
|
||||
|
||||
typedef struct KeyHandlerEditSessionDTO
|
||||
{
|
||||
KeyHandlerEditSessionDTO::KeyHandlerEditSessionDTO(TfEditCookie tFEC, _In_ ITfContext *pTfContext, UINT virualCode,
|
||||
WCHAR inputChar, KEYSTROKE_FUNCTION arrowKeyFunction,
|
||||
uint64_t pipeRequestId,
|
||||
const std::wstring &sessionPrefetchedText)
|
||||
{
|
||||
ec = tFEC;
|
||||
pContext = pTfContext;
|
||||
code = virualCode;
|
||||
wch = inputChar;
|
||||
arrowKey = arrowKeyFunction;
|
||||
requestId = pipeRequestId;
|
||||
prefetchedText = sessionPrefetchedText;
|
||||
}
|
||||
|
||||
TfEditCookie ec;
|
||||
ITfContext *pContext;
|
||||
UINT code;
|
||||
WCHAR wch;
|
||||
KEYSTROKE_FUNCTION arrowKey;
|
||||
uint64_t requestId;
|
||||
std::wstring prefetchedText;
|
||||
} KeyHandlerEditSessionDTO;
|
||||
|
||||
class CKeyStateCategory
|
||||
{
|
||||
public:
|
||||
CKeyStateCategory(_In_ CMetasequoiaIME *pTextService);
|
||||
|
||||
protected:
|
||||
~CKeyStateCategory(void);
|
||||
|
||||
public:
|
||||
HRESULT KeyStateHandler(KEYSTROKE_FUNCTION function, KeyHandlerEditSessionDTO dto);
|
||||
void Release(void);
|
||||
|
||||
protected:
|
||||
// HandleKeyInput
|
||||
virtual HRESULT HandleKeyInput(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyFinalizeTextStoreAndInput
|
||||
virtual HRESULT HandleKeyFinalizeTextStoreAndInput(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyFinalizeTextStore
|
||||
virtual HRESULT HandleKeyFinalizeTextStore(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyFinalizeCandidatelistAndInput
|
||||
virtual HRESULT HandleKeyFinalizeCandidatelistAndInput(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyFinalizeCandidatelist
|
||||
virtual HRESULT HandleKeyFinalizeCandidatelist(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyFinalizeCandidatelist
|
||||
virtual HRESULT HandleKeyFinalizeCandidatelistForVKReturn(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyConvert
|
||||
virtual HRESULT HandleKeyConvert(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyConvertWild
|
||||
virtual HRESULT HandleKeyConvertWildCard(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyCancel
|
||||
virtual HRESULT HandleKeyCancel(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// _HandleKeyToogleIMEMode
|
||||
virtual HRESULT HandleKeyToogleIMEMode(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyBackspace
|
||||
virtual HRESULT HandleKeyBackspace(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyDelete
|
||||
virtual HRESULT HandleKeyDelete(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyArrow
|
||||
virtual HRESULT HandleKeyArrow(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyDoubleSingleByte
|
||||
virtual HRESULT HandleKeyDoubleSingleByte(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyPunctuation
|
||||
virtual HRESULT HandleKeyPunctuation(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeySelectByNumber
|
||||
virtual HRESULT HandleKeySelectByNumber(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
protected:
|
||||
CMetasequoiaIME *_pTextService;
|
||||
};
|
||||
|
||||
class CKeyStateComposing : public CKeyStateCategory
|
||||
{
|
||||
public:
|
||||
CKeyStateComposing(_In_ CMetasequoiaIME *pTextService);
|
||||
|
||||
protected:
|
||||
// _HandleCompositionInput
|
||||
HRESULT HandleKeyInput(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyCompositionFinalizeTextStoreAndInput
|
||||
HRESULT HandleKeyFinalizeTextStoreAndInput(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyFinalizeTextStore
|
||||
HRESULT HandleKeyFinalizeTextStore(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyCompositionFinalizeCandidatelistAndInput
|
||||
HRESULT HandleKeyFinalizeCandidatelistAndInput(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyCompositionFinalizeCandidatelist
|
||||
HRESULT HandleKeyFinalizeCandidatelist(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleCompositionConvert
|
||||
HRESULT HandleKeyConvert(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyCompositionConvertWildCard
|
||||
HRESULT HandleKeyConvertWildCard(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleCancel
|
||||
HRESULT HandleKeyCancel(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyToogleIMEMode
|
||||
HRESULT HandleKeyToogleIMEMode(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleCompositionBackspace
|
||||
HRESULT HandleKeyBackspace(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleCompositionDelete
|
||||
HRESULT HandleKeyDelete(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleArrowKey
|
||||
HRESULT HandleKeyArrow(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyDoubleSingleByte
|
||||
HRESULT HandleKeyDoubleSingleByte(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyCompositionPunctuation
|
||||
HRESULT HandleKeyPunctuation(KeyHandlerEditSessionDTO dto);
|
||||
};
|
||||
|
||||
class CKeyStateCandidate : public CKeyStateCategory
|
||||
{
|
||||
public:
|
||||
CKeyStateCandidate(_In_ CMetasequoiaIME *pTextService);
|
||||
|
||||
protected:
|
||||
// HandleKeyFinalizeCandidatelist
|
||||
HRESULT HandleKeyFinalizeCandidatelist(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
HRESULT HandleKeyFinalizeCandidatelistForVKReturn(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyFinalizeCandidatelistAndInput
|
||||
HRESULT HandleKeyFinalizeCandidatelistAndInput(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
//_HandleCandidateConvert
|
||||
HRESULT HandleKeyConvert(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
//_HandleCancel
|
||||
HRESULT HandleKeyCancel(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
//_HandleCandidateArrowKey
|
||||
HRESULT HandleKeyArrow(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
//_HandleCandidateSelectByNumber
|
||||
HRESULT HandleKeySelectByNumber(KeyHandlerEditSessionDTO dto);
|
||||
};
|
||||
|
||||
// degeneration class
|
||||
class CKeyStateNull : public CKeyStateCategory
|
||||
{
|
||||
public:
|
||||
CKeyStateNull(_In_ CMetasequoiaIME *pTextService) : CKeyStateCategory(pTextService) {};
|
||||
|
||||
protected:
|
||||
// _HandleNullInput
|
||||
HRESULT HandleKeyInput(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeyInput(dto);
|
||||
};
|
||||
|
||||
// HandleKeyNullFinalizeTextStoreAndInput
|
||||
HRESULT HandleKeyFinalizeTextStoreAndInput(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeyFinalizeTextStoreAndInput(dto);
|
||||
};
|
||||
|
||||
// HandleKeyFinalizeTextStore
|
||||
HRESULT HandleKeyFinalizeTextStore(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeyFinalizeTextStore(dto);
|
||||
};
|
||||
|
||||
// HandleKeyNullFinalizeCandidatelistAndInput
|
||||
HRESULT HandleKeyFinalizeCandidatelistAndInput(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeyFinalizeCandidatelistAndInput(dto);
|
||||
};
|
||||
|
||||
// HandleKeyNullFinalizeCandidatelist
|
||||
HRESULT HandleKeyFinalizeCandidatelist(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeyFinalizeCandidatelist(dto);
|
||||
};
|
||||
|
||||
//_HandleNullConvert
|
||||
HRESULT HandleKeyConvert(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeyConvert(dto);
|
||||
};
|
||||
|
||||
//_HandleNullCancel
|
||||
HRESULT HandleKeyCancel(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeyCancel(dto);
|
||||
};
|
||||
|
||||
// HandleKeyNullConvertWild
|
||||
HRESULT HandleKeyConvertWildCard(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeyConvertWildCard(dto);
|
||||
};
|
||||
|
||||
//_HandleNullBackspace
|
||||
HRESULT HandleKeyBackspace(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeyBackspace(dto);
|
||||
};
|
||||
|
||||
//_HandleNullArrowKey
|
||||
HRESULT HandleKeyArrow(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeyArrow(dto);
|
||||
};
|
||||
|
||||
// HandleKeyDoubleSingleByte
|
||||
HRESULT HandleKeyDoubleSingleByte(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeyDoubleSingleByte(dto);
|
||||
};
|
||||
|
||||
// HandleKeyPunctuation
|
||||
HRESULT HandleKeyPunctuation(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeyPunctuation(dto);
|
||||
};
|
||||
|
||||
//_HandleNullCandidateSelectByNumber
|
||||
HRESULT HandleKeySelectByNumber(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeySelectByNumber(dto);
|
||||
};
|
||||
};
|
||||
#pragma once
|
||||
#include "Globals.h"
|
||||
#include "Private.h"
|
||||
#include "MetasequoiaIME.h"
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
class CKeyStateCategory;
|
||||
|
||||
class CKeyStateCategoryFactory
|
||||
{
|
||||
public:
|
||||
static CKeyStateCategoryFactory *Instance();
|
||||
CKeyStateCategory *MakeKeyStateCategory(KEYSTROKE_CATEGORY keyCategory, _In_ CMetasequoiaIME *pTextService);
|
||||
void Release();
|
||||
|
||||
protected:
|
||||
CKeyStateCategoryFactory();
|
||||
|
||||
private:
|
||||
static thread_local CKeyStateCategoryFactory *_instance;
|
||||
};
|
||||
|
||||
typedef struct KeyHandlerEditSessionDTO
|
||||
{
|
||||
KeyHandlerEditSessionDTO::KeyHandlerEditSessionDTO(TfEditCookie tFEC, _In_ ITfContext *pTfContext, UINT virualCode,
|
||||
WCHAR inputChar, KEYSTROKE_FUNCTION arrowKeyFunction,
|
||||
uint64_t pipeRequestId,
|
||||
const std::wstring &sessionPrefetchedText)
|
||||
{
|
||||
ec = tFEC;
|
||||
pContext = pTfContext;
|
||||
code = virualCode;
|
||||
wch = inputChar;
|
||||
arrowKey = arrowKeyFunction;
|
||||
requestId = pipeRequestId;
|
||||
prefetchedText = sessionPrefetchedText;
|
||||
}
|
||||
|
||||
TfEditCookie ec;
|
||||
ITfContext *pContext;
|
||||
UINT code;
|
||||
WCHAR wch;
|
||||
KEYSTROKE_FUNCTION arrowKey;
|
||||
uint64_t requestId;
|
||||
std::wstring prefetchedText;
|
||||
} KeyHandlerEditSessionDTO;
|
||||
|
||||
class CKeyStateCategory
|
||||
{
|
||||
public:
|
||||
CKeyStateCategory(_In_ CMetasequoiaIME *pTextService);
|
||||
|
||||
protected:
|
||||
~CKeyStateCategory(void);
|
||||
|
||||
public:
|
||||
HRESULT KeyStateHandler(KEYSTROKE_FUNCTION function, KeyHandlerEditSessionDTO dto);
|
||||
void Release(void);
|
||||
|
||||
protected:
|
||||
// HandleKeyInput
|
||||
virtual HRESULT HandleKeyInput(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyFinalizeTextStoreAndInput
|
||||
virtual HRESULT HandleKeyFinalizeTextStoreAndInput(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyFinalizeTextStore
|
||||
virtual HRESULT HandleKeyFinalizeTextStore(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyFinalizeCandidatelistAndInput
|
||||
virtual HRESULT HandleKeyFinalizeCandidatelistAndInput(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyFinalizeCandidatelist
|
||||
virtual HRESULT HandleKeyFinalizeCandidatelist(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyFinalizeCandidatelist
|
||||
virtual HRESULT HandleKeyFinalizeCandidatelistForVKReturn(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyConvert
|
||||
virtual HRESULT HandleKeyConvert(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyConvertWild
|
||||
virtual HRESULT HandleKeyConvertWildCard(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyCancel
|
||||
virtual HRESULT HandleKeyCancel(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// _HandleKeyToogleIMEMode
|
||||
virtual HRESULT HandleKeyToogleIMEMode(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyBackspace
|
||||
virtual HRESULT HandleKeyBackspace(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyDelete
|
||||
virtual HRESULT HandleKeyDelete(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyArrow
|
||||
virtual HRESULT HandleKeyArrow(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyDoubleSingleByte
|
||||
virtual HRESULT HandleKeyDoubleSingleByte(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyPunctuation
|
||||
virtual HRESULT HandleKeyPunctuation(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeySelectByNumber
|
||||
virtual HRESULT HandleKeySelectByNumber(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
protected:
|
||||
CMetasequoiaIME *_pTextService;
|
||||
};
|
||||
|
||||
class CKeyStateComposing : public CKeyStateCategory
|
||||
{
|
||||
public:
|
||||
CKeyStateComposing(_In_ CMetasequoiaIME *pTextService);
|
||||
|
||||
protected:
|
||||
// _HandleCompositionInput
|
||||
HRESULT HandleKeyInput(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyCompositionFinalizeTextStoreAndInput
|
||||
HRESULT HandleKeyFinalizeTextStoreAndInput(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyFinalizeTextStore
|
||||
HRESULT HandleKeyFinalizeTextStore(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyCompositionFinalizeCandidatelistAndInput
|
||||
HRESULT HandleKeyFinalizeCandidatelistAndInput(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyCompositionFinalizeCandidatelist
|
||||
HRESULT HandleKeyFinalizeCandidatelist(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleCompositionConvert
|
||||
HRESULT HandleKeyConvert(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyCompositionConvertWildCard
|
||||
HRESULT HandleKeyConvertWildCard(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleCancel
|
||||
HRESULT HandleKeyCancel(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyToogleIMEMode
|
||||
HRESULT HandleKeyToogleIMEMode(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleCompositionBackspace
|
||||
HRESULT HandleKeyBackspace(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleCompositionDelete
|
||||
HRESULT HandleKeyDelete(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleArrowKey
|
||||
HRESULT HandleKeyArrow(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyDoubleSingleByte
|
||||
HRESULT HandleKeyDoubleSingleByte(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyCompositionPunctuation
|
||||
HRESULT HandleKeyPunctuation(KeyHandlerEditSessionDTO dto);
|
||||
};
|
||||
|
||||
class CKeyStateCandidate : public CKeyStateCategory
|
||||
{
|
||||
public:
|
||||
CKeyStateCandidate(_In_ CMetasequoiaIME *pTextService);
|
||||
|
||||
protected:
|
||||
// HandleKeyFinalizeCandidatelist
|
||||
HRESULT HandleKeyFinalizeCandidatelist(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
HRESULT HandleKeyFinalizeCandidatelistForVKReturn(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyFinalizeCandidatelistAndInput
|
||||
HRESULT HandleKeyFinalizeCandidatelistAndInput(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
//_HandleCandidateConvert
|
||||
HRESULT HandleKeyConvert(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
//_HandleCancel
|
||||
HRESULT HandleKeyCancel(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
//_HandleCandidateArrowKey
|
||||
HRESULT HandleKeyArrow(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
//_HandleCandidateSelectByNumber
|
||||
HRESULT HandleKeySelectByNumber(KeyHandlerEditSessionDTO dto);
|
||||
};
|
||||
|
||||
// degeneration class
|
||||
class CKeyStateNull : public CKeyStateCategory
|
||||
{
|
||||
public:
|
||||
CKeyStateNull(_In_ CMetasequoiaIME *pTextService) : CKeyStateCategory(pTextService) {};
|
||||
|
||||
protected:
|
||||
// _HandleNullInput
|
||||
HRESULT HandleKeyInput(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeyInput(dto);
|
||||
};
|
||||
|
||||
// HandleKeyNullFinalizeTextStoreAndInput
|
||||
HRESULT HandleKeyFinalizeTextStoreAndInput(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeyFinalizeTextStoreAndInput(dto);
|
||||
};
|
||||
|
||||
// HandleKeyFinalizeTextStore
|
||||
HRESULT HandleKeyFinalizeTextStore(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeyFinalizeTextStore(dto);
|
||||
};
|
||||
|
||||
// HandleKeyNullFinalizeCandidatelistAndInput
|
||||
HRESULT HandleKeyFinalizeCandidatelistAndInput(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeyFinalizeCandidatelistAndInput(dto);
|
||||
};
|
||||
|
||||
// HandleKeyNullFinalizeCandidatelist
|
||||
HRESULT HandleKeyFinalizeCandidatelist(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeyFinalizeCandidatelist(dto);
|
||||
};
|
||||
|
||||
//_HandleNullConvert
|
||||
HRESULT HandleKeyConvert(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeyConvert(dto);
|
||||
};
|
||||
|
||||
//_HandleNullCancel
|
||||
HRESULT HandleKeyCancel(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeyCancel(dto);
|
||||
};
|
||||
|
||||
// HandleKeyNullConvertWild
|
||||
HRESULT HandleKeyConvertWildCard(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeyConvertWildCard(dto);
|
||||
};
|
||||
|
||||
//_HandleNullBackspace
|
||||
HRESULT HandleKeyBackspace(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeyBackspace(dto);
|
||||
};
|
||||
|
||||
//_HandleNullArrowKey
|
||||
HRESULT HandleKeyArrow(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeyArrow(dto);
|
||||
};
|
||||
|
||||
// HandleKeyDoubleSingleByte
|
||||
HRESULT HandleKeyDoubleSingleByte(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeyDoubleSingleByte(dto);
|
||||
};
|
||||
|
||||
// HandleKeyPunctuation
|
||||
HRESULT HandleKeyPunctuation(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeyPunctuation(dto);
|
||||
};
|
||||
|
||||
//_HandleNullCandidateSelectByNumber
|
||||
HRESULT HandleKeySelectByNumber(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return __super::HandleKeySelectByNumber(dto);
|
||||
};
|
||||
};
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,74 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
#include "Private.h"
|
||||
#include "MetasequoiaIME.h"
|
||||
#include "CompositionProcessorEngine.h"
|
||||
#include "Globals.h"
|
||||
#include "Compartment.h"
|
||||
|
||||
class CCompartment;
|
||||
class CCompartmentEventSink;
|
||||
|
||||
class CLangBarItemButton : public ITfLangBarItemButton, public ITfSource
|
||||
{
|
||||
public:
|
||||
CLangBarItemButton(REFGUID guidLangBar, LPCWSTR description, LPCWSTR tooltip, DWORD onIconIndex, DWORD offIconIndex,
|
||||
BOOL isSecureMode);
|
||||
~CLangBarItemButton();
|
||||
|
||||
// IUnknown
|
||||
STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj);
|
||||
STDMETHODIMP_(ULONG) AddRef(void);
|
||||
STDMETHODIMP_(ULONG) Release(void);
|
||||
|
||||
// ITfLangBarItem
|
||||
STDMETHODIMP GetInfo(_Out_ TF_LANGBARITEMINFO *pInfo);
|
||||
STDMETHODIMP GetStatus(_Out_ DWORD *pdwStatus);
|
||||
STDMETHODIMP Show(BOOL fShow);
|
||||
STDMETHODIMP GetTooltipString(_Out_ BSTR *pbstrToolTip);
|
||||
|
||||
// ITfLangBarItemButton
|
||||
STDMETHODIMP OnClick(TfLBIClick click, POINT pt, _In_ const RECT *prcArea);
|
||||
STDMETHODIMP InitMenu(_In_ ITfMenu *pMenu);
|
||||
STDMETHODIMP OnMenuSelect(UINT wID);
|
||||
STDMETHODIMP GetIcon(_Out_ HICON *phIcon);
|
||||
STDMETHODIMP GetText(_Out_ BSTR *pbstrText);
|
||||
|
||||
// ITfSource
|
||||
STDMETHODIMP AdviseSink(__RPC__in REFIID riid, __RPC__in_opt IUnknown *punk, __RPC__out DWORD *pdwCookie);
|
||||
STDMETHODIMP UnadviseSink(DWORD dwCookie);
|
||||
|
||||
// Add/Remove languagebar item
|
||||
HRESULT _AddItem(_In_ ITfThreadMgr *pThreadMgr);
|
||||
HRESULT _RemoveItem(_In_ ITfThreadMgr *pThreadMgr);
|
||||
|
||||
// Register compartment for button On/Off switch
|
||||
BOOL _RegisterCompartment(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId, REFGUID guidCompartment);
|
||||
BOOL _UnregisterCompartment();
|
||||
|
||||
void CleanUp();
|
||||
|
||||
void SetStatus(DWORD dwStatus, BOOL fSet);
|
||||
void RefreshIcon();
|
||||
|
||||
private:
|
||||
ITfLangBarItemSink *_pLangBarItemSink;
|
||||
|
||||
TF_LANGBARITEMINFO _tfLangBarItemInfo;
|
||||
LPCWSTR _pTooltipText;
|
||||
DWORD _onIconIndex;
|
||||
DWORD _offIconIndex;
|
||||
|
||||
BOOL _isAddedToLanguageBar;
|
||||
BOOL _isSecureMode;
|
||||
DWORD _status;
|
||||
|
||||
CCompartment *_pCompartment;
|
||||
CCompartmentEventSink *_pCompartmentEventSink;
|
||||
static HRESULT _CompartmentCallback(_In_ void *pv, REFGUID guidCompartment);
|
||||
|
||||
// The cookie for the sink to CLangBarItemButton.
|
||||
static const DWORD _cookie = 0;
|
||||
|
||||
LONG _refCount;
|
||||
};
|
||||
#pragma once
|
||||
|
||||
#include "Private.h"
|
||||
#include "MetasequoiaIME.h"
|
||||
#include "CompositionProcessorEngine.h"
|
||||
#include "Globals.h"
|
||||
#include "Compartment.h"
|
||||
|
||||
class CCompartment;
|
||||
class CCompartmentEventSink;
|
||||
|
||||
class CLangBarItemButton : public ITfLangBarItemButton, public ITfSource
|
||||
{
|
||||
public:
|
||||
CLangBarItemButton(REFGUID guidLangBar, LPCWSTR description, LPCWSTR tooltip, DWORD onIconIndex, DWORD offIconIndex,
|
||||
BOOL isSecureMode);
|
||||
~CLangBarItemButton();
|
||||
|
||||
// IUnknown
|
||||
STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj);
|
||||
STDMETHODIMP_(ULONG) AddRef(void);
|
||||
STDMETHODIMP_(ULONG) Release(void);
|
||||
|
||||
// ITfLangBarItem
|
||||
STDMETHODIMP GetInfo(_Out_ TF_LANGBARITEMINFO *pInfo);
|
||||
STDMETHODIMP GetStatus(_Out_ DWORD *pdwStatus);
|
||||
STDMETHODIMP Show(BOOL fShow);
|
||||
STDMETHODIMP GetTooltipString(_Out_ BSTR *pbstrToolTip);
|
||||
|
||||
// ITfLangBarItemButton
|
||||
STDMETHODIMP OnClick(TfLBIClick click, POINT pt, _In_ const RECT *prcArea);
|
||||
STDMETHODIMP InitMenu(_In_ ITfMenu *pMenu);
|
||||
STDMETHODIMP OnMenuSelect(UINT wID);
|
||||
STDMETHODIMP GetIcon(_Out_ HICON *phIcon);
|
||||
STDMETHODIMP GetText(_Out_ BSTR *pbstrText);
|
||||
|
||||
// ITfSource
|
||||
STDMETHODIMP AdviseSink(__RPC__in REFIID riid, __RPC__in_opt IUnknown *punk, __RPC__out DWORD *pdwCookie);
|
||||
STDMETHODIMP UnadviseSink(DWORD dwCookie);
|
||||
|
||||
// Add/Remove languagebar item
|
||||
HRESULT _AddItem(_In_ ITfThreadMgr *pThreadMgr);
|
||||
HRESULT _RemoveItem(_In_ ITfThreadMgr *pThreadMgr);
|
||||
|
||||
// Register compartment for button On/Off switch
|
||||
BOOL _RegisterCompartment(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId, REFGUID guidCompartment);
|
||||
BOOL _UnregisterCompartment();
|
||||
|
||||
void CleanUp();
|
||||
|
||||
void SetStatus(DWORD dwStatus, BOOL fSet);
|
||||
void RefreshIcon();
|
||||
|
||||
private:
|
||||
ITfLangBarItemSink *_pLangBarItemSink;
|
||||
|
||||
TF_LANGBARITEMINFO _tfLangBarItemInfo;
|
||||
LPCWSTR _pTooltipText;
|
||||
DWORD _onIconIndex;
|
||||
DWORD _offIconIndex;
|
||||
|
||||
BOOL _isAddedToLanguageBar;
|
||||
BOOL _isSecureMode;
|
||||
DWORD _status;
|
||||
|
||||
CCompartment *_pCompartment;
|
||||
CCompartmentEventSink *_pCompartmentEventSink;
|
||||
static HRESULT _CompartmentCallback(_In_ void *pv, REFGUID guidCompartment);
|
||||
|
||||
// The cookie for the sink to CLangBarItemButton.
|
||||
static const DWORD _cookie = 0;
|
||||
|
||||
LONG _refCount;
|
||||
};
|
||||
+281
-281
@@ -1,281 +1,281 @@
|
||||
#ifndef UNICODE
|
||||
#define UNICODE
|
||||
#endif // !UNICODE
|
||||
|
||||
#ifndef _UNICODE
|
||||
#define _UNICODE
|
||||
#endif // !UNICODE
|
||||
|
||||
#include "Private.h"
|
||||
#include "RegKey.h"
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// ctor
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
CRegKey::CRegKey()
|
||||
{
|
||||
_keyHandle = nullptr;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// dtor
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
CRegKey::~CRegKey()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// operator
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
HKEY CRegKey::GetHKEY()
|
||||
{
|
||||
return _keyHandle;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// Create
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
LONG CRegKey::Create(_In_ HKEY hKeyPresent, _In_ LPCWSTR pwszKeyName, _In_reads_opt_(255) LPWSTR pwszClass,
|
||||
DWORD dwOptions, REGSAM samDesired, _Inout_ LPSECURITY_ATTRIBUTES lpSecAttr,
|
||||
_Out_opt_ LPDWORD lpdwDisposition)
|
||||
{
|
||||
DWORD disposition = 0;
|
||||
HKEY keyHandle = nullptr;
|
||||
|
||||
LONG res = RegCreateKeyEx(hKeyPresent, pwszKeyName, 0, pwszClass, dwOptions, samDesired, lpSecAttr, &keyHandle,
|
||||
&disposition);
|
||||
|
||||
if (lpdwDisposition != nullptr)
|
||||
{
|
||||
*lpdwDisposition = disposition;
|
||||
}
|
||||
|
||||
if (res == ERROR_SUCCESS)
|
||||
{
|
||||
Close();
|
||||
_keyHandle = keyHandle;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// Open
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
LONG CRegKey::Open(_In_ HKEY hKeyParent, _In_ LPCWSTR pwszKeyName, REGSAM samDesired)
|
||||
{
|
||||
HKEY keyHandle = nullptr;
|
||||
|
||||
LONG res = RegOpenKeyEx(hKeyParent, pwszKeyName, 0, samDesired, &keyHandle);
|
||||
if (res == ERROR_SUCCESS)
|
||||
{
|
||||
Close();
|
||||
_keyHandle = keyHandle;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// Close
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
LONG CRegKey::Close()
|
||||
{
|
||||
LONG res = ERROR_SUCCESS;
|
||||
if (_keyHandle)
|
||||
{
|
||||
res = RegCloseKey(_keyHandle);
|
||||
_keyHandle = nullptr;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// DeleteSubKey
|
||||
// RecurseDeleteKey
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
LONG CRegKey::DeleteSubKey(_In_ LPCWSTR pwszSubKey)
|
||||
{
|
||||
return RegDeleteKey(_keyHandle, pwszSubKey);
|
||||
}
|
||||
|
||||
LONG CRegKey::RecurseDeleteKey(_In_ LPCWSTR pwszSubKey)
|
||||
{
|
||||
CRegKey key;
|
||||
LONG res = key.Open(_keyHandle, pwszSubKey, KEY_READ | KEY_WRITE);
|
||||
if (res != ERROR_SUCCESS)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
FILETIME time;
|
||||
WCHAR subKeyName[256] = {'\0'};
|
||||
DWORD subKeyNameSize = ARRAYSIZE(subKeyName);
|
||||
|
||||
while (RegEnumKeyEx(key.GetHKEY(), 0, subKeyName, &subKeyNameSize, NULL, NULL, NULL, &time) == ERROR_SUCCESS)
|
||||
{
|
||||
subKeyName[ARRAYSIZE(subKeyName) - 1] = L'\0';
|
||||
res = key.RecurseDeleteKey(subKeyName);
|
||||
if (res != ERROR_SUCCESS)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
subKeyNameSize = ARRAYSIZE(subKeyName);
|
||||
}
|
||||
|
||||
key.Close();
|
||||
|
||||
return DeleteSubKey(pwszSubKey);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// DeleteValue
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
LONG CRegKey::DeleteValue(_In_ LPCWSTR pwszValue)
|
||||
{
|
||||
return RegDeleteValue(_keyHandle, pwszValue);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// QueryStingValue
|
||||
// SetStringValue
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
LONG CRegKey::QueryStringValue(_In_opt_ LPCWSTR pwszValueName, _Out_writes_opt_(*pnChars) LPWSTR pwszValue,
|
||||
_Inout_ ULONG *pnChars)
|
||||
{
|
||||
LONG res = 0;
|
||||
DWORD dataType = REG_NONE;
|
||||
ULONG pwszValueSize = 0;
|
||||
|
||||
if (pnChars == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
pwszValueSize = (*pnChars) * sizeof(WCHAR);
|
||||
*pnChars = 0;
|
||||
|
||||
res = RegQueryValueEx(_keyHandle, pwszValueName, NULL, &dataType, (LPBYTE)pwszValue, &pwszValueSize);
|
||||
if (res != ERROR_SUCCESS)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
if ((dataType != REG_SZ) && (dataType != REG_EXPAND_SZ))
|
||||
{
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
*pnChars = pwszValueSize / sizeof(WCHAR);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
LONG CRegKey::SetStringValue(_In_opt_ LPCWSTR pwszValueName, _In_ LPCWSTR pwszValue, DWORD dwType)
|
||||
{
|
||||
size_t lenOfValue = 0;
|
||||
if (pwszValue == nullptr)
|
||||
{
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (StringCchLength(pwszValue, STRSAFE_MAX_CCH, &lenOfValue) != S_OK)
|
||||
{
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
DWORD len = static_cast<DWORD>(lenOfValue);
|
||||
return RegSetValueEx(_keyHandle, pwszValueName, NULL, dwType, (LPBYTE)pwszValue, (++len) * sizeof(WCHAR));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// QueryDWORDValue
|
||||
// SetDWORDValue
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
LONG CRegKey::QueryDWORDValue(_In_opt_ LPCWSTR pwszValueName, _Out_ DWORD &dwValue)
|
||||
{
|
||||
LONG res = 0;
|
||||
DWORD dataType = REG_NONE;
|
||||
ULONG pwszValueSize = 0;
|
||||
|
||||
pwszValueSize = sizeof(DWORD);
|
||||
res = RegQueryValueEx(_keyHandle, pwszValueName, NULL, &dataType, (LPBYTE)(&dwValue), &pwszValueSize);
|
||||
if (res != ERROR_SUCCESS)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
if (dataType != REG_DWORD)
|
||||
{
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
LONG CRegKey::SetDWORDValue(_In_opt_ LPCWSTR pwszValueName, DWORD dwValue)
|
||||
{
|
||||
return RegSetValueEx(_keyHandle, pwszValueName, NULL, REG_DWORD, (LPBYTE)(&dwValue), sizeof(DWORD));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// QueryBinaryValue
|
||||
// SetBinaryValue
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
LONG CRegKey::QueryBinaryValue(_In_opt_ LPCWSTR pwszValueName, _Out_writes_opt_(cbData) BYTE *lpData, DWORD cbData)
|
||||
{
|
||||
LONG res = 0;
|
||||
DWORD dataType = REG_NONE;
|
||||
ULONG pwszValueSize = 0;
|
||||
|
||||
pwszValueSize = cbData;
|
||||
res = RegQueryValueEx(_keyHandle, pwszValueName, NULL, &dataType, lpData, &pwszValueSize);
|
||||
if (res != ERROR_SUCCESS)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
if (dataType != REG_BINARY)
|
||||
{
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
if (pwszValueSize != cbData)
|
||||
{
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
LONG CRegKey::SetBinaryValue(_In_opt_ LPCWSTR pwszValueName, _In_reads_(cbData) BYTE *lpData, DWORD cbData)
|
||||
{
|
||||
return RegSetValueEx(_keyHandle, pwszValueName, NULL, REG_BINARY, lpData, cbData);
|
||||
}
|
||||
#ifndef UNICODE
|
||||
#define UNICODE
|
||||
#endif // !UNICODE
|
||||
|
||||
#ifndef _UNICODE
|
||||
#define _UNICODE
|
||||
#endif // !UNICODE
|
||||
|
||||
#include "Private.h"
|
||||
#include "RegKey.h"
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// ctor
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
CRegKey::CRegKey()
|
||||
{
|
||||
_keyHandle = nullptr;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// dtor
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
CRegKey::~CRegKey()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// operator
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
HKEY CRegKey::GetHKEY()
|
||||
{
|
||||
return _keyHandle;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// Create
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
LONG CRegKey::Create(_In_ HKEY hKeyPresent, _In_ LPCWSTR pwszKeyName, _In_reads_opt_(255) LPWSTR pwszClass,
|
||||
DWORD dwOptions, REGSAM samDesired, _Inout_ LPSECURITY_ATTRIBUTES lpSecAttr,
|
||||
_Out_opt_ LPDWORD lpdwDisposition)
|
||||
{
|
||||
DWORD disposition = 0;
|
||||
HKEY keyHandle = nullptr;
|
||||
|
||||
LONG res = RegCreateKeyEx(hKeyPresent, pwszKeyName, 0, pwszClass, dwOptions, samDesired, lpSecAttr, &keyHandle,
|
||||
&disposition);
|
||||
|
||||
if (lpdwDisposition != nullptr)
|
||||
{
|
||||
*lpdwDisposition = disposition;
|
||||
}
|
||||
|
||||
if (res == ERROR_SUCCESS)
|
||||
{
|
||||
Close();
|
||||
_keyHandle = keyHandle;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// Open
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
LONG CRegKey::Open(_In_ HKEY hKeyParent, _In_ LPCWSTR pwszKeyName, REGSAM samDesired)
|
||||
{
|
||||
HKEY keyHandle = nullptr;
|
||||
|
||||
LONG res = RegOpenKeyEx(hKeyParent, pwszKeyName, 0, samDesired, &keyHandle);
|
||||
if (res == ERROR_SUCCESS)
|
||||
{
|
||||
Close();
|
||||
_keyHandle = keyHandle;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// Close
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
LONG CRegKey::Close()
|
||||
{
|
||||
LONG res = ERROR_SUCCESS;
|
||||
if (_keyHandle)
|
||||
{
|
||||
res = RegCloseKey(_keyHandle);
|
||||
_keyHandle = nullptr;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// DeleteSubKey
|
||||
// RecurseDeleteKey
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
LONG CRegKey::DeleteSubKey(_In_ LPCWSTR pwszSubKey)
|
||||
{
|
||||
return RegDeleteKey(_keyHandle, pwszSubKey);
|
||||
}
|
||||
|
||||
LONG CRegKey::RecurseDeleteKey(_In_ LPCWSTR pwszSubKey)
|
||||
{
|
||||
CRegKey key;
|
||||
LONG res = key.Open(_keyHandle, pwszSubKey, KEY_READ | KEY_WRITE);
|
||||
if (res != ERROR_SUCCESS)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
FILETIME time;
|
||||
WCHAR subKeyName[256] = {'\0'};
|
||||
DWORD subKeyNameSize = ARRAYSIZE(subKeyName);
|
||||
|
||||
while (RegEnumKeyEx(key.GetHKEY(), 0, subKeyName, &subKeyNameSize, NULL, NULL, NULL, &time) == ERROR_SUCCESS)
|
||||
{
|
||||
subKeyName[ARRAYSIZE(subKeyName) - 1] = L'\0';
|
||||
res = key.RecurseDeleteKey(subKeyName);
|
||||
if (res != ERROR_SUCCESS)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
subKeyNameSize = ARRAYSIZE(subKeyName);
|
||||
}
|
||||
|
||||
key.Close();
|
||||
|
||||
return DeleteSubKey(pwszSubKey);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// DeleteValue
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
LONG CRegKey::DeleteValue(_In_ LPCWSTR pwszValue)
|
||||
{
|
||||
return RegDeleteValue(_keyHandle, pwszValue);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// QueryStingValue
|
||||
// SetStringValue
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
LONG CRegKey::QueryStringValue(_In_opt_ LPCWSTR pwszValueName, _Out_writes_opt_(*pnChars) LPWSTR pwszValue,
|
||||
_Inout_ ULONG *pnChars)
|
||||
{
|
||||
LONG res = 0;
|
||||
DWORD dataType = REG_NONE;
|
||||
ULONG pwszValueSize = 0;
|
||||
|
||||
if (pnChars == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
pwszValueSize = (*pnChars) * sizeof(WCHAR);
|
||||
*pnChars = 0;
|
||||
|
||||
res = RegQueryValueEx(_keyHandle, pwszValueName, NULL, &dataType, (LPBYTE)pwszValue, &pwszValueSize);
|
||||
if (res != ERROR_SUCCESS)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
if ((dataType != REG_SZ) && (dataType != REG_EXPAND_SZ))
|
||||
{
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
*pnChars = pwszValueSize / sizeof(WCHAR);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
LONG CRegKey::SetStringValue(_In_opt_ LPCWSTR pwszValueName, _In_ LPCWSTR pwszValue, DWORD dwType)
|
||||
{
|
||||
size_t lenOfValue = 0;
|
||||
if (pwszValue == nullptr)
|
||||
{
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (StringCchLength(pwszValue, STRSAFE_MAX_CCH, &lenOfValue) != S_OK)
|
||||
{
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
DWORD len = static_cast<DWORD>(lenOfValue);
|
||||
return RegSetValueEx(_keyHandle, pwszValueName, NULL, dwType, (LPBYTE)pwszValue, (++len) * sizeof(WCHAR));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// QueryDWORDValue
|
||||
// SetDWORDValue
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
LONG CRegKey::QueryDWORDValue(_In_opt_ LPCWSTR pwszValueName, _Out_ DWORD &dwValue)
|
||||
{
|
||||
LONG res = 0;
|
||||
DWORD dataType = REG_NONE;
|
||||
ULONG pwszValueSize = 0;
|
||||
|
||||
pwszValueSize = sizeof(DWORD);
|
||||
res = RegQueryValueEx(_keyHandle, pwszValueName, NULL, &dataType, (LPBYTE)(&dwValue), &pwszValueSize);
|
||||
if (res != ERROR_SUCCESS)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
if (dataType != REG_DWORD)
|
||||
{
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
LONG CRegKey::SetDWORDValue(_In_opt_ LPCWSTR pwszValueName, DWORD dwValue)
|
||||
{
|
||||
return RegSetValueEx(_keyHandle, pwszValueName, NULL, REG_DWORD, (LPBYTE)(&dwValue), sizeof(DWORD));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// QueryBinaryValue
|
||||
// SetBinaryValue
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
LONG CRegKey::QueryBinaryValue(_In_opt_ LPCWSTR pwszValueName, _Out_writes_opt_(cbData) BYTE *lpData, DWORD cbData)
|
||||
{
|
||||
LONG res = 0;
|
||||
DWORD dataType = REG_NONE;
|
||||
ULONG pwszValueSize = 0;
|
||||
|
||||
pwszValueSize = cbData;
|
||||
res = RegQueryValueEx(_keyHandle, pwszValueName, NULL, &dataType, lpData, &pwszValueSize);
|
||||
if (res != ERROR_SUCCESS)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
if (dataType != REG_BINARY)
|
||||
{
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
if (pwszValueSize != cbData)
|
||||
{
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
LONG CRegKey::SetBinaryValue(_In_opt_ LPCWSTR pwszValueName, _In_reads_(cbData) BYTE *lpData, DWORD cbData)
|
||||
{
|
||||
return RegSetValueEx(_keyHandle, pwszValueName, NULL, REG_BINARY, lpData, cbData);
|
||||
}
|
||||
@@ -1,37 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include "Private.h"
|
||||
|
||||
class CRegKey
|
||||
{
|
||||
public:
|
||||
CRegKey();
|
||||
~CRegKey();
|
||||
|
||||
HKEY GetHKEY();
|
||||
|
||||
LONG Create(_In_ HKEY hKeyPresent, _In_ LPCWSTR pwszKeyName, _In_reads_opt_(255) LPWSTR pwszClass = REG_NONE,
|
||||
DWORD dwOptions = REG_OPTION_NON_VOLATILE, REGSAM samDesired = KEY_READ | KEY_WRITE,
|
||||
_Inout_ LPSECURITY_ATTRIBUTES lpSecAttr = nullptr, _Out_opt_ LPDWORD lpdwDisposition = nullptr);
|
||||
|
||||
LONG Open(_In_ HKEY hKeyParent, _In_ LPCWSTR pwszKeyName, REGSAM samDesired = KEY_READ | KEY_WRITE);
|
||||
|
||||
LONG Close();
|
||||
|
||||
LONG DeleteSubKey(_In_ LPCWSTR pwszSubKey);
|
||||
LONG RecurseDeleteKey(_In_ LPCWSTR pwszSubKey);
|
||||
LONG DeleteValue(_In_ LPCWSTR pwszValue);
|
||||
|
||||
LONG QueryStringValue(_In_opt_ LPCWSTR pwszValueName, _Out_writes_opt_(*pnChars) LPWSTR pwszValue,
|
||||
_Inout_ ULONG *pnChars);
|
||||
LONG SetStringValue(_In_opt_ LPCWSTR pwszValueName, _In_ LPCWSTR pwszValue, DWORD dwType = REG_SZ);
|
||||
|
||||
LONG QueryDWORDValue(_In_opt_ LPCWSTR pwszValueName, _Out_ DWORD &dwValue);
|
||||
LONG SetDWORDValue(_In_opt_ LPCWSTR pwszValueName, DWORD dwValue);
|
||||
|
||||
LONG QueryBinaryValue(_In_opt_ LPCWSTR pwszValueName, _Out_writes_opt_(cbData) BYTE *lpData, DWORD cbData);
|
||||
LONG SetBinaryValue(_In_opt_ LPCWSTR pwszValueName, _In_reads_(cbData) BYTE *lpData, DWORD cbData);
|
||||
|
||||
private:
|
||||
HKEY _keyHandle;
|
||||
};
|
||||
#pragma once
|
||||
|
||||
#include "Private.h"
|
||||
|
||||
class CRegKey
|
||||
{
|
||||
public:
|
||||
CRegKey();
|
||||
~CRegKey();
|
||||
|
||||
HKEY GetHKEY();
|
||||
|
||||
LONG Create(_In_ HKEY hKeyPresent, _In_ LPCWSTR pwszKeyName, _In_reads_opt_(255) LPWSTR pwszClass = REG_NONE,
|
||||
DWORD dwOptions = REG_OPTION_NON_VOLATILE, REGSAM samDesired = KEY_READ | KEY_WRITE,
|
||||
_Inout_ LPSECURITY_ATTRIBUTES lpSecAttr = nullptr, _Out_opt_ LPDWORD lpdwDisposition = nullptr);
|
||||
|
||||
LONG Open(_In_ HKEY hKeyParent, _In_ LPCWSTR pwszKeyName, REGSAM samDesired = KEY_READ | KEY_WRITE);
|
||||
|
||||
LONG Close();
|
||||
|
||||
LONG DeleteSubKey(_In_ LPCWSTR pwszSubKey);
|
||||
LONG RecurseDeleteKey(_In_ LPCWSTR pwszSubKey);
|
||||
LONG DeleteValue(_In_ LPCWSTR pwszValue);
|
||||
|
||||
LONG QueryStringValue(_In_opt_ LPCWSTR pwszValueName, _Out_writes_opt_(*pnChars) LPWSTR pwszValue,
|
||||
_Inout_ ULONG *pnChars);
|
||||
LONG SetStringValue(_In_opt_ LPCWSTR pwszValueName, _In_ LPCWSTR pwszValue, DWORD dwType = REG_SZ);
|
||||
|
||||
LONG QueryDWORDValue(_In_opt_ LPCWSTR pwszValueName, _Out_ DWORD &dwValue);
|
||||
LONG SetDWORDValue(_In_opt_ LPCWSTR pwszValueName, DWORD dwValue);
|
||||
|
||||
LONG QueryBinaryValue(_In_opt_ LPCWSTR pwszValueName, _Out_writes_opt_(cbData) BYTE *lpData, DWORD cbData);
|
||||
LONG SetBinaryValue(_In_opt_ LPCWSTR pwszValueName, _In_reads_(cbData) BYTE *lpData, DWORD cbData);
|
||||
|
||||
private:
|
||||
HKEY _keyHandle;
|
||||
};
|
||||
+289
-289
@@ -1,289 +1,289 @@
|
||||
#ifndef UNICODE
|
||||
#define UNICODE
|
||||
#endif // !UNICODE
|
||||
|
||||
#ifndef _UNICODE
|
||||
#define _UNICODE
|
||||
#endif // !UNICODE
|
||||
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "RegKey.h"
|
||||
|
||||
static const WCHAR RegInfo_Prefix_CLSID[] = L"CLSID\\";
|
||||
static const WCHAR RegInfo_Key_InProSvr32[] = L"InProcServer32";
|
||||
static const WCHAR RegInfo_Key_ThreadModel[] = L"ThreadingModel";
|
||||
|
||||
// IME text service description, will be displayed in the language menu when switching IME
|
||||
static const WCHAR TEXTSERVICE_DESC[] = L"Metasequoia \u6c34\u6749\u8f93\u5165\u6cd5";
|
||||
|
||||
static const GUID SupportCategories[] = {
|
||||
GUID_TFCAT_TIP_KEYBOARD,
|
||||
GUID_TFCAT_DISPLAYATTRIBUTEPROVIDER,
|
||||
GUID_TFCAT_TIPCAP_UIELEMENTENABLED,
|
||||
GUID_TFCAT_TIPCAP_SECUREMODE,
|
||||
GUID_TFCAT_TIPCAP_COMLESS,
|
||||
GUID_TFCAT_TIPCAP_INPUTMODECOMPARTMENT,
|
||||
GUID_TFCAT_TIPCAP_IMMERSIVESUPPORT,
|
||||
GUID_TFCAT_TIPCAP_SYSTRAYSUPPORT,
|
||||
};
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// RegisterProfiles
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL RegisterProfiles()
|
||||
{
|
||||
HRESULT hr = S_FALSE;
|
||||
|
||||
ITfInputProcessorProfileMgr *pITfInputProcessorProfileMgr = nullptr;
|
||||
hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER, IID_ITfInputProcessorProfileMgr,
|
||||
(void **)&pITfInputProcessorProfileMgr);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WCHAR achIconFile[MAX_PATH] = {'\0'};
|
||||
DWORD cchA = 0;
|
||||
cchA = GetModuleFileName(Global::dllInstanceHandle, achIconFile, MAX_PATH);
|
||||
cchA = cchA >= MAX_PATH ? (MAX_PATH - 1) : cchA;
|
||||
achIconFile[cchA] = '\0';
|
||||
|
||||
size_t lenOfDesc = 0;
|
||||
hr = StringCchLength(TEXTSERVICE_DESC, STRSAFE_MAX_CCH, &lenOfDesc);
|
||||
if (hr != S_OK)
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
hr = pITfInputProcessorProfileMgr->RegisterProfile(
|
||||
Global::MetasequoiaIMECLSID, TEXTSERVICE_LANGID, Global::MetasequoiaIMEGuidProfile, TEXTSERVICE_DESC,
|
||||
static_cast<ULONG>(lenOfDesc), achIconFile, cchA, (UINT)TEXTSERVICE_ICON_INDEX, NULL, 0, TRUE, 0);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Exit:
|
||||
if (pITfInputProcessorProfileMgr)
|
||||
{
|
||||
pITfInputProcessorProfileMgr->Release();
|
||||
}
|
||||
|
||||
return (hr == S_OK);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// UnregisterProfiles
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void UnregisterProfiles()
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
ITfInputProcessorProfileMgr *pITfInputProcessorProfileMgr = nullptr;
|
||||
hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER, IID_ITfInputProcessorProfileMgr,
|
||||
(void **)&pITfInputProcessorProfileMgr);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
hr = pITfInputProcessorProfileMgr->UnregisterProfile(Global::MetasequoiaIMECLSID, TEXTSERVICE_LANGID,
|
||||
Global::MetasequoiaIMEGuidProfile, 0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Exit:
|
||||
if (pITfInputProcessorProfileMgr)
|
||||
{
|
||||
pITfInputProcessorProfileMgr->Release();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// RegisterCategories
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL RegisterCategories()
|
||||
{
|
||||
ITfCategoryMgr *pCategoryMgr = nullptr;
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
hr = CoCreateInstance(CLSID_TF_CategoryMgr, NULL, CLSCTX_INPROC_SERVER, IID_ITfCategoryMgr, (void **)&pCategoryMgr);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// for each (GUID guid in SupportCategories)
|
||||
for (const auto &guid : SupportCategories)
|
||||
{
|
||||
hr = pCategoryMgr->RegisterCategory(Global::MetasequoiaIMECLSID, guid, Global::MetasequoiaIMECLSID);
|
||||
}
|
||||
|
||||
pCategoryMgr->Release();
|
||||
|
||||
return (hr == S_OK);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// UnregisterCategories
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void UnregisterCategories()
|
||||
{
|
||||
ITfCategoryMgr *pCategoryMgr = S_OK;
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
hr = CoCreateInstance(CLSID_TF_CategoryMgr, NULL, CLSCTX_INPROC_SERVER, IID_ITfCategoryMgr, (void **)&pCategoryMgr);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// for each (GUID guid in SupportCategories)
|
||||
for (const auto &guid : SupportCategories)
|
||||
{
|
||||
pCategoryMgr->UnregisterCategory(Global::MetasequoiaIMECLSID, guid, Global::MetasequoiaIMECLSID);
|
||||
}
|
||||
|
||||
pCategoryMgr->Release();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// RecurseDeleteKey
|
||||
//
|
||||
// RecurseDeleteKey is necessary because on NT RegDeleteKey doesn't work if the
|
||||
// specified key has subkeys
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
LONG RecurseDeleteKey(_In_ HKEY hParentKey, _In_ LPCTSTR lpszKey)
|
||||
{
|
||||
HKEY regKeyHandle = nullptr;
|
||||
LONG res = 0;
|
||||
FILETIME time;
|
||||
WCHAR stringBuffer[256] = {'\0'};
|
||||
DWORD size = ARRAYSIZE(stringBuffer);
|
||||
|
||||
if (RegOpenKey(hParentKey, lpszKey, ®KeyHandle) != ERROR_SUCCESS)
|
||||
{
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
res = ERROR_SUCCESS;
|
||||
while (RegEnumKeyEx(regKeyHandle, 0, stringBuffer, &size, NULL, NULL, NULL, &time) == ERROR_SUCCESS)
|
||||
{
|
||||
stringBuffer[ARRAYSIZE(stringBuffer) - 1] = '\0';
|
||||
res = RecurseDeleteKey(regKeyHandle, stringBuffer);
|
||||
if (res != ERROR_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
size = ARRAYSIZE(stringBuffer);
|
||||
}
|
||||
RegCloseKey(regKeyHandle);
|
||||
|
||||
return res == ERROR_SUCCESS ? RegDeleteKey(hParentKey, lpszKey) : res;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// RegisterServer
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL RegisterServer()
|
||||
{
|
||||
DWORD copiedStringLen = 0;
|
||||
HKEY regKeyHandle = nullptr;
|
||||
HKEY regSubkeyHandle = nullptr;
|
||||
BOOL ret = FALSE;
|
||||
WCHAR achIMEKey[ARRAYSIZE(RegInfo_Prefix_CLSID) + CLSID_STRLEN] = {'\0'};
|
||||
WCHAR achFileName[MAX_PATH] = {'\0'};
|
||||
|
||||
if (!CLSIDToString(Global::MetasequoiaIMECLSID, achIMEKey + ARRAYSIZE(RegInfo_Prefix_CLSID) - 1))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memcpy(achIMEKey, RegInfo_Prefix_CLSID, sizeof(RegInfo_Prefix_CLSID) - sizeof(WCHAR));
|
||||
|
||||
if (RegCreateKeyEx(HKEY_CLASSES_ROOT, achIMEKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, ®KeyHandle,
|
||||
&copiedStringLen) == ERROR_SUCCESS)
|
||||
{
|
||||
if (RegSetValueEx(regKeyHandle, NULL, 0, REG_SZ, (const BYTE *)TEXTSERVICE_DESC,
|
||||
(_countof(TEXTSERVICE_DESC)) * sizeof(WCHAR)) != ERROR_SUCCESS)
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (RegCreateKeyEx(regKeyHandle, RegInfo_Key_InProSvr32, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
|
||||
®SubkeyHandle, &copiedStringLen) == ERROR_SUCCESS)
|
||||
{
|
||||
copiedStringLen = GetModuleFileNameW(Global::dllInstanceHandle, achFileName, ARRAYSIZE(achFileName));
|
||||
copiedStringLen = (copiedStringLen >= (MAX_PATH - 1)) ? MAX_PATH : (++copiedStringLen);
|
||||
if (RegSetValueEx(regSubkeyHandle, NULL, 0, REG_SZ, (const BYTE *)achFileName,
|
||||
(copiedStringLen) * sizeof(WCHAR)) != ERROR_SUCCESS)
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
if (RegSetValueEx(regSubkeyHandle, RegInfo_Key_ThreadModel, 0, REG_SZ, (const BYTE *)TEXTSERVICE_MODEL,
|
||||
(_countof(TEXTSERVICE_MODEL)) * sizeof(WCHAR)) != ERROR_SUCCESS)
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
if (regSubkeyHandle)
|
||||
{
|
||||
RegCloseKey(regSubkeyHandle);
|
||||
regSubkeyHandle = nullptr;
|
||||
}
|
||||
if (regKeyHandle)
|
||||
{
|
||||
RegCloseKey(regKeyHandle);
|
||||
regKeyHandle = nullptr;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// UnregisterServer
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void UnregisterServer()
|
||||
{
|
||||
WCHAR achIMEKey[ARRAYSIZE(RegInfo_Prefix_CLSID) + CLSID_STRLEN] = {'\0'};
|
||||
|
||||
if (!CLSIDToString(Global::MetasequoiaIMECLSID, achIMEKey + ARRAYSIZE(RegInfo_Prefix_CLSID) - 1))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(achIMEKey, RegInfo_Prefix_CLSID, sizeof(RegInfo_Prefix_CLSID) - sizeof(WCHAR));
|
||||
|
||||
RecurseDeleteKey(HKEY_CLASSES_ROOT, achIMEKey);
|
||||
}
|
||||
#ifndef UNICODE
|
||||
#define UNICODE
|
||||
#endif // !UNICODE
|
||||
|
||||
#ifndef _UNICODE
|
||||
#define _UNICODE
|
||||
#endif // !UNICODE
|
||||
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "RegKey.h"
|
||||
|
||||
static const WCHAR RegInfo_Prefix_CLSID[] = L"CLSID\\";
|
||||
static const WCHAR RegInfo_Key_InProSvr32[] = L"InProcServer32";
|
||||
static const WCHAR RegInfo_Key_ThreadModel[] = L"ThreadingModel";
|
||||
|
||||
// IME text service description, will be displayed in the language menu when switching IME
|
||||
static const WCHAR TEXTSERVICE_DESC[] = L"Metasequoia \u6c34\u6749\u8f93\u5165\u6cd5";
|
||||
|
||||
static const GUID SupportCategories[] = {
|
||||
GUID_TFCAT_TIP_KEYBOARD,
|
||||
GUID_TFCAT_DISPLAYATTRIBUTEPROVIDER,
|
||||
GUID_TFCAT_TIPCAP_UIELEMENTENABLED,
|
||||
GUID_TFCAT_TIPCAP_SECUREMODE,
|
||||
GUID_TFCAT_TIPCAP_COMLESS,
|
||||
GUID_TFCAT_TIPCAP_INPUTMODECOMPARTMENT,
|
||||
GUID_TFCAT_TIPCAP_IMMERSIVESUPPORT,
|
||||
GUID_TFCAT_TIPCAP_SYSTRAYSUPPORT,
|
||||
};
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// RegisterProfiles
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL RegisterProfiles()
|
||||
{
|
||||
HRESULT hr = S_FALSE;
|
||||
|
||||
ITfInputProcessorProfileMgr *pITfInputProcessorProfileMgr = nullptr;
|
||||
hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER, IID_ITfInputProcessorProfileMgr,
|
||||
(void **)&pITfInputProcessorProfileMgr);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WCHAR achIconFile[MAX_PATH] = {'\0'};
|
||||
DWORD cchA = 0;
|
||||
cchA = GetModuleFileName(Global::dllInstanceHandle, achIconFile, MAX_PATH);
|
||||
cchA = cchA >= MAX_PATH ? (MAX_PATH - 1) : cchA;
|
||||
achIconFile[cchA] = '\0';
|
||||
|
||||
size_t lenOfDesc = 0;
|
||||
hr = StringCchLength(TEXTSERVICE_DESC, STRSAFE_MAX_CCH, &lenOfDesc);
|
||||
if (hr != S_OK)
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
hr = pITfInputProcessorProfileMgr->RegisterProfile(
|
||||
Global::MetasequoiaIMECLSID, TEXTSERVICE_LANGID, Global::MetasequoiaIMEGuidProfile, TEXTSERVICE_DESC,
|
||||
static_cast<ULONG>(lenOfDesc), achIconFile, cchA, (UINT)TEXTSERVICE_ICON_INDEX, NULL, 0, TRUE, 0);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Exit:
|
||||
if (pITfInputProcessorProfileMgr)
|
||||
{
|
||||
pITfInputProcessorProfileMgr->Release();
|
||||
}
|
||||
|
||||
return (hr == S_OK);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// UnregisterProfiles
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void UnregisterProfiles()
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
ITfInputProcessorProfileMgr *pITfInputProcessorProfileMgr = nullptr;
|
||||
hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER, IID_ITfInputProcessorProfileMgr,
|
||||
(void **)&pITfInputProcessorProfileMgr);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
hr = pITfInputProcessorProfileMgr->UnregisterProfile(Global::MetasequoiaIMECLSID, TEXTSERVICE_LANGID,
|
||||
Global::MetasequoiaIMEGuidProfile, 0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Exit:
|
||||
if (pITfInputProcessorProfileMgr)
|
||||
{
|
||||
pITfInputProcessorProfileMgr->Release();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// RegisterCategories
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL RegisterCategories()
|
||||
{
|
||||
ITfCategoryMgr *pCategoryMgr = nullptr;
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
hr = CoCreateInstance(CLSID_TF_CategoryMgr, NULL, CLSCTX_INPROC_SERVER, IID_ITfCategoryMgr, (void **)&pCategoryMgr);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// for each (GUID guid in SupportCategories)
|
||||
for (const auto &guid : SupportCategories)
|
||||
{
|
||||
hr = pCategoryMgr->RegisterCategory(Global::MetasequoiaIMECLSID, guid, Global::MetasequoiaIMECLSID);
|
||||
}
|
||||
|
||||
pCategoryMgr->Release();
|
||||
|
||||
return (hr == S_OK);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// UnregisterCategories
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void UnregisterCategories()
|
||||
{
|
||||
ITfCategoryMgr *pCategoryMgr = S_OK;
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
hr = CoCreateInstance(CLSID_TF_CategoryMgr, NULL, CLSCTX_INPROC_SERVER, IID_ITfCategoryMgr, (void **)&pCategoryMgr);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// for each (GUID guid in SupportCategories)
|
||||
for (const auto &guid : SupportCategories)
|
||||
{
|
||||
pCategoryMgr->UnregisterCategory(Global::MetasequoiaIMECLSID, guid, Global::MetasequoiaIMECLSID);
|
||||
}
|
||||
|
||||
pCategoryMgr->Release();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// RecurseDeleteKey
|
||||
//
|
||||
// RecurseDeleteKey is necessary because on NT RegDeleteKey doesn't work if the
|
||||
// specified key has subkeys
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
LONG RecurseDeleteKey(_In_ HKEY hParentKey, _In_ LPCTSTR lpszKey)
|
||||
{
|
||||
HKEY regKeyHandle = nullptr;
|
||||
LONG res = 0;
|
||||
FILETIME time;
|
||||
WCHAR stringBuffer[256] = {'\0'};
|
||||
DWORD size = ARRAYSIZE(stringBuffer);
|
||||
|
||||
if (RegOpenKey(hParentKey, lpszKey, ®KeyHandle) != ERROR_SUCCESS)
|
||||
{
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
res = ERROR_SUCCESS;
|
||||
while (RegEnumKeyEx(regKeyHandle, 0, stringBuffer, &size, NULL, NULL, NULL, &time) == ERROR_SUCCESS)
|
||||
{
|
||||
stringBuffer[ARRAYSIZE(stringBuffer) - 1] = '\0';
|
||||
res = RecurseDeleteKey(regKeyHandle, stringBuffer);
|
||||
if (res != ERROR_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
size = ARRAYSIZE(stringBuffer);
|
||||
}
|
||||
RegCloseKey(regKeyHandle);
|
||||
|
||||
return res == ERROR_SUCCESS ? RegDeleteKey(hParentKey, lpszKey) : res;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// RegisterServer
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL RegisterServer()
|
||||
{
|
||||
DWORD copiedStringLen = 0;
|
||||
HKEY regKeyHandle = nullptr;
|
||||
HKEY regSubkeyHandle = nullptr;
|
||||
BOOL ret = FALSE;
|
||||
WCHAR achIMEKey[ARRAYSIZE(RegInfo_Prefix_CLSID) + CLSID_STRLEN] = {'\0'};
|
||||
WCHAR achFileName[MAX_PATH] = {'\0'};
|
||||
|
||||
if (!CLSIDToString(Global::MetasequoiaIMECLSID, achIMEKey + ARRAYSIZE(RegInfo_Prefix_CLSID) - 1))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memcpy(achIMEKey, RegInfo_Prefix_CLSID, sizeof(RegInfo_Prefix_CLSID) - sizeof(WCHAR));
|
||||
|
||||
if (RegCreateKeyEx(HKEY_CLASSES_ROOT, achIMEKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, ®KeyHandle,
|
||||
&copiedStringLen) == ERROR_SUCCESS)
|
||||
{
|
||||
if (RegSetValueEx(regKeyHandle, NULL, 0, REG_SZ, (const BYTE *)TEXTSERVICE_DESC,
|
||||
(_countof(TEXTSERVICE_DESC)) * sizeof(WCHAR)) != ERROR_SUCCESS)
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (RegCreateKeyEx(regKeyHandle, RegInfo_Key_InProSvr32, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
|
||||
®SubkeyHandle, &copiedStringLen) == ERROR_SUCCESS)
|
||||
{
|
||||
copiedStringLen = GetModuleFileNameW(Global::dllInstanceHandle, achFileName, ARRAYSIZE(achFileName));
|
||||
copiedStringLen = (copiedStringLen >= (MAX_PATH - 1)) ? MAX_PATH : (++copiedStringLen);
|
||||
if (RegSetValueEx(regSubkeyHandle, NULL, 0, REG_SZ, (const BYTE *)achFileName,
|
||||
(copiedStringLen) * sizeof(WCHAR)) != ERROR_SUCCESS)
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
if (RegSetValueEx(regSubkeyHandle, RegInfo_Key_ThreadModel, 0, REG_SZ, (const BYTE *)TEXTSERVICE_MODEL,
|
||||
(_countof(TEXTSERVICE_MODEL)) * sizeof(WCHAR)) != ERROR_SUCCESS)
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
if (regSubkeyHandle)
|
||||
{
|
||||
RegCloseKey(regSubkeyHandle);
|
||||
regSubkeyHandle = nullptr;
|
||||
}
|
||||
if (regKeyHandle)
|
||||
{
|
||||
RegCloseKey(regKeyHandle);
|
||||
regKeyHandle = nullptr;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// UnregisterServer
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void UnregisterServer()
|
||||
{
|
||||
WCHAR achIMEKey[ARRAYSIZE(RegInfo_Prefix_CLSID) + CLSID_STRLEN] = {'\0'};
|
||||
|
||||
if (!CLSIDToString(Global::MetasequoiaIMECLSID, achIMEKey + ARRAYSIZE(RegInfo_Prefix_CLSID) - 1))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(achIMEKey, RegInfo_Prefix_CLSID, sizeof(RegInfo_Prefix_CLSID) - sizeof(WCHAR));
|
||||
|
||||
RecurseDeleteKey(HKEY_CLASSES_ROOT, achIMEKey);
|
||||
}
|
||||
+276
-276
@@ -1,276 +1,276 @@
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "MetasequoiaIME.h"
|
||||
|
||||
// from Register.cpp
|
||||
BOOL RegisterProfiles();
|
||||
void UnregisterProfiles();
|
||||
BOOL RegisterCategories();
|
||||
void UnregisterCategories();
|
||||
BOOL RegisterServer();
|
||||
void UnregisterServer();
|
||||
|
||||
void FreeGlobalObjects(void);
|
||||
|
||||
class CClassFactory;
|
||||
static CClassFactory *classFactoryObjects[1] = {nullptr};
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// DllAddRef
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void DllAddRef(void)
|
||||
{
|
||||
InterlockedIncrement(&Global::dllRefCount);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// DllRelease
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void DllRelease(void)
|
||||
{
|
||||
if (InterlockedDecrement(&Global::dllRefCount) < 0)
|
||||
{
|
||||
EnterCriticalSection(&Global::CS);
|
||||
|
||||
if (nullptr != classFactoryObjects[0])
|
||||
{
|
||||
FreeGlobalObjects();
|
||||
}
|
||||
assert(Global::dllRefCount == -1);
|
||||
|
||||
LeaveCriticalSection(&Global::CS);
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CClassFactory declaration with IClassFactory Interface
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class CClassFactory : public IClassFactory
|
||||
{
|
||||
public:
|
||||
// IUnknown methods
|
||||
STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj);
|
||||
STDMETHODIMP_(ULONG) AddRef(void);
|
||||
STDMETHODIMP_(ULONG) Release(void);
|
||||
|
||||
// IClassFactory methods
|
||||
STDMETHODIMP CreateInstance(_In_opt_ IUnknown *pUnkOuter, _In_ REFIID riid, _COM_Outptr_ void **ppvObj);
|
||||
STDMETHODIMP LockServer(BOOL fLock);
|
||||
|
||||
// Constructor
|
||||
CClassFactory(REFCLSID rclsid, HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, REFIID riid, void **ppvObj))
|
||||
: _rclsid(rclsid)
|
||||
{
|
||||
_pfnCreateInstance = pfnCreateInstance;
|
||||
}
|
||||
|
||||
public:
|
||||
REFCLSID _rclsid;
|
||||
HRESULT (*_pfnCreateInstance)(IUnknown *pUnkOuter, REFIID riid, _COM_Outptr_ void **ppvObj);
|
||||
|
||||
private:
|
||||
CClassFactory &operator=(const CClassFactory &rhn)
|
||||
{
|
||||
rhn;
|
||||
};
|
||||
};
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CClassFactory::QueryInterface
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CClassFactory::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
|
||||
{
|
||||
if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown))
|
||||
{
|
||||
*ppvObj = this;
|
||||
DllAddRef();
|
||||
return NOERROR;
|
||||
}
|
||||
*ppvObj = nullptr;
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CClassFactory::AddRef
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI_(ULONG) CClassFactory::AddRef()
|
||||
{
|
||||
DllAddRef();
|
||||
return (Global::dllRefCount + 1);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CClassFactory::Release
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI_(ULONG) CClassFactory::Release()
|
||||
{
|
||||
DllRelease();
|
||||
return (Global::dllRefCount + 1);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CClassFactory::CreateInstance
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CClassFactory::CreateInstance(_In_opt_ IUnknown *pUnkOuter, _In_ REFIID riid, _COM_Outptr_ void **ppvObj)
|
||||
{
|
||||
return _pfnCreateInstance(pUnkOuter, riid, ppvObj);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CClassFactory::LockServer
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CClassFactory::LockServer(BOOL fLock)
|
||||
{
|
||||
if (fLock)
|
||||
{
|
||||
DllAddRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
DllRelease();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// BuildGlobalObjects
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void BuildGlobalObjects(void)
|
||||
{
|
||||
classFactoryObjects[0] =
|
||||
new (std::nothrow) CClassFactory(Global::MetasequoiaIMECLSID, CMetasequoiaIME::CreateInstance);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// FreeGlobalObjects
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void FreeGlobalObjects(void)
|
||||
{
|
||||
for (int i = 0; i < ARRAYSIZE(classFactoryObjects); i++)
|
||||
{
|
||||
if (nullptr != classFactoryObjects[i])
|
||||
{
|
||||
delete classFactoryObjects[i];
|
||||
classFactoryObjects[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
DeleteObject(Global::defaultlFontHandle);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// DllGetClassObject
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
_Check_return_ STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ void **ppv)
|
||||
{
|
||||
if (classFactoryObjects[0] == nullptr)
|
||||
{
|
||||
EnterCriticalSection(&Global::CS);
|
||||
|
||||
// need to check ref again after grabbing mutex
|
||||
if (classFactoryObjects[0] == nullptr)
|
||||
{
|
||||
BuildGlobalObjects();
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&Global::CS);
|
||||
}
|
||||
|
||||
if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown))
|
||||
{
|
||||
for (int i = 0; i < ARRAYSIZE(classFactoryObjects); i++)
|
||||
{
|
||||
if (nullptr != classFactoryObjects[i] && IsEqualGUID(rclsid, classFactoryObjects[i]->_rclsid))
|
||||
{
|
||||
*ppv = (void *)classFactoryObjects[i];
|
||||
DllAddRef(); // class factory holds DLL ref count
|
||||
return NOERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*ppv = nullptr;
|
||||
|
||||
return CLASS_E_CLASSNOTAVAILABLE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// DllCanUnloadNow
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI DllCanUnloadNow(void)
|
||||
{
|
||||
if (Global::dllRefCount >= 0)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// DllUnregisterServer
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI DllUnregisterServer(void)
|
||||
{
|
||||
UnregisterProfiles();
|
||||
UnregisterCategories();
|
||||
UnregisterServer();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// DllRegisterServer
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI DllRegisterServer(void)
|
||||
{
|
||||
if ((!RegisterServer()) || (!RegisterProfiles()) || (!RegisterCategories()))
|
||||
{
|
||||
DllUnregisterServer();
|
||||
return E_FAIL;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "MetasequoiaIME.h"
|
||||
|
||||
// from Register.cpp
|
||||
BOOL RegisterProfiles();
|
||||
void UnregisterProfiles();
|
||||
BOOL RegisterCategories();
|
||||
void UnregisterCategories();
|
||||
BOOL RegisterServer();
|
||||
void UnregisterServer();
|
||||
|
||||
void FreeGlobalObjects(void);
|
||||
|
||||
class CClassFactory;
|
||||
static CClassFactory *classFactoryObjects[1] = {nullptr};
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// DllAddRef
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void DllAddRef(void)
|
||||
{
|
||||
InterlockedIncrement(&Global::dllRefCount);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// DllRelease
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void DllRelease(void)
|
||||
{
|
||||
if (InterlockedDecrement(&Global::dllRefCount) < 0)
|
||||
{
|
||||
EnterCriticalSection(&Global::CS);
|
||||
|
||||
if (nullptr != classFactoryObjects[0])
|
||||
{
|
||||
FreeGlobalObjects();
|
||||
}
|
||||
assert(Global::dllRefCount == -1);
|
||||
|
||||
LeaveCriticalSection(&Global::CS);
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CClassFactory declaration with IClassFactory Interface
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class CClassFactory : public IClassFactory
|
||||
{
|
||||
public:
|
||||
// IUnknown methods
|
||||
STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj);
|
||||
STDMETHODIMP_(ULONG) AddRef(void);
|
||||
STDMETHODIMP_(ULONG) Release(void);
|
||||
|
||||
// IClassFactory methods
|
||||
STDMETHODIMP CreateInstance(_In_opt_ IUnknown *pUnkOuter, _In_ REFIID riid, _COM_Outptr_ void **ppvObj);
|
||||
STDMETHODIMP LockServer(BOOL fLock);
|
||||
|
||||
// Constructor
|
||||
CClassFactory(REFCLSID rclsid, HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, REFIID riid, void **ppvObj))
|
||||
: _rclsid(rclsid)
|
||||
{
|
||||
_pfnCreateInstance = pfnCreateInstance;
|
||||
}
|
||||
|
||||
public:
|
||||
REFCLSID _rclsid;
|
||||
HRESULT (*_pfnCreateInstance)(IUnknown *pUnkOuter, REFIID riid, _COM_Outptr_ void **ppvObj);
|
||||
|
||||
private:
|
||||
CClassFactory &operator=(const CClassFactory &rhn)
|
||||
{
|
||||
rhn;
|
||||
};
|
||||
};
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CClassFactory::QueryInterface
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CClassFactory::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
|
||||
{
|
||||
if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown))
|
||||
{
|
||||
*ppvObj = this;
|
||||
DllAddRef();
|
||||
return NOERROR;
|
||||
}
|
||||
*ppvObj = nullptr;
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CClassFactory::AddRef
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI_(ULONG) CClassFactory::AddRef()
|
||||
{
|
||||
DllAddRef();
|
||||
return (Global::dllRefCount + 1);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CClassFactory::Release
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI_(ULONG) CClassFactory::Release()
|
||||
{
|
||||
DllRelease();
|
||||
return (Global::dllRefCount + 1);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CClassFactory::CreateInstance
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CClassFactory::CreateInstance(_In_opt_ IUnknown *pUnkOuter, _In_ REFIID riid, _COM_Outptr_ void **ppvObj)
|
||||
{
|
||||
return _pfnCreateInstance(pUnkOuter, riid, ppvObj);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CClassFactory::LockServer
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CClassFactory::LockServer(BOOL fLock)
|
||||
{
|
||||
if (fLock)
|
||||
{
|
||||
DllAddRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
DllRelease();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// BuildGlobalObjects
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void BuildGlobalObjects(void)
|
||||
{
|
||||
classFactoryObjects[0] =
|
||||
new (std::nothrow) CClassFactory(Global::MetasequoiaIMECLSID, CMetasequoiaIME::CreateInstance);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// FreeGlobalObjects
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void FreeGlobalObjects(void)
|
||||
{
|
||||
for (int i = 0; i < ARRAYSIZE(classFactoryObjects); i++)
|
||||
{
|
||||
if (nullptr != classFactoryObjects[i])
|
||||
{
|
||||
delete classFactoryObjects[i];
|
||||
classFactoryObjects[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
DeleteObject(Global::defaultlFontHandle);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// DllGetClassObject
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
_Check_return_ STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ void **ppv)
|
||||
{
|
||||
if (classFactoryObjects[0] == nullptr)
|
||||
{
|
||||
EnterCriticalSection(&Global::CS);
|
||||
|
||||
// need to check ref again after grabbing mutex
|
||||
if (classFactoryObjects[0] == nullptr)
|
||||
{
|
||||
BuildGlobalObjects();
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&Global::CS);
|
||||
}
|
||||
|
||||
if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown))
|
||||
{
|
||||
for (int i = 0; i < ARRAYSIZE(classFactoryObjects); i++)
|
||||
{
|
||||
if (nullptr != classFactoryObjects[i] && IsEqualGUID(rclsid, classFactoryObjects[i]->_rclsid))
|
||||
{
|
||||
*ppv = (void *)classFactoryObjects[i];
|
||||
DllAddRef(); // class factory holds DLL ref count
|
||||
return NOERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*ppv = nullptr;
|
||||
|
||||
return CLASS_E_CLASSNOTAVAILABLE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// DllCanUnloadNow
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI DllCanUnloadNow(void)
|
||||
{
|
||||
if (Global::dllRefCount >= 0)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// DllUnregisterServer
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI DllUnregisterServer(void)
|
||||
{
|
||||
UnregisterProfiles();
|
||||
UnregisterCategories();
|
||||
UnregisterServer();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// DllRegisterServer
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI DllRegisterServer(void)
|
||||
{
|
||||
if ((!RegisterServer()) || (!RegisterProfiles()) || (!RegisterCategories()))
|
||||
{
|
||||
DllUnregisterServer();
|
||||
return E_FAIL;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
@@ -1,49 +1,49 @@
|
||||
#include "Private.h"
|
||||
#include "TfInputProcessorProfile.h"
|
||||
|
||||
CTfInputProcessorProfile::CTfInputProcessorProfile()
|
||||
{
|
||||
_pInputProcessorProfile = nullptr;
|
||||
}
|
||||
|
||||
CTfInputProcessorProfile::~CTfInputProcessorProfile()
|
||||
{
|
||||
if (_pInputProcessorProfile)
|
||||
{
|
||||
_pInputProcessorProfile->Release();
|
||||
_pInputProcessorProfile = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CTfInputProcessorProfile::CreateInstance()
|
||||
{
|
||||
HRESULT hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, nullptr, CLSCTX_INPROC_SERVER,
|
||||
IID_ITfInputProcessorProfiles, (void **)&_pInputProcessorProfile);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT CTfInputProcessorProfile::GetCurrentLanguage(_Out_ LANGID *plangid)
|
||||
{
|
||||
if (_pInputProcessorProfile)
|
||||
{
|
||||
return _pInputProcessorProfile->GetCurrentLanguage(plangid);
|
||||
}
|
||||
else
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CTfInputProcessorProfile::GetDefaultLanguageProfile(LANGID langid, REFGUID catid, _Out_ CLSID *pclsid,
|
||||
_Out_ GUID *pguidProfile)
|
||||
{
|
||||
if (_pInputProcessorProfile)
|
||||
{
|
||||
return _pInputProcessorProfile->GetDefaultLanguageProfile(langid, catid, pclsid, pguidProfile);
|
||||
}
|
||||
else
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
#include "Private.h"
|
||||
#include "TfInputProcessorProfile.h"
|
||||
|
||||
CTfInputProcessorProfile::CTfInputProcessorProfile()
|
||||
{
|
||||
_pInputProcessorProfile = nullptr;
|
||||
}
|
||||
|
||||
CTfInputProcessorProfile::~CTfInputProcessorProfile()
|
||||
{
|
||||
if (_pInputProcessorProfile)
|
||||
{
|
||||
_pInputProcessorProfile->Release();
|
||||
_pInputProcessorProfile = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CTfInputProcessorProfile::CreateInstance()
|
||||
{
|
||||
HRESULT hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, nullptr, CLSCTX_INPROC_SERVER,
|
||||
IID_ITfInputProcessorProfiles, (void **)&_pInputProcessorProfile);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT CTfInputProcessorProfile::GetCurrentLanguage(_Out_ LANGID *plangid)
|
||||
{
|
||||
if (_pInputProcessorProfile)
|
||||
{
|
||||
return _pInputProcessorProfile->GetCurrentLanguage(plangid);
|
||||
}
|
||||
else
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CTfInputProcessorProfile::GetDefaultLanguageProfile(LANGID langid, REFGUID catid, _Out_ CLSID *pclsid,
|
||||
_Out_ GUID *pguidProfile)
|
||||
{
|
||||
if (_pInputProcessorProfile)
|
||||
{
|
||||
return _pInputProcessorProfile->GetDefaultLanguageProfile(langid, catid, pclsid, pguidProfile);
|
||||
}
|
||||
else
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "Private.h"
|
||||
|
||||
class CTfInputProcessorProfile
|
||||
{
|
||||
public:
|
||||
CTfInputProcessorProfile();
|
||||
~CTfInputProcessorProfile();
|
||||
|
||||
HRESULT CreateInstance();
|
||||
HRESULT GetCurrentLanguage(_Out_ LANGID *plangid);
|
||||
HRESULT GetDefaultLanguageProfile(LANGID langid, REFGUID catid, _Out_ CLSID *pclsid, _Out_ GUID *pguidProfile);
|
||||
|
||||
private:
|
||||
ITfInputProcessorProfiles *_pInputProcessorProfile;
|
||||
};
|
||||
#pragma once
|
||||
|
||||
#include "Private.h"
|
||||
|
||||
class CTfInputProcessorProfile
|
||||
{
|
||||
public:
|
||||
CTfInputProcessorProfile();
|
||||
~CTfInputProcessorProfile();
|
||||
|
||||
HRESULT CreateInstance();
|
||||
HRESULT GetCurrentLanguage(_Out_ LANGID *plangid);
|
||||
HRESULT GetDefaultLanguageProfile(LANGID langid, REFGUID catid, _Out_ CLSID *pclsid, _Out_ GUID *pguidProfile);
|
||||
|
||||
private:
|
||||
ITfInputProcessorProfiles *_pInputProcessorProfile;
|
||||
};
|
||||
+300
-300
@@ -1,300 +1,300 @@
|
||||
#include "FanyDefines.h"
|
||||
#include "Private.h"
|
||||
#include "TfTextLayoutSink.h"
|
||||
#include "MetasequoiaIME.h"
|
||||
#include "GetTextExtentEditSession.h"
|
||||
#include <debugapi.h>
|
||||
#include <fmt/xchar.h>
|
||||
#include "../Utils/PerfTimer.h"
|
||||
|
||||
POINT GetPhysicalTextAnchor(_In_ ITfContextView *pContextView, _In_ const RECT &textExtent)
|
||||
{
|
||||
POINT anchor = {textExtent.left, textExtent.bottom};
|
||||
HWND hostWindow = nullptr;
|
||||
if (SUCCEEDED(pContextView->GetWnd(&hostWindow)) && hostWindow)
|
||||
{
|
||||
hostWindow = GetAncestor(hostWindow, GA_ROOT);
|
||||
POINT physicalAnchor = anchor;
|
||||
if (hostWindow && LogicalToPhysicalPointForPerMonitorDPI(hostWindow, &physicalAnchor))
|
||||
{
|
||||
anchor = physicalAnchor;
|
||||
}
|
||||
}
|
||||
return anchor;
|
||||
}
|
||||
|
||||
CTfTextLayoutSink::CTfTextLayoutSink(_In_ CMetasequoiaIME *pTextService)
|
||||
{
|
||||
_pTextService = pTextService;
|
||||
_pTextService->AddRef();
|
||||
|
||||
_pRangeComposition = nullptr;
|
||||
_pContextDocument = nullptr;
|
||||
_tfEditCookie = TF_INVALID_EDIT_COOKIE;
|
||||
|
||||
_dwCookieTextLayoutSink = TF_INVALID_COOKIE;
|
||||
_hasValidAnchor = false;
|
||||
|
||||
_refCount = 1;
|
||||
|
||||
DllAddRef();
|
||||
}
|
||||
|
||||
CTfTextLayoutSink::~CTfTextLayoutSink()
|
||||
{
|
||||
if (_pTextService)
|
||||
{
|
||||
_pTextService->Release();
|
||||
}
|
||||
|
||||
DllRelease();
|
||||
}
|
||||
|
||||
STDAPI CTfTextLayoutSink::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
|
||||
{
|
||||
if (ppvObj == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*ppvObj = nullptr;
|
||||
|
||||
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfTextLayoutSink))
|
||||
{
|
||||
*ppvObj = (ITfTextLayoutSink *)this;
|
||||
}
|
||||
|
||||
if (*ppvObj)
|
||||
{
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
STDAPI_(ULONG) CTfTextLayoutSink::AddRef()
|
||||
{
|
||||
return ++_refCount;
|
||||
}
|
||||
|
||||
STDAPI_(ULONG) CTfTextLayoutSink::Release()
|
||||
{
|
||||
LONG cr = --_refCount;
|
||||
|
||||
assert(_refCount >= 0);
|
||||
|
||||
if (_refCount == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
return cr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfTextLayoutSink::OnLayoutChange
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CTfTextLayoutSink::OnLayoutChange(_In_ ITfContext *pContext, TfLayoutCode lcode,
|
||||
_In_ ITfContextView *pContextView)
|
||||
{
|
||||
PerfTimer timer;
|
||||
const bool isDocumentContext = (pContext == _pContextDocument);
|
||||
|
||||
// we're interested in only document context.
|
||||
if (pContext != _pContextDocument)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
double requestEditSessionElapsedMs = 0;
|
||||
switch (lcode)
|
||||
{
|
||||
case TF_LC_CREATE: {
|
||||
}
|
||||
case TF_LC_CHANGE: {
|
||||
CGetTextExtentEditSession *pEditSession = nullptr;
|
||||
pEditSession = new (std::nothrow)
|
||||
CGetTextExtentEditSession(_pTextService, pContext, pContextView, _pRangeComposition, this);
|
||||
if (nullptr != (pEditSession))
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
PerfTimer requestTimer;
|
||||
pContext->RequestEditSession(_pTextService->_GetClientId(), pEditSession, TF_ES_SYNC | TF_ES_READ, &hr);
|
||||
requestEditSessionElapsedMs = requestTimer.ElapsedMs();
|
||||
pEditSession->Release();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TF_LC_DESTROY:
|
||||
_LayoutDestroyNotification();
|
||||
break;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CTfTextLayoutSink::_StartLayout(_In_ ITfContext *pContextDocument, TfEditCookie ec,
|
||||
_In_ ITfRange *pRangeComposition)
|
||||
{
|
||||
PerfTimer timer;
|
||||
_pContextDocument = pContextDocument;
|
||||
_pContextDocument->AddRef();
|
||||
|
||||
_pRangeComposition = pRangeComposition;
|
||||
_pRangeComposition->AddRef();
|
||||
|
||||
_tfEditCookie = ec;
|
||||
_hasValidAnchor = false;
|
||||
HRESULT hr = _AdviseTextLayoutSink();
|
||||
return hr;
|
||||
}
|
||||
|
||||
VOID CTfTextLayoutSink::_EndLayout()
|
||||
{
|
||||
PerfTimer timer;
|
||||
const bool hadRangeComposition = (_pRangeComposition != nullptr);
|
||||
const bool hadContextDocument = (_pContextDocument != nullptr);
|
||||
HRESULT unadviseHr = S_OK;
|
||||
_hasValidAnchor = false;
|
||||
|
||||
if (_pRangeComposition)
|
||||
{
|
||||
_pRangeComposition->Release();
|
||||
_pRangeComposition = nullptr;
|
||||
}
|
||||
|
||||
if (_pContextDocument)
|
||||
{
|
||||
unadviseHr = _UnadviseTextLayoutSink();
|
||||
_pContextDocument->Release();
|
||||
_pContextDocument = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CTfTextLayoutSink::_AdviseTextLayoutSink()
|
||||
{
|
||||
PerfTimer timer;
|
||||
HRESULT hr = S_OK;
|
||||
ITfSource *pSource = nullptr;
|
||||
|
||||
hr = _pContextDocument->QueryInterface(IID_ITfSource, (void **)&pSource);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = pSource->AdviseSink(IID_ITfTextLayoutSink, (ITfTextLayoutSink *)this, &_dwCookieTextLayoutSink);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
pSource->Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
pSource->Release();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT CTfTextLayoutSink::_UnadviseTextLayoutSink()
|
||||
{
|
||||
PerfTimer timer;
|
||||
HRESULT hr = S_OK;
|
||||
ITfSource *pSource = nullptr;
|
||||
|
||||
if (nullptr == _pContextDocument)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
hr = _pContextDocument->QueryInterface(IID_ITfSource, (void **)&pSource);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = pSource->UnadviseSink(_dwCookieTextLayoutSink);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
pSource->Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
pSource->Release();
|
||||
_dwCookieTextLayoutSink = TF_INVALID_COOKIE;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取 caret 的坐标
|
||||
*
|
||||
* 本质上是通过 _pContextView->GetTextExt 获取 caret 坐标,
|
||||
* 因此,涉及到 caret 坐标的地方不止这里,还有其他地方,是直接
|
||||
* 使用 _pContextView->GetTextExt 来获取坐标的。
|
||||
*
|
||||
* @param lpRect
|
||||
* @return HRESULT
|
||||
*/
|
||||
HRESULT CTfTextLayoutSink::_GetTextExt(_Out_ RECT *lpRect, _Out_ POINT *lpAnchor)
|
||||
{
|
||||
PerfTimer timer;
|
||||
HRESULT hr = S_OK;
|
||||
BOOL isClipped = TRUE;
|
||||
ITfContextView *pContextView = nullptr;
|
||||
|
||||
hr = _pContextDocument->GetActiveView(&pContextView);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = pContextView->GetTextExt(_tfEditCookie, _pRangeComposition, lpRect, &isClipped);
|
||||
|
||||
// TS_E_NOLAYOUT means "the host has not laid this range out yet, ask again",
|
||||
// not "the caret is gone". Chromium-based hosts (Electron apps, browsers)
|
||||
// answer it routinely while their renderer is behind, and far more often
|
||||
// while the machine is busy. Adopting the off-screen sentinel here parks the
|
||||
// candidate window at INVALID_Y for one frame and the next measurement pulls
|
||||
// it back — that is the flicker seen under load. Report the failure so the
|
||||
// caller keeps the anchor it already has; TF_LC_CHANGE delivers the real
|
||||
// position as soon as layout completes. Only do this once this layout
|
||||
// session has produced a good anchor, so composition start still falls back
|
||||
// to the sentinel rather than reusing a stale one from another document.
|
||||
if (hr == TS_E_NOLAYOUT && _hasValidAnchor)
|
||||
{
|
||||
pContextView->Release();
|
||||
if (Global::TsfDiagnosticLogEnabled.load(std::memory_order_relaxed))
|
||||
{
|
||||
QueueTsfDiagnosticLog(L"[candidate-layout] kept last anchor across transient TS_E_NOLAYOUT");
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// Set default value to make sure the window is hidden by moving it out of the screen
|
||||
lpRect->left = 0;
|
||||
lpRect->bottom = Global::INVALID_Y;
|
||||
*lpAnchor = {0, Global::INVALID_Y};
|
||||
}
|
||||
else if (isClipped && lpRect && (lpRect->right <= lpRect->left || lpRect->bottom <= lpRect->top))
|
||||
{
|
||||
// Office often reports isClipped=TRUE with a still-usable rect; only reject
|
||||
// degenerate clipped extents that would anchor the candidate off-screen.
|
||||
lpRect->left = 0;
|
||||
lpRect->bottom = Global::INVALID_Y;
|
||||
*lpAnchor = {0, Global::INVALID_Y};
|
||||
}
|
||||
else
|
||||
{
|
||||
*lpAnchor = GetPhysicalTextAnchor(pContextView, *lpRect);
|
||||
_hasValidAnchor = true;
|
||||
}
|
||||
pContextView->Release();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
#include "FanyDefines.h"
|
||||
#include "Private.h"
|
||||
#include "TfTextLayoutSink.h"
|
||||
#include "MetasequoiaIME.h"
|
||||
#include "GetTextExtentEditSession.h"
|
||||
#include <debugapi.h>
|
||||
#include <fmt/xchar.h>
|
||||
#include "../Utils/PerfTimer.h"
|
||||
|
||||
POINT GetPhysicalTextAnchor(_In_ ITfContextView *pContextView, _In_ const RECT &textExtent)
|
||||
{
|
||||
POINT anchor = {textExtent.left, textExtent.bottom};
|
||||
HWND hostWindow = nullptr;
|
||||
if (SUCCEEDED(pContextView->GetWnd(&hostWindow)) && hostWindow)
|
||||
{
|
||||
hostWindow = GetAncestor(hostWindow, GA_ROOT);
|
||||
POINT physicalAnchor = anchor;
|
||||
if (hostWindow && LogicalToPhysicalPointForPerMonitorDPI(hostWindow, &physicalAnchor))
|
||||
{
|
||||
anchor = physicalAnchor;
|
||||
}
|
||||
}
|
||||
return anchor;
|
||||
}
|
||||
|
||||
CTfTextLayoutSink::CTfTextLayoutSink(_In_ CMetasequoiaIME *pTextService)
|
||||
{
|
||||
_pTextService = pTextService;
|
||||
_pTextService->AddRef();
|
||||
|
||||
_pRangeComposition = nullptr;
|
||||
_pContextDocument = nullptr;
|
||||
_tfEditCookie = TF_INVALID_EDIT_COOKIE;
|
||||
|
||||
_dwCookieTextLayoutSink = TF_INVALID_COOKIE;
|
||||
_hasValidAnchor = false;
|
||||
|
||||
_refCount = 1;
|
||||
|
||||
DllAddRef();
|
||||
}
|
||||
|
||||
CTfTextLayoutSink::~CTfTextLayoutSink()
|
||||
{
|
||||
if (_pTextService)
|
||||
{
|
||||
_pTextService->Release();
|
||||
}
|
||||
|
||||
DllRelease();
|
||||
}
|
||||
|
||||
STDAPI CTfTextLayoutSink::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
|
||||
{
|
||||
if (ppvObj == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*ppvObj = nullptr;
|
||||
|
||||
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfTextLayoutSink))
|
||||
{
|
||||
*ppvObj = (ITfTextLayoutSink *)this;
|
||||
}
|
||||
|
||||
if (*ppvObj)
|
||||
{
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
STDAPI_(ULONG) CTfTextLayoutSink::AddRef()
|
||||
{
|
||||
return ++_refCount;
|
||||
}
|
||||
|
||||
STDAPI_(ULONG) CTfTextLayoutSink::Release()
|
||||
{
|
||||
LONG cr = --_refCount;
|
||||
|
||||
assert(_refCount >= 0);
|
||||
|
||||
if (_refCount == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
return cr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfTextLayoutSink::OnLayoutChange
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CTfTextLayoutSink::OnLayoutChange(_In_ ITfContext *pContext, TfLayoutCode lcode,
|
||||
_In_ ITfContextView *pContextView)
|
||||
{
|
||||
PerfTimer timer;
|
||||
const bool isDocumentContext = (pContext == _pContextDocument);
|
||||
|
||||
// we're interested in only document context.
|
||||
if (pContext != _pContextDocument)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
double requestEditSessionElapsedMs = 0;
|
||||
switch (lcode)
|
||||
{
|
||||
case TF_LC_CREATE: {
|
||||
}
|
||||
case TF_LC_CHANGE: {
|
||||
CGetTextExtentEditSession *pEditSession = nullptr;
|
||||
pEditSession = new (std::nothrow)
|
||||
CGetTextExtentEditSession(_pTextService, pContext, pContextView, _pRangeComposition, this);
|
||||
if (nullptr != (pEditSession))
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
PerfTimer requestTimer;
|
||||
pContext->RequestEditSession(_pTextService->_GetClientId(), pEditSession, TF_ES_SYNC | TF_ES_READ, &hr);
|
||||
requestEditSessionElapsedMs = requestTimer.ElapsedMs();
|
||||
pEditSession->Release();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TF_LC_DESTROY:
|
||||
_LayoutDestroyNotification();
|
||||
break;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CTfTextLayoutSink::_StartLayout(_In_ ITfContext *pContextDocument, TfEditCookie ec,
|
||||
_In_ ITfRange *pRangeComposition)
|
||||
{
|
||||
PerfTimer timer;
|
||||
_pContextDocument = pContextDocument;
|
||||
_pContextDocument->AddRef();
|
||||
|
||||
_pRangeComposition = pRangeComposition;
|
||||
_pRangeComposition->AddRef();
|
||||
|
||||
_tfEditCookie = ec;
|
||||
_hasValidAnchor = false;
|
||||
HRESULT hr = _AdviseTextLayoutSink();
|
||||
return hr;
|
||||
}
|
||||
|
||||
VOID CTfTextLayoutSink::_EndLayout()
|
||||
{
|
||||
PerfTimer timer;
|
||||
const bool hadRangeComposition = (_pRangeComposition != nullptr);
|
||||
const bool hadContextDocument = (_pContextDocument != nullptr);
|
||||
HRESULT unadviseHr = S_OK;
|
||||
_hasValidAnchor = false;
|
||||
|
||||
if (_pRangeComposition)
|
||||
{
|
||||
_pRangeComposition->Release();
|
||||
_pRangeComposition = nullptr;
|
||||
}
|
||||
|
||||
if (_pContextDocument)
|
||||
{
|
||||
unadviseHr = _UnadviseTextLayoutSink();
|
||||
_pContextDocument->Release();
|
||||
_pContextDocument = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CTfTextLayoutSink::_AdviseTextLayoutSink()
|
||||
{
|
||||
PerfTimer timer;
|
||||
HRESULT hr = S_OK;
|
||||
ITfSource *pSource = nullptr;
|
||||
|
||||
hr = _pContextDocument->QueryInterface(IID_ITfSource, (void **)&pSource);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = pSource->AdviseSink(IID_ITfTextLayoutSink, (ITfTextLayoutSink *)this, &_dwCookieTextLayoutSink);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
pSource->Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
pSource->Release();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT CTfTextLayoutSink::_UnadviseTextLayoutSink()
|
||||
{
|
||||
PerfTimer timer;
|
||||
HRESULT hr = S_OK;
|
||||
ITfSource *pSource = nullptr;
|
||||
|
||||
if (nullptr == _pContextDocument)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
hr = _pContextDocument->QueryInterface(IID_ITfSource, (void **)&pSource);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = pSource->UnadviseSink(_dwCookieTextLayoutSink);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
pSource->Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
pSource->Release();
|
||||
_dwCookieTextLayoutSink = TF_INVALID_COOKIE;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取 caret 的坐标
|
||||
*
|
||||
* 本质上是通过 _pContextView->GetTextExt 获取 caret 坐标,
|
||||
* 因此,涉及到 caret 坐标的地方不止这里,还有其他地方,是直接
|
||||
* 使用 _pContextView->GetTextExt 来获取坐标的。
|
||||
*
|
||||
* @param lpRect
|
||||
* @return HRESULT
|
||||
*/
|
||||
HRESULT CTfTextLayoutSink::_GetTextExt(_Out_ RECT *lpRect, _Out_ POINT *lpAnchor)
|
||||
{
|
||||
PerfTimer timer;
|
||||
HRESULT hr = S_OK;
|
||||
BOOL isClipped = TRUE;
|
||||
ITfContextView *pContextView = nullptr;
|
||||
|
||||
hr = _pContextDocument->GetActiveView(&pContextView);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = pContextView->GetTextExt(_tfEditCookie, _pRangeComposition, lpRect, &isClipped);
|
||||
|
||||
// TS_E_NOLAYOUT means "the host has not laid this range out yet, ask again",
|
||||
// not "the caret is gone". Chromium-based hosts (Electron apps, browsers)
|
||||
// answer it routinely while their renderer is behind, and far more often
|
||||
// while the machine is busy. Adopting the off-screen sentinel here parks the
|
||||
// candidate window at INVALID_Y for one frame and the next measurement pulls
|
||||
// it back — that is the flicker seen under load. Report the failure so the
|
||||
// caller keeps the anchor it already has; TF_LC_CHANGE delivers the real
|
||||
// position as soon as layout completes. Only do this once this layout
|
||||
// session has produced a good anchor, so composition start still falls back
|
||||
// to the sentinel rather than reusing a stale one from another document.
|
||||
if (hr == TS_E_NOLAYOUT && _hasValidAnchor)
|
||||
{
|
||||
pContextView->Release();
|
||||
if (Global::TsfDiagnosticLogEnabled.load(std::memory_order_relaxed))
|
||||
{
|
||||
QueueTsfDiagnosticLog(L"[candidate-layout] kept last anchor across transient TS_E_NOLAYOUT");
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// Set default value to make sure the window is hidden by moving it out of the screen
|
||||
lpRect->left = 0;
|
||||
lpRect->bottom = Global::INVALID_Y;
|
||||
*lpAnchor = {0, Global::INVALID_Y};
|
||||
}
|
||||
else if (isClipped && lpRect && (lpRect->right <= lpRect->left || lpRect->bottom <= lpRect->top))
|
||||
{
|
||||
// Office often reports isClipped=TRUE with a still-usable rect; only reject
|
||||
// degenerate clipped extents that would anchor the candidate off-screen.
|
||||
lpRect->left = 0;
|
||||
lpRect->bottom = Global::INVALID_Y;
|
||||
*lpAnchor = {0, Global::INVALID_Y};
|
||||
}
|
||||
else
|
||||
{
|
||||
*lpAnchor = GetPhysicalTextAnchor(pContextView, *lpRect);
|
||||
_hasValidAnchor = true;
|
||||
}
|
||||
pContextView->Release();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@@ -1,55 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
#include "Private.h"
|
||||
|
||||
class CMetasequoiaIME;
|
||||
|
||||
POINT GetPhysicalTextAnchor(_In_ ITfContextView *pContextView, _In_ const RECT &textExtent);
|
||||
|
||||
class CTfTextLayoutSink : public ITfTextLayoutSink
|
||||
{
|
||||
public:
|
||||
CTfTextLayoutSink(_In_ CMetasequoiaIME *pTextService);
|
||||
virtual ~CTfTextLayoutSink();
|
||||
|
||||
// IUnknown methods
|
||||
STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj);
|
||||
STDMETHODIMP_(ULONG) AddRef(void);
|
||||
STDMETHODIMP_(ULONG) Release(void);
|
||||
|
||||
// ITfTextLayoutSink
|
||||
STDMETHODIMP OnLayoutChange(_In_ ITfContext *pContext, TfLayoutCode lcode, _In_ ITfContextView *pContextView);
|
||||
|
||||
HRESULT _StartLayout(_In_ ITfContext *pContextDocument, TfEditCookie ec, _In_ ITfRange *pRangeComposition);
|
||||
VOID _EndLayout();
|
||||
|
||||
HRESULT _GetTextExt(_Out_ RECT *lpRect, _Out_ POINT *lpAnchor);
|
||||
ITfContext *_GetContextDocument()
|
||||
{
|
||||
return _pContextDocument;
|
||||
};
|
||||
|
||||
// Callers that read the caret straight from ITfContextView (the edit-session
|
||||
// path) report their success here, so _GetTextExt knows whether Global::Point
|
||||
// already holds a usable anchor for this layout session.
|
||||
void _MarkAnchorValid()
|
||||
{
|
||||
_hasValidAnchor = true;
|
||||
}
|
||||
|
||||
virtual VOID _LayoutChangeNotification(_In_ RECT *lpRect) = 0;
|
||||
virtual VOID _LayoutDestroyNotification() = 0;
|
||||
|
||||
private:
|
||||
HRESULT _AdviseTextLayoutSink();
|
||||
HRESULT _UnadviseTextLayoutSink();
|
||||
|
||||
private:
|
||||
ITfRange *_pRangeComposition;
|
||||
ITfContext *_pContextDocument;
|
||||
TfEditCookie _tfEditCookie;
|
||||
CMetasequoiaIME *_pTextService;
|
||||
DWORD _dwCookieTextLayoutSink;
|
||||
LONG _refCount;
|
||||
bool _hasValidAnchor;
|
||||
};
|
||||
#pragma once
|
||||
|
||||
#include "Private.h"
|
||||
|
||||
class CMetasequoiaIME;
|
||||
|
||||
POINT GetPhysicalTextAnchor(_In_ ITfContextView *pContextView, _In_ const RECT &textExtent);
|
||||
|
||||
class CTfTextLayoutSink : public ITfTextLayoutSink
|
||||
{
|
||||
public:
|
||||
CTfTextLayoutSink(_In_ CMetasequoiaIME *pTextService);
|
||||
virtual ~CTfTextLayoutSink();
|
||||
|
||||
// IUnknown methods
|
||||
STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj);
|
||||
STDMETHODIMP_(ULONG) AddRef(void);
|
||||
STDMETHODIMP_(ULONG) Release(void);
|
||||
|
||||
// ITfTextLayoutSink
|
||||
STDMETHODIMP OnLayoutChange(_In_ ITfContext *pContext, TfLayoutCode lcode, _In_ ITfContextView *pContextView);
|
||||
|
||||
HRESULT _StartLayout(_In_ ITfContext *pContextDocument, TfEditCookie ec, _In_ ITfRange *pRangeComposition);
|
||||
VOID _EndLayout();
|
||||
|
||||
HRESULT _GetTextExt(_Out_ RECT *lpRect, _Out_ POINT *lpAnchor);
|
||||
ITfContext *_GetContextDocument()
|
||||
{
|
||||
return _pContextDocument;
|
||||
};
|
||||
|
||||
// Callers that read the caret straight from ITfContextView (the edit-session
|
||||
// path) report their success here, so _GetTextExt knows whether Global::Point
|
||||
// already holds a usable anchor for this layout session.
|
||||
void _MarkAnchorValid()
|
||||
{
|
||||
_hasValidAnchor = true;
|
||||
}
|
||||
|
||||
virtual VOID _LayoutChangeNotification(_In_ RECT *lpRect) = 0;
|
||||
virtual VOID _LayoutDestroyNotification() = 0;
|
||||
|
||||
private:
|
||||
HRESULT _AdviseTextLayoutSink();
|
||||
HRESULT _UnadviseTextLayoutSink();
|
||||
|
||||
private:
|
||||
ITfRange *_pRangeComposition;
|
||||
ITfContext *_pContextDocument;
|
||||
TfEditCookie _tfEditCookie;
|
||||
CMetasequoiaIME *_pTextService;
|
||||
DWORD _dwCookieTextLayoutSink;
|
||||
LONG _refCount;
|
||||
bool _hasValidAnchor;
|
||||
};
|
||||
@@ -1,34 +1,34 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <string>
|
||||
|
||||
namespace FanyUtils
|
||||
{
|
||||
std::string GetIMEDataDirPath();
|
||||
void SendKeys(std::wstring pinyin);
|
||||
std::wstring string_to_wstring(const std::string &str);
|
||||
std::string wstring_to_string(const std::wstring &wstr);
|
||||
std::string to_lower_copy(const std::string &str);
|
||||
std::wstring GetCurrentProcessName();
|
||||
std::string::size_type count_utf8_chars(const std::string &str);
|
||||
// Read input.default_ime_mode from %LOCALAPPDATA%\metasequoiaime\config.toml.
|
||||
// Returns TRUE for Chinese (default), FALSE for English.
|
||||
BOOL ReadConfiguredDefaultImeModeChinese();
|
||||
// Read input.mode from the shared config. TRUE when Japanese input is active.
|
||||
BOOL ReadConfiguredJapaneseInputMode();
|
||||
// Read input.punctuation_lock from shared config.toml.
|
||||
// 0 = follow IME, 1 = always Chinese punctuation, 2 = always English punctuation.
|
||||
int ReadConfiguredPunctuationLock();
|
||||
// Refresh the in-process lock cache from config.toml.
|
||||
void RefreshPunctuationLockFromConfig();
|
||||
|
||||
struct SwitchLanguageHotkeys
|
||||
{
|
||||
bool shift = true;
|
||||
bool ctrl = false;
|
||||
bool ctrl_alt_space = true;
|
||||
bool character_set_ctrl_shift_f = true;
|
||||
};
|
||||
// Read keybindings.switch_language_* from shared config.toml.
|
||||
SwitchLanguageHotkeys ReadConfiguredSwitchLanguageHotkeys();
|
||||
} // namespace FanyUtils
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <string>
|
||||
|
||||
namespace FanyUtils
|
||||
{
|
||||
std::string GetIMEDataDirPath();
|
||||
void SendKeys(std::wstring pinyin);
|
||||
std::wstring string_to_wstring(const std::string &str);
|
||||
std::string wstring_to_string(const std::wstring &wstr);
|
||||
std::string to_lower_copy(const std::string &str);
|
||||
std::wstring GetCurrentProcessName();
|
||||
std::string::size_type count_utf8_chars(const std::string &str);
|
||||
// Read input.default_ime_mode from %LOCALAPPDATA%\metasequoiaime\config.toml.
|
||||
// Returns TRUE for Chinese (default), FALSE for English.
|
||||
BOOL ReadConfiguredDefaultImeModeChinese();
|
||||
// Read input.mode from the shared config. TRUE when Japanese input is active.
|
||||
BOOL ReadConfiguredJapaneseInputMode();
|
||||
// Read input.punctuation_lock from shared config.toml.
|
||||
// 0 = follow IME, 1 = always Chinese punctuation, 2 = always English punctuation.
|
||||
int ReadConfiguredPunctuationLock();
|
||||
// Refresh the in-process lock cache from config.toml.
|
||||
void RefreshPunctuationLockFromConfig();
|
||||
|
||||
struct SwitchLanguageHotkeys
|
||||
{
|
||||
bool shift = true;
|
||||
bool ctrl = false;
|
||||
bool ctrl_alt_space = true;
|
||||
bool character_set_ctrl_shift_f = true;
|
||||
};
|
||||
// Read keybindings.switch_language_* from shared config.toml.
|
||||
SwitchLanguageHotkeys ReadConfiguredSwitchLanguageHotkeys();
|
||||
} // namespace FanyUtils
|
||||
Reference in new issue
Block a user