X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Ffreeglut_structure.c;h=8b0a837e3eaec4a3acf7fa16b7aa5d6f990b8aa7;hb=aa4643b483379e0f1e40b8abc6584363cf395216;hp=cc1e9a383d86a93ed374b0eabcc26ec81dcd00aa;hpb=7fad69335a7488fd62a47281d7a5a22acf20db16;p=freeglut diff --git a/src/freeglut_structure.c b/src/freeglut_structure.c index cc1e9a3..8b0a837 100644 --- a/src/freeglut_structure.c +++ b/src/freeglut_structure.c @@ -42,6 +42,7 @@ SFG_Structure fgStructure = { { NULL, NULL }, /* The list of windows */ { NULL, NULL }, /* The list of menus */ + { NULL, NULL }, /* Windows to Destroy list */ NULL, /* The current window */ NULL, /* The current menu */ NULL, /* The menu OpenGL context */ @@ -54,9 +55,12 @@ SFG_Structure fgStructure = { { NULL, NULL }, /* The list of windows */ void fgClearCallBacks( SFG_Window *window ) { - int i; - for( i = 0; i < TOTAL_CALLBACKS; ++i ) - window->CallBacks[ i ] = NULL; + if( window ) + { + int i; + for( i = 0; i < TOTAL_CALLBACKS; ++i ) + window->CallBacks[ i ] = NULL; + } } /* @@ -66,7 +70,8 @@ void fgClearCallBacks( SFG_Window *window ) * If parent is set to NULL, the window created will be a topmost one. */ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title, - int x, int y, int w, int h, GLboolean gameMode ) + int x, int y, int w, int h, + GLboolean gameMode, GLboolean isMenu ) { /* * Have the window object created @@ -80,16 +85,17 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title, * If the freeglut internals haven't been initialized yet, * do it now. Hack's idea courtesy of Chris Purnell... */ - if( !fgState.Time.Set ) + if( !fgState.Initialised ) glutInit( &fakeArgc, NULL ); /* * Initialize the object properties */ window->ID = ++fgStructure.WindowID; + window->State.OldHeight = window->State.OldWidth = -1; fgListInit( &window->Children ); - if( parent != NULL ) + if( parent ) { fgListAppend( &parent->Children, &window->Node ); window->Parent = parent; @@ -101,16 +107,15 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title, * Set the default mouse cursor and reset the modifiers value */ window->State.Cursor = GLUT_CURSOR_INHERIT; - window->State.Modifiers = 0xffffffff; - window->IsMenu = fgState.BuildingAMenu ; + window->IsMenu = isMenu; /* * Open the window now. The fgOpenWindow() function is system * dependant, and resides in freeglut_window.c. Uses fgState. */ fgOpenWindow( window, title, x, y, w, h, gameMode, - (parent != NULL) ? TRUE : FALSE ); + parent ? GL_TRUE : GL_FALSE ); return window; } @@ -120,8 +125,8 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title, */ SFG_Menu* fgCreateMenu( FGCBMenu menuCallback ) { - int x = 100, y = 100, w = 100, h = 100 ; - SFG_Window *current_window = fgStructure.Window ; + int x = 100, y = 100, w = 100, h = 100; + SFG_Window *current_window = fgStructure.Window; /* * Have the menu object created @@ -133,37 +138,28 @@ SFG_Menu* fgCreateMenu( FGCBMenu menuCallback ) * If the freeglut internals haven't been initialized yet, * do it now. Hack's idea courtesy of Chris Purnell... */ - if( !fgState.Time.Set ) + if( !fgState.Initialised ) glutInit( &fakeArgc, NULL ); - menu->ParentWindow = fgStructure.Window ; + menu->ParentWindow = fgStructure.Window; /* - * Create a window for the menu to reside in. Set the - * global variable BuildingAMenu to true so we can ensure - * it is created without decorations. + * Create a window for the menu to reside in. */ - fgState.BuildingAMenu = TRUE ; - fgCreateWindow ( NULL, NULL, x, y, w, h, FALSE ) ; - menu->Window = fgStructure.Window ; - glutDisplayFunc ( fgDisplayMenu ) ; - - /* - * While BuildingAMenu is true, all windows built have no decorations. - * That's not a good default behavior, so let's set it false again. - */ - fgState.BuildingAMenu = FALSE ; + fgCreateWindow( NULL, NULL, x, y, w, h, GL_FALSE, GL_TRUE ); + menu->Window = fgStructure.Window; + glutDisplayFunc( fgDisplayMenu ); - glutHideWindow () ; /* Hide the window for now */ - fgSetWindow ( current_window ) ; + glutHideWindow( ); /* Hide the window for now */ + fgSetWindow( current_window ); /* * Initialize the object properties: */ menu->ID = ++fgStructure.MenuID; menu->Callback = menuCallback; - menu->ActiveEntry = NULL ; + menu->ActiveEntry = NULL; fgListInit( &menu->Entries ); fgListAppend( &fgStructure.Menus, &menu->Node ); @@ -177,26 +173,16 @@ SFG_Menu* fgCreateMenu( FGCBMenu menuCallback ) } /* - * Linked list of windows to destroy ... this is so we don't destroy a - * window from the middle of its callback. Some C compilers take an - * extremely dim view of this. - */ - -static SFG_WindowList* WindowsToDestroy = (SFG_WindowList*)NULL ; - -/* * Function to add a window to the linked list of windows to destroy. * Subwindows are automatically added because they hang from the window * structure. */ -void fgAddToWindowDestroyList ( SFG_Window* window, GLboolean needToClose ) +void fgAddToWindowDestroyList( SFG_Window* window ) { 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; + fgListAppend( &fgStructure.WindowsToDestroy, &new_list_entry->node ); /* * Check if the window is the current one... @@ -215,37 +201,8 @@ void fgAddToWindowDestroyList ( SFG_Window* window, GLboolean needToClose ) { void *destroy = FETCH_WCB( *window, Destroy ); fgClearCallBacks( window ); - FETCH_WCB( *window, Destroy ) = destroy; + SET_WCB( *window, Destroy, destroy ); } - - - /* - * 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--; - - /* - * 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; } /* @@ -253,22 +210,12 @@ void fgAddToWindowDestroyList ( SFG_Window* window, GLboolean needToClose ) */ 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 ) + while( fgStructure.WindowsToDestroy.First ) { - SFG_WindowList *next = window_ptr->next; - fgDestroyWindow( window_ptr->window, window_ptr->needToClose ); + SFG_WindowList *window_ptr = fgStructure.WindowsToDestroy.First; + fgDestroyWindow( window_ptr->window ); + fgListRemove( &fgStructure.WindowsToDestroy, &window_ptr->node ); free( window_ptr ); - window_ptr = next; - - if( !window_ptr ) - { - window_ptr = WindowsToDestroy; - WindowsToDestroy = ( SFG_WindowList* )NULL; - } } } @@ -277,49 +224,39 @@ void fgCloseWindows( ) * another function, defined in freeglut_window.c is called, but this is * a whole different story... */ -void fgDestroyWindow( SFG_Window* window, GLboolean needToClose ) +void fgDestroyWindow( SFG_Window* window ) { - SFG_Window* subWindow; - int menu_index ; + int menu_index; - assert( window != NULL ); + assert( window ); freeglut_assert_ready; - while ( (subWindow = (SFG_Window *)window->Children.First) != NULL ) - fgDestroyWindow( subWindow, needToClose ); + while( window->Children.First ) + fgDestroyWindow( ( SFG_Window * )window->Children.First ); - /* - * 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 ; - INVOKE_WCB( *window, Destroy, ( ) ); - fgSetWindow ( activeWindow ) ; + SFG_Window *activeWindow = fgStructure.Window; + INVOKE_WCB( *window, Destroy, ( ) ); + fgSetWindow( activeWindow ); } - if ( window->Parent != NULL ) + if( window->Parent ) fgListRemove( &window->Parent->Children, &window->Node ); else fgListRemove( &fgStructure.Windows, &window->Node ); - if ( window->ActiveMenu != NULL ) - fgDeactivateMenu ( window ) ; + if( window->ActiveMenu ) + fgDeactivateMenu( window ); - for ( menu_index = 0; menu_index < 3; menu_index ++ ) - { - if ( window->Menu[menu_index] != NULL ) - window->Menu[menu_index]->ParentWindow = NULL ; - } + for( menu_index = 0; menu_index < 3; menu_index ++ ) + if( window->Menu[ menu_index ] ) + window->Menu[ menu_index ]->ParentWindow = NULL; - if( needToClose == TRUE ) - fgCloseWindow( window ); - free( window ); - if ( fgStructure.Window == window ) - fgStructure.Window = NULL ; fgClearCallBacks( window ); + fgCloseWindow( window ); + free( window ); + if( fgStructure.Window == window ) + fgStructure.Window = NULL; } /* @@ -335,14 +272,15 @@ static void fghRemoveMenuFromWindow( SFG_Window* window, SFG_Menu* menu ) * Check if the menu is attached to the current window, * if so, have it detached (by overwriting with a NULL): */ - for( i=0; i<3; i++ ) + for( i = 0; i < 3; i++ ) if( window->Menu[ i ] == menu ) window->Menu[ i ] = NULL; /* * Call this function for all of the window's children recursively: */ - for( subWindow = (SFG_Window *)window->Children.First; subWindow; + for( subWindow = (SFG_Window *)window->Children.First; + subWindow; subWindow = (SFG_Window *)subWindow->Node.Next) fghRemoveMenuFromWindow( subWindow, menu ); } @@ -353,13 +291,13 @@ static void fghRemoveMenuFromWindow( SFG_Window* window, SFG_Menu* menu ) */ static void fghRemoveMenuFromMenu( SFG_Menu* from, SFG_Menu* menu ) { - SFG_MenuEntry *entry; + SFG_MenuEntry *entry; - for( entry = (SFG_MenuEntry *)from->Entries.First; - entry; - entry = (SFG_MenuEntry *)entry->Node.Next ) - if (entry->SubMenu == menu) - entry->SubMenu = NULL; + for( entry = (SFG_MenuEntry *)from->Entries.First; + entry; + entry = ( SFG_MenuEntry * )entry->Node.Next ) + if( entry->SubMenu == menu ) + entry->SubMenu = NULL; } /* @@ -368,65 +306,65 @@ static void fghRemoveMenuFromMenu( SFG_Menu* from, SFG_Menu* menu ) */ void fgDestroyMenu( SFG_Menu* menu ) { - SFG_Window *window; - SFG_Menu *from; - SFG_MenuEntry *entry; - - assert( menu != NULL ); - freeglut_assert_ready; - - /* - * First of all, have all references to this menu removed from all windows: - */ - for( window = (SFG_Window *)fgStructure.Windows.First; - window; - window = (SFG_Window *)window->Node.Next ) - fghRemoveMenuFromWindow( window, menu ); - - /* - * Now proceed with removing menu entries that lead to this menu - */ - for( from = (SFG_Menu *)fgStructure.Menus.First; - from; - from = (SFG_Menu *)from->Node.Next ) - fghRemoveMenuFromMenu( from, menu ); - - /* - * If the programmer defined a destroy callback, call it - * A. Donev: But first make this the active menu - */ - if ( menu->Destroy != NULL ) - { - SFG_Menu *activeMenu=fgStructure.Menu; - fgStructure.Menu = menu; - menu->Destroy () ; - fgStructure.Menu = activeMenu; - } - - /* - * Now we are pretty sure the menu is not used anywhere - * and that we can remove all of its entries - */ - while( (entry = (SFG_MenuEntry *)menu->Entries.First) != NULL ) - { - fgListRemove(&menu->Entries, &entry->Node); - - if( entry->Text ) - free( entry->Text ); - entry->Text = NULL; - - free( entry ); - entry = NULL; - } - - if ( fgStructure.Window == menu->Window ) - fgSetWindow ( menu->ParentWindow ) ; - fgDestroyWindow ( menu->Window, TRUE ) ; - fgListRemove( &fgStructure.Menus, &menu->Node ); - if( fgStructure.Menu == menu ) - fgStructure.Menu = NULL; - - free( menu ); + SFG_Window *window; + SFG_Menu *from; + SFG_MenuEntry *entry; + + assert( menu ); + freeglut_assert_ready; + + /* + * First of all, have all references to this menu removed from all windows: + */ + for( window = (SFG_Window *)fgStructure.Windows.First; + window; + window = (SFG_Window *)window->Node.Next ) + fghRemoveMenuFromWindow( window, menu ); + + /* + * Now proceed with removing menu entries that lead to this menu + */ + for( from = ( SFG_Menu * )fgStructure.Menus.First; + from; + from = ( SFG_Menu * )from->Node.Next ) + fghRemoveMenuFromMenu( from, menu ); + + /* + * If the programmer defined a destroy callback, call it + * A. Donev: But first make this the active menu + */ + if( menu->Destroy ) + { + SFG_Menu *activeMenu=fgStructure.Menu; + fgStructure.Menu = menu; + menu->Destroy( ); + fgStructure.Menu = activeMenu; + } + + /* + * Now we are pretty sure the menu is not used anywhere + * and that we can remove all of its entries + */ + while( entry = ( SFG_MenuEntry * )menu->Entries.First ) + { + fgListRemove( &menu->Entries, &entry->Node ); + + if( entry->Text ) + free( entry->Text ); + entry->Text = NULL; + + free( entry ); + entry = NULL; + } + + if( fgStructure.Window == menu->Window ) + fgSetWindow( menu->ParentWindow ); + fgDestroyWindow( menu->Window ); + fgListRemove( &fgStructure.Menus, &menu->Node ); + if( fgStructure.Menu == menu ) + fgStructure.Menu = NULL; + + free( menu ); } /* @@ -437,14 +375,15 @@ void fgDestroyMenu( SFG_Menu* menu ) */ void fgCreateStructure( void ) { - /* - * We will be needing two lists: the first containing windows, - * and the second containing the user-defined menus. - * Also, no current window/menu is set, as none has been created yet. - */ - - fgListInit(&fgStructure.Windows); - fgListInit(&fgStructure.Menus); + /* + * We will be needing two lists: the first containing windows, + * and the second containing the user-defined menus. + * Also, no current window/menu is set, as none has been created yet. + */ + + fgListInit(&fgStructure.Windows); + fgListInit(&fgStructure.Menus); + fgListInit(&fgStructure.WindowsToDestroy); } /* @@ -454,19 +393,21 @@ void fgCreateStructure( void ) */ void fgDestroyStructure( void ) { - SFG_Window *window; - SFG_Menu *menu; - - freeglut_assert_ready; + freeglut_assert_ready; - /* - * Make sure all windows and menus have been deallocated - */ - while( (menu = (SFG_Menu *)fgStructure.Menus.First) != NULL ) - fgDestroyMenu( menu ); + /* + * Clean up the WindowsToDestroy list. + */ + fgCloseWindows( ); - while( (window = (SFG_Window *)fgStructure.Windows.First) != NULL ) - fgDestroyWindow( window, TRUE ); + /* + * Make sure all windows and menus have been deallocated + */ + while( fgStructure.Menus.First ) + fgDestroyMenu( ( SFG_Menu * )fgStructure.Menus.First ); + + while( fgStructure.Windows.First ) + fgDestroyWindow( ( SFG_Window * )fgStructure.Windows.First ); } /* @@ -474,22 +415,22 @@ void fgDestroyStructure( void ) */ void fgEnumWindows( FGCBenumerator enumCallback, SFG_Enumerator* enumerator ) { - SFG_Window *window; - - assert( (enumCallback != NULL) && (enumerator != NULL) ); - freeglut_assert_ready; - - /* - * Check every of the top-level windows - */ - for( window = (SFG_Window *)fgStructure.Windows.First; - window; - window = (SFG_Window *)window->Node.Next ) - { - enumCallback( window, enumerator ); - if( enumerator->found == TRUE ) - return; - } + SFG_Window *window; + + assert( enumCallback && enumerator ); + freeglut_assert_ready; + + /* + * Check every of the top-level windows + */ + for( window = ( SFG_Window * )fgStructure.Windows.First; + window; + window = ( SFG_Window * )window->Node.Next ) + { + enumCallback( window, enumerator ); + if( enumerator->found ) + return; + } } /* @@ -499,19 +440,19 @@ void fgEnumWindows( FGCBenumerator enumCallback, SFG_Enumerator* enumerator ) void fgEnumSubWindows( SFG_Window* window, FGCBenumerator enumCallback, SFG_Enumerator* enumerator ) { - SFG_Window *child; - - assert( (enumCallback != NULL) && (enumerator != NULL) ); - freeglut_assert_ready; - - for( child = (SFG_Window *)window->Children.First; - child; - child = (SFG_Window *)child->Node.Next ) - { - enumCallback( child, enumerator ); - if( enumerator->found == TRUE ) - return; - } + SFG_Window *child; + + assert( enumCallback && enumerator ); + freeglut_assert_ready; + + for( child = ( SFG_Window * )window->Children.First; + child; + child = ( SFG_Window * )child->Node.Next ) + { + enumCallback( child, enumerator ); + if( enumerator->found ) + return; + } } /* @@ -520,20 +461,15 @@ void fgEnumSubWindows( SFG_Window* window, FGCBenumerator enumCallback, static void fghcbWindowByHandle( SFG_Window *window, SFG_Enumerator *enumerator ) { - freeglut_return_if_fail( enumerator->found == FALSE ); - -#if TARGET_HOST_UNIX_X11 - #define WBHANDLE (Window) -#elif TARGET_HOST_WIN32 - #define WBHANDLE (HWND) -#endif + if ( enumerator->found ) + return; /* * Check the window's handle. Hope this works. Looks ugly. That's for sure. */ - if( window->Window.Handle == WBHANDLE (enumerator->data) ) + if( window->Window.Handle == (SFG_WindowHandleType) (enumerator->data) ) { - enumerator->found = TRUE; + enumerator->found = GL_TRUE; enumerator->data = window; return; @@ -543,8 +479,6 @@ static void fghcbWindowByHandle( SFG_Window *window, * Otherwise, check this window's children */ fgEnumSubWindows( window, fghcbWindowByHandle, enumerator ); - -#undef WBHANDLE } /* @@ -552,23 +486,18 @@ static void fghcbWindowByHandle( SFG_Window *window, * first window in the queue matching the specified window handle. * The function is defined in freeglut_structure.c file. */ -SFG_Window* fgWindowByHandle -#if TARGET_HOST_UNIX_X11 -( Window hWindow ) -#elif TARGET_HOST_WIN32 -( HWND hWindow ) -#endif +SFG_Window* fgWindowByHandle ( SFG_WindowHandleType hWindow ) { SFG_Enumerator enumerator; /* * This is easy and makes use of the windows enumeration defined above */ - enumerator.found = FALSE; + enumerator.found = GL_FALSE; enumerator.data = (void *)hWindow; fgEnumWindows( fghcbWindowByHandle, &enumerator ); - if( enumerator.found == TRUE ) + if( enumerator.found ) return( SFG_Window *) enumerator.data; return NULL; } @@ -581,14 +510,15 @@ static void fghcbWindowByID( SFG_Window *window, SFG_Enumerator *enumerator ) /* * Make sure we do not overwrite our precious results... */ - freeglut_return_if_fail( enumerator->found == FALSE ); + if( enumerator->found ) + return; /* * Check the window's handle. Hope this works. Looks ugly. That's for sure. */ - if( window->ID == (int) (enumerator->data) ) /* XXX int/ptr conversion! */ + if( window->ID == *( int *)(enumerator->data) ) { - enumerator->found = TRUE; + enumerator->found = GL_TRUE; enumerator->data = window; return; @@ -612,11 +542,11 @@ SFG_Window* fgWindowByID( int windowID ) /* * Uses a method very similiar for fgWindowByHandle... */ - enumerator.found = FALSE; - enumerator.data = (void *) windowID; /* XXX int/pointer conversion! */ + enumerator.found = GL_FALSE; + enumerator.data = ( void * )&windowID; fgEnumWindows( fghcbWindowByID, &enumerator ); - if( enumerator.found == TRUE ) - return( SFG_Window *) enumerator.data; + if( enumerator.found ) + return ( SFG_Window * )enumerator.data; return NULL; } @@ -654,7 +584,7 @@ void fgListAppend(SFG_List *list, SFG_Node *node) { SFG_Node *ln; - if ( (ln = (SFG_Node *)list->Last) != NULL ) + if ( ln = (SFG_Node *)list->Last ) { ln->Next = node; node->Prev = ln; @@ -673,13 +603,13 @@ void fgListRemove(SFG_List *list, SFG_Node *node) { SFG_Node *ln; - if ( (ln = (SFG_Node *)node->Next) != NULL ) + if( ln = (SFG_Node *)node->Next ) ln->Prev = node->Prev; - if ( (ln = (SFG_Node *)node->Prev) != NULL ) + if( ln = (SFG_Node *)node->Prev ) ln->Next = node->Next; - if ( (ln = (SFG_Node *)list->First) == node ) + if( (ln = (SFG_Node *)list->First) == node ) list->First = node->Next; - if ( (ln = (SFG_Node *)list->Last) == node ) + if( (ln = (SFG_Node *)list->Last) == node ) list->Last = node->Prev; } @@ -688,10 +618,34 @@ int fgListLength(SFG_List *list) SFG_Node *node; int length = 0; - for( node = (SFG_Node *)list->First; node; node = (SFG_Node *)node->Next ) + for( node =( SFG_Node * )list->First; + node; + node = ( SFG_Node * )node->Next ) ++length; return length; } + +void fgListInsert(SFG_List *list, SFG_Node *next, SFG_Node *node) +{ + SFG_Node *prev; + + if( (node->Next = next) ) + { + prev = next->Prev; + next->Prev = node; + } + else + { + prev = list->Last; + list->Last = node; + } + + if( (node->Prev = prev) ) + prev->Next = node; + else + list->First = node; +} + /*** END OF FILE ***/