First commit.
No files matched your search
@@ -0,0 +1,6 @@
|
||||
---
|
||||
BasedOnStyle: Microsoft
|
||||
IndentWidth: 4
|
||||
|
||||
# 不要给头文件排序
|
||||
SortIncludes: false
|
||||
@@ -0,0 +1,2 @@
|
||||
CompileFlags:
|
||||
Add: [-Wno-microsoft-goto, -Wno-unused-value] # 忽略某些警告
|
||||
@@ -0,0 +1 @@
|
||||
build/
|
||||
@@ -0,0 +1,118 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "SampleIME.h"
|
||||
#include "CompositionProcessorEngine.h"
|
||||
|
||||
BOOL CSampleIME::VerifySampleIMECLSID(_In_ REFCLSID clsid)
|
||||
{
|
||||
if (IsEqualCLSID(clsid, Global::SampleIMECLSID))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfActiveLanguageProfileNotifySink::OnActivated
|
||||
//
|
||||
// Sink called by the framework when changes activate language profile.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CSampleIME::OnActivated(_In_ REFCLSID clsid, _In_ REFGUID guidProfile, _In_ BOOL isActivated)
|
||||
{
|
||||
guidProfile;
|
||||
|
||||
if (FALSE == VerifySampleIMECLSID(clsid))
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (isActivated)
|
||||
{
|
||||
_AddTextProcessorEngine();
|
||||
}
|
||||
|
||||
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 CSampleIME::_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 CSampleIME::_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;
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "BaseDictionaryEngine.h"
|
||||
#include "Globals.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
// ctor
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CBaseDictionaryEngine::CBaseDictionaryEngine(LCID locale, _In_ CFile *pDictionaryFile)
|
||||
{
|
||||
_locale = locale;
|
||||
_pDictionaryFile = pDictionaryFile;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
// dtor
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CBaseDictionaryEngine::~CBaseDictionaryEngine()
|
||||
{
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
// SortListItemByFindKeyCode
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
VOID CBaseDictionaryEngine::SortListItemByFindKeyCode(_Inout_ CSampleImeArray<CCandidateListItem> *pItemList)
|
||||
{
|
||||
MergeSortByFindKeyCode(pItemList, 0, pItemList->Count() - 1);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
// MergeSortByFindKeyCode
|
||||
//
|
||||
// Mergesort the array of element in CCandidateListItem::_FindKeyCode
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
VOID CBaseDictionaryEngine::MergeSortByFindKeyCode(_Inout_ CSampleImeArray<CCandidateListItem> *pItemList, int leftRange, int rightRange)
|
||||
{
|
||||
int candidateCount = CalculateCandidateCount(leftRange, rightRange);
|
||||
|
||||
if (candidateCount > 2)
|
||||
{
|
||||
int mid = leftRange + (candidateCount / 2);
|
||||
|
||||
MergeSortByFindKeyCode(pItemList, leftRange, mid);
|
||||
MergeSortByFindKeyCode(pItemList, mid, rightRange);
|
||||
|
||||
CSampleImeArray<CCandidateListItem> ListItemTemp;
|
||||
|
||||
int leftRangeTemp = 0;
|
||||
int midTemp = 0;
|
||||
for (leftRangeTemp = leftRange, midTemp = mid; leftRangeTemp != mid || midTemp != rightRange;)
|
||||
{
|
||||
CStringRange* psrgLeftTemp = nullptr;
|
||||
CStringRange* psrgMidTemp = nullptr;
|
||||
|
||||
psrgLeftTemp = &pItemList->GetAt(leftRangeTemp)->_FindKeyCode;
|
||||
psrgMidTemp = &pItemList->GetAt(midTemp)->_FindKeyCode;
|
||||
|
||||
CCandidateListItem* pLI = nullptr;
|
||||
pLI = ListItemTemp.Append();
|
||||
if (pLI)
|
||||
{
|
||||
if (leftRangeTemp == mid)
|
||||
{
|
||||
*pLI = *pItemList->GetAt(midTemp++);
|
||||
}
|
||||
else if (midTemp == rightRange || CStringRange::Compare(_locale, psrgLeftTemp, psrgMidTemp) != CSTR_GREATER_THAN)
|
||||
{
|
||||
*pLI = *pItemList->GetAt(leftRangeTemp++);
|
||||
}
|
||||
else
|
||||
{
|
||||
*pLI = *pItemList->GetAt(midTemp++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
leftRangeTemp = leftRange;
|
||||
for (UINT count = 0; count < ListItemTemp.Count(); count++)
|
||||
{
|
||||
*pItemList->GetAt(leftRangeTemp++) = *ListItemTemp.GetAt(count);
|
||||
}
|
||||
}
|
||||
else if (candidateCount == 2)
|
||||
{
|
||||
CStringRange *psrgLeft = nullptr;
|
||||
CStringRange *psrgLeftNext = nullptr;
|
||||
|
||||
psrgLeft = &pItemList->GetAt(leftRange )->_FindKeyCode;
|
||||
psrgLeftNext = &pItemList->GetAt(leftRange+1)->_FindKeyCode;
|
||||
|
||||
if (CStringRange::Compare(_locale, psrgLeft, psrgLeftNext) == CSTR_GREATER_THAN)
|
||||
{
|
||||
CCandidateListItem ListItem;
|
||||
ListItem = *pItemList->GetAt(leftRange);
|
||||
*pItemList->GetAt(leftRange ) = *pItemList->GetAt(leftRange+1);
|
||||
*pItemList->GetAt(leftRange+1) = ListItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CBaseDictionaryEngine::CalculateCandidateCount(int leftRange, int rightRange)
|
||||
{
|
||||
assert(leftRange >= 0);
|
||||
assert(rightRange >= 0);
|
||||
|
||||
return (rightRange - leftRange + 1);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "File.h"
|
||||
#include "SampleIMEBaseStructure.h"
|
||||
|
||||
class CBaseDictionaryEngine
|
||||
{
|
||||
public:
|
||||
CBaseDictionaryEngine(LCID locale, _In_ CFile *pDictionaryFile);
|
||||
virtual ~CBaseDictionaryEngine();
|
||||
|
||||
virtual VOID CollectWord(_In_ CStringRange *psrgKeyCode, _Out_ CSampleImeArray<CStringRange> *pasrgWordString)
|
||||
{
|
||||
psrgKeyCode;
|
||||
pasrgWordString = nullptr;
|
||||
}
|
||||
|
||||
virtual VOID CollectWord(_In_ CStringRange *psrgKeyCode, _Out_ CSampleImeArray<CCandidateListItem> *pItemList)
|
||||
{
|
||||
psrgKeyCode;
|
||||
pItemList = nullptr;
|
||||
}
|
||||
|
||||
virtual VOID SortListItemByFindKeyCode(_Inout_ CSampleImeArray<CCandidateListItem> *pItemList);
|
||||
|
||||
protected:
|
||||
CFile* _pDictionaryFile;
|
||||
LCID _locale;
|
||||
|
||||
private:
|
||||
VOID MergeSortByFindKeyCode(_Inout_ CSampleImeArray<CCandidateListItem> *pItemList, int leftRange, int rightRange);
|
||||
int CalculateCandidateCount(int leftRange, int rightRange);
|
||||
};
|
||||
@@ -0,0 +1,662 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "BaseWindow.h"
|
||||
|
||||
#define idTimer_UIObject 39772
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CBaseWindow::ctor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CBaseWindow::CBaseWindow()
|
||||
{
|
||||
_wndHandle = nullptr;
|
||||
_pParentWnd = nullptr;
|
||||
_pUIWnd = nullptr;
|
||||
|
||||
_pTimerUIObj = nullptr;
|
||||
_pUIObjCapture = nullptr;
|
||||
|
||||
_enableVirtualWnd = TRUE;
|
||||
_visibleVirtualWnd = TRUE;
|
||||
_RectOfVirtualWnd.left = 0;
|
||||
_RectOfVirtualWnd.top = 0;
|
||||
_RectOfVirtualWnd.right = 0;
|
||||
_RectOfVirtualWnd.bottom = 0;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CBaseWindow::dtor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CBaseWindow::~CBaseWindow()
|
||||
{
|
||||
_SetThis(_wndHandle, nullptr);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CBaseWindow::_InitWindowClass
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/* static */
|
||||
BOOL CBaseWindow::_InitWindowClass(_In_ LPCWSTR lpwszClassName, _Out_ ATOM *patom)
|
||||
{
|
||||
WNDCLASS wc;
|
||||
|
||||
wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_IME;
|
||||
wc.lpfnWndProc = CBaseWindow::_WindowProc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = Global::dllInstanceHandle;
|
||||
wc.hIcon = nullptr;
|
||||
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||
wc.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
|
||||
wc.lpszMenuName = nullptr;
|
||||
wc.lpszClassName = lpwszClassName;
|
||||
|
||||
*patom = RegisterClass(&wc);
|
||||
|
||||
return (*patom != 0);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CBaseWindow::_UninitClass
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/* static */
|
||||
void CBaseWindow::_UninitWindowClass(ATOM atom)
|
||||
{
|
||||
if (atom != 0)
|
||||
{
|
||||
UnregisterClass((LPCTSTR)atom, Global::dllInstanceHandle);
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CBaseWindow::_Create
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CBaseWindow::_Create(ATOM atom, DWORD dwExStyle, DWORD dwStyle, _In_opt_ CBaseWindow *pParentWnd, int wndWidth, int wndHeight, _In_opt_ HWND parentWndHandle)
|
||||
{
|
||||
_pParentWnd = pParentWnd;
|
||||
|
||||
if (atom != 0)
|
||||
{
|
||||
// create real window
|
||||
|
||||
_wndHandle = CreateWindowEx(dwExStyle,
|
||||
(LPCTSTR)atom,
|
||||
NULL,
|
||||
dwStyle,
|
||||
0, 0,
|
||||
wndWidth, wndHeight,
|
||||
_pParentWnd ? _pParentWnd->_GetWnd() : parentWndHandle, // parentWndHandle
|
||||
NULL,
|
||||
Global::dllInstanceHandle,
|
||||
this); // lpParam
|
||||
|
||||
if (!_wndHandle)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CBaseWindow::_Destroy
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CBaseWindow::_Destroy()
|
||||
{
|
||||
if (_wndHandle != nullptr)
|
||||
{
|
||||
DestroyWindow(_wndHandle);
|
||||
_wndHandle = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CBaseWindow::_Move
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CBaseWindow::_Move(int x, int y)
|
||||
{
|
||||
if (_wndHandle != nullptr)
|
||||
{
|
||||
SetWindowPos(_wndHandle, 0, x, y, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
|
||||
}
|
||||
else
|
||||
{
|
||||
int dx = x - _RectOfVirtualWnd.left;
|
||||
int dy = y - _RectOfVirtualWnd.top;
|
||||
|
||||
_RectOfVirtualWnd.left += dx;
|
||||
_RectOfVirtualWnd.top += dy;
|
||||
_RectOfVirtualWnd.right += dx;
|
||||
_RectOfVirtualWnd.bottom += dy;
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CBaseWindow::_Resize
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CBaseWindow::_Resize(int x, int y, int cx, int cy)
|
||||
{
|
||||
if (_wndHandle != nullptr)
|
||||
{
|
||||
MoveWindow(_wndHandle, x, y, cx, cy, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
_RectOfVirtualWnd.left = x;
|
||||
_RectOfVirtualWnd.top = y;
|
||||
_RectOfVirtualWnd.right = x + cx;
|
||||
_RectOfVirtualWnd.bottom = y + cy;
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CBaseWindow::_Show
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CBaseWindow::_Show(BOOL isShowWnd)
|
||||
{
|
||||
if (_wndHandle != nullptr)
|
||||
{
|
||||
if (isShowWnd)
|
||||
{
|
||||
ShowWindow(_wndHandle, SW_SHOWNA);
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowWindow(_wndHandle, SW_HIDE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_visibleVirtualWnd = isShowWnd;
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CBaseWindow::_IsWindowVisible
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CBaseWindow::_IsWindowVisible()
|
||||
{
|
||||
if (_wndHandle != nullptr)
|
||||
{
|
||||
return IsWindowVisible(_wndHandle);
|
||||
}
|
||||
else
|
||||
{
|
||||
return _visibleVirtualWnd;
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CBaseWindow::_Enable
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CBaseWindow::_Enable(BOOL enableWindowReceiveInput)
|
||||
{
|
||||
if (_wndHandle != nullptr)
|
||||
{
|
||||
EnableWindow(_wndHandle, enableWindowReceiveInput);
|
||||
}
|
||||
else
|
||||
{
|
||||
_enableVirtualWnd = enableWindowReceiveInput;
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CBaseWindow::_IsEnabled
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CBaseWindow::_IsEnabled()
|
||||
{
|
||||
if (_wndHandle != nullptr)
|
||||
{
|
||||
return IsWindowEnabled(_wndHandle);
|
||||
}
|
||||
else
|
||||
{
|
||||
return _enableVirtualWnd;
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CBaseWindow::_InvalidateRect
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CBaseWindow::_InvalidateRect()
|
||||
{
|
||||
if (_wndHandle != nullptr)
|
||||
{
|
||||
InvalidateRect(_wndHandle, NULL, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
CBaseWindow *pobj = _pParentWnd;
|
||||
while (pobj != nullptr)
|
||||
{
|
||||
if (pobj->_wndHandle)
|
||||
{
|
||||
InvalidateRect(pobj->_wndHandle, &_RectOfVirtualWnd, TRUE);
|
||||
break;
|
||||
}
|
||||
pobj = pobj->_pParentWnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CBaseWindow::_GetWindowRect
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CBaseWindow::_GetWindowRect(_Inout_ LPRECT lpRect)
|
||||
{
|
||||
if (_wndHandle != nullptr)
|
||||
{
|
||||
return GetWindowRect(_wndHandle, lpRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
*lpRect = _RectOfVirtualWnd;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CBaseWindow::_GetClientRect
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CBaseWindow::_GetClientRect(_Inout_ LPRECT lpRect)
|
||||
{
|
||||
if (_wndHandle != nullptr)
|
||||
{
|
||||
return GetClientRect(_wndHandle, lpRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
*lpRect = _RectOfVirtualWnd;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _GetWindowExtent
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CBaseWindow::_GetWindowExtent(_In_ const RECT *prcTextExtent, _In_opt_ RECT *prcCandidateExtent, _Inout_ POINT *pptCandidate)
|
||||
{
|
||||
RECT rcWorkArea = {0, 0, 0, 0};
|
||||
|
||||
// Get work area
|
||||
GetWorkAreaFromPoint(*(LPPOINT)&prcTextExtent->left, &rcWorkArea);
|
||||
|
||||
// Calc candidate window extent
|
||||
if (prcCandidateExtent)
|
||||
{
|
||||
CalcFitPointAroundTextExtent(prcTextExtent, &rcWorkArea, prcCandidateExtent, pptCandidate);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CalcFitPointAroundTextExtent
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CBaseWindow::CalcFitPointAroundTextExtent(_In_ const RECT *prcTextExtent, _In_ const RECT *prcWorkArea, _In_ const RECT *prcWindow, _Out_ POINT *ppt)
|
||||
{
|
||||
RECT rcTargetWindow[2];
|
||||
DWORD dwFlags[2];
|
||||
|
||||
// set rcTargetWindow[0] which rectangle attached on bottom side of text extent
|
||||
rcTargetWindow[0] = *prcWindow;
|
||||
OffsetRect(&rcTargetWindow[0], prcTextExtent->left, prcTextExtent->bottom);
|
||||
|
||||
// set rcTargetWindow[1] which rectangle attached on top side of text extent
|
||||
rcTargetWindow[1] = *prcWindow;
|
||||
OffsetRect(&rcTargetWindow[1], prcTextExtent->left, prcTextExtent->top - (prcWindow->bottom - prcWindow->top));
|
||||
|
||||
//
|
||||
// check target rectangle fit in workarea
|
||||
//
|
||||
for (DWORD i = 0; i < ARRAYSIZE(rcTargetWindow); i++)
|
||||
{
|
||||
dwFlags[i] = RectInRect(prcWorkArea, &rcTargetWindow[i]);
|
||||
|
||||
// generally, rcTargetWindow[0] or rcTargetWindow[1] have neither of these flags
|
||||
// but in the case where window is just complete way off the screen e.g. user
|
||||
// starts input, then drag window way off screen, both of these will be true
|
||||
if ((dwFlags[i] & RECT_OVER_TOP) || (dwFlags[i] & RECT_OVER_BOTTOM))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dwFlags[i] == RECT_INSIDE)
|
||||
{
|
||||
*ppt = *(POINT*)&rcTargetWindow[i].left;
|
||||
return;
|
||||
}
|
||||
else if ((dwFlags[i] & RECT_OVER_LEFT) != 0)
|
||||
{
|
||||
ppt->x = 0;
|
||||
ppt->y = rcTargetWindow[i].top;
|
||||
return;
|
||||
}
|
||||
else if ((dwFlags[i] & RECT_OVER_RIGHT) != 0)
|
||||
{
|
||||
ppt->x = prcWorkArea->right - (prcWindow->right - prcWindow->left);
|
||||
ppt->y = rcTargetWindow[i].top;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// if both rcTargetWindow have RECT_OVER_TOP or RECT_OVER_BOTTOM,
|
||||
// then "dock" the window to top or bottom of working area.
|
||||
if ((dwFlags[0] & RECT_OVER_TOP) != 0)
|
||||
{
|
||||
ppt->y = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ppt->y = prcWorkArea->bottom - (prcWindow->bottom - prcWindow->top);
|
||||
}
|
||||
|
||||
// dock to left/right edge if RECT_OVER_LEFT or RECT_OVER_RIGHT.
|
||||
// else just stay where we are
|
||||
if ((dwFlags[0] & RECT_OVER_LEFT) != 0)
|
||||
{
|
||||
ppt->x = 0;
|
||||
}
|
||||
else if ((dwFlags[0] & RECT_OVER_RIGHT) != 0)
|
||||
{
|
||||
ppt->x = prcWorkArea->right - (prcWindow->right - prcWindow->left);
|
||||
}
|
||||
else
|
||||
{
|
||||
ppt->x = prcTextExtent->left;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// RectInRect
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DWORD CBaseWindow::RectInRect(_In_ const RECT *prcLimit, _In_ const RECT *prcTarget)
|
||||
{
|
||||
DWORD dwFlags = 0;
|
||||
// Check if prcTarget is entirely inside prcLimit
|
||||
if (prcLimit->left <= prcTarget->left && prcTarget->right <= prcLimit->right &&
|
||||
prcLimit->top <= prcTarget->top && prcTarget->bottom <= prcLimit->bottom)
|
||||
{
|
||||
return RECT_INSIDE;
|
||||
}
|
||||
|
||||
// Check horizontal range. Target can be
|
||||
// - wider than the limit (assert here since it should never happen)
|
||||
// - entirely outside the limit (RECT_OVERLEFT or RECT_OVERRIGHT)
|
||||
// - partially inside the limit (RECT_OVERLEFT or RECT_OVERRIGHT)
|
||||
if (prcTarget->left < prcLimit->left && prcTarget->right > prcLimit->right)
|
||||
{
|
||||
assert(FALSE);
|
||||
dwFlags |= RECT_TOO_WIDE;
|
||||
}
|
||||
else if (prcTarget->left < prcLimit->left)
|
||||
{
|
||||
dwFlags |= RECT_OVER_LEFT;
|
||||
}
|
||||
else if (prcTarget->right > prcLimit->right)
|
||||
{
|
||||
dwFlags |= RECT_OVER_RIGHT;
|
||||
}
|
||||
|
||||
// Check vertical range. Target can be
|
||||
// - taller than the limit (assert here since it should never happen)
|
||||
// - entirely outside the limit (RECT_OVERTOP or RECT_OVERBOTTOM)
|
||||
// - partially inside the limit (RECT_OVERTOP or RECT_OVERBOTTOM)
|
||||
if (prcTarget->top < prcLimit->top && prcTarget->bottom > prcLimit->bottom)
|
||||
{
|
||||
assert(FALSE);
|
||||
dwFlags |= RECT_TOO_TALL;
|
||||
}
|
||||
else if (prcTarget->top < prcLimit->top)
|
||||
{
|
||||
dwFlags |= RECT_OVER_TOP;
|
||||
}
|
||||
else if (prcTarget->bottom > prcLimit->bottom)
|
||||
{
|
||||
dwFlags |= RECT_OVER_BOTTOM;
|
||||
}
|
||||
|
||||
return dwFlags;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CBaseWindow::_NotifyCommand
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
LRESULT CBaseWindow::_NotifyCommand(UINT uMsg, DWORD dwSB, int nPos)
|
||||
{
|
||||
CBaseWindow* pUIWnd = _GetUIWnd();
|
||||
if (pUIWnd && pUIWnd->_GetWnd())
|
||||
{
|
||||
WPARAM wParam = MAKEWPARAM(dwSB, nPos);
|
||||
if (pUIWnd->_GetWnd())
|
||||
{
|
||||
return SendMessage(pUIWnd->_GetWnd(), uMsg, wParam, (LPARAM)0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _SetCaptureObject
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CBaseWindow::_SetCaptureObject(_In_opt_ CBaseWindow *pUIObj)
|
||||
{
|
||||
CBaseWindow* pUIWnd = _GetTopmostUIWnd();
|
||||
if (nullptr == pUIWnd)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pUIWnd->_pUIObjCapture = pUIObj;
|
||||
if (pUIObj != nullptr)
|
||||
{
|
||||
SetCapture(pUIWnd->_GetWnd());
|
||||
}
|
||||
else
|
||||
{
|
||||
ReleaseCapture();
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _SetTimerObject
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CBaseWindow::_SetTimerObject(_In_opt_ CBaseWindow *pUIObj, UINT uElapse)
|
||||
{
|
||||
CBaseWindow* pUIWnd = _GetTopmostUIWnd();
|
||||
if (nullptr == pUIWnd)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pUIWnd->_pTimerUIObj = pUIObj;
|
||||
if (pUIObj != nullptr)
|
||||
{
|
||||
SetTimer(pUIWnd->_GetWnd(), idTimer_UIObject, uElapse, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
KillTimer(pUIWnd->_GetWnd(), idTimer_UIObject);
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CBaseWindow::_WindowProc
|
||||
//
|
||||
// CBaseWindow window proc.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/* static */
|
||||
LRESULT CALLBACK CBaseWindow::_WindowProc(_In_ HWND wndHandle, UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam)
|
||||
{
|
||||
if (uMsg == WM_CREATE)
|
||||
{
|
||||
_SetThis(wndHandle, ((CREATESTRUCT*)lParam)->lpCreateParams);
|
||||
}
|
||||
|
||||
CBaseWindow* pv = _GetThis(wndHandle);
|
||||
if (!pv)
|
||||
{
|
||||
return DefWindowProc(wndHandle, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
if (uMsg == WM_TIMER)
|
||||
{
|
||||
switch (wParam)
|
||||
{
|
||||
case idTimer_UIObject:
|
||||
if (pv->_GetTimerObject() != nullptr)
|
||||
{
|
||||
pv->_GetTimerObject()->_OnTimer();
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return pv->_WindowProcCallback(wndHandle, uMsg, wParam, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CBaseWindow::GetWorkAreaFromPoint
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CBaseWindow::GetWorkAreaFromPoint(_In_ const POINT& ptPoint, _Out_ LPRECT lprcWorkArea)
|
||||
{
|
||||
if (lprcWorkArea == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lprcWorkArea->left = 0;
|
||||
lprcWorkArea->top = 0;
|
||||
lprcWorkArea->right = 0;
|
||||
lprcWorkArea->bottom = 0;
|
||||
|
||||
HMONITOR hMonitor = MonitorFromPoint(ptPoint, MONITOR_DEFAULTTONEAREST);
|
||||
if (hMonitor)
|
||||
{
|
||||
MONITORINFO MonitorInfo = {0};
|
||||
|
||||
MonitorInfo.cbSize = sizeof(MONITORINFO);
|
||||
if (GetMonitorInfo(hMonitor, &MonitorInfo))
|
||||
{
|
||||
*lprcWorkArea = MonitorInfo.rcWork;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SystemParametersInfo(SPI_GETWORKAREA, 0, lprcWorkArea, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
BOOL CBaseWindow::_IsTimer()
|
||||
{
|
||||
CBaseWindow* pobj = _GetTopmostUIWnd();
|
||||
if (pobj != nullptr)
|
||||
{
|
||||
return (pobj->_pTimerUIObj != nullptr);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL CBaseWindow::_IsCapture()
|
||||
{
|
||||
CBaseWindow* pobj = _GetTopmostUIWnd();
|
||||
if (pobj != nullptr)
|
||||
{
|
||||
return (pobj->_pUIObjCapture != nullptr);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CBaseWindow* CBaseWindow::_GetTopmostUIWnd()
|
||||
{
|
||||
CBaseWindow* pobj = this;
|
||||
|
||||
while (pobj->_pParentWnd != nullptr)
|
||||
{
|
||||
pobj = pobj->_pParentWnd;
|
||||
}
|
||||
|
||||
return pobj->_pUIWnd;
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#define RECT_INSIDE (0x0001)
|
||||
#define RECT_OVER_LEFT (0x0002)
|
||||
#define RECT_OVER_TOP (0x0004)
|
||||
#define RECT_OVER_RIGHT (0x0008)
|
||||
#define RECT_OVER_BOTTOM (0x0010)
|
||||
#define RECT_TOO_WIDE (0x0020)
|
||||
#define RECT_TOO_TALL (0x0040)
|
||||
#define RECT_ERROR (0x0080)
|
||||
|
||||
class CStringRange;
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CBaseWindow
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class CBaseWindow
|
||||
{
|
||||
public:
|
||||
CBaseWindow();
|
||||
virtual ~CBaseWindow();
|
||||
|
||||
static BOOL _InitWindowClass(_In_ LPCWSTR lpwszClassName, _Out_ ATOM *patom);
|
||||
static void _UninitWindowClass(ATOM atom);
|
||||
|
||||
virtual BOOL _Create(ATOM atom, DWORD dwExStyle, DWORD dwStyle, _In_opt_ CBaseWindow *pParentWnd = nullptr, int wndWidth = 0, int wndHeight = 0, _In_opt_ HWND parentWndHandle = nullptr);
|
||||
virtual void _Destroy();
|
||||
|
||||
virtual void _Move(int x, int y);
|
||||
virtual void _Resize(int x, int y, int cx, int cy);
|
||||
virtual void _Show(BOOL isShowWnd);
|
||||
virtual BOOL _IsWindowVisible();
|
||||
virtual void _Enable(BOOL enableWindowReceiveInput);
|
||||
virtual BOOL _IsEnabled();
|
||||
virtual void _InvalidateRect();
|
||||
virtual BOOL _GetWindowRect(_Inout_ LPRECT lpRect);
|
||||
virtual BOOL _GetClientRect(_Inout_ LPRECT lpRect);
|
||||
|
||||
virtual LRESULT CALLBACK _WindowProcCallback(_In_ HWND wndHandle, UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam) = 0;
|
||||
virtual void _OnPaint(_In_ HDC dcHandle, _In_ PAINTSTRUCT *pps) { dcHandle; pps; }
|
||||
virtual void _OnLButtonDown(POINT pt) { pt; }
|
||||
virtual void _OnLButtonUp(POINT pt) { pt; }
|
||||
virtual void _OnMouseMove(POINT pt) { pt; }
|
||||
virtual void _OnTimer() { }
|
||||
|
||||
CBaseWindow* _GetTopmostUIWnd();
|
||||
|
||||
HRESULT _GetWindowExtent(_In_ const RECT *prcTextExtent, _In_opt_ RECT *prcCandidateExtent, _Inout_ POINT *pptCandidate);
|
||||
|
||||
HWND _GetWnd()
|
||||
{
|
||||
return _wndHandle;
|
||||
}
|
||||
|
||||
CBaseWindow *_GetParent()
|
||||
{
|
||||
return _pParentWnd;
|
||||
}
|
||||
|
||||
void _SetUIWnd(_In_ CBaseWindow *pUIWnd)
|
||||
{
|
||||
_pUIWnd = pUIWnd;
|
||||
}
|
||||
|
||||
CBaseWindow* _GetUIWnd()
|
||||
{
|
||||
return _pUIWnd;
|
||||
}
|
||||
|
||||
CBaseWindow *_GetCaptureObject()
|
||||
{
|
||||
return _pUIObjCapture;
|
||||
}
|
||||
|
||||
CBaseWindow *_GetTimerObject()
|
||||
{
|
||||
return _pTimerUIObj;
|
||||
}
|
||||
|
||||
UINT _GetScrollDelay()
|
||||
{
|
||||
return (GetDoubleClickTime() * 4 / 5);
|
||||
}
|
||||
|
||||
UINT _GetScrollSpeed()
|
||||
{
|
||||
return (_GetScrollDelay() / 8);
|
||||
}
|
||||
|
||||
protected:
|
||||
LRESULT _NotifyCommand(UINT uMsg, DWORD dwSB, int nPos);
|
||||
|
||||
void _StartCapture()
|
||||
{
|
||||
_SetCaptureObject(this);
|
||||
}
|
||||
|
||||
void _EndCapture()
|
||||
{
|
||||
_SetCaptureObject(nullptr);
|
||||
}
|
||||
|
||||
BOOL _IsCapture();
|
||||
|
||||
void _StartTimer(UINT uElapse)
|
||||
{
|
||||
_SetTimerObject(this, uElapse);
|
||||
}
|
||||
|
||||
void _EndTimer()
|
||||
{
|
||||
_SetTimerObject(nullptr);
|
||||
}
|
||||
|
||||
BOOL _IsTimer();
|
||||
|
||||
private:
|
||||
void _SetCaptureObject(_In_opt_ CBaseWindow *pUIObj);
|
||||
void _SetTimerObject(_In_opt_ CBaseWindow *pUIObj, UINT uElapse = 0);
|
||||
|
||||
void GetWorkAreaFromPoint(_In_ const POINT& ptPoint, _Out_ LPRECT lprcWorkArea);
|
||||
void CalcFitPointAroundTextExtent(_In_ const RECT *prcTextExtent, _In_ const RECT *prcWorkArea, _In_ const RECT *prcWindow, _Out_ POINT *ppt);
|
||||
DWORD RectInRect(_In_ const RECT *prcLimit, _In_ const RECT *prcTarget);
|
||||
|
||||
static LRESULT CALLBACK _WindowProc(_In_ HWND wndHandle, UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam);
|
||||
|
||||
static CBaseWindow *_GetThis(_In_ HWND wndHandle)
|
||||
{
|
||||
return (CBaseWindow *)GetWindowLongPtr(wndHandle, GWLP_USERDATA);
|
||||
}
|
||||
|
||||
static void _SetThis(_In_ HWND wndHandle, _In_opt_ void *lpv)
|
||||
{
|
||||
SetWindowLongPtr(wndHandle, GWLP_USERDATA, (LONG_PTR)lpv);
|
||||
}
|
||||
|
||||
private:
|
||||
HWND _wndHandle;
|
||||
|
||||
CBaseWindow *_pParentWnd;
|
||||
CBaseWindow *_pUIWnd;
|
||||
|
||||
CBaseWindow *_pTimerUIObj;
|
||||
CBaseWindow *_pUIObjCapture;
|
||||
|
||||
BOOL _enableVirtualWnd;
|
||||
BOOL _visibleVirtualWnd;
|
||||
RECT _RectOfVirtualWnd;
|
||||
};
|
||||
@@ -0,0 +1,90 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "BaseWindow.h"
|
||||
#include "ButtonWindow.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CButtonWindow
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CButtonWindow::CButtonWindow()
|
||||
{
|
||||
typeOfControl = 0;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ~CButtonWindow
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CButtonWindow::~CButtonWindow()
|
||||
{
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _OnPaint
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CButtonWindow::_OnPaint(_In_ HDC dcHandle, _In_ PAINTSTRUCT *pps)
|
||||
{
|
||||
dcHandle;
|
||||
pps;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _OnLButtonDown
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CButtonWindow::_OnLButtonDown(POINT pt)
|
||||
{
|
||||
pt;
|
||||
|
||||
typeOfControl = DFCS_PUSHED;
|
||||
_StartCapture();
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _WindowProcCallback
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
LRESULT CALLBACK CButtonWindow::_WindowProcCallback(_In_ HWND wndHandle, UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam)
|
||||
{
|
||||
wndHandle;
|
||||
uMsg;
|
||||
wParam;
|
||||
lParam;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _OnLButtonUp
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CButtonWindow::_OnLButtonUp(POINT pt)
|
||||
{
|
||||
pt;
|
||||
|
||||
if (_IsCapture())
|
||||
{
|
||||
_EndCapture();
|
||||
}
|
||||
|
||||
typeOfControl = 0;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BaseWindow.h"
|
||||
|
||||
class CButtonWindow : public CBaseWindow
|
||||
{
|
||||
public:
|
||||
CButtonWindow();
|
||||
virtual ~CButtonWindow();
|
||||
|
||||
LRESULT CALLBACK _WindowProcCallback(_In_ HWND wndHandle, UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam);
|
||||
|
||||
virtual void _OnPaint(_In_ HDC dcHandle, _In_ PAINTSTRUCT *pps);
|
||||
virtual void _OnLButtonDown(POINT pt);
|
||||
virtual void _OnLButtonUp(POINT pt);
|
||||
|
||||
protected:
|
||||
UINT typeOfControl; // DFCS_PUSHED, DFCS_INACTIVE or others for DrawFrameControl
|
||||
};
|
||||
@@ -0,0 +1,85 @@
|
||||
"./ActiveLanguageProfileNotifySink.cpp"
|
||||
"./BaseDictionaryEngine.cpp"
|
||||
"./BaseDictionaryEngine.h"
|
||||
"./BaseWindow.cpp"
|
||||
"./BaseWindow.h"
|
||||
"./ButtonWindow.cpp"
|
||||
"./ButtonWindow.h"
|
||||
"./CandidateListUIPresenter.cpp"
|
||||
"./CandidateListUIPresenter.h"
|
||||
"./CandidateWindow.cpp"
|
||||
"./CandidateWindow.h"
|
||||
"./Compartment.cpp"
|
||||
"./Compartment.h"
|
||||
"./Composition.cpp"
|
||||
"./CompositionProcessorEngine.cpp"
|
||||
"./CompositionProcessorEngine.h"
|
||||
"./Define.h"
|
||||
"./DictionaryParser.cpp"
|
||||
"./DictionaryParser.h"
|
||||
"./DictionarySearch.cpp"
|
||||
"./DictionarySearch.h"
|
||||
"./DisplayAttribute.cpp"
|
||||
"./DisplayAttributeInfo.cpp"
|
||||
"./DisplayAttributeInfo.h"
|
||||
"./DisplayAttributeProvider.cpp"
|
||||
"./DisplayString.h"
|
||||
"./DllMain.cpp"
|
||||
"./EditSession.cpp"
|
||||
"./EditSession.h"
|
||||
"./EndComposition.cpp"
|
||||
"./EnumDisplayAttributeInfo.cpp"
|
||||
"./EnumDisplayAttributeInfo.h"
|
||||
"./EnumTfCandidates.cpp"
|
||||
"./EnumTfCandidates.h"
|
||||
"./File.cpp"
|
||||
"./File.h"
|
||||
"./FileMapping.cpp"
|
||||
"./FileMapping.h"
|
||||
"./FunctionProviderSink.cpp"
|
||||
"./GetTextExtentEditSession.cpp"
|
||||
"./GetTextExtentEditSession.h"
|
||||
"./Globals.cpp"
|
||||
"./Globals.h"
|
||||
"./KeyEventSink.cpp"
|
||||
"./KeyHandler.cpp"
|
||||
"./KeyHandlerEditSession.cpp"
|
||||
"./KeyHandlerEditSession.h"
|
||||
"./KeyStateCategory.cpp"
|
||||
"./KeyStateCategory.h"
|
||||
"./LanguageBar.cpp"
|
||||
"./LanguageBar.h"
|
||||
"./Private.h"
|
||||
"./Register.cpp"
|
||||
"./RegKey.cpp"
|
||||
"./RegKey.h"
|
||||
"./resource.h"
|
||||
"./SampleIME.cpp"
|
||||
"./SampleIME.def"
|
||||
"./SampleIME.h"
|
||||
"./SampleIME.rc"
|
||||
"./SampleIMEBaseStructure.cpp"
|
||||
"./SampleIMEBaseStructure.h"
|
||||
"./SampleIMEStructureArray.h"
|
||||
"./ScrollBarWindow.cpp"
|
||||
"./ScrollBarWindow.h"
|
||||
"./SearchCandidateProvider.cpp"
|
||||
"./SearchCandidateProvider.h"
|
||||
"./Server.cpp"
|
||||
"./ShadowWindow.cpp"
|
||||
"./ShadowWindow.h"
|
||||
"./StartComposition.cpp"
|
||||
"./stdafx.h"
|
||||
"./TableDictionaryEngine.cpp"
|
||||
"./TableDictionaryEngine.h"
|
||||
"./TextEditSink.cpp"
|
||||
"./TfInputProcessorProfile.cpp"
|
||||
"./TfInputProcessorProfile.h"
|
||||
"./TfTextLayoutSink.cpp"
|
||||
"./TfTextLayoutSink.h"
|
||||
"./ThreadFocusSink.cpp"
|
||||
"./ThreadMgrEventSink.cpp"
|
||||
"./TipCandidateList.cpp"
|
||||
"./TipCandidateList.h"
|
||||
"./TipCandidateString.cpp"
|
||||
"./TipCandidateString.h"
|
||||
@@ -0,0 +1,98 @@
|
||||
cmake_minimum_required(VERSION 3.25.0)
|
||||
|
||||
project(fanytsfime)
|
||||
|
||||
# http://www.utf8everywhere.org/
|
||||
add_definitions(
|
||||
/D_UNICODE=1
|
||||
/DUNICODE=1
|
||||
)
|
||||
|
||||
add_library(SampleIME SHARED
|
||||
"./ActiveLanguageProfileNotifySink.cpp"
|
||||
"./BaseDictionaryEngine.cpp"
|
||||
"./BaseDictionaryEngine.h"
|
||||
"./BaseWindow.cpp"
|
||||
"./BaseWindow.h"
|
||||
"./ButtonWindow.cpp"
|
||||
"./ButtonWindow.h"
|
||||
"./CandidateListUIPresenter.cpp"
|
||||
"./CandidateListUIPresenter.h"
|
||||
"./CandidateWindow.cpp"
|
||||
"./CandidateWindow.h"
|
||||
"./Compartment.cpp"
|
||||
"./Compartment.h"
|
||||
"./Composition.cpp"
|
||||
"./CompositionProcessorEngine.cpp"
|
||||
"./CompositionProcessorEngine.h"
|
||||
"./Define.h"
|
||||
"./DictionaryParser.cpp"
|
||||
"./DictionaryParser.h"
|
||||
"./DictionarySearch.cpp"
|
||||
"./DictionarySearch.h"
|
||||
"./DisplayAttribute.cpp"
|
||||
"./DisplayAttributeInfo.cpp"
|
||||
"./DisplayAttributeInfo.h"
|
||||
"./DisplayAttributeProvider.cpp"
|
||||
"./DisplayString.h"
|
||||
"./DllMain.cpp"
|
||||
"./EditSession.cpp"
|
||||
"./EditSession.h"
|
||||
"./EndComposition.cpp"
|
||||
"./EnumDisplayAttributeInfo.cpp"
|
||||
"./EnumDisplayAttributeInfo.h"
|
||||
"./EnumTfCandidates.cpp"
|
||||
"./EnumTfCandidates.h"
|
||||
"./File.cpp"
|
||||
"./File.h"
|
||||
"./FileMapping.cpp"
|
||||
"./FileMapping.h"
|
||||
"./FunctionProviderSink.cpp"
|
||||
"./GetTextExtentEditSession.cpp"
|
||||
"./GetTextExtentEditSession.h"
|
||||
"./Globals.cpp"
|
||||
"./Globals.h"
|
||||
"./KeyEventSink.cpp"
|
||||
"./KeyHandler.cpp"
|
||||
"./KeyHandlerEditSession.cpp"
|
||||
"./KeyHandlerEditSession.h"
|
||||
"./KeyStateCategory.cpp"
|
||||
"./KeyStateCategory.h"
|
||||
"./LanguageBar.cpp"
|
||||
"./LanguageBar.h"
|
||||
"./Private.h"
|
||||
"./Register.cpp"
|
||||
"./RegKey.cpp"
|
||||
"./RegKey.h"
|
||||
"./resource.h"
|
||||
"./SampleIME.cpp"
|
||||
"./SampleIME.def"
|
||||
"./SampleIME.h"
|
||||
"./SampleIME.rc"
|
||||
"./SampleIMEBaseStructure.cpp"
|
||||
"./SampleIMEBaseStructure.h"
|
||||
"./SampleIMEStructureArray.h"
|
||||
"./ScrollBarWindow.cpp"
|
||||
"./ScrollBarWindow.h"
|
||||
"./SearchCandidateProvider.cpp"
|
||||
"./SearchCandidateProvider.h"
|
||||
"./Server.cpp"
|
||||
"./ShadowWindow.cpp"
|
||||
"./ShadowWindow.h"
|
||||
"./StartComposition.cpp"
|
||||
"./stdafx.h"
|
||||
"./TableDictionaryEngine.cpp"
|
||||
"./TableDictionaryEngine.h"
|
||||
"./TextEditSink.cpp"
|
||||
"./TfInputProcessorProfile.cpp"
|
||||
"./TfInputProcessorProfile.h"
|
||||
"./TfTextLayoutSink.cpp"
|
||||
"./TfTextLayoutSink.h"
|
||||
"./ThreadFocusSink.cpp"
|
||||
"./ThreadMgrEventSink.cpp"
|
||||
"./TipCandidateList.cpp"
|
||||
"./TipCandidateList.h"
|
||||
"./TipCandidateString.cpp"
|
||||
"./TipCandidateString.h"
|
||||
)
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "KeyHandlerEditSession.h"
|
||||
#include "CandidateWindow.h"
|
||||
#include "TfTextLayoutSink.h"
|
||||
#include "SampleIME.h"
|
||||
#include "SampleIMEBaseStructure.h"
|
||||
|
||||
class CReadingLine;
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CCandidateListUIPresenter
|
||||
//
|
||||
// ITfCandidateListUIElement / ITfIntegratableCandidateListUIElement is used for
|
||||
// UILess mode support
|
||||
// ITfCandidateListUIElementBehavior sends the Selection behavior message to
|
||||
// 3rd party IME.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class CCandidateListUIPresenter : public CTfTextLayoutSink,
|
||||
public ITfCandidateListUIElementBehavior,
|
||||
public ITfIntegratableCandidateListUIElement
|
||||
{
|
||||
public:
|
||||
CCandidateListUIPresenter(_In_ CSampleIME *pTextService, ATOM atom,
|
||||
KEYSTROKE_CATEGORY Category,
|
||||
_In_ CCandidateRange *pIndexRange,
|
||||
BOOL hideWindow);
|
||||
virtual ~CCandidateListUIPresenter();
|
||||
|
||||
// IUnknown
|
||||
STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj);
|
||||
STDMETHODIMP_(ULONG) AddRef(void);
|
||||
STDMETHODIMP_(ULONG) Release(void);
|
||||
|
||||
// ITfUIElement
|
||||
STDMETHODIMP GetDescription(BSTR *pbstr);
|
||||
STDMETHODIMP GetGUID(GUID *pguid);
|
||||
STDMETHODIMP Show(BOOL showCandidateWindow);
|
||||
STDMETHODIMP IsShown(BOOL *pIsShow);
|
||||
|
||||
// ITfCandidateListUIElement
|
||||
STDMETHODIMP GetUpdatedFlags(DWORD *pdwFlags);
|
||||
STDMETHODIMP GetDocumentMgr(ITfDocumentMgr **ppdim);
|
||||
STDMETHODIMP GetCount(UINT *pCandidateCount);
|
||||
STDMETHODIMP GetSelection(UINT *pSelectedCandidateIndex);
|
||||
STDMETHODIMP GetString(UINT uIndex, BSTR *pbstr);
|
||||
STDMETHODIMP GetPageIndex(UINT *pIndex, UINT uSize, UINT *puPageCnt);
|
||||
STDMETHODIMP SetPageIndex(UINT *pIndex, UINT uPageCnt);
|
||||
STDMETHODIMP GetCurrentPage(UINT *puPage);
|
||||
|
||||
// ITfCandidateListUIElementBehavior methods
|
||||
STDMETHODIMP SetSelection(UINT nIndex);
|
||||
STDMETHODIMP Finalize(void);
|
||||
STDMETHODIMP Abort(void);
|
||||
|
||||
// ITfIntegratableCandidateListUIElement
|
||||
STDMETHODIMP SetIntegrationStyle(GUID guidIntegrationStyle);
|
||||
STDMETHODIMP GetSelectionStyle(_Out_ TfIntegratableCandidateListSelectionStyle *ptfSelectionStyle);
|
||||
STDMETHODIMP OnKeyDown(_In_ WPARAM wParam, _In_ LPARAM lParam, _Out_ BOOL *pIsEaten);
|
||||
STDMETHODIMP ShowCandidateNumbers(_Out_ BOOL *pIsShow);
|
||||
STDMETHODIMP FinalizeExactCompositionString();
|
||||
|
||||
virtual HRESULT _StartCandidateList(TfClientId tfClientId, _In_ ITfDocumentMgr *pDocumentMgr, _In_ ITfContext *pContextDocument, TfEditCookie ec, _In_ ITfRange *pRangeComposition, UINT wndWidth);
|
||||
void _EndCandidateList();
|
||||
|
||||
void _SetText(_In_ CSampleImeArray<CCandidateListItem> *pCandidateList, BOOL isAddFindKeyCode);
|
||||
void _ClearList();
|
||||
VOID _SetTextColor(COLORREF crColor, COLORREF crBkColor);
|
||||
VOID _SetFillColor(HBRUSH hBrush);
|
||||
|
||||
DWORD_PTR _GetSelectedCandidateString(_Outptr_result_maybenull_ const WCHAR **ppwchCandidateString);
|
||||
BOOL _SetSelectionInPage(int nPos) { return _pCandidateWnd->_SetSelectionInPage(nPos); }
|
||||
|
||||
BOOL _MoveSelection(_In_ int offSet);
|
||||
BOOL _SetSelection(_In_ int selectedIndex);
|
||||
BOOL _MovePage(_In_ int offSet);
|
||||
|
||||
void _MoveWindowToTextExt();
|
||||
|
||||
// CTfTextLayoutSink
|
||||
virtual VOID _LayoutChangeNotification(_In_ RECT *lpRect);
|
||||
virtual VOID _LayoutDestroyNotification();
|
||||
|
||||
// Event for ITfThreadFocusSink
|
||||
virtual HRESULT OnSetThreadFocus();
|
||||
virtual HRESULT OnKillThreadFocus();
|
||||
|
||||
void RemoveSpecificCandidateFromList(_In_ LCID Locale, _Inout_ CSampleImeArray<CCandidateListItem> &candidateList, _In_ CStringRange &srgCandidateString);
|
||||
void AdviseUIChangedByArrowKey(_In_ KEYSTROKE_FUNCTION arrowKey);
|
||||
|
||||
private:
|
||||
virtual HRESULT CALLBACK _CandidateChangeNotification(_In_ enum CANDWND_ACTION action);
|
||||
|
||||
static HRESULT _CandWndCallback(_In_ void *pv, _In_ enum CANDWND_ACTION action);
|
||||
|
||||
friend COLORREF _AdjustTextColor(_In_ COLORREF crColor, _In_ COLORREF crBkColor);
|
||||
|
||||
HRESULT _UpdateUIElement();
|
||||
|
||||
HRESULT ToShowCandidateWindow();
|
||||
|
||||
HRESULT ToHideCandidateWindow();
|
||||
|
||||
HRESULT BeginUIElement();
|
||||
HRESULT EndUIElement();
|
||||
|
||||
HRESULT MakeCandidateWindow(_In_ ITfContext *pContextDocument, _In_ UINT wndWidth);
|
||||
void DisposeCandidateWindow();
|
||||
|
||||
void AddCandidateToCandidateListUI(_In_ CSampleImeArray<CCandidateListItem> *pCandidateList, BOOL isAddFindKeyCode);
|
||||
|
||||
void SetPageIndexWithScrollInfo(_In_ CSampleImeArray<CCandidateListItem> *pCandidateList);
|
||||
|
||||
protected:
|
||||
CCandidateWindow *_pCandidateWnd;
|
||||
BOOL _isShowMode;
|
||||
BOOL _hideWindow;
|
||||
|
||||
private:
|
||||
|
||||
HWND _parentWndHandle;
|
||||
ATOM _atom;
|
||||
CCandidateRange* _pIndexRange;
|
||||
KEYSTROKE_CATEGORY _Category;
|
||||
DWORD _updatedFlags;
|
||||
DWORD _uiElementId;
|
||||
CSampleIME* _pTextService;
|
||||
LONG _refCount;
|
||||
};
|
||||
@@ -0,0 +1,118 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "private.h"
|
||||
#include "BaseWindow.h"
|
||||
#include "ShadowWindow.h"
|
||||
#include "ScrollBarWindow.h"
|
||||
#include "SampleIMEBaseStructure.h"
|
||||
|
||||
enum CANDWND_ACTION
|
||||
{
|
||||
CAND_ITEM_SELECT
|
||||
};
|
||||
|
||||
typedef HRESULT (*CANDWNDCALLBACK)(void *pv, enum CANDWND_ACTION action);
|
||||
|
||||
class CCandidateWindow : public CBaseWindow
|
||||
{
|
||||
public:
|
||||
CCandidateWindow(_In_ CANDWNDCALLBACK pfnCallback, _In_ void *pv, _In_ CCandidateRange *pIndexRange, _In_ BOOL isStoreAppMode);
|
||||
virtual ~CCandidateWindow();
|
||||
|
||||
BOOL _Create(ATOM atom, _In_ UINT wndWidth, _In_opt_ HWND parentWndHandle);
|
||||
|
||||
void _Move(int x, int y);
|
||||
void _Show(BOOL isShowWnd);
|
||||
|
||||
VOID _SetTextColor(_In_ COLORREF crColor, _In_ COLORREF crBkColor);
|
||||
VOID _SetFillColor(_In_ HBRUSH hBrush);
|
||||
|
||||
LRESULT CALLBACK _WindowProcCallback(_In_ HWND wndHandle, UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam);
|
||||
void _OnPaint(_In_ HDC dcHandle, _In_ PAINTSTRUCT *pps);
|
||||
void _OnLButtonDown(POINT pt);
|
||||
void _OnLButtonUp(POINT pt);
|
||||
void _OnMouseMove(POINT pt);
|
||||
void _OnVScroll(DWORD dwSB, _In_ DWORD nPos);
|
||||
|
||||
void _AddString(_Inout_ CCandidateListItem *pCandidateItem, _In_ BOOL isAddFindKeyCode);
|
||||
void _ClearList();
|
||||
UINT _GetCount()
|
||||
{
|
||||
return _candidateList.Count();
|
||||
}
|
||||
UINT _GetSelection()
|
||||
{
|
||||
return _currentSelection;
|
||||
}
|
||||
void _SetScrollInfo(_In_ int nMax, _In_ int nPage);
|
||||
|
||||
DWORD _GetCandidateString(_In_ int iIndex, _Outptr_result_maybenull_z_ const WCHAR **ppwchCandidateString);
|
||||
DWORD _GetSelectedCandidateString(_Outptr_result_maybenull_ const WCHAR **ppwchCandidateString);
|
||||
|
||||
BOOL _MoveSelection(_In_ int offSet, _In_ BOOL isNotify);
|
||||
BOOL _SetSelection(_In_ int iPage, _In_ BOOL isNotify);
|
||||
void _SetSelection(_In_ int nIndex);
|
||||
BOOL _MovePage(_In_ int offSet, _In_ BOOL isNotify);
|
||||
BOOL _SetSelectionInPage(int nPos);
|
||||
|
||||
HRESULT _GetPageIndex(UINT *pIndex, _In_ UINT uSize, _Inout_ UINT *puPageCnt);
|
||||
HRESULT _SetPageIndex(UINT *pIndex, _In_ UINT uPageCnt);
|
||||
HRESULT _GetCurrentPage(_Inout_ UINT *pCurrentPage);
|
||||
HRESULT _GetCurrentPage(_Inout_ int *pCurrentPage);
|
||||
|
||||
private:
|
||||
void _HandleMouseMsg(_In_ UINT mouseMsg, _In_ POINT point);
|
||||
void _DrawList(_In_ HDC dcHandle, _In_ UINT iIndex, _In_ RECT *prc);
|
||||
void _DrawBorder(_In_ HWND wndHandle, _In_ int cx);
|
||||
BOOL _SetSelectionOffset(_In_ int offSet);
|
||||
BOOL _AdjustPageIndexForSelection();
|
||||
HRESULT _CurrentPageHasEmptyItems(_Inout_ BOOL *pfHasEmptyItems);
|
||||
|
||||
// LightDismiss feature support, it will fire messages lightdismiss-related to the light dismiss layout.
|
||||
void _FireMessageToLightDismiss(_In_ HWND wndHandle, _In_ WINDOWPOS *pWndPos);
|
||||
|
||||
BOOL _CreateMainWindow(ATOM atom, _In_opt_ HWND parentWndHandle);
|
||||
BOOL _CreateBackGroundShadowWindow();
|
||||
BOOL _CreateVScrollWindow();
|
||||
|
||||
HRESULT _AdjustPageIndex(_Inout_ UINT & currentPage, _Inout_ UINT & currentPageIndex);
|
||||
|
||||
void _ResizeWindow();
|
||||
void _DeleteShadowWnd();
|
||||
void _DeleteVScrollBarWnd();
|
||||
|
||||
friend COLORREF _AdjustTextColor(_In_ COLORREF crColor, _In_ COLORREF crBkColor);
|
||||
|
||||
private:
|
||||
UINT _currentSelection;
|
||||
CSampleImeArray<CCandidateListItem> _candidateList;
|
||||
CSampleImeArray<UINT> _PageIndex;
|
||||
|
||||
COLORREF _crTextColor;
|
||||
COLORREF _crBkColor;
|
||||
HBRUSH _brshBkColor;
|
||||
|
||||
TEXTMETRIC _TextMetric;
|
||||
int _cyRow;
|
||||
int _cxTitle;
|
||||
UINT _wndWidth;
|
||||
|
||||
CCandidateRange* _pIndexRange;
|
||||
|
||||
CANDWNDCALLBACK _pfnCallback;
|
||||
void* _pObj;
|
||||
|
||||
CShadowWindow* _pShadowWnd;
|
||||
CScrollBarWindow* _pVScrollBarWnd;
|
||||
|
||||
BOOL _dontAdjustOnEmptyItemPage;
|
||||
BOOL _isStoreAppMode;
|
||||
};
|
||||
@@ -0,0 +1,343 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#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)
|
||||
{
|
||||
_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)
|
||||
{
|
||||
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();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _Unadvise
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CCompartmentEventSink::_Unadvise()
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
ITfSource* pSource = nullptr;
|
||||
|
||||
hr = _pCompartment->QueryInterface(IID_ITfSource, (void **)&pSource);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pSource->UnadviseSink(_dwCookie);
|
||||
pSource->Release();
|
||||
}
|
||||
|
||||
_pCompartment->Release();
|
||||
_pCompartment = nullptr;
|
||||
_dwCookie = 0;
|
||||
|
||||
return hr;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#pragma once
|
||||
|
||||
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;
|
||||
};
|
||||
@@ -0,0 +1,377 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "SampleIME.h"
|
||||
#include "CompositionProcessorEngine.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfCompositionSink::OnCompositionTerminated
|
||||
//
|
||||
// Callback for ITfCompositionSink. The system calls this method whenever
|
||||
// someone other than this service ends a composition.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CSampleIME::OnCompositionTerminated(TfEditCookie ecWrite, _In_ ITfComposition *pComposition)
|
||||
{
|
||||
// Clear dummy composition
|
||||
_RemoveDummyCompositionForComposing(ecWrite, pComposition);
|
||||
|
||||
// Clear display attribute and end composition, _EndComposition will release composition for us
|
||||
ITfContext* pContext = _pContext;
|
||||
if (pContext)
|
||||
{
|
||||
pContext->AddRef();
|
||||
}
|
||||
|
||||
_EndComposition(_pContext);
|
||||
|
||||
_DeleteCandidateList(FALSE, pContext);
|
||||
|
||||
if (pContext)
|
||||
{
|
||||
pContext->Release();
|
||||
pContext = nullptr;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _IsComposing
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CSampleIME::_IsComposing()
|
||||
{
|
||||
return _pComposition != nullptr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _SetComposition
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CSampleIME::_SetComposition(_In_ ITfComposition *pComposition)
|
||||
{
|
||||
_pComposition = pComposition;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _AddComposingAndChar
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_AddComposingAndChar(TfEditCookie ec, _In_ ITfContext *pContext, _In_ CStringRange *pstrAddString)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
ULONG fetched = 0;
|
||||
TF_SELECTION tfSelection;
|
||||
|
||||
if (pContext->GetSelection(ec, TF_DEFAULT_SELECTION, 1, &tfSelection, &fetched) != S_OK || fetched == 0)
|
||||
return S_FALSE;
|
||||
|
||||
//
|
||||
// make range start to selection
|
||||
//
|
||||
ITfRange* pAheadSelection = nullptr;
|
||||
hr = pContext->GetStart(ec, &pAheadSelection);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pAheadSelection->ShiftEndToRange(ec, tfSelection.range, TF_ANCHOR_START);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ITfRange* pRange = nullptr;
|
||||
BOOL exist_composing = _FindComposingRange(ec, pContext, pAheadSelection, &pRange);
|
||||
|
||||
_SetInputString(ec, pContext, pRange, pstrAddString, exist_composing);
|
||||
|
||||
if (pRange)
|
||||
{
|
||||
pRange->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tfSelection.range->Release();
|
||||
|
||||
if (pAheadSelection)
|
||||
{
|
||||
pAheadSelection->Release();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _AddCharAndFinalize
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_AddCharAndFinalize(TfEditCookie ec, _In_ ITfContext *pContext, _In_ CStringRange *pstrAddString)
|
||||
{
|
||||
HRESULT hr = E_FAIL;
|
||||
|
||||
ULONG fetched = 0;
|
||||
TF_SELECTION tfSelection;
|
||||
|
||||
if ((hr = pContext->GetSelection(ec, TF_DEFAULT_SELECTION, 1, &tfSelection, &fetched)) != S_OK || fetched != 1)
|
||||
return hr;
|
||||
|
||||
// we use SetText here instead of InsertTextAtSelection because we've already started a composition
|
||||
// we don't want to the app to adjust the insertion point inside our composition
|
||||
hr = tfSelection.range->SetText(ec, 0, pstrAddString->Get(), (LONG)pstrAddString->GetLength());
|
||||
if (hr == S_OK)
|
||||
{
|
||||
// update the selection, we'll make it an insertion point just past
|
||||
// the inserted text.
|
||||
tfSelection.range->Collapse(ec, TF_ANCHOR_END);
|
||||
pContext->SetSelection(ec, 1, &tfSelection);
|
||||
}
|
||||
|
||||
tfSelection.range->Release();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _FindComposingRange
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CSampleIME::_FindComposingRange(TfEditCookie ec, _In_ ITfContext *pContext, _In_ ITfRange *pSelection, _Outptr_result_maybenull_ ITfRange **ppRange)
|
||||
{
|
||||
if (ppRange == nullptr)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*ppRange = nullptr;
|
||||
|
||||
// find GUID_PROP_COMPOSING
|
||||
ITfProperty* pPropComp = nullptr;
|
||||
IEnumTfRanges* enumComp = nullptr;
|
||||
|
||||
HRESULT hr = pContext->GetProperty(GUID_PROP_COMPOSING, &pPropComp);
|
||||
if (FAILED(hr) || pPropComp == nullptr)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hr = pPropComp->EnumRanges(ec, &enumComp, pSelection);
|
||||
if (FAILED(hr) || enumComp == nullptr)
|
||||
{
|
||||
pPropComp->Release();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL isCompExist = FALSE;
|
||||
VARIANT var;
|
||||
ULONG fetched = 0;
|
||||
|
||||
while (enumComp->Next(1, ppRange, &fetched) == S_OK && fetched == 1)
|
||||
{
|
||||
hr = pPropComp->GetValue(ec, *ppRange, &var);
|
||||
if (hr == S_OK)
|
||||
{
|
||||
if (var.vt == VT_I4 && var.lVal != 0)
|
||||
{
|
||||
isCompExist = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
(*ppRange)->Release();
|
||||
*ppRange = nullptr;
|
||||
}
|
||||
|
||||
pPropComp->Release();
|
||||
enumComp->Release();
|
||||
|
||||
return isCompExist;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _SetInputString
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_SetInputString(TfEditCookie ec, _In_ ITfContext *pContext, _Out_opt_ ITfRange *pRange, _In_ CStringRange *pstrAddString, BOOL exist_composing)
|
||||
{
|
||||
ITfRange* pRangeInsert = nullptr;
|
||||
if (!exist_composing)
|
||||
{
|
||||
_InsertAtSelection(ec, pContext, pstrAddString, &pRangeInsert);
|
||||
if (pRangeInsert == nullptr)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
pRange = pRangeInsert;
|
||||
}
|
||||
if (pRange != nullptr)
|
||||
{
|
||||
pRange->SetText(ec, 0, pstrAddString->Get(), (LONG)pstrAddString->GetLength());
|
||||
}
|
||||
|
||||
_SetCompositionLanguage(ec, pContext);
|
||||
|
||||
_SetCompositionDisplayAttributes(ec, pContext, _gaDisplayAttributeInput);
|
||||
|
||||
// update the selection, we'll make it an insertion point just past
|
||||
// the inserted text.
|
||||
ITfRange* pSelection = nullptr;
|
||||
TF_SELECTION sel;
|
||||
|
||||
if ((pRange != nullptr) && (pRange->Clone(&pSelection) == S_OK))
|
||||
{
|
||||
pSelection->Collapse(ec, TF_ANCHOR_END);
|
||||
|
||||
sel.range = pSelection;
|
||||
sel.style.ase = TF_AE_NONE;
|
||||
sel.style.fInterimChar = FALSE;
|
||||
pContext->SetSelection(ec, 1, &sel);
|
||||
pSelection->Release();
|
||||
}
|
||||
|
||||
if (pRangeInsert)
|
||||
{
|
||||
pRangeInsert->Release();
|
||||
}
|
||||
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _InsertAtSelection
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_InsertAtSelection(TfEditCookie ec, _In_ ITfContext *pContext, _In_ CStringRange *pstrAddString, _Outptr_ ITfRange **ppCompRange)
|
||||
{
|
||||
ITfRange* rangeInsert = nullptr;
|
||||
ITfInsertAtSelection* pias = nullptr;
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (ppCompRange == nullptr)
|
||||
{
|
||||
hr = E_INVALIDARG;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
*ppCompRange = nullptr;
|
||||
|
||||
hr = pContext->QueryInterface(IID_ITfInsertAtSelection, (void **)&pias);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
hr = pias->InsertTextAtSelection(ec, TF_IAS_QUERYONLY, pstrAddString->Get(), (LONG)pstrAddString->GetLength(), &rangeInsert);
|
||||
|
||||
if ( FAILED(hr) || rangeInsert == nullptr)
|
||||
{
|
||||
rangeInsert = nullptr;
|
||||
pias->Release();
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
*ppCompRange = rangeInsert;
|
||||
pias->Release();
|
||||
hr = S_OK;
|
||||
|
||||
Exit:
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _RemoveDummyCompositionForComposing
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_RemoveDummyCompositionForComposing(TfEditCookie ec, _In_ ITfComposition *pComposition)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
ITfRange* pRange = nullptr;
|
||||
|
||||
if (pComposition)
|
||||
{
|
||||
hr = pComposition->GetRange(&pRange);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
pRange->SetText(ec, 0, nullptr, 0);
|
||||
pRange->Release();
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _SetCompositionLanguage
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CSampleIME::_SetCompositionLanguage(TfEditCookie ec, _In_ ITfContext *pContext)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
BOOL ret = TRUE;
|
||||
|
||||
CCompositionProcessorEngine* pCompositionProcessorEngine = nullptr;
|
||||
pCompositionProcessorEngine = _pCompositionProcessorEngine;
|
||||
|
||||
LANGID langidProfile = 0;
|
||||
pCompositionProcessorEngine->GetLanguageProfile(&langidProfile);
|
||||
|
||||
ITfRange* pRangeComposition = nullptr;
|
||||
ITfProperty* pLanguageProperty = nullptr;
|
||||
|
||||
// we need a range and the context it lives in
|
||||
hr = _pComposition->GetRange(&pRangeComposition);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
ret = FALSE;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
// get our the language property
|
||||
hr = pContext->GetProperty(GUID_PROP_LANGID, &pLanguageProperty);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
ret = FALSE;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
VARIANT var;
|
||||
var.vt = VT_I4; // we're going to set DWORD
|
||||
var.lVal = langidProfile;
|
||||
|
||||
hr = pLanguageProperty->SetValue(ec, pRangeComposition, &var);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
ret = FALSE;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
pLanguageProperty->Release();
|
||||
pRangeComposition->Release();
|
||||
|
||||
Exit:
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sal.h"
|
||||
#include "TableDictionaryEngine.h"
|
||||
#include "KeyHandlerEditSession.h"
|
||||
#include "SampleIMEBaseStructure.h"
|
||||
#include "FileMapping.h"
|
||||
#include "Compartment.h"
|
||||
#include "define.h"
|
||||
|
||||
class CCompositionProcessorEngine
|
||||
{
|
||||
public:
|
||||
CCompositionProcessorEngine(void);
|
||||
~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 AddVirtualKey(WCHAR wch);
|
||||
void RemoveVirtualKey(DWORD_PTR dwIndex);
|
||||
void PurgeVirtualKey();
|
||||
|
||||
DWORD_PTR GetVirtualKeyLength() { return _keystrokeBuffer.GetLength(); }
|
||||
WCHAR GetVirtualKey(DWORD_PTR dwIndex);
|
||||
|
||||
void GetReadingStrings(_Inout_ CSampleImeArray<CStringRange> *pReadingStrings, _Out_ BOOL *pIsWildcardIncluded);
|
||||
void GetCandidateList(_Inout_ CSampleImeArray<CCandidateListItem> *pCandidateList, BOOL isIncrementalWordSearch, BOOL isWildcardSearch);
|
||||
void GetCandidateStringInConverted(CStringRange &searchString, _In_ CSampleImeArray<CCandidateListItem> *pCandidateList);
|
||||
|
||||
// Preserved key handler
|
||||
void OnPreservedKey(REFGUID rguid, _Out_ BOOL *pIsEaten, _In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId);
|
||||
|
||||
// Punctuation
|
||||
BOOL IsPunctuation(WCHAR wch);
|
||||
WCHAR GetPunctuation(WCHAR wch);
|
||||
|
||||
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 IsMakePhraseFromText() { return _hasMakePhraseFromText; }
|
||||
BOOL IsKeystrokeSort() { return _isKeystrokeSort; }
|
||||
|
||||
// Dictionary engine
|
||||
BOOL IsDictionaryAvailable() { return (_pTableDictionaryEngine ? TRUE : FALSE); }
|
||||
|
||||
// Language bar control
|
||||
void SetLanguageBarStatus(DWORD status, BOOL isSet);
|
||||
|
||||
void ConversionModeCompartmentUpdated(_In_ ITfThreadMgr *pThreadMgr);
|
||||
|
||||
void ShowAllLanguageBarIcons();
|
||||
void HideAllLanguageBarIcons();
|
||||
|
||||
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_ CSampleImeArray<_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_ CSampleImeArray<_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 InitializeSampleIMECompartment(_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_ CSampleImeArray<TF_PRESERVEDKEY> *pTSFPreservedKeyTable);
|
||||
|
||||
static HRESULT CompartmentCallback(_In_ void *pv, REFGUID guidCompartment);
|
||||
void PrivateCompartmentsUpdated(_In_ ITfThreadMgr *pThreadMgr);
|
||||
void KeyboardOpenCompartmentUpdated(_In_ ITfThreadMgr *pThreadMgr);
|
||||
|
||||
|
||||
BOOL SetupDictionaryFile();
|
||||
CFile* GetDictionaryFile();
|
||||
|
||||
private:
|
||||
struct _KEYSTROKE
|
||||
{
|
||||
UINT VirtualKey;
|
||||
UINT Modifiers;
|
||||
KEYSTROKE_FUNCTION Function;
|
||||
|
||||
_KEYSTROKE()
|
||||
{
|
||||
VirtualKey = 0;
|
||||
Modifiers = 0;
|
||||
Function = FUNCTION_NONE;
|
||||
}
|
||||
};
|
||||
_KEYSTROKE _keystrokeTable[26];
|
||||
|
||||
CTableDictionaryEngine* _pTableDictionaryEngine;
|
||||
CStringRange _keystrokeBuffer;
|
||||
|
||||
BOOL _hasWildcardIncludedInKeystrokeBuffer;
|
||||
|
||||
LANGID _langid;
|
||||
GUID _guidProfile;
|
||||
TfClientId _tfClientId;
|
||||
|
||||
CSampleImeArray<_KEYSTROKE> _KeystrokeComposition;
|
||||
CSampleImeArray<_KEYSTROKE> _KeystrokeCandidate;
|
||||
CSampleImeArray<_KEYSTROKE> _KeystrokeCandidateWildcard;
|
||||
CSampleImeArray<_KEYSTROKE> _KeystrokeCandidateSymbol;
|
||||
CSampleImeArray<_KEYSTROKE> _KeystrokeSymbol;
|
||||
|
||||
// Preserved key data
|
||||
class XPreservedKey
|
||||
{
|
||||
public:
|
||||
XPreservedKey();
|
||||
~XPreservedKey();
|
||||
BOOL UninitPreservedKey(_In_ ITfThreadMgr *pThreadMgr);
|
||||
|
||||
public:
|
||||
CSampleImeArray<TF_PRESERVEDKEY> TSFPreservedKeyTable;
|
||||
GUID Guid;
|
||||
LPCWSTR Description;
|
||||
};
|
||||
|
||||
XPreservedKey _PreservedKey_IMEMode;
|
||||
XPreservedKey _PreservedKey_DoubleSingleByte;
|
||||
XPreservedKey _PreservedKey_Punctuation;
|
||||
|
||||
// Punctuation data
|
||||
CSampleImeArray<CPunctuationPair> _PunctuationPair;
|
||||
CSampleImeArray<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;
|
||||
|
||||
// Configuration data
|
||||
BOOL _isWildcard : 1;
|
||||
BOOL _isDisableWildcardAtFirst : 1;
|
||||
BOOL _hasMakePhraseFromText : 1;
|
||||
BOOL _isKeystrokeSort : 1;
|
||||
BOOL _isComLessMode : 1;
|
||||
CCandidateRange _candidateListIndexRange;
|
||||
UINT _candidateListPhraseModifier;
|
||||
UINT _candidateWndWidth;
|
||||
|
||||
CFileMapping* _pDictionaryFile;
|
||||
|
||||
static const int OUT_OF_FILE_INDEX = -1;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#pragma once
|
||||
#include "resource.h"
|
||||
|
||||
#define TEXTSERVICE_MODEL L"Apartment"
|
||||
#define TEXTSERVICE_LANGID MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)
|
||||
#define TEXTSERVICE_ICON_INDEX -IDIS_SAMPLEIME
|
||||
#define TEXTSERVICE_DIC L"SampleIMESimplifiedQuanPin.txt"
|
||||
|
||||
#define IME_MODE_ON_ICON_INDEX IDI_IME_MODE_ON
|
||||
#define IME_MODE_OFF_ICON_INDEX IDI_IME_MODE_OFF
|
||||
#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 SAMPLEIME_FONT_DEFAULT L"Microsoft YaHei UI"
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// 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_ITEM_COLOR (RGB(0x00, 0x00, 0x00))
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// 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}")
|
||||
@@ -0,0 +1,3 @@
|
||||
# The *.txt files in this directory are UTF-16-encoded and should
|
||||
# therefore be treated as pure binary data.
|
||||
*.txt binary
|
||||
@@ -0,0 +1,222 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "DictionaryParser.h"
|
||||
#include "SampleIMEBaseStructure.h"
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// ctor
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
CDictionaryParser::CDictionaryParser(LCID locale)
|
||||
{
|
||||
_locale = locale;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// dtor
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
CDictionaryParser::~CDictionaryParser()
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// ParseLine
|
||||
//
|
||||
// dwBufLen - in character count
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
BOOL CDictionaryParser::ParseLine(_In_reads_(dwBufLen) LPCWSTR pwszBuffer, DWORD_PTR dwBufLen, _Out_ CParserStringRange *psrgKeyword, _Inout_opt_ CSampleImeArray<CParserStringRange> *pValue)
|
||||
{
|
||||
LPCWSTR pwszKeyWordDelimiter = nullptr;
|
||||
pwszKeyWordDelimiter = GetToken(pwszBuffer, dwBufLen, Global::KeywordDelimiter, psrgKeyword);
|
||||
if (!(pwszKeyWordDelimiter))
|
||||
{
|
||||
return FALSE; // End of file
|
||||
}
|
||||
|
||||
dwBufLen -= (pwszKeyWordDelimiter - pwszBuffer);
|
||||
pwszBuffer = pwszKeyWordDelimiter + 1;
|
||||
dwBufLen--;
|
||||
|
||||
// Get value.
|
||||
if (pValue)
|
||||
{
|
||||
if (dwBufLen)
|
||||
{
|
||||
CParserStringRange* psrgValue = pValue->Append();
|
||||
if (!psrgValue)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
psrgValue->Set(pwszBuffer, dwBufLen);
|
||||
RemoveWhiteSpaceFromBegin(psrgValue);
|
||||
RemoveWhiteSpaceFromEnd(psrgValue);
|
||||
RemoveStringDelimiter(psrgValue);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// GetToken
|
||||
//
|
||||
// dwBufLen - in character count
|
||||
//
|
||||
// return - pointer of delimiter which specified chDelimiter
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
_Ret_maybenull_
|
||||
LPCWSTR CDictionaryParser::GetToken(_In_reads_(dwBufLen) LPCWSTR pwszBuffer, DWORD_PTR dwBufLen, _In_ const WCHAR chDelimiter, _Out_ CParserStringRange *psrgValue)
|
||||
{
|
||||
WCHAR ch = '\0';
|
||||
|
||||
psrgValue->Set(pwszBuffer, dwBufLen);
|
||||
|
||||
ch = *pwszBuffer;
|
||||
while ((ch) && (ch != chDelimiter) && dwBufLen)
|
||||
{
|
||||
dwBufLen--;
|
||||
pwszBuffer++;
|
||||
|
||||
if (ch == Global::StringDelimiter)
|
||||
{
|
||||
while (*pwszBuffer && (*pwszBuffer != Global::StringDelimiter) && dwBufLen)
|
||||
{
|
||||
dwBufLen--;
|
||||
pwszBuffer++;
|
||||
}
|
||||
if (*pwszBuffer && dwBufLen)
|
||||
{
|
||||
dwBufLen--;
|
||||
pwszBuffer++;
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
ch = *pwszBuffer;
|
||||
}
|
||||
|
||||
if (*pwszBuffer && dwBufLen)
|
||||
{
|
||||
LPCWSTR pwszStart = psrgValue->Get();
|
||||
|
||||
psrgValue->Set(pwszStart, pwszBuffer - pwszStart);
|
||||
|
||||
RemoveWhiteSpaceFromBegin(psrgValue);
|
||||
RemoveWhiteSpaceFromEnd(psrgValue);
|
||||
RemoveStringDelimiter(psrgValue);
|
||||
|
||||
return pwszBuffer;
|
||||
}
|
||||
|
||||
RemoveWhiteSpaceFromBegin(psrgValue);
|
||||
RemoveWhiteSpaceFromEnd(psrgValue);
|
||||
RemoveStringDelimiter(psrgValue);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// RemoveWhiteSpaceFromBegin
|
||||
// RemoveWhiteSpaceFromEnd
|
||||
// RemoveStringDelimiter
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
BOOL CDictionaryParser::RemoveWhiteSpaceFromBegin(_Inout_opt_ CStringRange *pString)
|
||||
{
|
||||
DWORD_PTR dwIndexTrace = 0; // in char
|
||||
|
||||
if (pString == nullptr)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (SkipWhiteSpace(_locale, pString->Get(), pString->GetLength(), &dwIndexTrace) != S_OK)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pString->Set(pString->Get() + dwIndexTrace, pString->GetLength() - dwIndexTrace);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CDictionaryParser::RemoveWhiteSpaceFromEnd(_Inout_opt_ CStringRange *pString)
|
||||
{
|
||||
if (pString == nullptr)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DWORD_PTR dwTotalBufLen = pString->GetLength();
|
||||
LPCWSTR pwszEnd = pString->Get() + dwTotalBufLen - 1;
|
||||
|
||||
while (dwTotalBufLen && (IsSpace(_locale, *pwszEnd) || *pwszEnd == L'\r' || *pwszEnd == L'\n'))
|
||||
{
|
||||
pwszEnd--;
|
||||
dwTotalBufLen--;
|
||||
}
|
||||
|
||||
pString->Set(pString->Get(), dwTotalBufLen);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CDictionaryParser::RemoveStringDelimiter(_Inout_opt_ CStringRange *pString)
|
||||
{
|
||||
if (pString == nullptr)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (pString->GetLength() >= 2)
|
||||
{
|
||||
if ((*pString->Get() == Global::StringDelimiter) && (*(pString->Get()+pString->GetLength()-1) == Global::StringDelimiter))
|
||||
{
|
||||
pString->Set(pString->Get()+1, pString->GetLength()-2);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// GetOneLine
|
||||
//
|
||||
// dwBufLen - in character count
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
DWORD_PTR CDictionaryParser::GetOneLine(_In_z_ LPCWSTR pwszBuffer, DWORD_PTR dwBufLen)
|
||||
{
|
||||
DWORD_PTR dwIndexTrace = 0; // in char
|
||||
|
||||
if (FAILED(FindChar(L'\r', pwszBuffer, dwBufLen, &dwIndexTrace)))
|
||||
{
|
||||
if (FAILED(FindChar(L'\0', pwszBuffer, dwBufLen, &dwIndexTrace)))
|
||||
{
|
||||
return dwBufLen;
|
||||
}
|
||||
}
|
||||
|
||||
return dwIndexTrace;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Globals.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
class CParserStringRange : public CStringRange
|
||||
{
|
||||
public:
|
||||
CParserStringRange() : CStringRange()
|
||||
{
|
||||
_fEscapeIncluded = FALSE;
|
||||
}
|
||||
|
||||
BOOL _fEscapeIncluded; // flag. This string range included escape sequence.
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
class CDictionaryParser
|
||||
{
|
||||
public:
|
||||
CDictionaryParser(LCID locale);
|
||||
virtual ~CDictionaryParser();
|
||||
|
||||
BOOL ParseLine(_In_reads_(dwBufLen) LPCWSTR pwszBuffer, DWORD_PTR dwBufLen, _Out_ CParserStringRange *psrgKeyword, _Inout_opt_ CSampleImeArray<CParserStringRange> *pValue = nullptr);
|
||||
|
||||
// dwBufLen - in character count
|
||||
_Ret_maybenull_
|
||||
LPCWSTR GetToken(_In_reads_(dwBufLen) LPCWSTR pwszBuffer, DWORD_PTR dwBufLen, _In_ const WCHAR chDelimiter, _Out_ CParserStringRange *srgKeyWord);
|
||||
|
||||
protected:
|
||||
BOOL RemoveWhiteSpaceFromBegin(_Inout_opt_ CStringRange *pString);
|
||||
BOOL RemoveWhiteSpaceFromEnd(_Inout_opt_ CStringRange *pString);
|
||||
BOOL RemoveStringDelimiter(_Inout_opt_ CStringRange *pString);
|
||||
|
||||
DWORD_PTR GetOneLine(_In_z_ LPCWSTR pwszBuffer, DWORD_PTR dwBufLen);
|
||||
|
||||
LCID _locale; // used for CompareString
|
||||
};
|
||||
@@ -0,0 +1,250 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "DictionarySearch.h"
|
||||
#include "SampleIMEBaseStructure.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ctor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CDictionarySearch::CDictionarySearch(LCID locale, _In_ CFile *pFile, _In_ CStringRange *pSearchKeyCode) : CDictionaryParser(locale)
|
||||
{
|
||||
_pFile = pFile;
|
||||
_pSearchKeyCode = pSearchKeyCode;
|
||||
_charIndex = 0;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// dtor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CDictionarySearch::~CDictionarySearch()
|
||||
{
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// FindPhrase
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CDictionarySearch::FindPhrase(_Out_ CDictionaryResult **ppdret)
|
||||
{
|
||||
return FindWorker(FALSE, ppdret, FALSE); // NO WILDCARD
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// FindPhraseForWildcard
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CDictionarySearch::FindPhraseForWildcard(_Out_ CDictionaryResult **ppdret)
|
||||
{
|
||||
return FindWorker(FALSE, ppdret, TRUE); // Wildcard
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// FindConvertedStringForWildcard
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CDictionarySearch::FindConvertedStringForWildcard(CDictionaryResult **ppdret)
|
||||
{
|
||||
return FindWorker(TRUE, ppdret, TRUE); // Wildcard
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// FindWorker
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CDictionarySearch::FindWorker(BOOL isTextSearch, _Out_ CDictionaryResult **ppdret, BOOL isWildcardSearch)
|
||||
{
|
||||
DWORD_PTR dwTotalBufLen = GetBufferInWCharLength(); // in char
|
||||
if (dwTotalBufLen == 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const WCHAR *pwch = GetBufferInWChar();
|
||||
DWORD_PTR indexTrace = 0; // in char
|
||||
*ppdret = nullptr;
|
||||
BOOL isFound = FALSE;
|
||||
DWORD_PTR bufLenOneLine = 0;
|
||||
|
||||
TryAgain:
|
||||
bufLenOneLine = GetOneLine(&pwch[indexTrace], dwTotalBufLen);
|
||||
if (bufLenOneLine == 0)
|
||||
{
|
||||
goto FindNextLine;
|
||||
}
|
||||
else
|
||||
{
|
||||
CParserStringRange keyword;
|
||||
DWORD_PTR bufLen = 0;
|
||||
LPWSTR pText = nullptr;
|
||||
|
||||
if (!ParseLine(&pwch[indexTrace], bufLenOneLine, &keyword))
|
||||
{
|
||||
return FALSE; // error
|
||||
}
|
||||
|
||||
if (!isTextSearch)
|
||||
{
|
||||
// Compare Dictionary key code and input key code
|
||||
if (!isWildcardSearch)
|
||||
{
|
||||
if (CStringRange::Compare(_locale, &keyword, _pSearchKeyCode) != CSTR_EQUAL)
|
||||
{
|
||||
if (bufLen)
|
||||
{
|
||||
delete [] pText;
|
||||
}
|
||||
goto FindNextLine;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Wildcard search
|
||||
if (!CStringRange::WildcardCompare(_locale, _pSearchKeyCode, &keyword))
|
||||
{
|
||||
if (bufLen)
|
||||
{
|
||||
delete [] pText;
|
||||
}
|
||||
goto FindNextLine;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Compare Dictionary converted string and input string
|
||||
CSampleImeArray<CParserStringRange> convertedStrings;
|
||||
if (!ParseLine(&pwch[indexTrace], bufLenOneLine, &keyword, &convertedStrings))
|
||||
{
|
||||
if (bufLen)
|
||||
{
|
||||
delete [] pText;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
if (convertedStrings.Count() == 1)
|
||||
{
|
||||
CStringRange* pTempString = convertedStrings.GetAt(0);
|
||||
|
||||
if (!isWildcardSearch)
|
||||
{
|
||||
if (CStringRange::Compare(_locale, pTempString, _pSearchKeyCode) != CSTR_EQUAL)
|
||||
{
|
||||
if (bufLen)
|
||||
{
|
||||
delete [] pText;
|
||||
}
|
||||
goto FindNextLine;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Wildcard search
|
||||
if (!CStringRange::WildcardCompare(_locale, _pSearchKeyCode, pTempString))
|
||||
{
|
||||
if (bufLen)
|
||||
{
|
||||
delete [] pText;
|
||||
}
|
||||
goto FindNextLine;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bufLen)
|
||||
{
|
||||
delete [] pText;
|
||||
}
|
||||
goto FindNextLine;
|
||||
}
|
||||
}
|
||||
|
||||
if (bufLen)
|
||||
{
|
||||
delete [] pText;
|
||||
}
|
||||
|
||||
// Prepare return's CDictionaryResult
|
||||
*ppdret = new (std::nothrow) CDictionaryResult();
|
||||
if (!*ppdret)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CSampleImeArray<CParserStringRange> valueStrings;
|
||||
if (!ParseLine(&pwch[indexTrace], bufLenOneLine, &keyword, &valueStrings))
|
||||
{
|
||||
if (*ppdret)
|
||||
{
|
||||
delete *ppdret;
|
||||
*ppdret = nullptr;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
(*ppdret)->_FindKeyCode = keyword;
|
||||
(*ppdret)->_SearchKeyCode = *_pSearchKeyCode;
|
||||
|
||||
for (UINT i = 0; i < valueStrings.Count(); i++)
|
||||
{
|
||||
CStringRange* findPhrase = (*ppdret)->_FindPhraseList.Append();
|
||||
if (findPhrase)
|
||||
{
|
||||
*findPhrase = *valueStrings.GetAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Seek to next line
|
||||
isFound = TRUE;
|
||||
}
|
||||
|
||||
FindNextLine:
|
||||
dwTotalBufLen -= bufLenOneLine;
|
||||
if (dwTotalBufLen == 0)
|
||||
{
|
||||
indexTrace += bufLenOneLine;
|
||||
_charIndex += indexTrace;
|
||||
|
||||
if (!isFound && *ppdret)
|
||||
{
|
||||
delete *ppdret;
|
||||
*ppdret = nullptr;
|
||||
}
|
||||
return (isFound ? TRUE : FALSE); // End of file
|
||||
}
|
||||
|
||||
indexTrace += bufLenOneLine;
|
||||
if (pwch[indexTrace] == L'\r' || pwch[indexTrace] == L'\n' || pwch[indexTrace] == L'\0')
|
||||
{
|
||||
bufLenOneLine = 1;
|
||||
goto FindNextLine;
|
||||
}
|
||||
|
||||
if (isFound)
|
||||
{
|
||||
_charIndex += indexTrace;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
goto TryAgain;
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "File.h"
|
||||
#include "DictionaryParser.h"
|
||||
#include "SampleIMEBaseStructure.h"
|
||||
|
||||
class CDictionaryResult;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CDictionarySearch declaration.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CDictionarySearch : CDictionaryParser
|
||||
{
|
||||
public:
|
||||
CDictionarySearch(LCID locale, _In_ CFile *pFile, _In_ CStringRange *pSearchKeyCode);
|
||||
virtual ~CDictionarySearch();
|
||||
|
||||
BOOL FindPhrase(_Out_ CDictionaryResult **ppdret);
|
||||
BOOL FindPhraseForWildcard(_Out_ CDictionaryResult **ppdret);
|
||||
|
||||
BOOL FindConvertedStringForWildcard(CDictionaryResult **ppdret);
|
||||
|
||||
CStringRange* _pSearchKeyCode;
|
||||
|
||||
DWORD_PTR _charIndex; // in character. Always point start of line in dictionary file.
|
||||
|
||||
private:
|
||||
BOOL FindWorker(BOOL isTextSearch, _Out_ CDictionaryResult **ppdret, BOOL isWildcardSearch);
|
||||
|
||||
DWORD_PTR GetBufferInWCharLength()
|
||||
{
|
||||
return (_pFile->GetFileSize() / sizeof(WCHAR)) - _charIndex; // in char count as a returned length.
|
||||
}
|
||||
|
||||
const WCHAR* GetBufferInWChar()
|
||||
{
|
||||
return _pFile->GetReadBufferPointer() + _charIndex;
|
||||
}
|
||||
|
||||
CFile* _pFile;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CDictionaryResult declaration.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CDictionaryResult
|
||||
{
|
||||
public:
|
||||
CDictionaryResult() { }
|
||||
virtual ~CDictionaryResult() { }
|
||||
|
||||
CDictionaryResult& operator=(CDictionaryResult& dret)
|
||||
{
|
||||
_FindKeyCode = dret._FindKeyCode;
|
||||
_FindPhraseList = dret._FindPhraseList;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CStringRange _SearchKeyCode;
|
||||
CStringRange _FindKeyCode;
|
||||
CSampleImeArray<CStringRange> _FindPhraseList;
|
||||
};
|
||||
@@ -0,0 +1,115 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "globals.h"
|
||||
#include "SampleIME.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _ClearCompositionDisplayAttributes
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CSampleIME::_ClearCompositionDisplayAttributes(TfEditCookie ec, _In_ ITfContext *pContext)
|
||||
{
|
||||
ITfRange* pRangeComposition = nullptr;
|
||||
ITfProperty* pDisplayAttributeProperty = nullptr;
|
||||
|
||||
// get the compositon range.
|
||||
if (FAILED(_pComposition->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 CSampleIME::_SetCompositionDisplayAttributes(TfEditCookie ec, _In_ ITfContext *pContext, TfGuidAtom gaDisplayAttribute)
|
||||
{
|
||||
ITfRange* pRangeComposition = nullptr;
|
||||
ITfProperty* pDisplayAttributeProperty = 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;
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
pRangeComposition->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 CSampleIME::_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::SampleIMEGuidDisplayAttributeInput, &_gaDisplayAttributeInput);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
// register the display attribute for the converted text.
|
||||
hr = pCategoryMgr->RegisterGUID(Global::SampleIMEGuidDisplayAttributeConverted, &_gaDisplayAttributeConverted);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Exit:
|
||||
pCategoryMgr->Release();
|
||||
|
||||
return (hr == S_OK);
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#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"Sample IME Text Service Display Attribute Input";
|
||||
const WCHAR CDisplayAttributeInfoConverted::_s_szDescription[] = L"Sample IME Text Service Display Attribute Converted";
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// DisplayAttribute
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
const TF_DISPLAYATTRIBUTE CDisplayAttributeInfoInput::_s_DisplayAttribute =
|
||||
{
|
||||
{ TF_CT_COLORREF, RGB(0, 103,206) }, // text color
|
||||
{ TF_CT_NONE, 0 }, // background color (TF_CT_NONE => app default)
|
||||
TF_LS_DOT, // underline style
|
||||
FALSE, // underline boldness
|
||||
{ TF_CT_COLORREF, RGB(0, 103,206) }, // underline color
|
||||
TF_ATTR_INPUT // attribute info
|
||||
};
|
||||
|
||||
const TF_DISPLAYATTRIBUTE CDisplayAttributeInfoConverted::_s_DisplayAttribute =
|
||||
{
|
||||
{ TF_CT_COLORREF, RGB(255, 255, 255) }, // text color
|
||||
{ TF_CT_COLORREF, RGB( 0, 255, 255) }, // 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);
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// 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::SampleIMEGuidDisplayAttributeInput;
|
||||
_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::SampleIMEGuidDisplayAttributeConverted;
|
||||
_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[];
|
||||
};
|
||||
@@ -0,0 +1,81 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "globals.h"
|
||||
#include "SampleIME.h"
|
||||
#include "DisplayAttributeInfo.h"
|
||||
#include "EnumDisplayAttributeInfo.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfDisplayAttributeProvider::EnumDisplayAttributeInfo
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CSampleIME::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 CSampleIME::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::SampleIMEGuidDisplayAttributeInput))
|
||||
{
|
||||
*ppInfo = new (std::nothrow) CDisplayAttributeInfoInput();
|
||||
if ((*ppInfo) == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
}
|
||||
else if (IsEqualGUID(guidInfo, Global::SampleIMEGuidDisplayAttributeConverted))
|
||||
{
|
||||
*ppInfo = new (std::nothrow) CDisplayAttributeInfoConverted();
|
||||
if ((*ppInfo) == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// DisplayString.h
|
||||
//
|
||||
// CDisplayString declaration.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "StringRange.h"
|
||||
#include "PointerArray.h"
|
||||
|
||||
class CDisplayString
|
||||
{
|
||||
public:
|
||||
CDisplayString() { }
|
||||
~CDisplayString() { }
|
||||
|
||||
int Count() { }
|
||||
// VOID SetDisplayString(int iIndex, WCHAR* pchText, USHORT cchMax, TF_DISPLAYATTRIBUTE tfDisplayAttribute) { }
|
||||
// VOID GetDisplayString(int iIndex, WCHAR* pchText, USHORT cchMax, USHORT* pch, TF_DISPLAYATTRIBUTE tfDisplayAttribute) { }
|
||||
VOID SetLogicalFont(LOGFONTW LogFont) { }
|
||||
VOID GetLogicalFont(LOGFONTW* pLogFont) { }
|
||||
|
||||
private:
|
||||
//typedef struct _DISPLAY_STRING {
|
||||
// CStringRange _StringRange; // Unicode string.
|
||||
// // Length and MaximumLength is in character count.
|
||||
// // Buffer doesn't add zero terminate.
|
||||
// TF_DISPLAYATTRIBUTE _tfDisplayAttribute; // Display attribute for each array.
|
||||
//} DISPLAY_STRING;
|
||||
|
||||
//
|
||||
// Array of DISPLAY_STRING
|
||||
//
|
||||
//CPointerArray<DISPLAY_STRING> _pDisplayString;
|
||||
|
||||
// Logical font
|
||||
LOGFONTW _logfont;
|
||||
};
|
||||
@@ -0,0 +1,54 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
if (!Global::RegisterWindowClass()) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
|
||||
DeleteCriticalSection(&Global::CS);
|
||||
|
||||
break;
|
||||
|
||||
case DLL_THREAD_ATTACH:
|
||||
|
||||
break;
|
||||
|
||||
case DLL_THREAD_DETACH:
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "EditSession.h"
|
||||
#include "SampleIME.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ctor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CEditSessionBase::CEditSessionBase(_In_ CSampleIME *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 = (ITfLangBarItemButton *)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;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
class CSampleIME;
|
||||
|
||||
class CEditSessionBase : public ITfEditSession
|
||||
{
|
||||
public:
|
||||
CEditSessionBase(_In_ CSampleIME *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;
|
||||
CSampleIME *_pTextService;
|
||||
|
||||
private:
|
||||
LONG _refCount; // COM ref count
|
||||
};
|
||||
@@ -0,0 +1,98 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "EditSession.h"
|
||||
#include "SampleIME.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ITfEditSession
|
||||
// CEditSessionBase
|
||||
// CEndCompositionEditSession class
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CEndCompositionEditSession
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class CEndCompositionEditSession : public CEditSessionBase
|
||||
{
|
||||
public:
|
||||
CEndCompositionEditSession(_In_ CSampleIME *pTextService, _In_ ITfContext *pContext) : CEditSessionBase(pTextService, pContext)
|
||||
{
|
||||
}
|
||||
|
||||
// ITfEditSession
|
||||
STDMETHODIMP DoEditSession(TfEditCookie ec)
|
||||
{
|
||||
_pTextService->_TerminateComposition(ec, _pContext, TRUE);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CSampleIME class
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _TerminateComposition
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CSampleIME::_TerminateComposition(TfEditCookie ec, _In_ ITfContext *pContext, BOOL isCalledFromDeactivate)
|
||||
{
|
||||
isCalledFromDeactivate;
|
||||
|
||||
if (_pComposition != nullptr)
|
||||
{
|
||||
// remove the display attribute from the composition range.
|
||||
_ClearCompositionDisplayAttributes(ec, pContext);
|
||||
|
||||
if (FAILED(_pComposition->EndComposition(ec)))
|
||||
{
|
||||
// if we fail to EndComposition, then we need to close the reverse reading window.
|
||||
_DeleteCandidateList(TRUE, pContext);
|
||||
}
|
||||
|
||||
_pComposition->Release();
|
||||
_pComposition = nullptr;
|
||||
|
||||
if (_pContext)
|
||||
{
|
||||
_pContext->Release();
|
||||
_pContext = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _EndComposition
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CSampleIME::_EndComposition(_In_opt_ ITfContext *pContext)
|
||||
{
|
||||
CEndCompositionEditSession *pEditSession = new (std::nothrow) CEndCompositionEditSession(this, pContext);
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (nullptr != pEditSession)
|
||||
{
|
||||
pContext->RequestEditSession(_tfClientId, pEditSession, TF_ES_ASYNCDONTCARE | TF_ES_READWRITE, &hr);
|
||||
pEditSession->Release();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,226 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "globals.h"
|
||||
#include "SampleIME.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;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#pragma once
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// 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
|
||||
};
|
||||
@@ -0,0 +1,146 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "private.h"
|
||||
#include "EnumTfCandidates.h"
|
||||
|
||||
HRESULT CEnumTfCandidates::CreateInstance(_Out_ CEnumTfCandidates **ppobj, _In_ const CSampleImeArray<ITfCandidateString*> &rgelm, UINT currentNum)
|
||||
{
|
||||
if (ppobj == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*ppobj = nullptr;
|
||||
|
||||
*ppobj = new (std::nothrow) CEnumTfCandidates(rgelm, currentNum);
|
||||
if (*ppobj == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CEnumTfCandidates::CreateInstance(REFIID riid, _Out_ void **ppvObj, _In_ const CSampleImeArray<ITfCandidateString*> &rgelm, UINT currentNum)
|
||||
{
|
||||
if (ppvObj == nullptr)
|
||||
{
|
||||
return E_POINTER;
|
||||
}
|
||||
*ppvObj = nullptr;
|
||||
|
||||
*ppvObj = new (std::nothrow) CEnumTfCandidates(rgelm, currentNum);
|
||||
if (*ppvObj == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
return ((CEnumTfCandidates*)(*ppvObj))->QueryInterface(riid, ppvObj);
|
||||
}
|
||||
|
||||
CEnumTfCandidates::CEnumTfCandidates(_In_ const CSampleImeArray<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);
|
||||
_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(__uuidof(IEnumTfCandidates), (void**)ppEnum, _rgelm, _currentCandidateStrIndex);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Globals.h"
|
||||
|
||||
class CEnumTfCandidates : public IEnumTfCandidates
|
||||
{
|
||||
protected:
|
||||
// constructor/destructor
|
||||
CEnumTfCandidates(_In_ const CSampleImeArray<ITfCandidateString*> &rgelm, UINT currentNum);
|
||||
|
||||
virtual ~CEnumTfCandidates(void);
|
||||
|
||||
public:
|
||||
// create instance
|
||||
static HRESULT CreateInstance(_Out_ CEnumTfCandidates **ppobj, _In_ const CSampleImeArray<ITfCandidateString*> &rgelm, UINT currentNum = 0);
|
||||
static HRESULT CreateInstance(REFIID riid, _Out_ void **ppvObj, _In_ const CSampleImeArray<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;
|
||||
CSampleImeArray<ITfCandidateString*> _rgelm;
|
||||
UINT _currentCandidateStrIndex;
|
||||
};
|
||||
@@ -0,0 +1,254 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#ifndef UNICODE
|
||||
#define UNICODE
|
||||
#endif // !UNICODE
|
||||
|
||||
#ifndef _UNICODE
|
||||
#define _UNICODE
|
||||
#endif // !UNICODE
|
||||
|
||||
#include "Private.h"
|
||||
#include "File.h"
|
||||
#include "SampleIMEBaseStructure.h"
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// ctor
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
CFile::CFile(UINT codePage)
|
||||
{
|
||||
_codePage = codePage;
|
||||
_fileHandle = nullptr;
|
||||
_pReadBuffer = nullptr;
|
||||
_fileSize = 0;
|
||||
_filePosPointer = 0;
|
||||
_pFileName = nullptr;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// dtor
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
CFile::~CFile()
|
||||
{
|
||||
if (_pReadBuffer)
|
||||
{
|
||||
delete[] _pReadBuffer;
|
||||
_pReadBuffer = nullptr;
|
||||
}
|
||||
if (_fileHandle)
|
||||
{
|
||||
CloseHandle(_fileHandle);
|
||||
_fileHandle = nullptr;
|
||||
}
|
||||
if (_pFileName)
|
||||
{
|
||||
delete[] _pFileName;
|
||||
_pFileName = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// CreateFile
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
BOOL CFile::CreateFile(_In_ PCWSTR pFileName, DWORD desiredAccess, DWORD creationDisposition, DWORD sharedMode,
|
||||
_Inout_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD flagsAndAttributes,
|
||||
_Inout_opt_ HANDLE templateFileHandle)
|
||||
{
|
||||
size_t fullPathLen = wcslen(pFileName);
|
||||
if (!_pFileName)
|
||||
{
|
||||
_pFileName = new (std::nothrow) WCHAR[fullPathLen + 1];
|
||||
}
|
||||
if (!_pFileName)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
StringCchCopyN(_pFileName, fullPathLen + 1, pFileName, fullPathLen);
|
||||
|
||||
_fileHandle = ::CreateFile(pFileName, desiredAccess, sharedMode, lpSecurityAttributes, creationDisposition,
|
||||
flagsAndAttributes, templateFileHandle);
|
||||
|
||||
if (_fileHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_fileSize = ::GetFileSize(_fileHandle, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// SetupReadBuffer
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
BOOL CFile::SetupReadBuffer()
|
||||
{
|
||||
const WCHAR *pWideBuffer = nullptr;
|
||||
|
||||
_pReadBuffer = (const WCHAR *)new (std::nothrow) BYTE[_fileSize];
|
||||
if (!_pReadBuffer)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DWORD dwNumberOfByteRead = 0;
|
||||
if (!ReadFile(_fileHandle, (LPVOID)_pReadBuffer, (DWORD)_fileSize, &dwNumberOfByteRead, NULL))
|
||||
{
|
||||
delete[] _pReadBuffer;
|
||||
_pReadBuffer = nullptr;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!IsTextUnicode(_pReadBuffer, dwNumberOfByteRead, NULL))
|
||||
{
|
||||
// This is ASCII file.
|
||||
// Read file with Unicode conversion.
|
||||
int wideLength = 0;
|
||||
|
||||
wideLength = MultiByteToWideChar(_codePage, 0, (LPCSTR)_pReadBuffer, dwNumberOfByteRead, NULL, 0);
|
||||
if (wideLength <= 0)
|
||||
{
|
||||
delete[] _pReadBuffer;
|
||||
_pReadBuffer = nullptr;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pWideBuffer = new (std::nothrow) WCHAR[wideLength];
|
||||
if (!pWideBuffer)
|
||||
{
|
||||
delete[] _pReadBuffer;
|
||||
_pReadBuffer = nullptr;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
wideLength =
|
||||
MultiByteToWideChar(_codePage, 0, (LPCSTR)_pReadBuffer, (DWORD)_fileSize, (LPWSTR)pWideBuffer, wideLength);
|
||||
if (wideLength <= 0)
|
||||
{
|
||||
delete[] pWideBuffer;
|
||||
delete[] _pReadBuffer;
|
||||
_pReadBuffer = nullptr;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_fileSize = wideLength * sizeof(WCHAR);
|
||||
delete[] _pReadBuffer;
|
||||
_pReadBuffer = pWideBuffer;
|
||||
}
|
||||
else if (_fileSize > sizeof(WCHAR))
|
||||
{
|
||||
// Read file in allocated buffer
|
||||
pWideBuffer = new (std::nothrow) WCHAR[_fileSize / sizeof(WCHAR) - 1];
|
||||
if (!pWideBuffer)
|
||||
{
|
||||
delete[] _pReadBuffer;
|
||||
_pReadBuffer = nullptr;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// skip unicode byte-order signature
|
||||
SetFilePointer(_fileHandle, sizeof(WCHAR), NULL, FILE_BEGIN);
|
||||
|
||||
if (!ReadFile(_fileHandle, (LPVOID)pWideBuffer, (DWORD)(_fileSize - sizeof(WCHAR)), &dwNumberOfByteRead, NULL))
|
||||
{
|
||||
delete[] pWideBuffer;
|
||||
delete[] _pReadBuffer;
|
||||
_pReadBuffer = nullptr;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_fileSize -= sizeof(WCHAR);
|
||||
delete[] _pReadBuffer;
|
||||
_pReadBuffer = pWideBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// IsEndOfFile
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CFile::IsEndOfFile()
|
||||
{
|
||||
return _fileSize == _filePosPointer ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// NextLine
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
VOID CFile::NextLine()
|
||||
{
|
||||
DWORD_PTR totalBufLen = GetBufferInWCharLength();
|
||||
if (totalBufLen == 0)
|
||||
{
|
||||
goto SetEOF;
|
||||
}
|
||||
const WCHAR *pwch = GetBufferInWChar();
|
||||
|
||||
DWORD_PTR indexTrace = 0; // in char
|
||||
|
||||
if (FindChar(L'\r', pwch, totalBufLen, &indexTrace) != S_OK)
|
||||
{
|
||||
goto SetEOF;
|
||||
}
|
||||
if (indexTrace >= DWORD_MAX - 1)
|
||||
{
|
||||
goto SetEOF;
|
||||
}
|
||||
|
||||
indexTrace++; // skip CR
|
||||
totalBufLen -= indexTrace;
|
||||
if (totalBufLen == 0)
|
||||
{
|
||||
goto SetEOF;
|
||||
}
|
||||
|
||||
if (pwch[indexTrace] != L'\n')
|
||||
{
|
||||
_filePosPointer += (indexTrace * sizeof(WCHAR));
|
||||
return;
|
||||
}
|
||||
|
||||
indexTrace++;
|
||||
totalBufLen--;
|
||||
if (totalBufLen == 0)
|
||||
{
|
||||
goto SetEOF;
|
||||
}
|
||||
|
||||
_filePosPointer += (indexTrace * sizeof(WCHAR));
|
||||
|
||||
return;
|
||||
|
||||
SetEOF:
|
||||
_filePosPointer = _fileSize;
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#pragma once
|
||||
|
||||
// #include "Private.h"
|
||||
|
||||
class CFile
|
||||
{
|
||||
public:
|
||||
CFile(UINT codePage = CP_ACP);
|
||||
virtual ~CFile();
|
||||
|
||||
BOOL CreateFile(_In_ PCWSTR pFileName, DWORD desiredAccess, DWORD creationDisposition,
|
||||
DWORD sharedMode = 0, _Inout_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes = nullptr, DWORD flagsAndAttributes = 0, _Inout_opt_ HANDLE templateFileHandle = nullptr);
|
||||
|
||||
BOOL IsEndOfFile();
|
||||
VOID NextLine();
|
||||
|
||||
_Ret_maybenull_
|
||||
const WCHAR *GetReadBufferPointer()
|
||||
{
|
||||
if (!_pReadBuffer)
|
||||
{
|
||||
if (!SetupReadBuffer())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return _pReadBuffer;
|
||||
}
|
||||
|
||||
DWORD_PTR GetFileSize() { return _fileSize;}
|
||||
|
||||
LPCWSTR GetFileName() { return _pFileName;}
|
||||
|
||||
protected:
|
||||
virtual BOOL SetupReadBuffer();
|
||||
|
||||
protected:
|
||||
const WCHAR* _pReadBuffer; // read buffer memory.
|
||||
DWORD_PTR _fileSize; // in byte.
|
||||
HANDLE _fileHandle; // file handle for CreateFile
|
||||
|
||||
private:
|
||||
DWORD_PTR GetBufferInWCharLength()
|
||||
{
|
||||
if (_filePosPointer == 0 && _fileSize > 0)
|
||||
{
|
||||
// skip Unicode byte order mark
|
||||
GetReadBufferPointer();
|
||||
}
|
||||
return(_fileSize - _filePosPointer) / sizeof(WCHAR); // in char count as a returned length.
|
||||
}
|
||||
|
||||
const WCHAR *GetBufferInWChar()
|
||||
{
|
||||
const WCHAR *pwch = GetReadBufferPointer();
|
||||
return(const WCHAR*)((BYTE*)pwch + _filePosPointer);
|
||||
}
|
||||
|
||||
private:
|
||||
UINT _codePage; // used for MultiByteToWideChar
|
||||
DWORD_PTR _filePosPointer; // in byte. Always point start of line.
|
||||
LPWSTR _pFileName;
|
||||
};
|
||||
@@ -0,0 +1,87 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "FileMapping.h"
|
||||
#include "Globals.h"
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// ctor
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
CFileMapping::CFileMapping() : CFile()
|
||||
{
|
||||
_fileMappingHandle = nullptr;
|
||||
_pMapBuffer = nullptr;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// dtor
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
CFileMapping::~CFileMapping()
|
||||
{
|
||||
if (_pMapBuffer)
|
||||
{
|
||||
UnmapViewOfFile(_pMapBuffer);
|
||||
_pMapBuffer = nullptr;
|
||||
_pReadBuffer = nullptr;
|
||||
}
|
||||
if (_fileMappingHandle)
|
||||
{
|
||||
CloseHandle(_fileMappingHandle);
|
||||
_fileMappingHandle = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// SetupReadBuffer
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
BOOL CFileMapping::SetupReadBuffer()
|
||||
{
|
||||
if (_fileSize > sizeof(WCHAR))
|
||||
{
|
||||
//
|
||||
// Read file in file mapping
|
||||
//
|
||||
_fileMappingHandle = CreateFileMapping(_fileHandle, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
if (_fileMappingHandle)
|
||||
{
|
||||
_pMapBuffer = (const WCHAR *)MapViewOfFile(_fileMappingHandle, FILE_MAP_READ, 0, 0, 0);
|
||||
if (_pMapBuffer)
|
||||
{
|
||||
if (IsTextUnicode(_pMapBuffer, (int)_fileSize, NULL))
|
||||
{
|
||||
_pReadBuffer = (WCHAR*)_pMapBuffer;
|
||||
|
||||
// skip Unicode byte order mark
|
||||
if (*((WCHAR*)_pMapBuffer) == Global::UnicodeByteOrderMark)
|
||||
{
|
||||
_pReadBuffer++;
|
||||
_fileSize--;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
UnmapViewOfFile(_pReadBuffer);
|
||||
_pReadBuffer = nullptr;
|
||||
}
|
||||
|
||||
CloseHandle(_fileMappingHandle);
|
||||
_fileMappingHandle = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "File.h"
|
||||
|
||||
class CFileMapping : public CFile
|
||||
{
|
||||
public:
|
||||
CFileMapping();
|
||||
virtual ~CFileMapping();
|
||||
|
||||
BOOL CreateFile(_In_ PCWSTR pFileName, DWORD desiredAccess, DWORD creationDisposition,
|
||||
DWORD sharedMode = 0, _Inout_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes = nullptr, DWORD flagsAndAttributes = 0, _Inout_opt_ HANDLE templateFileHandle = nullptr)
|
||||
|
||||
{
|
||||
return CFile::CreateFile(pFileName, desiredAccess, creationDisposition,
|
||||
sharedMode, lpSecurityAttributes, flagsAndAttributes, templateFileHandle);
|
||||
}
|
||||
|
||||
BOOL IsEndOfFile()
|
||||
{
|
||||
return CFile::IsEndOfFile();
|
||||
}
|
||||
VOID NextLine()
|
||||
{
|
||||
CFile::NextLine();
|
||||
}
|
||||
|
||||
const WCHAR *GetReadBufferPointer() { return CFile::GetReadBufferPointer(); }
|
||||
DWORD_PTR GetFileSize() { return CFile::GetFileSize(); }
|
||||
|
||||
LPCWSTR GetFileName() { return CFile::GetFileName(); }
|
||||
|
||||
protected:
|
||||
BOOL SetupReadBuffer();
|
||||
|
||||
private:
|
||||
HANDLE _fileMappingHandle; // file handle for CreateFileMapping
|
||||
const VOID *_pMapBuffer; // read buffer memory.
|
||||
};
|
||||
@@ -0,0 +1,55 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "SampleIME.h"
|
||||
#include "SearchCandidateProvider.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _InitFunctionProviderSink
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CSampleIME::_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 CSampleIME::_UninitFunctionProviderSink()
|
||||
{
|
||||
ITfSourceSingle* pSourceSingle = nullptr;
|
||||
if (SUCCEEDED(_pThreadMgr->QueryInterface(IID_ITfSourceSingle, (void **)&pSourceSingle)))
|
||||
{
|
||||
pSourceSingle->UnadviseSingleSink(_tfClientId, IID_ITfFunctionProvider);
|
||||
pSourceSingle->Release();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "EditSession.h"
|
||||
#include "GetTextExtentEditSession.h"
|
||||
#include "TfTextLayoutSink.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ctor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CGetTextExtentEditSession::CGetTextExtentEditSession(_In_ CSampleIME *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)
|
||||
{
|
||||
RECT rc = {0, 0, 0, 0};
|
||||
BOOL isClipped = TRUE;
|
||||
|
||||
if (SUCCEEDED(_pContextView->GetTextExt(ec, _pRangeComposition, &rc, &isClipped)))
|
||||
{
|
||||
_pTfTextLayoutSink->_LayoutChangeNotification(&rc);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "EditSession.h"
|
||||
|
||||
class CSampleIME;
|
||||
class CTfTextLayoutSink;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ITfEditSession
|
||||
// CEditSessionBase
|
||||
// CGetTextExtentEditSession class
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CGetTextExtentEditSession
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class CGetTextExtentEditSession : public CEditSessionBase
|
||||
{
|
||||
public:
|
||||
CGetTextExtentEditSession(_In_ CSampleIME *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;
|
||||
};
|
||||
@@ -0,0 +1,460 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "resource.h"
|
||||
#include "BaseWindow.h"
|
||||
#include "define.h"
|
||||
#include "SampleIMEBaseStructure.h"
|
||||
|
||||
namespace Global {
|
||||
HINSTANCE dllInstanceHandle;
|
||||
|
||||
LONG dllRefCount = -1;
|
||||
|
||||
CRITICAL_SECTION CS;
|
||||
HFONT defaultlFontHandle; // Global font object we use everywhere
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// SampleIME CLSID
|
||||
//---------------------------------------------------------------------
|
||||
// {D2291A80-84D8-4641-9AB2-BDD1472C846B}
|
||||
extern const CLSID SampleIMECLSID = {
|
||||
0xd2291a80,
|
||||
0x84d8,
|
||||
0x4641,
|
||||
{ 0x9a, 0xb2, 0xbd, 0xd1, 0x47, 0x2c, 0x84, 0x6b }
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Profile GUID
|
||||
//---------------------------------------------------------------------
|
||||
// {83955C0E-2C09-47a5-BCF3-F2B98E11EE8B}
|
||||
extern const GUID SampleIMEGuidProfile = {
|
||||
0x83955c0e,
|
||||
0x2c09,
|
||||
0x47a5,
|
||||
{ 0xbc, 0xf3, 0xf2, 0xb9, 0x8e, 0x11, 0xee, 0x8b }
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// PreserveKey GUID
|
||||
//---------------------------------------------------------------------
|
||||
// {4B62B54B-F828-43B5-9095-A96DF9CBDF38}
|
||||
extern const GUID SampleIMEGuidImeModePreserveKey = {
|
||||
0x4b62b54b,
|
||||
0xf828,
|
||||
0x43b5,
|
||||
{ 0x90, 0x95, 0xa9, 0x6d, 0xf9, 0xcb, 0xdf, 0x38 }
|
||||
};
|
||||
|
||||
// {5A08D6C4-4563-4E46-8DDB-65E75C4E73A3}
|
||||
extern const GUID SampleIMEGuidDoubleSingleBytePreserveKey = {
|
||||
0x5a08d6c4,
|
||||
0x4563,
|
||||
0x4e46,
|
||||
{ 0x8d, 0xdb, 0x65, 0xe7, 0x5c, 0x4e, 0x73, 0xa3 }
|
||||
};
|
||||
|
||||
// {175F062E-B961-4AED-A3DF-59F78A02862D}
|
||||
extern const GUID SampleIMEGuidPunctuationPreserveKey = {
|
||||
0x175f062e,
|
||||
0xb961,
|
||||
0x4aed,
|
||||
{ 0xa3, 0xdf, 0x59, 0xf7, 0x8a, 0x2, 0x86, 0x2d }
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Compartments
|
||||
//---------------------------------------------------------------------
|
||||
// {101011C5-CF72-4F0C-A515-153019593F10}
|
||||
extern const GUID SampleIMEGuidCompartmentDoubleSingleByte = {
|
||||
0x101011c5,
|
||||
0xcf72,
|
||||
0x4f0c,
|
||||
{ 0xa5, 0x15, 0x15, 0x30, 0x19, 0x59, 0x3f, 0x10 }
|
||||
};
|
||||
|
||||
// {DD321BCC-A7F8-4561-9B61-9B3508C9BA97}
|
||||
extern const GUID SampleIMEGuidCompartmentPunctuation = {
|
||||
0xdd321bcc,
|
||||
0xa7f8,
|
||||
0x4561,
|
||||
{ 0x9b, 0x61, 0x9b, 0x35, 0x8, 0xc9, 0xba, 0x97 }
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// LanguageBars
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
// {89BE500C-9462-4070-9DB0-B467BB051327}
|
||||
extern const GUID SampleIMEGuidLangBarIMEMode = {
|
||||
0x89be500c,
|
||||
0x9462,
|
||||
0x4070,
|
||||
{ 0x9d, 0xb0, 0xb4, 0x67, 0xbb, 0x5, 0x13, 0x27 }
|
||||
};
|
||||
|
||||
// {6A11D9DE-46DB-455B-A257-2EB615746BF4}
|
||||
extern const GUID SampleIMEGuidLangBarDoubleSingleByte = {
|
||||
0x6a11d9de,
|
||||
0x46db,
|
||||
0x455b,
|
||||
{ 0xa2, 0x57, 0x2e, 0xb6, 0x15, 0x74, 0x6b, 0xf4 }
|
||||
};
|
||||
|
||||
// {F29C731A-A51E-49FB-8A3C-EE51752912E2}
|
||||
extern const GUID SampleIMEGuidLangBarPunctuation = {
|
||||
0xf29c731a,
|
||||
0xa51e,
|
||||
0x49fb,
|
||||
{ 0x8a, 0x3c, 0xee, 0x51, 0x75, 0x29, 0x12, 0xe2 }
|
||||
};
|
||||
|
||||
// {4C802E2C-8140-4436-A5E5-F7C544EBC9CD}
|
||||
extern const GUID SampleIMEGuidDisplayAttributeInput = {
|
||||
0x4c802e2c,
|
||||
0x8140,
|
||||
0x4436,
|
||||
{ 0xa5, 0xe5, 0xf7, 0xc5, 0x44, 0xeb, 0xc9, 0xcd }
|
||||
};
|
||||
|
||||
// {9A1CC683-F2A7-4701-9C6E-2DA69A5CD474}
|
||||
extern const GUID SampleIMEGuidDisplayAttributeConverted = {
|
||||
0x9a1cc683,
|
||||
0xf2a7,
|
||||
0x4701,
|
||||
{ 0x9c, 0x6e, 0x2d, 0xa6, 0x9a, 0x5c, 0xd4, 0x74 }
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// UI element
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
// {84B0749F-8DE7-4732-907A-3BCB150A01A8}
|
||||
extern const GUID SampleIMEGuidCandUIElement = {
|
||||
0x84b0749f,
|
||||
0x8de7,
|
||||
0x4732,
|
||||
{ 0x90, 0x7a, 0x3b, 0xcb, 0x15, 0xa, 0x1, 0xa8 }
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Unicode byte order mark
|
||||
//---------------------------------------------------------------------
|
||||
extern const WCHAR UnicodeByteOrderMark = 0xFEFF;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// dictionary table delimiter
|
||||
//---------------------------------------------------------------------
|
||||
extern const WCHAR KeywordDelimiter = L'=';
|
||||
extern const WCHAR StringDelimiter = L'\"';
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// defined item in setting file table [PreservedKey] section
|
||||
//---------------------------------------------------------------------
|
||||
extern const WCHAR ImeModeDescription[] = L"Chinese/English input (Shift)";
|
||||
extern const int ImeModeOnIcoIndex = IME_MODE_ON_ICON_INDEX;
|
||||
extern const int ImeModeOffIcoIndex = IME_MODE_OFF_ICON_INDEX;
|
||||
|
||||
extern const WCHAR DoubleSingleByteDescription[] = L"Double/Single byte (Shift+Space)";
|
||||
extern const int DoubleSingleByteOnIcoIndex = IME_DOUBLE_ON_INDEX;
|
||||
extern const int DoubleSingleByteOffIcoIndex = IME_DOUBLE_OFF_INDEX;
|
||||
|
||||
extern const WCHAR PunctuationDescription[] = L"Chinese/English punctuation (Ctrl+.)";
|
||||
extern const int PunctuationOnIcoIndex = IME_PUNCTUATION_ON_INDEX;
|
||||
extern const int PunctuationOffIcoIndex = IME_PUNCTUATION_OFF_INDEX;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// defined item in setting file table [LanguageBar] section
|
||||
//---------------------------------------------------------------------
|
||||
extern const WCHAR LangbarImeModeDescription[] = L"Conversion mode";
|
||||
extern const WCHAR LangbarDoubleSingleByteDescription[] = L"Character width";
|
||||
extern const WCHAR LangbarPunctuationDescription[] = L"Punctuation";
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// windows class / titile / atom
|
||||
//---------------------------------------------------------------------
|
||||
extern const WCHAR CandidateClassName[] = L"SampleIME.CandidateWindow";
|
||||
ATOM AtomCandidateWindow;
|
||||
|
||||
extern const WCHAR ShadowClassName[] = L"SampleIME.ShadowWindow";
|
||||
ATOM AtomShadowWindow;
|
||||
|
||||
extern const WCHAR ScrollBarClassName[] = L"SampleIME.ScrollBarWindow";
|
||||
ATOM AtomScrollBarWindow;
|
||||
|
||||
BOOL RegisterWindowClass()
|
||||
{
|
||||
if (!CBaseWindow::_InitWindowClass(CandidateClassName, &AtomCandidateWindow))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (!CBaseWindow::_InitWindowClass(ShadowClassName, &AtomShadowWindow))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (!CBaseWindow::_InitWindowClass(ScrollBarClassName, &AtomScrollBarWindow))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// defined full width characters for Double/Single byte conversion
|
||||
//---------------------------------------------------------------------
|
||||
extern const WCHAR FullWidthCharTable[] = {
|
||||
// ! " # $ % & ' ( ) * + , - . /
|
||||
0x3000, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, 0xFF06, 0xFF07, 0xFF08, 0xFF09, 0xFF0A, 0xFF0B, 0xFF0C, 0xFF0D, 0xFF0E, 0xFF0F,
|
||||
// 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
|
||||
0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17, 0xFF18, 0xFF19, 0xFF1A, 0xFF1B, 0xFF1C, 0xFF1D, 0xFF1E, 0xFF1F,
|
||||
// @ A B C D E F G H I J K L M N 0
|
||||
0xFF20, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F,
|
||||
// P Q R S T U V W X Y Z [ \ ] ^ _
|
||||
0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A, 0xFF3B, 0xFF3C, 0xFF3D, 0xFF3E, 0xFF3F,
|
||||
// ' a b c d e f g h i j k l m n o
|
||||
0xFF40, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,
|
||||
// p q r s t u v w x y z { | } ~
|
||||
0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0xFF5B, 0xFF5C, 0xFF5D, 0xFF5E
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// defined punctuation characters
|
||||
//---------------------------------------------------------------------
|
||||
extern const struct _PUNCTUATION PunctuationTable[14] = {
|
||||
{L'!', 0xFF01},
|
||||
{L'$', 0xFFE5},
|
||||
{L'&', 0x2014},
|
||||
{L'(', 0xFF08},
|
||||
{L')', 0xFF09},
|
||||
{L',', 0xFF0C},
|
||||
{L'.', 0x3002},
|
||||
{L':', 0xFF1A},
|
||||
{L';', 0xFF1B},
|
||||
{L'?', 0xFF1F},
|
||||
{L'@', 0x00B7},
|
||||
{L'\\', 0x3001},
|
||||
{L'^', 0x2026},
|
||||
{L'_', 0x2014}
|
||||
};
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CheckModifiers
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#define TF_MOD_ALLALT (TF_MOD_RALT | TF_MOD_LALT | TF_MOD_ALT)
|
||||
#define TF_MOD_ALLCONTROL (TF_MOD_RCONTROL | TF_MOD_LCONTROL | TF_MOD_CONTROL)
|
||||
#define TF_MOD_ALLSHIFT (TF_MOD_RSHIFT | TF_MOD_LSHIFT | TF_MOD_SHIFT)
|
||||
#define TF_MOD_RLALT (TF_MOD_RALT | TF_MOD_LALT)
|
||||
#define TF_MOD_RLCONTROL (TF_MOD_RCONTROL | TF_MOD_LCONTROL)
|
||||
#define TF_MOD_RLSHIFT (TF_MOD_RSHIFT | TF_MOD_LSHIFT)
|
||||
|
||||
#define CheckMod(m0, m1, mod) \
|
||||
if (m1 & TF_MOD_ ## mod ##) \
|
||||
{ \
|
||||
if (!(m0 & TF_MOD_ ## mod ##)) \
|
||||
{ \
|
||||
return FALSE; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if ((m1 ^ m0) & TF_MOD_RL ## mod ##) \
|
||||
{ \
|
||||
return FALSE; \
|
||||
} \
|
||||
} \
|
||||
|
||||
|
||||
|
||||
BOOL CheckModifiers(UINT modCurrent, UINT mod)
|
||||
{
|
||||
mod &= ~TF_MOD_ON_KEYUP;
|
||||
|
||||
if (mod & TF_MOD_IGNORE_ALL_MODIFIER)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (modCurrent == mod)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (modCurrent && !mod)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CheckMod(modCurrent, mod, ALT);
|
||||
CheckMod(modCurrent, mod, SHIFT);
|
||||
CheckMod(modCurrent, mod, CONTROL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// UpdateModifiers
|
||||
//
|
||||
// wParam - virtual-key code
|
||||
// lParam - [0-15] Repeat count
|
||||
// [16-23] Scan code
|
||||
// [24] Extended key
|
||||
// [25-28] Reserved
|
||||
// [29] Context code
|
||||
// [30] Previous key state
|
||||
// [31] Transition state
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
USHORT ModifiersValue = 0;
|
||||
BOOL IsShiftKeyDownOnly = FALSE;
|
||||
BOOL IsControlKeyDownOnly = FALSE;
|
||||
BOOL IsAltKeyDownOnly = FALSE;
|
||||
|
||||
BOOL UpdateModifiers(WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
// high-order bit : key down
|
||||
// low-order bit : toggled
|
||||
SHORT sksMenu = GetKeyState(VK_MENU);
|
||||
SHORT sksCtrl = GetKeyState(VK_CONTROL);
|
||||
SHORT sksShft = GetKeyState(VK_SHIFT);
|
||||
|
||||
switch (wParam & 0xff)
|
||||
{
|
||||
case VK_MENU:
|
||||
// is VK_MENU down?
|
||||
if (sksMenu & 0x8000)
|
||||
{
|
||||
// is extended key?
|
||||
if (lParam & 0x01000000)
|
||||
{
|
||||
ModifiersValue |= (TF_MOD_RALT | TF_MOD_ALT);
|
||||
}
|
||||
else
|
||||
{
|
||||
ModifiersValue |= (TF_MOD_LALT | TF_MOD_ALT);
|
||||
}
|
||||
|
||||
// is previous key state up?
|
||||
if (!(lParam & 0x40000000))
|
||||
{
|
||||
// is VK_CONTROL and VK_SHIFT up?
|
||||
if (!(sksCtrl & 0x8000) && !(sksShft & 0x8000))
|
||||
{
|
||||
IsAltKeyDownOnly = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
IsShiftKeyDownOnly = FALSE;
|
||||
IsControlKeyDownOnly = FALSE;
|
||||
IsAltKeyDownOnly = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case VK_CONTROL:
|
||||
// is VK_CONTROL down?
|
||||
if (sksCtrl & 0x8000)
|
||||
{
|
||||
// is extended key?
|
||||
if (lParam & 0x01000000)
|
||||
{
|
||||
ModifiersValue |= (TF_MOD_RCONTROL | TF_MOD_CONTROL);
|
||||
}
|
||||
else
|
||||
{
|
||||
ModifiersValue |= (TF_MOD_LCONTROL | TF_MOD_CONTROL);
|
||||
}
|
||||
|
||||
// is previous key state up?
|
||||
if (!(lParam & 0x40000000))
|
||||
{
|
||||
// is VK_SHIFT and VK_MENU up?
|
||||
if (!(sksShft & 0x8000) && !(sksMenu & 0x8000))
|
||||
{
|
||||
IsControlKeyDownOnly = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
IsShiftKeyDownOnly = FALSE;
|
||||
IsControlKeyDownOnly = FALSE;
|
||||
IsAltKeyDownOnly = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case VK_SHIFT:
|
||||
// is VK_SHIFT down?
|
||||
if (sksShft & 0x8000)
|
||||
{
|
||||
// is scan code 0x36(right shift)?
|
||||
if (((lParam >> 16) & 0x00ff) == 0x36)
|
||||
{
|
||||
ModifiersValue |= (TF_MOD_RSHIFT | TF_MOD_SHIFT);
|
||||
}
|
||||
else
|
||||
{
|
||||
ModifiersValue |= (TF_MOD_LSHIFT | TF_MOD_SHIFT);
|
||||
}
|
||||
|
||||
// is previous key state up?
|
||||
if (!(lParam & 0x40000000))
|
||||
{
|
||||
// is VK_MENU and VK_CONTROL up?
|
||||
if (!(sksMenu & 0x8000) && !(sksCtrl & 0x8000))
|
||||
{
|
||||
IsShiftKeyDownOnly = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
IsShiftKeyDownOnly = FALSE;
|
||||
IsControlKeyDownOnly = FALSE;
|
||||
IsAltKeyDownOnly = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
IsShiftKeyDownOnly = FALSE;
|
||||
IsControlKeyDownOnly = FALSE;
|
||||
IsAltKeyDownOnly = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(sksMenu & 0x8000))
|
||||
{
|
||||
ModifiersValue &= ~TF_MOD_ALLALT;
|
||||
}
|
||||
if (!(sksCtrl & 0x8000))
|
||||
{
|
||||
ModifiersValue &= ~TF_MOD_ALLCONTROL;
|
||||
}
|
||||
if (!(sksShft & 0x8000))
|
||||
{
|
||||
ModifiersValue &= ~TF_MOD_ALLSHIFT;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// override CompareElements
|
||||
//---------------------------------------------------------------------
|
||||
BOOL CompareElements(LCID locale, const CStringRange* pElement1, const CStringRange* pElement2)
|
||||
{
|
||||
return (CStringRange::Compare(locale, (CStringRange*)pElement1, (CStringRange*)pElement2) == CSTR_EQUAL) ? TRUE : FALSE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "private.h"
|
||||
#include "define.h"
|
||||
#include "SampleIMEBaseStructure.h"
|
||||
|
||||
void DllAddRef();
|
||||
void DllRelease();
|
||||
|
||||
|
||||
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 ATOM AtomCandidateWindow;
|
||||
extern ATOM AtomShadowWindow;
|
||||
extern ATOM AtomScrollBarWindow;
|
||||
|
||||
BOOL RegisterWindowClass();
|
||||
|
||||
extern LONG dllRefCount;
|
||||
|
||||
extern CRITICAL_SECTION CS;
|
||||
extern HFONT defaultlFontHandle; // Global font object we use everywhere
|
||||
|
||||
extern const CLSID SampleIMECLSID;
|
||||
extern const CLSID SampleIMEGuidProfile;
|
||||
extern const CLSID SampleIMEGuidImeModePreserveKey;
|
||||
extern const CLSID SampleIMEGuidDoubleSingleBytePreserveKey;
|
||||
extern const CLSID SampleIMEGuidPunctuationPreserveKey;
|
||||
|
||||
LRESULT CALLBACK ThreadKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
|
||||
BOOL CheckModifiers(UINT uModCurrent, UINT uMod);
|
||||
BOOL UpdateModifiers(WPARAM wParam, LPARAM lParam);
|
||||
|
||||
extern USHORT ModifiersValue;
|
||||
extern BOOL IsShiftKeyDownOnly;
|
||||
extern BOOL IsControlKeyDownOnly;
|
||||
extern BOOL IsAltKeyDownOnly;
|
||||
|
||||
extern const GUID SampleIMEGuidCompartmentDoubleSingleByte;
|
||||
extern const GUID SampleIMEGuidCompartmentPunctuation;
|
||||
|
||||
extern const WCHAR FullWidthCharTable[];
|
||||
extern const struct _PUNCTUATION PunctuationTable[14];
|
||||
|
||||
extern const GUID SampleIMEGuidLangBarIMEMode;
|
||||
extern const GUID SampleIMEGuidLangBarDoubleSingleByte;
|
||||
extern const GUID SampleIMEGuidLangBarPunctuation;
|
||||
|
||||
extern const GUID SampleIMEGuidDisplayAttributeInput;
|
||||
extern const GUID SampleIMEGuidDisplayAttributeConverted;
|
||||
|
||||
extern const GUID SampleIMEGuidCandUIElement;
|
||||
|
||||
extern const WCHAR UnicodeByteOrderMark;
|
||||
extern const WCHAR KeywordDelimiter;
|
||||
extern const WCHAR StringDelimiter;
|
||||
|
||||
extern const WCHAR ImeModeDescription[];
|
||||
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[];
|
||||
}
|
||||
@@ -0,0 +1,457 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "SampleIME.h"
|
||||
#include "CandidateListUIPresenter.h"
|
||||
#include "CompositionProcessorEngine.h"
|
||||
#include "KeyHandlerEditSession.h"
|
||||
#include "Compartment.h"
|
||||
|
||||
// 0xF003, 0xF004 are the keys that the touch keyboard sends for next/previous
|
||||
#define THIRDPARTY_NEXTPAGE static_cast<WORD>(0xF003)
|
||||
#define THIRDPARTY_PREVPAGE static_cast<WORD>(0xF004)
|
||||
|
||||
// Because the code mostly works with VKeys, here map a WCHAR back to a VKKey for certain
|
||||
// vkeys that the IME handles specially
|
||||
__inline UINT VKeyFromVKPacketAndWchar(UINT vk, WCHAR wch)
|
||||
{
|
||||
UINT vkRet = vk;
|
||||
if (LOWORD(vk) == VK_PACKET)
|
||||
{
|
||||
if (wch == L' ')
|
||||
{
|
||||
vkRet = VK_SPACE;
|
||||
}
|
||||
else if ((wch >= L'0') && (wch <= L'9'))
|
||||
{
|
||||
vkRet = static_cast<UINT>(wch);
|
||||
}
|
||||
else if ((wch >= L'a') && (wch <= L'z'))
|
||||
{
|
||||
vkRet = (UINT)(L'A') + ((UINT)(L'z') - static_cast<UINT>(wch));
|
||||
}
|
||||
else if ((wch >= L'A') && (wch <= L'Z'))
|
||||
{
|
||||
vkRet = static_cast<UINT>(wch);
|
||||
}
|
||||
else if (wch == THIRDPARTY_NEXTPAGE)
|
||||
{
|
||||
vkRet = VK_NEXT;
|
||||
}
|
||||
else if (wch == THIRDPARTY_PREVPAGE)
|
||||
{
|
||||
vkRet = VK_PRIOR;
|
||||
}
|
||||
}
|
||||
return vkRet;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _IsKeyEaten
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CSampleIME::_IsKeyEaten(_In_ ITfContext *pContext, UINT codeIn, _Out_ UINT *pCodeOut, _Out_writes_(1) WCHAR *pwch, _Out_opt_ _KEYSTROKE_STATE *pKeyState)
|
||||
{
|
||||
pContext;
|
||||
|
||||
*pCodeOut = codeIn;
|
||||
|
||||
BOOL isOpen = FALSE;
|
||||
CCompartment CompartmentKeyboardOpen(_pThreadMgr, _tfClientId, GUID_COMPARTMENT_KEYBOARD_OPENCLOSE);
|
||||
CompartmentKeyboardOpen._GetCompartmentBOOL(isOpen);
|
||||
|
||||
BOOL isDoubleSingleByte = FALSE;
|
||||
CCompartment CompartmentDoubleSingleByte(_pThreadMgr, _tfClientId, Global::SampleIMEGuidCompartmentDoubleSingleByte);
|
||||
CompartmentDoubleSingleByte._GetCompartmentBOOL(isDoubleSingleByte);
|
||||
|
||||
BOOL isPunctuation = FALSE;
|
||||
CCompartment CompartmentPunctuation(_pThreadMgr, _tfClientId, Global::SampleIMEGuidCompartmentPunctuation);
|
||||
CompartmentPunctuation._GetCompartmentBOOL(isPunctuation);
|
||||
|
||||
if (pKeyState)
|
||||
{
|
||||
pKeyState->Category = CATEGORY_NONE;
|
||||
pKeyState->Function = FUNCTION_NONE;
|
||||
}
|
||||
if (pwch)
|
||||
{
|
||||
*pwch = L'\0';
|
||||
}
|
||||
|
||||
// if the keyboard is disabled, we don't eat keys.
|
||||
if (_IsKeyboardDisabled())
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Map virtual key to character code
|
||||
//
|
||||
BOOL isTouchKeyboardSpecialKeys = FALSE;
|
||||
WCHAR wch = ConvertVKey(codeIn);
|
||||
*pCodeOut = VKeyFromVKPacketAndWchar(codeIn, wch);
|
||||
if ((wch == THIRDPARTY_NEXTPAGE) || (wch == THIRDPARTY_PREVPAGE))
|
||||
{
|
||||
// We always eat the above softkeyboard special keys
|
||||
isTouchKeyboardSpecialKeys = TRUE;
|
||||
if (pwch)
|
||||
{
|
||||
*pwch = wch;
|
||||
}
|
||||
}
|
||||
|
||||
// if the keyboard is closed, we don't eat keys, with the exception of the touch keyboard specials keys
|
||||
if (!isOpen && !isDoubleSingleByte && !isPunctuation)
|
||||
{
|
||||
return isTouchKeyboardSpecialKeys;
|
||||
}
|
||||
|
||||
if (pwch)
|
||||
{
|
||||
*pwch = wch;
|
||||
}
|
||||
|
||||
//
|
||||
// Get composition engine
|
||||
//
|
||||
CCompositionProcessorEngine *pCompositionProcessorEngine;
|
||||
pCompositionProcessorEngine = _pCompositionProcessorEngine;
|
||||
|
||||
if (isOpen)
|
||||
{
|
||||
//
|
||||
// The candidate or phrase list handles the keys through ITfKeyEventSink.
|
||||
//
|
||||
// eat only keys that CKeyHandlerEditSession can handles.
|
||||
//
|
||||
if (pCompositionProcessorEngine->IsVirtualKeyNeed(*pCodeOut, pwch, _IsComposing(), _candidateMode, _isCandidateWithWildcard, pKeyState))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Punctuation
|
||||
//
|
||||
if (pCompositionProcessorEngine->IsPunctuation(wch))
|
||||
{
|
||||
if ((_candidateMode == CANDIDATE_NONE) && isPunctuation)
|
||||
{
|
||||
if (pKeyState)
|
||||
{
|
||||
pKeyState->Category = CATEGORY_COMPOSING;
|
||||
pKeyState->Function = FUNCTION_PUNCTUATION;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Double/Single byte
|
||||
//
|
||||
if (isDoubleSingleByte && pCompositionProcessorEngine->IsDoubleSingleByte(wch))
|
||||
{
|
||||
if (_candidateMode == CANDIDATE_NONE)
|
||||
{
|
||||
if (pKeyState)
|
||||
{
|
||||
pKeyState->Category = CATEGORY_COMPOSING;
|
||||
pKeyState->Function = FUNCTION_DOUBLE_SINGLE_BYTE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return isTouchKeyboardSpecialKeys;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ConvertVKey
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
WCHAR CSampleIME::ConvertVKey(UINT code)
|
||||
{
|
||||
//
|
||||
// Map virtual key to scan code
|
||||
//
|
||||
UINT scanCode = 0;
|
||||
scanCode = MapVirtualKey(code, 0);
|
||||
|
||||
//
|
||||
// Keyboard state
|
||||
//
|
||||
BYTE abKbdState[256] = {'\0'};
|
||||
if (!GetKeyboardState(abKbdState))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Map virtual key to character code
|
||||
//
|
||||
WCHAR wch = '\0';
|
||||
if (ToUnicode(code, scanCode, abKbdState, &wch, 1, 0) == 1)
|
||||
{
|
||||
return wch;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _IsKeyboardDisabled
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CSampleIME::_IsKeyboardDisabled()
|
||||
{
|
||||
ITfDocumentMgr* pDocMgrFocus = nullptr;
|
||||
ITfContext* pContext = nullptr;
|
||||
BOOL isDisabled = FALSE;
|
||||
|
||||
if ((_pThreadMgr->GetFocus(&pDocMgrFocus) != S_OK) ||
|
||||
(pDocMgrFocus == nullptr))
|
||||
{
|
||||
// if there is no focus document manager object, the keyboard
|
||||
// is disabled.
|
||||
isDisabled = TRUE;
|
||||
}
|
||||
else if ((pDocMgrFocus->GetTop(&pContext) != S_OK) ||
|
||||
(pContext == nullptr))
|
||||
{
|
||||
// if there is no context object, the keyboard is disabled.
|
||||
isDisabled = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
CCompartment CompartmentKeyboardDisabled(_pThreadMgr, _tfClientId, GUID_COMPARTMENT_KEYBOARD_DISABLED);
|
||||
CompartmentKeyboardDisabled._GetCompartmentBOOL(isDisabled);
|
||||
|
||||
CCompartment CompartmentEmptyContext(_pThreadMgr, _tfClientId, GUID_COMPARTMENT_EMPTYCONTEXT);
|
||||
CompartmentEmptyContext._GetCompartmentBOOL(isDisabled);
|
||||
}
|
||||
|
||||
if (pContext)
|
||||
{
|
||||
pContext->Release();
|
||||
}
|
||||
|
||||
if (pDocMgrFocus)
|
||||
{
|
||||
pDocMgrFocus->Release();
|
||||
}
|
||||
|
||||
return isDisabled;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfKeyEventSink::OnSetFocus
|
||||
//
|
||||
// Called by the system whenever this service gets the keystroke device focus.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CSampleIME::OnSetFocus(BOOL fForeground)
|
||||
{
|
||||
fForeground;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfKeyEventSink::OnTestKeyDown
|
||||
//
|
||||
// Called by the system to query this service wants a potential keystroke.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CSampleIME::OnTestKeyDown(ITfContext *pContext, WPARAM wParam, LPARAM lParam, BOOL *pIsEaten)
|
||||
{
|
||||
Global::UpdateModifiers(wParam, lParam);
|
||||
|
||||
_KEYSTROKE_STATE KeystrokeState;
|
||||
WCHAR wch = '\0';
|
||||
UINT code = 0;
|
||||
*pIsEaten = _IsKeyEaten(pContext, (UINT)wParam, &code, &wch, &KeystrokeState);
|
||||
|
||||
if (KeystrokeState.Category == CATEGORY_INVOKE_COMPOSITION_EDIT_SESSION)
|
||||
{
|
||||
//
|
||||
// Invoke key handler edit session
|
||||
//
|
||||
KeystrokeState.Category = CATEGORY_COMPOSING;
|
||||
|
||||
_InvokeKeyHandler(pContext, code, wch, (DWORD)lParam, KeystrokeState);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfKeyEventSink::OnKeyDown
|
||||
//
|
||||
// Called by the system to offer this service a keystroke. If *pIsEaten == TRUE
|
||||
// on exit, the application will not handle the keystroke.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CSampleIME::OnKeyDown(ITfContext *pContext, WPARAM wParam, LPARAM lParam, BOOL *pIsEaten)
|
||||
{
|
||||
Global::UpdateModifiers(wParam, lParam);
|
||||
|
||||
_KEYSTROKE_STATE KeystrokeState;
|
||||
WCHAR wch = '\0';
|
||||
UINT code = 0;
|
||||
|
||||
*pIsEaten = _IsKeyEaten(pContext, (UINT)wParam, &code, &wch, &KeystrokeState);
|
||||
|
||||
if (*pIsEaten)
|
||||
{
|
||||
bool needInvokeKeyHandler = true;
|
||||
//
|
||||
// Invoke key handler edit session
|
||||
//
|
||||
if (code == VK_ESCAPE)
|
||||
{
|
||||
KeystrokeState.Category = CATEGORY_COMPOSING;
|
||||
}
|
||||
|
||||
// Always eat THIRDPARTY_NEXTPAGE and THIRDPARTY_PREVPAGE keys, but don't always process them.
|
||||
if ((wch == THIRDPARTY_NEXTPAGE) || (wch == THIRDPARTY_PREVPAGE))
|
||||
{
|
||||
needInvokeKeyHandler = !((KeystrokeState.Category == CATEGORY_NONE) && (KeystrokeState.Function == FUNCTION_NONE));
|
||||
}
|
||||
|
||||
if (needInvokeKeyHandler)
|
||||
{
|
||||
_InvokeKeyHandler(pContext, code, wch, (DWORD)lParam, KeystrokeState);
|
||||
}
|
||||
}
|
||||
else if (KeystrokeState.Category == CATEGORY_INVOKE_COMPOSITION_EDIT_SESSION)
|
||||
{
|
||||
// Invoke key handler edit session
|
||||
KeystrokeState.Category = CATEGORY_COMPOSING;
|
||||
_InvokeKeyHandler(pContext, code, wch, (DWORD)lParam, KeystrokeState);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfKeyEventSink::OnTestKeyUp
|
||||
//
|
||||
// Called by the system to query this service wants a potential keystroke.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CSampleIME::OnTestKeyUp(ITfContext *pContext, WPARAM wParam, LPARAM lParam, BOOL *pIsEaten)
|
||||
{
|
||||
if (pIsEaten == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
Global::UpdateModifiers(wParam, lParam);
|
||||
|
||||
WCHAR wch = '\0';
|
||||
UINT code = 0;
|
||||
|
||||
*pIsEaten = _IsKeyEaten(pContext, (UINT)wParam, &code, &wch, NULL);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfKeyEventSink::OnKeyUp
|
||||
//
|
||||
// Called by the system to offer this service a keystroke. If *pIsEaten == TRUE
|
||||
// on exit, the application will not handle the keystroke.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CSampleIME::OnKeyUp(ITfContext *pContext, WPARAM wParam, LPARAM lParam, BOOL *pIsEaten)
|
||||
{
|
||||
Global::UpdateModifiers(wParam, lParam);
|
||||
|
||||
WCHAR wch = '\0';
|
||||
UINT code = 0;
|
||||
|
||||
*pIsEaten = _IsKeyEaten(pContext, (UINT)wParam, &code, &wch, NULL);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfKeyEventSink::OnPreservedKey
|
||||
//
|
||||
// Called when a hotkey (registered by us, or by the system) is typed.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CSampleIME::OnPreservedKey(ITfContext *pContext, REFGUID rguid, BOOL *pIsEaten)
|
||||
{
|
||||
pContext;
|
||||
|
||||
CCompositionProcessorEngine *pCompositionProcessorEngine;
|
||||
pCompositionProcessorEngine = _pCompositionProcessorEngine;
|
||||
|
||||
pCompositionProcessorEngine->OnPreservedKey(rguid, pIsEaten, _GetThreadMgr(), _GetClientId());
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _InitKeyEventSink
|
||||
//
|
||||
// Advise a keystroke sink.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CSampleIME::_InitKeyEventSink()
|
||||
{
|
||||
ITfKeystrokeMgr* pKeystrokeMgr = nullptr;
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (FAILED(_pThreadMgr->QueryInterface(IID_ITfKeystrokeMgr, (void **)&pKeystrokeMgr)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hr = pKeystrokeMgr->AdviseKeyEventSink(_tfClientId, (ITfKeyEventSink *)this, TRUE);
|
||||
|
||||
pKeystrokeMgr->Release();
|
||||
|
||||
return (hr == S_OK);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _UninitKeyEventSink
|
||||
//
|
||||
// Unadvise a keystroke sink. Assumes we have advised one already.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CSampleIME::_UninitKeyEventSink()
|
||||
{
|
||||
ITfKeystrokeMgr* pKeystrokeMgr = nullptr;
|
||||
|
||||
if (FAILED(_pThreadMgr->QueryInterface(IID_ITfKeystrokeMgr, (void **)&pKeystrokeMgr)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pKeystrokeMgr->UnadviseKeyEventSink(_tfClientId);
|
||||
|
||||
pKeystrokeMgr->Release();
|
||||
}
|
||||
@@ -0,0 +1,635 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "EditSession.h"
|
||||
#include "SampleIME.h"
|
||||
#include "CandidateListUIPresenter.h"
|
||||
#include "CompositionProcessorEngine.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CSampleIME class
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _IsRangeCovered
|
||||
//
|
||||
// Returns TRUE if pRangeTest is entirely contained within pRangeCover.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CSampleIME::_IsRangeCovered(TfEditCookie ec, _In_ ITfRange *pRangeTest, _In_ ITfRange *pRangeCover)
|
||||
{
|
||||
LONG lResult = 0;;
|
||||
|
||||
if (FAILED(pRangeCover->CompareStart(ec, pRangeTest, TF_ANCHOR_START, &lResult))
|
||||
|| (lResult > 0))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (FAILED(pRangeCover->CompareEnd(ec, pRangeTest, TF_ANCHOR_END, &lResult))
|
||||
|| (lResult < 0))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _DeleteCandidateList
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
VOID CSampleIME::_DeleteCandidateList(BOOL isForce, _In_opt_ ITfContext *pContext)
|
||||
{
|
||||
isForce;pContext;
|
||||
|
||||
CCompositionProcessorEngine* pCompositionProcessorEngine = nullptr;
|
||||
pCompositionProcessorEngine = _pCompositionProcessorEngine;
|
||||
pCompositionProcessorEngine->PurgeVirtualKey();
|
||||
|
||||
if (_pCandidateListUIPresenter)
|
||||
{
|
||||
_pCandidateListUIPresenter->_EndCandidateList();
|
||||
|
||||
_candidateMode = CANDIDATE_NONE;
|
||||
_isCandidateWithWildcard = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _HandleComplete
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_HandleComplete(TfEditCookie ec, _In_ ITfContext *pContext)
|
||||
{
|
||||
_DeleteCandidateList(FALSE, pContext);
|
||||
|
||||
// just terminate the composition
|
||||
_TerminateComposition(ec, pContext);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _HandleCancel
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_HandleCancel(TfEditCookie ec, _In_ ITfContext *pContext)
|
||||
{
|
||||
_RemoveDummyCompositionForComposing(ec, _pComposition);
|
||||
|
||||
_DeleteCandidateList(FALSE, pContext);
|
||||
|
||||
_TerminateComposition(ec, pContext);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _HandleCompositionInput
|
||||
//
|
||||
// If the keystroke happens within a composition, eat the key and return S_OK.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_HandleCompositionInput(TfEditCookie ec, _In_ ITfContext *pContext, WCHAR wch)
|
||||
{
|
||||
ITfRange* pRangeComposition = nullptr;
|
||||
TF_SELECTION tfSelection;
|
||||
ULONG fetched = 0;
|
||||
BOOL isCovered = TRUE;
|
||||
|
||||
CCompositionProcessorEngine* pCompositionProcessorEngine = nullptr;
|
||||
pCompositionProcessorEngine = _pCompositionProcessorEngine;
|
||||
|
||||
if ((_pCandidateListUIPresenter != nullptr) && (_candidateMode != CANDIDATE_INCREMENTAL))
|
||||
{
|
||||
_HandleCompositionFinalize(ec, pContext, FALSE);
|
||||
}
|
||||
|
||||
// Start the new (std::nothrow) compositon if there is no composition.
|
||||
if (!_IsComposing())
|
||||
{
|
||||
_StartComposition(pContext);
|
||||
}
|
||||
|
||||
// first, test where a keystroke would go in the document if we did an insert
|
||||
if (pContext->GetSelection(ec, TF_DEFAULT_SELECTION, 1, &tfSelection, &fetched) != S_OK || fetched != 1)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
// is the insertion point covered by a composition?
|
||||
if (SUCCEEDED(_pComposition->GetRange(&pRangeComposition)))
|
||||
{
|
||||
isCovered = _IsRangeCovered(ec, tfSelection.range, pRangeComposition);
|
||||
|
||||
pRangeComposition->Release();
|
||||
|
||||
if (!isCovered)
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Add virtual key to composition processor engine
|
||||
pCompositionProcessorEngine->AddVirtualKey(wch);
|
||||
|
||||
_HandleCompositionInputWorker(pCompositionProcessorEngine, ec, pContext);
|
||||
|
||||
Exit:
|
||||
tfSelection.range->Release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _HandleCompositionInputWorker
|
||||
//
|
||||
// If the keystroke happens within a composition, eat the key and return S_OK.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_HandleCompositionInputWorker(_In_ CCompositionProcessorEngine *pCompositionProcessorEngine, TfEditCookie ec, _In_ ITfContext *pContext)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
CSampleImeArray<CStringRange> readingStrings;
|
||||
BOOL isWildcardIncluded = TRUE;
|
||||
|
||||
//
|
||||
// Get reading string from composition processor engine
|
||||
//
|
||||
pCompositionProcessorEngine->GetReadingStrings(&readingStrings, &isWildcardIncluded);
|
||||
|
||||
for (UINT index = 0; index < readingStrings.Count(); index++)
|
||||
{
|
||||
hr = _AddComposingAndChar(ec, pContext, readingStrings.GetAt(index));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Get candidate string from composition processor engine
|
||||
//
|
||||
CSampleImeArray<CCandidateListItem> candidateList;
|
||||
|
||||
pCompositionProcessorEngine->GetCandidateList(&candidateList, TRUE, FALSE);
|
||||
|
||||
if ((candidateList.Count()))
|
||||
{
|
||||
hr = _CreateAndStartCandidate(pCompositionProcessorEngine, ec, pContext);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
_pCandidateListUIPresenter->_ClearList();
|
||||
_pCandidateListUIPresenter->_SetText(&candidateList, TRUE);
|
||||
}
|
||||
}
|
||||
else if (_pCandidateListUIPresenter)
|
||||
{
|
||||
_pCandidateListUIPresenter->_ClearList();
|
||||
}
|
||||
else if (readingStrings.Count() && isWildcardIncluded)
|
||||
{
|
||||
hr = _CreateAndStartCandidate(pCompositionProcessorEngine, ec, pContext);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
_pCandidateListUIPresenter->_ClearList();
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _CreateAndStartCandidate
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_CreateAndStartCandidate(_In_ CCompositionProcessorEngine *pCompositionProcessorEngine, TfEditCookie ec, _In_ ITfContext *pContext)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (((_candidateMode == CANDIDATE_PHRASE) && (_pCandidateListUIPresenter))
|
||||
|| ((_candidateMode == CANDIDATE_NONE) && (_pCandidateListUIPresenter)))
|
||||
{
|
||||
// Recreate candidate list
|
||||
_pCandidateListUIPresenter->_EndCandidateList();
|
||||
delete _pCandidateListUIPresenter;
|
||||
_pCandidateListUIPresenter = nullptr;
|
||||
|
||||
_candidateMode = CANDIDATE_NONE;
|
||||
_isCandidateWithWildcard = FALSE;
|
||||
}
|
||||
|
||||
if (_pCandidateListUIPresenter == nullptr)
|
||||
{
|
||||
_pCandidateListUIPresenter = new (std::nothrow) CCandidateListUIPresenter(this, Global::AtomCandidateWindow,
|
||||
CATEGORY_CANDIDATE,
|
||||
pCompositionProcessorEngine->GetCandidateListIndexRange(),
|
||||
FALSE);
|
||||
if (!_pCandidateListUIPresenter)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
_candidateMode = CANDIDATE_INCREMENTAL;
|
||||
_isCandidateWithWildcard = FALSE;
|
||||
|
||||
// we don't cache the document manager object. So get it from pContext.
|
||||
ITfDocumentMgr* pDocumentMgr = nullptr;
|
||||
if (SUCCEEDED(pContext->GetDocumentMgr(&pDocumentMgr)))
|
||||
{
|
||||
// get the composition range.
|
||||
ITfRange* pRange = nullptr;
|
||||
if (SUCCEEDED(_pComposition->GetRange(&pRange)))
|
||||
{
|
||||
hr = _pCandidateListUIPresenter->_StartCandidateList(_tfClientId, pDocumentMgr, pContext, ec, pRange, pCompositionProcessorEngine->GetCandidateWindowWidth());
|
||||
pRange->Release();
|
||||
}
|
||||
pDocumentMgr->Release();
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _HandleCompositionFinalize
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_HandleCompositionFinalize(TfEditCookie ec, _In_ ITfContext *pContext, BOOL isCandidateList)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (isCandidateList && _pCandidateListUIPresenter)
|
||||
{
|
||||
// Finalize selected candidate string from CCandidateListUIPresenter
|
||||
DWORD_PTR candidateLen = 0;
|
||||
const WCHAR *pCandidateString = nullptr;
|
||||
|
||||
candidateLen = _pCandidateListUIPresenter->_GetSelectedCandidateString(&pCandidateString);
|
||||
|
||||
CStringRange candidateString;
|
||||
candidateString.Set(pCandidateString, candidateLen);
|
||||
|
||||
if (candidateLen)
|
||||
{
|
||||
// Finalize character
|
||||
hr = _AddCharAndFinalize(ec, pContext, &candidateString);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Finalize current text store strings
|
||||
if (_IsComposing())
|
||||
{
|
||||
ULONG fetched = 0;
|
||||
TF_SELECTION tfSelection;
|
||||
|
||||
if (FAILED(pContext->GetSelection(ec, TF_DEFAULT_SELECTION, 1, &tfSelection, &fetched)) || fetched != 1)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
ITfRange* pRangeComposition = nullptr;
|
||||
if (SUCCEEDED(_pComposition->GetRange(&pRangeComposition)))
|
||||
{
|
||||
if (_IsRangeCovered(ec, tfSelection.range, pRangeComposition))
|
||||
{
|
||||
_EndComposition(pContext);
|
||||
}
|
||||
|
||||
pRangeComposition->Release();
|
||||
}
|
||||
|
||||
tfSelection.range->Release();
|
||||
}
|
||||
}
|
||||
|
||||
_HandleCancel(ec, pContext);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _HandleCompositionConvert
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_HandleCompositionConvert(TfEditCookie ec, _In_ ITfContext *pContext, BOOL isWildcardSearch)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
CSampleImeArray<CCandidateListItem> candidateList;
|
||||
|
||||
//
|
||||
// Get candidate string from composition processor engine
|
||||
//
|
||||
CCompositionProcessorEngine* pCompositionProcessorEngine = nullptr;
|
||||
pCompositionProcessorEngine = _pCompositionProcessorEngine;
|
||||
pCompositionProcessorEngine->GetCandidateList(&candidateList, FALSE, isWildcardSearch);
|
||||
|
||||
// If there is no candlidate listin the current reading string, we don't do anything. Just wait for
|
||||
// next char to be ready for the conversion with it.
|
||||
int nCount = candidateList.Count();
|
||||
if (nCount)
|
||||
{
|
||||
if (_pCandidateListUIPresenter)
|
||||
{
|
||||
_pCandidateListUIPresenter->_EndCandidateList();
|
||||
delete _pCandidateListUIPresenter;
|
||||
_pCandidateListUIPresenter = nullptr;
|
||||
|
||||
_candidateMode = CANDIDATE_NONE;
|
||||
_isCandidateWithWildcard = FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// create an instance of the candidate list class.
|
||||
//
|
||||
if (_pCandidateListUIPresenter == nullptr)
|
||||
{
|
||||
_pCandidateListUIPresenter = new (std::nothrow) CCandidateListUIPresenter(this, Global::AtomCandidateWindow,
|
||||
CATEGORY_CANDIDATE,
|
||||
pCompositionProcessorEngine->GetCandidateListIndexRange(),
|
||||
FALSE);
|
||||
if (!_pCandidateListUIPresenter)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
_candidateMode = CANDIDATE_ORIGINAL;
|
||||
}
|
||||
|
||||
_isCandidateWithWildcard = isWildcardSearch;
|
||||
|
||||
// we don't cache the document manager object. So get it from pContext.
|
||||
ITfDocumentMgr* pDocumentMgr = nullptr;
|
||||
if (SUCCEEDED(pContext->GetDocumentMgr(&pDocumentMgr)))
|
||||
{
|
||||
// get the composition range.
|
||||
ITfRange* pRange = nullptr;
|
||||
if (SUCCEEDED(_pComposition->GetRange(&pRange)))
|
||||
{
|
||||
hr = _pCandidateListUIPresenter->_StartCandidateList(_tfClientId, pDocumentMgr, pContext, ec, pRange, pCompositionProcessorEngine->GetCandidateWindowWidth());
|
||||
pRange->Release();
|
||||
}
|
||||
pDocumentMgr->Release();
|
||||
}
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
_pCandidateListUIPresenter->_SetText(&candidateList, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _HandleCompositionBackspace
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_HandleCompositionBackspace(TfEditCookie ec, _In_ ITfContext *pContext)
|
||||
{
|
||||
ITfRange* pRangeComposition = nullptr;
|
||||
TF_SELECTION tfSelection;
|
||||
ULONG fetched = 0;
|
||||
BOOL isCovered = TRUE;
|
||||
|
||||
// Start the new (std::nothrow) compositon if there is no composition.
|
||||
if (!_IsComposing())
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// first, test where a keystroke would go in the document if we did an insert
|
||||
if (FAILED(pContext->GetSelection(ec, TF_DEFAULT_SELECTION, 1, &tfSelection, &fetched)) || fetched != 1)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
// is the insertion point covered by a composition?
|
||||
if (SUCCEEDED(_pComposition->GetRange(&pRangeComposition)))
|
||||
{
|
||||
isCovered = _IsRangeCovered(ec, tfSelection.range, pRangeComposition);
|
||||
|
||||
pRangeComposition->Release();
|
||||
|
||||
if (!isCovered)
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Add virtual key to composition processor engine
|
||||
//
|
||||
CCompositionProcessorEngine* pCompositionProcessorEngine = nullptr;
|
||||
pCompositionProcessorEngine = _pCompositionProcessorEngine;
|
||||
|
||||
DWORD_PTR vKeyLen = pCompositionProcessorEngine->GetVirtualKeyLength();
|
||||
|
||||
if (vKeyLen)
|
||||
{
|
||||
pCompositionProcessorEngine->RemoveVirtualKey(vKeyLen - 1);
|
||||
|
||||
if (pCompositionProcessorEngine->GetVirtualKeyLength())
|
||||
{
|
||||
_HandleCompositionInputWorker(pCompositionProcessorEngine, ec, pContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
_HandleCancel(ec, pContext);
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
tfSelection.range->Release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _HandleCompositionArrowKey
|
||||
//
|
||||
// Update the selection within a composition.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_HandleCompositionArrowKey(TfEditCookie ec, _In_ ITfContext *pContext, KEYSTROKE_FUNCTION keyFunction)
|
||||
{
|
||||
ITfRange* pRangeComposition = nullptr;
|
||||
TF_SELECTION tfSelection;
|
||||
ULONG fetched = 0;
|
||||
|
||||
// get the selection
|
||||
if (FAILED(pContext->GetSelection(ec, TF_DEFAULT_SELECTION, 1, &tfSelection, &fetched))
|
||||
|| fetched != 1)
|
||||
{
|
||||
// no selection, eat the keystroke
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// get the composition range
|
||||
if (FAILED(_pComposition->GetRange(&pRangeComposition)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
// For incremental candidate list
|
||||
if (_pCandidateListUIPresenter)
|
||||
{
|
||||
_pCandidateListUIPresenter->AdviseUIChangedByArrowKey(keyFunction);
|
||||
}
|
||||
|
||||
pContext->SetSelection(ec, 1, &tfSelection);
|
||||
|
||||
pRangeComposition->Release();
|
||||
|
||||
Exit:
|
||||
tfSelection.range->Release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _HandleCompositionPunctuation
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_HandleCompositionPunctuation(TfEditCookie ec, _In_ ITfContext *pContext, WCHAR wch)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (_candidateMode != CANDIDATE_NONE && _pCandidateListUIPresenter)
|
||||
{
|
||||
DWORD_PTR candidateLen = 0;
|
||||
const WCHAR* pCandidateString = nullptr;
|
||||
|
||||
candidateLen = _pCandidateListUIPresenter->_GetSelectedCandidateString(&pCandidateString);
|
||||
|
||||
CStringRange candidateString;
|
||||
candidateString.Set(pCandidateString, candidateLen);
|
||||
|
||||
if (candidateLen)
|
||||
{
|
||||
_AddComposingAndChar(ec, pContext, &candidateString);
|
||||
}
|
||||
}
|
||||
//
|
||||
// Get punctuation char from composition processor engine
|
||||
//
|
||||
CCompositionProcessorEngine* pCompositionProcessorEngine = nullptr;
|
||||
pCompositionProcessorEngine = _pCompositionProcessorEngine;
|
||||
|
||||
WCHAR punctuation = pCompositionProcessorEngine->GetPunctuation(wch);
|
||||
|
||||
CStringRange punctuationString;
|
||||
punctuationString.Set(&punctuation, 1);
|
||||
|
||||
// Finalize character
|
||||
hr = _AddCharAndFinalize(ec, pContext, &punctuationString);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
_HandleCancel(ec, pContext);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _HandleCompositionDoubleSingleByte
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_HandleCompositionDoubleSingleByte(TfEditCookie ec, _In_ ITfContext *pContext, WCHAR wch)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
WCHAR fullWidth = Global::FullWidthCharTable[wch - 0x20];
|
||||
|
||||
CStringRange fullWidthString;
|
||||
fullWidthString.Set(&fullWidth, 1);
|
||||
|
||||
// Finalize character
|
||||
hr = _AddCharAndFinalize(ec, pContext, &fullWidthString);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
_HandleCancel(ec, pContext);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _InvokeKeyHandler
|
||||
//
|
||||
// This text service is interested in handling keystrokes to demonstrate the
|
||||
// use the compositions. Some apps will cancel compositions if they receive
|
||||
// keystrokes while a compositions is ongoing.
|
||||
//
|
||||
// param
|
||||
// [in] uCode - virtual key code of WM_KEYDOWN wParam
|
||||
// [in] dwFlags - WM_KEYDOWN lParam
|
||||
// [in] dwKeyFunction - Function regarding virtual key
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_InvokeKeyHandler(_In_ ITfContext *pContext, UINT code, WCHAR wch, DWORD flags, _KEYSTROKE_STATE keyState)
|
||||
{
|
||||
flags;
|
||||
|
||||
CKeyHandlerEditSession* pEditSession = nullptr;
|
||||
HRESULT hr = E_FAIL;
|
||||
|
||||
// we'll insert a char ourselves in place of this keystroke
|
||||
pEditSession = new (std::nothrow) CKeyHandlerEditSession(this, pContext, code, wch, keyState);
|
||||
if (pEditSession == nullptr)
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
//
|
||||
// Call CKeyHandlerEditSession::DoEditSession().
|
||||
//
|
||||
// Do not specify TF_ES_SYNC so edit session is not invoked on WinWord
|
||||
//
|
||||
hr = pContext->RequestEditSession(_tfClientId, pEditSession, TF_ES_ASYNCDONTCARE | TF_ES_READWRITE, &hr);
|
||||
|
||||
pEditSession->Release();
|
||||
|
||||
Exit:
|
||||
return hr;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "KeyHandlerEditSession.h"
|
||||
#include "EditSession.h"
|
||||
#include "SampleIME.h"
|
||||
#include "CompositionProcessorEngine.h"
|
||||
#include "KeyStateCategory.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ITfEditSession
|
||||
// CEditSessionBase
|
||||
// CKeyHandlerEditSession class
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CKeyHandlerEditSession::DoEditSession
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CKeyHandlerEditSession::DoEditSession(TfEditCookie ec)
|
||||
{
|
||||
HRESULT hResult = S_OK;
|
||||
|
||||
CKeyStateCategoryFactory* pKeyStateCategoryFactory = CKeyStateCategoryFactory::Instance();
|
||||
CKeyStateCategory* pKeyStateCategory = pKeyStateCategoryFactory->MakeKeyStateCategory(_KeyState.Category, _pTextService);
|
||||
|
||||
if (pKeyStateCategory)
|
||||
{
|
||||
KeyHandlerEditSessionDTO keyHandlerEditSessioDTO(ec, _pContext, _uCode,_wch, _KeyState.Function);
|
||||
hResult = pKeyStateCategory->KeyStateHandler(_KeyState.Function, keyHandlerEditSessioDTO);
|
||||
|
||||
pKeyStateCategory->Release();
|
||||
pKeyStateCategoryFactory->Release();
|
||||
}
|
||||
|
||||
return hResult;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "EditSession.h"
|
||||
#include "Globals.h"
|
||||
|
||||
class CKeyHandlerEditSession : public CEditSessionBase
|
||||
{
|
||||
public:
|
||||
CKeyHandlerEditSession(CSampleIME *pTextService, ITfContext *pContext, UINT uCode, WCHAR wch, _KEYSTROKE_STATE keyState) : CEditSessionBase(pTextService, pContext)
|
||||
{
|
||||
_uCode = uCode;
|
||||
_wch = wch;
|
||||
_KeyState = keyState;
|
||||
}
|
||||
|
||||
// ITfEditSession
|
||||
STDMETHODIMP DoEditSession(TfEditCookie ec);
|
||||
|
||||
private:
|
||||
UINT _uCode; // virtual key code
|
||||
WCHAR _wch; // character code
|
||||
_KEYSTROKE_STATE _KeyState; // key function regarding virtual key
|
||||
};
|
||||
@@ -0,0 +1,370 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "KeyStateCategory.h"
|
||||
|
||||
CKeyStateCategoryFactory* CKeyStateCategoryFactory::_instance;
|
||||
|
||||
CKeyStateCategoryFactory::CKeyStateCategoryFactory()
|
||||
{
|
||||
_instance = nullptr;
|
||||
}
|
||||
|
||||
CKeyStateCategoryFactory* CKeyStateCategoryFactory::Instance()
|
||||
{
|
||||
if (nullptr == _instance)
|
||||
{
|
||||
_instance = new (std::nothrow) CKeyStateCategoryFactory();
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
|
||||
CKeyStateCategory* CKeyStateCategoryFactory::MakeKeyStateCategory(KEYSTROKE_CATEGORY keyCategory, _In_ CSampleIME *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;
|
||||
|
||||
case CATEGORY_PHRASE:
|
||||
pKeyState = new (std::nothrow) CKeyStatePhrase(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_ CSampleIME *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_CONVERT:
|
||||
return HandleKeyConvert(dto);
|
||||
|
||||
case FUNCTION_CONVERT_WILDCARD:
|
||||
return HandleKeyConvertWildCard(dto);
|
||||
|
||||
case FUNCTION_CANCEL:
|
||||
return HandleKeyCancel(dto);
|
||||
|
||||
case FUNCTION_BACKSPACE:
|
||||
return HandleKeyBackspace(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);
|
||||
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
//_HandleCompositionBackspace
|
||||
HRESULT CKeyStateCategory::HandleKeyBackspace(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_ CSampleIME *pTextService) : CKeyStateCategory(pTextService)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyInput(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCompositionInput(dto.ec, dto.pContext, dto.wch);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyFinalizeTextStoreAndInput(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
_pTextService->_HandleCompositionFinalize(dto.ec, dto.pContext, FALSE);
|
||||
return _pTextService->_HandleCompositionInput(dto.ec, dto.pContext, dto.wch);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyFinalizeCandidatelist(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCompositionFinalize(dto.ec, dto.pContext, TRUE);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyConvert(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
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::HandleKeyBackspace(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCompositionBackspace(dto.ec, dto.pContext);
|
||||
}
|
||||
|
||||
HRESULT CKeyStateComposing::HandleKeyArrow(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCompositionArrowKey(dto.ec, dto.pContext, dto.arrowKey);
|
||||
}
|
||||
|
||||
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.wch);
|
||||
}
|
||||
|
||||
/*
|
||||
class CKeyStateCandidate
|
||||
*/
|
||||
CKeyStateCandidate::CKeyStateCandidate(_In_ CSampleIME *pTextService) : CKeyStateCategory(pTextService)
|
||||
{
|
||||
}
|
||||
|
||||
// _HandleCandidateInput
|
||||
HRESULT CKeyStateCandidate::HandleKeyFinalizeCandidatelist(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCandidateFinalize(dto.ec, dto.pContext);
|
||||
}
|
||||
|
||||
// HandleKeyFinalizeCandidatelistAndInput
|
||||
HRESULT CKeyStateCandidate::HandleKeyFinalizeCandidatelistAndInput(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
_pTextService->_HandleCandidateFinalize(dto.ec, dto.pContext);
|
||||
return _pTextService->_HandleCompositionInput(dto.ec, dto.pContext, dto.wch);
|
||||
}
|
||||
|
||||
//_HandleCandidateConvert
|
||||
HRESULT CKeyStateCandidate::HandleKeyConvert(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCandidateConvert(dto.ec, dto.pContext);
|
||||
}
|
||||
|
||||
//_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);
|
||||
}
|
||||
|
||||
//_HandleCandidateSelectByNumber
|
||||
HRESULT CKeyStateCandidate::HandleKeySelectByNumber(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCandidateSelectByNumber(dto.ec, dto.pContext, dto.code);
|
||||
}
|
||||
|
||||
/*
|
||||
class CKeyStatePhrase
|
||||
*/
|
||||
|
||||
CKeyStatePhrase::CKeyStatePhrase(_In_ CSampleIME *pTextService) : CKeyStateCategory(pTextService)
|
||||
{
|
||||
}
|
||||
|
||||
//HandleKeyFinalizeCandidatelist
|
||||
HRESULT CKeyStatePhrase::HandleKeyFinalizeCandidatelist(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandlePhraseFinalize(dto.ec, dto.pContext);
|
||||
}
|
||||
|
||||
//HandleKeyCancel
|
||||
HRESULT CKeyStatePhrase::HandleKeyCancel(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandleCancel(dto.ec, dto.pContext);
|
||||
}
|
||||
|
||||
//HandleKeyArrow
|
||||
HRESULT CKeyStatePhrase::HandleKeyArrow(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandlePhraseArrowKey(dto.ec, dto.pContext, dto.arrowKey);
|
||||
}
|
||||
|
||||
//HandleKeySelectByNumber
|
||||
HRESULT CKeyStatePhrase::HandleKeySelectByNumber(KeyHandlerEditSessionDTO dto)
|
||||
{
|
||||
return _pTextService->_HandlePhraseSelectByNumber(dto.ec, dto.pContext, dto.code);
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#pragma once
|
||||
#include "Globals.h"
|
||||
#include "Private.h"
|
||||
#include "SampleIME.h"
|
||||
|
||||
class CKeyStateCategory;
|
||||
|
||||
class CKeyStateCategoryFactory
|
||||
{
|
||||
public:
|
||||
static CKeyStateCategoryFactory* Instance();
|
||||
CKeyStateCategory* MakeKeyStateCategory(KEYSTROKE_CATEGORY keyCategory, _In_ CSampleIME *pTextService);
|
||||
void Release();
|
||||
|
||||
protected:
|
||||
CKeyStateCategoryFactory();
|
||||
|
||||
private:
|
||||
static CKeyStateCategoryFactory* _instance;
|
||||
|
||||
};
|
||||
|
||||
typedef struct KeyHandlerEditSessionDTO
|
||||
{
|
||||
KeyHandlerEditSessionDTO::KeyHandlerEditSessionDTO(TfEditCookie tFEC, _In_ ITfContext *pTfContext, UINT virualCode, WCHAR inputChar, KEYSTROKE_FUNCTION arrowKeyFunction)
|
||||
{
|
||||
ec = tFEC;
|
||||
pContext = pTfContext;
|
||||
code = virualCode;
|
||||
wch = inputChar;
|
||||
arrowKey = arrowKeyFunction;
|
||||
}
|
||||
|
||||
TfEditCookie ec;
|
||||
ITfContext* pContext;
|
||||
UINT code;
|
||||
WCHAR wch;
|
||||
KEYSTROKE_FUNCTION arrowKey;
|
||||
}KeyHandlerEditSessionDTO;
|
||||
|
||||
class CKeyStateCategory
|
||||
{
|
||||
public:
|
||||
CKeyStateCategory(_In_ CSampleIME *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);
|
||||
|
||||
// HandleKeyConvert
|
||||
virtual HRESULT HandleKeyConvert(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyConvertWild
|
||||
virtual HRESULT HandleKeyConvertWildCard(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyCancel
|
||||
virtual HRESULT HandleKeyCancel(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyBackspace
|
||||
virtual HRESULT HandleKeyBackspace(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:
|
||||
CSampleIME* _pTextService;
|
||||
};
|
||||
|
||||
class CKeyStateComposing : public CKeyStateCategory
|
||||
{
|
||||
public:
|
||||
CKeyStateComposing(_In_ CSampleIME *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);
|
||||
|
||||
// HandleCompositionBackspace
|
||||
HRESULT HandleKeyBackspace(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleArrowKey
|
||||
HRESULT HandleKeyArrow(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyDoubleSingleByte
|
||||
HRESULT HandleKeyDoubleSingleByte(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
// HandleKeyCompositionPunctuation
|
||||
HRESULT HandleKeyPunctuation(KeyHandlerEditSessionDTO dto);
|
||||
};
|
||||
|
||||
class CKeyStateCandidate : public CKeyStateCategory
|
||||
{
|
||||
public:
|
||||
CKeyStateCandidate(_In_ CSampleIME *pTextService);
|
||||
|
||||
protected:
|
||||
// HandleKeyFinalizeCandidatelist
|
||||
HRESULT HandleKeyFinalizeCandidatelist(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);
|
||||
};
|
||||
|
||||
class CKeyStatePhrase : public CKeyStateCategory
|
||||
{
|
||||
public:
|
||||
CKeyStatePhrase(_In_ CSampleIME *pTextService);
|
||||
|
||||
protected:
|
||||
//_HandleCancel
|
||||
HRESULT HandleKeyFinalizeCandidatelist(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
//_HandleCancel
|
||||
HRESULT HandleKeyCancel(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
//_HandlePhraseArrowKey
|
||||
HRESULT HandleKeyArrow(KeyHandlerEditSessionDTO dto);
|
||||
|
||||
//_HandlePhraseSelectByNumber
|
||||
HRESULT HandleKeySelectByNumber(KeyHandlerEditSessionDTO dto);
|
||||
};
|
||||
|
||||
//degeneration class
|
||||
class CKeyStateNull : public CKeyStateCategory
|
||||
{
|
||||
public:
|
||||
CKeyStateNull(_In_ CSampleIME *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); };
|
||||
};
|
||||
@@ -0,0 +1,662 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "SampleIME.h"
|
||||
#include "CompositionProcessorEngine.h"
|
||||
#include "LanguageBar.h"
|
||||
#include "Globals.h"
|
||||
#include "Compartment.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CSampleIME::_UpdateLanguageBarOnSetFocus
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CSampleIME::_UpdateLanguageBarOnSetFocus(_In_ ITfDocumentMgr *pDocMgrFocus)
|
||||
{
|
||||
BOOL needDisableButtons = FALSE;
|
||||
|
||||
if (!pDocMgrFocus)
|
||||
{
|
||||
needDisableButtons = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
IEnumTfContexts* pEnumContext = nullptr;
|
||||
|
||||
if (FAILED(pDocMgrFocus->EnumContexts(&pEnumContext)) || !pEnumContext)
|
||||
{
|
||||
needDisableButtons = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ULONG fetched = 0;
|
||||
ITfContext* pContext = nullptr;
|
||||
|
||||
if (FAILED(pEnumContext->Next(1, &pContext, &fetched)) || fetched != 1)
|
||||
{
|
||||
needDisableButtons = TRUE;
|
||||
}
|
||||
|
||||
if (!pContext)
|
||||
{
|
||||
// context is not associated
|
||||
needDisableButtons = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
pContext->Release();
|
||||
}
|
||||
}
|
||||
|
||||
if (pEnumContext)
|
||||
{
|
||||
pEnumContext->Release();
|
||||
}
|
||||
}
|
||||
|
||||
CCompositionProcessorEngine* pCompositionProcessorEngine = nullptr;
|
||||
pCompositionProcessorEngine = _pCompositionProcessorEngine;
|
||||
|
||||
pCompositionProcessorEngine->SetLanguageBarStatus(TF_LBI_STATUS_DISABLED, needDisableButtons);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CCompositionProcessorEngine::SetLanguageBarStatus
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
VOID CCompositionProcessorEngine::SetLanguageBarStatus(DWORD status, BOOL isSet)
|
||||
{
|
||||
if (_pLanguageBar_IMEMode) {
|
||||
_pLanguageBar_IMEMode->SetStatus(status, isSet);
|
||||
}
|
||||
if (_pLanguageBar_DoubleSingleByte) {
|
||||
_pLanguageBar_DoubleSingleByte->SetStatus(status, isSet);
|
||||
}
|
||||
if (_pLanguageBar_Punctuation) {
|
||||
_pLanguageBar_Punctuation->SetStatus(status, isSet);
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CLangBarItemButton::ctor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CLangBarItemButton::CLangBarItemButton(REFGUID guidLangBar, LPCWSTR description, LPCWSTR tooltip, DWORD onIconIndex, DWORD offIconIndex, BOOL isSecureMode)
|
||||
{
|
||||
DWORD bufLen = 0;
|
||||
|
||||
DllAddRef();
|
||||
|
||||
// initialize TF_LANGBARITEMINFO structure.
|
||||
_tfLangBarItemInfo.clsidService = Global::SampleIMECLSID; // This LangBarItem belongs to this TextService.
|
||||
_tfLangBarItemInfo.guidItem = guidLangBar; // GUID of this LangBarItem.
|
||||
_tfLangBarItemInfo.dwStyle = (TF_LBI_STYLE_BTN_BUTTON | TF_LBI_STYLE_SHOWNINTRAY); // This LangBar is a button type.
|
||||
_tfLangBarItemInfo.ulSort = 0; // The position of this LangBar Item is not specified.
|
||||
StringCchCopy(_tfLangBarItemInfo.szDescription, ARRAYSIZE(_tfLangBarItemInfo.szDescription), description); // Set the description of this LangBar Item.
|
||||
|
||||
// Initialize the sink pointer to NULL.
|
||||
_pLangBarItemSink = nullptr;
|
||||
|
||||
// Initialize ICON index and file name.
|
||||
_onIconIndex = onIconIndex;
|
||||
_offIconIndex = offIconIndex;
|
||||
|
||||
// Initialize compartment.
|
||||
_pCompartment = nullptr;
|
||||
_pCompartmentEventSink = nullptr;
|
||||
|
||||
_isAddedToLanguageBar = FALSE;
|
||||
_isSecureMode = isSecureMode;
|
||||
_status = 0;
|
||||
|
||||
_refCount = 1;
|
||||
|
||||
// Initialize Tooltip
|
||||
_pTooltipText = nullptr;
|
||||
if (tooltip)
|
||||
{
|
||||
size_t len = 0;
|
||||
if (StringCchLength(tooltip, STRSAFE_MAX_CCH, &len) != S_OK)
|
||||
{
|
||||
len = 0;
|
||||
}
|
||||
bufLen = static_cast<DWORD>(len) + 1;
|
||||
_pTooltipText = (LPCWSTR) new (std::nothrow) WCHAR[ bufLen ];
|
||||
if (_pTooltipText)
|
||||
{
|
||||
StringCchCopy((LPWSTR)_pTooltipText, bufLen, tooltip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CLangBarItemButton::dtor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CLangBarItemButton::~CLangBarItemButton()
|
||||
{
|
||||
DllRelease();
|
||||
CleanUp();
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CLangBarItemButton::CleanUp
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CLangBarItemButton::CleanUp()
|
||||
{
|
||||
if (_pTooltipText)
|
||||
{
|
||||
delete [] _pTooltipText;
|
||||
_pTooltipText = nullptr;
|
||||
}
|
||||
|
||||
ITfThreadMgr* pThreadMgr = nullptr;
|
||||
HRESULT hr = CoCreateInstance(CLSID_TF_ThreadMgr,
|
||||
NULL,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
IID_ITfThreadMgr,
|
||||
(void**)&pThreadMgr);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
_UnregisterCompartment(pThreadMgr);
|
||||
|
||||
_RemoveItem(pThreadMgr);
|
||||
pThreadMgr->Release();
|
||||
pThreadMgr = nullptr;
|
||||
}
|
||||
|
||||
if (_pCompartment)
|
||||
{
|
||||
delete _pCompartment;
|
||||
_pCompartment = nullptr;
|
||||
}
|
||||
|
||||
if (_pCompartmentEventSink)
|
||||
{
|
||||
delete _pCompartmentEventSink;
|
||||
_pCompartmentEventSink = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CLangBarItemButton::QueryInterface
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CLangBarItemButton::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
|
||||
{
|
||||
if (ppvObj == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*ppvObj = nullptr;
|
||||
|
||||
if (IsEqualIID(riid, IID_IUnknown) ||
|
||||
IsEqualIID(riid, IID_ITfLangBarItem) ||
|
||||
IsEqualIID(riid, IID_ITfLangBarItemButton))
|
||||
{
|
||||
*ppvObj = (ITfLangBarItemButton *)this;
|
||||
}
|
||||
else if (IsEqualIID(riid, IID_ITfSource))
|
||||
{
|
||||
*ppvObj = (ITfSource *)this;
|
||||
}
|
||||
|
||||
if (*ppvObj)
|
||||
{
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CLangBarItemButton::AddRef
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI_(ULONG) CLangBarItemButton::AddRef()
|
||||
{
|
||||
return ++_refCount;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CLangBarItemButton::Release
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI_(ULONG) CLangBarItemButton::Release()
|
||||
{
|
||||
LONG cr = --_refCount;
|
||||
|
||||
assert(_refCount >= 0);
|
||||
|
||||
if (_refCount == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
return cr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// GetInfo
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CLangBarItemButton::GetInfo(_Out_ TF_LANGBARITEMINFO *pInfo)
|
||||
{
|
||||
_tfLangBarItemInfo.dwStyle |= TF_LBI_STYLE_SHOWNINTRAY;
|
||||
*pInfo = _tfLangBarItemInfo;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// GetStatus
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CLangBarItemButton::GetStatus(_Out_ DWORD *pdwStatus)
|
||||
{
|
||||
if (pdwStatus == nullptr)
|
||||
{
|
||||
E_INVALIDARG;
|
||||
}
|
||||
|
||||
*pdwStatus = _status;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// SetStatus
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CLangBarItemButton::SetStatus(DWORD dwStatus, BOOL fSet)
|
||||
{
|
||||
BOOL isChange = FALSE;
|
||||
|
||||
if (fSet)
|
||||
{
|
||||
if (!(_status & dwStatus))
|
||||
{
|
||||
_status |= dwStatus;
|
||||
isChange = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_status & dwStatus)
|
||||
{
|
||||
_status &= ~dwStatus;
|
||||
isChange = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (isChange && _pLangBarItemSink)
|
||||
{
|
||||
_pLangBarItemSink->OnUpdate(TF_LBI_STATUS | TF_LBI_ICON);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// Show
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CLangBarItemButton::Show(BOOL fShow)
|
||||
{
|
||||
fShow;
|
||||
if (_pLangBarItemSink)
|
||||
{
|
||||
_pLangBarItemSink->OnUpdate(TF_LBI_STATUS);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// GetTooltipString
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CLangBarItemButton::GetTooltipString(_Out_ BSTR *pbstrToolTip)
|
||||
{
|
||||
*pbstrToolTip = SysAllocString(_pTooltipText);
|
||||
|
||||
return (*pbstrToolTip == nullptr) ? E_OUTOFMEMORY : S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// OnClick
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CLangBarItemButton::OnClick(TfLBIClick click, POINT pt, _In_ const RECT *prcArea)
|
||||
{
|
||||
click;pt;
|
||||
prcArea;
|
||||
|
||||
BOOL isOn = FALSE;
|
||||
|
||||
_pCompartment->_GetCompartmentBOOL(isOn);
|
||||
_pCompartment->_SetCompartmentBOOL(isOn ? FALSE : TRUE);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// InitMenu
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CLangBarItemButton::InitMenu(_In_ ITfMenu *pMenu)
|
||||
{
|
||||
pMenu;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// OnMenuSelect
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CLangBarItemButton::OnMenuSelect(UINT wID)
|
||||
{
|
||||
wID;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// GetIcon
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CLangBarItemButton::GetIcon(_Out_ HICON *phIcon)
|
||||
{
|
||||
BOOL isOn = FALSE;
|
||||
|
||||
if (!_pCompartment)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
if (!phIcon)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
*phIcon = nullptr;
|
||||
|
||||
_pCompartment->_GetCompartmentBOOL(isOn);
|
||||
|
||||
DWORD status = 0;
|
||||
GetStatus(&status);
|
||||
|
||||
// If IME is working on the UAC mode, the size of ICON should be 24 x 24.
|
||||
int desiredSize = 16;
|
||||
if (_isSecureMode) // detect UAC mode
|
||||
{
|
||||
desiredSize = _isSecureMode ? 24 : 16;
|
||||
}
|
||||
|
||||
if (isOn && !(status & TF_LBI_STATUS_DISABLED))
|
||||
{
|
||||
if (Global::dllInstanceHandle)
|
||||
{
|
||||
*phIcon = reinterpret_cast<HICON>(LoadImage(Global::dllInstanceHandle, MAKEINTRESOURCE(_onIconIndex), IMAGE_ICON, desiredSize, desiredSize, 0));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Global::dllInstanceHandle)
|
||||
{
|
||||
*phIcon = reinterpret_cast<HICON>(LoadImage(Global::dllInstanceHandle, MAKEINTRESOURCE(_offIconIndex), IMAGE_ICON, desiredSize, desiredSize, 0));
|
||||
}
|
||||
}
|
||||
|
||||
return (*phIcon != NULL) ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// GetText
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CLangBarItemButton::GetText(_Out_ BSTR *pbstrText)
|
||||
{
|
||||
*pbstrText = SysAllocString(_tfLangBarItemInfo.szDescription);
|
||||
|
||||
return (*pbstrText == nullptr) ? E_OUTOFMEMORY : S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// AdviseSink
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CLangBarItemButton::AdviseSink(__RPC__in REFIID riid, __RPC__in_opt IUnknown *punk, __RPC__out DWORD *pdwCookie)
|
||||
{
|
||||
// We allow only ITfLangBarItemSink interface.
|
||||
if (!IsEqualIID(IID_ITfLangBarItemSink, riid))
|
||||
{
|
||||
return CONNECT_E_CANNOTCONNECT;
|
||||
}
|
||||
|
||||
// We support only one sink once.
|
||||
if (_pLangBarItemSink != nullptr)
|
||||
{
|
||||
return CONNECT_E_ADVISELIMIT;
|
||||
}
|
||||
|
||||
// Query the ITfLangBarItemSink interface and store it into _pLangBarItemSink.
|
||||
if (punk == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
if (punk->QueryInterface(IID_ITfLangBarItemSink, (void **)&_pLangBarItemSink) != S_OK)
|
||||
{
|
||||
_pLangBarItemSink = nullptr;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
// return our cookie.
|
||||
*pdwCookie = _cookie;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// UnadviseSink
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CLangBarItemButton::UnadviseSink(DWORD dwCookie)
|
||||
{
|
||||
// Check the given cookie.
|
||||
if (dwCookie != _cookie)
|
||||
{
|
||||
return CONNECT_E_NOCONNECTION;
|
||||
}
|
||||
|
||||
// If there is nno connected sink, we just fail.
|
||||
if (_pLangBarItemSink == nullptr)
|
||||
{
|
||||
return CONNECT_E_NOCONNECTION;
|
||||
}
|
||||
|
||||
_pLangBarItemSink->Release();
|
||||
_pLangBarItemSink = nullptr;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _AddItem
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CLangBarItemButton::_AddItem(_In_ ITfThreadMgr *pThreadMgr)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
ITfLangBarItemMgr* pLangBarItemMgr = nullptr;
|
||||
|
||||
if (_isAddedToLanguageBar)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
hr = pThreadMgr->QueryInterface(IID_ITfLangBarItemMgr, (void **)&pLangBarItemMgr);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pLangBarItemMgr->AddItem(this);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
_isAddedToLanguageBar = TRUE;
|
||||
}
|
||||
pLangBarItemMgr->Release();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _RemoveItem
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CLangBarItemButton::_RemoveItem(_In_ ITfThreadMgr *pThreadMgr)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
ITfLangBarItemMgr* pLangBarItemMgr = nullptr;
|
||||
|
||||
if (!_isAddedToLanguageBar)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
hr = pThreadMgr->QueryInterface(IID_ITfLangBarItemMgr, (void **)&pLangBarItemMgr);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pLangBarItemMgr->RemoveItem(this);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
_isAddedToLanguageBar = FALSE;
|
||||
}
|
||||
pLangBarItemMgr->Release();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _RegisterCompartment
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CLangBarItemButton::_RegisterCompartment(_In_ ITfThreadMgr *pThreadMgr, TfClientId tfClientId, REFGUID guidCompartment)
|
||||
{
|
||||
_pCompartment = new (std::nothrow) CCompartment(pThreadMgr, tfClientId, guidCompartment);
|
||||
if (_pCompartment)
|
||||
{
|
||||
// Advice ITfCompartmentEventSink
|
||||
_pCompartmentEventSink = new (std::nothrow) CCompartmentEventSink(_CompartmentCallback, this);
|
||||
if (_pCompartmentEventSink)
|
||||
{
|
||||
_pCompartmentEventSink->_Advise(pThreadMgr, guidCompartment);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete _pCompartment;
|
||||
_pCompartment = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return _pCompartment ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _UnregisterCompartment
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CLangBarItemButton::_UnregisterCompartment(_In_ ITfThreadMgr *pThreadMgr)
|
||||
{
|
||||
pThreadMgr;
|
||||
if (_pCompartment)
|
||||
{
|
||||
// Unadvice ITfCompartmentEventSink
|
||||
if (_pCompartmentEventSink)
|
||||
{
|
||||
_pCompartmentEventSink->_Unadvise();
|
||||
}
|
||||
|
||||
// clear ITfCompartment
|
||||
_pCompartment->_ClearCompartment();
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _CompartmentCallback
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// static
|
||||
HRESULT CLangBarItemButton::_CompartmentCallback(_In_ void *pv, REFGUID guidCompartment)
|
||||
{
|
||||
CLangBarItemButton* fakeThis = (CLangBarItemButton*)pv;
|
||||
|
||||
GUID guid = GUID_NULL;
|
||||
fakeThis->_pCompartment->_GetGUID(&guid);
|
||||
|
||||
if (IsEqualGUID(guid, guidCompartment))
|
||||
{
|
||||
if (fakeThis->_pLangBarItemSink)
|
||||
{
|
||||
fakeThis->_pLangBarItemSink->OnUpdate(TF_LBI_STATUS | TF_LBI_ICON);
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#pragma once
|
||||
|
||||
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(_In_ ITfThreadMgr *pThreadMgr);
|
||||
|
||||
void CleanUp();
|
||||
|
||||
void SetStatus(DWORD dwStatus, BOOL fSet);
|
||||
|
||||
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;
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#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"
|
||||
@@ -0,0 +1,13 @@
|
||||
how to install ime
|
||||
|
||||
```
|
||||
regsvr32 "C:\Program Files\SampleIME\SampleIME.dll"
|
||||
regsvr32 "C:\Program Files (x86)\SampleIME\SampleIME.dll"
|
||||
```
|
||||
|
||||
how to uninstall ime
|
||||
|
||||
```shell
|
||||
regsvr32 /u "C:\Program Files\SampleIME\SampleIME.dll"
|
||||
regsvr32 /u "C:\Program Files (x86)\SampleIME\SampleIME.dll"
|
||||
```
|
||||
@@ -0,0 +1,278 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#pragma once
|
||||
|
||||
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;
|
||||
};
|
||||
@@ -0,0 +1,283 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "Globals.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";
|
||||
|
||||
static const WCHAR TEXTSERVICE_DESC[] = L"Sample IME";
|
||||
|
||||
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::SampleIMECLSID,
|
||||
TEXTSERVICE_LANGID,
|
||||
Global::SampleIMEGuidProfile,
|
||||
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::SampleIMECLSID, TEXTSERVICE_LANGID, Global::SampleIMEGuidProfile, 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)
|
||||
{
|
||||
hr = pCategoryMgr->RegisterCategory(Global::SampleIMECLSID, guid, Global::SampleIMECLSID);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
pCategoryMgr->UnregisterCategory(Global::SampleIMECLSID, guid, Global::SampleIMECLSID);
|
||||
}
|
||||
|
||||
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::SampleIMECLSID, 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::SampleIMECLSID, achIMEKey + ARRAYSIZE(RegInfo_Prefix_CLSID) - 1))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(achIMEKey, RegInfo_Prefix_CLSID, sizeof(RegInfo_Prefix_CLSID) - sizeof(WCHAR));
|
||||
|
||||
RecurseDeleteKey(HKEY_CLASSES_ROOT, achIMEKey);
|
||||
}
|
||||
@@ -0,0 +1,432 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "globals.h"
|
||||
#include "SampleIME.h"
|
||||
#include "CandidateListUIPresenter.h"
|
||||
#include "CompositionProcessorEngine.h"
|
||||
#include "Compartment.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CreateInstance
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/* static */
|
||||
HRESULT CSampleIME::CreateInstance(_In_ IUnknown *pUnkOuter, REFIID riid, _Outptr_ void **ppvObj)
|
||||
{
|
||||
CSampleIME* pSampleIME = nullptr;
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (ppvObj == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*ppvObj = nullptr;
|
||||
|
||||
if (nullptr != pUnkOuter)
|
||||
{
|
||||
return CLASS_E_NOAGGREGATION;
|
||||
}
|
||||
|
||||
pSampleIME = new (std::nothrow) CSampleIME();
|
||||
if (pSampleIME == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
hr = pSampleIME->QueryInterface(riid, ppvObj);
|
||||
|
||||
pSampleIME->Release();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ctor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CSampleIME::CSampleIME()
|
||||
{
|
||||
DllAddRef();
|
||||
|
||||
_pThreadMgr = nullptr;
|
||||
|
||||
_threadMgrEventSinkCookie = TF_INVALID_COOKIE;
|
||||
|
||||
_pTextEditSinkContext = nullptr;
|
||||
_textEditSinkCookie = TF_INVALID_COOKIE;
|
||||
|
||||
_activeLanguageProfileNotifySinkCookie = TF_INVALID_COOKIE;
|
||||
|
||||
_dwThreadFocusSinkCookie = TF_INVALID_COOKIE;
|
||||
|
||||
_pComposition = nullptr;
|
||||
|
||||
_pCompositionProcessorEngine = nullptr;
|
||||
|
||||
_candidateMode = CANDIDATE_NONE;
|
||||
_pCandidateListUIPresenter = nullptr;
|
||||
_isCandidateWithWildcard = FALSE;
|
||||
|
||||
_pDocMgrLastFocused = nullptr;
|
||||
|
||||
_pSIPIMEOnOffCompartment = nullptr;
|
||||
_dwSIPIMEOnOffCompartmentSinkCookie = 0;
|
||||
_msgWndHandle = nullptr;
|
||||
|
||||
_pContext = nullptr;
|
||||
|
||||
_refCount = 1;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// dtor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CSampleIME::~CSampleIME()
|
||||
{
|
||||
if (_pCandidateListUIPresenter)
|
||||
{
|
||||
delete _pCandidateListUIPresenter;
|
||||
_pCandidateListUIPresenter = nullptr;
|
||||
}
|
||||
DllRelease();
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// QueryInterface
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CSampleIME::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
|
||||
{
|
||||
if (ppvObj == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*ppvObj = nullptr;
|
||||
|
||||
if (IsEqualIID(riid, IID_IUnknown) ||
|
||||
IsEqualIID(riid, IID_ITfTextInputProcessor))
|
||||
{
|
||||
*ppvObj = (ITfTextInputProcessor *)this;
|
||||
}
|
||||
else if (IsEqualIID(riid, IID_ITfTextInputProcessorEx))
|
||||
{
|
||||
*ppvObj = (ITfTextInputProcessorEx *)this;
|
||||
}
|
||||
else if (IsEqualIID(riid, IID_ITfThreadMgrEventSink))
|
||||
{
|
||||
*ppvObj = (ITfThreadMgrEventSink *)this;
|
||||
}
|
||||
else if (IsEqualIID(riid, IID_ITfTextEditSink))
|
||||
{
|
||||
*ppvObj = (ITfTextEditSink *)this;
|
||||
}
|
||||
else if (IsEqualIID(riid, IID_ITfKeyEventSink))
|
||||
{
|
||||
*ppvObj = (ITfKeyEventSink *)this;
|
||||
}
|
||||
else if (IsEqualIID(riid, IID_ITfActiveLanguageProfileNotifySink))
|
||||
{
|
||||
*ppvObj = (ITfActiveLanguageProfileNotifySink *)this;
|
||||
}
|
||||
else if (IsEqualIID(riid, IID_ITfCompositionSink))
|
||||
{
|
||||
*ppvObj = (ITfKeyEventSink *)this;
|
||||
}
|
||||
else if (IsEqualIID(riid, IID_ITfDisplayAttributeProvider))
|
||||
{
|
||||
*ppvObj = (ITfDisplayAttributeProvider *)this;
|
||||
}
|
||||
else if (IsEqualIID(riid, IID_ITfThreadFocusSink))
|
||||
{
|
||||
*ppvObj = (ITfThreadFocusSink *)this;
|
||||
}
|
||||
else if (IsEqualIID(riid, IID_ITfFunctionProvider))
|
||||
{
|
||||
*ppvObj = (ITfFunctionProvider *)this;
|
||||
}
|
||||
else if (IsEqualIID(riid, IID_ITfFunction))
|
||||
{
|
||||
*ppvObj = (ITfFunction *)this;
|
||||
}
|
||||
else if (IsEqualIID(riid, IID_ITfFnGetPreferredTouchKeyboardLayout))
|
||||
{
|
||||
*ppvObj = (ITfFnGetPreferredTouchKeyboardLayout *)this;
|
||||
}
|
||||
|
||||
if (*ppvObj)
|
||||
{
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// AddRef
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI_(ULONG) CSampleIME::AddRef()
|
||||
{
|
||||
return ++_refCount;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// Release
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI_(ULONG) CSampleIME::Release()
|
||||
{
|
||||
LONG cr = --_refCount;
|
||||
|
||||
assert(_refCount >= 0);
|
||||
|
||||
if (_refCount == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
return cr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfTextInputProcessorEx::ActivateEx
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CSampleIME::ActivateEx(ITfThreadMgr *pThreadMgr, TfClientId tfClientId, DWORD dwFlags)
|
||||
{
|
||||
_pThreadMgr = pThreadMgr;
|
||||
_pThreadMgr->AddRef();
|
||||
|
||||
_tfClientId = tfClientId;
|
||||
_dwActivateFlags = dwFlags;
|
||||
|
||||
if (!_InitThreadMgrEventSink())
|
||||
{
|
||||
goto ExitError;
|
||||
}
|
||||
|
||||
ITfDocumentMgr* pDocMgrFocus = nullptr;
|
||||
if (SUCCEEDED(_pThreadMgr->GetFocus(&pDocMgrFocus)) && (pDocMgrFocus != nullptr))
|
||||
{
|
||||
_InitTextEditSink(pDocMgrFocus);
|
||||
pDocMgrFocus->Release();
|
||||
}
|
||||
|
||||
if (!_InitKeyEventSink())
|
||||
{
|
||||
goto ExitError;
|
||||
}
|
||||
|
||||
if (!_InitActiveLanguageProfileNotifySink())
|
||||
{
|
||||
goto ExitError;
|
||||
}
|
||||
|
||||
if (!_InitThreadFocusSink())
|
||||
{
|
||||
goto ExitError;
|
||||
}
|
||||
|
||||
if (!_InitDisplayAttributeGuidAtom())
|
||||
{
|
||||
goto ExitError;
|
||||
}
|
||||
|
||||
if (!_InitFunctionProviderSink())
|
||||
{
|
||||
goto ExitError;
|
||||
}
|
||||
|
||||
if (!_AddTextProcessorEngine())
|
||||
{
|
||||
goto ExitError;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
|
||||
ExitError:
|
||||
Deactivate();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfTextInputProcessorEx::Deactivate
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CSampleIME::Deactivate()
|
||||
{
|
||||
if (_pCompositionProcessorEngine)
|
||||
{
|
||||
delete _pCompositionProcessorEngine;
|
||||
_pCompositionProcessorEngine = nullptr;
|
||||
}
|
||||
|
||||
ITfContext* pContext = _pContext;
|
||||
if (_pContext)
|
||||
{
|
||||
pContext->AddRef();
|
||||
_EndComposition(_pContext);
|
||||
}
|
||||
|
||||
if (_pCandidateListUIPresenter)
|
||||
{
|
||||
delete _pCandidateListUIPresenter;
|
||||
_pCandidateListUIPresenter = nullptr;
|
||||
|
||||
if (pContext)
|
||||
{
|
||||
pContext->Release();
|
||||
}
|
||||
|
||||
_candidateMode = CANDIDATE_NONE;
|
||||
_isCandidateWithWildcard = FALSE;
|
||||
}
|
||||
|
||||
_UninitFunctionProviderSink();
|
||||
|
||||
_UninitThreadFocusSink();
|
||||
|
||||
_UninitActiveLanguageProfileNotifySink();
|
||||
|
||||
_UninitKeyEventSink();
|
||||
|
||||
_UninitThreadMgrEventSink();
|
||||
|
||||
CCompartment CompartmentKeyboardOpen(_pThreadMgr, _tfClientId, GUID_COMPARTMENT_KEYBOARD_OPENCLOSE);
|
||||
CompartmentKeyboardOpen._ClearCompartment();
|
||||
|
||||
CCompartment CompartmentDoubleSingleByte(_pThreadMgr, _tfClientId, Global::SampleIMEGuidCompartmentDoubleSingleByte);
|
||||
CompartmentDoubleSingleByte._ClearCompartment();
|
||||
|
||||
CCompartment CompartmentPunctuation(_pThreadMgr, _tfClientId, Global::SampleIMEGuidCompartmentPunctuation);
|
||||
CompartmentDoubleSingleByte._ClearCompartment();
|
||||
|
||||
if (_pThreadMgr != nullptr)
|
||||
{
|
||||
_pThreadMgr->Release();
|
||||
}
|
||||
|
||||
_tfClientId = TF_CLIENTID_NULL;
|
||||
|
||||
if (_pDocMgrLastFocused)
|
||||
{
|
||||
_pDocMgrLastFocused->Release();
|
||||
_pDocMgrLastFocused = nullptr;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfFunctionProvider::GetType
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
HRESULT CSampleIME::GetType(__RPC__out GUID *pguid)
|
||||
{
|
||||
HRESULT hr = E_INVALIDARG;
|
||||
if (pguid)
|
||||
{
|
||||
*pguid = Global::SampleIMECLSID;
|
||||
hr = S_OK;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfFunctionProvider::::GetDescription
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
HRESULT CSampleIME::GetDescription(__RPC__deref_out_opt BSTR *pbstrDesc)
|
||||
{
|
||||
HRESULT hr = E_INVALIDARG;
|
||||
if (pbstrDesc != nullptr)
|
||||
{
|
||||
*pbstrDesc = nullptr;
|
||||
hr = E_NOTIMPL;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfFunctionProvider::::GetFunction
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
HRESULT CSampleIME::GetFunction(__RPC__in REFGUID rguid, __RPC__in REFIID riid, __RPC__deref_out_opt IUnknown **ppunk)
|
||||
{
|
||||
HRESULT hr = E_NOINTERFACE;
|
||||
|
||||
if ((IsEqualGUID(rguid, GUID_NULL))
|
||||
&& (IsEqualGUID(riid, __uuidof(ITfFnSearchCandidateProvider))))
|
||||
{
|
||||
hr = _pITfFnSearchCandidateProvider->QueryInterface(riid, (void**)ppunk);
|
||||
}
|
||||
else if (IsEqualGUID(rguid, GUID_NULL))
|
||||
{
|
||||
hr = QueryInterface(riid, (void **)ppunk);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfFunction::GetDisplayName
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
HRESULT CSampleIME::GetDisplayName(_Out_ BSTR *pbstrDisplayName)
|
||||
{
|
||||
HRESULT hr = E_INVALIDARG;
|
||||
if (pbstrDisplayName != nullptr)
|
||||
{
|
||||
*pbstrDisplayName = nullptr;
|
||||
hr = E_NOTIMPL;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfFnGetPreferredTouchKeyboardLayout::GetLayout
|
||||
// The tkblayout will be Optimized layout.
|
||||
//----------------------------------------------------------------------------
|
||||
HRESULT CSampleIME::GetLayout(_Out_ TKBLayoutType *ptkblayoutType, _Out_ WORD *pwPreferredLayoutId)
|
||||
{
|
||||
HRESULT hr = E_INVALIDARG;
|
||||
if ((ptkblayoutType != nullptr) && (pwPreferredLayoutId != nullptr))
|
||||
{
|
||||
*ptkblayoutType = TKBLT_OPTIMIZED;
|
||||
*pwPreferredLayoutId = TKBL_OPT_SIMPLIFIED_CHINESE_PINYIN;
|
||||
hr = S_OK;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
LIBRARY SampleIME.dll
|
||||
|
||||
EXPORTS
|
||||
DllGetClassObject PRIVATE
|
||||
DllCanUnloadNow PRIVATE
|
||||
DllRegisterServer PRIVATE
|
||||
DllUnregisterServer PRIVATE
|
||||
@@ -0,0 +1,248 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "KeyHandlerEditSession.h"
|
||||
#include "SampleIMEBaseStructure.h"
|
||||
|
||||
class CLangBarItemButton;
|
||||
class CCandidateListUIPresenter;
|
||||
class CCompositionProcessorEngine;
|
||||
|
||||
const DWORD WM_CheckGlobalCompartment = WM_USER;
|
||||
LRESULT CALLBACK CSampleIME_WindowProc(HWND wndHandle, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
class CSampleIME : public ITfTextInputProcessorEx,
|
||||
public ITfThreadMgrEventSink,
|
||||
public ITfTextEditSink,
|
||||
public ITfKeyEventSink,
|
||||
public ITfCompositionSink,
|
||||
public ITfDisplayAttributeProvider,
|
||||
public ITfActiveLanguageProfileNotifySink,
|
||||
public ITfThreadFocusSink,
|
||||
public ITfFunctionProvider,
|
||||
public ITfFnGetPreferredTouchKeyboardLayout
|
||||
{
|
||||
public:
|
||||
CSampleIME();
|
||||
~CSampleIME();
|
||||
|
||||
// IUnknown
|
||||
STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj);
|
||||
STDMETHODIMP_(ULONG) AddRef(void);
|
||||
STDMETHODIMP_(ULONG) Release(void);
|
||||
|
||||
// ITfTextInputProcessor
|
||||
STDMETHODIMP Activate(ITfThreadMgr *pThreadMgr, TfClientId tfClientId) {
|
||||
return ActivateEx(pThreadMgr, tfClientId, 0);
|
||||
}
|
||||
// ITfTextInputProcessorEx
|
||||
STDMETHODIMP ActivateEx(ITfThreadMgr *pThreadMgr, TfClientId tfClientId, DWORD dwFlags);
|
||||
STDMETHODIMP Deactivate();
|
||||
|
||||
// ITfThreadMgrEventSink
|
||||
STDMETHODIMP OnInitDocumentMgr(_In_ ITfDocumentMgr *pDocMgr);
|
||||
STDMETHODIMP OnUninitDocumentMgr(_In_ ITfDocumentMgr *pDocMgr);
|
||||
STDMETHODIMP OnSetFocus(_In_ ITfDocumentMgr *pDocMgrFocus, _In_ ITfDocumentMgr *pDocMgrPrevFocus);
|
||||
STDMETHODIMP OnPushContext(_In_ ITfContext *pContext);
|
||||
STDMETHODIMP OnPopContext(_In_ ITfContext *pContext);
|
||||
|
||||
// ITfTextEditSink
|
||||
STDMETHODIMP OnEndEdit(__RPC__in_opt ITfContext *pContext, TfEditCookie ecReadOnly, __RPC__in_opt ITfEditRecord *pEditRecord);
|
||||
|
||||
// ITfKeyEventSink
|
||||
STDMETHODIMP OnSetFocus(BOOL fForeground);
|
||||
STDMETHODIMP OnTestKeyDown(ITfContext *pContext, WPARAM wParam, LPARAM lParam, BOOL *pIsEaten);
|
||||
STDMETHODIMP OnKeyDown(ITfContext *pContext, WPARAM wParam, LPARAM lParam, BOOL *pIsEaten);
|
||||
STDMETHODIMP OnTestKeyUp(ITfContext *pContext, WPARAM wParam, LPARAM lParam, BOOL *pIsEaten);
|
||||
STDMETHODIMP OnKeyUp(ITfContext *pContext, WPARAM wParam, LPARAM lParam, BOOL *pIsEaten);
|
||||
STDMETHODIMP OnPreservedKey(ITfContext *pContext, REFGUID rguid, BOOL *pIsEaten);
|
||||
|
||||
// ITfCompositionSink
|
||||
STDMETHODIMP OnCompositionTerminated(TfEditCookie ecWrite, _In_ ITfComposition *pComposition);
|
||||
|
||||
// ITfDisplayAttributeProvider
|
||||
STDMETHODIMP EnumDisplayAttributeInfo(__RPC__deref_out_opt IEnumTfDisplayAttributeInfo **ppEnum);
|
||||
STDMETHODIMP GetDisplayAttributeInfo(__RPC__in REFGUID guidInfo, __RPC__deref_out_opt ITfDisplayAttributeInfo **ppInfo);
|
||||
|
||||
// ITfActiveLanguageProfileNotifySink
|
||||
STDMETHODIMP OnActivated(_In_ REFCLSID clsid, _In_ REFGUID guidProfile, _In_ BOOL isActivated);
|
||||
|
||||
// ITfThreadFocusSink
|
||||
STDMETHODIMP OnSetThreadFocus();
|
||||
STDMETHODIMP OnKillThreadFocus();
|
||||
|
||||
// ITfFunctionProvider
|
||||
STDMETHODIMP GetType(__RPC__out GUID *pguid);
|
||||
STDMETHODIMP GetDescription(__RPC__deref_out_opt BSTR *pbstrDesc);
|
||||
STDMETHODIMP GetFunction(__RPC__in REFGUID rguid, __RPC__in REFIID riid, __RPC__deref_out_opt IUnknown **ppunk);
|
||||
|
||||
// ITfFunction
|
||||
STDMETHODIMP GetDisplayName(_Out_ BSTR *pbstrDisplayName);
|
||||
|
||||
// ITfFnGetPreferredTouchKeyboardLayout, it is the Optimized layout feature.
|
||||
STDMETHODIMP GetLayout(_Out_ TKBLayoutType *ptkblayoutType, _Out_ WORD *pwPreferredLayoutId);
|
||||
|
||||
// CClassFactory factory callback
|
||||
static HRESULT CreateInstance(_In_ IUnknown *pUnkOuter, REFIID riid, _Outptr_ void **ppvObj);
|
||||
|
||||
// utility function for thread manager.
|
||||
ITfThreadMgr* _GetThreadMgr() { return _pThreadMgr; }
|
||||
TfClientId _GetClientId() { return _tfClientId; }
|
||||
|
||||
// functions for the composition object.
|
||||
void _SetComposition(_In_ ITfComposition *pComposition);
|
||||
void _TerminateComposition(TfEditCookie ec, _In_ ITfContext *pContext, BOOL isCalledFromDeactivate = FALSE);
|
||||
void _SaveCompositionContext(_In_ ITfContext *pContext);
|
||||
|
||||
// key event handlers for composition/candidate/phrase common objects.
|
||||
HRESULT _HandleComplete(TfEditCookie ec, _In_ ITfContext *pContext);
|
||||
HRESULT _HandleCancel(TfEditCookie ec, _In_ ITfContext *pContext);
|
||||
|
||||
// key event handlers for composition object.
|
||||
HRESULT _HandleCompositionInput(TfEditCookie ec, _In_ ITfContext *pContext, WCHAR wch);
|
||||
HRESULT _HandleCompositionFinalize(TfEditCookie ec, _In_ ITfContext *pContext, BOOL fCandidateList);
|
||||
HRESULT _HandleCompositionConvert(TfEditCookie ec, _In_ ITfContext *pContext, BOOL isWildcardSearch);
|
||||
HRESULT _HandleCompositionBackspace(TfEditCookie ec, _In_ ITfContext *pContext);
|
||||
HRESULT _HandleCompositionArrowKey(TfEditCookie ec, _In_ ITfContext *pContext, KEYSTROKE_FUNCTION keyFunction);
|
||||
HRESULT _HandleCompositionPunctuation(TfEditCookie ec, _In_ ITfContext *pContext, WCHAR wch);
|
||||
HRESULT _HandleCompositionDoubleSingleByte(TfEditCookie ec, _In_ ITfContext *pContext, WCHAR wch);
|
||||
|
||||
// key event handlers for candidate object.
|
||||
HRESULT _HandleCandidateFinalize(TfEditCookie ec, _In_ ITfContext *pContext);
|
||||
HRESULT _HandleCandidateConvert(TfEditCookie ec, _In_ ITfContext *pContext);
|
||||
HRESULT _HandleCandidateArrowKey(TfEditCookie ec, _In_ ITfContext *pContext, _In_ KEYSTROKE_FUNCTION keyFunction);
|
||||
HRESULT _HandleCandidateSelectByNumber(TfEditCookie ec, _In_ ITfContext *pContext, _In_ UINT uCode);
|
||||
|
||||
// key event handlers for phrase object.
|
||||
HRESULT _HandlePhraseFinalize(TfEditCookie ec, _In_ ITfContext *pContext);
|
||||
HRESULT _HandlePhraseArrowKey(TfEditCookie ec, _In_ ITfContext *pContext, _In_ KEYSTROKE_FUNCTION keyFunction);
|
||||
HRESULT _HandlePhraseSelectByNumber(TfEditCookie ec, _In_ ITfContext *pContext, _In_ UINT uCode);
|
||||
|
||||
BOOL _IsSecureMode(void) { return (_dwActivateFlags & TF_TMAE_SECUREMODE) ? TRUE : FALSE; }
|
||||
BOOL _IsComLess(void) { return (_dwActivateFlags & TF_TMAE_COMLESS) ? TRUE : FALSE; }
|
||||
BOOL _IsStoreAppMode(void) { return (_dwActivateFlags & TF_TMF_IMMERSIVEMODE) ? TRUE : FALSE; };
|
||||
|
||||
CCompositionProcessorEngine* GetCompositionProcessorEngine() { return (_pCompositionProcessorEngine); };
|
||||
|
||||
// comless helpers
|
||||
static HRESULT CSampleIME::CreateInstance(REFCLSID rclsid, REFIID riid, _Outptr_result_maybenull_ LPVOID* ppv, _Out_opt_ HINSTANCE* phInst, BOOL isComLessMode);
|
||||
static HRESULT CSampleIME::ComLessCreateInstance(REFGUID rclsid, REFIID riid, _Outptr_result_maybenull_ void **ppv, _Out_opt_ HINSTANCE *phInst);
|
||||
static HRESULT CSampleIME::GetComModuleName(REFGUID rclsid, _Out_writes_(cchPath)WCHAR* wchPath, DWORD cchPath);
|
||||
|
||||
private:
|
||||
// functions for the composition object.
|
||||
HRESULT _HandleCompositionInputWorker(_In_ CCompositionProcessorEngine *pCompositionProcessorEngine, TfEditCookie ec, _In_ ITfContext *pContext);
|
||||
HRESULT _CreateAndStartCandidate(_In_ CCompositionProcessorEngine *pCompositionProcessorEngine, TfEditCookie ec, _In_ ITfContext *pContext);
|
||||
HRESULT _HandleCandidateWorker(TfEditCookie ec, _In_ ITfContext *pContext);
|
||||
|
||||
void _StartComposition(_In_ ITfContext *pContext);
|
||||
void _EndComposition(_In_opt_ ITfContext *pContext);
|
||||
BOOL _IsComposing();
|
||||
BOOL _IsKeyboardDisabled();
|
||||
|
||||
HRESULT _AddComposingAndChar(TfEditCookie ec, _In_ ITfContext *pContext, _In_ CStringRange *pstrAddString);
|
||||
HRESULT _AddCharAndFinalize(TfEditCookie ec, _In_ ITfContext *pContext, _In_ CStringRange *pstrAddString);
|
||||
|
||||
BOOL _FindComposingRange(TfEditCookie ec, _In_ ITfContext *pContext, _In_ ITfRange *pSelection, _Outptr_result_maybenull_ ITfRange **ppRange);
|
||||
HRESULT _SetInputString(TfEditCookie ec, _In_ ITfContext *pContext, _Out_opt_ ITfRange *pRange, _In_ CStringRange *pstrAddString, BOOL exist_composing);
|
||||
HRESULT _InsertAtSelection(TfEditCookie ec, _In_ ITfContext *pContext, _In_ CStringRange *pstrAddString, _Outptr_ ITfRange **ppCompRange);
|
||||
|
||||
HRESULT _RemoveDummyCompositionForComposing(TfEditCookie ec, _In_ ITfComposition *pComposition);
|
||||
|
||||
// Invoke key handler edit session
|
||||
HRESULT _InvokeKeyHandler(_In_ ITfContext *pContext, UINT code, WCHAR wch, DWORD flags, _KEYSTROKE_STATE keyState);
|
||||
|
||||
// function for the language property
|
||||
BOOL _SetCompositionLanguage(TfEditCookie ec, _In_ ITfContext *pContext);
|
||||
|
||||
// function for the display attribute
|
||||
void _ClearCompositionDisplayAttributes(TfEditCookie ec, _In_ ITfContext *pContext);
|
||||
BOOL _SetCompositionDisplayAttributes(TfEditCookie ec, _In_ ITfContext *pContext, TfGuidAtom gaDisplayAttribute);
|
||||
BOOL _InitDisplayAttributeGuidAtom();
|
||||
|
||||
BOOL _InitThreadMgrEventSink();
|
||||
void _UninitThreadMgrEventSink();
|
||||
|
||||
BOOL _InitTextEditSink(_In_ ITfDocumentMgr *pDocMgr);
|
||||
|
||||
void _UpdateLanguageBarOnSetFocus(_In_ ITfDocumentMgr *pDocMgrFocus);
|
||||
|
||||
BOOL _InitKeyEventSink();
|
||||
void _UninitKeyEventSink();
|
||||
|
||||
BOOL _InitActiveLanguageProfileNotifySink();
|
||||
void _UninitActiveLanguageProfileNotifySink();
|
||||
|
||||
BOOL _IsKeyEaten(_In_ ITfContext *pContext, UINT codeIn, _Out_ UINT *pCodeOut, _Out_writes_(1) WCHAR *pwch, _Out_opt_ _KEYSTROKE_STATE *pKeyState);
|
||||
|
||||
BOOL _IsRangeCovered(TfEditCookie ec, _In_ ITfRange *pRangeTest, _In_ ITfRange *pRangeCover);
|
||||
VOID _DeleteCandidateList(BOOL fForce, _In_opt_ ITfContext *pContext);
|
||||
|
||||
WCHAR ConvertVKey(UINT code);
|
||||
|
||||
BOOL _InitThreadFocusSink();
|
||||
void _UninitThreadFocusSink();
|
||||
|
||||
BOOL _InitFunctionProviderSink();
|
||||
void _UninitFunctionProviderSink();
|
||||
|
||||
BOOL _AddTextProcessorEngine();
|
||||
|
||||
BOOL VerifySampleIMECLSID(_In_ REFCLSID clsid);
|
||||
|
||||
friend LRESULT CALLBACK CSampleIME_WindowProc(HWND wndHandle, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
private:
|
||||
ITfThreadMgr* _pThreadMgr;
|
||||
TfClientId _tfClientId;
|
||||
DWORD _dwActivateFlags;
|
||||
|
||||
// The cookie of ThreadMgrEventSink
|
||||
DWORD _threadMgrEventSinkCookie;
|
||||
|
||||
ITfContext* _pTextEditSinkContext;
|
||||
DWORD _textEditSinkCookie;
|
||||
|
||||
// The cookie of ActiveLanguageProfileNotifySink
|
||||
DWORD _activeLanguageProfileNotifySinkCookie;
|
||||
|
||||
// The cookie of ThreadFocusSink
|
||||
DWORD _dwThreadFocusSinkCookie;
|
||||
|
||||
// Composition Processor Engine object.
|
||||
CCompositionProcessorEngine* _pCompositionProcessorEngine;
|
||||
|
||||
// Language bar item object.
|
||||
CLangBarItemButton* _pLangBarItem;
|
||||
|
||||
// the current composition object.
|
||||
ITfComposition* _pComposition;
|
||||
|
||||
// guidatom for the display attibute.
|
||||
TfGuidAtom _gaDisplayAttributeInput;
|
||||
TfGuidAtom _gaDisplayAttributeConverted;
|
||||
|
||||
CANDIDATE_MODE _candidateMode;
|
||||
CCandidateListUIPresenter *_pCandidateListUIPresenter;
|
||||
BOOL _isCandidateWithWildcard : 1;
|
||||
|
||||
ITfDocumentMgr* _pDocMgrLastFocused;
|
||||
|
||||
ITfContext* _pContext;
|
||||
|
||||
ITfCompartment* _pSIPIMEOnOffCompartment;
|
||||
DWORD _dwSIPIMEOnOffCompartmentSinkCookie;
|
||||
|
||||
HWND _msgWndHandle;
|
||||
|
||||
LONG _refCount;
|
||||
|
||||
// Support the search integration
|
||||
ITfFnSearchCandidateProvider* _pITfFnSearchCandidateProvider;
|
||||
};
|
||||
@@ -0,0 +1,122 @@
|
||||
// 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_SAMPLEIME ICON "image\\SampleIme.ico"
|
||||
IDI_IME_MODE_ON ICON "image\\ImeModeOn.ico"
|
||||
IDI_IME_MODE_OFF ICON "image\\ImeModeOff.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 1,0,0,1
|
||||
PRODUCTVERSION 1,0,0,1
|
||||
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 Sample code of Windows 8 IME"
|
||||
VALUE "FileVersion", "1.0.0.1"
|
||||
VALUE "InternalName", "SampleIM.dll"
|
||||
VALUE "LegalCopyright", "Copyright (C)"
|
||||
VALUE "OriginalFilename", "SampleIM.dll"
|
||||
VALUE "ProductName", "SampleIME"
|
||||
VALUE "ProductVersion", "1.0.0.1"
|
||||
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_SAMPLEIME "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
|
||||
|
||||
@@ -0,0 +1,267 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Dictionary\SampleIMESimplifiedQuanPin.txt" />
|
||||
<None Include="image\DoubleSingleByteOff.ico" />
|
||||
<None Include="image\DoubleSingleByteOn.ico" />
|
||||
<None Include="image\ImeModeOff.ico" />
|
||||
<None Include="image\ImeModeOn.ico" />
|
||||
<None Include="image\PunctuationOff.ico" />
|
||||
<None Include="image\PunctuationOn.ico" />
|
||||
<None Include="image\SampleIme.ico" />
|
||||
<None Include="SampleIME.def" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="BaseDictionaryEngine.h" />
|
||||
<ClInclude Include="BaseWindow.h" />
|
||||
<ClInclude Include="ButtonWindow.h" />
|
||||
<ClInclude Include="CandidateListUIPresenter.h" />
|
||||
<ClInclude Include="CandidateWindow.h" />
|
||||
<ClInclude Include="Compartment.h" />
|
||||
<ClInclude Include="CompositionProcessorEngine.h" />
|
||||
<ClInclude Include="define.h" />
|
||||
<ClInclude Include="EnumTfCandidates.h" />
|
||||
<ClInclude Include="KeyStateCategory.h" />
|
||||
<ClInclude Include="SampleIMEBaseStructure.h" />
|
||||
<ClInclude Include="SearchCandidateProvider.h" />
|
||||
<ClInclude Include="DictionaryParser.h" />
|
||||
<ClInclude Include="DictionarySearch.h" />
|
||||
<ClInclude Include="DisplayAttributeInfo.h" />
|
||||
<ClInclude Include="EditSession.h" />
|
||||
<ClInclude Include="EnumDisplayAttributeInfo.h" />
|
||||
<ClInclude Include="File.h" />
|
||||
<ClInclude Include="FileMapping.h" />
|
||||
<ClInclude Include="GetTextExtentEditSession.h" />
|
||||
<ClInclude Include="Globals.h" />
|
||||
<ClInclude Include="KeyHandlerEditSession.h" />
|
||||
<ClInclude Include="LanguageBar.h" />
|
||||
<ClInclude Include="Private.h" />
|
||||
<ClInclude Include="RegKey.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="SampleIME.h" />
|
||||
<ClInclude Include="ScrollBarWindow.h" />
|
||||
<ClInclude Include="ShadowWindow.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="TableDictionaryEngine.h" />
|
||||
<ClInclude Include="TfInputProcessorProfile.h" />
|
||||
<ClInclude Include="TfTextLayoutSink.h" />
|
||||
<ClInclude Include="TipCandidateList.h" />
|
||||
<ClInclude Include="TipCandidateString.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ActiveLanguageProfileNotifySink.cpp" />
|
||||
<ClCompile Include="BaseDictionaryEngine.cpp" />
|
||||
<ClCompile Include="BaseWindow.cpp" />
|
||||
<ClCompile Include="ButtonWindow.cpp" />
|
||||
<ClCompile Include="CandidateListUIPresenter.cpp" />
|
||||
<ClCompile Include="CandidateWindow.cpp" />
|
||||
<ClCompile Include="Compartment.cpp" />
|
||||
<ClCompile Include="Composition.cpp" />
|
||||
<ClCompile Include="CompositionProcessorEngine.cpp" />
|
||||
<ClCompile Include="EnumTfCandidates.cpp" />
|
||||
<ClCompile Include="KeyStateCategory.cpp" />
|
||||
<ClCompile Include="SampleIMEBaseStructure.cpp" />
|
||||
<ClCompile Include="SearchCandidateProvider.cpp" />
|
||||
<ClCompile Include="DictionaryParser.cpp" />
|
||||
<ClCompile Include="DictionarySearch.cpp" />
|
||||
<ClCompile Include="DisplayAttribute.cpp" />
|
||||
<ClCompile Include="DisplayAttributeInfo.cpp" />
|
||||
<ClCompile Include="DisplayAttributeProvider.cpp" />
|
||||
<ClCompile Include="DllMain.cpp" />
|
||||
<ClCompile Include="EditSession.cpp" />
|
||||
<ClCompile Include="EndComposition.cpp" />
|
||||
<ClCompile Include="EnumDisplayAttributeInfo.cpp" />
|
||||
<ClCompile Include="File.cpp" />
|
||||
<ClCompile Include="FileMapping.cpp" />
|
||||
<ClCompile Include="FunctionProviderSink.cpp" />
|
||||
<ClCompile Include="GetTextExtentEditSession.cpp" />
|
||||
<ClCompile Include="Globals.cpp" />
|
||||
<ClCompile Include="KeyEventSink.cpp" />
|
||||
<ClCompile Include="KeyHandler.cpp" />
|
||||
<ClCompile Include="KeyHandlerEditSession.cpp" />
|
||||
<ClCompile Include="LanguageBar.cpp" />
|
||||
<ClCompile Include="Register.cpp" />
|
||||
<ClCompile Include="RegKey.cpp" />
|
||||
<ClCompile Include="ScrollBarWindow.cpp" />
|
||||
<ClCompile Include="Server.cpp" />
|
||||
<ClCompile Include="ShadowWindow.cpp" />
|
||||
<ClCompile Include="StartComposition.cpp" />
|
||||
<ClCompile Include="TableDictionaryEngine.cpp" />
|
||||
<ClCompile Include="SampleIME.cpp" />
|
||||
<ClCompile Include="TextEditSink.cpp" />
|
||||
<ClCompile Include="TfInputProcessorProfile.cpp" />
|
||||
<ClCompile Include="TfTextLayoutSink.cpp" />
|
||||
<ClCompile Include="ThreadFocusSink.cpp" />
|
||||
<ClCompile Include="ThreadMgrEventSink.cpp" />
|
||||
<ClCompile Include="TipCandidateList.cpp" />
|
||||
<ClCompile Include="TipCandidateString.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="SampleIME.rc" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{0C8FE010-5146-44D8-AF99-82702C15FEA5}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>SampleIME</RootNamespace>
|
||||
<ProjectName>SampleIME</ProjectName>
|
||||
<VCTargetsPath Condition="'$(VCTargetsPath11)' != '' and '$(VSVersion)' == '' and $(VisualStudioVersion) == ''">$(VCTargetsPath11)</VCTargetsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;SampleIME_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\Windows Kits\8.0\Include\um;$(MSBuildProgramFiles32)\Windows Kits\8.0\Include\shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(MSBuildProgramFiles32)\Windows Kits\8.0\Lib\win8\um\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>SampleIME.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;SampleIME_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\Windows Kits\8.0\Include\um;$(MSBuildProgramFiles32)\Windows Kits\8.0\Include\shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(MSBuildProgramFiles32)\Windows Kits\8.0\Lib\win8\um\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>SampleIME.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;SampleIME_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\Windows Kits\8.0\Include\um;$(MSBuildProgramFiles32)\Windows Kits\8.0\Include\shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<BrowseInformation>false</BrowseInformation>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>false</EnableCOMDATFolding>
|
||||
<OptimizeReferences>false</OptimizeReferences>
|
||||
<AdditionalLibraryDirectories>$(MSBuildProgramFiles32)\Windows Kits\8.0\Lib\win8\um\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>SampleIME.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;SampleIME_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\Windows Kits\8.0\Include\um;$(MSBuildProgramFiles32)\Windows Kits\8.0\Include\shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<BrowseInformation>false</BrowseInformation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>false</EnableCOMDATFolding>
|
||||
<OptimizeReferences>false</OptimizeReferences>
|
||||
<AdditionalLibraryDirectories>$(MSBuildProgramFiles32)\Windows Kits\8.0\Lib\win8\um\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>SampleIME.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,301 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Dictionary">
|
||||
<UniqueIdentifier>{fe9b9e3e-f048-48b1-ae0b-718fc88cff49}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="SampleIME.def">
|
||||
<Filter>Source Files</Filter>
|
||||
</None>
|
||||
<None Include="Dictionary\SampleIMESimplifiedQuanPin.txt">
|
||||
<Filter>Dictionary</Filter>
|
||||
</None>
|
||||
<None Include="image\SampleIme.ico">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="image\ImeModeOn.ico">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="image\ImeModeOff.ico">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="image\DoubleSingleByteOn.ico">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="image\DoubleSingleByteOff.ico">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="image\PunctuationOn.ico">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="image\PunctuationOff.ico">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="BaseDictionaryEngine.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="BaseWindow.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ButtonWindow.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CandidateWindow.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Compartment.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CompositionProcessorEngine.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DictionaryParser.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DictionarySearch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DisplayAttributeInfo.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="EditSession.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="EnumDisplayAttributeInfo.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="File.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FileMapping.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GetTextExtentEditSession.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Globals.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="KeyHandlerEditSession.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="LanguageBar.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Private.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="RegKey.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ScrollBarWindow.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ShadowWindow.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TableDictionaryEngine.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TfInputProcessorProfile.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TfTextLayoutSink.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SampleIME.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SearchCandidateProvider.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TipCandidateList.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="EnumTfCandidates.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TipCandidateString.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="KeyStateCategory.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CandidateListUIPresenter.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SampleIMEBaseStructure.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="define.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ActiveLanguageProfileNotifySink.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="BaseDictionaryEngine.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="BaseWindow.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ButtonWindow.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CandidateWindow.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Compartment.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Composition.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CompositionProcessorEngine.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DictionaryParser.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DictionarySearch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DisplayAttribute.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DisplayAttributeInfo.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DisplayAttributeProvider.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DllMain.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="EditSession.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="EndComposition.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="EnumDisplayAttributeInfo.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="File.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FileMapping.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GetTextExtentEditSession.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Globals.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="KeyEventSink.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="KeyHandler.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="KeyHandlerEditSession.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="LanguageBar.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Register.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="RegKey.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ScrollBarWindow.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Server.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ShadowWindow.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="StartComposition.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TableDictionaryEngine.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TextEditSink.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TfInputProcessorProfile.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TfTextLayoutSink.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ThreadFocusSink.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ThreadMgrEventSink.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SampleIME.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FunctionProviderSink.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SearchCandidateProvider.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TipCandidateList.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="EnumTfCandidates.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TipCandidateString.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="KeyStateCategory.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CandidateListUIPresenter.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SampleIMEBaseStructure.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="SampleIME.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,325 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#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 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';
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
_pairPunctuation = 0;
|
||||
_isPairToggle = FALSE;
|
||||
}
|
||||
|
||||
CPunctuationPair::CPunctuationPair(WCHAR code, WCHAR punctuation, WCHAR pair)
|
||||
{
|
||||
_punctuation._Code = code;
|
||||
_punctuation._Punctuation = punctuation;
|
||||
_pairPunctuation = pair;
|
||||
_isPairToggle = FALSE;
|
||||
}
|
||||
|
||||
CPunctuationNestPair::CPunctuationNestPair()
|
||||
{
|
||||
_punctuation_begin._Code = 0;
|
||||
_punctuation_begin._Punctuation = 0;
|
||||
_pairPunctuation_begin = 0;
|
||||
|
||||
_punctuation_end._Code = 0;
|
||||
_punctuation_end._Punctuation = 0;
|
||||
_pairPunctuation_end = 0;
|
||||
|
||||
_nestCount = 0;
|
||||
}
|
||||
|
||||
CPunctuationNestPair::CPunctuationNestPair(WCHAR codeBegin, WCHAR punctuationBegin, WCHAR pairBegin,
|
||||
WCHAR codeEnd, WCHAR punctuationEnd, WCHAR pairEnd)
|
||||
{
|
||||
pairEnd;punctuationEnd;
|
||||
_punctuation_begin._Code = codeBegin;
|
||||
_punctuation_begin._Punctuation = punctuationBegin;
|
||||
_pairPunctuation_begin = pairBegin;
|
||||
|
||||
_punctuation_end._Code = codeEnd;
|
||||
_punctuation_end._Punctuation = punctuationBegin;
|
||||
_pairPunctuation_end = pairBegin;
|
||||
|
||||
_nestCount = 0;
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <vector>
|
||||
#include "assert.h"
|
||||
#include <iostream>
|
||||
|
||||
using std::cout;
|
||||
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_PHRASE,
|
||||
CATEGORY_PHRASEFROMKEYSTROKE,
|
||||
CATEGORY_INVOKE_COMPOSITION_EDIT_SESSION
|
||||
};
|
||||
|
||||
enum KEYSTROKE_FUNCTION
|
||||
{
|
||||
FUNCTION_NONE = 0,
|
||||
FUNCTION_INPUT,
|
||||
|
||||
FUNCTION_CANCEL,
|
||||
FUNCTION_FINALIZE_TEXTSTORE,
|
||||
FUNCTION_FINALIZE_TEXTSTORE_AND_INPUT,
|
||||
FUNCTION_FINALIZE_CANDIDATELIST,
|
||||
FUNCTION_FINALIZE_CANDIDATELIST_AND_INPUT,
|
||||
FUNCTION_CONVERT,
|
||||
FUNCTION_CONVERT_WILDCARD,
|
||||
FUNCTION_SELECT_BY_NUMBER,
|
||||
FUNCTION_BACKSPACE,
|
||||
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
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// candidate list
|
||||
//---------------------------------------------------------------------
|
||||
enum CANDIDATE_MODE
|
||||
{
|
||||
CANDIDATE_NONE = 0,
|
||||
CANDIDATE_ORIGINAL,
|
||||
CANDIDATE_PHRASE,
|
||||
CANDIDATE_INCREMENTAL,
|
||||
CANDIDATE_WITH_NEXT_COMPOSITION
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// structure
|
||||
//---------------------------------------------------------------------
|
||||
struct _KEYSTROKE_STATE
|
||||
{
|
||||
KEYSTROKE_CATEGORY Category;
|
||||
KEYSTROKE_FUNCTION Function;
|
||||
};
|
||||
|
||||
struct _PUNCTUATION
|
||||
{
|
||||
WCHAR _Code;
|
||||
WCHAR _Punctuation;
|
||||
};
|
||||
|
||||
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 CSampleImeArray
|
||||
{
|
||||
typedef typename std::vector<T> CSampleImeInnerArray;
|
||||
typedef typename std::vector<T>::iterator CSampleImeInnerIter;
|
||||
|
||||
public:
|
||||
CSampleImeArray(): _innerVect()
|
||||
{
|
||||
}
|
||||
|
||||
explicit CSampleImeArray(size_t count): _innerVect(count)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~CSampleImeArray()
|
||||
{
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
CSampleImeInnerIter 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:
|
||||
CSampleImeInnerArray _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:
|
||||
CSampleImeArray<DWORD> _CandidateListIndexRange;
|
||||
};
|
||||
|
||||
class CStringRange
|
||||
{
|
||||
public:
|
||||
CStringRange();
|
||||
~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);
|
||||
|
||||
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;
|
||||
_FindKeyCode = rhs._FindKeyCode;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
class CPunctuationPair
|
||||
{
|
||||
public:
|
||||
CPunctuationPair();
|
||||
CPunctuationPair(WCHAR code, WCHAR punctuation, WCHAR pair);
|
||||
|
||||
struct _PUNCTUATION _punctuation;
|
||||
WCHAR _pairPunctuation;
|
||||
BOOL _isPairToggle;
|
||||
};
|
||||
|
||||
class CPunctuationNestPair
|
||||
{
|
||||
public:
|
||||
CPunctuationNestPair();
|
||||
CPunctuationNestPair(WCHAR wchCode_begin, WCHAR wch_begin, WCHAR wchPair_begin,
|
||||
WCHAR wchCode_end, WCHAR wch_end, WCHAR wchPair_end);
|
||||
|
||||
struct _PUNCTUATION _punctuation_begin;
|
||||
WCHAR _pairPunctuation_begin;
|
||||
|
||||
struct _PUNCTUATION _punctuation_end;
|
||||
WCHAR _pairPunctuation_end;
|
||||
|
||||
int _nestCount;
|
||||
};
|
||||
@@ -0,0 +1,80 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// CSampleIMESampleIMEStructureArray.h
|
||||
//
|
||||
// CSampleIMEStructureArray declaration.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
template<class T>
|
||||
class CSampleIMEStructureArray
|
||||
{
|
||||
typedef typename std::vector<T> value_type;
|
||||
typedef const T& CONST_REF;
|
||||
typedef typename value_type CSampleIMEArray;
|
||||
typedef typename value_type::iterator CSampleIMEIter;
|
||||
|
||||
public:
|
||||
CSampleIMEStructureArray(): _imeVector()
|
||||
{
|
||||
}
|
||||
|
||||
explicit CSampleIMEStructureArray(size_t iCount): _imeVector(iCount)
|
||||
{
|
||||
}
|
||||
|
||||
CSampleIMEStructureArray(size_t iCount, CONST_REF tVal): _imeVector(iCount, tVal)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~CSampleIMEStructureArray() {}
|
||||
|
||||
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);
|
||||
|
||||
CSampleIMEIter beginIter = _imeVector.begin() + iIndex;
|
||||
CSampleIMEIter 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:
|
||||
CSampleIMEArray _imeVector; // the actual array of data
|
||||
CSampleIMEIter _imeIter;
|
||||
};
|
||||
@@ -0,0 +1,650 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "BaseWindow.h"
|
||||
#include "ScrollBarWindow.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CScrollBarWindowFactory class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
CScrollBarWindowFactory* CScrollBarWindowFactory::_instance;
|
||||
|
||||
CScrollBarWindowFactory::CScrollBarWindowFactory()
|
||||
{
|
||||
_instance = nullptr;
|
||||
}
|
||||
|
||||
CScrollBarWindowFactory* CScrollBarWindowFactory::Instance()
|
||||
{
|
||||
if (nullptr == _instance)
|
||||
{
|
||||
_instance = new (std::nothrow) CScrollBarWindowFactory();
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
|
||||
CScrollBarWindow* CScrollBarWindowFactory::MakeScrollBarWindow(SHELL_MODE shellMode)
|
||||
{
|
||||
CScrollBarWindow* pScrollBarWindow = nullptr;
|
||||
|
||||
switch (shellMode)
|
||||
{
|
||||
case STOREAPP:
|
||||
pScrollBarWindow = new (std::nothrow) CScrollBarWindow();
|
||||
break;
|
||||
|
||||
case DESKTOP:
|
||||
pScrollBarWindow = new (std::nothrow) CScrollBarNullWindow();
|
||||
break;
|
||||
|
||||
default:
|
||||
pScrollBarWindow = new (std::nothrow) CScrollBarNullWindow();
|
||||
break;
|
||||
}
|
||||
return pScrollBarWindow;
|
||||
}
|
||||
|
||||
void CScrollBarWindowFactory::Release()
|
||||
{
|
||||
if (_instance)
|
||||
{
|
||||
delete _instance;
|
||||
_instance = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CScrollBarWindow class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ctor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CScrollBarWindow::CScrollBarWindow()
|
||||
{
|
||||
_pBtnUp = nullptr;
|
||||
_pBtnDn = nullptr;
|
||||
|
||||
_scrollDir = SCROLL_NONE_DIR;
|
||||
|
||||
_sizeOfScrollBtn.cx = GetSystemMetrics(SM_CXVSCROLL) * 2;
|
||||
_sizeOfScrollBtn.cy = GetSystemMetrics(SM_CYVSCROLL) * 2;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// dtor
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CScrollBarWindow::~CScrollBarWindow()
|
||||
{
|
||||
if (_pBtnUp)
|
||||
{
|
||||
delete _pBtnUp;
|
||||
_pBtnUp = nullptr;
|
||||
}
|
||||
if (_pBtnDn)
|
||||
{
|
||||
delete _pBtnDn;
|
||||
_pBtnDn = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _Create
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CScrollBarWindow::_Create(ATOM atom, DWORD dwExStyle, DWORD dwStyle, CBaseWindow *pParent, int wndWidth, int wndHeight)
|
||||
{
|
||||
if (!CBaseWindow::_Create(atom, dwExStyle, dwStyle, pParent, wndWidth, wndHeight))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_pBtnUp = new (std::nothrow) CScrollButtonWindow(dwStyle & WS_HSCROLL ? DFCS_SCROLLLEFT : DFCS_SCROLLUP);
|
||||
if (_pBtnUp == nullptr)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_pBtnUp->_Create(NULL, 0, 0, this);
|
||||
_pBtnUp->_SetUIWnd(_GetUIWnd());
|
||||
|
||||
_pBtnDn = new (std::nothrow) CScrollButtonWindow(dwStyle & WS_HSCROLL ? DFCS_SCROLLRIGHT : DFCS_SCROLLDOWN);
|
||||
if (_pBtnDn == nullptr)
|
||||
{
|
||||
delete _pBtnUp;
|
||||
_pBtnUp = nullptr;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_pBtnDn->_Create(NULL, 0, 0, this);
|
||||
_pBtnDn->_SetUIWnd(_GetUIWnd());
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _WindowProcCallback
|
||||
//
|
||||
// Scrollbar window proc.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
LRESULT CALLBACK CScrollBarWindow::_WindowProcCallback(_In_ HWND wndHandle, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam)
|
||||
{
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_PAINT:
|
||||
{
|
||||
HDC dcHandle = nullptr;
|
||||
PAINTSTRUCT ps;
|
||||
|
||||
dcHandle = BeginPaint(wndHandle, &ps);
|
||||
|
||||
// paint itself at first
|
||||
_OnPaint(dcHandle, &ps);
|
||||
|
||||
// paint all children
|
||||
_pBtnUp->_OnPaint(dcHandle, &ps);
|
||||
_pBtnDn->_OnPaint(dcHandle, &ps);
|
||||
|
||||
EndPaint(wndHandle, &ps);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return DefWindowProc(wndHandle, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _OnPaint
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CScrollBarWindow::_OnPaint(_In_ HDC dcHandle, _In_ PAINTSTRUCT *pps)
|
||||
{
|
||||
HBRUSH hBrush = nullptr;
|
||||
CBaseWindow* pUIWnd = _GetUIWnd();
|
||||
|
||||
if (pUIWnd != nullptr && pUIWnd->_GetWnd())
|
||||
{
|
||||
hBrush = (HBRUSH)DefWindowProc(pUIWnd->_GetWnd(), WM_CTLCOLORSCROLLBAR, (WPARAM)dcHandle, (LPARAM)pUIWnd->_GetWnd());
|
||||
}
|
||||
|
||||
if (hBrush == nullptr)
|
||||
{
|
||||
hBrush = GetSysColorBrush(COLOR_SCROLLBAR);
|
||||
}
|
||||
|
||||
FillRect(dcHandle, &pps->rcPaint, hBrush);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _OnLButtonDown
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CScrollBarWindow::_OnLButtonDown(POINT pt)
|
||||
{
|
||||
_StartCapture();
|
||||
|
||||
RECT rc = {0, 0, 0, 0};
|
||||
|
||||
_pBtnUp->_GetClientRect(&rc);
|
||||
if (PtInRect(&rc, pt))
|
||||
{
|
||||
_pBtnUp->_OnLButtonDown(pt);
|
||||
}
|
||||
else
|
||||
{
|
||||
_pBtnDn->_GetClientRect(&rc);
|
||||
if (PtInRect(&rc, pt))
|
||||
{
|
||||
_pBtnDn->_OnLButtonDown(pt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _OnLButtonUp
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CScrollBarWindow::_OnLButtonUp(POINT pt)
|
||||
{
|
||||
if (_IsCapture())
|
||||
{
|
||||
CBaseWindow* pUIWnd = _GetTopmostUIWnd();
|
||||
if (pUIWnd)
|
||||
{
|
||||
CBaseWindow *pCapture = pUIWnd->_GetCaptureObject();
|
||||
if (pCapture && pCapture != this)
|
||||
{
|
||||
pCapture->_OnLButtonUp(pt);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RECT rc = {0, 0, 0, 0};
|
||||
|
||||
_pBtnUp->_GetClientRect(&rc);
|
||||
if (PtInRect(&rc, pt))
|
||||
{
|
||||
_pBtnUp->_OnLButtonUp(pt);
|
||||
}
|
||||
else
|
||||
{
|
||||
_pBtnDn->_GetClientRect(&rc);
|
||||
if (PtInRect(&rc, pt))
|
||||
{
|
||||
_pBtnDn->_OnLButtonUp(pt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_IsCapture())
|
||||
{
|
||||
_EndCapture();
|
||||
}
|
||||
if (_IsTimer())
|
||||
{
|
||||
_EndTimer();
|
||||
}
|
||||
|
||||
_scrollDir = SCROLL_NONE_DIR;
|
||||
_InvalidateRect();
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _OnMouseMove
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CScrollBarWindow::_OnMouseMove(POINT pt)
|
||||
{
|
||||
RECT rc = {0, 0, 0, 0};
|
||||
|
||||
_pBtnUp->_GetClientRect(&rc);
|
||||
if (PtInRect(&rc, pt))
|
||||
{
|
||||
_pBtnUp->_OnMouseMove(pt);
|
||||
}
|
||||
else
|
||||
{
|
||||
_pBtnDn->_GetClientRect(&rc);
|
||||
if (PtInRect(&rc, pt))
|
||||
{
|
||||
_pBtnDn->_OnMouseMove(pt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _OnOwnerWndMoved
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CScrollBarWindow::_OnOwnerWndMoved(BOOL isResized)
|
||||
{
|
||||
isResized;
|
||||
|
||||
if (IsWindow(_GetWnd()) && IsWindowVisible(_GetWnd()))
|
||||
{
|
||||
_AdjustWindowPos();
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _Resize
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CScrollBarWindow::_Resize(int x, int y, int cx, int cy)
|
||||
{
|
||||
CBaseWindow::_Resize(x, y, cx, cy);
|
||||
|
||||
RECT rc = {0, 0, 0, 0};
|
||||
|
||||
_GetBtnUpRect(&rc);
|
||||
_pBtnUp->_Resize(rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top);
|
||||
|
||||
_GetBtnDnRect(&rc);
|
||||
_pBtnDn->_Resize(rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _Show
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CScrollBarWindow::_Show(BOOL isShowWnd)
|
||||
{
|
||||
if (_IsWindowVisible() != isShowWnd)
|
||||
{
|
||||
CBaseWindow::_Show(isShowWnd);
|
||||
|
||||
_pBtnUp->_Show(isShowWnd);
|
||||
_pBtnDn->_Show(isShowWnd);
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _Enable
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CScrollBarWindow::_Enable(BOOL isEnable)
|
||||
{
|
||||
if (_IsEnabled() != isEnable)
|
||||
{
|
||||
CBaseWindow::_Enable(isEnable);
|
||||
|
||||
_pBtnUp->_Enable(isEnable);
|
||||
_pBtnDn->_Enable(isEnable);
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _AdjustWindowPos
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CScrollBarWindow::_AdjustWindowPos()
|
||||
{
|
||||
if (!IsWindow(_GetWnd()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RECT rc = {0, 0, 0, 0};
|
||||
CBaseWindow* pParent = _GetParent();
|
||||
if (pParent == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GetWindowRect(pParent->_GetWnd(), &rc);
|
||||
SetWindowPos(_GetWnd(), pParent->_GetWnd(),
|
||||
rc.left,
|
||||
rc.top,
|
||||
rc.right - rc.left,
|
||||
rc.bottom - rc.top,
|
||||
SWP_NOOWNERZORDER | SWP_NOACTIVATE);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _SetScrollInfo
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CScrollBarWindow::_SetScrollInfo(_In_ CScrollInfo *lpsi)
|
||||
{
|
||||
_scrollInfo = *lpsi;
|
||||
|
||||
BOOL isEnable = (_scrollInfo.nMax > _scrollInfo.nPage);
|
||||
|
||||
_Enable(isEnable);
|
||||
|
||||
_scrollDir = SCROLL_NONE_DIR;
|
||||
|
||||
_SetCurPos(_scrollInfo.nPos, -1);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _GetScrollInfo
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CScrollBarWindow::_GetScrollInfo(_Out_ CScrollInfo *lpsi)
|
||||
{
|
||||
*lpsi = _scrollInfo;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _GetBtnUpRect
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CScrollBarWindow::_GetBtnUpRect(_Out_ RECT *prc)
|
||||
{
|
||||
RECT rc = {0, 0, 0, 0};
|
||||
|
||||
_GetClientRect(&rc);
|
||||
|
||||
if (prc == nullptr)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
prc->left = rc.left;
|
||||
prc->top = rc.top;
|
||||
prc->right = rc.right;
|
||||
prc->bottom = rc.top + min(_sizeOfScrollBtn.cy, (rc.bottom - rc.top)/2);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _GetBtnDnRect
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CScrollBarWindow::_GetBtnDnRect(_Out_ RECT *prc)
|
||||
{
|
||||
RECT rc = {0, 0, 0, 0};
|
||||
|
||||
_GetClientRect(&rc);
|
||||
|
||||
if (prc == nullptr)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
prc->left = rc.left;
|
||||
prc->top = rc.bottom - min(_sizeOfScrollBtn.cy, (rc.bottom - rc.top)/2);
|
||||
prc->right = rc.right;
|
||||
prc->bottom = rc.bottom;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _GetScrollArea
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CScrollBarWindow::_GetScrollArea(_Out_ RECT *prc)
|
||||
{
|
||||
RECT rcBtnUp = {0, 0, 0, 0};
|
||||
RECT rcBtnDn = {0, 0, 0, 0};
|
||||
|
||||
_GetBtnUpRect(&rcBtnUp);
|
||||
_GetBtnDnRect(&rcBtnDn);
|
||||
|
||||
RECT rc = {0, 0, 0, 0};
|
||||
|
||||
_GetClientRect(&rc);
|
||||
|
||||
if (prc == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
prc->left = rc.left;
|
||||
prc->top = rc.top + (rcBtnUp.bottom - rcBtnUp.top);
|
||||
prc->right = rc.right;
|
||||
prc->bottom = rc.bottom - (rcBtnDn.bottom - rcBtnDn.top);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _SetCurPos
|
||||
//
|
||||
// param: dwSB - SB_xxx for WM_VSCROLL or WM_HSCROLL.
|
||||
// if -1 is specified, function doesn't send WM_xSCROLL message
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CScrollBarWindow::_SetCurPos(int nPos, int dwSB)
|
||||
{
|
||||
int posMax = (_scrollInfo.nMax <= _scrollInfo.nPage) ? 0 : _scrollInfo.nMax - _scrollInfo.nPage;
|
||||
|
||||
nPos = min(nPos, posMax);
|
||||
nPos = max(nPos, 0);
|
||||
|
||||
_scrollInfo.nPos = nPos;
|
||||
|
||||
if (_IsWindowVisible()) {
|
||||
_InvalidateRect();
|
||||
}
|
||||
|
||||
if ((_IsCapture() && dwSB != -1) || (dwSB == SB_THUMBPOSITION))
|
||||
{
|
||||
_NotifyCommand(WM_VSCROLL, dwSB, nPos);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CScrollButtonWindow class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _OnPaint
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CScrollButtonWindow::_OnPaint(_In_ HDC dcHandle, _In_ PAINTSTRUCT *pps)
|
||||
{
|
||||
pps;
|
||||
|
||||
RECT rc = {0, 0, 0, 0};
|
||||
|
||||
_GetClientRect(&rc);
|
||||
|
||||
DrawFrameControl(dcHandle, &rc, DFC_SCROLL, subTypeOfControl | typeOfControl | (!_IsEnabled() ? DFCS_INACTIVE : 0));
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _OnLButtonDown
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CScrollButtonWindow::_OnLButtonDown(POINT pt)
|
||||
{
|
||||
CButtonWindow::_OnLButtonDown(pt);
|
||||
|
||||
CScrollBarWindow* pParent = (CScrollBarWindow*)_GetParent(); // more secure w/ dynamic_cast
|
||||
if (pParent == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (subTypeOfControl)
|
||||
{
|
||||
case DFCS_SCROLLDOWN:
|
||||
_NotifyCommand(WM_VSCROLL, SB_LINEDOWN, 0);
|
||||
pParent->_ShiftLine(+1, FALSE);
|
||||
break;
|
||||
case DFCS_SCROLLUP:
|
||||
_NotifyCommand(WM_VSCROLL, SB_LINEUP, 0);
|
||||
pParent->_ShiftLine(-1, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
_StartTimer(_GetScrollDelay());
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _OnLButtonUp
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CScrollButtonWindow::_OnLButtonUp(POINT pt)
|
||||
{
|
||||
CButtonWindow::_OnLButtonUp(pt);
|
||||
|
||||
_InvalidateRect();
|
||||
|
||||
if (_IsTimer())
|
||||
{
|
||||
_EndTimer();
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _OnTimer : Speed up page Down/Up while holding Down/Up Button
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CScrollButtonWindow::_OnTimer()
|
||||
{
|
||||
POINT pt = {0, 0};
|
||||
CScrollBarWindow* pParent = (CScrollBarWindow*)_GetParent(); // more secure w/ dynamic_cast
|
||||
if (pParent == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// start another faster timer
|
||||
_StartTimer(_GetScrollSpeed());
|
||||
|
||||
GetCursorPos(&pt);
|
||||
MapWindowPoints(HWND_DESKTOP, pParent->_GetWnd(), &pt, 1);
|
||||
|
||||
RECT rc = {0, 0, 0, 0};
|
||||
|
||||
_GetClientRect(&rc);
|
||||
|
||||
if (PtInRect(&rc, pt))
|
||||
{
|
||||
switch (subTypeOfControl)
|
||||
{
|
||||
case DFCS_SCROLLDOWN:
|
||||
_NotifyCommand(WM_VSCROLL, SB_LINEDOWN, 0);
|
||||
pParent->_ShiftLine(+1, FALSE);
|
||||
break;
|
||||
case DFCS_SCROLLUP:
|
||||
_NotifyCommand(WM_VSCROLL, SB_LINEUP, 0);
|
||||
pParent->_ShiftLine(-1, FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2005 Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// ScrollBarWindow.h
|
||||
//
|
||||
// CScrollBarWindow declaration.
|
||||
//
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BaseWindow.h"
|
||||
#include "ButtonWindow.h"
|
||||
|
||||
class CScrollButtonWindow;
|
||||
|
||||
enum SCROLLBAR_DIRECTION
|
||||
{
|
||||
SCROLL_NONE_DIR,
|
||||
SCROLL_PAGEDOWN, // or page left
|
||||
SCROLL_PAGEUP // or page right
|
||||
};
|
||||
|
||||
enum SHELL_MODE
|
||||
{
|
||||
STOREAPP,
|
||||
DESKTOP,
|
||||
};
|
||||
|
||||
struct CScrollInfo
|
||||
{
|
||||
CScrollInfo()
|
||||
{
|
||||
nMax = 0;
|
||||
nPage = 0;
|
||||
nPos = 0;
|
||||
}
|
||||
|
||||
int nMax;
|
||||
int nPage;
|
||||
int nPos;
|
||||
};
|
||||
|
||||
class CScrollBarWindow;
|
||||
|
||||
class CScrollBarWindowFactory
|
||||
{
|
||||
public:
|
||||
static CScrollBarWindowFactory* Instance();
|
||||
CScrollBarWindow* MakeScrollBarWindow(SHELL_MODE shellMode);
|
||||
void Release();
|
||||
|
||||
protected:
|
||||
CScrollBarWindowFactory();
|
||||
|
||||
private:
|
||||
static CScrollBarWindowFactory* _instance;
|
||||
|
||||
};
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CScrollBarWindow declaration.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CScrollBarWindow : public CBaseWindow
|
||||
{
|
||||
public:
|
||||
CScrollBarWindow();
|
||||
virtual ~CScrollBarWindow();
|
||||
|
||||
BOOL _Create(ATOM atom, DWORD dwExStyle, DWORD dwStyle, CBaseWindow *pParent = nullptr, int wndWidth = 0, int wndHeight = 0);
|
||||
|
||||
void _Resize(int x, int y, int cx, int cy);
|
||||
void _Show(BOOL isShowWnd);
|
||||
void _Enable(BOOL isEnable);
|
||||
|
||||
LRESULT CALLBACK _WindowProcCallback(_In_ HWND wndHandle, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam);
|
||||
virtual void _OnPaint(_In_ HDC dcHandle, _In_ PAINTSTRUCT *pps);
|
||||
virtual void _OnLButtonDown(POINT pt);
|
||||
virtual void _OnLButtonUp(POINT pt);
|
||||
virtual void _OnMouseMove(POINT pt);
|
||||
virtual void _OnTimer() { };
|
||||
|
||||
virtual void _OnOwnerWndMoved(BOOL isResized);
|
||||
|
||||
virtual void _SetScrollInfo(_In_ CScrollInfo *lpsi);
|
||||
virtual void _GetScrollInfo(_Out_ CScrollInfo *lpsi);
|
||||
|
||||
virtual BOOL _GetBtnUpRect(_Out_ RECT *prc);
|
||||
virtual BOOL _GetBtnDnRect(_Out_ RECT *prc);
|
||||
|
||||
virtual void _ShiftLine(int nLine, BOOL isNotify)
|
||||
{
|
||||
DWORD dwSB = 0;
|
||||
|
||||
dwSB = (nLine > 0 ? SB_LINEDOWN :
|
||||
nLine < 0 ? SB_LINEUP : 0);
|
||||
|
||||
_SetCurPos(_scrollInfo.nPos + nLine, isNotify ? dwSB : -1);
|
||||
}
|
||||
|
||||
virtual void _ShiftPage(int nPage, BOOL isNotify)
|
||||
{
|
||||
DWORD dwSB = 0;
|
||||
|
||||
dwSB = (nPage > 0 ? SB_PAGEDOWN :
|
||||
nPage < 0 ? SB_PAGEUP : 0);
|
||||
|
||||
_SetCurPos(_scrollInfo.nPos + _scrollInfo.nPage * nPage, isNotify ? dwSB : -1);
|
||||
}
|
||||
|
||||
virtual void _ShiftPosition(int iPos, BOOL isNotify)
|
||||
{
|
||||
_SetCurPos(iPos, isNotify ? SB_THUMBPOSITION : -1);
|
||||
}
|
||||
|
||||
virtual void _GetScrollArea(_Out_ RECT *prc);
|
||||
virtual void _SetCurPos(int nPos, int dwSB);
|
||||
|
||||
private:
|
||||
void _AdjustWindowPos();
|
||||
|
||||
CScrollButtonWindow* _pBtnUp;
|
||||
CScrollButtonWindow* _pBtnDn;
|
||||
|
||||
CScrollInfo _scrollInfo;
|
||||
SIZE _sizeOfScrollBtn;
|
||||
SCROLLBAR_DIRECTION _scrollDir;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CScrollBarNullWindow declaration.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CScrollBarNullWindow : public CScrollBarWindow
|
||||
{
|
||||
public:
|
||||
CScrollBarNullWindow() { };
|
||||
virtual ~CScrollBarNullWindow() { };
|
||||
|
||||
virtual BOOL _Create(ATOM atom, DWORD dwExStyle, DWORD dwStyle, _In_opt_ CBaseWindow *pParent = nullptr, int wndWidth = 0, int wndHeight = 0)
|
||||
{
|
||||
atom; dwExStyle; dwStyle; pParent; wndWidth; wndHeight;
|
||||
return TRUE;
|
||||
};
|
||||
|
||||
virtual void _Destroy() { };
|
||||
|
||||
virtual void _Move(int x, int y) { x;y; };
|
||||
virtual void _Resize(int x, int y, int cx, int cy) { x; y; cx; cy; };
|
||||
virtual void _Show(BOOL isShowWnd) { isShowWnd; };
|
||||
virtual BOOL _IsWindowVisible() { return TRUE; };
|
||||
virtual void _Enable(BOOL isEnable) { isEnable; };
|
||||
virtual BOOL _IsEnabled() { return TRUE; };
|
||||
virtual void _InvalidateRect() { };
|
||||
virtual BOOL _GetWindowRect(_Out_ LPRECT lpRect) { lpRect->bottom = 0; lpRect->left = 0; lpRect->right = 0; lpRect->top = 0; return TRUE; };
|
||||
virtual BOOL _GetClientRect(_Out_ LPRECT lpRect) { lpRect->bottom = 0; lpRect->left = 0; lpRect->right = 0; lpRect->top = 0; return TRUE; };
|
||||
|
||||
virtual LRESULT CALLBACK _WindowProcCallback(_In_ HWND wndHandle, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam)
|
||||
{
|
||||
wndHandle; uMsg; wParam; lParam;
|
||||
return 0;
|
||||
};
|
||||
virtual void _OnPaint(_In_ HDC dcHandle, _In_ PAINTSTRUCT *pps) { dcHandle;pps; };
|
||||
virtual void _OnLButtonDown(POINT pt) { pt; };
|
||||
virtual void _OnLButtonUp(POINT pt) { pt; };
|
||||
virtual void _OnMouseMove(POINT pt) { pt; };
|
||||
virtual void _OnTimer() { };
|
||||
|
||||
virtual void _OnOwnerWndMoved(BOOL isResized) { isResized; };
|
||||
|
||||
virtual void _SetScrollInfo(_In_ CScrollInfo *lpsi) { lpsi; };
|
||||
virtual void _GetScrollInfo(_In_ CScrollInfo *lpsi) { lpsi; };
|
||||
|
||||
virtual BOOL _GetBtnUpRect(_Out_ RECT *prc) { prc->bottom = 0; prc->left = 0; prc->right = 0; prc->top = 0; return TRUE; };
|
||||
virtual BOOL _GetBtnDnRect(_Out_ RECT *prc) { prc->bottom = 0; prc->left = 0; prc->right = 0; prc->top = 0; return TRUE; };
|
||||
|
||||
virtual void _ShiftLine(int nLine, BOOL isNotify) { nLine; isNotify; };
|
||||
virtual void _ShiftPage(int nPage, BOOL isNotify) { nPage; isNotify; };
|
||||
virtual void _ShiftPosition(int iPos, BOOL isNotify) { iPos; isNotify; };
|
||||
virtual void _GetScrollArea(_Out_ RECT *prc) { prc->bottom = 0; prc->left = 0; prc->right = 0; prc->top = 0; };
|
||||
virtual void _SetCurPos(int nPos, DWORD dwSB) { nPos; dwSB; };
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CScrollButtonWondow declaration.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CScrollButtonWindow : public CButtonWindow
|
||||
{
|
||||
public:
|
||||
CScrollButtonWindow(UINT uSubType)
|
||||
{
|
||||
subTypeOfControl = uSubType;
|
||||
}
|
||||
virtual ~CScrollButtonWindow()
|
||||
{
|
||||
}
|
||||
|
||||
LRESULT CALLBACK _WindowProcCallback(_In_ HWND wndHandle, UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam)
|
||||
{
|
||||
wndHandle;uMsg;wParam;lParam;
|
||||
return 0;
|
||||
}
|
||||
virtual void _OnPaint(_In_ HDC dcHandle, _In_ PAINTSTRUCT *pps);
|
||||
virtual void _OnLButtonDown(POINT pt);
|
||||
virtual void _OnLButtonUp(POINT pt);
|
||||
virtual void _OnTimer();
|
||||
|
||||
private:
|
||||
UINT subTypeOfControl; // DFCS_SCROLLxxx for DrawFrameControl
|
||||
};
|
||||
@@ -0,0 +1,210 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "private.h"
|
||||
#include "SearchCandidateProvider.h"
|
||||
#include <new>
|
||||
#include "SampleIME.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;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
|
||||
create instance of CSearchCandidateProvider
|
||||
|
||||
------------------------------------------------------------------------------*/
|
||||
HRESULT CSearchCandidateProvider::CreateInstance(REFIID riid, _Outptr_ void **ppvObj, _In_ ITfTextInputProcessorEx *ptip)
|
||||
{
|
||||
if (ppvObj == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*ppvObj = nullptr;
|
||||
|
||||
*ppvObj = new (std::nothrow) CSearchCandidateProvider(ptip);
|
||||
if (nullptr == *ppvObj)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
return ((CSearchCandidateProvider*)(*ppvObj))->QueryInterface(riid, ppvObj);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
|
||||
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 = ((CSampleIME*)_pTip)->GetCompositionProcessorEngine();
|
||||
if (nullptr == pCompositionProcessorEngine)
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
CSampleImeArray<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++)
|
||||
{
|
||||
ITfCandidateString* pCandStr = nullptr;
|
||||
CTipCandidateString::CreateInstance(IID_ITfCandidateString, (void**)&pCandStr);
|
||||
|
||||
((CTipCandidateString*)pCandStr)->SetIndex(iCand);
|
||||
((CTipCandidateString*)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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#pragma once
|
||||
|
||||
//
|
||||
// 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);
|
||||
static HRESULT CreateInstance(REFIID riid, _Outptr_ void **ppvObj, _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;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,285 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "SampleIME.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::SampleIMECLSID, CSampleIME::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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,370 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "BaseWindow.h"
|
||||
#include "ShadowWindow.h"
|
||||
|
||||
#define SHADOW_ALPHANUMBER (5)
|
||||
#define ALPHA(x) (255 - (x))
|
||||
|
||||
//// Gray scale values for the shadow grades
|
||||
#define GS01 255
|
||||
#define GS02 254
|
||||
#define GS03 253
|
||||
#define GS04 252
|
||||
#define GS05 250
|
||||
#define GS06 246
|
||||
#define GS07 245
|
||||
#define GS08 242
|
||||
#define GS09 241
|
||||
#define GS10 227
|
||||
#define GS11 217
|
||||
#define GS12 213
|
||||
#define GS13 212
|
||||
#define GS14 199
|
||||
#define GS15 180
|
||||
#define GS16 172
|
||||
#define GS17 171
|
||||
#define GS18 155
|
||||
#define GS19 144
|
||||
#define GS20 142
|
||||
|
||||
// pre-computed alpha values for the shadow
|
||||
const BYTE AlphaTable[SHADOW_ALPHANUMBER] = {
|
||||
ALPHA(GS04), ALPHA(GS09), ALPHA(GS13), ALPHA(GS17), ALPHA(GS20)
|
||||
};
|
||||
|
||||
const BYTE CornerShadowAlphaMetric[SHADOW_ALPHANUMBER][SHADOW_ALPHANUMBER] = {
|
||||
ALPHA(GS08), ALPHA(GS06), ALPHA(GS05), ALPHA(GS03), ALPHA(GS02),
|
||||
ALPHA(GS11), ALPHA(GS10), ALPHA(GS09), ALPHA(GS05), ALPHA(GS02),
|
||||
ALPHA(GS15), ALPHA(GS14), ALPHA(GS10), ALPHA(GS07), ALPHA(GS03),
|
||||
ALPHA(GS18), ALPHA(GS15), ALPHA(GS11), ALPHA(GS08), ALPHA(GS03),
|
||||
ALPHA(GS19), ALPHA(GS16), ALPHA(GS12), ALPHA(GS09), ALPHA(GS04),
|
||||
};
|
||||
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _Create
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CShadowWindow::_Create(ATOM atom, DWORD dwExStyle, DWORD dwStyle, _In_opt_ CBaseWindow *pParent, int wndWidth, int wndHeight)
|
||||
{
|
||||
if (!CBaseWindow::_Create(atom, dwExStyle, dwStyle, pParent, wndWidth, wndHeight))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return _Initialize();
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _WindowProcCallback
|
||||
//
|
||||
// Shadow window proc.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
LRESULT CALLBACK CShadowWindow::_WindowProcCallback(_In_ HWND wndHandle, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_PAINT:
|
||||
{
|
||||
HDC dcHandle;
|
||||
PAINTSTRUCT ps;
|
||||
|
||||
dcHandle = BeginPaint(wndHandle, &ps);
|
||||
|
||||
HBRUSH hBrush = CreateSolidBrush(_color);
|
||||
FillRect(dcHandle, &ps.rcPaint, hBrush);
|
||||
DeleteObject(hBrush);
|
||||
|
||||
EndPaint(wndHandle, &ps);
|
||||
}
|
||||
return 0;
|
||||
|
||||
case WM_SETTINGCHANGE:
|
||||
_OnSettingChange();
|
||||
break;
|
||||
}
|
||||
|
||||
return DefWindowProc(wndHandle, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _OnSettingChange
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CShadowWindow::_OnSettingChange()
|
||||
{
|
||||
_InitSettings();
|
||||
|
||||
DWORD dwWndStyleEx = GetWindowLong(_GetWnd(), GWL_EXSTYLE);
|
||||
|
||||
if (_isGradient)
|
||||
{
|
||||
SetWindowLong(_GetWnd(), GWL_EXSTYLE, (dwWndStyleEx | WS_EX_LAYERED));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowLong(_GetWnd(), GWL_EXSTYLE, (dwWndStyleEx & ~WS_EX_LAYERED));
|
||||
}
|
||||
|
||||
_AdjustWindowPos();
|
||||
_InitShadow();
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _OnOwnerWndMoved
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CShadowWindow::_OnOwnerWndMoved(BOOL isResized)
|
||||
{
|
||||
if (IsWindow(_GetWnd()) && _IsWindowVisible())
|
||||
{
|
||||
_AdjustWindowPos();
|
||||
if (isResized)
|
||||
{
|
||||
_InitShadow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _Show
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CShadowWindow::_Show(BOOL isShowWnd)
|
||||
{
|
||||
_OnOwnerWndMoved(TRUE);
|
||||
CBaseWindow::_Show(isShowWnd);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _Initialize
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CShadowWindow::_Initialize()
|
||||
{
|
||||
_InitSettings();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _InitSettings
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CShadowWindow::_InitSettings()
|
||||
{
|
||||
HDC dcHandle = GetDC(nullptr);
|
||||
|
||||
// device caps
|
||||
int cBitsPixelScreen = GetDeviceCaps(dcHandle, BITSPIXEL);
|
||||
|
||||
_isGradient = cBitsPixelScreen > 8;
|
||||
|
||||
ReleaseDC(nullptr, dcHandle);
|
||||
|
||||
if (_isGradient)
|
||||
{
|
||||
_color = RGB(0, 0, 0);
|
||||
_sizeShift.cx = SHADOW_ALPHANUMBER;
|
||||
_sizeShift.cy = SHADOW_ALPHANUMBER;
|
||||
}
|
||||
else
|
||||
{
|
||||
_color = RGB(128, 128, 128);
|
||||
_sizeShift.cx = 2;
|
||||
_sizeShift.cy = 2;
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _AdjustWindowPos
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CShadowWindow::_AdjustWindowPos()
|
||||
{
|
||||
if (!IsWindow(_GetWnd()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
HWND hWndOwner = _pWndOwner->_GetWnd();
|
||||
RECT rc = {0, 0, 0, 0};
|
||||
|
||||
GetWindowRect(hWndOwner, &rc);
|
||||
SetWindowPos(_GetWnd(), hWndOwner,
|
||||
rc.left + _sizeShift.cx,
|
||||
rc.top + _sizeShift.cy,
|
||||
rc.right - rc.left,
|
||||
rc.bottom - rc.top,
|
||||
SWP_NOOWNERZORDER | SWP_NOACTIVATE);
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _InitShadow
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#define GETRGBALPHA(_x_, _y_) ((RGBALPHA *)pDIBits + (_y_) * size.cx + (_x_))
|
||||
|
||||
void CShadowWindow::_InitShadow()
|
||||
{
|
||||
typedef struct _RGBAPLHA {
|
||||
BYTE rgbBlue;
|
||||
BYTE rgbGreen;
|
||||
BYTE rgbRed;
|
||||
BYTE rgbAlpha;
|
||||
} RGBALPHA;
|
||||
|
||||
HDC dcScreenHandle = nullptr;
|
||||
HDC dcLayeredHandle = nullptr;
|
||||
RECT rcWindow = {0, 0, 0, 0};
|
||||
SIZE size = {0, 0};
|
||||
BITMAPINFO bitmapInfo;
|
||||
HBITMAP bitmapMemHandle = nullptr;
|
||||
HBITMAP bitmapOldHandle = nullptr;
|
||||
void* pDIBits = nullptr;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
POINT ptSrc = {0, 0};
|
||||
POINT ptDst = {0, 0};
|
||||
BLENDFUNCTION Blend;
|
||||
|
||||
if (!_isGradient)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SetWindowLong(_GetWnd(), GWL_EXSTYLE, (GetWindowLong(_GetWnd(), GWL_EXSTYLE) | WS_EX_LAYERED));
|
||||
|
||||
_GetWindowRect(&rcWindow);
|
||||
size.cx = rcWindow.right - rcWindow.left;
|
||||
size.cy = rcWindow.bottom - rcWindow.top;
|
||||
|
||||
dcScreenHandle = GetDC(nullptr);
|
||||
if (dcScreenHandle == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
dcLayeredHandle = CreateCompatibleDC(dcScreenHandle);
|
||||
if (dcLayeredHandle == nullptr) {
|
||||
ReleaseDC(nullptr, dcScreenHandle);
|
||||
return;
|
||||
}
|
||||
|
||||
// create bitmap
|
||||
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bitmapInfo.bmiHeader.biWidth = size.cx;
|
||||
bitmapInfo.bmiHeader.biHeight = size.cy;
|
||||
bitmapInfo.bmiHeader.biPlanes = 1;
|
||||
bitmapInfo.bmiHeader.biBitCount = 32;
|
||||
bitmapInfo.bmiHeader.biCompression = BI_RGB;
|
||||
bitmapInfo.bmiHeader.biSizeImage = 0;
|
||||
bitmapInfo.bmiHeader.biXPelsPerMeter = 100;
|
||||
bitmapInfo.bmiHeader.biYPelsPerMeter = 100;
|
||||
bitmapInfo.bmiHeader.biClrUsed = 0;
|
||||
bitmapInfo.bmiHeader.biClrImportant = 0;
|
||||
|
||||
bitmapMemHandle = CreateDIBSection(dcScreenHandle, &bitmapInfo, DIB_RGB_COLORS, &pDIBits, nullptr, 0);
|
||||
if (pDIBits == nullptr || bitmapMemHandle == nullptr) {
|
||||
ReleaseDC(nullptr, dcScreenHandle);
|
||||
DeleteDC(dcLayeredHandle);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(pDIBits, 0, ((((32 * size.cx) + 31) & ~31) / 8) * size.cy);
|
||||
|
||||
// edges
|
||||
for (i = 0; i < SHADOW_ALPHANUMBER; i++) {
|
||||
RGBALPHA *ppxl;
|
||||
BYTE bAlpha = AlphaTable[i];
|
||||
|
||||
// bottom
|
||||
if (i <= (size.cy + 1)/2) {
|
||||
for (j = SHADOW_ALPHANUMBER; j < size.cx - SHADOW_ALPHANUMBER; j++) {
|
||||
ppxl = GETRGBALPHA(j, i);
|
||||
ppxl->rgbAlpha = bAlpha;
|
||||
}
|
||||
}
|
||||
|
||||
// right
|
||||
if (i <= (size.cx + 1)/2) {
|
||||
for (j = SHADOW_ALPHANUMBER; j < size.cy - SHADOW_ALPHANUMBER; j++) {
|
||||
ppxl = GETRGBALPHA(size.cx - 1 - i, j);
|
||||
ppxl->rgbAlpha = bAlpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// corners
|
||||
for (i = 0; i < SHADOW_ALPHANUMBER; i++) {
|
||||
for (j = 0; j < SHADOW_ALPHANUMBER; j++) {
|
||||
RGBALPHA *ppxl;
|
||||
BYTE bAlpha;
|
||||
bAlpha = CornerShadowAlphaMetric[i][SHADOW_ALPHANUMBER - j - 1];
|
||||
|
||||
// top-right
|
||||
if ((i <= (size.cy + 1)/2) && (j <= (size.cx + 1)/2)) {
|
||||
ppxl = GETRGBALPHA(size.cx - 1 - j, size.cy - 1 - i);
|
||||
ppxl->rgbAlpha = bAlpha;
|
||||
}
|
||||
|
||||
// bottom-left
|
||||
if ((i <= (size.cy + 1)/2) && (j <= (size.cx + 1)/2)) {
|
||||
ppxl = GETRGBALPHA(j, i + 1);
|
||||
ppxl->rgbAlpha = bAlpha;
|
||||
}
|
||||
|
||||
// bottom-right
|
||||
if ((i <= (size.cy + 1)/2) && (j <= (size.cx + 1)/2)) {
|
||||
ppxl = GETRGBALPHA(size.cx - 1 - j, i + 1);
|
||||
ppxl->rgbAlpha = bAlpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ptSrc.x = 0;
|
||||
ptSrc.y = 0;
|
||||
ptDst.x = rcWindow.left;
|
||||
ptDst.y = rcWindow.top;
|
||||
Blend.BlendOp = AC_SRC_OVER;
|
||||
Blend.BlendFlags = 0;
|
||||
Blend.SourceConstantAlpha = 255;
|
||||
Blend.AlphaFormat = AC_SRC_ALPHA;
|
||||
|
||||
bitmapOldHandle = (HBITMAP)SelectObject(dcLayeredHandle, bitmapMemHandle);
|
||||
|
||||
UpdateLayeredWindow(_GetWnd(), dcScreenHandle, nullptr, &size, dcLayeredHandle, &ptSrc, 0, &Blend, ULW_ALPHA);
|
||||
|
||||
SelectObject(dcLayeredHandle, bitmapOldHandle);
|
||||
|
||||
// done
|
||||
ReleaseDC(nullptr, dcScreenHandle);
|
||||
DeleteDC(dcLayeredHandle);
|
||||
DeleteObject(bitmapMemHandle);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BaseWindow.h"
|
||||
|
||||
class CShadowWindow : public CBaseWindow
|
||||
{
|
||||
public:
|
||||
CShadowWindow(_In_ CBaseWindow *pWndOwner)
|
||||
{
|
||||
_pWndOwner = pWndOwner;
|
||||
_color = RGB(0, 0, 0);
|
||||
_sizeShift.cx = 0;
|
||||
_sizeShift.cy = 0;
|
||||
_isGradient = FALSE;
|
||||
}
|
||||
virtual ~CShadowWindow()
|
||||
{
|
||||
}
|
||||
|
||||
BOOL _Create(ATOM atom, DWORD dwExStyle, DWORD dwStyle, _In_opt_ CBaseWindow *pParent = nullptr, int wndWidth = 0, int wndHeight = 0);
|
||||
|
||||
void _Show(BOOL isShowWnd);
|
||||
|
||||
LRESULT CALLBACK _WindowProcCallback(_In_ HWND wndHandle, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
void _OnSettingChange();
|
||||
void _OnOwnerWndMoved(BOOL isResized);
|
||||
|
||||
private:
|
||||
BOOL _Initialize();
|
||||
void _InitSettings();
|
||||
void _AdjustWindowPos();
|
||||
void _InitShadow();
|
||||
|
||||
private:
|
||||
CBaseWindow* _pWndOwner;
|
||||
COLORREF _color;
|
||||
SIZE _sizeShift;
|
||||
BOOL _isGradient;
|
||||
};
|
||||
@@ -0,0 +1,133 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "EditSession.h"
|
||||
#include "SampleIME.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CStartCompositinoEditSession
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class CStartCompositionEditSession : public CEditSessionBase
|
||||
{
|
||||
public:
|
||||
CStartCompositionEditSession(_In_ CSampleIME *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;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CSampleIME class
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _StartComposition
|
||||
//
|
||||
// this starts the new (std::nothrow) composition at the selection of the current
|
||||
// focus context.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CSampleIME::_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 CSampleIME::_SaveCompositionContext(_In_ ITfContext *pContext)
|
||||
{
|
||||
assert(_pContext == nullptr);
|
||||
|
||||
pContext->AddRef();
|
||||
_pContext = pContext;
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "TableDictionaryEngine.h"
|
||||
#include "DictionarySearch.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CollectWord
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
VOID CTableDictionaryEngine::CollectWord(_In_ CStringRange *pKeyCode, _Inout_ CSampleImeArray<CStringRange> *pWordStrings)
|
||||
{
|
||||
CDictionaryResult* pdret = nullptr;
|
||||
CDictionarySearch dshSearch(_locale, _pDictionaryFile, pKeyCode);
|
||||
|
||||
while (dshSearch.FindPhrase(&pdret))
|
||||
{
|
||||
for (UINT index = 0; index < pdret->_FindPhraseList.Count(); index++)
|
||||
{
|
||||
CStringRange* pPhrase = nullptr;
|
||||
pPhrase = pWordStrings->Append();
|
||||
if (pPhrase)
|
||||
{
|
||||
*pPhrase = *pdret->_FindPhraseList.GetAt(index);
|
||||
}
|
||||
}
|
||||
|
||||
delete pdret;
|
||||
pdret = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
VOID CTableDictionaryEngine::CollectWord(_In_ CStringRange *pKeyCode, _Inout_ CSampleImeArray<CCandidateListItem> *pItemList)
|
||||
{
|
||||
CDictionaryResult* pdret = nullptr;
|
||||
CDictionarySearch dshSearch(_locale, _pDictionaryFile, pKeyCode);
|
||||
|
||||
while (dshSearch.FindPhrase(&pdret))
|
||||
{
|
||||
for (UINT iIndex = 0; iIndex < pdret->_FindPhraseList.Count(); iIndex++)
|
||||
{
|
||||
CCandidateListItem* pLI = nullptr;
|
||||
pLI = pItemList->Append();
|
||||
if (pLI)
|
||||
{
|
||||
pLI->_ItemString.Set(*pdret->_FindPhraseList.GetAt(iIndex));
|
||||
pLI->_FindKeyCode.Set(pdret->_FindKeyCode.Get(), pdret->_FindKeyCode.GetLength());
|
||||
}
|
||||
}
|
||||
|
||||
delete pdret;
|
||||
pdret = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CollectWordForWildcard
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
VOID CTableDictionaryEngine::CollectWordForWildcard(_In_ CStringRange *pKeyCode, _Inout_ CSampleImeArray<CCandidateListItem> *pItemList)
|
||||
{
|
||||
CDictionaryResult* pdret = nullptr;
|
||||
CDictionarySearch dshSearch(_locale, _pDictionaryFile, pKeyCode);
|
||||
|
||||
while (dshSearch.FindPhraseForWildcard(&pdret))
|
||||
{
|
||||
for (UINT iIndex = 0; iIndex < pdret->_FindPhraseList.Count(); iIndex++)
|
||||
{
|
||||
CCandidateListItem* pLI = nullptr;
|
||||
pLI = pItemList->Append();
|
||||
if (pLI)
|
||||
{
|
||||
pLI->_ItemString.Set(*pdret->_FindPhraseList.GetAt(iIndex));
|
||||
pLI->_FindKeyCode.Set(pdret->_FindKeyCode.Get(), pdret->_FindKeyCode.GetLength());
|
||||
}
|
||||
}
|
||||
|
||||
delete pdret;
|
||||
pdret = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// CollectWordFromConvertedStringForWildcard
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
VOID CTableDictionaryEngine::CollectWordFromConvertedStringForWildcard(_In_ CStringRange *pString, _Inout_ CSampleImeArray<CCandidateListItem> *pItemList)
|
||||
{
|
||||
CDictionaryResult* pdret = nullptr;
|
||||
CDictionarySearch dshSearch(_locale, _pDictionaryFile, pString);
|
||||
|
||||
while (dshSearch.FindConvertedStringForWildcard(&pdret)) // TAIL ALL CHAR MATCH
|
||||
{
|
||||
for (UINT index = 0; index < pdret->_FindPhraseList.Count(); index++)
|
||||
{
|
||||
CCandidateListItem* pLI = nullptr;
|
||||
pLI = pItemList->Append();
|
||||
if (pLI)
|
||||
{
|
||||
pLI->_ItemString.Set(*pdret->_FindPhraseList.GetAt(index));
|
||||
pLI->_FindKeyCode.Set(pdret->_FindKeyCode.Get(), pdret->_FindKeyCode.GetLength());
|
||||
}
|
||||
}
|
||||
|
||||
delete pdret;
|
||||
pdret = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BaseDictionaryEngine.h"
|
||||
|
||||
class CTableDictionaryEngine : public CBaseDictionaryEngine
|
||||
{
|
||||
public:
|
||||
CTableDictionaryEngine(LCID locale, _In_ CFile *pDictionaryFile) : CBaseDictionaryEngine(locale, pDictionaryFile) { }
|
||||
virtual ~CTableDictionaryEngine() { }
|
||||
|
||||
// Collect word from phrase string.
|
||||
// param
|
||||
// [in] psrgKeyCode - Specified key code pointer
|
||||
// [out] pasrgWordString - Specified returns pointer of word as CStringRange.
|
||||
// returns
|
||||
// none.
|
||||
VOID CollectWord(_In_ CStringRange *pKeyCode, _Inout_ CSampleImeArray<CStringRange> *pWordStrings);
|
||||
VOID CollectWord(_In_ CStringRange *pKeyCode, _Inout_ CSampleImeArray<CCandidateListItem> *pItemList);
|
||||
|
||||
VOID CollectWordForWildcard(_In_ CStringRange *psrgKeyCode, _Inout_ CSampleImeArray<CCandidateListItem> *pItemList);
|
||||
|
||||
VOID CollectWordFromConvertedStringForWildcard(_In_ CStringRange *pString, _Inout_ CSampleImeArray<CCandidateListItem> *pItemList);
|
||||
};
|
||||
@@ -0,0 +1,134 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "globals.h"
|
||||
#include "SampleIME.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfTextEditSink::OnEndEdit
|
||||
//
|
||||
// Called by the system whenever anyone releases a write-access document lock.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CSampleIME::OnEndEdit(__RPC__in_opt ITfContext *pContext, TfEditCookie ecReadOnly, __RPC__in_opt ITfEditRecord *pEditRecord)
|
||||
{
|
||||
BOOL isSelectionChanged;
|
||||
|
||||
//
|
||||
// did the selection change?
|
||||
// The selection change includes the movement of caret as well.
|
||||
// The caret position is represent as the empty selection range when
|
||||
// there is no selection.
|
||||
//
|
||||
if (pEditRecord == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
if (SUCCEEDED(pEditRecord->GetSelectionStatus(&isSelectionChanged)) &&
|
||||
isSelectionChanged)
|
||||
{
|
||||
// If the selection is moved to out side of the current composition,
|
||||
// we terminate the composition. This TextService supports only one
|
||||
// composition in one context object.
|
||||
if (_IsComposing())
|
||||
{
|
||||
TF_SELECTION tfSelection;
|
||||
ULONG fetched = 0;
|
||||
|
||||
if (pContext == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
if (FAILED(pContext->GetSelection(ecReadOnly, TF_DEFAULT_SELECTION, 1, &tfSelection, &fetched)) || fetched != 1)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
ITfRange* pRangeComposition = nullptr;
|
||||
if (SUCCEEDED(_pComposition->GetRange(&pRangeComposition)))
|
||||
{
|
||||
if (!_IsRangeCovered(ecReadOnly, tfSelection.range, pRangeComposition))
|
||||
{
|
||||
_EndComposition(pContext);
|
||||
}
|
||||
|
||||
pRangeComposition->Release();
|
||||
}
|
||||
|
||||
tfSelection.range->Release();
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _InitTextEditSink
|
||||
//
|
||||
// Init a text edit sink on the topmost context of the document.
|
||||
// Always release any previous sink.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CSampleIME::_InitTextEditSink(_In_ ITfDocumentMgr *pDocMgr)
|
||||
{
|
||||
ITfSource* pSource = nullptr;
|
||||
BOOL ret = TRUE;
|
||||
|
||||
// clear out any previous sink first
|
||||
if (_textEditSinkCookie != TF_INVALID_COOKIE)
|
||||
{
|
||||
if (SUCCEEDED(_pTextEditSinkContext->QueryInterface(IID_ITfSource, (void **)&pSource)))
|
||||
{
|
||||
pSource->UnadviseSink(_textEditSinkCookie);
|
||||
pSource->Release();
|
||||
}
|
||||
|
||||
_pTextEditSinkContext->Release();
|
||||
_pTextEditSinkContext = nullptr;
|
||||
_textEditSinkCookie = TF_INVALID_COOKIE;
|
||||
}
|
||||
|
||||
if (pDocMgr == nullptr)
|
||||
{
|
||||
return TRUE; // caller just wanted to clear the previous sink
|
||||
}
|
||||
|
||||
if (FAILED(pDocMgr->GetTop(&_pTextEditSinkContext)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (_pTextEditSinkContext == nullptr)
|
||||
{
|
||||
return TRUE; // empty document, no sink possible
|
||||
}
|
||||
|
||||
ret = FALSE;
|
||||
if (SUCCEEDED(_pTextEditSinkContext->QueryInterface(IID_ITfSource, (void **)&pSource)))
|
||||
{
|
||||
if (SUCCEEDED(pSource->AdviseSink(IID_ITfTextEditSink, (ITfTextEditSink *)this, &_textEditSinkCookie)))
|
||||
{
|
||||
ret = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
_textEditSinkCookie = TF_INVALID_COOKIE;
|
||||
}
|
||||
pSource->Release();
|
||||
}
|
||||
|
||||
if (ret == FALSE)
|
||||
{
|
||||
_pTextEditSinkContext->Release();
|
||||
_pTextEditSinkContext = nullptr;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#pragma once
|
||||
|
||||
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;
|
||||
};
|
||||
@@ -0,0 +1,220 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "TfTextLayoutSink.h"
|
||||
#include "SampleIME.h"
|
||||
#include "GetTextExtentEditSession.h"
|
||||
|
||||
CTfTextLayoutSink::CTfTextLayoutSink(_In_ CSampleIME *pTextService)
|
||||
{
|
||||
_pTextService = pTextService;
|
||||
_pTextService->AddRef();
|
||||
|
||||
_pRangeComposition = nullptr;
|
||||
_pContextDocument = nullptr;
|
||||
_tfEditCookie = TF_INVALID_EDIT_COOKIE;
|
||||
|
||||
_dwCookieTextLayoutSink = TF_INVALID_COOKIE;
|
||||
|
||||
_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)
|
||||
{
|
||||
// we're interested in only document context.
|
||||
if (pContext != _pContextDocument)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
switch (lcode)
|
||||
{
|
||||
case TF_LC_CHANGE:
|
||||
{
|
||||
CGetTextExtentEditSession* pEditSession = nullptr;
|
||||
pEditSession = new (std::nothrow) CGetTextExtentEditSession(_pTextService, pContext, pContextView, _pRangeComposition, this);
|
||||
if (nullptr != (pEditSession))
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
pContext->RequestEditSession(_pTextService->_GetClientId(), pEditSession, TF_ES_SYNC | TF_ES_READ, &hr);
|
||||
|
||||
pEditSession->Release();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TF_LC_DESTROY:
|
||||
_LayoutDestroyNotification();
|
||||
break;
|
||||
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CTfTextLayoutSink::_StartLayout(_In_ ITfContext *pContextDocument, TfEditCookie ec, _In_ ITfRange *pRangeComposition)
|
||||
{
|
||||
_pContextDocument = pContextDocument;
|
||||
_pContextDocument->AddRef();
|
||||
|
||||
_pRangeComposition = pRangeComposition;
|
||||
_pRangeComposition->AddRef();
|
||||
|
||||
_tfEditCookie = ec;
|
||||
|
||||
return _AdviseTextLayoutSink();
|
||||
}
|
||||
|
||||
VOID CTfTextLayoutSink::_EndLayout()
|
||||
{
|
||||
if (_pRangeComposition)
|
||||
{
|
||||
_pRangeComposition->Release();
|
||||
_pRangeComposition = nullptr;
|
||||
}
|
||||
|
||||
if (_pContextDocument)
|
||||
{
|
||||
_UnadviseTextLayoutSink();
|
||||
_pContextDocument->Release();
|
||||
_pContextDocument = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CTfTextLayoutSink::_AdviseTextLayoutSink()
|
||||
{
|
||||
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()
|
||||
{
|
||||
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();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT CTfTextLayoutSink::_GetTextExt(_Out_ RECT *lpRect)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
BOOL isClipped = TRUE;
|
||||
ITfContextView* pContextView = nullptr;
|
||||
|
||||
hr = _pContextDocument->GetActiveView(&pContextView);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (FAILED(hr = pContextView->GetTextExt(_tfEditCookie, _pRangeComposition, lpRect, &isClipped)))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
pContextView->Release();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#pragma once
|
||||
|
||||
class CSampleIME;
|
||||
|
||||
class CTfTextLayoutSink : public ITfTextLayoutSink
|
||||
{
|
||||
public:
|
||||
CTfTextLayoutSink(_In_ CSampleIME *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);
|
||||
ITfContext* _GetContextDocument() { return _pContextDocument; };
|
||||
|
||||
virtual VOID _LayoutChangeNotification(_In_ RECT *lpRect) = 0;
|
||||
virtual VOID _LayoutDestroyNotification() = 0;
|
||||
|
||||
private:
|
||||
HRESULT _AdviseTextLayoutSink();
|
||||
HRESULT _UnadviseTextLayoutSink();
|
||||
|
||||
private:
|
||||
ITfRange* _pRangeComposition;
|
||||
ITfContext* _pContextDocument;
|
||||
TfEditCookie _tfEditCookie;
|
||||
CSampleIME* _pTextService;
|
||||
DWORD _dwCookieTextLayoutSink;
|
||||
LONG _refCount;
|
||||
};
|
||||
@@ -0,0 +1,106 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "SampleIME.h"
|
||||
#include "CandidateListUIPresenter.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfTextLayoutSink::OnSetThreadFocus
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CSampleIME::OnSetThreadFocus()
|
||||
{
|
||||
if (_pCandidateListUIPresenter)
|
||||
{
|
||||
ITfDocumentMgr* pCandidateListDocumentMgr = nullptr;
|
||||
ITfContext* pTfContext = _pCandidateListUIPresenter->_GetContextDocument();
|
||||
|
||||
if ((nullptr != pTfContext) && SUCCEEDED(pTfContext->GetDocumentMgr(&pCandidateListDocumentMgr)))
|
||||
{
|
||||
if (pCandidateListDocumentMgr == _pDocMgrLastFocused)
|
||||
{
|
||||
_pCandidateListUIPresenter->OnSetThreadFocus();
|
||||
}
|
||||
|
||||
pCandidateListDocumentMgr->Release();
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfTextLayoutSink::OnKillThreadFocus
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CSampleIME::OnKillThreadFocus()
|
||||
{
|
||||
if (_pCandidateListUIPresenter)
|
||||
{
|
||||
ITfDocumentMgr* pCandidateListDocumentMgr = nullptr;
|
||||
ITfContext* pTfContext = _pCandidateListUIPresenter->_GetContextDocument();
|
||||
|
||||
if ((nullptr != pTfContext) && SUCCEEDED(pTfContext->GetDocumentMgr(&pCandidateListDocumentMgr)))
|
||||
{
|
||||
if (_pDocMgrLastFocused)
|
||||
{
|
||||
_pDocMgrLastFocused->Release();
|
||||
_pDocMgrLastFocused = nullptr;
|
||||
}
|
||||
_pDocMgrLastFocused = pCandidateListDocumentMgr;
|
||||
if (_pDocMgrLastFocused)
|
||||
{
|
||||
_pDocMgrLastFocused->AddRef();
|
||||
}
|
||||
}
|
||||
_pCandidateListUIPresenter->OnKillThreadFocus();
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
BOOL CSampleIME::_InitThreadFocusSink()
|
||||
{
|
||||
ITfSource* pSource = nullptr;
|
||||
|
||||
if (FAILED(_pThreadMgr->QueryInterface(IID_ITfSource, (void **)&pSource)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (FAILED(pSource->AdviseSink(IID_ITfThreadFocusSink, (ITfThreadFocusSink *)this, &_dwThreadFocusSinkCookie)))
|
||||
{
|
||||
pSource->Release();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pSource->Release();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void CSampleIME::_UninitThreadFocusSink()
|
||||
{
|
||||
ITfSource* pSource = nullptr;
|
||||
|
||||
if (FAILED(_pThreadMgr->QueryInterface(IID_ITfSource, (void **)&pSource)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (FAILED(pSource->UnadviseSink(_dwThreadFocusSinkCookie)))
|
||||
{
|
||||
pSource->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
pSource->Release();
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "SampleIME.h"
|
||||
#include "CandidateListUIPresenter.h"
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfThreadMgrEventSink::OnInitDocumentMgr
|
||||
//
|
||||
// Sink called by the framework just before the first context is pushed onto
|
||||
// a document.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CSampleIME::OnInitDocumentMgr(_In_ ITfDocumentMgr *pDocMgr)
|
||||
{
|
||||
pDocMgr;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfThreadMgrEventSink::OnUninitDocumentMgr
|
||||
//
|
||||
// Sink called by the framework just after the last context is popped off a
|
||||
// document.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CSampleIME::OnUninitDocumentMgr(_In_ ITfDocumentMgr *pDocMgr)
|
||||
{
|
||||
pDocMgr;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfThreadMgrEventSink::OnSetFocus
|
||||
//
|
||||
// Sink called by the framework when focus changes from one document to
|
||||
// another. Either document may be NULL, meaning previously there was no
|
||||
// focus document, or now no document holds the input focus.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CSampleIME::OnSetFocus(_In_ ITfDocumentMgr *pDocMgrFocus, _In_ ITfDocumentMgr *pDocMgrPrevFocus)
|
||||
{
|
||||
pDocMgrPrevFocus;
|
||||
|
||||
_InitTextEditSink(pDocMgrFocus);
|
||||
|
||||
_UpdateLanguageBarOnSetFocus(pDocMgrFocus);
|
||||
|
||||
//
|
||||
// We have to hide/unhide candidate list depending on whether they are
|
||||
// associated with pDocMgrFocus.
|
||||
//
|
||||
if (_pCandidateListUIPresenter)
|
||||
{
|
||||
ITfDocumentMgr* pCandidateListDocumentMgr = nullptr;
|
||||
ITfContext* pTfContext = _pCandidateListUIPresenter->_GetContextDocument();
|
||||
if ((nullptr != pTfContext) && SUCCEEDED(pTfContext->GetDocumentMgr(&pCandidateListDocumentMgr)))
|
||||
{
|
||||
if (pCandidateListDocumentMgr != pDocMgrFocus)
|
||||
{
|
||||
_pCandidateListUIPresenter->OnKillThreadFocus();
|
||||
}
|
||||
else
|
||||
{
|
||||
_pCandidateListUIPresenter->OnSetThreadFocus();
|
||||
}
|
||||
|
||||
pCandidateListDocumentMgr->Release();
|
||||
}
|
||||
}
|
||||
|
||||
if (_pDocMgrLastFocused)
|
||||
{
|
||||
_pDocMgrLastFocused->Release();
|
||||
_pDocMgrLastFocused = nullptr;
|
||||
}
|
||||
|
||||
_pDocMgrLastFocused = pDocMgrFocus;
|
||||
|
||||
if (_pDocMgrLastFocused)
|
||||
{
|
||||
_pDocMgrLastFocused->AddRef();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfThreadMgrEventSink::OnPushContext
|
||||
//
|
||||
// Sink called by the framework when a context is pushed.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CSampleIME::OnPushContext(_In_ ITfContext *pContext)
|
||||
{
|
||||
pContext;
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// ITfThreadMgrEventSink::OnPopContext
|
||||
//
|
||||
// Sink called by the framework when a context is popped.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
STDAPI CSampleIME::OnPopContext(_In_ ITfContext *pContext)
|
||||
{
|
||||
pContext;
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _InitThreadMgrEventSink
|
||||
//
|
||||
// Advise our sink.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CSampleIME::_InitThreadMgrEventSink()
|
||||
{
|
||||
ITfSource* pSource = nullptr;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
if (FAILED(_pThreadMgr->QueryInterface(IID_ITfSource, (void **)&pSource)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (FAILED(pSource->AdviseSink(IID_ITfThreadMgrEventSink, (ITfThreadMgrEventSink *)this, &_threadMgrEventSinkCookie)))
|
||||
{
|
||||
_threadMgrEventSinkCookie = TF_INVALID_COOKIE;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
Exit:
|
||||
pSource->Release();
|
||||
return ret;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _UninitThreadMgrEventSink
|
||||
//
|
||||
// Unadvise our sink.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void CSampleIME::_UninitThreadMgrEventSink()
|
||||
{
|
||||
ITfSource* pSource = nullptr;
|
||||
|
||||
if (_threadMgrEventSinkCookie == TF_INVALID_COOKIE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(_pThreadMgr->QueryInterface(IID_ITfSource, (void **)&pSource)))
|
||||
{
|
||||
pSource->UnadviseSink(_threadMgrEventSinkCookie);
|
||||
pSource->Release();
|
||||
}
|
||||
|
||||
_threadMgrEventSinkCookie = TF_INVALID_COOKIE;
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CTipCandidateList::CreateInstance(REFIID riid, _Outptr_ void **ppvObj, size_t candStrReserveSize)
|
||||
{
|
||||
if (ppvObj == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*ppvObj = nullptr;
|
||||
|
||||
*ppvObj = new (std::nothrow) CTipCandidateList(candStrReserveSize);
|
||||
if (*ppvObj == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
return ((CTipCandidateList*)(*ppvObj))->QueryInterface(riid, ppvObj);
|
||||
}
|
||||
|
||||
CTipCandidateList::CTipCandidateList(size_t candStrReserveSize)
|
||||
{
|
||||
_refCount = 0;
|
||||
|
||||
if (0 < candStrReserveSize)
|
||||
{
|
||||
_tfCandStrList.reserve(candStrReserveSize);
|
||||
}
|
||||
}
|
||||
|
||||
CTipCandidateList::~CTipCandidateList()
|
||||
{
|
||||
}
|
||||
|
||||
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(IID_IEnumTfCandidates, (void**)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;
|
||||
}
|
||||
|
||||
for (UINT i = 0; i < _tfCandStrList.Count(); i++)
|
||||
{
|
||||
ITfCandidateString** ppCandStrCur = _tfCandStrList.GetAt(i);
|
||||
ULONG indexCur = 0;
|
||||
if ((nullptr != ppCandStrCur) && (SUCCEEDED((*ppCandStrCur)->GetIndex(&indexCur))))
|
||||
{
|
||||
if (nIndex == indexCur)
|
||||
{
|
||||
BSTR bstr;
|
||||
CTipCandidateString* pTipCandidateStrCur = (CTipCandidateString*)(*ppCandStrCur);
|
||||
pTipCandidateStrCur->GetString(&bstr);
|
||||
|
||||
CTipCandidateString::CreateInstance(IID_ITfCandidateString, (void**)ppCandStr);
|
||||
|
||||
if (nullptr != (*ppCandStr))
|
||||
{
|
||||
CTipCandidateString* pTipCandidateStr = (CTipCandidateString*)(*ppCandStr);
|
||||
pTipCandidateStr->SetString((LPCWSTR)bstr, SysStringLen(bstr));
|
||||
}
|
||||
|
||||
SysFreeString(bstr);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
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 **ppCandStr)
|
||||
{
|
||||
if (ppCandStr == nullptr)
|
||||
{
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
ITfCandidateString** ppCandLast = _tfCandStrList.Append();
|
||||
if (ppCandLast)
|
||||
{
|
||||
*ppCandLast = *ppCandStr;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "SampleIMEBaseStructure.h"
|
||||
|
||||
//
|
||||
// CTipCandidateList
|
||||
//
|
||||
|
||||
class CTipCandidateList : public ITfCandidateList
|
||||
{
|
||||
protected:
|
||||
CTipCandidateList(size_t candStrReserveSize);
|
||||
virtual ~CTipCandidateList();
|
||||
|
||||
public:
|
||||
static HRESULT CreateInstance(_Outptr_ ITfCandidateList **ppobj, size_t candStrReserveSize = 0);
|
||||
static HRESULT CreateInstance(REFIID riid, _Outptr_ void **ppvObj, 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 **ppCandStr);
|
||||
|
||||
protected:
|
||||
long _refCount;
|
||||
CSampleImeArray<ITfCandidateString*> _tfCandStrList;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CTipCandidateString::CreateInstance(REFIID riid, _Outptr_ void **ppvObj)
|
||||
{
|
||||
if (ppvObj == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*ppvObj = nullptr;
|
||||
|
||||
*ppvObj = new (std::nothrow) CTipCandidateString();
|
||||
if (*ppvObj == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
return ((CTipCandidateString*)(*ppvObj))->QueryInterface(riid, ppvObj);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "private.h"
|
||||
#include <string>
|
||||
|
||||
class CTipCandidateString : public ITfCandidateString
|
||||
{
|
||||
protected:
|
||||
CTipCandidateString();
|
||||
virtual ~CTipCandidateString();
|
||||
|
||||
public:
|
||||
static HRESULT CreateInstance(_Outptr_ CTipCandidateString **ppobj);
|
||||
static HRESULT CreateInstance(REFIID riid, _Outptr_ void **ppvObj);
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 39 KiB |