Index: FL/Fl.H
===================================================================
--- FL/Fl.H	(revision 10483)
+++ FL/Fl.H	(working copy)
@@ -125,6 +125,9 @@
 class FL_EXPORT Fl {
   Fl() {}; // no constructor!
   
+private:
+  static int use_high_res_GL_;
+  
 public: // should be private!
 #ifndef FL_DOXYGEN
   static int e_number;
@@ -1206,6 +1209,16 @@
   static void release_widget_pointer(Fl_Widget *&w);
   static void clear_widget_pointer(Fl_Widget const *w);
   /** @} */
+  
+  /**  sets whether GL windows should be drawn at high resolution on Apple
+   computers with retina displays
+   */
+  static void use_high_res_GL(int val) { use_high_res_GL_ = val; }
+  /**  returns whether GL windows should be drawn at high resolution on Apple
+   computers with retina displays.
+   Default is no.
+   */
+  static int use_high_res_GL() { return use_high_res_GL_; }
 
 #ifdef FLTK_HAVE_CAIRO
   /** \defgroup group_cairo Cairo support functions and classes 
Index: FL/Fl_Gl_Window.H
===================================================================
--- FL/Fl_Gl_Window.H	(revision 10483)
+++ FL/Fl_Gl_Window.H	(working copy)
@@ -89,7 +89,7 @@
     \code
     void mywindow::draw() {
      if (!valid()) {
-       glViewport(0,0,w(),h());
+       glViewport(0,0,pixel_w(),pixel_h());
        glFrustum(...);
        ...other initialization...
      }
@@ -168,7 +168,8 @@
   int mode(int a) {return mode(a,0);}
   /** See Fl_Mode mode() const */
   int mode(const int *a) {return mode(0, a);}
-  /** void See void context(void* v, int destroy_flag) */
+  /** Returns a pointer to the GLContext that this window is using.
+   \see void context(void* v, int destroy_flag) */
   void* context() const {return context_;}
   void context(void*, int destroy_flag = 0);
   void make_current();
@@ -201,6 +202,24 @@
   // Note: Doxygen docs in Fl_Widget.H to avoid redundancy.
   virtual Fl_Gl_Window* as_gl_window() {return this;}
   
+#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+  int pixel_w();
+  int pixel_h();
+#else
+  /** Gives the window width in OpenGL pixels.
+   Generally identical with the result of the w() function, but on macintosh computers
+   with a 'retina' display, and if Fl::use_high_res_GL(bool) is set to true, 
+   pixel_w() returns 2 * w().
+   */
+  int pixel_w() { return w(); }
+  /** Gives the window height in OpenGL pixels.
+   Generally identical with the result of the h() function, but on macintosh computers
+   with a 'retina' display, and if Fl::use_high_res_GL(bool) is set to true,
+   pixel_h() returns 2 * h().
+   */
+  int pixel_h() { return h(); }
+#endif
+  
   ~Fl_Gl_Window();
   /**
     Creates a new Fl_Gl_Window widget using the given size, and label string. 
Index: FL/mac.H
===================================================================
--- FL/mac.H	(revision 10483)
+++ FL/mac.H	(working copy)
@@ -74,8 +74,10 @@
 
 #ifdef __OBJC__
 @class NSCursor;
+@class NSOpenGLPixelFormat;
 #else
 class NSCursor;
+class NSOpenGLPixelFormat;
 #endif // __OBJC__
 
 typedef CGContextRef Fl_Offscreen;
@@ -126,10 +128,15 @@
   Fl_Window *w;            // FLTK window for 
   Fl_Region region;
   CGRect* subRect;         // make sure subwindow remains inside its parent window
-  Fl_X *next;              // linked tree to support subwindows
+  Fl_X *next;              // linked tree of all mapped windows and subwindows.
   int wait_for_expose;
   NSCursor *cursor;
-  bool mapped_to_retina;   // true when window is mapped to a retina display
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+  struct {                 // support for high resolution ('retina') displays
+    unsigned int mapped_to_retina : 1; // true when window is mapped to a retina display
+    unsigned int changed_resolution : 1; // true when window just switched between low and high resolutions
+  } retina;
+#endif
   static Fl_X* first;
   static Fl_X* i(const Fl_Window* w) {return w->i;}
   static int fake_X_wm(const Fl_Window*,int&,int&,int&,int&,int&);
@@ -143,7 +150,8 @@
   static void q_begin_image(CGRect&, int x, int y, int w, int h);
   static void q_end_image();
   // Cocoa additions
-  static CGSize window_pixel_size(Fl_Window* win);
+  static int resolution_scaling_factor(Fl_Window*);
+  static NSOpenGLPixelFormat *mode_to_NSOpenGLPixelFormat(int mode, const int*); // computes NSOpenGLPixelFormat from Gl window's mode
   void destroy(void);
   void map(void);
   void unmap(void);
Index: src/Fl.cxx
===================================================================
--- src/Fl.cxx	(revision 10483)
+++ src/Fl.cxx	(working copy)
@@ -2191,7 +2191,7 @@
   Fl::release_widget_pointer(wp_); // remove pointer from watch list
 }
 
-
+int Fl::use_high_res_GL_ = 0;
 //
 // End of "$Id$".
 //
Index: src/Fl_Gl_Choice.H
===================================================================
--- src/Fl_Gl_Choice.H	(revision 10483)
+++ src/Fl_Gl_Choice.H	(working copy)
@@ -51,11 +51,17 @@
 #  include <FL/gl.h>
 #  define GLContext HGLRC
 #elif defined(__APPLE_QUARTZ__)
-// warning: the Quartz version should probably use Core GL (CGL) instead of AGL
 #  include <OpenGL/gl.h>
-#  include <AGL/agl.h>
-#  define GLContext AGLContext
+#ifdef __OBJC__
+@class NSOpenGLPixelFormat;
+@class NSOpenGLContext;
 #else
+class NSOpenGLPixelFormat;
+class NSOpenGLContext;
+#endif // __OBJC__
+typedef NSOpenGLContext* FLOpenGLContextPtr;
+#  define GLContext FLOpenGLContextPtr
+#else
 #  include <GL/glx.h>
 #  define GLContext GLXContext
 #endif
@@ -70,8 +76,7 @@
   int pixelformat;	// the visual to use
   PIXELFORMATDESCRIPTOR pfd; // some wgl calls need this thing
 #elif defined(__APPLE_QUARTZ__)
-  // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
-  AGLPixelFormat pixelformat;
+  NSOpenGLPixelFormat* pixelformat;
 #else
   XVisualInfo *vis;	// the visual to use
   Colormap colormap;	// a colormap for that visual
@@ -89,7 +94,6 @@
 GLContext fl_create_gl_context(Fl_Window*, const Fl_Gl_Choice*, int layer=0);
 
 #elif defined(__APPLE_QUARTZ__)
-// warning: the Quartz version should probably use Core GL (CGL) instead of AGL
 
 GLContext fl_create_gl_context(Fl_Window*, const Fl_Gl_Choice*, int layer=0);
 
Index: src/Fl_Gl_Choice.cxx
===================================================================
--- src/Fl_Gl_Choice.cxx	(revision 10483)
+++ src/Fl_Gl_Choice.cxx	(working copy)
@@ -28,8 +28,11 @@
 #  include <FL/fl_utf8.h>
 
 #  ifdef __APPLE__
-#    include <ApplicationServices/ApplicationServices.h>
-#    include <FL/Fl_Window.H>
+extern NSOpenGLContext* gl_create_context_for_window(NSOpenGLPixelFormat *pixelformat,
+                                                     NSOpenGLContext *shared_ctx, Fl_Window *window);
+extern void gl_context_release(NSOpenGLContext*);
+extern void gl_context_makecurrent(NSOpenGLContext*);
+extern void gl_cleardrawable(void);
 #  endif
 
 #  ifdef WIN32
@@ -108,53 +111,7 @@
   }
 
 #elif defined(__APPLE_QUARTZ__)
-  // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
-  const int *blist;
-  int list[32];
-   
-  if (alistp)
-    blist = alistp;
-  else {
-    int n = 0;
-    if (m & FL_INDEX) {
-      list[n++] = AGL_BUFFER_SIZE;
-      list[n++] = 8; // glut tries many sizes, but this should work...
-    } else {
-      list[n++] = AGL_RGBA;
-      list[n++] = AGL_GREEN_SIZE;
-      list[n++] = (m & FL_RGB8) ? 8 : 1;
-      if (m & FL_ALPHA) {
-        list[n++] = AGL_ALPHA_SIZE;
-        list[n++] = (m & FL_RGB8) ? 8 : 1;
-      }
-      if (m & FL_ACCUM) {
-        list[n++] = AGL_ACCUM_GREEN_SIZE;
-        list[n++] = 1;
-        if (m & FL_ALPHA) {
-          list[n++] = AGL_ACCUM_ALPHA_SIZE;
-          list[n++] = 1;
-        }
-      }
-    }
-    if (m & FL_DOUBLE) {
-      list[n++] = AGL_DOUBLEBUFFER;
-    }
-    if (m & FL_DEPTH) {
-      list[n++] = AGL_DEPTH_SIZE; list[n++] = 24;
-    }
-    if (m & FL_STENCIL) {
-      list[n++] = AGL_STENCIL_SIZE; list[n++] = 1;
-    }
-#    ifdef AGL_STEREO
-    if (m & FL_STEREO) {
-      list[n++] = AGL_STEREO;
-    }
-#    endif
-    list[n] = AGL_NONE;
-    blist = list;
-  }
-  fl_open_display();
-  AGLPixelFormat fmt = aglChoosePixelFormat(NULL, 0, (GLint*)blist);
+  NSOpenGLPixelFormat* fmt = Fl_X::mode_to_NSOpenGLPixelFormat(m, alistp);
   if (!fmt) return 0;
   
 #elif defined(WIN32)
@@ -216,7 +173,6 @@
   g->pixelformat = pixelformat;
   g->pfd = chosen_pfd;
 #  elif defined(__APPLE_QUARTZ__)
-  // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
   g->pixelformat = fmt;
 #  else
 #    error unsupported platform
@@ -287,38 +243,13 @@
 }
 
 #  elif defined(__APPLE_QUARTZ__)
-#if !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && __LP64__)
-static CGrafPtr fl_GetWindowPort(WindowRef window)
-{
-  typedef CGrafPtr (*wf)(WindowRef);
-  static wf f = NULL;
-  if ( ! f) f = (wf)Fl_X::get_carbon_function("GetWindowPort");
-  return (*f)(window);
-}
-#endif
 
-// warning: the Quartz version should probably use Core GL (CGL) instead of AGL
 GLContext fl_create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int layer) {
   GLContext context, shared_ctx = 0;
   if (context_list && nContext) shared_ctx = context_list[0];
-  context = aglCreateContext( g->pixelformat, shared_ctx);
+  context = gl_create_context_for_window(g->pixelformat, shared_ctx, window);
   if (!context) return 0;
   add_context((GLContext)context);
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
-#if __LP64__
-  // 64 bit version
-  aglSetWindowRef(context, Fl_X::i(window)->window_ref() );
-#else
-  // 32 bit version >= 10.5
-  if (aglSetWindowRef != NULL)
-    aglSetWindowRef(context, Fl_X::i(window)->window_ref() );
-  else
-    aglSetDrawable( context, fl_GetWindowPort( Fl_X::i(window)->window_ref() ) );
-#endif
-#else
-  // 32 bit version < 10.5
-  aglSetDrawable( context, fl_GetWindowPort( Fl_X::i(window)->window_ref() ) );
-#endif
   return (context);
 }
 #  else
@@ -337,23 +268,7 @@
 #  elif defined(WIN32)
     wglMakeCurrent(Fl_X::i(w)->private_dc, context);
 #  elif defined(__APPLE_QUARTZ__)
-    // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
-#if __LP64__
-    // 64 bit version
-    aglSetWindowRef(context, Fl_X::i(w)->window_ref() );
-#else
-    // 32 bit version >= 10.5
-    if (aglSetWindowRef != NULL)
-      aglSetWindowRef(context, Fl_X::i(w)->window_ref() );
-    else
-      aglSetDrawable( context, fl_GetWindowPort( Fl_X::i(w)->window_ref() ) );
-#endif
-#else
-    // 32 bit version < 10.5
-    aglSetDrawable( context, fl_GetWindowPort( Fl_X::i(w)->window_ref() ) );
-#endif
-    aglSetCurrentContext(context);
+    gl_context_makecurrent(context);
 #  else
 #   error unsupported platform
 #  endif
@@ -368,15 +283,7 @@
 #  elif defined(WIN32)
   wglMakeCurrent(0, 0);
 #  elif defined(__APPLE_QUARTZ__)
-  // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
-  AGLContext ctx = aglGetCurrentContext();  
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
-  if (aglSetWindowRef != NULL)
-    { if(ctx) aglSetWindowRef(ctx, NULL ); }
-  else
-#endif
-  if(ctx) aglSetDrawable( ctx, NULL );
-  aglSetCurrentContext(0);
+  gl_cleardrawable();
 #  else
 #    error unsupported platform
 #  endif
@@ -389,8 +296,7 @@
 #  elif defined(WIN32)
   wglDeleteContext(context);
 #  elif defined(__APPLE_QUARTZ__)
-  // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
-  aglDestroyContext( context );
+  gl_context_release(context);
 #  else
 #    error unsupported platform
 #  endif
Index: src/Fl_Gl_Device_Plugin.cxx
===================================================================
--- src/Fl_Gl_Device_Plugin.cxx	(revision 10483)
+++ src/Fl_Gl_Device_Plugin.cxx	(working copy)
@@ -53,10 +53,13 @@
 {
 #if defined(__APPLE__)
   const int bytesperpixel = 4;
+  if (Fl_X::resolution_scaling_factor(glw) > 1) {
+    w = 2*w; h = 2*h; x = 2*x; y = 2*y;
+  }
 #else
   const int bytesperpixel = 3;
 #endif
-  glw->flush(); // forces a GL redraw necessary for the glpuzzle demo
+  glw->flush(); // forces a GL redraw, necessary for the glpuzzle demo
   // Read OpenGL context pixels directly.
   // For extra safety, save & restore OpenGL states that are changed
   glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
@@ -68,7 +71,7 @@
   int mByteWidth = w * bytesperpixel;
   mByteWidth = (mByteWidth + 3) & ~3;    // Align to 4 bytes
   uchar *baseAddress = new uchar[mByteWidth * h];
-  glReadPixels(x, glw->h() - (y+h), w, h,
+  glReadPixels(x, glw->pixel_h() - (y+h), w, h,
 #if defined(__APPLE__)
                GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
 #else
@@ -85,6 +88,11 @@
   return img;
 }
 
+static void imgProviderReleaseData (void *info, const void *data, size_t size)
+{
+  delete (Fl_RGB_Image *)info;
+}
+
 /**
  This class will make sure that OpenGL printing/screen capture is available if fltk_gl
  was linked to the program
@@ -97,7 +105,27 @@
     Fl_Gl_Window *glw = w->as_gl_window();
     if (!glw) return 0;
     Fl_RGB_Image *img = capture_gl_rectangle(glw, 0, 0, glw->w(), glw->h());
-    fl_draw_image(img->array + (glw->h() - 1) * img->ld(), x, y , glw->w(), glw->h(), 3, - img->ld());
+#ifdef __APPLE__
+    if (Fl_Surface_Device::surface()->class_name() == Fl_Printer::class_id) {
+      // convert the image to CGImage, and draw it at full res (useful on retina display)
+      CGColorSpaceRef cSpace = CGColorSpaceCreateDeviceRGB();
+      CGDataProviderRef provider = CGDataProviderCreateWithData(img, img->array, img->ld() * img->h(), imgProviderReleaseData);
+      CGImageRef cgimg = CGImageCreate(img->w(), img->h(), 8, 24, img->ld(), cSpace,
+                                     (CGBitmapInfo)(kCGImageAlphaNone),
+                                     provider, NULL, false, kCGRenderingIntentDefault);
+      CGColorSpaceRelease(cSpace);
+      CGDataProviderRelease(provider);
+      CGContextDrawImage(fl_gc, CGRectMake(0, 0, glw->w(), glw->h()), cgimg);
+      CFRelease(cgimg);
+      return 1;
+    } else if (img->w() > glw->w()) {
+      Fl_RGB_Image *img2 = (Fl_RGB_Image*)img->copy(glw->w(), glw->h());
+      delete img;
+      img = img2;
+    }
+#endif
+    int ld = img->ld() ? img->ld() : img->w() * img->d();
+    fl_draw_image(img->array + (img->h() - 1) * ld, x, y , img->w(), img->h(), 3, - ld);
     delete img;
     return 1;
   }
Index: src/Fl_Gl_Window.cxx
===================================================================
--- src/Fl_Gl_Window.cxx	(revision 10483)
+++ src/Fl_Gl_Window.cxx	(working copy)
@@ -26,10 +26,12 @@
 
 #include <FL/Fl.H>
 #include <FL/x.H>
+#include "Fl_Gl_Choice.H"
 #ifdef __APPLE__
 #include <FL/gl.h>
+extern void gl_context_update(NSOpenGLContext*);
+extern void gl_context_flushbuffer(NSOpenGLContext*);
 #endif
-#include "Fl_Gl_Choice.H"
 #include <FL/Fl_Gl_Window.H>
 #include <stdlib.h>
 #include <FL/fl_utf8.h>
@@ -97,6 +99,20 @@
 #endif /* __APPLE__ */
 }
 
