diff --git a/Geo/GEntity.h b/Geo/GEntity.h
index 80f75f24d6f7ffaa9a20449c0b22fa21ef70971d..adc4b0c9e4caa8a8e972df3c6d3e0f15a37522fb 100644
--- a/Geo/GEntity.h
+++ b/Geo/GEntity.h
@@ -22,10 +22,10 @@ class GEntity {
 
  private:
   GModel *_model;
+  MRep *_mrep;
   int _tag;
-  MRep *_geom, *_mesh;
   char _visible, _flag;
-
+  
  public:
 
   // All known entity types
@@ -43,11 +43,13 @@ class GEntity {
     Sphere,
     Cone,
     Torus,
+    RuledSurface,
     ParametricSurface,
     DiscreteSurface,
     Volume
   };
 
+  // Returns a string describing the entity type
   virtual std::string getTypeString()
   {
     char *name[] = {
@@ -64,6 +66,7 @@ class GEntity {
       "Sphere",
       "Cone",
       "Torus",
+      "Ruled surface",
       "Parametric surface",
       "Discrete surface",
       "Volume"
@@ -75,7 +78,7 @@ class GEntity {
       return name[type];
   }
 
-  GEntity(GModel *m, int t) : _model(m), _tag(t), _visible(true), _flag(0) {}
+  GEntity(GModel *m, int t) : _model(m), _mrep(0), _tag(t), _visible(true), _flag(0) {}
 
   virtual ~GEntity() {};
 
@@ -138,12 +141,6 @@ class GEntity {
   virtual char getFlag(){ return _flag; }
   virtual void setFlag(char val){ _flag = val; }
 
-  // Returns a renderable representation of the geometry
-  virtual MRep *geomRep(){ return _geom; }
-
-  // Returns a renderable representation of the mesh
-  virtual MRep *meshRep(){ return _mesh; }
-
   // Returns an information string for the entity
   virtual std::string getInfoString();
 
diff --git a/Geo/SVector3.cpp b/Geo/SVector3.cpp
index 9b50eaf29396ff389a484da23c4861124183ae73..4fd12a387428739a4387b7a71f2399375fcb88f5 100644
--- a/Geo/SVector3.cpp
+++ b/Geo/SVector3.cpp
@@ -42,7 +42,9 @@ double norm(const SVector3 &v)
 double SVector3::normalize()
 { 
   double n = norm(*this);
-  P[0] /= n; P[1]/= n; P[2] /= n;
+  if(n){
+    P[0] /= n; P[1]/= n; P[2] /= n;
+  }
   return n;
 }
 
diff --git a/Geo/gmshFace.cpp b/Geo/gmshFace.cpp
index 5ad0f936b06ff4f1c24ef82f05ec76dff2293cba..0fbc5259588c3a7e78fd24171dd4f457a3c4f305 100644
--- a/Geo/gmshFace.cpp
+++ b/Geo/gmshFace.cpp
@@ -195,6 +195,8 @@ GEntity::GeomType gmshFace::geomType() const
   switch(s->Typ){
   case MSH_SURF_NURBS: return Nurb;
   case MSH_SURF_PLAN: return Plane;
+  case MSH_SURF_REGL:
+  case MSH_SURF_TRIC: return RuledSurface;
   case MSH_SURF_DISCRETE: return DiscreteSurface;
   default: return Unknown;
   }
diff --git a/Graphics/Geom.cpp b/Graphics/Geom.cpp
index 3a2ac54377a09262ad551df10115bb3dea4939ed..9d3e4167f61d3bffaa368f2ddffa7c761cb09cf6 100644
--- a/Graphics/Geom.cpp
+++ b/Graphics/Geom.cpp
@@ -1,4 +1,4 @@
-// $Id: Geom.cpp,v 1.109 2006-08-13 06:59:14 geuzaine Exp $
+// $Id: Geom.cpp,v 1.110 2006-08-13 18:11:17 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -150,7 +150,8 @@ public :
       GPoint p = e->point(0.5 * (t_max - t_min));
       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;
+      double offset = (0.5 * CTX.geom.line_width + 0.3 * CTX.gl_fontsize) *
+	CTX.pixel_equiv_x;
       glRasterPos3d(p.x() + offset / CTX.s[0],
 		    p.y() + offset / CTX.s[1],
 		    p.z() + offset / CTX.s[2]);
@@ -160,10 +161,10 @@ public :
     if(CTX.geom.tangents) {
       double t = 0.5 * (t_max - t_min);
       GPoint p = e->point(t);
-      SVector3 der = e->firstDer(t) ;
-      double mod = sqrt(der[0] * der[0] + der[1] * der[1] + der[2] * der[2]);
+      SVector3 der = e->firstDer(t);
+      der.normalize();
       for(int i = 0; i < 3; i++)
-	der[i] = der[i] / mod * 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);
       Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
 		  CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius,
@@ -189,14 +190,14 @@ private:
       int N = 20;
       glBegin(GL_LINE_STRIP);
       for(int i = 0; i < N; i++) {
-	GPoint coords = f->point((double)i / (double)(N - 1), 0.5);
-	glVertex3d(coords.x(), coords.y(), coords.z());
+	GPoint p = f->point((double)i / (double)(N - 1), 0.5);
+	glVertex3d(p.x(), p.y(), p.z());
       }
       glEnd();
       glBegin(GL_LINE_STRIP);
       for(int i = 0; i < N; i++) {
-	GPoint coords = f->point(0.5, (double)i / (double)(N - 1));
-	glVertex3d(coords.x(), coords.y(), coords.z());
+	GPoint p = f->point(0.5, (double)i / (double)(N - 1));
+	glVertex3d(p.x(), p.y(), p.z());
       }
       glEnd();
       glDisable(GL_LINE_STIPPLE);
@@ -204,23 +205,21 @@ private:
     }
     
     if(CTX.geom.surfaces_num) {
-      GPoint coords = f->point(0.5, 0.5);
+      GPoint p = f->point(0.5, 0.5);
       char Num[100];
       sprintf(Num, "%d", f->tag());
       double offset = 0.3 * CTX.gl_fontsize * CTX.pixel_equiv_x;
-      glRasterPos3d(coords.x() + offset / CTX.s[0],
-		    coords.y() + offset / CTX.s[1],
-		    coords.z() + offset / CTX.s[2]);
+      glRasterPos3d(p.x() + offset / CTX.s[0],
+		    p.y() + offset / CTX.s[1],
+		    p.z() + offset / CTX.s[2]);
       Draw_String(Num);
     }
     
     if(CTX.geom.normals) {
-      SPoint2 p2 = SPoint2(0.5, 0.5);
-      SVector3 nn = f->normal(p2);
-      GPoint p = f->point(p2);
-      double n[3] = {nn.x() * CTX.geom.normals * CTX.pixel_equiv_x / CTX.s[0],
-		     nn.y() * CTX.geom.normals * CTX.pixel_equiv_x / CTX.s[1],
-		     nn.z() * CTX.geom.normals * CTX.pixel_equiv_x / CTX.s[2]};
+      GPoint p = f->point(0.5, 0.5);
+      SVector3 n = f->normal(SPoint2(0.5, 0.5));
+      for(int i = 0; i < 3; i++)
+	n[i] *= CTX.geom.normals * CTX.pixel_equiv_x / CTX.s[i];
       glColor4ubv((GLubyte *) & CTX.color.geom.normals);
       Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
 		  CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius,
@@ -258,19 +257,19 @@ private:
 	for(int i = 0; i < N; i++) {
 	  double t = (double)i / (double)(N - 1);
 	  double x, y, z;
-	  if(dir){
-	    x = t * 0.5 * (v0.x() + v1.x()) + (1. - t) * 0.5 * (v2.x() + v3.x());
-	    y = t * 0.5 * (v0.y() + v1.y()) + (1. - t) * 0.5 * (v2.y() + v3.y());
-	    z = t * 0.5 * (v0.z() + v1.z()) + (1. - t) * 0.5 * (v2.z() + v3.z());
+	  if(!dir){
+	    x = 0.5 * (t * (v0.x() + v1.x()) + (1. - t) * (v2.x() + v3.x()));
+	    y = 0.5 * (t * (v0.y() + v1.y()) + (1. - t) * (v2.y() + v3.y()));
+	    z = 0.5 * (t * (v0.z() + v1.z()) + (1. - t) * (v2.z() + v3.z()));
 	  }
 	  else{
-	    x = t * 0.5 * (v0.x() + v3.x()) + (1. - t) * 0.5 * (v2.x() + v1.x());
-	    y = t * 0.5 * (v0.y() + v3.y()) + (1. - t) * 0.5 * (v2.y() + v1.y());
-	    z = t * 0.5 * (v0.z() + v3.z()) + (1. - t) * 0.5 * (v2.z() + v1.z());
+	    x = 0.5 * (t * (v0.x() + v3.x()) + (1. - t) * (v2.x() + v1.x()));
+	    y = 0.5 * (t * (v0.y() + v3.y()) + (1. - t) * (v2.y() + v1.y()));
+	    z = 0.5 * (t * (v0.z() + v3.z()) + (1. - t) * (v2.z() + v1.z()));
 	  }
 	  pt.setPosition(x, y, z);
 	  if(f->containsPoint(pt)){
-	    pt_last_inside.setPosition(pt.x(), pt.y(), pt.z());
+	    pt_last_inside.setPosition(x, y, z);
 	    if(!end_line) { f->cross.push_back(pt); end_line = 1; }
 	  }
 	  else {
@@ -279,13 +278,13 @@ private:
 	}
 	if(end_line) f->cross.push_back(pt_last_inside);
       }
-      // if we couldn't determine a cross, add dummy point so that
+      // if we couldn't determine a cross, add a dummy point so that
       // we won't try again
       if(!f->cross.size()) f->cross.push_back(SPoint3(0., 0., 0.));
       CTX.threads_lock = 0;
     }
 
-    if(f->cross.size() < 2) return ;
+    if(f->cross.size() < 2) return;
 
     if(CTX.geom.surfaces) {
       glEnable(GL_LINE_STIPPLE);
@@ -314,10 +313,9 @@ private:
 		0.5 * (f->cross[0].y() + f->cross[1].y()),
 		0.5 * (f->cross[0].z() + f->cross[1].z()));
       SPoint2 uv = f->parFromPoint(p);
-      SVector3 nn = f->normal(uv);
-      double n[3] = {nn.x() * CTX.geom.normals * CTX.pixel_equiv_x / CTX.s[0],
-		     nn.y() * CTX.geom.normals * CTX.pixel_equiv_x / CTX.s[1],
-		     nn.z() * CTX.geom.normals * CTX.pixel_equiv_x / CTX.s[2]};
+      SVector3 n = f->normal(uv);
+      for(int i = 0; i < 3; i++)
+	n[i] *= CTX.geom.normals * CTX.pixel_equiv_x / CTX.s[i];
       glColor4ubv((GLubyte *) & CTX.color.geom.normals);
       Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
 		  CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius, 
diff --git a/Graphics/Mesh.cpp b/Graphics/Mesh.cpp
index 3b293abad3babe2daffaa29d8676347e7f4472ef..da6e90ad6f5555ed9692febc2db4be5add576605 100644
--- a/Graphics/Mesh.cpp
+++ b/Graphics/Mesh.cpp
@@ -1,4 +1,4 @@
-// $Id: Mesh.cpp,v 1.159 2006-08-12 17:44:25 geuzaine Exp $
+// $Id: Mesh.cpp,v 1.160 2006-08-13 18:11:17 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -64,19 +64,21 @@ void renumberFaceVertices(GFace *f, List_T *xyz)
 // define this to draw the vertex array by indexing elements
 //#define ELEM
 
-class drawMeshGFace 
+class drawMeshGFace
 {
 public :
-  void operator () (GFace *s)
+  void operator () (GFace *f)
   {  
-    if(!s->getVisibility())
+    if(!f->getVisibility())
       return;
     
     if(CTX.render_mode == GMSH_SELECT) {
       glPushName(2);
-      glPushName(s->tag());
+      glPushName(f->tag());
     }
 
+
+
 #if 0
     static int first = 1;
     static List_T *xyz;
@@ -84,9 +86,9 @@ public :
 
     if(first){
       first = 0;
-      printf("stripe surface %d\n", s->tag());
-      xyz = List_Create(s->mesh_vertices.size(), 1000, sizeof(float));
-      renumberFaceVertices(s, xyz);
+      printf("stripe surface %d\n", f->tag());
+      xyz = List_Create(f->mesh_vertices.size(), 1000, sizeof(float));
+      renumberFaceVertices(f, xyz);
 
       /*
       for(int i = 0; i < List_Nbr(xyz)/3; i+=3){
@@ -102,11 +104,11 @@ public :
       //actcParami(tc, ACTC_OUT_MAX_PRIM_VERTS, INT_MAX); // optimum 12?
       actcParami(tc, ACTC_OUT_MAX_PRIM_VERTS, 100); // optimum 12?
       actcBeginInput(tc);
-      for(unsigned int i = 0; i < s->triangles.size(); i++){
+      for(unsigned int i = 0; i < f->triangles.size(); i++){
 	actcAddTriangle(tc, 
-			s->triangles[i]->getVertex(0)->getNum(),
-			s->triangles[i]->getVertex(1)->getNum(),
-			s->triangles[i]->getVertex(2)->getNum());
+			f->triangles[i]->getVertex(0)->getNum(),
+			f->triangles[i]->getVertex(1)->getNum(),
+			f->triangles[i]->getVertex(2)->getNum());
       }
       actcEndInput(tc);
       actcBeginOutput(tc);
@@ -168,16 +170,16 @@ public :
 #endif
 
     unsigned int col;
-    if(s->getFlag() > 0){
+    if(f->getFlag() > 0){
       col = CTX.color.geom.surface_sel;
     }
     else if(CTX.mesh.color_carousel == 1){
-      col = CTX.color.mesh.carousel[abs(s->tag() % 20)];
+      col = CTX.color.mesh.carousel[abs(f->tag() % 20)];
     }
     else if(CTX.mesh.color_carousel == 2){
       int n = 1;
-      int np = s->physicals.size();
-      if(np) n = s->physicals[np - 1];
+      int np = f->physicals.size();
+      if(np) n = f->physicals[np - 1];
       col = CTX.color.mesh.carousel[abs(n % 20)];
     }
     else if(CTX.mesh.color_carousel == 3){
@@ -188,8 +190,8 @@ public :
     glColor4ubv((GLubyte *)&col);
 
     glBegin(GL_TRIANGLES);
-    for(unsigned int i = 0; i < s->triangles.size(); i++){
-      MTriangle *t = s->triangles[i];
+    for(unsigned int i = 0; i < f->triangles.size(); i++){
+      MTriangle *t = f->triangles[i];
       for(int j = 0; j < 3; j++){
 	MVertex *v = t->getVertex(j);
 	glVertex3d(v->x(), v->y(), v->z());