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