Moved as many callback setters as possible to macro function generators
authorRcmaniac25 <rcmaniac25@hotmail.com>
Fri, 30 Jun 2017 23:22:19 +0000 (23:22 +0000)
committerDiederick Niehorster <dcnieho@gmail.com>
Fri, 30 Jun 2017 23:22:19 +0000 (23:22 +0000)
Moved macro function generators to fg_callback_macros.h

git-svn-id: svn+ssh://svn.code.sf.net/p/freeglut/code/trunk/freeglut/freeglut@1820 7f0cb862-5218-0410-a997-914c9d46530a

src/fg_callback_macros.h
src/fg_callbacks.c

index 0c574d7..2aa6ccd 100644 (file)
 #define FREEGLUT_CALLBACK_MACROS_H
 
 /*
+ * ----------------------------------------------------------------------------------------------------------------------
+ * There are two sets of macros here. One is for executing window callbacks, the others are for setting window callbacks.
+ * ----------------------------------------------------------------------------------------------------------------------
+ */
+
+/*
  * Compiler defines:
  * FG_COMPILER_SUPPORTS_GCC_VA_ARGS_HACK: if the compiler supports GCC's variadic macro implementation (AKA, ##__VA_ARGS__)
  * FG_COMPILER_SUPPORTS_VA_ARGS: if the compiler supports variadic macros
 #endif
 
 /*
+ * --------------------------
+ * Executing window callbacks
+ * --------------------------
+ *
  * Info:
  *
  * This took a while to figure out, so be sure try to understand what is happening so that you can ensure that whatever you
 
 #endif
 
+/*
+ * ------------------------
+ * Setting window callbacks
+ * ------------------------
+ *
+ * These originally existed in fg_callbacks.c
+ */
+
+/*
+ * All of the window-specific callbacks setting methods can be generalized to this:
+ */
+#define SET_CURRENT_WINDOW_CALLBACK(a)                                    \
+do                                                                        \
+{                                                                         \
+    if( fgStructure.CurrentWindow == NULL )                               \
+        return;                                                           \
+    SET_WCB( ( *( fgStructure.CurrentWindow ) ), a, callback, userData ); \
+} while( 0 )
+
+/*
+ * 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 with these:
+ */
+#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT_UCALL(a,b)      \
+void FGAPIENTRY glut##a##FuncUcall( FGCB##b##UC callback, FGCBUserData userData ) \
+{                                                                         \
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glut"#a"FuncUcall" );             \
+    SET_CURRENT_WINDOW_CALLBACK( b );                                     \
+}
+#define IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,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 );                                 \
+}
+
+#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,b)            \
+               IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT_UCALL(a,b)      \
+               IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,b)
+
+/*
+ * Combine _glut and _cb macros:
+ */
+#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0(a)                     \
+        IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,a)                               \
+        IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a)
+
+#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0_2NAME(a,b)             \
+        IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,b)                               \
+        IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,b)
+
+#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG0(a)                               \
+               IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,a)                               \
+               IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,a)
+
+#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG0_2NAME(a,b)                       \
+               IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,b)                               \
+               IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,b)
+
+#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG1(a)                     \
+        IMPLEMENT_CALLBACK_FUNC_CB_ARG1(a,a)                               \
+        IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a)
+
+#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG1(a)                               \
+               IMPLEMENT_CALLBACK_FUNC_CB_ARG1(a,a)                               \
+               IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,a)
+
+#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(a)                     \
+        IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,a)                               \
+        IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a)
+
+#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2_2NAME(a,b)             \
+        IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,b)                               \
+        IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,b)
+
+#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG2(a)                               \
+               IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,a)                               \
+               IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,a)
+
+#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG2_2NAME(a,b)                       \
+               IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,b)                               \
+               IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,b)
+
+#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(a)                     \
+        IMPLEMENT_CALLBACK_FUNC_CB_ARG3(a,a)                               \
+        IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a)
+
+#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3_USER(a,arg1,arg2,arg3) \
+        IMPLEMENT_CALLBACK_FUNC_CB_ARG3_USER(a,a,arg1,arg2,arg3)           \
+        IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a)
+
+#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3(a)                               \
+               IMPLEMENT_CALLBACK_FUNC_CB_ARG3(a,a)                               \
+               IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,a)
+
+#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3_2NAME(a,b)                       \
+               IMPLEMENT_CALLBACK_FUNC_CB_ARG3(a,b)                               \
+               IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,b)
+
+#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG4(a)                     \
+        IMPLEMENT_CALLBACK_FUNC_CB_ARG4(a,a)                               \
+        IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a)
+
+#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG5(a)                     \
+        IMPLEMENT_CALLBACK_FUNC_CB_ARG5(a,a)                               \
+        IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a)
+
 #endif /* FREEGLUT_CALLBACK_MACROS_H */
 
 /*** END OF FILE ***/
