changed coding style. made `glutTimerFunc' less accurate, but far more reliable.
authorDaniel Borca <dborca@users.sourceforge.net>
Fri, 14 Jan 2005 08:50:08 +0000 (08:50 +0000)
committerDaniel Borca <dborca@users.sourceforge.net>
Fri, 14 Jan 2005 08:50:08 +0000 (08:50 +0000)
src/glut/dos/callback.c
src/glut/dos/glutint.h
src/glut/dos/init.c

index b322f673514df1ded114b2e96ba1b5c58f2fee7a..6bd05f406586c34ea0320cda1c5d8b8b30a0085d 100644 (file)
@@ -19,9 +19,9 @@
  */
 
 /*
- * DOS/DJGPP glut driver v1.5 for Mesa
+ * DOS/DJGPP glut driver v1.6 for Mesa
  *
- *  Copyright (C) 2002 - Borca Daniel
+ *  Copyright (C) 2002 - Daniel Borca
  *  Email : dborca@yahoo.com
  *  Web   : http://www.geocities.com/dborca
  */
 #include "glutint.h"
 
 
-
-typedef struct {
-        void (*func) (int); /* function to call */
-        int value;          /* value to pass to callback */
-        int ttl;            /* time to live (blank shots) */
-        int fid;            /* func-id as returned from PCHW */
-} GLUTSShotCB;
+GLUTSShotCB g_sscb[MAX_SSHOT_CB];
 
 GLUTidleCB g_idle_func = NULL;
 
 
-
-static void g_single_shot_callback (void *opaque)
+void APIENTRY
+glutDisplayFunc (GLUTdisplayCB func)
 {
- GLUTSShotCB *cb = (GLUTSShotCB *)opaque;
- if (!--cb->ttl) {
-    cb->func(cb->value);
-    pc_remove_int(cb->fid);
-    /* We won't be needing this slot anymore, so free it. This operation
-     * must be the last thing, and must be atomic, to mutex `glutTimerFunc'
-     */
-    cb->func = NULL;
- }
-} ENDOFUNC(g_single_shot_callback)
-
-
-
-void APIENTRY glutDisplayFunc (GLUTdisplayCB func)
-{
- g_curwin->display = func;
+   g_curwin->display = func;
 }
 
 
-
-void APIENTRY glutReshapeFunc (GLUTreshapeCB func)
+void APIENTRY
+glutReshapeFunc (GLUTreshapeCB func)
 {
- g_curwin->reshape = func;
  g_curwin->reshape = func;
 }
 
 
-
-void APIENTRY glutKeyboardFunc (GLUTkeyboardCB func)
+void APIENTRY
+glutKeyboardFunc (GLUTkeyboardCB func)
 {
- g_curwin->keyboard = func;
  g_curwin->keyboard = func;
 }
 
 
-
-void APIENTRY glutMouseFunc (GLUTmouseCB func)
+void APIENTRY
+glutMouseFunc (GLUTmouseCB func)
 {
- g_curwin->mouse = func;
  g_curwin->mouse = func;
 }
 
 
-
-void APIENTRY glutMotionFunc (GLUTmotionCB func)
+void APIENTRY
+glutMotionFunc (GLUTmotionCB func)
 {
- g_curwin->motion = func;
  g_curwin->motion = func;
 }
 
 
-
-void APIENTRY glutPassiveMotionFunc (GLUTpassiveCB func)
+void APIENTRY
+glutPassiveMotionFunc (GLUTpassiveCB func)
 {
- g_curwin->passive = func;
  g_curwin->passive = func;
 }
 
 
-
-void APIENTRY glutEntryFunc (GLUTentryCB func)
+void APIENTRY
+glutEntryFunc (GLUTentryCB func)
 {
- g_curwin->entry = func;
  g_curwin->entry = func;
 }
 
 
-
-void APIENTRY glutVisibilityFunc (GLUTvisibilityCB func)
+void APIENTRY
+glutVisibilityFunc (GLUTvisibilityCB func)
 {
- g_curwin->visibility = func;
  g_curwin->visibility = func;
 }
 
 
-
-void APIENTRY glutWindowStatusFunc (GLUTwindowStatusCB func)
+void APIENTRY
+glutWindowStatusFunc (GLUTwindowStatusCB func)
 {
 }
 
 
