gallium/draw: initial code to properly support llvm in the draw module
[mesa.git] / src / glut / os2 / os2_winproc.cpp
index e2d4ba9d55028942edcd1aa73f6e7251ef5dfc54..9cbdec1cd29760010a7321abc4f90fd3c383ee60 100644 (file)
-/* os2_winproc.c */\r
-\r
-\r
-#define INCL_DEV\r
-#include "WarpGL.h"\r
-#include "GL/os2mesa.h"\r
-\r
-\r
-#define  _MEERROR_H_\r
-#include <mmioos2.h>                   /* It is from MMPM toolkit           */\r
-#include <dive.h>\r
-#include <fourcc.h>\r
-\r
-\r
-#include "os2mesadef.h"\r
-#include "glutint.h"\r
-\r
-\r
-#define POKA 0\r
-\r
-#if POKA\r
-\r
-extern unsigned __glutMenuButton;\r
-extern GLUTidleCB __glutIdleFunc;\r
-extern GLUTtimer *__glutTimerList;\r
-extern void handleTimeouts(void);\r
-extern GLUTmenuItem *__glutGetUniqueMenuItem(GLUTmenu * menu, int unique);\r
-static HMENU __glutHMenu;\r
-\r
-#endif\r
-\r
-extern void _mesa_ResizeBuffersMESA( void );\r
-\r
-\r
-MRESULT EXPENTRY GlutWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 );\r
-MRESULT EXPENTRY GlutWindowChildProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 );\r
-void updateWindowState(GLUTwindow *window, int visState);\r
-\r
-volatile extern HAB   hab;      /* PM anchor block handle         */\r
-volatile extern HPS   hpsCurrent;\r
-\r
-RECTL     rCtls[52];\r
-ULONG     ulNumRcls;\r
-\r
-MRESULT EXPENTRY GlutWindowChildProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )\r
-{   MRESULT rc;\r
-    rc = GlutWindowProc(hwnd, msg, mp1, mp2 );\r
-    return rc;\r
-}\r
-\r
-MRESULT EXPENTRY GlutWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )\r
-{\r
-  HPS   hps = NULLHANDLE; /* presentation space handle */\r
-  GLUTwindow*   window;   /* GLUT window associated with message. */\r
-  GLUTmenu*     menu;     /* GLUT menu associated with message. */\r
-  RECTL rclClient;\r
-  POINTL point;\r
-  int button = -1,rc,key;\r
-\r
-\r
-/* Process the message. */\r
-\r
-   switch( msg )\r
-   {\r
-      case WM_CREATE:\r
-     {\r
-      SIZEL sizl = { 0L, 0L };\r
-      LONG  *alCaps;\r
-      HDC hdc;\r
-\r
-      /*+-----------------------------------------------------------------+*/\r
-      /*| The client window is being created.  Create the semaphore to    |*/\r
-      /*| control access to the presentation space.  Then create the      |*/\r
-      /*| thread that will draw the lines.                                |*/\r
-      /*+-----------------------------------------------------------------+*/\r
- //    DosCreateMutexSem( (PSZ)NULL, &hmtxPS, 0UL, FALSE );\r
-\r
-      hdc = WinOpenWindowDC(hwnd);\r
-\r
-      /*+-----------------------------------------------------------------+*/\r
-      /*| Create a non-cached presentation space.  We will not release    |*/\r
-      /*| this PS, as we will be Selecting a Palette to this PS and then  |*/\r
-      /*| animating the palette.  Upon releasing a PS the palette is no   |*/\r
-      /*| longer selected for obvious reasons.                            |*/\r
-      /*+-----------------------------------------------------------------+*/\r
-      hpsCurrent = GpiCreatePS( hab,\r
-                  hdc,\r
-                  &sizl,\r
-                  PU_PELS | GPIF_DEFAULT |\r
-                  GPIT_MICRO | GPIA_ASSOC );\r
-//      DevQueryCaps( hdc, lStart, lCount, alCaps );\r
-//      fPaletteCaps = alCaps[CAPS_ADDITIONAL_GRAPHICS] & CAPS_PALETTE_MANAGER;\r
-//      PaletteInit(3);\r
-       /* ¯¥p¥¢®¤ hpsBuffer ¢ p¥¦¨¬ RGB color table  */\r
-\r
-        GpiCreateLogColorTable(hpsCurrent,0 ,LCOLF_RGB,0,0,NULL);\r
-        GpiSetPattern(hpsCurrent,PATSYM_SOLID);\r
-        GpiSetPatternSet(hpsCurrent,LCID_DEFAULT);\r
-\r
-     }\r
-    break;\r
-\r
-         return 0;\r
-      case WM_CLOSE:\r
-        WinPostMsg( hwnd, WM_QUIT, NULL, NULL );\r
-\r
-        return 0;\r
-\r
-      case WM_PAINT:\r
-    window = __glutGetWindow(hwnd);\r
-    if (window)\r
-    {\r
-       PWMC ctx;\r
-//   hps = WinBeginPaint(hwnd,NULLHANDLE,&rclClient);\r
-    hps = WinBeginPaint(hwnd,NULLHANDLE,&rclClient);\r
-       // blit Dive buffer to screen.\r
-\r
-     {\r
-         SWP    swp;            // Window position\r
-         POINTL pointl;         // Point to offset from Desktop\r
-\r
-             // Convert the point to offset from desktop lower left.\r
-             pointl.x = 0;\r
-             pointl.y = 0;\r
-             WinMapWindowPoints ( hwnd, HWND_DESKTOP, &pointl, 1 );\r
-\r
-\r
-//            ctx = window->ctx;\r
-//            ctx->xDiveScr = pointl.x;\r
-//            ctx->yDiveScr = pointl.y;\r
-      }\r
-//      rc = DiveBlitImage (ctx->hDive,\r
-//                          ctx->ulDiveBufferNumber,\r
-//                      DIVE_BUFFER_SCREEN );\r
-//\r
-\r
-        if (window->win == hwnd) {\r
-          __glutPostRedisplay(window, GLUT_REPAIR_WORK);\r
-        } else if (window->overlay && window->overlay->win == hwnd) {\r
-         __glutPostRedisplay(window, GLUT_OVERLAY_REPAIR_WORK);\r
-        }\r
-        WinEndPaint(hps);\r
-    } else {\r
-\r
-        hps = WinBeginPaint(hwnd,NULLHANDLE,&rclClient);\r
-        WinFillRect(hps, &rclClient, CLR_WHITE);\r
-        WinEndPaint(hps);\r
-    }\r
-        break;\r
-\r
-    case WM_VRNDISABLED:\r
-\r
-//           pwinData->fDataInProcess = TRUE;\r
-//           DiveSetupBlitter ( pwinData->hDive, 0 );\r
-//           pwinData->fVrnDisabled = TRUE;\r
-        break;\r
-\r
-    case WM_VRNENABLED:\r
-      {    HRGN      hrgn;      /* Region handle  */\r
-           RGNRECT   rgnCtl;    /* Processing control structure  */\r
-//           RECTL     rCtls[52];\r
-//           ULONG     ulNumRcls;\r
-\r
-//            pwinData->fDataInProcess = TRUE;\r
-            hps = WinGetPS ( hwnd );\r
-            if ( !hps )\r
-                  break;\r
-            hrgn = GpiCreateRegion ( hps, 0L, NULL );\r
-            if ( hrgn )\r
-            {  /* NOTE: If mp1 is zero, then this was just a move message.\r
-               ** Illustrate the visible region on a WM_VRNENABLE.\r
-               */\r
-               WinQueryVisibleRegion ( hwnd, hrgn );\r
-               rgnCtl.ircStart     = 0;\r
-               rgnCtl.crc          = 50;\r
-               rgnCtl.ulDirection  = 1;\r
-\r
-               /* Get the all ORed rectangles */\r
-               if ( GpiQueryRegionRects ( hps, hrgn, NULL,\r
-                                          &rgnCtl, rCtls) )\r
-               {\r
-                  ulNumRcls = rgnCtl.crcReturned;\r
-\r
-                  /* Now find the window position and size, relative to parent.\r
-                  */\r
-//                  WinQueryWindowPos ( pwinData->hwndClient, &pwinData->swp );\r
-\r
-//                  rcl.xLeft   = 0;\r
-//                  rcl.yBottom = 0;\r
-\r
-                  /* Convert the point to offset from desktop lower left.\r
-                  */\r
-//                  pointl.x = pwinData->swp.x;\r
-//                  pointl.y = pwinData->swp.y;\r
-\r
-//                  WinMapWindowPoints ( pwinData->hwndFrame,\r
-//                                       HWND_DESKTOP, &pointl, 1 );\r
-\r
-//                  pwinData->cxWindowPos = pointl.x;\r
-//                  pwinData->cyWindowPos = pointl.y;\r
-\r
-               }\r
-               GpiDestroyRegion( hps, hrgn );\r
-            }\r
-            WinReleasePS( hps );\r
-\r
-      }\r
-        break;\r
-\r
-  case WM_SIZE:\r
-    window = __glutGetWindow(hwnd);\r
-    if (window)\r
-    {  int width,height;\r
-       width = SHORT1FROMMP(mp2);\r
-      height = SHORT2FROMMP(mp2);\r
-      if (width != window->width || height != window->height) {\r
-#if 0  /* Win32 GLUT does not support overlays for now. */\r
-       if (window->overlay) {\r
-         XResizeWindow(__glutDisplay, window->overlay->win, width, height);\r
-       }\r
-#endif\r
-       window->width = width;\r
-       window->height = height;\r
-       __glutSetWindow(window);\r
-       if(width <= 0 || height <= 0)\r
-                            break;\r
-       _mesa_ResizeBuffersMESA();\r
-\r
-       /* Do not execute OpenGL out of sequence with respect\r
-          to the SetWindowPos request! */\r
-       window->reshape(width, height);\r
-       window->forceReshape = FALSE;\r
-       /* A reshape should be considered like posting a\r
-          repair request. */\r
-       __glutPostRedisplay(window, GLUT_REPAIR_WORK);\r
-      }\r
-    }\r
-    return 0;\r
-  case WM_SHOW:\r
-    window = __glutGetWindow(hwnd);\r
-    if (window) {\r
-       int visState;\r
-       visState = SHORT1FROMMP( mp1 );\r
-       updateWindowState(window, visState);\r
-    }\r
-    return 0;\r
-\r
-  case WM_ACTIVATE:\r
-    window = __glutGetWindow(hwnd);\r
-//    /* Make sure we re-select the correct palette if needed. */\r
-//    if (LOWORD(wParam)) {\r
-//      PostMessage(hwnd, WM_PALETTECHANGED, 0, 0);\r
-//    }\r
-    if (window) {\r
-       int visState;\r
-       visState = SHORT1FROMMP( mp1 );\r
-       updateWindowState(window, visState);\r
-    }\r
-    return 0;\r
-\r
-  case WM_CHAR:\r
-  { USHORT fsflags;\r
-    window = __glutGetWindow(hwnd);\r
-    if (!window) {\r
-      break;\r
-    }\r
-    fsflags = SHORT1FROMMP(mp1);\r
-/* ?? */\r
-    if((fsflags & KC_KEYUP) )  /* ¨£­®p¨p㥬 ®â¦ â¨¥ ª­®¯ª¨, p¥ £¨p㥬 â®«ìª® ­  ­ ¦ â¨¥  */\r
-            break;\r
-///////////////////////////////////////////////////\r
-   if(!(fsflags & KC_CHAR) )\r
-   {\r
-        if (!(fsflags & KC_VIRTUALKEY))\r
-                             break;\r
-        key = 0;\r
-         /* Get the virtual key from mp2.       */\r
-         switch (SHORT2FROMMP(mp2))\r
-         {\r
-/* directional keys */\r
-          case VK_LEFT:  key = GLUT_KEY_LEFT;  break;\r
-          case VK_UP:    key = GLUT_KEY_UP;    break;\r
-          case VK_RIGHT: key = GLUT_KEY_RIGHT; break;\r
-          case VK_DOWN:  key = GLUT_KEY_DOWN;  break;\r
-\r
-          case VK_PAGEUP:  key = GLUT_KEY_PAGE_UP;    break;\r
-          case VK_PAGEDOWN:key = GLUT_KEY_PAGE_DOWN;  break;\r
-          case VK_HOME:    key = GLUT_KEY_HOME;break;\r
-          case VK_END:     key = GLUT_KEY_END; break;\r
-          case VK_INSERT:  key = GLUT_KEY_INSERT;     break;\r
-\r
-/* function keys */\r
-          case VK_F1 : key = GLUT_KEY_F1;  break;\r
-          case VK_F2 : key = GLUT_KEY_F2; break;\r
-          case VK_F3 : key = GLUT_KEY_F3; break;\r
-          case VK_F4 : key = GLUT_KEY_F4; break;\r
-          case VK_F5 : key = GLUT_KEY_F5; break;\r
-          case VK_F6 : key = GLUT_KEY_F6; break;\r
-          case VK_F7 : key = GLUT_KEY_F7; break;\r
-          case VK_F8 : key = GLUT_KEY_F8; break;\r
-          case VK_F9 : key = GLUT_KEY_F9; break;\r
-          case VK_F10: key = GLUT_KEY_F10;break;\r
-          case VK_F11: key = GLUT_KEY_F11; break;\r
-          case VK_F12: key = GLUT_KEY_F12; break;\r
-          case VK_ESC:   key = -1; break;  /* Character codes */\r
-          case VK_SPACE: key = -1; break;\r
-          case VK_TAB:   key = -1; break;\r
-         }\r
-         if(!key)\r
-         {     break; /* Key Not implemented  */\r
-         }\r
-         if(key > 0)\r
-         {   if (!window->special)  /* ­¥ ãáâ ­®¢«¥­® ®¡à ¡®â稪  */\r
-                             break;\r
-\r
-               WinQueryPointerPos(HWND_DESKTOP,&point);\r
-               ScreenToClient(window->win, &point);\r
-               __glutSetWindow(window);\r
-               __glutModifierMask = 0;\r
-               if(WinGetKeyState(HWND_DESKTOP,VK_SHIFT) & 0x8000)   /*  high order bit is on */\r
-                          __glutModifierMask |= ShiftMask;\r
-               if(WinGetKeyState(HWND_DESKTOP,VK_CTRL) & 0x8000)\r
-                          __glutModifierMask |= ControlMask;\r
-               if(WinGetKeyState(HWND_DESKTOP,VK_MENU) & 0x8000)\r
-                          __glutModifierMask |= Mod1Mask;\r
-               window->special(key, point.x, point.y);\r
-               __glutModifierMask = (unsigned int) ~0;\r
-               return 0;\r
-         }\r
-\r
-   }\r
-/////////////////////////////////////////////////////\r
-    /* If  we are ignoring auto repeated key strokes for the window, bail. */\r
-    if (window->ignoreKeyRepeat && (CHAR3FROMMP(mp1)) )\r
-                                                   break;\r
-     if(!((unsigned char)SHORT1FROMMP(mp2))  )  /* ¨£­®p¨p㥬 ­¥á¨¬¢®«ì­ë¥ ª®¤ë */\r
-                                            break;\r
-    if (window->keyboard) {\r
-       WinQueryPointerPos(HWND_DESKTOP,&point);\r
-\r
-      ScreenToClient(window->win, &point);\r
-      __glutSetWindow(window);\r
-      __glutModifierMask = 0;\r
-      if(WinGetKeyState(HWND_DESKTOP,VK_SHIFT) & 0x8000)   /*  high order bit is on */\r
-           __glutModifierMask |= ShiftMask;\r
-      if(WinGetKeyState(HWND_DESKTOP,VK_CTRL) & 0x8000)\r
-           __glutModifierMask |= ControlMask;\r
-      if(WinGetKeyState(HWND_DESKTOP,VK_MENU) & 0x8000)\r
-           __glutModifierMask |= Mod1Mask;\r
-      window->keyboard((unsigned char)SHORT1FROMMP(mp2), point.x, point.y);\r
-      __glutModifierMask = (unsigned int) ~0;\r
-    }\r
-    return 0;\r
-  } /* endof case WM_CHAR: */\r
-////////////////////////////////////////////////\r
-  case WM_BUTTON1DOWN:\r
-    button = GLUT_LEFT_BUTTON;\r
-  case WM_BUTTON3DOWN:\r
-    if (button < 0)\r
-      button = GLUT_MIDDLE_BUTTON;\r
-  case WM_BUTTON2DOWN:\r
-    if (button < 0)\r
-      button = GLUT_RIGHT_BUTTON;\r
-    {  POINTS psh;\r
-       psh = *((POINTS *)&mp1);\r
-       point.x = psh.x;\r
-       point.y = psh.y;\r
-    }\r
-    /* finish the menu if we get a button down message (user must have\r
-       cancelled the menu). */\r
-    if (__glutMappedMenu) {\r
-      /* TODO: take this out once the menu on middle mouse stuff works\r
-        properly. */\r
-      if (button == GLUT_MIDDLE_BUTTON)\r
-       return 0;\r
- /* get current mouse pointer position */\r
-//      WinQueryPointerPos(HWND_DESKTOP,&point);\r
- /* map from desktop to client window */\r
-//      WinMapWindowPoints(HWND_DESKTOP, hwnd, &point, 1);\r
-      __glutItemSelected = NULL;\r
-      __glutFinishMenu(hwnd, point.x, point.y);\r
-      return 0;\r
-    }\r
-    window = __glutGetWindow(hwnd);\r
-    if (window) {\r
-      window->buttonDownState = button+1;\r
-      menu = __glutGetMenuByNum(window->menu[button]);\r
-      if (menu) {\r
-//todo\r
-//   __glutMenuButton = button == GLUT_RIGHT_BUTTON ? TPM_RIGHTBUTTON :\r
-//                           button == GLUT_LEFT_BUTTON  ? TPM_LEFTBUTTON :\r
-//                           0x0001;\r
-//   __glutStartMenu(menu, window, point.x, point.y, x, y);\r
-      } else if (window->mouse) {\r
-\r
-       __glutSetWindow(window);\r
-       __glutModifierMask = 0;\r
-       if (WinGetKeyState(HWND_DESKTOP,VK_SHIFT) & 0x8000)  /* < 0 = high order bit is on. */\r
-            __glutModifierMask |= ShiftMask;\r
-       if (WinGetKeyState(HWND_DESKTOP,VK_CTRL) & 0x8000)\r
-            __glutModifierMask |= ControlMask;\r
-       if (WinGetKeyState(HWND_DESKTOP,VK_MENU) & 0x8000)\r
-            __glutModifierMask |= Mod1Mask;\r
-      window->mouse(button, GLUT_DOWN, point.x, point.y);\r
-      __glutModifierMask = (unsigned int)~0;\r
-      } else {\r
-   /* Stray mouse events.  Ignore. */\r
-      }\r
-    }\r
-    return 0;\r
-\r
-    break;\r
-/********************************************/\r
-  case WM_BUTTON1UP:\r
-    button = GLUT_LEFT_BUTTON;\r
-  case WM_BUTTON3UP:\r
-    if (button < 0)\r
-      button = GLUT_MIDDLE_BUTTON;\r
-  case WM_BUTTON2UP:\r
-    if (button < 0)\r
-      button = GLUT_RIGHT_BUTTON;\r
-    {  POINTS psh;\r
-       psh = *((POINTS *)&mp1);\r
-       point.x = psh.x;\r
-       point.y = psh.y;\r
-    }\r
-    /* Bail out if we're processing a menu. */\r
-    /* Bail out = ¢ë¡à®á¨âìáï á ¯ à èã⮬   */\r
-    if (__glutMappedMenu) {\r
-      WinQueryPointerPos(HWND_DESKTOP,&point);\r
-      WinMapWindowPoints(HWND_DESKTOP, hwnd, &point, 1);\r
-      /* if we're getting the middle button up signal, then something\r
-        on the menu was selected. */\r
-      if (button == GLUT_MIDDLE_BUTTON) {\r
-       return 0;\r
-       /* For some reason, the code below always returns -1 even\r
-          though the point IS IN THE ITEM!  Therefore, just bail out if\r
-          we get a middle mouse up.  The user must select using the\r
-          left mouse button.  Stupid Win32. */\r
-#if 0\r
-       int item = MenuItemFromPoint(hwnd, __glutHMenu, point);\r
-       if (item != -1)\r
-         __glutItemSelected = (GLUTmenuItem*)GetMenuItemID(__glutHMenu, item);\r
-       else\r
-         __glutItemSelected = NULL;\r
-       __glutFinishMenu(hwnd, point.x, point.y);\r
-#endif\r
-      } else {\r
-       __glutItemSelected = NULL;\r
-       __glutFinishMenu(hwnd, point.x, point.y);\r
-      }\r
-      return 0;\r
-    }\r
-\r
-    window = __glutGetWindow(hwnd);\r
-    if(window)\r
-           window->buttonDownState = 0;\r
-\r
-    if (window && window->mouse) {\r
-      __glutSetWindow(window);\r
-      __glutModifierMask = 0;\r
-      if (WinGetKeyState(HWND_DESKTOP,VK_SHIFT) & 0x8000)   /* < 0 = high order bit is on */\r
-                          __glutModifierMask |= ShiftMask;\r
-      if (WinGetKeyState(HWND_DESKTOP,VK_CTRL) & 0x8000)\r
-   __glutModifierMask |= ControlMask;\r
-      if (WinGetKeyState(HWND_DESKTOP,VK_MENU) & 0x8000)\r
-   __glutModifierMask |= Mod1Mask;\r
-      window->mouse(button, GLUT_UP, point.x, point.y);\r
-\r
-      __glutModifierMask = (unsigned int)~0;\r
-    } else {\r
-      /* Window might have been destroyed and all the\r
-    events for the window may not yet be received. */\r
-    }\r
-    return 0;\r
-\r
-\r
-    break;\r
-//////////////////////////////////////////////////\r
-  case WM_COMMAND:\r
-    window = __glutGetWindow(hwnd);\r
-    if (window)\r
-    {   if (window->wm_command)\r
-            window->wm_command(hwnd,mp1,mp2);\r
-    }\r
-    break;\r
-\r
-  case WM_MOUSEMOVE:\r
-    if (!__glutMappedMenu) {\r
-      window = __glutGetWindow(hwnd);\r
-      if (window) {\r
-          /* If motion function registered _and_ buttons held *\r
-             down, call motion function...  */\r
-          {  POINTS psh;\r
-             psh = *((POINTS *)&mp1);\r
-             point.x = psh.x;\r
-             point.y = psh.y;\r
-          }\r
-\r
-         if (window->motion && window->buttonDownState) {\r
-           __glutSetWindow(window);\r
-           window->motion(point.x, point.y);\r
-         }\r
-   /* If passive motion function registered _and_\r
-      buttons not held down, call passive motion\r
-      function...  */\r
-         else if (window->passive && !window->buttonDownState) {\r
-           __glutSetWindow(window);\r
-           window->passive(point.x, point.y);\r
-         }\r
-      }\r
-    } else {\r
-      /* Motion events are thrown away when a pop up menu is\r
-    active. */\r
-    }\r
-    return 0;\r
-\r
-\r
-      default:\r
- /* For all other messages, let the default window procedure process them. */\r
-       return ( WinDefWindowProc( hwnd, msg, mp1, mp2 ) );\r
-\r
-   } //endof switch( msg )\r
-   return ( WinDefWindowProc( hwnd, msg, mp1, mp2 ) );\r
-//   return NULL;\r
-}\r
-\r
-void APIENTRY glutCommandFunc(GLUTcommandCB Func)\r
-{\r
-extern GLUTwindow *__glutCurrentWindow;\r
-    __glutCurrentWindow->wm_command = Func;\r
-}\r
-\r
-\r
-\r
-\r
-void\r
-updateWindowState(GLUTwindow *window, int visState)\r
-{\r
-  GLUTwindow* child;\r
-\r
-  /* XXX shownState and visState are the same in Win32. */\r
-  window->shownState = visState;\r
-  if (visState != window->visState) {\r
-    if (window->windowStatus) {\r
-      window->visState = visState;\r
-      __glutSetWindow(window);\r
-      window->windowStatus(visState);\r
-    }\r
-  }\r
-  /* Since Win32 only sends an activate for the toplevel window,\r
-     update the visibility for all the child windows. */\r
-  child = window->children;\r
-  while (child) {\r
-    updateWindowState(child, visState);\r
-    child = child->siblings;\r
-  }\r
-}\r
-\r
-#if POKA\r
-\r
-LONG WINAPI\r
-__glutWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)\r
-{\r
-  POINT         point;                 /* Point structure. */\r
-  PAINTSTRUCT   ps;                    /* Paint structure. */\r
-  LPMINMAXINFO  minmax;                        /* Minimum/maximum info structure. */\r
-  GLUTwindow*   window;                        /* GLUT window associated with message. */\r
-  GLUTmenu*     menu;                  /* GLUT menu associated with message. */\r
-  int x, y, width, height, key;\r
-  int button = -1;\r
-\r
-  switch(msg) {\r
-  case WM_CREATE:\r
-    return 0;\r
-  case WM_CLOSE:\r
-    PostQuitMessage(0);\r
-    return 0;\r
-#if 0\r
-  case WM_DESTROY:\r
-    /* XXX NVidia's NT OpenGL can have problems closing down\r
-       its OpenGL internal data structures if we just allow\r
-       the process to terminate without unbinding and deleting\r
-       the windows context.  Apparently, DirectDraw unloads\r
-       before OPENGL32.DLL in the close down sequence, but\r
-       NVidia's NT OpenGL needs DirectDraw to close down its\r
-       data structures. */\r
-    window = __glutGetWindow(hwnd);\r
-    if (window) {\r
-      if (window->ctx) {\r
-        wglMakeCurrent(NULL, NULL);\r
-        wglDeleteContext(window->ctx);\r
-      }\r
-    }\r
-    return 0;\r
-#endif\r
-\r
-  case WM_SYSKEYUP:\r
-  case WM_KEYUP:\r
-    window = __glutGetWindow(hwnd);\r
-    if (!window) {\r
-      break;\r
-    }\r
-    /* Win32 is dumb and sends these messages only to the parent\r
-       window.  Therefore, find out if we're in a child window and\r
-       call the child windows keyboard callback if we are. */\r
-    if (window->parent) {\r
-      GetCursorPos(&point);\r
-      ScreenToClient(hwnd, &point);\r
-      hwnd = ChildWindowFromPoint(hwnd, point);\r
-      window = __glutGetWindow(hwnd);\r
-    }\r
-    if (window->specialUp || window->keyboardUp) {\r
-      GetCursorPos(&point);\r
-      ScreenToClient(window->win, &point);\r
-      __glutSetWindow(window);\r
-      __glutModifierMask = 0;\r
-      if (GetKeyState(VK_SHIFT) < 0)  /* < 0 = high order bit is on */\r
-       __glutModifierMask |= ShiftMask;\r
-      if (GetKeyState(VK_SHIFT) < 0)  /* < 0 = high order bit is on */\r
-       __glutModifierMask |= ControlMask;\r
-      if (GetKeyState(VK_MENU) < 0)\r
-       __glutModifierMask |= Mod1Mask;\r
-      switch (wParam) {\r
-      /* *INDENT-OFF* */\r
-      case VK_F1:     key = GLUT_KEY_F1; break;\r
-      case VK_F2:     key = GLUT_KEY_F2; break;\r
-      case VK_F3:     key = GLUT_KEY_F3; break;\r
-      case VK_F4:     key = GLUT_KEY_F4; break;\r
-      case VK_F5:     key = GLUT_KEY_F5; break;\r
-      case VK_F6:     key = GLUT_KEY_F6; break;\r
-      case VK_F7:     key = GLUT_KEY_F7; break;\r
-      case VK_F8:     key = GLUT_KEY_F8; break;\r
-      case VK_F9:     key = GLUT_KEY_F9; break;\r
-      case VK_F10:    key = GLUT_KEY_F10; break;\r
-      case VK_F11:    key = GLUT_KEY_F11; break;\r
-      case VK_F12:    key = GLUT_KEY_F12; break;\r
-      case VK_LEFT:   key = GLUT_KEY_LEFT; break;\r
-      case VK_UP:     key = GLUT_KEY_UP; break;\r
-      case VK_RIGHT:  key = GLUT_KEY_RIGHT; break;\r
-      case VK_DOWN:   key = GLUT_KEY_DOWN; break;\r
-      case VK_PRIOR:  key = GLUT_KEY_PAGE_UP; break;\r
-      case VK_NEXT:   key = GLUT_KEY_PAGE_DOWN; break;\r
-      case VK_HOME:   key = GLUT_KEY_HOME; break;\r
-      case VK_END:    key = GLUT_KEY_END; break;\r
-      case VK_INSERT: key = GLUT_KEY_INSERT; break;\r
-      case VK_DELETE:\r
-        /* Delete is an ASCII character. */\r
-       if (window->keyboardUp) {\r
-         window->keyboardUp((unsigned char) 127, point.x, point.y);\r
-       }\r
-       return 0;\r
-      /* *INDENT-ON* */\r
-      default:\r
-       if (window->keyboardUp) {\r
-         key = MapVirtualKey(wParam, 2);  /* Map to ASCII. */\r
-         if (isascii(key) && (key != 0)) {\r
-\r
-           /* XXX Attempt to determine modified ASCII character\r
-              is quite incomplete.  Digits, symbols, CapsLock,\r
-              Ctrl, and numeric keypad are all ignored.  Fix this. */\r
-\r
-           if (!(__glutModifierMask & ShiftMask))\r
-             key = tolower(key);\r
-           window->keyboardUp((unsigned char) key, point.x, point.y);\r
-          }\r
-        }\r
-       __glutModifierMask = (unsigned int) ~0;\r
-       return 0;\r
-      }\r
-      if (window->specialUp) {\r
-        window->specialUp(key, point.x, point.y);\r
-      }\r
-      __glutModifierMask = (unsigned int) ~0;\r
-    }\r
-    return 0;\r
-\r
-  case WM_SYSCHAR:\r
-  case WM_CHAR:\r
-    window = __glutGetWindow(hwnd);\r
-    if (!window) {\r
-      break;\r
-    }\r
-\r
-    /* Bit 30 of lParam is set if key already held down.  If\r
-       we are ignoring auto repeated key strokes for the window, bail. */\r
-    if (window->ignoreKeyRepeat && (lParam & (1 << 30)) ) {\r
-      break;\r
-    }\r
-\r
-    /* Win32 is dumb and sends these messages only to the parent\r
-       window.  Therefore, find out if we're in a child window and\r
-       call the child windows keyboard callback if we are. */\r
-    if (window->parent) {\r
-       GetCursorPos(&point);\r
-       ScreenToClient(hwnd, &point);\r
-       hwnd = ChildWindowFromPoint(hwnd, point);\r
-       window = __glutGetWindow(hwnd);\r
-    }\r
-    if (window->keyboard) {\r
-      GetCursorPos(&point);\r
-      ScreenToClient(window->win, &point);\r
-      __glutSetWindow(window);\r
-      __glutModifierMask = 0;\r
-      if (GetKeyState(VK_SHIFT) < 0)   /* < 0 = high order bit is on */\r
-       __glutModifierMask |= ShiftMask;\r
-      if (GetKeyState(VK_CONTROL) < 0)\r
-       __glutModifierMask |= ControlMask;\r
-      if (GetKeyState(VK_MENU) < 0)\r
-       __glutModifierMask |= Mod1Mask;\r
-      window->keyboard((unsigned char)wParam, point.x, point.y);\r
-      __glutModifierMask = (unsigned int) ~0;\r
-    }\r
-    return 0;\r
-\r
-  case WM_SYSKEYDOWN:\r
-  case WM_KEYDOWN:\r
-    window = __glutGetWindow(hwnd);\r
-    if (!window) {\r
-      break;\r
-    }\r
-\r
-    /* Bit 30 of lParam is set if key already held down.  If\r
-       we are ignoring auto repeated key strokes for the window, bail. */\r
-    if (window->ignoreKeyRepeat && (lParam & (1 << 30)) ) {\r
-      break;\r
-    }\r
-\r
-    /* Win32 is dumb and sends these messages only to the parent\r
-       window.  Therefore, find out if we're in a child window and\r
-       call the child windows keyboard callback if we are. */\r
-    if (window->parent) {\r
-       GetCursorPos(&point);\r
-       ScreenToClient(hwnd, &point);\r
-       hwnd = ChildWindowFromPoint(hwnd, point);\r
-       window = __glutGetWindow(hwnd);\r
-    }\r
-    if (window->special) {\r
-      switch (wParam) {\r
-       /* *INDENT-OFF* */\r
-       /* function keys */\r
-       case VK_F1:     key = GLUT_KEY_F1; break;\r
-       case VK_F2:     key = GLUT_KEY_F2; break;\r
-       case VK_F3:     key = GLUT_KEY_F3; break;\r
-       case VK_F4:     key = GLUT_KEY_F4; break;\r
-       case VK_F5:     key = GLUT_KEY_F5; break;\r
-       case VK_F6:     key = GLUT_KEY_F6; break;\r
-       case VK_F7:     key = GLUT_KEY_F7; break;\r
-       case VK_F8:     key = GLUT_KEY_F8; break;\r
-       case VK_F9:     key = GLUT_KEY_F9; break;\r
-       case VK_F10:    key = GLUT_KEY_F10; break;\r
-       case VK_F11:    key = GLUT_KEY_F11; break;\r
-       case VK_F12:    key = GLUT_KEY_F12; break;\r
-       /* directional keys */\r
-       case VK_LEFT:   key = GLUT_KEY_LEFT; break;\r
-       case VK_UP:     key = GLUT_KEY_UP; break;\r
-       case VK_RIGHT:  key = GLUT_KEY_RIGHT; break;\r
-       case VK_DOWN:   key = GLUT_KEY_DOWN; break;\r
-       /* *INDENT-ON* */\r
-\r
-       case VK_PRIOR:\r
-         /* VK_PRIOR is Win32's Page Up */\r
-         key = GLUT_KEY_PAGE_UP;\r
-         break;\r
-       case VK_NEXT:\r
-         /* VK_NEXT is Win32's Page Down */\r
-         key = GLUT_KEY_PAGE_DOWN;\r
-         break;\r
-       case VK_HOME:\r
-         key = GLUT_KEY_HOME;\r
-         break;\r
-       case VK_END:\r
-         key = GLUT_KEY_END;\r
-         break;\r
-       case VK_INSERT:\r
-         key = GLUT_KEY_INSERT;\r
-         break;\r
-        case VK_DELETE:\r
-         goto handleDelete;\r
-       default:\r
-         goto defproc;\r
-      }\r
-      GetCursorPos(&point);\r
-      ScreenToClient(window->win, &point);\r
-      __glutSetWindow(window);\r
-      __glutModifierMask = 0;\r
-      if (GetKeyState(VK_SHIFT) < 0)   /* < 0 = high order bit is on */\r
-       __glutModifierMask |= ShiftMask;\r
-      if (GetKeyState(VK_CONTROL) < 0)\r
-       __glutModifierMask |= ControlMask;\r
-      if (GetKeyState(VK_MENU) < 0)\r
-       __glutModifierMask |= Mod1Mask;\r
-      window->special(key, point.x, point.y);\r
-      __glutModifierMask = (unsigned int) ~0;\r
-    } else if (window->keyboard) {\r
-      /* Specially handle any keys that match ASCII values but\r
-         do not generate Windows WM_SYSCHAR or WM_CHAR messages. */\r
-      switch (wParam) {\r
-      case VK_DELETE:\r
-      handleDelete:\r
-        /* Delete is an ASCII character. */\r
-        GetCursorPos(&point);\r
-        ScreenToClient(window->win, &point);\r
-        __glutSetWindow(window);\r
-        __glutModifierMask = 0;\r
-        if (GetKeyState(VK_SHIFT) < 0) /* < 0 = high order bit is on */\r
-          __glutModifierMask |= ShiftMask;\r
-        if (GetKeyState(VK_CONTROL) < 0)\r
-          __glutModifierMask |= ControlMask;\r
-        if (GetKeyState(VK_MENU) < 0)\r
-          __glutModifierMask |= Mod1Mask;\r
-       window->keyboard((unsigned char) 127, point.x, point.y);\r
-        __glutModifierMask = (unsigned int) ~0;\r
-       return 0;\r
-      default:\r
-        /* Let the following WM_SYSCHAR or WM_CHAR message generate\r
-          the keyboard callback. */\r
-        break;\r
-      }\r
-    }\r
-    return 0;\r
-\r
-  case WM_LBUTTONDOWN:\r
-    button = GLUT_LEFT_BUTTON;\r
-  case WM_MBUTTONDOWN:\r
-    if (button < 0)\r
-      button = GLUT_MIDDLE_BUTTON;\r
-  case WM_RBUTTONDOWN:\r
-    if (button < 0)\r
-      button = GLUT_RIGHT_BUTTON;\r
-\r
-    /* finish the menu if we get a button down message (user must have\r
-       cancelled the menu). */\r
-    if (__glutMappedMenu) {\r
-      /* TODO: take this out once the menu on middle mouse stuff works\r
-        properly. */\r
-      if (button == GLUT_MIDDLE_BUTTON)\r
-       return 0;\r
-      GetCursorPos(&point);\r
-      ScreenToClient(hwnd, &point);\r
-      __glutItemSelected = NULL;\r
-      __glutFinishMenu(hwnd, point.x, point.y);\r
-      return 0;\r
-    }\r
-\r
-    /* set the capture so we can get mouse events outside the window */\r
-    SetCapture(hwnd);\r
-\r
-    /* Win32 doesn't return the same numbers as X does when the mouse\r
-       goes beyond the upper or left side of the window.  roll the\r
-       Win32's 0..2^16 pointer co-ord range to 0 +/- 2^15. */\r
-    x = LOWORD(lParam);\r
-    y = HIWORD(lParam);\r
-    if(x & 1 << 15) x -= (1 << 16);\r
-    if(y & 1 << 15) y -= (1 << 16);\r
-\r
-    window = __glutGetWindow(hwnd);\r
-    if (window) {\r
-      menu = __glutGetMenuByNum(window->menu[button]);\r
-      if (menu) {\r
-       point.x = LOWORD(lParam); point.y = HIWORD(lParam);\r
-       ClientToScreen(window->win, &point);\r
-       __glutMenuButton = button == GLUT_RIGHT_BUTTON ? TPM_RIGHTBUTTON :\r
-                           button == GLUT_LEFT_BUTTON  ? TPM_LEFTBUTTON :\r
-                           0x0001;\r
-       __glutStartMenu(menu, window, point.x, point.y, x, y);\r
-      } else if (window->mouse) {\r
-\r
-        __glutSetWindow(window);\r
-       __glutModifierMask = 0;\r
-       if (GetKeyState(VK_SHIFT) < 0)  /* < 0 = high order bit is on. */\r
-         __glutModifierMask |= ShiftMask;\r
-       if (GetKeyState(VK_CONTROL) < 0)\r
-         __glutModifierMask |= ControlMask;\r
-       if (GetKeyState(VK_MENU) < 0)\r
-         __glutModifierMask |= Mod1Mask;\r
-       window->mouse(button, GLUT_DOWN, x, y);\r
-       __glutModifierMask = (unsigned int)~0;\r
-      } else {\r
-       /* Stray mouse events.  Ignore. */\r
-      }\r
-    }\r
-    return 0;\r
-\r
-  case WM_LBUTTONUP:\r
-    button = GLUT_LEFT_BUTTON;\r
-  case WM_MBUTTONUP:\r
-    if (button < 0)\r
-      button = GLUT_MIDDLE_BUTTON;\r
-  case WM_RBUTTONUP:\r
-    if (button < 0)\r
-      button = GLUT_RIGHT_BUTTON;\r
-\r
-    /* Bail out if we're processing a menu. */\r
-    if (__glutMappedMenu) {\r
-      GetCursorPos(&point);\r
-      ScreenToClient(hwnd, &point);\r
-      /* if we're getting the middle button up signal, then something\r
-        on the menu was selected. */\r
-      if (button == GLUT_MIDDLE_BUTTON) {\r
-       return 0;\r
-       /* For some reason, the code below always returns -1 even\r
-          though the point IS IN THE ITEM!  Therefore, just bail out if\r
-          we get a middle mouse up.  The user must select using the\r
-          left mouse button.  Stupid Win32. */\r
-#if 0\r
-       int item = MenuItemFromPoint(hwnd, __glutHMenu, point);\r
-       if (item != -1)\r
-         __glutItemSelected = (GLUTmenuItem*)GetMenuItemID(__glutHMenu, item);\r
-       else\r
-         __glutItemSelected = NULL;\r
-       __glutFinishMenu(hwnd, point.x, point.y);\r
-#endif\r
-      } else {\r
-       __glutItemSelected = NULL;\r
-       __glutFinishMenu(hwnd, point.x, point.y);\r
-      }\r
-      return 0;\r
-    }\r
-\r
-    /* Release the mouse capture. */\r
-    ReleaseCapture();\r
-\r
-    window = __glutGetWindow(hwnd);\r
-    if (window && window->mouse) {\r
-      /* Win32 doesn't return the same numbers as X does when the\r
-        mouse goes beyond the upper or left side of the window.  roll\r
-        the Win32's 0..2^16 pointer co-ord range to 0 +/- 2^15. */\r
-      x = LOWORD(lParam);\r
-      y = HIWORD(lParam);\r
-      if(x & 1 << 15) x -= (1 << 16);\r
-      if(y & 1 << 15) y -= (1 << 16);\r
-\r
-      __glutSetWindow(window);\r
-      __glutModifierMask = 0;\r
-      if (GetKeyState(VK_SHIFT) < 0)   /* < 0 = high order bit is on */\r
-       __glutModifierMask |= ShiftMask;\r
-      if (GetKeyState(VK_CONTROL) < 0)\r
-       __glutModifierMask |= ControlMask;\r
-      if (GetKeyState(VK_MENU) < 0)\r
-       __glutModifierMask |= Mod1Mask;\r
-      window->mouse(button, GLUT_UP, x, y);\r
-      __glutModifierMask = (unsigned int)~0;\r
-    } else {\r
-      /* Window might have been destroyed and all the\r
-        events for the window may not yet be received. */\r
-    }\r
-    return 0;\r
-\r
-  case WM_ENTERMENULOOP:\r
-    /* KLUDGE: create a timer that fires every 100 ms when we start a\r
-       menu so that we can still process the idle & timer events (that\r
-       way, the timers will fire during a menu pick and so will the\r
-       idle func. */\r
-    SetTimer(hwnd, 1, 1, NULL);\r
-    return 0;\r
-\r
-  case WM_TIMER:\r
-#if 0\r
-    /* If the timer id is 2, then this is the timer that is set up in\r
-       the main glut message processing loop, and we don't want to do\r
-       anything but acknowledge that we got it.  It is used to prevent\r
-       CPU spiking when an idle function is installed. */\r
-    if (wParam == 2)\r
-      return 0;\r
-#endif\r
-\r
-    /* only worry about the idle function and the timeouts, since\r
-       these are the only events we expect to process during\r
-       processing of a menu. */\r
-    /* we no longer process the idle functions (as outlined in the\r
-       README), since drawing can't be done until the menu has\r
-       finished...it's pretty lame when the animation goes on, but\r
-       doesn't update, so you get this weird jerkiness. */\r
-#if 0\r
-     if (__glutIdleFunc)\r
-       __glutIdleFunc();\r
-#endif\r
-    if (__glutTimerList)\r
-      handleTimeouts();\r
-    return 0;\r
-\r
-  case WM_EXITMENULOOP:\r
-    /* nuke the above created timer...we don't need it anymore, since\r
-       the menu is gone now. */\r
-    KillTimer(hwnd, 1);\r
-    return 0;\r
-\r
-  case WM_MENUSELECT:\r
-    if (lParam != 0)\r
-      __glutHMenu = (HMENU)lParam;\r
-    return 0;\r
-\r
-  case WM_COMMAND:\r
-    if (__glutMappedMenu) {\r
-      if (GetSubMenu(__glutHMenu, LOWORD(wParam)))\r
-       __glutItemSelected = NULL;\r
-      else\r
-       __glutItemSelected =\r
-         __glutGetUniqueMenuItem(__glutMappedMenu, LOWORD(wParam));\r
-      GetCursorPos(&point);\r
-      ScreenToClient(hwnd, &point);\r
-      __glutFinishMenu(hwnd, point.x, point.y);\r
-    }\r
-    return 0;\r
-\r
-  case WM_MOUSEMOVE:\r
-    if (!__glutMappedMenu) {\r
-      window = __glutGetWindow(hwnd);\r
-      if (window) {\r
-          /* If motion function registered _and_ buttons held *\r
-             down, call motion function...  */\r
-       x = LOWORD(lParam);\r
-       y = HIWORD(lParam);\r
-\r
-       /* Win32 doesn't return the same numbers as X does when the\r
-          mouse goes beyond the upper or left side of the window.\r
-          roll the Win32's 0..2^16 pointer co-ord range to 0..+/-2^15. */\r
-       if(x & 1 << 15) x -= (1 << 16);\r
-       if(y & 1 << 15) y -= (1 << 16);\r
-\r
-       if (window->motion && wParam &\r
-            (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) {\r
-         __glutSetWindow(window);\r
-         window->motion(x, y);\r
-       }\r
-       /* If passive motion function registered _and_\r
-          buttons not held down, call passive motion\r
-          function...  */\r
-       else if (window->passive &&\r
-                ((wParam &\r
-                  (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) ==\r
-                 0)) {\r
-         __glutSetWindow(window);\r
-         window->passive(x, y);\r
-       }\r
-      }\r
-    } else {\r
-      /* Motion events are thrown away when a pop up menu is\r
-        active. */\r
-    }\r
-    return 0;\r
-\r
-  case WM_GETMINMAXINFO:\r
-    /* this voodoo is brought to you by Win32 (again).  It allows the\r
-       window to be bigger than the screen, and smaller than 100x100\r
-       (although it doesn't seem to help the y minimum). */\r
-    minmax = (LPMINMAXINFO)lParam;\r
-    minmax->ptMaxSize.x = __glutScreenWidth;\r
-    minmax->ptMaxSize.y = __glutScreenHeight;\r
-    minmax->ptMinTrackSize.x = 0;\r
-    minmax->ptMinTrackSize.y = 0;\r
-    minmax->ptMaxTrackSize.x = __glutScreenWidth +\r
-      GetSystemMetrics(SM_CXSIZE) * 2;\r
-    minmax->ptMaxTrackSize.y = __glutScreenHeight +\r
-      GetSystemMetrics(SM_CXSIZE) * 2 + GetSystemMetrics(SM_CYCAPTION);\r
-    return 0;\r
-\r
-  case WM_SIZE:\r
-    window = __glutGetWindow(hwnd);\r
-    if (window) {\r
-      width = LOWORD(lParam);\r
-      height = HIWORD(lParam);\r
-      if (width != window->width || height != window->height) {\r
-#if 0  /* Win32 GLUT does not support overlays for now. */\r
-       if (window->overlay) {\r
-         XResizeWindow(__glutDisplay, window->overlay->win, width, height);\r
-       }\r
-#endif\r
-       window->width = width;\r
-       window->height = height;\r
-       __glutSetWindow(window);\r
-       /* Do not execute OpenGL out of sequence with respect\r
-          to the SetWindowPos request! */\r
-       GdiFlush();\r
-       window->reshape(width, height);\r
-       window->forceReshape = FALSE;\r
-       /* A reshape should be considered like posting a\r
-          repair request. */\r
-       __glutPostRedisplay(window, GLUT_REPAIR_WORK);\r
-      }\r
-    }\r
-    return 0;\r
-\r
-  case WM_SETCURSOR:\r
-    /* If the cursor is not in the client area, then we want to send\r
-       this message to the default window procedure ('cause its\r
-       probably in the border or title, and we don't handle that\r
-       cursor.  otherwise, set our cursor.  Win32 makes us set the\r
-       cursor every time the mouse moves (DUMB!). */\r
-    if(LOWORD(lParam) != HTCLIENT) {\r
-      goto defproc;\r
-    }\r
-    window = __glutGetWindow(hwnd);\r
-    if (window) {\r
-      __glutSetCursor(window);\r
-    }\r
-    /* TODO: check out the info in DevStudio on WM_SETCURSOR in the\r
-       DefaultAction section. */\r
-    return 1;\r
-\r
-  case WM_SETFOCUS:\r
-    window = __glutGetWindow(hwnd);\r
-    if (window) {\r
-      window->entryState = WM_SETFOCUS;\r
-      if (window->entry) {\r
-       __glutSetWindow(window);\r
-       window->entry(GLUT_ENTERED);\r
-       /* XXX Generation of fake passive notify?  See how much\r
-          work the X11 code does to support fake passive notify\r
-          callbacks. */\r
-      }\r
-      if (window->joystick && __glutCurrentWindow) {\r
-        if (__glutCurrentWindow->joyPollInterval > 0) {\r
-         MMRESULT result;\r
-\r
-         /* Because Win32 will only let one window capture the\r
-            joystick at a time, we must capture it when we get the\r
-            focus and release it when we lose the focus. */\r
-         result = joySetCapture(__glutCurrentWindow->win,\r
-           JOYSTICKID1, 0, TRUE);\r
-         if (result != JOYERR_NOERROR) {\r
-           return 0;\r
-          }\r
-         (void) joySetThreshold(JOYSTICKID1,\r
-            __glutCurrentWindow->joyPollInterval);\r
-        }\r
-      }\r
-    }\r
-    return 0;\r
-\r
-  case WM_KILLFOCUS:\r
-    window = __glutGetWindow(hwnd);\r
-    if (window) {\r
-      window->entryState = WM_KILLFOCUS;\r
-      if (window->entry) {\r
-       __glutSetWindow(window);\r
-       window->entry(GLUT_LEFT);\r
-      }\r
-      if (window->joystick && __glutCurrentWindow) {\r
-       if (__glutCurrentWindow->joyPollInterval > 0) {\r
-         /* Because Win32 will only let one window capture the\r
-            joystick at a time, we must capture it when we get the\r
-            focus and release it when we lose the focus. */\r
-           (void) joyReleaseCapture(JOYSTICKID1);\r
-        }\r
-      }\r
-    }\r
-    return 0;\r
-  case WM_ACTIVATE:\r
-    window = __glutGetWindow(hwnd);\r
-    /* Make sure we re-select the correct palette if needed. */\r
-    if (LOWORD(wParam)) {\r
-      PostMessage(hwnd, WM_PALETTECHANGED, 0, 0);\r
-    }\r
-    if (window) {\r
-      int visState;\r
-\r
-      /* HIWORD(wParam) is the minimized flag. */\r
-      visState = !HIWORD(wParam);\r
-      updateWindowState(window, visState);\r
-    }\r
-    return 0;\r
-\r
-  /* Colour Palette Management */\r
-  case WM_PALETTECHANGED:\r
-    if (hwnd == (HWND)wParam) {\r
-      /* Don't respond to the message that we sent! */\r
-      break;\r
-    }\r
-    /* fall through to WM_QUERYNEWPALETTE */\r
-\r
-  case WM_QUERYNEWPALETTE:\r
-    window = __glutGetWindow(hwnd);\r
-    if (window && window->colormap) {\r
-      UnrealizeObject(window->colormap->cmap);\r
-      SelectPalette(window->hdc, window->colormap->cmap, FALSE);\r
-      RealizePalette(window->hdc);\r
-      return TRUE;\r
-    }\r
-    return FALSE;\r
-\r
-  case MM_JOY1MOVE:\r
-  case MM_JOY1ZMOVE:\r
-    window = __glutGetWindow(hwnd);\r
-    if (window->joystick) {\r
-      JOYINFOEX jix;\r
-      int x, y, z;\r
-\r
-      /* Because WIN32 only supports messages for X, Y, and Z\r
-         translations, we must poll for the rest */\r
-      jix.dwSize = sizeof(jix);\r
-      jix.dwFlags = JOY_RETURNALL;\r
-      joyGetPosEx(JOYSTICKID1,&jix);\r
-\r
-#define SCALE(v)  ((int) ((v - 32767)/32.768))\r
-\r
-      /* Convert to integer for scaling. */\r
-      x = jix.dwXpos;\r
-      y = jix.dwYpos;\r
-      z = jix.dwZpos;\r
-      window->joystick(jix.dwButtons, SCALE(x), SCALE(y), SCALE(z));\r
-\r
-      return TRUE;\r
-    }\r
-    return FALSE;\r
-  case MM_JOY1BUTTONDOWN:\r
-  case MM_JOY1BUTTONUP:\r
-    window = __glutGetWindow(hwnd);\r
-    if (window->joystick) {\r
-      JOYINFOEX jix;\r
-\r
-      /* Because WIN32 only supports messages for X, Y, and Z\r
-         translations, we must poll for the rest */\r
-      jix.dwSize = sizeof(jix);\r
-      jix.dwFlags = JOY_RETURNALL;\r
-      joyGetPosEx(JOYSTICKID1,&jix);\r
-\r
-      return TRUE;\r
-    }\r
-    return FALSE;\r
-\r
-#if 0\r
-  /* Miscellaneous messages (don't really need to enumerate them,\r
-     but it's good to know what you're not getting sometimes). */\r
-  case WM_DISPLAYCHANGE:\r
-    break;\r
-  case WM_NCHITTEST:\r
-    /* This event is generated by every mouse move event. */\r
-    goto defproc;\r
-  case WM_NCMOUSEMOVE:\r
-    goto defproc;\r
-  case WM_NCACTIVATE:\r
-    goto defproc;\r
-  case WM_NCPAINT:\r
-    goto defproc;\r
-  case WM_NCCALCSIZE:\r
-    goto defproc;\r
-  case WM_NCCREATE:\r
-    goto defproc;\r
-  case WM_NCDESTROY:\r
-    goto defproc;\r
-  case WM_NCLBUTTONDOWN:\r
-    goto defproc;\r
-  case WM_SETTEXT:\r
-    goto defproc;\r
-  case WM_GETTEXT:\r
-    goto defproc;\r
-  case WM_ACTIVATEAPP:\r
-    goto defproc;\r
-  case WM_GETICON:\r
-    goto defproc;\r
-  case WM_ERASEBKGND:\r
-    goto defproc;\r
-  case WM_WINDOWPOSCHANGING:\r
-    goto defproc;\r
-  case WM_WINDOWPOSCHANGED:\r
-    goto defproc;\r
-  case WM_MOUSEACTIVATE:\r
-    goto defproc;\r
-  case WM_SHOWWINDOW:\r
-    goto defproc;\r
-  case WM_MOVING:\r
-    goto defproc;\r
-  case WM_MOVE:\r
-    goto defproc;\r
-  case WM_KEYUP:\r
-    goto defproc;\r
-  case WM_CAPTURECHANGED:\r
-    goto defproc;\r
-  case WM_SYSCOMMAND:\r
-    goto defproc;\r
-  case WM_ENTERSIZEMOVE:\r
-    goto defproc;\r
-  case WM_ENTERIDLE:\r
-    goto defproc;\r
-#endif\r
-\r
-  default:\r
-    goto defproc;\r
-  }\r
-\r
-defproc:\r
-  return DefWindowProc(hwnd, msg, wParam, lParam);\r
-}\r
-\r
-#endif\r
-\r
-#if defined(__OS2PM__)\r
-Bool __glutSetWindowText(Window window, char *text)\r
-{\r
-  return WinSetWindowText(window, (PCSZ)text);\r
-\r
-}\r
-\r
-#endif\r
-\1a
\ No newline at end of file
+/* os2_winproc.c */
+
+
+#define INCL_DEV
+#include "WarpGL.h"
+#include "GL/os2mesa.h"
+
+
+#define  _MEERROR_H_
+#include <mmioos2.h>                   /* It is from MMPM toolkit           */
+#include <dive.h>
+#include <fourcc.h>
+
+
+#include "os2mesadef.h"
+#include "glutint.h"
+
+
+#define POKA 0
+
+#if POKA
+
+extern unsigned __glutMenuButton;
+extern GLUTidleCB __glutIdleFunc;
+extern GLUTtimer *__glutTimerList;
+extern void handleTimeouts(void);
+extern GLUTmenuItem *__glutGetUniqueMenuItem(GLUTmenu * menu, int unique);
+static HMENU __glutHMenu;
+
+#endif
+
+extern void _mesa_ResizeBuffersMESA( void );
+
+
+MRESULT EXPENTRY GlutWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 );
+MRESULT EXPENTRY GlutWindowChildProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 );
+void updateWindowState(GLUTwindow *window, int visState);
+
+volatile extern HAB   hab;      /* PM anchor block handle         */
+volatile extern HPS   hpsCurrent;
+
+RECTL     rCtls[52];
+ULONG     ulNumRcls;
+
+MRESULT EXPENTRY GlutWindowChildProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
+{   MRESULT rc;
+    rc = GlutWindowProc(hwnd, msg, mp1, mp2 );
+    return rc;
+}
+
+MRESULT EXPENTRY GlutWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
+{
+  HPS   hps = NULLHANDLE; /* presentation space handle */
+  GLUTwindow*   window;   /* GLUT window associated with message. */
+  GLUTmenu*     menu;     /* GLUT menu associated with message. */
+  RECTL rclClient;
+  POINTL point;
+  int button = -1,rc,key;
+
+
+/* Process the message. */
+
+   switch( msg )
+   {
+      case WM_CREATE:
+     {
+      SIZEL sizl = { 0L, 0L };
+      LONG  *alCaps;
+      HDC hdc;
+
+      /*+-----------------------------------------------------------------+*/
+      /*| The client window is being created.  Create the semaphore to    |*/
+      /*| control access to the presentation space.  Then create the      |*/
+      /*| thread that will draw the lines.                                |*/
+      /*+-----------------------------------------------------------------+*/
+ //    DosCreateMutexSem( (PSZ)NULL, &hmtxPS, 0UL, FALSE );
+
+      hdc = WinOpenWindowDC(hwnd);
+
+      /*+-----------------------------------------------------------------+*/
+      /*| Create a non-cached presentation space.  We will not release    |*/
+      /*| this PS, as we will be Selecting a Palette to this PS and then  |*/
+      /*| animating the palette.  Upon releasing a PS the palette is no   |*/
+      /*| longer selected for obvious reasons.                            |*/
+      /*+-----------------------------------------------------------------+*/
+      hpsCurrent = GpiCreatePS( hab,
+                  hdc,
+                  &sizl,
+                  PU_PELS | GPIF_DEFAULT |
+                  GPIT_MICRO | GPIA_ASSOC );
+//      DevQueryCaps( hdc, lStart, lCount, alCaps );
+//      fPaletteCaps = alCaps[CAPS_ADDITIONAL_GRAPHICS] & CAPS_PALETTE_MANAGER;
+//      PaletteInit(3);
+       /* ¯¥p¥¢®¤ hpsBuffer ¢ p¥¦¨¬ RGB color table  */
+
+        GpiCreateLogColorTable(hpsCurrent,0 ,LCOLF_RGB,0,0,NULL);
+        GpiSetPattern(hpsCurrent,PATSYM_SOLID);
+        GpiSetPatternSet(hpsCurrent,LCID_DEFAULT);
+
+     }
+    break;
+
+         return 0;
+      case WM_CLOSE:
+        WinPostMsg( hwnd, WM_QUIT, NULL, NULL );
+
+        return 0;
+
+      case WM_PAINT:
+    window = __glutGetWindow(hwnd);
+    if (window)
+    {
+       PWMC ctx;
+//   hps = WinBeginPaint(hwnd,NULLHANDLE,&rclClient);
+    hps = WinBeginPaint(hwnd,NULLHANDLE,&rclClient);
+       // blit Dive buffer to screen.
+
+     {
+         SWP    swp;            // Window position
+         POINTL pointl;         // Point to offset from Desktop
+
+             // Convert the point to offset from desktop lower left.
+             pointl.x = 0;
+             pointl.y = 0;
+             WinMapWindowPoints ( hwnd, HWND_DESKTOP, &pointl, 1 );
+
+
+//            ctx = window->ctx;
+//            ctx->xDiveScr = pointl.x;
+//            ctx->yDiveScr = pointl.y;
+      }
+//      rc = DiveBlitImage (ctx->hDive,
+//                          ctx->ulDiveBufferNumber,
+//                      DIVE_BUFFER_SCREEN );
+//
+
+        if (window->win == hwnd) {
+          __glutPostRedisplay(window, GLUT_REPAIR_WORK);
+        } else if (window->overlay && window->overlay->win == hwnd) {
+         __glutPostRedisplay(window, GLUT_OVERLAY_REPAIR_WORK);
+        }
+        WinEndPaint(hps);
+    } else {
+
+        hps = WinBeginPaint(hwnd,NULLHANDLE,&rclClient);
+        WinFillRect(hps, &rclClient, CLR_WHITE);
+        WinEndPaint(hps);
+    }
+        break;
+
+    case WM_VRNDISABLED:
+
+//           pwinData->fDataInProcess = TRUE;
+//           DiveSetupBlitter ( pwinData->hDive, 0 );
+//           pwinData->fVrnDisabled = TRUE;
+        break;
+
+    case WM_VRNENABLED:
+      {    HRGN      hrgn;      /* Region handle  */
+           RGNRECT   rgnCtl;    /* Processing control structure  */
+//           RECTL     rCtls[52];
+//           ULONG     ulNumRcls;
+
+//            pwinData->fDataInProcess = TRUE;
+            hps = WinGetPS ( hwnd );
+            if ( !hps )
+                  break;
+            hrgn = GpiCreateRegion ( hps, 0L, NULL );
+            if ( hrgn )
+            {  /* NOTE: If mp1 is zero, then this was just a move message.
+               ** Illustrate the visible region on a WM_VRNENABLE.
+               */
+               WinQueryVisibleRegion ( hwnd, hrgn );
+               rgnCtl.ircStart     = 0;
+               rgnCtl.crc          = 50;
+               rgnCtl.ulDirection  = 1;
+
+               /* Get the all ORed rectangles */
+               if ( GpiQueryRegionRects ( hps, hrgn, NULL,
+                                          &rgnCtl, rCtls) )
+               {
+                  ulNumRcls = rgnCtl.crcReturned;
+
+                  /* Now find the window position and size, relative to parent.
+                  */
+//                  WinQueryWindowPos ( pwinData->hwndClient, &pwinData->swp );
+
+//                  rcl.xLeft   = 0;
+//                  rcl.yBottom = 0;
+
+                  /* Convert the point to offset from desktop lower left.
+                  */
+//                  pointl.x = pwinData->swp.x;
+//                  pointl.y = pwinData->swp.y;
+
+//                  WinMapWindowPoints ( pwinData->hwndFrame,
+//                                       HWND_DESKTOP, &pointl, 1 );
+
+//                  pwinData->cxWindowPos = pointl.x;
+//                  pwinData->cyWindowPos = pointl.y;
+
+               }
+               GpiDestroyRegion( hps, hrgn );
+            }
+            WinReleasePS( hps );
+
+      }
+        break;
+
+  case WM_SIZE:
+    window = __glutGetWindow(hwnd);
+    if (window)
+    {  int width,height;
+       width = SHORT1FROMMP(mp2);
+      height = SHORT2FROMMP(mp2);
+      if (width != window->width || height != window->height) {
+#if 0  /* Win32 GLUT does not support overlays for now. */
+       if (window->overlay) {
+         XResizeWindow(__glutDisplay, window->overlay->win, width, height);
+       }
+#endif
+       window->width = width;
+       window->height = height;
+       __glutSetWindow(window);
+       if(width <= 0 || height <= 0)
+                            break;
+       _mesa_ResizeBuffersMESA();
+
+       /* Do not execute OpenGL out of sequence with respect
+          to the SetWindowPos request! */
+       window->reshape(width, height);
+       window->forceReshape = FALSE;
+       /* A reshape should be considered like posting a
+          repair request. */
+       __glutPostRedisplay(window, GLUT_REPAIR_WORK);
+      }
+    }
+    return 0;
+  case WM_SHOW:
+    window = __glutGetWindow(hwnd);
+    if (window) {
+       int visState;
+       visState = SHORT1FROMMP( mp1 );
+       updateWindowState(window, visState);
+    }
+    return 0;
+
+  case WM_ACTIVATE:
+    window = __glutGetWindow(hwnd);
+//    /* Make sure we re-select the correct palette if needed. */
+//    if (LOWORD(wParam)) {
+//      PostMessage(hwnd, WM_PALETTECHANGED, 0, 0);
+//    }
+    if (window) {
+       int visState;
+       visState = SHORT1FROMMP( mp1 );
+       updateWindowState(window, visState);
+    }
+    return 0;
+
+  case WM_CHAR:
+  { USHORT fsflags;
+    window = __glutGetWindow(hwnd);
+    if (!window) {
+      break;
+    }
+    fsflags = SHORT1FROMMP(mp1);
+/* ?? */
+    if((fsflags & KC_KEYUP) )  /* ¨£­®p¨p㥬 ®â¦ â¨¥ ª­®¯ª¨, p¥ £¨p㥬 â®«ìª® ­  ­ ¦ â¨¥  */
+            break;
+///////////////////////////////////////////////////
+   if(!(fsflags & KC_CHAR) )
+   {
+        if (!(fsflags & KC_VIRTUALKEY))
+                             break;
+        key = 0;
+         /* Get the virtual key from mp2.       */
+         switch (SHORT2FROMMP(mp2))
+         {
+/* directional keys */
+          case VK_LEFT:  key = GLUT_KEY_LEFT;  break;
+          case VK_UP:    key = GLUT_KEY_UP;    break;
+          case VK_RIGHT: key = GLUT_KEY_RIGHT; break;
+          case VK_DOWN:  key = GLUT_KEY_DOWN;  break;
+
+          case VK_PAGEUP:  key = GLUT_KEY_PAGE_UP;    break;
+          case VK_PAGEDOWN:key = GLUT_KEY_PAGE_DOWN;  break;
+          case VK_HOME:    key = GLUT_KEY_HOME;break;
+          case VK_END:     key = GLUT_KEY_END; break;
+          case VK_INSERT:  key = GLUT_KEY_INSERT;     break;
+
+/* function keys */
+          case VK_F1 : key = GLUT_KEY_F1;  break;
+          case VK_F2 : key = GLUT_KEY_F2; break;
+          case VK_F3 : key = GLUT_KEY_F3; break;
+          case VK_F4 : key = GLUT_KEY_F4; break;
+          case VK_F5 : key = GLUT_KEY_F5; break;
+          case VK_F6 : key = GLUT_KEY_F6; break;
+          case VK_F7 : key = GLUT_KEY_F7; break;
+          case VK_F8 : key = GLUT_KEY_F8; break;
+          case VK_F9 : key = GLUT_KEY_F9; break;
+          case VK_F10: key = GLUT_KEY_F10;break;
+          case VK_F11: key = GLUT_KEY_F11; break;
+          case VK_F12: key = GLUT_KEY_F12; break;
+          case VK_ESC:   key = -1; break;  /* Character codes */
+          case VK_SPACE: key = -1; break;
+          case VK_TAB:   key = -1; break;
+         }
+         if(!key)
+         {     break; /* Key Not implemented  */
+         }
+         if(key > 0)
+         {   if (!window->special)  /* ­¥ ãáâ ­®¢«¥­® ®¡à ¡®â稪  */
+                             break;
+
+               WinQueryPointerPos(HWND_DESKTOP,&point);
+               ScreenToClient(window->win, &point);
+               __glutSetWindow(window);
+               __glutModifierMask = 0;
+               if(WinGetKeyState(HWND_DESKTOP,VK_SHIFT) & 0x8000)   /*  high order bit is on */
+                          __glutModifierMask |= ShiftMask;
+               if(WinGetKeyState(HWND_DESKTOP,VK_CTRL) & 0x8000)
+                          __glutModifierMask |= ControlMask;
+               if(WinGetKeyState(HWND_DESKTOP,VK_MENU) & 0x8000)
+                          __glutModifierMask |= Mod1Mask;
+               window->special(key, point.x, point.y);
+               __glutModifierMask = (unsigned int) ~0;
+               return 0;
+         }
+
+   }
+/////////////////////////////////////////////////////
+    /* If  we are ignoring auto repeated key strokes for the window, bail. */
+    if (window->ignoreKeyRepeat && (CHAR3FROMMP(mp1)) )
+                                                   break;
+     if(!((unsigned char)SHORT1FROMMP(mp2))  )  /* ¨£­®p¨p㥬 ­¥á¨¬¢®«ì­ë¥ ª®¤ë */
+                                            break;
+    if (window->keyboard) {
+       WinQueryPointerPos(HWND_DESKTOP,&point);
+
+      ScreenToClient(window->win, &point);
+      __glutSetWindow(window);
+      __glutModifierMask = 0;
+      if(WinGetKeyState(HWND_DESKTOP,VK_SHIFT) & 0x8000)   /*  high order bit is on */
+           __glutModifierMask |= ShiftMask;
+      if(WinGetKeyState(HWND_DESKTOP,VK_CTRL) & 0x8000)
+           __glutModifierMask |= ControlMask;
+      if(WinGetKeyState(HWND_DESKTOP,VK_MENU) & 0x8000)
+           __glutModifierMask |= Mod1Mask;
+      window->keyboard((unsigned char)SHORT1FROMMP(mp2), point.x, point.y);
+      __glutModifierMask = (unsigned int) ~0;
+    }
+    return 0;
+  } /* endof case WM_CHAR: */
+////////////////////////////////////////////////
+  case WM_BUTTON1DOWN:
+    button = GLUT_LEFT_BUTTON;
+  case WM_BUTTON3DOWN:
+    if (button < 0)
+      button = GLUT_MIDDLE_BUTTON;
+  case WM_BUTTON2DOWN:
+    if (button < 0)
+      button = GLUT_RIGHT_BUTTON;
+    {  POINTS psh;
+       psh = *((POINTS *)&mp1);
+       point.x = psh.x;
+       point.y = psh.y;
+    }
+    /* finish the menu if we get a button down message (user must have
+       cancelled the menu). */
+    if (__glutMappedMenu) {
+      /* TODO: take this out once the menu on middle mouse stuff works
+        properly. */
+      if (button == GLUT_MIDDLE_BUTTON)
+       return 0;
+ /* get current mouse pointer position */
+//      WinQueryPointerPos(HWND_DESKTOP,&point);
+ /* map from desktop to client window */
+//      WinMapWindowPoints(HWND_DESKTOP, hwnd, &point, 1);
+      __glutItemSelected = NULL;
+      __glutFinishMenu(hwnd, point.x, point.y);
+      return 0;
+    }
+    window = __glutGetWindow(hwnd);
+    if (window) {
+      window->buttonDownState = button+1;
+      menu = __glutGetMenuByNum(window->menu[button]);
+      if (menu) {
+//todo
+//   __glutMenuButton = button == GLUT_RIGHT_BUTTON ? TPM_RIGHTBUTTON :
+//                           button == GLUT_LEFT_BUTTON  ? TPM_LEFTBUTTON :
+//                           0x0001;
+//   __glutStartMenu(menu, window, point.x, point.y, x, y);
+      } else if (window->mouse) {
+
+       __glutSetWindow(window);
+       __glutModifierMask = 0;
+       if (WinGetKeyState(HWND_DESKTOP,VK_SHIFT) & 0x8000)  /* < 0 = high order bit is on. */
+            __glutModifierMask |= ShiftMask;
+       if (WinGetKeyState(HWND_DESKTOP,VK_CTRL) & 0x8000)
+            __glutModifierMask |= ControlMask;
+       if (WinGetKeyState(HWND_DESKTOP,VK_MENU) & 0x8000)
+            __glutModifierMask |= Mod1Mask;
+      window->mouse(button, GLUT_DOWN, point.x, point.y);
+      __glutModifierMask = (unsigned int)~0;
+      } else {
+   /* Stray mouse events.  Ignore. */
+      }
+    }
+    return 0;
+
+    break;
+/********************************************/
+  case WM_BUTTON1UP:
+    button = GLUT_LEFT_BUTTON;
+  case WM_BUTTON3UP:
+    if (button < 0)
+      button = GLUT_MIDDLE_BUTTON;
+  case WM_BUTTON2UP:
+    if (button < 0)
+      button = GLUT_RIGHT_BUTTON;
+    {  POINTS psh;
+       psh = *((POINTS *)&mp1);
+       point.x = psh.x;
+       point.y = psh.y;
+    }
+    /* Bail out if we're processing a menu. */
+    /* Bail out = ¢ë¡à®á¨âìáï á ¯ à èã⮬   */
+    if (__glutMappedMenu) {
+      WinQueryPointerPos(HWND_DESKTOP,&point);
+      WinMapWindowPoints(HWND_DESKTOP, hwnd, &point, 1);
+      /* if we're getting the middle button up signal, then something
+        on the menu was selected. */
+      if (button == GLUT_MIDDLE_BUTTON) {
+       return 0;
+       /* For some reason, the code below always returns -1 even
+          though the point IS IN THE ITEM!  Therefore, just bail out if
+          we get a middle mouse up.  The user must select using the
+          left mouse button.  Stupid Win32. */
+#if 0
+       int item = MenuItemFromPoint(hwnd, __glutHMenu, point);
+       if (item != -1)
+         __glutItemSelected = (GLUTmenuItem*)GetMenuItemID(__glutHMenu, item);
+       else
+         __glutItemSelected = NULL;
+       __glutFinishMenu(hwnd, point.x, point.y);
+#endif
+      } else {
+       __glutItemSelected = NULL;
+       __glutFinishMenu(hwnd, point.x, point.y);
+      }
+      return 0;
+    }
+
+    window = __glutGetWindow(hwnd);
+    if(window)
+           window->buttonDownState = 0;
+
+    if (window && window->mouse) {
+      __glutSetWindow(window);
+      __glutModifierMask = 0;
+      if (WinGetKeyState(HWND_DESKTOP,VK_SHIFT) & 0x8000)   /* < 0 = high order bit is on */
+                          __glutModifierMask |= ShiftMask;
+      if (WinGetKeyState(HWND_DESKTOP,VK_CTRL) & 0x8000)
+   __glutModifierMask |= ControlMask;
+      if (WinGetKeyState(HWND_DESKTOP,VK_MENU) & 0x8000)
+   __glutModifierMask |= Mod1Mask;
+      window->mouse(button, GLUT_UP, point.x, point.y);
+
+      __glutModifierMask = (unsigned int)~0;
+    } else {
+      /* Window might have been destroyed and all the
+    events for the window may not yet be received. */
+    }
+    return 0;
+
+
+    break;
+//////////////////////////////////////////////////
+  case WM_COMMAND:
+    window = __glutGetWindow(hwnd);
+    if (window)
+    {   if (window->wm_command)
+            window->wm_command(hwnd,mp1,mp2);
+    }
+    break;
+
+  case WM_MOUSEMOVE:
+    if (!__glutMappedMenu) {
+      window = __glutGetWindow(hwnd);
+      if (window) {
+          /* If motion function registered _and_ buttons held *
+             down, call motion function...  */
+          {  POINTS psh;
+             psh = *((POINTS *)&mp1);
+             point.x = psh.x;
+             point.y = psh.y;
+          }
+
+         if (window->motion && window->buttonDownState) {
+           __glutSetWindow(window);
+           window->motion(point.x, point.y);
+         }
+   /* If passive motion function registered _and_
+      buttons not held down, call passive motion
+      function...  */
+         else if (window->passive && !window->buttonDownState) {
+           __glutSetWindow(window);
+           window->passive(point.x, point.y);
+         }
+      }
+    } else {
+      /* Motion events are thrown away when a pop up menu is
+    active. */
+    }
+    return 0;
+
+
+      default:
+ /* For all other messages, let the default window procedure process them. */
+       return ( WinDefWindowProc( hwnd, msg, mp1, mp2 ) );
+
+   } //endof switch( msg )
+   return ( WinDefWindowProc( hwnd, msg, mp1, mp2 ) );
+//   return NULL;
+}
+
+void APIENTRY glutCommandFunc(GLUTcommandCB Func)
+{
+extern GLUTwindow *__glutCurrentWindow;
+    __glutCurrentWindow->wm_command = Func;
+}
+
+
+
+
+void
+updateWindowState(GLUTwindow *window, int visState)
+{
+  GLUTwindow* child;
+
+  /* XXX shownState and visState are the same in Win32. */
+  window->shownState = visState;
+  if (visState != window->visState) {
+    if (window->windowStatus) {
+      window->visState = visState;
+      __glutSetWindow(window);
+      window->windowStatus(visState);
+    }
+  }
+  /* Since Win32 only sends an activate for the toplevel window,
+     update the visibility for all the child windows. */
+  child = window->children;
+  while (child) {
+    updateWindowState(child, visState);
+    child = child->siblings;
+  }
+}
+
+#if POKA
+
+LONG WINAPI
+__glutWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+  POINT         point;                 /* Point structure. */
+  PAINTSTRUCT   ps;                    /* Paint structure. */
+  LPMINMAXINFO  minmax;                        /* Minimum/maximum info structure. */
+  GLUTwindow*   window;                        /* GLUT window associated with message. */
+  GLUTmenu*     menu;                  /* GLUT menu associated with message. */
+  int x, y, width, height, key;
+  int button = -1;
+
+  switch(msg) {
+  case WM_CREATE:
+    return 0;
+  case WM_CLOSE:
+    PostQuitMessage(0);
+    return 0;
+#if 0
+  case WM_DESTROY:
+    /* XXX NVidia's NT OpenGL can have problems closing down
+       its OpenGL internal data structures if we just allow
+       the process to terminate without unbinding and deleting
+       the windows context.  Apparently, DirectDraw unloads
+       before OPENGL32.DLL in the close down sequence, but
+       NVidia's NT OpenGL needs DirectDraw to close down its
+       data structures. */
+    window = __glutGetWindow(hwnd);
+    if (window) {
+      if (window->ctx) {
+        wglMakeCurrent(NULL, NULL);
+        wglDeleteContext(window->ctx);
+      }
+    }
+    return 0;
+#endif
+
+  case WM_SYSKEYUP:
+  case WM_KEYUP:
+    window = __glutGetWindow(hwnd);
+    if (!window) {
+      break;
+    }
+    /* Win32 is dumb and sends these messages only to the parent
+       window.  Therefore, find out if we're in a child window and
+       call the child windows keyboard callback if we are. */
+    if (window->parent) {
+      GetCursorPos(&point);
+      ScreenToClient(hwnd, &point);
+      hwnd = ChildWindowFromPoint(hwnd, point);
+      window = __glutGetWindow(hwnd);
+    }
+    if (window->specialUp || window->keyboardUp) {
+      GetCursorPos(&point);
+      ScreenToClient(window->win, &point);
+      __glutSetWindow(window);
+      __glutModifierMask = 0;
+      if (GetKeyState(VK_SHIFT) < 0)  /* < 0 = high order bit is on */
+       __glutModifierMask |= ShiftMask;
+      if (GetKeyState(VK_SHIFT) < 0)  /* < 0 = high order bit is on */
+       __glutModifierMask |= ControlMask;
+      if (GetKeyState(VK_MENU) < 0)
+       __glutModifierMask |= Mod1Mask;
+      switch (wParam) {
+      /* *INDENT-OFF* */
+      case VK_F1:     key = GLUT_KEY_F1; break;
+      case VK_F2:     key = GLUT_KEY_F2; break;
+      case VK_F3:     key = GLUT_KEY_F3; break;
+      case VK_F4:     key = GLUT_KEY_F4; break;
+      case VK_F5:     key = GLUT_KEY_F5; break;
+      case VK_F6:     key = GLUT_KEY_F6; break;
+      case VK_F7:     key = GLUT_KEY_F7; break;
+      case VK_F8:     key = GLUT_KEY_F8; break;
+      case VK_F9:     key = GLUT_KEY_F9; break;
+      case VK_F10:    key = GLUT_KEY_F10; break;
+      case VK_F11:    key = GLUT_KEY_F11; break;
+      case VK_F12:    key = GLUT_KEY_F12; break;
+      case VK_LEFT:   key = GLUT_KEY_LEFT; break;
+      case VK_UP:     key = GLUT_KEY_UP; break;
+      case VK_RIGHT:  key = GLUT_KEY_RIGHT; break;
+      case VK_DOWN:   key = GLUT_KEY_DOWN; break;
+      case VK_PRIOR:  key = GLUT_KEY_PAGE_UP; break;
+      case VK_NEXT:   key = GLUT_KEY_PAGE_DOWN; break;
+      case VK_HOME:   key = GLUT_KEY_HOME; break;
+      case VK_END:    key = GLUT_KEY_END; break;
+      case VK_INSERT: key = GLUT_KEY_INSERT; break;
+      case VK_DELETE:
+        /* Delete is an ASCII character. */
+       if (window->keyboardUp) {
+         window->keyboardUp((unsigned char) 127, point.x, point.y);
+       }
+       return 0;
+      /* *INDENT-ON* */
+      default:
+       if (window->keyboardUp) {
+         key = MapVirtualKey(wParam, 2);  /* Map to ASCII. */
+         if (isascii(key) && (key != 0)) {
+
+           /* XXX Attempt to determine modified ASCII character
+              is quite incomplete.  Digits, symbols, CapsLock,
+              Ctrl, and numeric keypad are all ignored.  Fix this. */
+
+           if (!(__glutModifierMask & ShiftMask))
+             key = tolower(key);
+           window->keyboardUp((unsigned char) key, point.x, point.y);
+          }
+        }
+       __glutModifierMask = (unsigned int) ~0;
+       return 0;
+      }
+      if (window->specialUp) {
+        window->specialUp(key, point.x, point.y);
+      }
+      __glutModifierMask = (unsigned int) ~0;
+    }
+    return 0;
+
+  case WM_SYSCHAR:
+  case WM_CHAR:
+    window = __glutGetWindow(hwnd);
+    if (!window) {
+      break;
+    }
+
+    /* Bit 30 of lParam is set if key already held down.  If
+       we are ignoring auto repeated key strokes for the window, bail. */
+    if (window->ignoreKeyRepeat && (lParam & (1 << 30)) ) {
+      break;
+    }
+
+    /* Win32 is dumb and sends these messages only to the parent
+       window.  Therefore, find out if we're in a child window and
+       call the child windows keyboard callback if we are. */
+    if (window->parent) {
+       GetCursorPos(&point);
+       ScreenToClient(hwnd, &point);
+       hwnd = ChildWindowFromPoint(hwnd, point);
+       window = __glutGetWindow(hwnd);
+    }
+    if (window->keyboard) {
+      GetCursorPos(&point);
+      ScreenToClient(window->win, &point);
+      __glutSetWindow(window);
+      __glutModifierMask = 0;
+      if (GetKeyState(VK_SHIFT) < 0)   /* < 0 = high order bit is on */
+       __glutModifierMask |= ShiftMask;
+      if (GetKeyState(VK_CONTROL) < 0)
+       __glutModifierMask |= ControlMask;
+      if (GetKeyState(VK_MENU) < 0)
+       __glutModifierMask |= Mod1Mask;
+      window->keyboard((unsigned char)wParam, point.x, point.y);
+      __glutModifierMask = (unsigned int) ~0;
+    }
+    return 0;
+
+  case WM_SYSKEYDOWN:
+  case WM_KEYDOWN:
+    window = __glutGetWindow(hwnd);
+    if (!window) {
+      break;
+    }
+
+    /* Bit 30 of lParam is set if key already held down.  If
+       we are ignoring auto repeated key strokes for the window, bail. */
+    if (window->ignoreKeyRepeat && (lParam & (1 << 30)) ) {
+      break;
+    }
+
+    /* Win32 is dumb and sends these messages only to the parent
+       window.  Therefore, find out if we're in a child window and
+       call the child windows keyboard callback if we are. */
+    if (window->parent) {
+       GetCursorPos(&point);
+       ScreenToClient(hwnd, &point);
+       hwnd = ChildWindowFromPoint(hwnd, point);
+       window = __glutGetWindow(hwnd);
+    }
+    if (window->special) {
+      switch (wParam) {
+       /* *INDENT-OFF* */
+       /* function keys */
+       case VK_F1:     key = GLUT_KEY_F1; break;
+       case VK_F2:     key = GLUT_KEY_F2; break;
+       case VK_F3:     key = GLUT_KEY_F3; break;
+       case VK_F4:     key = GLUT_KEY_F4; break;
+       case VK_F5:     key = GLUT_KEY_F5; break;
+       case VK_F6:     key = GLUT_KEY_F6; break;
+       case VK_F7:     key = GLUT_KEY_F7; break;
+       case VK_F8:     key = GLUT_KEY_F8; break;
+       case VK_F9:     key = GLUT_KEY_F9; break;
+       case VK_F10:    key = GLUT_KEY_F10; break;
+       case VK_F11:    key = GLUT_KEY_F11; break;
+       case VK_F12:    key = GLUT_KEY_F12; break;
+       /* directional keys */
+       case VK_LEFT:   key = GLUT_KEY_LEFT; break;
+       case VK_UP:     key = GLUT_KEY_UP; break;
+       case VK_RIGHT:  key = GLUT_KEY_RIGHT; break;
+       case VK_DOWN:   key = GLUT_KEY_DOWN; break;
+       /* *INDENT-ON* */
+
+       case VK_PRIOR:
+         /* VK_PRIOR is Win32's Page Up */
+         key = GLUT_KEY_PAGE_UP;
+         break;
+       case VK_NEXT:
+         /* VK_NEXT is Win32's Page Down */
+         key = GLUT_KEY_PAGE_DOWN;
+         break;
+       case VK_HOME:
+         key = GLUT_KEY_HOME;
+         break;
+       case VK_END:
+         key = GLUT_KEY_END;
+         break;
+       case VK_INSERT:
+         key = GLUT_KEY_INSERT;
+         break;
+        case VK_DELETE:
+         goto handleDelete;
+       default:
+         goto defproc;
+      }
+      GetCursorPos(&point);
+      ScreenToClient(window->win, &point);
+      __glutSetWindow(window);
+      __glutModifierMask = 0;
+      if (GetKeyState(VK_SHIFT) < 0)   /* < 0 = high order bit is on */
+       __glutModifierMask |= ShiftMask;
+      if (GetKeyState(VK_CONTROL) < 0)
+       __glutModifierMask |= ControlMask;
+      if (GetKeyState(VK_MENU) < 0)
+       __glutModifierMask |= Mod1Mask;
+      window->special(key, point.x, point.y);
+      __glutModifierMask = (unsigned int) ~0;
+    } else if (window->keyboard) {
+      /* Specially handle any keys that match ASCII values but
+         do not generate Windows WM_SYSCHAR or WM_CHAR messages. */
+      switch (wParam) {
+      case VK_DELETE:
+      handleDelete:
+        /* Delete is an ASCII character. */
+        GetCursorPos(&point);
+        ScreenToClient(window->win, &point);
+        __glutSetWindow(window);
+        __glutModifierMask = 0;
+        if (GetKeyState(VK_SHIFT) < 0) /* < 0 = high order bit is on */
+          __glutModifierMask |= ShiftMask;
+        if (GetKeyState(VK_CONTROL) < 0)
+          __glutModifierMask |= ControlMask;
+        if (GetKeyState(VK_MENU) < 0)
+          __glutModifierMask |= Mod1Mask;
+       window->keyboard((unsigned char) 127, point.x, point.y);
+        __glutModifierMask = (unsigned int) ~0;
+       return 0;
+      default:
+        /* Let the following WM_SYSCHAR or WM_CHAR message generate
+          the keyboard callback. */
+        break;
+      }
+    }
+    return 0;
+
+  case WM_LBUTTONDOWN:
+    button = GLUT_LEFT_BUTTON;
+  case WM_MBUTTONDOWN:
+    if (button < 0)
+      button = GLUT_MIDDLE_BUTTON;
+  case WM_RBUTTONDOWN:
+    if (button < 0)
+      button = GLUT_RIGHT_BUTTON;
+
+    /* finish the menu if we get a button down message (user must have
+       cancelled the menu). */
+    if (__glutMappedMenu) {
+      /* TODO: take this out once the menu on middle mouse stuff works
+        properly. */
+      if (button == GLUT_MIDDLE_BUTTON)
+       return 0;
+      GetCursorPos(&point);
+      ScreenToClient(hwnd, &point);
+      __glutItemSelected = NULL;
+      __glutFinishMenu(hwnd, point.x, point.y);
+      return 0;
+    }
+
+    /* set the capture so we can get mouse events outside the window */
+    SetCapture(hwnd);
+
+    /* Win32 doesn't return the same numbers as X does when the mouse
+       goes beyond the upper or left side of the window.  roll the
+       Win32's 0..2^16 pointer co-ord range to 0 +/- 2^15. */
+    x = LOWORD(lParam);
+    y = HIWORD(lParam);
+    if(x & 1 << 15) x -= (1 << 16);
+    if(y & 1 << 15) y -= (1 << 16);
+
+    window = __glutGetWindow(hwnd);
+    if (window) {
+      menu = __glutGetMenuByNum(window->menu[button]);
+      if (menu) {
+       point.x = LOWORD(lParam); point.y = HIWORD(lParam);
+       ClientToScreen(window->win, &point);
+       __glutMenuButton = button == GLUT_RIGHT_BUTTON ? TPM_RIGHTBUTTON :
+                           button == GLUT_LEFT_BUTTON  ? TPM_LEFTBUTTON :
+                           0x0001;
+       __glutStartMenu(menu, window, point.x, point.y, x, y);
+      } else if (window->mouse) {
+
+        __glutSetWindow(window);
+       __glutModifierMask = 0;
+       if (GetKeyState(VK_SHIFT) < 0)  /* < 0 = high order bit is on. */
+         __glutModifierMask |= ShiftMask;
+       if (GetKeyState(VK_CONTROL) < 0)
+         __glutModifierMask |= ControlMask;
+       if (GetKeyState(VK_MENU) < 0)
+         __glutModifierMask |= Mod1Mask;
+       window->mouse(button, GLUT_DOWN, x, y);
+       __glutModifierMask = (unsigned int)~0;
+      } else {
+       /* Stray mouse events.  Ignore. */
+      }
+    }
+    return 0;
+
+  case WM_LBUTTONUP:
+    button = GLUT_LEFT_BUTTON;
+  case WM_MBUTTONUP:
+    if (button < 0)
+      button = GLUT_MIDDLE_BUTTON;
+  case WM_RBUTTONUP:
+    if (button < 0)
+      button = GLUT_RIGHT_BUTTON;
+
+    /* Bail out if we're processing a menu. */
+    if (__glutMappedMenu) {
+      GetCursorPos(&point);
+      ScreenToClient(hwnd, &point);
+      /* if we're getting the middle button up signal, then something
+        on the menu was selected. */
+      if (button == GLUT_MIDDLE_BUTTON) {
+       return 0;
+       /* For some reason, the code below always returns -1 even
+          though the point IS IN THE ITEM!  Therefore, just bail out if
+          we get a middle mouse up.  The user must select using the
+          left mouse button.  Stupid Win32. */
+#if 0
+       int item = MenuItemFromPoint(hwnd, __glutHMenu, point);
+       if (item != -1)
+         __glutItemSelected = (GLUTmenuItem*)GetMenuItemID(__glutHMenu, item);
+       else
+         __glutItemSelected = NULL;
+       __glutFinishMenu(hwnd, point.x, point.y);
+#endif
+      } else {
+       __glutItemSelected = NULL;
+       __glutFinishMenu(hwnd, point.x, point.y);
+      }
+      return 0;
+    }
+
+    /* Release the mouse capture. */
+    ReleaseCapture();
+
+    window = __glutGetWindow(hwnd);
+    if (window && window->mouse) {
+      /* Win32 doesn't return the same numbers as X does when the
+        mouse goes beyond the upper or left side of the window.  roll
+        the Win32's 0..2^16 pointer co-ord range to 0 +/- 2^15. */
+      x = LOWORD(lParam);
+      y = HIWORD(lParam);
+      if(x & 1 << 15) x -= (1 << 16);
+      if(y & 1 << 15) y -= (1 << 16);
+
+      __glutSetWindow(window);
+      __glutModifierMask = 0;
+      if (GetKeyState(VK_SHIFT) < 0)   /* < 0 = high order bit is on */
+       __glutModifierMask |= ShiftMask;
+      if (GetKeyState(VK_CONTROL) < 0)
+       __glutModifierMask |= ControlMask;
+      if (GetKeyState(VK_MENU) < 0)
+       __glutModifierMask |= Mod1Mask;
+      window->mouse(button, GLUT_UP, x, y);
+      __glutModifierMask = (unsigned int)~0;
+    } else {
+      /* Window might have been destroyed and all the
+        events for the window may not yet be received. */
+    }
+    return 0;
+
+  case WM_ENTERMENULOOP:
+    /* KLUDGE: create a timer that fires every 100 ms when we start a
+       menu so that we can still process the idle & timer events (that
+       way, the timers will fire during a menu pick and so will the
+       idle func. */
+    SetTimer(hwnd, 1, 1, NULL);
+    return 0;
+
+  case WM_TIMER:
+#if 0
+    /* If the timer id is 2, then this is the timer that is set up in
+       the main glut message processing loop, and we don't want to do
+       anything but acknowledge that we got it.  It is used to prevent
+       CPU spiking when an idle function is installed. */
+    if (wParam == 2)
+      return 0;
+#endif
+
+    /* only worry about the idle function and the timeouts, since
+       these are the only events we expect to process during
+       processing of a menu. */
+    /* we no longer process the idle functions (as outlined in the
+       README), since drawing can't be done until the menu has
+       finished...it's pretty lame when the animation goes on, but
+       doesn't update, so you get this weird jerkiness. */
+#if 0
+     if (__glutIdleFunc)
+       __glutIdleFunc();
+#endif
+    if (__glutTimerList)
+      handleTimeouts();
+    return 0;
+
+  case WM_EXITMENULOOP:
+    /* nuke the above created timer...we don't need it anymore, since
+       the menu is gone now. */
+    KillTimer(hwnd, 1);
+    return 0;
+
+  case WM_MENUSELECT:
+    if (lParam != 0)
+      __glutHMenu = (HMENU)lParam;
+    return 0;
+
+  case WM_COMMAND:
+    if (__glutMappedMenu) {
+      if (GetSubMenu(__glutHMenu, LOWORD(wParam)))
+       __glutItemSelected = NULL;
+      else
+       __glutItemSelected =
+         __glutGetUniqueMenuItem(__glutMappedMenu, LOWORD(wParam));
+      GetCursorPos(&point);
+      ScreenToClient(hwnd, &point);
+      __glutFinishMenu(hwnd, point.x, point.y);
+    }
+    return 0;
+
+  case WM_MOUSEMOVE:
+    if (!__glutMappedMenu) {
+      window = __glutGetWindow(hwnd);
+      if (window) {
+          /* If motion function registered _and_ buttons held *
+             down, call motion function...  */
+       x = LOWORD(lParam);
+       y = HIWORD(lParam);
+
+       /* Win32 doesn't return the same numbers as X does when the
+          mouse goes beyond the upper or left side of the window.
+          roll the Win32's 0..2^16 pointer co-ord range to 0..+/-2^15. */
+       if(x & 1 << 15) x -= (1 << 16);
+       if(y & 1 << 15) y -= (1 << 16);
+
+       if (window->motion && wParam &
+            (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) {
+         __glutSetWindow(window);
+         window->motion(x, y);
+       }
+       /* If passive motion function registered _and_
+          buttons not held down, call passive motion
+          function...  */
+       else if (window->passive &&
+                ((wParam &
+                  (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) ==
+                 0)) {
+         __glutSetWindow(window);
+         window->passive(x, y);
+       }
+      }
+    } else {
+      /* Motion events are thrown away when a pop up menu is
+        active. */
+    }
+    return 0;
+
+  case WM_GETMINMAXINFO:
+    /* this voodoo is brought to you by Win32 (again).  It allows the
+       window to be bigger than the screen, and smaller than 100x100
+       (although it doesn't seem to help the y minimum). */
+    minmax = (LPMINMAXINFO)lParam;
+    minmax->ptMaxSize.x = __glutScreenWidth;
+    minmax->ptMaxSize.y = __glutScreenHeight;
+    minmax->ptMinTrackSize.x = 0;
+    minmax->ptMinTrackSize.y = 0;
+    minmax->ptMaxTrackSize.x = __glutScreenWidth +
+      GetSystemMetrics(SM_CXSIZE) * 2;
+    minmax->ptMaxTrackSize.y = __glutScreenHeight +
+      GetSystemMetrics(SM_CXSIZE) * 2 + GetSystemMetrics(SM_CYCAPTION);
+    return 0;
+
+  case WM_SIZE:
+    window = __glutGetWindow(hwnd);
+    if (window) {
+      width = LOWORD(lParam);
+      height = HIWORD(lParam);
+      if (width != window->width || height != window->height) {
+#if 0  /* Win32 GLUT does not support overlays for now. */
+       if (window->overlay) {
+         XResizeWindow(__glutDisplay, window->overlay->win, width, height);
+       }
+#endif
+       window->width = width;
+       window->height = height;
+       __glutSetWindow(window);
+       /* Do not execute OpenGL out of sequence with respect
+          to the SetWindowPos request! */
+       GdiFlush();
+       window->reshape(width, height);
+       window->forceReshape = FALSE;
+       /* A reshape should be considered like posting a
+          repair request. */
+       __glutPostRedisplay(window, GLUT_REPAIR_WORK);
+      }
+    }
+    return 0;
+
+  case WM_SETCURSOR:
+    /* If the cursor is not in the client area, then we want to send
+       this message to the default window procedure ('cause its
+       probably in the border or title, and we don't handle that
+       cursor.  otherwise, set our cursor.  Win32 makes us set the
+       cursor every time the mouse moves (DUMB!). */
+    if(LOWORD(lParam) != HTCLIENT) {
+      goto defproc;
+    }
+    window = __glutGetWindow(hwnd);
+    if (window) {
+      __glutSetCursor(window);
+    }
+    /* TODO: check out the info in DevStudio on WM_SETCURSOR in the
+       DefaultAction section. */
+    return 1;
+
+  case WM_SETFOCUS:
+    window = __glutGetWindow(hwnd);
+    if (window) {
+      window->entryState = WM_SETFOCUS;
+      if (window->entry) {
+       __glutSetWindow(window);
+       window->entry(GLUT_ENTERED);
+       /* XXX Generation of fake passive notify?  See how much
+          work the X11 code does to support fake passive notify
+          callbacks. */
+      }
+      if (window->joystick && __glutCurrentWindow) {
+        if (__glutCurrentWindow->joyPollInterval > 0) {
+         MMRESULT result;
+
+         /* Because Win32 will only let one window capture the
+            joystick at a time, we must capture it when we get the
+            focus and release it when we lose the focus. */
+         result = joySetCapture(__glutCurrentWindow->win,
+           JOYSTICKID1, 0, TRUE);
+         if (result != JOYERR_NOERROR) {
+           return 0;
+          }
+         (void) joySetThreshold(JOYSTICKID1,
+            __glutCurrentWindow->joyPollInterval);
+        }
+      }
+    }
+    return 0;
+
+  case WM_KILLFOCUS:
+    window = __glutGetWindow(hwnd);
+    if (window) {
+      window->entryState = WM_KILLFOCUS;
+      if (window->entry) {
+       __glutSetWindow(window);
+       window->entry(GLUT_LEFT);
+      }
+      if (window->joystick && __glutCurrentWindow) {
+       if (__glutCurrentWindow->joyPollInterval > 0) {
+         /* Because Win32 will only let one window capture the
+            joystick at a time, we must capture it when we get the
+            focus and release it when we lose the focus. */
+           (void) joyReleaseCapture(JOYSTICKID1);
+        }
+      }
+    }
+    return 0;
+  case WM_ACTIVATE:
+    window = __glutGetWindow(hwnd);
+    /* Make sure we re-select the correct palette if needed. */
+    if (LOWORD(wParam)) {
+      PostMessage(hwnd, WM_PALETTECHANGED, 0, 0);
+    }
+    if (window) {
+      int visState;
+
+      /* HIWORD(wParam) is the minimized flag. */
+      visState = !HIWORD(wParam);
+      updateWindowState(window, visState);
+    }
+    return 0;
+
+  /* Colour Palette Management */
+  case WM_PALETTECHANGED:
+    if (hwnd == (HWND)wParam) {
+      /* Don't respond to the message that we sent! */
+      break;
+    }
+    /* fall through to WM_QUERYNEWPALETTE */
+
+  case WM_QUERYNEWPALETTE:
+    window = __glutGetWindow(hwnd);
+    if (window && window->colormap) {
+      UnrealizeObject(window->colormap->cmap);
+      SelectPalette(window->hdc, window->colormap->cmap, FALSE);
+      RealizePalette(window->hdc);
+      return TRUE;
+    }
+    return FALSE;
+
+  case MM_JOY1MOVE:
+  case MM_JOY1ZMOVE:
+    window = __glutGetWindow(hwnd);
+    if (window->joystick) {
+      JOYINFOEX jix;
+      int x, y, z;
+
+      /* Because WIN32 only supports messages for X, Y, and Z
+         translations, we must poll for the rest */
+      jix.dwSize = sizeof(jix);
+      jix.dwFlags = JOY_RETURNALL;
+      joyGetPosEx(JOYSTICKID1,&jix);
+
+#define SCALE(v)  ((int) ((v - 32767)/32.768))
+
+      /* Convert to integer for scaling. */
+      x = jix.dwXpos;
+      y = jix.dwYpos;
+      z = jix.dwZpos;
+      window->joystick(jix.dwButtons, SCALE(x), SCALE(y), SCALE(z));
+
+      return TRUE;
+    }
+    return FALSE;
+  case MM_JOY1BUTTONDOWN:
+  case MM_JOY1BUTTONUP:
+    window = __glutGetWindow(hwnd);
+    if (window->joystick) {
+      JOYINFOEX jix;
+
+      /* Because WIN32 only supports messages for X, Y, and Z
+         translations, we must poll for the rest */
+      jix.dwSize = sizeof(jix);
+      jix.dwFlags = JOY_RETURNALL;
+      joyGetPosEx(JOYSTICKID1,&jix);
+
+      return TRUE;
+    }
+    return FALSE;
+
+#if 0
+  /* Miscellaneous messages (don't really need to enumerate them,
+     but it's good to know what you're not getting sometimes). */
+  case WM_DISPLAYCHANGE:
+    break;
+  case WM_NCHITTEST:
+    /* This event is generated by every mouse move event. */
+    goto defproc;
+  case WM_NCMOUSEMOVE:
+    goto defproc;
+  case WM_NCACTIVATE:
+    goto defproc;
+  case WM_NCPAINT:
+    goto defproc;
+  case WM_NCCALCSIZE:
+    goto defproc;
+  case WM_NCCREATE:
+    goto defproc;
+  case WM_NCDESTROY:
+    goto defproc;
+  case WM_NCLBUTTONDOWN:
+    goto defproc;
+  case WM_SETTEXT:
+    goto defproc;
+  case WM_GETTEXT:
+    goto defproc;
+  case WM_ACTIVATEAPP:
+    goto defproc;
+  case WM_GETICON:
+    goto defproc;
+  case WM_ERASEBKGND:
+    goto defproc;
+  case WM_WINDOWPOSCHANGING:
+    goto defproc;
+  case WM_WINDOWPOSCHANGED:
+    goto defproc;
+  case WM_MOUSEACTIVATE:
+    goto defproc;
+  case WM_SHOWWINDOW:
+    goto defproc;
+  case WM_MOVING:
+    goto defproc;
+  case WM_MOVE:
+    goto defproc;
+  case WM_KEYUP:
+    goto defproc;
+  case WM_CAPTURECHANGED:
+    goto defproc;
+  case WM_SYSCOMMAND:
+    goto defproc;
+  case WM_ENTERSIZEMOVE:
+    goto defproc;
+  case WM_ENTERIDLE:
+    goto defproc;
+#endif
+
+  default:
+    goto defproc;
+  }
+
+defproc:
+  return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+#endif
+
+#if defined(__OS2PM__)
+Bool __glutSetWindowText(Window window, char *text)
+{
+  return WinSetWindowText(window, (PCSZ)text);
+
+}
+
+#endif