Major menu changes (they appear in their own window, have own rendering context)...
authorJ.C. Jones <jc@insufficient.coffee>
Sat, 2 Aug 2003 13:31:19 +0000 (13:31 +0000)
committerJ.C. Jones <jc@insufficient.coffee>
Sat, 2 Aug 2003 13:31:19 +0000 (13:31 +0000)
git-svn-id: svn+ssh://svn.code.sf.net/p/freeglut/code/trunk/freeglut/freeglut@152 7f0cb862-5218-0410-a997-914c9d46530a

src/freeglut_callbacks.c
src/freeglut_display.c
src/freeglut_glutfont_definitions.c
src/freeglut_init.c
src/freeglut_internal.h
src/freeglut_main.c
src/freeglut_menu.c
src/freeglut_state.c
src/freeglut_structure.c
src/freeglut_window.c

index b741a0c..ef404f7 100644 (file)
 void FGAPIENTRY glutDisplayFunc( void (* callback)( void ) )
 {
     SET_CALLBACK( Display );
+
+    /*
+     * Force a redisplay with the new callback
+     */
+    fgStructure.Window->State.Redisplay = TRUE;
+
 }
 
 /*
index de19841..ca3b151 100644 (file)
@@ -64,9 +64,8 @@ void FGAPIENTRY glutSwapBuffers( void )
     freeglut_assert_ready; freeglut_assert_window;
 
     /*
-     * Have the mouse cursor and/or the menus drawn for the current window
+     * Have the mouse cursor drawn for the current window
      */
-    fgDisplayMenu();
     fgDisplayCursor();
 
     /*
index 8154774..7cb34f8 100644 (file)
@@ -61,16 +61,16 @@ struct freeglutBitmapFont
 } ; 
 
 
-struct freeglutStrokeFont glutStrokeRoman ;
-struct freeglutStrokeFont glutStrokeMonoRoman ;
+struct freeglutStrokeFont *glutStrokeRoman ;
+struct freeglutStrokeFont *glutStrokeMonoRoman ;
 
-struct freeglutBitmapFont glutBitmap9By15 ;
-struct freeglutBitmapFont glutBitmap8By13 ;
-struct freeglutBitmapFont glutBitmapTimesRoman10 ;
-struct freeglutBitmapFont glutBitmapTimesRoman24 ;
-struct freeglutBitmapFont glutBitmapHelvetica10 ;
-struct freeglutBitmapFont glutBitmapHelvetica12 ;
-struct freeglutBitmapFont glutBitmapHelvetica18 ;
+struct freeglutBitmapFont *glutBitmap9By15 ;
+struct freeglutBitmapFont *glutBitmap8By13 ;
+struct freeglutBitmapFont *glutBitmapTimesRoman10 ;
+struct freeglutBitmapFont *glutBitmapTimesRoman24 ;
+struct freeglutBitmapFont *glutBitmapHelvetica10 ;
+struct freeglutBitmapFont *glutBitmapHelvetica12 ;
+struct freeglutBitmapFont *glutBitmapHelvetica18 ;
 
 #endif
 
index eb0935b..3399289 100644 (file)
@@ -75,6 +75,7 @@ SFG_State fgState = { { -1, -1, FALSE },  /* Position */
 #endif
                       { NULL, NULL }, /* Timers */
                       NULL, /* IdleCallback */
+                      FALSE, /* BuildingAMenu */
                       NULL, /* MenuStateCallback */
                       NULL, /* MenuStatusCallback */
                       { 640, 480, TRUE }, /* GameModeSize */
@@ -269,6 +270,15 @@ void fgDeinitialize( void )
     }
 
     /*
+     * If there was a menu created, destroy the rendering context
+     */
+    if ( fgStructure.MenuContext )
+    {
+      free ( fgStructure.MenuContext ) ;
+      fgStructure.MenuContext = NULL ;
+    }
+
+    /*
      * Perform the freeglut structure deinitialization
      */
     fgDestroyStructure();
index 70c845f..26ee0c2 100644 (file)
     #include <X11/Xatom.h>
     #include <X11/keysym.h>
 
-    #if HAVE_X11_EXTENSIONS_XF86VMODE_H
-        #include <X11/extensions/xf86vmode.h>
+    #ifndef __sgi
+    #ifndef SOLARIS
+    #include <X11/extensions/xf86vmode.h>
+    #endif
     #endif
 #endif
 
@@ -235,6 +237,7 @@ struct tagSFG_State
 
     FGCBidle         IdleCallback;         /* The global idle callback          */
 
+    GLboolean        BuildingAMenu;        /* True if we are presently making a menu */
     FGCBmenuState    MenuStateCallback;    /* Menu callbacks are global         */
     FGCBmenuStatus   MenuStatusCallback;
 
@@ -384,8 +387,25 @@ struct tagSFG_WindowCallbacks
 };
 
 /*
+ * This structure holds the OpenGL rendering context for all the menu windows
+ */
+typedef struct tagSFG_MenuContext SFG_MenuContext;
+struct tagSFG_MenuContext
+{
+#if TARGET_HOST_UNIX_X11
+    GLXContext          Context;                /* The menu OpenGL context   */
+    XVisualInfo*        VisualInfo;             /* The window's visual information */
+#elif TARGET_HOST_WIN32
+    HGLRC               Context;                /* The menu window's WGL context    */
+#endif
+
+};
+
+/*
  * This structure describes a menu
  */
+typedef struct tagSFG_Window SFG_Window;
+typedef struct tagSFG_MenuEntry SFG_MenuEntry;
 typedef struct tagSFG_Menu SFG_Menu;
 struct tagSFG_Menu
 {
@@ -399,12 +419,15 @@ struct tagSFG_Menu
     int                 Width;                  /* Menu box width in pixels  */
     int                 Height;                 /* Menu box height in pixels */
     int                 X, Y;                   /* Menu box raster position  */
+
+    SFG_MenuEntry      *ActiveEntry ;           /* Currently active entry in the menu */
+    SFG_Window         *Window ;                /* OpenGL window for menu    */
+    SFG_Window         *ParentWindow ;          /* OpenGL window in which the menu is defined */
 };
 
 /*
  * This is a menu entry
  */
