+ * SET_WCB() is used as:
+ *
+ * SET_WCB( window, cbname, func );
+ *
+ * ...where {window} is the freeglut window to set the callback,
+ * {cbname} 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 ) != (SFG_Proc)(func) ) \
+ (((window).CallBacks[CB_ ## cbname]) = (SFG_Proc)(func)); \
+} while( 0 )
+
+/*
+ * FETCH_WCB() is used as:
+ *
+ * FETCH_WCB( window, cbname );
+ *
+ * ...where {window} is the freeglut window to fetch the callback from,
+ * {cbname} is the window-specific callback to fetch.
+ *
+ * The result is correctly type-cast to the callback function pointer
+ * type.
+ */
+#define FETCH_WCB(window,cbname) \
+ ((window).CallBacks[CB_ ## cbname])
+
+/*
+ * INVOKE_WCB() is used as:
+ *
+ * INVOKE_WCB( window, cbname, ( arg_list ) );
+ *
+ * ...where {window} is the freeglut window,
+ * {cbname} is the window-specific callback to be invoked,
+ * {(arg_list)} is the parameter list.
+ *
+ * The callback is invoked as:
+ *
+ * callback( arg_list );
+ *
+ * ...so the parentheses are REQUIRED in the {arg_list}.
+ *
+ * NOTE that it does a sanity-check and also sets the
+ * current window.
+ *
+ */
+#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE) /* FIXME: also WinCE? */
+#define INVOKE_WCB(window,cbname,arg_list) \
+do \
+{ \
+ if( FETCH_WCB( window, cbname ) ) \
+ { \
+ FGCB ## cbname func = (FGCB ## cbname)(FETCH_WCB( window, cbname )); \
+ fgSetWindow( &window ); \
+ func arg_list; \
+ } \
+} while( 0 )
+#else
+#define INVOKE_WCB(window,cbname,arg_list) \
+do \
+{ \
+ if( FETCH_WCB( window, cbname ) ) \
+ { \
+ fgSetWindow( &window ); \
+ ((FGCB ## cbname)FETCH_WCB( window, cbname )) arg_list; \
+ } \
+} while( 0 )
+#endif
+
+/*
+ * The window callbacks the user can supply us with. Should be kept portable.
+ *
+ * This enumeration provides the freeglut CallBack numbers.
+ * The symbolic constants are indices into a window's array of
+ * function callbacks. The names are formed by splicing a common
+ * prefix onto the callback's base name. (This was originally
+ * done so that an early stage of development could live side-by-
+ * side with the old callback code. The old callback code used
+ * the bare callback's name as a structure member, so I used a
+ * prefix for the array index name.)
+ *
+ * XXX For consistancy, perhaps the prefix should match the
+ * XXX FETCH* and INVOKE* macro suffices. I.e., WCB_, rather than
+ * XXX CB_.