diff --git a/Common/Context.cpp b/Common/Context.cpp
deleted file mode 100644
index 79db6610b3eff56a731c13bf67f99121298338d6..0000000000000000000000000000000000000000
--- a/Common/Context.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-// Gmsh - Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
-//
-// See the LICENSE.txt file for license information. Please report all
-// bugs and problems to <gmsh@geuz.org>.
-
-#include "Numeric.h"
-#include "Context.h"
-#include "Trackball.h"
-
-// the single static option context
-Context_T CTX;
-
-void Context_T::buildRotationMatrix(void)
-{
-  if(useTrackball) {
-    build_rotmatrix(rot, quaternion);
-    setEulerAnglesFromRotationMatrix();
-  }
-  else {
-    double x = r[0] * M_PI / 180.;
-    double y = r[1] * M_PI / 180.;
-    double z = r[2] * M_PI / 180.;
-    double A = cos(x);
-    double B = sin(x);
-    double C = cos(y);
-    double D = sin(y);
-    double E = cos(z);
-    double F = sin(z);
-    double AD = A * D;
-    double BD = B * D;
-    rot[0] = C*E; rot[1] = BD*E+A*F; rot[2] =-AD*E+B*F; rot[3] = 0.;
-    rot[4] =-C*F; rot[5] =-BD*F+A*E; rot[6] = AD*F+B*E; rot[7] = 0.;
-    rot[8] = D;   rot[9] =-B*C;      rot[10] = A*C;     rot[11] = 0.;
-    rot[12] = 0.; rot[13] = 0.;      rot[14] = 0.;      rot[15] = 1.;
-    setQuaternionFromEulerAngles();
-  }
-}
-
-void Context_T::addQuaternion(double p1x, double p1y, double p2x, double p2y)
-{
-  double quat[4];
-  trackball(quat, p1x, p1y, p2x, p2y);
-  add_quats(quat, quaternion, quaternion);
-}
-
-void Context_T::addQuaternionFromAxisAndAngle(double axis[3], double angle)
-{
-  double a = angle * M_PI / 180.;
-  double quat[4];
-  axis_to_quat(axis, a, quat);
-  add_quats(quat, quaternion, quaternion);  
-}
-
-void Context_T::setQuaternion(double q0, double q1, double q2, double q3)
-{
-  quaternion[0] = q0;
-  quaternion[1] = q1;
-  quaternion[2] = q2;
-  quaternion[3] = q3;
-}
-
-void Context_T::setQuaternionFromEulerAngles()
-{
-  double x = r[0] * M_PI / 180.;
-  double y = r[1] * M_PI / 180.;
-  double z = r[2] * M_PI / 180.;
-  double xx[3] = {1.,0.,0.};
-  double yy[3] = {0.,1.,0.};
-  double zz[3] = {0.,0.,1.};
-  double q1[4], q2[4], q3[4], tmp[4];
-  axis_to_quat(xx, -x, q1);
-  axis_to_quat(yy, -y, q2);
-  axis_to_quat(zz, -z, q3);
-  add_quats(q1, q2, tmp);
-  add_quats(tmp, q3, quaternion);
-}
-
-void Context_T::setEulerAnglesFromRotationMatrix()
-{
-  r[1] = asin(rot[8]); // Calculate Y-axis angle
-  double C =  cos(r[1]);
-  r[1] *=  180. / M_PI;
-  if(fabs(C) > 0.005){ // Gimball lock?
-    double tmpx =  rot[10] / C; // No, so get X-axis angle
-    double tmpy = -rot[9] / C;
-    r[0] = atan2(tmpy, tmpx) * 180. / M_PI;
-    tmpx =  rot[0] / C; // Get Z-axis angle
-    tmpy = -rot[4] / C;
-    r[2] = atan2(tmpy, tmpx) * 180. / M_PI;
-  }
-  else{ // Gimball lock has occurred
-    r[0] = 0.; // Set X-axis angle to zero
-    double tmpx = rot[5]; // And calculate Z-axis angle
-    double tmpy = rot[1];
-    r[2] = atan2(tmpy, tmpx) * 180. / M_PI;
-  }
-  // return only positive angles in [0,360]
-  if(r[0] < 0.) r[0] += 360.;
-  if(r[1] < 0.) r[1] += 360.;
-  if(r[2] < 0.) r[2] += 360.;
-}
diff --git a/Common/Context.h b/Common/Context.h
index 54e35733ca80e286b83e4d11cf7f090085ee6baf..1a96d459caba8d182f7415102f38d555bdbf7f14 100644
--- a/Common/Context.h
+++ b/Common/Context.h
@@ -70,12 +70,7 @@ class Context_T {
   int initial_context; // 0=automatic; 1=geom; 2=mesh; 3=solver; 4=post 
   int nopopup; // never popup dialogs in scripts (use default values instead)
   int non_modal_windows; // make all windows "non modal"
-  double rot[16]; // current rotation matrix 
-  double r[3]; // current Euler angles (in degrees!) 
-  double t[3], s[3]; // current translation and scale 
-  double t_init[3]; // initial translation before applying modelview transform
   double clip_factor; // clipping plane distance factor
-  double quaternion[4]; // current quaternion used for "trackball" rotation
   int useTrackball; // do or do not use the trackball for rotations 
   double rotation_center[3]; // point around which to rotate the scene
   int rotation_center_cg; // rotate around the center of mass instead of rotation_center[]
@@ -101,25 +96,21 @@ class Context_T {
   int gl_font_enum; // font for opengl graphics (fltk enum value)
   int gl_fontsize; // font size for opengl graphics
   double point_size, line_width; // point/line widths
-  int viewport[4]; // current viewport 
-  double vxmin, vxmax, vymin, vymax; // current viewport in real coordinates 
   int light[6]; // status of lights
   double light_position[6][4]; // light sources positions 
   double shine, shine_exponent; // material specular reflection parameters
   int render_mode; // GMSH_RENDER, GMSH_SELECT, GMSH_FEEDBACK 
   double clip_plane[6][4]; // clipping planes 
-  int clip_whole_elements, clip_only_draw_intersecting_volume, clip_only_volume; // clip options
+  int clip_whole_elements, clip_only_draw_intersecting_volume; // clipping options
+  int clip_only_volume;
   int polygon_offset, polygon_offset_always; // polygon offset control
   double polygon_offset_factor, polygon_offset_units; // params for glPolygonOffset
-  double pixel_equiv_x, pixel_equiv_y; // approx equiv model length of a pixel 
   int color_scheme; // general color scheme
   int quadric_subdivisions; // nb of subdivisions for gluQuadrics (spheres/cylinders)
   int vector_type; // default vector display type (for normals, etc.)
   double arrow_rel_head_radius; // relative radius of arrow head
   double arrow_rel_stem_radius; // relative radius of arrow stem
   double arrow_rel_stem_length; // relative length of arrow stem
-  double model[16], proj[16]; // the modelview and projection matrix as they were
-                              // at the time of the last InitPosition() call
   double mesh_timer[3]; // records cpu times for 1-D, 2-D and 3-D mesh generation
   int forced_bbox; // dynamic variable tracking if the bbox is currently imposed
   int mouse_selection; // enable selection using the mouse
@@ -130,6 +121,12 @@ class Context_T {
   int hide_unselected; // hide all unselected entities
   int draw_all_models;
 
+  // these are used as temp vars until the GUI is ready
+  double tmp_r[3]; // current Euler angles (in degrees!) 
+  double tmp_t[3], tmp_s[3]; // current translation and scale 
+  double tmp_quaternion[4]; // current quaternion used for "trackball" rotation
+  int tmp_viewport[4]; // current viewport 
+
   // geometry options 
   struct{
     int points, lines, surfaces, volumes;
@@ -162,7 +159,8 @@ class Context_T {
     int optimize, optimize_netgen, refine_steps;
     int quality_type, label_type;
     double quality_inf, quality_sup, radius_inf, radius_sup;
-    double scaling_factor, lc_factor, rand_factor, lc_integration_precision, lc_min, lc_max, tolerance_edge_length;
+    double scaling_factor, lc_factor, rand_factor, lc_integration_precision;
+    double lc_min, lc_max, tolerance_edge_length;
     int lc_from_points, lc_from_curvature, lc_extend_from_boundary;
     int dual, voronoi, draw_skin_only;
     int light, light_two_side, light_lines;
@@ -189,7 +187,7 @@ class Context_T {
     int smooth, anim_cycle, combine_time, combine_remove_orig ;
     int file_format, plugins;
     double anim_delay ;
-    void (*plugin_draw_function)(void) ;
+    void (*plugin_draw_function)(void *context) ;
   }post;
 
   // solver options 
@@ -228,14 +226,6 @@ class Context_T {
     } mesh;
   } color;
   
-  // trackball functions 
-  void buildRotationMatrix(void);
-  void setQuaternion(double p1x, double p1y, double p2x, double p2y);
-  void addQuaternion(double p1x, double p1y, double p2x, double p2y);
-  void addQuaternionFromAxisAndAngle(double axis[3], double angle);
-  void setQuaternionFromEulerAngles(void);
-  void setEulerAnglesFromRotationMatrix(void);
-
   int big_endian; // is the machine big-endian?
 
   // how RGBA values are packed and unpacked into/from an unsigned
diff --git a/Common/CreateFile.cpp b/Common/CreateFile.cpp
index e7b527b5413d9a72e4514dcd9bb6b464f4c988e2..72d212eb4a04900eb84a919e70ffca01538647ac 100644
--- a/Common/CreateFile.cpp
+++ b/Common/CreateFile.cpp
@@ -117,8 +117,10 @@ void CreateOutputFile(const char *filename, int format)
   CTX.printing = 1;
 
 #if defined(HAVE_FLTK)
+  int vp[4];
+  GetStoredViewport(vp);
   GLint viewport[4];
-  for(int i = 0; i < 4; i++) viewport[i] = CTX.viewport[i];
+  for(int i = 0; i < 4; i++) viewport[i] = vp[i];
   GLint width = viewport[2] - viewport[0];
   GLint height = viewport[3] - viewport[1];
 #endif
@@ -139,7 +141,8 @@ void CreateOutputFile(const char *filename, int format)
 
   case FORMAT_MSH:
     GModel::current()->writeMSH(name, CTX.mesh.msh_file_version, CTX.mesh.binary, 
-                                CTX.mesh.save_all, CTX.mesh.save_parametric,CTX.mesh.scaling_factor);
+                                CTX.mesh.save_all, CTX.mesh.save_parametric,
+                                CTX.mesh.scaling_factor);
     break;
 
   case FORMAT_STL:
@@ -192,7 +195,8 @@ void CreateOutputFile(const char *filename, int format)
   case FORMAT_POS:
     GModel::current()->writePOS(name, CTX.print.pos_elementary, CTX.print.pos_element, 
                                 CTX.print.pos_gamma, CTX.print.pos_eta, CTX.print.pos_rho, 
-				CTX.print.pos_disto,CTX.mesh.save_all, CTX.mesh.scaling_factor);
+				CTX.print.pos_disto, CTX.mesh.save_all, 
+                                CTX.mesh.scaling_factor);
     break;
 
   case FORMAT_GEO:
@@ -306,8 +310,8 @@ void CreateOutputFile(const char *filename, int format)
           glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
           glMatrixMode(GL_PROJECTION);
           glLoadIdentity();
-          glOrtho((double)CTX.viewport[0], (double)CTX.viewport[2],
-                  (double)CTX.viewport[1], (double)CTX.viewport[3], -1., 1.);
+          glOrtho((double)viewport[0], (double)viewport[2],
+                  (double)viewport[1], (double)viewport[3], -1., 1.);
           glMatrixMode(GL_MODELVIEW);
           glLoadIdentity();
           glRasterPos2d(0, 0);
diff --git a/Common/GmshDefines.h b/Common/GmshDefines.h
index f8def9cb1662362781d6e2e519b72bda76a9a500..aeb8f1f15045c7078280ec8daae824077346ca86 100644
--- a/Common/GmshDefines.h
+++ b/Common/GmshDefines.h
@@ -101,4 +101,9 @@
 #define MESH_TRANSFINITE  1
 #define MESH_UNSTRUCTURED 2
 
+// Render mode
+#define GMSH_RENDER    1
+#define GMSH_SELECT    2
+#define GMSH_FEEDBACK  3
+
 #endif
diff --git a/Common/Makefile b/Common/Makefile
index 787d353ea4c1e96b1cc14e87dd08af2ab440c659..f5bfab8874a5f29b298df1bf4ffa27dca866bfdd 100644
--- a/Common/Makefile
+++ b/Common/Makefile
@@ -14,20 +14,18 @@ INC = ${DASH}I../Common ${DASH}I../Geo ${DASH}I../Mesh\
 
 CFLAGS = ${OPTIM} ${FLAGS} ${INC} ${SYSINCLUDE}
 
-SRC = Context.cpp\
-      Octree.cpp OctreeInternals.cpp\
-      Options.cpp\
-      CommandLine.cpp\
-      Gmsh.cpp\
+SRC = Gmsh.cpp\
       GmshMessage.cpp\
       GmshDaemon.cpp\
+      Options.cpp\
+      CommandLine.cpp\
       OS.cpp\
       OpenFile.cpp\
       CreateFile.cpp\
       Visibility.cpp\
-      Trackball.cpp\
       VertexArray.cpp\
       SmoothData.cpp\
+      Octree.cpp OctreeInternals.cpp\
       StringUtils.cpp\
       ListUtils.cpp\
       TreeUtils.cpp avl.cpp\
@@ -59,10 +57,28 @@ depend:
 	rm -f Makefile.new
 
 # DO NOT DELETE THIS LINE
-Context${OBJEXT}: Context.cpp ../Numeric/Numeric.h ../Numeric/NumericEmbedded.h \
-  Context.h ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h Trackball.h
-Octree${OBJEXT}: Octree.cpp Octree.h OctreeInternals.h
-OctreeInternals${OBJEXT}: OctreeInternals.cpp GmshMessage.h OctreeInternals.h
+Gmsh${OBJEXT}: Gmsh.cpp GmshDefines.h ../Geo/GModel.h ../Geo/GVertex.h \
+  ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
+  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Geo/GPoint.h \
+  ../Geo/SPoint2.h ../Geo/GEdge.h ../Geo/GEntity.h ../Geo/GVertex.h \
+  ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint3.h ../Geo/SPoint2.h \
+  ../Geo/GFace.h ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/GEdgeLoop.h \
+  ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
+  ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
+  ../Geo/SBoundingBox3d.h GmshMessage.h OpenFile.h CreateFile.h Options.h \
+  ../Post/ColorTable.h CommandLine.h OS.h ../Numeric/Numeric.h \
+  ../Numeric/NumericEmbedded.h ../Mesh/Generator.h ../Mesh/Field.h \
+  ../Post/PView.h Context.h ../Geo/CGNSOptions.h \
+  ../Mesh/PartitionOptions.h ../Mesh/Partition.h GmshDaemon.h \
+  ../Plugin/PluginManager.h
+GmshMessage${OBJEXT}: GmshMessage.cpp GmshMessage.h Gmsh.h Options.h \
+  ../Post/ColorTable.h Context.h ../Geo/CGNSOptions.h \
+  ../Mesh/PartitionOptions.h OS.h ../Fltk/GUI.h ../Fltk/Opengl_Window.h \
+  ../Graphics/drawContext.h ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h \
+  ../Fltk/Colorbar_Window.h ../Common/GmshUI.h ../Fltk/Popup_Button.h \
+  ../Fltk/SpherePosition_Widget.h ../Mesh/Field.h ../Post/PView.h \
+  ../Fltk/GUI_Extras.h
+GmshDaemon${OBJEXT}: GmshDaemon.cpp GmshMessage.h OS.h GmshSocket.h
 Options${OBJEXT}: Options.cpp GmshUI.h GmshDefines.h ../Geo/GModel.h \
   ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
   ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Geo/GPoint.h \
@@ -71,7 +87,7 @@ Options${OBJEXT}: Options.cpp GmshUI.h GmshDefines.h ../Geo/GModel.h \
   ../Geo/GFace.h ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/GEdgeLoop.h \
   ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
   ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.h GmshMessage.h ../Graphics/Draw.h \
+  ../Geo/SBoundingBox3d.h GmshMessage.h ../Fltk/Draw.h \
   ../Mesh/Generator.h Context.h ../Geo/CGNSOptions.h \
   ../Mesh/PartitionOptions.h Options.h ../Post/ColorTable.h \
   DefaultOptions.h ../Mesh/Field.h ../Post/PView.h \
@@ -80,8 +96,8 @@ Options${OBJEXT}: Options.cpp GmshUI.h GmshDefines.h ../Geo/GModel.h \
   ../Numeric/GmshMatrix.h ../Common/GmshMessage.h \
   ../Plugin/PluginManager.h ../Plugin/Plugin.h ../Common/Options.h \
   ../Post/PViewDataList.h ../Post/PViewData.h ../Fltk/Solvers.h \
-  ../Fltk/GUI.h ../Fltk/Opengl_Window.h ../Fltk/Colorbar_Window.h \
-  ../Common/GmshUI.h ../Fltk/Popup_Button.h \
+  ../Fltk/GUI.h ../Fltk/Opengl_Window.h ../Graphics/drawContext.h \
+  ../Fltk/Colorbar_Window.h ../Common/GmshUI.h ../Fltk/Popup_Button.h \
   ../Fltk/SpherePosition_Widget.h
 CommandLine${OBJEXT}: CommandLine.cpp GmshUI.h GmshDefines.h GmshVersion.h \
   GmshMessage.h OpenFile.h CommandLine.h Context.h ../Geo/CGNSOptions.h \
@@ -94,27 +110,6 @@ CommandLine${OBJEXT}: CommandLine.cpp GmshUI.h GmshDefines.h GmshVersion.h \
   ../Geo/GEdgeLoop.h ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h \
   ../Geo/Pair.h ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
   ../Geo/SBoundingBox3d.h CreateFile.h OS.h ../Post/PView.h
-Gmsh${OBJEXT}: Gmsh.cpp GmshDefines.h ../Geo/GModel.h ../Geo/GVertex.h \
-  ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Geo/GPoint.h \
-  ../Geo/SPoint2.h ../Geo/GEdge.h ../Geo/GEntity.h ../Geo/GVertex.h \
-  ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint3.h ../Geo/SPoint2.h \
-  ../Geo/GFace.h ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/GEdgeLoop.h \
-  ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
-  ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.h GmshMessage.h OpenFile.h CreateFile.h Options.h \
-  ../Post/ColorTable.h CommandLine.h OS.h ../Numeric/Numeric.h \
-  ../Numeric/NumericEmbedded.h ../Mesh/Generator.h ../Mesh/Field.h \
-  ../Post/PView.h Context.h ../Geo/CGNSOptions.h \
-  ../Mesh/PartitionOptions.h ../Mesh/Partition.h GmshDaemon.h \
-  ../Plugin/PluginManager.h
-GmshMessage${OBJEXT}: GmshMessage.cpp GmshMessage.h Gmsh.h Options.h \
-  ../Post/ColorTable.h Context.h ../Geo/CGNSOptions.h \
-  ../Mesh/PartitionOptions.h OS.h ../Fltk/GUI.h ../Fltk/Opengl_Window.h \
-  ../Fltk/Colorbar_Window.h ../Common/GmshUI.h ../Fltk/Popup_Button.h \
-  ../Fltk/SpherePosition_Widget.h ../Mesh/Field.h ../Post/PView.h \
-  ../Geo/SPoint3.h ../Fltk/GUI_Extras.h
-GmshDaemon${OBJEXT}: GmshDaemon.cpp GmshMessage.h OS.h GmshSocket.h
 OS${OBJEXT}: OS.cpp GmshMessage.h
 OpenFile${OBJEXT}: OpenFile.cpp GmshMessage.h ../Geo/Geo.h \
   ../Common/GmshDefines.h ../Geo/gmshSurface.h ../Geo/Pair.h \
@@ -133,9 +128,9 @@ OpenFile${OBJEXT}: OpenFile.cpp GmshMessage.h ../Geo/Geo.h \
   ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h OpenFile.h \
   CommandLine.h ../Graphics/ReadImg.h OS.h StringUtils.h \
   ../Parser/Parser.h ../Post/PView.h ../Post/PViewData.h GmshUI.h \
-  ../Graphics/Draw.h ../Graphics/SelectBuffer.h ../Fltk/GUI.h \
-  ../Fltk/Opengl_Window.h ../Fltk/Colorbar_Window.h ../Common/GmshUI.h \
-  ../Post/ColorTable.h ../Fltk/Popup_Button.h \
+  ../Fltk/Draw.h ../Graphics/SelectBuffer.h ../Graphics/drawContext.h \
+  ../Fltk/GUI.h ../Fltk/Opengl_Window.h ../Fltk/Colorbar_Window.h \
+  ../Common/GmshUI.h ../Post/ColorTable.h ../Fltk/Popup_Button.h \
   ../Fltk/SpherePosition_Widget.h ../Mesh/Field.h
 CreateFile${OBJEXT}: CreateFile.cpp GmshMessage.h ../Geo/GModel.h \
   ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
@@ -149,7 +144,7 @@ CreateFile${OBJEXT}: CreateFile.cpp GmshMessage.h ../Geo/GModel.h \
   ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h Options.h \
   ../Post/ColorTable.h GmshUI.h ../Graphics/gl2ps.h ../Graphics/gl2gif.h \
   ../Graphics/PixelBuffer.h ../Common/GmshUI.h ../Common/GmshMessage.h \
-  ../Common/MallocUtils.h ../Graphics/Draw.h ../Graphics/gl2jpeg.h \
+  ../Fltk/Draw.h ../Common/MallocUtils.h ../Graphics/gl2jpeg.h \
   ../Graphics/PixelBuffer.h ../Graphics/gl2png.h \
   ../Graphics/PixelBuffer.h ../Graphics/gl2ppm.h \
   ../Graphics/PixelBuffer.h ../Graphics/gl2yuv.h \
@@ -168,13 +163,14 @@ Visibility${OBJEXT}: Visibility.cpp Visibility.h GmshDefines.h ../Geo/GVertex.h
   ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h \
   ../Geo/SVector3.h ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
   ../Numeric/GmshMatrix.h ../Parser/Parser.h
-Trackball${OBJEXT}: Trackball.cpp Trackball.h
 VertexArray${OBJEXT}: VertexArray.cpp VertexArray.h ../Geo/SVector3.h \
   ../Geo/SPoint3.h Context.h ../Geo/CGNSOptions.h \
   ../Mesh/PartitionOptions.h ../Numeric/Numeric.h \
   ../Numeric/NumericEmbedded.h
 SmoothData${OBJEXT}: SmoothData.cpp SmoothData.h ../Numeric/Numeric.h \
   ../Numeric/NumericEmbedded.h
+Octree${OBJEXT}: Octree.cpp Octree.h OctreeInternals.h
+OctreeInternals${OBJEXT}: OctreeInternals.cpp GmshMessage.h OctreeInternals.h
 StringUtils${OBJEXT}: StringUtils.cpp StringUtils.h
 ListUtils${OBJEXT}: ListUtils.cpp MallocUtils.h ListUtils.h TreeUtils.h avl.h \
   GmshMessage.h
diff --git a/Common/Options.cpp b/Common/Options.cpp
index 5ac555ec77c0c51644bda0e1172f990fc1abb2eb..11dd79b05f54fe52e30327a4412a16890160a017 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -33,7 +33,8 @@ extern GUI *WID;
 extern void activate_cb(Fl_Widget* w, void* data);
 #endif
 
-extern Context_T CTX;
+// the single static option context
+Context_T CTX;
 
 // General routines for string options
 
@@ -104,7 +105,7 @@ static void Print_StringOptions(int num, int level, int diff, int help,
           fprintf(file, "%s\n", tmp);
         else{
           // remove \n, \t, \r
-          for(int i = 0; i < strlen(tmp); i++)
+          for(unsigned int i = 0; i < strlen(tmp); i++)
             if(tmp[i] == '\n' || tmp[i] == '\t' || tmp[i] == '\r') tmp[i] = ' ';
           // Warning: must call Msg::Direct(level, ...) here, because
           // we cannot use tmp as a format string (it can contain %s!)
@@ -116,7 +117,8 @@ static void Print_StringOptions(int num, int level, int diff, int help,
   }
 }
 
-static const char *Get_OptionSaveLevel(int level){
+static const char *Get_OptionSaveLevel(int level)
+{
   if(level & GMSH_SESSIONRC){
     return "General.SessionFileName";
   }
@@ -463,13 +465,11 @@ void Init_Options(int num)
   CTX.output_filename = NULL;
   CTX.bgm_filename = NULL;
   CTX.lc = 1.0;
-  CTX.viewport[0] = CTX.viewport[1] = 0;
+  CTX.tmp_viewport[0] = CTX.tmp_viewport[1] = 0;
   CTX.min[0] = CTX.min[1] = CTX.min[2] = 0.0;
   CTX.max[0] = CTX.max[1] = CTX.max[2] = 1.0;
   CTX.cg[0] = CTX.cg[1] = CTX.cg[2] = 0.0;
-  CTX.vxmin = CTX.vymin = CTX.vxmax = CTX.vymax = 0.;
   CTX.render_mode = GMSH_RENDER;
-  CTX.pixel_equiv_x = CTX.pixel_equiv_y = 0.;
   CTX.polygon_offset = 0;
   CTX.printing = 0;
   CTX.mesh_timer[0] = CTX.mesh_timer[1] = CTX.mesh_timer[2] = 0.;
@@ -600,7 +600,8 @@ static void Print_ColorTable(int num, int diff, const char *prefix, FILE *file)
 }
 
 //used in field options, sorry if it's already implemented somewhere else...
-static void Sanitize_String_Texi(std::string &s){
+static void Sanitize_String_Texi(std::string &s)
+{
   int i=-1;
   while ((i=s.find('\n',i+1))>=0){
     s.insert(i,"@*");
@@ -2405,15 +2406,29 @@ double opt_general_graphics_fontsize(OPT_ARGS_NUM)
 double opt_general_viewport2(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
-    CTX.viewport[2] = (int)val;
-  return CTX.viewport[2];
+    CTX.tmp_viewport[2] = (int)val;
+#if defined(HAVE_FLTK)
+  if(WID){
+    if(action & GMSH_SET)
+      WID->g_opengl_window->getDrawContext()->viewport[2] = val;
+    return WID->g_opengl_window->getDrawContext()->viewport[2];
+  }
+#endif
+  return CTX.tmp_viewport[2];
 }
 
 double opt_general_viewport3(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
-    CTX.viewport[3] = (int)val;
-  return CTX.viewport[3];
+    CTX.tmp_viewport[3] = (int)val;
+#if defined(HAVE_FLTK)
+  if(WID){
+    if(action & GMSH_SET)
+      WID->g_opengl_window->getDrawContext()->viewport[3] = val;
+    return WID->g_opengl_window->getDrawContext()->viewport[3];
+  }
+#endif
+  return CTX.tmp_viewport[3];
 }
 
 double opt_general_polygon_offset_always(OPT_ARGS_NUM)
@@ -2727,22 +2742,43 @@ double opt_general_confirm_overwrite(OPT_ARGS_NUM)
 double opt_general_rotation0(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
-    CTX.r[0] = val;
-  return CTX.r[0];
+    CTX.tmp_r[0] = val;
+#if defined(HAVE_FLTK)
+  if(WID){
+    if(action & GMSH_SET)
+      WID->g_opengl_window->getDrawContext()->r[0] = val;
+    return WID->g_opengl_window->getDrawContext()->r[0];
+  }
+#endif
+  return CTX.tmp_r[0];
 }
 
 double opt_general_rotation1(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
-    CTX.r[1] = val;
-  return CTX.r[1];
+    CTX.tmp_r[1] = val;
+#if defined(HAVE_FLTK)
+  if(WID){
+    if(action & GMSH_SET)
+      WID->g_opengl_window->getDrawContext()->r[1] = val;
+    return WID->g_opengl_window->getDrawContext()->r[1];
+  }
+#endif
+  return CTX.tmp_r[1];
 }
 
 double opt_general_rotation2(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
-    CTX.r[2] = val;
-  return CTX.r[2];
+    CTX.tmp_r[2] = val;
+#if defined(HAVE_FLTK)
+  if(WID){
+    if(action & GMSH_SET)
+      WID->g_opengl_window->getDrawContext()->r[2] = val;
+    return WID->g_opengl_window->getDrawContext()->r[2];
+  }
+#endif
+  return CTX.tmp_r[2];
 }
 
 double opt_general_rotation_center0(OPT_ARGS_NUM)
@@ -2781,111 +2817,161 @@ double opt_general_rotation_center2(OPT_ARGS_NUM)
 double opt_general_quaternion0(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
-    CTX.quaternion[0] = val;
+    CTX.tmp_quaternion[0] = val;
 #if defined(HAVE_FLTK)
-  if(WID && (action & GMSH_GUI))
-    WID->update_manip_window();
+  if(WID){
+    if(action & GMSH_SET)
+      WID->g_opengl_window->getDrawContext()->quaternion[0] = val;
+    if(action & GMSH_GUI)
+      WID->update_manip_window();
+    return WID->g_opengl_window->getDrawContext()->quaternion[0];
+  }
 #endif
-  return CTX.quaternion[0];
+  return CTX.tmp_quaternion[0];
 }
 
 double opt_general_quaternion1(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
-    CTX.quaternion[1] = val;
+    CTX.tmp_quaternion[1] = val;
 #if defined(HAVE_FLTK)
-  if(WID && (action & GMSH_GUI))
-    WID->update_manip_window();
+  if(WID){
+    if(action & GMSH_SET)
+      WID->g_opengl_window->getDrawContext()->quaternion[1] = val;
+    if(action & GMSH_GUI)
+      WID->update_manip_window();
+    return WID->g_opengl_window->getDrawContext()->quaternion[1];
+  }
 #endif
-  return CTX.quaternion[1];
+  return CTX.tmp_quaternion[1];
 }
 
 double opt_general_quaternion2(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
-    CTX.quaternion[2] = val;
+    CTX.tmp_quaternion[2] = val;
 #if defined(HAVE_FLTK)
-  if(WID && (action & GMSH_GUI))
-    WID->update_manip_window();
+  if(WID){
+    if(action & GMSH_SET)
+      WID->g_opengl_window->getDrawContext()->quaternion[2] = val;
+    if(action & GMSH_GUI)
+      WID->update_manip_window();
+    return WID->g_opengl_window->getDrawContext()->quaternion[2];
+  }
 #endif
-  return CTX.quaternion[2];
+  return CTX.tmp_quaternion[2];
 }
 
 double opt_general_quaternion3(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
-    CTX.quaternion[3] = val;
+    CTX.tmp_quaternion[3] = val;
 #if defined(HAVE_FLTK)
-  if(WID && (action & GMSH_GUI))
-    WID->update_manip_window();
+  if(WID){
+    if(action & GMSH_SET)
+      WID->g_opengl_window->getDrawContext()->quaternion[3] = val;
+    if(action & GMSH_GUI)
+      WID->update_manip_window();
+    return WID->g_opengl_window->getDrawContext()->quaternion[3];
+  }
 #endif
-  return CTX.quaternion[3];
+  return CTX.tmp_quaternion[3];
 }
 
 double opt_general_translation0(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
-    CTX.t[0] = val;
+    CTX.tmp_t[0] = val;
 #if defined(HAVE_FLTK)
-  if(WID && (action & GMSH_GUI))
-    WID->update_manip_window();
+  if(WID){
+    if(action & GMSH_SET)
+      WID->g_opengl_window->getDrawContext()->t[0] = val;
+    if(action & GMSH_GUI)
+      WID->update_manip_window();
+    return WID->g_opengl_window->getDrawContext()->t[0];
+  }
 #endif
-  return CTX.t[0];
+  return CTX.tmp_t[0];
 }
 
 double opt_general_translation1(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
-    CTX.t[1] = val;
+    CTX.tmp_t[1] = val;
 #if defined(HAVE_FLTK)
-  if(WID && (action & GMSH_GUI))
-    WID->update_manip_window();
+  if(WID){
+    if(action & GMSH_SET)
+      WID->g_opengl_window->getDrawContext()->t[1] = val;
+    if(action & GMSH_GUI)
+      WID->update_manip_window();
+    return WID->g_opengl_window->getDrawContext()->t[1];
+  }
 #endif
-  return CTX.t[1];
+  return CTX.tmp_t[1];
 }
 
 double opt_general_translation2(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
-    CTX.t[2] = val;
+    CTX.tmp_t[2] = val;
 #if defined(HAVE_FLTK)
-  if(WID && (action & GMSH_GUI))
-    WID->update_manip_window();
+  if(WID){
+    if(action & GMSH_SET)
+      WID->g_opengl_window->getDrawContext()->t[2] = val;
+    if(action & GMSH_GUI)
+      WID->update_manip_window();
+    return WID->g_opengl_window->getDrawContext()->t[2];
+  }
 #endif
-  return CTX.t[2];
+  return CTX.tmp_t[2];
 }
 
 double opt_general_scale0(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
-    CTX.s[0] = val ? val : 1.0;
+    CTX.tmp_s[0] = val ? val : 1.0;
 #if defined(HAVE_FLTK)
-  if(WID && (action & GMSH_GUI))
-    WID->update_manip_window();
+  if(WID){
+    if(action & GMSH_SET)
+      WID->g_opengl_window->getDrawContext()->s[0] = val ? val : 1.0;
+    if(action & GMSH_GUI)
+      WID->update_manip_window();
+    return WID->g_opengl_window->getDrawContext()->s[0];
+  }
 #endif
-  return CTX.s[0];
+  return CTX.tmp_s[0];
 }
 
 double opt_general_scale1(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
-    CTX.s[1] = val ? val : 1.0;
+    CTX.tmp_s[1] = val ? val : 1.0;
 #if defined(HAVE_FLTK)
-  if(WID && (action & GMSH_GUI))
-    WID->update_manip_window();
+  if(WID){
+    if(action & GMSH_SET)
+      WID->g_opengl_window->getDrawContext()->s[1] = val ? val : 1.0;
+    if(action & GMSH_GUI)
+      WID->update_manip_window();
+    return WID->g_opengl_window->getDrawContext()->s[1];
+  }
 #endif
-  return CTX.s[1];
+  return CTX.tmp_s[1];
 }
 
 double opt_general_scale2(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
-    CTX.s[2] = val ? val : 1.0;
+    CTX.tmp_s[2] = val ? val : 1.0;
 #if defined(HAVE_FLTK)
-  if(WID && (action & GMSH_GUI))
-    WID->update_manip_window();
+  if(WID){
+    if(action & GMSH_SET)
+      WID->g_opengl_window->getDrawContext()->s[2] = val ? val : 1.0;
+    if(action & GMSH_GUI)
+      WID->update_manip_window();
+    return WID->g_opengl_window->getDrawContext()->s[2];
+  }
 #endif
-  return CTX.s[2];
+  return CTX.tmp_s[2];
 }
 
 double opt_general_clip_factor(OPT_ARGS_NUM)
@@ -3130,7 +3216,8 @@ double opt_general_axes(OPT_ARGS_NUM)
   return CTX.axes;
 }
 
-double opt_general_axes_mikado(OPT_ARGS_NUM){
+double opt_general_axes_mikado(OPT_ARGS_NUM)
+{
   if(action & GMSH_SET) {
     CTX.axes_mikado = (int)val;
   }
diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp
index 967ab7fe86c529ba6ce3b7b9f2acdd4c254553e6..5fce333190e9efbf240742138cfd02f8a8c74f5f 100644
--- a/Fltk/Callbacks.cpp
+++ b/Fltk/Callbacks.cpp
@@ -374,68 +374,70 @@ void status_xyz1p_cb(CALLBACK_ARGS)
 {
   const char *str = (const char*)data;
 
+  drawContext *ctx = WID->g_opengl_window->getDrawContext();
+
   if(!strcmp(str, "r")){ // rotate 90 degress around axis perp to the screen
     double axis[3] = {0., 0., 1.};
     if(!Fl::event_state(FL_SHIFT))
-      CTX.addQuaternionFromAxisAndAngle(axis, -90.);
+      ctx->addQuaternionFromAxisAndAngle(axis, -90.);
     else
-      CTX.addQuaternionFromAxisAndAngle(axis, 90.);
+      ctx->addQuaternionFromAxisAndAngle(axis, 90.);
     Draw();
   }
   else if(!strcmp(str, "x")){ // X pointing out or into the screen
     if(!Fl::event_state(FL_SHIFT)){
-      CTX.r[0] = -90.;
-      CTX.r[1] = 0.;
-      CTX.r[2] = -90.;
+      ctx->r[0] = -90.;
+      ctx->r[1] = 0.;
+      ctx->r[2] = -90.;
     }
     else{
-      CTX.r[0] = -90.;
-      CTX.r[1] = 0.;
-      CTX.r[2] = 90.;
+      ctx->r[0] = -90.;
+      ctx->r[1] = 0.;
+      ctx->r[2] = 90.;
     }
-    CTX.setQuaternionFromEulerAngles();
+    ctx->setQuaternionFromEulerAngles();
     Draw();
   }
   else if(!strcmp(str, "y")){ // Y pointing out or into the screen
     if(!Fl::event_state(FL_SHIFT)){
-      CTX.r[0] = -90.;
-      CTX.r[1] = 0.;
-      CTX.r[2] = 180.;
+      ctx->r[0] = -90.;
+      ctx->r[1] = 0.;
+      ctx->r[2] = 180.;
     }
     else{
-      CTX.r[0] = -90.;
-      CTX.r[1] = 0.;
-      CTX.r[2] = 0.;
+      ctx->r[0] = -90.;
+      ctx->r[1] = 0.;
+      ctx->r[2] = 0.;
     }
-    CTX.setQuaternionFromEulerAngles();
+    ctx->setQuaternionFromEulerAngles();
     Draw();
   }
   else if(!strcmp(str, "z")){ // Z pointing out or into the screen
     if(!Fl::event_state(FL_SHIFT)){
-      CTX.r[0] = 0.;
-      CTX.r[1] = 0.;
-      CTX.r[2] = 0.;
+      ctx->r[0] = 0.;
+      ctx->r[1] = 0.;
+      ctx->r[2] = 0.;
     }
     else{
-      CTX.r[0] = 0.;
-      CTX.r[1] = 180.;
-      CTX.r[2] = 0.;
+      ctx->r[0] = 0.;
+      ctx->r[1] = 180.;
+      ctx->r[2] = 0.;
     }
-    CTX.setQuaternionFromEulerAngles();
+    ctx->setQuaternionFromEulerAngles();
     Draw();
   }
   else if(!strcmp(str, "1:1")){ // reset translation and scaling
-    CTX.t[0] = CTX.t[1] = CTX.t[2] = 0.;
-    CTX.s[0] = CTX.s[1] = CTX.s[2] = 1.;
+    ctx->t[0] = ctx->t[1] = ctx->t[2] = 0.;
+    ctx->s[0] = ctx->s[1] = ctx->s[2] = 1.;
     Draw();
   }
   else if(!strcmp(str, "reset")){ // reset everything
-    CTX.t[0] = CTX.t[1] = CTX.t[2] = 0.;
-    CTX.s[0] = CTX.s[1] = CTX.s[2] = 1.;
-    CTX.r[0] = 0.;
-    CTX.r[1] = 0.;
-    CTX.r[2] = 0.;
-    CTX.setQuaternionFromEulerAngles();
+    ctx->t[0] = ctx->t[1] = ctx->t[2] = 0.;
+    ctx->s[0] = ctx->s[1] = ctx->s[2] = 1.;
+    ctx->r[0] = 0.;
+    ctx->r[1] = 0.;
+    ctx->r[2] = 0.;
+    ctx->setQuaternionFromEulerAngles();
     Draw();
   }
   else if(!strcmp(str, "p")){ // toggle projection mode
@@ -2459,16 +2461,17 @@ void manip_cb(CALLBACK_ARGS)
 
 void manip_update_cb(CALLBACK_ARGS)
 {
-  CTX.r[0] = WID->manip_value[0]->value();
-  CTX.r[1] = WID->manip_value[1]->value();
-  CTX.r[2] = WID->manip_value[2]->value();
-  CTX.t[0] = WID->manip_value[3]->value();
-  CTX.t[1] = WID->manip_value[4]->value();
-  CTX.t[2] = WID->manip_value[5]->value();
-  CTX.s[0] = WID->manip_value[6]->value();
-  CTX.s[1] = WID->manip_value[7]->value();
-  CTX.s[2] = WID->manip_value[8]->value();
-  CTX.setQuaternionFromEulerAngles();
+  drawContext *ctx = WID->g_opengl_window->getDrawContext();
+  ctx->r[0] = WID->manip_value[0]->value();
+  ctx->r[1] = WID->manip_value[1]->value();
+  ctx->r[2] = WID->manip_value[2]->value();
+  ctx->t[0] = WID->manip_value[3]->value();
+  ctx->t[1] = WID->manip_value[4]->value();
+  ctx->t[2] = WID->manip_value[5]->value();
+  ctx->s[0] = WID->manip_value[6]->value();
+  ctx->s[1] = WID->manip_value[7]->value();
+  ctx->s[2] = WID->manip_value[8]->value();
+  ctx->setQuaternionFromEulerAngles();
   Draw();
 }
 
diff --git a/Fltk/Opengl.cpp b/Fltk/Draw.cpp
similarity index 63%
rename from Fltk/Opengl.cpp
rename to Fltk/Draw.cpp
index 0266d566f67e733c545787d185be3ceca3c93259..6de266aef87d49d4c09327e430d003668789f772 100644
--- a/Fltk/Opengl.cpp
+++ b/Fltk/Draw.cpp
@@ -3,20 +3,16 @@
 // See the LICENSE.txt file for license information. Please report all
 // bugs and problems to <gmsh@geuz.org>.
 
+#include "GUI.h"
 #include "GmshUI.h"
 #include "GmshDefines.h"
-#include "Numeric.h"
-#include "Context.h"
 #include "Draw.h"
-#include "SelectBuffer.h"
 #include "StringUtils.h"
-#include "GUI.h"
 #include "gl2ps.h"
+#include "Context.h"
 
-extern GUI *WID;
 extern Context_T CTX;
-
-// Draw specialization
+extern GUI *WID;
 
 void SetOpenglContext()
 {
@@ -24,12 +20,45 @@ void SetOpenglContext()
   WID->make_opengl_current();
 }
 
+void ClearOpengl()
+{
+  glClearColor(CTX.UNPACK_RED(CTX.color.bg) / 255.,
+               CTX.UNPACK_GREEN(CTX.color.bg) / 255.,
+               CTX.UNPACK_BLUE(CTX.color.bg) / 255., 0.);
+  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+}
+
 void Draw()
 {
   if(!WID) return;
   WID->redraw_opengl();
 }
 
+void Draw2d3d()
+{
+  if(!WID) return;
+  WID->g_opengl_window->getDrawContext()->draw3d();
+  WID->g_opengl_window->getDrawContext()->draw2d();
+}
+
+void DrawPlugin(void (*draw)(void *context))
+{
+  CTX.post.plugin_draw_function = draw;
+  int old = CTX.draw_bbox;
+  CTX.draw_bbox = 1;
+  if(CTX.fast_redraw){
+    CTX.post.draw = 0;
+    CTX.mesh.draw = 0;
+  }
+  if(!CTX.batch) 
+    Draw();
+  // this is reset in each plugin run/cancel callback:
+  // CTX.post.plugin_draw_function = NULL;
+  CTX.draw_bbox = old;
+  CTX.post.draw = 1;
+  CTX.mesh.draw = 1;
+}
+
 void Draw_String(std::string s, const char *font_name, int font_enum, 
                  int font_size, int align)
 {
@@ -137,89 +166,45 @@ void Draw_OnScreenMessages()
   gl_font(CTX.gl_font_enum, CTX.gl_fontsize);
   double h = gl_height();
   
+  drawContext *ctx = WID->g_opengl_window->getDrawContext();
+  
   if(strlen(WID->onscreen_buffer[0])){
     double w = gl_width(WID->onscreen_buffer[0]);
-    glRasterPos2d(CTX.viewport[2]/2.-w/2., CTX.viewport[3] - 1.2*h);
+    glRasterPos2d(ctx->viewport[2] / 2. - w / 2., 
+                  ctx->viewport[3] - 1.2 * h);
     gl_draw(WID->onscreen_buffer[0]);
   }
   if(strlen(WID->onscreen_buffer[1])){
     double w = gl_width(WID->onscreen_buffer[1]);
-    glRasterPos2d(CTX.viewport[2]/2.-w/2., CTX.viewport[3] - 2.4*h);
+    glRasterPos2d(ctx->viewport[2] / 2. - w / 2.,
+                  ctx->viewport[3] - 2.4 * h);
     gl_draw(WID->onscreen_buffer[1]);
   }
 }
 
-// Select entity routine
+void GetStoredViewport(int viewport[4])
+{
+  if(!WID) return;
+  for(int i = 0; i < 4; i++)
+    viewport[i] = WID->g_opengl_window->getDrawContext()->viewport[i];
+}
 
-char SelectEntity(int type, 
-                  std::vector<GVertex*> &vertices,
-                  std::vector<GEdge*> &edges,
-                  std::vector<GFace*> &faces,
-                  std::vector<GRegion*> &regions,
-                  std::vector<MElement*> &elements)
+void Viewport2World(double win[3], double xyz[3])
 {
-  if(!WID) return 'q';
-
-  WID->g_opengl_window->take_focus(); // force keyboard focus in GL window 
-  WID->g_opengl_window->SelectionMode = true; // enable lasso selection
-
-  WID->selection = type;
-  WID->try_selection = 0;
-  WID->quit_selection = 0;
-  WID->end_selection = 0;
-  WID->undo_selection = 0;
-  WID->invert_selection = 0;
-
-  while(1) {
-    vertices.clear();
-    edges.clear();
-    faces.clear();
-    regions.clear();
-    elements.clear();
-    WID->wait();
-    if(WID->quit_selection) {
-      WID->selection = ENT_NONE;
-      WID->g_opengl_window->SelectionMode = false;
-      WID->g_opengl_window->LassoMode = false;
-      WID->g_opengl_window->AddPointMode = false;
-      WID->g_opengl_window->cursor(FL_CURSOR_DEFAULT, FL_BLACK, FL_WHITE);
-      return 'q';
-    }
-    if(WID->end_selection) {
-      WID->end_selection = 0;
-      WID->selection = ENT_NONE;
-      return 'e';
-    }
-    if(WID->undo_selection) {
-      WID->undo_selection = 0;
-      return 'u';
-    }
-    if(WID->invert_selection) {
-      WID->invert_selection = 0;
-      return 'i';
-    }
-    if(WID->try_selection) {
-      bool add = (WID->try_selection > 0) ? true : false;
-      bool multi = (abs(WID->try_selection) > 1) ? true : false;
-      WID->try_selection = 0;
-      if(WID->selection == ENT_NONE){ // just report the mouse click
-        WID->g_opengl_window->SelectionMode = false;
-        return 'c';
-      }
-      else if(ProcessSelectionBuffer(WID->selection, multi, true,
-                                     WID->try_selection_xywh[0],
-                                     WID->try_selection_xywh[1], 
-                                     WID->try_selection_xywh[2],
-                                     WID->try_selection_xywh[3], 
-                                     vertices, edges, faces, regions,
-                                     elements)){
-        WID->selection = ENT_NONE;
-        WID->g_opengl_window->SelectionMode = false;
-        if(add)
-          return 'l';
-        else
-          return 'r';
-      }
-    }
-  }
+  GLint viewport[4];
+  GLdouble model[16], proj[16];
+  glGetIntegerv(GL_VIEWPORT, viewport);
+  glGetDoublev(GL_PROJECTION_MATRIX, proj);
+  glGetDoublev(GL_MODELVIEW_MATRIX, model);
+  gluUnProject(win[0], win[1], win[2], model, proj, viewport, &xyz[0], &xyz[1], &xyz[2]);
+}
+
+void World2Viewport(double xyz[3], double win[3])
+{
+  GLint viewport[4];
+  GLdouble model[16], proj[16];
+  glGetIntegerv(GL_VIEWPORT, viewport);
+  glGetDoublev(GL_PROJECTION_MATRIX, proj);
+  glGetDoublev(GL_MODELVIEW_MATRIX, model);
+  gluProject(xyz[0], xyz[1], xyz[2], model, proj, viewport, &win[0], &win[1], &win[2]);
 }
diff --git a/Fltk/Draw.h b/Fltk/Draw.h
new file mode 100644
index 0000000000000000000000000000000000000000..e23db3134af99572798ce9d3f507a05fa99eb5f0
--- /dev/null
+++ b/Fltk/Draw.h
@@ -0,0 +1,28 @@
+// Gmsh - Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#ifndef _DRAW_H_
+#define _DRAW_H_
+
+#include <string>
+
+void SetOpenglContext();
+void ClearOpengl();
+
+void Draw();
+void Draw2d3d();
+void DrawPlugin(void (*draw)(void *context));
+
+void Draw_String(std::string);
+void Draw_String(std::string, double style);
+void Draw_String_Center(std::string);
+void Draw_String_Right(std::string);
+void Draw_OnScreenMessages();
+
+void GetStoredViewport(int viewport[4]);
+void Viewport2World(double win[3], double xyz[3]);
+void World2Viewport(double xyz[3], double win[3]);
+
+#endif
diff --git a/Fltk/GUI.cpp b/Fltk/GUI.cpp
index 0fc846c4d8487635b57576162b815076499f81d7..4af972db829167abdad5cbda87c38cd0c1e22fe4 100644
--- a/Fltk/GUI.cpp
+++ b/Fltk/GUI.cpp
@@ -510,8 +510,6 @@ int GetFontSize()
 
 // Definition of global shortcuts
 
-#include "GmshSocket.h"
-
 int GUI::global_shortcuts(int event)
 {
   // we only handle shortcuts here
@@ -523,15 +521,6 @@ int GUI::global_shortcuts(int event)
     mod_geometry_cb(0, 0);
     return 1;
   }
-  // FIXME TESTING ONLY -- TO REMOVE LATER
-  else if(Fl::test_shortcut(FL_CTRL + 'p')) {
-    Msg::Info("TEST DAEMON!");
-    if(SINFO[2].server){
-      Msg::Info("SENDING COMMAND!");
-      SINFO[2].server->SendString(GmshSocket::CLIENT_INFO, "HEY YOU!");
-    }
-    return 1;
-  }
   else if(Fl::test_shortcut('1') || Fl::test_shortcut(FL_F + 1)) {
     mesh_1d_cb(0, 0);
     mod_mesh_cb(0, 0);
@@ -1444,8 +1433,8 @@ void GUI::create_graphic_window()
 
   int sh = 2 * fontsize - 4;    // status bar height
   int sw = fontsize + 3;        // status button width
-  int width = CTX.viewport[2] - CTX.viewport[0];
-  int glheight = CTX.viewport[3] - CTX.viewport[1];
+  int width = CTX.tmp_viewport[2] - CTX.tmp_viewport[0];
+  int glheight = CTX.tmp_viewport[3] - CTX.tmp_viewport[1];
   int height = glheight + sh;
 
   // the graphic window is the main window: it should be a normal
@@ -2441,8 +2430,6 @@ void GUI::create_option_window()
       mesh_choice[5]->menu(menu_recombine_algo);
       mesh_choice[5]->align(FL_ALIGN_RIGHT);
       mesh_choice[5]->callback(mesh_options_ok_cb);
-      // not reimplemented yet
-      //      ((Fl_Menu_Item*)mesh_choice[5]->menu())[1].deactivate();
 
       mesh_value[0] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 4 * BH, IW, BH, "Smoothing steps");
       mesh_value[0]->minimum(0);
@@ -4682,17 +4669,17 @@ void GUI::update_manip_window(int force)
   if(force || manip_window->shown()){
     double val1 = CTX.lc;
     for(int i = 0; i < 3; i++){
-      manip_value[i]->value(CTX.r[i]);
+      manip_value[i]->value(g_opengl_window->getDrawContext()->r[i]);
       manip_value[i]->minimum(-360.);
       manip_value[i]->maximum(360.);
       manip_value[i]->step(1.);
 
-      manip_value[i+3]->value(CTX.t[i]);
+      manip_value[i+3]->value(g_opengl_window->getDrawContext()->t[i]);
       manip_value[i+3]->minimum(-val1);
       manip_value[i+3]->maximum(val1);
       manip_value[i+3]->step(val1/200.);
 
-      manip_value[i+6]->value(CTX.s[i]);
+      manip_value[i+6]->value(g_opengl_window->getDrawContext()->s[i]);
       manip_value[i+6]->minimum(0.01);
       manip_value[i+6]->maximum(100.);
       manip_value[i+6]->step(0.01);
diff --git a/Fltk/Makefile b/Fltk/Makefile
index 8d90c4c1bda5fa6fa880bfd056bdf808bac97719..ee51ec063e2b1b179ae18cca9124d44bdc92220d 100644
--- a/Fltk/Makefile
+++ b/Fltk/Makefile
@@ -20,7 +20,7 @@ SRC = Main.cpp \
         GUI_Projection.cpp\
         GUI_Classifier.cpp\
       Callbacks.cpp\
-      Opengl.cpp\
+      Draw.cpp\
       Opengl_Window.cpp\
       Colorbar_Window.cpp\
       Solvers.cpp
@@ -54,30 +54,29 @@ depend:
 	rm -f Makefile.new
 
 # DO NOT DELETE THIS LINE
-Main${OBJEXT}: Main.cpp GUI.h Opengl_Window.h Colorbar_Window.h \
+Main${OBJEXT}: Main.cpp GUI.h Opengl_Window.h ../Graphics/drawContext.h \
+  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h Colorbar_Window.h \
   ../Common/GmshUI.h ../Post/ColorTable.h Popup_Button.h \
   SpherePosition_Widget.h ../Mesh/Field.h ../Post/PView.h \
-  ../Geo/SPoint3.h ../Common/Gmsh.h ../Common/GmshMessage.h \
-  ../Graphics/Draw.h ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h \
-  ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h \
-  ../Common/Options.h ../Parser/Parser.h ../Common/OpenFile.h \
-  ../Common/CommandLine.h Solvers.h ../Plugin/PluginManager.h \
-  ../Geo/GModel.h ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/Range.h \
-  ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h ../Geo/GPoint.h \
-  ../Geo/SPoint2.h ../Geo/GEdge.h ../Geo/GEntity.h ../Geo/GVertex.h \
-  ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint3.h ../Geo/SPoint2.h \
-  ../Geo/GFace.h ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/GEdgeLoop.h \
-  ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
-  ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.h ../Mesh/BackgroundMesh.h
+  ../Common/Gmsh.h ../Common/GmshMessage.h Draw.h ../Common/Context.h \
+  ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h ../Common/Options.h \
+  ../Parser/Parser.h ../Common/OpenFile.h ../Common/CommandLine.h \
+  Solvers.h ../Plugin/PluginManager.h ../Geo/GModel.h ../Geo/GVertex.h \
+  ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
+  ../Geo/SBoundingBox3d.h ../Geo/GPoint.h ../Geo/SPoint2.h ../Geo/GEdge.h \
+  ../Geo/GEntity.h ../Geo/GVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h \
+  ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/GFace.h ../Geo/GEntity.h \
+  ../Geo/GPoint.h ../Geo/GEdgeLoop.h ../Geo/GEdge.h ../Geo/SPoint2.h \
+  ../Geo/SVector3.h ../Geo/Pair.h ../Geo/GRegion.h ../Geo/GEntity.h \
+  ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h ../Mesh/BackgroundMesh.h
 GUI${OBJEXT}: GUI.cpp ../Common/GmshUI.h ../Common/GmshDefines.h \
   ../Common/GmshMessage.h ../Numeric/Numeric.h \
   ../Numeric/NumericEmbedded.h ../Common/Context.h ../Geo/CGNSOptions.h \
   ../Mesh/PartitionOptions.h ../Common/Options.h ../Post/ColorTable.h \
-  ../Graphics/Draw.h ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h GUI.h \
-  Opengl_Window.h Colorbar_Window.h Popup_Button.h \
-  SpherePosition_Widget.h ../Mesh/Field.h ../Post/PView.h Callbacks.h \
-  Win32Icon.h ../Common/OpenFile.h ../Common/CommandLine.h \
+  Draw.h GUI.h Opengl_Window.h ../Graphics/drawContext.h \
+  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h Colorbar_Window.h \
+  Popup_Button.h SpherePosition_Widget.h ../Mesh/Field.h ../Post/PView.h \
+  Callbacks.h Win32Icon.h ../Common/OpenFile.h ../Common/CommandLine.h \
   ../Mesh/Generator.h Solvers.h ../Plugin/PluginManager.h \
   ../Plugin/Plugin.h ../Post/PViewDataList.h ../Post/PViewData.h \
   ../Common/ListUtils.h ../Numeric/GmshMatrix.h Shortcut_Window.h \
@@ -89,13 +88,13 @@ GUI${OBJEXT}: GUI.cpp ../Common/GmshUI.h ../Common/GmshDefines.h \
   ../Geo/GPoint.h ../Geo/GEdgeLoop.h ../Geo/GEdge.h ../Geo/SPoint2.h \
   ../Geo/SVector3.h ../Geo/Pair.h ../Geo/GRegion.h ../Geo/GEntity.h \
   ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h ../Geo/GeoStringInterface.h \
-  ../Common/StringUtils.h ../Common/GmshSocket.h
+  ../Common/StringUtils.h
 GUI_Extras${OBJEXT}: GUI_Extras.cpp ../Common/GmshUI.h ../Common/GmshDefines.h \
   ../Common/CreateFile.h ../Common/Options.h ../Post/ColorTable.h \
   ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h \
-  ../Graphics/Draw.h ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h GUI.h \
-  Opengl_Window.h Colorbar_Window.h Popup_Button.h \
-  SpherePosition_Widget.h ../Mesh/Field.h ../Post/PView.h \
+  Draw.h GUI.h Opengl_Window.h ../Graphics/drawContext.h \
+  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h Colorbar_Window.h \
+  Popup_Button.h SpherePosition_Widget.h ../Mesh/Field.h ../Post/PView.h \
   Shortcut_Window.h ../Geo/GModel.h ../Geo/GVertex.h ../Geo/GEntity.h \
   ../Geo/Range.h ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h ../Geo/GPoint.h \
   ../Geo/SPoint2.h ../Geo/GEdge.h ../Geo/GEntity.h ../Geo/GVertex.h \
@@ -116,10 +115,10 @@ GUI_Projection${OBJEXT}: GUI_Projection.cpp ../Geo/GModelIO_Fourier.h \
   ../Geo/MVertex.h ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h \
   ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h \
   ../Geo/SVector3.h ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
-  ../Numeric/GmshMatrix.h ../Graphics/Draw.h ../Common/Options.h \
-  ../Post/ColorTable.h ../Common/Context.h ../Geo/CGNSOptions.h \
-  ../Mesh/PartitionOptions.h ../Common/StringUtils.h \
-  ../Graphics/SelectBuffer.h GUI_Projection.h ../Common/GmshUI.h \
+  ../Numeric/GmshMatrix.h Draw.h ../Common/Options.h ../Post/ColorTable.h \
+  ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h \
+  ../Common/StringUtils.h ../Graphics/SelectBuffer.h \
+  ../Graphics/drawContext.h GUI_Projection.h ../Common/GmshUI.h \
   ../Geo/fourierProjectionFace.h ../Geo/GModel.h ../Geo/Range.h GUI.h \
   Opengl_Window.h Colorbar_Window.h Popup_Button.h \
   SpherePosition_Widget.h ../Mesh/Field.h ../Post/PView.h \
@@ -139,12 +138,13 @@ GUI_Classifier${OBJEXT}: GUI_Classifier.cpp GUI_Classifier.h ../Common/GmshUI.h
   ../Geo/MVertex.h ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h \
   ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h \
   ../Geo/SVector3.h ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
-  ../Numeric/GmshMatrix.h GUI.h Opengl_Window.h Colorbar_Window.h \
-  ../Post/ColorTable.h Popup_Button.h SpherePosition_Widget.h \
-  ../Mesh/Field.h ../Post/PView.h Shortcut_Window.h ../Numeric/Numeric.h \
-  ../Numeric/NumericEmbedded.h ../Graphics/Draw.h ../Common/Options.h \
-  ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h \
-  ../Graphics/SelectBuffer.h GUI_Projection.h \
+  ../Numeric/GmshMatrix.h GUI.h Opengl_Window.h ../Graphics/drawContext.h \
+  Colorbar_Window.h ../Post/ColorTable.h Popup_Button.h \
+  SpherePosition_Widget.h ../Mesh/Field.h ../Post/PView.h \
+  Shortcut_Window.h ../Numeric/Numeric.h ../Numeric/NumericEmbedded.h \
+  Draw.h ../Common/Options.h ../Common/Context.h ../Geo/CGNSOptions.h \
+  ../Mesh/PartitionOptions.h ../Graphics/SelectBuffer.h \
+  ../Graphics/drawContext.h GUI_Projection.h \
   ../Geo/fourierProjectionFace.h ../Geo/GModel.h ../Geo/Range.h \
   GUI_Extras.h ../Mesh/meshGFaceDelaunayInsertion.h \
   ../Mesh/meshGFaceOptimize.h ../Mesh/meshGFaceDelaunayInsertion.h \
@@ -164,35 +164,31 @@ Callbacks${OBJEXT}: Callbacks.cpp ../Common/GmshUI.h ../Common/GmshMessage.h \
   ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h \
   ../Geo/SVector3.h ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h \
   ../Geo/GeoStringInterface.h ../Geo/findLinks.h ../Mesh/Generator.h \
-  ../Mesh/HighOrder.h ../Graphics/Draw.h ../Graphics/SelectBuffer.h \
-  ../Post/PView.h ../Post/PViewOptions.h ../Post/ColorTable.h \
-  ../Post/PViewData.h ../Common/CreateFile.h ../Common/OpenFile.h \
-  ../Common/CommandLine.h ../Common/Context.h ../Geo/CGNSOptions.h \
-  ../Mesh/PartitionOptions.h ../Common/Options.h GUI.h Opengl_Window.h \
-  Colorbar_Window.h Popup_Button.h SpherePosition_Widget.h \
-  ../Mesh/Field.h GUI_Extras.h Callbacks.h ../Plugin/Plugin.h \
-  ../Post/PViewDataList.h ../Post/PViewData.h ../Plugin/PluginManager.h \
-  ../Common/Visibility.h ../Common/GmshDefines.h ../Numeric/Numeric.h \
+  ../Mesh/HighOrder.h Draw.h ../Graphics/SelectBuffer.h \
+  ../Graphics/drawContext.h ../Post/PView.h ../Post/PViewOptions.h \
+  ../Post/ColorTable.h ../Post/PViewData.h ../Common/CreateFile.h \
+  ../Common/OpenFile.h ../Common/CommandLine.h ../Common/Context.h \
+  ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h ../Common/Options.h \
+  GUI.h Opengl_Window.h Colorbar_Window.h Popup_Button.h \
+  SpherePosition_Widget.h ../Mesh/Field.h GUI_Extras.h Callbacks.h \
+  ../Plugin/Plugin.h ../Post/PViewDataList.h ../Post/PViewData.h \
+  ../Plugin/PluginManager.h ../Common/Visibility.h \
+  ../Common/GmshDefines.h ../Numeric/Numeric.h \
   ../Numeric/NumericEmbedded.h Solvers.h ../Common/OS.h \
   ../Mesh/BackgroundMesh.h
-Opengl${OBJEXT}: Opengl.cpp ../Common/GmshUI.h ../Common/GmshDefines.h \
-  ../Numeric/Numeric.h ../Numeric/NumericEmbedded.h ../Common/Context.h \
-  ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h ../Graphics/Draw.h \
-  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Graphics/SelectBuffer.h \
-  ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.h ../Geo/GPoint.h ../Geo/SPoint2.h ../Geo/GEdge.h \
-  ../Geo/GEntity.h ../Geo/GVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h \
-  ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/GFace.h ../Geo/GEntity.h \
-  ../Geo/GPoint.h ../Geo/GEdgeLoop.h ../Geo/GEdge.h ../Geo/SPoint2.h \
-  ../Geo/SVector3.h ../Geo/Pair.h ../Geo/GRegion.h ../Geo/GEntity.h \
-  ../Common/StringUtils.h GUI.h Opengl_Window.h Colorbar_Window.h \
-  ../Post/ColorTable.h Popup_Button.h SpherePosition_Widget.h \
-  ../Mesh/Field.h ../Post/PView.h ../Graphics/gl2ps.h
+Draw${OBJEXT}: Draw.cpp GUI.h Opengl_Window.h ../Graphics/drawContext.h \
+  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h Colorbar_Window.h \
+  ../Common/GmshUI.h ../Post/ColorTable.h Popup_Button.h \
+  SpherePosition_Widget.h ../Mesh/Field.h ../Post/PView.h \
+  ../Common/GmshDefines.h Draw.h ../Common/StringUtils.h \
+  ../Graphics/gl2ps.h ../Common/Context.h ../Geo/CGNSOptions.h \
+  ../Mesh/PartitionOptions.h
 Opengl_Window${OBJEXT}: Opengl_Window.cpp ../Common/GmshUI.h \
-  ../Common/GmshDefines.h ../Common/GmshMessage.h ../Numeric/Numeric.h \
-  ../Numeric/NumericEmbedded.h ../Common/Context.h ../Geo/CGNSOptions.h \
-  ../Mesh/PartitionOptions.h ../Graphics/Draw.h ../Geo/SBoundingBox3d.h \
-  ../Geo/SPoint3.h ../Graphics/SelectBuffer.h ../Geo/GVertex.h \
+  ../Common/GmshDefines.h ../Common/GmshMessage.h Draw.h \
+  ../Numeric/Numeric.h ../Numeric/NumericEmbedded.h ../Common/Context.h \
+  ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h \
+  ../Graphics/SelectBuffer.h ../Graphics/drawContext.h \
+  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Geo/GVertex.h \
   ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
   ../Geo/SBoundingBox3d.h ../Geo/GPoint.h ../Geo/SPoint2.h ../Geo/GEdge.h \
   ../Geo/GEntity.h ../Geo/GVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h \
@@ -206,14 +202,14 @@ Opengl_Window${OBJEXT}: Opengl_Window.cpp ../Common/GmshUI.h \
   ../Geo/MVertex.h ../Geo/SVector3.h ../Numeric/FunctionSpace.h \
   ../Numeric/GmshMatrix.h
 Colorbar_Window${OBJEXT}: Colorbar_Window.cpp ../Common/GmshUI.h GUI.h \
-  Opengl_Window.h Colorbar_Window.h ../Post/ColorTable.h Popup_Button.h \
+  Opengl_Window.h ../Graphics/drawContext.h ../Geo/SBoundingBox3d.h \
+  ../Geo/SPoint3.h Colorbar_Window.h ../Post/ColorTable.h Popup_Button.h \
   SpherePosition_Widget.h ../Mesh/Field.h ../Post/PView.h \
-  ../Geo/SPoint3.h ../Common/Context.h ../Geo/CGNSOptions.h \
-  ../Mesh/PartitionOptions.h
+  ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h
 Solvers${OBJEXT}: Solvers.cpp ../Common/GmshMessage.h ../Common/StringUtils.h \
   Solvers.h ../Common/GmshSocket.h ../Common/OpenFile.h \
-  ../Common/GmshUI.h GUI.h Opengl_Window.h Colorbar_Window.h \
+  ../Common/GmshUI.h GUI.h Opengl_Window.h ../Graphics/drawContext.h \
+  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h Colorbar_Window.h \
   ../Post/ColorTable.h Popup_Button.h SpherePosition_Widget.h \
-  ../Mesh/Field.h ../Post/PView.h ../Geo/SPoint3.h ../Graphics/Draw.h \
-  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Common/Context.h \
+  ../Mesh/Field.h ../Post/PView.h Draw.h ../Common/Context.h \
   ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h ../Common/OS.h
diff --git a/Fltk/Opengl_Window.cpp b/Fltk/Opengl_Window.cpp
index bbd6e2ac5bc397168b570470c908cf9e6a3a426c..9f67f501358b271d89e5968cd5438217af1f196e 100644
--- a/Fltk/Opengl_Window.cpp
+++ b/Fltk/Opengl_Window.cpp
@@ -6,9 +6,9 @@
 #include "GmshUI.h"
 #include "GmshDefines.h"
 #include "GmshMessage.h"
+#include "Draw.h"
 #include "Numeric.h"
 #include "Context.h"
-#include "Draw.h"
 #include "SelectBuffer.h"
 #include "GUI.h"
 #include "Opengl_Window.h"
@@ -17,11 +17,11 @@
 extern GUI *WID;
 extern Context_T CTX;
 
-void MousePosition::set()
+void MousePosition::set(drawContext *ctx)
 {
   for(int i = 0; i < 3; i++){
-    s[i] = CTX.s[i];
-    t[i] = CTX.t[i];
+    s[i] = ctx->s[i];
+    t[i] = ctx->t[i];
   }
 
   win[0] = (double)Fl::event_x();
@@ -29,42 +29,55 @@ void MousePosition::set()
   win[2] = 0.;
 
   wnr[0] = 
-    (CTX.vxmin + win[0] / (double)CTX.viewport[2] * (CTX.vxmax - CTX.vxmin)) 
-    / CTX.s[0] - CTX.t[0] + CTX.t_init[0] / CTX.s[0];
+    (ctx->vxmin + win[0] / (double)ctx->viewport[2] * (ctx->vxmax - ctx->vxmin)) 
+    / ctx->s[0] - ctx->t[0] + ctx->t_init[0] / ctx->s[0];
   wnr[1] = 
-    (CTX.vymax - win[1] / (double)CTX.viewport[3] * (CTX.vymax - CTX.vymin))
-    / CTX.s[1] - CTX.t[1] + CTX.t_init[1] / CTX.s[1];
+    (ctx->vymax - win[1] / (double)ctx->viewport[3] * (ctx->vymax - ctx->vymin))
+    / ctx->s[1] - ctx->t[1] + ctx->t_init[1] / ctx->s[1];
   wnr[2] = 0.;
 }
 
-void MousePosition::recenter()
+void MousePosition::recenter(drawContext *ctx)
 {
   // compute the equivalent translation to apply *after* the scaling
   // so that the scaling is done around the point which was clicked:
-  CTX.t[0] = t[0] * (s[0] / CTX.s[0]) - wnr[0] * (1. - (s[0] / CTX.s[0]));
-  CTX.t[1] = t[1] * (s[1] / CTX.s[1]) - wnr[1] * (1. - (s[1] / CTX.s[1]));
+  ctx->t[0] = t[0] * (s[0] / ctx->s[0]) - wnr[0] * (1. - (s[0] / ctx->s[0]));
+  ctx->t[1] = t[1] * (s[1] / ctx->s[1]) - wnr[1] * (1. - (s[1] / ctx->s[1]));
 }
   
-void lasso_zoom(MousePosition &click1, MousePosition &click2)
+static void lassoZoom(drawContext *ctx, MousePosition &click1, MousePosition &click2)
 {
   if(click1.win[0] == click2.win[0] || click1.win[1] == click2.win[1])
     return;
 
-  CTX.s[0] *= (double)CTX.viewport[2] / (click2.win[0] - click1.win[0]);
-  CTX.s[1] *= (double)CTX.viewport[3] / (click2.win[1] - click1.win[1]);
-  CTX.s[2] = std::min(CTX.s[0], CTX.s[1]); // bof...
+  ctx->s[0] *= (double)ctx->viewport[2] / (click2.win[0] - click1.win[0]);
+  ctx->s[1] *= (double)ctx->viewport[3] / (click2.win[1] - click1.win[1]);
+  ctx->s[2] = std::min(ctx->s[0], ctx->s[1]); // bof...
   
   // recenter around the center of the lasso rectangle
   MousePosition tmp(click1);
   tmp.wnr[0] = 0.5 * (click1.wnr[0] + click2.wnr[0]);
   tmp.wnr[1] = 0.5 * (click1.wnr[1] + click2.wnr[1]);
-  tmp.recenter();
+  tmp.recenter(ctx);
 
-  InitPosition();
+  ctx->initPosition();
   Draw();
   WID->update_manip_window();
 }
 
+Opengl_Window::Opengl_Window(int x, int y, int w, int h, const char *l)
+  : Fl_Gl_Window(x, y, w, h, l)
+{
+  AddPointMode = LassoMode = SelectionMode = false;
+  _point[0] = _point[1] = _point[2] = 0.;
+  _ctx = new drawContext();
+}
+
+Opengl_Window::~Opengl_Window()
+{ 
+  delete _ctx; 
+}
+
 void Opengl_Window::draw()
 {
   static int locked = 0;
@@ -77,20 +90,20 @@ void Opengl_Window::draw()
 
   if(!valid()) {
     valid(1);
-    CTX.viewport[0] = 0;
-    CTX.viewport[1] = 0;
-    CTX.viewport[2] = w();
-    CTX.viewport[3] = h();
-    glViewport(CTX.viewport[0], CTX.viewport[1],
-               CTX.viewport[2], CTX.viewport[3]);
+    _ctx->viewport[0] = 0;
+    _ctx->viewport[1] = 0;
+    _ctx->viewport[2] = w();
+    _ctx->viewport[3] = h();
+    glViewport(_ctx->viewport[0], _ctx->viewport[1],
+               _ctx->viewport[2], _ctx->viewport[3]);
   }
   else {
-    if((w() != CTX.viewport[2] - CTX.viewport[0]) ||
-       (h() != CTX.viewport[3] - CTX.viewport[1])) {
-      WID->set_size(CTX.viewport[2] - CTX.viewport[0],
-                    CTX.viewport[3] - CTX.viewport[1]);
-      glViewport(CTX.viewport[0], CTX.viewport[1],
-                 CTX.viewport[2], CTX.viewport[3]);
+    if((w() != _ctx->viewport[2] - _ctx->viewport[0]) ||
+       (h() != _ctx->viewport[3] - _ctx->viewport[1])) {
+      WID->set_size(_ctx->viewport[2] - _ctx->viewport[0],
+                    _ctx->viewport[3] - _ctx->viewport[1]);
+      glViewport(_ctx->viewport[0], _ctx->viewport[1],
+                 _ctx->viewport[2], _ctx->viewport[3]);
     }
   }
 
@@ -99,8 +112,8 @@ void Opengl_Window::draw()
     // (without using overlays!)
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
-    glOrtho((double)CTX.viewport[0], (double)CTX.viewport[2],
-            (double)CTX.viewport[1], (double)CTX.viewport[3], -1., 1.);
+    glOrtho((double)_ctx->viewport[0], (double)_ctx->viewport[2],
+            (double)_ctx->viewport[1], (double)_ctx->viewport[3], -1., 1.);
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
     glColor3d(1., 1., 1.);
@@ -115,13 +128,13 @@ void Opengl_Window::draw()
     glLineWidth(0.2);
     for(int i = 0; i < 2; i++){
       glBegin(GL_LINE_STRIP);
-      glVertex2d(click.win[0], CTX.viewport[3] - click.win[1]);
-      glVertex2d(lasso.win[0], CTX.viewport[3] - click.win[1]);
-      glVertex2d(lasso.win[0], CTX.viewport[3] - lasso.win[1]);
-      glVertex2d(click.win[0], CTX.viewport[3] - lasso.win[1]);
-      glVertex2d(click.win[0], CTX.viewport[3] - click.win[1]);
+      glVertex2d(_click.win[0], _ctx->viewport[3] - _click.win[1]);
+      glVertex2d(_lasso.win[0], _ctx->viewport[3] - _click.win[1]);
+      glVertex2d(_lasso.win[0], _ctx->viewport[3] - _lasso.win[1]);
+      glVertex2d(_click.win[0], _ctx->viewport[3] - _lasso.win[1]);
+      glVertex2d(_click.win[0], _ctx->viewport[3] - _click.win[1]);
       glEnd();
-      if(!i) lasso.set();
+      if(!i) _lasso.set(_ctx);
     }
     glDisable(GL_BLEND);
     if(SelectionMode && CTX.mouse_selection)
@@ -135,21 +148,21 @@ void Opengl_Window::draw()
       CTX.post.draw = 0;
     }
     ClearOpengl();
-    Draw3d();
+    _ctx->draw3d();
     glColor4ubv((GLubyte *) & CTX.color.fg);
     glPointSize(CTX.geom.point_size);
     glBegin(GL_POINTS);
-    glVertex3d(point[0], point[1], point[2]);
+    glVertex3d(_point[0], _point[1], _point[2]);
     glEnd();
-    Draw2d();
+    _ctx->draw2d();
     CTX.mesh.draw = 1;
     CTX.post.draw = 1;
   }
   else{
     // draw the whole scene
     ClearOpengl();
-    Draw3d();
-    Draw2d();
+    _ctx->draw3d();
+    _ctx->draw2d();
   }
 
   locked = 0;
@@ -178,30 +191,30 @@ int Opengl_Window::handle(int event)
     
   case FL_PUSH:
     take_focus(); // force keyboard focus when we click in the window
-    curr.set();
+    _curr.set(_ctx);
     if(Fl::event_button() == 1 && 
        !Fl::event_state(FL_SHIFT) && !Fl::event_state(FL_ALT)) {
       if(!LassoMode && Fl::event_state(FL_CTRL)) {
         LassoMode = true;
-        lasso.set();
+        _lasso.set(_ctx);
       }
       else if(LassoMode) {
         LassoMode = false;
         if(SelectionMode && CTX.mouse_selection){
           WID->try_selection = 2; // will try to select multiple entities
-          WID->try_selection_xywh[0] = (int)(click.win[0] + curr.win[0])/2;
-          WID->try_selection_xywh[1] = (int)(click.win[1] + curr.win[1])/2;
-          WID->try_selection_xywh[2] = (int)fabs(click.win[0] - curr.win[0]);
-          WID->try_selection_xywh[3] = (int)fabs(click.win[1] - curr.win[1]);
+          WID->try_selection_xywh[0] = (int)(_click.win[0] + _curr.win[0])/2;
+          WID->try_selection_xywh[1] = (int)(_click.win[1] + _curr.win[1])/2;
+          WID->try_selection_xywh[2] = (int)fabs(_click.win[0] - _curr.win[0]);
+          WID->try_selection_xywh[3] = (int)fabs(_click.win[1] - _curr.win[1]);
         }
         else{
-          lasso_zoom(click, curr);
+          lassoZoom(_ctx, _click, _curr);
         }
       }
       else if(CTX.mouse_selection){
         WID->try_selection = 1; // will try to select clicked entity
-        WID->try_selection_xywh[0] = (int)curr.win[0];
-        WID->try_selection_xywh[1] = (int)curr.win[1];
+        WID->try_selection_xywh[0] = (int)_curr.win[0];
+        WID->try_selection_xywh[1] = (int)_curr.win[1];
         WID->try_selection_xywh[2] = 5;
         WID->try_selection_xywh[3] = 5;
       }
@@ -210,27 +223,27 @@ int Opengl_Window::handle(int event)
             (Fl::event_button() == 1 && Fl::event_state(FL_SHIFT))) {
       if(!LassoMode && Fl::event_state(FL_CTRL)) {
         // make zoom isotropic
-        CTX.s[1] = CTX.s[0];
-        CTX.s[2] = CTX.s[0];
+        _ctx->s[1] = _ctx->s[0];
+        _ctx->s[2] = _ctx->s[0];
         redraw();
       }
       else if(LassoMode) {
         LassoMode = false;
         if(SelectionMode && CTX.mouse_selection){
           WID->try_selection = -2; // will try to unselect multiple entities
-          WID->try_selection_xywh[0] = (int)(click.win[0] + curr.win[0])/2;
-          WID->try_selection_xywh[1] = (int)(click.win[1] + curr.win[1])/2;
-          WID->try_selection_xywh[2] = (int)fabs(click.win[0] - curr.win[0]);
-          WID->try_selection_xywh[3] = (int)fabs(click.win[1] - curr.win[1]);
+          WID->try_selection_xywh[0] = (int)(_click.win[0] + _curr.win[0])/2;
+          WID->try_selection_xywh[1] = (int)(_click.win[1] + _curr.win[1])/2;
+          WID->try_selection_xywh[2] = (int)fabs(_click.win[0] - _curr.win[0]);
+          WID->try_selection_xywh[3] = (int)fabs(_click.win[1] - _curr.win[1]);
         }
         else{
-          lasso_zoom(click, curr);
+          lassoZoom(_ctx, _click, _curr);
         }
       }
       else if(CTX.mouse_selection){
         WID->try_selection = -1; // will try to unselect clicked entity
-        WID->try_selection_xywh[0] = (int)curr.win[0];
-        WID->try_selection_xywh[1] = (int)curr.win[1];
+        WID->try_selection_xywh[0] = (int)_curr.win[0];
+        WID->try_selection_xywh[1] = (int)_curr.win[1];
         WID->try_selection_xywh[2] = 5;
         WID->try_selection_xywh[3] = 5;
       }
@@ -238,51 +251,51 @@ int Opengl_Window::handle(int event)
     else {
       if(Fl::event_state(FL_CTRL) && !LassoMode) {
         if(CTX.useTrackball)
-          CTX.setQuaternion(0., 0., 0., 1.);
+          _ctx->setQuaternion(0., 0., 0., 1.);
         else
-          CTX.r[0] = CTX.r[1] = CTX.r[2] = 0.;
-        CTX.t[0] = CTX.t[1] = CTX.t[2] = 0.;
-        CTX.s[0] = CTX.s[1] = CTX.s[2] = 1.;
+          _ctx->r[0] = _ctx->r[1] = _ctx->r[2] = 0.;
+        _ctx->t[0] = _ctx->t[1] = _ctx->t[2] = 0.;
+        _ctx->s[0] = _ctx->s[1] = _ctx->s[2] = 1.;
         redraw();
       }
       else {
         LassoMode = false;
       }
     }
-    click.set();
-    prev.set();
+    _click.set(_ctx);
+    _prev.set(_ctx);
     WID->update_manip_window();
     return 1;
 
   case FL_RELEASE:
-    curr.set();
+    _curr.set(_ctx);
     CTX.draw_rotation_center = 0;
     if(!LassoMode) {
       CTX.mesh.draw = 1;
       CTX.post.draw = 1;
       redraw();
     }
-    prev.set();
+    _prev.set(_ctx);
     return 1;
 
   case FL_MOUSEWHEEL:
     {
       double dy = Fl::event_dy();
       double fact = (5. * CTX.zoom_factor * fabs(dy) + h()) / (double)h();
-      CTX.s[0] *= ((dy > 0) ? fact : 1./fact);
-      CTX.s[1] = CTX.s[0];
-      CTX.s[2] = CTX.s[0];
-      prev.recenter();
+      _ctx->s[0] *= ((dy > 0) ? fact : 1./fact);
+      _ctx->s[1] = _ctx->s[0];
+      _ctx->s[2] = _ctx->s[0];
+      _prev.recenter(_ctx);
       redraw();
     }
     WID->update_manip_window();
     return 1;
 
   case FL_DRAG:
-    curr.set();
+    _curr.set(_ctx);
     {
-      double dx = curr.win[0] - prev.win[0];
-      double dy = curr.win[1] - prev.win[1];
+      double dx = _curr.win[0] - _prev.win[0];
+      double dy = _curr.win[1] - _prev.win[1];
       if(LassoMode) {
         redraw();
       }
@@ -290,39 +303,39 @@ int Opengl_Window::handle(int event)
         if(Fl::event_state(FL_META)) {
           // will try to select or unselect entities on the fly
           WID->try_selection = Fl::event_state(FL_SHIFT) ? -1 : 1; 
-          WID->try_selection_xywh[0] = (int)curr.win[0];
-          WID->try_selection_xywh[1] = (int)curr.win[1];
+          WID->try_selection_xywh[0] = (int)_curr.win[0];
+          WID->try_selection_xywh[1] = (int)_curr.win[1];
           WID->try_selection_xywh[2] = 5;
           WID->try_selection_xywh[3] = 5;
         }
         else if(Fl::event_button() == 1 && 
                 !Fl::event_state(FL_SHIFT) && !Fl::event_state(FL_ALT)) {
           if(CTX.useTrackball)
-            CTX.addQuaternion((2. * prev.win[0] - w()) / w(),
-                              (h() - 2. * prev.win[1]) / h(),
-                              (2. * curr.win[0] - w()) / w(),
-                              (h() - 2. * curr.win[1]) / h());
+            _ctx->addQuaternion((2. * _prev.win[0] - w()) / w(),
+                              (h() - 2. * _prev.win[1]) / h(),
+                              (2. * _curr.win[0] - w()) / w(),
+                              (h() - 2. * _curr.win[1]) / h());
           else {
-            CTX.r[1] += ((fabs(dx) > fabs(dy)) ? 180. * dx / (double)w() : 0.);
-            CTX.r[0] += ((fabs(dx) > fabs(dy)) ? 0. : 180. * dy / (double)h());
+            _ctx->r[1] += ((fabs(dx) > fabs(dy)) ? 180. * dx / (double)w() : 0.);
+            _ctx->r[0] += ((fabs(dx) > fabs(dy)) ? 0. : 180. * dy / (double)h());
           }
         }
         else if(Fl::event_button() == 2 ||
                 (Fl::event_button() == 1 && Fl::event_state(FL_SHIFT))) {
           if(fabs(dy) > fabs(dx)) {
             double fact = (CTX.zoom_factor * fabs(dy) + h()) / (double)h();
-            CTX.s[0] *= ((dy > 0) ? fact : 1./fact);
-            CTX.s[1] = CTX.s[0];
-            CTX.s[2] = CTX.s[0];
-            click.recenter();
+            _ctx->s[0] *= ((dy > 0) ? fact : 1./fact);
+            _ctx->s[1] = _ctx->s[0];
+            _ctx->s[2] = _ctx->s[0];
+            _click.recenter(_ctx);
           }
           else if(!CTX.useTrackball)
-            CTX.r[2] += -180. * dx / (double)w();
+            _ctx->r[2] += -180. * dx / (double)w();
         }
         else {
-          CTX.t[0] += (curr.wnr[0] - click.wnr[0]);
-          CTX.t[1] += (curr.wnr[1] - click.wnr[1]);
-          CTX.t[2] = 0.;
+          _ctx->t[0] += (_curr.wnr[0] - _click.wnr[0]);
+          _ctx->t[1] += (_curr.wnr[1] - _click.wnr[1]);
+          _ctx->t[2] = 0.;
         }
         CTX.draw_rotation_center = 1;
         if(CTX.fast_redraw) {
@@ -332,12 +345,12 @@ int Opengl_Window::handle(int event)
         redraw();
       }
     }
-    prev.set();
+    _prev.set(_ctx);
     WID->update_manip_window();
     return 1;
 
   case FL_MOVE:
-    curr.set();
+    _curr.set(_ctx);
     if(LassoMode) {
       redraw();
     }
@@ -345,37 +358,37 @@ int Opengl_Window::handle(int event)
       WID->g_opengl_window->cursor(FL_CURSOR_CROSS, FL_BLACK, FL_WHITE);
       // find line in real space corresponding to current cursor position
       double p[3],d[3];
-      Unproject(curr.win[0], curr.win[1], p, d);
+      _ctx->unproject(_curr.win[0], _curr.win[1], p, d);
       // fin closest point to the center of gravity
       double r[3] = {CTX.cg[0] - p[0], CTX.cg[1] - p[1], CTX.cg[2] - p[2]}, t;
       prosca(r, d, &t);
       for(int i = 0; i < 3; i++){
-        point[i] = p[i] + t * d[i];
+        _point[i] = p[i] + t * d[i];
         if(CTX.geom.snap[i]){
-          double d = point[i]/CTX.geom.snap[i];
+          double d = _point[i] / CTX.geom.snap[i];
           double f = floor(d);
           double c = ceil(d);
           double n = (d - f < c - d) ? f : c;
-          point[i] = n * CTX.geom.snap[i];
+          _point[i] = n * CTX.geom.snap[i];
         }
       }
       char str[32];
-      sprintf(str, "%g", point[0]); WID->context_geometry_input[2]->value(str);
-      sprintf(str, "%g", point[1]); WID->context_geometry_input[3]->value(str);
-      sprintf(str, "%g", point[2]); WID->context_geometry_input[4]->value(str);
+      sprintf(str, "%g", _point[0]); WID->context_geometry_input[2]->value(str);
+      sprintf(str, "%g", _point[1]); WID->context_geometry_input[3]->value(str);
+      sprintf(str, "%g", _point[2]); WID->context_geometry_input[4]->value(str);
       redraw();
     }
     else{ // hover mode
-      if(curr.win[0] != prev.win[0] || curr.win[1] != prev.win[1]){
+      if(_curr.win[0] != _prev.win[0] || _curr.win[1] != _prev.win[1]){
         WID->make_opengl_current();
         std::vector<GVertex*> vertices;
         std::vector<GEdge*> edges;
         std::vector<GFace*> faces;
         std::vector<GRegion*> regions;
         std::vector<MElement*> elements;
-        bool res = ProcessSelectionBuffer(WID->selection, false, 
+        bool res = ProcessSelectionBuffer(_ctx, WID->selection, false, 
                                           CTX.mouse_hover_meshes, 
-                                          (int)curr.win[0], (int)curr.win[1], 5, 5, 
+                                          (int)_curr.win[0], (int)_curr.win[1], 5, 5, 
                                           vertices, edges, faces, regions,
                                           elements);
         if((WID->selection == ENT_ALL && res) ||
@@ -397,10 +410,87 @@ int Opengl_Window::handle(int event)
 		    me ? me->getInfoString().c_str() : "");
       }
     }
-    prev.set();
+    _prev.set(_ctx);
     return 1;
 
   default:
     return Fl_Gl_Window::handle(event);
   }
 }
+
+
+// Select entity routine
+
+char SelectEntity(int type, 
+                  std::vector<GVertex*> &vertices,
+                  std::vector<GEdge*> &edges,
+                  std::vector<GFace*> &faces,
+                  std::vector<GRegion*> &regions,
+                  std::vector<MElement*> &elements)
+{
+  if(!WID) return 'q';
+
+  WID->g_opengl_window->take_focus(); // force keyboard focus in GL window 
+  WID->g_opengl_window->SelectionMode = true; // enable lasso selection
+
+  WID->selection = type;
+  WID->try_selection = 0;
+  WID->quit_selection = 0;
+  WID->end_selection = 0;
+  WID->undo_selection = 0;
+  WID->invert_selection = 0;
+
+  while(1) {
+    vertices.clear();
+    edges.clear();
+    faces.clear();
+    regions.clear();
+    elements.clear();
+    WID->wait();
+    if(WID->quit_selection) {
+      WID->selection = ENT_NONE;
+      WID->g_opengl_window->SelectionMode = false;
+      WID->g_opengl_window->LassoMode = false;
+      WID->g_opengl_window->AddPointMode = false;
+      WID->g_opengl_window->cursor(FL_CURSOR_DEFAULT, FL_BLACK, FL_WHITE);
+      return 'q';
+    }
+    if(WID->end_selection) {
+      WID->end_selection = 0;
+      WID->selection = ENT_NONE;
+      return 'e';
+    }
+    if(WID->undo_selection) {
+      WID->undo_selection = 0;
+      return 'u';
+    }
+    if(WID->invert_selection) {
+      WID->invert_selection = 0;
+      return 'i';
+    }
+    if(WID->try_selection) {
+      bool add = (WID->try_selection > 0) ? true : false;
+      bool multi = (abs(WID->try_selection) > 1) ? true : false;
+      WID->try_selection = 0;
+      if(WID->selection == ENT_NONE){ // just report the mouse click
+        WID->g_opengl_window->SelectionMode = false;
+        return 'c';
+      }
+      else if(ProcessSelectionBuffer(WID->g_opengl_window->getDrawContext(),
+                                     WID->selection, multi, true,
+                                     WID->try_selection_xywh[0],
+                                     WID->try_selection_xywh[1], 
+                                     WID->try_selection_xywh[2],
+                                     WID->try_selection_xywh[3], 
+                                     vertices, edges, faces, regions,
+                                     elements)){
+        WID->selection = ENT_NONE;
+        WID->g_opengl_window->SelectionMode = false;
+        if(add)
+          return 'l';
+        else
+          return 'r';
+      }
+    }
+  }
+}
diff --git a/Fltk/Opengl_Window.h b/Fltk/Opengl_Window.h
index c6b49987d4f8c18a5b7e433e8e694402b656b952..1dca77460bb4632b45b52a8e528e4e05f12e2118 100644
--- a/Fltk/Opengl_Window.h
+++ b/Fltk/Opengl_Window.h
@@ -8,18 +8,21 @@
 
 #include <FL/Fl_Gl_Window.H>
 #include <FL/Fl_Box.H>
+#include "drawContext.h"
 
 class MousePosition {
  public:
   double win[3]; // window coordinates
   double wnr[3]; // world coordinates BEFORE rotation
   double s[3]; // scaling state when the event was recorded
-  double t[3];  // translation state when the event was recorded
-  MousePosition(){
+  double t[3]; // translation state when the event was recorded
+  MousePosition()
+  {
     for(int i = 0; i < 3; i++)
       win[i] = wnr[i] = s[i] = t[i] = 0.;
   }
-  MousePosition(const MousePosition &instance){
+  MousePosition(const MousePosition &instance)
+  {
     for(int i = 0; i < 3; i++){
       win[i] = instance.win[i];
       wnr[i] = instance.wnr[i];
@@ -27,38 +30,33 @@ class MousePosition {
       t[i] = instance.t[i];
     }
   }
-  void set();
-  void recenter();
+  void set(drawContext *ctx);
+  void recenter(drawContext *ctx);
 };
 
 class Opengl_Window : public Fl_Gl_Window {
- public:
-  bool AddPointMode, LassoMode, SelectionMode;
  private:
-  MousePosition click, curr, prev, lasso;
-  double point[3];
+  MousePosition _click, _curr, _prev, _lasso;
+  double _point[3];
+  drawContext *_ctx;
   void draw();
   int handle(int);
  public:
-  Opengl_Window(int x,int y,int w,int h,const char *l=0)
-    : Fl_Gl_Window(x, y, w, h, l) {
-    AddPointMode = LassoMode = SelectionMode = false;
-    point[0] = point[1] = point[2] = 0.;
-  }
+  bool AddPointMode, LassoMode, SelectionMode;
+  Opengl_Window(int x, int y, int w, int h, const char *l=0);
+  ~Opengl_Window();
+  drawContext *getDrawContext(){ return _ctx; }
 };
 
 // This dummy box class permits to define a box widget that will not
 // eat the FL_ENTER/FL_LEAVE events (the new Box widget in fltk >1.1
 // does that, so that our Opengl_Window->handle() was not called each
-// time the mouse moved...)
-//
-// There is probably a better solution...
-
+// time the mouse moved)
 class Dummy_Box : public Fl_Box {
-  int handle(int){ return 0; }; // always!
-public:
-  Dummy_Box(int x,int y,int w,int h,const char *l=0)
-    : Fl_Box(x, y, w, h, l) {}
+ private:
+  int handle(int){ return 0; } // always!
+ public:
+  Dummy_Box(int x,int y,int w,int h,const char *l=0) : Fl_Box(x, y, w, h, l) {}
 };
 
 #endif
diff --git a/Geo/GFaceCompound.cpp b/Geo/GFaceCompound.cpp
index 0b1649a93e6c7c1bd19a77bd582a6ca71cc000f0..a4acb2df9200be146c6fabdd83fcdead059d3e4a 100644
--- a/Geo/GFaceCompound.cpp
+++ b/Geo/GFaceCompound.cpp
@@ -137,7 +137,7 @@ static bool orderVertices (const std::list<GEdge*> &e ,
   double tot_length = 0;
   for ( ; it != e.end() ; ++it ){
     //    printf("GLine %d\n",(*it)->tag());
-    for ( int i = 0 ; i < (*it)->lines.size(); i++ ){	
+    for (unsigned int i = 0 ; i < (*it)->lines.size(); i++ ){	
       temp.push_back((*it)->lines[i]);  
       MVertex *v0 = (*it)->lines[i]->getVertex(0);
       MVertex *v1 = (*it)->lines[i]->getVertex(1);    
@@ -217,16 +217,16 @@ void GFaceCompound::parametrize (bool _isU, int ITER) const
     // maps the boundary onto a circle
     std::vector<MVertex*> ordered;
     std::vector<double> coords;  
-    //    Msg::Info("%d edges on the contour", l_edges.size()); 
-    //    for (std::list<GEdge*>::const_iterator it = l_edges.begin();
+    // Msg::Info("%d edges on the contour", l_edges.size()); 
+    // for (std::list<GEdge*>::const_iterator it = l_edges.begin();
     //	 it !=l_edges.end();++it)printf("%d ",(*it)->tag());
-    //    printf("\n");
+    // printf("\n");
     bool success = orderVertices (l_edges, ordered, coords);
     if (!success)throw;
-    for (int i=0; i<ordered.size();i++){
+    for (unsigned int i = 0; i < ordered.size(); i++){
       MVertex *v = ordered[i];
-      const double theta = 2*M_PI*coords[i];
-      //      printf("fixing %d to %g\n",v->getIndex(),theta);
+      const double theta = 2 * M_PI * coords[i];
+      // printf("fixing %d to %g\n",v->getIndex(),theta);
       if (_isU) myAssembler.fixVertex(v, 0, 1, cos(theta));
       else myAssembler.fixVertex(v, 0, 1, sin(theta));
     }
@@ -311,14 +311,14 @@ void GFaceCompound::computeNormals () const
   for ( ; it != _compound.end() ; ++it){
     for (unsigned int i = 0; i < (*it)->triangles.size(); ++i){
       MTriangle *t = (*it)->triangles[i];
-      double det = t->getJacobian(0,0,0,J);
+      t->getJacobian(0, 0, 0, J);
       //      SVector3 n (J[2][0],J[2][1],J[2][2]);
       SVector3 d1(J[0][0], J[0][1], J[0][2]);
       SVector3 d2(J[1][0], J[1][1], J[1][2]);
       SVector3 n = crossprod(d1, d2);
       n.normalize();
-      for (int j=0;j<3;j++){
-	std::map<MVertex*,SVector3>::iterator itn = _normals.find(t->getVertex(j));
+      for (int j = 0; j < 3; j++){
+	std::map<MVertex*, SVector3>::iterator itn = _normals.find(t->getVertex(j));
 	if (itn == _normals.end())_normals[t->getVertex(j)] = n;
 	else itn->second += n;
       }
diff --git a/Graphics/Axes.cpp b/Graphics/Axes.cpp
deleted file mode 100644
index ee93f164f768e47d15bcb1a6f27c47826bc99288..0000000000000000000000000000000000000000
--- a/Graphics/Axes.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-// Gmsh - Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
-//
-// See the LICENSE.txt file for license information. Please report all
-// bugs and problems to <gmsh@geuz.org>.
-
-#include "GmshUI.h"
-#include "Draw.h"
-#include "Context.h"
-#include "gl2ps.h"
-#include "GModel.h"
-
-extern Context_T CTX;
-
-void Draw_Axes()
-{
-  bool geometryExists = false;
-  for(unsigned int i = 0; i < GModel::list.size(); i++){
-    if(!GModel::list[i]->empty()){
-      geometryExists = true;
-      break;
-    }
-  }
-    
-  if(geometryExists && (CTX.draw_bbox || !CTX.mesh.draw)) {
-    glColor4ubv((GLubyte *) & CTX.color.fg);
-    glLineWidth(CTX.line_width);
-    gl2psLineWidth(CTX.line_width * CTX.print.eps_line_width_factor);
-    Draw_Box(CTX.min[0], CTX.min[1], CTX.min[2], 
-             CTX.max[0], CTX.max[1], CTX.max[2]);
-    glColor3d(1.,0.,0.);
-    for(int j = 0; j < 6; j++)
-      if(CTX.geom.clip & (1 << j) || CTX.mesh.clip & (1 << j))
-        Draw_PlaneInBoundingBox(CTX.min[0], CTX.min[1], CTX.min[2],
-                                CTX.max[0], CTX.max[1], CTX.max[2],
-                                CTX.clip_plane[j][0], CTX.clip_plane[j][1], 
-                                CTX.clip_plane[j][2], CTX.clip_plane[j][3]);
-  }
-
-  if(CTX.axes){
-    glColor4ubv((GLubyte *) & CTX.color.axes);
-    glLineWidth(CTX.line_width);
-    gl2psLineWidth(CTX.line_width * CTX.print.eps_line_width_factor);
-    if(!CTX.axes_auto_position){
-      Draw_Axes(CTX.axes, CTX.axes_tics, CTX.axes_format, CTX.axes_label, 
-                CTX.axes_position, CTX.axes_mikado);
-    }
-    else if(geometryExists){
-      double bb[6] = {CTX.min[0], CTX.max[0], CTX.min[1], 
-                      CTX.max[1], CTX.min[2], CTX.max[2]};
-      Draw_Axes(CTX.axes, CTX.axes_tics, CTX.axes_format, CTX.axes_label, 
-                bb, CTX.axes_mikado);
-    }
-  }
-
-  if(CTX.draw_rotation_center){
-    glColor4ubv((GLubyte *) & CTX.color.fg);
-    if(CTX.rotation_center_cg)
-      Draw_Sphere(CTX.point_size, CTX.cg[0], CTX.cg[1], CTX.cg[2], CTX.geom.light);
-    else
-      Draw_Sphere(CTX.point_size, CTX.rotation_center[0], CTX.rotation_center[1], 
-                  CTX.rotation_center[2], CTX.geom.light);
-  }
-
-}
diff --git a/Graphics/Draw.h b/Graphics/Draw.h
deleted file mode 100644
index 012f67e5bc21d9059295488ceead5a51f798e7e9..0000000000000000000000000000000000000000
--- a/Graphics/Draw.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Gmsh - Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
-//
-// See the LICENSE.txt file for license information. Please report all
-// bugs and problems to <gmsh@geuz.org>.
-
-#ifndef _DRAW_H_
-#define _DRAW_H_
-
-#include <string>
-#include "SBoundingBox3d.h"
-
-#define GMSH_RENDER    1
-#define GMSH_SELECT    2
-#define GMSH_FEEDBACK  3
-
-void SetOpenglContext();
-void ClearOpengl();
-
-void InitProjection(int xpick=0, int ypick=0, int wpick=0, int hpick=0);
-void InitPosition();
-void InitRenderModel();
-
-void Unproject(double x, double y, double p[3], double d[3]);
-void Viewport2World(double win[3], double xyz[3]);
-void World2Viewport(double xyz[3], double win[3]);
-
-int Fix2DCoordinates(double *x, double *y);
-
-void Draw3d();
-void Draw2d();
-void DrawPlugin(void (*draw)());
-void Draw();
-
-void Draw_String(std::string);
-void Draw_String(std::string, double style);
-void Draw_String_Center(std::string);
-void Draw_String_Right(std::string);
-void Draw_Axes();
-void Draw_Geom();
-void Draw_Mesh();
-void Draw_Post();
-void Draw_Graph2D();
-void Draw_Text2D();
-void Draw_OnScreenMessages();
-void Draw_Scales();
-
-void Draw_Sphere(double size, double x, double y, double z, int light);
-void Draw_Cylinder(double width, double *x, double *y, double *z, int light);
-void Draw_TapCylinder(double width, double val1, double val2, double ValMin, 
-                      double ValMax, double *x, double *y, double *z, int light);
-void Draw_Vector(int Type, int Fill,
-                 double relHeadRadius, double relStemLength, double relStemRadius,
-                 double x, double y, double z, double dx, double dy, double dz,
-                 int light);
-void Draw_Box(double xmin, double ymin, double zmin,
-              double xmax, double ymax, double zmax, bool labels=true);
-void Draw_PlaneInBoundingBox(double xmin, double ymin, double zmin,
-                             double xmax, double ymax, double zmax,
-                             double a, double b, double c, double d, int shade=0);
-void Draw_SmallAxes();
-void Draw_Axes(int mode, int tics[3], char format[3][256], char label[3][256],
-               double bbox[6],int mikado);
-void Draw_Axes(int mode, int tics[3], char format[3][256], char label[3][256],
-               SBoundingBox3d &bbox,int mikado);
-
-#endif
-
diff --git a/Graphics/Entity.cpp b/Graphics/Entity.cpp
deleted file mode 100644
index 8b5c2c0e35defea5f65db1634e244455ad165f55..0000000000000000000000000000000000000000
--- a/Graphics/Entity.cpp
+++ /dev/null
@@ -1,856 +0,0 @@
-// Gmsh - Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
-//
-// See the LICENSE.txt file for license information. Please report all
-// bugs and problems to <gmsh@geuz.org>.
-
-#include <string.h>
-#include "GmshUI.h"
-#include "Numeric.h"
-#include "Draw.h"
-#include "Context.h"
-#include "gl2ps.h"
-
-extern Context_T CTX;
-
-void Draw_Point(int type, double size, double *x, double *y, double *z,
-                int light)
-{
-  if(type)
-    Draw_Sphere(size, x[0], y[0], z[0], light);
-  else {
-    glBegin(GL_POINTS);
-    glVertex3d(x[0], y[0], z[0]);
-    glEnd();
-  }
-}
-
-void Draw_Sphere(double size, double x, double y, double z, int light)
-{
-  if(light) glEnable(GL_LIGHTING);
-
-  static int first = 1;
-  static GLUquadricObj *qua;
-
-  if(first){
-    first = 0;
-    qua = gluNewQuadric();
-  }
-
-  glPushMatrix();
-  glTranslated(x, y, z);
-  double s = size * CTX.pixel_equiv_x / CTX.s[0]; // size is in pixels
-  glScaled(s, s, s);
-  gluSphere(qua, 1, CTX.quadric_subdivisions, CTX.quadric_subdivisions);
-  glPopMatrix();
-  glDisable(GL_LIGHTING);
-}
-
-
-void Draw_TapCylinder(double width, double val1, double val2, 
-                      double ValMin, double ValMax, 
-                      double *x, double *y, double *z, int light)
-{
-  if(light) glEnable(GL_LIGHTING);
-
-  static int first = 1;
-  static GLUquadricObj *qua;
-
-  if(first){
-    first = 0;
-    qua = gluNewQuadric();
-  }
-
-  double dx = x[1] - x[0];
-  double dy = y[1] - y[0];
-  double dz = z[1] - z[0];
-  double length = sqrt(dx*dx + dy*dy + dz*dz);
-  double radius1 = width * (val1-ValMin)/(ValMax-ValMin) * CTX.pixel_equiv_x /CTX.s[0];
-  double radius2 = width * (val2-ValMin)/(ValMax-ValMin) * CTX.pixel_equiv_x /CTX.s[0];
-  double zdir[3] = {0., 0., 1.};
-  double vdir[3] = {dx/length, dy/length, dz/length};
-  double axis[3], cosphi, phi;
-  prodve(zdir, vdir, axis);
-  prosca(zdir, vdir, &cosphi);
-  if(!norme(axis)){
-    axis[0] = 0.;
-    axis[1] = 1.;
-    axis[2] = 0.;
-  }
-  phi = 180. * myacos(cosphi) / M_PI;
-
-  glPushMatrix();
-  glTranslated(x[0], y[0], z[0]);
-  glRotated(phi, axis[0], axis[1], axis[2]);
-  gluCylinder(qua, radius1, radius2, length, CTX.quadric_subdivisions, 1);
-  glPopMatrix();
-
-  glDisable(GL_LIGHTING);
-}
-
-void Draw_Cylinder(double width, double *x, double *y, double *z, int light)
-{
-  if(light) glEnable(GL_LIGHTING);
-
-  static int first = 1;
-  static GLUquadricObj *qua;
-
-  if(first){
-    first = 0;
-    qua = gluNewQuadric();
-  }
-
-  double dx = x[1] - x[0];
-  double dy = y[1] - y[0];
-  double dz = z[1] - z[0];
-  double length = sqrt(dx*dx + dy*dy + dz*dz);
-  double radius = width * CTX.pixel_equiv_x / CTX.s[0];
-  double zdir[3] = {0., 0., 1.};
-  double vdir[3] = {dx/length, dy/length, dz/length};
-  double axis[3], cosphi, phi;
-  prodve(zdir, vdir, axis);
-  prosca(zdir, vdir, &cosphi);
-  if(!norme(axis)){
-    axis[0] = 0.;
-    axis[1] = 1.;
-    axis[2] = 0.;
-  }
-  phi = 180. * myacos(cosphi) / M_PI;
-
-  glPushMatrix();
-  glTranslated(x[0], y[0], z[0]);
-  glRotated(phi, axis[0], axis[1], axis[2]);
-  gluCylinder(qua, radius, radius, length, CTX.quadric_subdivisions, 1);
-  glPopMatrix();
-
-  glDisable(GL_LIGHTING);
-}
-
-void Draw_Line(int type, double width, double *x, double *y, double *z,
-               int light)
-{
-  if(type==1)
-    Draw_Cylinder(width, x, y, z, light);
-  else {
-    glBegin(GL_LINES);
-    glVertex3d(x[0], y[0], z[0]);
-    glVertex3d(x[1], y[1], z[1]);
-    glEnd();
-  }
-}
-
-void Draw_SimpleVector(int arrow, int fill,
-                       double relHeadRadius, double relStemLength, double relStemRadius,
-                       double x, double y, double z,
-                       double dx, double dy, double dz, 
-                       double d, int light)
-{
-  double n[3], t[3], u[3];
-
-  n[0] = dx / d;
-  n[1] = dy / d;
-  n[2] = dz / d;
-
-  if((fabs(n[0]) >= fabs(n[1]) && fabs(n[0]) >= fabs(n[2])) ||
-     (fabs(n[1]) >= fabs(n[0]) && fabs(n[1]) >= fabs(n[2]))) {
-    t[0] = n[1];
-    t[1] = -n[0];
-    t[2] = 0.;
-  }
-  else {
-    t[0] = 0.;
-    t[1] = n[2];
-    t[2] = -n[1];
-  }
-
-  double l = sqrt(t[0] * t[0] + t[1] * t[1] + t[2] * t[2]);
-  t[0] /= l;
-  t[1] /= l;
-  t[2] /= l;
-
-  u[0] = n[1] * t[2] - n[2] * t[1];
-  u[1] = n[2] * t[0] - n[0] * t[2];
-  u[2] = n[0] * t[1] - n[1] * t[0];
-
-  l = sqrt(u[0] * u[0] + u[1] * u[1] + u[2] * u[2]);
-  u[0] /= l;
-  u[1] /= l;
-  u[2] /= l;
-
-  double b = relHeadRadius * d;
-
-  if(arrow){
-    double f1 = relStemLength;
-    double f2 = (1-2.*relStemRadius) * f1; // hack :-)
-
-    if(fill) {
-      glBegin(GL_LINES);
-      glVertex3d(x, y, z);
-      glVertex3d(x + f1 * dx, y + f1 * dy, z + f1 * dz);
-      glEnd();
-      
-      if(light && fill) glEnable(GL_LIGHTING);
-      glBegin(GL_TRIANGLES);
-      if(light) glNormal3dv(u);
-      glVertex3d(x + dx, y + dy, z + dz);
-      glVertex3d(x + f2 * dx + b * (t[0]), y + f2 * dy + b * (t[1]),
-                 z + f2 * dz + b * (t[2]));
-      glVertex3d(x + f1 * dx, y + f1 * dy, z + f1 * dz);
-      
-      glVertex3d(x + f1 * dx, y + f1 * dy, z + f1 * dz);
-      glVertex3d(x + f2 * dx + b * (-t[0]), y + f2 * dy + b * (-t[1]),
-                 z + f2 * dz + b * (-t[2]));
-      glVertex3d(x + dx, y + dy, z + dz);
-      
-      if(light) glNormal3dv(t);
-      glVertex3d(x + dx, y + dy, z + dz);
-      glVertex3d(x + f2 * dx + b * (-u[0]), y + f2 * dy + b * (-u[1]),
-                 z + f2 * dz + b * (-u[2]));
-      glVertex3d(x + f1 * dx, y + f1 * dy, z + f1 * dz);
-
-      glVertex3d(x + f1 * dx, y + f1 * dy, z + f1 * dz);      
-      glVertex3d(x + f2 * dx + b * (u[0]), y + f2 * dy + b * (u[1]),
-                 z + f2 * dz + b * (u[2]));
-      glVertex3d(x + dx, y + dy, z + dz);
-      glEnd();
-      glDisable(GL_LIGHTING);
-    }
-    else {
-      glBegin(GL_LINE_STRIP);
-      glVertex3d(x, y, z);
-      glVertex3d(x + dx, y + dy, z + dz);
-      glVertex3d(x + f2 * dx + b * (t[0]), y + f2 * dy + b * (t[1]),
-                 z + f2 * dz + b * (t[2]));
-      glVertex3d(x + f1 * dx, y + f1 * dy, z + f1 * dz);
-      glVertex3d(x + f2 * dx + b * (-t[0]), y + f2 * dy + b * (-t[1]),
-                 z + f2 * dz + b * (-t[2]));
-      glVertex3d(x + dx, y + dy, z + dz);
-      glVertex3d(x + f2 * dx + b * (-u[0]), y + f2 * dy + b * (-u[1]),
-                 z + f2 * dz + b * (-u[2]));
-      glVertex3d(x + f1 * dx, y + f1 * dy, z + f1 * dz);
-      glVertex3d(x + f2 * dx + b * (u[0]), y + f2 * dy + b * (u[1]),
-                 z + f2 * dz + b * (u[2]));
-      glVertex3d(x + dx, y + dy, z + dz);
-      glEnd();
-    }
-  }
-  else{ // simple pyramid
-    if(fill){
-      double top[3] = { x+dx,      y+dy,      z+dz };
-      double tp[3]  = { x+b*t[0],  y+b*t[1],  z+b*t[2] };
-      double tm[3]  = { x-b*t[0],  y-b*t[1],  z-b*t[2] };
-      double up[3]  = { x+b*u[0],  y+b*u[1],  z+b*u[2] };
-      double um[3]  = { x-b*u[0],  y-b*u[1],  z-b*u[2] };
-      double nn[3];
-
-      if(light && fill) glEnable(GL_LIGHTING);
-      glBegin(GL_TRIANGLES);
-      if(light){
-        normal3points(tm[0], tm[1], tm[2], um[0], um[1], um[2],
-                      top[0], top[1], top[2], nn);
-        glNormal3dv(nn);
-      }
-      glVertex3d(tm[0], tm[1], tm[2]);
-      glVertex3d(um[0], um[1], um[2]);
-      glVertex3d(top[0], top[1], top[2]);
-
-      if(light){
-        normal3points(um[0], um[1], um[2], tp[0], tp[1], tp[2],
-                      top[0], top[1], top[2], nn);
-        glNormal3dv(nn);
-      }
-      glVertex3d(um[0], um[1], um[2]);
-      glVertex3d(tp[0], tp[1], tp[2]);
-      glVertex3d(top[0], top[1], top[2]);
-
-      if(light){
-        normal3points(tp[0], tp[1], tp[2], up[0], up[1], up[2],
-                      top[0], top[1], top[2], nn);
-        glNormal3dv(nn);
-      }
-      glVertex3d(tp[0], tp[1], tp[2]);
-      glVertex3d(up[0], up[1], up[2]);
-      glVertex3d(top[0], top[1], top[2]);
-
-      if(light){
-        normal3points(up[0], up[1], up[2], tm[0], tm[1], tm[2],
-                      top[0], top[1], top[2], nn);
-        glNormal3dv(nn);
-      }
-      glVertex3d(up[0], up[1], up[2]);
-      glVertex3d(tm[0], tm[1], tm[2]);
-      glVertex3d(top[0], top[1], top[2]);
-      glEnd();
-      glDisable(GL_LIGHTING);
-    }
-    else{
-      glBegin(GL_LINE_LOOP);
-      glVertex3d(x+b*(t[0]),  y+b*(t[1]),  z+b*(t[2]));
-      glVertex3d(x+b*(-u[0]), y+b*(-u[1]), z+b*(-u[2]));
-      glVertex3d(x+b*(-t[0]), y+b*(-t[1]), z+b*(-t[2]));
-      glVertex3d(x+b*(u[0]),  y+b*(u[1]),  z+b*(u[2]));
-      glEnd();
-      
-      glBegin(GL_LINES);
-      glVertex3d(x+b*(t[0]),  y+b*(t[1]),  z+b*(t[2]));
-      glVertex3d(x+dx,        y+dy,        z+dz);
-      
-      glVertex3d(x+b*(-u[0]), y+b*(-u[1]), z+b*(-u[2]));
-      glVertex3d(x+dx,        y+dy,        z+dz);
-      
-      glVertex3d(x+b*(-t[0]), y+b*(-t[1]), z+b*(-t[2]));
-      glVertex3d(x+dx,        y+dy,        z+dz);
-      
-      glVertex3d (x+b*(u[0]), y+b*(u[1]),  z+b*(u[2]));
-      glVertex3d(x+dx,        y+dy,        z+dz);
-      glEnd();
-    }
-  }
-
-}
-
-void Draw_3DArrow(double relHeadRadius, double relStemLength, double relStemRadius,
-                  double x, double y, double z, double dx, double dy, double dz,
-                  double length, int light)
-{
-  if(light) glEnable(GL_LIGHTING);
-
-  int subdiv = CTX.quadric_subdivisions;
-  double head_r = relHeadRadius * length;
-  double head_l = (1. - relStemLength) * length;
-  double stem_r = relStemRadius * length;
-  double stem_l = relStemLength * length;
-
-  static int first = 1;
-  static GLUquadricObj *qua;
-
-  if(first){
-    first = 0;
-    qua = gluNewQuadric();
-  }
-
-  double zdir[3] = {0., 0., 1.};
-  double vdir[3] = {dx/length, dy/length, dz/length};
-  double axis[3], cosphi, phi;
-  prodve(zdir, vdir, axis);
-  prosca(zdir, vdir, &cosphi);
-  if(!norme(axis)){
-    axis[0] = 0.;
-    axis[1] = 1.;
-    axis[2] = 0.;
-  }
-  phi = 180. * myacos(cosphi) / M_PI; 
-
-  glPushMatrix();
-  glTranslated(x, y, z);
-  glRotated(phi, axis[0], axis[1], axis[2]);
-  glTranslated(0., 0., stem_l);
-  if(head_l && head_r)
-    gluCylinder(qua, head_r, 0., head_l, subdiv, 1);
-  if(head_r > stem_r)
-    gluDisk(qua, stem_r, head_r, subdiv, 1);
-  else
-    gluDisk(qua, head_r, stem_r, subdiv, 1);      
-  glTranslated(0., 0., -stem_l);
-  if(stem_l && stem_r){
-    gluCylinder(qua, stem_r, stem_r, stem_l, subdiv, 1);
-    gluDisk(qua, 0, stem_r, subdiv, 1);
-  }
-  glPopMatrix();
-
-  glDisable(GL_LIGHTING);
-}
-
-void Draw_Vector(int Type, int Fill,
-                 double relHeadRadius, double relStemLength, double relStemRadius,
-                 double x, double y, double z, double dx, double dy, double dz,
-                 int light)
-{
-  double length = sqrt(dx * dx + dy * dy + dz * dz);
-
-  if(length == 0.0) return;
-
-  switch(Type){
-  case 1:
-    glBegin(GL_LINES);
-    glVertex3d(x, y, z);
-    glVertex3d(x + dx, y + dy, z + dz);
-    glEnd();
-    break;
-  case 6:
-    if(relHeadRadius){
-      glBegin(GL_POINTS);
-      glVertex3d(x + dx, y + dy, z + dz);
-      glEnd();
-    }
-    glBegin(GL_LINES);
-    glVertex3d(x + dx, y + dy, z + dz);
-    // color gradient
-    glColor4ubv((GLubyte *) & CTX.color.bg);
-    glVertex3d(x, y, z);
-    glEnd();
-    break;
-  case 2:
-    Draw_SimpleVector(1, Fill, relHeadRadius, relStemLength, relStemRadius,
-                      x, y, z, dx, dy, dz, length, light);
-    break;
-  case 3:
-    Draw_SimpleVector(0, Fill, relHeadRadius, relStemLength, relStemRadius,
-                      x, y, z, dx, dy, dz, length, light);
-    break;
-  case 4:
-  default:
-    Draw_3DArrow(relHeadRadius, relStemLength, relStemRadius,
-                 x, y, z, dx, dy, dz, length, light);
-    break;
-  }
-}
-
-class point{
-public:
-  double x, y, z;
-  bool valid;
-  point() : x(0.), y(0.), z(0.), valid(false) {;};
-  point(double xi, double yi, double zi) :
-    x(xi), y(yi), z(zi), valid(true) {;};
-};
-
-class plane{
-private:
-    double _a, _b, _c, _d;
-public:
-    plane(double a, double b, double c, double d) :
-        _a(a), _b(b), _c(c), _d(d) {;};
-    double val(point &p){
-        return _a*p.x + _b*p.y + _c*p.z + _d;
-    };
-    point intersect(point &p1, point &p2){
-        double v1 = val(p1), v2 = val(p2);
-        if(fabs(v1) < 1.e-12){
-            if(fabs(v2) < 1.e-12)
-                return point();
-            else
-                return point(p1.x, p1.y, p1.z);
-        }
-        else if(fabs(v2) < 1.e-12){
-            return point(p2.x, p2.y, p2.z);
-        }
-        else if(v1 * v2 < 0.){
-            double coef = - v1 / (v2 - v1);
-            return point(coef * (p2.x - p1.x) + p1.x,
-                         coef * (p2.y - p1.y) + p1.y,
-                         coef * (p2.z - p1.z) + p1.z);
-        }
-        else
-            return point();
-    };
-};
-
-void Draw_Box(double xmin, double ymin, double zmin,
-              double xmax, double ymax, double zmax,
-              bool labels)
-{
-  glBegin(GL_LINE_LOOP);
-  glVertex3d(xmin, ymin, zmin);
-  glVertex3d(xmax, ymin, zmin);
-  glVertex3d(xmax, ymax, zmin);
-  glVertex3d(xmin, ymax, zmin);
-  glEnd();
-  glBegin(GL_LINE_LOOP);
-  glVertex3d(xmin, ymin, zmax);
-  glVertex3d(xmax, ymin, zmax);
-  glVertex3d(xmax, ymax, zmax);
-  glVertex3d(xmin, ymax, zmax);
-  glEnd();
-  glBegin(GL_LINES);
-  glVertex3d(xmin, ymin, zmin);
-  glVertex3d(xmin, ymin, zmax);
-  glVertex3d(xmax, ymin, zmin);
-  glVertex3d(xmax, ymin, zmax);
-  glVertex3d(xmax, ymax, zmin);
-  glVertex3d(xmax, ymax, zmax);
-  glVertex3d(xmin, ymax, zmin);
-  glVertex3d(xmin, ymax, zmax);
-  glEnd();
-  if(labels){
-    char label[256];
-    double offset = 0.3 * CTX.gl_fontsize * CTX.pixel_equiv_x;
-    glRasterPos3d(xmin + offset / CTX.s[0], 
-                  ymin + offset / CTX.s[1], 
-                  zmin + offset / CTX.s[2]);
-    sprintf(label, "(%g,%g,%g)", xmin, ymin, zmin);
-    Draw_String(label);
-    glRasterPos3d(xmax + offset / CTX.s[0], 
-                  ymax + offset / CTX.s[1], 
-                  zmax + offset / CTX.s[2]);
-    sprintf(label, "(%g,%g,%g)", xmax, ymax, zmax);
-    Draw_String(label);
-  }
-}
-
-void Draw_PlaneInBoundingBox(double xmin, double ymin, double zmin,
-                             double xmax, double ymax, double zmax,
-                             double a, double b, double c, double d,
-                             int shade)
-{
-
-  plane pl(a, b, c, d);
-  point p1(xmin, ymin, zmin), p2(xmax, ymin, zmin);
-  point p3(xmax, ymax, zmin), p4(xmin, ymax, zmin);
-  point p5(xmin, ymin, zmax), p6(xmax, ymin, zmax);
-  point p7(xmax, ymax, zmax), p8(xmin, ymax, zmax);
-
-  point edge[12];
-  edge[0] = pl.intersect(p1, p2);
-  edge[1] = pl.intersect(p1, p4);
-  edge[2] = pl.intersect(p1, p5);
-  edge[3] = pl.intersect(p2, p3);
-  edge[4] = pl.intersect(p2, p6);
-  edge[5] = pl.intersect(p3, p4);
-  edge[6] = pl.intersect(p3, p7);
-  edge[7] = pl.intersect(p4, p8);
-  edge[8] = pl.intersect(p5, p6);
-  edge[9] = pl.intersect(p5, p8);
-  edge[10] = pl.intersect(p6, p7);
-  edge[11] = pl.intersect(p7, p8);
-
-  int face[6][4] = {
-    {0, 2, 4, 8},
-    {0, 1, 3, 5},
-    {1, 2, 7, 9},
-    {3, 4, 6, 10},
-    {5, 6, 7, 11},
-    {8, 9, 10, 11}
-  };
-  
-  double n[3] = {a,b,c}, ll = 50;
-  norme(n);
-  if(CTX.arrow_rel_stem_radius)
-    ll = CTX.line_width/CTX.arrow_rel_stem_radius;
-  n[0] *= ll * CTX.pixel_equiv_x / CTX.s[0];
-  n[1] *= ll * CTX.pixel_equiv_x / CTX.s[1];
-  n[2] *= ll * CTX.pixel_equiv_x / CTX.s[2];
-  double length = sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]);
-
-  int n_shade = 0;
-  point p_shade[24];
-
-  for(int i = 0; i < 6; i++){
-    int nb = 0;
-    point p[4];
-    for(int j = 0; j < 4; j++){
-      if(edge[face[i][j]].valid == true)
-        p[nb++] = edge[face[i][j]];
-    }
-    if(nb > 1){
-      for(int j = 1; j < nb; j++){
-        double xx[2] = {p[j].x, p[j-1].x};
-        double yy[2] = {p[j].y, p[j-1].y};
-        double zz[2] = {p[j].z, p[j-1].z};
-        Draw_Cylinder(CTX.line_width, xx, yy, zz, 1);
-      }
-      for(int j = 0; j < nb; j++){
-        Draw_3DArrow(CTX.arrow_rel_head_radius, 
-                     CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius,
-                     p[j].x, p[j].y, p[j].z, n[0], n[1], n[2], length, 1);
-        if(shade){
-          p_shade[n_shade].x = p[j].x;
-          p_shade[n_shade].y = p[j].y;
-          p_shade[n_shade].z = p[j].z;
-          n_shade++;
-        }
-      }
-    }
-  }
-
-  if(shade){
-    // disable two-side lighting beacuse polygon can overlap itself
-    GLboolean twoside;
-    glGetBooleanv(GL_LIGHT_MODEL_TWO_SIDE, &twoside);
-    glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
-    glEnable(GL_LIGHTING);
-    glBegin(GL_POLYGON);
-    glNormal3d(n[0], n[1], n[2]);
-    for(int j = 0; j < n_shade; j++){
-      glVertex3d(p_shade[j].x, p_shade[j].y, p_shade[j].z);
-    }   
-    glEnd();
-    glDisable(GL_LIGHTING);
-    glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, twoside);
-  }
-}
-
-void Draw_SmallAxes()
-{
-  double l = CTX.small_axes_size;
-  double o = CTX.gl_fontsize / 5;
-
-  double cx = CTX.small_axes_pos[0];
-  double cy = CTX.small_axes_pos[1];
-  Fix2DCoordinates(&cx, &cy);
-
-  double xx = l * CTX.rot[0];
-  double xy = l * CTX.rot[1];
-  double yx = l * CTX.rot[4];
-  double yy = l * CTX.rot[5];
-  double zx = l * CTX.rot[8];
-  double zy = l * CTX.rot[9];
-
-  glLineWidth(CTX.line_width);
-  gl2psLineWidth(CTX.line_width * CTX.print.eps_line_width_factor);
-  glColor4ubv((GLubyte *) & CTX.color.small_axes);
-
-  glBegin(GL_LINES);
-  glVertex2d(cx, cy);
-  glVertex2d(cx + xx, cy + xy);
-  glVertex2d(cx, cy);
-  glVertex2d(cx + yx, cy + yy);
-  glVertex2d(cx, cy);
-  glVertex2d(cx + zx, cy + zy);
-  glEnd();
-  glRasterPos2d(cx + xx + o, cy + xy + o);
-  Draw_String("X");
-  glRasterPos2d(cx + yx + o, cy + yy + o);
-  Draw_String("Y");
-  glRasterPos2d(cx + zx + o, cy + zy + o);
-  Draw_String("Z");
-}
-
-int Draw_Tics(int comp, int n, char *format, char *label,
-              double p1[3], double p2[3], double perp[3], int mikado)
-{
-  // draws n tic marks (in direction perp) and labels along the line p1->p2
-
-  double t[3] = { p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2] };
-  double l = norme(t);
-  double w = 10 * CTX.pixel_equiv_x / CTX.s[0]; // big tics 10 pixels
-  double w2 = 5 * CTX.pixel_equiv_x / CTX.s[0]; // small tics 5 pixels
-
-  glRasterPos3d(p2[0]+t[0]*w*1.4, p2[1]+t[1]*w*1.4, p2[2]+t[2]*w*1.4);
-  Draw_String(label);
-
-  if(n < 2) return 0;
-
-  if(!strlen(format)) return n;
-
-  double lp = norme(perp);
-  if(!lp){
-    switch(comp){
-    case 0: perp[1] = -1.; break;
-    case 1: perp[0] = -1.; break;
-    case 2: perp[0] = 1.; break;
-    default: break;
-    }
-  }
-  
-  double tmp = 2. * CTX.gl_fontsize * CTX.pixel_equiv_x / CTX.s[0];
-  if(n * tmp > l) n = 3;
-  if(n * tmp > l) n = 2;
-  
-  double step = l/(double)(n-1);
-
-  for(int i = 0; i < n; i++){
-    double d = i * step;
-    double p[3] = { p1[0]+t[0]*d, p1[1]+t[1]*d, p1[2]+t[2]*d };
-    double q[3] = { p[0]+perp[0]*w, p[1]+perp[1]*w, p[2]+perp[2]*w };
-    double r[3] = { p[0]+perp[0]*w*1.4, p[1]+perp[1]*w*1.4, p[2]+perp[2]*w*1.4 };
-
-    glBegin(GL_LINES);
-    glVertex3d(p[0], p[1], p[2]);
-    glVertex3d(q[0], q[1], q[2]);
-    glEnd();
-
-    if(i < n-1 && !mikado){
-      for(int j = 1; j < 10; j++){
-        double dd = d + j * step/10.;
-        double pp[3] = { p1[0]+t[0]*dd, p1[1]+t[1]*dd, p1[2]+t[2]*dd };
-        double qq[3] = { pp[0]+perp[0]*w2, pp[1]+perp[1]*w2, pp[2]+perp[2]*w2 };
-        glBegin(GL_LINES);
-        glVertex3d(pp[0], pp[1], pp[2]);
-        glVertex3d(qq[0], qq[1], qq[2]);
-        glEnd();
-      }
-    }
-
-    char str[256];
-    if(comp < 0) // display the length (ruler)
-      sprintf(str, format, d);
-    else // display the coordinate
-      sprintf(str, format, p[comp]);
-    double winp[3], winr[3];
-    World2Viewport(p, winp);
-    World2Viewport(r, winr);
-    gl_font(CTX.gl_font_enum, CTX.gl_fontsize);
-    if(fabs(winr[0] - winp[0]) < 2.) // center align
-      winr[0] -= gl_width(str) / 2.;
-    else if(winr[0] < winp[0]) // right align
-      winr[0] -= gl_width(str);
-    if(fabs(winr[1] - winp[1]) < 2.) // center align
-      winr[1] -= gl_height() / 3.;
-    else if(winr[1] < winp[1]) // top align
-      winr[1] -= gl_height();
-    Viewport2World(winr, r);
-    glRasterPos3d(r[0], r[1], r[2]);
-    Draw_String(str);
-  }
-
-  return n;
-}
-
-void Draw_GridStipple(int n1, int n2, double p1[3], double p2[3], double p3[3])
-{
-  double t1[3] = { p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2] };
-  double t2[3] = { p3[0]-p1[0], p3[1]-p1[1], p3[2]-p1[2] };
-  double l1 = norme(t1);
-  double l2 = norme(t2);
-
-  glEnable(GL_LINE_STIPPLE);
-  glLineStipple(1, 0x1111);
-  gl2psEnable(GL2PS_LINE_STIPPLE);
-  glBegin(GL_LINES);
-  
-  for(int i = 1; i < n1-1; i++){
-    double d = (double)i/(double)(n1-1) * l1;
-    glVertex3d(p1[0] + t1[0]*d,
-               p1[1] + t1[1]*d,
-               p1[2] + t1[2]*d);
-    glVertex3d(p1[0] + t1[0]*d + t2[0]*l2, 
-               p1[1] + t1[1]*d + t2[1]*l2, 
-               p1[2] + t1[2]*d + t2[2]*l2);
-  }
-  for(int i = 1; i < n2-1; i++){
-    double d = (double)i/(double)(n2-1) * l2;
-    glVertex3d(p1[0] + t2[0]*d, 
-               p1[1] + t2[1]*d, 
-               p1[2] + t2[2]*d);
-    glVertex3d(p1[0] + t2[0]*d + t1[0]*l1, 
-               p1[1] + t2[1]*d + t1[1]*l1, 
-               p1[2] + t2[2]*d + t1[2]*l1);
-  }
-
-  glEnd();
-  glDisable(GL_LINE_STIPPLE);
-  gl2psDisable(GL2PS_LINE_STIPPLE);
-}
-
-void Draw_Axes(int mode, int tics[3], char format[3][256], char label[3][256], 
-               SBoundingBox3d &bb, int mikado)
-{
-  double bbox[6] = {bb.min().x(), bb.max().x(),
-                    bb.min().y(), bb.max().y(),
-                    bb.min().z(), bb.max().z()};
-  Draw_Axes(mode, tics, format, label, bbox, mikado);
-}
-
-void Draw_Axe(double xmin, double ymin, double zmin,
-              double xmax, double ymax, double zmax, int nticks, int mikado)
-{
-  if(mikado){
-    nticks = (nticks - 1) * mikado;
-    if(nticks < 1) nticks = 1;
-    double dd[3] = {(xmax - xmin) / nticks, 
-                    (ymax - ymin) / nticks, 
-                    (zmax - zmin) / nticks};
-    double axe_color[4];
-    glGetDoublev(GL_CURRENT_COLOR, axe_color);
-    for(int i = 1; i <= nticks; i++){
-      if(i % 2) glColor4dv(axe_color);
-      else glColor3f(1, 1, 1);
-      double cx[2] ={xmin + (i - 1) * dd[0], xmin + i * dd[0]};
-      double cy[2] ={ymin + (i - 1) * dd[1], ymin + i * dd[1]};
-      double cz[2] ={zmin + (i - 1) * dd[2], zmin + i * dd[2]};
-      Draw_Cylinder(3.5, cx, cy, cz, 1);
-    }
-    glColor4dv(axe_color);
-  }
-  else{
-    glBegin(GL_LINES);
-    glVertex3d(xmin, ymin, zmin); 
-    glVertex3d(xmax, ymax, zmax);
-    glEnd();
-  }
-}
-
-void Draw_Axes(int mode, int tics[3], char format[3][256], char label[3][256], 
-               double bb[6], int mikado)
-{
-  // mode 0: nothing
-  //      1: axes
-  //      2: box
-  //      3: full grid
-  //      4: open grid
-  //      5: ruler
-
-  if((mode < 1) || (bb[0] == bb[1] && bb[2] == bb[3] && bb[4] == bb[5]))
-    return;
-
-  double xmin = bb[0], xmax = bb[1];
-  double ymin = bb[2], ymax = bb[3];
-  double zmin = bb[4], zmax = bb[5];
-  double orig[3] = {xmin, ymin, zmin};
-
-  if(mode == 5){ // draw ruler from xyz_min to xyz_max
-    double end[3] = {xmax, ymax, zmax};
-    double dir[3] = {xmax-xmin, ymax-ymin, zmax-zmin};
-    double perp[3];
-    if((fabs(dir[0]) >= fabs(dir[1]) && fabs(dir[0]) >= fabs(dir[2])) ||
-       (fabs(dir[1]) >= fabs(dir[0]) && fabs(dir[1]) >= fabs(dir[2]))){
-      perp[0] = dir[1]; perp[1] = -dir[0]; perp[2] = 0.;
-    }
-    else{
-      perp[0] = 0.; perp[1] = dir[2]; perp[2] = -dir[1];
-    }
-    Draw_Tics(-1, tics[0], format[0], label[0], orig, end, perp, mikado);
-    Draw_Axe(xmin, ymin, zmin, xmax, ymax, zmax, tics[0], mikado);
-    return;
-  }
-  double xx[3] = {xmax, ymin, zmin};
-  double yy[3] = {xmin, ymax, zmin};
-  double zz[3] = {xmin, ymin, zmax};
-  double dxm[3] = {0., (ymin != ymax) ? -1. : 0., (zmin != zmax) ? -1. : 0.};
-  double dym[3] = {(xmin != xmax) ? -1. : 0., 0., (zmin != zmax) ? -1. : 0.};
-  double dzm[3] = {(xmin != xmax) ? -1. : 0., (ymin != ymax) ? -1. : 0., 0.};
-  
-  int nx = (xmin != xmax) ? 
-    Draw_Tics(0, tics[0], format[0], label[0], orig, xx, dxm, mikado) : 0;
-  int ny = (ymin != ymax) ? 
-    Draw_Tics(1, tics[1], format[1], label[1], orig, yy, dym, mikado) : 0;
-  int nz = (zmin != zmax) ? 
-    Draw_Tics(2, tics[2], format[2], label[2], orig, zz, dzm, mikado) : 0;
-
-  Draw_Axe(xmin, ymin, zmin, xmax, ymin, zmin, nx, mikado);
-  Draw_Axe(xmin, ymin, zmin, xmin, ymax, zmin, ny, mikado);
-  Draw_Axe(xmin, ymin, zmin, xmin, ymin, zmax, nz, mikado);
-
-  // open box
-  if(mode > 1){
-    Draw_Axe(xmin, ymax, zmin, xmax, ymax, zmin, nx, mikado);
-    Draw_Axe(xmax, ymin, zmin, xmax, ymax, zmin, ny, mikado);
-    Draw_Axe(xmax, ymin, zmin, xmax, ymin, zmax, nz, mikado);
-    Draw_Axe(xmin, ymin, zmax, xmax, ymin, zmax, nx, mikado);
-    Draw_Axe(xmin, ymin, zmax, xmin, ymax, zmax, ny, mikado);
-    Draw_Axe(xmin, ymax, zmin, xmin, ymax, zmax, nz, mikado);
-  }
-
-  // closed box
-  if(mode == 2 || mode == 3){
-    Draw_Axe(xmin, ymax, zmax, xmax, ymax, zmax, nx, mikado);
-    Draw_Axe(xmax, ymin, zmax, xmax, ymax, zmax, ny, mikado);
-    Draw_Axe(xmax, ymax, zmin, xmax, ymax, zmax, nz, mikado);
-  }
-  
-  if(mode > 2){
-    Draw_GridStipple(nx, ny, orig, xx, yy);
-    Draw_GridStipple(ny, nz, orig, yy, zz);
-    Draw_GridStipple(nx, nz, orig, xx, zz);
-  }
-
-  if(mode == 3){
-    double orig2[3] = {xmax, ymax, zmax};
-    double xy[3] = {xmax, ymax, zmin};
-    double yz[3] = {xmin, ymax, zmax};
-    double xz[3] = {xmax, ymin, zmax};
-    if(zmin != zmax) Draw_GridStipple(nx, ny, orig2, yz, xz);
-    if(xmin != xmax) Draw_GridStipple(ny, nz, orig2, xz, xy);
-    if(ymin != ymax) Draw_GridStipple(nx, nz, orig2, yz, xy);
-  }
-}
diff --git a/Graphics/Makefile b/Graphics/Makefile
index f0f4ef7a7970a8d0152ec963b43453243763fb5a..024dba366af36d54be22022ad4e289eb39babe18 100644
--- a/Graphics/Makefile
+++ b/Graphics/Makefile
@@ -14,17 +14,18 @@ INC = ${DASH}I../Common ${DASH}I../Geo ${DASH}I../Mesh\
 
 CFLAGS = ${OPTIM} ${FLAGS} ${INC} ${SYSINCLUDE}
 
-SRC = Draw.cpp \
-      Mesh.cpp \
-      Geom.cpp \
-      Post.cpp \
+SRC = Trackball.cpp \
       SelectBuffer.cpp \
       Iso.cpp \
-      Entity.cpp \
       ReadImg.cpp \
-      Axes.cpp \
-      Scale.cpp \
-      Graph2D.cpp \
+      drawContext.cpp \
+      drawMesh.cpp \
+      drawGeom.cpp \
+      drawPost.cpp \
+      drawAxes.cpp \
+      drawScales.cpp \
+      drawGraph2d.cpp \
+      drawGlyph.cpp \
       gl2ps.cpp\
       gl2gif.cpp\
       gl2jpeg.cpp\
@@ -58,8 +59,30 @@ depend:
 	rm -f Makefile.new
 
 # DO NOT DELETE THIS LINE
-Draw${OBJEXT}: Draw.cpp ../Common/GmshUI.h ../Common/GmshDefines.h \
-  ../Common/GmshMessage.h Draw.h ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h \
+Trackball${OBJEXT}: Trackball.cpp Trackball.h
+SelectBuffer${OBJEXT}: SelectBuffer.cpp ../Common/GmshUI.h \
+  ../Common/GmshDefines.h ../Common/GmshMessage.h ../Geo/GModel.h \
+  ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
+  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Geo/GPoint.h \
+  ../Geo/SPoint2.h ../Geo/GEdge.h ../Geo/GEntity.h ../Geo/GVertex.h \
+  ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint3.h ../Geo/SPoint2.h \
+  ../Geo/GFace.h ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/GEdgeLoop.h \
+  ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
+  ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
+  ../Geo/SBoundingBox3d.h ../Geo/MElement.h ../Geo/MVertex.h \
+  ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h ../Geo/MVertex.h \
+  ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h ../Common/Context.h \
+  ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h SelectBuffer.h \
+  drawContext.h ../Common/VertexArray.h
+Iso${OBJEXT}: Iso.cpp ../Numeric/Numeric.h ../Numeric/NumericEmbedded.h
+ReadImg${OBJEXT}: ReadImg.cpp ReadImg.h ../Common/GmshMessage.h \
+  ../Common/GmshUI.h ../Post/PView.h ../Geo/SPoint3.h \
+  ../Post/PViewDataList.h ../Post/PViewData.h ../Geo/SBoundingBox3d.h \
+  ../Geo/SPoint3.h ../Common/ListUtils.h
+drawContext${OBJEXT}: drawContext.cpp ../Common/GmshUI.h ../Common/GmshDefines.h \
+  ../Common/GmshMessage.h ../Fltk/Draw.h drawContext.h \
+  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h Trackball.h \
   ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h \
   ../Numeric/Numeric.h ../Numeric/NumericEmbedded.h ../Geo/GModel.h \
   ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
@@ -70,24 +93,26 @@ Draw${OBJEXT}: Draw.cpp ../Common/GmshUI.h ../Common/GmshDefines.h \
   ../Geo/SVector3.h ../Geo/Pair.h ../Geo/GRegion.h ../Geo/GEntity.h \
   ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h ../Post/PView.h \
   ../Post/PViewOptions.h ../Post/ColorTable.h
-Mesh${OBJEXT}: Mesh.cpp ../Common/GmshMessage.h ../Common/GmshUI.h \
-  ../Geo/GModel.h ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/Range.h \
-  ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h \
-  ../Geo/GPoint.h ../Geo/SPoint2.h ../Geo/GEdge.h ../Geo/GEntity.h \
-  ../Geo/GVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint3.h \
-  ../Geo/SPoint2.h ../Geo/GFace.h ../Geo/GEntity.h ../Geo/GPoint.h \
-  ../Geo/GEdgeLoop.h ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h \
-  ../Geo/Pair.h ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.h ../Geo/MElement.h ../Common/GmshDefines.h \
+drawMesh${OBJEXT}: drawMesh.cpp drawContext.h ../Geo/SBoundingBox3d.h \
+  ../Geo/SPoint3.h ../Common/GmshMessage.h ../Common/GmshUI.h \
+  ../Common/GmshDefines.h ../Geo/GModel.h ../Geo/GVertex.h \
+  ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
+  ../Geo/SBoundingBox3d.h ../Geo/GPoint.h ../Geo/SPoint2.h ../Geo/GEdge.h \
+  ../Geo/GEntity.h ../Geo/GVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h \
+  ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/GFace.h ../Geo/GEntity.h \
+  ../Geo/GPoint.h ../Geo/GEdgeLoop.h ../Geo/GEdge.h ../Geo/SPoint2.h \
+  ../Geo/SVector3.h ../Geo/Pair.h ../Geo/GRegion.h ../Geo/GEntity.h \
+  ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h ../Geo/MElement.h \
   ../Geo/MVertex.h ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h \
   ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h \
   ../Geo/SVector3.h ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h \
-  Draw.h ../Common/Context.h ../Geo/CGNSOptions.h \
+  ../Fltk/Draw.h ../Common/Context.h ../Geo/CGNSOptions.h \
   ../Mesh/PartitionOptions.h ../Common/OS.h gl2ps.h \
   ../Common/VertexArray.h ../Common/SmoothData.h ../Post/PView.h \
   ../Post/PViewData.h
-Geom${OBJEXT}: Geom.cpp ../Common/GmshUI.h Draw.h ../Geo/SBoundingBox3d.h \
-  ../Geo/SPoint3.h ../Common/Context.h ../Geo/CGNSOptions.h \
+drawGeom${OBJEXT}: drawGeom.cpp drawContext.h ../Geo/SBoundingBox3d.h \
+  ../Geo/SPoint3.h ../Common/GmshUI.h ../Common/GmshDefines.h \
+  ../Fltk/Draw.h ../Common/Context.h ../Geo/CGNSOptions.h \
   ../Mesh/PartitionOptions.h gl2ps.h ../Common/VertexArray.h \
   ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/GModel.h ../Geo/GVertex.h \
   ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
@@ -97,69 +122,46 @@ Geom${OBJEXT}: Geom.cpp ../Common/GmshUI.h Draw.h ../Geo/SBoundingBox3d.h \
   ../Geo/GEdgeLoop.h ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h \
   ../Geo/Pair.h ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
   ../Geo/SBoundingBox3d.h
-Post${OBJEXT}: Post.cpp ../Common/GmshMessage.h ../Common/GmshUI.h \
-  ../Numeric/Numeric.h ../Numeric/NumericEmbedded.h Draw.h \
-  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h Iso.h ../Post/PView.h \
-  ../Post/PViewOptions.h ../Post/ColorTable.h ../Post/PViewData.h \
-  ../Common/VertexArray.h ../Geo/SVector3.h ../Geo/SPoint3.h \
-  ../Common/SmoothData.h ../Common/Context.h ../Geo/CGNSOptions.h \
-  ../Mesh/PartitionOptions.h gl2ps.h
-SelectBuffer${OBJEXT}: SelectBuffer.cpp ../Common/GmshMessage.h \
-  ../Common/GmshUI.h ../Common/GmshDefines.h ../Geo/GModel.h \
+drawPost${OBJEXT}: drawPost.cpp drawContext.h ../Geo/SBoundingBox3d.h \
+  ../Geo/SPoint3.h ../Common/GmshMessage.h ../Common/GmshUI.h \
+  ../Numeric/Numeric.h ../Numeric/NumericEmbedded.h ../Fltk/Draw.h Iso.h \
+  ../Post/PView.h ../Post/PViewOptions.h ../Post/ColorTable.h \
+  ../Post/PViewData.h ../Common/VertexArray.h ../Geo/SVector3.h \
+  ../Geo/SPoint3.h ../Common/SmoothData.h ../Common/Context.h \
+  ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h gl2ps.h
+drawAxes${OBJEXT}: drawAxes.cpp drawContext.h ../Geo/SBoundingBox3d.h \
+  ../Geo/SPoint3.h ../Common/GmshUI.h ../Fltk/Draw.h ../Geo/GModel.h \
   ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Geo/GPoint.h \
-  ../Geo/SPoint2.h ../Geo/GEdge.h ../Geo/GEntity.h ../Geo/GVertex.h \
-  ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint3.h ../Geo/SPoint2.h \
-  ../Geo/GFace.h ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/GEdgeLoop.h \
-  ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
-  ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.h ../Geo/MElement.h ../Geo/MVertex.h \
-  ../Geo/SPoint2.h ../Geo/SPoint3.h ../Geo/MEdge.h ../Geo/MVertex.h \
-  ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
-  ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h Draw.h \
-  ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h \
-  SelectBuffer.h ../Common/VertexArray.h
-Iso${OBJEXT}: Iso.cpp ../Numeric/Numeric.h ../Numeric/NumericEmbedded.h
-Entity${OBJEXT}: Entity.cpp ../Common/GmshUI.h ../Numeric/Numeric.h \
-  ../Numeric/NumericEmbedded.h Draw.h ../Geo/SBoundingBox3d.h \
-  ../Geo/SPoint3.h ../Common/Context.h ../Geo/CGNSOptions.h \
-  ../Mesh/PartitionOptions.h gl2ps.h
-ReadImg${OBJEXT}: ReadImg.cpp ReadImg.h ../Common/GmshMessage.h \
-  ../Common/GmshUI.h ../Post/PView.h ../Geo/SPoint3.h \
-  ../Post/PViewDataList.h ../Post/PViewData.h ../Geo/SBoundingBox3d.h \
-  ../Geo/SPoint3.h ../Common/ListUtils.h
-Axes${OBJEXT}: Axes.cpp ../Common/GmshUI.h Draw.h ../Geo/SBoundingBox3d.h \
-  ../Geo/SPoint3.h ../Common/Context.h ../Geo/CGNSOptions.h \
-  ../Mesh/PartitionOptions.h gl2ps.h ../Geo/GModel.h ../Geo/GVertex.h \
-  ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
   ../Geo/SBoundingBox3d.h ../Geo/GPoint.h ../Geo/SPoint2.h ../Geo/GEdge.h \
   ../Geo/GEntity.h ../Geo/GVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h \
   ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/GFace.h ../Geo/GEntity.h \
   ../Geo/GPoint.h ../Geo/GEdgeLoop.h ../Geo/GEdge.h ../Geo/SPoint2.h \
   ../Geo/SVector3.h ../Geo/Pair.h ../Geo/GRegion.h ../Geo/GEntity.h \
-  ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h
-Scale${OBJEXT}: Scale.cpp ../Common/GmshUI.h Draw.h ../Geo/SBoundingBox3d.h \
-  ../Geo/SPoint3.h ../Post/PView.h ../Post/PViewOptions.h \
-  ../Post/ColorTable.h ../Post/PViewData.h ../Common/Context.h \
-  ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h gl2ps.h
-Graph2D${OBJEXT}: Graph2D.cpp ../Common/GmshUI.h Draw.h ../Geo/SBoundingBox3d.h \
-  ../Geo/SPoint3.h ../Post/PView.h ../Post/PViewOptions.h \
-  ../Post/ColorTable.h ../Post/PViewData.h gl2ps.h ../Common/Context.h \
+  ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h ../Common/Context.h \
   ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h ../Numeric/Numeric.h \
-  ../Numeric/NumericEmbedded.h
+  ../Numeric/NumericEmbedded.h gl2ps.h
+drawScales${OBJEXT}: drawScales.cpp drawContext.h ../Geo/SBoundingBox3d.h \
+  ../Geo/SPoint3.h ../Common/GmshUI.h ../Fltk/Draw.h ../Post/PView.h \
+  ../Post/PViewOptions.h ../Post/ColorTable.h ../Post/PViewData.h \
+  ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h \
+  gl2ps.h
+drawGraph2d${OBJEXT}: drawGraph2d.cpp drawContext.h ../Geo/SBoundingBox3d.h \
+  ../Geo/SPoint3.h ../Common/GmshUI.h ../Fltk/Draw.h ../Post/PView.h \
+  ../Post/PViewOptions.h ../Post/ColorTable.h ../Post/PViewData.h gl2ps.h \
+  ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h \
+  ../Numeric/Numeric.h ../Numeric/NumericEmbedded.h
+drawGlyph${OBJEXT}: drawGlyph.cpp drawContext.h ../Geo/SBoundingBox3d.h \
+  ../Geo/SPoint3.h ../Common/GmshUI.h ../Numeric/Numeric.h \
+  ../Numeric/NumericEmbedded.h ../Fltk/Draw.h ../Common/Context.h \
+  ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h gl2ps.h
 gl2ps${OBJEXT}: gl2ps.cpp gl2ps.h
 gl2gif${OBJEXT}: gl2gif.cpp ../Common/MallocUtils.h gl2gif.h PixelBuffer.h \
-  ../Common/GmshUI.h ../Common/GmshMessage.h Draw.h \
-  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h
+  ../Common/GmshUI.h ../Common/GmshMessage.h ../Fltk/Draw.h
 gl2jpeg${OBJEXT}: gl2jpeg.cpp gl2jpeg.h PixelBuffer.h ../Common/GmshUI.h \
-  ../Common/GmshMessage.h ../Common/MallocUtils.h Draw.h \
-  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h
+  ../Common/GmshMessage.h ../Fltk/Draw.h ../Common/MallocUtils.h
 gl2png${OBJEXT}: gl2png.cpp gl2png.h PixelBuffer.h ../Common/GmshUI.h \
-  ../Common/GmshMessage.h ../Common/MallocUtils.h Draw.h \
-  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h
+  ../Common/GmshMessage.h ../Fltk/Draw.h ../Common/MallocUtils.h
 gl2ppm${OBJEXT}: gl2ppm.cpp gl2ppm.h PixelBuffer.h ../Common/GmshUI.h \
-  ../Common/GmshMessage.h ../Common/MallocUtils.h Draw.h \
-  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h
+  ../Common/GmshMessage.h ../Fltk/Draw.h ../Common/MallocUtils.h
 gl2yuv${OBJEXT}: gl2yuv.cpp ../Common/MallocUtils.h gl2yuv.h PixelBuffer.h \
-  ../Common/GmshUI.h ../Common/GmshMessage.h Draw.h \
-  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h
+  ../Common/GmshUI.h ../Common/GmshMessage.h ../Fltk/Draw.h
diff --git a/Graphics/PixelBuffer.h b/Graphics/PixelBuffer.h
index c74f2e4de0e5162eef9c16869cfc0e41055c3c1e..cfdd63f559c1ed52a33a1a4a7142bc7e8f75ae19 100644
--- a/Graphics/PixelBuffer.h
+++ b/Graphics/PixelBuffer.h
@@ -8,8 +8,8 @@
 
 #include "GmshUI.h"
 #include "GmshMessage.h"
-#include "MallocUtils.h"
 #include "Draw.h"
+#include "MallocUtils.h"
 
 #if defined(HAVE_OSMESA)
 #include <GL/osmesa.h>
@@ -65,8 +65,7 @@ class PixelBuffer{
     if(!offscreen){
       SetOpenglContext();
       ClearOpengl();
-      Draw3d();
-      Draw2d();
+      Draw2d3d();
       glFinish();
       glPixelStorei(GL_PACK_ALIGNMENT, 1);
       glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
@@ -87,8 +86,7 @@ class PixelBuffer{
 	Msg::Error("OSMesaMakeCurrent failed");
       }
       ClearOpengl();
-      Draw3d();
-      Draw2d();
+      Draw2d3d();
       glFinish();
       OSMesaDestroyContext(ctx);
 #else
diff --git a/Graphics/SelectBuffer.cpp b/Graphics/SelectBuffer.cpp
index 0d11044a5c87bc978b7537c87e374cdb693e0f67..d5213551ece3daa658c65550230e6405f824e316 100644
--- a/Graphics/SelectBuffer.cpp
+++ b/Graphics/SelectBuffer.cpp
@@ -3,12 +3,11 @@
 // See the LICENSE.txt file for license information. Please report all
 // bugs and problems to <gmsh@geuz.org>.
 
-#include "GmshMessage.h"
 #include "GmshUI.h"
 #include "GmshDefines.h"
+#include "GmshMessage.h"
 #include "GModel.h"
 #include "MElement.h"
-#include "Draw.h"
 #include "Context.h"
 #include "SelectBuffer.h"
 #include "VertexArray.h"
@@ -47,7 +46,7 @@ static MElement *getElement(GEntity *e, int va_type, int index)
   return 0;
 }
 
-bool ProcessSelectionBuffer(int entityType,
+bool ProcessSelectionBuffer(drawContext *ctx, int entityType,
                             bool multipleSelection, bool meshSelection,
                             int x, int y, int w, int h,
                             std::vector<GVertex*> &vertices,
@@ -77,10 +76,10 @@ bool ProcessSelectionBuffer(int entityType,
 
   glInitNames();
   glPushMatrix();
-  InitProjection(x, y, w, h);
-  InitPosition();
-  Draw_Geom();
-  if(meshSelection) Draw_Mesh();
+  ctx->initProjection(x, y, w, h);
+  ctx->initPosition();
+  ctx->drawGeom();
+  if(meshSelection) ctx->drawMesh();
   glPopMatrix();
 
   GLint numhits = glRenderMode(GL_RENDER);
diff --git a/Graphics/SelectBuffer.h b/Graphics/SelectBuffer.h
index 5f07678f585b65eaae1f49f5f3f832e3f49acb61..65068b154518c2800c12e985444d4aeee65e7fa2 100644
--- a/Graphics/SelectBuffer.h
+++ b/Graphics/SelectBuffer.h
@@ -7,6 +7,7 @@
 #define _SELECT_BUFFER_H_
 
 #include <vector>
+#include "drawContext.h"
 #include "GVertex.h"
 #include "GEdge.h"
 #include "GFace.h"
@@ -14,7 +15,7 @@
 
 class MElement;
 
-bool ProcessSelectionBuffer(int entityType, 
+bool ProcessSelectionBuffer(drawContext *ctx, int entityType, 
                             bool multipleSelection, bool meshSelection,
                             int x, int y, int w, int h, 
                             std::vector<GVertex*> &vertices,
diff --git a/Common/Trackball.cpp b/Graphics/Trackball.cpp
similarity index 100%
rename from Common/Trackball.cpp
rename to Graphics/Trackball.cpp
diff --git a/Common/Trackball.h b/Graphics/Trackball.h
similarity index 100%
rename from Common/Trackball.h
rename to Graphics/Trackball.h
diff --git a/Graphics/drawAxes.cpp b/Graphics/drawAxes.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..635ef316f3ce9fc293fe35031712279f8b025ecc
--- /dev/null
+++ b/Graphics/drawAxes.cpp
@@ -0,0 +1,356 @@
+// Gmsh - Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#include "drawContext.h"
+#include "GmshUI.h"
+#include "Draw.h"
+#include "GModel.h"
+#include "Context.h"
+#include "Numeric.h"
+#include "gl2ps.h"
+
+extern Context_T CTX;
+
+static int drawTics(int comp, int n, char *format, char *label,
+                    double p1[3], double p2[3], double perp[3], int mikado,
+                    double pixelfact)
+{
+  // draws n tic marks (in direction perp) and labels along the line p1->p2
+
+  double t[3] = {p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]};
+  double l = norme(t);
+  double w = 10 * pixelfact; // big tics 10 pixels
+  double w2 = 5 * pixelfact; // small tics 5 pixels
+
+  glRasterPos3d(p2[0] + t[0] * w * 1.4,
+                p2[1] + t[1] * w * 1.4,
+                p2[2] + t[2] * w * 1.4);
+  Draw_String(label);
+
+  if(n < 2) return 0;
+
+  if(!strlen(format)) return n;
+
+  double lp = norme(perp);
+  if(!lp){
+    switch(comp){
+    case 0: perp[1] = -1.; break;
+    case 1: perp[0] = -1.; break;
+    case 2: perp[0] = 1.; break;
+    default: break;
+    }
+  }
+  
+  double tmp = 2. * CTX.gl_fontsize * pixelfact;
+  if(n * tmp > l) n = 3;
+  if(n * tmp > l) n = 2;
+  
+  double step = l / (double)(n - 1);
+
+  for(int i = 0; i < n; i++){
+    double d = i * step;
+    double p[3] = {p1[0] + t[0] * d, p1[1] + t[1] * d, p1[2] + t[2] * d};
+    double q[3] = {p[0] + perp[0] * w, 
+                   p[1] + perp[1] * w, 
+                   p[2] + perp[2] * w};
+    double r[3] = {p[0] + perp[0] * w * 1.4,
+                   p[1] + perp[1] * w * 1.4, 
+                   p[2] + perp[2] * w * 1.4 };
+
+    glBegin(GL_LINES);
+    glVertex3d(p[0], p[1], p[2]);
+    glVertex3d(q[0], q[1], q[2]);
+    glEnd();
+
+    if(i < n-1 && !mikado){
+      for(int j = 1; j < 10; j++){
+        double dd = d + j * step/10.;
+        double pp[3] = {p1[0] + t[0] * dd, 
+                        p1[1] + t[1] * dd,
+                        p1[2] + t[2] * dd};
+        double qq[3] = {pp[0] + perp[0] * w2,
+                        pp[1] + perp[1] * w2,
+                        pp[2] + perp[2] * w2};
+        glBegin(GL_LINES);
+        glVertex3d(pp[0], pp[1], pp[2]);
+        glVertex3d(qq[0], qq[1], qq[2]);
+        glEnd();
+      }
+    }
+
+    char str[256];
+    if(comp < 0) // display the length (ruler)
+      sprintf(str, format, d);
+    else // display the coordinate
+      sprintf(str, format, p[comp]);
+    double winp[3], winr[3];
+    World2Viewport(p, winp);
+    World2Viewport(r, winr);
+    gl_font(CTX.gl_font_enum, CTX.gl_fontsize);
+    if(fabs(winr[0] - winp[0]) < 2.) // center align
+      winr[0] -= gl_width(str) / 2.;
+    else if(winr[0] < winp[0]) // right align
+      winr[0] -= gl_width(str);
+    if(fabs(winr[1] - winp[1]) < 2.) // center align
+      winr[1] -= gl_height() / 3.;
+    else if(winr[1] < winp[1]) // top align
+      winr[1] -= gl_height();
+    Viewport2World(winr, r);
+    glRasterPos3d(r[0], r[1], r[2]);
+    Draw_String(str);
+  }
+
+  return n;
+}
+
+static void drawGridStipple(int n1, int n2, double p1[3], double p2[3], double p3[3])
+{
+  double t1[3] = {p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]};
+  double t2[3] = {p3[0] - p1[0], p3[1] - p1[1], p3[2] - p1[2]};
+  double l1 = norme(t1);
+  double l2 = norme(t2);
+
+  glEnable(GL_LINE_STIPPLE);
+  glLineStipple(1, 0x1111);
+  gl2psEnable(GL2PS_LINE_STIPPLE);
+  glBegin(GL_LINES);
+  
+  for(int i = 1; i < n1 - 1; i++){
+    double d = (double)i / (double)(n1 - 1) * l1;
+    glVertex3d(p1[0] + t1[0] * d,
+               p1[1] + t1[1] * d,
+               p1[2] + t1[2] * d);
+    glVertex3d(p1[0] + t1[0] * d + t2[0] * l2, 
+               p1[1] + t1[1] * d + t2[1] * l2, 
+               p1[2] + t1[2] * d + t2[2] * l2);
+  }
+  for(int i = 1; i < n2 - 1; i++){
+    double d = (double)i/(double)(n2 - 1) * l2;
+    glVertex3d(p1[0] + t2[0] * d, 
+               p1[1] + t2[1] * d, 
+               p1[2] + t2[2] * d);
+    glVertex3d(p1[0] + t2[0] * d + t1[0] * l1, 
+               p1[1] + t2[1] * d + t1[1] * l1, 
+               p1[2] + t2[2] * d + t1[2] * l1);
+  }
+
+  glEnd();
+  glDisable(GL_LINE_STIPPLE);
+  gl2psDisable(GL2PS_LINE_STIPPLE);
+}
+
+void drawContext::drawAxis(double xmin, double ymin, double zmin,
+                           double xmax, double ymax, double zmax, 
+                           int nticks, int mikado)
+{
+  if(mikado){
+    nticks = (nticks - 1) * mikado;
+    if(nticks < 1) nticks = 1;
+    double dd[3] = {(xmax - xmin) / nticks, 
+                    (ymax - ymin) / nticks, 
+                    (zmax - zmin) / nticks};
+    double axe_color[4];
+    glGetDoublev(GL_CURRENT_COLOR, axe_color);
+    for(int i = 1; i <= nticks; i++){
+      if(i % 2) glColor4dv(axe_color);
+      else glColor3f(1, 1, 1);
+      double cx[2] = {xmin + (i - 1) * dd[0], xmin + i * dd[0]};
+      double cy[2] = {ymin + (i - 1) * dd[1], ymin + i * dd[1]};
+      double cz[2] = {zmin + (i - 1) * dd[2], zmin + i * dd[2]};
+      drawCylinder(3.5, cx, cy, cz, 1);
+    }
+    glColor4dv(axe_color);
+  }
+  else{
+    glBegin(GL_LINES);
+    glVertex3d(xmin, ymin, zmin); 
+    glVertex3d(xmax, ymax, zmax);
+    glEnd();
+  }
+}
+
+void drawContext::drawAxes(int mode, int tics[3], char format[3][256],
+                           char label[3][256], double bb[6], int mikado)
+{
+  // mode 0: nothing
+  //      1: axes
+  //      2: box
+  //      3: full grid
+  //      4: open grid
+  //      5: ruler
+
+  if((mode < 1) || (bb[0] == bb[1] && bb[2] == bb[3] && bb[4] == bb[5]))
+    return;
+
+  double xmin = bb[0], xmax = bb[1];
+  double ymin = bb[2], ymax = bb[3];
+  double zmin = bb[4], zmax = bb[5];
+  double orig[3] = {xmin, ymin, zmin};
+
+  double pixelfact = pixel_equiv_x / s[0];
+
+  if(mode == 5){ // draw ruler from xyz_min to xyz_max
+    double end[3] = {xmax, ymax, zmax};
+    double dir[3] = {xmax-xmin, ymax-ymin, zmax-zmin};
+    double perp[3];
+    if((fabs(dir[0]) >= fabs(dir[1]) && fabs(dir[0]) >= fabs(dir[2])) ||
+       (fabs(dir[1]) >= fabs(dir[0]) && fabs(dir[1]) >= fabs(dir[2]))){
+      perp[0] = dir[1]; perp[1] = -dir[0]; perp[2] = 0.;
+    }
+    else{
+      perp[0] = 0.; perp[1] = dir[2]; perp[2] = -dir[1];
+    }
+    drawTics(-1, tics[0], format[0], label[0], orig, end, perp, mikado, pixelfact);
+    drawAxis(xmin, ymin, zmin, xmax, ymax, zmax, tics[0], mikado);
+    return;
+  }
+  double xx[3] = {xmax, ymin, zmin};
+  double yy[3] = {xmin, ymax, zmin};
+  double zz[3] = {xmin, ymin, zmax};
+  double dxm[3] = {0., (ymin != ymax) ? -1. : 0., (zmin != zmax) ? -1. : 0.};
+  double dym[3] = {(xmin != xmax) ? -1. : 0., 0., (zmin != zmax) ? -1. : 0.};
+  double dzm[3] = {(xmin != xmax) ? -1. : 0., (ymin != ymax) ? -1. : 0., 0.};
+  
+  int nx = (xmin != xmax) ? 
+    drawTics(0, tics[0], format[0], label[0], orig, xx, dxm, mikado, pixelfact) : 0;
+  int ny = (ymin != ymax) ? 
+    drawTics(1, tics[1], format[1], label[1], orig, yy, dym, mikado, pixelfact) : 0;
+  int nz = (zmin != zmax) ? 
+    drawTics(2, tics[2], format[2], label[2], orig, zz, dzm, mikado, pixelfact) : 0;
+
+  drawAxis(xmin, ymin, zmin, xmax, ymin, zmin, nx, mikado);
+  drawAxis(xmin, ymin, zmin, xmin, ymax, zmin, ny, mikado);
+  drawAxis(xmin, ymin, zmin, xmin, ymin, zmax, nz, mikado);
+
+  // open box
+  if(mode > 1){
+    drawAxis(xmin, ymax, zmin, xmax, ymax, zmin, nx, mikado);
+    drawAxis(xmax, ymin, zmin, xmax, ymax, zmin, ny, mikado);
+    drawAxis(xmax, ymin, zmin, xmax, ymin, zmax, nz, mikado);
+    drawAxis(xmin, ymin, zmax, xmax, ymin, zmax, nx, mikado);
+    drawAxis(xmin, ymin, zmax, xmin, ymax, zmax, ny, mikado);
+    drawAxis(xmin, ymax, zmin, xmin, ymax, zmax, nz, mikado);
+  }
+
+  // closed box
+  if(mode == 2 || mode == 3){
+    drawAxis(xmin, ymax, zmax, xmax, ymax, zmax, nx, mikado);
+    drawAxis(xmax, ymin, zmax, xmax, ymax, zmax, ny, mikado);
+    drawAxis(xmax, ymax, zmin, xmax, ymax, zmax, nz, mikado);
+  }
+  
+  if(mode > 2){
+    drawGridStipple(nx, ny, orig, xx, yy);
+    drawGridStipple(ny, nz, orig, yy, zz);
+    drawGridStipple(nx, nz, orig, xx, zz);
+  }
+
+  if(mode == 3){
+    double orig2[3] = {xmax, ymax, zmax};
+    double xy[3] = {xmax, ymax, zmin};
+    double yz[3] = {xmin, ymax, zmax};
+    double xz[3] = {xmax, ymin, zmax};
+    if(zmin != zmax) drawGridStipple(nx, ny, orig2, yz, xz);
+    if(xmin != xmax) drawGridStipple(ny, nz, orig2, xz, xy);
+    if(ymin != ymax) drawGridStipple(nx, nz, orig2, yz, xy);
+  }
+}
+
+void drawContext::drawAxes(int mode, int tics[3], char format[3][256], 
+                           char label[3][256], SBoundingBox3d &bb, int mikado)
+{
+  double bbox[6] = {bb.min().x(), bb.max().x(),
+                    bb.min().y(), bb.max().y(),
+                    bb.min().z(), bb.max().z()};
+  drawAxes(mode, tics, format, label, bbox, mikado);
+}
+
+void drawContext::drawAxes()
+{
+  bool geometryExists = false;
+  for(unsigned int i = 0; i < GModel::list.size(); i++){
+    if(!GModel::list[i]->empty()){
+      geometryExists = true;
+      break;
+    }
+  }
+    
+  if(geometryExists && (CTX.draw_bbox || !CTX.mesh.draw)) {
+    glColor4ubv((GLubyte *) & CTX.color.fg);
+    glLineWidth(CTX.line_width);
+    gl2psLineWidth(CTX.line_width * CTX.print.eps_line_width_factor);
+    drawBox(CTX.min[0], CTX.min[1], CTX.min[2], 
+            CTX.max[0], CTX.max[1], CTX.max[2]);
+    glColor3d(1.,0.,0.);
+    for(int j = 0; j < 6; j++)
+      if(CTX.geom.clip & (1 << j) || CTX.mesh.clip & (1 << j))
+        drawPlaneInBoundingBox(CTX.min[0], CTX.min[1], CTX.min[2],
+                               CTX.max[0], CTX.max[1], CTX.max[2],
+                               CTX.clip_plane[j][0], CTX.clip_plane[j][1], 
+                               CTX.clip_plane[j][2], CTX.clip_plane[j][3]);
+  }
+
+  if(CTX.axes){
+    glColor4ubv((GLubyte *) & CTX.color.axes);
+    glLineWidth(CTX.line_width);
+    gl2psLineWidth(CTX.line_width * CTX.print.eps_line_width_factor);
+    if(!CTX.axes_auto_position){
+      drawAxes(CTX.axes, CTX.axes_tics, CTX.axes_format, CTX.axes_label, 
+               CTX.axes_position, CTX.axes_mikado);
+    }
+    else if(geometryExists){
+      double bb[6] = {CTX.min[0], CTX.max[0], CTX.min[1], 
+                      CTX.max[1], CTX.min[2], CTX.max[2]};
+      drawAxes(CTX.axes, CTX.axes_tics, CTX.axes_format, CTX.axes_label, 
+               bb, CTX.axes_mikado);
+    }
+  }
+
+  if(CTX.draw_rotation_center){
+    glColor4ubv((GLubyte *) & CTX.color.fg);
+    if(CTX.rotation_center_cg)
+      drawSphere(CTX.point_size, CTX.cg[0], CTX.cg[1], CTX.cg[2], CTX.geom.light);
+    else
+      drawSphere(CTX.point_size, CTX.rotation_center[0], CTX.rotation_center[1], 
+                 CTX.rotation_center[2], CTX.geom.light);
+  }
+
+}
+
+void drawContext::drawSmallAxes()
+{
+  double l = CTX.small_axes_size;
+  double o = CTX.gl_fontsize / 5;
+
+  double cx = CTX.small_axes_pos[0];
+  double cy = CTX.small_axes_pos[1];
+  fix2dCoordinates(&cx, &cy);
+
+  double xx = l * rot[0];
+  double xy = l * rot[1];
+  double yx = l * rot[4];
+  double yy = l * rot[5];
+  double zx = l * rot[8];
+  double zy = l * rot[9];
+
+  glLineWidth(CTX.line_width);
+  gl2psLineWidth(CTX.line_width * CTX.print.eps_line_width_factor);
+  glColor4ubv((GLubyte *) & CTX.color.small_axes);
+
+  glBegin(GL_LINES);
+  glVertex2d(cx, cy);
+  glVertex2d(cx + xx, cy + xy);
+  glVertex2d(cx, cy);
+  glVertex2d(cx + yx, cy + yy);
+  glVertex2d(cx, cy);
+  glVertex2d(cx + zx, cy + zy);
+  glEnd();
+  glRasterPos2d(cx + xx + o, cy + xy + o);
+  Draw_String("X");
+  glRasterPos2d(cx + yx + o, cy + yy + o);
+  Draw_String("Y");
+  glRasterPos2d(cx + zx + o, cy + zy + o);
+  Draw_String("Z");
+}
diff --git a/Graphics/Draw.cpp b/Graphics/drawContext.cpp
similarity index 55%
rename from Graphics/Draw.cpp
rename to Graphics/drawContext.cpp
index 51e0f0652a57d3a026e54c45946d82ef2a4c8850..c9f3891092892654d3e846902cd2cf601f6c84b7 100644
--- a/Graphics/Draw.cpp
+++ b/Graphics/drawContext.cpp
@@ -7,6 +7,8 @@
 #include "GmshDefines.h"
 #include "GmshMessage.h"
 #include "Draw.h"
+#include "drawContext.h"
+#include "Trackball.h"
 #include "Context.h"
 #include "Numeric.h"
 #include "GModel.h"
@@ -15,7 +17,117 @@
 
 extern Context_T CTX;
 
-int NeedPolygonOffset()
+drawContext::drawContext(drawTransform *transform) 
+  : _transform(transform)
+{
+  // initialize from temp values in global context
+  for(int i = 0; i < 3; i++){
+    r[i] = CTX.tmp_r[i];
+    t[i] = CTX.tmp_t[i];
+    s[i] = CTX.tmp_s[i];
+  }
+  for(int i = 0; i < 4; i++){
+    quaternion[i] = CTX.tmp_quaternion[i];
+  }
+  viewport[0] = viewport[1] = 0;
+  viewport[2] = CTX.tmp_viewport[2];
+  viewport[3] = CTX.tmp_viewport[3];
+
+  vxmin = vymin = vxmax = vymax = 0.;
+  pixel_equiv_x = pixel_equiv_y = 0.;
+}
+
+void drawContext::buildRotationMatrix()
+{
+  if(CTX.useTrackball) {
+    build_rotmatrix(rot, quaternion);
+    setEulerAnglesFromRotationMatrix();
+  }
+  else {
+    double x = r[0] * M_PI / 180.;
+    double y = r[1] * M_PI / 180.;
+    double z = r[2] * M_PI / 180.;
+    double A = cos(x);
+    double B = sin(x);
+    double C = cos(y);
+    double D = sin(y);
+    double E = cos(z);
+    double F = sin(z);
+    double AD = A * D;
+    double BD = B * D;
+    rot[0] = C*E; rot[1] = BD*E+A*F; rot[2] =-AD*E+B*F; rot[3] = 0.;
+    rot[4] =-C*F; rot[5] =-BD*F+A*E; rot[6] = AD*F+B*E; rot[7] = 0.;
+    rot[8] = D;   rot[9] =-B*C;      rot[10] = A*C;     rot[11] = 0.;
+    rot[12] = 0.; rot[13] = 0.;      rot[14] = 0.;      rot[15] = 1.;
+    setQuaternionFromEulerAngles();
+  }
+}
+
+void drawContext::addQuaternion(double p1x, double p1y, double p2x, double p2y)
+{
+  double quat[4];
+  trackball(quat, p1x, p1y, p2x, p2y);
+  add_quats(quat, quaternion, quaternion);
+}
+
+void drawContext::addQuaternionFromAxisAndAngle(double axis[3], double angle)
+{
+  double a = angle * M_PI / 180.;
+  double quat[4];
+  axis_to_quat(axis, a, quat);
+  add_quats(quat, quaternion, quaternion);  
+}
+
+void drawContext::setQuaternion(double q0, double q1, double q2, double q3)
+{
+  quaternion[0] = q0;
+  quaternion[1] = q1;
+  quaternion[2] = q2;
+  quaternion[3] = q3;
+}
+
+void drawContext::setQuaternionFromEulerAngles()
+{
+  double x = r[0] * M_PI / 180.;
+  double y = r[1] * M_PI / 180.;
+  double z = r[2] * M_PI / 180.;
+  double xx[3] = {1.,0.,0.};
+  double yy[3] = {0.,1.,0.};
+  double zz[3] = {0.,0.,1.};
+  double q1[4], q2[4], q3[4], tmp[4];
+  axis_to_quat(xx, -x, q1);
+  axis_to_quat(yy, -y, q2);
+  axis_to_quat(zz, -z, q3);
+  add_quats(q1, q2, tmp);
+  add_quats(tmp, q3, quaternion);
+}
+
+void drawContext::setEulerAnglesFromRotationMatrix()
+{
+  r[1] = asin(rot[8]); // Calculate Y-axis angle
+  double C =  cos(r[1]);
+  r[1] *=  180. / M_PI;
+  if(fabs(C) > 0.005){ // Gimball lock?
+    double tmpx =  rot[10] / C; // No, so get X-axis angle
+    double tmpy = -rot[9] / C;
+    r[0] = atan2(tmpy, tmpx) * 180. / M_PI;
+    tmpx =  rot[0] / C; // Get Z-axis angle
+    tmpy = -rot[4] / C;
+    r[2] = atan2(tmpy, tmpx) * 180. / M_PI;
+  }
+  else{ // Gimball lock has occurred
+    r[0] = 0.; // Set X-axis angle to zero
+    double tmpx = rot[5]; // And calculate Z-axis angle
+    double tmpy = rot[1];
+    r[2] = atan2(tmpy, tmpx) * 180. / M_PI;
+  }
+  // return only positive angles in [0,360]
+  if(r[0] < 0.) r[0] += 360.;
+  if(r[1] < 0.) r[1] += 360.;
+  if(r[2] < 0.) r[2] += 360.;
+}
+
+static int needPolygonOffset()
 {
   GModel *m = GModel::current();
   if(m->getMeshStatus() == 2 &&
@@ -31,7 +143,7 @@ int NeedPolygonOffset()
   return 0;
 }
 
-void Draw3d()
+void drawContext::draw3d()
 {
   // We should only enable the polygon offset when there is a mix of
   // lines and polygons to be drawn; enabling it all the time can lead
@@ -45,23 +157,23 @@ void Draw3d()
   // produce a resolvable offset for a given implementation.
   glPolygonOffset(CTX.polygon_offset_factor, CTX.polygon_offset_units);
   if(CTX.polygon_offset_factor || CTX.polygon_offset_units)
-    CTX.polygon_offset = CTX.polygon_offset_always ? 1 : NeedPolygonOffset();
+    CTX.polygon_offset = CTX.polygon_offset_always ? 1 : needPolygonOffset();
   else
     CTX.polygon_offset = 0;
 
   glDepthFunc(GL_LESS);
   glEnable(GL_DEPTH_TEST);
 
-  InitProjection();
-  InitRenderModel();
-  InitPosition();
-  Draw_Axes();
-  Draw_Geom();
-  Draw_Mesh();
-  Draw_Post();
+  initProjection();
+  initRenderModel();
+  initPosition();
+  drawAxes();
+  drawGeom();
+  drawMesh();
+  drawPost();
 }
 
-void Draw2d()
+void drawContext::draw2d()
 {
   glDisable(GL_DEPTH_TEST);
   for(int i = 0; i < 6; i++)
@@ -69,79 +181,53 @@ void Draw2d()
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
-  glOrtho((double)CTX.viewport[0], (double)CTX.viewport[2],
-          (double)CTX.viewport[1], (double)CTX.viewport[3], -1., 1.);
+  glOrtho((double)viewport[0], (double)viewport[2],
+          (double)viewport[1], (double)viewport[3], -1., 1.);
   // hack to make the 2D primitives appear "in front" in GL2PS
-  glTranslated(0., 0., CTX.clip_factor > 1. ? 1./CTX.clip_factor : CTX.clip_factor);
+  glTranslated(0., 0., CTX.clip_factor > 1. ? 1. / CTX.clip_factor : CTX.clip_factor);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
 
-  Draw_Graph2D();
-  Draw_Text2D();
+  drawGraph2d();
+  drawText2d();
   Draw_OnScreenMessages();
-  if(CTX.post.draw) Draw_Scales();
-
+  if(CTX.post.draw) 
+    drawScales();
   if(CTX.small_axes)
-    Draw_SmallAxes();
+    drawSmallAxes();
 }
 
-void DrawPlugin(void (*draw)())
-{
-  CTX.post.plugin_draw_function = draw;
-  int old = CTX.draw_bbox;
-  CTX.draw_bbox = 1;
-  if(CTX.fast_redraw){
-    CTX.post.draw = 0;
-    CTX.mesh.draw = 0;
-  }
-  if(!CTX.batch) 
-    Draw();
-  // this is reset in each plugin run/cancel callback:
-  // CTX.post.plugin_draw_function = NULL;
-  CTX.draw_bbox = old;
-  CTX.post.draw = 1;
-  CTX.mesh.draw = 1;
-}
-
-void ClearOpengl()
-{
-  glClearColor(CTX.UNPACK_RED(CTX.color.bg) / 255.,
-               CTX.UNPACK_GREEN(CTX.color.bg) / 255.,
-               CTX.UNPACK_BLUE(CTX.color.bg) / 255., 0.);
-  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
-}
-
-void InitProjection(int xpick, int ypick, int wpick, int hpick)
+void drawContext::initProjection(int xpick, int ypick, int wpick, int hpick)
 {
   double Va = 
-    (GLdouble) (CTX.viewport[3] - CTX.viewport[1]) /
-    (GLdouble) (CTX.viewport[2] - CTX.viewport[0]);
+    (GLdouble) (viewport[3] - viewport[1]) /
+    (GLdouble) (viewport[2] - viewport[0]);
   double Wa = (CTX.max[1] - CTX.min[1]) / (CTX.max[0] - CTX.min[0]);
 
   // compute the viewport in World coordinates (with margins)
   if(Va > Wa) {
-    CTX.vxmin = CTX.min[0];
-    CTX.vxmax = CTX.max[0];
-    CTX.vymin = 0.5 * (CTX.min[1] + CTX.max[1] - Va * (CTX.max[0] - CTX.min[0]));
-    CTX.vymax = 0.5 * (CTX.min[1] + CTX.max[1] + Va * (CTX.max[0] - CTX.min[0]));
+    vxmin = CTX.min[0];
+    vxmax = CTX.max[0];
+    vymin = 0.5 * (CTX.min[1] + CTX.max[1] - Va * (CTX.max[0] - CTX.min[0]));
+    vymax = 0.5 * (CTX.min[1] + CTX.max[1] + Va * (CTX.max[0] - CTX.min[0]));
   }
   else {
-    CTX.vxmin = 0.5 * (CTX.min[0] + CTX.max[0] - (CTX.max[1] - CTX.min[1]) / Va);
-    CTX.vxmax = 0.5 * (CTX.min[0] + CTX.max[0] + (CTX.max[1] - CTX.min[1]) / Va);
-    CTX.vymin = CTX.min[1];
-    CTX.vymax = CTX.max[1];
+    vxmin = 0.5 * (CTX.min[0] + CTX.max[0] - (CTX.max[1] - CTX.min[1]) / Va);
+    vxmax = 0.5 * (CTX.min[0] + CTX.max[0] + (CTX.max[1] - CTX.min[1]) / Va);
+    vymin = CTX.min[1];
+    vymax = CTX.max[1];
   }
-  CTX.vxmin -= (CTX.vxmax - CTX.vxmin) / 3.;
-  CTX.vxmax += 0.25 * (CTX.vxmax - CTX.vxmin);
-  CTX.vymin -= (CTX.vymax - CTX.vymin) / 3.;
-  CTX.vymax += 0.25 * (CTX.vymax - CTX.vymin);
+  vxmin -= (vxmax - vxmin) / 3.;
+  vxmax += 0.25 * (vxmax - vxmin);
+  vymin -= (vymax - vymin) / 3.;
+  vymax += 0.25 * (vymax - vymin);
 
   // store what one pixel represents in world coordinates
-  CTX.pixel_equiv_x = (CTX.vxmax - CTX.vxmin) / (CTX.viewport[2] - CTX.viewport[0]);
-  CTX.pixel_equiv_y = (CTX.vymax - CTX.vymin) / (CTX.viewport[3] - CTX.viewport[1]);
+  pixel_equiv_x = (vxmax - vxmin) / (viewport[2] - viewport[0]);
+  pixel_equiv_y = (vymax - vymin) / (viewport[3] - viewport[1]);
 
   // no initial translation of the model
-  CTX.t_init[0] = CTX.t_init[1] = CTX.t_init[2] = 0.;
+  t_init[0] = t_init[1] = t_init[2] = 0.;
 
   // setup ortho or perspective projection matrix
   glMatrixMode(GL_PROJECTION);
@@ -149,8 +235,8 @@ void InitProjection(int xpick, int ypick, int wpick, int hpick)
 
   // restrict picking to a rectangular region around xpick,ypick in SELECT mode
   if(CTX.render_mode == GMSH_SELECT)
-    gluPickMatrix((GLdouble)xpick, (GLdouble)(CTX.viewport[3] - ypick),
-                  (GLdouble)wpick, (GLdouble)hpick, (GLint *)CTX.viewport);
+    gluPickMatrix((GLdouble)xpick, (GLdouble)(viewport[3] - ypick),
+                  (GLdouble)wpick, (GLdouble)hpick, (GLint *)viewport);
 
   double grad_z, grad_xy;
   double zmax = std::max(fabs(CTX.min[2]), fabs(CTX.max[2]));
@@ -161,8 +247,8 @@ void InitProjection(int xpick, int ypick, int wpick, int hpick)
     // large enough to manipulate the model and zoom, but not too big
     // (the z-buffer resolution, e.g., on software Mesa can become
     // insufficient)
-    double clip = zmax * CTX.s[2] * CTX.clip_factor;
-    glOrtho(CTX.vxmin, CTX.vxmax, CTX.vymin, CTX.vymax, -clip, clip);
+    double clip = zmax * s[2] * CTX.clip_factor;
+    glOrtho(vxmin, vxmax, vymin, vymax, -clip, clip);
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
     grad_z = 0.99 * clip;
@@ -175,16 +261,16 @@ void InitProjection(int xpick, int ypick, int wpick, int hpick)
     // recenter the model such that the perspective is always at the
     // center of gravity (we should maybe add an option to choose
     // this, as we do for the rotation center)
-    CTX.t_init[0] = CTX.cg[0];
-    CTX.t_init[1] = CTX.cg[1];
-    CTX.vxmin -= CTX.t_init[0];
-    CTX.vxmax -= CTX.t_init[0];
-    CTX.vymin -= CTX.t_init[1];
-    CTX.vymax -= CTX.t_init[1];
-    glFrustum(CTX.vxmin, CTX.vxmax, CTX.vymin, CTX.vymax, clip_near, clip_far);
+    t_init[0] = CTX.cg[0];
+    t_init[1] = CTX.cg[1];
+    vxmin -= t_init[0];
+    vxmax -= t_init[0];
+    vymin -= t_init[1];
+    vymax -= t_init[1];
+    glFrustum(vxmin, vxmax, vymin, vymax, clip_near, clip_far);
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
-    glTranslated(-coef * CTX.t_init[0], -coef * CTX.t_init[1], -coef * clip_near);
+    glTranslated(-coef * t_init[0], -coef * t_init[1], -coef * clip_near);
     glScaled(coef, coef, coef);
     grad_z = 0.99 * clip_far;
     grad_xy = clip_far / clip_near;
@@ -198,27 +284,27 @@ void InitProjection(int xpick, int ypick, int wpick, int hpick)
     if(CTX.bg_gradient == 1){ // vertical
       glBegin(GL_QUADS);
       glColor4ubv((GLubyte *) & CTX.color.bg);
-      glVertex3d(grad_xy * CTX.vxmin, grad_xy * CTX.vymin, 0.);
-      glVertex3d(grad_xy * CTX.vxmax, grad_xy * CTX.vymin, 0.);
+      glVertex3d(grad_xy * vxmin, grad_xy * vymin, 0.);
+      glVertex3d(grad_xy * vxmax, grad_xy * vymin, 0.);
       glColor4ubv((GLubyte *) & CTX.color.bg_grad);
-      glVertex3d(grad_xy * CTX.vxmax, grad_xy * CTX.vymax, 0.);
-      glVertex3d(grad_xy * CTX.vxmin, grad_xy * CTX.vymax, 0.);
+      glVertex3d(grad_xy * vxmax, grad_xy * vymax, 0.);
+      glVertex3d(grad_xy * vxmin, grad_xy * vymax, 0.);
       glEnd();
     }
     else if(CTX.bg_gradient == 2){ // horizontal
       glBegin(GL_QUADS);
       glColor4ubv((GLubyte *) & CTX.color.bg);
-      glVertex3d(grad_xy * CTX.vxmax, grad_xy * CTX.vymin, 0.);
-      glVertex3d(grad_xy * CTX.vxmax, grad_xy * CTX.vymax, 0.);
+      glVertex3d(grad_xy * vxmax, grad_xy * vymin, 0.);
+      glVertex3d(grad_xy * vxmax, grad_xy * vymax, 0.);
       glColor4ubv((GLubyte *) & CTX.color.bg_grad);
-      glVertex3d(grad_xy * CTX.vxmin, grad_xy * CTX.vymax, 0.);
-      glVertex3d(grad_xy * CTX.vxmin, grad_xy * CTX.vymin, 0.);
+      glVertex3d(grad_xy * vxmin, grad_xy * vymax, 0.);
+      glVertex3d(grad_xy * vxmin, grad_xy * vymin, 0.);
       glEnd();
     }
     else{ // radial
-      double cx = grad_xy * (CTX.vxmin + CTX.vxmax) / 2.;
-      double cy = grad_xy * (CTX.vymin + CTX.vymax) / 2.;
-      double r = grad_xy * std::max(CTX.vxmax - CTX.vxmin, CTX.vymax - CTX.vymin) / 2.;
+      double cx = grad_xy * (vxmin + vxmax) / 2.;
+      double cy = grad_xy * (vymin + vymax) / 2.;
+      double r = grad_xy * std::max(vxmax - vxmin, vymax - vymin) / 2.;
       glBegin(GL_TRIANGLE_FAN);
       glColor4ubv((GLubyte *) & CTX.color.bg_grad);
       glVertex3d(cx, cy, 0.);
@@ -235,14 +321,12 @@ void InitProjection(int xpick, int ypick, int wpick, int hpick)
   }
 }
 
-void InitRenderModel()
+void drawContext::initRenderModel()
 {
-  GLfloat r, g, b;
-
   glPushMatrix();
   glLoadIdentity();
-  glScaled(CTX.s[0], CTX.s[1], CTX.s[2]);
-  glTranslated(CTX.t[0], CTX.t[1], CTX.t[2]);
+  glScaled(s[0], s[1], s[2]);
+  glTranslated(t[0], t[1], t[2]);
   
   for(int i = 0; i < 6; i++) {
     if(CTX.light[i]) {
@@ -252,9 +336,9 @@ void InitRenderModel()
                              (GLfloat)CTX.light_position[i][3]};
       glLightfv((GLenum)(GL_LIGHT0 + i), GL_POSITION, position);
 
-      r = CTX.UNPACK_RED(CTX.color.ambient_light[i])/255.;
-      g = CTX.UNPACK_GREEN(CTX.color.ambient_light[i])/255.;
-      b = CTX.UNPACK_BLUE(CTX.color.ambient_light[i])/255.;
+      GLfloat r = CTX.UNPACK_RED(CTX.color.ambient_light[i])/255.;
+      GLfloat g = CTX.UNPACK_GREEN(CTX.color.ambient_light[i])/255.;
+      GLfloat b = CTX.UNPACK_BLUE(CTX.color.ambient_light[i])/255.;
       GLfloat ambient[4] = {r, g, b, 1.0};
       glLightfv((GLenum)(GL_LIGHT0 + i), GL_AMBIENT, ambient);
 
@@ -303,10 +387,10 @@ void InitRenderModel()
   glDisable(GL_LIGHTING);
 }
 
-void InitPosition()
+void drawContext::initPosition()
 {
-  glScaled(CTX.s[0], CTX.s[1], CTX.s[2]);
-  glTranslated(CTX.t[0], CTX.t[1], CTX.t[2]);
+  glScaled(s[0], s[1], s[2]);
+  glTranslated(t[0], t[1], t[2]);
 
   if(CTX.rotation_center_cg)
     glTranslated(CTX.cg[0], CTX.cg[1], CTX.cg[2]);
@@ -315,8 +399,8 @@ void InitPosition()
                  CTX.rotation_center[1],
                  CTX.rotation_center[2]);
   
-  CTX.buildRotationMatrix();
-  glMultMatrixd(CTX.rot);
+  buildRotationMatrix();
+  glMultMatrixd(rot);
 
   if(CTX.rotation_center_cg)
     glTranslated(-CTX.cg[0], -CTX.cg[1], -CTX.cg[2]);
@@ -328,8 +412,8 @@ void InitPosition()
   // store the projection and modelview matrices at this precise
   // moment (so that we can use them at any later time, even if the
   // context has changed, i.e., even if we are out of Draw())
-  glGetDoublev(GL_PROJECTION_MATRIX, CTX.proj);
-  glGetDoublev(GL_MODELVIEW_MATRIX, CTX.model);
+  glGetDoublev(GL_PROJECTION_MATRIX, proj);
+  glGetDoublev(GL_MODELVIEW_MATRIX, model);
 
   for(int i = 0; i < 6; i++)
     glClipPlane((GLenum)(GL_CLIP_PLANE0 + i), CTX.clip_plane[i]);
@@ -338,22 +422,21 @@ void InitPosition()
 // Takes a cursor position in window coordinates and returns the line
 // (given by a point and a unit direction vector), in real space, that
 // corresponds to that cursor position
-
-void Unproject(double x, double y, double p[3], double d[3])
+void drawContext::unproject(double x, double y, double p[3], double d[3])
 {
-  GLint viewport[4];
-  glGetIntegerv(GL_VIEWPORT, viewport);
+  GLint vp[4];
+  glGetIntegerv(GL_VIEWPORT, vp);
 
-  y = viewport[3]-y;
+  y = vp[3] - y;
 
   GLdouble x0, y0, z0, x1, y1, z1;
 
-  // we use CTX.model and CTX.proj instead of directly getGetDouble'ing
-  // the matrices since unproject can be called in or after Draw2D
-  
-  if(!gluUnProject(x, y, 0.0, CTX.model, CTX.proj, viewport, &x0, &y0, &z0))
+  // we use the stored model and proj matrices instead of directly
+  // getGetDouble'ing the matrices since unproject can be called in or
+  // after draw2d
+  if(!gluUnProject(x, y, 0.0, model, proj, vp, &x0, &y0, &z0))
     Msg::Warning("unproject1 failed");
-  if(!gluUnProject(x, y, 1.0, CTX.model, CTX.proj, viewport, &x1, &y1, &z1))
+  if(!gluUnProject(x, y, 1.0, model, proj, vp, &x1, &y1, &z1))
     Msg::Warning("unproject2 failed");
   
   p[0] = x0;
@@ -367,23 +450,3 @@ void Unproject(double x, double y, double p[3], double d[3])
   d[1] /= len;
   d[2] /= len;
 }
-
-void Viewport2World(double win[3], double xyz[3])
-{
-  GLint viewport[4];
-  GLdouble model[16], proj[16];
-  glGetIntegerv(GL_VIEWPORT, viewport);
-  glGetDoublev(GL_PROJECTION_MATRIX, proj);
-  glGetDoublev(GL_MODELVIEW_MATRIX, model);
-  gluUnProject(win[0], win[1], win[2], model, proj, viewport, &xyz[0], &xyz[1], &xyz[2]);
-}
-
-void World2Viewport(double xyz[3], double win[3])
-{
-  GLint viewport[4];
-  GLdouble model[16], proj[16];
-  glGetIntegerv(GL_VIEWPORT, viewport);
-  glGetDoublev(GL_PROJECTION_MATRIX, proj);
-  glGetDoublev(GL_MODELVIEW_MATRIX, model);
-  gluProject(xyz[0], xyz[1], xyz[2], model, proj, viewport, &win[0], &win[1], &win[2]);
-}
diff --git a/Graphics/drawContext.h b/Graphics/drawContext.h
new file mode 100644
index 0000000000000000000000000000000000000000..294a981f15cfd0395b63f5bed8fcea56a091c771
--- /dev/null
+++ b/Graphics/drawContext.h
@@ -0,0 +1,128 @@
+// Gmsh - Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#ifndef _DRAW_CONTEXT_H_
+#define _DRAW_CONTEXT_H_
+
+#include "SBoundingBox3d.h"
+
+class drawTransform {
+ public:
+  drawTransform(){}
+  virtual ~drawTransform(){}
+  virtual void transform(double &x, double &y, double &z){}
+};
+
+class drawTransformScaled : public drawTransform {
+ private:
+  bool _identityTransform;
+  double _mat[3][3];
+ public:
+  drawTransformScaled(double mat[3][3]) : drawTransform()
+  {
+    if(mat[0][0] != 1. || mat[0][1] != 0. || mat[0][2] != 0. ||
+       mat[1][0] != 0. || mat[1][1] != 1. || mat[1][2] != 0. ||
+       mat[2][0] != 0. || mat[2][1] != 0. || mat[2][2] != 1.)
+      _identityTransform = false;
+    else
+      _identityTransform = true;
+    for(int i = 0; i < 3; i++)
+      for(int j = 0; j < 3; j++)
+        _mat[i][j] = mat[i][j];
+  }
+  virtual void transform(double &x, double &y, double &z)
+  {
+    if(_identityTransform) return;
+    double xyz[3] = {x, y, z};
+    x = y = z = 0.;
+    for(int k = 0; k < 3; k++){
+      x += _mat[0][k] * xyz[k];
+      y += _mat[1][k] * xyz[k];
+      z += _mat[2][k] * xyz[k];
+    }
+  }
+};
+
+class drawContext {
+ private:
+  drawTransform *_transform;
+ public:
+
+  double r[3]; // current Euler angles (in degrees!) 
+  double t[3], s[3]; // current translation and scale 
+  double quaternion[4]; // current quaternion used for "trackball" rotation
+  int viewport[4]; // current viewport 
+
+  double rot[16]; // current rotation matrix 
+  double t_init[3]; // initial translation before applying modelview transform
+  double vxmin, vxmax, vymin, vymax; // current viewport in real coordinates 
+  double pixel_equiv_x, pixel_equiv_y; // approx equiv model length of a pixel 
+  double model[16], proj[16]; // the modelview and projection matrix as they were
+                              // at the time of the last InitPosition() call
+
+  drawContext(drawTransform *transform=0);
+  virtual ~drawContext(){}
+  void setTransform(drawTransform *transform){ _transform = transform; }
+  drawTransform *getTransform(){ return _transform; }
+  void transform(double &x, double &y, double &z)
+  {
+    if(_transform) _transform->transform(x, y, z); 
+  }
+
+  // trackball functions 
+  void buildRotationMatrix();
+  void setQuaternion(double p1x, double p1y, double p2x, double p2y);
+  void addQuaternion(double p1x, double p1y, double p2x, double p2y);
+  void addQuaternionFromAxisAndAngle(double axis[3], double angle);
+  void setQuaternionFromEulerAngles();
+  void setEulerAnglesFromRotationMatrix();
+
+  void initProjection(int xpick=0, int ypick=0, int wpick=0, int hpick=0);
+  void initRenderModel();
+  void initPosition();
+  void unproject(double x, double y, double p[3], double d[3]);
+  int fix2dCoordinates(double *x, double *y);
+
+  void draw3d();
+  void draw2d();
+
+  void drawGeom();
+  void drawMesh();
+  void drawPost();
+
+  void drawText2d();
+  void drawGraph2d();
+
+  void drawAxis(double xmin, double ymin, double zmin,
+                double xmax, double ymax, double zmax, 
+                int nticks, int mikado);
+  void drawAxes(int mode, int tics[3], char format[3][256],
+                char label[3][256], double bb[6], int mikado);
+  void drawAxes(int mode, int tics[3], char format[3][256], 
+                char label[3][256], SBoundingBox3d &bb, int mikado);
+  void drawAxes();
+  void drawSmallAxes();
+
+  void drawScales();
+
+  void drawSphere(double size, double x, double y, double z, int light);
+  void drawCylinder(double width, double *x, double *y, double *z, int light);
+  void drawTaperedCylinder(double width, double val1, double val2, 
+                           double ValMin, double ValMax, 
+                           double *x, double *y, double *z, int light);
+  void drawVector(int Type, int Fill,
+                  double relHeadRadius, double relStemLength,
+                  double relStemRadius, double x, double y, double z,
+                  double dx, double dy, double dz, int light);
+  void drawBox(double xmin, double ymin, double zmin,
+               double xmax, double ymax, double zmax,
+               bool labels=true);
+  void drawPlaneInBoundingBox(double xmin, double ymin, double zmin,
+                              double xmax, double ymax, double zmax,
+                              double a, double b, double c, double d,
+                              int shade=0);
+};
+
+#endif
diff --git a/Graphics/Geom.cpp b/Graphics/drawGeom.cpp
similarity index 76%
rename from Graphics/Geom.cpp
rename to Graphics/drawGeom.cpp
index 4866ad7ef2492b2b344591bc7ecb235a1fdd606c..689e31da6af79f191605bad60e496eac02743f01 100644
--- a/Graphics/Geom.cpp
+++ b/Graphics/drawGeom.cpp
@@ -3,7 +3,9 @@
 // See the LICENSE.txt file for license information. Please report all
 // bugs and problems to <gmsh@geuz.org>.
 
+#include "drawContext.h"
 #include "GmshUI.h"
+#include "GmshDefines.h"
 #include "Draw.h"
 #include "Context.h"
 #include "gl2ps.h"
@@ -13,59 +15,11 @@
 
 extern Context_T CTX;
 
-class visContext{
- public:
-  visContext(){}
-  virtual ~visContext(){}
-  virtual void transform(double &x, double &y, double &z){}
-};
-
-class visContextScaled : public visContext {
- private:
-  bool _identityTransform;
-  double _mat[3][3];
- public:
-  visContextScaled(double mat[3][3]) : visContext()
-  {
-    if(mat[0][0] != 1. || mat[0][1] != 0. || mat[0][2] != 0. ||
-       mat[1][0] != 0. || mat[1][1] != 1. || mat[1][2] != 0. ||
-       mat[2][0] != 0. || mat[2][1] != 0. || mat[2][2] != 1.)
-      _identityTransform = false;
-    else
-      _identityTransform = true;
-    for(int i = 0; i < 3; i++)
-      for(int j = 0; j < 3; j++)
-        _mat[i][j] = mat[i][j];
-  }
-  virtual void transform(double &x, double &y, double &z)
-  {
-    if(_identityTransform) return;
-    double xyz[3] = {x, y, z};
-    x = y = z = 0.;
-    for(int k = 0; k < 3; k++){
-      x += _mat[0][k] * xyz[k];
-      y += _mat[1][k] * xyz[k];
-      z += _mat[2][k] * xyz[k];
-    }
-  }
-};
-
-static void drawBBox(GEntity *e)
-{
-  return;
-  glColor4ubv((GLubyte *) & CTX.color.fg);
-  glLineWidth(CTX.line_width);
-  gl2psLineWidth(CTX.line_width * CTX.print.eps_line_width_factor);
-  SBoundingBox3d bb = e->bounds();
-  Draw_Box(bb.min().x(), bb.min().y(), bb.min().z(),
-           bb.max().x(), bb.max().y(), bb.max().z());
-}
-
 class drawGVertex {
  private :
-  visContext *_ctx;
+  drawContext *_ctx;
  public :
-  drawGVertex(visContext *ctx) : _ctx(ctx){}
+  drawGVertex(drawContext *ctx) : _ctx(ctx){}
   void operator () (GVertex *v)
   {
     if(!v->getVisibility()) return;
@@ -102,9 +56,9 @@ class drawGVertex {
     if(CTX.geom.points) {
       if(CTX.geom.point_type > 0) {
         if(v->getSelection())
-          Draw_Sphere(CTX.geom.point_sel_size, x, y, z, CTX.geom.light);
+          _ctx->drawSphere(CTX.geom.point_sel_size, x, y, z, CTX.geom.light);
         else
-          Draw_Sphere(CTX.geom.point_size, x, y, z, CTX.geom.light);
+          _ctx->drawSphere(CTX.geom.point_size, x, y, z, CTX.geom.light);
       }
       else {
         glBegin(GL_POINTS);
@@ -117,10 +71,10 @@ class drawGVertex {
       char Num[100];
       sprintf(Num, "%d", v->tag());
       double offset = (0.5 * CTX.geom.point_size + 0.3 * CTX.gl_fontsize) * 
-        CTX.pixel_equiv_x;
-      glRasterPos3d(x + offset / CTX.s[0],
-                    y + offset / CTX.s[1],
-                    z + offset / CTX.s[2]);
+        _ctx->pixel_equiv_x;
+      glRasterPos3d(x + offset / _ctx->s[0],
+                    y + offset / _ctx->s[1],
+                    z + offset / _ctx->s[2]);
       Draw_String(Num);
     }
     
@@ -133,9 +87,9 @@ class drawGVertex {
 
 class drawGEdge {
  private :
-  visContext *_ctx;
+  drawContext *_ctx;
  public :
-  drawGEdge(visContext *ctx) : _ctx(ctx){}
+  drawGEdge(drawContext *ctx) : _ctx(ctx){}
   void operator () (GEdge *e)
   {
     if(!e->getVisibility()) return;
@@ -184,8 +138,8 @@ class drawGEdge {
           double z[2] = {p1.z(), p2.z()};
           _ctx->transform(x[0], y[0], z[0]);
           _ctx->transform(x[1], y[1], z[1]);
-          Draw_Cylinder(e->getSelection() ? CTX.geom.line_sel_width : 
-                        CTX.geom.line_width, x, y, z, CTX.geom.light);
+          _ctx->drawCylinder(e->getSelection() ? CTX.geom.line_sel_width : 
+                             CTX.geom.line_width, x, y, z, CTX.geom.light);
         }
       }
       else {
@@ -206,12 +160,12 @@ class drawGEdge {
       char Num[100];
       sprintf(Num, "%d", e->tag());
       double offset = (0.5 * CTX.geom.line_width + 0.3 * CTX.gl_fontsize) *
-        CTX.pixel_equiv_x;
+        _ctx->pixel_equiv_x;
       double x = p.x(), y = p.y(), z = p.z();
       _ctx->transform(x, y, z);
-      glRasterPos3d(x + offset / CTX.s[0],
-                    y + offset / CTX.s[1],
-                    z + offset / CTX.s[2]);
+      glRasterPos3d(x + offset / _ctx->s[0],
+                    y + offset / _ctx->s[1],
+                    z + offset / _ctx->s[2]);
       Draw_String(Num);
     }
     
@@ -221,18 +175,16 @@ class drawGEdge {
       SVector3 der = e->firstDer(t);
       der.normalize();
       for(int i = 0; i < 3; i++)
-        der[i] *= CTX.geom.tangents * CTX.pixel_equiv_x / CTX.s[i];
+        der[i] *= CTX.geom.tangents * _ctx->pixel_equiv_x / _ctx->s[i];
       glColor4ubv((GLubyte *) & CTX.color.geom.tangents);
       double x = p.x(), y = p.y(), z = p.z();
       _ctx->transform(x, y, z);
       // FIXME: transform the tangent
-      Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
-                  CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius,
-                  x, y, z, der[0], der[1], der[2], CTX.geom.light);
+      _ctx->drawVector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
+                       CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius,
+                       x, y, z, der[0], der[1], der[2], CTX.geom.light);
     }
 
-    if(CTX.draw_bbox) drawBBox(e);
-    
     if(select) {
       glPopName();
       glPopName();
@@ -242,7 +194,7 @@ class drawGEdge {
 
 class drawGFace {
  private:
-  visContext *_ctx;
+  drawContext *_ctx;
   void _drawVertexArray(VertexArray *va, bool useNormalArray, int forceColor=0, 
                         unsigned int color=0)
   {
@@ -325,12 +277,12 @@ class drawGFace {
       GPoint p = f->point(uav, vav);
       char Num[100];
       sprintf(Num, "%d", f->tag());
-      double offset = 0.3 * CTX.gl_fontsize * CTX.pixel_equiv_x;
+      double offset = 0.3 * CTX.gl_fontsize * _ctx->pixel_equiv_x;
       double x = p.x(), y = p.y(), z = p.z();
       _ctx->transform(x, y, z);
-      glRasterPos3d(x + offset / CTX.s[0],
-                    y + offset / CTX.s[1],
-                    z + offset / CTX.s[2]);
+      glRasterPos3d(x + offset / _ctx->s[0],
+                    y + offset / _ctx->s[1],
+                    z + offset / _ctx->s[2]);
       Draw_String(Num);
     }
     
@@ -338,14 +290,14 @@ class drawGFace {
       GPoint p = f->point(uav, vav);
       SVector3 n = f->normal(SPoint2(uav, vav));
       for(int i = 0; i < 3; i++)
-        n[i] *= CTX.geom.normals * CTX.pixel_equiv_x / CTX.s[i];
+        n[i] *= CTX.geom.normals * _ctx->pixel_equiv_x / _ctx->s[i];
       glColor4ubv((GLubyte *) & CTX.color.geom.normals);
       double x = p.x(), y = p.y(), z = p.z();
       _ctx->transform(x, y, z);
       // FIXME: transform the normal
-      Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
-                  CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius,
-                  x, y, z, n[0], n[1], n[2], CTX.geom.light);
+      _ctx->drawVector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
+                       CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius,
+                       x, y, z, n[0], n[1], n[2], CTX.geom.light);
     }
   }
   void _drawPlaneGFace(GFace *f)
@@ -390,14 +342,14 @@ class drawGFace {
     if(CTX.geom.surfaces_num) {
       char Num[100];
       sprintf(Num, "%d", f->tag());
-      double offset = 0.3 * CTX.gl_fontsize * CTX.pixel_equiv_x;
+      double offset = 0.3 * CTX.gl_fontsize * _ctx->pixel_equiv_x;
       double x = 0.5 * (f->cross[0].x() + f->cross[1].x());
       double y = 0.5 * (f->cross[0].y() + f->cross[1].y());
       double z = 0.5 * (f->cross[0].z() + f->cross[1].z());
       _ctx->transform(x, y, z);
-      glRasterPos3d(x + offset / CTX.s[0],
-                    y + offset / CTX.s[0],
-                    z + offset / CTX.s[0]);
+      glRasterPos3d(x + offset / _ctx->s[0],
+                    y + offset / _ctx->s[0],
+                    z + offset / _ctx->s[0]);
       Draw_String(Num);
     }
 
@@ -408,19 +360,19 @@ class drawGFace {
       SPoint2 uv = f->parFromPoint(p);
       SVector3 n = f->normal(uv);
       for(int i = 0; i < 3; i++)
-        n[i] *= CTX.geom.normals * CTX.pixel_equiv_x / CTX.s[i];
+        n[i] *= CTX.geom.normals * _ctx->pixel_equiv_x / _ctx->s[i];
       glColor4ubv((GLubyte *) & CTX.color.geom.normals);
       double x = p.x(), y = p.y(), z = p.z();
       _ctx->transform(x, y, z);
       // FIXME: transform the normal
-      Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
-                  CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius, 
-                  x, y, z, n[0], n[1], n[2], CTX.geom.light);
+      _ctx->drawVector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
+                       CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius, 
+                       x, y, z, n[0], n[1], n[2], CTX.geom.light);
     }
   }
  
  public :
-  drawGFace(visContext *ctx) : _ctx(ctx) {}
+  drawGFace(drawContext *ctx) : _ctx(ctx) {}
   void operator () (GFace *f)
   {
     if(!f->getVisibility()) return;
@@ -450,8 +402,6 @@ class drawGFace {
     else
       _drawParametricGFace(f);
     
-    if(CTX.draw_bbox) drawBBox(f);
-    
     if(select) {
       glPopName();
       glPopName();
@@ -461,9 +411,9 @@ class drawGFace {
 
 class drawGRegion {
  private :
-  visContext *_ctx;
+  drawContext *_ctx;
  public :
-  drawGRegion(visContext *ctx) : _ctx(ctx){}
+  drawGRegion(drawContext *ctx) : _ctx(ctx){}
   void operator () (GRegion *r)
   {
     if(!r->getVisibility()) return;
@@ -487,20 +437,18 @@ class drawGRegion {
     _ctx->transform(x, y, z);
 
     if(CTX.geom.volumes)
-      Draw_Sphere(size, x, y, z, CTX.geom.light);
+      _ctx->drawSphere(size, x, y, z, CTX.geom.light);
 
     if(CTX.geom.volumes_num){
       char Num[100];
       sprintf(Num, "%d", r->tag());
-      double offset = (0.5 * size + 0.3 * CTX.gl_fontsize) * CTX.pixel_equiv_x;
-      glRasterPos3d(x + offset / CTX.s[0],
-                    y + offset / CTX.s[1],
-                    z + offset / CTX.s[2]);
+      double offset = (0.5 * size + 0.3 * CTX.gl_fontsize) * _ctx->pixel_equiv_x;
+      glRasterPos3d(x + offset / _ctx->s[0],
+                    y + offset / _ctx->s[1],
+                    z + offset / _ctx->s[2]);
       Draw_String(Num);
     }
 
-    if(CTX.draw_bbox) drawBBox(r);
-
     if(select) {
       glPopName();
       glPopName();
@@ -508,7 +456,7 @@ class drawGRegion {
   }
 };
 
-void Draw_Geom()
+void drawContext::drawGeom()
 {
   if(!CTX.geom.draw) return;
 
@@ -523,21 +471,17 @@ void Draw_Geom()
     else
       glDisable((GLenum)(GL_CLIP_PLANE0 + i));
 
-  visContext ctx;
-  //double mat[3][3] = {{2, 0, 0}, {0, 1, 0}, {0, 0, 1}};
-  //visContextScaled ctx(mat);
-
   for(unsigned int i = 0; i < GModel::list.size(); i++){
     GModel *m = GModel::list[i];
     if(CTX.draw_all_models || m == GModel::current()){
       if(CTX.geom.points || CTX.geom.points_num)
-        std::for_each(m->firstVertex(), m->lastVertex(), drawGVertex(&ctx));
+        std::for_each(m->firstVertex(), m->lastVertex(), drawGVertex(this));
       if(CTX.geom.lines || CTX.geom.lines_num || CTX.geom.tangents)
-        std::for_each(m->firstEdge(), m->lastEdge(), drawGEdge(&ctx));
+        std::for_each(m->firstEdge(), m->lastEdge(), drawGEdge(this));
       if(CTX.geom.surfaces || CTX.geom.surfaces_num || CTX.geom.normals)
-        std::for_each(m->firstFace(), m->lastFace(), drawGFace(&ctx));
+        std::for_each(m->firstFace(), m->lastFace(), drawGFace(this));
       if(CTX.geom.volumes || CTX.geom.volumes_num)
-        std::for_each(m->firstRegion(), m->lastRegion(), drawGRegion(&ctx));
+        std::for_each(m->firstRegion(), m->lastRegion(), drawGRegion(this));
     }
   }
   
diff --git a/Graphics/drawGlyph.cpp b/Graphics/drawGlyph.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fb8a19f7ed96d1bdc9b92a779d9434c5448bd381
--- /dev/null
+++ b/Graphics/drawGlyph.cpp
@@ -0,0 +1,556 @@
+// Gmsh - Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#include <string.h>
+#include "drawContext.h"
+#include "GmshUI.h"
+#include "Numeric.h"
+#include "Draw.h"
+#include "Context.h"
+#include "gl2ps.h"
+
+extern Context_T CTX;
+
+void drawContext::drawSphere(double size, double x, double y, double z, int light)
+{
+  if(light) glEnable(GL_LIGHTING);
+
+  static int first = 1;
+  static GLUquadricObj *qua;
+
+  if(first){
+    first = 0;
+    qua = gluNewQuadric();
+  }
+
+  glPushMatrix();
+  glTranslated(x, y, z);
+  double ss = size * pixel_equiv_x / s[0]; // size is in pixels
+  glScaled(ss, ss, ss);
+  gluSphere(qua, 1, CTX.quadric_subdivisions, CTX.quadric_subdivisions);
+  glPopMatrix();
+  glDisable(GL_LIGHTING);
+}
+
+void drawContext::drawTaperedCylinder(double width, double val1, double val2, 
+                                      double ValMin, double ValMax, 
+                                      double *x, double *y, double *z, int light)
+{
+  if(light) glEnable(GL_LIGHTING);
+
+  static int first = 1;
+  static GLUquadricObj *qua;
+
+  if(first){
+    first = 0;
+    qua = gluNewQuadric();
+  }
+
+  double dx = x[1] - x[0];
+  double dy = y[1] - y[0];
+  double dz = z[1] - z[0];
+  double length = sqrt(dx * dx + dy * dy + dz * dz);
+  double fact = (ValMax - ValMin) * pixel_equiv_x / s[0];
+  double radius1 = width * (val1 - ValMin) / fact;
+  double radius2 = width * (val2 - ValMin) / fact;
+  double zdir[3] = {0., 0., 1.};
+  double vdir[3] = {dx / length, dy / length, dz / length};
+  double axis[3], cosphi, phi;
+  prodve(zdir, vdir, axis);
+  prosca(zdir, vdir, &cosphi);
+  if(!norme(axis)){
+    axis[0] = 0.;
+    axis[1] = 1.;
+    axis[2] = 0.;
+  }
+  phi = 180. * myacos(cosphi) / M_PI;
+
+  glPushMatrix();
+  glTranslated(x[0], y[0], z[0]);
+  glRotated(phi, axis[0], axis[1], axis[2]);
+  gluCylinder(qua, radius1, radius2, length, CTX.quadric_subdivisions, 1);
+  glPopMatrix();
+
+  glDisable(GL_LIGHTING);
+}
+
+void drawContext::drawCylinder(double width, double *x, double *y, double *z, int light)
+{
+  if(light) glEnable(GL_LIGHTING);
+
+  static int first = 1;
+  static GLUquadricObj *qua;
+
+  if(first){
+    first = 0;
+    qua = gluNewQuadric();
+  }
+
+  double dx = x[1] - x[0];
+  double dy = y[1] - y[0];
+  double dz = z[1] - z[0];
+  double length = sqrt(dx * dx + dy * dy + dz * dz);
+  double radius = width * pixel_equiv_x / s[0];
+  double zdir[3] = {0., 0., 1.};
+  double vdir[3] = {dx / length, dy / length, dz / length};
+  double axis[3], cosphi, phi;
+  prodve(zdir, vdir, axis);
+  prosca(zdir, vdir, &cosphi);
+  if(!norme(axis)){
+    axis[0] = 0.;
+    axis[1] = 1.;
+    axis[2] = 0.;
+  }
+  phi = 180. * myacos(cosphi) / M_PI;
+
+  glPushMatrix();
+  glTranslated(x[0], y[0], z[0]);
+  glRotated(phi, axis[0], axis[1], axis[2]);
+  gluCylinder(qua, radius, radius, length, CTX.quadric_subdivisions, 1);
+  glPopMatrix();
+
+  glDisable(GL_LIGHTING);
+}
+
+static void drawSimpleVector(int arrow, int fill,
+                             double relHeadRadius, double relStemLength, 
+                             double relStemRadius,
+                             double x, double y, double z,
+                             double dx, double dy, double dz, 
+                             double d, int light)
+{
+  double n[3], t[3], u[3];
+
+  n[0] = dx / d;
+  n[1] = dy / d;
+  n[2] = dz / d;
+
+  if((fabs(n[0]) >= fabs(n[1]) && fabs(n[0]) >= fabs(n[2])) ||
+     (fabs(n[1]) >= fabs(n[0]) && fabs(n[1]) >= fabs(n[2]))) {
+    t[0] = n[1];
+    t[1] = -n[0];
+    t[2] = 0.;
+  }
+  else {
+    t[0] = 0.;
+    t[1] = n[2];
+    t[2] = -n[1];
+  }
+
+  double l = sqrt(t[0] * t[0] + t[1] * t[1] + t[2] * t[2]);
+  t[0] /= l;
+  t[1] /= l;
+  t[2] /= l;
+
+  u[0] = n[1] * t[2] - n[2] * t[1];
+  u[1] = n[2] * t[0] - n[0] * t[2];
+  u[2] = n[0] * t[1] - n[1] * t[0];
+
+  l = sqrt(u[0] * u[0] + u[1] * u[1] + u[2] * u[2]);
+  u[0] /= l;
+  u[1] /= l;
+  u[2] /= l;
+
+  double b = relHeadRadius * d;
+
+  if(arrow){
+    double f1 = relStemLength;
+    double f2 = (1-2.*relStemRadius) * f1; // hack :-)
+
+    if(fill) {
+      glBegin(GL_LINES);
+      glVertex3d(x, y, z);
+      glVertex3d(x + f1 * dx, y + f1 * dy, z + f1 * dz);
+      glEnd();
+      
+      if(light && fill) glEnable(GL_LIGHTING);
+      glBegin(GL_TRIANGLES);
+      if(light) glNormal3dv(u);
+      glVertex3d(x + dx, y + dy, z + dz);
+      glVertex3d(x + f2 * dx + b * (t[0]), y + f2 * dy + b * (t[1]),
+                 z + f2 * dz + b * (t[2]));
+      glVertex3d(x + f1 * dx, y + f1 * dy, z + f1 * dz);
+      
+      glVertex3d(x + f1 * dx, y + f1 * dy, z + f1 * dz);
+      glVertex3d(x + f2 * dx + b * (-t[0]), y + f2 * dy + b * (-t[1]),
+                 z + f2 * dz + b * (-t[2]));
+      glVertex3d(x + dx, y + dy, z + dz);
+      
+      if(light) glNormal3dv(t);
+      glVertex3d(x + dx, y + dy, z + dz);
+      glVertex3d(x + f2 * dx + b * (-u[0]), y + f2 * dy + b * (-u[1]),
+                 z + f2 * dz + b * (-u[2]));
+      glVertex3d(x + f1 * dx, y + f1 * dy, z + f1 * dz);
+
+      glVertex3d(x + f1 * dx, y + f1 * dy, z + f1 * dz);      
+      glVertex3d(x + f2 * dx + b * (u[0]), y + f2 * dy + b * (u[1]),
+                 z + f2 * dz + b * (u[2]));
+      glVertex3d(x + dx, y + dy, z + dz);
+      glEnd();
+      glDisable(GL_LIGHTING);
+    }
+    else {
+      glBegin(GL_LINE_STRIP);
+      glVertex3d(x, y, z);
+      glVertex3d(x + dx, y + dy, z + dz);
+      glVertex3d(x + f2 * dx + b * (t[0]), y + f2 * dy + b * (t[1]),
+                 z + f2 * dz + b * (t[2]));
+      glVertex3d(x + f1 * dx, y + f1 * dy, z + f1 * dz);
+      glVertex3d(x + f2 * dx + b * (-t[0]), y + f2 * dy + b * (-t[1]),
+                 z + f2 * dz + b * (-t[2]));
+      glVertex3d(x + dx, y + dy, z + dz);
+      glVertex3d(x + f2 * dx + b * (-u[0]), y + f2 * dy + b * (-u[1]),
+                 z + f2 * dz + b * (-u[2]));
+      glVertex3d(x + f1 * dx, y + f1 * dy, z + f1 * dz);
+      glVertex3d(x + f2 * dx + b * (u[0]), y + f2 * dy + b * (u[1]),
+                 z + f2 * dz + b * (u[2]));
+      glVertex3d(x + dx, y + dy, z + dz);
+      glEnd();
+    }
+  }
+  else{ // simple pyramid
+    if(fill){
+      double top[3] = { x+dx,      y+dy,      z+dz };
+      double tp[3]  = { x+b*t[0],  y+b*t[1],  z+b*t[2] };
+      double tm[3]  = { x-b*t[0],  y-b*t[1],  z-b*t[2] };
+      double up[3]  = { x+b*u[0],  y+b*u[1],  z+b*u[2] };
+      double um[3]  = { x-b*u[0],  y-b*u[1],  z-b*u[2] };
+      double nn[3];
+
+      if(light && fill) glEnable(GL_LIGHTING);
+      glBegin(GL_TRIANGLES);
+      if(light){
+        normal3points(tm[0], tm[1], tm[2], um[0], um[1], um[2],
+                      top[0], top[1], top[2], nn);
+        glNormal3dv(nn);
+      }
+      glVertex3d(tm[0], tm[1], tm[2]);
+      glVertex3d(um[0], um[1], um[2]);
+      glVertex3d(top[0], top[1], top[2]);
+
+      if(light){
+        normal3points(um[0], um[1], um[2], tp[0], tp[1], tp[2],
+                      top[0], top[1], top[2], nn);
+        glNormal3dv(nn);
+      }
+      glVertex3d(um[0], um[1], um[2]);
+      glVertex3d(tp[0], tp[1], tp[2]);
+      glVertex3d(top[0], top[1], top[2]);
+
+      if(light){
+        normal3points(tp[0], tp[1], tp[2], up[0], up[1], up[2],
+                      top[0], top[1], top[2], nn);
+        glNormal3dv(nn);
+      }
+      glVertex3d(tp[0], tp[1], tp[2]);
+      glVertex3d(up[0], up[1], up[2]);
+      glVertex3d(top[0], top[1], top[2]);
+
+      if(light){
+        normal3points(up[0], up[1], up[2], tm[0], tm[1], tm[2],
+                      top[0], top[1], top[2], nn);
+        glNormal3dv(nn);
+      }
+      glVertex3d(up[0], up[1], up[2]);
+      glVertex3d(tm[0], tm[1], tm[2]);
+      glVertex3d(top[0], top[1], top[2]);
+      glEnd();
+      glDisable(GL_LIGHTING);
+    }
+    else{
+      glBegin(GL_LINE_LOOP);
+      glVertex3d(x+b*(t[0]),  y+b*(t[1]),  z+b*(t[2]));
+      glVertex3d(x+b*(-u[0]), y+b*(-u[1]), z+b*(-u[2]));
+      glVertex3d(x+b*(-t[0]), y+b*(-t[1]), z+b*(-t[2]));
+      glVertex3d(x+b*(u[0]),  y+b*(u[1]),  z+b*(u[2]));
+      glEnd();
+      
+      glBegin(GL_LINES);
+      glVertex3d(x+b*(t[0]),  y+b*(t[1]),  z+b*(t[2]));
+      glVertex3d(x+dx,        y+dy,        z+dz);
+      
+      glVertex3d(x+b*(-u[0]), y+b*(-u[1]), z+b*(-u[2]));
+      glVertex3d(x+dx,        y+dy,        z+dz);
+      
+      glVertex3d(x+b*(-t[0]), y+b*(-t[1]), z+b*(-t[2]));
+      glVertex3d(x+dx,        y+dy,        z+dz);
+      
+      glVertex3d (x+b*(u[0]), y+b*(u[1]),  z+b*(u[2]));
+      glVertex3d(x+dx,        y+dy,        z+dz);
+      glEnd();
+    }
+  }
+
+}
+
+static void drawArrow3d(double relHeadRadius, double relStemLength, double relStemRadius,
+                        double x, double y, double z, double dx, double dy, double dz,
+                        double length, int light)
+{
+  if(light) glEnable(GL_LIGHTING);
+
+  int subdiv = CTX.quadric_subdivisions;
+  double head_r = relHeadRadius * length;
+  double head_l = (1. - relStemLength) * length;
+  double stem_r = relStemRadius * length;
+  double stem_l = relStemLength * length;
+
+  static int first = 1;
+  static GLUquadricObj *qua;
+
+  if(first){
+    first = 0;
+    qua = gluNewQuadric();
+  }
+
+  double zdir[3] = {0., 0., 1.};
+  double vdir[3] = {dx/length, dy/length, dz/length};
+  double axis[3], cosphi, phi;
+  prodve(zdir, vdir, axis);
+  prosca(zdir, vdir, &cosphi);
+  if(!norme(axis)){
+    axis[0] = 0.;
+    axis[1] = 1.;
+    axis[2] = 0.;
+  }
+  phi = 180. * myacos(cosphi) / M_PI; 
+
+  glPushMatrix();
+  glTranslated(x, y, z);
+  glRotated(phi, axis[0], axis[1], axis[2]);
+  glTranslated(0., 0., stem_l);
+  if(head_l && head_r)
+    gluCylinder(qua, head_r, 0., head_l, subdiv, 1);
+  if(head_r > stem_r)
+    gluDisk(qua, stem_r, head_r, subdiv, 1);
+  else
+    gluDisk(qua, head_r, stem_r, subdiv, 1);      
+  glTranslated(0., 0., -stem_l);
+  if(stem_l && stem_r){
+    gluCylinder(qua, stem_r, stem_r, stem_l, subdiv, 1);
+    gluDisk(qua, 0, stem_r, subdiv, 1);
+  }
+  glPopMatrix();
+
+  glDisable(GL_LIGHTING);
+}
+
+void drawContext::drawVector(int Type, int Fill,
+                             double relHeadRadius, double relStemLength,
+                             double relStemRadius, double x, double y, double z,
+                             double dx, double dy, double dz, int light)
+{
+  double length = sqrt(dx * dx + dy * dy + dz * dz);
+
+  if(length == 0.0) return;
+
+  switch(Type){
+  case 1:
+    glBegin(GL_LINES);
+    glVertex3d(x, y, z);
+    glVertex3d(x + dx, y + dy, z + dz);
+    glEnd();
+    break;
+  case 6:
+    if(relHeadRadius){
+      glBegin(GL_POINTS);
+      glVertex3d(x + dx, y + dy, z + dz);
+      glEnd();
+    }
+    glBegin(GL_LINES);
+    glVertex3d(x + dx, y + dy, z + dz);
+    // color gradient
+    glColor4ubv((GLubyte *) & CTX.color.bg);
+    glVertex3d(x, y, z);
+    glEnd();
+    break;
+  case 2:
+    drawSimpleVector(1, Fill, relHeadRadius, relStemLength, relStemRadius,
+                     x, y, z, dx, dy, dz, length, light);
+    break;
+  case 3:
+    drawSimpleVector(0, Fill, relHeadRadius, relStemLength, relStemRadius,
+                     x, y, z, dx, dy, dz, length, light);
+    break;
+  case 4:
+  default:
+    drawArrow3d(relHeadRadius, relStemLength, relStemRadius,
+                x, y, z, dx, dy, dz, length, light);
+    break;
+  }
+}
+
+class point{
+ public:
+  double x, y, z;
+  bool valid;
+  point() : x(0.), y(0.), z(0.), valid(false) {}
+  point(double xi, double yi, double zi) : x(xi), y(yi), z(zi), valid(true) {}
+};
+
+class plane{
+ private:
+  double _a, _b, _c, _d;
+ public:
+  plane(double a, double b, double c, double d) : _a(a), _b(b), _c(c), _d(d) {}
+  double val(point &p)
+  {
+    return _a * p.x + _b * p.y + _c * p.z + _d;
+  };
+  point intersect(point &p1, point &p2)
+  {
+    double v1 = val(p1), v2 = val(p2);
+    if(fabs(v1) < 1.e-12){
+      if(fabs(v2) < 1.e-12)
+        return point();
+      else
+        return point(p1.x, p1.y, p1.z);
+    }
+    else if(fabs(v2) < 1.e-12){
+      return point(p2.x, p2.y, p2.z);
+    }
+    else if(v1 * v2 < 0.){
+      double coef = - v1 / (v2 - v1);
+      return point(coef * (p2.x - p1.x) + p1.x,
+                   coef * (p2.y - p1.y) + p1.y,
+                   coef * (p2.z - p1.z) + p1.z);
+    }
+    else
+      return point();
+  }
+};
+
+void drawContext::drawBox(double xmin, double ymin, double zmin,
+                          double xmax, double ymax, double zmax,
+                          bool labels)
+{
+  glBegin(GL_LINE_LOOP);
+  glVertex3d(xmin, ymin, zmin);
+  glVertex3d(xmax, ymin, zmin);
+  glVertex3d(xmax, ymax, zmin);
+  glVertex3d(xmin, ymax, zmin);
+  glEnd();
+  glBegin(GL_LINE_LOOP);
+  glVertex3d(xmin, ymin, zmax);
+  glVertex3d(xmax, ymin, zmax);
+  glVertex3d(xmax, ymax, zmax);
+  glVertex3d(xmin, ymax, zmax);
+  glEnd();
+  glBegin(GL_LINES);
+  glVertex3d(xmin, ymin, zmin);
+  glVertex3d(xmin, ymin, zmax);
+  glVertex3d(xmax, ymin, zmin);
+  glVertex3d(xmax, ymin, zmax);
+  glVertex3d(xmax, ymax, zmin);
+  glVertex3d(xmax, ymax, zmax);
+  glVertex3d(xmin, ymax, zmin);
+  glVertex3d(xmin, ymax, zmax);
+  glEnd();
+  if(labels){
+    char label[256];
+    double offset = 0.3 * CTX.gl_fontsize * pixel_equiv_x;
+    glRasterPos3d(xmin + offset / s[0], 
+                  ymin + offset / s[1], 
+                  zmin + offset / s[2]);
+    sprintf(label, "(%g,%g,%g)", xmin, ymin, zmin);
+    Draw_String(label);
+    glRasterPos3d(xmax + offset / s[0], 
+                  ymax + offset / s[1], 
+                  zmax + offset / s[2]);
+    sprintf(label, "(%g,%g,%g)", xmax, ymax, zmax);
+    Draw_String(label);
+  }
+}
+
+void drawContext::drawPlaneInBoundingBox(double xmin, double ymin, double zmin,
+                                         double xmax, double ymax, double zmax,
+                                         double a, double b, double c, double d,
+                                         int shade)
+{
+  plane pl(a, b, c, d);
+  point p1(xmin, ymin, zmin), p2(xmax, ymin, zmin);
+  point p3(xmax, ymax, zmin), p4(xmin, ymax, zmin);
+  point p5(xmin, ymin, zmax), p6(xmax, ymin, zmax);
+  point p7(xmax, ymax, zmax), p8(xmin, ymax, zmax);
+
+  point edge[12];
+  edge[0] = pl.intersect(p1, p2);
+  edge[1] = pl.intersect(p1, p4);
+  edge[2] = pl.intersect(p1, p5);
+  edge[3] = pl.intersect(p2, p3);
+  edge[4] = pl.intersect(p2, p6);
+  edge[5] = pl.intersect(p3, p4);
+  edge[6] = pl.intersect(p3, p7);
+  edge[7] = pl.intersect(p4, p8);
+  edge[8] = pl.intersect(p5, p6);
+  edge[9] = pl.intersect(p5, p8);
+  edge[10] = pl.intersect(p6, p7);
+  edge[11] = pl.intersect(p7, p8);
+
+  int face[6][4] = {
+    {0, 2, 4, 8},
+    {0, 1, 3, 5},
+    {1, 2, 7, 9},
+    {3, 4, 6, 10},
+    {5, 6, 7, 11},
+    {8, 9, 10, 11}
+  };
+  
+  double n[3] = {a,b,c}, ll = 50;
+  norme(n);
+  if(CTX.arrow_rel_stem_radius)
+    ll = CTX.line_width / CTX.arrow_rel_stem_radius;
+  n[0] *= ll * pixel_equiv_x / s[0];
+  n[1] *= ll * pixel_equiv_x / s[1];
+  n[2] *= ll * pixel_equiv_x / s[2];
+  double length = sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]);
+
+  int n_shade = 0;
+  point p_shade[24];
+
+  for(int i = 0; i < 6; i++){
+    int nb = 0;
+    point p[4];
+    for(int j = 0; j < 4; j++){
+      if(edge[face[i][j]].valid == true)
+        p[nb++] = edge[face[i][j]];
+    }
+    if(nb > 1){
+      for(int j = 1; j < nb; j++){
+        double xx[2] = {p[j].x, p[j-1].x};
+        double yy[2] = {p[j].y, p[j-1].y};
+        double zz[2] = {p[j].z, p[j-1].z};
+        drawCylinder(CTX.line_width, xx, yy, zz, 1);
+      }
+      for(int j = 0; j < nb; j++){
+        drawArrow3d(CTX.arrow_rel_head_radius, 
+                    CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius,
+                    p[j].x, p[j].y, p[j].z, n[0], n[1], n[2], length, 1);
+        if(shade){
+          p_shade[n_shade].x = p[j].x;
+          p_shade[n_shade].y = p[j].y;
+          p_shade[n_shade].z = p[j].z;
+          n_shade++;
+        }
+      }
+    }
+  }
+
+  if(shade){
+    // disable two-side lighting beacuse polygon can overlap itself
+    GLboolean twoside;
+    glGetBooleanv(GL_LIGHT_MODEL_TWO_SIDE, &twoside);
+    glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
+    glEnable(GL_LIGHTING);
+    glBegin(GL_POLYGON);
+    glNormal3d(n[0], n[1], n[2]);
+    for(int j = 0; j < n_shade; j++){
+      glVertex3d(p_shade[j].x, p_shade[j].y, p_shade[j].z);
+    }   
+    glEnd();
+    glDisable(GL_LIGHTING);
+    glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, twoside);
+  }
+}
diff --git a/Graphics/Graph2D.cpp b/Graphics/drawGraph2d.cpp
similarity index 93%
rename from Graphics/Graph2D.cpp
rename to Graphics/drawGraph2d.cpp
index ea7815ae14ebcf915c9f55901e3d074fdc5c7c09..d4f3e6eb089253eb1b10e11bb3a6a4766ef197f4 100644
--- a/Graphics/Graph2D.cpp
+++ b/Graphics/drawGraph2d.cpp
@@ -3,6 +3,7 @@
 // See the LICENSE.txt file for license information. Please report all
 // bugs and problems to <gmsh@geuz.org>.
 
+#include "drawContext.h"
 #include "GmshUI.h"
 #include "Draw.h"
 #include "PView.h"
@@ -14,25 +15,25 @@
 
 extern Context_T CTX;
 
-int Fix2DCoordinates(double *x, double *y)
+int drawContext::fix2dCoordinates(double *x, double *y)
 {
   int ret = (*x > 99999 && *y > 99999) ? 3 : (*y > 99999) ? 2 : (*x > 99999) ? 1 : 0;
 
   if(*x < 0) // measure from right border
-    *x = CTX.viewport[2] + *x;
+    *x = viewport[2] + *x;
   else if(*x > 99999) // by convention, x-centered
-    *x = CTX.viewport[2] / 2;
+    *x = viewport[2] / 2;
 
   if(*y < 0) // measure from bottom border
     *y = -(*y);
   else if(*y > 99999) // by convention, y-centered
-    *y = CTX.viewport[3] / 2.;
+    *y = viewport[3] / 2.;
   else
-    *y = CTX.viewport[3] - *y;
+    *y = viewport[3] - *y;
   return ret;
 }
 
-void Draw_Text2D()
+void drawContext::drawText2d()
 {
   for(unsigned int i = 0; i < PView::list.size(); i++){
     PViewData *data = PView::list[i]->getData();
@@ -43,7 +44,7 @@ void Draw_Text2D()
         double x, y, style;
         std::string str;
         data->getString2D(j, opt->TimeStep, str, x, y, style);
-        Fix2DCoordinates(&x, &y);
+        fix2dCoordinates(&x, &y);
         glRasterPos2d(x, y);
         Draw_String(str.c_str(), style);
       }
@@ -400,7 +401,7 @@ static void drawGraph(PView *p, double xleft, double ytop, double width, double
   drawGraphCurves(p, xleft, ytop, width, height, x, xmin, xmax, y);
 }
 
-void Draw_Graph2D()
+void drawContext::drawGraph2d()
 {
   std::vector<PView*> graphs;
   for(unsigned int i = 0; i < PView::list.size(); i++){
@@ -425,40 +426,40 @@ void Draw_Graph2D()
     PViewOptions *opt = graphs[i]->getOptions();
     if(!opt->AutoPosition){
       double x = opt->Position[0], y = opt->Position[1];
-      int center = Fix2DCoordinates(&x, &y);
+      int center = fix2dCoordinates(&x, &y);
       drawGraph(p, x - (center & 1 ? opt->Size[0] / 2. : 0), 
                 y + (center & 2 ? opt->Size[1] / 2. : 0), 
                 opt->Size[0], opt->Size[1]);
     }
     else{
-      double winw = CTX.viewport[2] - CTX.viewport[0];
-      double winh = CTX.viewport[3] - CTX.viewport[1];
+      double winw = viewport[2] - viewport[0];
+      double winh = viewport[3] - viewport[1];
       if(graphs.size() == 1){
         double fracw = 0.75, frach = 0.75;
         double w = fracw * winw - xsep;
         double h = frach * winh - ysep;
-        double x = CTX.viewport[0] + (1 - fracw) / 2. * winw;
-        double y = CTX.viewport[1] + (1 - frach) / 2. * winh;
-        drawGraph(p, x + 0.95 * xsep, CTX.viewport[3] - (y + 0.4 * ysep), w, h);
+        double x = viewport[0] + (1 - fracw) / 2. * winw;
+        double y = viewport[1] + (1 - frach) / 2. * winh;
+        drawGraph(p, x + 0.95 * xsep, viewport[3] - (y + 0.4 * ysep), w, h);
       }
       else if(graphs.size() == 2){
         double fracw = 0.75, frach = 0.85;
         double w = fracw * winw - xsep;
         double h = frach * winh / 2. - ysep;
-        double x = CTX.viewport[0] + (1 - fracw) / 2. * winw;
-        double y = CTX.viewport[1] + (1 - frach) / 3. * winh;
+        double x = viewport[0] + (1 - fracw) / 2. * winw;
+        double y = viewport[1] + (1 - frach) / 3. * winh;
         if(i == 1) y += (h + ysep + (1 - frach) / 3. * winh);
-        drawGraph(p, x + 0.95 * xsep, CTX.viewport[3] - (y + 0.4 * ysep), w, h);
+        drawGraph(p, x + 0.95 * xsep, viewport[3] - (y + 0.4 * ysep), w, h);
       }
       else{
         double fracw = 0.85, frach = 0.85;
         double w = fracw * winw / 2. - xsep;
         double h = frach * winh / 2. - ysep;
-        double x = CTX.viewport[0] + (1 - fracw) / 3. * winw;
+        double x = viewport[0] + (1 - fracw) / 3. * winw;
         if(i == 1 || i == 3) x += (w + xsep + (1-fracw)/3. * winw);
-        double y = CTX.viewport[1] + (1 - frach) / 3. * winh;
+        double y = viewport[1] + (1 - frach) / 3. * winh;
         if(i == 2 || i == 3) y += (h + ysep + (1 - frach) / 3. * winh);
-        drawGraph(p, x + 0.95 * xsep, CTX.viewport[3] - (y + 0.4 * ysep), w, h);
+        drawGraph(p, x + 0.95 * xsep, viewport[3] - (y + 0.4 * ysep), w, h);
       }
     }
   }
diff --git a/Graphics/Mesh.cpp b/Graphics/drawMesh.cpp
similarity index 92%
rename from Graphics/Mesh.cpp
rename to Graphics/drawMesh.cpp
index 4d0a285519d7dc2260ab90bd105f3a4722da4a99..166b9a57a2bf591333fe473261e394e01fc31868 100644
--- a/Graphics/Mesh.cpp
+++ b/Graphics/drawMesh.cpp
@@ -4,8 +4,10 @@
 // bugs and problems to <gmsh@geuz.org>.
 
 #include <math.h>
+#include "drawContext.h"
 #include "GmshMessage.h"
 #include "GmshUI.h"
+#include "GmshDefines.h"
 #include "GModel.h"
 #include "MElement.h"
 #include "Draw.h"
@@ -198,7 +200,7 @@ static void drawElementLabels(GEntity *e, std::vector<T*> &elements,
 }
 
 template<class T>
-static void drawNormals(std::vector<T*> &elements)
+static void drawNormals(drawContext *ctx, std::vector<T*> &elements)
 {
   glColor4ubv((GLubyte *) & CTX.color.mesh.normals);
   for(unsigned int i = 0; i < elements.size(); i++){
@@ -206,16 +208,16 @@ static void drawNormals(std::vector<T*> &elements)
     if(!isElementVisible(ele)) continue;
     SVector3 n = ele->getFace(0).normal();
     for(int j = 0; j < 3; j++)
-      n[j] *= CTX.mesh.normals * CTX.pixel_equiv_x / CTX.s[j];
+      n[j] *= CTX.mesh.normals * ctx->pixel_equiv_x / ctx->s[j];
     SPoint3 pc = ele->barycenter();
-    Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
-                CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius,
-                pc.x(), pc.y(), pc.z(), n[0], n[1], n[2], CTX.mesh.light);
+    ctx->drawVector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
+                    CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius,
+                    pc.x(), pc.y(), pc.z(), n[0], n[1], n[2], CTX.mesh.light);
   }
 }
 
 template<class T>
-static void drawTangents(std::vector<T*> &elements)
+static void drawTangents(drawContext *ctx, std::vector<T*> &elements)
 {
   glColor4ubv((GLubyte *) & CTX.color.mesh.tangents);
   for(unsigned int i = 0; i < elements.size(); i++){
@@ -223,11 +225,11 @@ static void drawTangents(std::vector<T*> &elements)
     if(!isElementVisible(ele)) continue;
     SVector3 t = ele->getEdge(0).tangent();
     for(int j = 0; j < 3; j++)
-      t[j] *= CTX.mesh.tangents * CTX.pixel_equiv_x / CTX.s[j];
+      t[j] *= CTX.mesh.tangents * ctx->pixel_equiv_x / ctx->s[j];
     SPoint3 pc = ele->barycenter();
-    Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
-                CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius,
-                pc.x(), pc.y(), pc.z(), t[0], t[1], t[2], CTX.mesh.light);
+    ctx->drawVector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
+                    CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius,
+                    pc.x(), pc.y(), pc.z(), t[0], t[1], t[2], CTX.mesh.light);
   }
 }
 
@@ -261,7 +263,7 @@ static void drawVertexLabel(GEntity *e, MVertex *v, int partition=-1)
   Draw_String(str);
 }
 
-static void drawVerticesPerEntity(GEntity *e)
+static void drawVerticesPerEntity(drawContext *ctx, GEntity *e)
 {
   if(CTX.mesh.points) {
     if(CTX.mesh.point_type) {
@@ -272,7 +274,7 @@ static void drawVerticesPerEntity(GEntity *e)
           glColor4ubv((GLubyte *) & CTX.color.mesh.vertex_sup);
         else
           glColor4ubv((GLubyte *) & CTX.color.mesh.vertex);     
-        Draw_Sphere(CTX.mesh.point_size, v->x(), v->y(), v->z(), CTX.mesh.light);
+        ctx->drawSphere(CTX.mesh.point_size, v->x(), v->y(), v->z(), CTX.mesh.light);
       }
     }
     else{
@@ -297,7 +299,8 @@ static void drawVerticesPerEntity(GEntity *e)
 }
 
 template<class T>
-static void drawVerticesPerElement(GEntity *e, std::vector<T*> &elements)
+static void drawVerticesPerElement(drawContext *ctx, GEntity *e, 
+                                   std::vector<T*> &elements)
 {
   for(unsigned int i = 0; i < elements.size(); i++){
     MElement *ele = elements[i];
@@ -310,7 +313,7 @@ static void drawVerticesPerElement(GEntity *e, std::vector<T*> &elements)
           else
             glColor4ubv((GLubyte *) & CTX.color.mesh.vertex);   
           if(CTX.mesh.point_type)
-            Draw_Sphere(CTX.mesh.point_size, v->x(), v->y(), v->z(), CTX.mesh.light);
+            ctx->drawSphere(CTX.mesh.point_size, v->x(), v->y(), v->z(), CTX.mesh.light);
           else{
             glBegin(GL_POINTS);
             glVertex3d(v->x(), v->y(), v->z());
@@ -568,7 +571,10 @@ static void drawArrays(GEntity *e, VertexArray *va, GLint type, bool useNormalAr
 // GVertex drawing routines
 
 class drawMeshGVertex {
+ private:
+  drawContext *_ctx;
  public:
+  drawMeshGVertex(drawContext *ctx) : _ctx(ctx){}
   void operator () (GVertex *v)
   {  
     if(!v->getVisibility()) return;
@@ -580,7 +586,7 @@ class drawMeshGVertex {
     }
 
     if(CTX.mesh.points || CTX.mesh.points_num)
-      drawVerticesPerEntity(v);
+      drawVerticesPerEntity(_ctx, v);
 
     if(select) {
       glPopName();
@@ -619,7 +625,10 @@ class initMeshGEdge {
 };
 
 class drawMeshGEdge {
+ private:
+  drawContext *_ctx;
  public:
+  drawMeshGEdge(drawContext *ctx) : _ctx(ctx){}
   void operator () (GEdge *e)
   {  
     if(!e->getVisibility()) return;
@@ -638,13 +647,13 @@ class drawMeshGEdge {
 
     if(CTX.mesh.points || CTX.mesh.points_num){
       if(e->getAllElementsVisible())
-        drawVerticesPerEntity(e);
+        drawVerticesPerEntity(_ctx, e);
       else
-        drawVerticesPerElement(e, e->lines);
+        drawVerticesPerElement(_ctx, e, e->lines);
     }
 
     if(CTX.mesh.tangents)
-      drawTangents(e->lines);
+      drawTangents(_ctx, e->lines);
 
     if(select) {
       glPopName();
@@ -712,7 +721,10 @@ class initMeshGFace {
 };
 
 class drawMeshGFace {
+ private:
+  drawContext *_ctx;
  public:
+  drawMeshGFace(drawContext *ctx) : _ctx(ctx){}
   void operator () (GFace *f)
   {  
     if(!f->getVisibility()) return;
@@ -736,16 +748,16 @@ class drawMeshGFace {
 
     if(CTX.mesh.points || CTX.mesh.points_num){
       if(f->getAllElementsVisible())
-        drawVerticesPerEntity(f);
+        drawVerticesPerEntity(_ctx, f);
       else{
-        if(CTX.mesh.triangles) drawVerticesPerElement(f, f->triangles);
-        if(CTX.mesh.quadrangles) drawVerticesPerElement(f, f->quadrangles);
+        if(CTX.mesh.triangles) drawVerticesPerElement(_ctx, f, f->triangles);
+        if(CTX.mesh.quadrangles) drawVerticesPerElement(_ctx, f, f->quadrangles);
       }
     }
 
     if(CTX.mesh.normals) {
-      if(CTX.mesh.triangles) drawNormals(f->triangles);
-      if(CTX.mesh.quadrangles) drawNormals(f->quadrangles);
+      if(CTX.mesh.triangles) drawNormals(_ctx, f->triangles);
+      if(CTX.mesh.quadrangles) drawNormals(_ctx, f->quadrangles);
     }
 
     if(CTX.mesh.dual) {
@@ -835,7 +847,10 @@ class initMeshGRegion {
 };
 
 class drawMeshGRegion {
+ private:
+  drawContext *_ctx;
  public:
+  drawMeshGRegion(drawContext *ctx) : _ctx(ctx){}
   void operator () (GRegion *r)
   {  
     if(!r->getVisibility()) return;
@@ -867,12 +882,12 @@ class drawMeshGRegion {
 
     if(CTX.mesh.points || CTX.mesh.points_num){
       if(r->getAllElementsVisible())
-        drawVerticesPerEntity(r);
+        drawVerticesPerEntity(_ctx, r);
       else{
-        if(CTX.mesh.tetrahedra) drawVerticesPerElement(r, r->tetrahedra);
-        if(CTX.mesh.hexahedra) drawVerticesPerElement(r, r->hexahedra);
-        if(CTX.mesh.prisms) drawVerticesPerElement(r, r->prisms);
-        if(CTX.mesh.pyramids) drawVerticesPerElement(r, r->pyramids);
+        if(CTX.mesh.tetrahedra) drawVerticesPerElement(_ctx, r, r->tetrahedra);
+        if(CTX.mesh.hexahedra) drawVerticesPerElement(_ctx, r, r->hexahedra);
+        if(CTX.mesh.prisms) drawVerticesPerElement(_ctx, r, r->prisms);
+        if(CTX.mesh.pyramids) drawVerticesPerElement(_ctx, r, r->pyramids);
       }
     }
 
@@ -893,7 +908,7 @@ class drawMeshGRegion {
 
 // Main drawing routine
 
-void Draw_Mesh()
+void drawContext::drawMesh()
 {
   if(!CTX.mesh.draw) return;
 
@@ -949,13 +964,13 @@ void Draw_Mesh()
             std::for_each(m->firstRegion(), m->lastRegion(), initMeshGRegion());
         }
         if(status >= 0)
-          std::for_each(m->firstVertex(), m->lastVertex(), drawMeshGVertex());
+          std::for_each(m->firstVertex(), m->lastVertex(), drawMeshGVertex(this));
         if(status >= 1)
-          std::for_each(m->firstEdge(), m->lastEdge(), drawMeshGEdge());
+          std::for_each(m->firstEdge(), m->lastEdge(), drawMeshGEdge(this));
         if(status >= 2)
-          std::for_each(m->firstFace(), m->lastFace(), drawMeshGFace());
+          std::for_each(m->firstFace(), m->lastFace(), drawMeshGFace(this));
         if(status >= 3)
-          std::for_each(m->firstRegion(), m->lastRegion(), drawMeshGRegion());
+          std::for_each(m->firstRegion(), m->lastRegion(), drawMeshGRegion(this));
       }
     }
 
diff --git a/Graphics/Post.cpp b/Graphics/drawPost.cpp
similarity index 94%
rename from Graphics/Post.cpp
rename to Graphics/drawPost.cpp
index 83d605c04299d8b5e8122a2bc63fc6d1f03e06a8..4afd7edad55c542515793e6de4db0bc726b84a98 100644
--- a/Graphics/Post.cpp
+++ b/Graphics/drawPost.cpp
@@ -5,6 +5,7 @@
 
 #include <math.h>
 #include <algorithm>
+#include "drawContext.h"
 #include "GmshMessage.h"
 #include "GmshUI.h"
 #include "Numeric.h"
@@ -990,7 +991,8 @@ static void addElementsInArrays(PView *p, bool preprocessNormalsOnly)
   }
 }
 
-static void drawArrays(PView *p, VertexArray *va, GLint type, bool useNormalArray)
+static void drawArrays(drawContext *ctx, PView *p, VertexArray *va, GLint type, 
+                       bool useNormalArray)
 {
   if(!va || !va->getNumVertices()) return;
 
@@ -1019,7 +1021,7 @@ static void drawArrays(PView *p, VertexArray *va, GLint type, bool useNormalArra
 	}
       }
       else
-	Draw_Sphere(opt->PointSize * f, p[0], p[1], p[2], opt->Light);
+	ctx->drawSphere(opt->PointSize * f, p[0], p[1], p[2], opt->Light);
     }
   }
   else if(type == GL_LINES && opt->LineType > 0){
@@ -1032,10 +1034,10 @@ static void drawArrays(PView *p, VertexArray *va, GLint type, bool useNormalArra
         char *n0 = va->getNormalArray(3 * i);
         char *n1 = va->getNormalArray(3 * (i + 1));
         double v0 = char2float(*n0), v1 = char2float(*n1);
-        Draw_TapCylinder(opt->LineWidth, v0, v1, 0., 1., x, y, z, opt->Light);
+        ctx->drawTaperedCylinder(opt->LineWidth, v0, v1, 0., 1., x, y, z, opt->Light);
       }
       else
-        Draw_Cylinder(opt->LineWidth, x, y, z, opt->Light);
+        ctx->drawCylinder(opt->LineWidth, x, y, z, opt->Light);
     }
   }
   else{
@@ -1060,7 +1062,7 @@ static void drawArrays(PView *p, VertexArray *va, GLint type, bool useNormalArra
   glDisable(GL_LIGHTING);
 }
 
-static void drawVectorArray(PView *p, VertexArray *va)
+static void drawVectorArray(drawContext *ctx, PView *p, VertexArray *va)
 {
   if(!va || va->getNumVerticesPerElement() != 2) return;
 
@@ -1085,7 +1087,7 @@ static void drawVectorArray(PView *p, VertexArray *va)
       // only draw vectors larger than 1 pixel on screen, except when
       // drawing "comet" glyphs
       if(opt->VectorType == 6 || fabs(px) > 1. || fabs(py) > 1. || fabs(pz) > 1.){
-        double d = CTX.pixel_equiv_x / CTX.s[0];
+        double d = ctx->pixel_equiv_x / ctx->s[0];
         double dx = px * d, dy = py * d, dz = pz * d;
         double x = s[0], y = s[1], z = s[2];
         if(opt->CenterGlyphs){
@@ -1093,9 +1095,9 @@ static void drawVectorArray(PView *p, VertexArray *va)
           y -= 0.5 * dy;
           z -= 0.5 * dz;
         }
-        Draw_Vector(opt->VectorType, opt->IntervalsType != PViewOptions::Iso,
-                    opt->ArrowRelHeadRadius, opt->ArrowRelStemLength,
-                    opt->ArrowRelStemRadius, x, y, z, dx, dy, dz, opt->Light);
+        ctx->drawVector(opt->VectorType, opt->IntervalsType != PViewOptions::Iso,
+                        opt->ArrowRelHeadRadius, opt->ArrowRelStemLength,
+                        opt->ArrowRelStemRadius, x, y, z, dx, dy, dz, opt->Light);
       }
     }
   }
@@ -1161,8 +1163,8 @@ static void drawNumberGlyphs(PView *p, int numNodes, int numComp,
   }
 }
 
-static void drawNormalVectorGlyphs(PView *p, int numNodes, double xyz[NMAX][3],
-				   double val[NMAX][9])
+static void drawNormalVectorGlyphs(drawContext *ctx, PView *p, int numNodes, 
+                                   double xyz[NMAX][3], double val[NMAX][9])
 {
   PViewOptions *opt = p->getOptions();
 
@@ -1174,15 +1176,15 @@ static void drawNormalVectorGlyphs(PView *p, int numNodes, double xyz[NMAX][3],
   SVector3 n = normal3(xyz);
   n.normalize();
   for(int i = 0; i < 3; i++)
-    n[i] *= opt->Normals * CTX.pixel_equiv_x / CTX.s[i];
+    n[i] *= opt->Normals * ctx->pixel_equiv_x / ctx->s[i];
   glColor4ubv((GLubyte *) & opt->color.normals);
-  Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
-              CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius, 
-              pc[0], pc[1], pc[2], n[0], n[1], n[2], opt->Light);
+  ctx->drawVector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
+                  CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius, 
+                  pc[0], pc[1], pc[2], n[0], n[1], n[2], opt->Light);
 }
 
-static void drawTangentVectorGlyphs(PView *p, int numNodes, double xyz[NMAX][3],
-				    double val[NMAX][9])
+static void drawTangentVectorGlyphs(drawContext *ctx, PView *p, int numNodes,
+                                    double xyz[NMAX][3], double val[NMAX][9])
 {
   PViewOptions *opt = p->getOptions();
 
@@ -1192,14 +1194,14 @@ static void drawTangentVectorGlyphs(PView *p, int numNodes, double xyz[NMAX][3],
   SVector3 t(p0, p1);
   t.normalize();
   for(int i = 0; i < 3; i++)
-    t[i] *= opt->Tangents * CTX.pixel_equiv_x / CTX.s[i];
+    t[i] *= opt->Tangents * ctx->pixel_equiv_x / ctx->s[i];
   glColor4ubv((GLubyte *) & opt->color.tangents);
-  Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
-              CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius, 
-              pc[0], pc[1], pc[2], t[0], t[1], t[2], opt->Light);
+  ctx->drawVector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
+                  CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius, 
+                  pc[0], pc[1], pc[2], t[0], t[1], t[2], opt->Light);
 }
 
-static void drawGlyphs(PView *p)
+static void drawGlyphs(drawContext *ctx, PView *p)
 {
   // use adaptive data if available
   PViewData *data = p->getData(true);
@@ -1229,9 +1231,9 @@ static void drawGlyphs(PView *p)
       if(opt->IntervalsType == PViewOptions::Numeric)
         drawNumberGlyphs(p, numNodes, numComp, xyz, val);
       if(dim == 2 && opt->Normals)
-        drawNormalVectorGlyphs(p, numNodes, xyz, val);
+        drawNormalVectorGlyphs(ctx, p, numNodes, xyz, val);
       else if(dim == 1 && opt->Tangents)
-        drawTangentVectorGlyphs(p, numNodes, xyz, val);  
+        drawTangentVectorGlyphs(ctx, p, numNodes, xyz, val);  
     }
   }
 }
@@ -1348,10 +1350,10 @@ class initPView {
   }
 };
 
-static bool eyeChanged(PView *p)
+static bool eyeChanged(drawContext *ctx, PView *p)
 {
   double zeye = 100 * CTX.lc;
-  SPoint3 tmp(CTX.rot[2] * zeye, CTX.rot[6] * zeye, CTX.rot[10] * zeye);
+  SPoint3 tmp(ctx->rot[2] * zeye, ctx->rot[6] * zeye, ctx->rot[10] * zeye);
   if(tmp.distance(p->getEye()) > 1.e-3){
     p->setEye(tmp);
     return true;
@@ -1360,7 +1362,10 @@ static bool eyeChanged(PView *p)
 }
 
 class drawPView {
+ private:
+  drawContext *_ctx;
  public:
+  drawPView(drawContext *ctx) : _ctx(ctx) {}
   void operator () (PView *p)
   {
     // use adaptive data if available
@@ -1403,7 +1408,7 @@ class drawPView {
         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
         // glBlendEquation(GL_FUNC_ADD);
         glEnable(GL_BLEND);
-        if(eyeChanged(p)){
+        if(eyeChanged(_ctx, p)){
           Msg::Debug("Sorting View[%d] for transparency", p->getIndex());
           p->va_triangles->sort(p->getEye().x(), p->getEye().y(), p->getEye().z());
         }
@@ -1426,16 +1431,16 @@ class drawPView {
     }
 
     // draw all the vertex arrays
-    drawArrays(p, p->va_points, GL_POINTS, false);
-    drawArrays(p, p->va_lines, GL_LINES, opt->Light && opt->LightLines);
-    drawArrays(p, p->va_triangles, GL_TRIANGLES, opt->Light);
+    drawArrays(_ctx, p, p->va_points, GL_POINTS, false);
+    drawArrays(_ctx, p, p->va_lines, GL_LINES, opt->Light && opt->LightLines);
+    drawArrays(_ctx, p, p->va_triangles, GL_TRIANGLES, opt->Light);
 
     // draw the "pseudo" vertex arrays for vectors
-    drawVectorArray(p, p->va_vectors);
+    drawVectorArray(_ctx, p, p->va_vectors);
 
     // to avoid looping over elements we should also store these
     // glyphs in "pseudo" vertex arrays
-    drawGlyphs(p);
+    drawGlyphs(_ctx, p);
 
     // draw the 3D strings
     if(opt->DrawStrings){
@@ -1462,18 +1467,21 @@ class drawPView {
       glLineWidth(CTX.line_width);
       gl2psLineWidth(CTX.line_width * CTX.print.eps_line_width_factor);
       if(!opt->AxesAutoPosition)
-        Draw_Axes(opt->Axes, opt->AxesTics, opt->AxesFormat, opt->AxesLabel,
-                  opt->AxesPosition,opt->AxesMikado);
+        _ctx->drawAxes(opt->Axes, opt->AxesTics, opt->AxesFormat, opt->AxesLabel,
+                       opt->AxesPosition, opt->AxesMikado);
       else if(!opt->TmpBBox.empty())
-        Draw_Axes(opt->Axes, opt->AxesTics, opt->AxesFormat, opt->AxesLabel,
-                  opt->TmpBBox,opt->AxesMikado);
+        _ctx->drawAxes(opt->Axes, opt->AxesTics, opt->AxesFormat, opt->AxesLabel,
+                       opt->TmpBBox, opt->AxesMikado);
     }
     
   }
 };
 
 class drawPViewBoundingBox {
- public :
+ private:
+  drawContext *_ctx;
+ public:
+  drawPViewBoundingBox(drawContext *ctx) : _ctx(ctx) {}
   void operator () (PView *p)
   {
     PViewData *data = p->getData();
@@ -1488,27 +1496,27 @@ class drawPViewBoundingBox {
     glLineWidth(CTX.line_width);
     gl2psLineWidth(CTX.line_width * CTX.print.eps_line_width_factor);
 
-    Draw_Box(bb.min().x(), bb.min().y(), bb.min().z(),
-             bb.max().x(), bb.max().y(), bb.max().z());
+    _ctx->drawBox(bb.min().x(), bb.min().y(), bb.min().z(),
+                  bb.max().x(), bb.max().y(), bb.max().z());
     glColor3d(1., 0., 0.);
     for(int i = 0; i < 6; i++)
       if(opt->Clip & (1 << i))
-        Draw_PlaneInBoundingBox(bb.min().x(), bb.min().y(), bb.min().z(),
-                                bb.max().x(), bb.max().y(), bb.max().z(),
-                                CTX.clip_plane[i][0], CTX.clip_plane[i][1], 
-                                CTX.clip_plane[i][2], CTX.clip_plane[i][3]);
+        _ctx->drawPlaneInBoundingBox(bb.min().x(), bb.min().y(), bb.min().z(),
+                                     bb.max().x(), bb.max().y(), bb.max().z(),
+                                     CTX.clip_plane[i][0], CTX.clip_plane[i][1], 
+                                     CTX.clip_plane[i][2], CTX.clip_plane[i][3]);
   }
 };
 
-void Draw_Post()
+void drawContext::drawPost()
 {
   // draw any plugin-specific stuff
-  if(CTX.post.plugin_draw_function) (*CTX.post.plugin_draw_function)();
+  if(CTX.post.plugin_draw_function) (*CTX.post.plugin_draw_function)(this);
 
   if(PView::list.empty()) return;
 
   if(CTX.draw_bbox || !CTX.post.draw)
-    std::for_each(PView::list.begin(), PView::list.end(), drawPViewBoundingBox());
+    std::for_each(PView::list.begin(), PView::list.end(), drawPViewBoundingBox(this));
 
   if(!CTX.post.draw) return;
 
@@ -1516,7 +1524,7 @@ void Draw_Post()
   if(!busy){
     busy = true;
     std::for_each(PView::list.begin(), PView::list.end(), initPView());
-    std::for_each(PView::list.begin(), PView::list.end(), drawPView());
+    std::for_each(PView::list.begin(), PView::list.end(), drawPView(this));
     busy = false;
   }
 }
diff --git a/Graphics/Scale.cpp b/Graphics/drawScales.cpp
similarity index 90%
rename from Graphics/Scale.cpp
rename to Graphics/drawScales.cpp
index fcca457466f99bcba7d013e7787c7428b80687bd..1b852df8ff8f4766b1acd0a46cf675ae86f2f7b9 100644
--- a/Graphics/Scale.cpp
+++ b/Graphics/drawScales.cpp
@@ -3,6 +3,7 @@
 // See the LICENSE.txt file for license information. Please report all
 // bugs and problems to <gmsh@geuz.org>.
 
+#include "drawContext.h"
 #include "GmshUI.h"
 #include "Draw.h"
 #include "PView.h"
@@ -213,7 +214,7 @@ static void drawScale(PView *p, double xmin, double ymin, double width,
   drawScaleLabel(p, xmin, ymin, width, height, tic, horizontal);
 }
 
-void Draw_Scales()
+void drawContext::drawScales()
 {
   std::vector<PView*> scales;
   for(unsigned int i = 0; i < PView::list.size(); i++){
@@ -245,26 +246,26 @@ void Draw_Scales()
     if(!opt->AutoPosition) {
       double w = opt->Size[0], h = opt->Size[1];
       double x = opt->Position[0], y = opt->Position[1] - h;
-      int c = Fix2DCoordinates(&x, &y);
+      int c = fix2dCoordinates(&x, &y);
       if(c & 1) x -= w / 2.;
       if(c & 2) y += h / 2.;
       drawScale(p, x, y, w, h, tic, CTX.post.horizontal_scales);
     }
     else if(CTX.post.horizontal_scales){
       double ysep = 20.;
-      double xc = (CTX.viewport[2] - CTX.viewport[0]) / 2.;
+      double xc = (viewport[2] - viewport[0]) / 2.;
       if(scales.size() == 1){
-        double w = (CTX.viewport[2] - CTX.viewport[0]) / 2., h = bar_size;
-        double x = xc - w / 2., y = CTX.viewport[1] + ysep;
+        double w = (viewport[2] - viewport[0]) / 2., h = bar_size;
+        double x = xc - w / 2., y = viewport[1] + ysep;
         drawScale(p, x, y, w, h, tic, 1);
       }
       else{
-        double xsep = maxw / 4. + (CTX.viewport[2] - CTX.viewport[0]) / 10.;
-        double w = (CTX.viewport[2] - CTX.viewport[0] - 4 * xsep) / 2.;
+        double xsep = maxw / 4. + (viewport[2] - viewport[0]) / 10.;
+        double w = (viewport[2] - viewport[0] - 4 * xsep) / 2.;
         if(w < 20.) w = 20.;
         double h = bar_size;
         double x = xc - (i % 2 ? -xsep / 1.5 : w + xsep / 1.5);
-        double y = CTX.viewport[1] + ysep + 
+        double y = viewport[1] + ysep + 
           (i / 2) * (bar_size + tic + 2 * gl_height() + ysep);
         drawScale(p, x, y, w, h, tic, 1);
       }
@@ -273,17 +274,17 @@ void Draw_Scales()
       double xsep = 20.;
       double dy = 2. * gl_height();
       if(scales.size() == 1){
-        double ysep = (CTX.viewport[3] - CTX.viewport[1]) / 6.;
-        double w = bar_size, h = CTX.viewport[3] - CTX.viewport[1] - 2 * ysep - dy;
-        double x = CTX.viewport[0] + xsep, y = CTX.viewport[1] + ysep + dy;
+        double ysep = (viewport[3] - viewport[1]) / 6.;
+        double w = bar_size, h = viewport[3] - viewport[1] - 2 * ysep - dy;
+        double x = viewport[0] + xsep, y = viewport[1] + ysep + dy;
         drawScale(p, x, y, w, h, tic, 0);
       }
       else{
-        double ysep = (CTX.viewport[3] - CTX.viewport[1]) / 15.;
+        double ysep = (viewport[3] - viewport[1]) / 15.;
         double w = bar_size;
-        double h = (CTX.viewport[3] - CTX.viewport[1] - 3 * ysep - 2.5 * dy) / 2.;
-        double x = CTX.viewport[0] + xsep + width_total + (i / 2) * xsep;
-        double y = CTX.viewport[1] + ysep + dy + (1 - i % 2) * (h + 1.5 * dy + ysep);
+        double h = (viewport[3] - viewport[1] - 3 * ysep - 2.5 * dy) / 2.;
+        double x = viewport[0] + xsep + width_total + (i / 2) * xsep;
+        double y = viewport[1] + ysep + dy + (1 - i % 2) * (h + 1.5 * dy + ysep);
         drawScale(p, x, y, w, h, tic, 0);
       }
       // compute width
diff --git a/Mesh/Refine.cpp b/Mesh/Refine.cpp
index ad3ad7908982786cfdc4d2d8d72aa254f17771d4..36ebf2dc159cfa0a8f01800e3b5745098eb5a2d6 100644
--- a/Mesh/Refine.cpp
+++ b/Mesh/Refine.cpp
@@ -81,7 +81,7 @@ static void Subdivide(GFace *gf, bool splitTrianglesIntoQuads)
     }
     delete q;
   }
-  if (splitTrianglesIntoQuads){
+  if(splitTrianglesIntoQuads){
     for(unsigned int i = 0; i < gf->triangles.size(); i++){
       MTriangle *t = gf->triangles[i];
       if(t->getNumVertices() == 6){
diff --git a/Mesh/gmshSmoothHighOrder.cpp b/Mesh/gmshSmoothHighOrder.cpp
index 839253efb3dba1fbdd246ffe4ec30b6b967aa335..5aa4e049fc03bfdde81374001c94609f992806aa 100644
--- a/Mesh/gmshSmoothHighOrder.cpp
+++ b/Mesh/gmshSmoothHighOrder.cpp
@@ -117,7 +117,7 @@ void gmshHighOrderSmoother::smooth ( std::vector<MElement*>  & all)
   }
 
   // 3 -> .4
-  printf("%d elements after adding %d layers\n", v.size(), nbLayers);
+  printf("%d elements after adding %d layers\n", (int)v.size(), nbLayers);
 
   addOneLayer(all, v, layer);
 
diff --git a/Mesh/meshGFaceOptimize.cpp b/Mesh/meshGFaceOptimize.cpp
index 978ef56900531d4fb2bea79fc6b4302b41ceac15..334934ecf2874b56f0e9e49ee53cacb2aee6c4e1 100644
--- a/Mesh/meshGFaceOptimize.cpp
+++ b/Mesh/meshGFaceOptimize.cpp
@@ -110,7 +110,7 @@ void buildVertexToElement(std::vector<T*> &eles, v2t_cont &adj)
 {
   for (unsigned int i = 0; i < eles.size(); i++){
     T *t = eles[i];
-    for (unsigned int j = 0; j < t->getNumVertices(); j++){
+    for (int j = 0; j < t->getNumVertices(); j++){
       MVertex *v = t->getVertex(j);
       v2t_cont :: iterator it = adj.find(v);
       if (it == adj.end()){
@@ -136,7 +136,7 @@ void buildEdgeToElement(std::vector<T*> &triangles, e2t_cont &adj)
 {
   for (unsigned int i = 0; i < triangles.size(); i++){
     T *t = triangles[i];
-    for (unsigned int j = 0; j < t->getNumEdges(); j++){
+    for (int j = 0; j < t->getNumEdges(); j++){
       MEdge e = t->getEdge(j);
       e2t_cont::iterator it = adj.find(e);
       if (it == adj.end()){
@@ -158,14 +158,15 @@ void buildEdgeToElement(GFace *gf, e2t_cont &adj)
   buildEdgeToElement(gf->quadrangles, adj);
 }
 
-void buildEdgeToTriangle(std::vector<MTriangle*> &tris, e2t_cont &adj){
+void buildEdgeToTriangle(std::vector<MTriangle*> &tris, e2t_cont &adj)
+{
   adj.clear();
   buildEdgeToElement(tris, adj);
 }
 
 void parametricCoordinates(MElement *t, GFace *gf, double u[4], double v[4])
 {
-  for (unsigned int j = 0; j < t->getNumVertices(); j++){
+  for (int j = 0; j < t->getNumVertices(); j++){
     MVertex *ver = t->getVertex(j);
     SPoint2 param;
     reparamMeshVertexOnFace(ver, gf, param);
@@ -818,7 +819,7 @@ static void _gmshRecombineIntoQuads(GFace *gf)
 				      it->second.first,
 				      it->second.second));
   }
-  bool rec = false;    
+
   std::set<recombine_triangle>::iterator itp = pairs.begin();
   while(itp != pairs.end()){
     // recombine if difference between max quad angle and right
@@ -853,7 +854,7 @@ static void _gmshRecombineIntoQuads(GFace *gf)
   }
 
   std::vector<MTriangle*> triangles2;
-  for (int i = 0; i < gf->triangles.size(); i++){
+  for (unsigned int i = 0; i < gf->triangles.size(); i++){
     if (touched.find(gf->triangles[i]) == touched.end()){
       triangles2.push_back(gf->triangles[i]);
     }
diff --git a/Numeric/gmshLaplace.h b/Numeric/gmshLaplace.h
index ae6444cf2093d8c61500c933ea09c0d0d6f3d537..f43a722bd0c6ebc4aa13294c968de5e2bf0e2ccb 100644
--- a/Numeric/gmshLaplace.h
+++ b/Numeric/gmshLaplace.h
@@ -14,8 +14,9 @@
 #include "GmshMatrix.h"
 
 class gmshLaplaceTerm : public gmshNodalFemTerm {
+ private:
+  const gmshFunction *_diffusivity;
   const int _iField ;
-  const gmshFunction * _diffusivity;
  protected:
   virtual int sizeOfR(MElement *e) const { return e->getNumVertices(); }
   virtual int sizeOfC(MElement *e) const { return e->getNumVertices(); }
@@ -27,7 +28,7 @@ class gmshLaplaceTerm : public gmshNodalFemTerm {
   }
  public:
   gmshLaplaceTerm(GModel *gm, gmshFunction *diffusivity, int iField = 0) : 
-    gmshNodalFemTerm(gm),_diffusivity(diffusivity), _iField(iField){}
+    gmshNodalFemTerm(gm), _diffusivity(diffusivity), _iField(iField){}
   virtual void elementMatrix(MElement *e, Double_Matrix &m) const;
 };
 
diff --git a/Numeric/gmshLinearSystemFull.h b/Numeric/gmshLinearSystemFull.h
index c20fb7348ce54bd42faadfdbd0018b7d991495d4..15205916e177ad45579d57229e3b1240c846f216 100644
--- a/Numeric/gmshLinearSystemFull.h
+++ b/Numeric/gmshLinearSystemFull.h
@@ -60,7 +60,7 @@ public :
   }
   virtual void zeroRightHandSide () 
   {
-    for (unsigned int i = 0; i < _b->size(); i++) (*_b)(i) = 0;
+    for (int i = 0; i < _b->size(); i++) (*_b)(i) = 0;
   }
   virtual int systemSolve () 
   {
diff --git a/Parser/Makefile b/Parser/Makefile
index fe6e803edf155c38b067f4f59e6aa4e600aa70ff..d76756be94a16bcad48d2607ee7ee4e3a090a561 100644
--- a/Parser/Makefile
+++ b/Parser/Makefile
@@ -69,7 +69,7 @@ Gmsh.tab${OBJEXT}: Gmsh.tab.cpp ../Common/GmshMessage.h ../Common/MallocUtils.h
   ../Geo/SPoint3.h ../Geo/SVector3.h ../Geo/SBoundingBox3d.h \
   ../Geo/SPoint2.h ../Geo/ExtrudeParams.h ../Common/SmoothData.h \
   ../Geo/GeoInterpolation.h ../Geo/Geo.h ../Mesh/Generator.h \
-  ../Graphics/Draw.h ../Common/Options.h ../Post/ColorTable.h \
+  ../Fltk/Draw.h ../Common/Options.h ../Post/ColorTable.h \
   ../Common/Colors.h ../Common/Options.h Parser.h ../Common/OpenFile.h \
   ../Common/CommandLine.h FunctionManager.h ../Common/OS.h \
   ../Common/CreateFile.h ../Mesh/Field.h ../Post/PView.h \
diff --git a/Plugin/Annotate.cpp b/Plugin/Annotate.cpp
index 05a2a6f38419a487b07fc84408f392f542332e82..6f2803ebdbd59fd14fff620291cc6091c5940ef6 100644
--- a/Plugin/Annotate.cpp
+++ b/Plugin/Annotate.cpp
@@ -48,20 +48,21 @@ static double getStyle()
   return (double)((align<<16)|(font<<8)|(fontsize));
 }
 
-void GMSH_AnnotatePlugin::draw()
+void GMSH_AnnotatePlugin::draw(void *context)
 {
 #if defined(HAVE_FLTK)
   double X = AnnotateOptions_Number[0].def;
   double Y = AnnotateOptions_Number[1].def;
   double Z = AnnotateOptions_Number[2].def;
   double style = getStyle();
+  drawContext *ctx = (drawContext*)context;
 
   glColor4ubv((GLubyte *) & CTX.color.fg);
   if(AnnotateOptions_Number[3].def){ // 3D
     glRasterPos3d(X, Y, Z);
     Draw_String(AnnotateOptions_String[0].def, style);
     // draw 10-pixel marker
-    double d = 10 * CTX.pixel_equiv_x / CTX.s[0];
+    double d = 10 * ctx->pixel_equiv_x / ctx->s[0];
     glBegin(GL_LINES);
     glVertex3d(X-d,Y,Z); glVertex3d(X+d,Y,Z);
     glVertex3d(X,Y-d,Z); glVertex3d(X,Y+d,Z);
@@ -75,11 +76,11 @@ void GMSH_AnnotatePlugin::draw()
 
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
-    glOrtho((double)CTX.viewport[0], (double)CTX.viewport[2],
-            (double)CTX.viewport[1], (double)CTX.viewport[3], -1., 1.);
+    glOrtho((double)ctx->viewport[0], (double)ctx->viewport[2],
+            (double)ctx->viewport[1], (double)ctx->viewport[3], -1., 1.);
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
-    Fix2DCoordinates(&X, &Y);
+    ctx->fix2dCoordinates(&X, &Y);
     glRasterPos2d(X, Y);
     Draw_String(AnnotateOptions_String[0].def, style);
     // draw 10-pixel marker
diff --git a/Plugin/Annotate.h b/Plugin/Annotate.h
index 01a6b4dcea0c8eac33096d5cef2f44e84a1ecff6..1e23dab69d63c282d404e932fabcebb709637ee9 100644
--- a/Plugin/Annotate.h
+++ b/Plugin/Annotate.h
@@ -38,7 +38,7 @@ public:
   static const char *callbackText(int, int, const char *);
   static const char *callbackFont(int, int, const char *);
   static const char *callbackAlign(int, int, const char *);
-  static void draw();
+  static void draw(void *context);
 };
 
 #endif
diff --git a/Plugin/CutGrid.cpp b/Plugin/CutGrid.cpp
index 442995011461c197d0e7ed3bd908dd4779bd3c16..a63fadaa397a9b64254a512d92c8f86ee82fa485 100644
--- a/Plugin/CutGrid.cpp
+++ b/Plugin/CutGrid.cpp
@@ -9,6 +9,7 @@
 
 #if defined(HAVE_FLTK)
 #include "GmshUI.h"
+#include "drawContext.h"
 #include "Draw.h"
 #endif
 
@@ -38,7 +39,7 @@ extern "C"
   }
 }
 
-void GMSH_CutGridPlugin::draw()
+void GMSH_CutGridPlugin::draw(void *context)
 {
 #if defined(HAVE_FLTK)
   glColor4ubv((GLubyte *) & CTX.color.fg);
@@ -61,10 +62,11 @@ void GMSH_CutGridPlugin::draw()
     glEnd();
   }
   else{
+    drawContext *ctx = (drawContext*)context;
     for(int i = 0; i < getNbU(); ++i){
       for(int j = 0; j < getNbV(); ++j){
         getPoint(i, j, p);
-        Draw_Sphere(CTX.point_size, p[0], p[1], p[2], 1);
+        ctx->drawSphere(CTX.point_size, p[0], p[1], p[2], 1);
       }
     }
   }
diff --git a/Plugin/CutGrid.h b/Plugin/CutGrid.h
index d0c145656545150c502fe658afc61836a4e536d1..a7383cd5385a3a6044473f0a11c0280e3d5b72a5 100644
--- a/Plugin/CutGrid.h
+++ b/Plugin/CutGrid.h
@@ -48,7 +48,7 @@ public:
   static double callbackU(int, int, double);
   static double callbackV(int, int, double);
   static double callbackConnect(int, int, double);
-  static void draw();
+  static void draw(void *context);
 };
 
 #endif
diff --git a/Plugin/CutParametric.cpp b/Plugin/CutParametric.cpp
index 7deb59f3f53ef2f3894262788e7cdd6f91863ad5..1211cbdfd0df13821eff9790ddbe36d9e29befcd 100644
--- a/Plugin/CutParametric.cpp
+++ b/Plugin/CutParametric.cpp
@@ -10,6 +10,7 @@
 
 #if defined(HAVE_FLTK)
 #include "GmshUI.h"
+#include "drawContext.h"
 #include "Draw.h"
 #endif
 
@@ -101,7 +102,7 @@ int GMSH_CutParametricPlugin::fillXYZ()
 #endif
 }
 
-void GMSH_CutParametricPlugin::draw()
+void GMSH_CutParametricPlugin::draw(void *context)
 {
 #if defined(HAVE_FLTK)
   if(recompute){
@@ -118,8 +119,9 @@ void GMSH_CutParametricPlugin::draw()
     glEnd();
   }
   else{
+    drawContext *ctx = (drawContext*)context;
     for(unsigned int i = 0; i < x.size(); ++i)
-      Draw_Sphere(CTX.point_size, x[i], y[i], z[i], 1);
+      ctx->drawSphere(CTX.point_size, x[i], y[i], z[i], 1);
   }
 #endif
 }
diff --git a/Plugin/CutParametric.h b/Plugin/CutParametric.h
index e5948feaca6f160fd02cb51861522e93762b0147..a4c2b9525c0c6c63ad9a7a1a6df95d7cc912b2b9 100644
--- a/Plugin/CutParametric.h
+++ b/Plugin/CutParametric.h
@@ -42,7 +42,7 @@ public:
   static const char *callbackX(int, int, const char *);
   static const char *callbackY(int, int, const char *);
   static const char *callbackZ(int, int, const char *);
-  static void draw();
+  static void draw(void *context);
 };
 
 #endif
diff --git a/Plugin/CutPlane.cpp b/Plugin/CutPlane.cpp
index 0f802b64b28af6afe246c72d6e9148426bed1bfc..3dfb4d4491055b5a081b05470f87ce91241aa79e 100644
--- a/Plugin/CutPlane.cpp
+++ b/Plugin/CutPlane.cpp
@@ -8,6 +8,7 @@
 
 #if defined(HAVE_FLTK)
 #include "GmshUI.h"
+#include "drawContext.h"
 #include "Draw.h"
 #endif
 
@@ -34,21 +35,22 @@ extern "C"
   }
 }
 
-void GMSH_CutPlanePlugin::draw()
+void GMSH_CutPlanePlugin::draw(void *context)
 {
 #if defined(HAVE_FLTK)
   int num = (int)CutPlaneOptions_Number[7].def;
+  drawContext *ctx = (drawContext*)context;
   if(num < 0) num = iview;
   if(num >= 0 && num < (int)PView::list.size()){
     glColor4ubv((GLubyte *) & CTX.color.fg);
     glLineWidth(CTX.line_width);
     SBoundingBox3d bb = PView::list[num]->getData()->getBoundingBox();
-    Draw_PlaneInBoundingBox(bb.min().x(), bb.min().y(), bb.min().z(), 
-                            bb.max().x(), bb.max().y(), bb.max().z(), 
-                            CutPlaneOptions_Number[0].def,
-                            CutPlaneOptions_Number[1].def,
-                            CutPlaneOptions_Number[2].def,
-                            CutPlaneOptions_Number[3].def);
+    ctx->drawPlaneInBoundingBox(bb.min().x(), bb.min().y(), bb.min().z(), 
+                                bb.max().x(), bb.max().y(), bb.max().z(), 
+                                CutPlaneOptions_Number[0].def,
+                                CutPlaneOptions_Number[1].def,
+                                CutPlaneOptions_Number[2].def,
+                                CutPlaneOptions_Number[3].def);
   }
 #endif
 }
diff --git a/Plugin/CutPlane.h b/Plugin/CutPlane.h
index f724ab1db233a5840a12057c0ba3c6e362fd20df..b9d8e1133aeb0d496b47fea7d11ad5622c53c8f8 100644
--- a/Plugin/CutPlane.h
+++ b/Plugin/CutPlane.h
@@ -36,7 +36,7 @@ public:
   static double callbackVol(int, int, double);
   static double callbackRecur(int, int, double);
   static double callbackTarget(int, int, double);
-  static void draw();
+  static void draw(void *context);
 };
 
 #endif
diff --git a/Plugin/CutSphere.cpp b/Plugin/CutSphere.cpp
index ddc9155eb4d20bdb3e533961e88675c0149e353b..4d439c35bee351683284dfccb305a8c06b3805ce 100644
--- a/Plugin/CutSphere.cpp
+++ b/Plugin/CutSphere.cpp
@@ -32,7 +32,7 @@ extern "C"
   }
 }
 
-void GMSH_CutSpherePlugin::draw()
+void GMSH_CutSpherePlugin::draw(void *context)
 {
 #if defined(HAVE_FLTK)
   static GLUquadricObj *qua;
diff --git a/Plugin/CutSphere.h b/Plugin/CutSphere.h
index a892a1ebaacd4c50d5e5bf68ead9b1e81ec40538..8d9867d6f760f212c86c191d0162c65333424972 100644
--- a/Plugin/CutSphere.h
+++ b/Plugin/CutSphere.h
@@ -33,7 +33,7 @@ public:
   static double callbackR(int, int, double);
   static double callbackVol(int, int, double);
   static double callbackRecur(int, int, double);
-  static void draw();
+  static void draw(void *context);
 };
 
 #endif
diff --git a/Plugin/Makefile b/Plugin/Makefile
index 5d9bd922ad2619a34c87969465029c04a66fcac7..418105be520af9b99cc5a60663980360e558f807 100644
--- a/Plugin/Makefile
+++ b/Plugin/Makefile
@@ -90,14 +90,14 @@ CutPlane${OBJEXT}: CutPlane.cpp CutPlane.h Levelset.h Plugin.h \
   ../Post/PViewData.h ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h \
   ../Common/ListUtils.h ../Numeric/GmshMatrix.h ../Common/Context.h \
   ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h ../Common/GmshUI.h \
-  ../Graphics/Draw.h
+  ../Graphics/drawContext.h ../Fltk/Draw.h
 CutSphere${OBJEXT}: CutSphere.cpp CutSphere.h Levelset.h Plugin.h \
   ../Common/Options.h ../Post/ColorTable.h ../Common/GmshMessage.h \
   ../Post/PView.h ../Geo/SPoint3.h ../Post/PViewDataList.h \
   ../Post/PViewData.h ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h \
   ../Common/ListUtils.h ../Numeric/GmshMatrix.h ../Common/Context.h \
   ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h ../Common/GmshUI.h \
-  ../Graphics/Draw.h
+  ../Fltk/Draw.h
 CutMap${OBJEXT}: CutMap.cpp CutMap.h Levelset.h Plugin.h ../Common/Options.h \
   ../Post/ColorTable.h ../Common/GmshMessage.h ../Post/PView.h \
   ../Geo/SPoint3.h ../Post/PViewDataList.h ../Post/PViewData.h \
@@ -116,7 +116,7 @@ CutParametric${OBJEXT}: CutParametric.cpp ../Post/OctreePost.h \
   ../Post/PViewData.h ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h \
   ../Common/ListUtils.h ../Numeric/GmshMatrix.h ../Common/Context.h \
   ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h ../Common/GmshUI.h \
-  ../Graphics/Draw.h
+  ../Graphics/drawContext.h ../Fltk/Draw.h
 Lambda2${OBJEXT}: Lambda2.cpp Lambda2.h Plugin.h ../Common/Options.h \
   ../Post/ColorTable.h ../Common/GmshMessage.h ../Post/PView.h \
   ../Geo/SPoint3.h ../Post/PViewDataList.h ../Post/PViewData.h \
@@ -142,14 +142,15 @@ StreamLines${OBJEXT}: StreamLines.cpp StreamLines.h Plugin.h ../Common/Options.h
   ../Numeric/GmshMatrix.h ../Post/OctreePost.h ../Common/Octree.h \
   ../Common/OctreeInternals.h ../Common/Context.h ../Geo/CGNSOptions.h \
   ../Mesh/PartitionOptions.h ../Post/PViewOptions.h ../Post/ColorTable.h \
-  ../Common/GmshUI.h ../Graphics/Draw.h
+  ../Common/GmshUI.h ../Graphics/drawContext.h ../Fltk/Draw.h
 CutGrid${OBJEXT}: CutGrid.cpp ../Post/OctreePost.h ../Common/Octree.h \
   ../Common/OctreeInternals.h CutGrid.h Plugin.h ../Common/Options.h \
   ../Post/ColorTable.h ../Common/GmshMessage.h ../Post/PView.h \
   ../Geo/SPoint3.h ../Post/PViewDataList.h ../Post/PViewData.h \
   ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Common/ListUtils.h \
   ../Numeric/GmshMatrix.h ../Common/Context.h ../Geo/CGNSOptions.h \
-  ../Mesh/PartitionOptions.h ../Common/GmshUI.h ../Graphics/Draw.h
+  ../Mesh/PartitionOptions.h ../Common/GmshUI.h ../Graphics/drawContext.h \
+  ../Fltk/Draw.h
 Transform${OBJEXT}: Transform.cpp Transform.h Plugin.h ../Common/Options.h \
   ../Post/ColorTable.h ../Common/GmshMessage.h ../Post/PView.h \
   ../Geo/SPoint3.h ../Post/PViewDataList.h ../Post/PViewData.h \
@@ -282,9 +283,9 @@ Annotate${OBJEXT}: Annotate.cpp Annotate.h Plugin.h ../Common/Options.h \
   ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Common/ListUtils.h \
   ../Numeric/GmshMatrix.h ../Common/Context.h ../Geo/CGNSOptions.h \
   ../Mesh/PartitionOptions.h ../Common/GmshUI.h ../Fltk/GUI.h \
-  ../Fltk/Opengl_Window.h ../Fltk/Colorbar_Window.h \
-  ../Fltk/Popup_Button.h ../Fltk/SpherePosition_Widget.h ../Mesh/Field.h \
-  ../Graphics/Draw.h
+  ../Fltk/Opengl_Window.h ../Graphics/drawContext.h \
+  ../Fltk/Colorbar_Window.h ../Fltk/Popup_Button.h \
+  ../Fltk/SpherePosition_Widget.h ../Mesh/Field.h ../Fltk/Draw.h
 Remove${OBJEXT}: Remove.cpp Remove.h Plugin.h ../Common/Options.h \
   ../Post/ColorTable.h ../Common/GmshMessage.h ../Post/PView.h \
   ../Geo/SPoint3.h ../Post/PViewDataList.h ../Post/PViewData.h \
@@ -296,7 +297,8 @@ Probe${OBJEXT}: Probe.cpp Probe.h Plugin.h ../Common/Options.h \
   ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Common/ListUtils.h \
   ../Numeric/GmshMatrix.h ../Common/Context.h ../Geo/CGNSOptions.h \
   ../Mesh/PartitionOptions.h ../Post/OctreePost.h ../Common/Octree.h \
-  ../Common/OctreeInternals.h ../Common/GmshUI.h ../Graphics/Draw.h
+  ../Common/OctreeInternals.h ../Common/GmshUI.h \
+  ../Graphics/drawContext.h ../Fltk/Draw.h
 HarmonicToTime${OBJEXT}: HarmonicToTime.cpp HarmonicToTime.h Plugin.h \
   ../Common/Options.h ../Post/ColorTable.h ../Common/GmshMessage.h \
   ../Post/PView.h ../Geo/SPoint3.h ../Post/PViewDataList.h \
diff --git a/Plugin/Probe.cpp b/Plugin/Probe.cpp
index 810563dc189f522b29144e160ea18b556ddeb621..c0aa4191136aec77714d9985569bcd2790a79056 100644
--- a/Plugin/Probe.cpp
+++ b/Plugin/Probe.cpp
@@ -9,6 +9,7 @@
 
 #if defined(HAVE_FLTK)
 #include "GmshUI.h"
+#include "drawContext.h"
 #include "Draw.h"
 #endif
 
@@ -31,7 +32,7 @@ extern "C"
   }
 }
 
-void GMSH_ProbePlugin::draw()
+void GMSH_ProbePlugin::draw(void *context)
 {
 #if defined(HAVE_FLTK)
   int num = (int)ProbeOptions_Number[3].def;
@@ -40,6 +41,7 @@ void GMSH_ProbePlugin::draw()
     double x = ProbeOptions_Number[0].def;
     double y = ProbeOptions_Number[1].def;
     double z = ProbeOptions_Number[2].def;
+    drawContext *ctx = (drawContext*)context;
     glColor4ubv((GLubyte *) & CTX.color.fg);
     glLineWidth(CTX.line_width);
     SBoundingBox3d bb = PView::list[num]->getData()->getBoundingBox();
@@ -55,14 +57,14 @@ void GMSH_ProbePlugin::draw()
     }
     else{
       // draw 10-pixel marker
-      double d = 10 * CTX.pixel_equiv_x / CTX.s[0];
+      double d = 10 * ctx->pixel_equiv_x / ctx->s[0];
       glBegin(GL_LINES);
       glVertex3d(x - d, y, z); glVertex3d(x + d, y, z);
       glVertex3d(x, y - d, z); glVertex3d(x, y + d, z);
       glVertex3d(x, y, z - d); glVertex3d(x, y, z + d);
       glEnd();
     }
-    Draw_Sphere(CTX.point_size, x, y, z, 1);
+    ctx->drawSphere(CTX.point_size, x, y, z, 1);
   }
 #endif
 }
diff --git a/Plugin/Probe.h b/Plugin/Probe.h
index 8504301fb930516470e21dff98c8816139def37d..1367774c1a0400d37ac769e4432d6ba0a4a4666b 100644
--- a/Plugin/Probe.h
+++ b/Plugin/Probe.h
@@ -30,7 +30,7 @@ public:
   static double callbackX(int, int, double);
   static double callbackY(int, int, double);
   static double callbackZ(int, int, double);
-  static void draw();
+  static void draw(void *context);
 };
 
 #endif
diff --git a/Plugin/StreamLines.cpp b/Plugin/StreamLines.cpp
index 7e984054601cc6b3aab69e726f20b7f3be641a78..74877316f2bdd4493e4f28a732f9efb9f8e7e454 100644
--- a/Plugin/StreamLines.cpp
+++ b/Plugin/StreamLines.cpp
@@ -11,6 +11,7 @@
 
 #if defined(HAVE_FLTK)
 #include "GmshUI.h"
+#include "drawContext.h"
 #include "Draw.h"
 #endif
 
@@ -43,15 +44,16 @@ extern "C"
   }
 }
 
-void GMSH_StreamLinesPlugin::draw()
+void GMSH_StreamLinesPlugin::draw(void *context)
 {
 #if defined(HAVE_FLTK)
   glColor4ubv((GLubyte *) & CTX.color.fg);
+  drawContext *ctx = (drawContext*)context;
   double p[3];
   for(int i = 0; i < getNbU(); ++i){
     for(int j = 0; j < getNbV(); ++j){
       getPoint(i, j, p);
-      Draw_Sphere(CTX.point_size, p[0], p[1], p[2], 1);
+      ctx->drawSphere(CTX.point_size, p[0], p[1], p[2], 1);
     }
   }
 #endif
diff --git a/Plugin/StreamLines.h b/Plugin/StreamLines.h
index a4ba37480f0dc810bf922d3f20633a93e44d6975..1e75981f6aa741056b2e57c5a5456242f0b5096f 100644
--- a/Plugin/StreamLines.h
+++ b/Plugin/StreamLines.h
@@ -41,7 +41,7 @@ public:
   static double callbackZ2(int, int, double);
   static double callbackU(int, int, double);
   static double callbackV(int, int, double);
-  static void draw();
+  static void draw(void *context);
 };
 
 #endif
diff --git a/contrib/Chaco/Makefile b/contrib/Chaco/Makefile
index d6a164806b2c5451e7ff8a97932ba440c764afb9..924338152bf05ba8f1d6cd9cccff7bf51c1c3581 100644
--- a/contrib/Chaco/Makefile
+++ b/contrib/Chaco/Makefile
@@ -108,13 +108,7 @@ ${LIB}: ${OBJ} ${OBJX}
 clean:
 	rm -f */*.o */*.obj
 
-# Doesn't quite work
-# depend:
-# 	(sed '/^# DO NOT DELETE THIS LINE/q' Makefile && \
-# 	${CXX} -MM ${CFLAGS} ${SRC} \
-# 	) >Makefile.new
-# 	cp Makefile Makefile.bak
-# 	cp Makefile.new Makefile
-# 	rm -f Makefile.new
+depend:
+	true
 
 # DO NOT DELETE THIS LINE
diff --git a/contrib/Netgen/Makefile b/contrib/Netgen/Makefile
index 3d3fe7cf2bcb470480e3ab693b8440a6e8431eae..ddf833a49eaea2fb8e73250d137e0451d5efa3a7 100644
--- a/contrib/Netgen/Makefile
+++ b/contrib/Netgen/Makefile
@@ -52,4 +52,3 @@ depend:
 	true
 
 # DO NOT DELETE THIS LINE
-nglib_addon${OBJEXT}: ../../Common/GmshMessage.h
diff --git a/doc/CREDITS.txt b/doc/CREDITS.txt
index ea1eb3280235c107834a8b4737325eff2dba2cb3..8841252e827ecf547ac5a3b41590563c26491e3e 100644
--- a/doc/CREDITS.txt
+++ b/doc/CREDITS.txt
@@ -36,7 +36,7 @@ written prior permission. The University of California makes no
 representations about the suitability of this software for any
 purpose. It is provided "as is" without express or implied warranty.
 
-The trackball code (Common/Trackball.*) is copyright (C) 1993, 1994,
+The trackball code (Graphics/Trackball.*) is copyright (C) 1993, 1994,
 Silicon Graphics, Inc. ALL RIGHTS RESERVED. Permission to use, copy,
 modify, and distribute this software for any purpose and without fee
 is hereby granted, provided that the above copyright notice appear in