winInput.cpp
Engine/source/platformWin32/winInput.cpp
Classes:
class
class
Public Variables
AsciiTable [NUM_KEYS]
VcodeRemap [256]
Public Functions
DefineEngineFunction(getJoystickAxes , const char * , (U32 deviceID) , "getJoystickAxes( instance )" )
DefineEngineFunction(isJoystickDetected , bool , () , "isJoystickDetected()" )
TranslateKeyCodeToOS(U8 keycode)
TranslateOSKeyCode(U8 vcode)
Detailed Description
Public Defines
KEY_FIRST()
NUM_KEYS() ( + 1 )
Public Variables
AsciiData AsciiTable [NUM_KEYS]
U8 VcodeRemap [256]
Public Functions
DefineEngineFunction(getJoystickAxes , const char * , (U32 deviceID) , "getJoystickAxes( instance )" )
DefineEngineFunction(isJoystickDetected , bool , () , "isJoystickDetected()" )
fillAsciiTable()
TranslateKeyCodeToOS(U8 keycode)
TranslateOSKeyCode(U8 vcode)
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#if !defined( TORQUE_SDL ) 25#include "platformWin32/platformWin32.h" 26 27#include "platform/platformInput.h" 28#include "platformWin32/winDirectInput.h" 29#include "console/console.h" 30#include "console/engineAPI.h" 31#include "core/util/journal/process.h" 32#include "windowManager/platformWindowMgr.h" 33 34#ifdef LOG_INPUT 35#include <time.h> 36#include <stdarg.h> 37#endif 38 39// Static class variables: 40InputManager* Input::smManager; 41bool Input::smActive; 42U8 Input::smModifierKeys; 43bool Input::smLastKeyboardActivated; 44bool Input::smLastMouseActivated; 45bool Input::smLastJoystickActivated; 46InputEvent Input::smInputEvent; 47 48#ifdef LOG_INPUT 49static HANDLE gInputLog; 50#endif 51 52static void fillAsciiTable(); 53 54//------------------------------------------------------------------------------ 55// 56// This function gets the standard ASCII code corresponding to our key code 57// and the existing modifier key state. 58// 59//------------------------------------------------------------------------------ 60struct AsciiData 61{ 62 struct KeyData 63 { 64 U16 ascii; 65 bool isDeadChar; 66 }; 67 68 KeyData upper; 69 KeyData lower; 70 KeyData goofy; 71}; 72 73 74#define NUM_KEYS ( KEY_OEM_102 + 1 ) 75#define KEY_FIRST KEY_ESCAPE 76static AsciiData AsciiTable[NUM_KEYS]; 77 78//------------------------------------------------------------------------------ 79void Input::init() 80{ 81 Con::printf( "Input Init:" ); 82 83 destroy(); 84 85#ifdef LOG_INPUT 86 struct tm* newTime; 87 time_t aclock; 88 time( &aclock ); 89 newTime = localtime( &aclock ); 90 asctime( newTime ); 91 92 gInputLog = CreateFile( L"input.log", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); 93 log( "Input log opened at %s\n", asctime( newTime ) ); 94#endif 95 96 smActive = false; 97 smLastKeyboardActivated = true; 98 smLastMouseActivated = true; 99 smLastJoystickActivated = true; 100 101 OSVERSIONINFO OSVersionInfo; 102 dMemset( &OSVersionInfo, 0, sizeof( OSVERSIONINFO ) ); 103 OSVersionInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO ); 104 if ( GetVersionEx( &OSVersionInfo ) ) 105 { 106#ifdef LOG_INPUT 107 log( "Operating System:\n" ); 108 switch ( OSVersionInfo.dwPlatformId ) 109 { 110 case VER_PLATFORM_WIN32s: 111 log( " Win32s on Windows 3.1 version %d.%d\n", OSVersionInfo.dwMajorVersion, OSVersionInfo.dwMinorVersion ); 112 break; 113 114 case VER_PLATFORM_WIN32_WINDOWS: 115 log( " Windows 95 version %d.%d\n", OSVersionInfo.dwMajorVersion, OSVersionInfo.dwMinorVersion ); 116 log( " Build number %d\n", LOWORD( OSVersionInfo.dwBuildNumber ) ); 117 break; 118 119 case VER_PLATFORM_WIN32_NT: 120 log( " WinNT version %d.%d\n", OSVersionInfo.dwMajorVersion, OSVersionInfo.dwMinorVersion ); 121 log( " Build number %d\n", OSVersionInfo.dwBuildNumber ); 122 break; 123 } 124 125 if ( OSVersionInfo.szCSDVersion != NULL ) 126 log( " %s\n", OSVersionInfo.szCSDVersion ); 127 128 log( "\n" ); 129#endif 130 131 if ( !( OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && OSVersionInfo.dwMajorVersion < 5 ) ) 132 { 133 smManager = new DInputManager; 134 if ( !smManager->enable() ) 135 { 136 Con::printf( " DirectInput not enabled." ); 137 delete smManager; 138 smManager = NULL; 139 } 140 else 141 { 142 DInputManager::init(); 143 Con::printf( " DirectInput enabled." ); 144 } 145 } 146 else 147 Con::printf( " WinNT detected -- DirectInput not enabled." ); 148 } 149 150 // Init the current modifier keys 151 setModifierKeys(0); 152 fillAsciiTable(); 153 Con::printf( "" ); 154 155 // Set ourselves to participate in per-frame processing. 156 Process::notify(Input::process, PROCESS_INPUT_ORDER); 157 158} 159 160//------------------------------------------------------------------------------ 161DefineEngineFunction( isJoystickDetected, bool, (), , "isJoystickDetected()") 162{ 163 return( DInputDevice::joystickDetected() ); 164} 165 166//------------------------------------------------------------------------------ 167DefineEngineFunction( getJoystickAxes, const char*, (U32 deviceID), , "getJoystickAxes( instance )") 168{ 169 DInputManager* mgr = dynamic_cast<DInputManager*>( Input::getManager() ); 170 if ( mgr ) 171 return( mgr->getJoystickAxesString( deviceID ) ); 172 173 return( "" ); 174} 175 176//------------------------------------------------------------------------------ 177static void fillAsciiTable() 178{ 179#ifdef LOG_INPUT 180 char buf[256]; 181 Input::log( "--- Filling the ASCII table! ---\n" ); 182#endif 183 184 //HKL layout = GetKeyboardLayout( 0 ); 185 U8 state[256]; 186 U16 ascii[2]; 187 U32 dikCode, vKeyCode, keyCode; 188 S32 result; 189 190 dMemset( &AsciiTable, 0, sizeof( AsciiTable ) ); 191 dMemset( &state, 0, sizeof( state ) ); 192 193 for ( keyCode = KEY_FIRST; keyCode < NUM_KEYS; keyCode++ ) 194 { 195 ascii[0] = ascii[1] = 0; 196 dikCode = Key_to_DIK( keyCode ); 197 198 // This is a special case for numpad keys. 199 // 200 // The KEY_NUMPAD# torque types represent the event generated when a 201 // numpad key is pressed WITH NUMLOCK ON. Therefore it does have an ascii 202 // value, but to get it from windows we must specify in the keyboard state 203 // that numlock is on. 204 if ( KEY_NUMPAD0 <= keyCode && keyCode <= KEY_NUMPAD9 ) 205 { 206 state[VK_NUMLOCK] = 0x80; 207 208 // Also, numpad keys return completely different keycodes when 209 // numlock is not pressed (home,insert,etc) and MapVirtualKey 210 // appears to always return those values. 211 // 212 // So I'm using TranslateKeyCodeToOS instead. Really it looks 213 // like we could be using this method for all of them and 214 // cut out the Key_to_DIK middleman. 215 // 216 vKeyCode = TranslateKeyCodeToOS( keyCode ); 217 218 result = ToAscii( vKeyCode, dikCode, state, ascii, 0 ); 219 220 AsciiTable[keyCode].lower.ascii = ascii[0]; 221 AsciiTable[keyCode].upper.ascii = 0; 222 AsciiTable[keyCode].goofy.ascii = 0; 223 224 state[VK_NUMLOCK] = 0; 225 226 continue; 227 } 228 229 if ( dikCode ) 230 { 231 //vKeyCode = MapVirtualKeyEx( dikCode, 1, layout ); 232 vKeyCode = MapVirtualKey( dikCode, 1 ); 233#ifdef LOG_INPUT 234 dSprintf( buf, sizeof( buf ), "KC: %#04X DK: %#04X VK: %#04X\n", 235 keyCode, dikCode, vKeyCode ); 236 Input::log( buf ); 237#endif 238 239 // Lower case: 240 ascii[0] = ascii[1] = 0; 241 //result = ToAsciiEx( vKeyCode, dikCode, state, ascii, 0, layout ); 242 result = ToAscii( vKeyCode, dikCode, state, ascii, 0 ); 243#ifdef LOG_INPUT 244 dSprintf( buf, sizeof( buf ), " LOWER- R: %d A[0]: %#06X A[1]: %#06X\n", 245 result, ascii[0], ascii[1] ); 246 Input::log( buf ); 247#endif 248 if ( result == 2 ) 249 AsciiTable[keyCode].lower.ascii = ascii[1] ? ascii[1] : ( ascii[0] >> 8 ); 250 else if ( result == 1 ) 251 AsciiTable[keyCode].lower.ascii = ascii[0]; 252 else if ( result < 0 ) 253 { 254 AsciiTable[keyCode].lower.ascii = ascii[0]; 255 AsciiTable[keyCode].lower.isDeadChar = true; 256 // Need to clear the dead character from the keyboard layout: 257 //ToAsciiEx( vKeyCode, dikCode, state, ascii, 0, layout ); 258 ToAscii( vKeyCode, dikCode, state, ascii, 0 ); 259 } 260 261 // Upper case: 262 ascii[0] = ascii[1] = 0; 263 state[VK_SHIFT] = 0x80; 264 //result = ToAsciiEx( vKeyCode, dikCode, state, ascii, 0, layout ); 265 result = ToAscii( vKeyCode, dikCode, state, ascii, 0 ); 266#ifdef LOG_INPUT 267 dSprintf( buf, sizeof( buf ), " UPPER- R: %d A[0]: %#06X A[1]: %#06X\n", 268 result, ascii[0], ascii[1] ); 269 Input::log( buf ); 270#endif 271 if ( result == 2 ) 272 AsciiTable[keyCode].upper.ascii = ascii[1] ? ascii[1] : ( ascii[0] >> 8 ); 273 else if ( result == 1 ) 274 AsciiTable[keyCode].upper.ascii = ascii[0]; 275 else if ( result < 0 ) 276 { 277 AsciiTable[keyCode].upper.ascii = ascii[0]; 278 AsciiTable[keyCode].upper.isDeadChar = true; 279 // Need to clear the dead character from the keyboard layout: 280 //ToAsciiEx( vKeyCode, dikCode, state, ascii, 0, layout ); 281 ToAscii( vKeyCode, dikCode, state, ascii, 0 ); 282 } 283 state[VK_SHIFT] = 0; 284 285 // Foreign mod case: 286 ascii[0] = ascii[1] = 0; 287 state[VK_CONTROL] = 0x80; 288 state[VK_MENU] = 0x80; 289 //result = ToAsciiEx( vKeyCode, dikCode, state, ascii, 0, layout ); 290 result = ToAscii( vKeyCode, dikCode, state, ascii, 0 ); 291#ifdef LOG_INPUT 292 dSprintf( buf, sizeof( buf ), " GOOFY- R: %d A[0]: %#06X A[1]: %#06X\n", 293 result, ascii[0], ascii[1] ); 294 Input::log( buf ); 295#endif 296 if ( result == 2 ) 297 AsciiTable[keyCode].goofy.ascii = ascii[1] ? ascii[1] : ( ascii[0] >> 8 ); 298 else if ( result == 1 ) 299 AsciiTable[keyCode].goofy.ascii = ascii[0]; 300 else if ( result < 0 ) 301 { 302 AsciiTable[keyCode].goofy.ascii = ascii[0]; 303 AsciiTable[keyCode].goofy.isDeadChar = true; 304 // Need to clear the dead character from the keyboard layout: 305 //ToAsciiEx( vKeyCode, dikCode, state, ascii, 0, layout ); 306 ToAscii( vKeyCode, dikCode, state, ascii, 0 ); 307 } 308 state[VK_CONTROL] = 0; 309 state[VK_MENU] = 0; 310 } 311 } 312 313#ifdef LOG_INPUT 314 Input::log( "--- Finished filling the ASCII table! ---\n\n" ); 315#endif 316} 317 318//------------------------------------------------------------------------------ 319U16 Input::getKeyCode( U16 asciiCode ) 320{ 321 U16 keyCode = 0; 322 U16 i; 323 324 // This is done three times so the lowerkey will always 325 // be found first. Some foreign keyboards have duplicate 326 // chars on some keys. 327 for ( i = KEY_FIRST; i < NUM_KEYS && !keyCode; i++ ) 328 { 329 if ( AsciiTable[i].lower.ascii == asciiCode ) 330 { 331 keyCode = i; 332 break; 333 }; 334 } 335 336 for ( i = KEY_FIRST; i < NUM_KEYS && !keyCode; i++ ) 337 { 338 if ( AsciiTable[i].upper.ascii == asciiCode ) 339 { 340 keyCode = i; 341 break; 342 }; 343 } 344 345 for ( i = KEY_FIRST; i < NUM_KEYS && !keyCode; i++ ) 346 { 347 if ( AsciiTable[i].goofy.ascii == asciiCode ) 348 { 349 keyCode = i; 350 break; 351 }; 352 } 353 354 return( keyCode ); 355} 356 357//------------------------------------------------------------------------------ 358U16 Input::getAscii( U16 keyCode, KEY_STATE keyState ) 359{ 360 if ( keyCode >= NUM_KEYS ) 361 return 0; 362 363 switch ( keyState ) 364 { 365 case STATE_LOWER: 366 return AsciiTable[keyCode].lower.ascii; 367 case STATE_UPPER: 368 return AsciiTable[keyCode].upper.ascii; 369 case STATE_GOOFY: 370 return AsciiTable[keyCode].goofy.ascii; 371 default: 372 return(0); 373 374 } 375} 376 377//------------------------------------------------------------------------------ 378void Input::destroy() 379{ 380 Process::remove(Input::process); 381 382#ifdef LOG_INPUT 383 if ( gInputLog ) 384 { 385 log( "*** CLOSING LOG ***\n" ); 386 CloseHandle( gInputLog ); 387 gInputLog = NULL; 388 } 389#endif 390 391 if ( smManager && smManager->isEnabled() ) 392 { 393 smManager->disable(); 394 delete smManager; 395 smManager = NULL; 396 } 397} 398 399//------------------------------------------------------------------------------ 400bool Input::enable() 401{ 402 if ( smManager && !smManager->isEnabled() ) 403 return( smManager->enable() ); 404 405 return( false ); 406} 407 408//------------------------------------------------------------------------------ 409void Input::disable() 410{ 411 if ( smManager && smManager->isEnabled() ) 412 smManager->disable(); 413} 414 415//------------------------------------------------------------------------------ 416 417void Input::activate() 418{ 419#ifdef UNICODE 420 //winState.imeHandle = ImmGetContext( getWin32WindowHandle() ); 421 //ImmReleaseContext( getWin32WindowHandle(), winState.imeHandle ); 422#endif 423 424 if ( !Con::getBoolVariable( "$enableDirectInput" ) ) 425 return; 426 427 if ( smManager && smManager->isEnabled() && !smActive ) 428 { 429 Con::printf( "Activating DirectInput..." ); 430#ifdef LOG_INPUT 431 Input::log( "Activating DirectInput...\n" ); 432#endif 433 smActive = true; 434 DInputManager* dInputManager = dynamic_cast<DInputManager*>( smManager ); 435 if ( dInputManager ) 436 { 437 if ( dInputManager->isJoystickEnabled() && smLastJoystickActivated ) 438 dInputManager->activateJoystick(); 439 } 440 } 441} 442 443//------------------------------------------------------------------------------ 444void Input::deactivate() 445{ 446 if ( smManager && smManager->isEnabled() && smActive ) 447 { 448#ifdef LOG_INPUT 449 Input::log( "Deactivating DirectInput...\n" ); 450#endif 451 DInputManager* dInputManager = dynamic_cast<DInputManager*>( smManager ); 452 453 if ( dInputManager ) 454 { 455 smLastJoystickActivated = dInputManager->isJoystickActive(); 456 dInputManager->deactivateJoystick(); 457 } 458 459 smActive = false; 460 Con::printf( "DirectInput deactivated." ); 461 } 462} 463 464//------------------------------------------------------------------------------ 465bool Input::isEnabled() 466{ 467 if ( smManager ) 468 return smManager->isEnabled(); 469 return false; 470} 471 472//------------------------------------------------------------------------------ 473bool Input::isActive() 474{ 475 return smActive; 476} 477 478//------------------------------------------------------------------------------ 479void Input::process() 480{ 481 if ( smManager && smManager->isEnabled() && smActive ) 482 smManager->process(); 483} 484 485//------------------------------------------------------------------------------ 486InputManager* Input::getManager() 487{ 488 return( smManager ); 489} 490 491#ifdef LOG_INPUT 492//------------------------------------------------------------------------------ 493void Input::log( const char* format, ... ) 494{ 495 if ( !gInputLog ) 496 return; 497 498 va_list argptr; 499 va_start( argptr, format ); 500 501 char buffer[512]; 502 dVsprintf( buffer, 511, format, argptr ); 503 DWORD bytes; 504 WriteFile( gInputLog, buffer, dStrlen( buffer ), &bytes, NULL ); 505 506 va_end( argptr ); 507} 508 509DefineEngineFunction( inputLog, void, (const char * log), , "inputLog( string )") 510{ 511 Input::log( "%s\n", log ); 512} 513#endif // LOG_INPUT 514 515 516//------------------------------------------------------------------------------ 517//------------------------------------------------------------------------------ 518static U8 VcodeRemap[256] = 519{ 5200, // 0x00 5210, // 0x01 VK_LBUTTON 5220, // 0x02 VK_RBUTTON 5230, // 0x03 VK_CANCEL 5240, // 0x04 VK_MBUTTON 5250, // 0x05 5260, // 0x06 5270, // 0x07 528KEY_BACKSPACE, // 0x08 VK_BACK 529KEY_TAB, // 0x09 VK_TAB 5300, // 0x0A 5310, // 0x0B 5320, // 0x0C VK_CLEAR 533KEY_RETURN, // 0x0D VK_RETURN 5340, // 0x0E 5350, // 0x0F 536KEY_SHIFT, // 0x10 VK_SHIFT 537KEY_CONTROL, // 0x11 VK_CONTROL 538KEY_ALT, // 0x12 VK_MENU 539KEY_PAUSE, // 0x13 VK_PAUSE 540KEY_CAPSLOCK, // 0x14 VK_CAPITAL 5410, // 0x15 VK_KANA, VK_HANGEUL, VK_HANGUL 5420, // 0x16 5430, // 0x17 VK_JUNJA 5440, // 0x18 VK_FINAL 5450, // 0x19 VK_HANJA, VK_KANJI 5460, // 0x1A 547KEY_ESCAPE, // 0x1B VK_ESCAPE 548 5490, // 0x1C VK_CONVERT 5500, // 0x1D VK_NONCONVERT 5510, // 0x1E VK_ACCEPT 5520, // 0x1F VK_MODECHANGE 553 554KEY_SPACE, // 0x20 VK_SPACE 555KEY_PAGE_UP, // 0x21 VK_PRIOR 556KEY_PAGE_DOWN, // 0x22 VK_NEXT 557KEY_END, // 0x23 VK_END 558KEY_HOME, // 0x24 VK_HOME 559KEY_LEFT, // 0x25 VK_LEFT 560KEY_UP, // 0x26 VK_UP 561KEY_RIGHT, // 0x27 VK_RIGHT 562KEY_DOWN, // 0x28 VK_DOWN 5630, // 0x29 VK_SELECT 564KEY_PRINT, // 0x2A VK_PRINT 5650, // 0x2B VK_EXECUTE 5660, // 0x2C VK_SNAPSHOT 567KEY_INSERT, // 0x2D VK_INSERT 568KEY_DELETE, // 0x2E VK_DELETE 569KEY_HELP, // 0x2F VK_HELP 570 571KEY_0, // 0x30 VK_0 VK_0 thru VK_9 are the same as ASCII '0' thru '9' (// 0x30 - // 0x39) 572KEY_1, // 0x31 VK_1 573KEY_2, // 0x32 VK_2 574KEY_3, // 0x33 VK_3 575KEY_4, // 0x34 VK_4 576KEY_5, // 0x35 VK_5 577KEY_6, // 0x36 VK_6 578KEY_7, // 0x37 VK_7 579KEY_8, // 0x38 VK_8 580KEY_9, // 0x39 VK_9 5810, // 0x3A 5820, // 0x3B 5830, // 0x3C 5840, // 0x3D 5850, // 0x3E 5860, // 0x3F 5870, // 0x40 588 589KEY_A, // 0x41 VK_A VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (// 0x41 - // 0x5A) 590KEY_B, // 0x42 VK_B 591KEY_C, // 0x43 VK_C 592KEY_D, // 0x44 VK_D 593KEY_E, // 0x45 VK_E 594KEY_F, // 0x46 VK_F 595KEY_G, // 0x47 VK_G 596KEY_H, // 0x48 VK_H 597KEY_I, // 0x49 VK_I 598KEY_J, // 0x4A VK_J 599KEY_K, // 0x4B VK_K 600KEY_L, // 0x4C VK_L 601KEY_M, // 0x4D VK_M 602KEY_N, // 0x4E VK_N 603KEY_O, // 0x4F VK_O 604KEY_P, // 0x50 VK_P 605KEY_Q, // 0x51 VK_Q 606KEY_R, // 0x52 VK_R 607KEY_S, // 0x53 VK_S 608KEY_T, // 0x54 VK_T 609KEY_U, // 0x55 VK_U 610KEY_V, // 0x56 VK_V 611KEY_W, // 0x57 VK_W 612KEY_X, // 0x58 VK_X 613KEY_Y, // 0x59 VK_Y 614KEY_Z, // 0x5A VK_Z 615 616 617KEY_WIN_LWINDOW, // 0x5B VK_LWIN 618KEY_WIN_RWINDOW, // 0x5C VK_RWIN 619KEY_WIN_APPS, // 0x5D VK_APPS 6200, // 0x5E 6210, // 0x5F 622 623KEY_NUMPAD0, // 0x60 VK_NUMPAD0 624KEY_NUMPAD1, // 0x61 VK_NUMPAD1 625KEY_NUMPAD2, // 0x62 VK_NUMPAD2 626KEY_NUMPAD3, // 0x63 VK_NUMPAD3 627KEY_NUMPAD4, // 0x64 VK_NUMPAD4 628KEY_NUMPAD5, // 0x65 VK_NUMPAD5 629KEY_NUMPAD6, // 0x66 VK_NUMPAD6 630KEY_NUMPAD7, // 0x67 VK_NUMPAD7 631KEY_NUMPAD8, // 0x68 VK_NUMPAD8 632KEY_NUMPAD9, // 0x69 VK_NUMPAD9 633KEY_MULTIPLY, // 0x6A VK_MULTIPLY 634KEY_ADD, // 0x6B VK_ADD 635KEY_SEPARATOR, // 0x6C VK_SEPARATOR 636KEY_SUBTRACT, // 0x6D VK_SUBTRACT 637KEY_DECIMAL, // 0x6E VK_DECIMAL 638KEY_DIVIDE, // 0x6F VK_DIVIDE 639KEY_F1, // 0x70 VK_F1 640KEY_F2, // 0x71 VK_F2 641KEY_F3, // 0x72 VK_F3 642KEY_F4, // 0x73 VK_F4 643KEY_F5, // 0x74 VK_F5 644KEY_F6, // 0x75 VK_F6 645KEY_F7, // 0x76 VK_F7 646KEY_F8, // 0x77 VK_F8 647KEY_F9, // 0x78 VK_F9 648KEY_F10, // 0x79 VK_F10 649KEY_F11, // 0x7A VK_F11 650KEY_F12, // 0x7B VK_F12 651KEY_F13, // 0x7C VK_F13 652KEY_F14, // 0x7D VK_F14 653KEY_F15, // 0x7E VK_F15 654KEY_F16, // 0x7F VK_F16 655KEY_F17, // 0x80 VK_F17 656KEY_F18, // 0x81 VK_F18 657KEY_F19, // 0x82 VK_F19 658KEY_F20, // 0x83 VK_F20 659KEY_F21, // 0x84 VK_F21 660KEY_F22, // 0x85 VK_F22 661KEY_F23, // 0x86 VK_F23 662KEY_F24, // 0x87 VK_F24 6630, // 0x88 6640, // 0x89 6650, // 0x8A 6660, // 0x8B 6670, // 0x8C 6680, // 0x8D 6690, // 0x8E 6700, // 0x8F 671 672KEY_NUMLOCK, // 0x90 VK_NUMLOCK 673KEY_SCROLLLOCK, // 0x91 VK_OEM_SCROLL 6740, // 0x92 6750, // 0x93 6760, // 0x94 6770, // 0x95 6780, // 0x96 6790, // 0x97 6800, // 0x98 6810, // 0x99 6820, // 0x9A 6830, // 0x9B 6840, // 0x9C 6850, // 0x9D 6860, // 0x9E 6870, // 0x9F 688 689KEY_LSHIFT, // 0xA0 VK_LSHIFT 690KEY_RSHIFT, // 0xA1 VK_RSHIFT 691KEY_LCONTROL, // 0xA2 VK_LCONTROL 692KEY_RCONTROL, // 0xA3 VK_RCONTROL 693KEY_LALT, // 0xA4 VK_LMENU 694KEY_RALT, // 0xA5 VK_RMENU 6950, // 0xA6 6960, // 0xA7 6970, // 0xA8 6980, // 0xA9 6990, // 0xAA 7000, // 0xAB 7010, // 0xAC 7020, // 0xAD 7030, // 0xAE 7040, // 0xAF 7050, // 0xB0 7060, // 0xB1 7070, // 0xB2 7080, // 0xB3 7090, // 0xB4 7100, // 0xB5 7110, // 0xB6 7120, // 0xB7 7130, // 0xB8 7140, // 0xB9 715KEY_SEMICOLON, // 0xBA VK_OEM_1 716KEY_EQUALS, // 0xBB VK_OEM_PLUS 717KEY_COMMA, // 0xBC VK_OEM_COMMA 718KEY_MINUS, // 0xBD VK_OEM_MINUS 719KEY_PERIOD, // 0xBE VK_OEM_PERIOD 720KEY_SLASH, // 0xBF VK_OEM_2 721KEY_TILDE, // 0xC0 VK_OEM_3 7220, // 0xC1 7230, // 0xC2 7240, // 0xC3 7250, // 0xC4 7260, // 0xC5 7270, // 0xC6 7280, // 0xC7 7290, // 0xC8 7300, // 0xC9 7310, // 0xCA 7320, // 0xCB 7330, // 0xCC 7340, // 0xCD 7350, // 0xCE 7360, // 0xCF 7370, // 0xD0 7380, // 0xD1 7390, // 0xD2 7400, // 0xD3 7410, // 0xD4 7420, // 0xD5 7430, // 0xD6 7440, // 0xD7 7450, // 0xD8 7460, // 0xD9 7470, // 0xDA 748KEY_LBRACKET, // 0xDB VK_OEM_4 749KEY_BACKSLASH, // 0xDC VK_OEM_5 750KEY_RBRACKET, // 0xDD VK_OEM_6 751KEY_APOSTROPHE, // 0xDE VK_OEM_7 7520, // 0xDF VK_OEM_8 7530, // 0xE0 7540, // 0xE1 VK_OEM_AX AX key on Japanese AX keyboard 755KEY_OEM_102, // 0xE2 VK_OEM_102 7560, // 0xE3 7570, // 0xE4 758 7590, // 0xE5 VK_PROCESSKEY 760 7610, // 0xE6 7620, // 0xE7 7630, // 0xE8 7640, // 0xE9 7650, // 0xEA 7660, // 0xEB 7670, // 0xEC 7680, // 0xED 7690, // 0xEE 7700, // 0xEF 771 7720, // 0xF0 7730, // 0xF1 7740, // 0xF2 7750, // 0xF3 7760, // 0xF4 7770, // 0xF5 778 7790, // 0xF6 VK_ATTN 7800, // 0xF7 VK_CRSEL 7810, // 0xF8 VK_EXSEL 7820, // 0xF9 VK_EREOF 7830, // 0xFA VK_PLAY 7840, // 0xFB VK_ZOOM 7850, // 0xFC VK_NONAME 7860, // 0xFD VK_PA1 7870, // 0xFE VK_OEM_CLEAR 7880 // 0xFF 789}; 790 791 792//------------------------------------------------------------------------------ 793// 794// This function translates a virtual key code to our corresponding internal 795// key code using the preceding table. 796// 797//------------------------------------------------------------------------------ 798U8 TranslateOSKeyCode(U8 vcode) 799{ 800 return VcodeRemap[vcode]; 801} 802 803U8 TranslateKeyCodeToOS(U8 keycode) 804{ 805 for(S32 i = 0;i < sizeof(VcodeRemap) / sizeof(U8);++i) 806 { 807 if(VcodeRemap[i] == keycode) 808 return i; 809 } 810 return 0; 811} 812 813//----------------------------------------------------------------------------- 814// Clipboard functions 815const char* Platform::getClipboard() 816{ 817 HGLOBAL hGlobal; 818 LPVOID pGlobal; 819 820 //make sure we can access the clipboard 821 if (!IsClipboardFormatAvailable(CF_TEXT)) 822 return ""; 823 if (!OpenClipboard(NULL)) 824 return ""; 825 826 hGlobal = GetClipboardData(CF_TEXT); 827 pGlobal = GlobalLock(hGlobal); 828 S32 cbLength = strlen((char *)pGlobal); 829 char *returnBuf = Con::getReturnBuffer(cbLength + 1); 830 strcpy(returnBuf, (char *)pGlobal); 831 returnBuf[cbLength] = '\0'; 832 GlobalUnlock(hGlobal); 833 CloseClipboard(); 834 835 //note - this function never returns NULL 836 return returnBuf; 837} 838 839//----------------------------------------------------------------------------- 840bool Platform::setClipboard(const char *text) 841{ 842 if (!text) 843 return false; 844 845 //make sure we can access the clipboard 846 if (!OpenClipboard(NULL)) 847 return false; 848 849 S32 cbLength = strlen(text); 850 851 HGLOBAL hGlobal; 852 LPVOID pGlobal; 853 854 hGlobal = GlobalAlloc(GHND, cbLength + 1); 855 pGlobal = GlobalLock (hGlobal); 856 857 strcpy((char *)pGlobal, text); 858 859 GlobalUnlock(hGlobal); 860 861 EmptyClipboard(); 862 SetClipboardData(CF_TEXT, hGlobal); 863 CloseClipboard(); 864 865 return true; 866} 867 868#endif 869