-typedef struct tagSFG_MenuEntry SFG_MenuEntry;
 struct tagSFG_MenuEntry
 {
     SFG_Node            Node;
@@ -419,7 +442,6 @@ struct tagSFG_MenuEntry
 /*
  * A window, making part of freeglut windows hierarchy. Should be kept portable.
  */
-typedef struct tagSFG_Window SFG_Window;
 struct tagSFG_Window
 {
     SFG_Node            Node;
@@ -435,6 +457,8 @@ struct tagSFG_Window
 
     SFG_Window*         Parent;                 /* The parent to this window */
     SFG_List            Children;               /* The subwindows d.l. list  */
+
+    GLboolean           IsMenu;                 /* Set to 1 if we are a menu */
 };
 
 /*
@@ -460,6 +484,8 @@ struct tagSFG_Structure
     SFG_Window*         Window;                 /* The currently active win. */
     SFG_Menu*           Menu;                   /* Same, but menu...         */
 
+    SFG_MenuContext*    MenuContext;            /* OpenGL rendering context for menus */
+
     SFG_Window*         GameMode;               /* The game mode window      */
 
     int                 WindowID;               /* The new current window ID */
@@ -673,6 +699,7 @@ void fgActivateMenu( SFG_Window* window, int button );
 void fgExecuteMenuCallback( SFG_Menu* menu ) ;
 GLboolean fgCheckActiveMenu ( SFG_Window *window, SFG_Menu *menu ) ;
 void fgDeactivateMenu( SFG_Window *window );
+void fgDeactivateSubMenu( SFG_MenuEntry *menuEntry );
 
 /*
  * This function gets called just before the buffers swap, so that
index f9c78ef..858116a 100644 (file)
@@ -652,9 +652,17 @@ void FGAPIENTRY glutMainLoopEvent( void )
         GETWINDOW( xmotion ); GETMOUSE( xmotion );
 
         /*
-         * Set the current window
+         * Fallback if there's an active menu hooked to this window
          */
-        fgStructure.Window = window ;
+        if( window->ActiveMenu != NULL )
+        {
+            /*
+             * Let's make the window redraw as a result of the mouse motion.
+             */
+            window->State.Redisplay = TRUE ;
+
+            break;
+        }
 
         /*
          * What kind of a movement was it?
@@ -670,6 +678,11 @@ void FGAPIENTRY glutMainLoopEvent( void )
           if( window->Callbacks.Motion != NULL )
           {
             /*
+             * Set the current window
+             */
+            fgStructure.Window = window ;
+
+            /*
              * Yup. Have it executed immediately
              */
             window->Callbacks.Motion( event.xmotion.x, event.xmotion.y );
@@ -683,6 +696,11 @@ void FGAPIENTRY glutMainLoopEvent( void )
           if( window->Callbacks.Passive != NULL )
           {
             /*
+             * Set the current window
+             */
+            fgStructure.Window = window ;
+
+            /*
              * That's right, and there is a passive callback, too.
              */
             window->Callbacks.Passive( event.xmotion.x, event.xmotion.y );
@@ -749,7 +767,7 @@ void FGAPIENTRY glutMainLoopEvent( void )
 
             /* Execute the menu callback */
             fgExecuteMenuCallback ( window->ActiveMenu ) ;
-            fgDeactivateMenu ( window ) ;
+            fgDeactivateMenu ( window->ActiveMenu->ParentWindow ) ;
 
             /* Restore the current window and menu */
             fgSetWindow ( save_window ) ;
@@ -757,7 +775,7 @@ void FGAPIENTRY glutMainLoopEvent( void )
           }
           else  /* Outside the menu, deactivate the menu if it's a downclick */
           {
-            if ( pressed == TRUE ) fgDeactivateMenu ( window ) ;
+            if ( pressed == TRUE ) fgDeactivateMenu ( window->ActiveMenu->ParentWindow ) ;
           }
 
           /*
@@ -779,6 +797,11 @@ void FGAPIENTRY glutMainLoopEvent( void )
           window->State.Redisplay = TRUE ;
 
           /*
+           * Set the current window
+           */
+          fgSetWindow( window );
+
+          /*
            * Activate the appropriate menu structure...
            */
           fgActivateMenu( window, button );
@@ -789,15 +812,10 @@ void FGAPIENTRY glutMainLoopEvent( void )
         /*
          * Check if there is a mouse callback hooked to the window
          */
-        if( window->Callbacks.Mouse == NULL )
+        if( fgStructure.Window->Callbacks.Mouse == NULL )
           break;
 
         /*
-         * Set the current window
-         */
-        fgSetWindow( window );
-
-        /*
          * Remember the current modifiers state
          */
         modifiers = 0;
@@ -807,12 +825,12 @@ void FGAPIENTRY glutMainLoopEvent( void )
           modifiers |= GLUT_ACTIVE_CTRL;
         if (event.xbutton.state & Mod1Mask)
           modifiers |= GLUT_ACTIVE_ALT;
-        window->State.Modifiers = modifiers;
+        fgStructure.Window->State.Modifiers = modifiers;
 
         /*
          * Finally execute the mouse callback
          */
-        window->Callbacks.Mouse(
+        fgStructure.Window->Callbacks.Mouse(
             button,
             event.type == ButtonPress ? GLUT_DOWN : GLUT_UP,
             event.xbutton.x,
@@ -822,7 +840,7 @@ void FGAPIENTRY glutMainLoopEvent( void )
         /*
          * Trash the modifiers state
          */
-        window->State.Modifiers = 0xffffffff;
+        fgStructure.Window->State.Modifiers = 0xffffffff;
       }
       break;
 
@@ -1170,17 +1188,48 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
         window->Window.Device = GetDC( hWnd );
 
         /*
-         * Setup the pixel format of our window
-         */
-        fgSetupPixelFormat( window, FALSE, PFD_MAIN_PLANE );
-
-        /*
          * Create or get the OpenGL rendering context now
          */
-        if ( fgState.UseCurrentContext == TRUE )
-          window->Window.Context = wglGetCurrentContext();
-        else
+        if ( fgState.BuildingAMenu )
+        {
+          /*
+           * Setup the pixel format of our window
+           */
+          unsigned int current_DisplayMode = fgState.DisplayMode ;
+          fgState.DisplayMode = GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH ;
+          fgSetupPixelFormat( window, FALSE, PFD_MAIN_PLANE );
+          fgState.DisplayMode = current_DisplayMode ;
+
+          /*
+           * If there isn't already an OpenGL rendering context for menu windows, make one
+           */
+          if ( !fgStructure.MenuContext )
+          {
+            fgStructure.MenuContext = (SFG_MenuContext *)malloc ( sizeof(SFG_MenuContext) ) ;
+            fgStructure.MenuContext->Context = wglCreateContext( window->Window.Device );
+          }
+          else
+            wglMakeCurrent ( window->Window.Device, fgStructure.MenuContext->Context ) ;
+
+/*          window->Window.Context = wglGetCurrentContext () ;   */
           window->Window.Context = wglCreateContext( window->Window.Device );
+        }
+        else
+        {
+          /*
+           * Setup the pixel format of our window
+           */
+          fgSetupPixelFormat( window, FALSE, PFD_MAIN_PLANE );
+
+          if ( fgState.UseCurrentContext == TRUE )
+          {
+            window->Window.Context = wglGetCurrentContext();
+            if ( ! window->Window.Context )
+              window->Window.Context = wglCreateContext( window->Window.Device );
+          }
+          else
+            window->Window.Context = wglCreateContext( window->Window.Device );
+        }
 
         /*
          * Still, we'll be needing to explicitly resize the window
@@ -1465,7 +1514,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
 
             /* Execute the menu callback */
             fgExecuteMenuCallback ( window->ActiveMenu ) ;
-            fgDeactivateMenu ( window ) ;
+            fgDeactivateMenu ( window->ActiveMenu->ParentWindow ) ;
 
             /* Restore the current window and menu */
             fgSetWindow ( save_window ) ;
@@ -1473,13 +1522,13 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
           }
           else  /* Outside the menu, deactivate the menu if it's a downclick */
           {
-            if ( pressed == TRUE ) fgDeactivateMenu ( window ) ;
+            if ( pressed == TRUE ) fgDeactivateMenu ( window->ActiveMenu->ParentWindow ) ;
           }
 
           /*
            * Let's make the window redraw as a result of the mouse click and menu activity.
            */
-          window->State.Redisplay = TRUE ;
+          if ( ! window->IsMenu ) window->State.Redisplay = TRUE ;
 
           break ;
         }