+#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+
+int Fl_Gl_Window::pixel_w()
+{
+  return Fl_X::resolution_scaling_factor(this) * w();
+}
+
+int Fl_Gl_Window::pixel_h()
+{
+  return Fl_X::resolution_scaling_factor(this) * h();
+}
+
+#endif
+
 /**
   The invalidate() method turns off valid() and is
   equivalent to calling value(0).
@@ -140,7 +156,6 @@
       show();
     }
 #elif defined(__APPLE_QUARTZ__)
-    // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
     redraw();
 #else
 #  error unsupported platform
@@ -163,6 +178,14 @@
 void Fl_Gl_Window::make_current() {
 //  puts("Fl_Gl_Window::make_current()");
 //  printf("make_current: context_=%p\n", context_);
+#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+  // detect if the window was moved between low and high resolution displays
+  if (Fl_X::i(this)->retina.changed_resolution){
+    Fl_X::i(this)->retina.changed_resolution = false;
+    invalidate();
+    gl_context_update(context_);
+  }
+#endif
   if (!context_) {
     mode_ &= ~NON_LOCAL_CONTEXT;
     context_ = fl_create_gl_context(this, g);
@@ -170,26 +193,12 @@
     context_valid(0);
 #ifdef __APPLE__
     // resets the pile of string textures used to draw strings
+    // necessary when the context is renewed
     gl_texture_reset();
 #endif
   }
   fl_set_gl_context(this, context_);
 
-#ifdef __APPLE__
-  // Set the buffer rectangle here, since in resize() we won't have the
-  // correct parent window size to work with...
-  GLint xywh[4];
-
-  xywh[0] = 0;
-  xywh[1] = 0;
-  xywh[2] = w();
-  xywh[3] = h();
-
-  aglSetInteger(context_, AGL_BUFFER_RECT, xywh);
-  aglEnable(context_, AGL_BUFFER_RECT);
-//  printf("make_current: xywh=[%d %d %d %d]\n", xywh[0], xywh[1], xywh[2], xywh[3]);
-#endif // __APPLE__
-
 #if defined(WIN32) && USE_COLORMAP
   if (fl_palette) {
     fl_GetDC(fl_xid(this));
@@ -219,8 +228,8 @@
   GLint v[2];
   glGetIntegerv(GL_MAX_VIEWPORT_DIMS, v);
   glLoadIdentity();
-  glViewport(w()-v[0], h()-v[1], v[0], v[1]);
-  glOrtho(w()-v[0], w(), h()-v[1], h(), -1, 1);
+  glViewport(pixel_w()-v[0], pixel_h()-v[1], v[0], v[1]);
+  glOrtho(pixel_w()-v[0], pixel_w(), pixel_h()-v[1], pixel_h(), -1, 1);
 #endif
 }
 
@@ -244,7 +253,7 @@
     // STR# 2944 [1]
     //    Save matrixmode/proj/modelview/rasterpos before doing overlay.
     //
-    int wo=w(), ho=h();
+    int wo=pixel_w(), ho=pixel_h();
     GLint matrixmode;
     GLfloat pos[4];
     glGetIntegerv(GL_MATRIX_MODE, &matrixmode);
@@ -270,8 +279,10 @@
     glMatrixMode(matrixmode);
     glRasterPos3f(pos[0], pos[1], pos[2]);              // restore original glRasterPos
   }
-  else
+  /* // nothing to do here under Cocoa because [NSOpenGLContext -flushBuffer] done later replaces it
+   else
     aglSwapBuffers((AGLContext)context_);
+   */
 #else
 # error unsupported platform
 #endif
@@ -290,19 +301,6 @@
   uchar save_valid_f = valid_f_;
 #endif
 
-#if defined(__APPLE_QUARTZ__)
-  // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
-  //: clear previous clipping in this shared port
-#if ! __LP64__
-/*GrafPtr port = GetWindowPort( Fl_X::i(this)->window_ref() );
-  Rect rect; SetRect( &rect, 0, 0, 0x7fff, 0x7fff );
-  GrafPtr old; GetPort( &old );
-  SetPort( port );
-  ClipRect( &rect );
-  SetPort( old );*/
-#endif
-#endif
-
 #if HAVE_GL_OVERLAY && defined(WIN32)
 
   // Draw into hardware overlay planes if they are damaged:
@@ -383,22 +381,25 @@
 	  glReadBuffer(GL_BACK);
 	  glDrawBuffer(GL_FRONT);
 	  glLoadIdentity();
-	  glViewport(0, 0, w(), h());
-	  glOrtho(0, w(), 0, h(), -1, 1);
+	  glViewport(0, 0, pixel_w(), pixel_h());
+	  glOrtho(0, pixel_w(), 0, pixel_h(), -1, 1);
 	  glRasterPos2i(0,0);
 	  ortho_window = this;
 	}
-	glCopyPixels(0,0,w(),h(),GL_COLOR);
+	glCopyPixels(0,0,pixel_w(),pixel_h(),GL_COLOR);
 	make_current(); // set current context back to draw overlay
 	damage1_ = 0;
 
       } else {
-	damage1_ = damage();
-	clear_damage(0xff); draw();
-	swap_buffers();
+        damage1_ = damage();
+        clear_damage(0xff); draw();
+        swap_buffers();
       }
 
     }
+#ifdef __APPLE__
+    gl_context_flushbuffer(context_);
+#endif
 
     if (overlay==this && SWAP_TYPE != SWAP) { // fake overlay in front buffer
       glDrawBuffer(GL_FRONT);
@@ -423,22 +424,27 @@
 //  printf("Fl_Gl_Window::resize(X=%d, Y=%d, W=%d, H=%d)\n", X, Y, W, H);
 //  printf("current: x()=%d, y()=%d, w()=%d, h()=%d\n", x(), y(), w(), h());
 
-  if (W != w() || H != h()) valid(0);
+  int is_a_resize = (W != Fl_Widget::w() || H != Fl_Widget::h());
+  if (is_a_resize) valid(0);
 
-#ifdef __APPLE__
-  if (X != x() || Y != y() || W != w() || H != h()) aglUpdateContext(context_);
-#elif !defined(WIN32)
-  if ((W != w() || H != h()) && !resizable() && overlay && overlay != this) {
+#if ! ( defined(__APPLE__) || defined(WIN32) )
+  if (is_a_resize && !resizable() && overlay && overlay != this) {
     ((Fl_Gl_Window*)overlay)->resize(0,0,W,H);
   }
 #endif
 
   Fl_Window::resize(X,Y,W,H);
+#ifdef __APPLE__
+  if (is_a_resize) {
+    gl_context_update(context_);
+    redraw();
+  }
+#endif
 }
 
 /**
-  Returns or sets a pointer to the GLContext that this window is
-  using. This is a system-dependent structure, but it is portable to copy
+  Sets a pointer to the GLContext that this window is using.
+  This is a system-dependent structure, but it is portable to copy
   the context from one window to another. You can also set it to NULL,
   which will force FLTK to recreate the context the next time make_current()
   is called, this is useful for getting around bugs in OpenGL implementations.
@@ -540,18 +546,6 @@
  */
 int Fl_Gl_Window::handle(int event) 
 {
-#ifdef __APPLE_QUARTZ__
-  if (event==FL_HIDE) {
-    // if we are not hidden, just the parent was hidden, so we must throw away the context
-    if (!visible_r())
-      context(0); // remove context without setting the hidden flags
-  }
-  if (event==FL_SHOW) {
-    // if we are not hidden, just the parent was shown, so we must create a new context
-    if (visible_r())
-      show(); //
-  }
-#endif
   return Fl_Window::handle(event);
 }
 
Index: src/Fl_cocoa.mm
===================================================================
--- src/Fl_cocoa.mm	(revision 10485)
+++ src/Fl_cocoa.mm	(working copy)
@@ -1106,7 +1106,12 @@
   while ((child = [enumerator nextObject]) != nil) {
     NSRect rchild;
     Fl_Window *sub = [child getFl_Window];
-    Fl_X::i(sub)->mapped_to_retina = Fl_X::i(parent)->mapped_to_retina;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+    Fl_X *subx = Fl_X::i(sub);
+    bool previous = subx->retina.mapped_to_retina;
+    subx->retina.mapped_to_retina = Fl_X::i(parent)->retina.mapped_to_retina;
+    if (previous != subx->retina.mapped_to_retina) subx->retina.changed_resolution = true;
+#endif
     rchild.origin = NSMakePoint(pframe.origin.x + sub->x(), pframe.origin.y + parent->h() - (sub->h() + sub->y()));
     rchild.size = NSMakeSize(sub->w(), sub->h());
     [child setFrame:rchild display:YES];
@@ -1134,21 +1139,23 @@
   }
 }
 
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
 //determines whether the window is mapped to a retina display
 static void compute_mapped_to_retina(Fl_Window *window)
 {
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
   if (fl_mac_os_version >= 100700) { // determine whether window is now mapped to a retina display
-    bool *mapped = &(Fl_X::i(window)->mapped_to_retina);
-    bool previous = *mapped;
-    NSSize s = [[fl_xid(window) contentView] convertSizeToBacking:NSMakeSize(10, 10)];
-    *mapped = (int(s.width + 0.5) > 10);
+    Fl_X *flx = Fl_X::i(window);
+    bool previous = flx->retina.mapped_to_retina;
+    NSSize s = [[flx->xid contentView] convertSizeToBacking:NSMakeSize(10, 10)];
+    flx->retina.mapped_to_retina = (int(s.width + 0.5) > 10);
+    if (previous != flx->retina.mapped_to_retina) flx->retina.changed_resolution = true;
     // window needs redrawn when moving from low res to retina
-    if ((!previous) && *mapped) window->redraw();
+    if ((!previous) && flx->retina.mapped_to_retina) window->redraw();
   }
+}
 #endif
