diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp
index ea120c46931a98bd829593ba90936f349e9671d9..8b3b39130bc10cbf38e68336e0c81d8e4ca17c5d 100644
--- a/Fltk/Callbacks.cpp
+++ b/Fltk/Callbacks.cpp
@@ -1,4 +1,4 @@
-// $Id: Callbacks.cpp,v 1.338 2005-03-09 02:18:40 geuzaine Exp $
+// $Id: Callbacks.cpp,v 1.339 2005-03-09 09:21:26 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -888,6 +888,15 @@ void mesh_cut_plane_cb(CALLBACK_ARGS)
   CTX.mesh.draw = 1;
 }
 
+void mesh_cut_plane_invert_cb(CALLBACK_ARGS)
+{
+  WID->mesh_value[14]->value(-WID->mesh_value[14]->value());
+  WID->mesh_value[15]->value(-WID->mesh_value[15]->value());
+  WID->mesh_value[16]->value(-WID->mesh_value[16]->value());
+  WID->mesh_value[17]->value(-WID->mesh_value[17]->value());
+  mesh_cut_plane_cb(NULL, NULL);
+}
+
 // Solver options
 
 void solver_options_cb(CALLBACK_ARGS)
@@ -1220,6 +1229,13 @@ void clip_update_cb(CALLBACK_ARGS)
   CTX.mesh.draw = 1;
 }
 
+void clip_invert_cb(CALLBACK_ARGS)
+{
+  for(int i = 0; i < 4; i++)
+    WID->clip_value[i]->value(-WID->clip_value[i]->value());
+  clip_update_cb(NULL, NULL);
+}
+
 void clip_reset_cb(CALLBACK_ARGS)
 {
   for(int i = 0; i < 6; i++){
diff --git a/Fltk/Callbacks.h b/Fltk/Callbacks.h
index 0d274e8baf130d3da90633d44a27866f070ae4c6..cf635fe910f072f63ba4b7e94e4f0408f54e6d46 100644
--- a/Fltk/Callbacks.h
+++ b/Fltk/Callbacks.h
@@ -95,6 +95,7 @@ void geometry_options_ok_cb(CALLBACK_ARGS);
 void mesh_options_cb(CALLBACK_ARGS);
 void mesh_options_ok_cb(CALLBACK_ARGS);
 void mesh_cut_plane_cb(CALLBACK_ARGS);
+void mesh_cut_plane_invert_cb(CALLBACK_ARGS);
 
 void solver_options_cb(CALLBACK_ARGS);
 void solver_options_ok_cb(CALLBACK_ARGS);
@@ -161,6 +162,7 @@ void visibility_ok_cb(CALLBACK_ARGS);
 
 void clip_cb(CALLBACK_ARGS);
 void clip_update_cb(CALLBACK_ARGS);
+void clip_invert_cb(CALLBACK_ARGS);
 void clip_num_cb(CALLBACK_ARGS);
 void clip_reset_cb(CALLBACK_ARGS);
 
diff --git a/Fltk/GUI.cpp b/Fltk/GUI.cpp
index d4fadede3a28c4f5075d2a864adf0ef1fca4a934..11ef99c39b537c1318ed01c2ab193dd55d82269d 100644
--- a/Fltk/GUI.cpp
+++ b/Fltk/GUI.cpp
@@ -1,4 +1,4 @@
-// $Id: GUI.cpp,v 1.419 2005-02-20 06:36:53 geuzaine Exp $
+// $Id: GUI.cpp,v 1.420 2005-03-09 09:21:26 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -2215,28 +2215,33 @@ void GUI::create_option_window()
       mesh_butt[16]->down_box(GMSH_TOGGLE_BOX);
       mesh_butt[16]->selection_color(GMSH_TOGGLE_COLOR);
 
-      mesh_value[14] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 2 * BH, IW, BH, "A");
+      int ii = fontsize;
+      Fl_Button *invert = new Fl_Button(L + 2 * WB, 2 * WB + 2 * BH, ii, 4*BH, "-");
+      invert->callback(mesh_cut_plane_invert_cb);
+      invert->tooltip("Invert orientation");
+
+      mesh_value[14] = new Fl_Value_Input(L + 2 * WB + ii, 2 * WB + 2 * BH, IW - ii, BH, "A");
       mesh_value[14]->align(FL_ALIGN_RIGHT);
       mesh_value[14]->callback(mesh_cut_plane_cb);
       mesh_value[14]->step(0.01);
       mesh_value[14]->minimum(-1.0);
       mesh_value[14]->maximum(1.0);
 
-      mesh_value[15] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 3 * BH, IW, BH, "B");
+      mesh_value[15] = new Fl_Value_Input(L + 2 * WB + ii, 2 * WB + 3 * BH, IW - ii, BH, "B");
       mesh_value[15]->align(FL_ALIGN_RIGHT);
       mesh_value[15]->callback(mesh_cut_plane_cb);
       mesh_value[15]->step(0.01);
       mesh_value[15]->minimum(-1.0);
       mesh_value[15]->maximum(1.0);
 
