X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=freeglut-1.3%2Ffreeglut_structure.c;h=6b54d50466682b830adff601e6e4a4cd5d7ae8d9;hb=a351855ee6b2ec6f477635a367c745d733219c3e;hp=af851f1f28da5f05501b29d3dc2f60475a3edaa9;hpb=c90e3f21e02020232054f78029ef9071c7359cfb;p=freeglut diff --git a/freeglut-1.3/freeglut_structure.c b/freeglut-1.3/freeglut_structure.c index af851f1..6b54d50 100644 --- a/freeglut-1.3/freeglut_structure.c +++ b/freeglut-1.3/freeglut_structure.c @@ -32,7 +32,7 @@ #define G_LOG_DOMAIN "freeglut-structure" #include "../include/GL/freeglut.h" -#include "../include/GL/freeglut_internal.h" +#include "freeglut_internal.h" /* -- GLOBAL EXPORTS ------------------------------------------------------- */ @@ -52,19 +52,19 @@ SFG_Structure fgStructure; * * If parent is set to NULL, the window created will be a topmost one. */ -SFG_Window* fgCreateWindow( SFG_Window* parent, const gchar* title, gint x, gint y, gint w, gint h, gboolean gameMode ) +SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title, int x, int y, int w, int h, GLboolean gameMode ) { /* * Have the window object created */ - SFG_Window* window = g_new0( SFG_Window, 1 ); - gint fakeArgc = 0; + SFG_Window* window = calloc( sizeof(SFG_Window), 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.Timer == NULL ) + if( !fgState.Time.Set ) glutInit( &fakeArgc, NULL ); /* @@ -73,6 +73,11 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const gchar* title, gint x, gint window->ID = ++fgStructure.WindowID; /* + * Initialize the children list + */ + fgListInit( &window->Children ); + + /* * Does this window have a parent? */ if( parent != NULL ) @@ -80,7 +85,7 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const gchar* title, gint x, gint /* * That's quite right, attach this windows as a child window */ - parent->Children = g_list_append( parent->Children, window ); + fgListAppend( &parent->Children, &window->Node ); window->Parent = parent; } else @@ -88,7 +93,7 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const gchar* title, gint x, gint /* * Otherwise add the newly created window to the topmost windows list */ - fgStructure.Windows = g_list_append( fgStructure.Windows, window ); + fgListAppend( &fgStructure.Windows, &window->Node ); } /* @@ -101,7 +106,7 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const gchar* title, gint x, gint * 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 ); + fgOpenWindow( window, title, x, y, w, h, gameMode, (parent != NULL) ? TRUE : FALSE ); /* * Return a pointer to the newly created window @@ -117,14 +122,14 @@ SFG_Menu* fgCreateMenu( FGCBmenu menuCallback ) /* * Have the menu object created */ - SFG_Menu* menu = g_new0( SFG_Menu, 1 ); - gint fakeArgc = 0; + SFG_Menu* 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.Timer == NULL ) + if( !fgState.Time.Set ) glutInit( &fakeArgc, NULL ); /* @@ -134,9 +139,14 @@ SFG_Menu* fgCreateMenu( FGCBmenu menuCallback ) menu->Callback = menuCallback; /* + * Initialize the entries list + */ + fgListInit( &menu->Entries ); + + /* * Add it to the menu structure hierarchy */ - fgStructure.Menus = g_list_append( fgStructure.Menus, menu ); + fgListAppend( &fgStructure.Menus, &menu->Node ); /* * Newly created menus implicitly become current ones @@ -150,105 +160,157 @@ SFG_Menu* fgCreateMenu( FGCBmenu menuCallback ) } /* - * This function destroys a window and all of it's subwindows. Actually, + * 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 ) +{ + 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; + + /* + * If the destroyed window has the highest window ID number, decrement the window ID number + */ + 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 () +{ + 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 ; + + if ( !window_ptr ) + { + window_ptr = WindowsToDestroy ; + WindowsToDestroy = (SFG_WindowList*)NULL ; + } + } +} + +/* + * This function destroys a window and all of its subwindows. Actually, * another function, defined in freeglut_window.c is called, but this is * a whole different story... */ -void fgDestroyWindow( SFG_Window* window, gboolean needToClose ) +void fgDestroyWindow( SFG_Window* window, GLboolean needToClose ) { - int i; + SFG_Window* subWindow; - g_assert( window != NULL ); + assert( window != NULL ); freeglut_assert_ready; /* * Does this window have any subwindows? */ - if( window->Children != NULL ) + while ( (subWindow = window->Children.First) != NULL ) { /* - * OKi, while there are any subwindows left... + * Destroy the first window in the list (possibly destroying + * its subwindows too). This is not very effective, but works */ - while( g_list_first( window->Children ) != NULL ) - { - SFG_Window* subWindow = g_list_first( window->Children )->data; - - /* - * Destroy the first window in the list (possibly destroying - * it's subwindows too. This is not very effective, but works - */ - fgDestroyWindow( subWindow, TRUE ); - - /* - * Remove the just destroyed node from the subwindows list - */ - window->Children = g_list_remove( window->Children, subWindow ); - } - - /* - * Have the list freed now (probably it already is, but you can - * never be sure with no GLib documentation on your hdd...) - */ - g_list_free( window->Children ); - window->Children = NULL; + fgDestroyWindow( subWindow, needToClose ); } /* - * Now we should remove the reference to this window from it's parent - */ - if( window->Parent != NULL ) - window->Parent->Children = g_list_remove( window->Parent->Children, window ); - - /* - * OK, this window seems disconnected from the structure enough - * in order to be closed without any bigger risks... + * If the programmer defined a destroy callback, call it + * A. Donev: But first make this the active window */ - if( needToClose == TRUE ) - fgCloseWindow( window ); + if ( window->Callbacks.Destroy != NULL ) + { + SFG_Window *activeWindow = fgStructure.Window ; + fgStructure.Window = window ; + window->Callbacks.Destroy () ; + fgStructure.Window = activeWindow ; + } /* - * Try removing the window from the parents list in fgStructure. - * This might fail as the window is not guaranteed to be there: + * Now we should remove the reference to this window from its parent */ - fgStructure.Windows = g_list_remove( fgStructure.Windows, window ); + if ( window->Parent != NULL ) + fgListRemove( &window->Parent->Children, &window->Node ); + else + fgListRemove( &fgStructure.Windows, &window->Node ); /* - * Check if the window is the current one... + * OK, this window seems disconnected from the structure enough + * in order to be closed without any bigger risks... */ - if( fgStructure.Window == window ) - fgStructure.Window = NULL; + if( needToClose == TRUE ) + fgCloseWindow( window ); /* * Finally, we can delete the window's object. It hopefully does * have everything inside it freed and we do not have to care... */ - g_free( window ); + free( window ); } /* - * This is a helper static function that removes a menu (given it's pointer) + * This is a helper static function that removes a menu (given its pointer) * from any windows that can be accessed from a given parent... */ static void fghRemoveMenuFromWindow( SFG_Window* window, SFG_Menu* menu ) { - gint i; + SFG_Window *subWindow; + int i; /* * 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++ ) + { if( window->Menu[ i ] == menu ) window->Menu[ i ] = NULL; + } /* * Call this function for all of the window's children recursively: */ - for( i=0; i<(gint) g_list_length( window->Children ); i++ ) - fghRemoveMenuFromWindow( - (SFG_Window *) g_list_nth( window->Children, i )->data, - menu - ); + for( subWindow = window->Children.First; subWindow; + subWindow = subWindow->Node.Next) + { + fghRemoveMenuFromWindow( subWindow, menu ); + } } /* @@ -257,49 +319,15 @@ static void fghRemoveMenuFromWindow( SFG_Window* window, SFG_Menu* menu ) */ static void fghRemoveMenuFromMenu( SFG_Menu* from, SFG_Menu* menu ) { - gboolean found = FALSE; - - /* - * Do not allow removing a menu from itself... - */ - if( from == menu ) - return; + SFG_MenuEntry *entry; - /* - * Look up for the first entry that matches the given - * menu and have it removed, then search again and again: - */ - do + for( entry = from->Entries.First; entry; entry = entry->Node.Next ) + { + if (entry->SubMenu == menu) { - /* - * Try searching for the incriminated menu entry - */ - GList* where = g_list_find( from->Entries, menu ); - - /* - * Make sure we still have a list to be searched - */ - if( where != NULL ) - { - /* - * Did we actually find the menu entry we want to remove? - */ - found = ((SFG_Menu *) where->data == menu); - - /* - * Need to check that, as the search might have failed - */ - if( found ) - from->Entries = g_list_remove( from->Entries, menu ); - } - else - { - /* - * It would be nice if we had a stop rule ;-) - */ - found = FALSE; - } - } while( found == TRUE ); + entry->SubMenu = NULL; + } + } } /* @@ -308,69 +336,75 @@ static void fghRemoveMenuFromMenu( SFG_Menu* from, SFG_Menu* menu ) */ void fgDestroyMenu( SFG_Menu* menu ) { - gint i; - - g_assert( menu != NULL ); - freeglut_assert_ready; - - /* - * First of all, have all references to this menu removed from all windows: - */ - for( i=0; i<(gint) g_list_length( fgStructure.Windows ); i++ ) - fghRemoveMenuFromWindow( - (SFG_Window *) g_list_nth( fgStructure.Windows, i )->data, - menu - ); - - /* - * Now proceed with removing menu entries that lead to this menu - */ - for( i=0; i<(gint) g_list_length( fgStructure.Menus ); i++ ) - fghRemoveMenuFromMenu( - (SFG_Menu *) g_list_nth( fgStructure.Menus, i )->data, - menu - ); - - /* - * Now we are pretty sure the menu is not used anywhere - * and that we can remove all of it's entries - */ - for( i=0; i<(gint) g_list_length( menu->Entries ); i++ ) - { - SFG_MenuEntry* entry = (SFG_MenuEntry *) g_list_nth( menu->Entries, i )->data; - - /* - * There might be a string allocated, have it freed: - */ - g_string_free( entry->Text, TRUE ); - - /* - * Deallocate the entry itself: - */ - g_free( entry ); - } - - /* - * Deallocate the entries list - */ - g_list_free( menu->Entries ); - menu->Entries = NULL; - - /* - * Remove the menu from the menus list - */ - fgStructure.Menus = g_list_remove( fgStructure.Menus, menu ); - - /* - * If that menu was the current one... - */ - if( fgStructure.Menu == menu ) - fgStructure.Menu = NULL; - - /* - * Have the menu structure freed - */ - g_free( 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 = fgStructure.Windows.First; window; window = window->Node.Next ) + { + fghRemoveMenuFromWindow( window, menu ); + } + + /* + * Now proceed with removing menu entries that lead to this menu + */ + for( from = fgStructure.Menus.First; from; from = 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 = menu->Entries.First) != NULL ) + { + fgListRemove(&menu->Entries, &entry->Node); + + /* + * There might be a string allocated, have it freed: + */ + free( entry->Text ); + + /* + * Deallocate the entry itself: + */ + free( entry ); + } + + /* + * Remove the menu from the menus list + */ + fgListRemove( &fgStructure.Menus, &menu->Node ); + + /* + * If that menu was the current one... + */ + if( fgStructure.Menu == menu ) + fgStructure.Menu = NULL; + + /* + * Have the menu structure freed + */ + free( menu ); } /* @@ -381,12 +415,14 @@ 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. However we do not need allocating anything, - * as it is done automagically by GLib when appending new entries to both of them. - * Also, no current window/menu is set, as none has been created yet. - */ + /* + * 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); } /* @@ -395,86 +431,90 @@ void fgCreateStructure( void ) */ void fgDestroyStructure( void ) { - /* - * Just make sure we are not called in vain... - */ - freeglut_assert_ready; - - /* - * Make sure all windows and menus have been deallocated - */ - while( fgStructure.Windows != NULL ) - fgDestroyWindow( (SFG_Window *) g_list_first( fgStructure.Windows )->data, TRUE ); - - while( fgStructure.Menus != NULL ) - fgDestroyMenu( (SFG_Menu *) g_list_first( fgStructure.Menus )->data ); + SFG_Window *window; + SFG_Menu *menu; + + /* + * Just make sure we are not called in vain... + */ + freeglut_assert_ready; + + /* + * Make sure all windows and menus have been deallocated + */ + while( (window = fgStructure.Windows.First) != NULL ) + fgDestroyWindow( window, TRUE ); + + while( (menu = fgStructure.Menus.First) != NULL ) + fgDestroyMenu( menu ); } /* * Helper function to enumerate through all registered top-level windows */ -void fgEnumWindows( GFunc enumCallback, SFG_Enumerator* enumerator ) +void fgEnumWindows( FGCBenumerator enumCallback, SFG_Enumerator* enumerator ) { - gint i; + SFG_Window *window; - g_assert( (enumCallback != NULL) && (enumerator != NULL) ); - freeglut_assert_ready; + assert( (enumCallback != NULL) && (enumerator != NULL) ); + freeglut_assert_ready; + /* + * Check every of the top-level windows + */ + for( window = fgStructure.Windows.First; window; + window = window->Node.Next ) + { /* - * Check every of the top-level windows + * Execute the callback... */ - for( i=0; i<(gint) g_list_length( fgStructure.Windows ); i++ ) - { - /* - * Execute the callback... - */ - enumCallback( (gpointer) g_list_nth( fgStructure.Windows, i )->data, (gpointer) enumerator ); + enumCallback( window, enumerator ); - /* - * If it has been marked as 'found', stop searching - */ - if( enumerator->found == TRUE ) - return; - } + /* + * If it has been marked as 'found', stop searching + */ + if( enumerator->found == TRUE ) + return; + } } /* * Helper function to enumerate through all a window's subwindows (single level descent) */ -void fgEnumSubWindows( SFG_Window* window, GFunc enumCallback, SFG_Enumerator* enumerator ) +void fgEnumSubWindows( SFG_Window* window, FGCBenumerator enumCallback, SFG_Enumerator* enumerator ) { - gint i; + SFG_Window *child; - g_assert( (enumCallback != NULL) && (enumerator != NULL) ); - freeglut_assert_ready; + assert( (enumCallback != NULL) && (enumerator != NULL) ); + freeglut_assert_ready; + /* + * Check every of the window's children: + */ + for( child = window->Children.First; child; child = child->Node.Next ) + { /* - * Check every of the window's children: + * Execute the callback... */ - for( i=0; i<(gint) g_list_length( window->Children ); i++ ) - { - /* - * Execute the callback... - */ - enumCallback( (gpointer) g_list_nth( window->Children, i )->data, (gpointer) enumerator ); + enumCallback( child, enumerator ); - /* - * If it has been marked as 'found', stop searching - */ - if( enumerator->found == TRUE ) - return; - } + /* + * If it has been marked as 'found', stop searching + */ + if( enumerator->found == TRUE ) + return; + } } /* - * A static helper function to look for a window given it's handle + * A static helper function to look for a window given its handle */ -static void fghcbWindowByHandle( gpointer window, gpointer enumerator ) +static void fghcbWindowByHandle( SFG_Window *window, SFG_Enumerator *enumerator ) { /* * Make sure we do not overwrite our precious results... */ - freeglut_return_if_fail( ((SFG_Enumerator *) enumerator)->found == FALSE ); + freeglut_return_if_fail( enumerator->found == FALSE ); #if TARGET_HOST_UNIX_X11 #define WBHANDLE (Window) @@ -485,10 +525,10 @@ static void fghcbWindowByHandle( gpointer window, gpointer enumerator ) /* * Check the window's handle. Hope this works. Looks ugly. That's for sure. */ - if( ((SFG_Window *) window)->Window.Handle == (WBHANDLE ((SFG_Enumerator *) enumerator)->data) ) + if( window->Window.Handle == WBHANDLE (enumerator->data) ) { - ((SFG_Enumerator *) enumerator)->found = TRUE; - ((SFG_Enumerator *) enumerator)->data = (gpointer) window; + enumerator->found = TRUE; + enumerator->data = window; return; } @@ -496,7 +536,7 @@ static void fghcbWindowByHandle( gpointer window, gpointer enumerator ) /* * Otherwise, check this window's children */ - fgEnumSubWindows( (SFG_Window *) window, fghcbWindowByHandle, enumerator ); + fgEnumSubWindows( window, fghcbWindowByHandle, enumerator ); #undef WBHANDLE } @@ -519,7 +559,7 @@ SFG_Window* fgWindowByHandle * This is easy and makes use of the windows enumeration defined above */ enumerator.found = FALSE; - enumerator.data = (gpointer) hWindow; + enumerator.data = (void *)hWindow; /* * Start the enumeration now: @@ -539,22 +579,22 @@ SFG_Window* fgWindowByHandle } /* - * A static helper function to look for a window given it's ID + * A static helper function to look for a window given its ID */ -static void fghcbWindowByID( gpointer window, gpointer enumerator ) +static void fghcbWindowByID( SFG_Window *window, SFG_Enumerator *enumerator ) { /* * Make sure we do not overwrite our precious results... */ - g_return_if_fail( ((SFG_Enumerator *) enumerator)->found == FALSE ); + freeglut_return_if_fail( enumerator->found == FALSE ); /* * Check the window's handle. Hope this works. Looks ugly. That's for sure. */ - if( ((SFG_Window *) window)->ID == (gint) (((SFG_Enumerator *) enumerator)->data) ) + if( window->ID == (int) (enumerator->data) ) { - ((SFG_Enumerator *) enumerator)->found = TRUE; - ((SFG_Enumerator *) enumerator)->data = (gpointer) window; + enumerator->found = TRUE; + enumerator->data = window; return; } @@ -562,7 +602,7 @@ static void fghcbWindowByID( gpointer window, gpointer enumerator ) /* * Otherwise, check this window's children */ - fgEnumSubWindows( (SFG_Window *) window, fghcbWindowByID, enumerator ); + fgEnumSubWindows( window, fghcbWindowByID, enumerator ); } /* @@ -570,7 +610,7 @@ static void fghcbWindowByID( gpointer window, gpointer enumerator ) * looking for a specified (sub)window identifier. The function * is defined in freeglut_structure.c file. */ -SFG_Window* fgWindowByID( gint windowID ) +SFG_Window* fgWindowByID( int windowID ) { SFG_Enumerator enumerator; @@ -578,7 +618,7 @@ SFG_Window* fgWindowByID( gint windowID ) * Uses a method very similiar for fgWindowByHandle... */ enumerator.found = FALSE; - enumerator.data = (gpointer) windowID; + enumerator.data = (void *) windowID; /* * Start the enumeration now: @@ -598,27 +638,21 @@ SFG_Window* fgWindowByID( gint windowID ) } /* - * Looks up a menu given it's ID. This is easier that fgWindowByXXX + * Looks up a menu given its ID. This is easier that fgWindowByXXX * as all menus are placed in a single doubly linked list... */ -SFG_Menu* fgMenuByID( gint menuID ) +SFG_Menu* fgMenuByID( int menuID ) { SFG_Menu *menu = NULL; - gint i; freeglut_assert_ready; /* * It's enough to check all entries in fgStructure.Menus... */ - for( i=0; i<(gint) g_list_length( fgStructure.Menus ); i++ ) + for( menu = fgStructure.Menus.First; menu; menu = menu->Node.Next ) { /* - * Grab the n-th element of the menu objects list... - */ - menu = (SFG_Menu *) g_list_nth( fgStructure.Menus, i )->data; - - /* * Does the ID number match? */ if( menu->ID == menuID ) @@ -631,13 +665,57 @@ SFG_Menu* fgMenuByID( gint menuID ) return( NULL ); } -/*** END OF FILE ***/ - +/* + * List functions... + */ +void fgListInit(SFG_List *list) +{ + list->First = NULL; + list->Last = NULL; +} +void fgListAppend(SFG_List *list, SFG_Node *node) +{ + SFG_Node *ln; + if ( (ln = list->Last) != NULL ) + { + ln->Next = node; + node->Prev = ln; + } + else + { + node->Prev = NULL; + list->First = node; + } + node->Next = NULL; + list->Last = node; +} +void fgListRemove(SFG_List *list, SFG_Node *node) +{ + SFG_Node *ln; + + if ( (ln = node->Next) != NULL ) + ln->Prev = node->Prev; + if ( (ln = node->Prev) != NULL ) + ln->Next = node->Next; + if ( (ln = list->First) == node ) + list->First = node->Next; + if ( (ln = list->Last) == node ) + list->Last = node->Prev; +} +int fgListLength(SFG_List *list) +{ + SFG_Node *node; + int length = 0; + for( node = list->First; node; node = node->Next ) + ++length; + return( length ); +} +/*** END OF FILE ***/