X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;ds=sidebyside;f=src%2Ffreeglut_structure.c;fp=src%2Ffreeglut_structure.c;h=0000000000000000000000000000000000000000;hb=d2f7ea29ea6d946f455f4363c3f058ff2bdfba35;hp=c5a2d734ed28f0632e053ac00346e84e11b77046;hpb=67e12a9904a16f2765c33dcd75b31926691416f1;p=freeglut diff --git a/src/freeglut_structure.c b/src/freeglut_structure.c deleted file mode 100644 index c5a2d73..0000000 --- a/src/freeglut_structure.c +++ /dev/null @@ -1,598 +0,0 @@ -/* - * freeglut_structure.c - * - * Windows and menus need tree structure - * - * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. - * Written by Pawel W. Olszta, - * Creation date: Sat Dec 18 1999 - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include -#include "freeglut_internal.h" - -/* -- GLOBAL EXPORTS ------------------------------------------------------- */ - -/* - * The SFG_Structure container holds information about windows and menus - * created between glutInit() and glutMainLoop() return. - */ - -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 */ - NULL, /* The game mode window */ - 0, /* The current new window ID */ - 0 }; /* The current new menu ID */ - - -/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */ - -static void fghClearCallBacks( SFG_Window *window ) -{ - if( 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... - * - * If parent is set to NULL, the window created will be a topmost one. - */ -SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title, - GLboolean positionUse, int x, int y, - GLboolean sizeUse, int w, int h, - GLboolean gameMode, GLboolean isMenu ) -{ - /* Have the window object created */ - SFG_Window *window = (SFG_Window *)calloc( sizeof(SFG_Window), 1 ); - -#if TARGET_HOST_UNIX_X11 - window->Window.FBConfig = NULL; -#endif - fghClearCallBacks( window ); - - /* Initialize the object properties */ - window->ID = ++fgStructure.WindowID; -#if TARGET_HOST_POSIX_X11 - window->State.OldHeight = window->State.OldWidth = -1; -#endif - - fgListInit( &window->Children ); - if( parent ) - { - fgListAppend( &parent->Children, &window->Node ); - window->Parent = parent; - } - else - fgListAppend( &fgStructure.Windows, &window->Node ); - - /* 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; - window->State.IsFullscreen = GL_FALSE; - - /* - * Open the window now. The fgOpenWindow() function is system - * dependant, and resides in freeglut_window.c. Uses fgState. - */ - fgOpenWindow( window, title, positionUse, x, y, sizeUse, w, h, gameMode, - (GLboolean)(parent ? GL_TRUE : GL_FALSE) ); - - return window; -} - -/* - * This private function creates a menu and adds it to the menus list - */ -SFG_Menu* fgCreateMenu( FGCBMenu menuCallback ) -{ - int x = 100, y = 100, w = 1, h = 1; - SFG_Window *current_window = fgStructure.CurrentWindow; - - /* Have the menu object created */ - SFG_Menu* menu = (SFG_Menu *)calloc( sizeof(SFG_Menu), 1 ); - - menu->ParentWindow = NULL; - - /* Create a window for the menu to reside in. */ - - 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: */ - menu->ID = ++fgStructure.MenuID; - menu->Callback = menuCallback; - menu->ActiveEntry = NULL; - - fgListInit( &menu->Entries ); - fgListAppend( &fgStructure.Menus, &menu->Node ); - - /* Newly created menus implicitly become current ones */ - fgStructure.CurrentMenu = menu; - - return menu; -} - -/* - * 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 ) -{ - SFG_WindowList *new_list_entry = - ( SFG_WindowList* )malloc( sizeof(SFG_WindowList ) ); - new_list_entry->window = window; - fgListAppend( &fgStructure.WindowsToDestroy, &new_list_entry->node ); - - /* Check if the window is the current one... */ - if( fgStructure.CurrentWindow == window ) - fgStructure.CurrentWindow = NULL; - - /* - * 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. - */ - { - FGCBDestroy destroy = (FGCBDestroy)FETCH_WCB( *window, Destroy ); - fghClearCallBacks( window ); - SET_WCB( *window, Destroy, destroy ); - } -} - -/* - * Function to close down all the windows in the "WindowsToDestroy" list - */ -void fgCloseWindows( ) -{ - while( fgStructure.WindowsToDestroy.First ) - { - SFG_WindowList *window_ptr = fgStructure.WindowsToDestroy.First; - fgDestroyWindow( window_ptr->window ); - fgListRemove( &fgStructure.WindowsToDestroy, &window_ptr->node ); - free( window_ptr ); - } -} - -/* - * 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 ) -{ - FREEGLUT_INTERNAL_ERROR_EXIT ( window, "Window destroy function called with null window", - "fgDestroyWindow" ); - - while( window->Children.First ) - fgDestroyWindow( ( SFG_Window * )window->Children.First ); - - { - SFG_Window *activeWindow = fgStructure.CurrentWindow; - INVOKE_WCB( *window, Destroy, ( ) ); - fgSetWindow( activeWindow ); - } - - if( window->Parent ) - fgListRemove( &window->Parent->Children, &window->Node ); - else - fgListRemove( &fgStructure.Windows, &window->Node ); - - if( window->ActiveMenu ) - fgDeactivateMenu( window ); - - fghClearCallBacks( window ); - fgCloseWindow( window ); - free( window ); - if( fgStructure.CurrentWindow == window ) - fgStructure.CurrentWindow = NULL; -} - -/* - * 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 ) -{ - 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 < FREEGLUT_MAX_MENUS; 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; - subWindow = (SFG_Window *)subWindow->Node.Next) - fghRemoveMenuFromWindow( subWindow, menu ); -} - -/* - * This is a static helper function that removes menu references - * from another menu, given two pointers to them... - */ -static void fghRemoveMenuFromMenu( SFG_Menu* from, SFG_Menu* menu ) -{ - SFG_MenuEntry *entry; - - for( entry = (SFG_MenuEntry *)from->Entries.First; - entry; - entry = ( SFG_MenuEntry * )entry->Node.Next ) - if( entry->SubMenu == menu ) - entry->SubMenu = NULL; -} - -/* - * This function destroys a menu specified by the parameter. All menus - * and windows are updated to make sure no ill pointers hang around. - */ -void fgDestroyMenu( SFG_Menu* menu ) -{ - SFG_Window *window; - SFG_Menu *from; - - 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: */ - 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.CurrentMenu; - fgStructure.CurrentMenu = menu; - menu->Destroy( ); - fgStructure.CurrentMenu = activeMenu; - } - - /* - * Now we are pretty sure the menu is not used anywhere - * and that we can remove all of its entries - */ - while( menu->Entries.First ) - { - SFG_MenuEntry *entry = ( SFG_MenuEntry * ) menu->Entries.First; - - fgListRemove( &menu->Entries, &entry->Node ); - - if( entry->Text ) - free( entry->Text ); - entry->Text = NULL; - - free( entry ); - } - - if( fgStructure.CurrentWindow == menu->Window ) - fgSetWindow( NULL ); - fgDestroyWindow( menu->Window ); - fgListRemove( &fgStructure.Menus, &menu->Node ); - if( fgStructure.CurrentMenu == menu ) - fgStructure.CurrentMenu = NULL; - - free( menu ); -} - -/* - * This function should be called on glutInit(). It will prepare the internal - * structure of freeglut to be used in the application. The structure will be - * destroyed using fgDestroyStructure() on glutMainLoop() return. In that - * case further use of freeglut should be preceeded with a glutInit() call. - */ -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); - fgListInit(&fgStructure.WindowsToDestroy); - - fgStructure.CurrentWindow = NULL; - fgStructure.CurrentMenu = NULL; - fgStructure.MenuContext = NULL; - fgStructure.GameModeWindow = NULL; - fgStructure.WindowID = 0; - fgStructure.MenuID = 0; -} - -/* - * This function is automatically called on glutMainLoop() return. - * It should deallocate and destroy all remnants of previous - * glutInit()-enforced structure initialization... - */ -void fgDestroyStructure( void ) -{ - /* Clean up the WindowsToDestroy list. */ - fgCloseWindows( ); - - /* 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 ); -} - -/* - * Helper function to enumerate through all registered top-level windows - */ -void fgEnumWindows( FGCBenumerator enumCallback, SFG_Enumerator* enumerator ) -{ - SFG_Window *window; - - FREEGLUT_INTERNAL_ERROR_EXIT ( enumCallback && enumerator, - "Enumerator or callback missing from window enumerator call", - "fgEnumWindows" ); - - /* 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; - } -} - -/* - * Helper function to enumerate through all a window's subwindows - * (single level descent) - */ -void fgEnumSubWindows( SFG_Window* window, FGCBenumerator enumCallback, - SFG_Enumerator* enumerator ) -{ - SFG_Window *child; - - 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; - child = ( SFG_Window * )child->Node.Next ) - { - enumCallback( child, enumerator ); - if( enumerator->found ) - return; - } -} - -/* - * A static helper function to look for a window given its handle - */ -static void fghcbWindowByHandle( SFG_Window *window, - SFG_Enumerator *enumerator ) -{ - if ( enumerator->found ) - return; - - /* 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; - - return; - } - - /* Otherwise, check this window's children */ - fgEnumSubWindows( window, fghcbWindowByHandle, enumerator ); -} - -/* - * fgWindowByHandle returns a (SFG_Window *) value pointing to the - * first window in the queue matching the specified window handle. - * The function is defined in freeglut_structure.c file. - */ -SFG_Window* fgWindowByHandle ( SFG_WindowHandleType hWindow ) -{ - SFG_Enumerator enumerator; - - /* This is easy and makes use of the windows enumeration defined above */ - enumerator.found = GL_FALSE; - enumerator.data = (void *)hWindow; - fgEnumWindows( fghcbWindowByHandle, &enumerator ); - - if( enumerator.found ) - return( SFG_Window *) enumerator.data; - return NULL; -} - -/* - * A static helper function to look for a window given its ID - */ -static void fghcbWindowByID( SFG_Window *window, SFG_Enumerator *enumerator ) -{ - /* 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) ) - { - enumerator->found = GL_TRUE; - enumerator->data = window; - - return; - } - - /* Otherwise, check this window's children */ - fgEnumSubWindows( window, fghcbWindowByID, enumerator ); -} - -/* - * This function is similiar to the previous one, except it is - * looking for a specified (sub)window identifier. The function - * is defined in freeglut_structure.c file. - */ -SFG_Window* fgWindowByID( int windowID ) -{ - SFG_Enumerator enumerator; - - /* Uses a method very similiar for fgWindowByHandle... */ - enumerator.found = GL_FALSE; - enumerator.data = ( void * )&windowID; - fgEnumWindows( fghcbWindowByID, &enumerator ); - if( enumerator.found ) - 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 one doubly linked list... - */ -SFG_Menu* fgMenuByID( int menuID ) -{ - SFG_Menu *menu = NULL; - - /* It's enough to check all entries in fgStructure.Menus... */ - for( menu = (SFG_Menu *)fgStructure.Menus.First; - menu; - menu = (SFG_Menu *)menu->Node.Next ) - if( menu->ID == menuID ) - return menu; - return NULL; -} - -/* - * List functions... - */ -void fgListInit(SFG_List *list) -{ - list->First = NULL; - list->Last = NULL; -} - -void fgListAppend(SFG_List *list, SFG_Node *node) -{ - if ( list->Last ) - { - SFG_Node *ln = (SFG_Node *) list->Last; - 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) -{ - 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( ( ( SFG_Node * )list->Last ) == node ) - list->Last = node->Prev; -} - -int fgListLength(SFG_List *list) -{ - SFG_Node *node; - int length = 0; - - 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 ***/