index 4fc0089..0e656a8 100644 (file)
 
 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
 
-
 /*
  * Global callbacks.
  */
+
 /* Sets the global idle callback */
 void FGAPIENTRY glutIdleFuncUcall( FGCBIdleUC callback, FGCBUserData userData )
 {
@@ -42,20 +42,7 @@ void FGAPIENTRY glutIdleFuncUcall( FGCBIdleUC callback, FGCBUserData userData )
     fgState.IdleCallbackData = userData;
 }
 
-static void fghIdleFuncCallback( FGCBUserData userData )
-{
-    FGCBIdle callback = (FGCBIdle)userData;
-    callback();
-}
-
-void FGAPIENTRY glutIdleFunc( FGCBIdle callback )
-{
-    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIdleFunc" );
-    if( callback )
-        glutIdleFuncUcall( fghIdleFuncCallback, (FGCBUserData)callback );
-    else
-        glutIdleFuncUcall( NULL, NULL );
-}
+IMPLEMENT_GLUT_CALLBACK_FUNC_ARG0(Idle)
 
 /* Creates a timer and sets its callback */
 void FGAPIENTRY glutTimerFuncUcall( unsigned int timeOut, FGCBTimerUC callback, int timerID, FGCBUserData userData )
@@ -90,11 +77,7 @@ void FGAPIENTRY glutTimerFuncUcall( unsigned int timeOut, FGCBTimerUC callback,
     fgListInsert( &fgState.Timers, &node->Node, &timer->Node );
 }
 
