Index: myglut-x11.c
===================================================================
--- myglut-x11.c	(revision 170)
+++ myglut-x11.c	(revision 171)
@@ -0,0 +1,548 @@
+/*
+    Raydium - CQFD Corp.
+    http://raydium.org/
+    License: GPL - GNU General Public License, see "gpl.txt" file.
+*/
+
+#include "myglut.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+#include <X11/cursorfont.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+//#include <X11/Xutil.h> // provided by glx
+
+#include <GL/glx.h>
+
+#ifdef HAVE_MOTIF
+#include <X11/Xm/MwmUtil.h>
+#else
+/* bit definitions for MwmHints.flags */
+#define MWM_HINTS_FUNCTIONS	(1L << 0)
+#define MWM_HINTS_DECORATIONS	(1L << 1)
+#define MWM_HINTS_INPUT_MODE	(1L << 2)
+#define MWM_HINTS_STATUS	(1L << 3)
+
+/* bit definitions for MwmHints.decorations */
+#define MWM_DECOR_ALL		(1L << 0)
+#define MWM_DECOR_BORDER	(1L << 1)
+#define MWM_DECOR_RESIZEH	(1L << 2)
+#define MWM_DECOR_TITLE		(1L << 3)
+#define MWM_DECOR_MENU		(1L << 4)
+#define MWM_DECOR_MINIMIZE	(1L << 5)
+#define MWM_DECOR_MAXIMIZE	(1L << 6)
+
+typedef struct
+{
+  unsigned long flags       ;
+  unsigned long functions   ;
+  unsigned long decorations ;
+           long inputMode   ;
+  unsigned long status      ;
+} PropMotifWmHints ;
+
+#define PROP_MOTIF_WM_HINTS_ELEMENTS	5
+
+#endif
+
+#ifndef GLX_SAMPLE_BUFFERS_ARB
+#define GLX_SAMPLE_BUFFERS_ARB 100000
+#define GLX_SAMPLES_ARB        100001
+#endif
+
+
+Display     *currDisplay ;
+XVisualInfo *visualInfo  ;
+Window       currHandle  ;
+GLXContext   currContext ;
+Window       rootWindow  ;
+Atom         delWinAtom  ;
+
+int currScreen;
+int currConnect;
+
+typedef struct PixelFormat
+{
+  int num_samples ;
+  int bits_per_pixel ; ;
+  int z_bits ;
+} PixelFormat;
+
+
+PixelFormat preferred_pixel_formats [] =
+{
+  /* NumSamples, RGB_bits, Z_bits */
+
+  {  0, 24, 24 },  /* Progressively nastier image formats */
+  {  0, 16, 24 },
+  {  0, 16, 16 },
+  { -1, -1, -1 }   /* Magic end marker */
+} ;
+
+void pwInit ( int x, int y, int w, int h, int multisample,
+              char *title, int border, int num_samples );
+
+
+// ---------------------- public API
+
+void glutInit(int *argc, char **argv)
+{
+currDisplay = NULL ;
+visualInfo  = NULL ;
+
+currScreen  = 0;
+currConnect = 0;
+
+glutReshapeFuncCB=NULL;
+glutKeyboardFuncCB=NULL;
+glutSpecialUpFuncCB=NULL;
+glutSpecialFuncCB=NULL;
+glutMotionFuncCB=NULL;
+glutPassiveMotionFuncCB=NULL;
+glutMouseFuncCB=NULL;
+glutDisplayFuncCB=NULL;
+glutIdleFuncCB=NULL;
+}
+
+
+
+
+void mylgutCloseWindow(void)
+{
+  glXDestroyContext ( currDisplay, currContext ) ;
+  XDestroyWindow    ( currDisplay, currHandle  ) ;
+  XFlush            ( currDisplay ) ;
+}
+
+
+
+//glutSetCursor
+void glutSetCursor(int cursor)
+{
+int currCursor;
+Pixmap pix ;
+char   blank_cursor[16*16];
+XColor bcol = { 0 } ;
+
+switch(cursor)
+    {
+    case GLUT_CURSOR_LEFT_ARROW:
+	currCursor = XC_left_ptr;
+	XDefineCursor( currDisplay, currHandle,
+                 XCreateFontCursor ( currDisplay, currCursor ) ) ;
+	break;
+    case GLUT_CURSOR_NONE:	
+    default:
+	memset(blank_cursor,0,16*16);
+      
+        pix = XCreateBitmapFromData ( currDisplay,
+                                      rootWindow,
+                                      blank_cursor, 16, 16 ) ;
+        XDefineCursor ( currDisplay, currHandle,
+                        XCreatePixmapCursor ( currDisplay,
+                            pix, pix, &bcol, &bcol, 0, 0 ) ) ;
+        XFreePixmap   ( currDisplay, pix ) ;
+        currCursor = 0 ;
+    }
+}
+
+//glutWarpPointer (move mouse)
+void glutWarpPointer(int x, int y)
+{
+  XWarpPointer(currDisplay, None, currHandle, 0, 0, 0, 0, x, y);
+  XFlush(currDisplay);
+}
+
+//glutSwapBuffers
+void glutSwapBuffers(void)
+{
+  glFlush () ;
+  glXSwapBuffers ( currDisplay, currHandle ) ;
+  // get events ?
+}
+
+
+//glutMainLoop is generic (myglut.c)
+
+// ------------- private part
+
+void chooseVisual (PixelFormat *pf)
+{
+  int attribs [ 100 ] ;
+  int n = 0 ;
+
+  attribs [n++] = GLX_RGBA ;
+
+  switch ( pf->bits_per_pixel )
+  {
+    case 3 :
+      attribs [n++] = GLX_RED_SIZE   ; attribs [n++] = 1 ;
+      attribs [n++] = GLX_GREEN_SIZE ; attribs [n++] = 1 ;
+      attribs [n++] = GLX_BLUE_SIZE  ; attribs [n++] = 1 ;
+      break ;
+
+    case 16 :
+      attribs [n++] = GLX_RED_SIZE   ; attribs [n++] = 5 ;
+      attribs [n++] = GLX_GREEN_SIZE ; attribs [n++] = 6 ;
+      attribs [n++] = GLX_BLUE_SIZE  ; attribs [n++] = 5 ;
+      break ;
+
+    case 24 :
+      attribs [n++] = GLX_RED_SIZE   ; attribs [n++] = 8 ;
+      attribs [n++] = GLX_GREEN_SIZE ; attribs [n++] = 8 ;
+      attribs [n++] = GLX_BLUE_SIZE  ; attribs [n++] = 8 ;
+      break ;
+  }
+
+  switch ( pf->z_bits )
+  {
+    case  1 : attribs [n++] = GLX_DEPTH_SIZE ; attribs [n++] =  1 ; break ; 
+    case 16 : attribs [n++] = GLX_DEPTH_SIZE ; attribs [n++] = 16 ; break ; 
+    case 24 : attribs [n++] = GLX_DEPTH_SIZE ; attribs [n++] = 24 ; break ;
+    case 32 : attribs [n++] = GLX_DEPTH_SIZE ; attribs [n++] = 32 ; break ;
+  }
+
+  if ( pf->num_samples > 0 )
+  {
+    attribs [n++] = GLX_SAMPLE_BUFFERS_ARB ; attribs [n++] = 1 ;
+    attribs [n++] = GLX_SAMPLES_ARB        ; attribs [n++] = pf->num_samples ;
+  }
+
+  attribs [n++] = GLX_DOUBLEBUFFER ;
+  attribs [n++] = None ;
+
+  visualInfo = glXChooseVisual ( currDisplay, currScreen, attribs ) ;
+}
+
+
+
+void pwInit ( int x, int y, int w, int h, int multisample,
+              char *title, int border, int num_samples )
+{
+  char *displayName;
+  int i;
+  int origin[2];
+  int size[2];
+
+  XSetWindowAttributes attribs ;
+  XTextProperty   textProperty ;
+  XSizeHints         sizeHints ;
+  XWMHints             wmHints ;
+  unsigned int            mask ;
+  PixelFormat               pf ;
+  
+
+  displayName=getenv ( "DISPLAY" ) ;
+
+  if ( displayName == NULL ) displayName = ":0.0" ;
+
+  currDisplay = XOpenDisplay ( displayName ) ;
+
+  if ( currDisplay == NULL )
+  {
+    raydium_log("(my)glut: ERROR: Can't open display '%s'",
+                            XDisplayName ( displayName ) ) ;
+    exit ( 1 ) ;
+  }
+
+  /* OpenGL GLX extension availability? */
+
+  if ( ! glXQueryExtension ( currDisplay, NULL, NULL ) )
+  {
+    raydium_log("(my)glut: ERROR: GLX extension not available on display '%s'",
+                                             XDisplayName ( displayName ) ) ;
+    exit ( 1 ) ;
+  }
+
+  currScreen   = DefaultScreen    ( currDisplay ) ;
+  rootWindow   = RootWindow       ( currDisplay, currScreen ) ;
+  currConnect  = ConnectionNumber ( currDisplay ) ;
+  delWinAtom   = XInternAtom      ( currDisplay, "WM_DELETE_WINDOW", 0 ) ;
+
+  if ( w == -1 ) w = DisplayWidth  ( currDisplay, currScreen ) ;
+  if ( h == -1 ) h = DisplayHeight ( currDisplay, currScreen ) ;
+
+  origin [ 0 ] = x ;
+  origin [ 1 ] = y ;
+  size   [ 0 ] = w ;
+  size   [ 1 ] = h ;
+
+
+  for (i = 0 ; preferred_pixel_formats [ i ] . num_samples >= 0 ; i++ )
+  {
+    pf = preferred_pixel_formats [ i ] ;
+    pf . num_samples = num_samples ;
+
+    chooseVisual ( &pf ) ;
+
+    if ( visualInfo != NULL )
+      break ;
+  }
+
+  if ( visualInfo == NULL )
+  {
+    num_samples = 0 ;
+
+    for (i = 0 ; preferred_pixel_formats [ i ] . num_samples >= 0 ; i++ )
+    {
+      pf = preferred_pixel_formats [ i ] ;
+      pf . num_samples = num_samples ;
+
+      chooseVisual ( &pf ) ;
+
+      if ( visualInfo != NULL )
+        break ;
+    }
+
+    if ( visualInfo == NULL )
+    {
+      raydium_log("(my)glut: ERROR: Unable to open a suitable window");
+      exit ( 1 ) ;
+    }
+  }
+
+
+  attribs.event_mask = StructureNotifyMask | ExposureMask         |
+                       ButtonPressMask     | ButtonReleaseMask    |
+                       KeyPressMask        | KeyReleaseMask       |
+		       EnterWindowMask     | LeaveWindowMask      |
+                       PointerMotionMask   | ButtonMotionMask     |
+                       VisibilityChangeMask ;
+
+  attribs.background_pixmap = None ;
+  attribs.background_pixel  = 0    ;
+  attribs.border_pixel      = 0    ;
+
+  attribs.colormap = XCreateColormap ( currDisplay, rootWindow,
+                                       visualInfo->visual, AllocNone ) ;
+
+  mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask;
+
+  currHandle = XCreateWindow ( currDisplay, rootWindow,
+                           x, y, w, h, 0, visualInfo->depth,
+                           InputOutput, visualInfo->visual,
+                           mask, &attribs ) ;
+
+  currContext = glXCreateContext ( currDisplay, visualInfo, NULL, 1 ) ;
+
+  glXMakeCurrent ( currDisplay, currHandle, currContext ) ;
+
+  if ( ! glXIsDirect ( currDisplay, glXGetCurrentContext() ) )
+  {
+    raydium_log("(my)glut: WARNING: This is an *INDIRECT* rendering context.") ;
+  }
+
+  sizeHints.flags = 0 ;
+
+  if ( x >= 0 && y >= 0 )
+    sizeHints.flags |= USPosition ;
+
+  sizeHints.flags |= USSize ;
+
+  sizeHints.x      = x ; sizeHints.y      = y ;
+  sizeHints.width  = w ; sizeHints.height = h ;
+
+  wmHints.flags = StateHint;
+  wmHints.initial_state = NormalState ;
+
+  PropMotifWmHints hints  ;
+  Atom prop_t ;
+  Atom prop   ;
+
+  hints . flags = MWM_HINTS_DECORATIONS ;
+  hints . decorations = border ? MWM_DECOR_ALL : 0 ;
+
+  prop_t = prop = XInternAtom ( currDisplay, "_MOTIF_WM_HINTS", True ) ;
+
+  if ( prop != 0 )
+    XChangeProperty ( currDisplay, currHandle, prop, prop_t, 32,
+                      PropModeReplace, (unsigned char *) &hints,
+                      PROP_MOTIF_WM_HINTS_ELEMENTS) ;
+
+  XStringListToTextProperty ( (char **) &title, 1, &textProperty ) ;
+
+  XSetWMProperties ( currDisplay, currHandle,
+	                  &textProperty, &textProperty, 0, 0,
+                          &sizeHints, &wmHints, NULL ) ;
+  XSetWMProtocols  ( currDisplay, currHandle, &delWinAtom  , 1 );
+  XMapWindow       ( currDisplay, currHandle ) ;
+  glXMakeCurrent   ( currDisplay, currHandle, currContext ) ;
+
+  glutSetCursor(GLUT_CURSOR_LEFT_ARROW);
+
+  glClear ( GL_COLOR_BUFFER_BIT ) ;
+  glutSwapBuffers();
+  glClear ( GL_COLOR_BUFFER_BIT ) ;
+  glutSwapBuffers();
+
+  raydium_log("Found %ix%i with %i bits color buffer and %i bits zbuffer",sizeHints.width,sizeHints.height,pf.bits_per_pixel,pf.z_bits);
+}
+
+
+void myglutGetEvents (void)
+{
+  static int size[2]={-1,-1};
+  signed char repeating = 0 ;
+  char keyflags [ 32 ] ;
+  XEvent event ;
+
+  XComposeStatus composeStatus ;
+  char           asciiCode [ 32 ] ;
+  KeySym         keySym ;
+
+  int len,result;
+  signed char special=0;
+
+//  insideCallback = true ;
+
+  while ( XPending ( currDisplay ) )
+  {
+    int updown = GLUT_DOWN ;
+
+    XNextEvent ( currDisplay, &event ) ;
+
+//    refreshModifiers ( &event ) ;
+
+    switch ( event.type )
+    {
+      case ClientMessage   : exit(0) ; break ;
+      case DestroyNotify   : exit(0) ; break ;
+
+      case ConfigureNotify :
+        if ( currHandle == event.xconfigure.window &&
+              ( size[0] != event.xconfigure.width ||
+                size[1] != event.xconfigure.height ) )
+        {
+          size[0] = event.xconfigure.width ;
+          size[1] = event.xconfigure.height ;
+
+          glXMakeCurrent ( currDisplay, currHandle, currContext ) ;
+          glXWaitX    () ;
+
+          if (glutReshapeFuncCB)
+    	    glutReshapeFuncCB(size[0], size[1]);
+        }
+	break;
+
+      case MappingNotify:
+	XRefreshKeyboardMapping ( (XMappingEvent *) &event ) ;
+	break;
+
+      case EnterNotify     :
+      case LeaveNotify     :
+      case VisibilityNotify:
+      case Expose          : break ;
+
+      case MotionNotify    :
+        if (glutPassiveMotionFuncCB)
+         glutPassiveMotionFuncCB( event.xmotion.x, event.xmotion.y);
+        break ;
+
+      case ButtonRelease   :
+        updown = GLUT_UP ;
+        // FALLTHROUGH
+
+      case ButtonPress     :
+        {
+/*          int button = -1 ;
+
+          switch ( event.xbutton.button )
+          {
+            case 1 : button = PW_LEFT_BUTTON   ; break ;
+            case 2 : button = PW_MIDDLE_BUTTON ; break ;
+            case 3 : button = PW_RIGHT_BUTTON  ; break ;
+          }
+*/
+          if (glutMouseFuncCB)
+            glutMouseFuncCB(event.xbutton.button-1, updown, event.xbutton.x, event.xbutton.y ) ;
+        }
+        break ;
+
+      case KeyRelease      :
+        updown = GLUT_UP ;
+
+        XQueryKeymap ( currDisplay, keyflags ) ;
+
+        repeating = ( ( keyflags [ event.xkey.keycode >> 3 ] &
+                          ( 1 << ( event.xkey.keycode & 7 ) ) ) != 0 ) ;
+
+        // FALLTHROUGH 
+
+      case KeyPress        :
+        
+        //  Only generate a key up callback if the key is actually up
+        //  and not repeating.
+
+//        if ( ! autoRepeat && repeating )
+    //      break ;
+
+
+        len = XLookupString( &event.xkey, asciiCode, sizeof(asciiCode),
+                                 &keySym, &composeStatus ) ;
+        result = -1 ;
+
+        if( len > 0 )
+          result = asciiCode[ 0 ] ;
+        else
+        {
+	special=1;
+          switch( keySym )
+          {
+            case XK_F1:     result = GLUT_KEY_F1;     break;
+            case XK_F2:     result = GLUT_KEY_F2;     break;
+            case XK_F3:     result = GLUT_KEY_F3;     break;
+            case XK_F4:     result = GLUT_KEY_F4;     break;
+            case XK_F5:     result = GLUT_KEY_F5;     break;
+            case XK_F6:     result = GLUT_KEY_F6;     break;
+            case XK_F7:     result = GLUT_KEY_F7;     break;
+            case XK_F8:     result = GLUT_KEY_F8;     break;
+            case XK_F9:     result = GLUT_KEY_F9;     break;
+            case XK_F10:    result = GLUT_KEY_F10;    break;
+            case XK_F11:    result = GLUT_KEY_F11;    break;
+            case XK_F12:    result = GLUT_KEY_F12;    break;
+
+            case XK_Left:   result = GLUT_KEY_LEFT;   break;
+            case XK_Right:  result = GLUT_KEY_RIGHT;  break;
+            case XK_Up:     result = GLUT_KEY_UP;     break;
+            case XK_Down:   result = GLUT_KEY_DOWN;   break;
+
+            case XK_KP_Prior:
+            case XK_Prior:  result = GLUT_KEY_PAGE_UP; break;
+            case XK_KP_Next:
+            case XK_Next:   result = GLUT_KEY_PAGE_DOWN; break;
+            case XK_KP_Home:
+            case XK_Home:   result = GLUT_KEY_HOME;   break;
+            case XK_KP_End:
+            case XK_End:    result = GLUT_KEY_END;    break;
+            case XK_KP_Insert:
+            case XK_Insert: result = GLUT_KEY_INSERT; break;
+          }
+        }
+
+	if(result!=-1)
+	    {
+	    // special down
+	    if(special && updown==GLUT_DOWN && glutSpecialFuncCB && !repeating)
+		glutSpecialFuncCB(result,event.xkey.x, event.xkey.y);
+
+	    // special up
+	    if(special && updown==GLUT_UP && glutSpecialUpFuncCB && !repeating)
+		glutSpecialUpFuncCB(result,event.xkey.x, event.xkey.y);
+
+	    // normal
+	    if(!special && updown==GLUT_DOWN && glutKeyboardFuncCB)
+		glutKeyboardFuncCB(result,event.xkey.x, event.xkey.y);
+	    
+	    }
+
+        break ;
+    }
+  }
+
+//  insideCallback = false ;
+
+  glXMakeCurrent ( currDisplay, currHandle, currContext ) ;
+}
+