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