-
-void APIENTRY glutIdleFunc (GLUTidleCB func)
+void APIENTRY
+glutIdleFunc (GLUTidleCB func)
 {
- g_idle_func = func;
  g_idle_func = func;
 }
 
 
-
-void APIENTRY glutTimerFunc (unsigned int millis, GLUTtimerCB func, int value)
+void APIENTRY
+glutTimerFunc (unsigned int millis, GLUTtimerCB func, int value)
 {
- static GLUTSShotCB g_sscb[MAX_SSHOT_CB];
- static GLboolean virgin = GL_TRUE;
-
- int i;
- int ttl;
- unsigned int freq;
-
- if (virgin) {
-    virgin = GL_FALSE;
-    LOCKDATA(g_sscb);
-    LOCKFUNC(g_single_shot_callback);
-    /* we should lock the callee also... */
- }
+   int i;
 
- if (millis > 0) {
-    if (millis > 50) {
-       /* don't go beyond 20Hz */
-       freq = 200;
-       ttl = millis * freq / 1000;
-    } else {
-       freq = 1000 / millis;
-       ttl = 1;
-    }
-    for (i = 0; i < MAX_SSHOT_CB; i++) {
-        if (g_sscb[i].func == NULL) {
-           /* We will be needing this slot, so alloc it. This operation
-            * must be the first thing, and must be atomic, to mutex callbacks!
-            */
-           g_sscb[i].func = func;
-           g_sscb[i].value = value;
-           g_sscb[i].ttl = ttl;
-           /* There is a very small gap here: `pc_install_int' enables
-            * interrupts just before returning FID value (which will be
-            * used inside callback). The critical gap is 1 millisecond
-            * - which I'm sure we won't overrun...
-            */
-           g_sscb[i].fid = pc_install_int((PFUNC)func, &g_sscb[i], freq);
-           if (g_sscb[i].fid < 0) {
-              /* Interrupt could not be set! Release the slot back */
-              g_sscb[i].func = NULL;
-           }
-           break;
-        }
-    }
- }
+   if (millis > 0) {
+      for (i = 0; i < MAX_SSHOT_CB; i++) {
+         GLUTSShotCB *cb = &g_sscb[i];
+         if (cb->func == NULL) {
+            cb->value = value;
+            cb->func = func;
+            cb->time = glutGet(GLUT_ELAPSED_TIME) + millis;
+            break;
+         }
+      }
+   }
 }
 
 
-
-void APIENTRY glutSpecialFunc (GLUTspecialCB func)
+void APIENTRY
+glutSpecialFunc (GLUTspecialCB func)
 {
- g_curwin->special = func;
  g_curwin->special = func;
 }
 
 
-
-void APIENTRY glutSpaceballMotionFunc (GLUTspaceMotionCB func)
+void APIENTRY
+glutSpaceballMotionFunc (GLUTspaceMotionCB func)
 {
 }
 
 
-
-void APIENTRY glutSpaceballRotateFunc (GLUTspaceRotateCB func)
+void APIENTRY
+glutSpaceballRotateFunc (GLUTspaceRotateCB func)
 {
 }
 
 
-
-void APIENTRY glutSpaceballButtonFunc (GLUTspaceButtonCB func)
+void APIENTRY
+glutSpaceballButtonFunc (GLUTspaceButtonCB func)
 {
 }
 
 
-
-void APIENTRY glutDialsFunc (GLUTdialsCB func)
+void APIENTRY
+glutDialsFunc (GLUTdialsCB func)
 {
 }
 
 
-
-void APIENTRY glutButtonBoxFunc (GLUTbuttonBoxCB func)
+void APIENTRY
+glutButtonBoxFunc (GLUTbuttonBoxCB func)
 {
 }
 
 
-
-void APIENTRY glutTabletMotionFunc (GLUTtabletMotionCB func)
+void APIENTRY
+glutTabletMotionFunc (GLUTtabletMotionCB func)
 {
 }
 
 
-
-void APIENTRY glutTabletButtonFunc (GLUTtabletButtonCB func)
+void APIENTRY
+glutTabletButtonFunc (GLUTtabletButtonCB func)
 {
 }
 
 
-
-void APIENTRY glutJoystickFunc (GLUTjoystickCB func, int interval)
+void APIENTRY
+glutJoystickFunc (GLUTjoystickCB func, int interval)
 {
 }
