home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / MesaDLL / os2_winproc.cpp < prev    next >
Text File  |  2002-12-26  |  40KB  |  1,197 lines

  1. /* os2_winproc.c */
  2.  
  3.  
  4. #define INCL_DEV
  5. #include "WarpGL.h"
  6. #include "GL/os2mesa.h"
  7.  
  8.  
  9. #define  _MEERROR_H_
  10. #include <mmioos2.h>                   /* It is from MMPM toolkit           */
  11. #include <dive.h>
  12. #include <fourcc.h>
  13.  
  14.  
  15. #include "os2mesadef.h"
  16. #include "glutint.h"
  17.  
  18.  
  19. #define POKA 0
  20.  
  21. #if POKA
  22.  
  23. extern unsigned __glutMenuButton;
  24. extern GLUTidleCB __glutIdleFunc;
  25. extern GLUTtimer *__glutTimerList;
  26. extern void handleTimeouts(void);
  27. extern GLUTmenuItem *__glutGetUniqueMenuItem(GLUTmenu * menu, int unique);
  28. static HMENU __glutHMenu;
  29.  
  30. #endif
  31.  
  32. extern void _mesa_ResizeBuffersMESA( void );
  33.  
  34.  
  35. MRESULT EXPENTRY GlutWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 );
  36.  
  37. volatile extern HAB   hab;      /* PM anchor block handle         */
  38. volatile extern HPS   hpsCurrent;
  39.  
  40. RECTL     rCtls[52];
  41. ULONG     ulNumRcls;
  42.  
  43. MRESULT EXPENTRY GlutWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  44. {
  45.   HPS   hps = NULLHANDLE; /* presentation space handle */
  46.   GLUTwindow*   window;   /* GLUT window associated with message. */
  47.   GLUTmenu*     menu;     /* GLUT menu associated with message. */
  48.   RECTL rclClient;
  49.   POINTL point;
  50.   int button = -1,rc,key;
  51.  
  52.  
  53. /* Process the message. */
  54.  
  55.    switch( msg )
  56.    {
  57.       case WM_CREATE:
  58.      {
  59.       SIZEL sizl = { 0L, 0L };
  60.       LONG  *alCaps;
  61.       HDC hdc;
  62.  
  63.       /*+-----------------------------------------------------------------+*/
  64.       /*| The client window is being created.  Create the semaphore to    |*/
  65.       /*| control access to the presentation space.  Then create the      |*/
  66.       /*| thread that will draw the lines.                                |*/
  67.       /*+-----------------------------------------------------------------+*/
  68.  //    DosCreateMutexSem( (PSZ)NULL, &hmtxPS, 0UL, FALSE );
  69.  
  70.       hdc = WinOpenWindowDC(hwnd);
  71.  
  72.       /*+-----------------------------------------------------------------+*/
  73.       /*| Create a non-cached presentation space.  We will not release    |*/
  74.       /*| this PS, as we will be Selecting a Palette to this PS and then  |*/
  75.       /*| animating the palette.  Upon releasing a PS the palette is no   |*/
  76.       /*| longer selected for obvious reasons.                            |*/
  77.       /*+-----------------------------------------------------------------+*/
  78.       hpsCurrent = GpiCreatePS( hab,
  79.                   hdc,
  80.                   &sizl,
  81.                   PU_PELS | GPIF_DEFAULT |
  82.                   GPIT_MICRO | GPIA_ASSOC );
  83. //      DevQueryCaps( hdc, lStart, lCount, alCaps );
  84. //      fPaletteCaps = alCaps[CAPS_ADDITIONAL_GRAPHICS] & CAPS_PALETTE_MANAGER;
  85. //      PaletteInit(3);
  86.        /* »ÑpÑó«ñ hpsBuffer ó pѪ¿¼ RGB color table  */
  87.  
  88.         GpiCreateLogColorTable(hpsCurrent,0 ,LCOLF_RGB,0,0,NULL);
  89.         GpiSetPattern(hpsCurrent,PATSYM_SOLID);
  90.         GpiSetPatternSet(hpsCurrent,LCID_DEFAULT);
  91.  
  92.      }
  93.     break;
  94.  
  95.          return 0;
  96.       case WM_CLOSE:
  97.         WinPostMsg( hwnd, WM_QUIT, NULL, NULL );
  98.  
  99.         return 0;
  100.  
  101.       case WM_PAINT:
  102.     window = __glutGetWindow(hwnd);
  103.     if (window)
  104.     {
  105.        PWMC ctx;
  106. //   hps = WinBeginPaint(hwnd,NULLHANDLE,&rclClient);
  107.     hps = WinBeginPaint(hwnd,NULLHANDLE,&rclClient);
  108.        // blit Dive buffer to screen.
  109.  
  110.      {
  111.          SWP    swp;            // Window position
  112.          POINTL pointl;         // Point to offset from Desktop
  113.  
  114.              // Convert the point to offset from desktop lower left.
  115.              pointl.x = 0;
  116.              pointl.y = 0;
  117.              WinMapWindowPoints ( hwnd, HWND_DESKTOP, &pointl, 1 );
  118.  
  119.  
  120. //            ctx = window->ctx;
  121. //            ctx->xDiveScr = pointl.x;
  122. //            ctx->yDiveScr = pointl.y;
  123.       }
  124. //      rc = DiveBlitImage (ctx->hDive,
  125. //                          ctx->ulDiveBufferNumber,
  126. //                      DIVE_BUFFER_SCREEN );
  127. //
  128.  
  129.         if (window->win == hwnd) {
  130.           __glutPostRedisplay(window, GLUT_REPAIR_WORK);
  131.         } else if (window->overlay && window->overlay->win == hwnd) {
  132.          __glutPostRedisplay(window, GLUT_OVERLAY_REPAIR_WORK);
  133.         }
  134.         WinEndPaint(hps);
  135.     } else {
  136.  
  137.         hps = WinBeginPaint(hwnd,NULLHANDLE,&rclClient);
  138.         WinFillRect(hps, &rclClient, CLR_WHITE);
  139.         WinEndPaint(hps);
  140.     }
  141.         break;
  142.  
  143.     case WM_VRNDISABLED:
  144.  
  145. //           pwinData->fDataInProcess = TRUE;
  146. //           DiveSetupBlitter ( pwinData->hDive, 0 );
  147. //           pwinData->fVrnDisabled = TRUE;
  148.         break;
  149.  
  150.     case WM_VRNENABLED:
  151.       {    HRGN      hrgn;      /* Region handle  */
  152.            RGNRECT   rgnCtl;    /* Processing control structure  */
  153. //           RECTL     rCtls[52];
  154. //           ULONG     ulNumRcls;
  155.  
  156. //            pwinData->fDataInProcess = TRUE;
  157.             hps = WinGetPS ( hwnd );
  158.             if ( !hps )
  159.                   break;
  160.             hrgn = GpiCreateRegion ( hps, 0L, NULL );
  161.             if ( hrgn )
  162.             {  /* NOTE: If mp1 is zero, then this was just a move message.
  163.                ** Illustrate the visible region on a WM_VRNENABLE.
  164.                */
  165.                WinQueryVisibleRegion ( hwnd, hrgn );
  166.                rgnCtl.ircStart     = 0;
  167.                rgnCtl.crc          = 50;
  168.                rgnCtl.ulDirection  = 1;
  169.  
  170.                /* Get the all ORed rectangles */
  171.                if ( GpiQueryRegionRects ( hps, hrgn, NULL,
  172.                                           &rgnCtl, rCtls) )
  173.                {
  174.                   ulNumRcls = rgnCtl.crcReturned;
  175.  
  176.                   /* Now find the window position and size, relative to parent.
  177.                   */
  178. //                  WinQueryWindowPos ( pwinData->hwndClient, &pwinData->swp );
  179.  
  180. //                  rcl.xLeft   = 0;
  181. //                  rcl.yBottom = 0;
  182.  
  183.                   /* Convert the point to offset from desktop lower left.
  184.                   */
  185. //                  pointl.x = pwinData->swp.x;
  186. //                  pointl.y = pwinData->swp.y;
  187.  
  188. //                  WinMapWindowPoints ( pwinData->hwndFrame,
  189. //                                       HWND_DESKTOP, &pointl, 1 );
  190.  
  191. //                  pwinData->cxWindowPos = pointl.x;
  192. //                  pwinData->cyWindowPos = pointl.y;
  193.  
  194.                }
  195.                GpiDestroyRegion( hps, hrgn );
  196.             }
  197.             WinReleasePS( hps );
  198.  
  199.       }
  200.         break;
  201.  
  202.   case WM_SIZE:
  203.     window = __glutGetWindow(hwnd);
  204.     if (window)
  205.     {  int width,height;
  206.        width = SHORT1FROMMP(mp2);
  207.       height = SHORT2FROMMP(mp2);
  208.       if (width != window->width || height != window->height) {
  209. #if 0  /* Win32 GLUT does not support overlays for now. */
  210.        if (window->overlay) {
  211.          XResizeWindow(__glutDisplay, window->overlay->win, width, height);
  212.        }
  213. #endif
  214.        window->width = width;
  215.        window->height = height;
  216.        __glutSetWindow(window);
  217.     _mesa_ResizeBuffersMESA();
  218.  
  219.        /* Do not execute OpenGL out of sequence with respect
  220.           to the SetWindowPos request! */
  221.        window->reshape(width, height);
  222.        window->forceReshape = FALSE;
  223.        /* A reshape should be considered like posting a
  224.           repair request. */
  225.        __glutPostRedisplay(window, GLUT_REPAIR_WORK);
  226.       }
  227.     }
  228.     return 0;
  229.  
  230.   case WM_CHAR:
  231.   { USHORT fsflags;
  232.     window = __glutGetWindow(hwnd);
  233.     if (!window) {
  234.       break;
  235.     }
  236.     fsflags = SHORT1FROMMP(mp1);
  237. /* ?? */
  238.     if((fsflags & KC_KEYUP) )  /* ¿ú¡«p¿pπѼ «ΓªáΓ¿Ñ ¬¡«»¬¿, pÑáú¿pπѼ Γ«½∞¬« ¡á ¡áªáΓ¿Ñ  */
  239.             break;
  240. ///////////////////////////////////////////////////
  241.    if(!(fsflags & KC_CHAR) )
  242.    {
  243.         if (!(fsflags & KC_VIRTUALKEY))
  244.                              break;
  245.         key = 0;
  246.          /* Get the virtual key from mp2.       */
  247.          switch (SHORT2FROMMP(mp2))
  248.          {
  249. /* directional keys */
  250.           case VK_LEFT:  key = GLUT_KEY_LEFT;  break;
  251.           case VK_UP:    key = GLUT_KEY_UP;    break;
  252.           case VK_RIGHT: key = GLUT_KEY_RIGHT; break;
  253.           case VK_DOWN:  key = GLUT_KEY_DOWN;  break;
  254.  
  255.           case VK_PAGEUP:  key = GLUT_KEY_PAGE_UP;    break;
  256.           case VK_PAGEDOWN:key = GLUT_KEY_PAGE_DOWN;  break;
  257.           case VK_HOME:    key = GLUT_KEY_HOME;break;
  258.           case VK_END:     key = GLUT_KEY_END; break;
  259.           case VK_INSERT:  key = GLUT_KEY_INSERT;     break;
  260.  
  261. /* function keys */
  262.           case VK_F1 : key = GLUT_KEY_F1;  break;
  263.           case VK_F2 : key = GLUT_KEY_F2; break;
  264.           case VK_F3 : key = GLUT_KEY_F3; break;
  265.           case VK_F4 : key = GLUT_KEY_F4; break;
  266.           case VK_F5 : key = GLUT_KEY_F5; break;
  267.           case VK_F6 : key = GLUT_KEY_F6; break;
  268.           case VK_F7 : key = GLUT_KEY_F7; break;
  269.           case VK_F8 : key = GLUT_KEY_F8; break;
  270.           case VK_F9 : key = GLUT_KEY_F9; break;
  271.           case VK_F10: key = GLUT_KEY_F10;break;
  272.           case VK_F11: key = GLUT_KEY_F11; break;
  273.           case VK_F12: key = GLUT_KEY_F12; break;
  274.           case VK_ESC:   key = -1; break;  /* Character codes */
  275.           case VK_SPACE: key = -1; break;
  276.           case VK_TAB:   key = -1; break;
  277.          }
  278.          if(!key)
  279.          {     break; /* Key Not implemented  */
  280.          }
  281.          if(key > 0)
  282.          {   if (!window->special)  /* ¡Ñ πßΓá¡«ó½Ñ¡« «íαáí«Γτ¿¬á */
  283.                              break;
  284.  
  285.                WinQueryPointerPos(HWND_DESKTOP,&point);
  286.                ScreenToClient(window->win, &point);
  287.                __glutSetWindow(window);
  288.                __glutModifierMask = 0;
  289.                if(WinGetKeyState(HWND_DESKTOP,VK_SHIFT) & 0x8000)   /*  high order bit is on */
  290.                           __glutModifierMask |= ShiftMask;
  291.                if(WinGetKeyState(HWND_DESKTOP,VK_CTRL) & 0x8000)
  292.                           __glutModifierMask |= ControlMask;
  293.                if(WinGetKeyState(HWND_DESKTOP,VK_MENU) & 0x8000)
  294.                           __glutModifierMask |= Mod1Mask;
  295.                window->special(key, point.x, point.y);
  296.                __glutModifierMask = (unsigned int) ~0;
  297.                return 0;
  298.          }
  299.  
  300.    }
  301. /////////////////////////////////////////////////////
  302.     /* If  we are ignoring auto repeated key strokes for the window, bail. */
  303.     if (window->ignoreKeyRepeat && (CHAR3FROMMP(mp1)) )
  304.                                                    break;
  305.      if(!((unsigned char)SHORT1FROMMP(mp2))  )  /* ¿ú¡«p¿pπѼ ¡Ñß¿¼ó«½∞¡δÑ ¬«ñδ */
  306.                                             break;
  307.     if (window->keyboard) {
  308.        WinQueryPointerPos(HWND_DESKTOP,&point);
  309.  
  310.       ScreenToClient(window->win, &point);
  311.       __glutSetWindow(window);
  312.       __glutModifierMask = 0;
  313.       if(WinGetKeyState(HWND_DESKTOP,VK_SHIFT) & 0x8000)   /*  high order bit is on */
  314.            __glutModifierMask |= ShiftMask;
  315.       if(WinGetKeyState(HWND_DESKTOP,VK_CTRL) & 0x8000)
  316.            __glutModifierMask |= ControlMask;
  317.       if(WinGetKeyState(HWND_DESKTOP,VK_MENU) & 0x8000)
  318.            __glutModifierMask |= Mod1Mask;
  319.       window->keyboard((unsigned char)SHORT1FROMMP(mp2), point.x, point.y);
  320.       __glutModifierMask = (unsigned int) ~0;
  321.     }
  322.     return 0;
  323.   } /* endof case WM_CHAR: */
  324. ////////////////////////////////////////////////
  325.   case WM_BUTTON1DOWN:
  326.     button = GLUT_LEFT_BUTTON;
  327.   case WM_BUTTON3DOWN:
  328.     if (button < 0)
  329.       button = GLUT_MIDDLE_BUTTON;
  330.   case WM_BUTTON2DOWN:
  331.     if (button < 0)
  332.       button = GLUT_RIGHT_BUTTON;
  333.     {  POINTS psh;
  334.        psh = *((POINTS *)&mp1);
  335.        point.x = psh.x;
  336.        point.y = psh.y;
  337.     }
  338.     /* finish the menu if we get a button down message (user must have
  339.        cancelled the menu). */
  340.     if (__glutMappedMenu) {
  341.       /* TODO: take this out once the menu on middle mouse stuff works
  342.         properly. */
  343.       if (button == GLUT_MIDDLE_BUTTON)
  344.        return 0;
  345.  /* get current mouse pointer position */
  346. //      WinQueryPointerPos(HWND_DESKTOP,&point);
  347.  /* map from desktop to client window */
  348. //      WinMapWindowPoints(HWND_DESKTOP, hwnd, &point, 1);
  349.       __glutItemSelected = NULL;
  350.       __glutFinishMenu(hwnd, point.x, point.y);
  351.       return 0;
  352.     }
  353.     window = __glutGetWindow(hwnd);
  354.     if (window) {
  355.       menu = __glutGetMenuByNum(window->menu[button]);
  356.       if (menu) {
  357. //todo
  358. //   __glutMenuButton = button == GLUT_RIGHT_BUTTON ? TPM_RIGHTBUTTON :
  359. //                           button == GLUT_LEFT_BUTTON  ? TPM_LEFTBUTTON :
  360. //                           0x0001;
  361. //   __glutStartMenu(menu, window, point.x, point.y, x, y);
  362.       } else if (window->mouse) {
  363.  
  364.         __glutSetWindow(window);
  365.    __glutModifierMask = 0;
  366. //todo
  367. //   if (GetKeyState(VK_SHIFT) < 0)  /* < 0 = high order bit is on. */
  368. //     __glutModifierMask |= ShiftMask;
  369. //   if (GetKeyState(VK_CONTROL) < 0)
  370. //     __glutModifierMask |= ControlMask;
  371. //   if (GetKeyState(VK_MENU) < 0)
  372. //     __glutModifierMask |= Mod1Mask;
  373.    window->mouse(button, GLUT_DOWN, point.x, point.y);
  374.    __glutModifierMask = (unsigned int)~0;
  375.       } else {
  376.    /* Stray mouse events.  Ignore. */
  377.       }
  378.     }
  379.     return 0;
  380.  
  381.     break;
  382. /********************************************/
  383.   case WM_BUTTON1UP:
  384.     button = GLUT_LEFT_BUTTON;
  385.   case WM_BUTTON3UP:
  386.     if (button < 0)
  387.       button = GLUT_MIDDLE_BUTTON;
  388.   case WM_BUTTON2UP:
  389.     if (button < 0)
  390.       button = GLUT_RIGHT_BUTTON;
  391.     /* Bail out if we're processing a menu. */
  392.     if (__glutMappedMenu) {
  393.       WinQueryPointerPos(HWND_DESKTOP,&point);
  394.       WinMapWindowPoints(HWND_DESKTOP, hwnd, &point, 1);
  395.       /* if we're getting the middle button up signal, then something
  396.         on the menu was selected. */
  397.       if (button == GLUT_MIDDLE_BUTTON) {
  398.        return 0;
  399.        /* For some reason, the code below always returns -1 even
  400.           though the point IS IN THE ITEM!  Therefore, just bail out if
  401.           we get a middle mouse up.  The user must select using the
  402.           left mouse button.  Stupid Win32. */
  403. #if 0
  404.        int item = MenuItemFromPoint(hwnd, __glutHMenu, point);
  405.        if (item != -1)
  406.          __glutItemSelected = (GLUTmenuItem*)GetMenuItemID(__glutHMenu, item);
  407.        else
  408.          __glutItemSelected = NULL;
  409.        __glutFinishMenu(hwnd, point.x, point.y);
  410. #endif
  411.       } else {
  412.        __glutItemSelected = NULL;
  413.        __glutFinishMenu(hwnd, point.x, point.y);
  414.       }
  415.       return 0;
  416.     }
  417.  
  418.  
  419.  
  420.     break;
  421. //////////////////////////////////////////////////
  422.   case WM_COMMAND:
  423.     window = __glutGetWindow(hwnd);
  424.     if (window)
  425.     {   if (window->wm_command)
  426.             window->wm_command(hwnd,mp1,mp2);
  427.     }
  428.     break;
  429.  
  430.       default:
  431.  /* For all other messages, let the default window procedure process them. */
  432.        return ( WinDefWindowProc( hwnd, msg, mp1, mp2 ) );
  433.  
  434.    } //endof switch( msg )
  435.    return NULL;
  436. }
  437.  
  438. void APIENTRY glutCommandFunc(GLUTcommandCB Func)
  439. {
  440. extern GLUTwindow *__glutCurrentWindow;
  441.     __glutCurrentWindow->wm_command = Func;
  442. }
  443.  
  444.  
  445.  
  446. #if POKA
  447.  
  448. void
  449. updateWindowState(GLUTwindow *window, int visState)
  450. {
  451.   GLUTwindow* child;
  452.  
  453.   /* XXX shownState and visState are the same in Win32. */
  454.   window->shownState = visState;
  455.   if (visState != window->visState) {
  456.     if (window->windowStatus) {
  457.       window->visState = visState;
  458.       __glutSetWindow(window);
  459.       window->windowStatus(visState);
  460.     }
  461.   }
  462.   /* Since Win32 only sends an activate for the toplevel window,
  463.      update the visibility for all the child windows. */
  464.   child = window->children;
  465.   while (child) {
  466.     updateWindowState(child, visState);
  467.     child = child->siblings;
  468.   }
  469. }
  470.  
  471. LONG WINAPI
  472. __glutWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  473. {
  474.   POINT         point;                 /* Point structure. */
  475.   PAINTSTRUCT   ps;                    /* Paint structure. */
  476.   LPMINMAXINFO  minmax;                        /* Minimum/maximum info structure. */
  477.   GLUTwindow*   window;                        /* GLUT window associated with message. */
  478.   GLUTmenu*     menu;                  /* GLUT menu associated with message. */
  479.   int x, y, width, height, key;
  480.   int button = -1;
  481.  
  482.   switch(msg) {
  483.   case WM_CREATE:
  484.     return 0;
  485.   case WM_CLOSE:
  486.     PostQuitMessage(0);
  487.     return 0;
  488. #if 0
  489.   case WM_DESTROY:
  490.     /* XXX NVidia's NT OpenGL can have problems closing down
  491.        its OpenGL internal data structures if we just allow
  492.        the process to terminate without unbinding and deleting
  493.        the windows context.  Apparently, DirectDraw unloads
  494.        before OPENGL32.DLL in the close down sequence, but
  495.        NVidia's NT OpenGL needs DirectDraw to close down its
  496.        data structures. */
  497.     window = __glutGetWindow(hwnd);
  498.     if (window) {
  499.       if (window->ctx) {
  500.         wglMakeCurrent(NULL, NULL);
  501.         wglDeleteContext(window->ctx);
  502.       }
  503.     }
  504.     return 0;
  505. #endif
  506.  
  507.   case WM_SYSKEYUP:
  508.   case WM_KEYUP:
  509.     window = __glutGetWindow(hwnd);
  510.     if (!window) {
  511.       break;
  512.     }
  513.     /* Win32 is dumb and sends these messages only to the parent
  514.        window.  Therefore, find out if we're in a child window and
  515.        call the child windows keyboard callback if we are. */
  516.     if (window->parent) {
  517.       GetCursorPos(&point);
  518.       ScreenToClient(hwnd, &point);
  519.       hwnd = ChildWindowFromPoint(hwnd, point);
  520.       window = __glutGetWindow(hwnd);
  521.     }
  522.     if (window->specialUp || window->keyboardUp) {
  523.       GetCursorPos(&point);
  524.       ScreenToClient(window->win, &point);
  525.       __glutSetWindow(window);
  526.       __glutModifierMask = 0;
  527.       if (GetKeyState(VK_SHIFT) < 0)  /* < 0 = high order bit is on */
  528.        __glutModifierMask |= ShiftMask;
  529.       if (GetKeyState(VK_SHIFT) < 0)  /* < 0 = high order bit is on */
  530.        __glutModifierMask |= ControlMask;
  531.       if (GetKeyState(VK_MENU) < 0)
  532.        __glutModifierMask |= Mod1Mask;
  533.       switch (wParam) {
  534.       /* *INDENT-OFF* */
  535.       case VK_F1:     key = GLUT_KEY_F1; break;
  536.       case VK_F2:     key = GLUT_KEY_F2; break;
  537.       case VK_F3:     key = GLUT_KEY_F3; break;
  538.       case VK_F4:     key = GLUT_KEY_F4; break;
  539.       case VK_F5:     key = GLUT_KEY_F5; break;
  540.       case VK_F6:     key = GLUT_KEY_F6; break;
  541.       case VK_F7:     key = GLUT_KEY_F7; break;
  542.       case VK_F8:     key = GLUT_KEY_F8; break;
  543.       case VK_F9:     key = GLUT_KEY_F9; break;
  544.       case VK_F10:    key = GLUT_KEY_F10; break;
  545.       case VK_F11:    key = GLUT_KEY_F11; break;
  546.       case VK_F12:    key = GLUT_KEY_F12; break;
  547.       case VK_LEFT:   key = GLUT_KEY_LEFT; break;
  548.       case VK_UP:     key = GLUT_KEY_UP; break;
  549.       case VK_RIGHT:  key = GLUT_KEY_RIGHT; break;
  550.       case VK_DOWN:   key = GLUT_KEY_DOWN; break;
  551.       case VK_PRIOR:  key = GLUT_KEY_PAGE_UP; break;
  552.       case VK_NEXT:   key = GLUT_KEY_PAGE_DOWN; break;
  553.       case VK_HOME:   key = GLUT_KEY_HOME; break;
  554.       case VK_END:    key = GLUT_KEY_END; break;
  555.       case VK_INSERT: key = GLUT_KEY_INSERT; break;
  556.       case VK_DELETE:
  557.         /* Delete is an ASCII character. */
  558.        if (window->keyboardUp) {
  559.          window->keyboardUp((unsigned char) 127, point.x, point.y);
  560.        }
  561.        return 0;
  562.       /* *INDENT-ON* */
  563.       default:
  564.        if (window->keyboardUp) {
  565.          key = MapVirtualKey(wParam, 2);  /* Map to ASCII. */
  566.          if (isascii(key) && (key != 0)) {
  567.  
  568.            /* XXX Attempt to determine modified ASCII character
  569.               is quite incomplete.  Digits, symbols, CapsLock,
  570.               Ctrl, and numeric keypad are all ignored.  Fix this. */
  571.  
  572.            if (!(__glutModifierMask & ShiftMask))
  573.              key = tolower(key);
  574.            window->keyboardUp((unsigned char) key, point.x, point.y);
  575.           }
  576.         }
  577.        __glutModifierMask = (unsigned int) ~0;
  578.        return 0;
  579.       }
  580.       if (window->specialUp) {
  581.         window->specialUp(key, point.x, point.y);
  582.       }
  583.       __glutModifierMask = (unsigned int) ~0;
  584.     }
  585.     return 0;
  586.  
  587.   case WM_SYSCHAR:
  588.   case WM_CHAR:
  589.     window = __glutGetWindow(hwnd);
  590.     if (!window) {
  591.       break;
  592.     }
  593.  
  594.     /* Bit 30 of lParam is set if key already held down.  If
  595.        we are ignoring auto repeated key strokes for the window, bail. */
  596.     if (window->ignoreKeyRepeat && (lParam & (1 << 30)) ) {
  597.       break;
  598.     }
  599.  
  600.     /* Win32 is dumb and sends these messages only to the parent
  601.        window.  Therefore, find out if we're in a child window and
  602.        call the child windows keyboard callback if we are. */
  603.     if (window->parent) {
  604.        GetCursorPos(&point);
  605.        ScreenToClient(hwnd, &point);
  606.        hwnd = ChildWindowFromPoint(hwnd, point);
  607.        window = __glutGetWindow(hwnd);
  608.     }
  609.     if (window->keyboard) {
  610.       GetCursorPos(&point);
  611.       ScreenToClient(window->win, &point);
  612.       __glutSetWindow(window);
  613.       __glutModifierMask = 0;
  614.       if (GetKeyState(VK_SHIFT) < 0)   /* < 0 = high order bit is on */
  615.        __glutModifierMask |= ShiftMask;
  616.       if (GetKeyState(VK_CONTROL) < 0)
  617.        __glutModifierMask |= ControlMask;
  618.       if (GetKeyState(VK_MENU) < 0)
  619.        __glutModifierMask |= Mod1Mask;
  620.       window->keyboard((unsigned char)wParam, point.x, point.y);
  621.       __glutModifierMask = (unsigned int) ~0;
  622.     }
  623.     return 0;
  624.  
  625.   case WM_SYSKEYDOWN:
  626.   case WM_KEYDOWN:
  627.     window = __glutGetWindow(hwnd);
  628.     if (!window) {
  629.       break;
  630.     }
  631.  
  632.     /* Bit 30 of lParam is set if key already held down.  If
  633.        we are ignoring auto repeated key strokes for the window, bail. */
  634.     if (window->ignoreKeyRepeat && (lParam & (1 << 30)) ) {
  635.       break;
  636.     }
  637.  
  638.     /* Win32 is dumb and sends these messages only to the parent
  639.        window.  Therefore, find out if we're in a child window and
  640.        call the child windows keyboard callback if we are. */
  641.     if (window->parent) {
  642.        GetCursorPos(&point);
  643.        ScreenToClient(hwnd, &point);
  644.        hwnd = ChildWindowFromPoint(hwnd, point);
  645.        window = __glutGetWindow(hwnd);
  646.     }
  647.     if (window->special) {
  648.       switch (wParam) {
  649.        /* *INDENT-OFF* */
  650.        /* function keys */
  651.        case VK_F1:     key = GLUT_KEY_F1; break;
  652.        case VK_F2:     key = GLUT_KEY_F2; break;
  653.        case VK_F3:     key = GLUT_KEY_F3; break;
  654.        case VK_F4:     key = GLUT_KEY_F4; break;
  655.        case VK_F5:     key = GLUT_KEY_F5; break;
  656.        case VK_F6:     key = GLUT_KEY_F6; break;
  657.        case VK_F7:     key = GLUT_KEY_F7; break;
  658.        case VK_F8:     key = GLUT_KEY_F8; break;
  659.        case VK_F9:     key = GLUT_KEY_F9; break;
  660.        case VK_F10:    key = GLUT_KEY_F10; break;
  661.        case VK_F11:    key = GLUT_KEY_F11; break;
  662.        case VK_F12:    key = GLUT_KEY_F12; break;
  663.        /* directional keys */
  664.        case VK_LEFT:   key = GLUT_KEY_LEFT; break;
  665.        case VK_UP:     key = GLUT_KEY_UP; break;
  666.        case VK_RIGHT:  key = GLUT_KEY_RIGHT; break;
  667.        case VK_DOWN:   key = GLUT_KEY_DOWN; break;
  668.        /* *INDENT-ON* */
  669.  
  670.        case VK_PRIOR:
  671.          /* VK_PRIOR is Win32's Page Up */
  672.          key = GLUT_KEY_PAGE_UP;
  673.          break;
  674.        case VK_NEXT:
  675.          /* VK_NEXT is Win32's Page Down */
  676.          key = GLUT_KEY_PAGE_DOWN;
  677.          break;
  678.        case VK_HOME:
  679.          key = GLUT_KEY_HOME;
  680.          break;
  681.        case VK_END:
  682.          key = GLUT_KEY_END;
  683.          break;
  684.        case VK_INSERT:
  685.          key = GLUT_KEY_INSERT;
  686.          break;
  687.         case VK_DELETE:
  688.          goto handleDelete;
  689.        default:
  690.          goto defproc;
  691.       }
  692.       GetCursorPos(&point);
  693.       ScreenToClient(window->win, &point);
  694.       __glutSetWindow(window);
  695.       __glutModifierMask = 0;
  696.       if (GetKeyState(VK_SHIFT) < 0)   /* < 0 = high order bit is on */
  697.        __glutModifierMask |= ShiftMask;
  698.       if (GetKeyState(VK_CONTROL) < 0)
  699.        __glutModifierMask |= ControlMask;
  700.       if (GetKeyState(VK_MENU) < 0)
  701.        __glutModifierMask |= Mod1Mask;
  702.       window->special(key, point.x, point.y);
  703.       __glutModifierMask = (unsigned int) ~0;
  704.     } else if (window->keyboard) {
  705.       /* Specially handle any keys that match ASCII values but
  706.          do not generate Windows WM_SYSCHAR or WM_CHAR messages. */
  707.       switch (wParam) {
  708.       case VK_DELETE:
  709.       handleDelete:
  710.         /* Delete is an ASCII character. */
  711.         GetCursorPos(&point);
  712.         ScreenToClient(window->win, &point);
  713.         __glutSetWindow(window);
  714.         __glutModifierMask = 0;
  715.         if (GetKeyState(VK_SHIFT) < 0) /* < 0 = high order bit is on */
  716.           __glutModifierMask |= ShiftMask;
  717.         if (GetKeyState(VK_CONTROL) < 0)
  718.           __glutModifierMask |= ControlMask;
  719.         if (GetKeyState(VK_MENU) < 0)
  720.           __glutModifierMask |= Mod1Mask;
  721.        window->keyboard((unsigned char) 127, point.x, point.y);
  722.         __glutModifierMask = (unsigned int) ~0;
  723.        return 0;
  724.       default:
  725.         /* Let the following WM_SYSCHAR or WM_CHAR message generate
  726.           the keyboard callback. */
  727.         break;
  728.       }
  729.     }
  730.     return 0;
  731.  
  732.   case WM_LBUTTONDOWN:
  733.     button = GLUT_LEFT_BUTTON;
  734.   case WM_MBUTTONDOWN:
  735.     if (button < 0)
  736.       button = GLUT_MIDDLE_BUTTON;
  737.   case WM_RBUTTONDOWN:
  738.     if (button < 0)
  739.       button = GLUT_RIGHT_BUTTON;
  740.  
  741.     /* finish the menu if we get a button down message (user must have
  742.        cancelled the menu). */
  743.     if (__glutMappedMenu) {
  744.       /* TODO: take this out once the menu on middle mouse stuff works
  745.         properly. */
  746.       if (button == GLUT_MIDDLE_BUTTON)
  747.        return 0;
  748.       GetCursorPos(&point);
  749.       ScreenToClient(hwnd, &point);
  750.       __glutItemSelected = NULL;
  751.       __glutFinishMenu(hwnd, point.x, point.y);
  752.       return 0;
  753.     }
  754.  
  755.     /* set the capture so we can get mouse events outside the window */
  756.     SetCapture(hwnd);
  757.  
  758.     /* Win32 doesn't return the same numbers as X does when the mouse
  759.        goes beyond the upper or left side of the window.  roll the
  760.        Win32's 0..2^16 pointer co-ord range to 0 +/- 2^15. */
  761.     x = LOWORD(lParam);
  762.     y = HIWORD(lParam);
  763.     if(x & 1 << 15) x -= (1 << 16);
  764.     if(y & 1 << 15) y -= (1 << 16);
  765.  
  766.     window = __glutGetWindow(hwnd);
  767.     if (window) {
  768.       menu = __glutGetMenuByNum(window->menu[button]);
  769.       if (menu) {
  770.        point.x = LOWORD(lParam); point.y = HIWORD(lParam);
  771.        ClientToScreen(window->win, &point);
  772.        __glutMenuButton = button == GLUT_RIGHT_BUTTON ? TPM_RIGHTBUTTON :
  773.                            button == GLUT_LEFT_BUTTON  ? TPM_LEFTBUTTON :
  774.                            0x0001;
  775.        __glutStartMenu(menu, window, point.x, point.y, x, y);
  776.       } else if (window->mouse) {
  777.  
  778.         __glutSetWindow(window);
  779.        __glutModifierMask = 0;
  780.        if (GetKeyState(VK_SHIFT) < 0)  /* < 0 = high order bit is on. */
  781.          __glutModifierMask |= ShiftMask;
  782.        if (GetKeyState(VK_CONTROL) < 0)
  783.          __glutModifierMask |= ControlMask;
  784.        if (GetKeyState(VK_MENU) < 0)
  785.          __glutModifierMask |= Mod1Mask;
  786.        window->mouse(button, GLUT_DOWN, x, y);
  787.        __glutModifierMask = (unsigned int)~0;
  788.       } else {
  789.        /* Stray mouse events.  Ignore. */
  790.       }
  791.     }
  792.     return 0;
  793.  
  794.   case WM_LBUTTONUP:
  795.     button = GLUT_LEFT_BUTTON;
  796.   case WM_MBUTTONUP:
  797.     if (button < 0)
  798.       button = GLUT_MIDDLE_BUTTON;
  799.   case WM_RBUTTONUP:
  800.     if (button < 0)
  801.       button = GLUT_RIGHT_BUTTON;
  802.  
  803.     /* Bail out if we're processing a menu. */
  804.     if (__glutMappedMenu) {
  805.       GetCursorPos(&point);
  806.       ScreenToClient(hwnd, &point);
  807.       /* if we're getting the middle button up signal, then something
  808.         on the menu was selected. */
  809.       if (button == GLUT_MIDDLE_BUTTON) {
  810.        return 0;
  811.        /* For some reason, the code below always returns -1 even
  812.           though the point IS IN THE ITEM!  Therefore, just bail out if
  813.           we get a middle mouse up.  The user must select using the
  814.           left mouse button.  Stupid Win32. */
  815. #if 0
  816.        int item = MenuItemFromPoint(hwnd, __glutHMenu, point);
  817.        if (item != -1)
  818.          __glutItemSelected = (GLUTmenuItem*)GetMenuItemID(__glutHMenu, item);
  819.        else
  820.          __glutItemSelected = NULL;
  821.        __glutFinishMenu(hwnd, point.x, point.y);
  822. #endif
  823.       } else {
  824.        __glutItemSelected = NULL;
  825.        __glutFinishMenu(hwnd, point.x, point.y);
  826.       }
  827.       return 0;
  828.     }
  829.  
  830.     /* Release the mouse capture. */
  831.     ReleaseCapture();
  832.  
  833.     window = __glutGetWindow(hwnd);
  834.     if (window && window->mouse) {
  835.       /* Win32 doesn't return the same numbers as X does when the
  836.         mouse goes beyond the upper or left side of the window.  roll
  837.         the Win32's 0..2^16 pointer co-ord range to 0 +/- 2^15. */
  838.       x = LOWORD(lParam);
  839.       y = HIWORD(lParam);
  840.       if(x & 1 << 15) x -= (1 << 16);
  841.       if(y & 1 << 15) y -= (1 << 16);
  842.  
  843.       __glutSetWindow(window);
  844.       __glutModifierMask = 0;
  845.       if (GetKeyState(VK_SHIFT) < 0)   /* < 0 = high order bit is on */
  846.        __glutModifierMask |= ShiftMask;
  847.       if (GetKeyState(VK_CONTROL) < 0)
  848.        __glutModifierMask |= ControlMask;
  849.       if (GetKeyState(VK_MENU) < 0)
  850.        __glutModifierMask |= Mod1Mask;
  851.       window->mouse(button, GLUT_UP, x, y);
  852.       __glutModifierMask = (unsigned int)~0;
  853.     } else {
  854.       /* Window might have been destroyed and all the
  855.         events for the window may not yet be received. */
  856.     }
  857.     return 0;
  858.  
  859.   case WM_ENTERMENULOOP:
  860.     /* KLUDGE: create a timer that fires every 100 ms when we start a
  861.        menu so that we can still process the idle & timer events (that
  862.        way, the timers will fire during a menu pick and so will the
  863.        idle func. */
  864.     SetTimer(hwnd, 1, 1, NULL);
  865.     return 0;
  866.  
  867.   case WM_TIMER:
  868. #if 0
  869.     /* If the timer id is 2, then this is the timer that is set up in
  870.        the main glut message processing loop, and we don't want to do
  871.        anything but acknowledge that we got it.  It is used to prevent
  872.        CPU spiking when an idle function is installed. */
  873.     if (wParam == 2)
  874.       return 0;
  875. #endif
  876.  
  877.     /* only worry about the idle function and the timeouts, since
  878.        these are the only events we expect to process during
  879.        processing of a menu. */
  880.     /* we no longer process the idle functions (as outlined in the
  881.        README), since drawing can't be done until the menu has
  882.        finished...it's pretty lame when the animation goes on, but
  883.        doesn't update, so you get this weird jerkiness. */
  884. #if 0
  885.      if (__glutIdleFunc)
  886.        __glutIdleFunc();
  887. #endif
  888.     if (__glutTimerList)
  889.       handleTimeouts();
  890.     return 0;
  891.  
  892.   case WM_EXITMENULOOP:
  893.     /* nuke the above created timer...we don't need it anymore, since
  894.        the menu is gone now. */
  895.     KillTimer(hwnd, 1);
  896.     return 0;
  897.  
  898.   case WM_MENUSELECT:
  899.     if (lParam != 0)
  900.       __glutHMenu = (HMENU)lParam;
  901.     return 0;
  902.  
  903.   case WM_COMMAND:
  904.     if (__glutMappedMenu) {
  905.       if (GetSubMenu(__glutHMenu, LOWORD(wParam)))
  906.        __glutItemSelected = NULL;
  907.       else
  908.        __glutItemSelected =
  909.          __glutGetUniqueMenuItem(__glutMappedMenu, LOWORD(wParam));
  910.       GetCursorPos(&point);
  911.       ScreenToClient(hwnd, &point);
  912.       __glutFinishMenu(hwnd, point.x, point.y);
  913.     }
  914.     return 0;
  915.  
  916.   case WM_MOUSEMOVE:
  917.     if (!__glutMappedMenu) {
  918.       window = __glutGetWindow(hwnd);
  919.       if (window) {
  920.           /* If motion function registered _and_ buttons held *
  921.              down, call motion function...  */
  922.        x = LOWORD(lParam);
  923.        y = HIWORD(lParam);
  924.  
  925.        /* Win32 doesn't return the same numbers as X does when the
  926.           mouse goes beyond the upper or left side of the window.
  927.           roll the Win32's 0..2^16 pointer co-ord range to 0..+/-2^15. */
  928.        if(x & 1 << 15) x -= (1 << 16);
  929.        if(y & 1 << 15) y -= (1 << 16);
  930.  
  931.        if (window->motion && wParam &
  932.             (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) {
  933.          __glutSetWindow(window);
  934.          window->motion(x, y);
  935.        }
  936.        /* If passive motion function registered _and_
  937.           buttons not held down, call passive motion
  938.           function...  */
  939.        else if (window->passive &&
  940.                 ((wParam &
  941.                   (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) ==
  942.                  0)) {
  943.          __glutSetWindow(window);
  944.          window->passive(x, y);
  945.        }
  946.       }
  947.     } else {
  948.       /* Motion events are thrown away when a pop up menu is
  949.         active. */
  950.     }
  951.     return 0;
  952.  
  953.   case WM_GETMINMAXINFO:
  954.     /* this voodoo is brought to you by Win32 (again).  It allows the
  955.        window to be bigger than the screen, and smaller than 100x100
  956.        (although it doesn't seem to help the y minimum). */
  957.     minmax = (LPMINMAXINFO)lParam;
  958.     minmax->ptMaxSize.x = __glutScreenWidth;
  959.     minmax->ptMaxSize.y = __glutScreenHeight;
  960.     minmax->ptMinTrackSize.x = 0;
  961.     minmax->ptMinTrackSize.y = 0;
  962.     minmax->ptMaxTrackSize.x = __glutScreenWidth +
  963.       GetSystemMetrics(SM_CXSIZE) * 2;
  964.     minmax->ptMaxTrackSize.y = __glutScreenHeight +
  965.       GetSystemMetrics(SM_CXSIZE) * 2 + GetSystemMetrics(SM_CYCAPTION);
  966.     return 0;
  967.  
  968.   case WM_SIZE:
  969.     window = __glutGetWindow(hwnd);
  970.     if (window) {
  971.       width = LOWORD(lParam);
  972.       height = HIWORD(lParam);
  973.       if (width != window->width || height != window->height) {
  974. #if 0  /* Win32 GLUT does not support overlays for now. */
  975.        if (window->overlay) {
  976.          XResizeWindow(__glutDisplay, window->overlay->win, width, height);
  977.        }
  978. #endif
  979.        window->width = width;
  980.        window->height = height;
  981.        __glutSetWindow(window);
  982.        /* Do not execute OpenGL out of sequence with respect
  983.           to the SetWindowPos request! */
  984.        GdiFlush();
  985.        window->reshape(width, height);
  986.        window->forceReshape = FALSE;
  987.        /* A reshape should be considered like posting a
  988.           repair request. */
  989.        __glutPostRedisplay(window, GLUT_REPAIR_WORK);
  990.       }
  991.     }
  992.     return 0;
  993.  
  994.   case WM_SETCURSOR:
  995.     /* If the cursor is not in the client area, then we want to send
  996.        this message to the default window procedure ('cause its
  997.        probably in the border or title, and we don't handle that
  998.        cursor.  otherwise, set our cursor.  Win32 makes us set the
  999.        cursor every time the mouse moves (DUMB!). */
  1000.     if(LOWORD(lParam) != HTCLIENT) {
  1001.       goto defproc;
  1002.     }
  1003.     window = __glutGetWindow(hwnd);
  1004.     if (window) {
  1005.       __glutSetCursor(window);
  1006.     }
  1007.     /* TODO: check out the info in DevStudio on WM_SETCURSOR in the
  1008.        DefaultAction section. */
  1009.     return 1;
  1010.  
  1011.   case WM_SETFOCUS:
  1012.     window = __glutGetWindow(hwnd);
  1013.     if (window) {
  1014.       window->entryState = WM_SETFOCUS;
  1015.       if (window->entry) {
  1016.        __glutSetWindow(window);
  1017.        window->entry(GLUT_ENTERED);
  1018.        /* XXX Generation of fake passive notify?  See how much
  1019.           work the X11 code does to support fake passive notify
  1020.           callbacks. */
  1021.       }
  1022.       if (window->joystick && __glutCurrentWindow) {
  1023.         if (__glutCurrentWindow->joyPollInterval > 0) {
  1024.          MMRESULT result;
  1025.  
  1026.          /* Because Win32 will only let one window capture the
  1027.             joystick at a time, we must capture it when we get the
  1028.             focus and release it when we lose the focus. */
  1029.          result = joySetCapture(__glutCurrentWindow->win,
  1030.            JOYSTICKID1, 0, TRUE);
  1031.          if (result != JOYERR_NOERROR) {
  1032.            return 0;
  1033.           }
  1034.          (void) joySetThreshold(JOYSTICKID1,
  1035.             __glutCurrentWindow->joyPollInterval);
  1036.         }
  1037.       }
  1038.     }
  1039.     return 0;
  1040.  
  1041.   case WM_KILLFOCUS:
  1042.     window = __glutGetWindow(hwnd);
  1043.     if (window) {
  1044.       window->entryState = WM_KILLFOCUS;
  1045.       if (window->entry) {
  1046.        __glutSetWindow(window);
  1047.        window->entry(GLUT_LEFT);
  1048.       }
  1049.       if (window->joystick && __glutCurrentWindow) {
  1050.        if (__glutCurrentWindow->joyPollInterval > 0) {
  1051.          /* Because Win32 will only let one window capture the
  1052.             joystick at a time, we must capture it when we get the
  1053.             focus and release it when we lose the focus. */
  1054.            (void) joyReleaseCapture(JOYSTICKID1);
  1055.         }
  1056.       }
  1057.     }
  1058.     return 0;
  1059.   case WM_ACTIVATE:
  1060.     window = __glutGetWindow(hwnd);
  1061.     /* Make sure we re-select the correct palette if needed. */
  1062.     if (LOWORD(wParam)) {
  1063.       PostMessage(hwnd, WM_PALETTECHANGED, 0, 0);
  1064.     }
  1065.     if (window) {
  1066.       int visState;
  1067.  
  1068.       /* HIWORD(wParam) is the minimized flag. */
  1069.       visState = !HIWORD(wParam);
  1070.       updateWindowState(window, visState);
  1071.     }
  1072.     return 0;
  1073.  
  1074.   /* Colour Palette Management */
  1075.   case WM_PALETTECHANGED:
  1076.     if (hwnd == (HWND)wParam) {
  1077.       /* Don't respond to the message that we sent! */
  1078.       break;
  1079.     }
  1080.     /* fall through to WM_QUERYNEWPALETTE */
  1081.  
  1082.   case WM_QUERYNEWPALETTE:
  1083.     window = __glutGetWindow(hwnd);
  1084.     if (window && window->colormap) {
  1085.       UnrealizeObject(window->colormap->cmap);
  1086.       SelectPalette(window->hdc, window->colormap->cmap, FALSE);
  1087.       RealizePalette(window->hdc);
  1088.       return TRUE;
  1089.     }
  1090.     return FALSE;
  1091.  
  1092.   case MM_JOY1MOVE:
  1093.   case MM_JOY1ZMOVE:
  1094.     window = __glutGetWindow(hwnd);
  1095.     if (window->joystick) {
  1096.       JOYINFOEX jix;
  1097.       int x, y, z;
  1098.  
  1099.       /* Because WIN32 only supports messages for X, Y, and Z
  1100.          translations, we must poll for the rest */
  1101.       jix.dwSize = sizeof(jix);
  1102.       jix.dwFlags = JOY_RETURNALL;
  1103.       joyGetPosEx(JOYSTICKID1,&jix);
  1104.  
  1105. #define SCALE(v)  ((int) ((v - 32767)/32.768))
  1106.  
  1107.       /* Convert to integer for scaling. */
  1108.       x = jix.dwXpos;
  1109.       y = jix.dwYpos;
  1110.       z = jix.dwZpos;
  1111.       window->joystick(jix.dwButtons, SCALE(x), SCALE(y), SCALE(z));
  1112.  
  1113.       return TRUE;
  1114.     }
  1115.     return FALSE;
  1116.   case MM_JOY1BUTTONDOWN:
  1117.   case MM_JOY1BUTTONUP:
  1118.     window = __glutGetWindow(hwnd);
  1119.     if (window->joystick) {
  1120.       JOYINFOEX jix;
  1121.  
  1122.       /* Because WIN32 only supports messages for X, Y, and Z
  1123.          translations, we must poll for the rest */
  1124.       jix.dwSize = sizeof(jix);
  1125.       jix.dwFlags = JOY_RETURNALL;
  1126.       joyGetPosEx(JOYSTICKID1,&jix);
  1127.  
  1128.       return TRUE;
  1129.     }
  1130.     return FALSE;
  1131.  
  1132. #if 0
  1133.   /* Miscellaneous messages (don't really need to enumerate them,
  1134.      but it's good to know what you're not getting sometimes). */
  1135.   case WM_DISPLAYCHANGE:
  1136.     break;
  1137.   case WM_NCHITTEST:
  1138.     /* This event is generated by every mouse move event. */
  1139.     goto defproc;
  1140.   case WM_NCMOUSEMOVE:
  1141.     goto defproc;
  1142.   case WM_NCACTIVATE:
  1143.     goto defproc;
  1144.   case WM_NCPAINT:
  1145.     goto defproc;
  1146.   case WM_NCCALCSIZE:
  1147.     goto defproc;
  1148.   case WM_NCCREATE:
  1149.     goto defproc;
  1150.   case WM_NCDESTROY:
  1151.     goto defproc;
  1152.   case WM_NCLBUTTONDOWN:
  1153.     goto defproc;
  1154.   case WM_SETTEXT:
  1155.     goto defproc;
  1156.   case WM_GETTEXT:
  1157.     goto defproc;
  1158.   case WM_ACTIVATEAPP:
  1159.     goto defproc;
  1160.   case WM_GETICON:
  1161.     goto defproc;
  1162.   case WM_ERASEBKGND:
  1163.     goto defproc;
  1164.   case WM_WINDOWPOSCHANGING:
  1165.     goto defproc;
  1166.   case WM_WINDOWPOSCHANGED:
  1167.     goto defproc;
  1168.   case WM_MOUSEACTIVATE:
  1169.     goto defproc;
  1170.   case WM_SHOWWINDOW:
  1171.     goto defproc;
  1172.   case WM_MOVING:
  1173.     goto defproc;
  1174.   case WM_MOVE:
  1175.     goto defproc;
  1176.   case WM_KEYUP:
  1177.     goto defproc;
  1178.   case WM_CAPTURECHANGED:
  1179.     goto defproc;
  1180.   case WM_SYSCOMMAND:
  1181.     goto defproc;
  1182.   case WM_ENTERSIZEMOVE:
  1183.     goto defproc;
  1184.   case WM_ENTERIDLE:
  1185.     goto defproc;
  1186. #endif
  1187.  
  1188.   default:
  1189.     goto defproc;
  1190.   }
  1191.  
  1192. defproc:
  1193.   return DefWindowProc(hwnd, msg, wParam, lParam);
  1194. }
  1195.  
  1196. #endif
  1197.