1 
2 /* Copyright (c) Mark J. Kilgard, 1994. */
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 #include <stdlib.h>
9 #include <string.h>
10 #include <stdio.h>
11 #include <X11/Xlib.h>
12 
13 #include <GL/glut.h>
14 #include "glutint.h"
15 
16 /* GLUT inter-file variables */
17 char *__glutProgramName = NULL;
18 int __glutArgc = 0;
19 char **__glutArgv = NULL;
20 char *__glutGeometry = NULL;
21 Display *__glutDisplay = NULL;
22 int __glutScreen;
23 Window __glutRoot;
24 int __glutScreenHeight;
25 int __glutScreenWidth;
26 GLboolean __glutIconic = GL_FALSE;
27 GLboolean __glutDebug = GL_FALSE;
28 unsigned int __glutDisplayMode =
29   GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH;
30 int __glutConnectionFD;
31 XSizeHints __glutSizeHints = {0};
32 int __glutInitWidth = 300, __glutInitHeight = 300;
33 int __glutInitX = -1, __glutInitY = -1;
34 GLboolean __glutForceDirect = GL_FALSE,
35   __glutTryDirect = GL_TRUE;
36 Atom __glutWMDeleteWindow;
37 
38 static Bool synchronize = False;
39 
40 #if defined(__vms)
41 char *
strdup(const char * string)42 strdup(const char *string)
43 {
44   char *new;
45 
46   new = malloc(strlen(string) + 1);
47   if (new == NULL)
48     return NULL;
49   strcpy(new, string);
50   return new;
51 }
52 #endif
53 
54 void
__glutOpenXConnection(char * display)55 __glutOpenXConnection(char *display)
56 {
57   int errorBase, eventBase;
58 
59   __glutDisplay = XOpenDisplay(display);
60   if (!__glutDisplay)
61     __glutFatalError("could not open display: %s",
62       XDisplayName(display));
63   if (synchronize)
64     XSynchronize(__glutDisplay, True);
65   if (!glXQueryExtension(__glutDisplay, &errorBase, &eventBase))
66     __glutFatalError(
67       "OpenGL GLX extension not supported by display: %s",
68       XDisplayName(display));
69   __glutScreen = DefaultScreen(__glutDisplay);
70   __glutRoot = RootWindow(__glutDisplay, __glutScreen);
71   __glutScreenWidth = DisplayWidth(__glutDisplay, __glutScreen);
72   __glutScreenHeight = DisplayHeight(__glutDisplay,
73     __glutScreen);
74   __glutConnectionFD = ConnectionNumber(__glutDisplay);
75   __glutWMDeleteWindow = XInternAtom(__glutDisplay,
76     "WM_DELETE_WINDOW", False);
77 }
78 
79 void
__glutInitTime(struct timeval * beginning)80 __glutInitTime(struct timeval *beginning)
81 {
82   static int beenhere = 0;
83   static struct timeval genesis;
84 
85   if (!beenhere) {
86     GETTIMEOFDAY(&genesis);
87     beenhere = 1;
88   }
89   *beginning = genesis;
90 }
91 
92 static void
removeArgs(int * argcp,char ** argv,int numToRemove)93 removeArgs(int *argcp, char **argv, int numToRemove)
94 {
95   int i, j;
96 
97   for (i = 0, j = numToRemove; argv[j]; i++, j++) {
98     argv[i] = argv[j];
99   }
100   argv[i] = NULL;
101   *argcp -= numToRemove;
102 }
103 
104 void
glutInit(int * argcp,char ** argv)105 glutInit(int *argcp, char **argv)
106 {
107   char *display = NULL;
108   char *str;
109   struct timeval unused;
110   int i;
111 
112   if (__glutDisplay) {
113     __glutWarning("glutInit being called a second time.");
114     return;
115   }
116   /* determine temporary program name */
117   str = strrchr(argv[0], '/');
118   if (str == NULL) {
119     __glutProgramName = argv[0];
120   } else {
121     __glutProgramName = str + 1;
122   }
123 
124   /* make private copy of command line arguments */
125   __glutArgc = *argcp;
126   __glutArgv = (char **) malloc(__glutArgc * sizeof(char *));
127   if (!__glutArgv)
128     __glutFatalError("out of memory.");
129   for (i = 0; i < __glutArgc; i++) {
130     __glutArgv[i] = strdup(argv[i]);
131     if (!__glutArgv[i])
132       __glutFatalError("out of memory.");
133   }
134 
135   /* determine permanent program name */
136   str = strrchr(__glutArgv[0], '/');
137   if (str == NULL) {
138     __glutProgramName = __glutArgv[0];
139   } else {
140     __glutProgramName = str + 1;
141   }
142 
143   /* parse arguments for standard options */
144   for (i = 1; i < __glutArgc; i++) {
145     if (!strcmp(__glutArgv[i], "-display")) {
146       if (++i >= __glutArgc) {
147         __glutFatalError(
148           "follow -display option with X display name.");
149       }
150       display = __glutArgv[i];
151       removeArgs(argcp, &argv[1], 2);
152     } else if (!strcmp(__glutArgv[i], "-geometry")) {
153       int flags, x, y, width, height;
154 
155       if (++i >= __glutArgc) {
156         __glutFatalError(
157           "follow -geometry option with geometry parameter.");
158       }
159       /* Fix bogus "{width|height} may be used before set"
160          warning */
161       width = 0;
162       height = 0;
163 
164       flags = XParseGeometry(__glutArgv[i], &x, &y,
165         (unsigned int *) &width, (unsigned int *) &height);
166       if (WidthValue & flags) {
167         /* Careful because X does not allow zero or negative
168            width windows */
169         if (width > 0)
170           __glutInitWidth = width;
171       }
172       if (HeightValue & flags) {
173         /* Careful because X does not allow zero or negative
174            height windows */
175         if (height > 0)
176           __glutInitHeight = height;
177       }
178       glutInitWindowSize(__glutInitWidth, __glutInitHeight);
179       if (XValue & flags) {
180         if (XNegative & flags)
181           x = DisplayWidth(__glutDisplay, __glutScreen) +
182             x - __glutSizeHints.width;
183         /* Play safe: reject negative X locations */
184         if (x >= 0)
185           __glutInitX = x;
186       }
187       if (YValue & flags) {
188         if (YNegative & flags)
189           y = DisplayHeight(__glutDisplay, __glutScreen) +
190             y - __glutSizeHints.height;
191         /* Play safe: reject negative Y locations */
192         if (y >= 0)
193           __glutInitY = y;
194       }
195       glutInitWindowPosition(__glutInitX, __glutInitY);
196       removeArgs(argcp, &argv[1], 2);
197     } else if (!strcmp(__glutArgv[i], "-direct")) {
198       if (!__glutTryDirect)
199         __glutFatalError(
200           "cannot force both direct and indirect rendering.");
201       __glutForceDirect = GL_TRUE;
202       removeArgs(argcp, &argv[1], 1);
203     } else if (!strcmp(__glutArgv[i], "-indirect")) {
204       if (__glutForceDirect)
205         __glutFatalError(
206           "cannot force both direct and indirect rendering.");
207       __glutTryDirect = GL_FALSE;
208       removeArgs(argcp, &argv[1], 1);
209     } else if (!strcmp(__glutArgv[i], "-iconic")) {
210       __glutIconic = GL_TRUE;
211       removeArgs(argcp, &argv[1], 1);
212     } else if (!strcmp(__glutArgv[i], "-gldebug")) {
213       __glutDebug = GL_TRUE;
214       removeArgs(argcp, &argv[1], 1);
215     } else if (!strcmp(__glutArgv[i], "-sync")) {
216       synchronize = GL_TRUE;
217       removeArgs(argcp, &argv[1], 1);
218     } else {
219       /* once unknown option encountered, stop command line
220          processing */
221       break;
222     }
223   }
224   __glutOpenXConnection(display);
225   __glutInitTime(&unused);
226 }
227 
228 void
glutInitWindowPosition(int x,int y)229 glutInitWindowPosition(int x, int y)
230 {
231   __glutInitX = x;
232   __glutInitY = y;
233   if (x >= 0 && y >= 0) {
234     __glutSizeHints.x = x;
235     __glutSizeHints.y = y;
236     __glutSizeHints.flags |= USPosition;
237   } else {
238     __glutSizeHints.flags &= ~USPosition;
239   }
240 }
241 
242 void
glutInitWindowSize(int width,int height)243 glutInitWindowSize(int width, int height)
244 {
245   __glutInitWidth = width;
246   __glutInitHeight = height;
247   if (width > 0 && height > 0) {
248     __glutSizeHints.width = width;
249     __glutSizeHints.height = height;
250     __glutSizeHints.flags |= USSize;
251   } else {
252     __glutSizeHints.flags &= ~USSize;
253   }
254 }
255 
256 void
glutInitDisplayMode(unsigned int mask)257 glutInitDisplayMode(unsigned int mask)
258 {
259   __glutDisplayMode = mask;
260 }
261 
262