home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / MesaDLL / glut_win.cpp < prev    next >
C/C++ Source or Header  |  2002-12-14  |  36KB  |  1,212 lines

  1.  
  2. /* Copyright (c) Mark J. Kilgard, 1994, 1997.  */
  3.  
  4. /* This program is freely distributable without licensing fees
  5.    and is provided without guarantee or warrantee expressed or
  6.    implied. This program is -not- in the public domain. */
  7.  
  8. #ifdef __VMS
  9. #include <GL/vms_x_fix.h>
  10. #endif
  11.  
  12. #include <stdlib.h>
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <assert.h>
  16. #if defined(__OS2__)
  17. #define POKA 0
  18.   #include "WarpGL.h"
  19.   #include "glutos2.h"
  20.   #include "glutint.h"
  21.  
  22.   #include "gl\os2mesa.h"
  23.  
  24.             #include "GL_TEST.h"
  25.    int evglSetPixelFormat(int iPixelFormat);
  26.  
  27. #elif !defined(_WIN32)
  28.  
  29. #include <X11/Xlib.h>
  30. #include <X11/Xatom.h>
  31. #endif
  32.  
  33. #include "glutint.h"
  34.  
  35. GLUTwindow *__glutCurrentWindow = NULL;
  36. GLUTwindow **__glutWindowList = NULL;
  37. int __glutWindowListSize = 0;
  38. #if !defined(_WIN32) && !defined(__OS2__)
  39. GLUTstale *__glutStaleWindowList = NULL;
  40. #endif
  41. GLUTwindow *__glutMenuWindow = NULL;
  42.  
  43. void (*__glutFreeOverlayFunc) (GLUToverlay *);
  44. XVisualInfo *(*__glutDetermineVisualFromString) (char *string, Bool * treatAsSingle,
  45.   Criterion * requiredCriteria, int nRequired, int requiredMask, void** fbc) = NULL;
  46.  
  47. static Criterion requiredWindowCriteria[] =
  48. {
  49.   {LEVEL, EQ, 0},
  50.   {TRANSPARENT, EQ, 0}
  51. };
  52. static int numRequiredWindowCriteria = sizeof(requiredWindowCriteria) / sizeof(Criterion);
  53. static int requiredWindowCriteriaMask = (1 << LEVEL) | (1 << TRANSPARENT);
  54.  
  55. static void
  56. cleanWindowWorkList(GLUTwindow * window)
  57. {
  58.   GLUTwindow **pEntry = &__glutWindowWorkList;
  59.   GLUTwindow *entry = __glutWindowWorkList;
  60.  
  61.   /* Tranverse singly-linked window work list look for the
  62.      window. */
  63.   while (entry) {
  64.     if (entry == window) {
  65.       /* Found it; delete it. */
  66.       *pEntry = entry->prevWorkWin;
  67.       return;
  68.     } else {
  69.       pEntry = &entry->prevWorkWin;
  70.       entry = *pEntry;
  71.     }
  72.   }
  73. }
  74.  
  75. #if !defined(_WIN32)  && !defined(__OS2__)
  76.  
  77. static void
  78. cleanStaleWindowList(GLUTwindow * window)
  79. {
  80.   GLUTstale **pEntry = &__glutStaleWindowList;
  81.   GLUTstale *entry = __glutStaleWindowList;
  82.  
  83.   /* Tranverse singly-linked stale window list look for the
  84.      window ID. */
  85.   while (entry) {
  86.     if (entry->window == window) {
  87.       /* Found it; delete it. */
  88.       *pEntry = entry->next;
  89.       free(entry);
  90.       return;
  91.     } else {
  92.       pEntry = &entry->next;
  93.       entry = *pEntry;
  94.     }
  95.   }
  96. }
  97.  
  98. #endif
  99.  
  100. static GLUTwindow *__glutWindowCache = NULL;
  101.  
  102. GLUTwindow *
  103. __glutGetWindow(Window win)
  104. {
  105.   int i;
  106.  
  107.   /* Does win belong to the last window ID looked up? */
  108.   if (__glutWindowCache && (win == __glutWindowCache->win ||
  109.       (__glutWindowCache->overlay && win ==
  110.         __glutWindowCache->overlay->win))) {
  111.     return
  112.       __glutWindowCache;
  113.   }
  114.   /* Otherwise scan the window list looking for the window ID. */
  115.   for (i = 0; i < __glutWindowListSize; i++) {
  116.     if (__glutWindowList[i]) {
  117.       if (win == __glutWindowList[i]->win) {
  118.         __glutWindowCache = __glutWindowList[i];
  119.         return __glutWindowCache;
  120.       }
  121.       if (__glutWindowList[i]->overlay) {
  122.         if (win == __glutWindowList[i]->overlay->win) {
  123.           __glutWindowCache = __glutWindowList[i];
  124.           return __glutWindowCache;
  125.         }
  126.       }
  127.     }
  128.   }
  129. #if !defined(_WIN32)  && !defined(__OS2__)
  130.   {
  131.     GLUTstale *entry;
  132.  
  133.     /* Scan through destroyed overlay window IDs for which no
  134.        DestroyNotify has yet been received. */
  135.     for (entry = __glutStaleWindowList; entry; entry = entry->next) {
  136.       if (entry->win == win)
  137.         return entry->window;
  138.     }
  139.   }
  140. #endif
  141.   return NULL;
  142. }
  143.  
  144. /* CENTRY */
  145. int GLUTAPIENTRY
  146. glutGetWindow(void)
  147. {
  148.   if (__glutCurrentWindow) {
  149.     return __glutCurrentWindow->num + 1;
  150.   } else {
  151.     return 0;
  152.   }
  153. }
  154. /* ENDCENTRY */
  155.  
  156. void
  157. __glutSetWindow(GLUTwindow * window)
  158. {
  159.   /* It is tempting to try to short-circuit the call to
  160.      glXMakeCurrent if we "know" we are going to make current
  161.      to a window we are already current to.  In fact, this
  162.      assumption breaks when GLUT is expected to integrated with
  163.      other OpenGL windowing APIs that also make current to
  164.      OpenGL contexts.  Since glXMakeCurrent short-circuits the
  165.      "already bound" case, GLUT avoids the temptation to do so
  166.      too. */
  167.   __glutCurrentWindow = window;
  168.  
  169.   MAKE_CURRENT_LAYER(__glutCurrentWindow);
  170.  
  171. #if !defined(_WIN32)  && !defined(__OS2__)
  172.   /* We should be careful to force a finish between each
  173.      iteration through the GLUT main loop if indirect OpenGL
  174.      contexts are in use; indirect contexts tend to have  much
  175.      longer latency because lots of OpenGL extension requests
  176.      can queue up in the X protocol stream.  We accomplish this
  177.      by posting GLUT_FINISH_WORK to be done. */
  178.   if (!__glutCurrentWindow->isDirect)
  179.     __glutPutOnWorkList(__glutCurrentWindow, GLUT_FINISH_WORK);
  180. #endif
  181.  
  182.   /* If debugging is enabled, we'll want to check this window
  183.      for any OpenGL errors every iteration through the GLUT
  184.      main loop.  To accomplish this, we post the
  185.      GLUT_DEBUG_WORK to be done on this window. */
  186.   if (__glutDebug) {
  187.     __glutPutOnWorkList(__glutCurrentWindow, GLUT_DEBUG_WORK);
  188.   }
  189. }
  190.  
  191. /* CENTRY */
  192. void GLUTAPIENTRY
  193. glutSetWindow(int win)
  194. {
  195.   GLUTwindow *window;
  196.  
  197.   if (win < 1 || win > __glutWindowListSize) {
  198.     __glutWarning("glutSetWindow attempted on bogus window.");
  199.     return;
  200.   }
  201.   window = __glutWindowList[win - 1];
  202.   if (!window) {
  203.     __glutWarning("glutSetWindow attempted on bogus window.");
  204.     return;
  205.   }
  206.   __glutSetWindow(window);
  207. }
  208. /* ENDCENTRY */
  209.  
  210. static int
  211. getUnusedWindowSlot(void)
  212. {
  213.   int i;
  214.  
  215.   /* Look for allocated, unused slot. */
  216.   for (i = 0; i < __glutWindowListSize; i++) {
  217.     if (!__glutWindowList[i]) {
  218.       return i;
  219.     }
  220.   }
  221.   /* Allocate a new slot. */
  222.   __glutWindowListSize++;
  223.   if (__glutWindowList) {
  224.     __glutWindowList = (GLUTwindow **)
  225.       realloc(__glutWindowList,
  226.       __glutWindowListSize * sizeof(GLUTwindow *));
  227.   } else {
  228.     /* XXX Some realloc's do not correctly perform a malloc
  229.        when asked to perform a realloc on a NULL pointer,
  230.        though the ANSI C library spec requires this. */
  231.     __glutWindowList = (GLUTwindow **)
  232.       malloc(sizeof(GLUTwindow *));
  233.   }
  234.   if (!__glutWindowList)
  235.     __glutFatalError("out of memory.");
  236.   __glutWindowList[__glutWindowListSize - 1] = NULL;
  237.   return __glutWindowListSize - 1;
  238. }
  239.  
  240. static XVisualInfo *
  241. getVisualInfoCI(unsigned int mode)
  242. {
  243. #if POKA
  244.   static int bufSizeList[] =
  245.   {16, 12, 8, 4, 2, 1, 0};
  246.   XVisualInfo *vi;
  247.   int list[32];
  248.   int i, n = 0;
  249.  
  250.   /* Should not be looking at display mode mask if
  251.      __glutDisplayString is non-NULL. */
  252.   assert(!__glutDisplayString);
  253.  
  254.   list[n++] = GLX_BUFFER_SIZE;
  255.   list[n++] = 1;
  256.   if (GLUT_WIND_IS_DOUBLE(mode)) {
  257.     list[n++] = GLX_DOUBLEBUFFER;
  258.   }
  259.   if (GLUT_WIND_IS_STEREO(mode)) {
  260.     list[n++] = GLX_STEREO;
  261.   }
  262.   if (GLUT_WIND_HAS_DEPTH(mode)) {
  263.     list[n++] = GLX_DEPTH_SIZE;
  264.     list[n++] = 1;
  265.   }
  266.   if (GLUT_WIND_HAS_STENCIL(mode)) {
  267.     list[n++] = GLX_STENCIL_SIZE;
  268.     list[n++] = 1;
  269.   }
  270.   list[n] = (int) None; /* terminate list */
  271.  
  272.   /* glXChooseVisual specify GLX_BUFFER_SIZE prefers the
  273.      "smallest index buffer of at least the specified size".
  274.      This would be reasonable if GLUT allowed the user to
  275.      specify the required buffe size, but GLUT's display mode
  276.      is too simplistic (easy to use?). GLUT should try to find
  277.      the "largest".  So start with a large buffer size and
  278.      shrink until we find a matching one that exists. */
  279.  
  280.   for (i = 0; bufSizeList[i]; i++) {
  281.     /* XXX Assumes list[1] is where GLX_BUFFER_SIZE parameter
  282.        is. */
  283.     list[1] = bufSizeList[i];
  284.     vi = glXChooseVisual(__glutDisplay,
  285.       __glutScreen, list);
  286.     if (vi)
  287.       return vi;
  288.   }
  289.   return NULL;
  290. #else
  291.     return
  292.          glXChooseVisual(mode);
  293.  
  294. #endif
  295. }
  296.  
  297. static XVisualInfo *
  298. getVisualInfoRGB(unsigned int mode)
  299. {
  300. #if POKA
  301.   int list[32];
  302.   int n = 0;
  303.  
  304.   /* Should not be looking at display mode mask if
  305.      __glutDisplayString is non-NULL. */
  306.   assert(!__glutDisplayString);
  307.  
  308.   /* XXX Would a caching mechanism to minize the calls to
  309.      glXChooseVisual? You'd have to reference count
  310.      XVisualInfo* pointers.  Would also have to properly
  311.      interact with glutInitDisplayString. */
  312.  
  313.   list[n++] = GLX_RGBA;
  314.   list[n++] = GLX_RED_SIZE;
  315.   list[n++] = 1;
  316.   list[n++] = GLX_GREEN_SIZE;
  317.   list[n++] = 1;
  318.   list[n++] = GLX_BLUE_SIZE;
  319.   list[n++] = 1;
  320.   if (GLUT_WIND_HAS_ALPHA(mode)) {
  321.     list[n++] = GLX_ALPHA_SIZE;
  322.     list[n++] = 1;
  323.   }
  324.   if (GLUT_WIND_IS_DOUBLE(mode)) {
  325.     list[n++] = GLX_DOUBLEBUFFER;
  326.   }
  327.   if (GLUT_WIND_IS_STEREO(mode)) {
  328.     list[n++] = GLX_STEREO;
  329.   }
  330.   if (GLUT_WIND_HAS_DEPTH(mode)) {
  331.     list[n++] = GLX_DEPTH_SIZE;
  332.     list[n++] = 1;
  333.   }
  334.   if (GLUT_WIND_HAS_STENCIL(mode)) {
  335.     list[n++] = GLX_STENCIL_SIZE;
  336.     list[n++] = 1;
  337.   }
  338.   if (GLUT_WIND_HAS_ACCUM(mode)) {
  339.     list[n++] = GLX_ACCUM_RED_SIZE;
  340.     list[n++] = 1;
  341.     list[n++] = GLX_ACCUM_GREEN_SIZE;
  342.     list[n++] = 1;
  343.     list[n++] = GLX_ACCUM_BLUE_SIZE;
  344.     list[n++] = 1;
  345.     if (GLUT_WIND_HAS_ALPHA(mode)) {
  346.       list[n++] = GLX_ACCUM_ALPHA_SIZE;
  347.       list[n++] = 1;
  348.     }
  349.   }
  350. #if defined(GLX_VERSION_1_1) && (defined(GLX_SGIS_multisample) || defined(GLX_ARB_multisample))
  351.   if (GLUT_WIND_IS_MULTISAMPLE(mode)) {
  352.     if (!__glutIsSupportedByGLX("GLX_SGIS_multisample") &&
  353.         !__glutIsSupportedByGLX("GLX_ARB_multisample"))
  354.       return NULL;
  355. #if defined(GLX_ARB_multisample)
  356.     list[n++] = GLX_SAMPLES_ARB;
  357. #elif defined(GLX_SGIS_multisample)
  358.     list[n++] = GLX_SAMPLES_SGIS;
  359. #endif
  360.     /* XXX Is 4 a reasonable minimum acceptable number of
  361.        samples? */
  362.     list[n++] = 4;
  363.   }
  364. #endif
  365.   list[n] = (int) None; /* terminate list */
  366.  
  367.   return glXChooseVisual(__glutDisplay,
  368.     __glutScreen, list);
  369. #else  /* POKA */
  370.  
  371.     return
  372.          glXChooseVisual(mode);
  373.  
  374. #endif
  375. }
  376.  
  377. XVisualInfo *
  378. __glutGetVisualInfo(unsigned int mode)
  379. {
  380.   /* XXX GLUT_LUMINANCE not implemented for GLUT 3.0. */
  381.   if (GLUT_WIND_IS_LUMINANCE(mode))
  382.     return NULL;
  383.  
  384.   if (GLUT_WIND_IS_RGB(mode))
  385.     return getVisualInfoRGB(mode);
  386.   else
  387.     return getVisualInfoCI(mode);
  388. }
  389.  
  390. XVisualInfo *
  391. __glutDetermineVisual(
  392.   unsigned int displayMode,
  393.   Bool * treatAsSingle,
  394.   XVisualInfo * (getVisualInfo) (unsigned int))
  395. {
  396.   XVisualInfo *vis;
  397.  
  398.   /* Should not be looking at display mode mask if
  399.      __glutDisplayString is non-NULL. */
  400.   assert(!__glutDisplayString);
  401.  
  402.   *treatAsSingle = GLUT_WIND_IS_SINGLE(displayMode);
  403.   vis = getVisualInfo(displayMode);
  404.   if (!vis) {
  405.     /* Fallback cases when can't get exactly what was asked
  406.        for... */
  407.     if (GLUT_WIND_IS_SINGLE(displayMode)) {
  408.       /* If we can't find a single buffered visual, try looking
  409.          for a double buffered visual.  We can treat a double
  410.          buffered visual as a single buffer visual by changing
  411.          the draw buffer to GL_FRONT and treating any swap
  412.          buffers as no-ops. */
  413.       displayMode |= GLUT_DOUBLE;
  414.       vis = getVisualInfo(displayMode);
  415.       *treatAsSingle = True;
  416.     }
  417.     if (!vis && GLUT_WIND_IS_MULTISAMPLE(displayMode)) {
  418.       /* If we can't seem to get multisampling (ie, not Reality
  419.          Engine class graphics!), go without multisampling.  It
  420.          is up to the application to query how many multisamples
  421.          were allocated (0 equals no multisampling) if the
  422.          application is going to use multisampling for more than
  423.          just antialiasing. */
  424.       displayMode &= ~GLUT_MULTISAMPLE;
  425.       vis = getVisualInfo(displayMode);
  426.     }
  427.   }
  428.   return vis;
  429. }
  430.  
  431. static void GLUTCALLBACK
  432. __glutDefaultDisplay(void)
  433. {
  434.   /* XXX Remove the warning after GLUT 3.0. */
  435.   __glutWarning("The following is a new check for GLUT 3.0; update your code.");
  436.   __glutFatalError(
  437.     "redisplay needed for window %d, but no display callback.",
  438.     __glutCurrentWindow->num + 1);
  439. }
  440.  
  441. void GLUTCALLBACK
  442. __glutDefaultReshape(int width, int height)
  443. {
  444.   GLUToverlay *overlay;
  445.  
  446.   /* Adjust the viewport of the window (and overlay if one
  447.      exists). */
  448.   MAKE_CURRENT_WINDOW(__glutCurrentWindow);
  449.   glViewport(0, 0, (GLsizei) width, (GLsizei) height);
  450.   overlay = __glutCurrentWindow->overlay;
  451.   if (overlay) {
  452.     MAKE_CURRENT_OVERLAY(overlay);
  453.     glViewport(0, 0, (GLsizei) width, (GLsizei) height);
  454.   }
  455.   /* Make sure we are current to the current layer (application
  456.      should be able to count on the current layer not changing
  457.      unless the application explicitly calls glutUseLayer). */
  458.   MAKE_CURRENT_LAYER(__glutCurrentWindow);
  459. }
  460.  
  461. XVisualInfo *
  462. __glutDetermineWindowVisual(Bool * treatAsSingle, Bool * visAlloced, void **fbc)
  463. {
  464.   if (__glutDisplayString) {
  465.  
  466.     /* __glutDisplayString should be NULL except if
  467.        glutInitDisplayString has been called to register a
  468.        different display string.  Calling glutInitDisplayString
  469.        means using a string instead of an integer mask determine
  470.        the visual to use. Using the function pointer variable
  471.        __glutDetermineVisualFromString below avoids linking in
  472.        the code for implementing glutInitDisplayString (ie,
  473.        glut_dstr.o) unless glutInitDisplayString gets called by
  474.        the application. */
  475.  
  476.     assert(__glutDetermineVisualFromString);
  477.     *visAlloced = False;
  478.     *fbc = NULL;
  479.     return __glutDetermineVisualFromString(__glutDisplayString, treatAsSingle,
  480.       requiredWindowCriteria, numRequiredWindowCriteria, requiredWindowCriteriaMask, fbc);
  481.   } else {
  482.     *visAlloced = True;
  483.     *fbc = NULL;
  484.     return __glutDetermineVisual(__glutDisplayMode,
  485.       treatAsSingle, __glutGetVisualInfo);
  486.   }
  487. }
  488.  
  489. /* ARGSUSED5 */  /* Only Win32 uses gameMode parameter. */
  490. GLUTwindow *
  491. __glutCreateWindow(GLUTwindow * parent,
  492.   int x, int y, int width, int height, int gameMode)
  493. {
  494.   GLUTwindow *window;
  495.   XSetWindowAttributes wa;
  496.   unsigned long attribMask;
  497.   int winnum;
  498.   int i;
  499. #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
  500.   GLXFBConfigSGIX fbc;
  501. #else
  502.   void *fbc;
  503. #endif
  504.  
  505. #if defined(__OS2__)
  506.  {
  507.     extern HAB   hab;      /* PM anchor block handle         */
  508.     CLASSINFO classinfo;
  509.  
  510.     if(!WinQueryClassInfo(hab,"GLUT", &classinfo) )
  511.                                __glutOpenOS2Connection(NULL);
  512.   }
  513. #elif defined(_WIN32)
  514.   WNDCLASS wc;
  515.   int style;
  516.  
  517.   if (!GetClassInfo(GetModuleHandle(NULL), "GLUT", &wc)) {
  518.     __glutOpenWin32Connection(NULL);
  519.   }
  520. #else
  521.   if (!__glutDisplay) {
  522.     __glutOpenXConnection(NULL);
  523.   }
  524. #endif
  525.  
  526. #ifndef __OS2__
  527.   if (__glutGameModeWindow) {
  528.     __glutFatalError("cannot create windows in game mode.");
  529.   }
  530. #endif
  531.  
  532.   winnum = getUnusedWindowSlot();
  533.   window = (GLUTwindow *) malloc(sizeof(GLUTwindow));
  534.   if (!window) {
  535.     __glutFatalError("out of memory.");
  536.   }
  537.   window->num = winnum;
  538.  
  539. #if !defined(_WIN32)  && !defined(__OS2__)
  540.   window->vis = __glutDetermineWindowVisual(&window->treatAsSingle,
  541.     &window->visAlloced, (void**) &fbc);
  542.   if (!window->vis) {
  543.     __glutFatalError(
  544.       "visual with necessary capabilities not found.");
  545.   }
  546.   __glutSetupColormap(window->vis, &window->colormap, &window->cmap);
  547. #endif
  548.   window->eventMask = StructureNotifyMask | ExposureMask;
  549.  
  550.   attribMask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask;
  551.   wa.background_pixmap = None;
  552.   wa.border_pixel = 0;
  553.   wa.colormap = window->cmap;
  554.   wa.event_mask = window->eventMask;
  555.   if (parent) {
  556.     if (parent->eventMask & GLUT_HACK_STOP_PROPAGATE_MASK)
  557.       wa.event_mask |= GLUT_HACK_STOP_PROPAGATE_MASK;
  558.     attribMask |= CWDontPropagate;
  559.     wa.do_not_propagate_mask = parent->eventMask & GLUT_DONT_PROPAGATE_FILTER_MASK;
  560.   } else {
  561.     wa.do_not_propagate_mask = 0;
  562.   }
  563.  
  564.   /* Stash width and height before Win32's __glutAdjustCoords
  565.      possibly overwrites the values. */
  566.   window->width = width;
  567.   window->height = height;
  568.   window->forceReshape = True;
  569.   window->ignoreKeyRepeat = False;
  570.  
  571. #if defined(__OS2__)
  572.  
  573.  {  ULONG flStyle=0;
  574.     int ii;
  575.     ERRORID  erridErrorCode;/* last error id code */
  576.     extern HAB   hab;      /* PM anchor block handle         */
  577.  
  578.   if (parent) {
  579.     flStyle = WS_CLIPCHILDREN;
  580.   } else {
  581.     if (gameMode) {
  582.       /* Game mode window should be a WS_POPUP window to
  583.          ensure that the taskbar is hidden by it.  A standard
  584.          WS_OVERLAPPEDWINDOW does not hide the task bar. */
  585.       flStyle = /* WS_POPUP |*/ WS_MAXIMIZED;
  586.       flStyle = FCF_STANDARD |  WS_MAXIMIZED;
  587.     } else {
  588.       /* A standard toplevel window with borders and such. */
  589.       flStyle = FCF_STANDARD;
  590.   ;
  591. //      flStyle = WS_OVERLAPPEDWINDOW;
  592.     }
  593.   }
  594. {
  595.  HWND  hwnd;                           /* Cursor display window     */
  596.  ULONG ListBoxId;                      /* Window id                 */
  597.                                        /* (supplied by application) */
  598.  
  599.  
  600.  HWND hwndClient;        /* handle to the client                 */
  601.  HWND hwndFrame;         /* handle to the frame                  */
  602.  PFNWP GenericWndProc;
  603.  FRAMECDATA  fcd;
  604.  RECTL  rect;     /* Boundary rectangle                   */
  605.  
  606. extern HPS   hpsCurrent;
  607.  
  608.  
  609. /************************************************/
  610.  
  611. // flCreate = (FCF_STANDARD) & ~FCF_TASKLIST;
  612.  
  613.         window->frame = WinCreateStdWindow(HWND_DESKTOP,
  614.            0,       /* WS_VISIBLE frame-window style            */
  615.            &flStyle,         /* window style                  */
  616.            "GLUT",          /* class name                    */
  617.            "GLUT",/* window title                  */
  618.             0L,                  /* default client style          */
  619.             NULLHANDLE,          /* resource in executable file   */
  620.             ID_WINDOW,           /* resource id                   */
  621.             &hwndClient);        /* receives client window handle */
  622.  
  623.  erridErrorCode = WinGetLastError(hab);
  624.        window->win = hwndClient;
  625.   /***********************************************************************/
  626.   /*  Set up the frame control data for the frame window.                */
  627.   /***********************************************************************/
  628. //     fcd.cb = sizeof(FRAMECDATA);
  629. //     fcd.flCreateFlags = FCF_TITLEBAR |
  630. //                         FCF_SYSMENU |
  631. //                         FCF_SIZEBORDER |
  632. //                         //FCF_SHELLPOSITION |
  633. //                         FCF_MINMAX |  FCF_TASKLIST;
  634. //     fcd.hmodResources = NULLHANDLE;
  635. //     fcd.idResources = 0;
  636. //
  637. //
  638. // flStyle = WS_VISIBLE;                 /* Create window visible     */
  639. // /* Create button window */
  640. // hwnd = WinCreateWindow(HWND_DESKTOP,  /* Parent window             */
  641. //                        "GLUT",        /* Class name                */
  642. //                        "List Box",    /* Window text               */
  643. //                        flStyle,       /* Window style              */
  644. //                        0, 0,          /* Position (x,y)            */
  645. //                        200, 100,      /* Size (width,height)       */
  646. //                        NULLHANDLE,    /* Owner window              */
  647. //                        HWND_TOP,      /* Sibling window            */
  648. //                        0,             /* Window id                 */
  649. //                        &fcd,          /* Control data              */
  650. //                        NULL);         /* Pres parameters           */
  651. //
  652. //
  653. // erridErrorCode = WinGetLastError(hab);
  654. //
  655. //  fcd.flCreateFlags |= FCF_SYSMENU;
  656. //
  657. // window->win = WinCreateWindow(HWND_DESKTOP, "GLUT", "GLUT",
  658. //           flStyle,x, y, width, height,  parent ? parent->win : NULLHANDLE,
  659. //          HWND_TOP, window->num, &fcd, NULL);
  660.  
  661. /* converts a client window's boundaries into  an equivalent frame rectangle */
  662.  rect.xLeft = x;
  663.  rect.xRight = x+width;
  664.  rect.yBottom = y;
  665.  rect.yTop = y + height;
  666.  
  667.  /* calculate equivalent frame boundary from boundary data */
  668.   WinCalcFrameRect(window->frame, &rect, FALSE);
  669.  
  670.   WinSetWindowPos(window->frame,
  671.                   HWND_TOP,rect.xLeft,rect.yBottom,
  672.                   rect.xRight-rect.xLeft, rect.yTop-rect.yBottom,
  673.       SWP_ACTIVATE | SWP_MOVE | SWP_SIZE | SWP_SHOW|SWP_ZORDER); /* flags*/
  674.  
  675.   window->hdc = WinOpenWindowDC(window->win);
  676.   window->hpsBuffer = hpsCurrent;
  677.  
  678.   /* Must set the XHDC for fake glXChooseVisual & fake
  679.      glXCreateContext & fake XAllocColorCells. */
  680.   XHDC = window->hdc;
  681.   XHWND = window->win;
  682.   window->vis = __glutDetermineWindowVisual(&window->treatAsSingle,
  683.     &window->visAlloced, &fbc);
  684.     if (!window->vis)
  685.     {   __glutFatalError(
  686.         "pixel format with necessary capabilities not found.");
  687.     }
  688.     { int rc;
  689.       rc = wglChoosePixelFormat(window->hdc, window->vis),
  690.  
  691. //     evglSetPixelFormat(2); /* int iPixelFormat 1 - doublebuffer/2 - single buffer ??*/
  692.       wglSetPixelFormat(window->hdc,rc,window->vis);
  693.     }
  694.    __glutSetupColormap(window->vis, &window->colormap, &window->cmap);
  695.  
  696.   /* Make sure subwindows get a windowStatus callback. */
  697.   if (parent)
  698.        WinPostMsg(parent->win, WM_ACTIVATE, 0, 0);
  699.  
  700.  
  701.   }
  702. }
  703.  
  704. #elif defined(_WIN32)
  705.  
  706.   __glutAdjustCoords(parent ? parent->win : NULL,
  707.     &x, &y, &width, &height);
  708.   if (parent) {
  709.     style = WS_CHILD;
  710.   } else {
  711.     if (gameMode) {
  712.       /* Game mode window should be a WS_POPUP window to
  713.          ensure that the taskbar is hidden by it.  A standard
  714.          WS_OVERLAPPEDWINDOW does not hide the task bar. */
  715.       style = WS_POPUP | WS_MAXIMIZE;
  716.     } else {
  717.       /* A standard toplevel window with borders and such. */
  718.       style = WS_OVERLAPPEDWINDOW;
  719.     }
  720.   }
  721.   window->win = CreateWindow("GLUT", "GLUT",
  722.     WS_CLIPSIBLINGS | WS_CLIPCHILDREN | style,
  723.     x, y, width, height, parent ? parent->win : __glutRoot,
  724.     NULL, GetModuleHandle(NULL), 0);
  725.   window->hdc = GetDC(window->win);
  726.   /* Must set the XHDC for fake glXChooseVisual & fake
  727.      glXCreateContext & fake XAllocColorCells. */
  728.   XHDC = window->hdc;
  729.   window->vis = __glutDetermineWindowVisual(&window->treatAsSingle,
  730.     &window->visAlloced, &fbc);
  731.   if (!window->vis) {
  732.     __glutFatalError(
  733.       "pixel format with necessary capabilities not found.");
  734.   }
  735.   if (!SetPixelFormat(window->hdc,
  736.       ChoosePixelFormat(window->hdc, window->vis),
  737.       window->vis)) {
  738.     __glutFatalError("SetPixelFormat failed during window create.");
  739.   }
  740.   __glutSetupColormap(window->vis, &window->colormap, &window->cmap);
  741.   /* Make sure subwindows get a windowStatus callback. */
  742.   if (parent) {
  743.     PostMessage(parent->win, WM_ACTIVATE, 0, 0);
  744.   }
  745.   window->renderDc = window->hdc;
  746. #else
  747.   window->win = XCreateWindow(__glutDisplay,
  748.     parent == NULL ? __glutRoot : parent->win,
  749.     x, y, width, height, 0,
  750.     window->vis->depth, InputOutput, window->vis->visual,
  751.     attribMask, &wa);
  752. #endif
  753.   window->renderWin = window->win;
  754. #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
  755.   if (fbc) {
  756.     window->ctx = __glut_glXCreateContextWithConfigSGIX(__glutDisplay, fbc,
  757.       GLX_RGBA_TYPE_SGIX, None, __glutTryDirect);
  758.   } else
  759. #endif
  760.   {
  761.     window->ctx = glXCreateContext(__glutDisplay, window->vis,
  762.       None, __glutTryDirect);
  763.   }
  764.   if (!window->ctx) {
  765.     __glutFatalError(
  766.       "failed to create OpenGL rendering context.");
  767.   }
  768.   window->renderCtx = window->ctx;
  769. #if !defined(_WIN32) && !defined(__OS2__)
  770.   window->isDirect = glXIsDirect(__glutDisplay, window->ctx);
  771.   if (__glutForceDirect) {
  772.     if (!window->isDirect)
  773.       __glutFatalError("direct rendering not possible.");
  774.   }
  775. #endif
  776.  
  777.   window->parent = parent;
  778.   if (parent) {
  779.     window->siblings = parent->children;
  780.     parent->children = window;
  781.   } else {
  782.     window->siblings = NULL;
  783.   }
  784.   window->overlay = NULL;
  785.   window->children = NULL;
  786.   window->display = __glutDefaultDisplay;
  787.   window->reshape = __glutDefaultReshape;
  788.   window->mouse = NULL;
  789.   window->motion = NULL;
  790.   window->passive = NULL;
  791.   window->entry = NULL;
  792.   window->keyboard = NULL;
  793.   window->keyboardUp = NULL;
  794.   window->windowStatus = NULL;
  795.   window->visibility = NULL;
  796.   window->special = NULL;
  797.   window->specialUp = NULL;
  798.   window->buttonBox = NULL;
  799.   window->dials = NULL;
  800.   window->spaceMotion = NULL;
  801.   window->spaceRotate = NULL;
  802.   window->spaceButton = NULL;
  803.   window->tabletMotion = NULL;
  804.   window->tabletButton = NULL;
  805. #ifdef _WIN32
  806.   window->joystick = NULL;
  807.   window->joyPollInterval = 0;
  808. #endif
  809.  
  810. #ifdef __OS2__
  811.   window->wm_command = NULL;
  812. #endif
  813.  
  814.   window->tabletPos[0] = -1;
  815.   window->tabletPos[1] = -1;
  816.   window->shownState = 0;
  817.   window->visState = -1;  /* not VisibilityUnobscured,
  818.                              VisibilityPartiallyObscured, or
  819.                              VisibilityFullyObscured */
  820.   window->entryState = -1;  /* not EnterNotify or LeaveNotify */
  821.  
  822.   window->desiredConfMask = 0;
  823.   window->buttonUses = 0;
  824.   window->cursor = GLUT_CURSOR_INHERIT;
  825.  
  826.   /* Setup window to be mapped when glutMainLoop starts. */
  827.   window->workMask = GLUT_MAP_WORK;
  828. #ifdef _WIN32
  829.   if (gameMode) {
  830.     /* When mapping a game mode window, just show
  831.        the window.  We have already created the game
  832.        mode window with a maximize flag at creation
  833.        time.  Doing a ShowWindow(window->win, SW_SHOWNORMAL)
  834.        would be wrong for a game mode window since it
  835.        would unmaximize the window. */
  836.     window->desiredMapState = GameModeState;
  837.   } else {
  838.     window->desiredMapState = NormalState;
  839.   }
  840. #else
  841.   window->desiredMapState = NormalState;
  842. #endif
  843.   window->prevWorkWin = __glutWindowWorkList;
  844.   __glutWindowWorkList = window;
  845.  
  846.   /* Initially, no menus attached. */
  847.   for (i = 0; i < GLUT_MAX_MENUS; i++) {
  848.     window->menu[i] = 0;
  849.   }
  850.  
  851.   /* Add this new window to the window list. */
  852.   __glutWindowList[winnum] = window;
  853.  
  854.   /* Make the new window the current window. */
  855.   __glutSetWindow(window);
  856.  
  857.   __glutDetermineMesaSwapHackSupport();
  858.  
  859.   if (window->treatAsSingle) {
  860.     /* We do this because either the window really is single
  861.        buffered (in which case this is redundant, but harmless,
  862.        because this is the initial single-buffered context
  863.        state); or we are treating a double buffered window as a
  864.        single-buffered window because the system does not appear
  865.        to export any suitable single- buffered visuals (in which
  866.        the following are necessary). */
  867.     glDrawBuffer(GL_FRONT);
  868.     glReadBuffer(GL_FRONT);
  869.   }
  870.   return window;
  871. }
  872.  
  873. /* CENTRY */
  874. int GLUTAPIENTRY
  875. glutCreateWindow(const char *title)
  876. {
  877.   static int firstWindow = 1;
  878.   GLUTwindow *window;
  879. #if !defined(_WIN32) && !defined(__OS2__)
  880.   XWMHints *wmHints;
  881. #endif
  882.   Window win;
  883.   XTextProperty textprop;
  884.  
  885.   if (__glutGameModeWindow) {
  886.     __glutFatalError("cannot create windows in game mode.");
  887.   }
  888.   window = __glutCreateWindow(NULL,
  889.     __glutSizeHints.x, __glutSizeHints.y,
  890.     __glutInitWidth, __glutInitHeight,
  891.     /* not game mode */ 0);
  892.   win = window->win;
  893.   /* Setup ICCCM properties. */
  894.   textprop.value = (unsigned char *) title;
  895.   textprop.encoding = XA_STRING;
  896.   textprop.format = 8;
  897.   textprop.nitems = strlen(title);
  898. #if defined(__OS2__)
  899.   WinSetWindowText(window->frame, (PCSZ)title);
  900.   if (__glutIconic) {
  901.     window->desiredMapState = IconicState;
  902.   }
  903. #elif defined(_WIN32)
  904.   SetWindowText(win, title);
  905.   if (__glutIconic) {
  906.     window->desiredMapState = IconicState;
  907.   }
  908. #else
  909.   wmHints = XAllocWMHints();
  910.   wmHints->initial_state =
  911.     __glutIconic ? IconicState : NormalState;
  912.   wmHints->flags = StateHint;
  913.   XSetWMProperties(__glutDisplay, win, &textprop, &textprop,
  914.   /* Only put WM_COMMAND property on first window. */
  915.     firstWindow ? __glutArgv : NULL,
  916.     firstWindow ? __glutArgc : 0,
  917.     &__glutSizeHints, wmHints, NULL);
  918.   XFree(wmHints);
  919.   XSetWMProtocols(__glutDisplay, win, &__glutWMDeleteWindow, 1);
  920. #endif
  921.   firstWindow = 0;
  922.   return window->num + 1;
  923. }
  924.  
  925. #ifdef _WIN32
  926. int GLUTAPIENTRY
  927. __glutCreateWindowWithExit(const char *title, void (__cdecl *exitfunc)(int))
  928. {
  929.   __glutExitFunc = exitfunc;
  930.   return glutCreateWindow(title);
  931. }
  932. #endif
  933.  
  934. int GLUTAPIENTRY
  935. glutCreateSubWindow(int win, int x, int y, int width, int height)
  936. {
  937.   GLUTwindow *window;
  938.  
  939.   window = __glutCreateWindow(__glutWindowList[win - 1],
  940.     x, y, width, height, /* not game mode */ 0);
  941. #if !defined(_WIN32) && !defined(__OS2__)
  942.   {
  943.     GLUTwindow *toplevel;
  944.  
  945.     toplevel = __glutToplevelOf(window);
  946.     if (toplevel->cmap != window->cmap) {
  947.       __glutPutOnWorkList(toplevel, GLUT_COLORMAP_WORK);
  948.     }
  949.   }
  950. #endif
  951.   return window->num + 1;
  952. }
  953. /* ENDCENTRY */
  954.  
  955. void
  956. __glutDestroyWindow(GLUTwindow * window,
  957.   GLUTwindow * initialWindow)
  958. {
  959.   GLUTwindow **prev, *cur, *parent, *siblings;
  960.  
  961.   /* Recursively destroy any children. */
  962.   cur = window->children;
  963.   while (cur) {
  964.     siblings = cur->siblings;
  965.     __glutDestroyWindow(cur, initialWindow);
  966.     cur = siblings;
  967.   }
  968.   /* Remove from parent's children list (only necessary for
  969.      non-initial windows and subwindows!). */
  970.   parent = window->parent;
  971.   if (parent && parent == initialWindow->parent) {
  972.     prev = &parent->children;
  973.     cur = parent->children;
  974.     while (cur) {
  975.       if (cur == window) {
  976.         *prev = cur->siblings;
  977.         break;
  978.       }
  979.       prev = &(cur->siblings);
  980.       cur = cur->siblings;
  981.     }
  982.   }
  983.   /* Unbind if bound to this window. */
  984.   if (window == __glutCurrentWindow) {
  985.     UNMAKE_CURRENT();
  986.     __glutCurrentWindow = NULL;
  987.   }
  988.   /* Begin tearing down window itself. */
  989.   if (window->overlay) {
  990.     __glutFreeOverlayFunc(window->overlay);
  991.   }
  992.   XDestroyWindow(__glutDisplay, window->win);
  993.   glXDestroyContext(__glutDisplay, window->ctx);
  994.   if (window->colormap) {
  995.     /* Only color index windows have colormap data structure. */
  996.     __glutFreeColormap(window->colormap);
  997.   }
  998.   /* NULLing the __glutWindowList helps detect is a window
  999.      instance has been destroyed, given a window number. */
  1000.   __glutWindowList[window->num] = NULL;
  1001.  
  1002.   /* Cleanup data structures that might contain window. */
  1003.   cleanWindowWorkList(window);
  1004. #if !defined(_WIN32) && !defined(__OS2__)
  1005.   cleanStaleWindowList(window);
  1006. #endif
  1007.   /* Remove window from the "get window cache" if it is there. */
  1008.   if (__glutWindowCache == window)
  1009.     __glutWindowCache = NULL;
  1010.  
  1011.   if (window->visAlloced) {
  1012.     /* Only free XVisualInfo* gotten from glXChooseVisual. */
  1013.     XFree(window->vis);
  1014.   }
  1015.  
  1016.   if (window == __glutGameModeWindow) {
  1017.     /* Destroying the game mode window should implicitly
  1018.        have GLUT leave game mode. */
  1019.     __glutCloseDownGameMode();
  1020.   }
  1021.  
  1022.   free(window);
  1023. }
  1024.  
  1025. /* CENTRY */
  1026. void GLUTAPIENTRY
  1027. glutDestroyWindow(int win)
  1028. {
  1029.   GLUTwindow *window = __glutWindowList[win - 1];
  1030.  
  1031.   if (__glutMappedMenu && __glutMenuWindow == window) {
  1032.     __glutFatalUsage("destroying menu window not allowed while menus in use");
  1033.   }
  1034. #if !defined(_WIN32) && !defined(__OS2__)
  1035.   /* If not a toplevel window... */
  1036.   if (window->parent) {
  1037.     /* Destroying subwindows may change colormap requirements;
  1038.        recalculate toplevel window's WM_COLORMAP_WINDOWS
  1039.        property. */
  1040.     __glutPutOnWorkList(__glutToplevelOf(window->parent),
  1041.       GLUT_COLORMAP_WORK);
  1042.   }
  1043. #endif
  1044.   __glutDestroyWindow(window, window);
  1045.   XFlush(__glutDisplay);
  1046. }
  1047. /* ENDCENTRY */
  1048.  
  1049. void
  1050. __glutChangeWindowEventMask(long eventMask, Bool add)
  1051. {
  1052.   if (add) {
  1053.     /* Add eventMask to window's event mask. */
  1054.     if ((__glutCurrentWindow->eventMask & eventMask) !=
  1055.       eventMask) {
  1056.       __glutCurrentWindow->eventMask |= eventMask;
  1057.       __glutPutOnWorkList(__glutCurrentWindow,
  1058.         GLUT_EVENT_MASK_WORK);
  1059.     }
  1060.   } else {
  1061.     /* Remove eventMask from window's event mask. */
  1062.     if (__glutCurrentWindow->eventMask & eventMask) {
  1063.       __glutCurrentWindow->eventMask &= ~eventMask;
  1064.       __glutPutOnWorkList(__glutCurrentWindow,
  1065.         GLUT_EVENT_MASK_WORK);
  1066.     }
  1067.   }
  1068. }
  1069.  
  1070. void GLUTAPIENTRY
  1071. glutDisplayFunc(GLUTdisplayCB displayFunc)
  1072. {
  1073.   /* XXX Remove the warning after GLUT 3.0. */
  1074.   if (!displayFunc)
  1075.     __glutFatalError("NULL display callback not allowed in GLUT 3.0; update your code.");
  1076.   __glutCurrentWindow->display = displayFunc;
  1077. }
  1078.  
  1079. void GLUTAPIENTRY
  1080. glutMouseFunc(GLUTmouseCB mouseFunc)
  1081. {
  1082.   if (__glutCurrentWindow->mouse) {
  1083.     if (!mouseFunc) {
  1084.       /* Previous mouseFunc being disabled. */
  1085.       __glutCurrentWindow->buttonUses--;
  1086.       __glutChangeWindowEventMask(
  1087.         ButtonPressMask | ButtonReleaseMask,
  1088.         __glutCurrentWindow->buttonUses > 0);
  1089.     }
  1090.   } else {
  1091.     if (mouseFunc) {
  1092.       /* Previously no mouseFunc, new one being installed. */
  1093.       __glutCurrentWindow->buttonUses++;
  1094.       __glutChangeWindowEventMask(
  1095.         ButtonPressMask | ButtonReleaseMask, True);
  1096.     }
  1097.   }
  1098.   __glutCurrentWindow->mouse = mouseFunc;
  1099. }
  1100.  
  1101. void GLUTAPIENTRY
  1102. glutMotionFunc(GLUTmotionCB motionFunc)
  1103. {
  1104.   /* Hack.  Some window managers (4Dwm by default) will mask
  1105.      motion events if the client is not selecting for button
  1106.      press and release events. So we select for press and
  1107.      release events too (being careful to use reference
  1108.      counting).  */
  1109.   if (__glutCurrentWindow->motion) {
  1110.     if (!motionFunc) {
  1111.       /* previous mouseFunc being disabled */
  1112.       __glutCurrentWindow->buttonUses--;
  1113.       __glutChangeWindowEventMask(
  1114.         ButtonPressMask | ButtonReleaseMask,
  1115.         __glutCurrentWindow->buttonUses > 0);
  1116.     }
  1117.   } else {
  1118.     if (motionFunc) {
  1119.       /* Previously no mouseFunc, new one being installed. */
  1120.       __glutCurrentWindow->buttonUses++;
  1121.       __glutChangeWindowEventMask(
  1122.         ButtonPressMask | ButtonReleaseMask, True);
  1123.     }
  1124.   }
  1125.   /* Real work of selecting for passive mouse motion.  */
  1126.   __glutChangeWindowEventMask(
  1127.     Button1MotionMask | Button2MotionMask | Button3MotionMask,
  1128.     motionFunc != NULL);
  1129.   __glutCurrentWindow->motion = motionFunc;
  1130. }
  1131.  
  1132. void GLUTAPIENTRY
  1133. glutPassiveMotionFunc(GLUTpassiveCB passiveMotionFunc)
  1134. {
  1135.   __glutChangeWindowEventMask(PointerMotionMask,
  1136.     passiveMotionFunc != NULL);
  1137.  
  1138.   /* Passive motion also requires watching enters and leaves so
  1139.      that a fake passive motion event can be generated on an
  1140.      enter. */
  1141.   __glutChangeWindowEventMask(EnterWindowMask | LeaveWindowMask,
  1142.     __glutCurrentWindow->entry != NULL || passiveMotionFunc != NULL);
  1143.  
  1144.   __glutCurrentWindow->passive = passiveMotionFunc;
  1145. }
  1146.  
  1147. void GLUTAPIENTRY
  1148. glutEntryFunc(GLUTentryCB entryFunc)
  1149. {
  1150.   __glutChangeWindowEventMask(EnterWindowMask | LeaveWindowMask,
  1151.     entryFunc != NULL || __glutCurrentWindow->passive);
  1152.   __glutCurrentWindow->entry = entryFunc;
  1153.   if (!entryFunc) {
  1154.     __glutCurrentWindow->entryState = -1;
  1155.   }
  1156. }
  1157.  
  1158. void GLUTAPIENTRY
  1159. glutWindowStatusFunc(GLUTwindowStatusCB windowStatusFunc)
  1160. {
  1161.   __glutChangeWindowEventMask(VisibilityChangeMask,
  1162.     windowStatusFunc != NULL);
  1163.   __glutCurrentWindow->windowStatus = windowStatusFunc;
  1164.   if (!windowStatusFunc) {
  1165.     /* Make state invalid. */
  1166.     __glutCurrentWindow->visState = -1;
  1167.   }
  1168. }
  1169.  
  1170. static void GLUTCALLBACK
  1171. visibilityHelper(int status)
  1172. {
  1173.   if (status == GLUT_HIDDEN || status == GLUT_FULLY_COVERED)
  1174.     __glutCurrentWindow->visibility(GLUT_NOT_VISIBLE);
  1175.   else
  1176.     __glutCurrentWindow->visibility(GLUT_VISIBLE);
  1177. }
  1178.  
  1179.  
  1180. #ifdef __cplusplus
  1181. extern "C" {
  1182. #endif
  1183.  
  1184. void GLUTAPIENTRY
  1185. glutVisibilityFunc(GLUTvisibilityCB visibilityFunc);
  1186.  
  1187. #ifdef __cplusplus
  1188. }
  1189. #endif
  1190.  
  1191.  
  1192. void GLUTAPIENTRY
  1193. glutVisibilityFunc(GLUTvisibilityCB visibilityFunc)
  1194. {
  1195.   __glutCurrentWindow->visibility = visibilityFunc;
  1196.  
  1197.   if (visibilityFunc)
  1198.         glutWindowStatusFunc(visibilityHelper);
  1199.   else
  1200.     glutWindowStatusFunc(NULL);
  1201. }
  1202.  
  1203. void GLUTAPIENTRY
  1204. glutReshapeFunc(GLUTreshapeCB reshapeFunc)
  1205. {
  1206.   if (reshapeFunc) {
  1207.     __glutCurrentWindow->reshape = reshapeFunc;
  1208.   } else {
  1209.     __glutCurrentWindow->reshape = __glutDefaultReshape;
  1210.   }
  1211. }
  1212.