winInput.cpp

Engine/source/platformWin32/winInput.cpp

More...

Classes:

Public Defines

define
define
NUM_KEYS() (  + 1 )

Public Variables

AsciiTable [NUM_KEYS]
VcodeRemap [256]

Public Functions

DefineEngineFunction(getJoystickAxes , const char * , (U32 deviceID) , "getJoystickAxes( instance )" )
DefineEngineFunction(isJoystickDetected , bool , () , "isJoystickDetected()" )

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