diff --git a/stepmania/src/RageInput.cpp b/stepmania/src/RageInput.cpp index 28e0ef80d2..2aedec78b4 100644 --- a/stepmania/src/RageInput.cpp +++ b/stepmania/src/RageInput.cpp @@ -97,7 +97,7 @@ RString RageInput::GetDeviceSpecificInputString( const DeviceInput &di ) return di.ToString(); } -char RageInput::DeviceButtonToChar( DeviceButton button ) +wchar_t RageInput::DeviceButtonToChar( DeviceButton button, bool bUseCurrentKeyModifiers ) { FOREACH( InputHandler*, m_pDevices, i ) { @@ -107,7 +107,7 @@ char RageInput::DeviceButtonToChar( DeviceButton button ) FOREACH_CONST( InputDeviceInfo, vDevices, idi ) { if( idi->id == DEVICE_KEYBOARD ) - return (*i)->DeviceButtonToChar(button); + return (*i)->DeviceButtonToChar(button, bUseCurrentKeyModifiers); } } diff --git a/stepmania/src/RageInput.h b/stepmania/src/RageInput.h index 4d02fca1d3..37032cfa18 100644 --- a/stepmania/src/RageInput.h +++ b/stepmania/src/RageInput.h @@ -21,7 +21,7 @@ public: void WindowReset(); void AddHandler( InputHandler *pHandler ); RString GetDeviceSpecificInputString( const DeviceInput &di ); - char DeviceButtonToChar( DeviceButton button ); + wchar_t DeviceButtonToChar( DeviceButton button, bool bUseCurrentKeyModifiers ); InputDeviceState GetInputDeviceState( InputDevice id ); RString GetDisplayDevicesString() const; diff --git a/stepmania/src/RageInputDevice.cpp b/stepmania/src/RageInputDevice.cpp index c7edb3ae00..1a148d86a1 100644 --- a/stepmania/src/RageInputDevice.cpp +++ b/stepmania/src/RageInputDevice.cpp @@ -8,6 +8,7 @@ #include "RageUtil.h" #include "EnumHelper.h" #include "LocalizedString.h" +#include "RageInput.h" static map g_mapNamesToString; static map g_mapStringToNames; @@ -147,6 +148,16 @@ RString DeviceButtonToString( DeviceButton key ) return "unknown"; } +RString DeviceButtonToTranslatedString( DeviceButton key ) +{ + /* All printable ASCII except for uppercase alpha characters line up. */ + if( key >= 33 && key < 127 && + !(key >= 'A' && key <= 'Z' ) ) + return WStringToRString( wstring()+INPUTMAN->DeviceButtonToChar(key,false) ); + + return DeviceButtonToString( key ); +} + static LocalizedString HOME ( "DeviceButton", "Home" ); static LocalizedString END ( "DeviceButton", "End" ); static LocalizedString UP ( "DeviceButton", "Up" ); @@ -161,7 +172,7 @@ static LocalizedString PGUP ( "DeviceButton", "PgUp" ); static LocalizedString PGDN ( "DeviceButton", "PgDn" ); static LocalizedString BACKSLASH ( "DeviceButton", "Backslash" ); -RString DeviceButtonToLocalizedString( DeviceButton key ) +RString DeviceButtonToLocalizedAndTranslatedString( DeviceButton key ) { switch( key ) { @@ -178,7 +189,7 @@ RString DeviceButtonToLocalizedString( DeviceButton key ) case KEY_PGUP: return PGUP.GetValue(); case KEY_PGDN: return PGDN.GetValue(); case KEY_BACKSLASH: return BACKSLASH.GetValue(); - default: return Capitalize( DeviceButtonToString(key) ); + default: return Capitalize( DeviceButtonToTranslatedString(key) ); } } diff --git a/stepmania/src/RageInputDevice.h b/stepmania/src/RageInputDevice.h index 0afc0240dd..20ac298e56 100644 --- a/stepmania/src/RageInputDevice.h +++ b/stepmania/src/RageInputDevice.h @@ -292,7 +292,8 @@ enum DeviceButton }; RString DeviceButtonToString( DeviceButton i ); -RString DeviceButtonToLocalizedString( DeviceButton i ); +RString DeviceButtonToTranslatedString( DeviceButton i ); +RString DeviceButtonToLocalizedAndTranslatedString( DeviceButton i ); DeviceButton StringToDeviceButton( const RString& s ); struct DeviceInput diff --git a/stepmania/src/ScreenEdit.cpp b/stepmania/src/ScreenEdit.cpp index fb8ae5cf1c..f45046de4f 100644 --- a/stepmania/src/ScreenEdit.cpp +++ b/stepmania/src/ScreenEdit.cpp @@ -3596,9 +3596,9 @@ static RString GetDeviceButtonsLocalized( const vector &veb, const M DeviceInput diPress = editmap.button[*eb][s]; DeviceInput diHold = editmap.hold[*eb][s]; if( diPress.IsValid() ) - vsPress.push_back( DeviceButtonToLocalizedString(diPress.button) ); + vsPress.push_back( DeviceButtonToLocalizedAndTranslatedString(diPress.button) ); if( diHold.IsValid() ) - vsHold.push_back( DeviceButtonToLocalizedString(diHold.button) ); + vsHold.push_back( DeviceButtonToLocalizedAndTranslatedString(diHold.button) ); } } diff --git a/stepmania/src/ScreenNameEntryTraditional.cpp b/stepmania/src/ScreenNameEntryTraditional.cpp index fc40fb56cc..d564b4c83d 100644 --- a/stepmania/src/ScreenNameEntryTraditional.cpp +++ b/stepmania/src/ScreenNameEntryTraditional.cpp @@ -516,7 +516,7 @@ void ScreenNameEntryTraditional::Input( const InputEventPlus &input ) if( input.DeviceI == DeviceInput(DEVICE_KEYBOARD, KEY_BACK) ) c = CHAR_BACK; else - c = toupper( INPUTMAN->DeviceButtonToChar( input.DeviceI.button ) ); + c = towupper( INPUTMAN->DeviceButtonToChar(input.DeviceI.button,true) ); if( c ) { PlayerNumber pn = GAMESTATE->m_MasterPlayerNumber; diff --git a/stepmania/src/ScreenNetSelectBase.cpp b/stepmania/src/ScreenNetSelectBase.cpp index c19c2bb887..45bf7bbdea 100644 --- a/stepmania/src/ScreenNetSelectBase.cpp +++ b/stepmania/src/ScreenNetSelectBase.cpp @@ -95,10 +95,6 @@ void ScreenNetSelectBase::Input( const InputEventPlus &input ) if( (input.type != IET_FIRST_PRESS) && (input.type != IET_SLOW_REPEAT) && (input.type != IET_FAST_REPEAT ) ) return; - bool bHoldingShift = - INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_LSHIFT)) || - INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_RSHIFT)); - bool bHoldingCtrl = INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_LCTRL)) || INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_RCTRL)) || @@ -123,38 +119,9 @@ void ScreenNetSelectBase::Input( const InputEventPlus &input ) UpdateTextInput(); break; default: - char c; - c = INPUTMAN->DeviceButtonToChar( input.DeviceI.button ); + wchar_t c; + c = INPUTMAN->DeviceButtonToChar(input.DeviceI.button,true); - if( bHoldingShift && !bHoldingCtrl ) - { - c = (char)toupper(c); - - switch( c ) - { - case '`': c='~'; break; - case '1': c='!'; break; - case '2': c='@'; break; - case '3': c='#'; break; - case '4': c='$'; break; - case '5': c='%'; break; - case '6': c='^'; break; - case '7': c='&'; break; - case '8': c='*'; break; - case '9': c='('; break; - case '0': c=')'; break; - case '-': c='_'; break; - case '=': c='+'; break; - case '[': c='{'; break; - case ']': c='}'; break; - case '\'': c='"'; break; - case '\\': c='|'; break; - case ';': c=':'; break; - case ',': c='<'; break; - case '.': c='>'; break; - case '/': c='?'; break; - } - } if( (c >= ' ') && (!bHoldingCtrl) ) { m_sTextInput += c; diff --git a/stepmania/src/ScreenNetSelectMusic.cpp b/stepmania/src/ScreenNetSelectMusic.cpp index e4900bd8ca..8a728b15f8 100644 --- a/stepmania/src/ScreenNetSelectMusic.cpp +++ b/stepmania/src/ScreenNetSelectMusic.cpp @@ -129,7 +129,7 @@ void ScreenNetSelectMusic::Input( const InputEventPlus &input ) INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_RCTRL)) || (!NSMAN->useSMserver); //If we are disconnected, assume no chatting - char c = (char) toupper( INPUTMAN->DeviceButtonToChar(input.DeviceI.button) ); + wchar_t c = (wchar_t) towupper( INPUTMAN->DeviceButtonToChar(input.DeviceI.button,true) ); if ( bHoldingCtrl && ( c >= 'A' ) && ( c <= 'Z' ) ) { diff --git a/stepmania/src/ScreenTextEntry.cpp b/stepmania/src/ScreenTextEntry.cpp index 7878e6f9d0..03df4d062f 100644 --- a/stepmania/src/ScreenTextEntry.cpp +++ b/stepmania/src/ScreenTextEntry.cpp @@ -183,42 +183,10 @@ void ScreenTextEntry::Input( const InputEventPlus &input ) } else if( input.type == IET_FIRST_PRESS ) { - char c = INPUTMAN->DeviceButtonToChar( input.DeviceI.button ); + wchar_t c = INPUTMAN->DeviceButtonToChar(input.DeviceI.button,true); if( c >= ' ' ) { - bool bIsHoldingShift = - INPUTFILTER->IsBeingPressed( DeviceInput(input.DeviceI.device, KEY_RSHIFT)) || - INPUTFILTER->IsBeingPressed( DeviceInput(input.DeviceI.device, KEY_LSHIFT)); - if( bIsHoldingShift ) - { - c = (char)toupper( c ); - switch( c ) - { - case '`': c='~'; break; - case '1': c='!'; break; - case '2': c='@'; break; - case '3': c='#'; break; - case '4': c='$'; break; - case '5': c='%'; break; - case '6': c='^'; break; - case '7': c='&'; break; - case '8': c='*'; break; - case '9': c='('; break; - case '0': c=')'; break; - case '-': c='_'; break; - case '=': c='+'; break; - case '[': c='{'; break; - case ']': c='}'; break; - case '\'': c='"'; break; - case '\\': c='|'; break; - case ';': c=':'; break; - case ',': c='<'; break; - case '.': c='>'; break; - case '/': c='?'; break; - } - } - - TryAppendToAnswer( ssprintf( "%c", c ) ); + TryAppendToAnswer( WStringToRString(wstring()+c) ); TextEnteredDirectly(); } diff --git a/stepmania/src/arch/InputHandler/InputHandler.cpp b/stepmania/src/arch/InputHandler/InputHandler.cpp index 2d6ceafb1d..e573ae3a22 100644 --- a/stepmania/src/arch/InputHandler/InputHandler.cpp +++ b/stepmania/src/arch/InputHandler/InputHandler.cpp @@ -34,24 +34,67 @@ void InputHandler::ButtonPressed( DeviceInput di, bool Down ) } } -char InputHandler::DeviceButtonToChar( DeviceButton button ) +wchar_t InputHandler::DeviceButtonToChar( DeviceButton button, bool bUseCurrentKeyModifiers ) { - if( button < 127 ) - return (char) button; - - if( button >= KEY_KP_C0 && button <= KEY_KP_C9 ) - return (char) (button - KEY_KP_C0) + '0'; - + wchar_t c; switch( button ) { - case KEY_KP_SLASH: return '/'; - case KEY_KP_ASTERISK: return '*'; - case KEY_KP_HYPHEN: return '-'; - case KEY_KP_PLUS: return '+'; - case KEY_KP_PERIOD: return '.'; - case KEY_KP_EQUAL: return '='; + default: + if( button < 127 ) + c = (char) button; + else if( button >= KEY_KP_C0 && button <= KEY_KP_C9 ) + c =(char) (button - KEY_KP_C0) + '0'; + break; + case KEY_KP_SLASH: c ='/'; break; + case KEY_KP_ASTERISK: c ='*'; break; + case KEY_KP_HYPHEN: c ='-'; break; + case KEY_KP_PLUS: c ='+'; break; + case KEY_KP_PERIOD: c ='.'; break; + case KEY_KP_EQUAL: c ='='; break; } + if( bUseCurrentKeyModifiers ) + { + bool bHoldingShift = + INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_LSHIFT)) || + INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_RSHIFT)); + + bool bHoldingCtrl = + INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_LCTRL)) || + INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_RCTRL)); + + if( bHoldingShift && !bHoldingCtrl ) + { + c = (char)toupper(c); + + switch( c ) + { + case '`': c='~'; break; + case '1': c='!'; break; + case '2': c='@'; break; + case '3': c='#'; break; + case '4': c='$'; break; + case '5': c='%'; break; + case '6': c='^'; break; + case '7': c='&'; break; + case '8': c='*'; break; + case '9': c='('; break; + case '0': c=')'; break; + case '-': c='_'; break; + case '=': c='+'; break; + case '[': c='{'; break; + case ']': c='}'; break; + case '\'': c='"'; break; + case '\\': c='|'; break; + case ';': c=':'; break; + case ',': c='<'; break; + case '.': c='>'; break; + case '/': c='?'; break; + } + } + + } + return '\0'; } @@ -59,15 +102,15 @@ RString InputHandler::GetDeviceSpecificInputString( const DeviceInput &di ) { if( di.device == DEVICE_KEYBOARD ) { - char c = DeviceButtonToChar( di.button ); + wchar_t c = DeviceButtonToChar( di.button, false ); if( c ) { if( c == ' ' ) return "space"; // Don't show "Key " for space. else - return ssprintf( "Key %c", c ); + return "Key " + WStringToRString(wstring()+c); } - return DeviceButtonToString( di.button ); + return DeviceButtonToTranslatedString( di.button ); } return di.ToString(); diff --git a/stepmania/src/arch/InputHandler/InputHandler.h b/stepmania/src/arch/InputHandler/InputHandler.h index 4c7660a328..6a1d7f37d5 100644 --- a/stepmania/src/arch/InputHandler/InputHandler.h +++ b/stepmania/src/arch/InputHandler/InputHandler.h @@ -33,7 +33,7 @@ public: // Override to return a pretty string that's specific to the controller type. virtual RString GetDeviceSpecificInputString( const DeviceInput &di ); - virtual char DeviceButtonToChar( DeviceButton button ); + virtual wchar_t DeviceButtonToChar( DeviceButton button, bool bUseCurrentKeyModifiers ); // Override to find out whether the controller is currently plugged in. // Not all InputHandlers will support this. Not applicable to all InputHandlers. diff --git a/stepmania/src/arch/InputHandler/InputHandler_DirectInput.cpp b/stepmania/src/arch/InputHandler/InputHandler_DirectInput.cpp index 33e4ae6e19..67e0f1ae3b 100644 --- a/stepmania/src/arch/InputHandler/InputHandler_DirectInput.cpp +++ b/stepmania/src/arch/InputHandler/InputHandler_DirectInput.cpp @@ -272,7 +272,7 @@ void InputHandler_DInput::UpdatePolled( DIDevice &device, const RageTimer &tm ) for( int k = 0; k < 256; ++k ) { const DeviceButton key = (DeviceButton) device.Inputs[k].num; - ButtonPressed(DeviceInput(device.dev, key), !!(keys[k] & 0x80)); + ButtonPressed( DeviceInput(device.dev, key), !!(keys[k] & 0x80) ); } } break; @@ -645,7 +645,25 @@ void InputHandler_DInput::GetDevicesAndDescriptions( vector& vD vDevicesOut.push_back( InputDeviceInfo(Devices[i].dev, Devices[i].m_sName) ); } -char InputHandler_DInput::DeviceButtonToChar( DeviceButton button ) +static wchar_t ScancodeAndKeysToChar( DWORD scancode, unsigned char keys[256] ) +{ + static HKL layout = GetKeyboardLayout(0); // 0 == current thread + UINT vk = MapVirtualKeyEx( scancode, 1, layout ); + + unsigned short result[2]; // ToAscii writes a max of 2 chars + ZERO( result ); + // TODO: Use ToUnicodeEx + int iNum = ToAsciiEx( vk, scancode, keys, result, 0, layout ); + // iNum == 2 will happen only for dead keys. See MSDN for ToAsciiEx. + if( iNum == 1 ) + { + RString s = RString()+(char)result[0]; + return RStringToWstring( ConvertACPToUTF8(s) )[0]; + } + return '\0'; +} + +wchar_t InputHandler_DInput::DeviceButtonToChar( DeviceButton button, bool bUseCurrentKeyModifiers ) { FOREACH_CONST( DIDevice, Devices, d ) { @@ -657,28 +675,15 @@ char InputHandler_DInput::DeviceButtonToChar( DeviceButton button ) if( button != i->num ) continue; - DWORD scancode = i->ofs; - - HKL layout = GetKeyboardLayout(0); // 0 == current thread - - unsigned char state[256]; - // Don't fill key state. We'll do the shift/ctrl/alt - // translations ourself in ScreenTextEntry. - ZERO( state ); - - UINT vk = MapVirtualKeyEx( scancode, 1, layout ); - - unsigned short result[2]; // ToAscii writes a max of 2 chars - ZERO( result ); - // TODO: Use ToUnicodeEx - int iNum = ToAsciiEx( vk, scancode, state, result, 0, layout ); - if( iNum == 1 ) - return (char)result[0]; - // iNum == 2 will happen only for dead keys. See MSDN for ToAsciiEx. + unsigned char keys[256]; + ZERO( keys ); + if( bUseCurrentKeyModifiers ) + GetKeyboardState(keys); + return ScancodeAndKeysToChar( i->ofs, keys ); } } - return InputHandler::DeviceButtonToChar( button ); + return InputHandler::DeviceButtonToChar( button, bUseCurrentKeyModifiers ); } /* diff --git a/stepmania/src/arch/InputHandler/InputHandler_DirectInput.h b/stepmania/src/arch/InputHandler/InputHandler_DirectInput.h index e51dd1412c..1ba9e6b9c2 100644 --- a/stepmania/src/arch/InputHandler/InputHandler_DirectInput.h +++ b/stepmania/src/arch/InputHandler/InputHandler_DirectInput.h @@ -11,7 +11,7 @@ public: InputHandler_DInput(); ~InputHandler_DInput(); void GetDevicesAndDescriptions( vector& vDevicesOut ); - char DeviceButtonToChar( DeviceButton button ); + wchar_t DeviceButtonToChar( DeviceButton button, bool bUseCurrentKeyModifiers ); void Update(); bool DevicesChanged(); void WindowReset();