-/*\r
- * freeglut_init.c\r
- *\r
- * Various freeglut initialization functions.\r
- *\r
- * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.\r
- * Written by Pawel W. Olszta, <olszta@sourceforge.net>\r
- * Creation date: Thu Dec 2 1999\r
- *\r
- * Permission is hereby granted, free of charge, to any person obtaining a\r
- * copy of this software and associated documentation files (the "Software"),\r
- * to deal in the Software without restriction, including without limitation\r
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
- * and/or sell copies of the Software, and to permit persons to whom the\r
- * Software is furnished to do so, subject to the following conditions:\r
- *\r
- * The above copyright notice and this permission notice shall be included\r
- * in all copies or substantial portions of the Software.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
- */\r
-\r
-#define FREEGLUT_BUILDING_LIB\r
-#include <GL/freeglut.h>\r
-#include "freeglut_internal.h"\r
-\r
-#if TARGET_HOST_POSIX_X11\r
-#include <limits.h> /* LONG_MAX */\r
-#endif\r
-\r
-/*\r
- * TODO BEFORE THE STABLE RELEASE:\r
- *\r
- * fgDeinitialize() -- Win32's OK, X11 needs the OS-specific\r
- * deinitialization done\r
- * glutInitDisplayString() -- display mode string parsing\r
- *\r
- * Wouldn't it be cool to use gettext() for error messages? I just love\r
- * bash saying "nie znaleziono pliku" instead of "file not found" :)\r
- * Is gettext easily portable?\r
- */\r
-\r
-/* -- GLOBAL VARIABLES ----------------------------------------------------- */\r
-\r
-/*\r
- * A structure pointed by g_pDisplay holds all information\r
- * regarding the display, screen, root window etc.\r
- */\r
-SFG_Display fgDisplay;\r
-\r
-/*\r
- * The settings for the current freeglut session\r
- */\r
-SFG_State fgState = { { -1, -1, GL_FALSE }, /* Position */\r
- { 300, 300, GL_TRUE }, /* Size */\r
- GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH, /* DisplayMode */\r
- GL_FALSE, /* Initialised */\r
- GLUT_TRY_DIRECT_CONTEXT, /* DirectContext */\r
- GL_FALSE, /* ForceIconic */\r
- GL_FALSE, /* UseCurrentContext */\r
- GL_FALSE, /* GLDebugSwitch */\r
- GL_FALSE, /* XSyncSwitch */\r
- GLUT_KEY_REPEAT_ON, /* KeyRepeat */\r
- INVALID_MODIFIERS, /* Modifiers */\r
- 0, /* FPSInterval */\r
- 0, /* SwapCount */\r
- 0, /* SwapTime */\r
- 0, /* Time */\r
- { NULL, NULL }, /* Timers */\r
- { NULL, NULL }, /* FreeTimers */\r
- NULL, /* IdleCallback */\r
- 0, /* ActiveMenus */\r
- NULL, /* MenuStateCallback */\r
- NULL, /* MenuStatusCallback */\r
- { 640, 480, GL_TRUE }, /* GameModeSize */\r
- 16, /* GameModeDepth */\r
- 72, /* GameModeRefresh */\r
- GLUT_ACTION_EXIT, /* ActionOnWindowClose */\r
- GLUT_EXEC_STATE_INIT, /* ExecState */\r
- NULL, /* ProgramName */\r
- GL_FALSE, /* JoysticksInitialised */\r
- 0, /* NumActiveJoysticks */\r
- GL_FALSE, /* InputDevsInitialised */\r
- 0, /* MouseWheelTicks */\r
- 1, /* AuxiliaryBufferNumber */\r
- 4, /* SampleNumber */\r
- 1, /* MajorVersion */\r
- 0, /* MinorVersion */\r
- 0, /* ContextFlags */\r
- 0, /* ContextProfile */\r
- NULL, /* ErrorFunc */\r
- NULL /* WarningFunc */\r
-};\r
-\r
-\r
-/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */\r
-\r
-extern void fghInitialize( const char* displayName );\r
-extern void fghDeinitialiseInputDevices ( void );\r
-extern void fghCloseDisplay ( void );\r
-\r
-#if TARGET_HOST_POSIX_X11\r
-\r
-/* Return the atom associated with "name". */\r
-static Atom fghGetAtom(const char * name)\r
-{\r
- return XInternAtom(fgDisplay.Display, name, False);\r
-}\r
-\r
-/*\r
- * Check if "property" is set on "window". The property's values are returned\r
- * through "data". If the property is set and is of type "type", return the\r
- * number of elements in "data". Return zero otherwise. In both cases, use\r
- * "Xfree()" to free "data".\r
- */\r
-static int fghGetWindowProperty(Window window,\r
- Atom property,\r
- Atom type,\r
- unsigned char ** data)\r
-{\r
- /*\r
- * Caller always has to use "Xfree()" to free "data", since\r
- * "XGetWindowProperty() always allocates one extra byte in prop_return\r
- * [i.e. "data"] (even if the property is zero length) [..]".\r
- */\r
-\r
- int status; /* Returned by "XGetWindowProperty". */\r
-\r
- Atom type_returned;\r
- int temp_format; /* Not used. */\r
- unsigned long number_of_elements;\r
- unsigned long temp_bytes_after; /* Not used. */\r
-\r
-\r
- status = XGetWindowProperty(fgDisplay.Display,\r
- window,\r
- property,\r
- 0,\r
- LONG_MAX,\r
- False,\r
- type,\r
- &type_returned,\r
- &temp_format,\r
- &number_of_elements,\r
- &temp_bytes_after,\r
- data);\r
-\r
- FREEGLUT_INTERNAL_ERROR_EXIT(status == Success,\r
- "XGetWindowProperty failled",\r
- "fghGetWindowProperty");\r
-\r
- if (type_returned != type)\r
- {\r
- number_of_elements = 0;\r
- }\r
-\r
- return number_of_elements;\r
-}\r
-\r
-/* Check if the window manager is NET WM compliant. */\r
-static int fghNetWMSupported(void)\r
-{\r
- Atom wm_check;\r
- Window ** window_ptr_1;\r
-\r
- int number_of_windows;\r
- int net_wm_supported;\r
-\r
-\r
- net_wm_supported = 0;\r
-\r
- wm_check = fghGetAtom("_NET_SUPPORTING_WM_CHECK");\r
- window_ptr_1 = malloc(sizeof(Window *));\r
-\r
- /*\r
- * Check that the window manager has set this property on the root window.\r
- * The property must be the ID of a child window.\r
- */\r
- number_of_windows = fghGetWindowProperty(fgDisplay.RootWindow,\r
- wm_check,\r
- XA_WINDOW,\r
- (unsigned char **) window_ptr_1);\r
- if (number_of_windows == 1)\r
- {\r
- Window ** window_ptr_2;\r
-\r
- window_ptr_2 = malloc(sizeof(Window *));\r
-\r
- /* Check that the window has the same property set to the same value. */\r
- number_of_windows = fghGetWindowProperty(**window_ptr_1,\r
- wm_check,\r
- XA_WINDOW,\r
- (unsigned char **) window_ptr_2);\r
- if ((number_of_windows == 1) && (**window_ptr_1 == **window_ptr_2))\r
- {\r
- /* NET WM compliant */\r
- net_wm_supported = 1;\r
- }\r
-\r
- XFree(*window_ptr_2);\r
- free(window_ptr_2);\r
- }\r
-\r
- XFree(*window_ptr_1);\r
- free(window_ptr_1);\r
-\r
- return net_wm_supported;\r
-}\r
-\r
-/* Check if "hint" is present in "property" for "window". */\r
-int fgHintPresent(Window window, Atom property, Atom hint)\r
-{\r
- Atom *atoms;\r
- int number_of_atoms;\r
- int supported;\r
- int i;\r
-\r
- supported = 0;\r
-\r
- number_of_atoms = fghGetWindowProperty(window,\r
- property,\r
- XA_ATOM,\r
- (unsigned char **) &atoms);\r
- for (i = 0; i < number_of_atoms; i++)\r
- {\r
- if (atoms[i] == hint)\r
- {\r
- supported = 1;\r
- break;\r
- }\r
- }\r
-\r
- XFree(atoms);\r
- return supported;\r
-}\r
-\r
-#endif /* TARGET_HOST_POSIX_X11 */\r
-\r
-\r
-#if TARGET_HOST_POSIX_X11\r
-/*\r
- * A call to this function should initialize all the display stuff...\r
- */\r
-static void fghInitialize( const char* displayName )\r
-{\r
- fgDisplay.Display = XOpenDisplay( displayName );\r
-\r
- if( fgDisplay.Display == NULL )\r
- fgError( "failed to open display '%s'", XDisplayName( displayName ) );\r
-\r
- if( !glXQueryExtension( fgDisplay.Display, NULL, NULL ) )\r
- fgError( "OpenGL GLX extension not supported by display '%s'",\r
- XDisplayName( displayName ) );\r
-\r
- fgDisplay.Screen = DefaultScreen( fgDisplay.Display );\r
- fgDisplay.RootWindow = RootWindow(\r
- fgDisplay.Display,\r
- fgDisplay.Screen\r
- );\r
-\r
- fgDisplay.ScreenWidth = DisplayWidth(\r
- fgDisplay.Display,\r
- fgDisplay.Screen\r
- );\r
- fgDisplay.ScreenHeight = DisplayHeight(\r
- fgDisplay.Display,\r
- fgDisplay.Screen\r
- );\r
-\r
- fgDisplay.ScreenWidthMM = DisplayWidthMM(\r
- fgDisplay.Display,\r
- fgDisplay.Screen\r
- );\r
- fgDisplay.ScreenHeightMM = DisplayHeightMM(\r
- fgDisplay.Display,\r
- fgDisplay.Screen\r
- );\r
-\r
- fgDisplay.Connection = ConnectionNumber( fgDisplay.Display );\r
-\r
- /* Create the window deletion atom */\r
- fgDisplay.DeleteWindow = fghGetAtom("WM_DELETE_WINDOW");\r
-\r
- /* Create the state and full screen atoms */\r
- fgDisplay.State = None;\r
- fgDisplay.StateFullScreen = None;\r
-\r
- if (fghNetWMSupported())\r
- {\r
- const Atom supported = fghGetAtom("_NET_SUPPORTED");\r
- const Atom state = fghGetAtom("_NET_WM_STATE");\r
- \r
- /* Check if the state hint is supported. */\r
- if (fgHintPresent(fgDisplay.RootWindow, supported, state))\r
- {\r
- const Atom full_screen = fghGetAtom("_NET_WM_STATE_FULLSCREEN");\r
- \r
- fgDisplay.State = state;\r
- \r
- /* Check if the window manager supports full screen. */\r
- /** Check "_NET_WM_ALLOWED_ACTIONS" on our window instead? **/\r
- if (fgHintPresent(fgDisplay.RootWindow, supported, full_screen))\r
- {\r
- fgDisplay.StateFullScreen = full_screen;\r
- }\r
- }\r
- }\r
-\r
-\r
- fgState.Initialised = GL_TRUE;\r
-\r
- atexit(fgDeinitialize);\r
-\r
- /* InputDevice uses GlutTimerFunc(), so fgState.Initialised must be TRUE */\r
- fgInitialiseInputDevices();\r
-}\r
-\r
-#endif\r
-\r
-void fghCloseInputDevices ( void )\r
-{\r
- if ( fgState.JoysticksInitialised )\r
- fgJoystickClose( );\r
-\r
- if ( fgState.InputDevsInitialised )\r
- fgInputDeviceClose( );\r
-}\r
-\r
-\r
-#if TARGET_HOST_POSIX_X11\r
-static void fghDeinitialiseInputDevices ( void )\r
-{\r
- fghCloseInputDevices ();\r
-\r
- fgState.JoysticksInitialised = GL_FALSE;\r
- fgState.InputDevsInitialised = GL_FALSE;\r
-}\r
-\r
-\r
-static void fghCloseDisplay ( void )\r
-{\r
- /*\r
- * Make sure all X-client data we have created will be destroyed on\r
- * display closing\r
- */\r
- XSetCloseDownMode( fgDisplay.Display, DestroyAll );\r
-\r
- /*\r
- * Close the display connection, destroying all windows we have\r
- * created so far\r
- */\r
- XCloseDisplay( fgDisplay.Display );\r
-}\r
-\r
-#endif\r
-\r
-\r
-/*\r
- * Perform the freeglut deinitialization...\r
- */\r
-void fgDeinitialize( void )\r
-{\r
- SFG_Timer *timer;\r
-\r
- if( !fgState.Initialised )\r
- {\r
- return;\r
- }\r
-\r
- /* If we're in game mode, we want to leave game mode */\r
- if( fgStructure.GameModeWindow ) {\r
- glutLeaveGameMode();\r
- }\r
-\r
- /* If there was a menu created, destroy the rendering context */\r
- if( fgStructure.MenuContext )\r
- {\r
-#if TARGET_HOST_POSIX_X11\r
- /* Note that the MVisualInfo is not owned by the MenuContext! */\r
- glXDestroyContext( fgDisplay.Display, fgStructure.MenuContext->MContext );\r
-#endif\r
- free( fgStructure.MenuContext );\r
- fgStructure.MenuContext = NULL;\r
- }\r
-\r
- fgDestroyStructure( );\r
-\r
- while( ( timer = fgState.Timers.First) )\r
- {\r
- fgListRemove( &fgState.Timers, &timer->Node );\r
- free( timer );\r
- }\r
-\r
- while( ( timer = fgState.FreeTimers.First) )\r
- {\r
- fgListRemove( &fgState.FreeTimers, &timer->Node );\r
- free( timer );\r
- }\r
-\r
- fghDeinitialiseInputDevices ();\r
-\r
- fgState.MouseWheelTicks = 0;\r
-\r
- fgState.MajorVersion = 1;\r
- fgState.MinorVersion = 0;\r
- fgState.ContextFlags = 0;\r
- fgState.ContextProfile = 0;\r
-\r
- fgState.Initialised = GL_FALSE;\r
-\r
- fgState.Position.X = -1;\r
- fgState.Position.Y = -1;\r
- fgState.Position.Use = GL_FALSE;\r
-\r
- fgState.Size.X = 300;\r
- fgState.Size.Y = 300;\r
- fgState.Size.Use = GL_TRUE;\r
-\r
- fgState.DisplayMode = GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH;\r
-\r
- fgState.DirectContext = GLUT_TRY_DIRECT_CONTEXT;\r
- fgState.ForceIconic = GL_FALSE;\r
- fgState.UseCurrentContext = GL_FALSE;\r
- fgState.GLDebugSwitch = GL_FALSE;\r
- fgState.XSyncSwitch = GL_FALSE;\r
- fgState.ActionOnWindowClose = GLUT_ACTION_EXIT;\r
- fgState.ExecState = GLUT_EXEC_STATE_INIT;\r
-\r
- fgState.KeyRepeat = GLUT_KEY_REPEAT_ON;\r
- fgState.Modifiers = INVALID_MODIFIERS;\r
-\r
- fgState.GameModeSize.X = 640;\r
- fgState.GameModeSize.Y = 480;\r
- fgState.GameModeDepth = 16;\r
- fgState.GameModeRefresh = 72;\r
-\r
- fgListInit( &fgState.Timers );\r
- fgListInit( &fgState.FreeTimers );\r
-\r
- fgState.IdleCallback = NULL;\r
- fgState.MenuStateCallback = ( FGCBMenuState )NULL;\r
- fgState.MenuStatusCallback = ( FGCBMenuStatus )NULL;\r
-\r
- fgState.SwapCount = 0;\r
- fgState.SwapTime = 0;\r
- fgState.FPSInterval = 0;\r
-\r
- if( fgState.ProgramName )\r
- {\r
- free( fgState.ProgramName );\r
- fgState.ProgramName = NULL;\r
- }\r
-\r
- fghCloseDisplay ();\r
-\r
- fgState.Initialised = GL_FALSE;\r
-}\r
-\r
-/*\r
- * Everything inside the following #ifndef is copied from the X sources.\r
- */\r
-\r
-#if TARGET_HOST_MS_WINDOWS\r
-\r
-/*\r
-\r
-Copyright 1985, 1986, 1987,1998 The Open Group\r
-\r
-Permission to use, copy, modify, distribute, and sell this software and its\r
-documentation for any purpose is hereby granted without fee, provided that\r
-the above copyright notice appear in all copies and that both that\r
-copyright notice and this permission notice appear in supporting\r
-documentation.\r
-\r
-The above copyright notice and this permission notice shall be included\r
-in all copies or substantial portions of the Software.\r
-\r
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\r
-IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR\r
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\r
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\r
-OTHER DEALINGS IN THE SOFTWARE.\r
-\r
-Except as contained in this notice, the name of The Open Group shall\r
-not be used in advertising or otherwise to promote the sale, use or\r
-other dealings in this Software without prior written authorization\r
-from The Open Group.\r
-\r
-*/\r
-\r
-#define NoValue 0x0000\r
-#define XValue 0x0001\r
-#define YValue 0x0002\r
-#define WidthValue 0x0004\r
-#define HeightValue 0x0008\r
-#define AllValues 0x000F\r
-#define XNegative 0x0010\r
-#define YNegative 0x0020\r
-\r
-/*\r
- * XParseGeometry parses strings of the form\r
- * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where\r
- * width, height, xoffset, and yoffset are unsigned integers.\r
- * Example: "=80x24+300-49"\r
- * The equal sign is optional.\r
- * It returns a bitmask that indicates which of the four values\r
- * were actually found in the string. For each value found,\r
- * the corresponding argument is updated; for each value\r
- * not found, the corresponding argument is left unchanged.\r
- */\r
-\r
-static int\r
-ReadInteger(char *string, char **NextString)\r
-{\r
- register int Result = 0;\r
- int Sign = 1;\r
-\r
- if (*string == '+')\r
- string++;\r
- else if (*string == '-')\r
- {\r
- string++;\r
- Sign = -1;\r
- }\r
- for (; (*string >= '0') && (*string <= '9'); string++)\r
- {\r
- Result = (Result * 10) + (*string - '0');\r
- }\r
- *NextString = string;\r
- if (Sign >= 0)\r
- return Result;\r
- else\r
- return -Result;\r
-}\r
-\r
-static int XParseGeometry (\r
- const char *string,\r
- int *x,\r
- int *y,\r
- unsigned int *width, /* RETURN */\r
- unsigned int *height) /* RETURN */\r
-{\r
- int mask = NoValue;\r
- register char *strind;\r
- unsigned int tempWidth = 0, tempHeight = 0;\r
- int tempX = 0, tempY = 0;\r
- char *nextCharacter;\r
-\r
- if ( (string == NULL) || (*string == '\0'))\r
- return mask;\r
- if (*string == '=')\r
- string++; /* ignore possible '=' at beg of geometry spec */\r
-\r
- strind = (char *)string;\r
- if (*strind != '+' && *strind != '-' && *strind != 'x') {\r
- tempWidth = ReadInteger(strind, &nextCharacter);\r
- if (strind == nextCharacter)\r
- return 0;\r
- strind = nextCharacter;\r
- mask |= WidthValue;\r
- }\r
-\r
- if (*strind == 'x' || *strind == 'X') {\r
- strind++;\r
- tempHeight = ReadInteger(strind, &nextCharacter);\r
- if (strind == nextCharacter)\r
- return 0;\r
- strind = nextCharacter;\r
- mask |= HeightValue;\r
- }\r
-\r
- if ((*strind == '+') || (*strind == '-')) {\r
- if (*strind == '-') {\r
- strind++;\r
- tempX = -ReadInteger(strind, &nextCharacter);\r
- if (strind == nextCharacter)\r
- return 0;\r
- strind = nextCharacter;\r
- mask |= XNegative;\r
- }\r
- else\r
- {\r
- strind++;\r
- tempX = ReadInteger(strind, &nextCharacter);\r
- if (strind == nextCharacter)\r
- return 0;\r
- strind = nextCharacter;\r
- }\r
- mask |= XValue;\r
- if ((*strind == '+') || (*strind == '-')) {\r
- if (*strind == '-') {\r
- strind++;\r
- tempY = -ReadInteger(strind, &nextCharacter);\r
- if (strind == nextCharacter)\r
- return 0;\r
- strind = nextCharacter;\r
- mask |= YNegative;\r
- }\r
- else\r
- {\r
- strind++;\r
- tempY = ReadInteger(strind, &nextCharacter);\r
- if (strind == nextCharacter)\r
- return 0;\r
- strind = nextCharacter;\r
- }\r
- mask |= YValue;\r
- }\r
- }\r
-\r
- /* If strind isn't at the end of the string the it's an invalid\r
- geometry specification. */\r
-\r
- if (*strind != '\0') return 0;\r
-\r
- if (mask & XValue)\r
- *x = tempX;\r
- if (mask & YValue)\r
- *y = tempY;\r
- if (mask & WidthValue)\r
- *width = tempWidth;\r
- if (mask & HeightValue)\r
- *height = tempHeight;\r
- return mask;\r
-}\r
-#endif\r
-\r
-/* -- INTERFACE FUNCTIONS -------------------------------------------------- */\r
-\r
-/*\r
- * Perform initialization. This usually happens on the program startup\r
- * and restarting after glutMainLoop termination...\r
- */\r
-void FGAPIENTRY glutInit( int* pargc, char** argv )\r
-{\r
- char* displayName = NULL;\r
- char* geometry = NULL;\r
- int i, j, argc = *pargc;\r
-\r
- if( fgState.Initialised )\r
- fgError( "illegal glutInit() reinitialization attempt" );\r
-\r
- if (pargc && *pargc && argv && *argv && **argv)\r
- {\r
- fgState.ProgramName = strdup (*argv);\r
-\r
- if( !fgState.ProgramName )\r
- fgError ("Could not allocate space for the program's name.");\r
- }\r
-\r
- fgCreateStructure( );\r
-\r
- /* Get start time */\r
- fgState.Time = fgSystemTime();\r
-\r
- /* check if GLUT_FPS env var is set */\r
-#ifndef _WIN32_WCE\r
- {\r
- const char *fps = getenv( "GLUT_FPS" );\r
-\r
- if( fps )\r
- {\r
- int interval;\r
- sscanf( fps, "%d", &interval );\r
-\r
- if( interval <= 0 )\r
- fgState.FPSInterval = 5000; /* 5000 millisecond default */\r
- else\r
- fgState.FPSInterval = interval;\r
- }\r
- }\r
-\r
- displayName = getenv( "DISPLAY" );\r
-\r
- for( i = 1; i < argc; i++ )\r
- {\r
- if( strcmp( argv[ i ], "-display" ) == 0 )\r
- {\r
- if( ++i >= argc )\r
- fgError( "-display parameter must be followed by display name" );\r
-\r
- displayName = argv[ i ];\r
-\r
- argv[ i - 1 ] = NULL;\r
- argv[ i ] = NULL;\r
- ( *pargc ) -= 2;\r
- }\r
- else if( strcmp( argv[ i ], "-geometry" ) == 0 )\r
- {\r
- if( ++i >= argc )\r
- fgError( "-geometry parameter must be followed by window "\r
- "geometry settings" );\r
-\r
- geometry = argv[ i ];\r
-\r
- argv[ i - 1 ] = NULL;\r
- argv[ i ] = NULL;\r
- ( *pargc ) -= 2;\r
- }\r
- else if( strcmp( argv[ i ], "-direct" ) == 0)\r
- {\r
- if( fgState.DirectContext == GLUT_FORCE_INDIRECT_CONTEXT )\r
- fgError( "parameters ambiguity, -direct and -indirect "\r
- "cannot be both specified" );\r
-\r
- fgState.DirectContext = GLUT_FORCE_DIRECT_CONTEXT;\r
- argv[ i ] = NULL;\r
- ( *pargc )--;\r
- }\r
- else if( strcmp( argv[ i ], "-indirect" ) == 0 )\r
- {\r
- if( fgState.DirectContext == GLUT_FORCE_DIRECT_CONTEXT )\r
- fgError( "parameters ambiguity, -direct and -indirect "\r
- "cannot be both specified" );\r
-\r
- fgState.DirectContext = GLUT_FORCE_INDIRECT_CONTEXT;\r
- argv[ i ] = NULL;\r
- (*pargc)--;\r
- }\r
- else if( strcmp( argv[ i ], "-iconic" ) == 0 )\r
- {\r
- fgState.ForceIconic = GL_TRUE;\r
- argv[ i ] = NULL;\r
- ( *pargc )--;\r
- }\r
- else if( strcmp( argv[ i ], "-gldebug" ) == 0 )\r
- {\r
- fgState.GLDebugSwitch = GL_TRUE;\r
- argv[ i ] = NULL;\r
- ( *pargc )--;\r
- }\r
- else if( strcmp( argv[ i ], "-sync" ) == 0 )\r
- {\r
- fgState.XSyncSwitch = GL_TRUE;\r
- argv[ i ] = NULL;\r
- ( *pargc )--;\r
- }\r
- }\r
-\r
- /* Compact {argv}. */\r
- for( i = j = 1; i < *pargc; i++, j++ )\r
- {\r
- /* Guaranteed to end because there are "*pargc" arguments left */\r
- while ( argv[ j ] == NULL )\r
- j++;\r
- if ( i != j )\r
- argv[ i ] = argv[ j ];\r
- }\r
-\r
-#endif /* _WIN32_WCE */\r
-\r
- /*\r
- * Have the display created now. If there wasn't a "-display"\r
- * in the program arguments, we will use the DISPLAY environment\r
- * variable for opening the X display (see code above):\r
- */\r
- fghInitialize( displayName );\r
-\r
- /*\r
- * Geometry parsing deffered until here because we may need the screen\r
- * size.\r
- */\r
-\r
- if (geometry )\r
- {\r
- unsigned int parsedWidth, parsedHeight;\r
- int mask = XParseGeometry( geometry,\r
- &fgState.Position.X, &fgState.Position.Y,\r
- &parsedWidth, &parsedHeight );\r
- /* TODO: Check for overflow? */\r
- fgState.Size.X = parsedWidth;\r
- fgState.Size.Y = parsedHeight;\r
-\r
- if( (mask & (WidthValue|HeightValue)) == (WidthValue|HeightValue) )\r
- fgState.Size.Use = GL_TRUE;\r
-\r
- if( mask & XNegative )\r
- fgState.Position.X += fgDisplay.ScreenWidth - fgState.Size.X;\r
-\r
- if( mask & YNegative )\r
- fgState.Position.Y += fgDisplay.ScreenHeight - fgState.Size.Y;\r
-\r
- if( (mask & (XValue|YValue)) == (XValue|YValue) )\r
- fgState.Position.Use = GL_TRUE;\r
- }\r
-}\r
-\r
-#if TARGET_HOST_MS_WINDOWS\r
-void (__cdecl *__glutExitFunc)( int return_value ) = NULL;\r
-\r
-void FGAPIENTRY __glutInitWithExit( int *pargc, char **argv, void (__cdecl *exit_function)(int) )\r
-{\r
- __glutExitFunc = exit_function;\r
- glutInit(pargc, argv);\r
-}\r
-#endif\r
-\r
-/*\r
- * Undoes all the "glutInit" stuff\r
- */\r
-void FGAPIENTRY glutExit ( void )\r
-{\r
- fgDeinitialize ();\r
-}\r
-\r
-/*\r
- * Sets the default initial window position for new windows\r
- */\r
-void FGAPIENTRY glutInitWindowPosition( int x, int y )\r
-{\r
- fgState.Position.X = x;\r
- fgState.Position.Y = y;\r
-\r
- if( ( x >= 0 ) && ( y >= 0 ) )\r
- fgState.Position.Use = GL_TRUE;\r
- else\r
- fgState.Position.Use = GL_FALSE;\r
-}\r
-\r
-/*\r
- * Sets the default initial window size for new windows\r
- */\r
-void FGAPIENTRY glutInitWindowSize( int width, int height )\r
-{\r
- fgState.Size.X = width;\r
- fgState.Size.Y = height;\r
-\r
- if( ( width > 0 ) && ( height > 0 ) )\r
- fgState.Size.Use = GL_TRUE;\r
- else\r
- fgState.Size.Use = GL_FALSE;\r
-}\r
-\r
-/*\r
- * Sets the default display mode for all new windows\r
- */\r
-void FGAPIENTRY glutInitDisplayMode( unsigned int displayMode )\r
-{\r
- /* We will make use of this value when creating a new OpenGL context... */\r
- fgState.DisplayMode = displayMode;\r
-}\r
-\r
-\r
-/* -- INIT DISPLAY STRING PARSING ------------------------------------------ */\r
-\r
-static char* Tokens[] =\r
-{\r
- "alpha", "acca", "acc", "blue", "buffer", "conformant", "depth", "double",\r
- "green", "index", "num", "red", "rgba", "rgb", "luminance", "stencil",\r
- "single", "stereo", "samples", "slow", "win32pdf", "win32pfd", "xvisual",\r
- "xstaticgray", "xgrayscale", "xstaticcolor", "xpseudocolor",\r
- "xtruecolor", "xdirectcolor",\r
- "xstaticgrey", "xgreyscale", "xstaticcolour", "xpseudocolour",\r
- "xtruecolour", "xdirectcolour", "borderless", "aux"\r
-};\r
-#define NUM_TOKENS (sizeof(Tokens) / sizeof(*Tokens))\r
-\r
-void FGAPIENTRY glutInitDisplayString( const char* displayMode )\r
-{\r
- int glut_state_flag = 0 ;\r
- /*\r
- * Unpack a lot of options from a character string. The options are\r
- * delimited by blanks or tabs.\r
- */\r
- char *token ;\r
- size_t len = strlen ( displayMode );\r
- char *buffer = (char *)malloc ( (len+1) * sizeof(char) );\r
- memcpy ( buffer, displayMode, len );\r
- buffer[len] = '\0';\r
-\r
- token = strtok ( buffer, " \t" );\r
-\r
- while ( token )\r
- {\r
- /* Process this token */\r
- int i ;\r
-\r
- /* Temporary fix: Ignore any length specifications and at least\r
- * process the basic token\r
- * TODO: Fix this permanently\r
- */\r
- size_t cleanlength = strcspn ( token, "=<>~!" );\r
-\r
- for ( i = 0; i < NUM_TOKENS; i++ )\r
- {\r
- if ( strncmp ( token, Tokens[i], cleanlength ) == 0 ) break ;\r
- }\r
-\r
- switch ( i )\r
- {\r
- case 0 : /* "alpha": Alpha color buffer precision in bits */\r
- glut_state_flag |= GLUT_ALPHA ; /* Somebody fix this for me! */\r
- break ;\r
-\r
- case 1 : /* "acca": Red, green, blue, and alpha accumulation buffer\r
- precision in bits */\r
- break ;\r
-\r
- case 2 : /* "acc": Red, green, and blue accumulation buffer precision\r
- in bits with zero bits alpha */\r
- glut_state_flag |= GLUT_ACCUM ; /* Somebody fix this for me! */\r
- break ;\r
-\r
- case 3 : /* "blue": Blue color buffer precision in bits */\r
- break ;\r
-\r
- case 4 : /* "buffer": Number of bits in the color index color buffer\r
- */\r
- break ;\r
-\r
- case 5 : /* "conformant": Boolean indicating if the frame buffer\r
- configuration is conformant or not */\r
- break ;\r
-\r
- case 6 : /* "depth": Number of bits of precsion in the depth buffer */\r
- glut_state_flag |= GLUT_DEPTH ; /* Somebody fix this for me! */\r
- break ;\r
-\r
- case 7 : /* "double": Boolean indicating if the color buffer is\r
- double buffered */\r
- glut_state_flag |= GLUT_DOUBLE ;\r
- break ;\r
-\r
- case 8 : /* "green": Green color buffer precision in bits */\r
- break ;\r
-\r
- case 9 : /* "index": Boolean if the color model is color index or not\r
- */\r
- glut_state_flag |= GLUT_INDEX ;\r
- break ;\r
-\r
- case 10 : /* "num": A special capability name indicating where the\r
- value represents the Nth frame buffer configuration\r
- matching the description string */\r
- break ;\r
-\r
- case 11 : /* "red": Red color buffer precision in bits */\r
- break ;\r
-\r
- case 12 : /* "rgba": Number of bits of red, green, blue, and alpha in\r
- the RGBA color buffer */\r
- glut_state_flag |= GLUT_RGBA ; /* Somebody fix this for me! */\r
- break ;\r
-\r
- case 13 : /* "rgb": Number of bits of red, green, and blue in the\r
- RGBA color buffer with zero bits alpha */\r
- glut_state_flag |= GLUT_RGB ; /* Somebody fix this for me! */\r
- break ;\r
-\r
- case 14 : /* "luminance": Number of bits of red in the RGBA and zero\r
- bits of green, blue (alpha not specified) of color buffer\r
- precision */\r
- glut_state_flag |= GLUT_LUMINANCE ; /* Somebody fix this for me! */\r
- break ;\r
-\r
- case 15 : /* "stencil": Number of bits in the stencil buffer */\r
- glut_state_flag |= GLUT_STENCIL; /* Somebody fix this for me! */\r
- break ;\r
-\r
- case 16 : /* "single": Boolean indicate the color buffer is single\r
- buffered */\r
- glut_state_flag |= GLUT_SINGLE ;\r
- break ;\r
-\r
- case 17 : /* "stereo": Boolean indicating the color buffer supports\r
- OpenGL-style stereo */\r
- glut_state_flag |= GLUT_STEREO ;\r
- break ;\r
-\r
- case 18 : /* "samples": Indicates the number of multisamples to use\r
- based on GLX's SGIS_multisample extension (for\r
- antialiasing) */\r
- glut_state_flag |= GLUT_MULTISAMPLE ; /*Somebody fix this for me!*/\r
- break ;\r
-\r
- case 19 : /* "slow": Boolean indicating if the frame buffer\r
- configuration is slow or not */\r
- break ;\r
-\r
- case 20 : /* "win32pdf": (incorrect spelling but was there before */\r
- case 21 : /* "win32pfd": matches the Win32 Pixel Format Descriptor by\r
- number */\r
-#if TARGET_HOST_MS_WINDOWS\r
-#endif\r
- break ;\r
-\r
- case 22 : /* "xvisual": matches the X visual ID by number */\r
-#if TARGET_HOST_POSIX_X11\r
-#endif\r
- break ;\r
-\r
- case 23 : /* "xstaticgray": */\r
- case 29 : /* "xstaticgrey": boolean indicating if the frame buffer\r
- configuration's X visual is of type StaticGray */\r
-#if TARGET_HOST_POSIX_X11\r
-#endif\r
- break ;\r
-\r
- case 24 : /* "xgrayscale": */\r
- case 30 : /* "xgreyscale": boolean indicating if the frame buffer\r
- configuration's X visual is of type GrayScale */\r
-#if TARGET_HOST_POSIX_X11\r
-#endif\r
- break ;\r
-\r
- case 25 : /* "xstaticcolor": */\r
- case 31 : /* "xstaticcolour": boolean indicating if the frame buffer\r
- configuration's X visual is of type StaticColor */\r
-#if TARGET_HOST_POSIX_X11\r
-#endif\r
- break ;\r
-\r
- case 26 : /* "xpseudocolor": */\r
- case 32 : /* "xpseudocolour": boolean indicating if the frame buffer\r
- configuration's X visual is of type PseudoColor */\r
-#if TARGET_HOST_POSIX_X11\r
-#endif\r
- break ;\r
-\r
- case 27 : /* "xtruecolor": */\r
- case 33 : /* "xtruecolour": boolean indicating if the frame buffer\r
- configuration's X visual is of type TrueColor */\r
-#if TARGET_HOST_POSIX_X11\r
-#endif\r
- break ;\r
-\r
- case 28 : /* "xdirectcolor": */\r
- case 34 : /* "xdirectcolour": boolean indicating if the frame buffer\r
- configuration's X visual is of type DirectColor */\r
-#if TARGET_HOST_POSIX_X11\r
-#endif\r
- break ;\r
-\r
- case 35 : /* "borderless": windows should not have borders */\r
-#if TARGET_HOST_POSIX_X11\r
-#endif\r
- break ;\r
-\r
- case 36 : /* "aux": some number of aux buffers */\r
- glut_state_flag |= GLUT_AUX;\r
- break ;\r
-\r
- case 37 : /* Unrecognized */\r
- fgWarning ( "WARNING - Display string token not recognized: %s",\r
- token );\r
- break ;\r
- }\r
-\r
- token = strtok ( NULL, " \t" );\r
- }\r
-\r
- free ( buffer );\r
-\r
- /* We will make use of this value when creating a new OpenGL context... */\r
- fgState.DisplayMode = glut_state_flag;\r
-}\r
-\r
-/* -- SETTING OPENGL 3.0 CONTEXT CREATION PARAMETERS ---------------------- */\r
-\r
-void FGAPIENTRY glutInitContextVersion( int majorVersion, int minorVersion )\r
-{\r
- /* We will make use of these valuse when creating a new OpenGL context... */\r
- fgState.MajorVersion = majorVersion;\r
- fgState.MinorVersion = minorVersion;\r
-}\r
-\r
-\r
-void FGAPIENTRY glutInitContextFlags( int flags )\r
-{\r
- /* We will make use of this value when creating a new OpenGL context... */\r
- fgState.ContextFlags = flags;\r
-}\r
-\r
-void FGAPIENTRY glutInitContextProfile( int profile )\r
-{\r
- /* We will make use of this value when creating a new OpenGL context... */\r
- fgState.ContextProfile = profile;\r
-}\r
-\r
-/* -------------- User Defined Error/Warning Handler Support -------------- */\r
-\r
-/*\r
- * Sets the user error handler (note the use of va_list for the args to the fmt)\r
- */\r
-void FGAPIENTRY glutInitErrorFunc( void (* vfgError) ( const char *fmt, va_list ap ) )\r
-{\r
- /* This allows user programs to handle freeglut errors */\r
- fgState.ErrorFunc = vfgError;\r
-}\r
-\r
-/*\r
- * Sets the user warning handler (note the use of va_list for the args to the fmt)\r
- */\r
-void FGAPIENTRY glutInitWarningFunc( void (* vfgWarning) ( const char *fmt, va_list ap ) )\r
-{\r
- /* This allows user programs to handle freeglut warnings */\r
- fgState.WarningFunc = vfgWarning;\r
-}\r
-\r
-/*** END OF FILE ***/\r
+/*
+ * freeglut_init.c
+ *
+ * Various freeglut initialization functions.
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta@sourceforge.net>
+ * Creation date: Thu Dec 2 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.
+ */
+
+#define FREEGLUT_BUILDING_LIB
+#include <GL/freeglut.h>
+#include "freeglut_internal.h"
+
+/*
+ * TODO BEFORE THE STABLE RELEASE:
+ *
+ * fgDeinitialize() -- Win32's OK, X11 needs the OS-specific
+ * deinitialization done
+ * glutInitDisplayString() -- display mode string parsing
+ *
+ * Wouldn't it be cool to use gettext() for error messages? I just love
+ * bash saying "nie znaleziono pliku" instead of "file not found" :)
+ * Is gettext easily portable?
+ */
+
+/* -- GLOBAL VARIABLES ----------------------------------------------------- */
+
+/*
+ * A structure pointed by fgDisplay holds all information
+ * regarding the display, screen, root window etc.
+ */
+SFG_Display fgDisplay;
+
+/*
+ * The settings for the current freeglut session
+ */
+SFG_State fgState = { { -1, -1, GL_FALSE }, /* Position */
+ { 300, 300, GL_TRUE }, /* Size */
+ GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH, /* DisplayMode */
+ GL_FALSE, /* Initialised */
+ GLUT_TRY_DIRECT_CONTEXT, /* DirectContext */
+ GL_FALSE, /* ForceIconic */
+ GL_FALSE, /* UseCurrentContext */
+ GL_FALSE, /* GLDebugSwitch */
+ GL_FALSE, /* XSyncSwitch */
+ GLUT_KEY_REPEAT_ON, /* KeyRepeat */
+ INVALID_MODIFIERS, /* Modifiers */
+ 0, /* FPSInterval */
+ 0, /* SwapCount */
+ 0, /* SwapTime */
+ 0, /* Time */
+ { NULL, NULL }, /* Timers */
+ { NULL, NULL }, /* FreeTimers */
+ NULL, /* IdleCallback */
+ 0, /* ActiveMenus */
+ NULL, /* MenuStateCallback */
+ NULL, /* MenuStatusCallback */
+ { 640, 480, GL_TRUE }, /* GameModeSize */
+ 16, /* GameModeDepth */
+ 72, /* GameModeRefresh */
+ GLUT_ACTION_EXIT, /* ActionOnWindowClose */
+ GLUT_EXEC_STATE_INIT, /* ExecState */
+ NULL, /* ProgramName */
+ GL_FALSE, /* JoysticksInitialised */
+ 0, /* NumActiveJoysticks */
+ GL_FALSE, /* InputDevsInitialised */
+ 0, /* MouseWheelTicks */
+ 1, /* AuxiliaryBufferNumber */
+ 4, /* SampleNumber */
+ 1, /* MajorVersion */
+ 0, /* MinorVersion */
+ 0, /* ContextFlags */
+ 0, /* ContextProfile */
+ NULL, /* ErrorFunc */
+ NULL /* WarningFunc */
+};
+
+
+/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
+
+extern void fgPlatformInitialize( const char* displayName );
+extern void fgPlatformDeinitialiseInputDevices ( void );
+extern void fgPlatformCloseDisplay ( void );
+extern void fgPlatformDestroyContext ( SFG_PlatformDisplay pDisplay, SFG_WindowContextType MContext );
+
+
+void fghParseCommandLineArguments ( int* pargc, char** argv, char **pDisplayName, char **pGeometry )
+{
+#ifndef _WIN32_WCE
+ int i, j, argc = *pargc;
+
+ {
+ /* check if GLUT_FPS env var is set */
+ const char *fps = getenv( "GLUT_FPS" );
+
+ if( fps )
+ {
+ int interval;
+ sscanf( fps, "%d", &interval );
+
+ if( interval <= 0 )
+ fgState.FPSInterval = 5000; /* 5000 millisecond default */
+ else
+ fgState.FPSInterval = interval;
+ }
+ }
+
+ *pDisplayName = getenv( "DISPLAY" );
+
+ for( i = 1; i < argc; i++ )
+ {
+ if( strcmp( argv[ i ], "-display" ) == 0 )
+ {
+ if( ++i >= argc )
+ fgError( "-display parameter must be followed by display name" );
+
+ *pDisplayName = argv[ i ];
+
+ argv[ i - 1 ] = NULL;
+ argv[ i ] = NULL;
+ ( *pargc ) -= 2;
+ }
+ else if( strcmp( argv[ i ], "-geometry" ) == 0 )
+ {
+ if( ++i >= argc )
+ fgError( "-geometry parameter must be followed by window "
+ "geometry settings" );
+
+ *pGeometry = argv[ i ];
+
+ argv[ i - 1 ] = NULL;
+ argv[ i ] = NULL;
+ ( *pargc ) -= 2;
+ }
+ else if( strcmp( argv[ i ], "-direct" ) == 0)
+ {
+ if( fgState.DirectContext == GLUT_FORCE_INDIRECT_CONTEXT )
+ fgError( "parameters ambiguity, -direct and -indirect "
+ "cannot be both specified" );
+
+ fgState.DirectContext = GLUT_FORCE_DIRECT_CONTEXT;
+ argv[ i ] = NULL;
+ ( *pargc )--;
+ }
+ else if( strcmp( argv[ i ], "-indirect" ) == 0 )
+ {
+ if( fgState.DirectContext == GLUT_FORCE_DIRECT_CONTEXT )
+ fgError( "parameters ambiguity, -direct and -indirect "
+ "cannot be both specified" );
+
+ fgState.DirectContext = GLUT_FORCE_INDIRECT_CONTEXT;
+ argv[ i ] = NULL;
+ (*pargc)--;
+ }
+ else if( strcmp( argv[ i ], "-iconic" ) == 0 )
+ {
+ fgState.ForceIconic = GL_TRUE;
+ argv[ i ] = NULL;
+ ( *pargc )--;
+ }
+ else if( strcmp( argv[ i ], "-gldebug" ) == 0 )
+ {
+ fgState.GLDebugSwitch = GL_TRUE;
+ argv[ i ] = NULL;
+ ( *pargc )--;
+ }
+ else if( strcmp( argv[ i ], "-sync" ) == 0 )
+ {
+ fgState.XSyncSwitch = GL_TRUE;
+ argv[ i ] = NULL;
+ ( *pargc )--;
+ }
+ }
+
+ /* Compact {argv}. */
+ for( i = j = 1; i < *pargc; i++, j++ )
+ {
+ /* Guaranteed to end because there are "*pargc" arguments left */
+ while ( argv[ j ] == NULL )
+ j++;
+ if ( i != j )
+ argv[ i ] = argv[ j ];
+ }
+
+#endif /* _WIN32_WCE */
+
+}
+
+
+void fghCloseInputDevices ( void )
+{
+ if ( fgState.JoysticksInitialised )
+ fgJoystickClose( );
+
+ if ( fgState.InputDevsInitialised )
+ fgInputDeviceClose( );
+}
+
+
+/*
+ * Perform the freeglut deinitialization...
+ */
+void fgDeinitialize( void )
+{
+ SFG_Timer *timer;
+
+ if( !fgState.Initialised )
+ {
+ return;
+ }
+
+ /* If we're in game mode, we want to leave game mode */
+ if( fgStructure.GameModeWindow ) {
+ glutLeaveGameMode();
+ }
+
+ /* If there was a menu created, destroy the rendering context */
+ if( fgStructure.MenuContext )
+ {
+ fgPlatformDestroyContext (fgDisplay.pDisplay, fgStructure.MenuContext->MContext );
+ free( fgStructure.MenuContext );
+ fgStructure.MenuContext = NULL;
+ }
+
+ fgDestroyStructure( );
+
+ while( ( timer = fgState.Timers.First) )
+ {
+ fgListRemove( &fgState.Timers, &timer->Node );
+ free( timer );
+ }
+
+ while( ( timer = fgState.FreeTimers.First) )
+ {
+ fgListRemove( &fgState.FreeTimers, &timer->Node );
+ free( timer );
+ }
+
+ fgPlatformDeinitialiseInputDevices ();
+
+ fgState.MouseWheelTicks = 0;
+
+ fgState.MajorVersion = 1;
+ fgState.MinorVersion = 0;
+ fgState.ContextFlags = 0;
+ fgState.ContextProfile = 0;
+
+ fgState.Initialised = GL_FALSE;
+
+ fgState.Position.X = -1;
+ fgState.Position.Y = -1;
+ fgState.Position.Use = GL_FALSE;
+
+ fgState.Size.X = 300;
+ fgState.Size.Y = 300;
+ fgState.Size.Use = GL_TRUE;
+
+ fgState.DisplayMode = GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH;
+
+ fgState.DirectContext = GLUT_TRY_DIRECT_CONTEXT;
+ fgState.ForceIconic = GL_FALSE;
+ fgState.UseCurrentContext = GL_FALSE;
+ fgState.GLDebugSwitch = GL_FALSE;
+ fgState.XSyncSwitch = GL_FALSE;
+ fgState.ActionOnWindowClose = GLUT_ACTION_EXIT;
+ fgState.ExecState = GLUT_EXEC_STATE_INIT;
+
+ fgState.KeyRepeat = GLUT_KEY_REPEAT_ON;
+ fgState.Modifiers = INVALID_MODIFIERS;
+
+ fgState.GameModeSize.X = 640;
+ fgState.GameModeSize.Y = 480;
+ fgState.GameModeDepth = 16;
+ fgState.GameModeRefresh = 72;
+
+ fgListInit( &fgState.Timers );
+ fgListInit( &fgState.FreeTimers );
+
+ fgState.IdleCallback = NULL;
+ fgState.MenuStateCallback = ( FGCBMenuState )NULL;
+ fgState.MenuStatusCallback = ( FGCBMenuStatus )NULL;
+
+ fgState.SwapCount = 0;
+ fgState.SwapTime = 0;
+ fgState.FPSInterval = 0;
+
+ if( fgState.ProgramName )
+ {
+ free( fgState.ProgramName );
+ fgState.ProgramName = NULL;
+ }
+
+ fgPlatformCloseDisplay ();
+
+ fgState.Initialised = GL_FALSE;
+}
+
+
+/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
+
+#if !TARGET_HOST_POSIX_X11
+#include "Common/xparsegeometry_repl.h"
+#endif
+
+/*
+ * Perform initialization. This usually happens on the program startup
+ * and restarting after glutMainLoop termination...
+ */
+void FGAPIENTRY glutInit( int* pargc, char** argv )
+{
+ char* displayName = NULL;
+ char* geometry = NULL;
+ if( fgState.Initialised )
+ fgError( "illegal glutInit() reinitialization attempt" );
+
+ if (pargc && *pargc && argv && *argv && **argv)
+ {
+ fgState.ProgramName = strdup (*argv);
+
+ if( !fgState.ProgramName )
+ fgError ("Could not allocate space for the program's name.");
+ }
+
+ fgCreateStructure( );
+
+ /* Get start time */
+ fgState.Time = fgSystemTime();
+
+ fghParseCommandLineArguments ( pargc, argv, &displayName, &geometry );
+
+ /*
+ * Have the display created now. If there wasn't a "-display"
+ * in the program arguments, we will use the DISPLAY environment
+ * variable for opening the X display (see code above):
+ */
+ fgPlatformInitialize( displayName );
+
+ /*
+ * Geometry parsing deferred until here because we may need the screen
+ * size.
+ */
+
+ if (geometry )
+ {
+ unsigned int parsedWidth, parsedHeight;
+ int mask = XParseGeometry( geometry,
+ &fgState.Position.X, &fgState.Position.Y,
+ &parsedWidth, &parsedHeight );
+ /* TODO: Check for overflow? */
+ fgState.Size.X = parsedWidth;
+ fgState.Size.Y = parsedHeight;
+
+ if( (mask & (WidthValue|HeightValue)) == (WidthValue|HeightValue) )
+ fgState.Size.Use = GL_TRUE;
+
+ if( mask & XNegative )
+ fgState.Position.X += fgDisplay.ScreenWidth - fgState.Size.X;
+
+ if( mask & YNegative )
+ fgState.Position.Y += fgDisplay.ScreenHeight - fgState.Size.Y;
+
+ if( (mask & (XValue|YValue)) == (XValue|YValue) )
+ fgState.Position.Use = GL_TRUE;
+ }
+}
+
+/*
+ * Undoes all the "glutInit" stuff
+ */
+void FGAPIENTRY glutExit ( void )
+{
+ fgDeinitialize ();
+}
+
+/*
+ * Sets the default initial window position for new windows
+ */
+void FGAPIENTRY glutInitWindowPosition( int x, int y )
+{
+ fgState.Position.X = x;
+ fgState.Position.Y = y;
+
+ if( ( x >= 0 ) && ( y >= 0 ) )
+ fgState.Position.Use = GL_TRUE;
+ else
+ fgState.Position.Use = GL_FALSE;
+}
+
+/*
+ * Sets the default initial window size for new windows
+ */
+void FGAPIENTRY glutInitWindowSize( int width, int height )
+{
+ fgState.Size.X = width;
+ fgState.Size.Y = height;
+
+ if( ( width > 0 ) && ( height > 0 ) )
+ fgState.Size.Use = GL_TRUE;
+ else
+ fgState.Size.Use = GL_FALSE;
+}
+
+/*
+ * Sets the default display mode for all new windows
+ */
+void FGAPIENTRY glutInitDisplayMode( unsigned int displayMode )
+{
+ /* We will make use of this value when creating a new OpenGL context... */
+ fgState.DisplayMode = displayMode;
+}
+
+
+/* -- INIT DISPLAY STRING PARSING ------------------------------------------ */
+
+static char* Tokens[] =
+{
+ "alpha", "acca", "acc", "blue", "buffer", "conformant", "depth", "double",
+ "green", "index", "num", "red", "rgba", "rgb", "luminance", "stencil",
+ "single", "stereo", "samples", "slow", "win32pdf", "win32pfd", "xvisual",
+ "xstaticgray", "xgrayscale", "xstaticcolor", "xpseudocolor",
+ "xtruecolor", "xdirectcolor",
+ "xstaticgrey", "xgreyscale", "xstaticcolour", "xpseudocolour",
+ "xtruecolour", "xdirectcolour", "borderless", "aux"
+};
+#define NUM_TOKENS (sizeof(Tokens) / sizeof(*Tokens))
+
+void FGAPIENTRY glutInitDisplayString( const char* displayMode )
+{
+ int glut_state_flag = 0 ;
+ /*
+ * Unpack a lot of options from a character string. The options are
+ * delimited by blanks or tabs.
+ */
+ char *token ;
+ size_t len = strlen ( displayMode );
+ char *buffer = (char *)malloc ( (len+1) * sizeof(char) );
+ memcpy ( buffer, displayMode, len );
+ buffer[len] = '\0';
+
+ token = strtok ( buffer, " \t" );
+
+ while ( token )
+ {
+ /* Process this token */
+ int i ;
+
+ /* Temporary fix: Ignore any length specifications and at least
+ * process the basic token
+ * TODO: Fix this permanently
+ */
+ size_t cleanlength = strcspn ( token, "=<>~!" );
+
+ for ( i = 0; i < NUM_TOKENS; i++ )
+ {
+ if ( strncmp ( token, Tokens[i], cleanlength ) == 0 ) break ;
+ }
+
+ switch ( i )
+ {
+ case 0 : /* "alpha": Alpha color buffer precision in bits */
+ glut_state_flag |= GLUT_ALPHA ; /* Somebody fix this for me! */
+ break ;
+
+ case 1 : /* "acca": Red, green, blue, and alpha accumulation buffer
+ precision in bits */
+ break ;
+
+ case 2 : /* "acc": Red, green, and blue accumulation buffer precision
+ in bits with zero bits alpha */
+ glut_state_flag |= GLUT_ACCUM ; /* Somebody fix this for me! */
+ break ;
+
+ case 3 : /* "blue": Blue color buffer precision in bits */
+ break ;
+
+ case 4 : /* "buffer": Number of bits in the color index color buffer
+ */
+ break ;
+
+ case 5 : /* "conformant": Boolean indicating if the frame buffer
+ configuration is conformant or not */
+ break ;
+
+ case 6 : /* "depth": Number of bits of precsion in the depth buffer */
+ glut_state_flag |= GLUT_DEPTH ; /* Somebody fix this for me! */
+ break ;
+
+ case 7 : /* "double": Boolean indicating if the color buffer is
+ double buffered */
+ glut_state_flag |= GLUT_DOUBLE ;
+ break ;
+
+ case 8 : /* "green": Green color buffer precision in bits */
+ break ;
+
+ case 9 : /* "index": Boolean if the color model is color index or not
+ */
+ glut_state_flag |= GLUT_INDEX ;
+ break ;
+
+ case 10 : /* "num": A special capability name indicating where the
+ value represents the Nth frame buffer configuration
+ matching the description string */
+ break ;
+
+ case 11 : /* "red": Red color buffer precision in bits */
+ break ;
+
+ case 12 : /* "rgba": Number of bits of red, green, blue, and alpha in
+ the RGBA color buffer */
+ glut_state_flag |= GLUT_RGBA ; /* Somebody fix this for me! */
+ break ;
+
+ case 13 : /* "rgb": Number of bits of red, green, and blue in the
+ RGBA color buffer with zero bits alpha */
+ glut_state_flag |= GLUT_RGB ; /* Somebody fix this for me! */
+ break ;
+
+ case 14 : /* "luminance": Number of bits of red in the RGBA and zero
+ bits of green, blue (alpha not specified) of color buffer
+ precision */
+ glut_state_flag |= GLUT_LUMINANCE ; /* Somebody fix this for me! */
+ break ;
+
+ case 15 : /* "stencil": Number of bits in the stencil buffer */
+ glut_state_flag |= GLUT_STENCIL; /* Somebody fix this for me! */
+ break ;
+
+ case 16 : /* "single": Boolean indicate the color buffer is single
+ buffered */
+ glut_state_flag |= GLUT_SINGLE ;
+ break ;
+
+ case 17 : /* "stereo": Boolean indicating the color buffer supports
+ OpenGL-style stereo */
+ glut_state_flag |= GLUT_STEREO ;
+ break ;
+
+ case 18 : /* "samples": Indicates the number of multisamples to use
+ based on GLX's SGIS_multisample extension (for
+ antialiasing) */
+ glut_state_flag |= GLUT_MULTISAMPLE ; /*Somebody fix this for me!*/
+ break ;
+
+ case 19 : /* "slow": Boolean indicating if the frame buffer
+ configuration is slow or not */
+ break ;
+
+ case 20 : /* "win32pdf": (incorrect spelling but was there before */
+ case 21 : /* "win32pfd": matches the Win32 Pixel Format Descriptor by
+ number */
+#if TARGET_HOST_MS_WINDOWS
+#endif
+ break ;
+
+ case 22 : /* "xvisual": matches the X visual ID by number */
+#if TARGET_HOST_POSIX_X11
+#endif
+ break ;
+
+ case 23 : /* "xstaticgray": */
+ case 29 : /* "xstaticgrey": boolean indicating if the frame buffer
+ configuration's X visual is of type StaticGray */
+#if TARGET_HOST_POSIX_X11
+#endif
+ break ;
+
+ case 24 : /* "xgrayscale": */
+ case 30 : /* "xgreyscale": boolean indicating if the frame buffer
+ configuration's X visual is of type GrayScale */
+#if TARGET_HOST_POSIX_X11
+#endif
+ break ;
+
+ case 25 : /* "xstaticcolor": */
+ case 31 : /* "xstaticcolour": boolean indicating if the frame buffer
+ configuration's X visual is of type StaticColor */
+#if TARGET_HOST_POSIX_X11
+#endif
+ break ;
+
+ case 26 : /* "xpseudocolor": */
+ case 32 : /* "xpseudocolour": boolean indicating if the frame buffer
+ configuration's X visual is of type PseudoColor */
+#if TARGET_HOST_POSIX_X11
+#endif
+ break ;
+
+ case 27 : /* "xtruecolor": */
+ case 33 : /* "xtruecolour": boolean indicating if the frame buffer
+ configuration's X visual is of type TrueColor */
+#if TARGET_HOST_POSIX_X11
+#endif
+ break ;
+
+ case 28 : /* "xdirectcolor": */
+ case 34 : /* "xdirectcolour": boolean indicating if the frame buffer
+ configuration's X visual is of type DirectColor */
+#if TARGET_HOST_POSIX_X11
+#endif
+ break ;
+
+ case 35 : /* "borderless": windows should not have borders */
+#if TARGET_HOST_POSIX_X11
+#endif
+ break ;
+
+ case 36 : /* "aux": some number of aux buffers */
+ glut_state_flag |= GLUT_AUX;
+ break ;
+
+ case 37 : /* Unrecognized */
+ fgWarning ( "WARNING - Display string token not recognized: %s",
+ token );
+ break ;
+ }
+
+ token = strtok ( NULL, " \t" );
+ }
+
+ free ( buffer );
+
+ /* We will make use of this value when creating a new OpenGL context... */
+ fgState.DisplayMode = glut_state_flag;
+}
+
+/* -- SETTING OPENGL 3.0 CONTEXT CREATION PARAMETERS ---------------------- */
+
+void FGAPIENTRY glutInitContextVersion( int majorVersion, int minorVersion )
+{
+ /* We will make use of these valuse when creating a new OpenGL context... */
+ fgState.MajorVersion = majorVersion;
+ fgState.MinorVersion = minorVersion;
+}
+
+
+void FGAPIENTRY glutInitContextFlags( int flags )
+{
+ /* We will make use of this value when creating a new OpenGL context... */
+ fgState.ContextFlags = flags;
+}
+
+void FGAPIENTRY glutInitContextProfile( int profile )
+{
+ /* We will make use of this value when creating a new OpenGL context... */
+ fgState.ContextProfile = profile;
+}
+
+/* -------------- User Defined Error/Warning Handler Support -------------- */
+
+/*
+ * Sets the user error handler (note the use of va_list for the args to the fmt)
+ */
+void FGAPIENTRY glutInitErrorFunc( void (* vfgError) ( const char *fmt, va_list ap ) )
+{
+ /* This allows user programs to handle freeglut errors */
+ fgState.ErrorFunc = vfgError;
+}
+
+/*
+ * Sets the user warning handler (note the use of va_list for the args to the fmt)
+ */
+void FGAPIENTRY glutInitWarningFunc( void (* vfgWarning) ( const char *fmt, va_list ap ) )
+{
+ /* This allows user programs to handle freeglut warnings */
+ fgState.WarningFunc = vfgWarning;
+}
+
+/*** END OF FILE ***/