Made Modifers variable global as per glut classic.
[freeglut] / src / freeglut_init.c
1 /*
2  * freeglut_init.c
3  *
4  * Various freeglut initialization functions.
5  *
6  * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
7  * Written by Pawel W. Olszta, <olszta@sourceforge.net>
8  * Creation date: Thu Dec 2 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 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include "../include/GL/freeglut.h"
33 #include "freeglut_internal.h"
34
35 /*
36  * TODO BEFORE THE STABLE RELEASE:
37  *
38  *  fgDeinitialize()        -- Win32's OK, X11 needs the OS-specific
39  *                             deinitialization done
40  *  glutInitDisplayString() -- display mode string parsing
41  *
42  * Wouldn't it be cool to use gettext() for error messages? I just love
43  * bash saying  "nie znaleziono pliku" instead of "file not found" :)
44  * Is gettext easily portable?
45  */
46
47 /* -- GLOBAL VARIABLES ----------------------------------------------------- */
48
49 /*
50  * A structure pointed by g_pDisplay holds all information
51  * regarding the display, screen, root window etc.
52  */
53 SFG_Display fgDisplay;
54
55 /*
56  * The settings for the current freeglut session
57  */
58 SFG_State fgState = { { -1, -1, GL_FALSE },  /* Position */
59                       { 300, 300, GL_TRUE }, /* Size */
60                       GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH,  /* DisplayMode */
61                       GL_FALSE,              /* Initalized */
62                       GL_FALSE,              /* ForceDirectContext */
63                       GL_TRUE,               /* TryDirectContext */
64                       GL_FALSE,              /* ForceIconic */
65                       GL_FALSE,              /* UseCurrentContext */
66                       GL_FALSE,              /* GLDebugSwitch */
67                       GL_FALSE,              /* XSyncSwitch */
68                       GL_TRUE,               /* IgnoreKeyRepeat */
69                       0xffffffff,            /* Modifiers */
70                       0,                     /* FPSInterval */
71                       0,                     /* SwapCount */
72                       0,                     /* SwapTime */
73 #if TARGET_HOST_WIN32
74                       { 0, GL_FALSE },       /* Time */
75 #else
76                       { { 0, 0 }, GL_FALSE },
77 #endif
78                       { NULL, NULL },         /* Timers */
79                       NULL,                   /* IdleCallback */
80                       0,                      /* ActiveMenus */
81                       NULL,                   /* MenuStateCallback */
82                       NULL,                   /* MenuStatusCallback */
83                       { 640, 480, GL_TRUE },  /* GameModeSize */
84                       16,                     /* GameModeDepth */
85                       72,                     /* GameModeRefresh */
86                       GLUT_ACTION_EXIT,       /* ActionOnWindowClose */
87                       GLUT_EXEC_STATE_INIT    /* ExecState */
88                       NULL,                   /* ProgramName */
89 };
90
91
92 /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
93
94 /*
95  * A call to this function should initialize all the display stuff...
96  */
97 void fgInitialize( const char* displayName )
98 {
99 #if TARGET_HOST_UNIX_X11
100     fgDisplay.Display = XOpenDisplay( displayName );
101
102     if( fgDisplay.Display == NULL )
103         fgError( "failed to open display '%s'", XDisplayName( displayName ) );
104
105     if( !glXQueryExtension( fgDisplay.Display, NULL, NULL ) )
106         fgError( "OpenGL GLX extension not supported by display '%s'",
107             XDisplayName( displayName ) );
108
109     fgDisplay.Screen = DefaultScreen( fgDisplay.Display );
110     fgDisplay.RootWindow = RootWindow(
111         fgDisplay.Display,
112         fgDisplay.Screen
113     );
114
115     fgDisplay.ScreenWidth  = DisplayWidth(
116         fgDisplay.Display,
117         fgDisplay.Screen
118     );
119     fgDisplay.ScreenHeight = DisplayHeight(
120         fgDisplay.Display,
121         fgDisplay.Screen
122     );
123
124     fgDisplay.ScreenWidthMM = DisplayWidthMM(
125         fgDisplay.Display,
126         fgDisplay.Screen
127     );
128     fgDisplay.ScreenHeightMM = DisplayHeightMM(
129         fgDisplay.Display,
130         fgDisplay.Screen
131     );
132
133     fgDisplay.Connection = ConnectionNumber( fgDisplay.Display );
134
135     /*
136      * Create the window deletion atom
137      */
138     fgDisplay.DeleteWindow = XInternAtom(
139         fgDisplay.Display,
140         "WM_DELETE_WINDOW",
141         FALSE
142     );
143
144 #elif TARGET_HOST_WIN32
145
146     WNDCLASS wc;
147     ATOM atom;
148
149     /*
150      * What we need to do is to initialize the fgDisplay global structure here...
151      */
152     fgDisplay.Instance = GetModuleHandle( NULL );
153
154     atom = GetClassInfo( fgDisplay.Instance, "FREEGLUT", &wc );
155     if( atom == 0 )
156     {
157         ZeroMemory( &wc, sizeof(WNDCLASS) );
158
159         /*
160          * Each of the windows should have its own device context...
161          */
162         wc.style          = CS_OWNDC;
163         wc.lpfnWndProc    = fgWindowProc;
164         wc.cbClsExtra     = 0;
165         wc.cbWndExtra     = 0;
166         wc.hInstance      = fgDisplay.Instance;
167         wc.hIcon          = LoadIcon( fgDisplay.Instance, "GLUT_ICON" );
168         if (!wc.hIcon)
169           wc.hIcon        = LoadIcon( NULL, IDI_WINLOGO );
170
171         wc.hCursor        = LoadCursor( NULL, IDC_ARROW );
172         wc.hbrBackground  = NULL;
173         wc.lpszMenuName   = NULL;
174         wc.lpszClassName  = "FREEGLUT";
175
176         /*
177          * Register the window class
178          */
179         atom = RegisterClass( &wc );
180         assert( atom );
181     }
182
183     /*
184      * The screen dimensions can be obtained via GetSystemMetrics() calls
185      */
186     fgDisplay.ScreenWidth  = GetSystemMetrics( SM_CXSCREEN );
187     fgDisplay.ScreenHeight = GetSystemMetrics( SM_CYSCREEN );
188
189     {
190         HWND desktop = GetDesktopWindow( );
191         HDC  context = GetDC( desktop );
192
193         fgDisplay.ScreenWidthMM  = GetDeviceCaps( context, HORZSIZE );
194         fgDisplay.ScreenHeightMM = GetDeviceCaps( context, VERTSIZE );
195
196         ReleaseDC( desktop, context );
197     }
198
199 #endif
200
201     fgJoystickInit( 0 );
202
203     fgState.Initalized = GL_TRUE;
204 }
205
206 /*
207  * Perform the freeglut deinitialization...
208  */
209 void fgDeinitialize( void )
210 {
211     SFG_Timer *timer;
212
213     if( !fgState.Initalized )
214     {
215         fgWarning( "fgDeinitialize(): "
216                    "no valid initialization has been performed" );
217         return;
218     }
219
220     /* fgState.Initalized = GL_FALSE; */
221
222     /*
223      * If there was a menu created, destroy the rendering context
224      */
225     if( fgStructure.MenuContext )
226     {
227         free( fgStructure.MenuContext );
228         fgStructure.MenuContext = NULL;
229     }
230
231     fgDestroyStructure( );
232
233     while( timer = ( SFG_Timer * )fgState.Timers.First )
234     {
235         fgListRemove ( &fgState.Timers, &timer->Node );
236         free( timer );
237     }
238
239     fgJoystickClose( );
240
241     fgState.Initalized = GL_FALSE;
242
243     fgState.Position.X = -1;
244     fgState.Position.Y = -1;
245     fgState.Position.Use = GL_FALSE;
246
247     fgState.Size.X = 300;
248     fgState.Size.Y = 300;
249     fgState.Size.Use = GL_TRUE;
250
251     fgState.DisplayMode = GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH;
252
253     fgState.ForceDirectContext  = GL_FALSE;
254     fgState.TryDirectContext    = GL_TRUE;
255     fgState.ForceIconic         = GL_FALSE;
256     fgState.UseCurrentContext   = GL_FALSE;
257     fgState.GLDebugSwitch       = GL_FALSE;
258     fgState.XSyncSwitch         = GL_FALSE;
259     fgState.ActionOnWindowClose = GLUT_ACTION_EXIT;
260     fgState.ExecState           = GLUT_EXEC_STATE_INIT;
261
262     fgState.IgnoreKeyRepeat = GL_TRUE;
263     fgState.Modifiers       = 0xffffffff;
264
265     fgState.GameModeSize.X  = 640;
266     fgState.GameModeSize.Y  = 480;
267     fgState.GameModeDepth   =  16;
268     fgState.GameModeRefresh =  72;
269
270     fgState.Time.Set = GL_FALSE;
271
272     fgState.Timers.First = fgState.Timers.Last = NULL;
273     fgState.IdleCallback = NULL;
274     fgState.MenuStateCallback = ( FGCBMenuState )NULL;
275     fgState.MenuStatusCallback = ( FGCBMenuStatus )NULL;
276
277     fgState.SwapCount   = 0;
278     fgState.SwapTime    = 0;
279     fgState.FPSInterval = 0;
280
281     if( fgState.ProgramName )
282     {
283         free( fgState.ProgramName );
284         fgState.ProgramName = NULL;
285     }
286     
287
288 #if TARGET_HOST_UNIX_X11
289
290     /*
291      * Make sure all X-client data we have created will be destroyed on
292      * display closing
293      */
294     XSetCloseDownMode( fgDisplay.Display, DestroyAll );
295
296     /*
297      * Close the display connection, destroying all windows we have
298      * created so far
299      */
300     XCloseDisplay( fgDisplay.Display );
301
302 #endif
303 }
304
305 /*
306  * Everything inside the following #ifndef is copied from the X sources.
307  */
308
309 #ifndef TARGET_HOST_UNIX_X11
310
311 #define NoValue         0x0000
312 #define XValue          0x0001
313 #define YValue          0x0002
314 #define WidthValue      0x0004
315 #define HeightValue     0x0008
316 #define AllValues       0x000F
317 #define XNegative       0x0010
318 #define YNegative       0x0020
319
320 /*
321  *    XParseGeometry parses strings of the form
322  *   "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
323  *   width, height, xoffset, and yoffset are unsigned integers.
324  *   Example:  "=80x24+300-49"
325  *   The equal sign is optional.
326  *   It returns a bitmask that indicates which of the four values
327  *   were actually found in the string.  For each value found,
328  *   the corresponding argument is updated;  for each value
329  *   not found, the corresponding argument is left unchanged. 
330  */
331
332 static int
333 ReadInteger(char *string, char **NextString)
334 {
335     register int Result = 0;
336     int Sign = 1;
337     
338     if (*string == '+')
339         string++;
340     else if (*string == '-')
341     {
342         string++;
343         Sign = -1;
344     }
345     for (; (*string >= '0') && (*string <= '9'); string++)
346     {
347         Result = (Result * 10) + (*string - '0');
348     }
349     *NextString = string;
350     if (Sign >= 0)
351         return (Result);
352     else
353         return (-Result);
354 }
355
356 static int XParseGeometry (
357     _Xconst char *string,
358     int *x,
359     int *y,
360     unsigned int *width,    /* RETURN */
361     unsigned int *height)    /* RETURN */
362 {
363     int mask = NoValue;
364     register char *strind;
365     unsigned int tempWidth = 0, tempHeight = 0;
366     int tempX = 0, tempY = 0;
367     char *nextCharacter;
368
369     if ( (string == NULL) || (*string == '\0')) return(mask);
370     if (*string == '=')
371         string++;  /* ignore possible '=' at beg of geometry spec */
372
373     strind = (char *)string;
374     if (*strind != '+' && *strind != '-' && *strind != 'x') {
375         tempWidth = ReadInteger(strind, &nextCharacter);
376         if (strind == nextCharacter) 
377             return (0);
378         strind = nextCharacter;
379         mask |= WidthValue;
380     }
381
382     if (*strind == 'x' || *strind == 'X') {
383         strind++;
384         tempHeight = ReadInteger(strind, &nextCharacter);
385         if (strind == nextCharacter)
386             return (0);
387         strind = nextCharacter;
388         mask |= HeightValue;
389     }
390
391     if ((*strind == '+') || (*strind == '-')) {
392         if (*strind == '-') {
393             strind++;
394             tempX = -ReadInteger(strind, &nextCharacter);
395             if (strind == nextCharacter)
396                 return (0);
397             strind = nextCharacter;
398             mask |= XNegative;
399         }
400         else
401         {
402             strind++;
403             tempX = ReadInteger(strind, &nextCharacter);
404             if (strind == nextCharacter)
405                 return(0);
406             strind = nextCharacter;
407         }
408         mask |= XValue;
409         if ((*strind == '+') || (*strind == '-')) {
410             if (*strind == '-') {
411                 strind++;
412                 tempY = -ReadInteger(strind, &nextCharacter);
413                 if (strind == nextCharacter)
414                     return(0);
415                 strind = nextCharacter;
416                 mask |= YNegative;
417             }
418             else
419             {
420                 strind++;
421                 tempY = ReadInteger(strind, &nextCharacter);
422                 if (strind == nextCharacter)
423                     return(0);
424                 strind = nextCharacter;
425             }
426             mask |= YValue;
427         }
428     }
429
430     /* If strind isn't at the end of the string the it's an invalid
431        geometry specification. */
432
433     if (*strind != '\0') return (0);
434
435     if (mask & XValue)
436         *x = tempX;
437     if (mask & YValue)
438         *y = tempY;
439     if (mask & WidthValue)
440         *width = tempWidth;
441     if (mask & HeightValue)
442         *height = tempHeight;
443     return (mask);
444 }
445 #endif
446
447 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
448
449 /*
450  * Perform initialization. This usually happens on the program startup
451  * and restarting after glutMainLoop termination...
452  */
453 void FGAPIENTRY glutInit( int* pargc, char** argv )
454 {
455     char* displayName = NULL;
456     char* geometry = NULL;
457     int i, j, argc = *pargc;
458
459     if( fgState.Initalized )
460         fgError( "illegal glutInit() reinitialization attemp" );
461
462     if (pargc && *pargc && argv && *argv && **argv)
463     {
464         fgState.ProgramName = strdup (*argv);
465
466         if( !fgState.ProgramName )
467             fgError ("Could not allocate space for the program's name.");
468     }
469
470     fgCreateStructure( );
471
472     fgElapsedTime( );
473
474     /* check if GLUT_FPS env var is set */
475     {
476         const char *fps = getenv( "GLUT_FPS" );
477         if( fps )
478         {
479             sscanf( fps, "%d", &fgState.FPSInterval );
480             if( fgState.FPSInterval <= 0 )
481                 fgState.FPSInterval = 5000;  /* 5000 milliseconds */
482         }
483     }
484
485     displayName = getenv( "DISPLAY");
486
487     for( i = 1; i < argc; i++ )
488     {
489         if( strcmp( argv[ i ], "-display" ) == 0 )
490         {
491             if( ++i >= argc )
492                 fgError( "-display parameter must be followed by display name" );
493
494             displayName = argv[ i ];
495
496             argv[ i - 1 ] = NULL;
497             argv[ i     ] = NULL;
498             ( *pargc ) -= 2;
499         }
500         else if( strcmp( argv[ i ], "-geometry" ) == 0 )
501         {
502             if( ++i >= argc )
503                 fgError( "-geometry parameter must be followed by window "
504                          "geometry settings" );
505
506             geometry = argv[ i ];
507
508             argv[ i - 1 ] = NULL;
509             argv[ i     ] = NULL;
510             ( *pargc ) -= 2;
511         }
512         else if( strcmp( argv[ i ], "-direct" ) == 0)
513         {
514             if( ! fgState.TryDirectContext )
515                 fgError( "parameters ambiguity, -direct and -indirect "
516                     "cannot be both specified" );
517
518             fgState.ForceDirectContext = GL_TRUE;
519             argv[ i ] = NULL;
520             ( *pargc )--;
521         }
522         else if( strcmp( argv[ i ], "-indirect" ) == 0 )
523         {
524             if( fgState.ForceDirectContext )
525                 fgError( "parameters ambiguity, -direct and -indirect "
526                     "cannot be both specified" );
527
528             fgState.TryDirectContext = GL_FALSE;
529             argv[ i ] = NULL;
530             (*pargc)--;
531         }
532         else if( strcmp( argv[ i ], "-iconic" ) == 0 )
533         {
534             fgState.ForceIconic = GL_TRUE;
535             argv[ i ] = NULL;
536             ( *pargc )--;
537         }
538         else if( strcmp( argv[ i ], "-gldebug" ) == 0 )
539         {
540             fgState.GLDebugSwitch = GL_TRUE;
541             argv[ i ] = NULL;
542             ( *pargc )--;
543         }
544         else if( strcmp( argv[ i ], "-sync" ) == 0 )
545         {
546             fgState.XSyncSwitch = GL_TRUE;
547             argv[ i ] = NULL;
548             ( *pargc )--;
549         }
550     }
551
552     /*
553      * Compact {argv}.
554      */
555     j = 2;
556     for( i = 1; i < *pargc; i++, j++ )
557     {
558         if( argv[ i ] == NULL )
559         {
560             /* Guaranteed to end because there are "*pargc" arguments left */
561             while ( argv[ j ] == NULL )
562                 j++;
563             argv[ i ] = argv[ j ];
564         }
565     }
566
567     /*
568      * Have the display created now. As I am too lazy to implement
569      * the program arguments parsing, we will have the DISPLAY
570      * environment variable used for opening the X display:
571      *
572      * XXX The above comment is rather unclear.  We have just
573      * XXX completed parsing of the program arguments for GLUT
574      * XXX parameters.  We obviously canNOT parse the application-
575      * XXX specific parameters.  Can someone re-write the above
576      * XXX more clearly?
577      */
578     fgInitialize( displayName );
579
580     /*
581      * Geometry parsing deffered until here because we may need the screen
582      * size.
583      */
584
585     if (geometry )
586     {
587         int mask = XParseGeometry( geometry,
588                                    &fgState.Position.X, &fgState.Position.Y,
589                                    &fgState.Size.X, &fgState.Size.Y );
590
591         if( (mask & (WidthValue|HeightValue)) == (WidthValue|HeightValue) )
592             fgState.Size.Use = GL_TRUE;
593
594         if( mask & XNegative )
595             fgState.Position.X += fgDisplay.ScreenWidth - fgState.Size.X;
596
597         if( mask & YNegative )
598             fgState.Position.Y += fgDisplay.ScreenHeight - fgState.Size.Y;
599
600         if( (mask & (XValue|YValue)) == (XValue|YValue) )
601             fgState.Position.Use = GL_TRUE;
602     }
603 }
604
605 /*
606  * Sets the default initial window position for new windows
607  */
608 void FGAPIENTRY glutInitWindowPosition( int x, int y )
609 {
610     fgState.Position.X = x;
611     fgState.Position.Y = y;
612
613     if( ( x >= 0 ) && ( y >= 0 ) )
614         fgState.Position.Use = GL_TRUE;
615     else
616         fgState.Position.Use = GL_FALSE;
617 }
618
619 /*
620  * Sets the default initial window size for new windows
621  */
622 void FGAPIENTRY glutInitWindowSize( int width, int height )
623 {
624     fgState.Size.X = width;
625     fgState.Size.Y = height;
626
627     if( ( width > 0 ) && ( height > 0 ) )
628         fgState.Size.Use = GL_TRUE;
629     else
630         fgState.Size.Use = GL_FALSE;
631 }
632
633 /*
634  * Sets the default display mode for all new windows
635  */
636 void FGAPIENTRY glutInitDisplayMode( unsigned int displayMode )
637 {
638     /*
639      * We will make use of this value when creating a new OpenGL context...
640      */
641     fgState.DisplayMode = displayMode;
642 }
643
644
645 /* -- INIT DISPLAY STRING PARSING ------------------------------------------ */
646
647 #define NUM_TOKENS             28
648 static char* Tokens[] =
649 {
650     "alpha", "acca", "acc", "blue", "buffer", "conformant", "depth", "double",
651     "green", "index", "num", "red", "rgba", "rgb", "luminance", "stencil",
652     "single", "stereo", "samples", "slow", "win32pdf", "xvisual",
653     "xstaticgray", "xgrayscale", "xstaticcolor", "xpseudocolor",
654     "xtruecolor", "xdirectcolor"
655 };
656
657 static int TokenLengths[] =
658 {
659     5,       4,      3,     4,      6,        10,           5,       6,
660     5,       5,       3,     3,     4,      3,     9,           7,
661     6,        6,        7,         4,      8,          7,
662     11,            10,           12,             12,
663     10,           12
664 };
665
666 void FGAPIENTRY glutInitDisplayString( const char* displayMode )
667 {
668     int glut_state_flag = 0 ;
669     /*
670      * Unpack a lot of options from a character string.  The options are
671      * delimited by blanks or tabs.
672      */
673     char *token ;
674     int len = strlen ( displayMode ) ;
675     char *buffer = (char *)malloc ( (len+1) * sizeof(char) ) ;
676     memcpy ( buffer, displayMode, len ) ;
677     buffer[len] = '\0' ;
678
679     token = strtok ( buffer, " \t" ) ;
680     while ( token )
681     {
682         /*
683          * Process this token
684          */
685         int i ;
686         for ( i = 0; i < NUM_TOKENS; i++ )
687         {
688             if ( strncmp ( token, Tokens[i], TokenLengths[i] ) == 0 ) break ;
689         }
690
691         switch ( i )
692         {
693         case 0 :  /* "alpha":  Alpha color buffer precision in bits */
694             glut_state_flag |= GLUT_ALPHA ;  /* Somebody fix this for me! */
695             break ;
696
697         case 1 :  /* "acca":  Red, green, blue, and alpha accumulation buffer
698                      precision in bits */
699             break ;
700
701         case 2 :  /* "acc":  Red, green, and blue accumulation buffer precision
702                      in bits with zero bits alpha */
703             glut_state_flag |= GLUT_ACCUM ;  /* Somebody fix this for me! */
704             break ;
705
706         case 3 :  /* "blue":  Blue color buffer precision in bits */
707             break ;
708
709         case 4 :  /* "buffer":  Number of bits in the color index color buffer
710                    */
711             break ;
712
713         case 5 :  /* "conformant":  Boolean indicating if the frame buffer
714                      configuration is conformant or not */
715             break ;
716
717         case 6 : /* "depth":  Number of bits of precsion in the depth buffer */
718             glut_state_flag |= GLUT_DEPTH ;  /* Somebody fix this for me! */
719             break ;
720
721         case 7 :  /* "double":  Boolean indicating if the color buffer is
722                      double buffered */
723             glut_state_flag |= GLUT_DOUBLE ;
724             break ;
725
726         case 8 :  /* "green":  Green color buffer precision in bits */
727             break ;
728
729         case 9 :  /* "index":  Boolean if the color model is color index or not
730                    */
731             glut_state_flag |= GLUT_INDEX ;
732             break ;
733
734         case 10 :  /* "num":  A special capability  name indicating where the
735                       value represents the Nth frame buffer configuration
736                       matching the description string */
737             break ;
738
739         case 11 :  /* "red":  Red color buffer precision in bits */
740             break ;
741
742         case 12 :  /* "rgba":  Number of bits of red, green, blue, and alpha in
743                       the RGBA color buffer */
744             glut_state_flag |= GLUT_RGBA ;  /* Somebody fix this for me! */
745             break ;
746
747         case 13 :  /* "rgb":  Number of bits of red, green, and blue in the
748                       RGBA color buffer with zero bits alpha */
749             glut_state_flag |= GLUT_RGB ;  /* Somebody fix this for me! */
750             break ;
751
752         case 14 :  /* "luminance":  Number of bits of red in the RGBA and zero
753                       bits of green, blue (alpha not specified) of color buffer
754                       precision */
755             glut_state_flag |= GLUT_LUMINANCE ; /* Somebody fix this for me! */
756             break ;
757
758         case 15 :  /* "stencil":  Number of bits in the stencil buffer */
759             glut_state_flag |= GLUT_STENCIL;  /* Somebody fix this for me! */
760             break ;
761
762         case 16 :  /* "single":  Boolean indicate the color buffer is single
763                       buffered */
764             glut_state_flag |= GLUT_SINGLE ;
765             break ;
766
767         case 17 :  /* "stereo":  Boolean indicating the color buffer supports
768                       OpenGL-style stereo */
769             glut_state_flag |= GLUT_STEREO ;
770             break ;
771
772         case 18 :  /* "samples":  Indicates the number of multisamples to use
773                       based on GLX's SGIS_multisample extension (for
774                       antialiasing) */
775             glut_state_flag |= GLUT_MULTISAMPLE ; /*Somebody fix this for me!*/
776             break ;
777
778         case 19 :  /* "slow":  Boolean indicating if the frame buffer
779                       configuration is slow or not */
780             break ;
781
782         case 20 :  /* "win32pdf":  matches the Win32 Pixel Format Descriptor by
783                       number */
784 #if TARGET_HOST_WIN32
785 #endif
786             break ;
787
788         case 21 :  /* "xvisual":  matches the X visual ID by number */
789 #if TARGET_HOST_UNIX_X11
790 #endif
791             break ;
792
793         case 22 :  /* "xstaticgray":  boolean indicating if the frame buffer
794                       configuration's X visual is of type StaticGray */
795 #if TARGET_HOST_UNIX_X11
796 #endif
797             break ;
798
799         case 23 :  /* "xgrayscale":  boolean indicating if the frame buffer
800                       configuration's X visual is of type GrayScale */
801 #if TARGET_HOST_UNIX_X11
802 #endif
803             break ;
804
805         case 24 :  /* "xstaticcolor":  boolean indicating if the frame buffer
806                       configuration's X visual is of type StaticColor */
807 #if TARGET_HOST_UNIX_X11
808 #endif
809             break ;
810
811         case 25 :  /* "xpseudocolor":  boolean indicating if the frame buffer
812                       configuration's X visual is of type PseudoColor */
813 #if TARGET_HOST_UNIX_X11
814 #endif
815             break ;
816
817         case 26 :  /* "xtruecolor":  boolean indicating if the frame buffer
818                       configuration's X visual is of type TrueColor */
819 #if TARGET_HOST_UNIX_X11
820 #endif
821             break ;
822
823         case 27 :  /* "xdirectcolor":  boolean indicating if the frame buffer
824                       configuration's X visual is of type DirectColor */
825 #if TARGET_HOST_UNIX_X11
826 #endif
827             break ;
828
829         case 28 :  /* Unrecognized */
830             printf ( "WARNING - Display string token not recognized:  %s\n",
831                      token ) ;
832             break ;
833         }
834
835         token = strtok ( NULL, " \t" ) ;
836     }
837
838     free ( buffer ) ;
839
840     /*
841      * We will make use of this value when creating a new OpenGL context...
842      */
843     fgState.DisplayMode = glut_state_flag;
844 }
845
846 /*** END OF FILE ***/