@@ -1495,6 +1544,11 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
             window->State.Redisplay = TRUE ;
 
             /*
+             * Set the current window
+             */
+            fgSetWindow( window );
+
+            /*
              * Activate the appropriate menu structure...
              */
             fgActivateMenu( window, button );
@@ -1505,18 +1559,13 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
         /*
          * Check if there is a mouse callback hooked to the window
          */
-        if( window->Callbacks.Mouse == NULL )
+        if( fgStructure.Window->Callbacks.Mouse == NULL )
             break;
 
         /*
-         * Set the current window
-         */
-        fgSetWindow( window );
-
-        /*
          * Remember the current modifiers state.
          */
-        window->State.Modifiers = 
+        fgStructure.Window->State.Modifiers = 
             ( ( (GetKeyState( VK_LSHIFT   ) < 0 ) || ( GetKeyState( VK_RSHIFT   ) < 0 )) ? GLUT_ACTIVE_SHIFT : 0 ) |
             ( ( (GetKeyState( VK_LCONTROL ) < 0 ) || ( GetKeyState( VK_RCONTROL ) < 0 )) ? GLUT_ACTIVE_CTRL  : 0 ) |
             ( ( (GetKeyState( VK_LMENU    ) < 0 ) || ( GetKeyState( VK_RMENU    ) < 0 )) ? GLUT_ACTIVE_ALT   : 0 );
@@ -1524,7 +1573,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
         /*
          * Finally execute the mouse callback
          */
-        window->Callbacks.Mouse(
+        fgStructure.Window->Callbacks.Mouse(
             button,
             pressed == TRUE ? GLUT_DOWN : GLUT_UP,
             window->State.MouseX,
@@ -1534,7 +1583,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
         /*
          * Trash the modifiers state
          */
-        window->State.Modifiers = 0xffffffff;
+        fgStructure.Window->State.Modifiers = 0xffffffff;
     }
     break;
 
index 921deec..00e415d 100644 (file)
@@ -96,7 +96,14 @@ static GLboolean fghCheckMenuStatus( SFG_Window* window, SFG_Menu* menu )
        * that it caught the mouse cursor and we do not need to regenerate
        * the activity list, and so our parents do...
        */
-      if( fghCheckMenuStatus( window, menuEntry->SubMenu ) == TRUE )
+      GLboolean return_status = fghCheckMenuStatus( window, menuEntry->SubMenu ) ;
+
+      /*
+       * Reactivate the submenu as the checkMenuStatus may have turned it off if the mouse
+       * is in its parent menu entry.
+       */
+      menuEntry->SubMenu->IsActive = TRUE ;
+      if ( return_status == TRUE )
         return( TRUE );
     }
   }
@@ -104,8 +111,8 @@ static GLboolean fghCheckMenuStatus( SFG_Window* window, SFG_Menu* menu )
   /*
    * That much about our sub menus, let's get to checking the current menu:
    */
-  x = window->State.MouseX - menu->X;
-  y = window->State.MouseY - menu->Y;
+  x = window->State.MouseX;
+  y = window->State.MouseY;
 
   /*
    * Mark all menu entries inactive...
@@ -116,12 +123,13 @@ static GLboolean fghCheckMenuStatus( SFG_Window* window, SFG_Menu* menu )
     menuEntry->IsActive = FALSE;
   }
 
+
   menu->IsActive = FALSE;
 
   /*
    * Check if the mouse cursor is contained within the current menu box
    */