-      mesh_value[16] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 4 * BH, IW, BH, "C");
+      mesh_value[16] = new Fl_Value_Input(L + 2 * WB + ii, 2 * WB + 4 * BH, IW - ii, BH, "C");
       mesh_value[16]->align(FL_ALIGN_RIGHT);
       mesh_value[16]->callback(mesh_cut_plane_cb);
       mesh_value[16]->step(0.01);
       mesh_value[16]->minimum(-1.0);
       mesh_value[16]->maximum(1.0);
 
-      mesh_value[17] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 5 * BH, IW, BH, "D");
+      mesh_value[17] = new Fl_Value_Input(L + 2 * WB + ii, 2 * WB + 5 * BH, IW - ii, BH, "D");
       mesh_value[17]->align(FL_ALIGN_RIGHT);
       mesh_value[17]->callback(mesh_cut_plane_cb);
       mesh_value[17]->step(0.01);
@@ -3680,10 +3685,15 @@ void GUI::create_clip_window()
   clip_choice->menu(plane_number);
   clip_choice->callback(clip_num_cb);
 
-  clip_value[0] = new Fl_Value_Input(2 * WB + brw, 1 * WB + 1 * BH, BW, BH, "A");
-  clip_value[1] = new Fl_Value_Input(2 * WB + brw, 1 * WB + 2 * BH, BW, BH, "B");
-  clip_value[2] = new Fl_Value_Input(2 * WB + brw, 1 * WB + 3 * BH, BW, BH, "C");
-  clip_value[3] = new Fl_Value_Input(2 * WB + brw, 1 * WB + 4 * BH, BW, BH, "D");
+  int ii = fontsize;
+  Fl_Button *invert = new Fl_Button(2 * WB + brw, 1 * WB + 1 * BH, ii, 4*BH, "-");
+  invert->callback(clip_invert_cb);
+  invert->tooltip("Invert orientation");
+
+  clip_value[0] = new Fl_Value_Input(2 * WB + brw + ii, 1 * WB + 1 * BH, BW - ii, BH, "A");
+  clip_value[1] = new Fl_Value_Input(2 * WB + brw + ii, 1 * WB + 2 * BH, BW - ii, BH, "B");
+  clip_value[2] = new Fl_Value_Input(2 * WB + brw + ii, 1 * WB + 3 * BH, BW - ii, BH, "C");
+  clip_value[3] = new Fl_Value_Input(2 * WB + brw + ii, 1 * WB + 4 * BH, BW - ii, BH, "D");
   for(int i = 0; i < 4; i++){
     clip_value[i]->align(FL_ALIGN_RIGHT);
     clip_value[i]->callback(clip_update_cb);
diff --git a/Graphics/Entity.cpp b/Graphics/Entity.cpp
index 9af59771f290c055128382de99d8a54d731f79f3..111813b822b4d3f35f6fb1b5f83d42d651710051 100644
--- a/Graphics/Entity.cpp
+++ b/Graphics/Entity.cpp
@@ -1,4 +1,4 @@
-// $Id: Entity.cpp,v 1.55 2005-03-09 08:07:35 geuzaine Exp $
+// $Id: Entity.cpp,v 1.56 2005-03-09 09:21:26 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -26,107 +26,8 @@
 #include "Numeric.h"
 #include "Draw.h"
 #include "Context.h"
-extern Context_T CTX;
-
-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_PlaneInBoundingBox(double xmin, double ymin, double zmin,
-			     double xmax, double ymax, double zmax,
-			     double a, double b, double c, double d)
-{
-
-  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};
-  norme(n);
-  n[0] *= 50 * CTX.pixel_equiv_x / CTX.s[0];
-  n[1] *= 50 * CTX.pixel_equiv_x / CTX.s[1];
-  n[2] *= 50 * CTX.pixel_equiv_x / CTX.s[2];
-  
-  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){
-      glBegin(GL_LINE_STRIP);
-      for(int j = 0; j < nb; j++)
-	glVertex3d(p[j].x, p[j].y, p[j].z);
-      glEnd();
-      for(int j = 0; j < nb; j++)
-	Draw_Vector(CTX.vector_type, 0, 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], 1);
-    }
-  }
-}
+extern Context_T CTX;
 
 void Draw_Point(int type, double size, double *x, double *y, double *z,
                 int light)
