X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Ffreeglut_structure.c;h=1d064b68bd96461d28780bb281194a31de5bc52d;hb=1b9a554a58e5595d9512540df60a3d681dc784a9;hp=e7464bc7b29af87712dd4c719311d3c4de56099e;hpb=7d0fc844c337b9c8901317d6935c3462b59ceda5;p=freeglut diff --git a/src/freeglut_structure.c b/src/freeglut_structure.c index e7464bc..1d064b6 100644 --- a/src/freeglut_structure.c +++ b/src/freeglut_structure.c @@ -25,14 +25,9 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "../include/GL/freeglut.h" +#include #include "freeglut_internal.h" - /* -- GLOBAL EXPORTS ------------------------------------------------------- */ /* @@ -42,6 +37,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 */ @@ -52,7 +48,7 @@ SFG_Structure fgStructure = { { NULL, NULL }, /* The list of windows */ /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */ -void fgClearCallBacks( SFG_Window *window ) +static void fghClearCallBacks( SFG_Window *window ) { if( window ) { @@ -69,28 +65,21 @@ 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 positionUse, int x, int y, + GLboolean sizeUse, int w, int h, GLboolean gameMode, GLboolean isMenu ) { - /* - * Have the window object created - */ + /* Have the window object created */ 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... - */ - if( !fgState.Initialised ) - glutInit( &fakeArgc, NULL ); +#if TARGET_HOST_UNIX_X11 + window->Window.FBConfig = NULL; +#endif + fghClearCallBacks( window ); - /* - * Initialize the object properties - */ + /* Initialize the object properties */ window->ID = ++fgStructure.WindowID; + window->State.OldHeight = window->State.OldWidth = -1; fgListInit( &window->Children ); if( parent ) @@ -101,19 +90,20 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title, else fgListAppend( &fgStructure.Windows, &window->Node ); - /* - * Set the default mouse cursor and reset the modifiers value - */ + /* Set the default mouse cursor and reset the modifiers value */ window->State.Cursor = GLUT_CURSOR_INHERIT; window->IsMenu = isMenu; + window->State.IgnoreKeyRepeat = GL_FALSE; + window->State.KeyRepeating = GL_FALSE; + /* * 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 ? GL_TRUE : GL_FALSE ); + fgOpenWindow( window, title, positionUse, x, y, sizeUse, w, h, gameMode, + (GLboolean)(parent ? GL_TRUE : GL_FALSE) ); return window; } @@ -124,37 +114,24 @@ 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; + SFG_Window *current_window = fgStructure.CurrentWindow; - /* - * Have the menu object created - */ + /* Have the menu object created */ SFG_Menu* menu = (SFG_Menu *)calloc( sizeof(SFG_Menu), 1 ); - int fakeArgc = 0; - /* - * If the freeglut internals haven't been initialized yet, - * do it now. Hack's idea courtesy of Chris Purnell... - */ - if( !fgState.Initialised ) - glutInit( &fakeArgc, NULL ); + menu->ParentWindow = NULL; - menu->ParentWindow = fgStructure.Window; + /* Create a window for the menu to reside in. */ - /* - * Create a window for the menu to reside in. - */ - - fgCreateWindow( NULL, NULL, x, y, w, h, GL_FALSE, GL_TRUE ); - menu->Window = fgStructure.Window; + fgCreateWindow( NULL, "freeglut menu", GL_TRUE, x, y, GL_TRUE, w, h, + GL_FALSE, GL_TRUE ); + menu->Window = fgStructure.CurrentWindow; glutDisplayFunc( fgDisplayMenu ); glutHideWindow( ); /* Hide the window for now */ fgSetWindow( current_window ); - /* - * Initialize the object properties: - */ + /* Initialize the object properties: */ menu->ID = ++fgStructure.MenuID; menu->Callback = menuCallback; menu->ActiveEntry = NULL; @@ -162,41 +139,27 @@ SFG_Menu* fgCreateMenu( FGCBMenu menuCallback ) fgListInit( &menu->Entries ); fgListAppend( &fgStructure.Menus, &menu->Node ); - /* - * Newly created menus implicitly become current ones - */ - fgStructure.Menu = menu; + /* Newly created menus implicitly become current ones */ + fgStructure.CurrentMenu = menu; return menu; } /* - * 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... - */ - if( fgStructure.Window == window ) - fgStructure.Window = NULL; + /* Check if the window is the current one... */ + if( fgStructure.CurrentWindow == window ) + fgStructure.CurrentWindow = NULL; /* * Clear all window callbacks except Destroy, which will @@ -207,39 +170,10 @@ void fgAddToWindowDestroyList( SFG_Window* window, GLboolean needToClose ) * to ensure that they are no longer called after this point. */ { - void *destroy = FETCH_WCB( *window, Destroy ); - fgClearCallBacks( window ); - FETCH_WCB( *window, Destroy ) = destroy; + FGCBDestroy destroy = (FGCBDestroy)FETCH_WCB( *window, Destroy ); + fghClearCallBacks( window ); + 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; } /* @@ -247,22 +181,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; - } } } @@ -271,27 +195,18 @@ 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 ; - - assert( window ); - freeglut_assert_ready; + FREEGLUT_INTERNAL_ERROR_EXIT ( window, "Window destroy function called with null window", + "fgDestroyWindow" ); - while( (subWindow = ( SFG_Window * )window->Children.First) ) - 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 ; + SFG_Window *activeWindow = fgStructure.CurrentWindow; INVOKE_WCB( *window, Destroy, ( ) ); - fgSetWindow ( activeWindow ) ; + fgSetWindow( activeWindow ); } if( window->Parent ) @@ -302,18 +217,17 @@ void fgDestroyWindow( SFG_Window* window, GLboolean needToClose ) if( window->ActiveMenu ) fgDeactivateMenu( window ); - for ( menu_index = 0; menu_index < 3; menu_index ++ ) + fghClearCallBacks( window ); + fgCloseWindow( window ); +#if TARGET_HOST_UNIX_X11 + if (window->Window.FBConfig != NULL) { - if ( window->Menu[menu_index] ) - window->Menu[menu_index]->ParentWindow = NULL ; + XFree( window->Window.FBConfig ); } - - fgClearCallBacks( window ); - if( needToClose ) - fgCloseWindow( window ); +#endif free( window ); - if( fgStructure.Window == window ) - fgStructure.Window = NULL; + if( fgStructure.CurrentWindow == window ) + fgStructure.CurrentWindow = NULL; } /* @@ -325,17 +239,19 @@ static void fghRemoveMenuFromWindow( SFG_Window* window, SFG_Menu* menu ) SFG_Window *subWindow; int i; + /* Check whether this is the active menu in the window */ + if ( menu == window->ActiveMenu ) + window->ActiveMenu = NULL ; + /* * 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 < FREEGLUT_MAX_MENUS; i++ ) if( window->Menu[ i ] == menu ) window->Menu[ i ] = NULL; - /* - * Call this function for all of the window's children recursively: - */ + /* Call this function for all of the window's children recursively: */ for( subWindow = (SFG_Window *)window->Children.First; subWindow; subWindow = (SFG_Window *)subWindow->Node.Next) @@ -365,22 +281,17 @@ void fgDestroyMenu( SFG_Menu* menu ) { SFG_Window *window; SFG_Menu *from; - SFG_MenuEntry *entry; - assert( menu ); - freeglut_assert_ready; + FREEGLUT_INTERNAL_ERROR_EXIT ( menu, "Menu destroy function called with null menu", + "fgDestroyMenu" ); - /* - * First of all, have all references to this menu removed from all windows: - */ + /* 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 - */ + /* 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 ) @@ -392,18 +303,20 @@ void fgDestroyMenu( SFG_Menu* menu ) */ if( menu->Destroy ) { - SFG_Menu *activeMenu=fgStructure.Menu; - fgStructure.Menu = menu; + SFG_Menu *activeMenu=fgStructure.CurrentMenu; + fgStructure.CurrentMenu = menu; menu->Destroy( ); - fgStructure.Menu = activeMenu; + fgStructure.CurrentMenu = 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) ) + while( menu->Entries.First ) { + SFG_MenuEntry *entry = ( SFG_MenuEntry * ) menu->Entries.First; + fgListRemove( &menu->Entries, &entry->Node ); if( entry->Text ) @@ -411,15 +324,14 @@ void fgDestroyMenu( SFG_Menu* menu ) entry->Text = NULL; free( entry ); - entry = NULL; } - if( fgStructure.Window == menu->Window ) - fgSetWindow( menu->ParentWindow ); - fgDestroyWindow( menu->Window, GL_TRUE ); + if( fgStructure.CurrentWindow == menu->Window ) + fgSetWindow( NULL ); + fgDestroyWindow( menu->Window ); fgListRemove( &fgStructure.Menus, &menu->Node ); - if( fgStructure.Menu == menu ) - fgStructure.Menu = NULL; + if( fgStructure.CurrentMenu == menu ) + fgStructure.CurrentMenu = NULL; free( menu ); } @@ -440,6 +352,14 @@ void fgCreateStructure( void ) fgListInit(&fgStructure.Windows); fgListInit(&fgStructure.Menus); + fgListInit(&fgStructure.WindowsToDestroy); + + fgStructure.CurrentWindow = NULL; + fgStructure.CurrentMenu = NULL; + fgStructure.MenuContext = NULL; + fgStructure.GameModeWindow = NULL; + fgStructure.WindowID = 0; + fgStructure.MenuID = 0; } /* @@ -449,19 +369,15 @@ void fgCreateStructure( void ) */ void fgDestroyStructure( void ) { - SFG_Window *window; - SFG_Menu *menu; + /* Clean up the WindowsToDestroy list. */ + fgCloseWindows( ); - freeglut_assert_ready; + /* Make sure all windows and menus have been deallocated */ + while( fgStructure.Menus.First ) + fgDestroyMenu( ( SFG_Menu * )fgStructure.Menus.First ); - /* - * Make sure all windows and menus have been deallocated - */ - while( (menu = ( SFG_Menu * )fgStructure.Menus.First) ) - fgDestroyMenu( menu ); - - while( (window = ( SFG_Window * )fgStructure.Windows.First) ) - fgDestroyWindow( window, GL_TRUE ); + while( fgStructure.Windows.First ) + fgDestroyWindow( ( SFG_Window * )fgStructure.Windows.First ); } /* @@ -471,12 +387,11 @@ void fgEnumWindows( FGCBenumerator enumCallback, SFG_Enumerator* enumerator ) { SFG_Window *window; - assert( enumCallback && enumerator ); - freeglut_assert_ready; + FREEGLUT_INTERNAL_ERROR_EXIT ( enumCallback && enumerator, + "Enumerator or callback missing from window enumerator call", + "fgEnumWindows" ); - /* - * Check every of the top-level windows - */ + /* Check every of the top-level windows */ for( window = ( SFG_Window * )fgStructure.Windows.First; window; window = ( SFG_Window * )window->Node.Next ) @@ -496,8 +411,10 @@ void fgEnumSubWindows( SFG_Window* window, FGCBenumerator enumCallback, { SFG_Window *child; - assert( enumCallback && enumerator ); - freeglut_assert_ready; + FREEGLUT_INTERNAL_ERROR_EXIT ( enumCallback && enumerator, + "Enumerator or callback missing from subwindow enumerator call", + "fgEnumSubWindows" ); + FREEGLUT_INTERNAL_ERROR_EXIT_IF_NOT_INITIALISED ( "Window Enumeration" ); for( child = ( SFG_Window * )window->Children.First; child; @@ -518,16 +435,8 @@ static void fghcbWindowByHandle( SFG_Window *window, if ( enumerator->found ) return; -#if TARGET_HOST_UNIX_X11 - #define WBHANDLE (Window) -#elif TARGET_HOST_WIN32 - #define WBHANDLE (HWND) -#endif - - /* - * Check the window's handle. Hope this works. Looks ugly. That's for sure. - */ - if( window->Window.Handle == WBHANDLE (enumerator->data) ) + /* Check the window's handle. Hope this works. Looks ugly. That's for sure. */ + if( window->Window.Handle == (SFG_WindowHandleType) (enumerator->data) ) { enumerator->found = GL_TRUE; enumerator->data = window; @@ -535,12 +444,8 @@ static void fghcbWindowByHandle( SFG_Window *window, return; } - /* - * Otherwise, check this window's children - */ + /* Otherwise, check this window's children */ fgEnumSubWindows( window, fghcbWindowByHandle, enumerator ); - -#undef WBHANDLE } /* @@ -548,18 +453,11 @@ 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 - */ + /* This is easy and makes use of the windows enumeration defined above */ enumerator.found = GL_FALSE; enumerator.data = (void *)hWindow; fgEnumWindows( fghcbWindowByHandle, &enumerator ); @@ -574,16 +472,12 @@ SFG_Window* fgWindowByHandle */ static void fghcbWindowByID( SFG_Window *window, SFG_Enumerator *enumerator ) { - /* - * Make sure we do not overwrite our precious results... - */ - if ( enumerator->found ) + /* Make sure we do not overwrite our precious results... */ + 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! */ + /* Check the window's handle. Hope this works. Looks ugly. That's for sure. */ + if( window->ID == *( int *)(enumerator->data) ) { enumerator->found = GL_TRUE; enumerator->data = window; @@ -591,9 +485,7 @@ static void fghcbWindowByID( SFG_Window *window, SFG_Enumerator *enumerator ) return; } - /* - * Otherwise, check this window's children - */ + /* Otherwise, check this window's children */ fgEnumSubWindows( window, fghcbWindowByID, enumerator ); } @@ -606,30 +498,24 @@ SFG_Window* fgWindowByID( int windowID ) { SFG_Enumerator enumerator; - /* - * Uses a method very similiar for fgWindowByHandle... - */ + /* Uses a method very similiar for fgWindowByHandle... */ enumerator.found = GL_FALSE; - enumerator.data = (void *) windowID; /* XXX int/pointer conversion! */ + enumerator.data = ( void * )&windowID; fgEnumWindows( fghcbWindowByID, &enumerator ); if( enumerator.found ) - return( SFG_Window *) enumerator.data; + return ( SFG_Window * )enumerator.data; return NULL; } /* * Looks up a menu given its ID. This is easier that fgWindowByXXX - * as all menus are placed in a single doubly linked list... + * as all menus are placed in one doubly linked list... */ SFG_Menu* fgMenuByID( int menuID ) { SFG_Menu *menu = NULL; - freeglut_assert_ready; - - /* - * It's enough to check all entries in fgStructure.Menus... - */ + /* It's enough to check all entries in fgStructure.Menus... */ for( menu = (SFG_Menu *)fgStructure.Menus.First; menu; menu = (SFG_Menu *)menu->Node.Next ) @@ -649,10 +535,9 @@ void fgListInit(SFG_List *list) void fgListAppend(SFG_List *list, SFG_Node *node) { - SFG_Node *ln; - - if ( (ln = (SFG_Node *)list->Last) ) + if ( list->Last ) { + SFG_Node *ln = (SFG_Node *) list->Last; ln->Next = node; node->Prev = ln; } @@ -668,15 +553,13 @@ void fgListAppend(SFG_List *list, SFG_Node *node) void fgListRemove(SFG_List *list, SFG_Node *node) { - SFG_Node *ln; - - if( (ln = (SFG_Node *)node->Next) ) - ln->Prev = node->Prev; - if( (ln = (SFG_Node *)node->Prev) ) - ln->Next = node->Next; - if( (ln = (SFG_Node *)list->First) == node ) + if( node->Next ) + ( ( SFG_Node * )node->Next )->Prev = node->Prev; + if( node->Prev ) + ( ( SFG_Node * )node->Prev )->Next = node->Next; + if( ( ( SFG_Node * )list->First ) == node ) list->First = node->Next; - if( (ln = (SFG_Node *)list->Last) == node ) + if( ( ( SFG_Node * )list->Last ) == node ) list->Last = node->Prev; } @@ -693,4 +576,26 @@ int fgListLength(SFG_List *list) 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 ***/