[regression]: Fix the issue where using -/= to turn pages causes the program to crash and prevents page turning.

This commit is contained in:
fanlusky committed 2026-06-26 10:55:43 +08:00
1 parent 476a5c7181
commit bcaf34e1fb
6 files changed
+182 -89

No files matched your search

+65 -46
View File
@@ -452,12 +452,31 @@ BOOL CCompositionProcessorEngine::IsPunctuation(WCHAR wch)
namespace
{
bool IsCommitWithFirstCandidatePunctuationInCandidateMode(WCHAR wch, CANDIDATE_MODE candidateMode)
bool IsCommitWithFirstCandidatePunctuationInCandidateMode(UINT uCode, WCHAR wch, CANDIDATE_MODE candidateMode)
{
if (candidateMode == CANDIDATE_NONE)
{
return false;
}
// Candidate paging keys must keep their navigation semantics even if the
// corresponding character is also listed in CommitWithFirstCandPunc.
switch (uCode)
{
case VK_PRIOR:
case VK_NEXT:
case VK_OEM_MINUS:
case VK_OEM_PLUS:
case VK_SUBTRACT:
case VK_ADD:
case VK_HOME:
case VK_END:
case VK_TAB:
return false;
default:
break;
}
return wch != 0 && Global::CommitWithFirstCandPunc.count(wch) > 0;
}
@@ -1671,18 +1690,18 @@ void CCompositionProcessorEngine::SetDefaultCandidateTextFont()
// If engine need this virtual key code, returns true. Otherwise returns false.
//----------------------------------------------------------------------------
BOOL CCompositionProcessorEngine::IsVirtualKeyNeed( //
UINT uCode, //
BOOL CCompositionProcessorEngine::IsVirtualKeyNeed( //
UINT uCode, //
_In_reads_(1) WCHAR *pwch, //
BOOL fComposing, //
CANDIDATE_MODE candidateMode, //
BOOL hasCandidateWithWildcard, //
_Out_opt_ _KEYSTROKE_STATE *pKeyState //
)
{
if (pKeyState)
{
pKeyState->Category = CATEGORY_NONE;
)
{
if (pKeyState)
{
pKeyState->Category = CATEGORY_NONE;
pKeyState->Function = FUNCTION_NONE;
}
@@ -1701,7 +1720,7 @@ BOOL CCompositionProcessorEngine::IsVirtualKeyNeed( //
return TRUE;
}
if (IsCommitWithFirstCandidatePunctuationInCandidateMode(pwch ? *pwch : 0, candidateMode))
if (IsCommitWithFirstCandidatePunctuationInCandidateMode(uCode, pwch ? *pwch : 0, candidateMode))
{
if (pKeyState)
{
@@ -1986,13 +2005,13 @@ BOOL CCompositionProcessorEngine::IsVirtualKeyNeed( //
pKeyState->Function = FUNCTION_MOVE_PAGE_UP;
}
return TRUE;
case VK_OEM_MINUS:
if (pKeyState)
{
pKeyState->Category = CATEGORY_CANDIDATE;
pKeyState->Function = FUNCTION_MOVE_PAGE_UP;
}
return TRUE;
case VK_OEM_MINUS:
if (pKeyState)
{
pKeyState->Category = CATEGORY_CANDIDATE;
pKeyState->Function = FUNCTION_MOVE_PAGE_UP;
}
return TRUE;
case VK_NEXT:
if (pKeyState)
{
@@ -2000,13 +2019,13 @@ BOOL CCompositionProcessorEngine::IsVirtualKeyNeed( //
pKeyState->Function = FUNCTION_MOVE_PAGE_DOWN;
}
return TRUE;
case VK_OEM_PLUS:
if (pKeyState)
{
pKeyState->Category = CATEGORY_CANDIDATE;
pKeyState->Function = FUNCTION_MOVE_PAGE_DOWN;
}
return TRUE;
case VK_OEM_PLUS:
if (pKeyState)
{
pKeyState->Category = CATEGORY_CANDIDATE;
pKeyState->Function = FUNCTION_MOVE_PAGE_DOWN;
}
return TRUE;
case VK_TAB:
if (pKeyState)
{
@@ -2086,13 +2105,13 @@ BOOL CCompositionProcessorEngine::IsVirtualKeyNeed( //
pKeyState->Function = FUNCTION_MOVE_PAGE_UP;
}
return TRUE;
case VK_OEM_MINUS:
if (pKeyState)
{
pKeyState->Category = CATEGORY_CANDIDATE;
pKeyState->Function = FUNCTION_MOVE_PAGE_UP;
}
return TRUE;
case VK_OEM_MINUS:
if (pKeyState)
{
pKeyState->Category = CATEGORY_CANDIDATE;
pKeyState->Function = FUNCTION_MOVE_PAGE_UP;
}
return TRUE;
case VK_NEXT:
if (pKeyState)
{
@@ -2100,13 +2119,13 @@ BOOL CCompositionProcessorEngine::IsVirtualKeyNeed( //
pKeyState->Function = FUNCTION_MOVE_PAGE_DOWN;
}
return TRUE;
case VK_OEM_PLUS:
if (pKeyState)
{
pKeyState->Category = CATEGORY_CANDIDATE;
pKeyState->Function = FUNCTION_MOVE_PAGE_DOWN;
}
return TRUE;
case VK_OEM_PLUS:
if (pKeyState)
{
pKeyState->Category = CATEGORY_CANDIDATE;
pKeyState->Function = FUNCTION_MOVE_PAGE_DOWN;
}
return TRUE;
case VK_TAB:
if (pKeyState)
{
@@ -2180,15 +2199,15 @@ BOOL CCompositionProcessorEngine::IsVirtualKeyNeed( //
return FALSE;
}
if (*pwch && !IsVirtualKeyKeystrokeComposition(uCode, pKeyState, FUNCTION_NONE))
{
if (pKeyState)
{
pKeyState->Category = CATEGORY_INVOKE_COMPOSITION_EDIT_SESSION;
pKeyState->Function = FUNCTION_FINALIZE_TEXTSTORE;
}
return FALSE;
}
if (*pwch && !IsVirtualKeyKeystrokeComposition(uCode, pKeyState, FUNCTION_NONE))
{
if (pKeyState)
{
pKeyState->Category = CATEGORY_INVOKE_COMPOSITION_EDIT_SESSION;
pKeyState->Function = FUNCTION_FINALIZE_TEXTSTORE;
}
return FALSE;
}
#ifdef FANY_DEBUG
OutputDebugString(L"[msime]: Unknown keystroke.");
+24 -15
View File
@@ -13,10 +13,10 @@
#include "Ipc.h"
#include "FanyDefines.h"
namespace
{
std::wstring g_toggleImeFallbackBuffer;
}
namespace
{
std::wstring g_toggleImeFallbackBuffer;
}
//////////////////////////////////////////////////////////////////////
//
@@ -592,12 +592,21 @@ Exit:
//
//----------------------------------------------------------------------------
HRESULT CMetasequoiaIME::_HandleCompositionArrowKey(TfEditCookie ec, _In_ ITfContext *pContext,
KEYSTROKE_FUNCTION keyFunction)
{
ITfRange *pRangeComposition = nullptr;
TF_SELECTION tfSelection;
ULONG fetched = 0;
HRESULT CMetasequoiaIME::_HandleCompositionArrowKey(TfEditCookie ec, _In_ ITfContext *pContext,
KEYSTROKE_FUNCTION keyFunction)
{
if ((keyFunction == FUNCTION_MOVE_PAGE_UP) || (keyFunction == FUNCTION_MOVE_PAGE_DOWN) ||
(keyFunction == FUNCTION_MOVE_PAGE_TOP) || (keyFunction == FUNCTION_MOVE_PAGE_BOTTOM))
{
if ((_pCandidateListUIPresenter == nullptr) || (_pCandidateListUIPresenter->_GetCount() <= 1))
{
return S_OK;
}
}
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)
@@ -606,11 +615,11 @@ HRESULT CMetasequoiaIME::_HandleCompositionArrowKey(TfEditCookie ec, _In_ ITfCon
return S_OK;
}
// get the composition range
if (FAILED(_pComposition->GetRange(&pRangeComposition)))
{
goto Exit;
}
// get the composition range
if ((_pComposition == nullptr) || FAILED(_pComposition->GetRange(&pRangeComposition)))
{
goto Exit;
}
// For incremental candidate list
if (_pCandidateListUIPresenter)
+16 -17
View File
@@ -1,11 +1,10 @@
#include "Private.h"
#include "KeyHandlerEditSession.h"
#include "EditSession.h"
#include "MetasequoiaIME.h"
#include "CompositionProcessorEngine.h"
#include "KeyStateCategory.h"
//////////////////////////////////////////////////////////////////////
#include "MetasequoiaIME.h"
#include "CompositionProcessorEngine.h"
#include "KeyStateCategory.h"
//////////////////////////////////////////////////////////////////////
//
// ITfEditSession
// CEditSessionBase
@@ -19,21 +18,21 @@
//
//----------------------------------------------------------------------------
STDAPI CKeyHandlerEditSession::DoEditSession(TfEditCookie ec)
{
HRESULT hResult = S_OK;
CKeyStateCategoryFactory *pKeyStateCategoryFactory = CKeyStateCategoryFactory::Instance();
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();
if (pKeyStateCategory)
{
KeyHandlerEditSessionDTO keyHandlerEditSessioDTO(ec, _pContext, _uCode, _wch, _KeyState.Function);
hResult = pKeyStateCategory->KeyStateHandler(_KeyState.Function, keyHandlerEditSessioDTO);
pKeyStateCategory->Release();
pKeyStateCategoryFactory->Release();
}
return hResult;
+33 -3
View File
@@ -236,6 +236,20 @@ HRESULT CMetasequoiaIME::_HandleCandidateArrowKey( //
ec;
pContext;
if (_pCandidateListUIPresenter == nullptr)
{
return S_OK;
}
if ((keyFunction == FUNCTION_MOVE_PAGE_UP) || (keyFunction == FUNCTION_MOVE_PAGE_DOWN) ||
(keyFunction == FUNCTION_MOVE_PAGE_TOP) || (keyFunction == FUNCTION_MOVE_PAGE_BOTTOM))
{
if (_pCandidateListUIPresenter->_GetCount() <= 1)
{
return S_OK;
}
}
_pCandidateListUIPresenter->AdviseUIChangedByArrowKey(keyFunction);
return S_OK;
@@ -770,8 +784,19 @@ void CCandidateListUIPresenter::SetPageIndexWithScrollInfo( //
_In_ CMetasequoiaImeArray<CCandidateListItem> *pCandidateList //
)
{
UINT candCntInPage = _pIndexRange->Count();
UINT bufferSize = pCandidateList->Count() / candCntInPage + 1;
if ((pCandidateList == nullptr) || (_pIndexRange == nullptr))
{
return;
}
const UINT candCntInPage = _pIndexRange->Count();
if (candCntInPage == 0)
{
return;
}
const UINT candidateCount = pCandidateList->Count();
const UINT bufferSize = (candidateCount == 0) ? 0 : ((candidateCount - 1) / candCntInPage + 1);
UINT *puPageIndex = new (std::nothrow) UINT[bufferSize];
if (puPageIndex != nullptr)
{
@@ -783,7 +808,12 @@ void CCandidateListUIPresenter::SetPageIndexWithScrollInfo( //
_candidateState.SetPageIndex(puPageIndex, bufferSize);
delete[] puPageIndex;
}
_candidateState.SetScrollInfo(pCandidateList->Count(),
else if (bufferSize == 0)
{
_candidateState.SetPageIndex(nullptr, 0);
}
_candidateState.SetScrollInfo(candidateCount,
candCntInPage); // nMax:range of max, nPage:number of items in page
}
//+---------------------------------------------------------------------------
+4
View File
@@ -75,6 +75,10 @@ class CCandidateListUIPresenter : public CTfTextLayoutSink,
void _NotifyUI();
void _SetText(_In_ CMetasequoiaImeArray<CCandidateListItem> *pCandidateList, BOOL isAddFindKeyCode);
void _ClearList();
UINT _GetCount() const
{
return _candidateState.GetCount();
}
DWORD_PTR _GetSelectedCandidateString(_Outptr_result_maybenull_ const WCHAR **ppwchCandidateString);
BOOL _SetSelectionInPage(int nPos)
+40 -8
View File
@@ -1,6 +1,8 @@
#include "Private.h"
#include "CandidateSessionState.h"
#include <corecrt_wstring.h>
#include <debugapi.h>
#include "fmt/xchar.h"
CCandidateSessionState::CCandidateSessionState(_In_ CCandidateRange *pIndexRange)
{
@@ -132,13 +134,13 @@ DWORD CCandidateSessionState::GetSelectedCandidateString(
BOOL CCandidateSessionState::SetSelectionInPage(_In_ int nPos)
{
if (nPos < 0)
if ((nPos < 0) || (_candidateList.Count() == 0) || (_pageIndex.Count() == 0) || (_pIndexRange == nullptr))
{
return FALSE;
}
UINT pos = static_cast<UINT>(nPos);
if (pos >= _candidateList.Count())
const UINT pageSize = _pIndexRange->Count();
if (pageSize == 0)
{
return FALSE;
}
@@ -149,12 +151,24 @@ BOOL CCandidateSessionState::SetSelectionInPage(_In_ int nPos)
return FALSE;
}
_currentSelection = *_pageIndex.GetAt(currentPage) + nPos;
const UINT pageStart = *_pageIndex.GetAt(currentPage);
const UINT selection = pageStart + static_cast<UINT>(nPos);
if ((selection >= _candidateList.Count()) || (selection >= pageStart + pageSize))
{
return FALSE;
}
_currentSelection = selection;
return TRUE;
}
BOOL CCandidateSessionState::MoveSelection(_In_ int offSet)
{
if (_candidateList.Count() == 0)
{
return FALSE;
}
if (_currentSelection + offSet >= _candidateList.Count())
{
return FALSE;
@@ -199,6 +213,17 @@ BOOL CCandidateSessionState::MovePage(_In_ int offSet)
return TRUE;
}
if ((_candidateList.Count() == 0) || (_pageIndex.Count() == 0) || (_pIndexRange == nullptr))
{
return FALSE;
}
const UINT pageSize = _pIndexRange->Count();
if (pageSize == 0)
{
return FALSE;
}
int currentPage = 0;
if (FAILED(GetCurrentPage(&currentPage)))
{
@@ -211,14 +236,21 @@ BOOL CCandidateSessionState::MovePage(_In_ int offSet)
return FALSE;
}
if (_currentSelection % _pIndexRange->Count() == 0 && _currentSelection == *_pageIndex.GetAt(currentPage))
if ((_currentSelection % pageSize) == 0 && _currentSelection == *_pageIndex.GetAt(currentPage))
{
_dontAdjustOnEmptyItemPage = TRUE;
}
int selectionOffset = _currentSelection - *_pageIndex.GetAt(currentPage);
_currentSelection = *_pageIndex.GetAt(newPage) + selectionOffset;
_currentSelection = _candidateList.Count() > _currentSelection ? _currentSelection : _candidateList.Count() - 1;
const UINT currentPageStart = *_pageIndex.GetAt(currentPage);
const UINT newPageStart = *_pageIndex.GetAt(newPage);
if (newPageStart >= _candidateList.Count())
{
return FALSE;
}
const UINT selectionOffset = _currentSelection - currentPageStart;
const UINT maxSelectionInPage = min(pageSize - 1, _candidateList.Count() - 1 - newPageStart);
_currentSelection = newPageStart + min(selectionOffset, maxSelectionInPage);
return TRUE;
}