1d1350206e151f60da5a27945e0e8bd01703dc14
[freeglut] / progs / demos / CallbackMaker / CallbackMaker.c
1 /* CallbackMaker.c */
2 /*
3  * Program to invoke all the callbacks that "freeglut" supports
4  */
5
6
7 #include <GL/freeglut.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <stdarg.h>
11
12 static int sequence_number = 0 ;
13
14 int windows[2] = {0};
15
16 /* define status vars showing whether given callback has been called for given window */
17 #define CALLBACK_CALLED_VAR(name)                            int name##_called[2]   = {0};
18 #define CALLBACK_0V(name)                                    int name##_seq[2]      = {-1}; CALLBACK_CALLED_VAR(name); 
19 #define CALLBACK_1V(name,field)                              int name##_##field[2]  = {-1}; CALLBACK_0V(name);
20 #define CALLBACK_2V(name,field1,field2)                      int name##_##field2[2] = {-1}; CALLBACK_1V(name,field1);
21 #define CALLBACK_3V(name,field1,field2,field3)               int name##_##field3[2] = {-1}; CALLBACK_2V(name,field1,field2);
22 #define CALLBACK_4V(name,field1,field2,field3,field4)        int name##_##field4[2] = {-1}; CALLBACK_3V(name,field1,field2,field3);
23 #define CALLBACK_5V(name,field1,field2,field3,field4,field5) int name##_##field5[2] = {-1}; CALLBACK_4V(name,field1,field2,field3,field4);
24 CALLBACK_2V(reshape,width,height);
25 CALLBACK_2V(position,top,left);
26 CALLBACK_1V(visibility,vis);
27 CALLBACK_4V(key,key,x,y,mod);
28 CALLBACK_4V(keyup,key,x,y,mod);
29 CALLBACK_4V(special,key,x,y,mod);
30 CALLBACK_4V(specialup,key,x,y,mod);
31 CALLBACK_4V(joystick,a,b,c,d);
32 CALLBACK_5V(mouse,button,updown,x,y,mod);
33 CALLBACK_5V(mousewheel,number,direction,x,y,mod);
34 CALLBACK_3V(motion,x,y,mod);
35 CALLBACK_3V(passivemotion,x,y,mod);
36 CALLBACK_1V(entry,state);
37 CALLBACK_0V(close);
38 /* menudestroy is registered on each menu, not a window */
39 int menudestroy_called = 0 ;
40 /* menustatus and menustate are global callbacks, set for all menus at the same time */
41 int menustatus_called = 0;
42 int menustate_called = 0;
43
44 #define STRING_LENGTH   10
45
46 static void
47 bitmapPrintf (const char *fmt, ...)
48 {
49     static char buf[256];
50     va_list args;
51
52     va_start(args, fmt);
53 #if defined(WIN32) && !defined(__CYGWIN__)
54     (void) _vsnprintf (buf, sizeof(buf), fmt, args);
55 #else
56     (void) vsnprintf (buf, sizeof(buf), fmt, args);
57 #endif
58     va_end(args);
59     glutBitmapString ( GLUT_BITMAP_HELVETICA_12, (unsigned char*)buf ) ;
60 }
61
62 static int
63 getWindowAndIdx(int *winIdx)
64 {
65     int window = glutGetWindow();
66
67     if (winIdx)
68         (*winIdx) = window==windows[0]?0:1;
69
70     return window;
71 }
72
73 static void
74 Mod2Text(int mods, char *text)
75 {
76     if (mods&GLUT_ACTIVE_CTRL)
77         strcat(text,"CTRL");
78     if (mods&GLUT_ACTIVE_SHIFT)
79         if (text[0])
80             strcat(text,"+SHIFT");
81         else
82             strcat(text,"SHIFT");
83     if (mods&GLUT_ACTIVE_ALT)
84         if (text[0])
85             strcat(text,"+ALT");
86         else
87             strcat(text,"ALT");
88
89     if (!text[0])
90         strcat(text,"none");
91 }
92
93 static void 
94 Display(void)
95 {
96   int winIdx;
97   int window = getWindowAndIdx(&winIdx);
98   glClear ( GL_COLOR_BUFFER_BIT );
99
100   glDisable ( GL_DEPTH_TEST );
101   glMatrixMode ( GL_PROJECTION );
102   glPushMatrix();
103   glLoadIdentity();
104   glOrtho(0, glutGet ( GLUT_WINDOW_WIDTH ), 
105           0, glutGet ( GLUT_WINDOW_HEIGHT ), -1, 1 );
106   glMatrixMode ( GL_MODELVIEW );
107   glPushMatrix ();
108   glLoadIdentity ();
109   glColor3ub ( 0, 0, 0 );
110   glRasterPos2i ( 10, glutGet ( GLUT_WINDOW_HEIGHT ) - 20 );    /* 10pt margin above 10pt letters */
111
112   if ( entry_called[winIdx] )
113   {
114     bitmapPrintf ( "Entry %d:  %d\n", entry_seq[winIdx], entry_state[winIdx] );
115   }
116   
117   if ( visibility_called[winIdx] )
118   {
119     bitmapPrintf ( "Visibility %d:  %d\n", visibility_seq[winIdx], visibility_vis[winIdx] );
120   }
121
122   if ( reshape_called[winIdx] )
123   {
124     bitmapPrintf ( "Reshape %d:  %d %d\n", reshape_seq[winIdx], reshape_width[winIdx], reshape_height[winIdx] );
125   }
126
127   if ( position_called[winIdx] )
128   {
129     bitmapPrintf ( "Position %d:  %d %d\n", position_seq[winIdx], position_left[winIdx], position_top[winIdx] );
130   }
131
132   if ( key_called[winIdx] )
133   {
134     char mods[50] = {0};
135     Mod2Text(key_mod[winIdx],mods);
136     bitmapPrintf ( "Key %d:  %d(%c) %d %d (mod: %s)\n", key_seq[winIdx], key_key[winIdx], key_key[winIdx], key_x[winIdx], key_y[winIdx], mods );
137   }
138
139   if ( keyup_called[winIdx] )
140   {
141     char mods[50] = {0};
142     Mod2Text(keyup_mod[winIdx],mods);
143     bitmapPrintf ( "Key Up %d:  %d(%c) %d %d (mod: %s)\n", keyup_seq[winIdx], keyup_key[winIdx], keyup_key[winIdx], keyup_x[winIdx], keyup_y[winIdx], mods );
144   }
145
146   if ( special_called[winIdx] )
147   {
148     char mods[50] = {0};
149     Mod2Text(special_mod[winIdx],mods);
150     bitmapPrintf ( "Special %d:  %d(%c) %d %d (mod: %s)\n", special_seq[winIdx], special_key[winIdx], special_key[winIdx], special_x[winIdx], special_y[winIdx], mods );
151   }
152
153   if ( specialup_called[winIdx] )
154   {
155     char mods[50] = {0};
156     Mod2Text(specialup_mod[winIdx],mods);
157     bitmapPrintf ( "Special Up %d:  %d(%c) %d %d (mod: %s)\n", specialup_seq[winIdx], specialup_key[winIdx], specialup_key[winIdx], specialup_x[winIdx], specialup_y[winIdx], mods );
158   }
159
160   if ( joystick_called[winIdx] )
161   {
162     bitmapPrintf ( "Joystick %d:  %d %d %d %d\n", joystick_seq[winIdx], joystick_a[winIdx], joystick_b[winIdx], joystick_c[winIdx], joystick_d[winIdx] );
163   }
164
165   if ( mouse_called[winIdx] )
166   {
167     char mods[50] = {0};
168     Mod2Text(mouse_mod[winIdx],mods);
169     bitmapPrintf ( "Mouse %d:  %d %d %d %d (mod: %s)\n", mouse_seq[winIdx], mouse_button[winIdx], mouse_updown[winIdx], mouse_x[winIdx], mouse_y[winIdx], mods );
170   }
171
172   if ( mousewheel_called[winIdx] )
173   {
174     char mods[50] = {0};
175     Mod2Text(mousewheel_mod[winIdx],mods);
176     bitmapPrintf ( "Mouse Wheel %d:  %d %d %d %d (mod: %s)\n", mousewheel_seq[winIdx], mousewheel_number[winIdx], mousewheel_direction[winIdx], mousewheel_x[winIdx], mousewheel_y[winIdx], mods );
177   }
178
179   if ( motion_called[winIdx] )
180   {
181     char mods[50] = {0};
182     Mod2Text(motion_mod[winIdx],mods);
183     bitmapPrintf ( "Motion %d:  %d %d (mod: %s)\n", motion_seq[winIdx], motion_x[winIdx], motion_y[winIdx], mods );
184   }
185
186   if ( passivemotion_called[winIdx] )
187   {
188     char mods[50] = {0};
189     Mod2Text(passivemotion_mod[winIdx],mods);
190     bitmapPrintf ( "Passive Motion %d:  %d %d (mod: %s)\n", passivemotion_seq[winIdx], passivemotion_x[winIdx], passivemotion_y[winIdx], mods );
191   }
192
193   glMatrixMode ( GL_PROJECTION );
194   glPopMatrix ();
195   glMatrixMode ( GL_MODELVIEW );
196   glPopMatrix ();
197   glEnable ( GL_DEPTH_TEST );
198
199   printf ( "%6d Window %d Display Callback\n",
200             ++sequence_number, window ) ;
201   glutSwapBuffers();
202 }
203
204 static void
205 Warning(const char *fmt, va_list ap)
206 {
207     printf("%6d Warning callback:\n");
208
209     /* print warning message */
210     vprintf(fmt, ap);
211 }
212
213 static void
214 Error(const char *fmt, va_list ap)
215 {
216     char dummy_string[STRING_LENGTH];
217     printf("%6d Error callback:\n");
218
219     /* print warning message */
220     vprintf(fmt, ap);
221
222     /* terminate program, after pause for input so user can see */
223     printf ( "Please enter something to exit: " );
224     fgets ( dummy_string, STRING_LENGTH, stdin );
225
226     /* Call exit directly as freeglut is messed
227      * up internally when an error is called. 
228      */
229     exit(1);
230 }
231
232 static void 
233 Visibility(int vis)
234 {
235   int winIdx;
236   int window = getWindowAndIdx(&winIdx);
237   printf ( "%6d Window %d Visibility Callback:  %d\n",
238             ++sequence_number, window, vis ) ;
239   visibility_called[winIdx] = 1 ;
240   visibility_vis[winIdx] = vis ;
241   visibility_seq[winIdx] = sequence_number ;
242   glutPostRedisplay () ;
243 }
244
245 static void 
246 Reshape(int width, int height)
247 {
248   int winIdx;
249   int window = getWindowAndIdx(&winIdx);
250   printf ( "%6d Window %d Reshape Callback:  %d %d\n",
251             ++sequence_number, window, width, height ) ;
252   reshape_called[winIdx] = 1 ;
253   reshape_width[winIdx] = width ;
254   reshape_height[winIdx] = height ;
255   reshape_seq[winIdx] = sequence_number ;
256   glViewport(0,0,width,height);
257   glutPostRedisplay () ;
258 }
259
260 static void 
261 Position(int left, int top)
262 {
263   int winIdx;
264   int window = getWindowAndIdx(&winIdx);
265   printf ( "%6d Window %d Position Callback:  %d %d\n",
266             ++sequence_number, window, left, top ) ;
267   position_called[winIdx] = 1 ;
268   position_left[winIdx] = left ;
269   position_top[winIdx] = top ;
270   position_seq[winIdx] = sequence_number ;
271   glutPostRedisplay () ;
272 }
273
274 static void 
275 Key(unsigned char key, int x, int y)
276 {
277   int winIdx;
278   int window = getWindowAndIdx(&winIdx);
279   printf ( "%6d Window %d Keyboard Callback:  %d %d %d\n",
280             ++sequence_number, window, key, x, y ) ;
281   key_called[winIdx] = 1 ;
282   key_key[winIdx] = key ;
283   key_x[winIdx] = x ;
284   key_y[winIdx] = y ;
285   key_seq[winIdx] = sequence_number ;
286   key_mod[winIdx] = glutGetModifiers() ;
287   glutPostRedisplay () ;
288 }
289
290 static void 
291 KeyUp(unsigned char key, int x, int y)
292 {
293   int winIdx;
294   int window = getWindowAndIdx(&winIdx);
295   printf ( "%6d Window %d Key Release Callback:  %d %d %d\n",
296             ++sequence_number, window, key, x, y ) ;
297   keyup_called[winIdx] = 1 ;
298   keyup_key[winIdx] = key ;
299   keyup_x[winIdx] = x ;
300   keyup_y[winIdx] = y ;
301   keyup_seq[winIdx] = sequence_number ;
302   keyup_mod[winIdx] = glutGetModifiers() ;
303   glutPostRedisplay () ;
304 }
305
306 static void 
307 Special(int key, int x, int y)
308 {
309   int winIdx;
310   int window = getWindowAndIdx(&winIdx);
311   printf ( "%6d Window %d Special Key Callback:  %d %d %d\n",
312             ++sequence_number, window, key, x, y ) ;
313   special_called[winIdx] = 1 ;
314   special_key[winIdx] = key ;
315   special_x[winIdx] = x ;
316   special_y[winIdx] = y ;
317   special_seq[winIdx] = sequence_number ;
318   special_mod[winIdx] = glutGetModifiers() ;
319   glutPostRedisplay () ;
320 }
321
322 static void 
323 SpecialUp(int key, int x, int y)
324 {
325   int winIdx;
326   int window = getWindowAndIdx(&winIdx);
327   printf ( "%6d Window %d Special Key Release Callback:  %d %d %d\n",
328             ++sequence_number, window, key, x, y ) ;
329   specialup_called[winIdx] = 1 ;
330   specialup_key[winIdx] = key ;
331   specialup_x[winIdx] = x ;
332   specialup_y[winIdx] = y ;
333   specialup_seq[winIdx] = sequence_number ;
334   specialup_mod[winIdx] = glutGetModifiers() ;
335   glutPostRedisplay () ;
336 }
337
338 static void 
339 Joystick( unsigned int a, int b, int c, int d)  /* Need meaningful names */
340 {
341   int winIdx;
342   int window = getWindowAndIdx(&winIdx);
343   printf ( "%6d Window %d Joystick Callback:  %d %d %d %d\n",
344             ++sequence_number, window, a, b, c, d ) ;
345   joystick_called[winIdx] = 1 ;
346   joystick_a[winIdx] = a ;
347   joystick_b[winIdx] = b ;
348   joystick_c[winIdx] = c ;
349   joystick_d[winIdx] = d ;
350   joystick_seq[winIdx] = sequence_number ;
351   glutPostRedisplay () ;
352 }
353
354 static void 
355 Mouse(int button, int updown, int x, int y)
356 {
357   int winIdx;
358   int window = getWindowAndIdx(&winIdx);
359   printf ( "%6d Window %d Mouse Click Callback:  %d %d %d %d\n",
360             ++sequence_number, window, button, updown, x, y ) ;
361   mouse_called[winIdx] = 1 ;
362   mouse_button[winIdx] = button ;
363   mouse_updown[winIdx] = updown ;
364   mouse_x[winIdx] = x ;
365   mouse_y[winIdx] = y ;
366   mouse_seq[winIdx] = sequence_number ;
367   mouse_mod[winIdx] = glutGetModifiers() ;
368   glutPostRedisplay () ;
369 }
370
371 static void 
372 MouseWheel(int wheel_number, int direction, int x, int y)
373 {
374   int winIdx;
375   int window = getWindowAndIdx(&winIdx);
376   printf ( "%6d Window %d Mouse Wheel Callback:  %d %d %d %d\n",
377             ++sequence_number, window, wheel_number, direction, x, y ) ;
378   mousewheel_called[winIdx] = 1 ;
379   mousewheel_number[winIdx] = wheel_number ;
380   mousewheel_direction[winIdx] = direction ;
381   mousewheel_x[winIdx] = x ;
382   mousewheel_y[winIdx] = y ;
383   mousewheel_seq[winIdx] = sequence_number ;
384   mousewheel_mod[winIdx] = glutGetModifiers() ;
385   glutPostRedisplay () ;
386 }
387
388 static void 
389 Motion(int x, int y)
390 {
391   int winIdx;
392   int window = getWindowAndIdx(&winIdx);
393   printf ( "%6d Window %d Mouse Motion Callback:  %d %d\n",
394             ++sequence_number, window, x, y ) ;
395   motion_called[winIdx] = 1 ;
396   motion_x[winIdx] = x ;
397   motion_y[winIdx] = y ;
398   motion_seq[winIdx] = sequence_number ;
399   motion_mod[winIdx] = glutGetModifiers() ;
400   glutPostRedisplay () ;
401 }
402
403 static void 
404 PassiveMotion(int x, int y)
405 {
406   int winIdx;
407   int window = getWindowAndIdx(&winIdx);
408   printf ( "%6d Window %d Mouse Passive Motion Callback:  %d %d\n",
409             ++sequence_number, window, x, y ) ;
410   passivemotion_called[winIdx] = 1 ;
411   passivemotion_x[winIdx] = x ;
412   passivemotion_y[winIdx] = y ;
413   passivemotion_seq[winIdx] = sequence_number ;
414   passivemotion_mod[winIdx] = glutGetModifiers() ;
415   glutPostRedisplay () ;
416 }
417
418 static void 
419 Entry(int state)
420 {
421   int winIdx;
422   int window = getWindowAndIdx(&winIdx);
423   printf ( "%6d Window %d Entry Callback:  %d\n",
424             ++sequence_number, window, state ) ;
425   entry_called[winIdx] = 1 ;
426   entry_seq[winIdx] = sequence_number;
427   entry_state[winIdx] = state;
428   glutPostRedisplay () ;
429 }
430
431 static void 
432 Close(void)
433 {
434   int window = getWindowAndIdx(NULL);
435   printf ( "%6d Window %d Close Callback\n",
436             ++sequence_number, window ) ;
437 }
438
439 static void 
440 OverlayDisplay(void)
441 {
442   int window = getWindowAndIdx(NULL);
443   printf ( "%6d Window %d OverlayDisplay Callback\n",
444             ++sequence_number, window ) ;
445   glutPostRedisplay () ;
446 }
447
448 static void 
449 WindowStatus(int state)
450 {
451   int window = getWindowAndIdx(NULL);
452   printf ( "%6d Window %d WindowStatus Callback:  %d\n",
453             ++sequence_number, window, state ) ;
454   glutPostRedisplay () ;
455 }
456
457 static void 
458 SpaceMotion(int x, int y, int z)
459 {
460   int window = getWindowAndIdx(NULL);
461   printf ( "%6d Window %d SpaceMotion Callback:  %d %d %d\n",
462             ++sequence_number, window, x, y, z ) ;
463   glutPostRedisplay () ;
464 }
465
466 static void 
467 SpaceRotation(int x, int y, int z)
468 {
469   int window = getWindowAndIdx(NULL);
470   printf ( "%6d Window %d SpaceRotation Callback:  %d %d %d\n",
471             ++sequence_number, window, x, y, z ) ;
472   glutPostRedisplay () ;
473 }
474
475 static void 
476 SpaceButton(int button, int updown)
477 {
478   int window = getWindowAndIdx(NULL);
479   printf ( "%6d Window %d SpaceButton Callback:  %d %d\n",
480             ++sequence_number, window, button, updown ) ;
481   glutPostRedisplay () ;
482 }
483
484 static void 
485 Dials(int x, int y)
486 {
487   int window = getWindowAndIdx(NULL);
488   printf ( "%6d Window %d Dials Callback:  %d %d\n",
489             ++sequence_number, window, x, y ) ;
490   glutPostRedisplay () ;
491 }
492
493 static void 
494 ButtonBox(int button, int updown)
495 {
496   int window = getWindowAndIdx(NULL);
497   printf ( "%6d Window %d ButtonBox Callback:  %d %d\n",
498             ++sequence_number, window, button, updown ) ;
499   glutPostRedisplay () ;
500 }
501
502 static void 
503 TabletMotion(int x, int y)
504 {
505   int window = getWindowAndIdx(NULL);
506   printf ( "%6d Window %d TabletMotion Callback:  %d %d\n",
507             ++sequence_number, window, x, y ) ;
508   glutPostRedisplay () ;
509 }
510
511 static void 
512 TabletButton(int button, int updown, int x, int y)
513 {
514   int window = getWindowAndIdx(NULL);
515   printf ( "%6d Window %d TabletButton Callback:  %d %d %d %d\n",
516             ++sequence_number, window, button, updown, x, y ) ;
517   glutPostRedisplay () ;
518 }
519
520 static void
521 MenuCallback ( int value )
522 {
523   int menu = glutGetMenu();
524   int window = getWindowAndIdx(NULL);
525   printf( "%6d Menu %d MenuCallback for menu opened in Window %d - value is %d\n",
526           ++sequence_number, menu, window, value );
527 }
528
529 static void 
530 MenuDestroy( void )
531 {
532   int menu = glutGetMenu();
533   menudestroy_called = 1 ;
534   printf ( "%6d Menu %d MenuDestroy Callback\n",
535             ++sequence_number, menu ) ;
536 }
537
538 static void 
539 MenuStatus( int status, int x, int y )
540 {
541   /* Menu and window for which this event is triggered are current when the callback is called */
542   int menu = glutGetMenu();
543   int window = getWindowAndIdx(NULL);
544   menustatus_called = 1 ;
545   printf ( "%6d Menu %d MenuStatus Callback in Window %d:  %d %d %d\n",
546             ++sequence_number, menu, window, status, x, y ) ;
547   glutPostRedisplay () ;
548 }
549
550
551 static void 
552 MenuState( int status )
553 {
554   /* Menu and window for which this event is triggered are current when the callback is called */
555   int menu = glutGetMenu();
556   int window = getWindowAndIdx(NULL);
557   menustate_called = 1 ;
558   printf ( "%6d Menu %d MenuState Callback in Window %d:  %d\n",
559             ++sequence_number, menu, window, status) ;
560   glutPostRedisplay () ;
561 }
562
563 static void Idle ( void )
564 {
565   ++sequence_number ;
566 }
567
568 int 
569 main(int argc, char *argv[])
570 {
571   char dummy_string[STRING_LENGTH];
572
573   int menuID, subMenuA, subMenuB;
574
575   glutInitWarningFunc(Warning);
576   glutInitErrorFunc(Error);
577   glutInitWindowSize(500, 250);
578   glutInitWindowPosition ( 140, 140 );
579   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE );
580   glutInit(&argc, argv);
581   glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,GLUT_ACTION_CONTINUE_EXECUTION);
582
583   /* Set other global callback (global as in not associated with any specific menu or window) */
584   glutIdleFunc ( Idle );
585   glutMenuStatusFunc ( MenuStatus );
586   glutMenuStateFunc  ( MenuState ); /* Note that glutMenuStatusFunc is an enhanced version of the deprecated glutMenuStateFunc. */
587
588   windows[0] = glutCreateWindow( "Callback Demo" );
589   printf ( "Creating window %d as 'Callback Demo'\n", windows[0] ) ;
590
591   glClearColor(1.0, 1.0, 1.0, 1.0);
592
593   /* callbacks and settings specific to this window */
594   glutDisplayFunc( Display );
595   glutReshapeFunc( Reshape );
596   glutPositionFunc( Position );
597   glutKeyboardFunc( Key );
598   glutSpecialFunc( Special );
599   glutVisibilityFunc( Visibility );
600   glutKeyboardUpFunc( KeyUp );
601   glutSpecialUpFunc( SpecialUp );
602   glutJoystickFunc( Joystick, 100 );
603   glutMouseFunc ( Mouse ) ;
604   glutMouseWheelFunc ( MouseWheel ) ;
605   glutMotionFunc ( Motion ) ;
606   glutPassiveMotionFunc ( PassiveMotion ) ;
607   glutEntryFunc ( Entry ) ;
608   glutCloseFunc ( Close ) ;
609   glutOverlayDisplayFunc ( OverlayDisplay ) ;
610   glutWindowStatusFunc ( WindowStatus ) ;
611   glutSpaceballMotionFunc ( SpaceMotion ) ;
612   glutSpaceballRotateFunc ( SpaceRotation ) ;
613   glutSpaceballButtonFunc ( SpaceButton ) ;
614   glutButtonBoxFunc ( ButtonBox ) ;
615   glutDialsFunc ( Dials ) ;
616   glutTabletMotionFunc ( TabletMotion ) ;
617   glutTabletButtonFunc ( TabletButton ) ;
618   glutSetKeyRepeat(GLUT_KEY_REPEAT_OFF) ;
619
620   subMenuA = glutCreateMenu( MenuCallback );
621   glutAddMenuEntry( "Sub menu A1 (01)", 11 );
622   glutAddMenuEntry( "Sub menu A2 (02)", 12 );
623   glutAddMenuEntry( "Sub menu A3 (03)", 13 );
624   glutMenuDestroyFunc ( MenuDestroy );  /* callback specific to this menu */
625
626   subMenuB = glutCreateMenu( MenuCallback );
627   glutAddMenuEntry( "Sub menu B1 (04)", 14 );
628   glutAddMenuEntry( "Sub menu B2 (05)", 15 );
629   glutAddMenuEntry( "Sub menu B3 (06)", 16 );
630   glutAddSubMenu( "Going to sub menu A", subMenuA );
631   glutMenuDestroyFunc ( MenuDestroy );  /* callback specific to this menu */
632
633   menuID = glutCreateMenu( MenuCallback );
634   glutAddMenuEntry( "Entry one",   21 );
635   glutAddMenuEntry( "Entry two",   22 );
636   glutAddMenuEntry( "Entry three", 23 );
637   glutAddMenuEntry( "Entry four",  24 );
638   glutAddMenuEntry( "Entry five",  25 );
639   glutAddSubMenu( "Enter sub menu A", subMenuA );
640   glutAddSubMenu( "Enter sub menu B", subMenuB );
641   glutMenuDestroyFunc ( MenuDestroy );  /* callback specific to this menu */
642
643   glutAttachMenu( GLUT_LEFT_BUTTON );
644
645   glutInitWindowPosition ( 140+500+2*glutGet(GLUT_WINDOW_BORDER_WIDTH), 140 );
646   /* Position second window right next to the first */
647   windows[1] = glutCreateWindow( "Second Window" );
648   printf ( "Creating window %d as 'Second Window'\n", windows[1] ) ;
649
650   glClearColor(1.0, 1.0, 1.0, 1.0);
651
652   /* callbacks and settings specific to this window */
653   glutDisplayFunc( Display );
654   glutReshapeFunc( Reshape );
655   glutPositionFunc( Position );
656   glutKeyboardFunc( Key );
657   glutSpecialFunc( Special );
658   glutVisibilityFunc( Visibility );
659   glutKeyboardUpFunc( KeyUp );
660   glutSpecialUpFunc( SpecialUp );
661   /*  glutJoystickFunc( Joystick, 100 ); */
662   glutMouseFunc ( Mouse ) ;
663   glutMouseWheelFunc ( MouseWheel ) ;
664   glutMotionFunc ( Motion ) ;
665   glutPassiveMotionFunc ( PassiveMotion ) ;
666   glutEntryFunc ( Entry ) ;
667   glutCloseFunc ( Close ) ;
668   glutOverlayDisplayFunc ( OverlayDisplay ) ;
669   glutWindowStatusFunc ( WindowStatus ) ;
670   glutSpaceballMotionFunc ( SpaceMotion ) ;
671   glutSpaceballRotateFunc ( SpaceRotation ) ;
672   glutSpaceballButtonFunc ( SpaceButton ) ;
673   glutButtonBoxFunc ( ButtonBox ) ;
674   glutDialsFunc ( Dials ) ;
675   glutTabletMotionFunc ( TabletMotion ) ;
676   glutTabletButtonFunc ( TabletButton ) ;
677   glutSetKeyRepeat(GLUT_KEY_REPEAT_OFF) ;
678
679   glutSetMenu(subMenuB);
680   glutAttachMenu( GLUT_RIGHT_BUTTON );
681
682
683   printf ( "Please enter something to continue: " );
684   fgets ( dummy_string, STRING_LENGTH, stdin );
685
686   glutMainLoop();
687
688   printf ( "Back from the 'freeglut' main loop\n" ) ;
689
690   return EXIT_SUCCESS;
691 }