@@ -154,6 +55,7 @@ void Draw_Sphere(double size, double x, double y, double z, int light)
     gluSphere(qua, 1, CTX.quadric_subdivisions, CTX.quadric_subdivisions);
     glEndList();
   }
+
   glPushMatrix();
   glTranslated(x, y, z);
   glScaled(s, s, s);
@@ -177,6 +79,7 @@ void Draw_Disk(double size, double rint, double x, double y, double z, int light
     gluDisk(qua, rint, 1, 2*CTX.quadric_subdivisions, 2*CTX.quadric_subdivisions);
     glEndList();
   }
+
   glPushMatrix();
   glTranslated(x, y, z);
   glScaled(s, s, s);
@@ -197,8 +100,6 @@ void Draw_Cylinder(double width, double *x, double *y, double *z, int light)
     qua = gluNewQuadric();
   }
 
-  glPushMatrix();
-
   double dx = x[1] - x[0];
   double dy = y[1] - y[0];
   double dz = z[1] - z[0];
@@ -216,6 +117,7 @@ void Draw_Cylinder(double width, double *x, double *y, double *z, int light)
   }
   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);
@@ -428,8 +330,6 @@ void Draw_3DArrow(double relHeadRadius, double relStemLength, double relStemRadi
     qua = gluNewQuadric();
   }
 
-  glPushMatrix();
-
   double zdir[3] = {0., 0., 1.};
   double vdir[3] = {dx/length, dy/length, dz/length};
   double axis[3], cosphi, phi;
@@ -442,9 +342,9 @@ void Draw_3DArrow(double relHeadRadius, double relStemLength, double relStemRadi
   }
   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);
@@ -453,12 +353,10 @@ void Draw_3DArrow(double relHeadRadius, double relStemLength, double relStemRadi
   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);
@@ -498,7 +396,108 @@ void Draw_Vector(int Type, int Fill,
 
 }
 
+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_PlaneInBoundingBox(double xmin, double ymin, double zmin,
+			     double xmax, double ymax, double zmax,
+			     double a, double b, double c, double d)
+{
+
+  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]);
 
+  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);
+      }
+    }
+  }
+}
diff --git a/doc/VERSIONS b/doc/VERSIONS
index 72f6bea5cedbe6f4f5715c95c0d6ce89838527e0..8c5d6434ea8e482f24ae95c9c3fd1f73e2d06f24 100644
--- a/doc/VERSIONS
+++ b/doc/VERSIONS
@@ -1,10 +1,11 @@
-$Id: VERSIONS,v 1.314 2005-03-09 02:26:32 geuzaine Exp $
+$Id: VERSIONS,v 1.315 2005-03-09 09:21:26 geuzaine Exp $
 
 New since 1.59: added support for discrete curves; new Window menu on
 Mac OS X; generalized all octree-based plugins (CutGrid, StreamLines,
 Probe, etc.) to handle all element types (and not only scalar and
 vector triangles+tetrahedra); generalized Plugin(Evaluate) and
-Plugin(Extract); various small enhancements and bug fixes.
+Plugin(Extract); enhanced clipping plane interface; various small
+enhancements and bug fixes.
 
 New in 1.59: added support for discrete (triangulated) surfaces,
 either in STL format or with the new "Discrete Surface" command; added