1c041511dScube/***********************************************************
2c041511dScube *      Copyright (C) 1997, Be Inc.  Copyright (C) 1999, Jake Hamby.
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 *
9c041511dScube *  FILE:	glutInit.cpp
10c041511dScube *
11c041511dScube *	DESCRIPTION:	initialize GLUT state
12c041511dScube ***********************************************************/
13c041511dScube
14c041511dScube/***********************************************************
15c041511dScube *	Headers
16c041511dScube ***********************************************************/
17c041511dScube#include <GL/glut.h>
18c041511dScube#include <string.h>
19c041511dScube#include <stdlib.h>
20c041511dScube#include <signal.h>
21c041511dScube#include "glutint.h"
22c041511dScube#include "glutState.h"
23c041511dScube#include "glutBlocker.h"
24c041511dScube#include "beos_x11.h"
25c041511dScube
26c041511dScube/***********************************************************
27c041511dScube *	Global variables
28c041511dScube ***********************************************************/
29c041511dScubeGlutState gState;
30c041511dScubechar *__glutProgramName = NULL;
31c041511dScube
32c041511dScube/***********************************************************
33c041511dScube *	Private variables
34c041511dScube ***********************************************************/
35c041511dScubestatic int __glutArgc;
36c041511dScubestatic char **__glutArgv;
37c041511dScube
38c041511dScube/***********************************************************
39c041511dScube *	FUNCTION:	__glutInitTime
40c041511dScube *
41c041511dScube *	DESCRIPTION:  set up start time variable
42c041511dScube ***********************************************************/
43c041511dScubevoid __glutInitTime(bigtime_t *beginning)
44c041511dScube{
45c041511dScube  static int beenhere = 0;
46c041511dScube  static bigtime_t genesis;
47c041511dScube
48c041511dScube  if (!beenhere) {
49c041511dScube    genesis = system_time();
50c041511dScube    beenhere = 1;
51c041511dScube  }
52c041511dScube  *beginning = genesis;
53c041511dScube}
54c041511dScube
55c041511dScube/***********************************************************
56c041511dScube *	FUNCTION:	removeArgs
57c041511dScube *
58c041511dScube *	DESCRIPTION:  helper function for glutInit to remove args
59c041511dScube *		from argv variable passed in
60c041511dScube ***********************************************************/
61c041511dScubestatic void
62c041511dScuberemoveArgs(int *argcp, char **argv, int numToRemove)
63c041511dScube{
64c041511dScube  int i, j;
65c041511dScube
66c041511dScube  for (i = 0, j = numToRemove; argv[j]; i++, j++) {
67c041511dScube    argv[i] = argv[j];
68c041511dScube  }
69c041511dScube  argv[i] = NULL;
70c041511dScube  *argcp -= numToRemove;
71c041511dScube}
72c041511dScube
73c041511dScube/***********************************************************
74c041511dScube *	FUNCTION:	bAppThread
75c041511dScube *
76c041511dScube *	DESCRIPTION:  starts the BApplication message loop running
77c041511dScube ***********************************************************/
78c041511dScubestatic int32 bAppThread(void *arg) {
79c041511dScube	be_app->Lock();
80c041511dScube	return be_app->Run();
81c041511dScube}
82c041511dScube
83c041511dScube/***********************************************************
84c041511dScube *	FUNCTION:	sigHandler
85c041511dScube *
86c041511dScube *	DESCRIPTION:  shuts down the app on CTRL-C
87c041511dScube ***********************************************************/
88c041511dScubestatic void sigHandler(int) {
89c041511dScube  gState.quitAll = true;
90c041511dScube  gBlock.NewEvent();
91c041511dScube}
92c041511dScube
93c041511dScube/***********************************************************
94c041511dScube *	FUNCTION:	glutInit (2.1)
95c041511dScube *
96c041511dScube *	DESCRIPTION:  create BApplication, parse cmd-line arguments,
97c041511dScube *		and set up gState structure.
98c041511dScube ***********************************************************/
99c041511dScubevoid glutInit(int *argcp, char **argv) {
100c041511dScube  char *str, *geometry = NULL;
101c041511dScube  int i;
102c041511dScube
103c041511dScube  if (gState.display) {
104c041511dScube    __glutWarning("glutInit being called a second time.");
105c041511dScube    return;
106c041511dScube  }
107c041511dScube  /* Determine temporary program name. */
108c041511dScube  str = strrchr(argv[0], '/');
109c041511dScube  if (str == NULL) {
110c041511dScube    __glutProgramName = argv[0];
111c041511dScube  } else {
112c041511dScube    __glutProgramName = str + 1;
113c041511dScube  }
114c041511dScube
115c041511dScube  /* Make private copy of command line arguments. */
116c041511dScube  __glutArgc = *argcp;
117c041511dScube  __glutArgv = (char **) malloc(__glutArgc * sizeof(char *));
118c041511dScube  if (!__glutArgv)
119c041511dScube    __glutFatalError("out of memory.");
120c041511dScube  for (i = 0; i < __glutArgc; i++) {
121c041511dScube    __glutArgv[i] = strdup(argv[i]);
122c041511dScube    if (!__glutArgv[i])
123c041511dScube      __glutFatalError("out of memory.");
124c041511dScube  }
125c041511dScube
126c041511dScube  /* determine permanent program name */
127c041511dScube  str = strrchr(__glutArgv[0], '/');
128c041511dScube  if (str == NULL) {
129c041511dScube    __glutProgramName = __glutArgv[0];
130c041511dScube  } else {
131c041511dScube    __glutProgramName = str + 1;
132c041511dScube  }
133c041511dScube
134c041511dScube  /* parse arguments for standard options */
135c041511dScube  for (i = 1; i < __glutArgc; i++) {
136c041511dScube    if (!strcmp(__glutArgv[i], "-display")) {
137c041511dScube      __glutWarning("-display option only valid for X glut.");
138c041511dScube      if (++i >= __glutArgc) {
139c041511dScube        __glutFatalError(
140c041511dScube          "follow -display option with X display name.");
141c041511dScube      }
142c041511dScube      removeArgs(argcp, &argv[1], 2);
143c041511dScube    } else if (!strcmp(__glutArgv[i], "-geometry")) {
144c041511dScube      if (++i >= __glutArgc) {
145c041511dScube        __glutFatalError(
146c041511dScube          "follow -geometry option with geometry parameter.");
147c041511dScube      }
148c041511dScube      geometry = __glutArgv[i];
149c041511dScube      removeArgs(argcp, &argv[1], 2);
150c041511dScube    } else if (!strcmp(__glutArgv[i], "-direct")) {
151c041511dScube      __glutWarning("-direct option only valid for X glut.");
152c041511dScube      removeArgs(argcp, &argv[1], 1);
153c041511dScube    } else if (!strcmp(__glutArgv[i], "-indirect")) {
154c041511dScube      __glutWarning("-indirect option only valid for X glut.");
155c041511dScube      removeArgs(argcp, &argv[1], 1);
156c041511dScube    } else if (!strcmp(__glutArgv[i], "-iconic")) {
157c041511dScube      __glutWarning("-iconic option doesn't make sense in BeOS.");
158c041511dScube      removeArgs(argcp, &argv[1], 1);
159c041511dScube    } else if (!strcmp(__glutArgv[i], "-gldebug")) {
160c041511dScube      gState.debug = true;
161c041511dScube      removeArgs(argcp, &argv[1], 1);
162c041511dScube    } else if (!strcmp(__glutArgv[i], "-sync")) {
163c041511dScube      __glutWarning("-sync option only valid for X glut.");
164c041511dScube      removeArgs(argcp, &argv[1], 1);
165c041511dScube    } else {
166c041511dScube      /* Once unknown option encountered, stop command line
167c041511dScube         processing. */
168c041511dScube      break;
169c041511dScube    }
170c041511dScube  }
171c041511dScube
172c041511dScube  __glutInit();  /* Create BApplication first so DisplayWidth() works */
173c041511dScube  if (geometry) {
174c041511dScube    int flags, x, y, width, height;
175c041511dScube
176c041511dScube    /* Fix bogus "{width|height} may be used before set"
177c041511dScube       warning */
178c041511dScube    width = 0;
179c041511dScube    height = 0;
180c041511dScube
181c041511dScube    flags = XParseGeometry(geometry, &x, &y,
182c041511dScube      (unsigned int *) &width, (unsigned int *) &height);
183c041511dScube    if (WidthValue & flags) {
184c041511dScube      /* Careful because X does not allow zero or negative
185c041511dScube         width windows */
186c041511dScube      if (width > 0)
187c041511dScube        gState.initWidth = width;
188c041511dScube    }
189c041511dScube    if (HeightValue & flags) {
190c041511dScube      /* Careful because X does not allow zero or negative
191c041511dScube         height windows */
192c041511dScube      if (height > 0)
193c041511dScube        gState.initHeight = height;
194c041511dScube    }
195c041511dScube    if (XValue & flags) {
196c041511dScube      if (XNegative & flags)
197c041511dScube        x = DisplayWidth() + x - gState.initWidth;
198c041511dScube      /* Play safe: reject negative X locations */
199c041511dScube      if (x >= 0)
200c041511dScube        gState.initX = x;
201c041511dScube    }
202c041511dScube    if (YValue & flags) {
203c041511dScube      if (YNegative & flags)
204c041511dScube        y = DisplayHeight() + y - gState.initHeight;
205c041511dScube      /* Play safe: reject negative Y locations */
206c041511dScube      if (y >= 0)
207c041511dScube        gState.initY = y;
208c041511dScube    }
209c041511dScube  }
210c041511dScube}
211c041511dScube
212c041511dScube/***********************************************************
213c041511dScube *	FUNCTION:	__glutInit
214c041511dScube *
215c041511dScube *	DESCRIPTION:  create BApplication, parse cmd-line arguments,
216c041511dScube *		and set up gState structure.
217c041511dScube ***********************************************************/
218c041511dScubevoid __glutInit() {
219c041511dScube  // open BApplication
220c041511dScube  gState.display = new BApplication("application/x-glut-demo");
221c041511dScube  be_app->Unlock();
222c041511dScube  gState.appthread = spawn_thread(bAppThread, "BApplication", B_NORMAL_PRIORITY, 0);
223c041511dScube  resume_thread(gState.appthread);
224c041511dScube
225c041511dScube  bigtime_t unused;
226c041511dScube  __glutInitTime(&unused);
227c041511dScube
228c041511dScube  /* set atexit() function to destroy all windows before exiting */
229c041511dScube  if(atexit(__glutDestroyAllWindows))
230c041511dScube  	__glutFatalError("can't set exit handler");
231c041511dScube
232c041511dScube  /* similarly, destroy all windows on CTRL-C */
233c041511dScube  signal(SIGINT, sigHandler);
234c041511dScube}
235c041511dScube
236c041511dScube/***********************************************************
237c041511dScube *	FUNCTION:	glutInitWindowPosition (2.2)
238c041511dScube *
239c041511dScube *	DESCRIPTION:  set initial window position
240c041511dScube ***********************************************************/
241c041511dScubevoid glutInitWindowPosition(int x, int y) {
242c041511dScube	gState.initX = x;
243c041511dScube	gState.initY = y;
244c041511dScube}
245c041511dScube
246c041511dScube/***********************************************************
247c041511dScube *	FUNCTION:	glutInitWindowSize (2.2)
248c041511dScube *
249c041511dScube *	DESCRIPTION:  set initial window size
250c041511dScube ***********************************************************/
251c041511dScubevoid glutInitWindowSize(int width, int height) {
252c041511dScube	gState.initWidth = width;
253c041511dScube	gState.initHeight = height;
254c041511dScube}
255c041511dScube
256c041511dScube/***********************************************************
257c041511dScube *	FUNCTION:	glutInitDisplayMode (2.3)
258c041511dScube *
259c041511dScube *	DESCRIPTION:  set initial display mode
260c041511dScube ***********************************************************/
261c041511dScubevoid glutInitDisplayMode(unsigned int mode) {
262c041511dScube	gState.displayMode = mode;
263c041511dScube}
264