index 12750041fe14ea5aa9972c229629160dc46da340..eab8cd741aaca902771a073cadc6d44b6ebe3a1c 100644 (file)
@@ -21,7 +21,7 @@
 /*
  * DOS/DJGPP glut driver v1.6 for Mesa
  *
- *  Copyright (C) 2002 - Borca Daniel
+ *  Copyright (C) 2002 - Daniel Borca
  *  Email : dborca@users.sourceforge.net
  *  Web   : http://www.geocities.com/dborca
  */
@@ -35,7 +35,6 @@
 #include "GL/dmesa.h"
 
 
-
 /* GLUT  function types */
 typedef void (GLUTCALLBACK *GLUTdisplayCB) (void);
 typedef void (GLUTCALLBACK *GLUTreshapeCB) (int, int);
@@ -62,41 +61,41 @@ typedef void (GLUTCALLBACK *GLUTtabletButtonCB) (int, int, int, int);
 typedef void (GLUTCALLBACK *GLUTjoystickCB) (unsigned int, int, int, int);
 
 typedef struct GLUTwindow {
-        int num;                         /* window id */
-
-        DMesaContext context;
-        DMesaBuffer buffer;
-
-        int show_mouse;
-        GLboolean redisplay;
-
-        /* GLUT settable or visible window state. */
-        int xpos;
-        int ypos;
-        int width;                       /* window width in pixels */
-        int height;                      /* window height in pixels */
-
-        /* Per-window callbacks. */
-        GLUTdisplayCB      display;      /* redraw */
-        GLUTreshapeCB      reshape;      /* resize (width,height) */
-        GLUTmouseCB        mouse;        /* mouse (button,state,x,y) */
-        GLUTmotionCB       motion;       /* motion (x,y) */
-        GLUTpassiveCB      passive;      /* passive motion (x,y) */
-        GLUTentryCB        entry;        /* window entry/exit (state) */
-        GLUTkeyboardCB     keyboard;     /* keyboard (ASCII,x,y) */
-        GLUTkeyboardCB     keyboardUp;   /* keyboard up (ASCII,x,y) */
-        GLUTwindowStatusCB windowStatus; /* window status */
-        GLUTvisibilityCB   visibility;   /* visibility */
-        GLUTspecialCB      special;      /* special key */
-        GLUTspecialCB      specialUp;    /* special up key */
-        GLUTbuttonBoxCB    buttonBox;    /* button box */
-        GLUTdialsCB        dials;        /* dials */
-        GLUTspaceMotionCB  spaceMotion;  /* Spaceball motion */
-        GLUTspaceRotateCB  spaceRotate;  /* Spaceball rotate */
-        GLUTspaceButtonCB  spaceButton;  /* Spaceball button */
-        GLUTtabletMotionCB tabletMotion; /* tablet motion */
-        GLUTtabletButtonCB tabletButton; /* tablet button */
-        GLUTjoystickCB     joystick;     /* joystick */
+   int num;                         /* window id */
+
+   DMesaContext context;
+   DMesaBuffer buffer;
+
+   int show_mouse;
+   GLboolean redisplay;
+
+   /* GLUT settable or visible window state. */
+   int xpos;
+   int ypos;
+   int width;                       /* window width in pixels */
+   int height;                      /* window height in pixels */
+
+   /* Per-window callbacks. */
+   GLUTdisplayCB      display;      /* redraw */
+   GLUTreshapeCB      reshape;      /* resize (width,height) */
+   GLUTmouseCB        mouse;        /* mouse (button,state,x,y) */
+   GLUTmotionCB       motion;       /* motion (x,y) */
+   GLUTpassiveCB      passive;      /* passive motion (x,y) */
+   GLUTentryCB        entry;        /* window entry/exit (state) */
+   GLUTkeyboardCB     keyboard;     /* keyboard (ASCII,x,y) */
+   GLUTkeyboardCB     keyboardUp;   /* keyboard up (ASCII,x,y) */
+   GLUTwindowStatusCB windowStatus; /* window status */
+   GLUTvisibilityCB   visibility;   /* visibility */
+   GLUTspecialCB      special;      /* special key */
+   GLUTspecialCB      specialUp;    /* special up key */
+   GLUTbuttonBoxCB    buttonBox;    /* button box */
+   GLUTdialsCB        dials;        /* dials */
+   GLUTspaceMotionCB  spaceMotion;  /* Spaceball motion */
+   GLUTspaceRotateCB  spaceRotate;  /* Spaceball rotate */
+   GLUTspaceButtonCB  spaceButton;  /* Spaceball button */
+   GLUTtabletMotionCB tabletMotion; /* tablet motion */
+   GLUTtabletButtonCB tabletButton; /* tablet button */
+   GLUTjoystickCB     joystick;     /* joystick */
 } GLUTwindow;
 
 extern GLUTidleCB g_idle_func;
