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