+
+/*
+ * SET_WCB() is used as:
+ *
+ * SET_WCB( window, Visibility, func );
+ *
+ * ...where {window} is the freeglut window to set the callback,
+ * {Visibility} is the window-specific callback to set,
+ * {func} is a function-pointer.
+ *
+ * Originally, {FETCH_WCB( ... ) = func} was rather sloppily used,
+ * but this can cause warnings because the FETCH_WCB() macro type-
+ * casts its result, and a type-cast value shouldn't be an lvalue.
+ *
+ * The {if( FETCH_WCB( ... ) != func )} test is to do type-checking
+ * and for no other reason. Since it's hidden in the macro, the
+ * ugliness is felt to be rather benign.
+ */
+#define SET_WCB(window,cbname,func) \
+do \
+{ \
+ if( FETCH_WCB( window, cbname ) != func ) \
+ (((window).CallBacks[CB_ ## cbname]) = func); \
+} while( 0 ) \
+
+/*
+ * FETCH_WCB() is used as:
+ *
+ * FETCH_WCB( window, Visibility );
+ *
+ * ...where {window} is the freeglut window to fetch the callback from,
+ * {Visibility} is the window-specific callback to fetch.
+ *
+ * The result is correctly type-cast to the callback function pointer
+ * type.
+ */
+#define FETCH_WCB(window,cbname) \
+ ((FGCB ## cbname)((window).CallBacks[CB_ ## cbname]))
+
+/*
+ * INVOKE_WCB() is used as:
+ *
+ * INVOKE_WCB( window, Visibility, ( status ) );
+ *
+ * ...where {window} is the freeglut window,
+ * {Visibility} is the window-specific callback,
+ * {(status)} is the parameter list.
+ *
+ * The callback is invoked as:
+ *
+ * callback( status );
+ *
+ * ...so the parentheses are REQUIRED in the {arg_list}.
+ *
+ * NOTE that it does a sanity-check and also sets the
+ * current window.
+ *
+ */
+#define INVOKE_WCB(window,cbname,arg_list) \
+do \
+{ \
+ if( FETCH_WCB( window, cbname ) ) \
+ { \
+ fgSetWindow( &window ); \
+ FETCH_WCB( window, cbname ) arg_list; \
+ } \
+} while( 0 )
+