@@ -138,16 +137,19 @@ extern void *__glutFont(void *font);
 #endif
 
 
-
 /* hmmm... */
 #include "pc_hw/pc_hw.h"
 
+typedef struct {
+   void (*func) (int); /* function to call */
+   int value;          /* value to pass to callback */
+   int time;           /* end time */
+} GLUTSShotCB;
 
+extern GLUTSShotCB g_sscb[];
 
 #define MAX_WINDOWS 2
-
 #define MAX_SSHOT_CB 8
-
 #define RESERVED_COLORS 0
 
 #endif /* __glutint_h__ */
index b9fc0e53379a035d44bb5077fe5b3bb52999a3ac..85f5da629dc65f621887e1d9962d1af4a6ef6b3d 100644 (file)
@@ -19,9 +19,9 @@
  */
 
 /*
- * DOS/DJGPP glut driver v1.4 for Mesa
+ * DOS/DJGPP glut driver v1.5 for Mesa
  *
- *  Copyright (C) 2002 - Borca Daniel
+ *  Copyright (C) 2002 - Daniel Borca
  *  Email : dborca@users.sourceforge.net
  *  Web   : http://www.geocities.com/dborca
  */
@@ -41,7 +41,6 @@
 #define ACCUM_SIZE   16
 
 
-
 GLuint g_bpp = DEFAULT_BPP;
 GLuint g_alpha = ALPHA_SIZE;
 GLuint g_depth = DEPTH_SIZE;
@@ -60,261 +59,269 @@ GLuint g_init_w = DEFAULT_WIDTH, g_init_h = DEFAULT_HEIGHT;
 char *__glutProgramName = NULL;
 
 
-
-void APIENTRY glutInit (int *argc, char **argv)
+void APIENTRY
+glutInit (int *argc, char **argv)
 {
- char *str;
- const char *env;
-
- if ((env = getenv("DMESA_GLUT_BPP")) != NULL) {
-    g_bpp = atoi(env);
- }
- if ((env = getenv("DMESA_GLUT_ALPHA")) != NULL) {
-    g_alpha = atoi(env);
- }
- if ((env = getenv("DMESA_GLUT_DEPTH")) != NULL) {
-    g_depth = atoi(env);
- }
- if ((env = getenv("DMESA_GLUT_STENCIL")) != NULL) {
-    g_stencil = atoi(env);
- }
- if ((env = getenv("DMESA_GLUT_ACCUM")) != NULL) {
-    g_accum = atoi(env);
- }
- if ((env = getenv("DMESA_GLUT_REFRESH")) != NULL) {
-    g_refresh = atoi(env);
- }
-
- /* Determine program name. */
- str = strrchr(argv[0], '/');
- if (str == NULL) {
-    str = argv[0];
- } else {
-    str++;
- }
- __glutProgramName = __glutStrdup(str);
-
- /* check if GLUT_FPS env var is set */
- if ((env = getenv("GLUT_FPS")) != NULL) {
-    if ((g_fps = atoi(env)) <= 0) {
-       g_fps = 5000; /* 5000 milliseconds */
-    }
- }
-
- /* Initialize timer */
- glutGet(GLUT_ELAPSED_TIME);
  char *str;
  const char *env;
+
  if ((env = getenv("DMESA_GLUT_BPP")) != NULL) {
+      g_bpp = atoi(env);
  }
  if ((env = getenv("DMESA_GLUT_ALPHA")) != NULL) {
+      g_alpha = atoi(env);
  }
  if ((env = getenv("DMESA_GLUT_DEPTH")) != NULL) {
+      g_depth = atoi(env);
  }
  if ((env = getenv("DMESA_GLUT_STENCIL")) != NULL) {
+      g_stencil = atoi(env);
  }
  if ((env = getenv("DMESA_GLUT_ACCUM")) != NULL) {
+      g_accum = atoi(env);
  }
  if ((env = getenv("DMESA_GLUT_REFRESH")) != NULL) {
+      g_refresh = atoi(env);
  }
+
  /* Determine program name. */
  str = strrchr(argv[0], '/');
  if (str == NULL) {
+      str = argv[0];
  } else {
+      str++;
  }
  __glutProgramName = __glutStrdup(str);
+
  /* check if GLUT_FPS env var is set */
  if ((env = getenv("GLUT_FPS")) != NULL) {
+      if ((g_fps = atoi(env)) <= 0) {
+         g_fps = 5000; /* 5000 milliseconds */
+      }
  }
+
  /* Initialize timer */
  glutGet(GLUT_ELAPSED_TIME);
 }
 
 