-  if( x >= 0 && x < menu->Width && y >= 0 && y < menu->Height )
+  if ( ( x >= 0 ) && ( x < menu->Width ) && ( y >= 0 ) && ( y < menu->Height ) && ( window == menu->Window ) )
   {
     /*
      * Calculation of the highlighted menu item is easy enough now:
@@ -141,8 +149,21 @@ static GLboolean fghCheckMenuStatus( SFG_Window* window, SFG_Menu* menu )
     menuEntry->Ordinal = menuID;
 
     /*
+     * If this is not the same as the last active menu entry, deactivate the previous entry.
+     * Specifically, if the previous active entry was a submenu then deactivate it.
+     */
+    if ( menu->ActiveEntry && ( menuEntry != menu->ActiveEntry ) )
+    {
+      if ( menu->ActiveEntry->SubMenu != NULL )
+        fgDeactivateSubMenu ( menu->ActiveEntry ) ;
+    }
+
+    menu->ActiveEntry = menuEntry ;
+
+    /*
      * Don't forget about marking the current menu as active, too:
      */
+
     menu->IsActive = TRUE;
 
     /*
@@ -152,21 +173,31 @@ static GLboolean fghCheckMenuStatus( SFG_Window* window, SFG_Menu* menu )
      */
     if( menuEntry->SubMenu != NULL )
     {
-      /*
-       * Set up the initial menu position now...
-       */
+      if ( ! menuEntry->SubMenu->IsActive )
+      {
+        SFG_Window *current_window = fgStructure.Window ;
 
-      menuEntry->SubMenu->X = menu->X + menu->Width ;
-      menuEntry->SubMenu->Y = menu->Y + menuEntry->Ordinal * FREEGLUT_MENU_HEIGHT ;
+        /*
+         * Set up the initial menu position now...
+         */
 
-      /*
-       * Make sure the submenu stays within the window
-       */
-      if ( menuEntry->SubMenu->X + menuEntry->SubMenu->Width > glutGet ( GLUT_WINDOW_WIDTH ) )
-      {
-        menuEntry->SubMenu->X = menu->X - menuEntry->SubMenu->Width ;
-        if ( menuEntry->SubMenu->X < 0 )
-          menuEntry->SubMenu->X = glutGet ( GLUT_WINDOW_WIDTH ) - menuEntry->SubMenu->Width ;
+        /*
+         * Mark the menu as active, so that it gets displayed:
+         */
+        menuEntry->SubMenu->IsActive = TRUE ;
+
+        /*
+         * Set up the initial submenu position now:
+         */
+        menuEntry->SubMenu->X = menu->X + menu->Width ;
+        menuEntry->SubMenu->Y = menu->Y + menuEntry->Ordinal * FREEGLUT_MENU_HEIGHT ;
+
+        fgSetWindow ( menuEntry->SubMenu->Window ) ;
+        glutShowWindow () ;
+        glutPositionWindow ( menuEntry->SubMenu->X, menuEntry->SubMenu->Y ) ;
+        glutReshapeWindow ( menuEntry->SubMenu->Width, menuEntry->SubMenu->Height ) ;
+        menuEntry->SubMenu->Window->ActiveMenu = menuEntry->SubMenu ;
+        fgSetWindow ( current_window ) ;
       }
 
       /*
@@ -204,20 +235,20 @@ static void fghDisplayMenuBox( SFG_Menu* menu )
    * Have the menu box drawn first. The +- values are
    * here just to make it more nice-looking...
    */
-  glColor4f( 0.0f, 0.0f, 0.0f, 1.0f );
+  glColor4f( 0.1289f, 0.2257f, 0.28516f, 1.0f ); /* a non-black dark version of the below. */
   glBegin( GL_QUADS );
-    glVertex2i( menu->X              , menu->Y - 1                );
-    glVertex2i( menu->X + menu->Width, menu->Y - 1                );
-    glVertex2i( menu->X + menu->Width, menu->Y + 4 + menu->Height );
-    glVertex2i( menu->X              , menu->Y + 4 + menu->Height );
+    glVertex2i( 0          , 0            );
+    glVertex2i( menu->Width, 0            );
+    glVertex2i( menu->Width, menu->Height );
+    glVertex2i( 0          , menu->Height );
   glEnd();
 
   glColor4f( 0.3f, 0.4f, 0.5f, 1.0f );
   glBegin( GL_QUADS );
-    glVertex2i( menu->X - 2              , menu->Y + 1                );
-    glVertex2i( menu->X - 2 + menu->Width, menu->Y + 1                );
-    glVertex2i( menu->X - 2 + menu->Width, menu->Y + 2 + menu->Height );
-    glVertex2i( menu->X - 2              , menu->Y + 2 + menu->Height );
+    glVertex2i(             1, 1             );
+    glVertex2i( menu->Width-1, 1             );
+    glVertex2i( menu->Width-1, menu->Height-1);
+    glVertex2i(             1, menu->Height-1);
   glEnd();
 
   /*
@@ -243,10 +274,10 @@ static void fghDisplayMenuBox( SFG_Menu* menu )
        */
       glColor4f( 0.2f, 0.3f, 0.4f, 1.0f );
       glBegin( GL_QUADS );
-        glVertex2i( menu->X - 2              , menu->Y + (menuID + 0)*FREEGLUT_MENU_HEIGHT + 1 );
-        glVertex2i( menu->X - 2 + menu->Width, menu->Y + (menuID + 0)*FREEGLUT_MENU_HEIGHT + 1 );
-        glVertex2i( menu->X - 2 + menu->Width, menu->Y + (menuID + 1)*FREEGLUT_MENU_HEIGHT + 2 );
-        glVertex2i( menu->X - 2              , menu->Y + (menuID + 1)*FREEGLUT_MENU_HEIGHT + 2 );
+        glVertex2i( 2            , (menuID + 0)*FREEGLUT_MENU_HEIGHT + 1 );
+        glVertex2i( menu->Width-2, (menuID + 0)*FREEGLUT_MENU_HEIGHT + 1 );
+        glVertex2i( menu->Width-2, (menuID + 1)*FREEGLUT_MENU_HEIGHT + 2 );
+        glVertex2i( 2            , (menuID + 1)*FREEGLUT_MENU_HEIGHT + 2 );
       glEnd();
     }
   }
@@ -263,8 +294,8 @@ static void fghDisplayMenuBox( SFG_Menu* menu )
      * Move the raster into position...
      */
     glRasterPos2i(
-        menu->X + FREEGLUT_MENU_BORDER,
-        menu->Y + (i + 1)*FREEGLUT_MENU_HEIGHT
+        FREEGLUT_MENU_BORDER,
+        (i + 1)*FREEGLUT_MENU_HEIGHT-(int)(FREEGLUT_MENU_HEIGHT*0.3) /* Try to center the text - JCJ 31 July 2003*/
     );
 
     /*
@@ -292,8 +323,8 @@ static void fghDisplayMenuBox( SFG_Menu* menu )
       glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0        );
       glPixelStorei( GL_UNPACK_ALIGNMENT,   1        );
 
-      glRasterPos2i ( menu->X + menu->Width - 2 - width,
-                      menu->Y + (i + 1)*FREEGLUT_MENU_HEIGHT ) ;
+      glRasterPos2i ( menu->Width - 2 - width,
+                      (i + 1)*FREEGLUT_MENU_HEIGHT ) ;
       glBitmap ( width, FREEGLUT_MENU_HEIGHT, 0, 0, 0.0, 0.0, arrow_char ) ;
       glPopClientAttrib();
     }
@@ -313,12 +344,31 @@ static void fghDisplayMenuBox( SFG_Menu* menu )
       /*
        * Yeah, indeed. Have it redrawn now:
        */
+      fgSetWindow ( menuEntry->SubMenu->Window ) ;
       fghDisplayMenuBox( menuEntry->SubMenu );
+      fgSetWindow ( menu->Window ) ;
     }
   }
 }
 
 /*
+ * Private static function to set the parent window of a submenu and all of its submenus
+ */
+static void fghSetSubmenuParentWindow ( SFG_Window *window, SFG_Menu *menu )
+{
+  SFG_MenuEntry *menuEntry ;
+
+  menu->ParentWindow = window ;
+
+  for ( menuEntry = menu->Entries.First; menuEntry; menuEntry = menuEntry->Node.Next )
+  {
+    if ( menuEntry->SubMenu != NULL )
+      fghSetSubmenuParentWindow ( window, menuEntry->SubMenu ) ;
+  }
+}
+
+
+/*
  * Displays the currently active menu for the current window
  */
 void fgDisplayMenu( void )
