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