1c041511dScube 2c041511dScube/* Copyright (c) Mark J. Kilgard, 1994, 1997. */ 3c041511dScube 4c041511dScube/* This program is freely distributable without licensing fees 5c041511dScube and is provided without guarantee or warrantee expressed or 6c041511dScube implied. This program is -not- in the public domain. */ 7c041511dScube 8c041511dScube#ifdef __VMS 9c041511dScube#include <GL/vms_x_fix.h> 10c041511dScube#endif 11c041511dScube 12c041511dScube#include <stdlib.h> 13c041511dScube#include <string.h> 14c041511dScube#include <stdio.h> 15c041511dScube 16c041511dScube#if !defined(_WIN32) 17c041511dScube#include <X11/Xlib.h> 18c041511dScube#endif 19c041511dScube 20c041511dScube/* SGI optimization introduced in IRIX 6.3 to avoid X server 21c041511dScube round trips for interning common X atoms. */ 22c041511dScube#if defined(_SGI_EXTRA_PREDEFINES) && !defined(NO_FAST_ATOMS) 23c041511dScube#include <X11/SGIFastAtom.h> 24c041511dScube#else 25c041511dScube#define XSGIFastInternAtom(dpy,string,fast_name,how) XInternAtom(dpy,string,how) 26c041511dScube#endif 27c041511dScube 28c041511dScube#include "glutint.h" 29c041511dScube 30c041511dScube/* GLUT inter-file variables */ 31c041511dScube/* *INDENT-OFF* */ 32c041511dScubechar *__glutProgramName = NULL; 33c041511dScubeint __glutArgc = 0; 34c041511dScubechar **__glutArgv = NULL; 35c041511dScubechar *__glutGeometry = NULL; 36c041511dScubeDisplay *__glutDisplay = NULL; 37c041511dScubeint __glutScreen; 38c041511dScubeWindow __glutRoot; 39c041511dScubeint __glutScreenHeight; 40c041511dScubeint __glutScreenWidth; 41c041511dScubeGLboolean __glutIconic = GL_FALSE; 42c041511dScubeGLboolean __glutDebug = GL_FALSE; 43c041511dScubeunsigned int __glutDisplayMode = 44c041511dScube GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH; 45c041511dScubechar *__glutDisplayString = NULL; 46c041511dScubeint __glutConnectionFD; 47c041511dScubeXSizeHints __glutSizeHints = {0}; 48c041511dScubeint __glutInitWidth = 300, __glutInitHeight = 300; 49c041511dScubeint __glutInitX = -1, __glutInitY = -1; 50c041511dScubeGLboolean __glutForceDirect = GL_FALSE, 51c041511dScube __glutTryDirect = GL_TRUE; 52c041511dScubeAtom __glutWMDeleteWindow; 53b3dfa806Smrgchar *__glutPPMFile = NULL; 54c041511dScube/* *INDENT-ON* */ 55c041511dScube 56c041511dScube#ifdef _WIN32 57c041511dScubevoid (__cdecl *__glutExitFunc)(int retval) = NULL; 58c041511dScube#endif 59c041511dScube 60c041511dScubestatic Bool synchronize = False; 61c041511dScube 62c041511dScube#if defined(_WIN32) 63c041511dScube 64c041511dScube#ifdef __BORLANDC__ 65c041511dScube#include <float.h> /* For masking floating point exceptions. */ 66c041511dScube#endif 67c041511dScube 68c041511dScubevoid 69c041511dScube__glutOpenWin32Connection(char* display) 70c041511dScube{ 71c041511dScube static char *classname; 72c041511dScube WNDCLASS wc; 73c041511dScube HINSTANCE hInstance = GetModuleHandle(NULL); 74c041511dScube 75c041511dScube /* Make sure we register the window only once. */ 76c041511dScube if(classname) 77c041511dScube return; 78c041511dScube 79c041511dScube#ifdef __BORLANDC__ 80c041511dScube /* Under certain conditions (e.g. while rendering solid surfaces with 81c041511dScube lighting enabled) Microsoft OpenGL libraries cause some illegal 82c041511dScube operations like floating point overflow or division by zero. The 83c041511dScube default behaviour of Microsoft compilers is to mask (ignore) 84c041511dScube floating point exceptions, while Borland compilers do not. The 85c041511dScube following function of Borland RTL allows to mask exceptions. 86c041511dScube Advice from Pier Giorgio Esposito (mc2172@mclink.it). */ 87c041511dScube _control87(MCW_EM,MCW_EM); 88c041511dScube#endif 89c041511dScube 90c041511dScube classname = "GLUT"; 91c041511dScube 92c041511dScube /* Clear (important!) and then fill in the window class structure. */ 93c041511dScube memset(&wc, 0, sizeof(WNDCLASS)); 94c041511dScube wc.style = CS_OWNDC; 95c041511dScube wc.lpfnWndProc = (WNDPROC)__glutWindowProc; 96c041511dScube wc.hInstance = hInstance; 97c041511dScube wc.hIcon = LoadIcon(hInstance, "GLUT_ICON"); 98c041511dScube wc.hCursor = LoadCursor(hInstance, IDC_ARROW); 99c041511dScube wc.hbrBackground = NULL; 100c041511dScube wc.lpszMenuName = NULL; 101c041511dScube wc.lpszClassName = classname; 102c041511dScube 103c041511dScube /* Fill in a default icon if one isn't specified as a resource. */ 104c041511dScube if(!wc.hIcon) 105c041511dScube wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); 106c041511dScube 107c041511dScube if(!RegisterClass(&wc)) { 108c041511dScube __glutFatalError("RegisterClass() failed:" 109c041511dScube "Cannot register GLUT window class."); 110c041511dScube } 111c041511dScube 112c041511dScube __glutScreenWidth = GetSystemMetrics(SM_CXSCREEN); 113c041511dScube __glutScreenHeight = GetSystemMetrics(SM_CYSCREEN); 114c041511dScube 115c041511dScube /* Set the root window to NULL because windows creates a top-level 116c041511dScube window when the parent is NULL. X creates a top-level window 117c041511dScube when the parent is the root window. */ 118c041511dScube __glutRoot = NULL; 119c041511dScube 120c041511dScube /* Set the display to 1 -- we shouldn't be using this anywhere 121c041511dScube (except as an argument to X calls). */ 122c041511dScube __glutDisplay = (Display*)1; 123c041511dScube 124c041511dScube /* There isn't any concept of multiple screens in Win32, therefore, 125c041511dScube we don't need to keep track of the screen we're on... it's always 126c041511dScube the same one. */ 127c041511dScube __glutScreen = 0; 128c041511dScube} 129c041511dScube#else /* !_WIN32 */ 130c041511dScubevoid 131c041511dScube__glutOpenXConnection(char *display) 132c041511dScube{ 133c041511dScube int errorBase, eventBase; 134c041511dScube 135c041511dScube __glutDisplay = XOpenDisplay(display); 136c041511dScube if (!__glutDisplay) 137c041511dScube __glutFatalError("could not open display: %s", 138c041511dScube XDisplayName(display)); 139c041511dScube if (synchronize) 140c041511dScube XSynchronize(__glutDisplay, True); 141c041511dScube if (!glXQueryExtension(__glutDisplay, &errorBase, &eventBase)) 142c041511dScube __glutFatalError( 143c041511dScube "OpenGL GLX extension not supported by display: %s", 144c041511dScube XDisplayName(display)); 145c041511dScube __glutScreen = DefaultScreen(__glutDisplay); 146c041511dScube __glutRoot = RootWindow(__glutDisplay, __glutScreen); 147c041511dScube __glutScreenWidth = DisplayWidth(__glutDisplay, __glutScreen); 148c041511dScube __glutScreenHeight = DisplayHeight(__glutDisplay, 149c041511dScube __glutScreen); 150c041511dScube __glutConnectionFD = ConnectionNumber(__glutDisplay); 151c041511dScube __glutWMDeleteWindow = XSGIFastInternAtom(__glutDisplay, 152c041511dScube "WM_DELETE_WINDOW", SGI_XA_WM_DELETE_WINDOW, False); 153c041511dScube} 154c041511dScube#endif /* _WIN32 */ 155c041511dScube 156c041511dScubevoid 157c041511dScube#ifdef OLD_VMS 158c041511dScube __glutInitTime(struct timeval6 *beginning) 159c041511dScube#else 160c041511dScube __glutInitTime(struct timeval *beginning) 161c041511dScube#endif 162c041511dScube{ 163c041511dScube static int beenhere = 0; 164c041511dScube#ifdef OLD_VMS 165c041511dScube static struct timeval6 genesis; 166c041511dScube#else 167c041511dScube static struct timeval genesis; 168c041511dScube#endif 169c041511dScube 170c041511dScube if (!beenhere) { 171c041511dScube GETTIMEOFDAY(&genesis); 172c041511dScube beenhere = 1; 173c041511dScube } 174c041511dScube *beginning = genesis; 175c041511dScube} 176c041511dScube 177c041511dScubestatic void 178c041511dScuberemoveArgs(int *argcp, char **argv, int numToRemove) 179c041511dScube{ 180c041511dScube int i, j; 181c041511dScube 182c041511dScube for (i = 0, j = numToRemove; argv[j]; i++, j++) { 183c041511dScube argv[i] = argv[j]; 184c041511dScube } 185c041511dScube argv[i] = NULL; 186c041511dScube *argcp -= numToRemove; 187c041511dScube} 188c041511dScube 189c041511dScubevoid GLUTAPIENTRY 190c041511dScubeglutInit(int *argcp, char **argv) 191c041511dScube{ 192c041511dScube char *display = NULL; 193c041511dScube char *str, *geometry = NULL; 194c041511dScube#ifdef OLD_VMS 195c041511dScube struct timeval6 unused; 196c041511dScube#else 197c041511dScube struct timeval unused; 198c041511dScube#endif 199c041511dScube int i; 200c041511dScube 201c041511dScube if (__glutDisplay) { 202c041511dScube __glutWarning("glutInit being called a second time."); 203c041511dScube return; 204c041511dScube } 205c041511dScube /* Determine temporary program name. */ 206c041511dScube str = strrchr(argv[0], '/'); 207c041511dScube if (str == NULL) { 208c041511dScube __glutProgramName = argv[0]; 209c041511dScube } else { 210c041511dScube __glutProgramName = str + 1; 211c041511dScube } 212c041511dScube 213c041511dScube /* Make private copy of command line arguments. */ 214c041511dScube __glutArgc = *argcp; 215c041511dScube __glutArgv = (char **) malloc(__glutArgc * sizeof(char *)); 216c041511dScube if (!__glutArgv) 217c041511dScube __glutFatalError("out of memory."); 218c041511dScube for (i = 0; i < __glutArgc; i++) { 219c041511dScube __glutArgv[i] = __glutStrdup(argv[i]); 220c041511dScube if (!__glutArgv[i]) 221c041511dScube __glutFatalError("out of memory."); 222c041511dScube } 223c041511dScube 224c041511dScube /* determine permanent program name */ 225c041511dScube str = strrchr(__glutArgv[0], '/'); 226c041511dScube if (str == NULL) { 227c041511dScube __glutProgramName = __glutArgv[0]; 228c041511dScube } else { 229c041511dScube __glutProgramName = str + 1; 230c041511dScube } 231c041511dScube 232c041511dScube /* parse arguments for standard options */ 233c041511dScube for (i = 1; i < __glutArgc; i++) { 234c041511dScube if (!strcmp(__glutArgv[i], "-display")) { 235c041511dScube#if defined(_WIN32) 236c041511dScube __glutWarning("-display option not supported by Win32 GLUT."); 237c041511dScube#endif 238c041511dScube if (++i >= __glutArgc) { 239c041511dScube __glutFatalError( 240c041511dScube "follow -display option with X display name."); 241c041511dScube } 242c041511dScube display = __glutArgv[i]; 243c041511dScube removeArgs(argcp, &argv[1], 2); 244c041511dScube } else if (!strcmp(__glutArgv[i], "-geometry")) { 245c041511dScube if (++i >= __glutArgc) { 246c041511dScube __glutFatalError( 247c041511dScube "follow -geometry option with geometry parameter."); 248c041511dScube } 249c041511dScube geometry = __glutArgv[i]; 250c041511dScube removeArgs(argcp, &argv[1], 2); 251c041511dScube } else if (!strcmp(__glutArgv[i], "-direct")) { 252c041511dScube#if defined(_WIN32) 253c041511dScube __glutWarning("-direct option not supported by Win32 GLUT."); 254c041511dScube#endif 255c041511dScube if (!__glutTryDirect) 256c041511dScube __glutFatalError( 257c041511dScube "cannot force both direct and indirect rendering."); 258c041511dScube __glutForceDirect = GL_TRUE; 259c041511dScube removeArgs(argcp, &argv[1], 1); 260c041511dScube } else if (!strcmp(__glutArgv[i], "-indirect")) { 261c041511dScube#if defined(_WIN32) 262c041511dScube __glutWarning("-indirect option not supported by Win32 GLUT."); 263c041511dScube#endif 264c041511dScube if (__glutForceDirect) 265c041511dScube __glutFatalError( 266c041511dScube "cannot force both direct and indirect rendering."); 267c041511dScube __glutTryDirect = GL_FALSE; 268c041511dScube removeArgs(argcp, &argv[1], 1); 269c041511dScube } else if (!strcmp(__glutArgv[i], "-iconic")) { 270c041511dScube __glutIconic = GL_TRUE; 271c041511dScube removeArgs(argcp, &argv[1], 1); 272c041511dScube } else if (!strcmp(__glutArgv[i], "-gldebug")) { 273c041511dScube __glutDebug = GL_TRUE; 274c041511dScube removeArgs(argcp, &argv[1], 1); 275c041511dScube } else if (!strcmp(__glutArgv[i], "-sync")) { 276c041511dScube#if defined(_WIN32) 277c041511dScube __glutWarning("-sync option not supported by Win32 GLUT."); 278c041511dScube#endif 279c041511dScube synchronize = GL_TRUE; 280c041511dScube removeArgs(argcp, &argv[1], 1); 281c041511dScube } else { 282c041511dScube /* Once unknown option encountered, stop command line 283c041511dScube processing. */ 284c041511dScube break; 285c041511dScube } 286c041511dScube } 287c041511dScube#if defined(_WIN32) 288c041511dScube __glutOpenWin32Connection(display); 289c041511dScube#else 290c041511dScube __glutOpenXConnection(display); 291c041511dScube#endif 292c041511dScube if (geometry) { 293c041511dScube int flags, x, y, width, height; 294c041511dScube 295c041511dScube /* Fix bogus "{width|height} may be used before set" 296c041511dScube warning */ 297c041511dScube width = 0; 298c041511dScube height = 0; 299c041511dScube 300c041511dScube flags = XParseGeometry(geometry, &x, &y, 301c041511dScube (unsigned int *) &width, (unsigned int *) &height); 302c041511dScube if (WidthValue & flags) { 303c041511dScube /* Careful because X does not allow zero or negative 304c041511dScube width windows */ 305c041511dScube if (width > 0) 306c041511dScube __glutInitWidth = width; 307c041511dScube } 308c041511dScube if (HeightValue & flags) { 309c041511dScube /* Careful because X does not allow zero or negative 310c041511dScube height windows */ 311c041511dScube if (height > 0) 312c041511dScube __glutInitHeight = height; 313c041511dScube } 314c041511dScube glutInitWindowSize(__glutInitWidth, __glutInitHeight); 315c041511dScube if (XValue & flags) { 316c041511dScube if (XNegative & flags) 317c041511dScube x = DisplayWidth(__glutDisplay, __glutScreen) + 318c041511dScube x - __glutSizeHints.width; 319c041511dScube /* Play safe: reject negative X locations */ 320c041511dScube if (x >= 0) 321c041511dScube __glutInitX = x; 322c041511dScube } 323c041511dScube if (YValue & flags) { 324c041511dScube if (YNegative & flags) 325c041511dScube y = DisplayHeight(__glutDisplay, __glutScreen) + 326c041511dScube y - __glutSizeHints.height; 327c041511dScube /* Play safe: reject negative Y locations */ 328c041511dScube if (y >= 0) 329c041511dScube __glutInitY = y; 330c041511dScube } 331c041511dScube glutInitWindowPosition(__glutInitX, __glutInitY); 332c041511dScube } 333c041511dScube __glutInitTime(&unused); 334c041511dScube 335c041511dScube /* check if GLUT_FPS env var is set */ 336c041511dScube { 337c041511dScube const char *fps = getenv("GLUT_FPS"); 338c041511dScube if (fps) { 339c041511dScube sscanf(fps, "%d", &__glutFPS); 340c041511dScube if (__glutFPS <= 0) 341c041511dScube __glutFPS = 5000; /* 5000 milliseconds */ 342c041511dScube } 343c041511dScube } 344b3dfa806Smrg 345b3dfa806Smrg /* check if GLUT_PPM_FILE env var is set */ 346b3dfa806Smrg __glutPPMFile = getenv("GLUT_PPM_FILE"); 347c041511dScube} 348c041511dScube 349c041511dScube#ifdef _WIN32 350c041511dScubevoid GLUTAPIENTRY 351c041511dScube__glutInitWithExit(int *argcp, char **argv, void (__cdecl *exitfunc)(int)) 352c041511dScube{ 353c041511dScube __glutExitFunc = exitfunc; 354c041511dScube glutInit(argcp, argv); 355c041511dScube} 356c041511dScube#endif 357c041511dScube 358c041511dScube/* CENTRY */ 359c041511dScubevoid GLUTAPIENTRY 360c041511dScubeglutInitWindowPosition(int x, int y) 361c041511dScube{ 362c041511dScube __glutInitX = x; 363c041511dScube __glutInitY = y; 364c041511dScube if (x >= 0 && y >= 0) { 365c041511dScube __glutSizeHints.x = x; 366c041511dScube __glutSizeHints.y = y; 367c041511dScube __glutSizeHints.flags |= USPosition; 368c041511dScube } else { 369c041511dScube __glutSizeHints.flags &= ~USPosition; 370c041511dScube } 371c041511dScube} 372c041511dScube 373c041511dScubevoid GLUTAPIENTRY 374c041511dScubeglutInitWindowSize(int width, int height) 375c041511dScube{ 376c041511dScube __glutInitWidth = width; 377c041511dScube __glutInitHeight = height; 378c041511dScube if (width > 0 && height > 0) { 379c041511dScube __glutSizeHints.width = width; 380c041511dScube __glutSizeHints.height = height; 381c041511dScube __glutSizeHints.flags |= USSize; 382c041511dScube } else { 383c041511dScube __glutSizeHints.flags &= ~USSize; 384c041511dScube } 385c041511dScube} 386c041511dScube 387c041511dScubevoid GLUTAPIENTRY 388c041511dScubeglutInitDisplayMode(unsigned int mask) 389c041511dScube{ 390c041511dScube __glutDisplayMode = mask; 391c041511dScube} 392c041511dScube 393c041511dScube/* ENDCENTRY */ 394