+/*
+ * Types need to be defined for callbacks. It's not ideal, but it works for this.
+ */
+#define IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,b) \
+static void fgh##a##FuncCallback( FGCBUserData userData ) \
+{ \
+ FGCB##b callback = (FGCB##b)userData; \
+ callback(); \
+}
+#define IMPLEMENT_CALLBACK_FUNC_CB_ARG1(a,b) \
+static void fgh##a##FuncCallback( int arg1val, FGCBUserData userData ) \
+{ \
+ FGCB##b callback = (FGCB##b)userData; \
+ callback( arg1val ); \
+}
+#define IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,b) \
+static void fgh##a##FuncCallback( int arg1val, int arg2val, FGCBUserData userData ) \
+{ \
+ FGCB##b callback = (FGCB##b)userData; \
+ callback( arg1val, arg2val ); \
+}
+#define IMPLEMENT_CALLBACK_FUNC_CB_ARG3_USER(a,b,arg1,arg2,arg3) \
+static void fgh##a##FuncCallback( arg1 arg1val, arg2 arg2val, arg3 arg3val, FGCBUserData userData ) \
+{ \
+ FGCB##b callback = (FGCB##b)userData; \
+ callback( arg1val, arg2val, arg3val ); \
+}
+#define IMPLEMENT_CALLBACK_FUNC_CB_ARG3(a,b) IMPLEMENT_CALLBACK_FUNC_CB_ARG3_USER(a,b,int,int,int)
+#define IMPLEMENT_CALLBACK_FUNC_CB_ARG4(a,b) \
+static void fgh##a##FuncCallback( int arg1val, int arg2val, int arg3val, int arg4val, FGCBUserData userData ) \
+{ \
+ FGCB##b callback = (FGCB##b)userData; \
+ callback( arg1val, arg2val, arg3val, arg4val ); \
+}
+#define IMPLEMENT_CALLBACK_FUNC_CB_ARG5(a,b) \
+static void fgh##a##FuncCallback( int arg1val, int arg2val, int arg3val, int arg4val, int arg5val, FGCBUserData userData ) \
+{ \
+ FGCB##b callback = (FGCB##b)userData; \
+ callback( arg1val, arg2val, arg3val, arg4val, arg5val ); \
+}
+/*
+ * And almost every time the callback setter function can be implemented like this:
+ */
+#define IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,b) \
+void FGAPIENTRY glut##a##FuncUcall( FGCB##b##UC callback, FGCBUserData userData ) \
+{ \
+ FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glut"#a"FuncUcall" ); \
+ SET_CALLBACK( b ); \
+} \
+void FGAPIENTRY glut##a##Func( FGCB##b callback ) \
+{ \
+ FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glut"#a"Func" ); \
+ if( callback ) \
+ glut##a##FuncUcall( fgh##a##FuncCallback, (FGCBUserData)callback ); \
+ else \
+ glut##a##FuncUcall( NULL, NULL ); \
+}
+/*
+ * Combine _glut and _cb macros:
+ */
+#define IMPLEMENT_CALLBACK_FUNC_ARG0(a) \
+ IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,a) \
+ IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,a)
+
+#define IMPLEMENT_CALLBACK_FUNC_ARG0_2NAME(a,b) \
+ IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,b) \
+ IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,b)
+
+#define IMPLEMENT_CALLBACK_FUNC_ARG1(a) \
+ IMPLEMENT_CALLBACK_FUNC_CB_ARG1(a,a) \
+ IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,a)
+
+#define IMPLEMENT_CALLBACK_FUNC_ARG2(a) \
+ IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,a) \
+ IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,a)
+
+#define IMPLEMENT_CALLBACK_FUNC_ARG2_2NAME(a,b) \
+ IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,b) \
+ IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,b)
+
+#define IMPLEMENT_CALLBACK_FUNC_ARG3(a) \
+ IMPLEMENT_CALLBACK_FUNC_CB_ARG3(a,a) \
+ IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,a)
+
+#define IMPLEMENT_CALLBACK_FUNC_ARG3_USER(a,arg1,arg2,arg3) \
+ IMPLEMENT_CALLBACK_FUNC_CB_ARG3_USER(a,a,arg1,arg2,arg3)\
+ IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,a)
+
+#define IMPLEMENT_CALLBACK_FUNC_ARG4(a) \
+ IMPLEMENT_CALLBACK_FUNC_CB_ARG4(a,a) \
+ IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,a)
+
+#define IMPLEMENT_CALLBACK_FUNC_ARG5(a) \
+ IMPLEMENT_CALLBACK_FUNC_CB_ARG5(a,a) \
+ IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,a)
+
+/* Implement all these callback setter functions... */
+IMPLEMENT_CALLBACK_FUNC_ARG2(Position)
+IMPLEMENT_CALLBACK_FUNC_ARG3_USER(Keyboard,unsigned char,int,int)
+IMPLEMENT_CALLBACK_FUNC_ARG3_USER(KeyboardUp,unsigned char,int,int)
+IMPLEMENT_CALLBACK_FUNC_ARG3(Special)
+IMPLEMENT_CALLBACK_FUNC_ARG3(SpecialUp)
+IMPLEMENT_CALLBACK_FUNC_ARG4(Mouse)
+IMPLEMENT_CALLBACK_FUNC_ARG4(MouseWheel)
+IMPLEMENT_CALLBACK_FUNC_ARG2(Motion)
+IMPLEMENT_CALLBACK_FUNC_ARG2_2NAME(PassiveMotion,Passive)
+IMPLEMENT_CALLBACK_FUNC_ARG1(Entry)
+/* glutWMCloseFunc is an alias for glutCloseFunc; both set the window's Destroy callback */
+IMPLEMENT_CALLBACK_FUNC_ARG0_2NAME(Close,Destroy)
+IMPLEMENT_CALLBACK_FUNC_ARG0_2NAME(WMClose,Destroy)
+IMPLEMENT_CALLBACK_FUNC_ARG0(OverlayDisplay)
+IMPLEMENT_CALLBACK_FUNC_ARG1(WindowStatus)
+IMPLEMENT_CALLBACK_FUNC_ARG2(ButtonBox)
+IMPLEMENT_CALLBACK_FUNC_ARG2(Dials)
+IMPLEMENT_CALLBACK_FUNC_ARG2(TabletMotion)
+IMPLEMENT_CALLBACK_FUNC_ARG4(TabletButton)
+IMPLEMENT_CALLBACK_FUNC_ARG2(MultiEntry)
+IMPLEMENT_CALLBACK_FUNC_ARG5(MultiButton)
+IMPLEMENT_CALLBACK_FUNC_ARG3(MultiMotion)
+IMPLEMENT_CALLBACK_FUNC_ARG3(MultiPassive)
+IMPLEMENT_CALLBACK_FUNC_ARG0(InitContext)
+IMPLEMENT_CALLBACK_FUNC_ARG1(AppStatus)