@@ -337,9 +387,12 @@ void fgDisplayMenu( void )
     menu = window->ActiveMenu;
 
     /*
-     * Did we find an active window?
+     * Did we find an active menu?
      */
     freeglut_return_if_fail( menu != NULL );
+
+    fgSetWindow ( menu->Window ) ;
+
     /*
      * Prepare the OpenGL state to do the rendering first:
      */
@@ -388,6 +441,13 @@ void fgDisplayMenu( void )
     glPopMatrix();
     glMatrixMode( GL_MODELVIEW );
     glPopMatrix();
+
+    glutSwapBuffers () ;
+
+    /*
+     * Restore the current window
+     */
+    fgSetWindow ( window ) ;
 }
 
 /*
@@ -395,8 +455,6 @@ void fgDisplayMenu( void )
  */
 void fgActivateMenu( SFG_Window* window, int button )
 {
-  int x, y;
-
   /*
    * We'll be referencing this menu a lot, so remember its address:
    */
@@ -409,23 +467,22 @@ void fgActivateMenu( SFG_Window* window, int button )
   menu->IsActive = TRUE ;
 
   /*
-   * Grab the mouse cursor position respective to the current window
-   */
-  x = window->State.MouseX;
-  y = window->State.MouseY;
-
-  /*
    * Set up the initial menu position now:
    */
-  menu->X = x ;
-  menu->Y = y ;
 
-  fgSetWindow ( window ) ;
+  menu->X = window->State.MouseX + glutGet ( GLUT_WINDOW_X ) ;
+  menu->Y = window->State.MouseY + glutGet ( GLUT_WINDOW_Y ) ;
+
+  fgSetWindow ( menu->Window ) ;
+  glutShowWindow () ;
+  glutPositionWindow ( menu->X, menu->Y ) ;
+  glutReshapeWindow ( menu->Width, menu->Height ) ;
+  menu->Window->ActiveMenu = menu ;
 
-  if( x > ( glutGet( GLUT_WINDOW_WIDTH ) - menu->Width ) )
+/*  if( x > ( glutGet( GLUT_WINDOW_WIDTH ) - menu->Width ) )
     menu->X = glutGet( GLUT_WINDOW_WIDTH ) - menu->Width;
   if( y > ( glutGet( GLUT_WINDOW_HEIGHT ) - menu->Height) )
-    menu->Y = glutGet( GLUT_WINDOW_HEIGHT ) - menu->Height;
+    menu->Y = glutGet( GLUT_WINDOW_HEIGHT ) - menu->Height; */
 }
 
 /*
@@ -493,10 +550,13 @@ void fgExecuteMenuCallback( SFG_Menu* menu )
  */
 void fgDeactivateMenu( SFG_Window *window )
 {
+  SFG_Window *current_window = fgStructure.Window ;
+
     /*
      * Check if there is an active menu attached to this window...
      */
     SFG_Menu* menu = window->ActiveMenu;
+    SFG_MenuEntry *menuEntry ;
 
     /*
      * Did we find an active window?
@@ -504,10 +564,67 @@ void fgDeactivateMenu( SFG_Window *window )
     freeglut_return_if_fail( menu != NULL );
 
     /*
+     * Hide the present menu's window
+     */
+    fgSetWindow ( menu->Window ) ;
+    glutHideWindow () ;
+
+    /*
      * Forget about having that menu active anymore, now:
      */
-    window->ActiveMenu = NULL;
+    menu->Window->ActiveMenu = NULL ;
+    menu->ParentWindow->ActiveMenu = NULL ;
     menu->IsActive = FALSE ;
+
+    /*
+     * Hide all submenu windows, and the root menu's window.
+     */
+    for ( menuEntry = menu->Entries.First; menuEntry;
+          menuEntry = menuEntry->Node.Next )
+    {
+      /*
+       * Is that an active submenu by any case?
+       */
+      if ( ( menuEntry->SubMenu != NULL ) && menuEntry->SubMenu->IsActive )
+        fgDeactivateSubMenu ( menuEntry ) ;
+    }
+
+    fgStructure.Window = current_window ;
+}
+
+/*
+ * Deactivates a menu pointed by the function argument.
+ */
+void fgDeactivateSubMenu( SFG_MenuEntry *menuEntry )
+{
+  SFG_Window *current_window = fgStructure.Window ;
+  SFG_MenuEntry *subMenuIter ;
+    /*
+     * Hide the present menu's window
+     */
+    fgSetWindow ( menuEntry->SubMenu->Window ) ;
+    glutHideWindow () ;
+
+    /*
+     * Forget about having that menu active anymore, now:
+     */
+    menuEntry->SubMenu->Window->ActiveMenu = NULL ;
+    menuEntry->SubMenu->IsActive = FALSE ;
+
+    /*
+     * Hide all submenu windows, and the root menu's window.
+     */
+    for ( subMenuIter = menuEntry->SubMenu->Entries.First; subMenuIter;
+          subMenuIter = subMenuIter->Node.Next )
+    {
+      /*
+       * Is that an active submenu by any case?
+       */
+      if ( ( subMenuIter->SubMenu != NULL ) && subMenuIter->SubMenu->IsActive )
+        fgDeactivateSubMenu ( subMenuIter ) ;
+    }
+
+    fgStructure.Window = current_window ;
 }
 
 /*
@@ -535,6 +652,13 @@ void fghCalculateMenuBoxSize( void )
     menuEntry->Width = glutBitmapLength( FREEGLUT_MENU_FONT, menuEntry->Text );
 
     /*
+     * If the entry is a submenu, then it needs to be wider to accomodate the arrow. JCJ 31 July 2003
+     */
+
+    if (menuEntry->SubMenu != NULL)
+       menuEntry->Width += glutBitmapLength( FREEGLUT_MENU_FONT, " " );
+
+    /*
      * Check if it's the biggest we've found
      */
     if( menuEntry->Width > width )