-}
 
+
 @interface FLWindowDelegateBefore10_6 : FLWindowDelegate
 - (id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(id)client;
 @end
@@ -1206,7 +1213,9 @@
     update_e_xy_and_e_xy_root(nsw);
     resize_from_system = NULL;
     window->position((int)pt2.x, (int)(main_screen_height - pt2.y));
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
     compute_mapped_to_retina(window);
+#endif
     position_subwindows(window, YES);
    }
   fl_unlock_function();
@@ -1271,6 +1280,7 @@
   Fl_Window *window = [nsw getFl_Window];
   Fl::handle(FL_SHOW, window);
   update_e_xy_and_e_xy_root(nsw);
+  Fl::flush();
   fl_unlock_function();
 }
 - (void)windowWillMiniaturize:(NSNotification *)notif
@@ -2116,12 +2126,14 @@
 - (void)drawRect:(NSRect)rect
 {
   fl_lock_function();
-  through_drawRect = YES;
   FLWindow *cw = (FLWindow*)[self window];
   Fl_Window *w = [cw getFl_Window];
-  if (fl_x_to_redraw) fl_x_to_redraw->flush();
-  else handleUpdateEvent(w);
-  through_drawRect = NO;
+  if (w->visible()) {
+    through_drawRect = YES;
+    if (fl_x_to_redraw) fl_x_to_redraw->flush();
+    else handleUpdateEvent(w);
+    through_drawRect = NO;
+  }
   fl_unlock_function();
 }
 
@@ -2136,20 +2148,21 @@
   cocoaKeyboardHandler(theEvent);
   BOOL handled;
   NSUInteger mods = [theEvent modifierFlags];
-  if ( (mods & NSControlKeyMask) || (mods & NSCommandKeyMask) ) {
+  Fl_Window *w = [(FLWindow*)[theEvent window] getFl_Window];
+  if ( (mods & NSControlKeyMask) || (mods & NSCommandKeyMask) || (w->as_gl_window() && Fl::focus() == w)) {
     NSString *s = [theEvent characters];
     if ( (mods & NSShiftKeyMask) && (mods & NSCommandKeyMask) ) {
       s = [s uppercaseString]; // US keyboards return lowercase letter in s if cmd-shift-key is hit
       }
     [FLView prepareEtext:s];
     Fl::compose_state = 0;
-    handled = Fl::handle(FL_KEYBOARD, [(FLWindow*)[theEvent window] getFl_Window]);
+    handled = Fl::handle(FL_KEYBOARD, w);
   }
   else {
     in_key_event = YES;
     need_handle = NO;
     handled = [self fl_handle_keydown_event:theEvent];
-    if (need_handle) handled = Fl::handle(FL_KEYBOARD, [(FLWindow*)[theEvent window] getFl_Window]);
+    if (need_handle) handled = Fl::handle(FL_KEYBOARD, w);
     in_key_event = NO;
     }
   fl_unlock_function();
@@ -2212,8 +2225,13 @@
   Fl::first_window(window);
   cocoaKeyboardHandler(theEvent);
   in_key_event = YES;
-  need_handle = NO;
-  [self fl_handle_keydown_event:theEvent];
+  if (window->as_gl_window() && Fl::focus() == window ) { // ignore text input methods for GL windows
+    need_handle = YES;
+    [FLView prepareEtext:[theEvent characters]];
+  } else {
+    need_handle = NO;
+    [self fl_handle_keydown_event:theEvent];
+  }
   if (need_handle) Fl::handle(FL_KEYBOARD, window);
   in_key_event = NO;
   fl_unlock_function();
@@ -2562,6 +2580,112 @@
 }
 @end
 
