// 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; }