@@ -670,6 +794,11 @@ void FGAPIENTRY glutAddSubMenu( const char* label, int subMenuID )
   menuEntry->ID      = -1;
 
   /*
+   * Make the submenu's parent window be the menu's parent window
+   */
+  fghSetSubmenuParentWindow ( fgStructure.Menu->ParentWindow, subMenu ) ;
+
+  /*
    * Have the new menu entry attached to the current menu
    */
   fgListAppend( &fgStructure.Menu->Entries, &menuEntry->Node );
@@ -819,6 +948,11 @@ void FGAPIENTRY glutAttachMenu( int button )
      * It is safe now to attach the menu
      */
     fgStructure.Window->Menu[ button ] = fgStructure.Menu;
+
+    /*
+     * Make the parent window of the menu (and all submenus) the current window
+     */
+    fghSetSubmenuParentWindow ( fgStructure.Window, fgStructure.Menu ) ;
 }
 
 /*
index c225cae..3dbc4bb 100644 (file)
@@ -367,7 +367,8 @@ int FGAPIENTRY glutGet( GLenum eWhat )
         /*
          * ...then we've got to correct the results we've just received...
          */
-        if ( ( fgStructure.GameMode != fgStructure.Window ) && ( fgStructure.Window->Parent == NULL ) )
+        if ( ( fgStructure.GameMode != fgStructure.Window ) && ( fgStructure.Window->Parent == NULL ) &&
+             ( ! fgStructure.Window->IsMenu ) )
         {
           winRect.left   += GetSystemMetrics( SM_CXSIZEFRAME );
           winRect.right  -= GetSystemMetrics( SM_CXSIZEFRAME );
@@ -659,7 +660,8 @@ int FGAPIENTRY glutLayerGet( GLenum eWhat )
         /*
          * Check if an overlay display mode is possible
          */
-        return  FALSE;
+/*        return( fgSetupPixelFormat( fgStructure.Window, TRUE, PFD_OVERLAY_PLANE ) ); */
+      return FALSE ;
 
     case GLUT_LAYER_IN_USE:
         /*
index 6b54d50..9945e99 100644 (file)
  * The SFG_Structure container holds information about windows and menus
  * created between glutInit() and glutMainLoop() return.
  */
-SFG_Structure fgStructure;
+
+SFG_Structure fgStructure = { { NULL, NULL },  /* The list of windows       */
+                              { NULL, NULL },  /* The list of menus         */
+                              NULL,            /* The current window        */
+                              NULL,            /* The current menu          */
+                              NULL,            /* The menu OpenGL context   */
+                              NULL,            /* The game mode window      */
+                              0,               /* The current new window ID */
+                              0 };             /* The current new menu ID   */
 
 
 /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
@@ -103,6 +111,11 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title, int x, int y,
     window->State.Modifiers = 0xffffffff;
 
     /*
+     * If this window is a menu, set IsMenu in the structure
+     */
+    window->IsMenu = fgState.BuildingAMenu ;
+
+    /*
      * Open the window now. The fgOpenWindow() function is system
      * dependant, and resides in freeglut_window.c. Uses fgState.
      */
@@ -119,6 +132,9 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title, int x, int y,
  */
 SFG_Menu* fgCreateMenu( FGCBmenu menuCallback )
 {
+  int x = 100, y = 100, w = 100, h = 100 ;
+  SFG_Window *current_window = fgStructure.Window ;
+
     /*
      * Have the menu object created
      */
@@ -132,11 +148,34 @@ SFG_Menu* fgCreateMenu( FGCBmenu menuCallback )
     if( !fgState.Time.Set )
         glutInit( &fakeArgc, NULL );
 
+    menu->ParentWindow = fgStructure.Window ;
+
+    /*
+     * Create a window for the menu to reside in.  Set the
+     * global variable BuildingAMenu to true so we can ensure
+     * it is created without decorations.
+     */
+    fgState.BuildingAMenu = TRUE ;
+
+    fgCreateWindow ( NULL, NULL, x, y, w, h, FALSE ) ;
+    menu->Window = fgStructure.Window ;
+    glutDisplayFunc ( fgDisplayMenu ) ;
+
+    /*
+     * While BuildingAMenu is true, all windows built have no decorations.  That's
+     * not a good default behavior, so let's set it false again.
+     */
+    fgState.BuildingAMenu = FALSE ;
+
+    glutHideWindow () ;  /* Hide the window for now */
+    fgStructure.Window = current_window ;
+
     /*
      * Initialize the object properties:
      */
     menu->ID       = ++fgStructure.MenuID;
     menu->Callback = menuCallback;
+    menu->ActiveEntry = NULL ;
 
     /*
      * Initialize the entries list
@@ -391,6 +430,11 @@ void fgDestroyMenu( SFG_Menu* menu )
   }
 
   /*
+   * Destroy the window associated with the menu
+   */
+  fgDestroyWindow ( menu->Window, TRUE ) ;
+
+  /*
    * Remove the menu from the menus list
    */
   fgListRemove( &fgStructure.Menus, &menu->Node );
index 48ab127..08cb8d9 100644 (file)
@@ -233,7 +233,7 @@ GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly, unsigned
         * It might be the case for us to use double buffering
         */
   if( fgState.DisplayMode & GLUT_DOUBLE )
-       flags |= PFD_DOUBLEBUFFER;
+    flags |= PFD_DOUBLEBUFFER;
 
   /*
    * Specify which pixel format do we opt for...
@@ -363,7 +363,24 @@ void fgOpenWindow( SFG_Window* window, const char* title, int x, int y, int w, i
     /*
      * Here we are upon the stage. Have the visual selected.
      */
-    window->Window.VisualInfo = fgChooseVisual();
+    if ( fgState.BuildingAMenu )
+    {
+      /*
+       * If there isn't already an OpenGL rendering context for menu windows, make one
+       */
+      if ( !fgStructure.MenuContext )
+      {
+        unsigned int current_DisplayMode = fgState.DisplayMode ;
+        fgState.DisplayMode = GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH ;
+        window->Window.VisualInfo = fgChooseVisual();
+        fgState.DisplayMode = current_DisplayMode ;
+      }
+      else
+        window->Window.VisualInfo = fgChooseVisual();
+    }
+    else
+      window->Window.VisualInfo = fgChooseVisual();
+
     if ( ! window->Window.VisualInfo )
     {
       /*
@@ -430,7 +447,28 @@ void fgOpenWindow( SFG_Window* window, const char* title, int x, int y, int w, i
      * The GLX context creation, possibly trying the direct context rendering
      *  or else use the current context if the user has so specified
      */
-    if ( fgState.UseCurrentContext == TRUE )
+    if ( fgState.BuildingAMenu )
+    {
+      /*
+       * If there isn't already an OpenGL rendering context for menu windows, make one
+       */
+      if ( !fgStructure.MenuContext )
+      {
+        fgStructure.MenuContext = (SFG_MenuContext *)malloc ( sizeof(SFG_MenuContext) ) ;
+        fgStructure.MenuContext->VisualInfo = window->Window.VisualInfo ;
+        fgStructure.MenuContext->Context = glXCreateContext(
+            fgDisplay.Display, fgStructure.MenuContext->VisualInfo,
+            NULL, fgState.ForceDirectContext | fgState.TryDirectContext
+        );
+      }
+
+/*      window->Window.Context = fgStructure.MenuContext->Context ; */
+      window->Window.Context = glXCreateContext(
+            fgDisplay.Display, window->Window.VisualInfo,
+            NULL, fgState.ForceDirectContext | fgState.TryDirectContext
+        );
+    }
+    else if ( fgState.UseCurrentContext == TRUE )
     {
       window->Window.Context = glXGetCurrentContext();
 
@@ -564,7 +602,7 @@ void fgOpenWindow( SFG_Window* window, const char* title, int x, int y, int w, i
 
     if( gameMode == FALSE )
     {
-      if ( !isSubWindow )
+      if ( ( !isSubWindow ) && ( ! window->IsMenu ) )
       {
         /*
          * Update the window dimensions, taking account of window decorations.
@@ -575,26 +613,27 @@ void fgOpenWindow( SFG_Window* window, const char* title, int x, int y, int w, i
                h += (GetSystemMetrics( SM_CYSIZEFRAME ) )*2 + GetSystemMetrics( SM_CYCAPTION );
       }
 
-
       /*
             * Check if the user wants us to use the default position/size
             */
            if( fgState.Position.Use == FALSE ) { x = CW_USEDEFAULT; y = CW_USEDEFAULT; }
-         
-  if( fgState.Size    .Use == FALSE ) { w = CW_USEDEFAULT; h = CW_USEDEFAULT; }
+           if( fgState.Size    .Use == FALSE ) { w = CW_USEDEFAULT; h = CW_USEDEFAULT; }
 
-       
-    /*
+           /*
             * There's a small difference between creating the top, child and game mode windows
             */
            flags = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
 
-           if( window->Parent == NULL )
+      /*
+       * If we're a menu, set our flags to include WS_POPUP to remove decorations
+       */
+      if ( window->IsMenu )
+        flags |= WS_POPUP ;
+           else if( window->Parent == NULL )
                    flags |= WS_OVERLAPPEDWINDOW;
            else
                    flags |= WS_CHILD;
     }
-
     else
     {
         /*
@@ -608,7 +647,6 @@ void fgOpenWindow( SFG_Window* window, const char* title, int x, int y, int w, i
         flags = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
     }
 
-
     /*
      * Create the window now, passing the freeglut window structure as the parameter
      */
@@ -651,14 +689,12 @@ void fgOpenWindow( SFG_Window* window, const char* title, int x, int y, int w, i
       glReadBuffer ( GL_FRONT ) ;
     }
 
-
     /*
      * Set the newly created window as the current one
      */
     fgSetWindow( window );
 }
 
-
 /*
  * Closes a window, destroying the frame and OpenGL context
  */
@@ -697,7 +733,6 @@ void fgCloseWindow( SFG_Window* window )
 }
 
 
-
 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
 
 /*
@@ -712,7 +747,6 @@ int FGAPIENTRY glutCreateWindow( const char* title )
                             fgState.Size.X, fgState.Size.Y, FALSE )->ID );
 }
 
-
 /*
  * This function creates a sub window.
  */
@@ -744,7 +778,6 @@ int FGAPIENTRY glutCreateSubWindow( int parentID, int x, int y, int w, int h )
     return( window->ID );
 }
 
-
 /*
  * Destroys a window and all of its subwindows
  */
@@ -771,7 +804,6 @@ void FGAPIENTRY glutDestroyWindow( int windowID )
   fgState.ExecState = ExecState ;
 }
 
-
 /*
  * This function selects the current window
  */
@@ -808,11 +840,9 @@ void FGAPIENTRY glutSetWindow( int ID )
         return;
     }
 
-
     fgSetWindow ( window ) ;
 }
 
-
 /*
  * This function returns the ID number of the current window, 0 if none exists
  */
@@ -831,14 +861,12 @@ int FGAPIENTRY glutGetWindow( void )
         return( 0 );
     }
 
