Fix object/function pointer inconsistencies which are a problem for gcc 3.4.2.
[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 do                                                       \
38 {                                                        \
39     if( fgStructure.Window == NULL )                     \
40         return;                                          \
41     SET_WCB( ( *( fgStructure.Window ) ), a, callback ); \
42 } while( 0 )
43
44 /*
45  * Sets the Display callback for the current window
46  */
47 void FGAPIENTRY glutDisplayFunc( void (* callback)( void ) )
48 {
49     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDisplayFunc" );
50     if( !callback )
51         fgError( "Fatal error in program.  NULL display callback not "
52                  "permitted in GLUT 3.0+ or freeglut 2.0.1+" );
53     SET_CALLBACK( Display );
54 }
55
56 /*
57  * Sets the Reshape callback for the current window
58  */
59 void FGAPIENTRY glutReshapeFunc( void (* callback)( int, int ) )
60 {
61     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeFunc" );
62     SET_CALLBACK( Reshape );
63 }
64
65 /*
66  * Sets the Keyboard callback for the current window
67  */
68 void FGAPIENTRY glutKeyboardFunc( void (* callback)
69                                   ( unsigned char, int, int ) )
70 {
71     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutKeyboardFunc" );
72     SET_CALLBACK( Keyboard );
73 }
74
75 /*
76  * Sets the Special callback for the current window
77  */
78 void FGAPIENTRY glutSpecialFunc( void (* callback)( int, int, int ) )
79 {
80     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpecialFunc" );
81     SET_CALLBACK( Special );
82 }
83
84 /*
85  * Sets the global idle callback
86  */
87 void FGAPIENTRY glutIdleFunc( void (* callback)( void ) )
88 {
89     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIdleFunc" );
90     fgState.IdleCallback = callback;
91 }
92
93 /*
94  * Sets the Timer callback for the current window
95  */
96 void FGAPIENTRY glutTimerFunc( unsigned int timeOut, void (* callback)( int ),
97                                int timerID )
98 {
99     SFG_Timer *timer, *node;
100
101     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTimerFunc" );
102
103     if( (timer = fgState.FreeTimers.Last) )
104     {
105         fgListRemove( &fgState.FreeTimers, &timer->Node );
106     }
107     else
108     {
109         if( ! (timer = malloc(sizeof(SFG_Timer))) )
110             fgError( "Fatal error: "
111                      "Memory allocation failure in glutTimerFunc()" );
112     }
113
114     timer->Callback  = callback;
115     timer->ID        = timerID;
116     timer->TriggerTime = fgElapsedTime() + timeOut;
117
118     for( node = fgState.Timers.First; node; node = node->Node.Next )
119     {
120         if( node->TriggerTime > timer->TriggerTime )
121             break;
122     }
123
124     fgListInsert( &fgState.Timers, &node->Node, &timer->Node );
125 }
126
127 /*
128  * Sets the Visibility callback for the current window.
129  */
130 static void fghVisibility( int status )
131 {
132     int glut_status = GLUT_VISIBLE;
133
134     freeglut_return_if_fail( fgStructure.Window );
135
136     if( ( GLUT_HIDDEN == status )  || ( GLUT_FULLY_COVERED == status ) )
137         glut_status = GLUT_NOT_VISIBLE;
138     INVOKE_WCB( *( fgStructure.Window ), Visibility, ( glut_status ) );
139 }
140
141 void FGAPIENTRY glutVisibilityFunc( void (* callback)( int ) )
142 {
143     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutVisibilityFunc" );
144     SET_CALLBACK( Visibility );
145
146     if( callback )
147         glutWindowStatusFunc( fghVisibility );
148     else
149         glutWindowStatusFunc( NULL );
150 }
151
152 /*
153  * Sets the keyboard key release callback for the current window
154  */
155 void FGAPIENTRY glutKeyboardUpFunc( void (* callback)
156                                     ( unsigned char, int, int ) )
157 {
158     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutKeyboardUpFunc" );
159     SET_CALLBACK( KeyboardUp );
160 }
161
162 /*
163  * Sets the special key release callback for the current window
164  */
165 void FGAPIENTRY glutSpecialUpFunc( void (* callback)( int, int, int ) )
166 {
167     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpecialUpFunc" );
168     SET_CALLBACK( SpecialUp );
169 }
170
171 /*
172  * Sets the joystick callback and polling rate for the current window
173  */
174 void FGAPIENTRY glutJoystickFunc( void (* callback)
175                                   ( unsigned int, int, int, int ),
176                                   int pollInterval )
177 {
178     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickFunc" );
179     fgInitialiseJoysticks ();
180
181     SET_CALLBACK( Joystick );
182     fgStructure.Window->State.JoystickPollRate = pollInterval;
183
184     fgStructure.Window->State.JoystickLastPoll =
185         fgElapsedTime() - fgStructure.Window->State.JoystickPollRate;
186
187     if( fgStructure.Window->State.JoystickLastPoll < 0 )
188         fgStructure.Window->State.JoystickLastPoll = 0;
189 }
190
191 /*
192  * Sets the mouse callback for the current window
193  */
194 void FGAPIENTRY glutMouseFunc( void (* callback)( int, int, int, int ) )
195 {
196     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMouseFunc" );
197     SET_CALLBACK( Mouse );
198 }
199
200 /*
201  * Sets the mouse wheel callback for the current window
202  */
203 void FGAPIENTRY glutMouseWheelFunc( void (* callback)( int, int, int, int ) )
204 {
205     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMouseWheelFunc" );
206     SET_CALLBACK( MouseWheel );
207 }
208
209 /*
210  * Sets the mouse motion callback for the current window (one or more buttons
211  * are pressed)
212  */
213 void FGAPIENTRY glutMotionFunc( void (* callback)( int, int ) )
214 {
215     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMotionFunc" );
216     SET_CALLBACK( Motion );
217 }
218
219 /*
220  * Sets the passive mouse motion callback for the current window (no mouse
221  * buttons are pressed)
222  */
223 void FGAPIENTRY glutPassiveMotionFunc( void (* callback)( int, int ) )
224 {
225     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPassiveMotionFunc" );
226     SET_CALLBACK( Passive );
227 }
228
229 /*
230  * Window mouse entry/leave callback
231  */
232 void FGAPIENTRY glutEntryFunc( void (* callback)( int ) )
233 {
234     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutEntryFunc" );
235     SET_CALLBACK( Entry );
236 }
237
238 /*
239  * Window destruction callbacks
240  */
241 void FGAPIENTRY glutCloseFunc( void (* callback)( void ) )
242 {
243     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCloseFunc" );
244     SET_CALLBACK( Destroy );
245 }
246
247 void FGAPIENTRY glutWMCloseFunc( void (* callback)( void ) )
248 {
249     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWMCloseFunc" );
250     glutCloseFunc( callback );
251 }
252
253 /* A. Donev: Destruction callback for menus */
254 void FGAPIENTRY glutMenuDestroyFunc( void (* callback)( void ) )
255 {
256     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuDestroyFunc" );
257     if( fgStructure.Menu )
258         fgStructure.Menu->Destroy = callback;
259 }
260
261 /*
262  * Deprecated version of glutMenuStatusFunc callback setting method
263  */
264 void FGAPIENTRY glutMenuStateFunc( void (* callback)( int ) )
265 {
266     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStateFunc" );
267     fgState.MenuStateCallback = callback;
268 }
269
270 /*
271  * Sets the global menu status callback for the current window
272  */
273 void FGAPIENTRY glutMenuStatusFunc( void (* callback)( int, int, int ) )
274 {
275     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStatusFunc" );
276     fgState.MenuStatusCallback = callback;
277 }
278
279 /*
280  * Sets the overlay display callback for the current window
281  */
282 void FGAPIENTRY glutOverlayDisplayFunc( void (* callback)( void ) )
283 {
284     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutOverlayDisplayFunc" );
285     SET_CALLBACK( OverlayDisplay );
286 }
287
288 /*
289  * Sets the window status callback for the current window
290  */
291 void FGAPIENTRY glutWindowStatusFunc( void (* callback)( int ) )
292 {
293     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWindowStatusFunc" );
294     SET_CALLBACK( WindowStatus );
295 }
296
297 /*
298  * Sets the spaceball motion callback for the current window
299  */
300 void FGAPIENTRY glutSpaceballMotionFunc( void (* callback)( int, int, int ) )
301 {
302     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballMotionFunc" );
303     SET_CALLBACK( SpaceMotion );
304 }
305
306 /*
307  * Sets the spaceball rotate callback for the current window
308  */
309 void FGAPIENTRY glutSpaceballRotateFunc( void (* callback)( int, int, int ) )
310 {
311     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballRotateFunc" );
312     SET_CALLBACK( SpaceRotation );
313 }
314
315 /*
316  * Sets the spaceball button callback for the current window
317  */
318 void FGAPIENTRY glutSpaceballButtonFunc( void (* callback)( int, int ) )
319 {
320     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballButtonFunc" );
321     SET_CALLBACK( SpaceButton );
322 }
323
324 /*
325  * Sets the button box callback for the current window
326  */
327 void FGAPIENTRY glutButtonBoxFunc( void (* callback)( int, int ) )
328 {
329     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutButtonBoxFunc" );
330     SET_CALLBACK( ButtonBox );
331 }
332
333 /*
334  * Sets the dials box callback for the current window
335  */
336 void FGAPIENTRY glutDialsFunc( void (* callback)( int, int ) )
337 {
338     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDialsFunc" );
339     SET_CALLBACK( Dials );
340 }
341
342 /*
343  * Sets the tablet motion callback for the current window
344  */
345 void FGAPIENTRY glutTabletMotionFunc( void (* callback)( int, int ) )
346 {
347     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTabletMotionFunc" );
348     SET_CALLBACK( TabletMotion );
349 }
350
351 /*
352  * Sets the tablet buttons callback for the current window
353  */
354 void FGAPIENTRY glutTabletButtonFunc( void (* callback)( int, int, int, int ) )
355 {
356     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTabletButtonFunc" );
357     SET_CALLBACK( TabletButton );
358 }
359
360 /*** END OF FILE ***/