winInput.cpp 26 KB

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