-
     /*
      * Otherwise, return the ID of the current window
      */
     return( fgStructure.Window->ID );
 }
 
-
 /*
  * This function makes the current window visible
  */
@@ -860,8 +888,13 @@ void FGAPIENTRY glutShowWindow( void )
        ShowWindow( fgStructure.Window->Window.Handle, SW_SHOW );
 
 #endif
-}
 
+  /*
+   * Since the window is visible, we need to redisplay it ...
+   */
+  fgStructure.Window->State.Redisplay = TRUE;
+
+}
 
 /*
  * This function hides the current window
@@ -882,7 +915,6 @@ void FGAPIENTRY glutHideWindow( void )
          */
         XWithdrawWindow( fgDisplay.Display, fgStructure.Window->Window.Handle, fgDisplay.Screen );
     }
-
     else
     {
         /*
@@ -891,7 +923,6 @@ void FGAPIENTRY glutHideWindow( void )
         XUnmapWindow( fgDisplay.Display, fgStructure.Window->Window.Handle );
     }
 
-
     /*
      * Flush the X state now
      */
@@ -904,8 +935,12 @@ void FGAPIENTRY glutHideWindow( void )
        ShowWindow( fgStructure.Window->Window.Handle, SW_HIDE );
 
 #endif
-}
 
+  /*
+   * Since the window is hidden, we don't need to redisplay it ...
+   */
+  fgStructure.Window->State.Redisplay = FALSE;
+}
 
 /*
  * Iconify the current window (top-level windows only)
@@ -928,8 +963,13 @@ void FGAPIENTRY glutIconifyWindow( void )
        ShowWindow( fgStructure.Window->Window.Handle, SW_MINIMIZE );
 
 #endif
-}
 
+  /*
+   * Since the window is just an icon, we don't need to redisplay it ...
+   */
+  fgStructure.Window->State.Redisplay = FALSE;
+
+}
 
 /*
  * Set the current window's title
@@ -971,7 +1011,6 @@ void FGAPIENTRY glutSetWindowTitle( const char* title )
                XFlush( fgDisplay.Display );
        }
 
-
 #elif TARGET_HOST_WIN32
        /*
         * This seems to be a bit easier under Win32
@@ -981,7 +1020,6 @@ void FGAPIENTRY glutSetWindowTitle( const char* title )
 #endif
 }
 
-
 /*
  * Set the current window's iconified title
  */
