#include "config.h"
#endif
-#define G_LOG_DOMAIN "freeglut-structure"
-
#include "../include/GL/freeglut.h"
#include "freeglut_internal.h"
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
+void fgClearCallBacks( SFG_Window *window )
+{
+ int i;
+ for( i = 0; i < TOTAL_CALLBACKS; ++i )
+ window->CallBacks[ i ] = NULL;
+}
+
/*
* This private function creates, opens and adds to the hierarchy
* a freeglut window complete with OpenGL context and stuff...
SFG_Window *window = (SFG_Window *)calloc( sizeof(SFG_Window), 1 );
int fakeArgc = 0;
+ fgClearCallBacks( window );
+
/*
* If the freeglut internals haven't been initialized yet,
* do it now. Hack's idea courtesy of Chris Purnell...
/*
* This private function creates a menu and adds it to the menus list
*/
-SFG_Menu* fgCreateMenu( FGCBmenu menuCallback )
+SFG_Menu* fgCreateMenu( FGCBMenu menuCallback )
{
int x = 100, y = 100, w = 100, h = 100 ;
SFG_Window *current_window = fgStructure.Window ;
*/
void fgAddToWindowDestroyList ( SFG_Window* window, GLboolean needToClose )
{
- SFG_WindowList *new_list_entry =
- (SFG_WindowList*)malloc ( sizeof(SFG_WindowList) ) ;
- new_list_entry->window = window ;
- new_list_entry->needToClose = needToClose ;
- new_list_entry->next = WindowsToDestroy ;
- WindowsToDestroy = new_list_entry ;
+ SFG_WindowList *new_list_entry =
+ ( SFG_WindowList* )malloc( sizeof(SFG_WindowList ) );
+ new_list_entry->window = window;
+ new_list_entry->needToClose = needToClose;
+ new_list_entry->next = WindowsToDestroy;
+ WindowsToDestroy = new_list_entry;
- /*
- * Check if the window is the current one...
- */
- if ( fgStructure.Window == window )
- fgStructure.Window = NULL;
+ /*
+ * Check if the window is the current one...
+ */
+ if( fgStructure.Window == window )
+ fgStructure.Window = NULL;
- /*
- * If the destroyed window has the highest window ID number, decrement
- * the window ID number.
- *
- * XXX Do we REALLY want to *ever* recycle window IDs? Integers are
- * XXX plentiful, and clients may rely upon the implied promise in
- * XXX the GLUT docs to not recycle these. (I can't remember if it
- * XXX is explicit.)
- *
- * XXX If we *do* want to do this, we should actually recompute the
- * XXX highest window-ID; the new highest may not in fact be one less
- * XXX than what we have just deleted.
- */
- if ( window->ID == fgStructure.WindowID )
- fgStructure.WindowID-- ;
+ /*
+ * Clear all window callbacks except Destroy, which will
+ * be invoked later. Right now, we are potentially carrying
+ * out a freeglut operation at the behest of a client callback,
+ * so we are reluctant to re-enter the client with the Destroy
+ * callback, right now. The others are all wiped out, however,
+ * to ensure that they are no longer called after this point.
+ */
+ {
+ void *destroy = FETCH_WCB( *window, Destroy );
+ fgClearCallBacks( window );
+ FETCH_WCB( *window, Destroy ) = destroy;
+ }
+
- /*
- * Check the execution state. If this has been called from
- * "glutDestroyWindow", a statement in that function will reset the
- * "ExecState" after this function returns.
- */
- if ( fgState.ActionOnWindowClose != GLUT_ACTION_CONTINUE_EXECUTION )
- {
/*
- * Set the execution state flag to drop out of the main loop.
+ * If the destroyed window has the highest window ID number, decrement
+ * the window ID number.
+ *
+ * XXX Do we REALLY want to *ever* recycle window IDs? Integers are
+ * XXX plentiful, and clients may rely upon the implied promise in
+ * XXX the GLUT docs to not recycle these. (I can't remember if it
+ * XXX is explicit.)
+ *
+ * XXX If we *do* want to do this, we should actually recompute the
+ * XXX highest window-ID; the new highest may not in fact be one less
+ * XXX than what we have just deleted.
*/
- if ( fgState.ActionOnWindowClose == GLUT_ACTION_EXIT )
- fgState.ExecState = GLUT_EXEC_STATE_STOP ;
- }
+ if ( window->ID == fgStructure.WindowID )
+ fgStructure.WindowID--;
+
+ /*
+ * Check the execution state. If this has been called from
+ * "glutDestroyWindow", a statement in that function will reset the
+ * "ExecState" after this function returns.
+ */
+ if( fgState.ActionOnWindowClose != GLUT_ACTION_CONTINUE_EXECUTION )
+ /*
+ * Set the execution state flag to drop out of the main loop.
+ */
+ if( fgState.ActionOnWindowClose == GLUT_ACTION_EXIT )
+ fgState.ExecState = GLUT_EXEC_STATE_STOP;
}
/*
* Function to close down all the windows in the "WindowsToDestroy" list
*/
-void fgCloseWindows ()
+void fgCloseWindows( )
{
- SFG_WindowList *window_ptr = WindowsToDestroy ;
- WindowsToDestroy = (SFG_WindowList*)NULL ;
- /* In case the destroy callbacks cause more windows to be closed */
-
- while ( window_ptr )
- {
- SFG_WindowList *next = window_ptr->next ;
- fgDestroyWindow ( window_ptr->window, window_ptr->needToClose ) ;
- free ( window_ptr ) ;
- window_ptr = next ;
+ SFG_WindowList *window_ptr = WindowsToDestroy;
+ WindowsToDestroy = ( SFG_WindowList* )NULL;
+ /* In case the destroy callbacks cause more windows to be closed */
- if ( !window_ptr )
+ while( window_ptr )
{
- window_ptr = WindowsToDestroy ;
- WindowsToDestroy = (SFG_WindowList*)NULL ;
+ SFG_WindowList *next = window_ptr->next;
+ fgDestroyWindow( window_ptr->window, window_ptr->needToClose );
+ free( window_ptr );
+ window_ptr = next;
+
+ if( !window_ptr )
+ {
+ window_ptr = WindowsToDestroy;
+ WindowsToDestroy = ( SFG_WindowList* )NULL;
+ }
}
- }
}
/*
while ( (subWindow = (SFG_Window *)window->Children.First) != NULL )
fgDestroyWindow( subWindow, needToClose );
- if ( window->Callbacks.Destroy != NULL )
+ /*
+ * XXX Since INVOKE_WCB() tests the function pointer, why not make
+ * XXX this unconditional? Overhead is close to nil, and it would
+ * XXX clarify the code by omitting a conditional test.
+ */
+ if ( FETCH_WCB( *window, Destroy ) )
{
SFG_Window *activeWindow = fgStructure.Window ;
- fgSetWindow ( window ) ;
- window->Callbacks.Destroy () ;
+ INVOKE_WCB( *window, Destroy, ( ) );
fgSetWindow ( activeWindow ) ;
}
free( window );
if ( fgStructure.Window == window )
fgStructure.Window = NULL ;
+ fgClearCallBacks( window );
}
/*
/*
* Check the window's handle. Hope this works. Looks ugly. That's for sure.
*/
- if( window->ID == (int) (enumerator->data) )
+ if( window->ID == (int) (enumerator->data) ) /* XXX int/ptr conversion! */
{
enumerator->found = TRUE;
enumerator->data = window;
* Uses a method very similiar for fgWindowByHandle...
*/
enumerator.found = FALSE;
- enumerator.data = (void *) windowID;
+ enumerator.data = (void *) windowID; /* XXX int/pointer conversion! */
fgEnumWindows( fghcbWindowByID, &enumerator );
if( enumerator.found == TRUE )
return( SFG_Window *) enumerator.data;
/*
* It's enough to check all entries in fgStructure.Menus...
*/
- for( menu = (SFG_Menu *)fgStructure.Menus.First; menu; menu = (SFG_Menu *)menu->Node.Next )
- {
- /*
- * Does the ID number match?
- */
+ for( menu = (SFG_Menu *)fgStructure.Menus.First;
+ menu;
+ menu = (SFG_Menu *)menu->Node.Next )
if( menu->ID == menuID )
- return( menu );
- }
-
- /*
- * We have not found the requested menu ID
- */
- return( NULL );
+ return menu;
+ return NULL;
}
/*
for( node = (SFG_Node *)list->First; node; node = (SFG_Node *)node->Next )
++length;
- return( length );
+ return length;
}
/*** END OF FILE ***/