-static void fghTimerFuncCallback( int ID, FGCBUserData userData )
-{
-    FGCBTimer callback = (FGCBTimer)userData;
-    callback( ID );
-}
+IMPLEMENT_CALLBACK_FUNC_CB_ARG1(Timer, Timer)
 
 void FGAPIENTRY glutTimerFunc( unsigned int timeOut, FGCBTimer callback, int timerID )
 {
@@ -120,20 +103,7 @@ void FGAPIENTRY glutMenuStatusFuncUcall( FGCBMenuStatusUC callback, FGCBUserData
     fgState.MenuStatusCallbackData = userData;
 }
 
-static void fghMenuStatusFuncCallback( int menuState, int mouseX, int mouseY, FGCBUserData userData )
-{
-    FGCBMenuStatus callback = (FGCBMenuStatus)userData;
-    callback( menuState, mouseX, mouseY );
-}
-
-void FGAPIENTRY glutMenuStatusFunc( FGCBMenuStatus callback )
-{
-    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStatusFunc" );
-    if( callback )
-        glutMenuStatusFuncUcall( fghMenuStatusFuncCallback, (FGCBUserData)callback );
-    else
-        glutMenuStatusFuncUcall( NULL, NULL );
-}
+IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3(MenuStatus)
 
 /*
  * Menu specific callbacks.
@@ -149,154 +119,34 @@ void FGAPIENTRY glutMenuDestroyFuncUcall( FGCBDestroyUC callback, FGCBUserData u
     }
 }
 
-static void fghMenuDestroyFuncCallback( FGCBUserData userData )
-{
-    FGCBDestroy callback = (FGCBDestroy)userData;
-    callback();
-}
-
-void FGAPIENTRY glutMenuDestroyFunc( FGCBDestroy callback )
-{
-    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuDestroyFunc" );
-    if( callback )
-        glutMenuDestroyFuncUcall( fghMenuDestroyFuncCallback, (FGCBUserData)callback );
-    else
-        glutMenuDestroyFuncUcall( NULL, NULL );
-}
-
-
-/*
- * All of the window-specific callbacks setting methods can be generalized to this:
- */
-#define SET_CALLBACK(a)                                         \
-do                                                              \
-{                                                               \
-    if( fgStructure.CurrentWindow == NULL )                     \
-        return;                                                 \
-    SET_WCB( ( *( fgStructure.CurrentWindow ) ), a, callback, userData ); \
-} while( 0 )
-/*
- * 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_GLUT_CALLBACK_FUNC_ARG0_2NAME(MenuDestroy, Destroy)
 
 /* 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)
+IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(Position)
+IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3_USER(Keyboard,unsigned char,int,int)
+IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3_USER(KeyboardUp,unsigned char,int,int)
+IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(Special)
+IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(SpecialUp)
+IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG4(Mouse)
+IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG4(MouseWheel)
+IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(Motion)
+IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2_2NAME(PassiveMotion,Passive)
+IMPLEMENT_CURRENT_WINDOW_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)
+IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0_2NAME(Close,Destroy)
+IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0_2NAME(WMClose,Destroy)
+IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0(OverlayDisplay)
+IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG1(WindowStatus)
+IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(ButtonBox)
+IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(Dials)
+IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(TabletMotion)
+IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG4(TabletButton)
+IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(MultiEntry)
+IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG5(MultiButton)
+IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(MultiMotion)
+IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(MultiPassive)
+IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0(InitContext)
+IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG1(AppStatus)
 
 /*
  * Sets the Display callback for the current window
@@ -307,23 +157,10 @@ void FGAPIENTRY glutDisplayFuncUcall( FGCBDisplayUC callback, FGCBUserData userD
     if( !callback )
         fgError( "Fatal error in program.  NULL display callback not "
                  "permitted in GLUT 3.0+ or freeglut 2.0.1+" );
-    SET_CALLBACK( Display );
-}
-
-static void fghDisplayFuncCallback( FGCBUserData userData )
-{
-    FGCBDisplay callback = (FGCBDisplay)userData;
-    callback();
+    SET_CURRENT_WINDOW_CALLBACK( Display );
 }
 
-void FGAPIENTRY glutDisplayFunc( FGCBDisplay callback )
-{
-    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDisplayFunc" );
-    if( callback )
-        glutDisplayFuncUcall( fghDisplayFuncCallback, (FGCBUserData)callback );
-    else
-        glutDisplayFuncUcall( NULL, NULL );
-}
+IMPLEMENT_GLUT_CALLBACK_FUNC_ARG0(Display)
 
 void fghDefaultReshape( int width, int height, FGCBUserData userData )
 {
@@ -340,23 +177,10 @@ void FGAPIENTRY glutReshapeFuncUcall( FGCBReshapeUC callback, FGCBUserData userD
         userData = NULL;
     }
 
-    SET_CALLBACK( Reshape );
+    SET_CURRENT_WINDOW_CALLBACK( Reshape );
 }
 
-static void fghReshapeFuncCallback( int width, int height, FGCBUserData userData )
-{
-    FGCBReshape callback = (FGCBReshape)userData;
-    callback( width, height );
-}
-
-void FGAPIENTRY glutReshapeFunc( FGCBReshape callback )
-{
-    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeFunc" );
-    if( callback )
-        glutReshapeFuncUcall( fghReshapeFuncCallback, (FGCBUserData)callback );
-    else
-        glutReshapeFuncUcall( NULL, NULL );
-}
+IMPLEMENT_GLUT_CALLBACK_FUNC_ARG2(Reshape)
 
 /*
  * Sets the Visibility callback for the current window.
@@ -381,7 +205,7 @@ static void fghVisibility( int status, FGCBUserData userData )
     freeglut_return_if_fail( fgStructure.CurrentWindow );
 
     /* Translate window status func states to visibility states */
-    if( ( GLUT_HIDDEN == status )  || ( GLUT_FULLY_COVERED == status ) )
+    if( ( status == GLUT_HIDDEN)  || ( status == GLUT_FULLY_COVERED) )
         vis_status = GLUT_NOT_VISIBLE;
     else    /* GLUT_FULLY_RETAINED, GLUT_PARTIALLY_RETAINED */
         vis_status = GLUT_VISIBLE;
@@ -398,7 +222,7 @@ void FGAPIENTRY glutVisibilityFuncUcall( FGCBVisibilityUC callback, FGCBUserData
         userData = NULL;
     }
 
-    SET_CALLBACK( Visibility );
+    SET_CURRENT_WINDOW_CALLBACK( Visibility );
 
     if( callback )
         glutWindowStatusFuncUcall( fghVisibility, NULL );
@@ -406,20 +230,7 @@ void FGAPIENTRY glutVisibilityFuncUcall( FGCBVisibilityUC callback, FGCBUserData
         glutWindowStatusFuncUcall( NULL, NULL );
 }
 
-static void fghVisibilityFuncCallback( int visibility, FGCBUserData userData )
-{
-    FGCBVisibility callback = (FGCBVisibility)userData;
-    callback( visibility );
-}
-
-void FGAPIENTRY glutVisibilityFunc( FGCBVisibility callback )
-{
-    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutVisibilityFunc" );
-    if( callback )
-        glutVisibilityFuncUcall( fghVisibilityFuncCallback, (FGCBUserData)callback );
-    else
-        glutVisibilityFuncUcall( NULL, NULL );
-}
+IMPLEMENT_GLUT_CALLBACK_FUNC_ARG1(Visibility)
 
 /*
  * Sets the joystick callback and polling rate for the current window
@@ -446,7 +257,7 @@ void FGAPIENTRY glutJoystickFuncUcall( FGCBJoystickUC callback, int pollInterval
               ) )
         --fgState.NumActiveJoysticks;
 
-    SET_CALLBACK( Joystick );
+    SET_CURRENT_WINDOW_CALLBACK( Joystick );
     fgStructure.CurrentWindow->State.JoystickPollRate = pollInterval;
 
     /* set last poll time such that joystick will be polled asap */
@@ -480,23 +291,10 @@ void FGAPIENTRY glutSpaceballMotionFuncUcall( FGCBSpaceMotionUC callback, FGCBUs
     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballMotionFuncUcall" );
     fgInitialiseSpaceball();
 
-    SET_CALLBACK( SpaceMotion );
-}
-
-static void fghSpaceballMotionFuncCallback( int x, int y, int z, FGCBUserData userData )
-{
-    FGCBSpaceMotion callback = (FGCBSpaceMotion)userData;
-    callback( x, y, z );
+    SET_CURRENT_WINDOW_CALLBACK( SpaceMotion );
 }
 
-void FGAPIENTRY glutSpaceballMotionFunc( FGCBSpaceMotion callback )
-{
-    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballMotionFunc" );
-    if( callback )
-        glutSpaceballMotionFuncUcall( fghSpaceballMotionFuncCallback, (FGCBUserData)callback );
-    else
-        glutSpaceballMotionFuncUcall( NULL, NULL );
-}
+IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3_2NAME(SpaceballMotion, SpaceMotion)
 
 /*
  * Sets the spaceball rotate callback for the current window
@@ -506,23 +304,10 @@ void FGAPIENTRY glutSpaceballRotateFuncUcall( FGCBSpaceRotationUC callback, FGCB
     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballRotateFuncUcall" );
     fgInitialiseSpaceball();
 
-    SET_CALLBACK( SpaceRotation );
+    SET_CURRENT_WINDOW_CALLBACK( SpaceRotation );
 }
 
-static void fghSpaceballRotateFuncCallback( int x, int y, int z, FGCBUserData userData )
-{
-    FGCBSpaceRotation callback = (FGCBSpaceRotation)userData;
-    callback( x, y, z );
-}
-
-void FGAPIENTRY glutSpaceballRotateFunc( FGCBSpaceRotation callback )
-{
-    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballRotateFunc" );
-    if( callback )
-        glutSpaceballRotateFuncUcall( fghSpaceballRotateFuncCallback, (FGCBUserData)callback );
-    else
-        glutSpaceballRotateFuncUcall( NULL, NULL );
-}
+IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3_2NAME(SpaceballRotate, SpaceRotation)
 
 /*
  * Sets the spaceball button callback for the current window
@@ -532,22 +317,9 @@ void FGAPIENTRY glutSpaceballButtonFuncUcall( FGCBSpaceButtonUC callback, FGCBUs
     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballButtonFuncUcall" );
     fgInitialiseSpaceball();
 
-    SET_CALLBACK( SpaceButton );
+    SET_CURRENT_WINDOW_CALLBACK( SpaceButton );
 }
 
-static void fghSpaceballButtonFuncCallback( int button, int buttonState, FGCBUserData userData )
-{
-    FGCBSpaceButton callback = (FGCBSpaceButton)userData;
-    callback( button, buttonState );
-}
-
-void FGAPIENTRY glutSpaceballButtonFunc( FGCBSpaceButton callback )
-{
-    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballButtonFunc" );
-    if( callback )
-        glutSpaceballButtonFuncUcall( fghSpaceballButtonFuncCallback, (FGCBUserData)callback );
-    else
-        glutSpaceballButtonFuncUcall( NULL, NULL );
-}
+IMPLEMENT_GLUT_CALLBACK_FUNC_ARG2_2NAME(SpaceballButton, SpaceButton)
 
 /*** END OF FILE ***/