openDecal/Native/DecalInput/TypeAction.cpp
erik d1442e3747 Initial commit: Complete open-source Decal rebuild
All 5 phases of the open-source Decal rebuild:

Phase 1: 14 decompiled .NET projects (Interop.*, Adapter, FileService, DecalUtil)
Phase 2: 10 native DLLs rewritten as C# COM servers with matching GUIDs
  - DecalDat, DHS, SpellFilter, DecalInput, DecalNet, DecalFilters
  - Decal.Core, DecalControls, DecalRender, D3DService
Phase 3: C++ shims for Inject.DLL (D3D9 hooking) and LauncherHook.DLL
Phase 4: DenAgent WinForms tray application
Phase 5: WiX installer and build script

25 C# projects building with 0 errors.
Native C++ projects require VS 2022 + Windows SDK (x86).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 18:27:56 +01:00

231 lines
5.3 KiB
C++

// TypeAction.cpp : Implementation of cTypeAction
#include "stdafx.h"
#include "DecalInput.h"
#include "TypeAction.h"
/////////////////////////////////////////////////////////////////////////////
// cTypeAction
HRESULT cTypeAction::extractKey( LPTSTR &szIter, long nShiftState, IInputService *pService )
{
HRESULT hRes;
switch( *szIter )
{
case _T( '\0' ):
return E_INVALIDARG;
case _T( '{' ):
// Make sure this is a good key
{
for( TCHAR *szChar = szIter + 1; *szChar != _T( '\0' ); ++ szChar )
{
if( *szChar == _T( '}' ) )
{
// Look up this character in the site table
std::string strspecial( szIter + 1, szChar - ( szIter + 1 ) );
long nVK;
hRes = pService->get_KeyByName( _bstr_t( strspecial.c_str() ), &nVK );
if( FAILED( hRes ) )
{
_ASSERTE( FALSE );
return E_INVALIDARG;
}
cKey key = { nShiftState, nVK };
m_keys.push_back( key );
szIter = szChar + 1;
break;
}
}
if( *szChar == _T( '\0' ) )
{
// Unterminated constant
return E_INVALIDARG;
}
}
break;
case _T( '<' ):
{
for( TCHAR *szChar = szIter + 1; *szChar != _T( '\0' ); ++ szChar )
{
if( *szChar == _T( '>' ) )
{
// Look up this character in the site table
std::string strspecial( szIter + 1, szChar - ( szIter + 1 ) );
long nVK;
hRes = pService->get_CommandKey( _bstr_t( strspecial.c_str() ), &nVK );
if( hRes != S_OK )
{
_ASSERTE( FALSE );
return E_INVALIDARG;
}
cKey key = { nShiftState, nVK };
m_keys.push_back( key );
szIter = szChar + 1;
break;
}
}
if( *szChar == _T( '\0' ) )
{
// Unterminated constant
return E_INVALIDARG;
}
}
break;
default:
{
// Convert the character
WORD wVkScan = VkKeyScan( *szIter );
cKey key = { nShiftState | ( wVkScan & SHIFT_MASK ),
wVkScan & VKEY_MASK };
m_keys.push_back( key );
++ szIter;
}
}
return S_OK;
}
HRESULT cTypeAction::onLoad( LPTSTR szData )
{
USES_CONVERSION;
typedef std::stack< long > cShiftStack;
cShiftStack shifts;
long nCurrentShift = 0;
CComPtr< IInputService > pService;
HRESULT hRes = m_pSite->get_Service( &pService );
if( FAILED( hRes ) )
return hRes;
for( TCHAR *szIter = szData; *szIter != _T( '\0' ); )
{
switch( *szIter )
{
case _T( '+' ):
if( szIter[ 1 ] == _T( '(' ) )
{
szIter += 2;
shifts.push( nCurrentShift );
nCurrentShift |= MASK_SHIFT;
}
else
{
++ szIter;
hRes = extractKey( szIter, nCurrentShift | MASK_SHIFT, pService );
if( FAILED( hRes ) )
return hRes;
}
break;
case _T( '^' ):
if( szIter[ 1 ] == _T( '(' ) )
{
szIter += 2;
shifts.push( nCurrentShift );
nCurrentShift |= MASK_CTRL;
}
else
{
++ szIter;
hRes = extractKey( szIter, nCurrentShift | MASK_SHIFT, pService );
if( FAILED( hRes ) )
return hRes;
}
break;
case _T( '%' ):
if( szIter[ 1 ] == _T( '(' ) )
{
szIter += 2;
shifts.push( nCurrentShift );
nCurrentShift |= MASK_ALT;
}
else
{
++ szIter;
hRes = extractKey( szIter, nCurrentShift | MASK_SHIFT, pService );
if( FAILED( hRes ) )
return hRes;
}
break;
case _T( ')' ):
{
if( shifts.size() == 0 )
{
// Misplaced ')'
_ASSERT( FALSE );
return E_INVALIDARG;
}
nCurrentShift = shifts.top();
shifts.pop();
++ szIter;
}
break;
default:
hRes = extractKey( szIter, nCurrentShift, pService );
if( FAILED( hRes ) )
return hRes;
break;
}
}
if( shifts.size() > 0 )
{
// Unterminated shift
_ASSERT( FALSE );
return E_INVALIDARG;
}
// Successful parsing WTG!
return S_OK;
}
STDMETHODIMP cTypeAction::Execute()
{
long nShift = 0;
for( cKeyList::iterator i = m_keys.begin(); i != m_keys.end(); ++ i )
{
transitionShift( nShift, i->m_nShiftState );
pressKey( i->m_nVK, true );
pressKey( i->m_nVK, false );
nShift = i->m_nShiftState;
}
// Make sure all shift keys are released
transitionShift( nShift, 0 );
flushInput();
return S_OK;
}
STDMETHODIMP cTypeAction::Push()
{
doInput( m_keys.begin(), m_keys.end(), true );
return S_OK;
}
STDMETHODIMP cTypeAction::Pop()
{
doInput( m_keys.rbegin(), m_keys.rend(), false );
return S_OK;
}