|
|
//****************************************************************************
//
// File: joycpl.c
// Content: Joystick configuration and testing
// History:
// Date By Reason
// ==== == ======
// 03-oct-94 craige initial implementation
// 05-nov-94 craige generalized 4 axis joysticks and other improvements
// 11-nov-94 craige allow multiple copies of tab to run
// 22-nov-94 craige tweaks to calibration code
// 29-nov-94 craige small bugs
// 08-dec-94 craige generalized second joystick
// 11-dec-94 craige split into component parts
// 15-dec-94 craige allow N joysticks
// 18-dec-94 craige process UV
// 05-jan-95 craige external rudder bug
// 05-mar-95 craige Bug 9998: pass id -1 to get base dev caps
// Bug 15334: allow reset of user values for compatiblity
// 06-mar-95 craige Bug 7608: deleting VxD name if joystick not present
// caused unplugged joystick to never come back
//
// Copyright (c) Microsoft Corporation 1994
//
//****************************************************************************
#pragma pack (8)
#include "stdafx.h"
#include "assert.h"
#include "joycpl.h"
#include "resource.h"
#include "baseids.h"
#include "pov.h"
#include "pinfo.h"
#include "comstr.h"
#include "joyarray.h" // Help array
extern USHORT gnID; // ID as sent from Client via SetID
extern BOOL fIsSideWinder; static BOOL fIsLoaded = 0;
// Context sensitive help stuff!
static void OnContextMenu(WPARAM wParam); extern const DWORD gaHelpIDs[];
#ifdef DEBUG
void cdecl MBOX(LPSTR szFormat, ...) { char ach[256];
wvsprintf( ach,szFormat,(LPSTR)(&szFormat+1)); MessageBox( NULL, ach, "JOYCPL", MB_OK | MB_SYSTEMMODAL );
} #endif
extern "C" WINMMAPI MMRESULT WINAPI joyConfigChanged(DWORD);
/***************************************************************************
MEMORY MANAGEMENT ROUTINES FOLLOW ***************************************************************************/
#ifdef DEBUG
DWORD allocCount; #endif
// DoAlloc - allocate memory
LPVOID DoAlloc( DWORD size ) { LPVOID res;
res = LocalAlloc( LPTR, size ); #ifdef DEBUG
allocCount++; #endif
return(res);
} /* DoAlloc */
/*
* DoFree - free allocated memory */ void DoFree( LPVOID ptr ) { if( ptr != NULL ) { LocalFree( ptr ); #ifdef DEBUG
allocCount--; if( allocCount < 0 ) { DPF( "JOYCPL: Too many frees, allocCount=%d\r\n", allocCount ); } #endif
}
} /* DoFree */
/***************************************************************************
REGISTRY RELATED ROUTINES FOLLOW ***************************************************************************/
// getDevCaps - get the joystick device caps
static void getDevCaps( LPGLOBALVARS pgv ) { JOYCAPS jc;
if( joyGetDevCaps( pgv->iJoyId, &jc, sizeof( jc ) ) == JOYERR_NOERROR ) { pgv->joyRange.jpMin.dwX = jc.wXmin; pgv->joyRange.jpMax.dwX = jc.wXmax; pgv->joyRange.jpMin.dwY = jc.wYmin; pgv->joyRange.jpMax.dwY = jc.wYmax; pgv->joyRange.jpMin.dwZ = jc.wZmin; pgv->joyRange.jpMax.dwZ = jc.wZmax; pgv->joyRange.jpMin.dwR = jc.wRmin; pgv->joyRange.jpMax.dwR = jc.wRmax; pgv->joyRange.jpMin.dwU = jc.wUmin; pgv->joyRange.jpMax.dwU = jc.wUmax; pgv->joyRange.jpMin.dwV = jc.wVmin; pgv->joyRange.jpMax.dwV = jc.wVmax; pgv->dwMaxAxes = (DWORD) jc.wMaxAxes; }
} /* getDevCaps */
/*
* RegistryUpdated - notify the driver that the registry is updated */ void RegistryUpdated( LPGLOBALVARS pgv ) { // joyConfigChanged( 0 );
if( pgv != NULL ) getDevCaps( pgv ); // devcaps could change
} /* RegistryUpdated */
/*
* createSettingsKeyFromCurr - create a settings key for a specific joystick */ static void createSettingsKeyFromCurr( LPGLOBALVARS pgv, LPSTR str ) { assert(pgv);
char tmp[MAX_STR]; int type; LPJOYDATA pjd;
pjd = pgv->pjd; assert(pjd);
if( pgv->joyHWCurr.dwUsageSettings & JOY_US_ISOEM ) { type = pgv->joyHWCurr.dwType - JOY_HW_LASTENTRY;
if( type < 0 || type >= pjd->oemCount ) tmp[0] = 0; else lstrcpy( tmp, pjd->oemList[type].keyname ); } else wsprintf( tmp, "predef%d", pgv->joyHWCurr.dwType );
wsprintf( str, "%s\\%s", pjd->regSettingsCfgKey, tmp );
} /* createSettingsKeyFromCurr */
static CListBox ChangeListCtrl;
// regSaveSpecificJoyHW - save specific joystick hardware config. to the registry
static void regSaveSpecificJoyHW( LPGLOBALVARS pgv ) { assert(pgv);
char str[MAX_STR]; HKEY hkey; char jcfg[MAX_STR];
if( pgv->joyHWCurr.dwType == JOY_HW_NONE ) return;
createSettingsKeyFromCurr( pgv, str );
if( !RegCreateKey( HKEY_LOCAL_MACHINE, str, &hkey ) ) { GETKEYNAME( pgv, jcfg, REGSTR_VAL_JOYNCONFIG ); RegSetValueEx( hkey, jcfg, 0, REG_BINARY, (CONST LPBYTE)&pgv->joyHWCurr, sizeof( pgv->joyHWCurr )); RegCloseKey( hkey ); }
} /* regSaveSpecificJoyHW */
/*
* regCreateCurrKey - create the current joystick settings key */ static HKEY regCreateCurrKey( LPGLOBALVARS pgv ) { assert(pgv);
HKEY hkey;
if( !RegCreateKey( HKEY_LOCAL_MACHINE, pgv->pjd->regCurrCfgKey, &hkey ) ) return(hkey); else return(NULL);
} /* regCreateCurrKey */
// RegSaveCurrentJoyHW - save the joystick info to the current entry in the registry
void RegSaveCurrentJoyHW( LPGLOBALVARS pgv ) { HKEY hkey; LPSTR sptr; char vname[MAX_STR]; char oname[MAX_STR]; char coname[MAX_STR]; int type; LPJOYDATA pjd;
assert(pgv);
hkey = regCreateCurrKey( pgv ); assert(hkey);
if( hkey == NULL ) { DPF( "Could not save current joystick settings!\r\n" ); return; }
pjd = pgv->pjd; assert(pjd);
if( pgv->joyHWCurr.dwUsageSettings & JOY_US_ISOEM ) sptr = pjd->oemList[ pgv->joyHWCurr.dwType - JOY_HW_LASTENTRY ].keyname;
GETKEYNAME( pgv, vname, REGSTR_VAL_JOYNCONFIG ); GETKEYNAME( pgv, oname, REGSTR_VAL_JOYNOEMNAME ); GETKEYNAME( pgv, coname, REGSTR_VAL_JOYNOEMCALLOUT );
RegSetValueEx( hkey, vname, 0, REG_BINARY, (CONST LPBYTE)&pgv->joyHWCurr, sizeof( pgv->joyHWCurr ) ); if( pgv->joyHWCurr.dwUsageSettings & JOY_US_ISOEM ) { RegSetValueEx( hkey, oname, 0, REG_SZ,(const unsigned char *) sptr, strlen( sptr ) + 1 );
// set up VxD name for this joystick
type = pgv->joyHWCurr.dwType - JOY_HW_LASTENTRY; if( (pjd->oemList[type].vxd_name[0] != 0) ) { RegSetValueEx( hkey, coname, 0, REG_SZ, (const unsigned char *) pjd->oemList[type].vxd_name, lstrlen( pjd->oemList[type].vxd_name )+1 ); } else RegDeleteValue( hkey, coname ); } else { RegDeleteValue( hkey, oname ); RegDeleteValue( hkey, coname ); }
RegCloseKey( hkey );
} /* RegSaveCurrentJoyHW */
// regPermSaveAllInfo - save joystick data to the registry for good
static void regPermSaveAllInfo( LPGLOBALVARS pgv ) {
assert(pgv);
// save specific hardware settings to the registry
regSaveSpecificJoyHW( pgv );
// save current current hardware to the registry
RegSaveCurrentJoyHW( pgv );
RegistryUpdated( pgv );
} /* regPermSaveAllInfo */
// setHWCurrType - set the current hardware type (check for OEM type)
static BOOL setHWCurrType( LPGLOBALVARS pgv, HKEY hkey, LPJOYREGHWCONFIG pcfg ) { assert(pgv); assert(hkey); assert(pcfg);
char str[MAX_STR]; char pname[MAX_STR]; int i; DWORD regtype; DWORD cb; LPJOYDATA pjd;
if( !(pcfg->dwUsageSettings & JOY_US_ISOEM) ) return(TRUE);
GETKEYNAME( pgv, pname, REGSTR_VAL_JOYNOEMNAME ); cb = sizeof( str ); if( RegQueryValueEx( hkey, pname, NULL, ®type, (CONST LPBYTE)str, &cb) ) return(FALSE);
if( regtype != REG_SZ ) return(FALSE);
pjd = pgv->pjd; assert(pjd);
for( i=0;i<pjd->oemCount;i++ ) { if( !lstrcmpi( str, pjd->oemList[i].keyname ) ) { pcfg->dwType = i + JOY_HW_LASTENTRY; return(TRUE); } } return(FALSE);
} /* setHWCurrType */
// regGetCurrHW - get the information about the current configuration from the registry
static void regGetCurrHW( LPGLOBALVARS pgv ) { assert(pgv);
DWORD regtype; DWORD cb; JOYREGHWCONFIG config; HKEY hkey; char str[MAX_STR];
if( hkey = regCreateCurrKey( pgv ) ) { cb = sizeof( config ); GETKEYNAME( pgv, str, REGSTR_VAL_JOYNCONFIG );
if( !RegQueryValueEx( hkey, str, NULL, ®type, (CONST LPBYTE)&config, &cb) ) { if( regtype == REG_BINARY && cb == sizeof( config ) ) { if( setHWCurrType( pgv, hkey, &config ) ) pgv->joyHWCurr = config; } } }
cb = sizeof( config ); RegCloseKey( hkey );
} /* regGetCurrHW */
// regGetOEMStr - get an OEM string
static BOOL regGetOEMStr( HKEY hkey, LPSTR keyname, LPSTR buff, int size, LPSTR *res ) { assert(hkey); assert(keyname);
DWORD cb; DWORD type; LPSTR str; int slen;
cb = size; slen = 1; if( !RegQueryValueEx( hkey, keyname, NULL, &type, (CONST LPBYTE)buff, &cb ) ) { if( type == REG_SZ ) slen = strlen( buff ) + 1; }
str = (char *) DoAlloc( slen ); assert(str); if( str != NULL ) { if( slen == 1 ) str[0] = 0; else lstrcpy( str, buff ); }
*res = str;
if( str == NULL ) return(TRUE);
return(FALSE);
} /* regGetOEMStr */
#define RANGE_MIN 0
#define RANGE_MAX 65535
/*
* checkNonStandardUserVals */ static BOOL checkNonStandardUserVals( LPJOYREGUSERVALUES puv ) { assert(puv);
if( (puv->jrvRanges.jpMin.dwX != RANGE_MIN) || (puv->jrvRanges.jpMin.dwY != RANGE_MIN) || (puv->jrvRanges.jpMin.dwZ != RANGE_MIN) || (puv->jrvRanges.jpMin.dwR != RANGE_MIN) || (puv->jrvRanges.jpMin.dwU != RANGE_MIN) || (puv->jrvRanges.jpMin.dwV != RANGE_MIN) || (puv->jrvRanges.jpMax.dwX != RANGE_MAX) || (puv->jrvRanges.jpMax.dwY != RANGE_MAX) || (puv->jrvRanges.jpMax.dwZ != RANGE_MAX) || (puv->jrvRanges.jpMax.dwR != RANGE_MAX) || (puv->jrvRanges.jpMax.dwU != RANGE_MAX) || (puv->jrvRanges.jpMax.dwV != RANGE_MAX) || (puv->dwTimeOut != 0x1000) || (puv->jpDeadZone.dwX != 0) || (puv->jpDeadZone.dwY != 0) ) { return(TRUE); } return(FALSE);
} /* checkNonStandardUserVals */
// regSetUserVals - set user values to our defaults
static void regSetUserVals( LPJOYDATA pjd, BOOL retest ) { assert(pjd);
JOYREGUSERVALUES uv; JOYREGUSERVALUES ouv; HKEY hkey; DWORD regtype; DWORD cb;
if( !RegOpenKey( HKEY_LOCAL_MACHINE, pjd->regCfgKey, &hkey ) ) { /*
* build the default settings */ memset( &uv, 0, sizeof( uv ) );
// fix #2245, take the Greater of the two timeout values.
uv.dwTimeOut = (pjd->userVals.dwTimeOut > 0x1000) ? pjd->userVals.dwTimeOut : 0x1000;
uv.jpDeadZone.dwX = 0; uv.jpDeadZone.dwY = 0; uv.jrvRanges.jpMin.dwX = RANGE_MIN; uv.jrvRanges.jpMin.dwY = RANGE_MIN; uv.jrvRanges.jpMin.dwZ = RANGE_MIN; uv.jrvRanges.jpMin.dwR = RANGE_MIN; uv.jrvRanges.jpMin.dwU = RANGE_MIN; uv.jrvRanges.jpMin.dwV = RANGE_MIN; uv.jrvRanges.jpMax.dwX = RANGE_MAX; uv.jrvRanges.jpMax.dwY = RANGE_MAX; uv.jrvRanges.jpMax.dwZ = RANGE_MAX; uv.jrvRanges.jpMax.dwR = RANGE_MAX; uv.jrvRanges.jpMax.dwU = RANGE_MAX; uv.jrvRanges.jpMax.dwV = RANGE_MAX;
if( retest ) { /*
* see if the values have changed since we last set them: * if yes, then we need to reset our remembered values */ DPF( "Looking for USER entries\r\n" ); cb = sizeof( ouv ); if( !RegQueryValueEx( hkey, REGSTR_VAL_JOYUSERVALUES, NULL, ®type, (CONST LPBYTE)&ouv, &cb) ) { DPF( "found REGSTR_VAL_JOYUSERVALUES\r\n" ); if( regtype == REG_BINARY && cb == sizeof( ouv ) ) { if( memcmp( &uv, &ouv, sizeof( uv ) ) ) { DPF( "USER entries changed!\r\n" ); pjd->bHasUserVals = TRUE; pjd->bDeleteUserVals = FALSE; pjd->userVals = ouv; } } } else { if( pjd->bHasUserVals ) { DPF( "USER entries changed, no longer exist!\r\n" ); pjd->bHasUserVals = FALSE; pjd->bDeleteUserVals = TRUE; } } }
/*
* set our new values */ RegSetValueEx( hkey, REGSTR_VAL_JOYUSERVALUES, 0, REG_BINARY, (CONST LPBYTE)&uv, sizeof( uv ) ); RegCloseKey( hkey ); }
} /* regSetUserVals */
// regUserValsInit - save old user values, and init to ones we like
static void regUserValsInit( LPJOYDATA pjd ) { assert(pjd);
HKEY hkey; DWORD regtype; DWORD cb;
pjd->bHasUserVals = FALSE; pjd->bDeleteUserVals = FALSE;
if( !RegOpenKey( HKEY_LOCAL_MACHINE, pjd->regCfgKey, &hkey ) ) { cb = sizeof( pjd->userVals );
if( !RegQueryValueEx( hkey, REGSTR_VAL_JOYUSERVALUES, NULL, ®type, (CONST LPBYTE)&pjd->userVals, &cb) ) { if( regtype == REG_BINARY && cb == sizeof( pjd->userVals ) ) { pjd->bHasUserVals = TRUE; DPF( "USER entries exist!\r\n" ); }
pjd->bHasNonStandardUserVals = checkNonStandardUserVals( &pjd->userVals ); } else { pjd->bDeleteUserVals = TRUE; pjd->bHasNonStandardUserVals = FALSE; DPF( "USER entries don't exist!\r\n" ); }
RegCloseKey( hkey ); }
regSetUserVals( pjd, FALSE );
} /* regUserValsInit */
// regUserValsFini - restore old user values
static void regUserValsFini( LPJOYDATA pjd ) { assert(pjd);
HKEY hkey = 0; if( pjd->bHasUserVals || pjd->bDeleteUserVals ) { if( !RegOpenKey( HKEY_LOCAL_MACHINE, pjd->regCfgKey, &hkey ) ) { if( pjd->bHasUserVals ) { DPF( "resetting USER entries!\r\n" ); RegSetValueEx( hkey, REGSTR_VAL_JOYUSERVALUES, 0, REG_BINARY, (CONST LPBYTE)&pjd->userVals, sizeof( pjd->userVals ) ); } else { DPF( "deleting USER entries!\r\n" ); RegDeleteValue( hkey, REGSTR_VAL_JOYUSERVALUES ); } RegistryUpdated( NULL ); } pjd->bHasUserVals = FALSE; pjd->bDeleteUserVals = FALSE; }
} /* regUserValsFini */
/***************************************************************************
CUSTOM JOYSTICK SELECTION FUNCTIONS FOLLOW ***************************************************************************/
/*
* custom joystick variables */ typedef struct { LPGLOBALVARS pgv; BOOL bHasZ; BOOL bHasR; BOOL bHasPOV; BOOL bIsYoke; BOOL bIsGamePad; BOOL bIsCarCtrl; BOOL bHas2Buttons; } cust_vars, *LPCUSTVARS;
// enableCustomSpecial - enable the special section of the custom dialog box
static void enableCustomSpecial( HWND hwnd, BOOL on ) { ASSERT (::IsWindow(hwnd));
HWND hCtrl = GetDlgItem( hwnd, IDC_JOYISYOKE ); ASSERT (::IsWindow(hCtrl)); EnableWindow( hCtrl, on );
hCtrl = GetDlgItem( hwnd, IDC_JOYISGAMEPAD ); ASSERT (::IsWindow(hCtrl)); EnableWindow( hCtrl, on );
hCtrl = GetDlgItem( hwnd, IDC_JOYISCARCTRL ); ASSERT (::IsWindow(hCtrl)); EnableWindow( hCtrl, on );
CheckDlgButton( hwnd, IDC_JOYUSESPECIAL, on );
if( !on ) { CheckDlgButton( hwnd, IDC_JOYISYOKE, FALSE ); CheckDlgButton( hwnd, IDC_JOYISGAMEPAD, FALSE ); CheckDlgButton( hwnd, IDC_JOYISCARCTRL, FALSE ); }
} /* enableCustomSpecial */
// CustomProc - callback procedure for custom joystick setup
BOOL CALLBACK CustomProc( HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam) { int id; LPGLOBALVARS pgv; LPCUSTVARS pcv;
switch( umsg ) { case WM_DESTROY: /*
* don't free the dialog's variables here, they are returned to the * creator; the creator will free them */ break; case WM_INITDIALOG: // create variables for the custom dialog
pcv = (cust_vars *) DoAlloc( sizeof( cust_vars ) ); assert(pcv); SetWindowLong( hwnd, DWL_USER, (LONG) pcv ); if( pcv == NULL ) { EndDialog( hwnd, 0 ); return(FALSE); } pgv = (LPGLOBALVARS) lParam;
assert(pgv); pcv->pgv = pgv;
// set up initial dialog state
pcv->bHasZ = (pgv->joyHWCurr.hws.dwFlags & JOY_HWS_HASZ); pcv->bHasR = (pgv->joyHWCurr.hws.dwFlags & JOY_HWS_HASR); pcv->bHas2Buttons = (pgv->joyHWCurr.hws.dwNumButtons == 2); pcv->bHasPOV = (pgv->joyHWCurr.hws.dwFlags & JOY_HWS_HASPOV); pcv->bIsYoke = (pgv->joyHWCurr.hws.dwFlags & JOY_HWS_ISYOKE); pcv->bIsGamePad = (pgv->joyHWCurr.hws.dwFlags & JOY_HWS_ISGAMEPAD); pcv->bIsCarCtrl = (pgv->joyHWCurr.hws.dwFlags & JOY_HWS_ISCARCTRL);
if( pcv->bHasZ && pcv->bHasR ) { CheckRadioButton( hwnd, IDC_JOY2AXIS, IDC_JOY4AXIS, IDC_JOY4AXIS ); } else if( pcv->bHasZ ) { CheckRadioButton( hwnd, IDC_JOY2AXIS, IDC_JOY4AXIS, IDC_JOY3AXIS ); } else { CheckRadioButton( hwnd, IDC_JOY2AXIS, IDC_JOY4AXIS, IDC_JOY2AXIS ); }
if( pcv->bHas2Buttons ) { CheckRadioButton( hwnd, IDC_JOY2BUTTON, IDC_JOY4BUTTON, IDC_JOY2BUTTON ); } else { CheckRadioButton( hwnd, IDC_JOY2BUTTON, IDC_JOY4BUTTON, IDC_JOY4BUTTON ); }
CheckDlgButton( hwnd, IDC_JOYHASPOV, pcv->bHasPOV ); id = -1; if( pcv->bIsYoke ) { id = IDC_JOYISYOKE; } else if( pcv->bIsGamePad ) { id = IDC_JOYISGAMEPAD; } else if( pcv->bIsCarCtrl ) { id = IDC_JOYISCARCTRL; } if( id != -1 ) { enableCustomSpecial( hwnd, TRUE ); CheckRadioButton( hwnd, IDC_JOYISYOKE, IDC_JOYISCARCTRL, id ); } else { enableCustomSpecial( hwnd, FALSE ); } return(FALSE);
case WM_COMMAND: pcv = (LPCUSTVARS) GetWindowLong( hwnd, DWL_USER ); id = GET_WM_COMMAND_ID(wParam, lParam); switch( id ) { case IDC_JOY2AXIS: case IDC_JOY3AXIS: case IDC_JOY4AXIS: CheckRadioButton( hwnd, IDC_JOY2AXIS, IDC_JOY4AXIS, id ); pcv->bHasZ = FALSE; pcv->bHasR = FALSE; if( id == IDC_JOY3AXIS ) { pcv->bHasZ = TRUE; } else if( id == IDC_JOY4AXIS ) { pcv->bHasZ = TRUE; pcv->bHasR = TRUE; } break; case IDC_JOY2BUTTON: case IDC_JOY4BUTTON: CheckRadioButton( hwnd, IDC_JOY2BUTTON, IDC_JOY4BUTTON, id ); pcv->bHas2Buttons = (id == IDC_JOY2BUTTON); break; case IDC_JOYUSESPECIAL: enableCustomSpecial( hwnd, IsDlgButtonChecked( hwnd, IDC_JOYUSESPECIAL ) ); pcv->bIsYoke = FALSE; pcv->bIsGamePad = FALSE; pcv->bIsCarCtrl = FALSE; break; case IDC_JOYHASPOV: pcv->bHasPOV = !pcv->bHasPOV; break; case IDC_JOYISYOKE: case IDC_JOYISGAMEPAD: case IDC_JOYISCARCTRL: pcv->bIsYoke = (id == IDC_JOYISYOKE); pcv->bIsGamePad = (id == IDC_JOYISGAMEPAD); pcv->bIsCarCtrl = (id == IDC_JOYISCARCTRL); CheckRadioButton( hwnd, IDC_JOYISYOKE, IDC_JOYISCARCTRL, id ); break; case IDCANCEL: EndDialog( hwnd, 0 ); break; case IDOK: pcv = (LPCUSTVARS) GetWindowLong( hwnd, DWL_USER ); EndDialog(hwnd, (int) pcv ); break; } break; default: break; } return(FALSE);
} /* CustomProc */
/***************************************************************************
MAIN DIALOG FUNCTIONS FOLLOW ***************************************************************************/
// variables used by joystick tab dialog
typedef struct { LPGLOBALVARS pgv; } JTVARS, *LPJTVARS;
// numJoyAxes - get number of axes on a joystick
static int numJoyAxes( LPGLOBALVARS pgv ) { assert(pgv);
DWORD flags; int axis_count;
flags = pgv->joyHWCurr.hws.dwFlags; axis_count = 2; if( flags & JOY_HWS_HASZ ) { axis_count++; } if( flags & JOY_HWS_HASR ) { axis_count++; } if( (flags & JOY_HWS_HASPOV) && (flags & JOY_HWS_POVISPOLL) ) { axis_count++; } return(axis_count);
} /* numJoyAxes */
// saveHWSettings - save the current hardware settings
static void saveHWSettings( LPGLOBALVARS pgv ) { assert(pgv);
pgv->joyHWOrig = pgv->joyHWCurr;
} /* saveHWSettings */
// restoreHWSettings - restore current hw settings to saved values
static void restoreHWSettings( LPGLOBALVARS pgv ) { assert(pgv);
pgv->joyHWCurr = pgv->joyHWOrig; RegSaveCurrentJoyHW( pgv );
} /* restoreHWSettings */
// getActiveFlags - poll and test which joysticks are currently plugged in
static unsigned getActiveFlags( LPGLOBALVARS pgv ) { JOYINFOEX ji; MMRESULT rc; unsigned val;
assert(pgv);
// check for presense of joystick 1 and joystick 2
val = 0; ji.dwSize = sizeof( ji ); ji.dwFlags = JOY_RETURNX|JOY_RETURNY|JOY_CAL_READXYONLY|JOY_CAL_READALWAYS; rc = joyGetPosEx( pgv->iJoyId, &ji ); DPF( "joyGetPosEx = %d\r\n", rc ); if( rc == JOYERR_NOERROR ) { val = HASJOY; }
// check if either could have a rudder attached.
ji.dwFlags = JOY_RETURNR | JOY_CAL_READRONLY; if( (numJoyAxes( pgv ) < 4) && !(pgv->joyHWCurr.hws.dwFlags & JOY_HWS_HASR ) ) { rc = joyGetPosEx( pgv->iJoyId, &ji ); if( rc ==JOYERR_NOERROR ) { val |= HASRUDDERMAYBE; } } return(val);
} /* getActiveFlags */
// enableTestCal - enable/disable test and calibrate buttons
static void enableTestCal( HWND hwnd, int hw_type ) { ASSERT(::IsWindow(hwnd));
BOOL enable = (hw_type != JOY_HW_NONE);
HWND hCtrl = GetDlgItem( hwnd, IDC_JOYCALIBRATE ); ASSERT (::IsWindow(hCtrl)); EnableWindow( hCtrl, enable ); } /* enableTestCal */
// cleanUpJoyDlg - clean up allocated stuff
static void cleanUpJoyDlg( HWND hwnd ) { assert(hwnd);
LPGLOBALVARS pgv;
pgv = (LPGLOBALVARS) GetWindowLong( hwnd, DWL_USER ); if( pgv == NULL ) return;
// ditch timer
if( pgv->pjd->bHasTimer ) { KillTimer( hwnd, TIMER_ID ); pgv->pjd->bHasTimer = FALSE; }
// done with our variables
#if defined( WANT_SHEETS )
DoFree( pgv ); #endif
} /* cleanUpJoyDlg */
// enableJoyWindows - enable controls for a joystick
static void enableJoyWindows( LPGLOBALVARS pgv, HWND hwnd, BOOL enable ) { HWND hCtrl = GetDlgItem(hwnd,IDC_JOYCALIBRATE); ASSERT (::IsWindow(hCtrl)); EnableWindow( hCtrl, enable ); } /* enableJoyWindows */
// enableActiveJoystick - enable dialog controls based on presence of joysticks
static void enableActiveJoystick( LPGLOBALVARS pgv, HWND hwnd ) { assert(pgv); assert(hwnd);
BOOL allowj; char str[MAX_STR]; unsigned joys; LPSTR text;
// check what joysticks are active; if it hasn't changed, just return
joys = getActiveFlags( pgv ); if( pgv->joyActiveFlags == joys ) return;
pgv->joyActiveFlags = joys;
// turn off the rudder if it is gone
if( !(joys & HASRUDDERMAYBE) ) { pgv->joyHWCurr.dwUsageSettings &= ~JOY_US_HASRUDDER; CheckDlgButton( hwnd, IDC_JOY1HASRUDDER, FALSE ); }
// enable the appropriate windows
allowj = ((joys & HASJOY) != 0); enableJoyWindows( pgv, hwnd, allowj );
HWND hCtrl = GetDlgItem( hwnd, IDC_JOY1HASRUDDER ); ASSERT (::IsWindow(hCtrl)); EnableWindow( hCtrl, allowj && (joys & HASRUDDERMAYBE) );
// set message for the user if there is no joystick plugged in, or if there is no joystick driver present
if( allowj ) { text = ""; } else { text = str;
LoadString( GetResourceInstance(), (joyGetNumDevs()) ? IDS_JOYUNPLUGGED : IDS_JOYNOTPRESENT, str, sizeof( str ) ); }
if( allowj ) enableTestCal( hwnd, pgv->joyHWCurr.dwType );
if( allowj ) pgv->joyHWCurr.dwUsageSettings |= JOY_US_PRESENT; else pgv->joyHWCurr.dwUsageSettings &= ~JOY_US_PRESENT;
RegSaveCurrentJoyHW( pgv ); RegistryUpdated( pgv );
} /* enableActiveJoystick */
#ifdef DEAD_CODE
/*
* getNewJoyInfo - get information from the registry about a new joystick. * If no info, default to joyHWDefault settings */ static void getNewJoyInfo( LPGLOBALVARS pgv, HWND hwnd ) { assert(pgv); assert(hwnd);
DWORD hw_type; HKEY hkey; char str[MAX_STR]; char jcfg[MAX_STR]; DWORD regtype; JOYREGHWCONFIG config; DWORD cb; BOOL same; int rc;
GETKEYNAME( pgv, jcfg, REGSTR_VAL_JOYNCONFIG );
// get the hardware type
hw_type = SendDlgItemMessage( hwnd, IDC_JOYSELECT, CB_GETCURSEL, 0, 0L ); same = (hw_type == pgv->joyHWCurr.dwType);
// read the info from the registry if a new hardware type selected
if( !same ) { pgv->joyHWCurr = pgv->pjd->joyHWDefaults[ hw_type ]; createSettingsKeyFromCurr( pgv, str ); if( !RegOpenKey( HKEY_LOCAL_MACHINE, str, &hkey ) ) { cb = sizeof( pgv->joyHWCurr ); if( !RegQueryValueEx( hkey, jcfg, NULL, ®type, (CONST LPBYTE)&config, &cb) ) { if( regtype == REG_BINARY && cb == sizeof( config ) ) { pgv->joyHWCurr.hws = config.hws; pgv->joyHWCurr.hwv = config.hwv; pgv->joyHWCurr.dwUsageSettings = config.dwUsageSettings; } } RegCloseKey( hkey ); }
// set up the rudder bit
if( pgv->joyHWCurr.dwUsageSettings & JOY_US_HASRUDDER ) { CheckDlgButton( hwnd, IDC_JOY1HASRUDDER, TRUE ); } else { if( IsDlgButtonChecked( hwnd, IDC_JOY1HASRUDDER ) ) { pgv->joyHWCurr.dwUsageSettings |= JOY_US_HASRUDDER; } else { pgv->joyHWCurr.dwUsageSettings &= ~JOY_US_HASRUDDER; } } }
// disable test/calibrate buttons based on hardware picked
enableTestCal( hwnd, hw_type );
// if custom selected, go get the data from the user
if( hw_type == JOY_HW_CUSTOM ) { //ISSUE-2001/03/29-timgill Old code issue
//HINSTANCE hInst = (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE);
HINSTANCE hInst = (HINSTANCE)GetResourceInstance(); assert(hInst); rc = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_JOYCUSTOM), hwnd, (int (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long))CustomProc, (LONG) pgv ); if( rc ) { LPCUSTVARS pcv;
pcv = (LPCUSTVARS) rc; pgv->joyHWCurr.dwUsageSettings |= JOY_US_PRESENT; pgv->joyHWCurr.hws.dwFlags &= ~(JOY_HWS_HASR|JOY_HWS_HASZ| JOY_HWS_HASPOV|JOY_HWS_ISYOKE| JOY_HWS_ISGAMEPAD| JOY_HWS_ISCARCTRL| JOY_HWS_POVISPOLL| JOY_HWS_POVISBUTTONCOMBOS ); /*
* NOTE: for a custom joystick, we always assume that Z is * implemented on J2 Y. */ if( pcv->bHasZ ) pgv->joyHWCurr.hws.dwFlags |= JOY_HWS_HASZ; /*
* NOTE: for a custom joystick, we always assume that R is * implemented on J2 X. */ if( pcv->bHasR ) pgv->joyHWCurr.hws.dwFlags |= JOY_HWS_HASR;
if( pcv->bHasPOV ) pgv->joyHWCurr.hws.dwFlags |= JOY_HWS_HASPOV;
if( pcv->bIsYoke ) pgv->joyHWCurr.hws.dwFlags |= JOY_HWS_ISYOKE;
if( pcv->bIsGamePad ) { pgv->joyHWCurr.hws.dwFlags |= JOY_HWS_ISGAMEPAD; } if( pcv->bIsCarCtrl ) { pgv->joyHWCurr.hws.dwFlags |= JOY_HWS_ISCARCTRL; } if( pcv->bHas2Buttons ) { pgv->joyHWCurr.hws.dwNumButtons = 2; } else { pgv->joyHWCurr.hws.dwNumButtons = 4; } DoFree( pcv ); same = FALSE; } }
/*
* update the registry with the new current joystick */ if( !same ) { RegSaveCurrentJoyHW( pgv ); RegistryUpdated( pgv ); PropSheet_Changed( GetParent(hwnd), hwnd ); pgv->joyActiveFlags = (unsigned) -1; enableActiveJoystick( pgv, hwnd ); }
} /* getNewJoyInfo */ #endif //DEAD_CODE
// initCurrentHW - set up the current hardware for the first time
static void initCurrentHW( LPGLOBALVARS pgv ) { assert(pgv);
regGetCurrHW( pgv ); pgv->joyActiveFlags = (unsigned) -1; saveHWSettings( pgv );
} /* initCurrentHW */
// newJoyId - set up for a new joystick id
static LPGLOBALVARS newJoyId( LPGLOBALVARS pgv, HWND hwnd, int joyid ) {
assert(pgv); assert(hwnd);
// if( joyid == pgv->iJoyId )
// return pgv;
#if !defined( WANT_SHEETS )
pgv = &pgv->pjd->pgvlist[ joyid ]; #endif
pgv->iJoyId = joyid;
/*
* save the pointer to the variables */ SetWindowLong( hwnd, DWL_USER, (LONG) pgv );
#if defined( WANT_SHEETS )
/*
* set up current joystick hardware */ initCurrentHW( pgv ); #endif
// set up windows
pgv->joyActiveFlags = (unsigned) -1; enableActiveJoystick( pgv, hwnd );
CheckDlgButton( hwnd, IDC_JOY1HASRUDDER, ( pgv->joyHWCurr.dwUsageSettings & JOY_US_HASRUDDER ) ? TRUE : FALSE);
// select the current info
// SendDlgItemMessage( hwnd, IDC_JOYSELECT, CB_SETCURSEL, pgv->joyHWCurr.dwType, 0L );
#if !defined( WANT_SHEETS )
// SendDlgItemMessage( hwnd, IDC_JOYCURRENTID, CB_SETCURSEL, pgv->iJoyId, 0L );
#endif
return(pgv);
} /* newJoyId */
/*
* showResetInfo * static void showResetInfo( HWND hwnd, BOOL show ) { ASSERT (::IsWindow(hwnd));
// HWND hCtrl = GetDlgItem( hwnd, IDC_JOYTROUBLESHOOT_FRAME );
// ASSERT (::IsWindow(hCtrl));
// EnableWindow( hCtrl, show );
// hCtrl = GetDlgItem( hwnd, IDC_JOYTROUBLESHOOT_TEXT );
// ASSERT (::IsWindow(hCtrl));
// EnableWindow( hCtrl, show );
// hCtrl = GetDlgItem( hwnd, IDC_JOYRESET );
// ASSERT (::IsWindow(hCtrl));
// EnableWindow( hCtrl, show );
} * showResetInfo */
// doJoyDlgInitDialog - process initialization for joystick tabbed dialog
static BOOL doJoyDlgInitDialog( HWND hwnd, LPARAM lParam ) { assert(IsWindow(hwnd));
HINSTANCE hinst = GetWindowInstance( hwnd ); HINSTANCE hResInst = GetResourceInstance(); LPPROPSHEETPAGE ppsp; // int i;
// char str[MAX_STR];
LPGLOBALVARS pgv; LPJOYDATA pjd; LPJOYDATAPTR pjdp;
/*
LRESULT lr; HKEY hKey; ULONG cb; PACKETINFO PacketInfo; //
// set labels
//
// load icon
if (fIsSideWinder) { HANDLE hDevice; DWORD dwVerSize; char sz[256]; char sz2[256]; JOYCAPS jc; // set icon
HICON hIcon =(struct HICON__ *) LoadImage(hResInst,(PSTR)IDI_SIDEWINDER, IMAGE_ICON, 64, 64, 0); ASSERT(hIcon); HWND hCtrl = GetDlgItem(hwnd, IDC_SIDEWINDERICON); ASSERT (::IsWindow(hCtrl)); ShowWindow(hCtrl, SW_SHOW); hCtrl = GetDlgItem(hwnd, IDC_SIDEWINDERICON); ASSERT (::IsWindow(hCtrl)); Static_SetIcon(hCtrl, hIcon); // set title
pszCommonString->LoadString(IDS_PROP_TBAR); lstrcpy(sz, (LPCTSTR)*pszCommonString); SetWindowText(GetParent(hwnd), sz); // product name
SetDialogItemText(hwnd, IDC_TEXT_PRODUCTNAME, IDS_SETTING_PRODUCT_NAME+1); // version
GetSystemDirectory(sz, sizeof(sz)); lstrcat(sz, "\\MSGAME.VXD"); dwVerSize = GetFileVersionInfoSize(sz, &cb); if (dwVerSize) { VS_FIXEDFILEINFO* pVer; UINT cbVer; char* p = (char*)malloc(dwVerSize); GetFileVersionInfo(sz, 0, dwVerSize, (void*)p); VerQueryValue((void*)p, "\\", (void**)&pVer, &cbVer); wsprintf( sz, "%d.%02d.%02d", HIWORD(pVer->dwFileVersionMS), LOWORD(pVer->dwFileVersionMS), LOWORD(pVer->dwFileVersionLS)); SetDlgItemText(hwnd, IDC_TEXT_VERSION, sz); free(p); } // copyright
SetDialogItemText(hwnd, IDC_TEXT_COPYRIGHT, IDS_COPYRIGHT+1); // PID
pszCommonString->LoadString(IDS_SETTING_PRODUCT_NAME+2); lstrcpy(sz2, (LPCTSTR)*pszCommonString); wsprintf(sz, "Software\\Microsoft\\%s\\1.0\\registration", sz2); lr = RegOpenKey(HKEY_LOCAL_MACHINE, sz, &hKey); *sz = 0; cb = sizeof(sz); lr = RegQueryValueEx(hKey, "ProductID", 0, 0, (BYTE*)sz, &cb); RegCloseKey(hKey); SetDlgItemText(hwnd, IDC_TEXT_PID, sz); // diagnostics
joyGetDevCaps(0, &jc, sizeof(jc)); if (!strcmp(jc.szOEMVxD, "MSGAME.VXD")) { hDevice = CreateFile( "\\\\.\\MSGAME.VXD", 0, 0, 0, 0, FILE_FLAG_DELETE_ON_CLOSE, 0); if (hDevice!=INVALID_HANDLE_VALUE) { lr = DeviceIoControl( hDevice, 6, &PacketInfo, sizeof(PACKETINFO), 0, 0, &cb, 0); CloseHandle(hDevice); } wsprintf( sz, "%08x-%08x-%02x", PacketInfo.nFailures, PacketInfo.nAttempts, PacketInfo.iMode); SetDlgItemText(hwnd, IDC_TEXT_DIAGNOSTIC, sz); } SetDlgItemText(hwnd, IDC_TEXT_DIAGNOSTIC, sz); // hide calibration button and rudder options
hCtrl = GetDlgItem(hwnd, IDC_JOYCALIBRATE); ASSERT (::IsWindow(hCtrl)); ShowWindow(hCtrl, 0); hCtrl = GetDlgItem(hwnd, IDC_GROUP_RUDDER); ASSERT (::IsWindow(hCtrl)); ShowWindow(hCtrl, 0); hCtrl = GetDlgItem(hwnd, IDC_TEXT_RUDDERHELP); ASSERT (::IsWindow(hCtrl)); ShowWindow(hCtrl, 0); hCtrl = GetDlgItem(hwnd, IDC_JOY1HASRUDDER); ASSERT (::IsWindow(hCtrl)); ShowWindow(hCtrl, 0); } */
// pointer to data
ppsp = (LPPROPSHEETPAGE) lParam; pjdp = (LPJOYDATAPTR) ppsp->lParam; pjd = pjdp->pjd;
// blj: Fix #8049, Assign the proper ID for the joysick assigned to this property sheet.
pjdp->iJoyId = gnID;
// create global variables. These will be used by all dialogs
#if defined( WANT_SHEETS )
pgv = DoAlloc( sizeof( GLOBALVARS ) ); assert(pgv); if( pgv == NULL ) return(FALSE);
// get joystick id that this sheet is for
pgv->iJoyId = pjdp->iJoyId; pgv->pjd = pjd; DPF( "Tab for joystick %d started\r\n", pgv->iJoyId ); #else
pgv = &pjd->pgvlist[ pjdp->iJoyId ]; #endif
// get device caps
getDevCaps( pgv );
/* these are for the old combo boxes that used to display the controllers... this is no longer needed
// set up pre-defined joystick list
for( i=IDS_JOYHW0; i<IDS_JOYHWLAST; i++ ) { if (LoadString( hResInst , i, str, sizeof( str ))) SendDlgItemMessage( hwnd, IDC_JOYSELECT, CB_ADDSTRING, 0, (LPARAM)(LPSTR) str ); }
// set up OEM joystick list
for( i=0;i<pjd->oemCount;i++ ) SendDlgItemMessage( hwnd, IDC_JOYSELECT, CB_ADDSTRING, 0, (LPARAM)(LPSTR) pjd->oemList[i].ident_string );
// this can all go away!!!
// set up joystick choices list
#if !defined(WANT_SHEETS)
{ int numdevs; char strid[MAX_STR]; if( LoadString( hResInst, IDS_JOY, str, sizeof( str ) ) ) { numdevs = joyGetNumDevs(); for( i=0;i<numdevs;i++ ) { wsprintf( strid, "%s %d", str, i+1 ); SendDlgItemMessage( hwnd, IDC_JOYCURRENTID, CB_ADDSTRING, 0, (LPARAM)(LPSTR) strid ); } } } #endif
*/
// pgv->iJoyId = -1;
newJoyId( pgv, hwnd, pjdp->iJoyId);
// enable/disable our Reset button
// showResetInfo( hwnd, pjd->bHasNonStandardUserVals );
return(TRUE);
} /* doJoyDlgInitDialog */
/*
* doJoyDlgCommand - process WM_COMMAND message for main joystick tabbed dialog */ static void doJoyDlgCommand( HWND hwnd, int id, HWND hctl, UINT code ) { assert(hwnd);
LPGLOBALVARS pgv;
pgv = (LPGLOBALVARS) GetWindowLong( hwnd, DWL_USER ); assert(pgv);
switch( id ) { #ifdef DEAD_CODE
// new joystick has been picked
case IDC_JOYSELECT: if( code == CBN_SELCHANGE ) getNewJoyInfo( pgv, hwnd ); break; #endif // DEAD_CODE
#if !defined( WANT_SHEET )
// new joystick id has been picked
case IDC_JOYCURRENTID: if( code == CBN_SELCHANGE ) { int joyid; joyid = SendDlgItemMessage( hwnd, IDC_JOYCURRENTID, CB_GETCURSEL, 0, 0L ); pgv = newJoyId( pgv, hwnd, joyid ); regSetUserVals( pgv->pjd, TRUE ); RegSaveCurrentJoyHW( pgv ); RegistryUpdated( pgv ); } break; #endif
// calibrate current joystick
case IDC_JOYCALIBRATE: pgv->pjd->bUseTimer = FALSE; DoCalibrate( pgv, hwnd ); pgv->pjd->bUseTimer = TRUE; break;
#ifdef DEAD_CODE
// test either joystick 1 or joystick 2
case IDC_JOYTEST: pgv->pjd->bUseTimer = FALSE; DoTest( pgv, hwnd, NULL, pgv ); pgv->pjd->bUseTimer = TRUE; break; #endif
// reset to user values
case IDC_JOYRESET: pgv->pjd->bResetUserVals = TRUE; PropSheet_Changed( GetParent(hwnd), hwnd ); break;
// rudder selected/unselected
case IDC_JOY1HASRUDDER: { LPJOYREGHWCONFIG pcfg; // rudder status changed, force recalibration (leave POV alone if it was button based)
pcfg = &pgv->joyHWCurr; assert(pcfg);
if( (pcfg->hws.dwFlags & JOY_HWS_HASPOV) && (pcfg->hws.dwFlags & JOY_HWS_POVISBUTTONCOMBOS) ) pcfg->hwv.dwCalFlags &= JOY_ISCAL_POV; else pcfg->hwv.dwCalFlags = 0;
if( IsDlgButtonChecked( hwnd, id ) ) pcfg->dwUsageSettings |= JOY_US_HASRUDDER; else pcfg->dwUsageSettings &= ~JOY_US_HASRUDDER;
pgv->joyActiveFlags = (unsigned) -1; enableActiveJoystick( pgv, hwnd );
// tell vjoyd that the device has changed!
joyConfigChanged(0);
PropSheet_Changed( GetParent(hwnd), hwnd ); break; }
case ID_APPLY: { DPF( "ID_APPLY\r\n" );
#if !defined( WANT_SHEETS )
{ // int i;
// int numjoys;
// numjoys = joyGetNumDevs();
// for( i=0;i<numjoys;i++ )
{ regPermSaveAllInfo( &pgv->pjd->pgvlist[gnID] ); saveHWSettings( &pgv->pjd->pgvlist[gnID] ); } } #else
regPermSaveAllInfo( pgv ); saveHWSettings( pgv ); #endif
if( pgv->pjd->bResetUserVals ) { regUserValsFini( pgv->pjd ); regUserValsInit( pgv->pjd ); pgv->pjd->bResetUserVals = FALSE; } // showResetInfo( hwnd, pgv->pjd->bHasNonStandardUserVals );
// BUG 419 FIX: brute force method
InvalidateRect(GetParent(hwnd), 0, 0); break; }
case ID_INIT: DPF( "ID_INIT\r\n" ); joyConfigChanged(0);
pgv->iJoyId = gnID;
// we've been re-activated, reset the current joystick settings
regSetUserVals( pgv->pjd, TRUE ); RegSaveCurrentJoyHW( pgv ); RegistryUpdated( pgv ); break;
case IDOK: DPF( "IDOK\r\n" );
joyConfigChanged(0);
EndDialog(hwnd, TRUE ); break;
case IDCANCEL: DPF( "IDCANCEL\r\n" ); pgv->pjd->bResetUserVals = FALSE; #if !defined( WANT_SHEETS )
{ // int i;
// int numjoys;
// numjoys = joyGetNumDevs();
// for( i=0;i<numjoys;i++ ) {
restoreHWSettings( &pgv->pjd->pgvlist[gnID] ); // }
} #else
restoreHWSettings( pgv ); #endif
RegistryUpdated( pgv ); EndDialog(hwnd, FALSE ); break;
default: break; }
} /* doJoyDlgCommand */
/*
* JoystickDlg - dialog procedure for joystick tabbed dialog */ BOOL CALLBACK JoystickDlg( HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam) { BOOL rc;
switch( umsg ) { case WM_HELP: OnHelp(lParam); return(1);
case WM_CONTEXTMENU: OnContextMenu(wParam); return(1);
case WM_INITDIALOG: rc = doJoyDlgInitDialog( hwnd, lParam );
if( !rc ) EndDialog( hwnd, 0 ); return(FALSE);
case WM_COMMAND: HANDLE_WM_COMMAND( hwnd, wParam, lParam, doJoyDlgCommand ); break;
case WM_ACTIVATE: // we've been activated, pretend we were re-selected
if( LOWORD( wParam ) != WA_INACTIVE ) FORWARD_WM_COMMAND( hwnd, ID_INIT, 0, 0, SendMessage ); break;
case WM_DESTROY: cleanUpJoyDlg( hwnd ); break;
case WM_NOTIFY: { NMHDR FAR * lpnm = (NMHDR FAR *)lParam; switch( lpnm->code ) { case PSN_KILLACTIVE: FORWARD_WM_COMMAND( hwnd, IDOK, 0, 0, SendMessage ); FORWARD_WM_COMMAND( hwnd, ID_INIT, 0, 0, SendMessage ); // ADDED CML 7/03/96
KillTimer(hwnd, TIMER_ID); return(TRUE);
case PSN_APPLY: FORWARD_WM_COMMAND( hwnd, ID_APPLY, 0, 0, SendMessage ); return(TRUE);
case PSN_SETACTIVE: FORWARD_WM_COMMAND( hwnd, ID_INIT, 0, 0, SendMessage ); // ADDED CML 7/03/96
// PSN_SETACTIVE gets sent for the first page on loading of the sheet,
// even if that page is not displayed
// check to see if we have been loaded
if( !fIsLoaded ) { fIsLoaded=1; break; }
return(TRUE);
case PSN_RESET: FORWARD_WM_COMMAND( hwnd, IDCANCEL, 0, 0, SendMessage ); return(TRUE); } break; } default: break; } return(FALSE);
} /* JoystickDlg */
/***************************************************************************
GLOBAL JOYSTICK DATA FUNCTIONS FOLLOW ***************************************************************************/
// default joysticks
#define TYPE00 0
#define TYPE01 0
#define TYPE02 0
#define TYPE03 0
#define TYPE04 JOY_HWS_ISGAMEPAD
#define TYPE05 JOY_HWS_ISYOKE
#define TYPE06 JOY_HWS_HASZ | JOY_HWS_ISYOKE
#define TYPE07 JOY_HWS_HASZ
#define TYPE08 JOY_HWS_HASZ
#define TYPE09 JOY_HWS_ISGAMEPAD
#define TYPE10 JOY_HWS_ISYOKE
#define TYPE11 JOY_HWS_HASZ | JOY_HWS_ISYOKE
static JOYREGHWCONFIG _joyHWDefaults[] = { { {TYPE00,0},JOY_US_PRESENT,{{0,0,0,0,0,0,0,0,0},{0,0,0,0}},JOY_HW_NONE}, { {TYPE01,2},JOY_US_PRESENT,{{0,0,0,0,0,0,0,0,0},{0,0,0,0}},JOY_HW_CUSTOM}, { {TYPE02,2},JOY_US_PRESENT,{{0,0,0,0,0,0,0,0,0},{0,0,0,0}},JOY_HW_2A_2B_GENERIC}, { {TYPE03,4},JOY_US_PRESENT,{{0,0,0,0,0,0,0,0,0},{0,0,0,0}},JOY_HW_2A_4B_GENERIC}, { {TYPE04,2},JOY_US_PRESENT,{{0,0,0,0,0,0,0,0,0},{0,0,0,0}},JOY_HW_2B_GAMEPAD}, { {TYPE05,2},JOY_US_PRESENT,{{0,0,0,0,0,0,0,0,0},{0,0,0,0}},JOY_HW_2B_FLIGHTYOKE}, { {TYPE06,2},JOY_US_PRESENT,{{0,0,0,0,0,0,0,0,0},{0,0,0,0}},JOY_HW_2B_FLIGHTYOKETHROTTLE}, { {TYPE07,2},JOY_US_PRESENT,{{0,0,0,0,0,0,0,0,0},{0,0,0,0}},JOY_HW_3A_2B_GENERIC}, { {TYPE08,4},JOY_US_PRESENT,{{0,0,0,0,0,0,0,0,0},{0,0,0,0}},JOY_HW_3A_4B_GENERIC}, { {TYPE09,4},JOY_US_PRESENT,{{0,0,0,0,0,0,0,0,0},{0,0,0,0}},JOY_HW_4B_GAMEPAD}, { {TYPE10,4},JOY_US_PRESENT,{{0,0,0,0,0,0,0,0,0},{0,0,0,0}},JOY_HW_4B_FLIGHTYOKE}, { {TYPE11,4},JOY_US_PRESENT,{{0,0,0,0,0,0,0,0,0},{0,0,0,0}},JOY_HW_4B_FLIGHTYOKETHROTTLE}, };
// registry strings for calibration messages
static LPSTR _oemCalRegStrs[] = { REGSTR_VAL_JOYOEMCAL1, REGSTR_VAL_JOYOEMCAL2, REGSTR_VAL_JOYOEMCAL3, REGSTR_VAL_JOYOEMCAL4, REGSTR_VAL_JOYOEMCAL5, REGSTR_VAL_JOYOEMCAL6, REGSTR_VAL_JOYOEMCAL7, REGSTR_VAL_JOYOEMCAL8, REGSTR_VAL_JOYOEMCAL9, REGSTR_VAL_JOYOEMCAL10, REGSTR_VAL_JOYOEMCAL11, REGSTR_VAL_JOYOEMCAL12, };
/*
* base registry keys */ static char szCfgKey[] = REGSTR_PATH_JOYCONFIG "\\"; static char szCurrCfgKey[] = "\\" REGSTR_KEY_JOYCURR; static char szSettingsCfgKey[] = "\\" REGSTR_KEY_JOYSETTINGS;
// freeOEMListItem - free a list of oem data
static void freeOEMListItem( LPJOYDATA pjd, int i ) { int j;
DoFree( pjd->oemList[i].keyname ); DoFree( pjd->oemList[i].ident_string ); DoFree( pjd->oemList[i].vxd_name ); DoFree( pjd->oemList[i].xy_label ); DoFree( pjd->oemList[i].z_label ); DoFree( pjd->oemList[i].r_label ); DoFree( pjd->oemList[i].u_label ); DoFree( pjd->oemList[i].v_label ); DoFree( pjd->oemList[i].pov_label ); DoFree( pjd->oemList[i].testmove_desc ); DoFree( pjd->oemList[i].testbutton_desc ); DoFree( pjd->oemList[i].testmove_cap ); DoFree( pjd->oemList[i].testbutton_cap ); DoFree( pjd->oemList[i].testwin_cap ); DoFree( pjd->oemList[i].cal_cap ); DoFree( pjd->oemList[i].calwin_cap ); for( j=0;j<NUM_CAL_STRS;j++ ) { DoFree( pjd->oemList[i].cal_strs[j] ); }
} /* freeOEMListItem */
/*
* initHWDefaults - initialize the hardware list: use defaults + OEM types * defined in the registry */ static void initHWDefaults( LPJOYDATA pjd ) { assert(pjd);
int list_size; int def_size; DWORD isubkey; DWORD keyidx; HKEY hkey; HKEY hsubkey; char str[MAX_STR]; DWORD clsize; DWORD num_subkeys; DWORD dont_care; DWORD longest_key; FILETIME ftime; LPSTR keyname; JOYREGHWSETTINGS hws; DWORD longest_val; DWORD type; DWORD cb; int i; int j; int ctype; LPSTR tmpstr; int fail;
def_size = sizeof( _joyHWDefaults )/sizeof( _joyHWDefaults[0] ); list_size = def_size; pjd->oemCount = 0; if( !RegOpenKey( HKEY_LOCAL_MACHINE, REGSTR_PATH_JOYOEM, &hkey ) ) { clsize = sizeof( str ); if( !RegQueryInfoKey ( hkey, str, &clsize, NULL, &num_subkeys, &longest_key, &dont_care, &dont_care, &dont_care, &dont_care, // address of buffer for longest value data length
&dont_care, &ftime ) ) { pjd->oemList = (OEMLIST *)DoAlloc( num_subkeys * sizeof( OEMLIST )); if( pjd->oemList != NULL ) { pjd->oemCount = num_subkeys; list_size += num_subkeys; } longest_key++; } }
pjd->joyHWDefaults = (struct joyreghwconfig_tag *) DoAlloc( list_size * sizeof( JOYREGHWCONFIG ) ); if( pjd->joyHWDefaults == NULL ) { pjd->joyHWDefaults = _joyHWDefaults; } else { memcpy( pjd->joyHWDefaults, _joyHWDefaults, def_size * sizeof( JOYREGHWCONFIG ) ); /*
* if we have keys in the registry, go fetch them */ if( list_size > def_size ) { isubkey = 0; keyidx = 0; keyname = (char *) DoAlloc( longest_key ); if( keyname == NULL ) { keyname = str; longest_key = sizeof( str ); } /*
* run through all keys, getting the info on them */ while( !RegEnumKey( hkey, keyidx, keyname, longest_key ) ) { if( !RegOpenKey( hkey, keyname, &hsubkey ) ) { if( !RegQueryInfoKey ( hsubkey, str, &clsize, NULL, &dont_care, &dont_care, &dont_care, &dont_care, &dont_care, &longest_val, &dont_care, &ftime ) ) { pjd->oemList[isubkey].keyname = (char *)DoAlloc( strlen( keyname ) +1 ); tmpstr = (char *) DoAlloc( longest_val+1 ); if( pjd->oemList[isubkey].keyname != NULL && tmpstr != NULL ) { lstrcpy( pjd->oemList[isubkey].keyname, keyname ); cb = sizeof( hws ); if( !RegQueryValueEx( hsubkey, REGSTR_VAL_JOYOEMDATA, NULL, &type, (CONST LPBYTE)&hws, &cb) ) { if( type == REG_BINARY && cb == sizeof( hws ) ) { pjd->oemList[isubkey].hws = hws; } } fail = 0; fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMCALLOUT, tmpstr, longest_val, &pjd->oemList[isubkey].vxd_name ); fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMNAME, tmpstr, longest_val, &pjd->oemList[isubkey].ident_string ); for( j=0;j<NUM_CAL_STRS;j++ ) { fail |= regGetOEMStr( hsubkey, _oemCalRegStrs[j], tmpstr, longest_val, &pjd->oemList[isubkey].cal_strs[j] ); } fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMXYLABEL, tmpstr, longest_val, &pjd->oemList[isubkey].xy_label ); fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMZLABEL, tmpstr, longest_val, &pjd->oemList[isubkey].z_label ); fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMRLABEL, tmpstr, longest_val, &pjd->oemList[isubkey].r_label ); fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMULABEL, tmpstr, longest_val, &pjd->oemList[isubkey].u_label ); fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMVLABEL, tmpstr, longest_val, &pjd->oemList[isubkey].v_label ); fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMPOVLABEL, tmpstr, longest_val, &pjd->oemList[isubkey].pov_label ); fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMTESTMOVEDESC, tmpstr, longest_val, &pjd->oemList[isubkey].testmove_desc ); fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMTESTBUTTONDESC, tmpstr, longest_val, &pjd->oemList[isubkey].testbutton_desc ); fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMTESTMOVECAP, tmpstr, longest_val, &pjd->oemList[isubkey].testmove_cap ); fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMTESTBUTTONCAP, tmpstr, longest_val, &pjd->oemList[isubkey].testbutton_cap ); fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMTESTWINCAP, tmpstr, longest_val, &pjd->oemList[isubkey].testwin_cap ); fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMCALCAP, tmpstr, longest_val, &pjd->oemList[isubkey].cal_cap ); fail |= regGetOEMStr( hsubkey, REGSTR_VAL_JOYOEMCALWINCAP, tmpstr, longest_val, &pjd->oemList[isubkey].calwin_cap ); if( fail ) { freeOEMListItem( pjd, isubkey ); } else { isubkey++; } } else { DoFree( pjd->oemList[isubkey].keyname ); } DoFree( tmpstr ); RegCloseKey( hsubkey ); } } keyidx++; } pjd->oemCount = isubkey;
/*
* sort the list, and then fill in the joyHWDefault array */ if( pjd->oemCount > 0 ) { for( i=0;i<pjd->oemCount;i++ ) { for( j=i;j<pjd->oemCount;j++ ) { OEMLIST ol; if( lstrcmp( pjd->oemList[i].ident_string, pjd->oemList[j].ident_string ) > 0 ) { ol = pjd->oemList[i]; pjd->oemList[i] = pjd->oemList[j]; pjd->oemList[j] = ol; } } } for( i=0;i<pjd->oemCount;i++ ) { ctype = i+JOY_HW_LASTENTRY; memset( &pjd->joyHWDefaults[ctype], 0, sizeof( pjd->joyHWDefaults[ctype] ) ); pjd->joyHWDefaults[ctype].hws = pjd->oemList[i].hws; pjd->joyHWDefaults[ctype].dwUsageSettings = JOY_US_ISOEM|JOY_US_PRESENT; pjd->joyHWDefaults[ctype].dwType = ctype; } } if( keyname != str ) { DoFree( keyname ); } } }
} /* initHWDefaults */
/*
* finiHWList - finished with the hardware list, free it */ static void finiHWList( LPJOYDATA pjd ) { int i;
assert(pjd);
if( pjd->joyHWDefaults != NULL ) { if( pjd->joyHWDefaults != _joyHWDefaults ) { DoFree( pjd->joyHWDefaults ); } pjd->joyHWDefaults = NULL; } if( pjd->oemList != NULL ) { for( i=0;i<pjd->oemCount;i++ ) { freeOEMListItem( pjd, i ); } DoFree( pjd->oemList ); pjd->oemList = NULL; pjd->oemCount = 0; }
} /* finiHWList */
/*
* getRegKeys - get the registry keys we need */ static void getRegKeys( LPJOYDATA pjd ) { JOYCAPS jc; int len;
assert(pjd);
/*
* call with magic ID of -1, which retrieves base info without * checking for anything joystick specific */ joyGetDevCaps( (UINT) -1, &jc, sizeof( jc ) );
// set up registry keys
pjd->regCfgKey = NULL; pjd->regCurrCfgKey = NULL; pjd->regSettingsCfgKey = NULL;
len = sizeof( szCfgKey ) + strlen( jc.szRegKey ); pjd->regCfgKey = (char *) DoAlloc( len ); if( pjd->regCfgKey != NULL ) { lstrcpy( pjd->regCfgKey, szCfgKey ); lstrcpy( &pjd->regCfgKey[ sizeof( szCfgKey ) - 1], jc.szRegKey ); pjd->regCurrCfgKey = (char *)DoAlloc( len + sizeof( szCurrCfgKey ) - 1 ); if( pjd->regCurrCfgKey != NULL ) { lstrcpy( pjd->regCurrCfgKey, pjd->regCfgKey ); lstrcpy( &pjd->regCurrCfgKey[ len-1 ], szCurrCfgKey ); } pjd->regSettingsCfgKey = (char *)DoAlloc( len + sizeof( szSettingsCfgKey ) - 1 ); if( pjd->regSettingsCfgKey != NULL ) { lstrcpy( pjd->regSettingsCfgKey, pjd->regCfgKey ); lstrcpy( &pjd->regSettingsCfgKey[ len-1 ], szSettingsCfgKey ); } }
} /* getRegKeys */
/*
* JoystickDataInit */ LPJOYDATA JoystickDataInit( void ) { LPJOYDATA pjd;
pjd = (JOYDATA *) DoAlloc( sizeof( JOYDATA ) ); assert(pjd); if( pjd == NULL ) return(NULL);
// go set up all our defaults + oem lists
initHWDefaults( pjd );
// get registry keys used by everyone
getRegKeys( pjd );
// brushes for use by button display and bar display (z & r info)
pjd->hbUp = CreateSolidBrush( ACTIVE_COLOR ); pjd->hbDown = CreateSolidBrush( INACTIVE_COLOR );
// set up user values we like
regUserValsInit( pjd );
#if !defined( WANT_SHEETS )
{ // set up array of "global" vars (global to a joystick id)
int numjoys; int i;
numjoys = joyGetNumDevs(); if( numjoys == 0 ) { // blj: I'd love to have called JoyError Here, but we don't have a
// valid window handle to pass it!
char szTitle[STR_LEN_32]; char szMessage[STR_LEN_128];
if( LoadString(GetResourceInstance(), IDS_JOYREADERROR, szTitle, sizeof(szTitle)) == 0 ) { OutputDebugString (TEXT("GCDEF.DLL: Unable to load string IDS_JOYREADERROR!\n")); return(NULL); }
if( LoadString(GetResourceInstance(), IDS_JOYUNPLUGGED, szMessage, sizeof(szMessage)) == 0 ) { OutputDebugString (TEXT("GCDEF.DLL: Unable to load string IDS_JOYUNPLUGGED!\n")); return(NULL); }
MessageBox( NULL, szMessage, szTitle, MB_OK | MB_ICONERROR | MB_TASKMODAL );
return(NULL); }
pjd->pgvlist = (_GLOBALVARS *)DoAlloc( sizeof( GLOBALVARS ) * numjoys ); if( pjd->pgvlist == NULL ) return(NULL);
for( i=0;i<numjoys;i++ ) { pjd->pgvlist[i].iJoyId = i; pjd->pgvlist[i].pjd = pjd; initCurrentHW( &pjd->pgvlist[i] ); }
} #endif
return(pjd);
} /* JoystickDataInit */
/*
* JoystickDataFini - finished with DLL wide joystick data data */ void JoystickDataFini( LPJOYDATA pjd ) { assert(pjd);
// ditch brushes
if( pjd->hbUp != NULL ) DeleteObject( pjd->hbUp );
if( pjd->hbDown != NULL ) DeleteObject( pjd->hbDown );
// done with hardware list
finiHWList( pjd );
// restore user values in registry
regUserValsFini( pjd );
// done with registry keys
DoFree( pjd->regCfgKey ); DoFree( pjd->regCurrCfgKey ); DoFree( pjd->regSettingsCfgKey );
#if !defined( WANT_SHEETS )
DoFree( pjd->pgvlist ); #endif
// free up the joystick data
DoFree( pjd ); #ifdef DEBUG
if( allocCount != 0 ) MBOX( "Memory left unfreed: %d allocations", allocCount ); #endif
} /* JoystickDataFini */
////////////////////////////////////////////////////////////////////////////////////////
// OnContextMenu(WPARAM wParam)
////////////////////////////////////////////////////////////////////////////////////////
void OnContextMenu(WPARAM wParam) { short nSize = STR_LEN_32;
// point to help file
char *pszHelpFileName = new char[nSize]; ASSERT (pszHelpFileName);
// returns help file name and size of string
GetHelpFileName(pszHelpFileName, &nSize);
WinHelp((HWND)wParam, pszHelpFileName, HELP_CONTEXTMENU, (DWORD)gaHelpIDs);
if( pszHelpFileName ) delete[] (pszHelpFileName); }
///////////////////////////////////////////////////////////////////////////////
// FUNCTION: GetHelpFileName(LPSTR lpszHelpFileName)
//
// PURPOSE: Populates lpszHelpFileName with the Help File Name from the registry
//
// RETURN: ERROR_SUCCESS if successfull, -1 otherwise
///////////////////////////////////////////////////////////////////////////////
LRESULT GetHelpFileName(LPSTR lpszHelpFileName, short* nSize) { if( LoadString(GetResourceInstance(), IDS_HELPFILENAME, lpszHelpFileName, *nSize) ) return(S_OK); else return(E_FAIL); }
void OnHelp(LPARAM lParam) { ASSERT ( lParam );
short nSize = STR_LEN_32;
// point to help file
char *pszHelpFileName = new char[nSize]; ASSERT (pszHelpFileName);
// returns help file name and size of string
GetHelpFileName(pszHelpFileName, &nSize);
LPHELPINFO lphi = (LPHELPINFO)lParam; if( lphi->iContextType==HELPINFO_WINDOW ) WinHelp((HWND)lphi->hItemHandle, pszHelpFileName, HELP_WM_HELP, (DWORD)gaHelpIDs);
if( pszHelpFileName ) delete[] (pszHelpFileName); }
|