@@ -1022,7 +1060,6 @@ void FGAPIENTRY glutSetIconTitle( const char* title )
                XFlush( fgDisplay.Display );
        }
 
-
 #elif TARGET_HOST_WIN32
        /*
         * This seems to be a bit easier under Win32
@@ -1032,7 +1069,6 @@ void FGAPIENTRY glutSetIconTitle( const char* title )
 #endif
 }
 
-
 /*
  * Change the current window's size
  */
@@ -1062,12 +1098,14 @@ void FGAPIENTRY glutReshapeWindow( int width, int height )
     if ( fgStructure.Window->Parent == NULL )  /* If this is not a subwindow ... */
     {
       /*
-       * Adjust the size of the window to allow for the size of the frame
+       * Adjust the size of the window to allow for the size of the frame, if we are not a menu
        */
-               width += GetSystemMetrics( SM_CXSIZEFRAME ) * 2;
-               height += GetSystemMetrics( SM_CYSIZEFRAME ) * 2 + GetSystemMetrics( SM_CYCAPTION );
+      if ( ! fgStructure.Window->IsMenu )
+      {
+               width += GetSystemMetrics( SM_CXSIZEFRAME ) * 2;
+               height += GetSystemMetrics( SM_CYSIZEFRAME ) * 2 + GetSystemMetrics( SM_CYCAPTION );
+      }
     }
-
     else  /* This is a subwindow, get the parent window's position and subtract it off */
     {
       GetWindowRect ( fgStructure.Window->Parent->Window.Handle, &winRect ) ;
@@ -1075,7 +1113,6 @@ void FGAPIENTRY glutReshapeWindow( int width, int height )
       y -= winRect.top + GetSystemMetrics( SM_CYSIZEFRAME ) + GetSystemMetrics( SM_CYCAPTION ) ;
     }
 
-
                /*
                 * Resize the window, forcing a redraw to happen
                 */
@@ -1088,11 +1125,9 @@ void FGAPIENTRY glutReshapeWindow( int width, int height )
                        TRUE
                );
        }
-
 #endif
 }
 
-
 /*
  * Change the current window's position
  */
@@ -1129,11 +1164,9 @@ void FGAPIENTRY glutPositionWindow( int x, int y )
                );
        }
 
-
 #endif
 }
 
-
 /*
  * Lowers the current window (by Z order change)
  */
@@ -1161,7 +1194,6 @@ void FGAPIENTRY glutPushWindow( void )
 #endif
 }
 
-
 /*
  * Raises the current window (by Z order change)
  */
@@ -1189,7 +1221,6 @@ void FGAPIENTRY glutPopWindow( void )
 #endif
 }
 
-
 /*
  * Resize the current window so that it fits the whole screen
  */
@@ -1208,7 +1239,6 @@ void FGAPIENTRY glutFullScreen( void )
     );
 }
 
-
 /*
  * A.Donev: Set and retrieve the window's user data
  */
@@ -1217,11 +1247,18 @@ void* FGAPIENTRY glutGetWindowData( void )
    return(fgStructure.Window->UserData);
 }
 
-
 void FGAPIENTRY glutSetWindowData(void* data)
 {
   fgStructure.Window->UserData=data;
 }
 
-
 /*** END OF FILE ***/
+
+
+
+
+
+
+
+
+