reman3/Rayman_X/cpa/tempgrp/INO/Specif/KeybDI.c

419 lines
14 KiB
C

/***************************************************************************/
/* Description: KeybDI.c, part of CPA INO library */
/* Keyboard specific implementation */
/* */
/* Author: F. Jentey */
/* Last Update: 05/03/97 */
/* 30/07/97 Direct Input */
/***************************************************************************/
#include <locale.h>
#include "INO\errINO.h"
#include "InitDI.h"
#include "INOInit.h"
#include "Keyboard.h"
/**************************************************************************
Globale vars
***************************************************************************/
/* Keyboard config variables : get the country keyboard config */
char INO_LayoutName[KL_NAMELENGTH];
HKL INO_LayoutHandle;
/* Table for virtual key code use for ASCII conversion */
/* INO_acDikToVirtual is used for the numeric pad, coz */
/* MapVirtualKeyEx() doesn't Verr Num state. */
BYTE INO_acVirtualKeyCodeTab[256];
BYTE INO_acDikToVirtual[256];
/* Store the key use in the game */
unsigned short INO_ActiveKey[128];
unsigned short INO_ActiveKeyNumber;
/**********************************************************************************/
/* This fonction returns the ASCII code corresponding to a key code if this key */
/* is printable. */
/**********************************************************************************/
short INO_fn_wDikToAscii(short wKeyCode, INO_tdhDevice hDev)
{
unsigned long VirtualKeyCode;
long iResult;
unsigned short a_uwASCIICode[2];
/* Get the VirtualKey code of the key */
/* We suppose all DIK code correspond to scan code. */
/* For numeric pad key, use the dik to virtual key */
/* code translation table. */
if ( (((wKeyCode>0x46) && (wKeyCode<0x54)) || (wKeyCode==0xb5)) &&
(GetKeyState(VK_NUMLOCK) & INO_C_ucKeyToggled) )
VirtualKeyCode = INO_acDikToVirtual[wKeyCode];
else
VirtualKeyCode = MapVirtualKeyEx(wKeyCode, 1, INO_LayoutHandle);
/* La fameuse modif qui tue - Elie */
if ( (VirtualKeyCode == 0) ||
(VirtualKeyCode == VK_CAPITAL) ||
(VirtualKeyCode == VK_SCROLL) ||
(VirtualKeyCode == VK_NUMLOCK) ||
(VirtualKeyCode == VK_SHIFT) ||
(VirtualKeyCode == VK_CONTROL) ||
(VirtualKeyCode == VK_MENU) ||
((VirtualKeyCode >= VK_F1) && (VirtualKeyCode<=VK_F24))
)
return (0);
/* Fill the INO_acVirtualKeyCodeTab array with SHIFT, ALT and CTRL state */
INO_acVirtualKeyCodeTab[VK_SHIFT] = INO_C_ucKeyDown &
( M_KeyState(hDev,C_ucKey_LSHIFT) |
M_KeyState(hDev,C_ucKey_RSHIFT) );
INO_acVirtualKeyCodeTab[VK_CONTROL] = INO_C_ucKeyDown &
( M_KeyState(hDev,C_ucKey_LCTRL) |
M_KeyState(hDev,C_ucKey_RCTRL) );
INO_acVirtualKeyCodeTab[VK_MENU] = INO_C_ucKeyDown &
( M_KeyState(hDev,C_ucKey_LALT) |
M_KeyState(hDev,C_ucKey_RALT) );
INO_acVirtualKeyCodeTab[VK_CAPITAL] = GetKeyState(VK_CAPITAL) & INO_C_ucKeyToggled;
/* Deuxieme modif qui tue - Elie */
/* INO_acVirtualKeyCodeTab[VK_NUMLOCK] = GetKeyState(VK_NUMLOCK) & INO_C_ucKeyToggled;*/
iResult = ToAsciiEx(VirtualKeyCode, wKeyCode, INO_acVirtualKeyCodeTab, a_uwASCIICode,0 , INO_LayoutHandle);
switch (iResult)
{
case 0:
return (0);
case 1:
iResult = (int)(a_uwASCIICode[0] & 0xFF);
/*if (!isprint(iResult) /*&& iswprint(iResult) ) */
/* return (0);*/
break;
case 2:
return (0);
}
return ((short)iResult);
}
/* Remove an active key. An error occurs when the specified key isn't */
/* active.By default, all keys are active, but you can remove some keys */
/* if they aren't used to speed up the fn_wKbRead function. */
short INO_fn_wRemoveActiveKey(short wKeyCode)
{
short i,j;
for (i=0 ;i<INO_ActiveKeyNumber; i++)
{
if (INO_ActiveKey[i] == wKeyCode)
{
for (j=i+1; j<INO_ActiveKeyNumber; j++)
INO_ActiveKey[j-1] = INO_ActiveKey[j];
INO_ActiveKeyNumber--;
return (1);
}
}
return (0);
}
/* Add a key to be managed. There is an error if the specified key is */
/* already active. */
short INO_fn_wAddActiveKey(short wKeyCode)
{
short i;
if (INO_ActiveKeyNumber > 127)
{
/* TO DO: error message */
return (0);
}
/* Test if key is already active */
for (i=0 ;i<INO_ActiveKeyNumber; i++)
{
if (INO_ActiveKey[i] == wKeyCode)
return (0);
}
INO_ActiveKey[INO_ActiveKeyNumber] = wKeyCode;
INO_ActiveKeyNumber++;
return (0);
}
/*********************************************************************
INITIALISATION
*********************************************************************/
/* Init keyboard capabilities. */
short INO_fn_wInitKeyboardCaps(INO_tdhDevice hDev)
{
short wASCIIForKeyA, i;
short wDev;
unsigned long ulSubType;
for (i=0; i<INO_C_wNbMaxDevice; i++)
if (INO_g_a_stDIDevice[i].m_hDevice == hDev) break;
if (i == INO_C_wNbMaxDevice) return (0);
wDev = i;
ulSubType = INO_fn_wFillDeviceCaps(hDev);
if (!ulSubType)
return(0);
memset(INO_ActiveKey,0,sizeof(unsigned short)*128);
INO_ActiveKeyNumber = 0;
/* For ASCII conversion */
GetKeyboardLayoutName(INO_LayoutName);
INO_LayoutHandle = LoadKeyboardLayout(INO_LayoutName,KLF_ACTIVATE);
/* Set the default active Key (All keys) */
for ( i=0x01 ; i<0x58 ; i++ )
INO_fn_wAddActiveKey(i);
INO_fn_wAddActiveKey(0x69); /* Pause */
INO_fn_wAddActiveKey(0x9c);
INO_fn_wAddActiveKey(0x9d);
INO_fn_wAddActiveKey(0xb5);
INO_fn_wAddActiveKey(0xb7);
INO_fn_wAddActiveKey(0xb8);
INO_fn_wAddActiveKey(0xc7);
INO_fn_wAddActiveKey(0xc5); /* Num Lock */
INO_fn_wAddActiveKey(0xc8);
INO_fn_wAddActiveKey(0xc9);
INO_fn_wAddActiveKey(0xcb);
INO_fn_wAddActiveKey(0xcd);
INO_fn_wAddActiveKey(0xcf);
INO_fn_wAddActiveKey(0xd0);
INO_fn_wAddActiveKey(0xd1);
INO_fn_wAddActiveKey(0xd2);
INO_fn_wAddActiveKey(0xd3);
INO_fn_wAddActiveKey(0xdb);
INO_fn_wAddActiveKey(0xdc);
INO_fn_wAddActiveKey(0xdd);
/* Fill the Dik to Virtual key code translation table */
/* for numeric pad (Vk when Verr Num is ON) */
INO_acDikToVirtual[C_ucKey_PAD_0] = VK_NUMPAD0;
INO_acDikToVirtual[C_ucKey_PAD_1] = VK_NUMPAD1;
INO_acDikToVirtual[C_ucKey_PAD_2] = VK_NUMPAD2;
INO_acDikToVirtual[C_ucKey_PAD_3] = VK_NUMPAD3;
INO_acDikToVirtual[C_ucKey_PAD_4] = VK_NUMPAD4;
INO_acDikToVirtual[C_ucKey_PAD_5] = VK_NUMPAD5;
INO_acDikToVirtual[C_ucKey_PAD_6] = VK_NUMPAD6;
INO_acDikToVirtual[C_ucKey_PAD_7] = VK_NUMPAD7;
INO_acDikToVirtual[C_ucKey_PAD_8] = VK_NUMPAD8;
INO_acDikToVirtual[C_ucKey_PAD_9] = VK_NUMPAD9;
INO_acDikToVirtual[C_ucKey_PAD_DIV] = VK_DIVIDE;
INO_acDikToVirtual[C_ucKey_PAD_MUL] = VK_MULTIPLY;
INO_acDikToVirtual[C_ucKey_PAD_SUB] = VK_SUBTRACT;
INO_acDikToVirtual[C_ucKey_PAD_ADD] = VK_ADD;
INO_acDikToVirtual[C_ucKey_PAD_POINT] = VK_DECIMAL;
/* Find keyboard type (Azerty / Qwerty) */
wASCIIForKeyA = INO_fn_wDikToAscii(C_ucKey_A,hDev) & 0xFF;
if ((wASCIIForKeyA == 'a') || (wASCIIForKeyA == 'A'))
((INO_tdstKeyboardCaps*)(hDev->m_p_stCaps))->m_wIsAzerty = 1;
else
((INO_tdstKeyboardCaps*)(hDev->m_p_stCaps))->m_wIsAzerty = 0;
return (1);
}
/* This function must be called at regular interval, for example each VBL. */
/* It Update the informations about the keyboard. */
short INO_fn_wReadKeyboard(INO_tdhDevice hDev)
{
HRESULT DInputErr;
unsigned short i, j;
short DownKey[INO_C_wMaxKeyDown];
short DownKeyNumber;
short LastKeyHasChanged, StateHasChanged;
short wDev;
INO_tdstKeyboardState *p_stState = M_KState(hDev);
INO_tdstKeyboardRecord *p_stH = (INO_tdstKeyboardRecord*)hDev->m_pvHistoric;
unsigned char *p_ucCurrentTab, *p_ucPrevTab;
if (!INO_M_bIsConnected(hDev))
return (0);
for (wDev=0; wDev<INO_C_wNbMaxDevice; wDev++)
if (INO_g_a_stDIDevice[wDev].m_hDevice == hDev) break;
if (wDev == INO_C_wNbMaxDevice)
{
INO_fn_vUpdateLastError(E_uwINO_WarningInvalidDevice);
return (0);
}
/* Increase the internal engine loop counter */
hDev->m_ulLastTimeCount++;
/* Flip the keyboard state buffer */
p_stState->m_wCurrentTab = 1 - p_stState->m_wCurrentTab;
p_ucCurrentTab = p_stState->m_a_ucTabKey[p_stState->m_wCurrentTab];
p_ucPrevTab = p_stState->m_a_ucTabKey[1-p_stState->m_wCurrentTab];
/* Try to acquire the keyboard if not done */
if (!(p_stState->m_ucStatus & INO_C_ucAcquired) ||
(p_stState->m_ucStatus & INO_C_ucAccessError) )
{
DInputErr = M_DIAcquire(wDev);
switch (DInputErr)
{
case DI_OK:
case S_FALSE:
hDev->m_p_stState->m_ucStatus |= INO_C_ucAcquired;
hDev->m_p_stState->m_ucStatus &= ~INO_C_ucAccessError;
break;
case DIERR_INPUTLOST:
case DIERR_NOTACQUIRED:
case DIERR_OTHERAPPHASPRIO:
return (0);
default:
hDev->m_p_stState->m_ucStatus &= ~INO_C_ucAcquired;
hDev->m_p_stState->m_ucStatus |= INO_C_ucAccessError;
INO_fn_vUpdateLastError(E_uwINO_DirectInputError);
return (0);
}
}
/* Read all key */
DInputErr = M_DIGetState(wDev, sizeof(BYTE)*256, p_ucCurrentTab);
switch (DInputErr)
{
case DI_OK:
case E_PENDING:
break;
case DIERR_INPUTLOST:
case DIERR_NOTACQUIRED:
hDev->m_p_stState->m_ucStatus &= ~INO_C_ucAcquired;
return (0);
default:
INO_fn_vUpdateLastError(E_uwINO_DirectInputError);
hDev->m_p_stState->m_ucStatus |= INO_C_ucAccessError;
hDev->m_p_stState->m_ucStatus &= ~INO_C_ucAcquired;
return (0);
}
/* Check if the keyboard state has changed by comparing the current buffer with */
/* the previous one. Store the key code of the down key in the local tab */
/* ChangedKey. */
StateHasChanged = 0;
LastKeyHasChanged = 0;
DownKeyNumber = 0;
for (i=0 ; i<INO_ActiveKeyNumber ; i++)
{
j = INO_ActiveKey[i];
if (p_ucCurrentTab[j] != p_ucPrevTab[j])
{
StateHasChanged = 1;
if (p_ucCurrentTab[j])
{
LastKeyHasChanged = 1;
p_stState->m_wLastKey = j;
}
}
if ((DownKeyNumber < INO_C_wMaxKeyDown) && p_ucCurrentTab[j])
DownKey[DownKeyNumber++] = j;
}
if (LastKeyHasChanged)
{
/* Update last ASCII code */
p_stState->m_wLastASCII = INO_fn_wDikToAscii(p_stState->m_wLastKey,hDev);
/* Update the current string */
if (p_stState->m_wLastASCII)
{
if (p_stState->m_wCurrentStringLength == INO_C_wStringMaxLength)
{
for (i=0; i<INO_C_wStringMaxLength-1; i++)
p_stState->m_szCurrentString[i] = p_stState->m_szCurrentString[i+1];
p_stState->m_szCurrentString[INO_C_wStringMaxLength-1] = (char)p_stState->m_wLastASCII;
}
else
{
p_stState->m_szCurrentString[p_stState->m_wCurrentStringLength] = (char)p_stState->m_wLastASCII;
p_stState->m_wCurrentStringLength++;
}
}
}
else
p_stState->m_wLastASCII = 0;
/* Update historic. */
/* Test if it's the first call of the fn_wJKbReadKeyboard */
if (hDev->m_wRecordNumber == 0)
{
p_stH[0].m_ulDate = hDev->m_ulLastTimeCount;
p_stH[0].m_wNbKeyDown = 0;
hDev->m_wRecordNumber = 1;
StateHasChanged = 0;
}
/* If not, update the historic if keyboard state has changed */
else
{
if (StateHasChanged)
{
hDev->m_wHistoricHead++;
if (hDev->m_wHistoricHead == hDev->m_wHistoricSize) hDev->m_wHistoricHead = 0;
if (hDev->m_wRecordNumber != hDev->m_wHistoricSize) hDev->m_wRecordNumber++;
p_stH[hDev->m_wHistoricHead].m_ulDate = hDev->m_ulLastTimeCount;
p_stH[hDev->m_wHistoricHead].m_wNbKeyDown = 0;
for (i=0; i<DownKeyNumber; i++)
p_stH[hDev->m_wHistoricHead].m_wKeyDown[i] = DownKey[i];
p_stH[hDev->m_wHistoricHead].m_wNbKeyDown = DownKeyNumber;
}
}
p_stState->m_wStateHasChanged = StateHasChanged;
return (1);
}
/*
This function return C_wKbTrue if the selected key was down in the
specified previous state.
*/
short INO_fn_bKeyWasDown(INO_tdhDevice hDev, short wKeyCode, short wHistoricIndex)
{
long index, i;
INO_tdstKeyboardRecord *p_stState;
if (wHistoricIndex > hDev->m_wHistoricSize-1)
return (0);
else
{
index = (hDev->m_wHistoricHead - wHistoricIndex + hDev->m_wHistoricSize) % hDev->m_wHistoricSize;
p_stState = &((INO_tdstKeyboardRecord*)(hDev->m_pvHistoric))[index];
for (i=0 ; i<p_stState->m_wNbKeyDown; i++ )
if (p_stState->m_wKeyDown[i] == wKeyCode ) return (1);
}
return (0);
}
short INO_fn_wCheckCheatCode(INO_tdhDevice hDev,char *p_szTestString)
{
short l;
char *p_szCurrentS;
INO_tdstKeyboardState *p_stState = (INO_tdstKeyboardState*)(hDev->m_p_stState);
l = strlen(p_szTestString);
if (l > INO_C_wStringMaxLength) return (0);
if (l > p_stState->m_wCurrentStringLength) return (0);
p_szCurrentS = &p_stState->m_szCurrentString[p_stState->m_wCurrentStringLength-l];
return (strcmp(p_szCurrentS,p_szTestString) == 0);
}