-
-void APIENTRY glutInitDisplayMode (unsigned int mode)
+void APIENTRY
+glutInitDisplayMode (unsigned int mode)
 {
- g_display_mode = mode;
  g_display_mode = mode;
 }
 
 
-
-void APIENTRY glutInitWindowPosition (int x, int y)
+void APIENTRY
+glutInitWindowPosition (int x, int y)
 {
- g_init_x = x;
- g_init_y = y;
  g_init_x = x;
  g_init_y = y;
 }
 
 
-
-void APIENTRY glutInitWindowSize (int width, int height)
+void APIENTRY
+glutInitWindowSize (int width, int height)
 {
- g_init_w = width;
- g_init_h = height;
  g_init_w = width;
  g_init_h = height;
 }
 
 
-
 #define DO_REDISPLAY(w, ccin, ccout) \
-        do {                                                             \
-            if (w->redisplay && w->display) {                            \
-               int rv = GL_TRUE;                                         \
-                                                                         \
-               idle         = GL_FALSE;                                  \
-               w->redisplay = GL_FALSE;                                  \
-                                                                         \
-               /* test IN condition (whether we need to `MakeCurrent') */\
-               if (ccin) {                                               \
-                  rv = DMesaMakeCurrent(w->context, w->buffer);          \
-               }                                                         \
-                                                                         \
-               /* do the display only if `MakeCurrent' didn't failed */  \
-               if (rv) {                                                 \
-                  if (w->show_mouse && !(g_display_mode & GLUT_DOUBLE)) {\
-                     /* XXX scare mouse */                               \
-                     w->display();                                       \
-                     /* XXX unscare mouse */                             \
-                  } else {                                               \
-                     w->display();                                       \
-                  }                                                      \
-                                                                         \
-                  /* update OUT condition */                             \
-                  ccout;                                                 \
-               }                                                         \
-            }                                                            \
-        } while (0)
-
-
-
-void APIENTRY glutMainLoop (void)
+   do {                                                            \
+      if (w->redisplay && w->display) {                            \
+         int rv = GL_TRUE;                                         \
+                                                                   \
+         idle         = GL_FALSE;                                  \
+         w->redisplay = GL_FALSE;                                  \
+                                                                   \
+         /* test IN condition (whether we need to `MakeCurrent') */\
+         if (ccin) {                                               \
+            rv = DMesaMakeCurrent(w->context, w->buffer);          \
+         }                                                         \
+                                                                   \
+         /* do the display only if `MakeCurrent' didn't failed */  \
+         if (rv) {                                                 \
+            if (w->show_mouse && !(g_display_mode & GLUT_DOUBLE)) {\
+               /* XXX scare mouse */                               \
+               w->display();                                       \
+               /* XXX unscare mouse */                             \
+            } else {                                               \
+               w->display();                                       \
+            }                                                      \
+                                                                   \
+            /* update OUT condition */                             \
+            ccout;                                                 \
+         }                                                         \
+      }                                                            \
+   } while (0)
+
+
+void APIENTRY
+glutMainLoop (void)
 {
- int i, n;
- GLUTwindow *w;
- GLboolean idle;
- static int old_mouse_x = 0;
- static int old_mouse_y = 0;
- static int old_mouse_b = 0;
-
- {
-  GLint screen_size[2];
-  DMesaGetIntegerv(DMESA_GET_SCREEN_SIZE, screen_size);
-  g_screen_w = screen_size[0];
-  g_screen_h = screen_size[1];
-  DMesaGetIntegerv(DMESA_GET_DRIVER_CAPS, &g_driver_caps);
- }
-
- pc_install_keyb();
- __glutInitMouse();
-
- for (i = 0; i < MAX_WINDOWS; i++) {
-     w = g_windows[i];
-     if (w != NULL) {
-        glutSetWindow(w->num);
-        glutPostRedisplay();
-        if (w->reshape) {
-           w->reshape(w->width, w->height);
-        }
-        if (w->visibility) {
-           w->visibility(GLUT_VISIBLE);
-        }
-     }
- }
-
- while (GL_TRUE) {
-       idle = GL_TRUE;
-
-       n = 0;
-       for (i = 0; i < MAX_WINDOWS; i++) {
-           w = g_windows[i];
-           if ((w != NULL) && (w != g_curwin)) {
-              /* 1) redisplay `w'
-               * 2) `MakeCurrent' always
-               * 3) update number of non-default windows
-               */
-              DO_REDISPLAY(w, GL_TRUE, n++);
-           }
-       }
-       /* 1) redisplay `g_curwin'
-        * 2) `MakeCurrent' only if we previously did non-default windows
-        * 3) don't update anything
-        */
-       DO_REDISPLAY(g_curwin, n, n);
-
-       if (g_mouse) {
-          int mouse_x;
-          int mouse_y;
-          int mouse_z;
-          int mouse_b;
-
-          /* query mouse */
-          mouse_b = pc_query_mouse(&mouse_x, &mouse_y, &mouse_z);
-
-          /* relative to window coordinates */
-          g_mouse_x = mouse_x - g_curwin->xpos;
-          g_mouse_y = mouse_y - g_curwin->ypos;
-
-          /* mouse was moved? */
-          if ((mouse_x != old_mouse_x) || (mouse_y != old_mouse_y)) {
-             idle        = GL_FALSE;
-             old_mouse_x = mouse_x;
-             old_mouse_y = mouse_y;
-
-             if (mouse_b) {
-                /* any button pressed */
-                if (g_curwin->motion) {
-                   g_curwin->motion(g_mouse_x, g_mouse_y);
-                }
-             } else {
-                /* no button pressed */
-                if (g_curwin->passive) {
-                   g_curwin->passive(g_mouse_x, g_mouse_y);
-                }
-             }
-          }
-
-          /* button state changed? */
-          if (mouse_b != old_mouse_b) {
-             GLUTmouseCB mouse_func;
-
-             if ((mouse_func = g_curwin->mouse)) {
-                if ((old_mouse_b & 1) && !(mouse_b & 1))
-                   mouse_func(GLUT_LEFT_BUTTON, GLUT_UP,     g_mouse_x, g_mouse_y);
-                else if (!(old_mouse_b & 1) && (mouse_b & 1))
-                   mouse_func(GLUT_LEFT_BUTTON, GLUT_DOWN,   g_mouse_x, g_mouse_y);
-
-                if ((old_mouse_b & 2) && !(mouse_b & 2))
-                   mouse_func(GLUT_RIGHT_BUTTON, GLUT_UP,    g_mouse_x, g_mouse_y);
-                else if (!(old_mouse_b & 2) && (mouse_b & 2))
-                   mouse_func(GLUT_RIGHT_BUTTON, GLUT_DOWN,  g_mouse_x, g_mouse_y);
-
-                if ((old_mouse_b & 4) && !(mouse_b & 4))
-                   mouse_func(GLUT_MIDDLE_BUTTON, GLUT_UP,   g_mouse_x, g_mouse_y);
-                else if (!(old_mouse_b & 3) && (mouse_b & 4))
-                   mouse_func(GLUT_MIDDLE_BUTTON, GLUT_DOWN, g_mouse_x, g_mouse_y);
-             }
-
-             idle        = GL_FALSE;
-             old_mouse_b = mouse_b;
-          }
-       }
-
-       if (pc_keypressed()) {
-          int key;
-          int glut_key;
-
-          idle = GL_FALSE;
-          key  = pc_readkey();
-
-          switch (key>>16) {
-                 case KEY_F1:     glut_key = GLUT_KEY_F1;        goto special;
-                 case KEY_F2:     glut_key = GLUT_KEY_F2;        goto special;
-                 case KEY_F3:     glut_key = GLUT_KEY_F3;        goto special;
-                 case KEY_F4:     glut_key = GLUT_KEY_F4;        goto special;
-                 case KEY_F5:     glut_key = GLUT_KEY_F5;        goto special;
-                 case KEY_F6:     glut_key = GLUT_KEY_F6;        goto special;
-                 case KEY_F7:     glut_key = GLUT_KEY_F7;        goto special;
-                 case KEY_F8:     glut_key = GLUT_KEY_F8;        goto special;
-                 case KEY_F9:     glut_key = GLUT_KEY_F9;        goto special;
-                 case KEY_F10:    glut_key = GLUT_KEY_F10;       goto special;
-                 case KEY_F11:    glut_key = GLUT_KEY_F11;       goto special;
-                 case KEY_F12:    glut_key = GLUT_KEY_F12;       goto special;
-                 case KEY_LEFT:   glut_key = GLUT_KEY_LEFT;      goto special;
-                 case KEY_UP:     glut_key = GLUT_KEY_UP;        goto special;
-                 case KEY_RIGHT:  glut_key = GLUT_KEY_RIGHT;     goto special;
-                 case KEY_DOWN:   glut_key = GLUT_KEY_DOWN;      goto special;
-                 case KEY_PGUP:   glut_key = GLUT_KEY_PAGE_UP;   goto special;
-                 case KEY_PGDN:   glut_key = GLUT_KEY_PAGE_DOWN; goto special;
-                 case KEY_HOME:   glut_key = GLUT_KEY_HOME;      goto special;
-                 case KEY_END:    glut_key = GLUT_KEY_END;       goto special;
-                 case KEY_INSERT: glut_key = GLUT_KEY_INSERT;    goto special;
-                 special:
-                      if (g_curwin->special) {
-                         g_curwin->special(glut_key, g_mouse_x, g_mouse_y);
-                      }
-                      break;
-                 default:
-                      if (g_curwin->keyboard) {
-                         g_curwin->keyboard(key & 0xFF, g_mouse_x, g_mouse_y);
-                      }
-          }
-       }
-
-       if (idle && g_idle_func)
-          g_idle_func();
- }
+   int i, n;
+   GLUTwindow *w;
+   GLboolean idle;
+   static int old_mouse_x = 0;
+   static int old_mouse_y = 0;
+   static int old_mouse_b = 0;
+
+   {
+      GLint screen_size[2];
+      DMesaGetIntegerv(DMESA_GET_SCREEN_SIZE, screen_size);
+      g_screen_w = screen_size[0];
+      g_screen_h = screen_size[1];
+      DMesaGetIntegerv(DMESA_GET_DRIVER_CAPS, &g_driver_caps);
+   }
+
+   pc_install_keyb();
+   __glutInitMouse();
+
+   for (i = 0; i < MAX_WINDOWS; i++) {
+      w = g_windows[i];
+      if (w != NULL) {
+         glutSetWindow(w->num);
+         glutPostRedisplay();
+         if (w->reshape) {
+            w->reshape(w->width, w->height);
+         }
+         if (w->visibility) {
+            w->visibility(GLUT_VISIBLE);
+         }
+      }
+   }
+
+   while (GL_TRUE) {
+      idle = GL_TRUE;
+
+      n = 0;
+      for (i = 0; i < MAX_WINDOWS; i++) {
+         w = g_windows[i];
+         if ((w != NULL) && (w != g_curwin)) {
+            /* 1) redisplay `w'
+             * 2) `MakeCurrent' always
+             * 3) update number of non-default windows
+             */
+            DO_REDISPLAY(w, GL_TRUE, n++);
+         }
+      }
+      /* 1) redisplay `g_curwin'
+       * 2) `MakeCurrent' only if we previously did non-default windows
+       * 3) don't update anything
+       */
+      DO_REDISPLAY(g_curwin, n, n);
+
+      if (g_mouse) {
+         int mouse_x;
+         int mouse_y;
+         int mouse_z;
+         int mouse_b;
+
+         /* query mouse */
+         mouse_b = pc_query_mouse(&mouse_x, &mouse_y, &mouse_z);
+
+         /* relative to window coordinates */
+         g_mouse_x = mouse_x - g_curwin->xpos;
+         g_mouse_y = mouse_y - g_curwin->ypos;
+
+         /* mouse was moved? */
+         if ((mouse_x != old_mouse_x) || (mouse_y != old_mouse_y)) {
+            idle        = GL_FALSE;
+            old_mouse_x = mouse_x;
+            old_mouse_y = mouse_y;
+
+            if (mouse_b) {
+               /* any button pressed */
+               if (g_curwin->motion) {
+                  g_curwin->motion(g_mouse_x, g_mouse_y);
+               }
+            } else {
+               /* no button pressed */
+               if (g_curwin->passive) {
+                  g_curwin->passive(g_mouse_x, g_mouse_y);
+               }
+            }
+         }
+
+         /* button state changed? */
+         if (mouse_b != old_mouse_b) {
+            GLUTmouseCB mouse_func;
+
+            if ((mouse_func = g_curwin->mouse)) {
+               if ((old_mouse_b & 1) && !(mouse_b & 1))
+                  mouse_func(GLUT_LEFT_BUTTON, GLUT_UP,     g_mouse_x, g_mouse_y);
+               else if (!(old_mouse_b & 1) && (mouse_b & 1))
+                  mouse_func(GLUT_LEFT_BUTTON, GLUT_DOWN,   g_mouse_x, g_mouse_y);
+
+               if ((old_mouse_b & 2) && !(mouse_b & 2))
+                  mouse_func(GLUT_RIGHT_BUTTON, GLUT_UP,    g_mouse_x, g_mouse_y);
+               else if (!(old_mouse_b & 2) && (mouse_b & 2))
+                  mouse_func(GLUT_RIGHT_BUTTON, GLUT_DOWN,  g_mouse_x, g_mouse_y);
+
+               if ((old_mouse_b & 4) && !(mouse_b & 4))
+                  mouse_func(GLUT_MIDDLE_BUTTON, GLUT_UP,   g_mouse_x, g_mouse_y);
+               else if (!(old_mouse_b & 3) && (mouse_b & 4))
+                  mouse_func(GLUT_MIDDLE_BUTTON, GLUT_DOWN, g_mouse_x, g_mouse_y);
+            }
+
+            idle        = GL_FALSE;
+            old_mouse_b = mouse_b;
+         }
+      }
+
+      if (pc_keypressed()) {
+         int key;
+         int glut_key;
+
+         idle = GL_FALSE;
+         key  = pc_readkey();
+
+         switch (key>>16) {
+            case KEY_F1:     glut_key = GLUT_KEY_F1;        goto special;
+            case KEY_F2:     glut_key = GLUT_KEY_F2;        goto special;
+            case KEY_F3:     glut_key = GLUT_KEY_F3;        goto special;
+            case KEY_F4:     glut_key = GLUT_KEY_F4;        goto special;
+            case KEY_F5:     glut_key = GLUT_KEY_F5;        goto special;
+            case KEY_F6:     glut_key = GLUT_KEY_F6;        goto special;
+            case KEY_F7:     glut_key = GLUT_KEY_F7;        goto special;
+            case KEY_F8:     glut_key = GLUT_KEY_F8;        goto special;
+            case KEY_F9:     glut_key = GLUT_KEY_F9;        goto special;
+            case KEY_F10:    glut_key = GLUT_KEY_F10;       goto special;
+            case KEY_F11:    glut_key = GLUT_KEY_F11;       goto special;
+            case KEY_F12:    glut_key = GLUT_KEY_F12;       goto special;
+            case KEY_LEFT:   glut_key = GLUT_KEY_LEFT;      goto special;
+            case KEY_UP:     glut_key = GLUT_KEY_UP;        goto special;
+            case KEY_RIGHT:  glut_key = GLUT_KEY_RIGHT;     goto special;
+            case KEY_DOWN:   glut_key = GLUT_KEY_DOWN;      goto special;
+            case KEY_PGUP:   glut_key = GLUT_KEY_PAGE_UP;   goto special;
+            case KEY_PGDN:   glut_key = GLUT_KEY_PAGE_DOWN; goto special;
+            case KEY_HOME:   glut_key = GLUT_KEY_HOME;      goto special;
+            case KEY_END:    glut_key = GLUT_KEY_END;       goto special;
+            case KEY_INSERT: glut_key = GLUT_KEY_INSERT;    goto special;
+            special:
+               if (g_curwin->special) {
+                  g_curwin->special(glut_key, g_mouse_x, g_mouse_y);
+               }
+               break;
+            default:
+               if (g_curwin->keyboard) {
+                  g_curwin->keyboard(key & 0xFF, g_mouse_x, g_mouse_y);
+               }
+         }
+      }
+
+      if (idle && g_idle_func)
+         g_idle_func();
+
+      for (i = 0; i < MAX_SSHOT_CB; i++) {
+         int time = glutGet(GLUT_ELAPSED_TIME);
+         GLUTSShotCB *cb = &g_sscb[i];
+         if (cb->func && (time >= cb->time)) {
+            cb->func(cb->value);
+            cb->func = NULL;
+         }
+      }
+   }
 }