windows-nt/Source/XPSP1/NT/multimedia/directx/gamectrl/gcdef/joycal.cpp
2020-09-26 16:20:57 +08:00

1948 lines
55 KiB
C++

//****************************************************************************
//
// File: joycal.c
// Content: Joystick calibration dialog
// History:
// Date By Reason
// ==== == ======
// 11-dec-94 craige split out of joycpl.c; some tweaks
// 15-dec-94 craige allow N joysticks
// 17-dec-94 craige new UI as requested by ChrisB
// 18-dec-94 craige process UV
// 05-jan-95 craige new centering confirmation messages
// 04-mar-95 craige bug 10761 - separate strings for pluralization
// bug 12036 - now works when "Back" clicked off of
// custom 4-axis with POV hat
//
// Copyright (c) Microsoft Corporation 1994-1995
//
//****************************************************************************
#pragma pack (8)
#include "stdafx.h"
#include "joycpl.h"
#include "resource.h"
#include "pov.h"
#include "assert.h"
#include "baseids.h"
#include "comstr.h"
#undef NewLoadString
#define NewLoadString(a, b, c, d) \
pszCommonString->LoadString(b); \
lstrcpy( c, (LPCTSTR)*pszCommonString )
// Context sensitive help stuff!
static void OnContextMenu(WPARAM wParam);
static void OnHelp (LPARAM);
static const DWORD CalibrateHelpIDs[] =
{
IDC_JOYLIST1, IDC_JOYLIST1,
IDC_JOYLIST2, IDC_JOYLIST2,
IDC_JOYLIST3, IDC_JOYLIST3,
IDC_JOYLIST4, IDC_JOYLIST4,
0, 0
};
/*
* This has the look and feel of a wizard, but isn't This leads to the
* obvious...
*
* Q: Why isn't this a "real" wizard?
*
* A: - it doesn't have multiple pages, it has a single page. the user
* sees different joystick items activate and de-activate on the dialog
* as he/she calibrates each axis. fussing with multiple sheets for each
* axis would be confusing and unnecessary.
*/
/*
* calibration states
*/
// %%% debug %%% alpha days
extern "C"
{
typedef enum
{
JCS_INIT=-1,
JCS_XY_CENTER1,
JCS_XY_MOVE,
JCS_XY_CENTER2,
JCS_Z_MOVE,
JCS_Z_PLACEHOLDER,
JCS_R_MOVE,
JCS_R_PLACEHOLDER,
JCS_U_MOVE,
JCS_U_PLACEHOLDER,
JCS_V_MOVE,
JCS_V_PLACEHOLDER,
JCS_POV_MOVEUP,
JCS_POV_MOVERIGHT,
JCS_POV_MOVEDOWN,
JCS_POV_MOVELEFT,
JCS_FINI
} cal_states;
typedef enum
{
JC_XY=0,
JC_Z,
JC_POV_UP,
JC_POV_RIGHT,
JC_POV_DOWN,
JC_POV_LEFT,
JC_R,
JC_U,
JC_V,
JC_FINI
} cal_wins;
// variables used in calibration
typedef struct
{
LPGLOBALVARS pgv;
cal_states cState;
BOOL bHasTimer;
BOOL bUseTimer;
HINSTANCE hinst;
JOYINFOEX ji;
JOYRANGE jr;
DWORD pov[JOY_POV_NUMDIRS];
int iAxisCount;
BOOL bPOVdone;
} CALVARS, *LPCALVARS;
extern "C" WINMMAPI MMRESULT WINAPI joyConfigChanged(DWORD);
#define JOY_CALIB_FLAGS JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ | \
JOY_RETURNR | JOY_RETURNU | JOY_RETURNV | \
JOY_RETURNBUTTONS | JOY_RETURNRAWDATA
/*
* we use raw data during calibration; RAW_SHIFT allows us to convert to
* a reasonable "real" value
*/
#define RAW_SHIFT 100
} // extern "C"
// setDefaultButton - make a button the default window
static void setDefaultButton( HWND hwnd, HWND hwdb )
{
// Optimized New Method
SendMessage(hwnd, WM_NEXTDLGCTL, (WPARAM)hwdb, (LPARAM)TRUE);
/* Optimized Old Method
DWORD style;
HWND hCtrl;
int idList[] = { IDC_JOYCALDONE, IDC_JOYCALNEXT,
IDC_JOYCALBACK, IDC_JOYPICKPOV };
#define SIZEOF_LIST 4
// turn off the current default push button
for (short i=0; i < SIZEOF_LIST; i++ )
{
hCtrl = GetDlgItem( hwnd, idList[i] );
if (hCtrl)
{
style = GetWindowLong( hCtrl, GWL_STYLE );
if ( style & BS_DEFPUSHBUTTON )
{
style &= ~BS_DEFPUSHBUTTON;
style |= BS_PUSHBUTTON;
SetWindowLong( hCtrl, GWL_STYLE, style );
break;
}
}
}
// make the specified button the default
style = GetWindowLong( hwdb, GWL_STYLE );
style &= ~(BS_PUSHBUTTON|BS_DEFPUSHBUTTON);
style |= BS_DEFPUSHBUTTON;
SetWindowLong( hwdb, GWL_STYLE, style );
*/
} // setDefaultButton
/*
* setLabel
*
* set the label for an axis based on current calibration state
*/
static void setLabel(
LPGLOBALVARS pgv,
HWND hwnd,
UINT id,
LPJOYREGHWCONFIG pcfg,
DWORD bit )
{
char str[MAX_STR];
int type;
HINSTANCE hinst;
HWND hwtext;
hinst = GetResourceInstance( );
assert(hinst);
// get text for this axis label...
if( pcfg->dwUsageSettings & JOY_US_ISOEM )
{
type = pcfg->dwType - JOY_HW_LASTENTRY;
if( type < 0 || type >= pgv->pjd->oemCount )
{
type = -1;
}
} else
{
type = -1;
}
switch( id )
{
case IDC_JOYLIST1_LABEL:
if( (type == -1) || (pgv->pjd->oemList[type].xy_label[0] == 0) )
{
NewLoadString( hinst, IDS_XYAXIS_LABEL, str, sizeof( str ) );
if( !lstrlen(str) ) return;
} else lstrcpy( str, pgv->pjd->oemList[type].xy_label );
break;
case IDC_JOYLIST2_LABEL:
if( (type == -1) || (pgv->pjd->oemList[type].z_label[0] == 0 ) )
{
NewLoadString( hinst, IDS_ZAXIS_LABEL, str, sizeof( str ) );
if( !lstrlen(str) ) return;
} else lstrcpy( str, pgv->pjd->oemList[type].z_label );
break;
case IDC_JOYLIST3_LABEL:
if( (type == -1) || (pgv->pjd->oemList[type].r_label[0] == 0) )
{
NewLoadString( hinst, IDS_RAXIS_LABEL, str, sizeof( str ) );
if( !lstrlen(str) ) return;
} else lstrcpy( str, pgv->pjd->oemList[type].r_label );
break;
case IDC_JOYLIST4_LABEL:
if( (type == -1) || (pgv->pjd->oemList[type].u_label[0] == 0) )
{
NewLoadString( hinst, IDS_UAXIS_LABEL, str, sizeof( str ) );
if( !lstrlen(str) ) return;
} else lstrcpy( str, pgv->pjd->oemList[type].u_label );
break;
case IDC_JOYLIST5_LABEL:
if( (type == -1) || (pgv->pjd->oemList[type].v_label[0] == 0) )
{
NewLoadString( hinst, IDS_VAXIS_LABEL, str, sizeof( str ) );
if( !lstrlen(str) ) return;
} else lstrcpy( str, pgv->pjd->oemList[type].v_label );
break;
case IDC_JOYPOV_LABEL:
if( (type == -1) || (pgv->pjd->oemList[type].pov_label[0] == 0) )
{
NewLoadString( hinst, IDS_POVAXIS_LABEL, str, sizeof( str ) );
if( !lstrlen(str) ) return;
} else lstrcpy( str, pgv->pjd->oemList[type].pov_label );
break;
}
hwtext = GetDlgItem( hwnd, id );
ASSERT (::IsWindow(hwtext));
if( hwtext != NULL )
SetWindowText( hwtext, str );
} /* setLabel */
// enableCalWindows - enable or disable specific calibration windows
static void enableCalWindows(
LPGLOBALVARS pgv,
LPJOYREGHWCONFIG pcfg,
HWND hwnd,
cal_wins id )
{
BOOL on;
HWND hwlb;
HWND hwb;
int iid;
// set up the buttons
hwb = GetDlgItem( hwnd,IDC_JOYCALDONE );
ASSERT (hwb);
if( id == JC_FINI )
{
hwlb = GetDlgItem( hwnd, IDC_JOYCALNEXT );
ASSERT (::IsWindow(hwlb));
ShowWindow(hwlb, SW_HIDE );
EnableWindow( hwb, TRUE );
ShowWindow( hwb, SW_NORMAL );
SetFocus( hwb );
setDefaultButton( hwnd, hwb );
} else
{
hwlb = GetDlgItem( hwnd, IDC_JOYCALNEXT );
ASSERT (::IsWindow(hwlb));
ShowWindow( hwlb, SW_NORMAL );
EnableWindow( hwb, FALSE );
ShowWindow( hwb, SW_HIDE );
}
setLabel( pgv, hwnd, IDC_JOYLIST1_LABEL, pcfg, JOY_ISCAL_XY );
// set up the XY window
on = FALSE;
if( id == JC_XY )
on = TRUE;
hwlb = GetDlgItem( hwnd, IDC_JOYLIST1 );
ASSERT (::IsWindow(hwlb));
if( !on )
InvalidateRect( hwlb, NULL, TRUE );
EnableWindow( hwlb, on );
EnableWindow( GetDlgItem( hwnd, IDC_JOYLIST1_LABEL ), on );
/*
* set up the Z window
*/
on = FALSE;
if( id == JC_Z )
on = TRUE;
hwlb = GetDlgItem( hwnd, IDC_JOYLIST2 );
if( !on )
{
InvalidateRect( hwlb, NULL, TRUE );
}
EnableWindow( hwlb, on );
EnableWindow( GetDlgItem( hwnd, IDC_JOYLIST2_LABEL ), on );
/*
* set up the R window
*/
on = FALSE;
if( id == JC_R )
{
on = TRUE;
}
hwlb = GetDlgItem( hwnd, IDC_JOYLIST3 );
if( !on )
{
InvalidateRect( hwlb, NULL, TRUE );
}
EnableWindow( hwlb, on );
EnableWindow( GetDlgItem( hwnd, IDC_JOYLIST3_LABEL ), on );
/*
* set up the U window
*/
on = FALSE;
if( id == JC_U )
{
on = TRUE;
}
hwlb = GetDlgItem( hwnd, IDC_JOYLIST4 );
if( hwlb != NULL )
{
if( !on )
{
InvalidateRect( hwlb, NULL, TRUE );
}
EnableWindow( hwlb, on );
EnableWindow( GetDlgItem( hwnd, IDC_JOYLIST4_LABEL ), on );
}
/*
* set up the V window
*/
on = FALSE;
if( id == JC_V )
{
on = TRUE;
}
hwlb = GetDlgItem( hwnd, IDC_JOYLIST5 );
if( hwlb != NULL )
{
if( !on )
{
InvalidateRect( hwlb, NULL, TRUE );
}
EnableWindow( hwlb, on );
EnableWindow( GetDlgItem( hwnd, IDC_JOYLIST5_LABEL ), on );
}
/*
* set up the POV icon
*/
on = FALSE;
if( id >= JC_POV_UP && id <= JC_POV_LEFT )
{
on = TRUE;
}
EnableWindow( GetDlgItem( hwnd, IDC_JOYPOV_LABEL ), on );
hwb = GetDlgItem( hwnd, IDC_JOYPICKPOV );
EnableWindow( hwb, on );
if( on )
{
ShowWindow( hwb, SW_NORMAL );
SetFocus( hwb );
setDefaultButton( hwnd, hwb );
switch( id )
{
case JC_POV_UP:
iid = IDI_JOYPOV_UP;
break;
case JC_POV_RIGHT:
iid = IDI_JOYPOV_RIGHT;
break;
case JC_POV_LEFT:
iid = IDI_JOYPOV_LEFT;
break;
case JC_POV_DOWN:
iid = IDI_JOYPOV_DOWN;
break;
}
} else
{
ShowWindow( hwb, SW_HIDE );
UpdateWindow( hwb );
iid = IDI_JOYPOV_GRAYED;
}
ChangeIcon( hwnd, iid, IDC_JOYPOV );
} /* enableCalWindows */
/*
* getJoyName - get the name of a joystick
*/
static int getJoyName( LPJOYREGHWCONFIG pcfg, BOOL plural )
{
int str2id;
if( pcfg->hws.dwFlags & JOY_HWS_ISYOKE )
{
str2id = ( plural ) ? IDS_JOYCAL_YOKES : IDS_JOYCAL_YOKE;
} else if( pcfg->hws.dwFlags & JOY_HWS_ISCARCTRL )
{
str2id = ( plural ) ? IDS_JOYCAL_CARS : IDS_JOYCAL_CAR;
} else if( pcfg->hws.dwFlags & JOY_HWS_ISGAMEPAD )
{
str2id = ( plural ) ? IDS_JOYCAL_GAMEPADS : IDS_JOYCAL_GAMEPAD;
} else
{
str2id = ( plural ) ? IDS_JOY2S : IDS_JOY2;
}
return(str2id);
} /* getJoyName */
/*
* joyCalStateChange - calibration state change
*/
static BOOL joyCalStateChange( LPCALVARS pcv, HWND hwnd, BOOL back )
{
HINSTANCE hinst;
HWND hwtext;
int strid;
int stridx = 0; // BUG FIX: CML 6/21/96 (FLASH RAID 270)
int str2id;
int str3id;
int str4id;
char str[2*MAX_STR];
char buff[2*MAX_STR];
char str2[64];
char str3[64];
char str4[64];
BOOL done;
LPJOYREGHWCONFIG pcfg;
BOOL rc;
int type;
LPGLOBALVARS pgv;
BOOL isdone;
assert(pcv);
assert(hwnd);
/*
* move to the next state: get the appropriate string
* to display, and enable the correct controls
*/
pgv = pcv->pgv;
assert(pgv);
rc = TRUE;
done = FALSE;
pcfg = &pgv->joyHWCurr;
str2id = -1;
str3id = -1;
str4id = -1;
(pcv->cState) = (cal_states) (pcv->cState + ((cal_states) 1));
EnableWindow( GetDlgItem( hwnd, IDC_JOYCALBACK ), back );
while( !done )
{
done = TRUE;
switch( pcv->cState )
{
case JCS_XY_CENTER1:
/*
* init. range variables
*/
pcv->jr.jpMin.dwX = (DWORD) -1;
pcv->jr.jpMin.dwY = (DWORD) -1;
pcv->jr.jpMin.dwZ = (DWORD) -1;
pcv->jr.jpMin.dwR = (DWORD) -1;
pcv->jr.jpMin.dwU = (DWORD) -1;
pcv->jr.jpMin.dwV = (DWORD) -1;
pcv->jr.jpMax.dwX = 0;
pcv->jr.jpMax.dwY = 0;
pcv->jr.jpMax.dwZ = 0;
pcv->jr.jpMax.dwR = 0;
pcv->jr.jpMax.dwU = 0;
pcv->jr.jpMax.dwV = 0;
// set strings to display
stridx = CALSTR1;
if( pcfg->hws.dwFlags & JOY_HWS_ISYOKE )
{
strid = IDS_JOYCALXY_CENTERYOKE;
} else if( pcfg->hws.dwFlags & JOY_HWS_ISCARCTRL )
{
strid = IDS_JOYCALXY_CENTERCAR;
} else if( pcfg->hws.dwFlags & JOY_HWS_ISGAMEPAD )
{
strid = IDS_JOYCALXY_CENTERGAMEPAD;
} else
{
strid = IDS_JOYCALXY_CENTER;
}
enableCalWindows( pgv, pcfg, hwnd, JC_XY );
break;
case JCS_XY_MOVE:
stridx = CALSTR2;
if( pcfg->hws.dwFlags & JOY_HWS_ISYOKE )
{
strid = IDS_JOYCALXY_MOVEYOKE;
} else if( pcfg->hws.dwFlags & JOY_HWS_ISCARCTRL )
{
strid = IDS_JOYCALXY_MOVECAR;
} else if( pcfg->hws.dwFlags & JOY_HWS_ISGAMEPAD )
{
strid = IDS_JOYCALXY_MOVEGAMEPAD;
} else
{
strid = IDS_JOYCALXY_MOVE;
}
break;
case JCS_XY_CENTER2:
stridx = CALSTR3;
if( pcfg->hws.dwFlags & JOY_HWS_ISYOKE )
{
strid = IDS_JOYCALXY_CENTERYOKE2;
} else if( pcfg->hws.dwFlags & JOY_HWS_ISCARCTRL )
{
strid = IDS_JOYCALXY_CENTERCAR2;
} else if( pcfg->hws.dwFlags & JOY_HWS_ISGAMEPAD )
{
strid = IDS_JOYCALXY_CENTERGAMEPAD2;
} else
{
strid = IDS_JOYCALXY_CENTER2;
}
break;
case JCS_Z_MOVE:
stridx = CALSTR4;
if( !(pcfg->hws.dwFlags & JOY_HWS_HASZ) )
{
pcv->cState = JCS_R_MOVE;
done = FALSE;
} else
{
enableCalWindows( pgv, pcfg, hwnd, JC_Z );
strid = IDS_JOYCALZ_MOVE;
str2id = getJoyName( pcfg, TRUE );
}
break;
case JCS_Z_PLACEHOLDER:
pcv->cState = JCS_R_MOVE;
done = FALSE;
break;
case JCS_R_MOVE:
stridx = CALSTR5;
if( !(pcfg->hws.dwFlags & JOY_HWS_HASR) && !(pcfg->dwUsageSettings & JOY_US_HASRUDDER) )
{
pcv->cState = JCS_U_MOVE;
done = FALSE;
} else
{
enableCalWindows( pgv, pcfg, hwnd, JC_R );
strid = IDS_JOYCALRUDDER_MOVE;
str2id = getJoyName( pcfg, TRUE );
}
break;
case JCS_R_PLACEHOLDER:
pcv->cState = JCS_U_MOVE;
done = FALSE;
break;
case JCS_U_MOVE:
stridx = CALSTR6;
if( !(pcfg->hws.dwFlags & JOY_HWS_HASU) )
{
pcv->cState = JCS_V_MOVE;
done = FALSE;
} else
{
enableCalWindows( pgv, pcfg, hwnd, JC_U );
strid = IDS_JOYCALU_MOVE;
str2id = getJoyName( pcfg, TRUE );
}
break;
case JCS_U_PLACEHOLDER:
pcv->cState = JCS_V_MOVE;
done = FALSE;
break;
case JCS_V_MOVE:
stridx = CALSTR7;
if( !(pcfg->hws.dwFlags & JOY_HWS_HASV) )
{
pcv->cState = JCS_POV_MOVEUP;
done = FALSE;
} else
{
enableCalWindows( pgv, pcfg, hwnd, JC_V );
strid = IDS_JOYCALV_MOVE;
str2id = getJoyName( pcfg, TRUE );
}
break;
case JCS_V_PLACEHOLDER:
pcv->cState = JCS_POV_MOVEUP;
done = FALSE;
break;
case JCS_POV_MOVEUP:
stridx = CALSTR8;
if( !(pcfg->hws.dwFlags & JOY_HWS_HASPOV) )
{
pcv->cState = JCS_FINI;
done = FALSE;
} else
{
enableCalWindows( pgv, pcfg, hwnd, JC_POV_UP );
strid = IDS_JOYCALPOV_MOVE;
str2id = IDS_JOYCAL_UP;
str3id = getJoyName( pcfg, TRUE );
str4id = IDS_JOYCAL_UP;
}
break;
case JCS_POV_MOVERIGHT:
stridx = CALSTR9;
enableCalWindows( pgv, pcfg, hwnd, JC_POV_RIGHT );
strid = IDS_JOYCALPOV_MOVE;
str2id = IDS_JOYCAL_RIGHT;
str3id = getJoyName( pcfg, TRUE );
str4id = IDS_JOYCAL_RIGHT;
break;
case JCS_POV_MOVEDOWN:
stridx = CALSTR10;
enableCalWindows( pgv, pcfg, hwnd, JC_POV_DOWN );
strid = IDS_JOYCALPOV_MOVE;
str2id = IDS_JOYCAL_DOWN;
str3id = getJoyName( pcfg, TRUE );
str4id = IDS_JOYCAL_DOWN;
break;
case JCS_POV_MOVELEFT:
stridx = CALSTR11;
enableCalWindows( pgv, pcfg, hwnd, JC_POV_LEFT );
strid = IDS_JOYCALPOV_MOVE;
str2id = IDS_JOYCAL_LEFT;
str3id = getJoyName( pcfg, TRUE );
str4id = IDS_JOYCAL_LEFT;
break;
case JCS_FINI:
/*
* see if everything that needs to be calibrated
* was actually calibrated
*/
if( !(pcfg->hwv.dwCalFlags & JOY_ISCAL_XY) )
{
isdone = FALSE;
} else if( (pcfg->hws.dwFlags & JOY_HWS_HASZ) &&
!(pcfg->hwv.dwCalFlags & JOY_ISCAL_Z) )
{
isdone = FALSE;
} else if( ((pcfg->hws.dwFlags & JOY_HWS_HASR) ||
(pcfg->dwUsageSettings & JOY_US_HASRUDDER)) &&
!(pcfg->hwv.dwCalFlags & JOY_ISCAL_R) )
{
isdone = FALSE;
} else if( (pcfg->hws.dwFlags & JOY_HWS_HASPOV) &&
!(pcfg->hwv.dwCalFlags & JOY_ISCAL_POV) )
{
isdone = FALSE;
} else if( (pcfg->hws.dwFlags & JOY_HWS_HASU) &&
!(pcfg->hwv.dwCalFlags & JOY_ISCAL_U) )
{
isdone = FALSE;
} else if( (pcfg->hws.dwFlags & JOY_HWS_HASV) &&
!(pcfg->hwv.dwCalFlags & JOY_ISCAL_V) )
{
isdone = FALSE;
} else
{
isdone = TRUE;
}
strid = ( isdone ) ? IDS_JOYCAL_DONE : IDS_JOYCAL_NOTDONE;
str2id = getJoyName( pcfg, FALSE );
str3id = getJoyName( pcfg, TRUE );
stridx = CALSTR12;
enableCalWindows( pgv, pcfg, hwnd, JC_FINI );
rc = FALSE;
break;
} // END OF SWITCH
} // END OF WHILE
// see if there is any OEM text specified
hinst = GetResourceInstance( );
assert(hinst);
hwtext = GetDlgItem( hwnd, IDC_JOYCALMSG );
if( pcfg->dwUsageSettings & JOY_US_ISOEM )
{
LPJOYDATA pjd;
pjd = pgv->pjd;
assert(pjd);
type = pcfg->dwType - JOY_HW_LASTENTRY;
if( pjd->oemList[type].cal_strs[ stridx ][0] != 0 )
{
SetWindowText( hwtext, pjd->oemList[type].cal_strs[ stridx] );
return(rc);
}
}
// no OEM text, use the defaults
LoadString( hinst, strid, str, sizeof(str));
if( lstrlen(str) )
{
if( str2id != -1 )
{
NewLoadString( hinst, str2id, str2, sizeof( str2 ) );
if( str2 )
{
if( str3id != -1 )
{
NewLoadString( hinst, str3id, str3, sizeof( str3 ) );
if( lstrlen(str3) )
{
if( str4id != -1 )
{
NewLoadString( hinst, str4id, str4, sizeof( str4 ) );
if( lstrlen(str4) )
{
// wsprintf( buff, str, str2, str3, str4 );
assert(str2);
assert(str3);
assert(str4);
LPSTR lpargs[] = {str2, str3, str4};
FormatMessage(FORMAT_MESSAGE_FROM_STRING |
FORMAT_MESSAGE_ARGUMENT_ARRAY,
(LPSTR) str,
0, 0,
buff,
sizeof(buff),
lpargs);
SetWindowText( hwtext, buff );
}
} else
{
wsprintf( buff, str, str2, str3 );
SetWindowText( hwtext, buff );
}
}
} else
{
wsprintf( buff, str, str2, str2 );
SetWindowText( hwtext, buff );
}
}
} else
{
SetWindowText( hwtext, str );
}
}
return(rc);
} /* joyCalStateChange */
/*
* joyCalStateSkip - skip the current state, move to the next one
*/
static void joyCalStateSkip( LPCALVARS pcv, HWND hwnd )
{
assert(pcv);
assert(hwnd);
#if 0
/*
* if we're calibrating XY, skip to Z
*/
if( pcv->cState <= JCS_XY_CENTER2 )
{
pcv->cState = JCS_XY_CENTER2;
/*
* if we're calibrating Z, skip to R
*/
} else if( pcv->cState < JCS_Z_PLACEHOLDER )
{
pcv->cState = JCS_Z_PLACEHOLDER;
/*
* if we're calibrating R, skip to U
*/
} else if( pcv->cState < JCS_R_PLACEHOLDER )
{
pcv->cState = JCS_R_PLACEHOLDER;
/*
* if we're calibrating U, skip to V
*/
} else if( pcv->cState < JCS_U_PLACEHOLDER )
{
pcv->cState = JCS_U_PLACEHOLDER;
/*
* if we're calibrating V, skip to POV
*/
} else if( pcv->cState < JCS_V_PLACEHOLDER )
{
pcv->cState = JCS_V_PLACEHOLDER;
/*
* we must be calibration POV, skip to the end
*/
} else
{
pcv->cState = JCS_POV_MOVELEFT;
}
#endif
/*
* state changed, reset to the new one
*/
CauseRedraw( &pcv->ji, FALSE );
joyCalStateChange( pcv, hwnd, TRUE );
} /* joyCalStateSkip */
/*
* resetCustomPOVFlags - set POV flags based on original values for custom joystick
*/
static void resetCustomPOVFlags( LPGLOBALVARS pgv, LPJOYREGHWCONFIG pcfg )
{
assert(pgv);
assert(pcfg);
if( pcfg->dwType == JOY_HW_CUSTOM )
{
pcfg->hws.dwFlags &= ~(JOY_HWS_POVISPOLL|JOY_HWS_POVISBUTTONCOMBOS);
if( pgv->bOrigPOVIsPoll )
pcfg->hws.dwFlags |= JOY_HWS_POVISPOLL;
if( pgv->bOrigPOVIsButtonCombos )
pcfg->hws.dwFlags |= JOY_HWS_POVISBUTTONCOMBOS;
}
} /* resetCustomPOVFlags */
/*
* joyCalStateBack - move back to start the previous state
*/
static void joyCalStateBack( LPCALVARS pcv, HWND hwnd )
{
assert(pcv);
assert(hwnd);
BOOL back;
LPJOYREGHWCONFIG pcfg;
LPGLOBALVARS pgv;
pgv = pcv->pgv;
assert(pgv);
back = TRUE;
pcfg = &pgv->joyHWCurr;
assert(pcfg);
/*
* at the end, backup
*/
if( pcv->cState == JCS_FINI )
{
// ADDED BY CML 6/21/96 TO FIX LOST FOCUS BUG (FLASH RAID 167)
SetFocus(GetDlgItem(hwnd, IDC_JOYCALBACK));
// END ADD
/*
* if there is POV, back up to it
*/
if( pcfg->hws.dwFlags & JOY_HWS_HASPOV )
{
pcv->cState = JCS_V_PLACEHOLDER;
resetCustomPOVFlags( pgv, pcfg );
/*
* if there is V, back up to it
*/
} else if( pcfg->hws.dwFlags & JOY_HWS_HASV )
{
pcv->cState = JCS_U_PLACEHOLDER;
/*
* if there is U, back up to it
*/
} else if( pcfg->hws.dwFlags & JOY_HWS_HASU )
{
pcv->cState = JCS_R_PLACEHOLDER;
/*
* if there is R, back up to it
*/
} else if( (pcfg->hws.dwFlags & JOY_HWS_HASR) || (pcfg->dwUsageSettings & JOY_US_HASRUDDER) )
{
pcv->cState = JCS_Z_PLACEHOLDER;
/*
* if there is Z, back up to it
*/
} else if( pcfg->hws.dwFlags & JOY_HWS_HASZ )
{
pcv->cState = JCS_XY_CENTER2;
/*
* no where else to go, back up to XY
*/
} else
{
// ADDED BY CML 6/21/96 TO FIX LOST FOCUS BUG (FLASH RAID 167)
SetFocus(GetDlgItem(hwnd, IDC_JOYCALNEXT));
// END ADD
// pcv->cState = JCS_INIT;
pcv->cState = JCS_XY_MOVE;
// back = FALSE;
}
/*
* doing POV, so restart it
*/
} else if( pcv->cState > JCS_POV_MOVEUP )
{
pcv->cState = JCS_V_PLACEHOLDER;
// pcfg->hws.dwFlags &= ~(JOY_HWS_POVISPOLL|JOY_HWS_POVISBUTTONCOMBOS);
resetCustomPOVFlags( pgv, pcfg );
/*
* just starting POV, back up
*/
} else if( pcv->cState == JCS_POV_MOVEUP )
{
// ADDED BY CML 6/21/96 TO FIX LOST FOCUS BUG (FLASH RAID 167)
SetFocus(GetDlgItem(hwnd, IDC_JOYCALBACK));
// END ADD
/*
* if there is V, back up to it
*/
if( pcfg->hws.dwFlags & JOY_HWS_HASV )
{
pcv->cState = JCS_U_PLACEHOLDER;
/*
* if there is U, back up to it
*/
} else if( pcfg->hws.dwFlags & JOY_HWS_HASU )
{
pcv->cState = JCS_R_PLACEHOLDER;
/*
* if there is R, back up to it
*/
} else if( (pcfg->hws.dwFlags & JOY_HWS_HASR) ||
(pcfg->dwUsageSettings & JOY_US_HASRUDDER) )
{
pcv->cState = JCS_Z_PLACEHOLDER;
/*
* if there is Z, back up to it
*/
} else if( pcfg->hws.dwFlags & JOY_HWS_HASZ )
{
pcv->cState = JCS_XY_CENTER2;
/*
* no where else to go, back up to XY
*/
} else
{
// ADDED BY CML 6/21/96 TO FIX LOST FOCUS BUG (FLASH RAID 167)
SetFocus(GetDlgItem(hwnd, IDC_JOYCALNEXT));
// END ADD
// pcv->cState = JCS_INIT;
pcv->cState = JCS_XY_MOVE;
// back = FALSE;
}
/*
* doing V, backup
*/
} else if( pcv->cState == JCS_V_MOVE )
{
/*
* if there is U, back up to it
*/
if( pcfg->hws.dwFlags & JOY_HWS_HASU )
{
pcv->cState = JCS_R_PLACEHOLDER;
/*
* if there is R, back up to it
*/
} else if( (pcfg->hws.dwFlags & JOY_HWS_HASR) ||
(pcfg->dwUsageSettings & JOY_US_HASRUDDER) )
{
pcv->cState = JCS_Z_PLACEHOLDER;
/*
* if there is Z, back up to it
*/
} else if( pcfg->hws.dwFlags & JOY_HWS_HASZ )
{
pcv->cState = JCS_XY_CENTER2;
/*
* no where else to go, back up to XY
*/
} else
{
// ADDED BY CML 6/21/96 TO FIX LOST FOCUS BUG (FLASH RAID 167)
SetFocus(GetDlgItem(hwnd, IDC_JOYCALNEXT));
// END ADD
// pcv->cState = JCS_INIT;
pcv->cState = JCS_XY_MOVE;
// back = FALSE;
}
/*
* doing U, backup
*/
} else if( pcv->cState == JCS_U_MOVE )
{
/*
* if there is R, back up to it
*/
if( (pcfg->hws.dwFlags & JOY_HWS_HASR) ||
(pcfg->dwUsageSettings & JOY_US_HASRUDDER) )
{
pcv->cState = JCS_Z_PLACEHOLDER;
/*
* if there is Z, back up to it
*/
} else if( pcfg->hws.dwFlags & JOY_HWS_HASZ )
{
pcv->cState = JCS_XY_CENTER2;
/*
* no where else to go, back up to XY
*/
} else
{
// pcv->cState = JCS_INIT;
pcv->cState = JCS_XY_MOVE;
// back = FALSE;
}
/*
* doing R, backup
*/
} else if( pcv->cState == JCS_R_MOVE )
{
/*
* if there is Z, back up to it
*/
if( pcfg->hws.dwFlags & JOY_HWS_HASZ )
{
pcv->cState = JCS_XY_CENTER2;
/*
* no where else to go, back up to XY
*/
} else
{
// ADDED BY CML 6/21/96 TO FIX LOST FOCUS BUG (FLASH RAID 167)
SetFocus(GetDlgItem(hwnd, IDC_JOYCALNEXT));
// END ADD
// pcv->cState = JCS_INIT;
pcv->cState = JCS_XY_MOVE;
// back = FALSE;
}
/*
* if we're doing Z or in the middle of XY, backup to XY
*/
} else if( pcv->cState == JCS_XY_MOVE )
{
SetFocus(GetDlgItem(hwnd, IDC_JOYCALNEXT));
pcv->cState = JCS_INIT;
back = FALSE;
} else
{
// ADDED BY CML 6/21/96 TO FIX LOST FOCUS BUG (FLASH RAID 167)
SetFocus(GetDlgItem(hwnd, IDC_JOYCALNEXT));
// END ADD
pcv->cState = (cal_states)(pcv->cState - 2);
// pcv->cState = JCS_INIT;
// back = FALSE;
}
/*
* state changed, reset to the new one
*/
CauseRedraw( &pcv->ji, FALSE );
joyCalStateChange( pcv, hwnd, back );
} /* joyCalStateBack */
// macro to get new max/min data for an axis
#define NEWMINMAX( a ) \
if( pji->dw##a##pos > pcv->jr.jpMax.dw##a ) { \
pcv->jr.jpMax.dw##a = pji->dw##a##pos; \
} \
if( pji->dw##a##pos < pcv->jr.jpMin.dw##a ) { \
pcv->jr.jpMin.dw##a = pji->dw##a##pos; \
} \
pji->dw##a##pos *= RAW_SHIFT;
// joyCollectCalInfo - record calibration info
static BOOL joyCollectCalInfo( LPCALVARS pcv, HWND hwnd, LPJOYINFOEX pji )
{
assert(pcv);
assert(hwnd);
assert(pji);
LPGLOBALVARS pgv;
LPJOYREGHWCONFIG pcfg;
pgv = pcv->pgv;
assert(pgv);
switch( pcv->cState )
{
// remember XY center
case JCS_XY_CENTER1:
case JCS_XY_CENTER2:
#ifdef _DEBUG
TRACE("%s: %d: dwXpos is %d dwYpos is %d\n", __FILE__, __LINE__, pji->dwXpos, pji->dwYpos);
#endif // _DEBUG
if( !pcv->jr.jpCenter.dwY )
{
pgv->joyRange.jpMax.dwY = pji->dwYpos << 1;
pcv->jr.jpCenter.dwY = pji->dwYpos;
}
if( !pcv->jr.jpCenter.dwX )
{
pgv->joyRange.jpMax.dwX = pji->dwXpos << 1;
pcv->jr.jpCenter.dwX = pji->dwXpos;
}
pgv->joyRange.jpMin.dwX = 0;
pgv->joyRange.jpMin.dwY = 0;
DoJoyMove( pgv, hwnd, pji, &pcv->ji, JOYMOVE_DRAWXY );
break;
// remember max/min XY values
case JCS_XY_MOVE:
if( pji->dwXpos > pcv->jr.jpMax.dwX )
{
pcv->jr.jpMax.dwX = pji->dwXpos;
}
if( pji->dwXpos < pcv->jr.jpMin.dwX )
{
pcv->jr.jpMin.dwX = pji->dwXpos;
}
if( pji->dwYpos > pcv->jr.jpMax.dwY )
{
pcv->jr.jpMax.dwY = pji->dwYpos;
}
if( pji->dwYpos < pcv->jr.jpMin.dwY )
{
pcv->jr.jpMin.dwY = pji->dwYpos;
}
DoJoyMove( pgv, hwnd, pji, &pcv->ji, JOYMOVE_DRAWXY );
break;
// remember max/min Z value
case JCS_Z_MOVE:
NEWMINMAX( Z );
DoJoyMove( pgv, hwnd, pji, &pcv->ji, JOYMOVE_DRAWZ );
break;
// remember max/min R value
case JCS_R_MOVE:
NEWMINMAX( R );
DoJoyMove( pgv, hwnd, pji, &pcv->ji, JOYMOVE_DRAWR );
break;
// remember max/min U value
case JCS_U_MOVE:
NEWMINMAX( U );
DoJoyMove( pgv, hwnd, pji, &pcv->ji, JOYMOVE_DRAWU );
break;
// remember max/min V value
case JCS_V_MOVE:
NEWMINMAX( V );
DoJoyMove( pgv, hwnd, pji, &pcv->ji, JOYMOVE_DRAWV );
break;
}
// if a button was pressed, move to the next state
if( ((pcv->ji.dwButtons & ALL_BUTTONS) != (pji->dwButtons & ALL_BUTTONS)) &&
((pji->dwButtons & JOY_BUTTON1) ||
(pji->dwButtons & JOY_BUTTON2) ||
(pji->dwButtons & JOY_BUTTON3) ||
(pji->dwButtons & JOY_BUTTON4) ||
(pji->dwButtons & JOY_BUTTON5) ||
(pji->dwButtons & JOY_BUTTON6) ||
(pji->dwButtons & JOY_BUTTON7) ||
(pji->dwButtons & JOY_BUTTON8) ||
(pji->dwButtons & JOY_BUTTON9) ||
(pji->dwButtons & JOY_BUTTON10) ||
(pji->dwButtons & JOY_BUTTON11) ||
(pji->dwButtons & JOY_BUTTON12) ||
(pji->dwButtons & JOY_BUTTON13) ||
(pji->dwButtons & JOY_BUTTON14) ||
(pji->dwButtons & JOY_BUTTON15) ||
(pji->dwButtons & JOY_BUTTON16) ||
(pji->dwButtons & JOY_BUTTON17) ||
(pji->dwButtons & JOY_BUTTON18) ||
(pji->dwButtons & JOY_BUTTON19) ||
(pji->dwButtons & JOY_BUTTON20) ||
(pji->dwButtons & JOY_BUTTON21) ||
(pji->dwButtons & JOY_BUTTON22) ||
(pji->dwButtons & JOY_BUTTON23) ||
(pji->dwButtons & JOY_BUTTON24) ||
(pji->dwButtons & JOY_BUTTON25) ||
(pji->dwButtons & JOY_BUTTON26) ||
(pji->dwButtons & JOY_BUTTON27) ||
(pji->dwButtons & JOY_BUTTON28) ||
(pji->dwButtons & JOY_BUTTON29) ||
(pji->dwButtons & JOY_BUTTON30) ||
(pji->dwButtons & JOY_BUTTON31) ||
(pji->dwButtons & JOY_BUTTON32) ) )
{
// check and see if we are leaving one calibration to the next;
// if yes, take time to stop and remember what the user just did
pcfg = &pgv->joyHWCurr;
assert(pcfg);
switch( pcv->cState )
{
case JCS_XY_CENTER1:
pcv->jr.jpCenter.dwX = pji->dwXpos;
pcv->jr.jpCenter.dwY = pji->dwYpos;
DPF( "Center 1: %d,%d\r\n", pji->dwXpos, pji->dwYpos );
break;
case JCS_XY_CENTER2:
DPF( "Center 2: %d,%d\r\n", pji->dwXpos, pji->dwYpos );
pcv->jr.jpCenter.dwX += pji->dwXpos;
pcv->jr.jpCenter.dwY += pji->dwYpos;
pcv->jr.jpCenter.dwX /= 2;
pcv->jr.jpCenter.dwY /= 2;
DPF( "Center Avg: %d,%d\r\n", pcv->jr.jpCenter.dwX, pcv->jr.jpCenter.dwY );
pcfg->hwv.jrvHardware.jpMin.dwX = pcv->jr.jpMin.dwX;
pcfg->hwv.jrvHardware.jpMin.dwY = pcv->jr.jpMin.dwY;
pcfg->hwv.jrvHardware.jpMax.dwX = pcv->jr.jpMax.dwX;
pcfg->hwv.jrvHardware.jpMax.dwY = pcv->jr.jpMax.dwY;
pcfg->hwv.jrvHardware.jpCenter.dwX = pcv->jr.jpCenter.dwX;
pcfg->hwv.jrvHardware.jpCenter.dwY = pcv->jr.jpCenter.dwY;
pcfg->hwv.dwCalFlags |= JOY_ISCAL_XY;
break;
case JCS_Z_MOVE:
pcfg->hwv.jrvHardware.jpMin.dwZ = pcv->jr.jpMin.dwZ;
pcfg->hwv.jrvHardware.jpMax.dwZ = pcv->jr.jpMax.dwZ;
pcfg->hwv.dwCalFlags |= JOY_ISCAL_Z;
break;
case JCS_R_MOVE:
pcfg->hwv.jrvHardware.jpMin.dwR = pcv->jr.jpMin.dwR;
pcfg->hwv.jrvHardware.jpMax.dwR = pcv->jr.jpMax.dwR;
pcfg->hwv.dwCalFlags |= JOY_ISCAL_R;
break;
case JCS_U_MOVE:
pcfg->hwv.jrvHardware.jpMin.dwU = pcv->jr.jpMin.dwU;
pcfg->hwv.jrvHardware.jpMax.dwU = pcv->jr.jpMax.dwU;
pcfg->hwv.dwCalFlags |= JOY_ISCAL_U;
break;
case JCS_V_MOVE:
pcfg->hwv.jrvHardware.jpMin.dwV = pcv->jr.jpMin.dwV;
pcfg->hwv.jrvHardware.jpMax.dwV = pcv->jr.jpMax.dwV;
pcfg->hwv.dwCalFlags |= JOY_ISCAL_V;
break;
}
pcv->ji.dwButtons = pji->dwButtons;
return(joyCalStateChange( pcv, hwnd, TRUE ));
}
pcv->ji.dwButtons = pji->dwButtons;
return(TRUE);
} /* joyCollectCalInfo */
/*
* joyCalibrateInitDialog - init the calibration dialog
*/
static BOOL joyCalibrateInitDialog( HWND hwnd, LPARAM lParam )
{
LPJOYREGHWCONFIG pcfg;
LPCALVARS pcv = NULL;
LPGLOBALVARS pgv = NULL;
ASSERT (::IsWindow(hwnd));
// set up calibration variables
pcv = (CALVARS *) DoAlloc( sizeof( CALVARS ) );
ASSERT(pcv);
if( pcv == NULL ) return(FALSE);
SetWindowLong( hwnd, DWL_USER, (LONG) pcv );
assert(pcv);
pgv = (LPGLOBALVARS) lParam;
assert(pgv);
pcv->pgv = pgv;
//
// set labels
//
LPSTR psz1 = new char[MAX_STR_LEN];
ASSERT (psz1);
LPSTR psz2 = new char[MAX_STR_LEN];
ASSERT (psz2);
if( !LoadString(GetResourceInstance(), IDS_JOYCALCAPN, psz1, MAX_STR_LEN) )
{
TRACE( "%s: %s - LoadString Failure!\n", __FILE__, __LINE__);
}
wsprintf(psz2, psz1, pgv->iJoyId+1);
SetWindowText(hwnd, psz2);
if( psz1 )
delete[] (psz1);
if( psz2 )
delete[] (psz2);
// init state info
pcv->cState = JCS_INIT;
// set dialog text based on OEM strings
SetOEMText( pgv, hwnd, FALSE );
// customize dialog based on Z axis, R axis, and POV hat
pcfg = &pgv->joyHWCurr;
assert(pcfg);
pcv->iAxisCount = 2;
if( pcfg->hws.dwFlags & JOY_HWS_HASZ )
pcv->iAxisCount++;
if( (pcfg->hws.dwFlags & JOY_HWS_HASR) || (pcfg->dwUsageSettings & JOY_US_HASRUDDER) )
pcv->iAxisCount++;
if( (pcfg->hws.dwFlags & JOY_HWS_HASPOV) && (pcfg->hws.dwFlags & JOY_HWS_POVISPOLL) )
pcv->iAxisCount++;
if( pcfg->hws.dwFlags & JOY_HWS_HASU )
pcv->iAxisCount++;
if( pcfg->hws.dwFlags & JOY_HWS_HASV )
pcv->iAxisCount++;
ShowControls( pcfg, hwnd );
HWND hCtrl = GetDlgItem( hwnd, IDC_JOYPOV_LABEL );
ASSERT (::IsWindow(hCtrl));
ShowWindow(hCtrl, pcfg->hws.dwFlags & JOY_HWS_HASPOV ? SW_SHOW : SW_HIDE);
// if all axes are used and we have POV then it MUST be buttons
if( pcfg->hws.dwFlags & JOY_HWS_HASPOV )
{
if( pgv->dwMaxAxes == 4 && pcv->iAxisCount == 4 )
pcfg->hws.dwFlags |= JOY_HWS_POVISBUTTONCOMBOS;
}
// other misc setup
pcv->bPOVdone = FALSE;
pcv->bHasTimer = SetTimer( hwnd, TIMER_ID, JOYPOLLTIME, NULL );
pcv->bUseTimer = TRUE;
if( !pcv->bHasTimer )
{
DPF( "No timer for joystick calibration!\r\n" );
return(FALSE);
}
if( !joyCalStateChange( pcv, hwnd, FALSE ) )
{
DPF( "Could not initialize joystick calibration\r\n" );
return(FALSE);
}
return(TRUE);
} /* joyCalibrateInitDialog */
/*
* setJIFlagsForPOV - get joyinfo flags to allow a raw POV poll
*/
static void setJIFlagsForPOV( LPCALVARS pcv, LPJOYREGHWCONFIG pcfg, DWORD *pflags )
{
/*
* for polled POV, we need to specifiy JOY_CAL_READ(3|4) to make
* the driver give us position values back instead of trying to
* give us a POV value back
*/
// if( pcfg->hws.dwFlags & JOY_HWS_HASPOV )
{
if( pcfg->hws.dwFlags & JOY_HWS_POVISPOLL )
{
switch( pcv->iAxisCount )
{
case 6:
(*pflags) |= JOY_CAL_READ6;
break;
case 5:
(*pflags) |= JOY_CAL_READ5;
break;
case 4:
(*pflags) |= JOY_CAL_READ4;
break;
case 3:
(*pflags) |= JOY_CAL_READ3;
break;
}
// If we don't have a 3rd or 4th axis on this joystick, try reading
// another axis anyway to see if the POV hat is on it
} else if( !(pcfg->hws.dwFlags & (JOY_HWS_POVISPOLL|JOY_HWS_POVISBUTTONCOMBOS)) )
{
switch( pcv->iAxisCount )
{
case 5:
(*pflags) |= JOY_CAL_READ6;
break;
case 4:
(*pflags) |= JOY_CAL_READ5;
break;
case 3:
(*pflags) |= JOY_CAL_READ4;
break;
case 2:
(*pflags) |= JOY_CAL_READ3;
break;
}
}
}
} /* setJIFlagsForPOV */
// tryPOV - try for a POV access
static BOOL tryPOV( LPCALVARS pcv, HWND hwnd )
{
assert(pcv);
assert(hwnd);
int rc;
BOOL ispoll;
BOOL isb;
BOOL nowaypoll;
JOYINFOEX ji;
DWORD val;
LPJOYREGHWCONFIG pcfg;
LPGLOBALVARS pgv;
int i;
pgv = pcv->pgv;
assert(pgv);
// reject call if not in a POV state
if( !(pcv->cState == JCS_POV_MOVEUP || pcv->cState == JCS_POV_MOVEDOWN ||
pcv->cState == JCS_POV_MOVELEFT || pcv->cState == JCS_POV_MOVERIGHT) )
return(FALSE);
// take a snapshot of the current joystick state
pcfg = &pgv->joyHWCurr;
assert(pcfg);
nowaypoll = FALSE;
ji.dwSize = sizeof( ji );
while( 1 )
{
// get joystick info
ji.dwFlags = JOY_CALIB_FLAGS;
// if you have a POV, set the flags for it!
if( pcfg->hws.dwFlags & JOY_HWS_HASPOV )
setJIFlagsForPOV( pcv, pcfg, &ji.dwFlags );
rc = joyGetPosEx( pgv->iJoyId, &ji );
if( rc == JOYERR_NOERROR )
break;
if( !(pcfg->hws.dwFlags & JOY_HWS_POVISPOLL) && (ji.dwFlags & (JOY_CAL_READ3|JOY_CAL_READ4|JOY_CAL_READ5|JOY_CAL_READ6)) )
{
// try again, but don't ask for extra axis
ji.dwFlags &= ~(JOY_CAL_READ6 | JOY_CAL_READ5 | JOY_CAL_READ4 | JOY_CAL_READ3);
rc = joyGetPosEx( pgv->iJoyId, &ji );
if( rc == JOYERR_NOERROR )
{
nowaypoll = TRUE; // pov can't possibly be polled
break;
} else return(JoyError( hwnd )) ? TRUE : FALSE; // have to wait for next "Select POV" to retry
} else return(JoyError( hwnd )) ? TRUE : FALSE; // have to wait for next "Select POV" to retry
}
/*
* here is where we determine if POV is polled or is button combos.
*
* See if we already know the answer (bits in joyHWCurr):
* if yes:
* we're done.
* if no:
* We see if there are currently multiple buttons down.
* if yes:
* POV is assumed to be button combos.
* if no:
* POV is assumed to be done with polling
*/
ispoll = FALSE;
isb = FALSE;
if( pcfg->hws.dwFlags & JOY_HWS_POVISPOLL )
{
ispoll = TRUE;
} else if( pcfg->hws.dwFlags & JOY_HWS_POVISBUTTONCOMBOS )
{
isb = TRUE;
}
if( !isb && !ispoll )
{
// the type is indeterminate, so we identify it
if( nowaypoll ||((ji.dwButtons != 0) &&
(ji.dwButtons != JOY_BUTTON1) &&
(ji.dwButtons != JOY_BUTTON2) &&
(ji.dwButtons != JOY_BUTTON3) &&
(ji.dwButtons != JOY_BUTTON4) &&
(ji.dwButtons != JOY_BUTTON5) &&
(ji.dwButtons != JOY_BUTTON6) &&
(ji.dwButtons != JOY_BUTTON7) &&
(ji.dwButtons != JOY_BUTTON8) &&
(ji.dwButtons != JOY_BUTTON9) &&
(ji.dwButtons != JOY_BUTTON10) &&
(ji.dwButtons != JOY_BUTTON11) &&
(ji.dwButtons != JOY_BUTTON12) &&
(ji.dwButtons != JOY_BUTTON13) &&
(ji.dwButtons != JOY_BUTTON14) &&
(ji.dwButtons != JOY_BUTTON15) &&
(ji.dwButtons != JOY_BUTTON16) &&
(ji.dwButtons != JOY_BUTTON17) &&
(ji.dwButtons != JOY_BUTTON18) &&
(ji.dwButtons != JOY_BUTTON19) &&
(ji.dwButtons != JOY_BUTTON20) &&
(ji.dwButtons != JOY_BUTTON21) &&
(ji.dwButtons != JOY_BUTTON22) &&
(ji.dwButtons != JOY_BUTTON23) &&
(ji.dwButtons != JOY_BUTTON24) &&
(ji.dwButtons != JOY_BUTTON25) &&
(ji.dwButtons != JOY_BUTTON26) &&
(ji.dwButtons != JOY_BUTTON27) &&
(ji.dwButtons != JOY_BUTTON28) &&
(ji.dwButtons != JOY_BUTTON29) &&
(ji.dwButtons != JOY_BUTTON30) &&
(ji.dwButtons != JOY_BUTTON31) &&
(ji.dwButtons != JOY_BUTTON32) ) )
{
isb = TRUE;
pcfg->hws.dwFlags |= JOY_HWS_POVISBUTTONCOMBOS;
} else
{
// we always assume J2 Y for a polling POV if unspecified
ispoll = TRUE;
pcfg->hws.dwFlags |= JOY_HWS_POVISPOLL;
}
// the driver needs to notified that we've made this decision
RegSaveCurrentJoyHW( pgv );
RegistryUpdated( pgv );
}
// record the data value for this POV reading
if( isb )
val = ji.dwButtons;
else
val = (pcfg->hws.dwFlags & JOY_HWS_HASZ) ? ji.dwRpos : ji.dwZpos;
switch( pcv->cState )
{
case JCS_POV_MOVEUP:
pcv->pov[JOY_POVVAL_FORWARD] = val;
break;
case JCS_POV_MOVERIGHT:
pcv->pov[JOY_POVVAL_RIGHT] = val;
break;
case JCS_POV_MOVEDOWN:
pcv->pov[JOY_POVVAL_BACKWARD] = val;
break;
case JCS_POV_MOVELEFT:
pcv->pov[JOY_POVVAL_LEFT] = val;
// since this was the last POV thing to calibrate, we need to save the calibration info
for( i=0;i<JOY_POV_NUMDIRS;i++ )
pcfg->hwv.dwPOVValues[i] = pcv->pov[i];
pcfg->hwv.dwCalFlags |= JOY_ISCAL_POV;
pcv->bPOVdone = TRUE;
break;
}
return(joyCalStateChange( pcv, hwnd, TRUE ));
} /* tryPOV */
#ifdef DEAD_CODE
// FixCustomPOVType - fix custom POV type info if POV wasn't calibrated; called by test dlg to update config
void FixCustomPOVType( LPCALVARS pcv )
{
assert(pcv);
if( !pcv->bPOVdone )
resetCustomPOVFlags( pcv->pgv, &pcv->pgv->joyHWCurr );
} /* FixCustomPOVType */
#endif // DEAD_CODE
// CalibrateProc - calibrate a joystick
BOOL CALLBACK CalibrateProc( HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam)
{
switch( umsg )
{
case WM_CONTEXTMENU:
OnContextMenu(wParam);
return(1);
case WM_HELP:
OnHelp(lParam);
return(1);
case WM_TIMER:
{
LPCALVARS pcv = (LPCALVARS) GetWindowLong( hwnd, DWL_USER );
assert(pcv);
if( pcv->bUseTimer )
{
JOYINFOEX *ji = new JOYINFOEX;
ASSERT (ji);
MMRESULT rc;
LPJOYREGHWCONFIG pcfg;
LPGLOBALVARS pgv;
pgv = pcv->pgv;
assert(pgv);
pcv->bUseTimer = FALSE;
ji->dwSize = sizeof( JOYINFOEX );
while( 1 )
{
// get current joystick info
ji->dwFlags = JOY_CALIB_FLAGS;
pcfg = &pgv->joyHWCurr;
ASSERT(pcfg);
// if there is a POV, set the flags for it!
if( pcfg->hws.dwFlags & JOY_HWS_HASPOV )
setJIFlagsForPOV( pcv, pcfg, &ji->dwFlags );
rc = joyGetPosEx( pgv->iJoyId, ji );
if( rc == JOYERR_NOERROR )
break;
// didn't work, try without extra POV axis
if( !(pcfg->hws.dwFlags & JOY_HWS_POVISPOLL) && (ji->dwFlags & (JOY_CAL_READ3|JOY_CAL_READ4|JOY_CAL_READ5|JOY_CAL_READ6)) )
{
ji->dwFlags &= ~(JOY_CAL_READ6 | JOY_CAL_READ5 | JOY_CAL_READ4 | JOY_CAL_READ3);
rc = joyGetPosEx( pgv->iJoyId, ji );
if( rc == JOYERR_NOERROR )
break;
}
if( !JoyError( hwnd ) )
{
// return now if cancel selected; don't turn back on the timer
PostMessage(hwnd, WM_COMMAND, IDCANCEL, 0); // ADDED CML 7/05/96
return(FALSE);
}
continue;
}
// how could you get here and rc != JOYERR_NOERROR?
if( rc == JOYERR_NOERROR )
joyCollectCalInfo( pcv, hwnd, ji );
if( ji )
delete (ji);
/*
* If we've started POV calibration, we need to look at the
* keyboard and ignore joystick, so don't turn the timer
* back on if we've started the POV calibration
*/
if( pcv->cState < JCS_POV_MOVEUP )
pcv->bUseTimer = TRUE;
}
break;
}
case WM_DESTROY:
{
LPCALVARS pcv = (LPCALVARS) GetWindowLong( hwnd, DWL_USER );
assert(pcv);
DoFree( pcv );
break;
}
case WM_INITDIALOG:
if( !joyCalibrateInitDialog( hwnd, lParam ) )
{
LPCALVARS pcv = (LPCALVARS) GetWindowLong( hwnd, DWL_USER );
assert(pcv);
if( pcv != NULL && pcv->bHasTimer )
{
KillTimer( hwnd, TIMER_ID );
pcv->bHasTimer = FALSE;
}
EndDialog( hwnd, 0 );
}
return(FALSE);
case WM_PAINT:
{
LPCALVARS pcv = (LPCALVARS) GetWindowLong( hwnd, DWL_USER );
assert(pcv);
CauseRedraw( &pcv->ji, FALSE );
return(FALSE);
}
case WM_COMMAND:
{
LPCALVARS pcv = (LPCALVARS) GetWindowLong( hwnd, DWL_USER );
assert(pcv);
int id = GET_WM_COMMAND_ID(wParam, lParam);
switch( id )
{
#ifdef DEAD_CODE
case IDC_JOYTEST:
{
BOOL timeon;
timeon = pcv->bUseTimer;
pcv->bUseTimer = FALSE;
DoTest( pcv->pgv, hwnd, (void (__cdecl *)(void *)) FixCustomPOVType, pcv );
pcv->bUseTimer = timeon;
break;
}
#endif //DEAD_CODE
case IDCANCEL:
// fall through
case IDC_JOYCALDONE:
if( pcv->bHasTimer )
{
KillTimer( hwnd, TIMER_ID );
pcv->bHasTimer = FALSE;
}
// {
// LPJOYREGHWCONFIG pcfg = &pcv->pgv->joyHWCurr;
// assert(pcfg);
// }
EndDialog( hwnd, (id == IDC_JOYCALDONE) );
break;
case IDC_JOYPICKPOV:
if( !tryPOV( pcv, hwnd ) )
{
ASSERT (::IsWindow(hwnd));
HWND hwb = GetDlgItem( hwnd, IDC_JOYPICKPOV );
ASSERT (::IsWindow(hwb));
ShowWindow( hwb, SW_HIDE );
EnableWindow( hwb, FALSE );
}
break;
case IDC_JOYCALNEXT:
pcv->bUseTimer = TRUE;
joyCalStateSkip( pcv, hwnd );
break;
case IDC_JOYCALBACK:
pcv->bUseTimer = TRUE;
joyCalStateBack( pcv, hwnd );
break;
default:
break;
}
break;
}
default:
break;
}
return(FALSE);
} // CalibrateProc
// DoCalibrate - do the calibration dialog
void DoCalibrate( LPGLOBALVARS pgv, HWND hwnd )
{
assert(pgv);
JOYREGHWCONFIG save_joycfg;
int rc;
int id;
// save the current config, and then add the rudder if it is present
save_joycfg = pgv->joyHWCurr;
// if this is a custom joystick, then don't assume anything
// about how the POV is set up
if( pgv->joyHWCurr.dwType == JOY_HW_CUSTOM )
{
pgv->bOrigPOVIsPoll = (pgv->joyHWCurr.hws.dwFlags & JOY_HWS_POVISPOLL);
pgv->bOrigPOVIsButtonCombos = (pgv->joyHWCurr.hws.dwFlags & JOY_HWS_POVISBUTTONCOMBOS);
pgv->joyHWCurr.hws.dwFlags &= ~(JOY_HWS_POVISPOLL|JOY_HWS_POVISBUTTONCOMBOS);
}
// update the registry with our new joystick info
RegSaveCurrentJoyHW( pgv );
RegistryUpdated( pgv );
// Fix for 8738, missing IDD_JOYCALIBRATE1 in resource table!
id = ( pgv->joyHWCurr.hws.dwFlags & (JOY_HWS_HASU|JOY_HWS_HASV)) ? IDD_JOYCALIBRATE1 : IDD_CAL;
rc = DialogBoxParam(GetResourceInstance(), MAKEINTRESOURCE( id ), hwnd,
(int (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long)) CalibrateProc, (LONG) pgv );
// update the registry with the new info or the old info
if( rc )
PropSheet_Changed( GetParent(hwnd), hwnd );
else
pgv->joyHWCurr = save_joycfg;
RegSaveCurrentJoyHW( pgv );
RegistryUpdated( pgv );
} /* DoCalibrate */
////////////////////////////////////////////////////////////////////////////////////////
// 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)CalibrateHelpIDs);
if( pszHelpFileName ) delete[] (pszHelpFileName);
}
////////////////////////////////////////////////////////////////////////////////////////
// OnHelp(LPARAM lParam)
////////////////////////////////////////////////////////////////////////////////////////
void OnHelp(LPARAM 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)CalibrateHelpIDs);
if( pszHelpFileName ) delete[] (pszHelpFileName);
}