+
+// For Fl_Gl_Window on retina display, returns 2, otherwise 1
+int Fl_X::resolution_scaling_factor(Fl_Window* win)
+{
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+  return (win->as_gl_window() && Fl::use_high_res_GL() && win->i->retina.mapped_to_retina) ? 2 : 1;
+#else
+  return 1;
+#endif
+}
+
+
+NSOpenGLPixelFormat* Fl_X::mode_to_NSOpenGLPixelFormat(int m, const int *alistp)
+{
+  NSOpenGLPixelFormatAttribute attribs[32];
+  int n = 0;
+  if (!alistp) {
+    if (m & FL_INDEX) {
+      //list[n++] = AGL_BUFFER_SIZE; list[n++] = 8; // glut tries many sizes, but this should work...
+    } else {
+      //list[n++] = AGL_RGBA;
+      //list[n++] = AGL_GREEN_SIZE;
+      //list[n++] = (m & FL_RGB8) ? 8 : 1;
+      attribs[n++] = NSOpenGLPFAColorSize;
+      attribs[n++] = (m & FL_RGB8) ? 24 : 1;
+      if (m & FL_ALPHA) {
+        //list[n++] = AGL_ALPHA_SIZE;
+        attribs[n++] = NSOpenGLPFAAlphaSize;
+        attribs[n++] = (m & FL_RGB8) ? 8 : 1;
+      }
+      if (m & FL_ACCUM) {
+        //list[n++] = AGL_ACCUM_GREEN_SIZE; list[n++] = 1;
+        attribs[n++] = NSOpenGLPFAAccumSize;
+        attribs[n++] = 1;
+        if (m & FL_ALPHA) {
+          //list[n++] = AGL_ACCUM_ALPHA_SIZE; list[n++] = 1;
+        }
+      }
+    }
+    if (m & FL_DOUBLE) {
+      //list[n++] = AGL_DOUBLEBUFFER;
+      attribs[n++] = NSOpenGLPFADoubleBuffer;
+    }
+    if (m & FL_DEPTH) {
+      //list[n++] = AGL_DEPTH_SIZE; list[n++] = 24;
+      attribs[n++] = NSOpenGLPFADepthSize;
+      attribs[n++] = 24;
+    }
+    if (m & FL_STENCIL) {
+      //list[n++] = AGL_STENCIL_SIZE; list[n++] = 1;
+      attribs[n++] = NSOpenGLPFAStencilSize;
+      attribs[n++] = 1;
+    }
+    if (m & FL_STEREO) {
+      //list[n++] = AGL_STEREO;
+      attribs[n++] = NSOpenGLPFAStereo;
+    }
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+    if (fl_mac_os_version >= 100700) {
+      attribs[n++] = NSOpenGLPFAOpenGLProfile;
+      attribs[n++] = NSOpenGLProfileVersionLegacy;
+    }
+#endif
+  } else {
+    while (alistp[n] && n < 30) {
+      attribs[n] = alistp[n];
+      n++;
+    }
+  }
+  attribs[n] = 0;
+  return [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; // I know, it's never released
+}
+
+NSOpenGLContext* gl_create_context_for_window(NSOpenGLPixelFormat *pixelformat,
+                                              NSOpenGLContext *shared_ctx, Fl_Window *window)
+{
+  NSOpenGLContext *context = [[NSOpenGLContext alloc] initWithFormat:pixelformat shareContext:shared_ctx];
+  if (context) [context setView:[fl_xid(window) contentView]];
+  return context;
+}
+
+void gl_context_update(NSOpenGLContext* ctxt)
+{
+  [ctxt update];
+}
+
+void gl_context_flushbuffer(NSOpenGLContext* ctxt)
+{
+  [ctxt flushBuffer];
+}
+
+void gl_context_release(NSOpenGLContext* ctxt)
+{
+  [ctxt release];
+}
+
+void gl_cleardrawable(void)
+{
+  [[NSOpenGLContext currentContext] clearDrawable];
+}
+
+void gl_context_makecurrent(NSOpenGLContext* ctxt)
+{
+  [ctxt makeCurrentContext];
+}
+
 void Fl_Window::fullscreen_x() {
   _set_fullscreen();
   /* On OS X < 10.6, it is necessary to recreate the window. This is done
@@ -2584,15 +2708,19 @@
  */ 
 void Fl_X::flush()
 {
-  if (through_drawRect || w->as_gl_window()) {
-    make_current_counts = 1;
-    w->flush();
-    make_current_counts = 0;
-    Fl_X::q_release_context();
+  if (through_drawRect) {
+    if (w->as_gl_window()) {
+      w->flush();
+    } else {
+      make_current_counts = 1;
+      w->flush();
+      make_current_counts = 0;
+      Fl_X::q_release_context();
+    }
     return;
   }
   // have Cocoa immediately redraw the window's view
-  FLView *view = (FLView*)[fl_xid(w) contentView];
+  FLView *view = (FLView*)[xid contentView];
   fl_x_to_redraw = this;
   [view setNeedsDisplay:YES];
   // will send the drawRect: message to the window's view after having prepared the adequate NSGraphicsContext
@@ -2688,8 +2816,11 @@
     x->subRect = 0;
     x->cursor = NULL;
     x->gc = 0;
-    if (w->parent()) x->mapped_to_retina = w->top_window()->i->mapped_to_retina;
-    else x->mapped_to_retina = false;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+    if (w->parent()) x->retina.mapped_to_retina = w->top_window()->i->retina.mapped_to_retina;
+    else x->retina.mapped_to_retina = false;
+    x->retina.changed_resolution = false;
+#endif
   
     NSRect crect;
     if (w->fullscreen_active()) {
@@ -2753,6 +2884,11 @@
       Fl_X::first = x;
     }
     FLView *myview = [[FLView alloc] initWithFrame:crect];
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+    if (w->as_gl_window() && fl_mac_os_version >= 100700 && Fl::use_high_res_GL()) {
+      [myview setWantsBestResolutionOpenGLSurface:YES];
+    }
+#endif
     [cw setContentView:myview];
     [myview release];
     [cw setLevel:winlevel];
@@ -2807,6 +2943,10 @@
     FLWindow *pxid = fl_xid(w->top_window());
     [pxid makeFirstResponder:[pxid contentView]];
   } else {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+    compute_mapped_to_retina(w);
+    x->retina.changed_resolution = false;
+#endif
     [cw makeKeyAndOrderFront:nil];
   }
   
@@ -2817,7 +2957,6 @@
     crect = [cw frame];
     w->x(int(crect.origin.x));
     w->y(int(main_screen_height - (crect.origin.y + w->h())));
-    compute_mapped_to_retina(w);
   }
   
     int old_event = Fl::e_number;
@@ -3006,7 +3145,9 @@
   if (make_current_counts) make_current_counts++;
   Fl_X::q_release_context();
   fl_window = i->xid;
-  Fl_X::set_high_resolution( i->mapped_to_retina );
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+  Fl_X::set_high_resolution( i->retina.mapped_to_retina );
+#endif
   current_ = this;
   
   NSGraphicsContext *nsgc = through_drawRect ? [NSGraphicsContext currentContext] :
@@ -3895,6 +4036,7 @@
 
 static NSBitmapImageRep* GL_rect_to_nsbitmap(Fl_Window *win, int x, int y, int w, int h)
 // captures a rectangle from a GL window and returns it as an allocated NSBitmapImageRep
+// the capture has high res on retina
 {
   Fl_Plugin_Manager pm("fltk:device");
   Fl_Device_Plugin *pi = (Fl_Device_Plugin*)pm.plugin("opengl.device.fltk.org");
Index: src/gl_draw.cxx
===================================================================
--- src/gl_draw.cxx	(revision 10483)
+++ src/gl_draw.cxx	(working copy)
@@ -36,9 +36,9 @@
 #include "Xutf8.h"
 #endif
 
-#if USE_XFT
-//extern XFontStruct* fl_xxfont();
-#endif // USE_XFT
+#ifdef __APPLE__
+static int gl_scale = 1; // set to 2 for high resolution Fl_Gl_Window
+#endif
 
 /** Returns the current font's height */
 int   gl_height() {return fl_height();}
@@ -53,11 +53,8 @@
 
 static Fl_Font_Descriptor *gl_fontsize;
 
-#define GL_DRAW_USES_TEXTURES  (defined(__APPLE__) && !__ppc__) // 1 only for non-PPC OSX
 #ifndef __APPLE__
 #  define USE_OksiD_style_GL_font_selection 1  // Most hosts except OSX
-#else
-#  undef USE_OksiD_style_GL_font_selection  // OSX
 #endif
 
 #if USE_XFT
@@ -70,7 +67,7 @@
 void  gl_font(int fontid, int size) {
   fl_font(fontid, size);
   Fl_Font_Descriptor *fl_fontsize = fl_graphics_driver->font_descriptor();
-#if !GL_DRAW_USES_TEXTURES
+#ifndef __APPLE__
   if (!fl_fontsize->listbase) {
 
 #ifdef  USE_OksiD_style_GL_font_selection
@@ -97,28 +94,12 @@
     fl_fontsize->listbase = glGenLists(256);
     wglUseFontBitmaps(fl_gc, base, count, fl_fontsize->listbase+base);
     SelectObject(fl_gc, oldFid);
-# elif defined(__APPLE_QUARTZ__)
-//AGL is not supported for use in 64-bit applications:
-//http://developer.apple.com/mac/library/documentation/Carbon/Conceptual/Carbon64BitGuide/OtherAPIChanges/OtherAPIChanges.html
-    short font, face, size;
-    uchar fn[256];
-    const char *pname = Fl::get_font_name(fontid, NULL);
-    fn[0]=strlen(pname);
-    strcpy((char*)(fn+1), pname);
-    GetFNum(fn, &font);
-    face = 0;
-    size = fl_fontsize->size;
-    fl_fontsize->listbase = glGenLists(256);
-	aglUseFont(aglGetCurrentContext(), font, face,
-               size, 0, 256, fl_fontsize->listbase);
-# else 
-#   error unsupported platform
 # endif
 
 #endif // USE_OksiD_style_GL_font_selection
   }
   glListBase(fl_fontsize->listbase);
-#endif // !GL_DRAW_USES_TEXTURES
+#endif // !__APPLE__
   gl_fontsize = fl_fontsize;
 }
 
@@ -143,8 +124,6 @@
   HFONT oldFid = (HFONT)SelectObject(fl_gc, gl_fontsize->fid);
   wglUseFontBitmapsW(fl_gc, ii, ii + 0x03ff, gl_fontsize->listbase+ii);
   SelectObject(fl_gc, oldFid);
-#elif defined(__APPLE_QUARTZ__)
-// handled by textures
 #else
 #  error unsupported platform
 #endif
@@ -189,7 +168,7 @@
 #endif
 }
 
-#if GL_DRAW_USES_TEXTURES
+#if __APPLE__
 static void gl_draw_textures(const char* str, int n);
 #endif
 
@@ -200,14 +179,8 @@
   */
 void gl_draw(const char* str, int n) {
 #ifdef __APPLE__  
-  
-#if GL_DRAW_USES_TEXTURES
   gl_draw_textures(str, n);
 #else
-  glCallLists(n, GL_UNSIGNED_BYTE, str);
-#endif
-  
-#else
   static xchar *buf = NULL;
   static int l = 0;
   int wn = fl_utf8toUtf16(str, n, (unsigned short*)buf, l);
@@ -284,11 +257,13 @@
   const char* str, 	// the (multi-line) string
   int x, int y, int w, int h, 	// bounding box
   Fl_Align align) {
-  fl_draw(str, x, -y-h, w, h, align, gl_draw_invert);
+  fl_draw(str, x, -y-h, w, h, align, gl_draw_invert, NULL, 0);
 }
 
 /** Measure how wide and tall the string will be when drawn by the gl_draw() function */
-void gl_measure(const char* str, int& x, int& y) {fl_measure(str,x,y);}
+void gl_measure(const char* str, int& x, int& y) {
+  fl_measure(str,x,y,0);
+}
 
 /**
   Outlines the given rectangle with the current color.
@@ -350,9 +325,9 @@
   glDrawPixels(w,h,d<4?GL_RGB:GL_RGBA,GL_UNSIGNED_BYTE,(const ulong*)b);
 }
 
-#if GL_DRAW_USES_TEXTURES || defined(FL_DOXYGEN)
+#if __APPLE__ || defined(FL_DOXYGEN)
 
-#include <FL/glu.h>
+#include <FL/glu.h>  // for gluUnProject()
 
 // manages a fifo pile of pre-computed string textures
 class gl_texture_fifo {
@@ -364,6 +339,7 @@
     Fl_Font_Descriptor *fdesc; // its font
     int width; // its width
     int height; // its height
+    int scale; // 1 or 2 for low/high resolution
   } data;
   data *fifo; // array of pile elements
   int size_; // pile height
@@ -408,14 +384,14 @@
   glMatrixMode (GL_MODELVIEW);
   glPushMatrix();
   glLoadIdentity ();
-  float winw = Fl_Window::current()->w();
-  float winh = Fl_Window::current()->h();
+  float winw = gl_scale * Fl_Window::current()->w();
+  float winh = gl_scale * Fl_Window::current()->h();
   glScalef (2.0f / winw, 2.0f /  winh, 1.0f);
   glTranslatef (-winw / 2.0f, -winh / 2.0f, 0.0f);
   //write the texture on screen
   GLfloat pos[4];
   glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
-  CGRect bounds = CGRectMake (pos[0], pos[1] - fl_descent(), fifo[rank].width, fifo[rank].height);
+  CGRect bounds = CGRectMake (pos[0], pos[1] - gl_scale*fl_descent(), fifo[rank].width, fifo[rank].height);
   
   // GL_COLOR_BUFFER_BIT for glBlendFunc, GL_ENABLE_BIT for glEnable / glDisable
   glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT); 
@@ -471,6 +447,9 @@
   fifo[current].utf8[n] = 0;
   fifo[current].width = 0, fifo[current].height = 0;
   fl_measure(fifo[current].utf8, fifo[current].width, fifo[current].height, 0);
+  fifo[current].width *= gl_scale;
+  fifo[current].height *= gl_scale;
+  fifo[current].scale = gl_scale;
   CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB();
   void *base = calloc(4*fifo[current].width, fifo[current].height);
   if (base == NULL) return -1;
@@ -481,8 +460,10 @@
   GLfloat colors[4];
   glGetFloatv(GL_CURRENT_COLOR, colors);
   fl_color((uchar)(colors[0]*255), (uchar)(colors[1]*255), (uchar)(colors[2]*255));
-  fl_draw(str, n, 0, fifo[current].height - fl_descent());
-  //put this bitmap in a texture  
+  CGContextTranslateCTM(fl_gc, 0, fifo[current].height - gl_scale*fl_descent());
+  CGContextScaleCTM(fl_gc, gl_scale, gl_scale);
+  fl_draw(str, n, 0, 0);
+  //put this bitmap in a texture
   glPushAttrib(GL_TEXTURE_BIT);
   glBindTexture (GL_TEXTURE_RECTANGLE_EXT, fifo[current].texName);
   glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -502,7 +483,7 @@
   int rank;
   for ( rank = 0; rank <= last; rank++) {
     if ( memcmp(str, fifo[rank].utf8, n) == 0 && fifo[rank].utf8[n] == 0 &&
-      fifo[rank].fdesc == gl_fontsize) return rank;
+      fifo[rank].fdesc == gl_fontsize && fifo[rank].scale == gl_scale) return rank;
   }
   return -1;
 }
@@ -512,6 +493,8 @@
 // draws a utf8 string using pre-computed texture if available
 static void gl_draw_textures(const char* str, int n) 
 {
+  gl_scale = Fl_X::resolution_scaling_factor(Fl_Window::current());
+  //fprintf(stderr,"gl_scale=%d\n",gl_scale);
   if (! gl_fifo) gl_fifo = new gl_texture_fifo();
   if (!gl_fifo->textures_generated) {
     for (int i = 0; i < gl_fifo->size_; i++) glGenTextures (1, &(gl_fifo->fifo[i].texName));
@@ -553,17 +536,9 @@
 
 /** @} */
 
-#elif defined(__APPLE__)
-// used only if __ppc__
-int gl_texture_pile_height(void) {return 0;}
-void gl_texture_pile_height(int max) {}
-#endif // GL_DRAW_USES_TEXTURES
-#if defined(__APPLE__)
 void gl_texture_reset()
 {
-#if GL_DRAW_USES_TEXTURES
   if (gl_fifo) gl_texture_pile_height(gl_texture_pile_height());
-#endif // GL_DRAW_USES_TEXTURES
 }
 #endif // __APPLE__
 
Index: src/gl_start.cxx
===================================================================
--- src/gl_start.cxx	(revision 10483)
+++ src/gl_start.cxx	(working copy)
@@ -48,6 +48,7 @@
 
 #ifdef __APPLE__
 static Fl_Gl_Choice* gl_choice;
+extern void gl_context_update(NSOpenGLContext*);
 #endif
 
 Fl_Region XRectangleRegion(int x, int y, int w, int h); // in fl_rect.cxx
@@ -61,14 +62,15 @@
     if (!gl_choice) Fl::gl_visual(0);
     context = fl_create_gl_context(Fl_Window::current(), gl_choice);
 #elif defined(__APPLE_QUARTZ__)
-    // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
     context = fl_create_gl_context(Fl_Window::current(), gl_choice);
 #else
 #  error Unsupported platform
 #endif
   }
   fl_set_gl_context(Fl_Window::current(), context);
-#if !defined(WIN32) && !defined(__APPLE__)
+#ifdef __APPLE__
+  gl_context_update(context); // supports window resizing
+#elif !defined(WIN32)
   glXWaitX();
 #endif
   if (pw != Fl_Window::current()->w() || ph != Fl_Window::current()->h()) {
@@ -110,7 +112,6 @@
 #elif defined(WIN32)
   gl_choice = c;
 #elif defined(__APPLE_QUARTZ__)
-  // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
   gl_choice = c;
 #else
 #  error Unsupported platform
Index: src/glut_compatability.cxx
===================================================================
--- src/glut_compatability.cxx	(revision 10483)
+++ src/glut_compatability.cxx	(working copy)
@@ -38,6 +38,9 @@
 #    include <dlfcn.h>
 #  endif // HAVE_DLFCN_H
 #  define MAXWINDOWS 32
+#  ifdef __APPLE__
+#    include <FL/x.H>
+#  endif
 static Fl_Glut_Window *windows[MAXWINDOWS+1];
 
 static void (*glut_idle_func)() = 0; // global glut idle function
@@ -59,7 +62,7 @@
 void Fl_Glut_Window::draw() {
   glut_window = this;
   indraw = 1;
-  if (!valid()) {reshape(w(),h()); valid(1);}
+  if (!valid()) {reshape(pixel_w(),pixel_h()); valid(1);}
   display();
   indraw = 0;
 }
@@ -70,7 +73,7 @@
 
 void Fl_Glut_Window::draw_overlay() {
   glut_window = this;
-  if (!valid()) {reshape(w(),h()); valid(1);}
+  if (!valid()) {reshape(pixel_w(),pixel_h()); valid(1);}
   overlaydisplay();
 }
 
@@ -80,6 +83,13 @@
   make_current();
   int ex = Fl::event_x();
   int ey = Fl::event_y();
+#ifdef __APPLE__
+  if (shown()) {
+    int factor = Fl_X::resolution_scaling_factor(this);
+    ex *= factor;
+    ey *= factor;
+  }
+#endif
   int button;
   switch (event) {
 
@@ -377,8 +387,8 @@
   case GLUT_RETURN_ZERO: return 0;
   case GLUT_WINDOW_X: return glut_window->x();
   case GLUT_WINDOW_Y: return glut_window->y();
-  case GLUT_WINDOW_WIDTH: return glut_window->w();
-  case GLUT_WINDOW_HEIGHT: return glut_window->h();
+  case GLUT_WINDOW_WIDTH: return glut_window->pixel_w();
+  case GLUT_WINDOW_HEIGHT: return glut_window->pixel_h();
   case GLUT_WINDOW_PARENT:
     if (glut_window->parent())
       return ((Fl_Glut_Window *)(glut_window->parent()))->number;
Index: test/cube.cxx
===================================================================
--- test/cube.cxx	(revision 10483)
+++ test/cube.cxx	(working copy)
@@ -94,7 +94,7 @@
   lasttime = lasttime+speed;
   if (!valid()) {
     glLoadIdentity();
-    glViewport(0,0,w(),h());
+    glViewport(0,0,pixel_w(),pixel_h());
     glEnable(GL_DEPTH_TEST);
     glFrustum(-1,1,-1,1,2,10000);
     glTranslatef(0,0,-10);
@@ -167,6 +167,7 @@
 // end of printing demo
 
 int main(int argc, char **argv) {
+  Fl::use_high_res_GL(1);
   makeform(argv[0]);
   // added to demo printing
   form->begin();
Index: test/fractals.cxx
===================================================================
--- test/fractals.cxx	(revision 10483)
+++ test/fractals.cxx	(working copy)
@@ -768,6 +768,7 @@
 
 int main(int argc, char** argv)
 {
+  Fl::use_high_res_GL(1);
 //  glutInit(&argc, argv); // this line removed for FLTK
 
   // create FLTK window:
Index: test/fullscreen.cxx
===================================================================
--- test/fullscreen.cxx	(revision 10483)
+++ test/fullscreen.cxx	(working copy)
@@ -84,7 +84,7 @@
     valid(1);
 //  printf("init\n");
     glLoadIdentity();
-    glViewport(0,0,w(),h());
+    glViewport(0,0,pixel_w(),pixel_h());
   }
   glClear(GL_COLOR_BUFFER_BIT);
   glColor3f(.5,.6,.7);
@@ -267,6 +267,7 @@
 
 int main(int argc, char **argv) {
 
+  Fl::use_high_res_GL(1);
   int i=0;
   if (Fl::args(argc,argv,i,arg) < argc)
     Fl::fatal("Options are:\n -2 = 2 windows\n -f = startup fullscreen\n%s",Fl::help);
Index: test/gl_overlay.cxx
===================================================================
--- test/gl_overlay.cxx	(revision 10483)
+++ test/gl_overlay.cxx	(working copy)
@@ -57,7 +57,7 @@
   if (!valid()) {
     valid(1);
     glLoadIdentity();
-    glViewport(0,0,w(),h());
+    glViewport(0,0,pixel_w(),pixel_h());
   }
 // draw an amazing but slow graphic:
   glClear(GL_COLOR_BUFFER_BIT);
@@ -78,7 +78,7 @@
   if (!valid()) {
     valid(1);
     glLoadIdentity();
-    glViewport(0,0,w(),h());
+    glViewport(0,0,pixel_w(),pixel_h());
   }
 // draw an amazing graphic:
   gl_color(FL_RED);
@@ -108,6 +108,7 @@
 #include <stdio.h>
 int main(int argc, char **argv) {
 
+  Fl::use_high_res_GL(1);
   Fl_Window window(300, 370);
 
   shape_window sw(10, 75, window.w()-20, window.h()-90);
Index: test/glpuzzle.cxx
===================================================================
--- test/glpuzzle.cxx	(revision 10483)
+++ test/glpuzzle.cxx	(working copy)
@@ -1,1477 +1,228 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <FL/Fl.H>
+#include <FL/Fl_Window.H>
+#include <FL/Fl_Gl_Window.H>
+#include <FL/gl.h>
+#include <FL/Fl_Shared_Image.H>	// fl_register_images()
 //
-// "$Id$"
+// OpenGL spinning cube with PNG image texturemap -- erco/ian 03/23/09
 //
-// OpenGL puzzle demo for the Fast Light Tool Kit (FLTK).
+//     Assumes /tmp/texture-128.png exists, and x/y res is 64x64, 128x128, etc.
+//     For an example image, see http://seriss.com/people/erco/fltk/texture-128.png
 //
-// This is a GLUT demo program to demonstrate fltk's GLUT emulation.
-// Search for "fltk" to find all the changes
+//     Builds with:
+//     fltk-config --use-gl --use-images --compile foo.cxx
 //
-// Copyright 1998-2010 by Bill Spitzak and others.
+#define WIN_W 400       // window width
+#define WIN_H 400       // window height
+#define FPS (1.0/24.0)  // frames per second playback
 //
-// This library is free software. Distribution and use rights are outlined in
-// the file "COPYING" which should have been included with this file.  If this
-// file is missing or damaged, see the license at:
+// OpenGL class to show texturemapped cube
 //
-//     http://www.fltk.org/COPYING.php
-//
-// Please report all bugs and problems on the following page:
-//
-//     http://www.fltk.org/str.php
-//
-
-// this block added for fltk's distribtion so it will compile w/o OpenGL:
-#include <config.h>
-#if !HAVE_GL || !HAVE_GL_GLU_H
-#include <FL/Fl.H>
-#include <FL/fl_message.H>
-int main(int, char**) {
-  fl_alert("This demo does not work without GL and GLU");
-  return 1;
-}
-#else
-// end of added block
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <time.h>
-#include <math.h>
-#include <FL/glut.H>	// changed for fltk
-#include <FL/glu.h>     // added for fltk
-#include "trackball.c"	// changed from trackball.h for fltk
-
-#define WIDTH 4
-#define HEIGHT 5
-#define PIECES 10
-#define OFFSETX -2
-#define OFFSETY -2.5
-#define OFFSETZ -0.5
-
-typedef char Config[HEIGHT][WIDTH];
-
-struct puzzle {
-  struct puzzle *backptr;
-  struct puzzle *solnptr;
-  Config pieces;
-  struct puzzle *next;
-  unsigned hashvalue;
-};
-
-#define HASHSIZE 10691
-
-struct puzzlelist {
-  struct puzzle *puzzle;
-  struct puzzlelist *next;
-};
-
-static char convert[PIECES + 1] =
-{0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 4};
-
-static unsigned char colors[PIECES + 1][3] =
-{
-  {0, 0, 0},
-  {255, 255, 127},
-  {255, 255, 127},
-  {255, 255, 127},
-  {255, 255, 127},
-  {255, 127, 255},
-  {255, 127, 255},
-  {255, 127, 255},
-  {255, 127, 255},
-  {255, 127, 127},
-  {255, 255, 255},
-};
-
-void changeState(void);
-
-static struct puzzle *hashtable[HASHSIZE];
-static struct puzzle *startPuzzle;
-static struct puzzlelist *puzzles;
-static struct puzzlelist *lastentry;
-
-int curX, curY, visible;
-
-#define MOVE_SPEED 0.2
-static unsigned char movingPiece;
-static float move_x, move_y;
-static float curquat[4];
-static int doubleBuffer = 1;
-static int depth = 1;
-
-static char xsize[PIECES + 1] =
-{0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2};
-static char ysize[PIECES + 1] =
-{0, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2};
-static float zsize[PIECES + 1] =
-{0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.6};
-
-static Config startConfig =
-{
-  {8, 10, 10, 7},
-  {8, 10, 10, 7},
-  {6, 9, 9, 5},
-  {6, 4, 3, 5},
-  {2, 0, 0, 1}
-};
-
-static Config thePuzzle =
-{
-  {8, 10, 10, 7},
-  {8, 10, 10, 7},
-  {6, 9, 9, 5},
-  {6, 4, 3, 5},
-  {2, 0, 0, 1}
-};
-
-static int xadds[4] =
-{-1, 0, 1, 0};
-static int yadds[4] =
-{0, -1, 0, 1};
-
-static long W = 400, H = 300;
-static GLint viewport[4];
-
-#define srandom srand
-#define random() (rand() >> 2)
-
-unsigned
-hash(Config config)
-{
-  int i, j, value;
-
-  value = 0;
-  for (i = 0; i < HEIGHT; i++) {
-    for (j = 0; j < WIDTH; j++) {
-      value = value + convert[(int)config[i][j]];
-      value *= 6;
-    }
+class MyGlWindow : public Fl_Gl_Window {
+  double spin;
+  GLuint TexID;
+  const char *texturefilename;
+  // TIMER CALLBACK
+  //    Handles rotation the object
+  //
+  static void Timer_CB(void *userdata) {
+    MyGlWindow *mygl = (MyGlWindow*)userdata;
+    mygl->spin += 2.0;       // spin
+    mygl->redraw();
+    Fl::repeat_timeout(FPS, Timer_CB, userdata);
   }
-  return (value);
-}
-
-int
-solution(Config config)
-{
-  if (config[4][1] == 10 && config[4][2] == 10)
-    return (1);
-  return (0);
-}
-
-float boxcoords[][3] =
-{
-  {0.2, 0.2, 0.9},
-  {0.8, 0.2, 0.9},
-  {0.8, 0.8, 0.9},
-  {0.2, 0.8, 0.9},
-  {0.2, 0.1, 0.8},
-  {0.8, 0.1, 0.8},
-  {0.9, 0.2, 0.8},
-  {0.9, 0.8, 0.8},
-  {0.8, 0.9, 0.8},
-  {0.2, 0.9, 0.8},
-  {0.1, 0.8, 0.8},
-  {0.1, 0.2, 0.8},
-  {0.2, 0.1, 0.2},
-  {0.8, 0.1, 0.2},
-  {0.9, 0.2, 0.2},
-  {0.9, 0.8, 0.2},
-  {0.8, 0.9, 0.2},
-  {0.2, 0.9, 0.2},
-  {0.1, 0.8, 0.2},
-  {0.1, 0.2, 0.2},
-  {0.2, 0.2, 0.1},
-  {0.8, 0.2, 0.1},
-  {0.8, 0.8, 0.1},
-  {0.2, 0.8, 0.1},
-};
-
-float boxnormals[][3] =
-{
-  {0, 0, 1},            /* 0 */
-  {0, 1, 0},
-  {1, 0, 0},
-  {0, 0, -1},
-  {0, -1, 0},
-  {-1, 0, 0},
-  {0.7071, 0.7071, 0.0000},  /* 6 */
-  {0.7071, -0.7071, 0.0000},
-  {-0.7071, 0.7071, 0.0000},
-  {-0.7071, -0.7071, 0.0000},
-  {0.7071, 0.0000, 0.7071},  /* 10 */
-  {0.7071, 0.0000, -0.7071},
-  {-0.7071, 0.0000, 0.7071},
-  {-0.7071, 0.0000, -0.7071},
-  {0.0000, 0.7071, 0.7071},  /* 14 */
-  {0.0000, 0.7071, -0.7071},
-  {0.0000, -0.7071, 0.7071},
-  {0.0000, -0.7071, -0.7071},
-  {0.5774, 0.5774, 0.5774},  /* 18 */
-  {0.5774, 0.5774, -0.5774},
-  {0.5774, -0.5774, 0.5774},
-  {0.5774, -0.5774, -0.5774},
-  {-0.5774, 0.5774, 0.5774},
-  {-0.5774, 0.5774, -0.5774},
-  {-0.5774, -0.5774, 0.5774},
-  {-0.5774, -0.5774, -0.5774},
-};
-
-int boxfaces[][4] =
-{
-  {0, 1, 2, 3},         /* 0 */
-  {9, 8, 16, 17},
-  {6, 14, 15, 7},
-  {20, 23, 22, 21},
-  {12, 13, 5, 4},
-  {19, 11, 10, 18},
-  {7, 15, 16, 8},       /* 6 */
-  {13, 14, 6, 5},
-  {18, 10, 9, 17},
-  {19, 12, 4, 11},
-  {1, 6, 7, 2},         /* 10 */
-  {14, 21, 22, 15},
-  {11, 0, 3, 10},
-  {20, 19, 18, 23},
-  {3, 2, 8, 9},         /* 14 */
-  {17, 16, 22, 23},
-  {4, 5, 1, 0},
-  {20, 21, 13, 12},
-  {2, 7, 8, -1},        /* 18 */
-  {16, 15, 22, -1},
-  {5, 6, 1, -1},
-  {13, 21, 14, -1},
-  {10, 3, 9, -1},
-  {18, 17, 23, -1},
-  {11, 4, 0, -1},
-  {20, 12, 19, -1},
-};
-
-#define NBOXFACES (sizeof(boxfaces)/sizeof(boxfaces[0]))
-
-/* Draw a box.  Bevel as desired. */
-void
-drawBox(int piece, float xoff, float yoff)
-{
-  int xlen, ylen;
-  int i, k;
-  float x, y, z;
-  float zlen;
-  float *v;
-
-  xlen = xsize[piece];
-  ylen = ysize[piece];
-  zlen = zsize[piece];
-
-  glColor3ubv(colors[piece]);
-  glBegin(GL_QUADS);
-  for (i = 0; i < 18; i++) {
-    glNormal3fv(boxnormals[i]);
-    for (k = 0; k < 4; k++) {
-      if (boxfaces[i][k] == -1)
-        continue;
-      v = boxcoords[boxfaces[i][k]];
-      x = v[0] + OFFSETX;
-      if (v[0] > 0.5)
-        x += xlen - 1;
-      y = v[1] + OFFSETY;
-      if (v[1] > 0.5)
-        y += ylen - 1;
-      z = v[2] + OFFSETZ;
-      if (v[2] > 0.5)
-        z += zlen - 1;
-      glVertex3f(xoff + x, yoff + y, z);
-    }
+public:
+  // CTOR
+  MyGlWindow(int x,int y,int w,int h,const char *l=0) : Fl_Gl_Window(x,y,w,h,l) {
+    spin = 0.0;
+    Fl::add_timeout(FPS, Timer_CB, (void*)this);       // 24fps timer
+    texturefilename = "/tmp/texture-128.png";
+    end();
   }
-  glEnd();
-  glBegin(GL_TRIANGLES);
-  for (i = 18; i < int(NBOXFACES); i++) {
-    glNormal3fv(boxnormals[i]);
-    for (k = 0; k < 3; k++) {
-      if (boxfaces[i][k] == -1)
-        continue;
-      v = boxcoords[boxfaces[i][k]];
-      x = v[0] + OFFSETX;
-      if (v[0] > 0.5)
-        x += xlen - 1;
-      y = v[1] + OFFSETY;
-      if (v[1] > 0.5)
-        y += ylen - 1;
-      z = v[2] + OFFSETZ;
-      if (v[2] > 0.5)
-        z += zlen - 1;
-      glVertex3f(xoff + x, yoff + y, z);
-    }
+  void TextureFilename(const char *val) {
+    texturefilename = val;
   }
-  glEnd();
-}
-
-float containercoords[][3] =
-{
-  {-0.1, -0.1, 1.0},
-  {-0.1, -0.1, -0.1},
-  {4.1, -0.1, -0.1},
-  {4.1, -0.1, 1.0},
-  {1.0, -0.1, 0.6},     /* 4 */
-  {3.0, -0.1, 0.6},
-  {1.0, -0.1, 0.0},
-  {3.0, -0.1, 0.0},
-  {1.0, 0.0, 0.0},      /* 8 */
-  {3.0, 0.0, 0.0},
-  {3.0, 0.0, 0.6},
-  {1.0, 0.0, 0.6},
-  {0.0, 0.0, 1.0},      /* 12 */
-  {4.0, 0.0, 1.0},
-  {4.0, 0.0, 0.0},
-  {0.0, 0.0, 0.0},
-  {0.0, 5.0, 0.0},      /* 16 */
-  {0.0, 5.0, 1.0},
-  {4.0, 5.0, 1.0},
-  {4.0, 5.0, 0.0},
-  {-0.1, 5.1, -0.1},    /* 20 */
-  {4.1, 5.1, -0.1},
-  {4.1, 5.1, 1.0},
-  {-0.1, 5.1, 1.0},
-};
-
-float containernormals[][3] =
-{
-  {0, -1, 0},
-  {0, -1, 0},
-  {0, -1, 0},
-  {0, -1, 0},
-  {0, -1, 0},
-  {0, 1, 0},
-  {0, 1, 0},
-  {0, 1, 0},
-  {1, 0, 0},
-  {1, 0, 0},
-  {1, 0, 0},
-  {-1, 0, 0},
-  {-1, 0, 0},
-  {-1, 0, 0},
-  {0, 1, 0},
-  {0, 0, -1},
-  {0, 0, -1},
-  {0, 0, 1},
-  {0, 0, 1},
-  {0, 0, 1},
-  {0, 0, 1},
-  {0, 0, 1},
-  {0, 0, 1},
-  {0, 0, 1},
-};
-
-int containerfaces[][4] =
-{
-  {1, 6, 4, 0},
-  {0, 4, 5, 3},
-  {1, 2, 7, 6},
-  {7, 2, 3, 5},
-  {16, 19, 18, 17},
-
-  {23, 22, 21, 20},
-  {12, 11, 8, 15},
-  {10, 13, 14, 9},
-
-  {15, 16, 17, 12},
-  {2, 21, 22, 3},
-  {6, 8, 11, 4},
-
-  {1, 0, 23, 20},
-  {14, 13, 18, 19},
-  {9, 7, 5, 10},
-
-  {12, 13, 10, 11},
-
-  {1, 20, 21, 2},
-  {4, 11, 10, 5},
-
-  {15, 8, 19, 16},
-  {19, 8, 9, 14},
-  {8, 6, 7, 9},
-  {0, 3, 13, 12},
-  {13, 3, 22, 18},
-  {18, 22, 23, 17},
-  {17, 23, 0, 12},
-};
-
-#define NCONTFACES (sizeof(containerfaces)/sizeof(containerfaces[0]))
-
-/* Draw the container */
-void
-drawContainer(void)
-{
-  int i, k;
-  float *v;
-
-  /* Y is reversed here because the model has it reversed */
-
-  /* Arbitrary bright wood-like color */
-  glColor3ub(209, 103, 23);
-  glBegin(GL_QUADS);
-  for (i = 0; i < int(NCONTFACES); i++) {
-    v = containernormals[i];
-    glNormal3f(v[0], -v[1], v[2]);
-    for (k = 3; k >= 0; k--) {
-      v = containercoords[containerfaces[i][k]];
-      glVertex3f(v[0] + OFFSETX, -(v[1] + OFFSETY), v[2] + OFFSETZ);
-    }
+  const char *TextureFilename() const {
+    return(texturefilename);
   }
-  glEnd();
-}
-
-void
-drawAll(void)
-{
-  int i, j;
-  int piece;
-  char done[PIECES + 1];
-  float m[4][4];
-
-  build_rotmatrix(m, curquat);
-  glMatrixMode(GL_MODELVIEW);
-  glLoadIdentity();
-  glTranslatef(0, 0, -10);
-  glMultMatrixf(&(m[0][0]));
-  glRotatef(180, 0, 0, 1);
-
-  if (depth) {
-    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-  } else {
-    glClear(GL_COLOR_BUFFER_BIT);
+  // PERSPECTIVE VIEW
+  //    Same as gluPerspective()..
+  //
+  void Perspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar) {
+    GLdouble xmin, xmax, ymin, ymax;
+    ymax = zNear * tan(fovy * M_PI / 360.0);
+    ymin = -ymax;
+    xmin = ymin * aspect;
+    xmax = ymax * aspect;
+    glFrustum(xmin, xmax, ymin, ymax, zNear, zFar);
   }
-  for (i = 1; i <= PIECES; i++) {
-    done[i] = 0;
-  }
-  glLoadName(0);
-  drawContainer();
-  for (i = 0; i < HEIGHT; i++) {
-    for (j = 0; j < WIDTH; j++) {
-      piece = thePuzzle[i][j];
-      if (piece == 0)
-        continue;
-      if (done[piece])
-        continue;
-      done[piece] = 1;
-      glLoadName(piece);
-      if (piece == movingPiece) {
-        drawBox(piece, move_x, move_y);
-      } else {
-        drawBox(piece, j, i);
-      }
+  // LOAD TEXTUREMAP USING FLTK'S SHARED IMAGE LIB
+  void LoadTexture(const char *filename, GLuint &TexID) {
+    Fl_Shared_Image *img = Fl_Shared_Image::get(filename);		// load texturemap
+    if ( ! img ) {
+	    fprintf(stderr, "%s: unknown image format\n", filename);
+	    exit(1);
     }
-  }
-}
-
-void
-redraw(void)
-{
-  glMatrixMode(GL_PROJECTION);
-  glLoadIdentity();
-  gluPerspective(45, viewport[2]*1.0/viewport[3], 0.1, 100.0);
-
-  drawAll();
-
-  if (doubleBuffer)
-    glutSwapBuffers();
-  else
-    glFinish();
-}
-
-void
-solidifyChain(struct puzzle *puzzle)
-{
-  int i;
-  char buf[256];
-
-  i = 0;
-  while (puzzle->backptr) {
-    i++;
-    puzzle->backptr->solnptr = puzzle;
-    puzzle = puzzle->backptr;
-  }
-  sprintf(buf, "%d moves to complete!", i);
-  glutSetWindowTitle(buf);
-}
-
-int
-addConfig(Config config, struct puzzle *back)
-{
-  unsigned hashvalue;
-  struct puzzle *newpiece;
-  struct puzzlelist *newlistentry;
-
-  hashvalue = hash(config);
-
-  newpiece = hashtable[hashvalue % HASHSIZE];
-  while (newpiece != NULL) {
-    if (newpiece->hashvalue == hashvalue) {
-      int i, j;
-
-      for (i = 0; i < WIDTH; i++) {
-        for (j = 0; j < HEIGHT; j++) {
-          if (convert[(int)config[j][i]] !=
-            convert[(int)newpiece->pieces[j][i]])
-            goto nomatch;
-        }
-      }
-      return 0;
+    if ( img->d() != 3 ) {
+	    fprintf(stderr, "%s: image depth is %d (expected 3)\n", filename, img->d());
+	    exit(1);
     }
-  nomatch:
-    newpiece = newpiece->next;
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img->w(), img->h(), 0,
+                 GL_RGB, GL_UNSIGNED_BYTE, img->data()[0]);
+    img->release();
   }
-
-  newpiece = (struct puzzle *) malloc(sizeof(struct puzzle));
-  newpiece->next = hashtable[hashvalue % HASHSIZE];
-  newpiece->hashvalue = hashvalue;
-  memcpy(newpiece->pieces, config, HEIGHT * WIDTH);
-  newpiece->backptr = back;
-  newpiece->solnptr = NULL;
-  hashtable[hashvalue % HASHSIZE] = newpiece;
-
-  newlistentry = (struct puzzlelist *) malloc(sizeof(struct puzzlelist));
-  newlistentry->puzzle = newpiece;
-  newlistentry->next = NULL;
-
-  if (lastentry) {
-    lastentry->next = newlistentry;
-  } else {
-    puzzles = newlistentry;
-  }
-  lastentry = newlistentry;
-
-  if (back == NULL) {
-    startPuzzle = newpiece;
-  }
-  if (solution(config)) {
-    solidifyChain(newpiece);
-    return 1;
-  }
-  return 0;
-}
-
-/* Checks if a space can move */
-int
-canmove0(Config pieces, int x, int y, int dir, Config newpieces)
-{
-  char piece;
-  int xadd, yadd;
-  int l, m;
-
-  xadd = xadds[dir];
-  yadd = yadds[dir];
-
-  if (x + xadd < 0 || x + xadd >= WIDTH ||
-    y + yadd < 0 || y + yadd >= HEIGHT)
-    return 0;
-  piece = pieces[y + yadd][x + xadd];
-  if (piece == 0)
-    return 0;
-  memcpy(newpieces, pieces, HEIGHT * WIDTH);
-  for (l = 0; l < WIDTH; l++) {
-    for (m = 0; m < HEIGHT; m++) {
-      if (newpieces[m][l] == piece)
-        newpieces[m][l] = 0;
-    }
-  }
-  xadd = -xadd;
-  yadd = -yadd;
-  for (l = 0; l < WIDTH; l++) {
-    for (m = 0; m < HEIGHT; m++) {
-      if (pieces[m][l] == piece) {
-        int newx, newy;
-
-        newx = l + xadd;
-        newy = m + yadd;
-        if (newx < 0 || newx >= WIDTH ||
-          newy < 0 || newy >= HEIGHT)
-          return 0;
-        if (newpieces[newy][newx] != 0)
-          return 0;
-        newpieces[newy][newx] = piece;
+  void CreateCube() {
+    // Materials
+    GLfloat ambient[]   = { 0.3, 0.3, 0.3, 1.0 };
+    GLfloat diffuse[]   = { 0.6, 0.6, 0.6, 1.0 };
+    GLfloat specular[]  = { 1.0, 1.0, 1.0, 1.0 };
+    GLfloat shininess[] = { 0.9 * 128.0 };		// 1=dull, 127=shiny
+    GLfloat emission[]  = { 0.0, 0.0, 0.0, 0.0 };
+    glMaterialfv(GL_FRONT, GL_AMBIENT,   ambient);
+    glMaterialfv(GL_FRONT, GL_DIFFUSE,   diffuse);
+    glMaterialfv(GL_FRONT, GL_SPECULAR,  specular);
+    glMaterialfv(GL_FRONT, GL_SHININESS, shininess);
+    glMaterialfv(GL_FRONT, GL_EMISSION,  emission);
+    static float cube_vertexes[6][4][4] = {		// cube and normals from SGI opengl example
+      { { -1.0, -1.0, -1.0, 1.0 },			// "scube.c" by Mark J. Kilgard
+        { -1.0, -1.0,  1.0, 1.0 },
+        { -1.0,  1.0,  1.0, 1.0 },
+        { -1.0,  1.0, -1.0, 1.0 } },
+      { {  1.0,  1.0,  1.0, 1.0 },
+        {  1.0, -1.0,  1.0, 1.0 },
+        {  1.0, -1.0, -1.0, 1.0 },
+        {  1.0,  1.0, -1.0, 1.0 } },
+      { { -1.0, -1.0, -1.0, 1.0 },
+        {  1.0, -1.0, -1.0, 1.0 },
+        {  1.0, -1.0,  1.0, 1.0 },
+        { -1.0, -1.0,  1.0, 1.0 } },
+      { {  1.0,  1.0,  1.0, 1.0 },
+        {  1.0,  1.0, -1.0, 1.0 },
+        { -1.0,  1.0, -1.0, 1.0 },
+        { -1.0,  1.0,  1.0, 1.0 } },
+      { { -1.0, -1.0, -1.0, 1.0 },
+        { -1.0,  1.0, -1.0, 1.0 },
+        {  1.0,  1.0, -1.0, 1.0 },
+        {  1.0, -1.0, -1.0, 1.0 } },
+      { {  1.0,  1.0,  1.0, 1.0 },
+        { -1.0,  1.0,  1.0, 1.0 },
+        { -1.0, -1.0,  1.0, 1.0 },
+        {  1.0, -1.0,  1.0, 1.0 }
       }
+    };
+    static float cube_normals[6][4] = {
+      { -1.0,  0.0,  0.0, 0.0 },
+      {  1.0,  0.0,  0.0, 0.0 },
+      {  0.0, -1.0,  0.0, 0.0 },
+      {  0.0,  1.0,  0.0, 0.0 },
+      {  0.0,  0.0, -1.0, 0.0 },
+      {  0.0,  0.0,  1.0, 0.0 }
+    };
+    // Cube
+    glColor3f(1.0, 1.0, 1.0);
+    for ( int i=0; i<6; i++ ) {
+      glNormal3fv(&cube_normals[i][0]);
+	    glBegin(GL_POLYGON);
+      glTexCoord2f(1.0, 0.0); glVertex4fv(&cube_vertexes[i][0][0]);
+      glTexCoord2f(0.0, 0.0); glVertex4fv(&cube_vertexes[i][1][0]);
+      glTexCoord2f(0.0, 1.0); glVertex4fv(&cube_vertexes[i][2][0]);
+      glTexCoord2f(1.0, 1.0); glVertex4fv(&cube_vertexes[i][3][0]);
+	    glEnd();
     }
   }
-  return 1;
-}
-
-/* Checks if a piece can move */
-int
-canmove(Config pieces, int x, int y, int dir, Config newpieces)
-{
-  int xadd, yadd;
-
-  xadd = xadds[dir];
-  yadd = yadds[dir];
-
-  if (x + xadd < 0 || x + xadd >= WIDTH ||
-    y + yadd < 0 || y + yadd >= HEIGHT)
-    return 0;
-  if (pieces[y + yadd][x + xadd] == pieces[y][x]) {
-    return canmove(pieces, x + xadd, y + yadd, dir, newpieces);
+  void CreateLight() {
+    GLfloat light_position[] = {  0.0,  0.0,  0.0, 1.0 };  // XYZW (W=0: xyz=direction, W!=0, xyz=position)
+    GLfloat light_white[]    = {  1.0,  1.0,  1.0, 0.0 };
+    glLightfv(GL_LIGHT0, GL_POSITION, light_position);
+    glLightfv(GL_LIGHT0, GL_AMBIENT,  light_white);
   }
-  if (pieces[y + yadd][x + xadd] != 0)
-    return 0;
-  return canmove0(pieces, x + xadd, y + yadd, (dir + 2) % 4, newpieces);
-}
-
-int
-generateNewConfigs(struct puzzle *puzzle)
-{
-  int i, j, k;
-  Config pieces;
-  Config newpieces;
-
-  memcpy(pieces, puzzle->pieces, HEIGHT * WIDTH);
-  for (i = 0; i < WIDTH; i++) {
-    for (j = 0; j < HEIGHT; j++) {
-      if (pieces[j][i] == 0) {
-        for (k = 0; k < 4; k++) {
-          if (canmove0(pieces, i, j, k, newpieces)) {
-            if (addConfig(newpieces, puzzle))
-              return 1;
-          }
-        }
-      }
-    }
+  // RESHAPED VIEWPORT
+  //     OpenGL stuff to do whenever window changes size
+  //
+  void ReshapeViewport() {
+    glViewport(0, 0, w(), h());
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    GLfloat ratio = (float(w()) / float(h()));
+    Perspective(30.0, ratio, 1.0, 30.0);
+    glTranslatef(0.0, 0.0, -8.0);
   }
-  return 0;
-}
-
-void
-freeSolutions(void)
-{
-  struct puzzlelist *nextpuz;
-  struct puzzle *puzzle, *next;
-  int i;
-
-  while (puzzles) {
-    nextpuz = puzzles->next;
-    free((char *) puzzles);
-    puzzles = nextpuz;
+  // OPENGL INITIALIZATION
+  //    OpenGL stuff to do *only once* on startup.
+  //
+  void GlInit() {
+    // Texture Map Init
+    glGenTextures(1, &TexID);
+    glBindTexture(GL_TEXTURE_2D, TexID);
+    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    // Load texture image, bind to TexID
+    LoadTexture(TextureFilename(), TexID);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glEnable(GL_TEXTURE_2D);
+    // Lighting Init
+    glEnable(GL_LIGHTING);
+    glEnable(GL_LIGHT0);
+    glShadeModel(GL_SMOOTH);
+    // Misc OpenGL Init
+    glEnable(GL_DEPTH_TEST);	// hidden surface
+    glDepthFunc(GL_LEQUAL);
   }
-  lastentry = NULL;
-  for (i = 0; i < HASHSIZE; i++) {
-    puzzle = hashtable[i];
-    hashtable[i] = NULL;
-    while (puzzle) {
-      next = puzzle->next;
-      free((char *) puzzle);
-      puzzle = next;
+  // FLTK DRAW
+  //    Called by FLTK to draw the scene.
+  //
+  void draw() {
+    // Initialize/handle reshaped viewport
+    if ( !valid() ) {
+      valid(1);
+	    // Make sure we only do GlInit() once
+	    static int first_time = 1;
+	    if ( first_time ) {
+        first_time = 0;
+        GlInit();
+	    }
+      ReshapeViewport();
+	    glMatrixMode(GL_MODELVIEW);
+	    glLoadIdentity();
+	    // Model view
+	    glMatrixMode(GL_MODELVIEW);
     }
-  }
-  startPuzzle = NULL;
-}
-
-int
-continueSolving(void)
-{
-  struct puzzle *nextpuz;
-  int i, j;
-  int movedPiece;
-  int movedir;
-  int fromx, fromy;
-  int tox, toy;
-
-  if (startPuzzle == NULL)
-    return 0;
-  if (startPuzzle->solnptr == NULL) {
-    freeSolutions();
-    return 0;
-  }
-  nextpuz = startPuzzle->solnptr;
-  movedPiece = 0;
-  movedir = 0;
-  for (i = 0; i < HEIGHT; i++) {
-    for (j = 0; j < WIDTH; j++) {
-      if (startPuzzle->pieces[i][j] != nextpuz->pieces[i][j]) {
-        if (startPuzzle->pieces[i][j]) {
-          movedPiece = startPuzzle->pieces[i][j];
-          fromx = j;
-          fromy = i;
-          if (i < HEIGHT - 1 && nextpuz->pieces[i + 1][j] == movedPiece) {
-            movedir = 3;
-          } else {
-            movedir = 2;
-          }
-          goto found_piece;
-        } else {
-          movedPiece = nextpuz->pieces[i][j];
-          if (i < HEIGHT - 1 &&
-            startPuzzle->pieces[i + 1][j] == movedPiece) {
-            fromx = j;
-            fromy = i + 1;
-            movedir = 1;
-          } else {
-            fromx = j + 1;
-            fromy = i;
-            movedir = 0;
-          }
-          goto found_piece;
-        }
-      }
+    // Clear
+    glClearColor(.5,.5,.5, 0.0);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    glLoadIdentity();
+    glPushMatrix();		// give light its own matrix
+    // Light
+    glTranslatef(0.0,  2.0,  8.0);
+    CreateLight();
+    glPopMatrix();
+    glPushMatrix();		// give object its own matrix
+    // Object
+    glRotatef(spin, 0.5, 1.0, 0.0); // show all sides of cube
+    CreateCube();
+    glPopMatrix();
+    // DEBUG: CHECK FOR ERRORS
+    GLenum err = glGetError();
+    if ( err != GL_NO_ERROR ) {
+      fprintf(stderr, "GLGETERROR=%d\n", (int)err);
     }
   }
-  glutSetWindowTitle((char *)"What!  No change?");
-  freeSolutions();
-  return 0;
-
-found_piece:
-  if (!movingPiece) {
-    movingPiece = movedPiece;
-    move_x = fromx;
-    move_y = fromy;
-  }
-  move_x += xadds[movedir] * MOVE_SPEED;
-  move_y += yadds[movedir] * MOVE_SPEED;
-
-  tox = fromx + xadds[movedir];
-  toy = fromy + yadds[movedir];
-
-  if (move_x > tox - MOVE_SPEED / 2 && move_x < tox + MOVE_SPEED / 2 &&
-    move_y > toy - MOVE_SPEED / 2 && move_y < toy + MOVE_SPEED / 2) {
-    startPuzzle = nextpuz;
-    movingPiece = 0;
-  }
-  memcpy(thePuzzle, startPuzzle->pieces, HEIGHT * WIDTH);
-  changeState();
-  return 1;
-}
-
-int
-solvePuzzle(void)
-{
-  struct puzzlelist *nextpuz;
-  char buf[256];
-  int i;
-
-  if (solution(thePuzzle)) {
-    glutSetWindowTitle((char *)"Puzzle already solved!");
-    return 0;
-  }
-  addConfig(thePuzzle, NULL);
-  i = 0;
-
-  while (puzzles) {
-    i++;
-    if (generateNewConfigs(puzzles->puzzle))
-      break;
-    nextpuz = puzzles->next;
-    free((char *) puzzles);
-    puzzles = nextpuz;
-  }
-  if (puzzles == NULL) {
-    freeSolutions();
-    sprintf(buf, "I can't solve it! (%d positions examined)", i);
-    glutSetWindowTitle(buf);
-    return 1;
-  }
-  return 1;
-}
-
-int
-selectPiece(int mousex, int mousey)
-{
-  long hits;
-  GLuint selectBuf[1024];
-  GLuint closest;
-  GLuint dist;
-
-  glSelectBuffer(1024, selectBuf);
-  (void) glRenderMode(GL_SELECT);
-  glInitNames();
-
-  /* Because LoadName() won't work with no names on the stack */
-  glPushName(0);
-
-  glMatrixMode(GL_PROJECTION);
-  glLoadIdentity();
-  gluPickMatrix(mousex, H - mousey, 4, 4, viewport);
-  gluPerspective(45, viewport[2]*1.0/viewport[3], 0.1, 100.0);
-
-  drawAll();
-
-  hits = glRenderMode(GL_RENDER);
-  if (hits <= 0) {
-    return 0;
-  }
-  closest = 0;
-  dist = 0xFFFFFFFFU; //2147483647;
-  while (hits) {
-    if (selectBuf[(hits - 1) * 4 + 1] < dist) {
-      dist = selectBuf[(hits - 1) * 4 + 1];
-      closest = selectBuf[(hits - 1) * 4 + 3];
-    }
-    hits--;
-  }
-  return closest;
-}
-
-void
-nukePiece(int piece)
-{
-  int i, j;
-
-  for (i = 0; i < HEIGHT; i++) {
-    for (j = 0; j < WIDTH; j++) {
-      if (thePuzzle[i][j] == piece) {
-        thePuzzle[i][j] = 0;
-      }
-    }
-  }
-}
-
-void
-multMatrices(const GLfloat a[16], const GLfloat b[16], GLfloat r[16])
-{
-  int i, j;
-
-  for (i = 0; i < 4; i++) {
-    for (j = 0; j < 4; j++) {
-      r[i * 4 + j] =
-        a[i * 4 + 0] * b[0 * 4 + j] +
-        a[i * 4 + 1] * b[1 * 4 + j] +
-        a[i * 4 + 2] * b[2 * 4 + j] +
-        a[i * 4 + 3] * b[3 * 4 + j];
-    }
-  }
-}
-
-void
-makeIdentity(GLfloat m[16])
-{
-  m[0 + 4 * 0] = 1;
-  m[0 + 4 * 1] = 0;
-  m[0 + 4 * 2] = 0;
-  m[0 + 4 * 3] = 0;
-  m[1 + 4 * 0] = 0;
-  m[1 + 4 * 1] = 1;
-  m[1 + 4 * 2] = 0;
-  m[1 + 4 * 3] = 0;
-  m[2 + 4 * 0] = 0;
-  m[2 + 4 * 1] = 0;
-  m[2 + 4 * 2] = 1;
-  m[2 + 4 * 3] = 0;
-  m[3 + 4 * 0] = 0;
-  m[3 + 4 * 1] = 0;
-  m[3 + 4 * 2] = 0;
-  m[3 + 4 * 3] = 1;
-}
-
-/*
-   ** inverse = invert(src)
- */
-int
-invertMatrix(const GLfloat src[16], GLfloat inverse[16])
-{
-  int i, j, k, swap;
-  double t;
-  GLfloat temp[4][4];
-
-  for (i = 0; i < 4; i++) {
-    for (j = 0; j < 4; j++) {
-      temp[i][j] = src[i * 4 + j];
-    }
-  }
-  makeIdentity(inverse);
-
-  for (i = 0; i < 4; i++) {
-    /* 
-       ** Look for largest element in column */
-    swap = i;
-    for (j = i + 1; j < 4; j++) {
-      if (fabs(temp[j][i]) > fabs(temp[i][i])) {
-        swap = j;
-      }
-    }
-
-    if (swap != i) {
-      /* 
-         ** Swap rows. */
-      for (k = 0; k < 4; k++) {
-        t = temp[i][k];
-        temp[i][k] = temp[swap][k];
-        temp[swap][k] = t;
-
-        t = inverse[i * 4 + k];
-        inverse[i * 4 + k] = inverse[swap * 4 + k];
-        inverse[swap * 4 + k] = t;
-      }
-    }
-    if (temp[i][i] == 0) {
-      /* 
-         ** No non-zero pivot.  The matrix is singular, which
-         shouldn't ** happen.  This means the user gave us a
-         bad matrix. */
-      return 0;
-    }
-    t = temp[i][i];
-    for (k = 0; k < 4; k++) {
-      temp[i][k] /= t;
-      inverse[i * 4 + k] /= t;
-    }
-    for (j = 0; j < 4; j++) {
-      if (j != i) {
-        t = temp[j][i];
-        for (k = 0; k < 4; k++) {
-          temp[j][k] -= temp[i][k] * t;
-          inverse[j * 4 + k] -= inverse[i * 4 + k] * t;
-        }
-      }
-    }
-  }
-  return 1;
-}
-
-/*
-   ** This is a screwball function.  What it does is the following:
-   ** Given screen x and y coordinates, compute the corresponding object space 
-   **   x and y coordinates given that the object space z is 0.9 + OFFSETZ.
-   ** Since the tops of (most) pieces are at z = 0.9 + OFFSETZ, we use that 
-   **   number.
- */
-int
-computeCoords(int piece, int mousex, int mousey,
-  GLfloat * selx, GLfloat * sely)
-{
-  GLfloat modelMatrix[16];
-  GLfloat projMatrix[16];
-  GLfloat finalMatrix[16];
-  GLfloat in[4];
-  GLfloat a, b, c, d;
-  GLfloat top, bot;
-  GLfloat z;
-  GLfloat w;
-  GLfloat height;
-
-  if (piece == 0)
-    return 0;
-  height = zsize[piece] - 0.1 + OFFSETZ;
-
-  glGetFloatv(GL_PROJECTION_MATRIX, projMatrix);
-  glGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix);
-  multMatrices(modelMatrix, projMatrix, finalMatrix);
-  if (!invertMatrix(finalMatrix, finalMatrix))
-    return 0;
-
-  in[0] = (2.0 * (mousex - viewport[0]) / viewport[2]) - 1;
-  in[1] = (2.0 * ((H - mousey) - viewport[1]) / viewport[3]) - 1;
-
-  a = in[0] * finalMatrix[0 * 4 + 2] +
-    in[1] * finalMatrix[1 * 4 + 2] +
-    finalMatrix[3 * 4 + 2];
-  b = finalMatrix[2 * 4 + 2];
-  c = in[0] * finalMatrix[0 * 4 + 3] +
-    in[1] * finalMatrix[1 * 4 + 3] +
-    finalMatrix[3 * 4 + 3];
-  d = finalMatrix[2 * 4 + 3];
-
-  /* 
-     ** Ok, now we need to solve for z: **   (a + b z) / (c + d 
-
-     z) = height. ** ("height" is the height in object space we 
-
-     want to solve z for) ** ** ==>  a + b z = height c +
-     height d z **      bz - height d z = height c - a ** z =
-     (height c - a) / (b - height d) */
-  top = height * c - a;
-  bot = b - height * d;
-  if (bot == 0.0)
-    return 0;
-
-  z = top / bot;
-
-  /* 
-     ** Ok, no problem. ** Now we solve for x and y.  We know
-     that w = c + d z, so we compute it. */
-  w = c + d * z;
-
-  /* 
-     ** Now for x and y: */
-  *selx = (in[0] * finalMatrix[0 * 4 + 0] +
-    in[1] * finalMatrix[1 * 4 + 0] +
-    z * finalMatrix[2 * 4 + 0] +
-    finalMatrix[3 * 4 + 0]) / w - OFFSETX;
-  *sely = (in[0] * finalMatrix[0 * 4 + 1] +
-    in[1] * finalMatrix[1 * 4 + 1] +
-    z * finalMatrix[2 * 4 + 1] +
-    finalMatrix[3 * 4 + 1]) / w - OFFSETY;
-  return 1;
-}
-
-static int selected;
-static int selectx, selecty;
-static float selstartx, selstarty;
-
-void
-grabPiece(int piece, float selx, float sely)
-{
-  int hit;
-
-  selectx = int(selx);
-  selecty = int(sely);
-  if (selectx < 0 || selecty < 0 || selectx >= WIDTH || selecty >= HEIGHT) {
-    return;
-  }
-  hit = thePuzzle[selecty][selectx];
-  if (hit != piece)
-    return;
-  if (hit) {
-    movingPiece = hit;
-    while (selectx > 0 && thePuzzle[selecty][selectx - 1] == movingPiece) {
-      selectx--;
-    }
-    while (selecty > 0 && thePuzzle[selecty - 1][selectx] == movingPiece) {
-      selecty--;
-    }
-    move_x = selectx;
-    move_y = selecty;
-    selected = 1;
-    selstartx = selx;
-    selstarty = sely;
+};
+int main(int argc, char *argv[]) {
+  fl_register_images();	// fltk image lib init
+  MyGlWindow* mygl = new MyGlWindow(10, 10, WIN_W-20, WIN_H-20, "Textured Image Test");
+  if ( argc >= 2 ) {
+    mygl->TextureFilename(argv[1]);
   } else {
-    selected = 0;
+    printf("Usage: %s <texture_filename.[png,jpg,gif,bmp]>\n"
+           "Texture file should be 64x64, 128x128, etc.\n"
+           "Defaulting to use '%s'\n\n", argv[0], mygl->TextureFilename());
   }
-  changeState();
+  mygl->resizable(mygl);
+  mygl->show();
+  return(Fl::run());
 }
-
-void
-moveSelection(float selx, float sely)
-{
-  float deltax, deltay;
-  int dir;
-  Config newpieces;
-
-  if (!selected)
-    return;
-  deltax = selx - selstartx;
-  deltay = sely - selstarty;
-
-  if (fabs(deltax) > fabs(deltay)) {
-    deltay = 0;
-    if (deltax > 0) {
-      if (deltax > 1)
-        deltax = 1;
-      dir = 2;
-    } else {
-      if (deltax < -1)
-        deltax = -1;
-      dir = 0;
-    }
-  } else {
-    deltax = 0;
-    if (deltay > 0) {
-      if (deltay > 1)
-        deltay = 1;
-      dir = 3;
-    } else {
-      if (deltay < -1)
-        deltay = -1;
-      dir = 1;
-    }
-  }
-  if (canmove(thePuzzle, selectx, selecty, dir, newpieces)) {
-    move_x = deltax + selectx;
-    move_y = deltay + selecty;
-    if (deltax > 0.5) {
-      memcpy(thePuzzle, newpieces, HEIGHT * WIDTH);
-      selectx++;
-      selstartx++;
-    } else if (deltax < -0.5) {
-      memcpy(thePuzzle, newpieces, HEIGHT * WIDTH);
-      selectx--;
-      selstartx--;
-    } else if (deltay > 0.5) {
-      memcpy(thePuzzle, newpieces, HEIGHT * WIDTH);
-      selecty++;
-      selstarty++;
-    } else if (deltay < -0.5) {
-      memcpy(thePuzzle, newpieces, HEIGHT * WIDTH);
-      selecty--;
-      selstarty--;
-    }
-  } else {
-    if (deltay > 0 && thePuzzle[selecty][selectx] == 10 &&
-      selectx == 1 && selecty == 3) {
-      /* Allow visual movement of solution piece outside of the 
-
-         box */
-      move_x = selectx;
-      move_y = sely - selstarty + selecty;
-    } else {
-      move_x = selectx;
-      move_y = selecty;
-    }
-  }
-}
-
-void
-dropSelection(void)
-{
-  if (!selected)
-    return;
-  movingPiece = 0;
-  selected = 0;
-  changeState();
-}
-
-static int left_mouse, middle_mouse;
-static int mousex, mousey;
-static int solving;
-static int spinning;
-static float lastquat[4];
-static int sel_piece;
-
-static void
-Reshape(int width, int height)
-{
-
-  W = width;
-  H = height;
-  glViewport(0, 0, W, H);
-  glGetIntegerv(GL_VIEWPORT, viewport);
-}
-
-void
-toggleSolve(void)
-{
-    if (solving) {
-      freeSolutions();
-      solving = 0;
-      glutChangeToMenuEntry(1, (char *)"Solving", 1);
-      glutSetWindowTitle((char *)"glpuzzle");
-      movingPiece = 0;
-    } else {
-      glutChangeToMenuEntry(1, (char *)"Stop solving", 1);
-      glutSetWindowTitle((char *)"Solving...");
-      if (solvePuzzle()) {
-        solving = 1;
-      }
-    }
-    changeState();
-    glutPostRedisplay();
-}
-
-void reset(void)
-{
-    if (solving) {
-      freeSolutions();
-      solving = 0;
-      glutChangeToMenuEntry(1, (char *)"Solving", 1);
-      glutSetWindowTitle((char *)"glpuzzle");
-      movingPiece = 0;
-      changeState();
-    }
-    memcpy(thePuzzle, startConfig, HEIGHT * WIDTH);
-    glutPostRedisplay();
-}
-
-void
-keyboard(unsigned char c, int x, int y)
-{
-  int piece;
-
-  switch (c) {
-  case 27:
-    exit(0);
-    break;
-  case 'D':
-  case 'd':
-    if (solving) {
-      freeSolutions();
-      solving = 0;
-      glutChangeToMenuEntry(1, (char *)"Solving", 1);
-      glutSetWindowTitle((char *)"glpuzzle");
-      movingPiece = 0;
-      changeState();
-    }
-    piece = selectPiece(x, y);
-    if (piece) {
-      nukePiece(piece);
-    }
-    glutPostRedisplay();
-    break;
-  case 'R':
-  case 'r':
-    reset();
-    break;
-  case 'S':
-  case 's':
-    toggleSolve();
-    break;
-  case 'b':
-  case 'B':
-    depth = 1 - depth;
-    if (depth) {
-      glEnable(GL_DEPTH_TEST);
-    } else {
-      glDisable(GL_DEPTH_TEST);
-    }
-    glutPostRedisplay();
-    break;
-  default:
-    break;
-  }
-}
-
-void
-motion(int x, int y)
-{
-  float selx, sely;
-
-  if (middle_mouse && !left_mouse) {
-    if (mousex != x || mousey != y) {
-      trackball(lastquat,
-        (2.0*mousex - W) / W,
-        (H - 2.0*mousey) / H,
-        (2.0*x - W) / W,
-        (H - 2.0*y) / H);
-      spinning = 1;
-    } else {
-      spinning = 0;
-    }
-    changeState();
-  } else {
-    computeCoords(sel_piece, x, y, &selx, &sely);
-    moveSelection(selx, sely);
-  }
-  mousex = x;
-  mousey = y;
-  glutPostRedisplay();
-}
-
-void
-mouse(int b, int s, int x, int y)
-{
-  float selx, sely;
-
-  mousex = x;
-  mousey = y;
-  curX = x;
-  curY = y;
-  if (s == GLUT_DOWN) {
-    switch (b) {
-    case GLUT_LEFT_BUTTON:
-      if (solving) {
-        freeSolutions();
-        solving = 0;
-      glutChangeToMenuEntry(1, (char *)"Solving", 1);
-        glutSetWindowTitle((char *)"glpuzzle");
-        movingPiece = 0;
-      }
-      left_mouse = GL_TRUE;
-      sel_piece = selectPiece(mousex, mousey);
-      if (!sel_piece) {
-      left_mouse = GL_FALSE;
-      middle_mouse = GL_TRUE; // let it rotate object
-      } else if (computeCoords(sel_piece, mousex, mousey, &selx, &sely)) {
-        grabPiece(sel_piece, selx, sely);
-      }
-      glutPostRedisplay();
-      break;
-    case GLUT_MIDDLE_BUTTON:
-      middle_mouse = GL_TRUE;
-      glutPostRedisplay();
-      break;
-    }
-  } else {
-    if (left_mouse) {
-      left_mouse = GL_FALSE;
-      dropSelection();
-      glutPostRedisplay();
-    } else if (middle_mouse) {
-      middle_mouse = GL_FALSE;
-      glutPostRedisplay();
-    }
-  }
-  motion(x, y);
-}
-
-void
-animate(void)
-{
-  if (spinning) {
-    add_quats(lastquat, curquat, curquat);
-  }
-  glutPostRedisplay();
-  if (solving) {
-    if (!continueSolving()) {
-      solving = 0;
-      glutChangeToMenuEntry(1, (char *)"Solving", 1);
-      glutSetWindowTitle((char *)"glpuzzle");
-    }
-  }
-  if ((!solving && !spinning) || !visible) {
-    glutIdleFunc(NULL);
-  }
-}
-
-void
-changeState(void)
-{
-  if (visible) {
-    if (!solving && !spinning) {
-      glutIdleFunc(NULL);
-    } else {
-      glutIdleFunc(animate);
-    }
-  } else {
-    glutIdleFunc(NULL);
-  }
-}
-
-void
-init(void)
-{
-  static float lmodel_ambient[] =
-  {0.0, 0.0, 0.0, 0.0};
-  static float lmodel_twoside[] =
-  {GL_FALSE};
-  static float lmodel_local[] =
-  {GL_FALSE};
-  static float light0_ambient[] =
-  {0.1, 0.1, 0.1, 1.0};
-  static float light0_diffuse[] =
-  {1.0, 1.0, 1.0, 0.0};
-  static float light0_position[] =
-  {0.8660254, 0.5, 1, 0};
-  static float light0_specular[] =
-  {0.0, 0.0, 0.0, 0.0};
-  static float bevel_mat_ambient[] =
-  {0.0, 0.0, 0.0, 1.0};
-  static float bevel_mat_shininess[] =
-  {40.0};
-  static float bevel_mat_specular[] =
-  {0.0, 0.0, 0.0, 0.0};
-  static float bevel_mat_diffuse[] =
-  {1.0, 0.0, 0.0, 0.0};
-
-  glEnable(GL_CULL_FACE);
-  glCullFace(GL_BACK);
-  glEnable(GL_DEPTH_TEST);
-  glClearDepth(1.0);
-
-  glClearColor(0.5, 0.5, 0.5, 0.0);
-  glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
-  glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
-  glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
-  glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
-  glEnable(GL_LIGHT0);
-
-  glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, lmodel_local);
-  glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
-  glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
-  glEnable(GL_LIGHTING);
-
-  glMaterialfv(GL_FRONT, GL_AMBIENT, bevel_mat_ambient);
-  glMaterialfv(GL_FRONT, GL_SHININESS, bevel_mat_shininess);
-  glMaterialfv(GL_FRONT, GL_SPECULAR, bevel_mat_specular);
-  glMaterialfv(GL_FRONT, GL_DIFFUSE, bevel_mat_diffuse);
-
-  glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
-  glEnable(GL_COLOR_MATERIAL);
-  glShadeModel(GL_FLAT);
-
-  trackball(curquat, 0.0, 0.0, 0.0, 0.0);
-  srandom(time(NULL));
-}
-
-static void
-Usage(void)
-{
-  puts("Usage: puzzle [-s]");
-  puts("   -s:  Run in single buffered mode");
-  exit(-1);
-}
-
-void
-visibility(int v)
-{
-  if (v == GLUT_VISIBLE) {
-    visible = 1;
-  } else {
-    visible = 0;
-  }
-  changeState();
-}
-
-void
-menu(int choice)
-{
-   switch(choice) {
-   case 1:
-      toggleSolve();
-      break;
-   case 2:
-      reset();
-      break;
-   case 3:
-      exit(0);
-      break;
-   }
-}
-
-int
-main(int argc, char **argv)
-{
-  long i;
-
-  glutInit(&argc, argv);
-  for (i = 1; i < argc; i++) {
-    if (argv[i][0] == '-') {
-      switch (argv[i][1]) {
-      case 's':
-        doubleBuffer = 0;
-        break;
-      default:
-        Usage();
-      }
-    } else {
-      Usage();
-    }
-  }
-
-  glutInitWindowSize(W, H);
-  if (doubleBuffer) {
-    glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE | GLUT_MULTISAMPLE);
-  } else {
-    glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | GLUT_SINGLE | GLUT_MULTISAMPLE);
-  }
-
-  glutCreateWindow("glpuzzle");
-  visible = 1; // added for fltk, bug in original program?
-
-  init();
-
-  glGetIntegerv(GL_VIEWPORT, viewport);
-
-  puts("");
-  puts("r   Reset puzzle");
-  puts("s   Solve puzzle (may take a few seconds to compute)");
-  puts("d   Destroy a piece - makes the puzzle easier");
-  puts("b   Toggles the depth buffer on and off");
-  puts("");
-  puts("Left mouse moves pieces");
-  puts("Middle mouse spins the puzzle");
-  puts("Right mouse has menu");
-
-  glutReshapeFunc(Reshape);
-  glutDisplayFunc(redraw);
-  glutKeyboardFunc(keyboard);
-  glutMotionFunc(motion);
-  glutMouseFunc(mouse);
-  glutVisibilityFunc(visibility);
-  glutCreateMenu(menu);
-  glutAddMenuEntry((char *)"Solve", 1);
-  glutAddMenuEntry((char *)"Reset", 2);
-  glutAddMenuEntry((char *)"Quit", 3);
-  glutAttachMenu(GLUT_RIGHT_BUTTON);
-  glutMainLoop();
-  return 0;             /* ANSI C requires main to return int. */
-}
-
-#endif // added for fltk's distribution
-
-//
-// End of "$Id$".
-//
Index: test/shape.cxx
===================================================================
--- test/shape.cxx	(revision 10483)
+++ test/shape.cxx	(working copy)
@@ -45,7 +45,7 @@
   if (!valid()) {
     valid(1);
     glLoadIdentity();
-    glViewport(0, 0, w(), h());
+    glViewport(0, 0, pixel_w(), pixel_h());
   }
 // draw an amazing graphic:
   glClear(GL_COLOR_BUFFER_BIT);
@@ -81,6 +81,7 @@
 
 int main(int argc, char **argv) {
 
+  Fl::use_high_res_GL(1);
   Fl_Window window(300, 330);
 
 // the shape window could be it's own window, but here we make it
