autoconf'd <fcntl.h> and <sys/ioctl.h> handling
[freeglut] / src / freeglut_callbacks.c
1 /*
2  * freeglut_callbacks.c
3  *
4  * The callbacks setting methods.
5  *
6  * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
7  * Written by Pawel W. Olszta, <olszta@sourceforge.net>
8  * Creation date: Fri Dec 3 1999
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included
18  * in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23  * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
24  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26  */
27
28 #include <GL/freeglut.h>
29 #include "freeglut_internal.h"
30
31 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
32
33 /*
34  * All of the callbacks setting methods can be generalized to this:
35  */
36 #define SET_CALLBACK(a)              \
37     if( fgStructure.Window == NULL ) \
38         return;                      \
39     SET_WCB( ( *( fgStructure.Window ) ), a, callback );
40
41 /*
42  * Sets the Display callback for the current window
43  */
44 void FGAPIENTRY glutDisplayFunc( void (* callback)( void ) )
45 {
46     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDisplayFunc" );
47     if( !callback )
48         fgError( "Fatal error in program.  NULL display callback not "
49                  "permitted in GLUT 3.0+ or freeglut 2.0.1+" );
50     SET_CALLBACK( Display );
51 }
52
53 /*
54  * Sets the Reshape callback for the current window
55  */
56 void FGAPIENTRY glutReshapeFunc( void (* callback)( int, int ) )
57 {
58     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeFunc" );
59     SET_CALLBACK( Reshape );
60 }
61
62 /*
63  * Sets the Keyboard callback for the current window
64  */
65 void FGAPIENTRY glutKeyboardFunc( void (* callback)
66                                   ( unsigned char, int, int ) )
67 {
68     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutKeyboardFunc" );
69     SET_CALLBACK( Keyboard );
70 }
71
72 /*
73  * Sets the Special callback for the current window
74  */
75 void FGAPIENTRY glutSpecialFunc( void (* callback)( int, int, int ) )
76 {
77     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpecialFunc" );
78     SET_CALLBACK( Special );
79 }
80
81 /*
82  * Sets the global idle callback
83  */
84 void FGAPIENTRY glutIdleFunc( void (* callback)( void ) )
85 {
86     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIdleFunc" );
87     fgState.IdleCallback = callback;
88 }
89
90 /*
91  * Sets the Timer callback for the current window
92  */
93 void FGAPIENTRY glutTimerFunc( unsigned int timeOut, void (* callback)( int ),
94                                int timerID )
95 {
96     SFG_Timer *timer, *node;
97
98     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTimerFunc" );
99
100     if( (timer = fgState.FreeTimers.Last) )
101     {
102         fgListRemove( &fgState.FreeTimers, &timer->Node );
103     }
104     else
105     {
106         if( ! (timer = malloc(sizeof(SFG_Timer))) )
107             fgError( "Fatal error: "
108                      "Memory allocation failure in glutTimerFunc()" );
109     }
110
111     timer->Callback  = callback;
112     timer->ID        = timerID;
113     timer->TriggerTime = fgElapsedTime() + timeOut;
114
115     for( node = fgState.Timers.First; node; node = node->Node.Next )
116     {
117         if( node->TriggerTime > timer->TriggerTime )
118             break;
119     }
120
121     fgListInsert( &fgState.Timers, &node->Node, &timer->Node );
122 }
123
124 /*
125  * Sets the Visibility callback for the current window.
126  */
127 static void fghVisibility( int status )
128 {
129     int glut_status = GLUT_VISIBLE;
130
131     freeglut_return_if_fail( fgStructure.Window );
132
133     if( ( GLUT_HIDDEN == status )  || ( GLUT_FULLY_COVERED == status ) )
134         glut_status = GLUT_NOT_VISIBLE;
135     INVOKE_WCB( *( fgStructure.Window ), Visibility, ( glut_status ) );
136 }
137
138 void FGAPIENTRY glutVisibilityFunc( void (* callback)( int ) )
139 {
140     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutVisibilityFunc" );
141     SET_CALLBACK( Visibility );
142
143     if( callback )
144         glutWindowStatusFunc( fghVisibility );
145     else
146         glutWindowStatusFunc( NULL );
147 }
148
149 /*
150  * Sets the keyboard key release callback for the current window
151  */
152 void FGAPIENTRY glutKeyboardUpFunc( void (* callback)
153                                     ( unsigned char, int, int ) )
154 {
155     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutKeyboardUpFunc" );
156     SET_CALLBACK( KeyboardUp );
157 }
158
159 /*
160  * Sets the special key release callback for the current window
161  */
162 void FGAPIENTRY glutSpecialUpFunc( void (* callback)( int, int, int ) )
163 {
164     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpecialUpFunc" );
165     SET_CALLBACK( SpecialUp );
166 }
167
168 /*
169  * Sets the joystick callback and polling rate for the current window
170  */
171 void FGAPIENTRY glutJoystickFunc( void (* callback)
172                                   ( unsigned int, int, int, int ),
173                                   int pollInterval )
174 {
175     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickFunc" );
176     fgInitialiseJoysticks ();
177
178     SET_CALLBACK( Joystick );
179     fgStructure.Window->State.JoystickPollRate = pollInterval;
180
181     fgStructure.Window->State.JoystickLastPoll =
182         fgElapsedTime() - fgStructure.Window->State.JoystickPollRate;
183
184     if( fgStructure.Window->State.JoystickLastPoll < 0 )
185         fgStructure.Window->State.JoystickLastPoll = 0;
186 }
187
188 /*
189  * Sets the mouse callback for the current window
190  */
191 void FGAPIENTRY glutMouseFunc( void (* callback)( int, int, int, int ) )
192 {
193     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMouseFunc" );
194     SET_CALLBACK( Mouse );
195 }
196
197 /*
198  * Sets the mouse wheel callback for the current window
199  */
200 void FGAPIENTRY glutMouseWheelFunc( void (* callback)( int, int, int, int ) )
201 {
202     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMouseWheelFunc" );
203     SET_CALLBACK( MouseWheel );
204 }
205
206 /*
207  * Sets the mouse motion callback for the current window (one or more buttons
208  * are pressed)
209  */
210 void FGAPIENTRY glutMotionFunc( void (* callback)( int, int ) )
211 {
212     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMotionFunc" );
213     SET_CALLBACK( Motion );
214 }
215
216 /*
217  * Sets the passive mouse motion callback for the current window (no mouse
218  * buttons are pressed)
219  */
220 void FGAPIENTRY glutPassiveMotionFunc( void (* callback)( int, int ) )
221 {
222     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPassiveMotionFunc" );
223     SET_CALLBACK( Passive );
224 }
225
226 /*
227  * Window mouse entry/leave callback
228  */
229 void FGAPIENTRY glutEntryFunc( void (* callback)( int ) )
230 {
231     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutEntryFunc" );
232     SET_CALLBACK( Entry );
233 }
234
235 /*
236  * Window destruction callbacks
237  */
238 void FGAPIENTRY glutCloseFunc( void (* callback)( void ) )
239 {
240     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCloseFunc" );
241     SET_CALLBACK( Destroy );
242 }
243
244 void FGAPIENTRY glutWMCloseFunc( void (* callback)( void ) )
245 {
246     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWMCloseFunc" );
247     glutCloseFunc( callback );
248 }
249
250 /* A. Donev: Destruction callback for menus */
251 void FGAPIENTRY glutMenuDestroyFunc( void (* callback)( void ) )
252 {
253     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuDestroyFunc" );
254     if( fgStructure.Menu )
255         fgStructure.Menu->Destroy = callback;
256 }
257
258 /*
259  * Deprecated version of glutMenuStatusFunc callback setting method
260  */
261 void FGAPIENTRY glutMenuStateFunc( void (* callback)( int ) )
262 {
263     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStateFunc" );
264     fgState.MenuStateCallback = callback;
265 }
266
267 /*
268  * Sets the global menu status callback for the current window
269  */
270 void FGAPIENTRY glutMenuStatusFunc( void (* callback)( int, int, int ) )
271 {
272     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStatusFunc" );
273     fgState.MenuStatusCallback = callback;
274 }
275
276 /*
277  * Sets the overlay display callback for the current window
278  */
279 void FGAPIENTRY glutOverlayDisplayFunc( void (* callback)( void ) )
280 {
281     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutOverlayDisplayFunc" );
282     SET_CALLBACK( OverlayDisplay );
283 }
284
285 /*
286  * Sets the window status callback for the current window
287  */
288 void FGAPIENTRY glutWindowStatusFunc( void (* callback)( int ) )
289 {
290     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWindowStatusFunc" );
291     SET_CALLBACK( WindowStatus );
292 }
293
294 /*
295  * Sets the spaceball motion callback for the current window
296  */
297 void FGAPIENTRY glutSpaceballMotionFunc( void (* callback)( int, int, int ) )
298 {
299     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballMotionFunc" );
300     SET_CALLBACK( SpaceMotion );
301 }
302
303 /*
304  * Sets the spaceball rotate callback for the current window
305  */
306 void FGAPIENTRY glutSpaceballRotateFunc( void (* callback)( int, int, int ) )
307 {
308     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballRotateFunc" );
309     SET_CALLBACK( SpaceRotation );
310 }
311
312 /*
313  * Sets the spaceball button callback for the current window
314  */
315 void FGAPIENTRY glutSpaceballButtonFunc( void (* callback)( int, int ) )
316 {
317     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballButtonFunc" );
318     SET_CALLBACK( SpaceButton );
319 }
320
321 /*
322  * Sets the button box callback for the current window
323  */
324 void FGAPIENTRY glutButtonBoxFunc( void (* callback)( int, int ) )
325 {
326     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutButtonBoxFunc" );
327     SET_CALLBACK( ButtonBox );
328 }
329
330 /*
331  * Sets the dials box callback for the current window
332  */
333 void FGAPIENTRY glutDialsFunc( void (* callback)( int, int ) )
334 {
335     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDialsFunc" );
336     SET_CALLBACK( Dials );
337 }
338
339 /*
340  * Sets the tablet motion callback for the current window
341  */
342 void FGAPIENTRY glutTabletMotionFunc( void (* callback)( int, int ) )
343 {
344     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTabletMotionFunc" );
345     SET_CALLBACK( TabletMotion );
346 }
347
348 /*
349  * Sets the tablet buttons callback for the current window
350  */
351 void FGAPIENTRY glutTabletButtonFunc( void (* callback)( int, int, int, int ) )
352 {
353     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTabletButtonFunc" );
354     SET_CALLBACK( TabletButton );
355 }
356
357 /*** END OF FILE ***/