diff --git a/Common/Options.cpp b/Common/Options.cpp
index c0ce4f4a148953fc83c0e0bf62f10e584a9ae2ef..467550dc551bacc2bee8af6aff5d83ad4dc43c0b 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -1,4 +1,4 @@
-// $Id: Options.cpp,v 1.155 2004-05-22 01:24:16 geuzaine Exp $
+// $Id: Options.cpp,v 1.156 2004-05-25 04:10:03 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -3653,7 +3653,7 @@ double opt_mesh_nb_triangles(OPT_ARGS_NUM)
 {
   double s[50];
   GetStatistics(s);
-  return s[7] - s[8];
+  return s[7];
 }
 
 double opt_mesh_nb_quadrangles(OPT_ARGS_NUM)
diff --git a/Fltk/GUI.cpp b/Fltk/GUI.cpp
index 0f587700f085795b16b3c4e8f3f872c6f759f922..a25ff7b81ff13a3dcf7d0da2d69b4dfdbc23a5a1 100644
--- a/Fltk/GUI.cpp
+++ b/Fltk/GUI.cpp
@@ -1,4 +1,4 @@
-// $Id: GUI.cpp,v 1.305 2004-05-22 01:29:46 geuzaine Exp $
+// $Id: GUI.cpp,v 1.306 2004-05-25 04:10:03 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -2564,144 +2564,52 @@ void GUI::create_statistics_window()
 void GUI::set_statistics()
 {
 
-  int i, num = 0;
-  static double s[50], p[20];
+  int num = 0;
+  static double s[50];
   static char label[50][256];
 
   GetStatistics(s);
 
   // geom
-  sprintf(label[num], "%g", s[0]);
-  stat_value[num]->value(label[num]);
-  num++;
-  sprintf(label[num], "%g", s[1]);
-  stat_value[num]->value(label[num]);
-  num++;
-  sprintf(label[num], "%g", s[2]);
-  stat_value[num]->value(label[num]);
-  num++;
-  sprintf(label[num], "%g", s[3]);
-  stat_value[num]->value(label[num]);
-  num++;
+  sprintf(label[num], "%g", s[0]); stat_value[num]->value(label[num]); num++;
+  sprintf(label[num], "%g", s[1]); stat_value[num]->value(label[num]); num++;
+  sprintf(label[num], "%g", s[2]); stat_value[num]->value(label[num]); num++;
+  sprintf(label[num], "%g", s[3]); stat_value[num]->value(label[num]); num++;
 
   // mesh
-  sprintf(label[num], "%g", s[4]);
-  stat_value[num]->value(label[num]);
-  num++;
-  sprintf(label[num], "%g", s[5]);
-  stat_value[num]->value(label[num]);
-  num++;
-  sprintf(label[num], "%g", s[6]);
-  stat_value[num]->value(label[num]);
-  num++;
-  sprintf(label[num], "%g", s[16]);
-  stat_value[num]->value(label[num]);
-  num++;
-  sprintf(label[num], "%g", s[7] - s[8]);
-  stat_value[num]->value(label[num]);
-  num++;
-  sprintf(label[num], "%g", s[8]);
-  stat_value[num]->value(label[num]);
-  num++;
-  sprintf(label[num], "%g", s[9]);
-  stat_value[num]->value(label[num]);
-  num++;
-  sprintf(label[num], "%g", s[10]);
-  stat_value[num]->value(label[num]);
-  num++;
-  sprintf(label[num], "%g", s[11]);
-  stat_value[num]->value(label[num]);
-  num++;
-  sprintf(label[num], "%g", s[12]);
-  stat_value[num]->value(label[num]);
-  num++;
-
-  sprintf(label[num], "%g", s[13]);
-  stat_value[num]->value(label[num]);
-  num++;
-  sprintf(label[num], "%g", s[14]);
-  stat_value[num]->value(label[num]);
-  num++;
-  sprintf(label[num], "%g", s[15]);
-  stat_value[num]->value(label[num]);
-  num++;
-
-  sprintf(label[num], "%.4g (%.4g->%.4g)", s[17], s[19], s[18]);
-  stat_value[num]->value(label[num]);
-  num++;
-  sprintf(label[num], "%.4g (%.4g->%.4g)", s[20], s[22], s[21]);
-  stat_value[num]->value(label[num]);
-  num++;
-  sprintf(label[num], "%.4g (%.4g->%.4g)", s[23], s[25], s[24]);
-  stat_value[num]->value(label[num]);
-  num++;
+  sprintf(label[num], "%g", s[4]); stat_value[num]->value(label[num]); num++;
+  sprintf(label[num], "%g", s[5]); stat_value[num]->value(label[num]); num++;
+  sprintf(label[num], "%g", s[6]); stat_value[num]->value(label[num]); num++;
+  sprintf(label[num], "%g", s[16]); stat_value[num]->value(label[num]); num++;
+  sprintf(label[num], "%g", s[7]); stat_value[num]->value(label[num]); num++;
+  sprintf(label[num], "%g", s[8]); stat_value[num]->value(label[num]); num++;
+  sprintf(label[num], "%g", s[9]); stat_value[num]->value(label[num]); num++;
+  sprintf(label[num], "%g", s[10]); stat_value[num]->value(label[num]); num++;
+  sprintf(label[num], "%g", s[11]); stat_value[num]->value(label[num]); num++;
+  sprintf(label[num], "%g", s[12]); stat_value[num]->value(label[num]); num++;
+
+  sprintf(label[num], "%g", s[13]); stat_value[num]->value(label[num]); num++;
+  sprintf(label[num], "%g", s[14]); stat_value[num]->value(label[num]); num++;
+  sprintf(label[num], "%g", s[15]); stat_value[num]->value(label[num]); num++;
+
+  sprintf(label[num], "%.4g (%.4g->%.4g)", s[17], s[18], s[19]);
+  stat_value[num]->value(label[num]); num++;
+  sprintf(label[num], "%.4g (%.4g->%.4g)", s[20], s[21], s[22]);
+  stat_value[num]->value(label[num]); num++;
+  sprintf(label[num], "%.4g (%.4g->%.4g)", s[23], s[24], s[25]);
+  stat_value[num]->value(label[num]); num++;
 
   // post
-  p[0] = List_Nbr(CTX.post.list);
-  sprintf(label[num], "%g", p[0]);
-  stat_value[num]->value(label[num]);
-  num++;
-  p[1] = p[2] = p[3] = p[4] = p[5] = p[6] = p[7] = p[8] = p[9] = 0;
-  p[10] = p[11] = p[12] = p[13] = p[14] = p[15] = p[16] = p[17] = p[18] = 0;
-  for(i = 0; i < List_Nbr(CTX.post.list); i++) {
-    Post_View *v = (Post_View *) List_Pointer(CTX.post.list, i);
-    p[1] += v->NbSP + v->NbVP + v->NbTP;
-    p[2] += v->NbSL + v->NbVL + v->NbTL;
-    p[3] += v->NbST + v->NbVT + v->NbTT;
-    p[4] += v->NbSQ + v->NbVQ + v->NbTQ;
-    p[5] += v->NbSS + v->NbVS + v->NbTS;
-    p[6] += v->NbSH + v->NbVH + v->NbTH;
-    p[7] += v->NbSI + v->NbVI + v->NbTI;
-    p[8] += v->NbSY + v->NbVY + v->NbTY;
-    p[9] += v->NbT2 + v->NbT3;
-    if(v->Visible) {
-      if(v->DrawPoints)
-        p[10] += (v->DrawScalars ? v->NbSP : 0) + (v->DrawVectors ? v->NbVP : 0) + (v->DrawTensors ? v->NbTP : 0);
-      if(v->DrawLines)
-        p[11] += (v->DrawScalars ? v->NbSL : 0) + (v->DrawVectors ? v->NbVL : 0) + (v->DrawTensors ? v->NbTL : 0);
-      if(v->DrawTriangles)
-        p[12] += (v->DrawScalars ? v->NbST : 0) + (v->DrawVectors ? v->NbVT : 0) + (v->DrawTensors ? v->NbTT : 0);
-      if(v->DrawQuadrangles)
-        p[13] += (v->DrawScalars ? v->NbSQ : 0) + (v->DrawVectors ? v->NbVQ : 0) + (v->DrawTensors ? v->NbTQ : 0);
-      if(v->DrawTetrahedra)
-        p[14] += (v->DrawScalars ? v->NbSS : 0) + (v->DrawVectors ? v->NbVS : 0) + (v->DrawTensors ? v->NbTS : 0);
-      if(v->DrawHexahedra)
-        p[15] += (v->DrawScalars ? v->NbSH : 0) + (v->DrawVectors ? v->NbVH : 0) + (v->DrawTensors ? v->NbTH : 0);
-      if(v->DrawPrisms)
-        p[16] += (v->DrawScalars ? v->NbSI : 0) + (v->DrawVectors ? v->NbVI : 0) + (v->DrawTensors ? v->NbTI : 0);
-      if(v->DrawPyramids)
-        p[17] += (v->DrawScalars ? v->NbSY : 0) + (v->DrawVectors ? v->NbVY : 0) + (v->DrawTensors ? v->NbTY : 0);
-      if(v->DrawStrings)
-        p[18] += v->NbT2 + v->NbT3;
-    }
-  }
-  sprintf(label[num], "%g/%g", p[10], p[1]);
-  stat_value[num]->value(label[num]);
-  num++;
-  sprintf(label[num], "%g/%g", p[11], p[2]);
-  stat_value[num]->value(label[num]);
-  num++;
-  sprintf(label[num], "%g/%g", p[12], p[3]);
-  stat_value[num]->value(label[num]);
-  num++;
-  sprintf(label[num], "%g/%g", p[13], p[4]);
-  stat_value[num]->value(label[num]);
-  num++;
-  sprintf(label[num], "%g/%g", p[14], p[5]);
-  stat_value[num]->value(label[num]);
-  num++;
-  sprintf(label[num], "%g/%g", p[15], p[6]);
-  stat_value[num]->value(label[num]);
-  num++;
-  sprintf(label[num], "%g/%g", p[16], p[7]);
-  stat_value[num]->value(label[num]);
-  num++;
-  sprintf(label[num], "%g/%g", p[17], p[8]);
-  stat_value[num]->value(label[num]);
-  num++;
-  sprintf(label[num], "%g/%g", p[18], p[9]);
-  stat_value[num]->value(label[num]);
-  num++;
+  sprintf(label[num], "%g", s[26]); stat_value[num]->value(label[num]); num++;
+  sprintf(label[num], "%g/%g", s[36], s[27]); stat_value[num]->value(label[num]); num++;
+  sprintf(label[num], "%g/%g", s[37], s[28]); stat_value[num]->value(label[num]); num++;
+  sprintf(label[num], "%g/%g", s[38], s[29]); stat_value[num]->value(label[num]); num++;
+  sprintf(label[num], "%g/%g", s[39], s[30]); stat_value[num]->value(label[num]); num++;
+  sprintf(label[num], "%g/%g", s[40], s[31]); stat_value[num]->value(label[num]); num++;
+  sprintf(label[num], "%g/%g", s[41], s[32]); stat_value[num]->value(label[num]); num++;
+  sprintf(label[num], "%g/%g", s[42], s[33]); stat_value[num]->value(label[num]); num++;
+  sprintf(label[num], "%g/%g", s[43], s[34]); stat_value[num]->value(label[num]); num++;
+  sprintf(label[num], "%g/%g", s[44], s[35]); stat_value[num]->value(label[num]); num++;
 }
 
 
diff --git a/Geo/Makefile b/Geo/Makefile
index ae888f12c42c117bdf0f9734de617288dc5444f0..9604f4ab3424e3906be9f9998aad0ef6980846cb 100644
--- a/Geo/Makefile
+++ b/Geo/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.48 2004-04-24 03:51:59 geuzaine Exp $
+# $Id: Makefile,v 1.49 2004-05-25 04:10:03 geuzaine Exp $
 #
 # Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 #
@@ -95,9 +95,10 @@ StepGeomDatabase.o: StepGeomDatabase.cpp ../Common/Gmsh.h \
   ../Common/Context.h
 ExtractContour.o: ExtractContour.cpp ../Common/Gmsh.h ../Common/Message.h \
   ../DataStr/Malloc.h ../DataStr/List.h ../DataStr/Tree.h \
-  ../DataStr/avl.h ../DataStr/Tools.h Geo.h CAD.h ../Mesh/Mesh.h \
+  ../DataStr/avl.h ../DataStr/Tools.h Geo.h GeoUtils.h ../Mesh/Mesh.h \
   ../Mesh/Vertex.h ../Mesh/Element.h ../Mesh/Simplex.h ../Mesh/Edge.h \
-  ../Geo/ExtrudeParams.h ../Mesh/STL.h ../Mesh/Metric.h ../Mesh/Matrix.h
+  ../Geo/ExtrudeParams.h ../Mesh/STL.h ../Mesh/Metric.h ../Mesh/Matrix.h \
+  CAD.h
 Print_Geo.o: Print_Geo.cpp ../Common/Gmsh.h ../Common/Message.h \
   ../DataStr/Malloc.h ../DataStr/List.h ../DataStr/Tree.h \
   ../DataStr/avl.h ../DataStr/Tools.h Geo.h ../Mesh/Mesh.h \
diff --git a/Graphics/CreateFile.cpp b/Graphics/CreateFile.cpp
index b7c2b34fc70653b6d48041b29c5bb438e87e8fe1..37c27d7e7847ce8ae50c3ea6d4cc460aea03e11b 100644
--- a/Graphics/CreateFile.cpp
+++ b/Graphics/CreateFile.cpp
@@ -1,4 +1,4 @@
-// $Id: CreateFile.cpp,v 1.60 2004-05-12 03:22:13 geuzaine Exp $
+// $Id: CreateFile.cpp,v 1.61 2004-05-25 04:10:03 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -74,51 +74,30 @@ void CreateOutputFile(char *name, int format)
     if(len <= 0)
       strcpy(ext, "");
 
-    if(!strcmp(ext, ".geo"))
-      CreateOutputFile(name, FORMAT_GEO);
-    else if(!strcmp(ext, ".opt"))
-      CreateOutputFile(name, FORMAT_OPT);
-    else if(!strcmp(ext, ".msh"))
-      CreateOutputFile(name, FORMAT_MSH);
-    else if(!strcmp(ext, ".unv"))
-      CreateOutputFile(name, FORMAT_UNV);
-    else if(!strcmp(ext, ".pos"))
-      CreateOutputFile(name, FORMAT_LC_SUR);
-    else if(!strcmp(ext, ".gif"))
-      CreateOutputFile(name, FORMAT_GIF);
-    else if(!strcmp(ext, ".jpg"))
-      CreateOutputFile(name, FORMAT_JPEG);
-    else if(!strcmp(ext, ".jpeg"))
-      CreateOutputFile(name, FORMAT_JPEG);
-    else if(!strcmp(ext, ".png"))
-      CreateOutputFile(name, FORMAT_PNG);
-    else if(!strcmp(ext, ".ps"))
-      CreateOutputFile(name, FORMAT_PS);
-    else if(!strcmp(ext, ".eps"))
-      CreateOutputFile(name, FORMAT_EPS);
-    else if(!strcmp(ext, ".pdf"))
-      CreateOutputFile(name, FORMAT_PDF);
-    else if(!strcmp(ext, ".tex"))
-      CreateOutputFile(name, FORMAT_TEX);
-    else if(!strcmp(ext, ".epstex"))
-      CreateOutputFile(name, FORMAT_EPSTEX);
-    else if(!strcmp(ext, ".pdftex"))
-      CreateOutputFile(name, FORMAT_PDFTEX);
-    else if(!strcmp(ext, ".jpegtex"))
-      CreateOutputFile(name, FORMAT_JPEGTEX);
-    else if(!strcmp(ext, ".ppm"))
-      CreateOutputFile(name, FORMAT_PPM);
-    else if(!strcmp(ext, ".yuv"))
-      CreateOutputFile(name, FORMAT_YUV);
-    else if(!strcmp(ext, ".gref"))
-      CreateOutputFile(name, FORMAT_GREF);
-    else if(!strcmp(ext, ".Gref"))
-      CreateOutputFile(name, FORMAT_GREF);
-    else if(!strcmp(ext, ".wrl"))
-      CreateOutputFile(name, FORMAT_VRML);
+    if(!strcmp(ext, ".geo"))       CreateOutputFile(name, FORMAT_GEO);
+    else if(!strcmp(ext, ".opt"))  CreateOutputFile(name, FORMAT_OPT);
+    else if(!strcmp(ext, ".msh"))  CreateOutputFile(name, FORMAT_MSH);
+    else if(!strcmp(ext, ".unv"))  CreateOutputFile(name, FORMAT_UNV);
+    else if(!strcmp(ext, ".dmg"))  CreateOutputFile(name, FORMAT_DMG);
+    else if(!strcmp(ext, ".pos"))  CreateOutputFile(name, FORMAT_LC_SUR);
+    else if(!strcmp(ext, ".gif"))  CreateOutputFile(name, FORMAT_GIF);
+    else if(!strcmp(ext, ".jpg"))  CreateOutputFile(name, FORMAT_JPEG);
+    else if(!strcmp(ext, ".jpeg")) CreateOutputFile(name, FORMAT_JPEG);
+    else if(!strcmp(ext, ".png"))  CreateOutputFile(name, FORMAT_PNG);
+    else if(!strcmp(ext, ".ps"))   CreateOutputFile(name, FORMAT_PS);
+    else if(!strcmp(ext, ".eps"))  CreateOutputFile(name, FORMAT_EPS);
+    else if(!strcmp(ext, ".pdf"))  CreateOutputFile(name, FORMAT_PDF);
+    else if(!strcmp(ext, ".tex"))  CreateOutputFile(name, FORMAT_TEX);
+    else if(!strcmp(ext, ".epstex")) CreateOutputFile(name, FORMAT_EPSTEX);
+    else if(!strcmp(ext, ".pdftex")) CreateOutputFile(name, FORMAT_PDFTEX);
+    else if(!strcmp(ext, ".jpegtex")) CreateOutputFile(name, FORMAT_JPEGTEX);
+    else if(!strcmp(ext, ".ppm"))  CreateOutputFile(name, FORMAT_PPM);
+    else if(!strcmp(ext, ".yuv"))  CreateOutputFile(name, FORMAT_YUV);
+    else if(!strcmp(ext, ".gref")) CreateOutputFile(name, FORMAT_GREF);
+    else if(!strcmp(ext, ".Gref")) CreateOutputFile(name, FORMAT_GREF);
+    else if(!strcmp(ext, ".wrl"))  CreateOutputFile(name, FORMAT_VRML);
     else
-      Msg(GERROR, "Unknown extension '%s' for automatic format detection",
-          ext);
+      Msg(GERROR, "Unknown extension '%s' for automatic format detection", ext);
     break;
 
   case FORMAT_GEO:
@@ -131,6 +110,7 @@ void CreateOutputFile(char *name, int format)
 
   case FORMAT_MSH:
   case FORMAT_UNV:
+  case FORMAT_DMG:
   case FORMAT_GREF:
   case FORMAT_VRML:
     Print_Mesh(&M, name, format);
diff --git a/Graphics/Draw.h b/Graphics/Draw.h
index 80aac8ae6b3e96a6aa2fd03a8f38f65bd064b52b..20ff3c46629edb1e79eb96b4dfa486c513815e39 100644
--- a/Graphics/Draw.h
+++ b/Graphics/Draw.h
@@ -89,14 +89,13 @@ void Draw_Mesh_Extruded_Surfaces(void *a, void *b);
 void Draw_Mesh_Curves(void *a, void *b);
 void Draw_Mesh_Points(void *a, void *b);
 
-void Draw_Simplex_Volume(void *a, void *b);
-void Draw_Simplex_Surface(void *a, void *b);
-void Draw_Simplex_Surface_Simple(void *a, void *b);
-void Draw_Simplex_Curves(void *a,void *b);
-
-void Draw_Hexahedron_Volume(void *a, void *b);
-void Draw_Prism_Volume(void *a, void *b);
-void Draw_Pyramid_Volume(void *a, void *b);
+void Draw_Mesh_Tetrahedron(void *a, void *b);
+void Draw_Mesh_Triangle(void *a, void *b);
+void Draw_Mesh_Line(void *a,void *b);
+void Draw_Mesh_Quadrangle(void *a, void *b);
+void Draw_Mesh_Hexahedron(void *a, void *b);
+void Draw_Mesh_Prism(void *a, void *b);
+void Draw_Mesh_Pyramid(void *a, void *b);
 
 void Draw_ScalarPoint(Post_View *View, int preproNormals,
 		      double ValMin, double ValMax, 
diff --git a/Graphics/Geom.cpp b/Graphics/Geom.cpp
index 7f0cda03e9fd414a4b63ca306bc6d6804760436b..18dfc56968a4273f3520832beb9cd87f62f155eb 100644
--- a/Graphics/Geom.cpp
+++ b/Graphics/Geom.cpp
@@ -1,4 +1,4 @@
-// $Id: Geom.cpp,v 1.62 2004-05-22 01:29:46 geuzaine Exp $
+// $Id: Geom.cpp,v 1.63 2004-05-25 04:10:04 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -574,10 +574,10 @@ void Draw_Surface(void *a, void *b)
   }
 
   if(s->Typ == MSH_SURF_STL) {
-    Tree_Action(s->STL->Simplexes, Draw_Simplex_Surface);
+    Tree_Action(s->STL->Simplexes, Draw_Mesh_Triangle);
   }
   else if(s->Typ == MSH_SURF_DISCRETE) {
-    Tree_Action(s->Simplexes, Draw_Simplex_Surface);
+    Tree_Action(s->Simplexes, Draw_Mesh_Triangle);
   }
   else if(s->Typ == MSH_SURF_PLAN)
     Draw_Plane_Surface(s);
diff --git a/Graphics/Mesh.cpp b/Graphics/Mesh.cpp
index e630f4638edef5adfd93ba89bfa6ddec44410d31..e91d218bcf00eaee3fd38b27daf58e6f11045268 100644
--- a/Graphics/Mesh.cpp
+++ b/Graphics/Mesh.cpp
@@ -1,4 +1,4 @@
-// $Id: Mesh.cpp,v 1.82 2004-05-04 22:31:54 geuzaine Exp $
+// $Id: Mesh.cpp,v 1.83 2004-05-25 04:10:04 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -209,20 +209,10 @@ void Draw_Mesh(Mesh * M)
 void Draw_Mesh_Volumes(void *a, void *b)
 {
   Volume *v = *(Volume **) a;
-  Tree_Action(v->Simplexes, Draw_Simplex_Volume);
-  Tree_Action(v->Hexahedra, Draw_Hexahedron_Volume);
-  Tree_Action(v->Prisms, Draw_Prism_Volume);
-  Tree_Action(v->Pyramids, Draw_Pyramid_Volume);
-}
-
-int Test_Simple_Surface_Draw()
-{
-  if(CTX.mesh.use_cut_plane ||
-     CTX.mesh.explode != 1.0 ||
-     CTX.mesh.dual || CTX.mesh.surfaces_num || CTX.mesh.normals)
-    return 0;
-  //printf("simple simplex surface drawing\n");
-  return 1;
+  Tree_Action(v->Simplexes, Draw_Mesh_Tetrahedron);
+  Tree_Action(v->Hexahedra, Draw_Mesh_Hexahedron);
+  Tree_Action(v->Prisms, Draw_Mesh_Prism);
+  Tree_Action(v->Pyramids, Draw_Mesh_Pyramid);
 }
 
 void Draw_Mesh_Surfaces(void *a, void *b)
@@ -232,10 +222,8 @@ void Draw_Mesh_Surfaces(void *a, void *b)
   thePhysical = getFirstPhysical(MSH_PHYSICAL_SURFACE, s->Num);
   if(!(s->Visible & VIS_MESH))
     return;
-  if(!Test_Simple_Surface_Draw())
-    Tree_Action(s->Simplexes, Draw_Simplex_Surface);
-  else
-    Tree_Action(s->Simplexes, Draw_Simplex_Surface_Simple);
+  Tree_Action(s->Simplexes, Draw_Mesh_Triangle);
+  Tree_Action(s->Quadrangles, Draw_Mesh_Quadrangle);
 }
 
 void Draw_Mesh_Extruded_Surfaces(void *a, void *b)
@@ -244,10 +232,8 @@ void Draw_Mesh_Extruded_Surfaces(void *a, void *b)
   v = *(Volume **) a;
   if(!(v->Visible & VIS_MESH))
     return;
-  if(!Test_Simple_Surface_Draw())
-    Tree_Action(v->Simp_Surf, Draw_Simplex_Surface);
-  else
-    Tree_Action(v->Simp_Surf, Draw_Simplex_Surface_Simple);
+  Tree_Action(v->Simp_Surf, Draw_Mesh_Triangle);
+  Tree_Action(v->Quad_Surf, Draw_Mesh_Quadrangle);
 }
 
 void Draw_Mesh_Curves(void *a, void *b)
@@ -259,7 +245,7 @@ void Draw_Mesh_Curves(void *a, void *b)
   thePhysical = getFirstPhysical(MSH_PHYSICAL_LINE, c->Num);
   if(!(c->Visible & VIS_MESH))
     return;
-  Tree_Action(c->Simplexes, Draw_Simplex_Curves);
+  Tree_Action(c->Simplexes, Draw_Mesh_Line);
 }
 
 double intersectCutPlane(int num, Vertex **v, int *edges, int *faces)
@@ -338,7 +324,7 @@ void Draw_Mesh_Points(void *a, void *b)
   }
 }
 
-void Draw_Simplex_Curves(void *a, void *b)
+void Draw_Mesh_Line(void *a, void *b)
 {
   Simplex *s;
   double Xc = 0.0, Yc = 0.0, Zc = 0.0, m[3];
@@ -436,10 +422,65 @@ void glNormal3verts(Vertex *v0, Vertex *v1, Vertex *v2, double n[3])
   glNormal3dv(n);
 }
 
-void Draw_Simplex_Surface_Common(Simplex * s, int L, int K, 
-				 double *pX, double *pY, double *pZ, double n[3])
+void Draw_Mesh_Triangle(void *a, void *b)
 {
-  int i;
+  double pX[6], pY[6], pZ[6];
+  double n[3];
+  char Num[256];
+
+  Simplex *s = *(Simplex **) a;
+
+  if(!s->V[2]) // the old extrusion algo puts lines in the simp_surf tree...
+    return;
+
+  if(!(s->Visible & VIS_MESH))
+    return;
+
+  MeshPartition **part = (MeshPartition**)List_Pointer_Test(THEM->Partitions, s->iPart);
+  if(part && !(*part)->Visible)
+    return;
+
+  if(intersectCutPlane(3, s->V) < 0)
+    return;
+
+  double Xc = (s->V[0]->Pos.X + s->V[1]->Pos.X + s->V[2]->Pos.X) / 3.;
+  double Yc = (s->V[0]->Pos.Y + s->V[1]->Pos.Y + s->V[2]->Pos.Y) / 3.;
+  double Zc = (s->V[0]->Pos.Z + s->V[1]->Pos.Z + s->V[2]->Pos.Z) / 3.;
+
+  int nn = s->VSUP ? 6 : 3;
+
+  int k = 0;
+  for(int i = 0; i < 3; i++) {
+    pX[k] = Xc + CTX.mesh.explode * (s->V[i]->Pos.X - Xc);
+    pY[k] = Yc + CTX.mesh.explode * (s->V[i]->Pos.Y - Yc);
+    pZ[k] = Zc + CTX.mesh.explode * (s->V[i]->Pos.Z - Zc);
+    k++;
+    if(s->VSUP){
+      pX[k] = Xc + CTX.mesh.explode * (s->VSUP[i]->Pos.X - Xc);
+      pY[k] = Yc + CTX.mesh.explode * (s->VSUP[i]->Pos.Y - Yc);
+      pZ[k] = Zc + CTX.mesh.explode * (s->VSUP[i]->Pos.Z - Zc);
+      k++;
+    }
+  }
+
+  if(CTX.mesh.dual) {
+    glColor4ubv((GLubyte *) & CTX.color.fg);
+    glEnable(GL_LINE_STIPPLE);
+    glLineStipple(1, 0x0F0F);
+    gl2psEnable(GL2PS_LINE_STIPPLE);
+    glBegin(GL_LINES);
+    int incr = s->VSUP ? 2 : 1;
+    for(int i = 0; i < nn; i+=incr) {
+      int j = i ? (i - 1) : 2;
+      glVertex3d(Xc, Yc, Zc);
+      glVertex3d((pX[i] + pX[j]) / 2.,
+		 (pY[i] + pY[j]) / 2.,
+		 (pZ[i] + pZ[j]) / 2.);
+    }
+    glEnd();
+    glDisable(GL_LINE_STIPPLE);
+    gl2psDisable(GL2PS_LINE_STIPPLE);
+  }
 
   if(CTX.mesh.normals || CTX.mesh.light)
     glNormal3verts(s->V[0], s->V[1], s->V[2], n);
@@ -456,17 +497,14 @@ void Draw_Simplex_Surface_Common(Simplex * s, int L, int K,
       ColorSwitch(thePhysical);
     else if(CTX.mesh.color_carousel == 3)
       ColorSwitch(s->iPart);
-    else if(K == 3)
-      glColor4ubv((GLubyte *) & CTX.color.mesh.triangle);
     else
-      glColor4ubv((GLubyte *) & CTX.color.mesh.quadrangle);
+      glColor4ubv((GLubyte *) & CTX.color.mesh.triangle);
   }
 
   if(CTX.mesh.surfaces_edges){
     glBegin(GL_LINE_LOOP);
-    for(i = 0; i < K * (1 + L); i++) {
+    for(int i = 0; i < nn; i++)
       glVertex3d(pX[i], pY[i], pZ[i]);
-    }
     glEnd();
   }
 
@@ -480,156 +518,101 @@ void Draw_Simplex_Surface_Common(Simplex * s, int L, int K,
       ColorSwitch(thePhysical);
     else if(CTX.mesh.color_carousel == 3)
       ColorSwitch(s->iPart);
-    else if(K == 3)
-      glColor4ubv((GLubyte *) & CTX.color.mesh.triangle);
     else
-      glColor4ubv((GLubyte *) & CTX.color.mesh.quadrangle);
+      glColor4ubv((GLubyte *) & CTX.color.mesh.triangle);
 
     if(CTX.mesh.light) glEnable(GL_LIGHTING);
     glEnable(GL_POLYGON_OFFSET_FILL);
 
-    if(!L) { // first order elements
-      if(K == 3) {
-	glBegin(GL_TRIANGLES);
-	glVertex3d(pX[0], pY[0], pZ[0]);
-	glVertex3d(pX[1], pY[1], pZ[1]);
-	glVertex3d(pX[2], pY[2], pZ[2]);
-	glEnd();
-      }
-      else {
-	glBegin(GL_QUADS);
-	glVertex3d(pX[0], pY[0], pZ[0]);
-	glVertex3d(pX[1], pY[1], pZ[1]);
-	glVertex3d(pX[2], pY[2], pZ[2]);
-	glVertex3d(pX[3], pY[3], pZ[3]);
-	glEnd();
-      }
+    if(!s->VSUP) { // first order elements
+      glBegin(GL_TRIANGLES);
+      glVertex3d(pX[0], pY[0], pZ[0]);
+      glVertex3d(pX[1], pY[1], pZ[1]);
+      glVertex3d(pX[2], pY[2], pZ[2]);
+      glEnd();
     }
     else {
-      if(K == 3) {
-	glBegin(GL_TRIANGLES);
-	glNormal3verts(s->V[0], s->VSUP[0], s->VSUP[2], n);
-	glVertex3d(pX[0], pY[0], pZ[0]);
-	glVertex3d(pX[1], pY[1], pZ[1]);
-	glVertex3d(pX[5], pY[5], pZ[5]);
-	glNormal3verts(s->VSUP[0], s->V[1], s->VSUP[1], n);
-	glVertex3d(pX[1], pY[1], pZ[1]);
-	glVertex3d(pX[2], pY[2], pZ[2]);
-	glVertex3d(pX[3], pY[3], pZ[3]);
-	glNormal3verts(s->VSUP[1], s->V[2], s->VSUP[2], n);
-	glVertex3d(pX[3], pY[3], pZ[3]);
-	glVertex3d(pX[4], pY[4], pZ[4]);
-	glVertex3d(pX[5], pY[5], pZ[5]);
-	glNormal3verts(s->VSUP[0], s->VSUP[1], s->VSUP[2], n);
-	glVertex3d(pX[1], pY[1], pZ[1]);
-	glVertex3d(pX[3], pY[3], pZ[3]);
-	glVertex3d(pX[5], pY[5], pZ[5]);
-	glEnd();
-      }
-      else {
-	// FIXME: should subdivide...
-	glBegin(GL_POLYGON);
-	for(i = 0; i < K * (1 + L); i++)
-	  glVertex3d(pX[i], pY[i], pZ[i]);
-	glEnd();
-      }
+      glBegin(GL_TRIANGLES);
+      glNormal3verts(s->V[0], s->VSUP[0], s->VSUP[2], n);
+      glVertex3d(pX[0], pY[0], pZ[0]);
+      glVertex3d(pX[1], pY[1], pZ[1]);
+      glVertex3d(pX[5], pY[5], pZ[5]);
+      glNormal3verts(s->VSUP[0], s->V[1], s->VSUP[1], n);
+      glVertex3d(pX[1], pY[1], pZ[1]);
+      glVertex3d(pX[2], pY[2], pZ[2]);
+      glVertex3d(pX[3], pY[3], pZ[3]);
+      glNormal3verts(s->VSUP[1], s->V[2], s->VSUP[2], n);
+      glVertex3d(pX[3], pY[3], pZ[3]);
+      glVertex3d(pX[4], pY[4], pZ[4]);
+      glVertex3d(pX[5], pY[5], pZ[5]);
+      glNormal3verts(s->VSUP[0], s->VSUP[1], s->VSUP[2], n);
+      glVertex3d(pX[1], pY[1], pZ[1]);
+      glVertex3d(pX[3], pY[3], pZ[3]);
+      glVertex3d(pX[5], pY[5], pZ[5]);
+      glEnd();
     }
     glDisable(GL_POLYGON_OFFSET_FILL);
     glDisable(GL_LIGHTING);
   }
-}
-
-void Draw_Simplex_Surface_Simple(void *a, void *b)
-{
-  Simplex *s;
-  int L, K;
-  double n[3], pX[8], pY[8], pZ[8];
-
-  s = *(Simplex **) a;
 
-  if(!s->V[2] || !(s->Visible & VIS_MESH))
-    return;
-
-  MeshPartition **part = (MeshPartition**)List_Pointer_Test(THEM->Partitions, s->iPart);
-  if(part && !(*part)->Visible)
-    return;
-
-  L = (s->VSUP) ? 1 : 0;
-  K = (s->V[3]) ? 4 : 3;
-
-  if(!L) {
-    for(int i = 0; i < K; i++) {
-      pX[i] = s->V[i]->Pos.X;
-      pY[i] = s->V[i]->Pos.Y;
-      pZ[i] = s->V[i]->Pos.Z;
-    }
+  if(CTX.mesh.surfaces_num) {
+    if(CTX.mesh.surfaces_faces)
+      glColor4ubv((GLubyte *) & CTX.color.mesh.line);
+    sprintf(Num, "%d", s->Num);
+    glRasterPos3d(Xc, Yc, Zc);
+    Draw_String(Num);
   }
-  else {
-    for(int i = 0; i < K; i++) {
-      pX[2*i] = s->V[i]->Pos.X;
-      pY[2*i] = s->V[i]->Pos.Y;
-      pZ[2*i] = s->V[i]->Pos.Z;
-      pX[2*i+1] = s->VSUP[i]->Pos.X;
-      pY[2*i+1] = s->VSUP[i]->Pos.Y;
-      pZ[2*i+1] = s->VSUP[i]->Pos.Z;
-    }
+
+  if(CTX.mesh.normals) {
+    norme(n);
+    glColor4ubv((GLubyte *) & CTX.color.mesh.normals);
+    n[0] *= CTX.mesh.normals * CTX.pixel_equiv_x / CTX.s[0];
+    n[1] *= CTX.mesh.normals * CTX.pixel_equiv_x / CTX.s[1];
+    n[2] *= CTX.mesh.normals * CTX.pixel_equiv_x / CTX.s[2];
+    Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
+		CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius,
+		Xc, Yc, Zc, n[0], n[1], n[2], NULL, CTX.mesh.light);
   }
-  
-  Draw_Simplex_Surface_Common(s, L, K, pX, pY, pZ, n);
 }
 
-void Draw_Simplex_Surface(void *a, void *b)
+void Draw_Mesh_Quadrangle(void *a, void *b)
 {
-  Simplex *s;
-  double Xc, Yc, Zc, pX[8], pY[8], pZ[8];
+  double pX[8], pY[8], pZ[8];
   double n[3];
-  int i, j, K, L, k;
   char Num[256];
 
-  s = *(Simplex **) a;
+  Quadrangle *q = *(Quadrangle **) a;
 
-  if(!s->V[2] || !(s->Visible & VIS_MESH))
+  if(!(q->Visible & VIS_MESH))
     return;
 
-  MeshPartition **part = (MeshPartition**)List_Pointer_Test(THEM->Partitions, s->iPart);
+  MeshPartition **part = (MeshPartition**)List_Pointer_Test(THEM->Partitions, q->iPart);
   if(part && !(*part)->Visible)
     return;
 
-  if(intersectCutPlane(3, s->V) < 0)
+  if(intersectCutPlane(4, q->V) < 0)
     return;
 
-  L = (s->VSUP) ? 1 : 0;
-  K = (s->V[3]) ? 4 : 3;
-
-  if(K == 4) {
-    Xc = .25 * (s->V[0]->Pos.X + s->V[1]->Pos.X +
-                s->V[2]->Pos.X + s->V[3]->Pos.X);
-    Yc = .25 * (s->V[0]->Pos.Y + s->V[1]->Pos.Y +
-                s->V[2]->Pos.Y + s->V[3]->Pos.Y);
-    Zc = .25 * (s->V[0]->Pos.Z + s->V[1]->Pos.Z +
-                s->V[2]->Pos.Z + s->V[3]->Pos.Z);
-  }
-  else {
-    Xc = (s->V[0]->Pos.X + s->V[1]->Pos.X + s->V[2]->Pos.X) / 3.;
-    Yc = (s->V[0]->Pos.Y + s->V[1]->Pos.Y + s->V[2]->Pos.Y) / 3.;
-    Zc = (s->V[0]->Pos.Z + s->V[1]->Pos.Z + s->V[2]->Pos.Z) / 3.;
-  }
+  double Xc = 0.25 * (q->V[0]->Pos.X + q->V[1]->Pos.X + 
+		      q->V[2]->Pos.X + q->V[3]->Pos.X);
+  double Yc = 0.25 * (q->V[0]->Pos.Y + q->V[1]->Pos.Y + 
+		      q->V[2]->Pos.Y + q->V[3]->Pos.Y);
+  double Zc = 0.25 * (q->V[0]->Pos.Z + q->V[1]->Pos.Z + 
+		      q->V[2]->Pos.Z + q->V[3]->Pos.Z);
 
-  k = 0;
-  for(i = 0; i < K; i++) {
-    pX[k] = Xc + CTX.mesh.explode * (s->V[i]->Pos.X - Xc);
-    pY[k] = Yc + CTX.mesh.explode * (s->V[i]->Pos.Y - Yc);
-    pZ[k] = Zc + CTX.mesh.explode * (s->V[i]->Pos.Z - Zc);
-    k += (L + 1);
-  }
+  int nn = q->VSUP ? 8 : 4;
 
-  if(L) {
-    k = 1;
-    for(i = 0; i < K; i++) {
-      pX[k] = Xc + CTX.mesh.explode * (s->VSUP[i]->Pos.X - Xc);
-      pY[k] = Yc + CTX.mesh.explode * (s->VSUP[i]->Pos.Y - Yc);
-      pZ[k] = Zc + CTX.mesh.explode * (s->VSUP[i]->Pos.Z - Zc);
-      k += (L + 1);
+  int k = 0;
+  for(int i = 0; i < 4; i++) {
+    pX[k] = Xc + CTX.mesh.explode * (q->V[i]->Pos.X - Xc);
+    pY[k] = Yc + CTX.mesh.explode * (q->V[i]->Pos.Y - Yc);
+    pZ[k] = Zc + CTX.mesh.explode * (q->V[i]->Pos.Z - Zc);
+    k++;
+    if(q->VSUP){
+      pX[k] = Xc + CTX.mesh.explode * (q->VSUP[i]->Pos.X - Xc);
+      pY[k] = Yc + CTX.mesh.explode * (q->VSUP[i]->Pos.Y - Yc);
+      pZ[k] = Zc + CTX.mesh.explode * (q->VSUP[i]->Pos.Z - Zc);
+      k++;
     }
   }
 
@@ -639,23 +622,83 @@ void Draw_Simplex_Surface(void *a, void *b)
     glLineStipple(1, 0x0F0F);
     gl2psEnable(GL2PS_LINE_STIPPLE);
     glBegin(GL_LINES);
-    for(i = 0; i < K; i++) {
-      (!i) ? j = K - 1 : j = i - 1;
+    int incr = q->VSUP ? 2 : 1;
+    for(int i = 0; i < nn; i+=incr) {
+      int j = i ? (i - 1) : 3;
       glVertex3d(Xc, Yc, Zc);
-      glVertex3d((pX[i] + pX[j]) / 2., (pY[i] + pY[j]) / 2.,
-                 (pZ[i] + pZ[j]) / 2.);
+      glVertex3d((pX[i] + pX[j]) / 2.,
+		 (pY[i] + pY[j]) / 2.,
+		 (pZ[i] + pZ[j]) / 2.);
     }
     glEnd();
     glDisable(GL_LINE_STIPPLE);
     gl2psDisable(GL2PS_LINE_STIPPLE);
   }
 
-  Draw_Simplex_Surface_Common(s, L, K, pX, pY, pZ, n);
+  if(CTX.mesh.normals || CTX.mesh.light)
+    glNormal3verts(q->V[0], q->V[1], q->V[2], n);
+
+  if(CTX.mesh.surfaces_faces){
+    glColor4ubv((GLubyte *) & CTX.color.mesh.line);
+  }
+  else{
+    if(theColor.type)
+      glColor4ubv((GLubyte *) & theColor.mesh);
+    else if(CTX.mesh.color_carousel == 1)
+      ColorSwitch(q->iEnt);
+    else if(CTX.mesh.color_carousel == 2)
+      ColorSwitch(thePhysical);
+    else if(CTX.mesh.color_carousel == 3)
+      ColorSwitch(q->iPart);
+    else
+      glColor4ubv((GLubyte *) & CTX.color.mesh.quadrangle);
+  }
+
+  if(CTX.mesh.surfaces_edges){
+    glBegin(GL_LINE_LOOP);
+    for(int i = 0; i < nn; i++)
+      glVertex3d(pX[i], pY[i], pZ[i]);
+    glEnd();
+  }
+
+  if(CTX.mesh.surfaces_faces) {
+
+    if(theColor.type)
+      glColor4ubv((GLubyte *) & theColor.mesh);
+    else if(CTX.mesh.color_carousel == 1)
+      ColorSwitch(q->iEnt);
+    else if(CTX.mesh.color_carousel == 2)
+      ColorSwitch(thePhysical);
+    else if(CTX.mesh.color_carousel == 3)
+      ColorSwitch(q->iPart);
+    else
+      glColor4ubv((GLubyte *) & CTX.color.mesh.quadrangle);
+
+    if(CTX.mesh.light) glEnable(GL_LIGHTING);
+    glEnable(GL_POLYGON_OFFSET_FILL);
+    if(!q->VSUP) { // first order elements
+      glBegin(GL_QUADS);
+      glVertex3d(pX[0], pY[0], pZ[0]);
+      glVertex3d(pX[1], pY[1], pZ[1]);
+      glVertex3d(pX[2], pY[2], pZ[2]);
+      glVertex3d(pX[3], pY[3], pZ[3]);
+      glEnd();
+    }
+    else {
+      // FIXME: should subdivide...
+      glBegin(GL_POLYGON);
+      for(int i = 0; i < nn; i++)
+	glVertex3d(pX[i], pY[i], pZ[i]);
+      glEnd();
+    }
+    glDisable(GL_POLYGON_OFFSET_FILL);
+    glDisable(GL_LIGHTING);
+  }
 
   if(CTX.mesh.surfaces_num) {
     if(CTX.mesh.surfaces_faces)
       glColor4ubv((GLubyte *) & CTX.color.mesh.line);
-    sprintf(Num, "%d", s->Num);
+    sprintf(Num, "%d", q->Num);
     glRasterPos3d(Xc, Yc, Zc);
     Draw_String(Num);
   }
@@ -672,7 +715,7 @@ void Draw_Simplex_Surface(void *a, void *b)
   }
 }
 
-void Draw_Simplex_Volume(void *a, void *b)
+void Draw_Mesh_Tetrahedron(void *a, void *b)
 {
   Simplex *s;
   char Num[100];
@@ -712,7 +755,7 @@ void Draw_Simplex_Volume(void *a, void *b)
   int edges = CTX.mesh.volumes_edges;
   int faces = CTX.mesh.volumes_faces;
 
-  if(intersectCutPlane(3, s->V, &edges, &faces) < 0)
+  if(intersectCutPlane(4, s->V, &edges, &faces) < 0)
     return;
 
   double Xc = .25 * (s->V[0]->Pos.X + s->V[1]->Pos.X +
@@ -926,7 +969,7 @@ void Draw_Simplex_Volume(void *a, void *b)
   }
 }
 
-void Draw_Hexahedron_Volume(void *a, void *b)
+void Draw_Mesh_Hexahedron(void *a, void *b)
 {
   Hexahedron *h;
   int i;
@@ -1115,7 +1158,7 @@ void Draw_Hexahedron_Volume(void *a, void *b)
 
 }
 
-void Draw_Prism_Volume(void *a, void *b)
+void Draw_Mesh_Prism(void *a, void *b)
 {
   Prism *p;
   int i;
@@ -1289,7 +1332,7 @@ void Draw_Prism_Volume(void *a, void *b)
   }
 }
 
-void Draw_Pyramid_Volume(void *a, void *b)
+void Draw_Mesh_Pyramid(void *a, void *b)
 {
   Pyramid *p;
   int i;
diff --git a/Makefile b/Makefile
index 7a0d078fdf826044d8567e9257da310fb526bd28..ce336bc1bedb59d317cbd9cdd90abab47186f112 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.345 2004-05-22 01:24:16 geuzaine Exp $
+# $Id: Makefile,v 1.346 2004-05-25 04:10:03 geuzaine Exp $
 #
 # Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 #
@@ -22,8 +22,8 @@
 include variables
 
 GMSH_MAJOR_VERSION = 1
-GMSH_MINOR_VERSION = 52
-GMSH_PATCH_VERSION = 2
+GMSH_MINOR_VERSION = 53
+GMSH_PATCH_VERSION = 0
 GMSH_EXTRA_VERSION = "-cvs"
 
 GMSH_VERSION = ${GMSH_MAJOR_VERSION}.${GMSH_MINOR_VERSION}.${GMSH_PATCH_VERSION}${GMSH_EXTRA_VERSION}
diff --git a/Mesh/1D_Mesh.cpp b/Mesh/1D_Mesh.cpp
index e352d6155f5756cd4aad936e673a88d16be56bf5..bb8b0bb56988408bce4d5c7bc2609f6156b934f4 100644
--- a/Mesh/1D_Mesh.cpp
+++ b/Mesh/1D_Mesh.cpp
@@ -1,4 +1,4 @@
-// $Id: 1D_Mesh.cpp,v 1.38 2004-05-07 22:49:57 geuzaine Exp $
+// $Id: 1D_Mesh.cpp,v 1.39 2004-05-25 04:10:04 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -154,7 +154,6 @@ void Maillage_Curve(void *data, void *dummy)
   }
 
   if(Extrude_Mesh(c)){
-    THEM->Statistics[4] += List_Nbr(c->Vertices);
     return;
   }
 
@@ -245,8 +244,6 @@ void Maillage_Curve(void *data, void *dummy)
     s = Create_Simplex(v1, v2, NULL, NULL);
     s->iEnt = c->Num;
     Tree_Add(c->Simplexes, &s);
-    List_Add(c->TrsfSimplexes, &s);
   }
 
-  THEM->Statistics[4] += List_Nbr(c->Vertices);
 }
diff --git a/Mesh/2D_Elliptic.cpp b/Mesh/2D_Elliptic.cpp
index f415216d560962a229f40b3f7e903d5b9a200ca0..416c65d776440006305116bfed67a6d747baa15d 100644
--- a/Mesh/2D_Elliptic.cpp
+++ b/Mesh/2D_Elliptic.cpp
@@ -1,4 +1,4 @@
-// $Id: 2D_Elliptic.cpp,v 1.17 2004-05-12 22:51:07 geuzaine Exp $
+// $Id: 2D_Elliptic.cpp,v 1.18 2004-05-25 04:10:04 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -32,7 +32,6 @@ int MeshEllipticSurface(Surface * sur)
   int i, j, k, nb, N1, N2, N3, N4;
   Curve *GG[444];
   Vertex **list;
-  Simplex *simp;
   double alpha, beta, gamma, u, v, lc, x, y, z;
   Vertex *S[4], *v11, *v12, *v13, *v21, *v22, *v23, *v31, *v32, *v33;
   List_T *l1, *l2, *l3, *l4;
@@ -233,35 +232,26 @@ int MeshEllipticSurface(Surface * sur)
   for(i = 0; i < N1 - 1; i++) {
     for(j = 0; j < N2 - 1; j++) {
       if(sur->Recombine) {
-        simp = Create_Quadrangle
+        Quadrangle *q = Create_Quadrangle
           (list[(i) + N1 * (j)], list[(i + 1) + N1 * (j)],
            list[(i + 1) + N1 * (j + 1)], list[i + N1 * (j + 1)]);
-        simp->iEnt = sur->Num;
-        Tree_Add(sur->Simplexes, &simp);
-        List_Add(sur->TrsfSimplexes, &simp);
+        q->iEnt = sur->Num;
+        Tree_Add(sur->Quadrangles, &q);
       }
       else {
-        simp = Create_Simplex(list[(i) + N1 * (j)], list[(i + 1) + N1 * (j)],
-                              list[(i) + N1 * (j + 1)], NULL);
+	Simplex *simp = Create_Simplex(list[(i) + N1 * (j)], list[(i + 1) + N1 * (j)],
+				       list[(i) + N1 * (j + 1)], NULL);
         simp->iEnt = sur->Num;
         Tree_Add(sur->Simplexes, &simp);
-        List_Add(sur->TrsfSimplexes, &simp);
-
-        simp =
-          Create_Simplex(list[(i + 1) + N1 * (j + 1)],
-                         list[(i) + N1 * (j + 1)], list[(i + 1) + N1 * (j)],
-                         NULL);
+	
+        simp = Create_Simplex(list[(i + 1) + N1 * (j + 1)],
+			      list[(i) + N1 * (j + 1)], list[(i + 1) + N1 * (j)],
+			      NULL);
         simp->iEnt = sur->Num;
         Tree_Add(sur->Simplexes, &simp);
-        List_Add(sur->TrsfSimplexes, &simp);
       }
     }
   }
 
-  // We count this here, to be able to distinguish very quickly
-  // between triangles and quadrangles later
-  if(sur->Recombine)
-    THEM->Statistics[8] += List_Nbr(sur->TrsfSimplexes);
-
   return 1;
 }
diff --git a/Mesh/2D_Mesh.cpp b/Mesh/2D_Mesh.cpp
index 180ccc867fbe0e82a1b08b2f4296825e073e9c33..03db21b9780dcdeda66de7e0c52b140e0fb62809 100644
--- a/Mesh/2D_Mesh.cpp
+++ b/Mesh/2D_Mesh.cpp
@@ -1,4 +1,4 @@
-// $Id: 2D_Mesh.cpp,v 1.56 2004-05-22 01:29:46 geuzaine Exp $
+// $Id: 2D_Mesh.cpp,v 1.57 2004-05-25 04:10:04 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -776,7 +776,7 @@ void Maillage_Surface(void *data, void *dum)
 {
   Surface **pS, *s;
   Tree_T *tnxe;
-  int ori, nbqua = 0;
+  int ori;
 
   pS = (Surface **) data;
   s = *pS;
@@ -809,81 +809,69 @@ void Maillage_Surface(void *data, void *dum)
   if(MeshTransfiniteSurface(s) ||
      MeshEllipticSurface(s) ||
      MeshCylindricalSurface(s) ||
-     MeshParametricSurface(s) || Extrude_Mesh(s)) {
+     MeshParametricSurface(s) || 
+     Extrude_Mesh(s)) {
     Tree_Action(THEM->Points, PutVertex_OnSurf);
     Tree_Action(s->Vertices, PutVertex_OnSurf);
     Tree_Action(s->Vertices, Add_In_Mesh);
-    THEM->Statistics[5] += Tree_Nbr(THESURFACE->Vertices);
-    THEM->Statistics[7] += Tree_Nbr(THESURFACE->Simplexes);
-
-    /* void TRIE_MON_GARS(void *a, void *b);
-       Tree_Action (THES->Simplexes, TRIE_MON_GARS);
-       Link_Simplexes(NULL, THES->Simplexes);
-       void  constraint_the_edge (int ,int ,int);
-       constraint_the_edge (6, 45, 85);
-     */
-    return;
-  }
-
-  int TypSurface = s->Typ;
-  Plan_Moyen(pS, dum);
-  Tree_Action(THEM->Points, Freeze_Vertex);
-  Tree_Action(s->Vertices, Freeze_Vertex);
-  Tree_Action(THEM->Points, Projette_Plan_Moyen);
-  Tree_Action(s->Vertices, Projette_Plan_Moyen);
-  Tree_Action(THEM->Curves, ActionEndTheCurve);
-  s->Typ = MSH_SURF_PLAN;
-  End_Surface(s, 0);
-
-  ori = Calcule_Contours(s);
-
-  if(CTX.mesh.algo == DELAUNAY_ISO)
-    Maillage_Automatique_VieuxCode(s, THEM, ori);
-  else if(CTX.mesh.algo == DELAUNAY_ANISO)
-    AlgorithmeMaillage2DAnisotropeModeJF(s);
-  else
-    Mesh_Shewchuk(s);
-
-  if(CTX.mesh.nb_smoothing) {
-    Msg(STATUS3, "Mesh smoothing");
-    tnxe = Tree_Create(sizeof(NXE), compareNXE);
-    create_NXE(s->Vertices, s->Simplexes, tnxe);
-    for(int i = 0; i < CTX.mesh.nb_smoothing; i++)
-      Tree_Action(tnxe, ActionLiss);
-    delete_NXE(tnxe);
   }
-
-
-  if(s->Recombine)
-    nbqua = Recombine(s->Vertices, s->Simplexes, s->RecombineAngle);
-
-  s->Typ = TypSurface;
-
-  if(s->Typ != MSH_SURF_PLAN) {
-    if(s->Extrude)
-      s->Extrude->Rotate(s->plan);
-    Tree_Action(s->Vertices, Calcule_Z);
-    if(s->Extrude)
-      s->Extrude->Rotate(s->invplan);
+  else{
+    int TypSurface = s->Typ;
+    Plan_Moyen(pS, dum);
+    Tree_Action(THEM->Points, Freeze_Vertex);
+    Tree_Action(s->Vertices, Freeze_Vertex);
+    Tree_Action(THEM->Points, Projette_Plan_Moyen);
+    Tree_Action(s->Vertices, Projette_Plan_Moyen);
+    Tree_Action(THEM->Curves, ActionEndTheCurve);
+    s->Typ = MSH_SURF_PLAN;
+    End_Surface(s, 0);
+
+    ori = Calcule_Contours(s);
+    
+    if(CTX.mesh.algo == DELAUNAY_ISO)
+      Maillage_Automatique_VieuxCode(s, THEM, ori);
+    else if(CTX.mesh.algo == DELAUNAY_ANISO)
+      AlgorithmeMaillage2DAnisotropeModeJF(s);
+    else
+      Mesh_Shewchuk(s);
+    
+    if(CTX.mesh.nb_smoothing) {
+      Msg(STATUS3, "Mesh smoothing");
+      tnxe = Tree_Create(sizeof(NXE), compareNXE);
+      create_NXE(s->Vertices, s->Simplexes, tnxe);
+      for(int i = 0; i < CTX.mesh.nb_smoothing; i++)
+	Tree_Action(tnxe, ActionLiss);
+      delete_NXE(tnxe);
+    }
+    
+    if(s->Recombine)
+      Recombine(s->Vertices, s->Simplexes, s->Quadrangles, s->RecombineAngle);
+    
+    s->Typ = TypSurface;
+    
+    if(s->Typ != MSH_SURF_PLAN) {
+      if(s->Extrude)
+	s->Extrude->Rotate(s->plan);
+      Tree_Action(s->Vertices, Calcule_Z);
+      if(s->Extrude)
+	s->Extrude->Rotate(s->invplan);
+    }
+    else
+      Tree_Action(s->Vertices, Calcule_Z_Plan);
+
+    Tree_Action(s->Vertices, Projette_Inverse);
+    Tree_Action(THEM->Points, Projette_Inverse);
+    
+    Tree_Action(THEM->Points, deFreeze_Vertex);
+    Tree_Action(s->Vertices, deFreeze_Vertex);
+    
+    Tree_Action(THEM->Points, PutVertex_OnSurf);
+    Tree_Action(s->Vertices, PutVertex_OnSurf);
+    Tree_Action(s->Vertices, Add_In_Mesh);
+    
+    Tree_Action(THEM->Curves, ActionEndTheCurve);
+    End_Surface(s->Support, 0);
+    End_Surface(s, 0);
   }
-  else
-    Tree_Action(s->Vertices, Calcule_Z_Plan);
-
-  Tree_Action(s->Vertices, Projette_Inverse);
-  Tree_Action(THEM->Points, Projette_Inverse);
-
-  Tree_Action(THEM->Points, deFreeze_Vertex);
-  Tree_Action(s->Vertices, deFreeze_Vertex);
-
-  Tree_Action(THEM->Points, PutVertex_OnSurf);
-  Tree_Action(s->Vertices, PutVertex_OnSurf);
-  Tree_Action(s->Vertices, Add_In_Mesh);
-
-  Tree_Action(THEM->Curves, ActionEndTheCurve);
-  End_Surface(s->Support, 0);
-  End_Surface(s, 0);
 
-  THEM->Statistics[5] += Tree_Nbr(THESURFACE->Vertices);
-  THEM->Statistics[7] += Tree_Nbr(THESURFACE->Simplexes);       // tri+qua
-  THEM->Statistics[8] += nbqua;
 }
diff --git a/Mesh/2D_Mesh_Aniso.cpp b/Mesh/2D_Mesh_Aniso.cpp
index 640ed3a87b597b1ce005d9ccf288fb21ead679ed..76ce117b87f9f1d076dabee2840a327bb4a52491 100644
--- a/Mesh/2D_Mesh_Aniso.cpp
+++ b/Mesh/2D_Mesh_Aniso.cpp
@@ -1,4 +1,4 @@
-// $Id: 2D_Mesh_Aniso.cpp,v 1.38 2004-05-07 22:49:57 geuzaine Exp $
+// $Id: 2D_Mesh_Aniso.cpp,v 1.39 2004-05-25 04:10:04 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -379,7 +379,7 @@ void constraint_the_edge(int isurf, int iv1, int iv2)
 
   if(!v1 || !v2)
     return;
-  EdgesContainer EdgesOnSurface(s->Simplexes, false);
+  EdgesContainer EdgesOnSurface(s->Simplexes);
   e.V[0] = v1;
   e.V[1] = v2;
   if(!EdgesOnSurface.Search(v1, v2)) {
@@ -394,7 +394,7 @@ void missing_edges_2d(Surface * s)
   Vertex *v1, *v2;
   Edge e;
 
-  EdgesContainer EdgesOnSurface(s->Simplexes, false);
+  EdgesContainer EdgesOnSurface(s->Simplexes);
 
   for(i = 0; i < List_Nbr(s->Generatrices); i++) {
     List_Read(s->Generatrices, i, &c);
diff --git a/Mesh/2D_Recombine.cpp b/Mesh/2D_Recombine.cpp
index 698c6ac04f78c42122d1997fd5d185e26d1100bc..46587078c542494f96cadeafe6ce20ee4a80eb8c 100644
--- a/Mesh/2D_Recombine.cpp
+++ b/Mesh/2D_Recombine.cpp
@@ -1,4 +1,4 @@
-// $Id: 2D_Recombine.cpp,v 1.18 2004-04-18 17:45:39 geuzaine Exp $
+// $Id: 2D_Recombine.cpp,v 1.19 2004-05-25 04:10:04 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -30,36 +30,36 @@
 extern Context_T CTX;
 
 static Tree_T *RecEdges, *Triangles, *RecSimplex, *TREEELM;
+static List_T *SimplexesToRemove;
 static double ALPHA;
 static int RECNUM;
 
-void addTriangles(void *data, void *dum)
+// Warning: these routines temporarily leave quads in the simplex
+// tree!
+
+void addTriangles(void *a, void *b)
 {
-  Simplex *S;
-  S = *(Simplex **) data;
-  if(S->V[2] && !S->V[3])
-    Tree_Add(Triangles, &S);
+  Simplex *s = *(Simplex **) a;
+  if(s->V[2] && !s->V[3])
+    Tree_Add(Triangles, &s);
 }
 
-void addrecedges(void *a, void *b)
+void addRecEdges(void *a, void *b)
 {
-  Edge *ed;
-  ed = (Edge *) a;
+  Edge *ed = (Edge *) a;
   if(ed->a < ALPHA)
     Tree_Add(RecEdges, ed);
 }
 
-void CalculeAngles(void *a, void *b)
+void computeAngles(void *a, void *b)
 {
-  Edge *ed;
-  double Angle;
-
-  ed = (Edge *) a;
+  Edge *ed = (Edge *) a;
   if(List_Nbr(ed->Simplexes) != 2) {
-    ed->a = 90.;
+    ed->a = 180.;
     return;
   }
 
+  double Angle;
   Angle = fabs(90. - angle_3pts(ed->O[0], ed->V[0], ed->O[1]));
   Angle = DMAX(fabs(90. - angle_3pts(ed->V[0], ed->O[1], ed->V[1])), Angle);
   Angle = DMAX(fabs(90. - angle_3pts(ed->O[1], ed->V[1], ed->O[0])), Angle);
@@ -67,14 +67,15 @@ void CalculeAngles(void *a, void *b)
   ed->a = Angle;
 }
 
-
-void Recombine_Farce(void *a, void *b)
+void recombineFace(void *a, void *b)
 {
-  Edge *ed;
-  Simplex *s1, *s2;
-  ed = (Edge *) a;
+  Edge *ed = (Edge *) a;
+
+  if(List_Nbr(ed->Simplexes) != 2)
+    return;
 
   if(ed->a < ALPHA) {
+    Simplex *s1, *s2;
     List_Read(ed->Simplexes, 0, &s1);
     List_Read(ed->Simplexes, 1, &s2);
     if(Tree_Search(RecSimplex, &s1))
@@ -87,6 +88,7 @@ void Recombine_Farce(void *a, void *b)
       return;
     Tree_Add(RecSimplex, &s1);
     Tree_Suppress(TREEELM, &s1);
+    List_Add(SimplexesToRemove, &s1);
     s2->V[3] = ed->V[0];
     s2->V[2] = ed->O[0];
     s2->V[1] = ed->V[1];
@@ -95,54 +97,81 @@ void Recombine_Farce(void *a, void *b)
   }
 }
 
-int Recombine(Tree_T * TreeAllVert, Tree_T * TreeAllElg, double a)
+void removeQuads(void *a, void *b)
+{
+  Simplex *s = *(Simplex **) a;
+  if(s->V[3])
+    List_Add(SimplexesToRemove, &s);
+}
+
+int Recombine(Tree_T * Vertices, Tree_T * Simplexes, Tree_T * Quadrangles, 
+	      double a)
 {
   Tree_T *tnxe;
   int ntot;
 
   ALPHA = a;
-  TREEELM = TreeAllElg;
+  TREEELM = Simplexes;
   ntot = 0;
 
   while(1) {
 
-    /* Initialisation */
+    // Initialization
     RECNUM = 0;
     RecEdges = Tree_Create(sizeof(Edge), compareedge_angle);
     RecSimplex = Tree_Create(sizeof(Simplex *), compareSimplex);
     Triangles = Tree_Create(sizeof(Simplex *), compareSimplex);
+    SimplexesToRemove = List_Create(100, 100, sizeof(Simplex*));
 
-    /* Recombinaison */
-    Tree_Action(TreeAllElg, addTriangles);
-    EdgesContainer edges(Triangles, false);
-    Tree_Action(edges.AllEdges, CalculeAngles);
-    Tree_Action(edges.AllEdges, addrecedges);
-    Tree_Action(RecEdges, Recombine_Farce);
+    // Recombination
+    Tree_Action(Simplexes, addTriangles);
+    EdgesContainer edges(Triangles);
+    Tree_Action(edges.AllEdges, computeAngles);
+    Tree_Action(edges.AllEdges, addRecEdges);
+    Tree_Action(RecEdges, recombineFace);
 
-    /* Lissage */
+    // Smoothing
     if(CTX.mesh.nb_smoothing) {
       Msg(STATUS3, "Mesh smoothing");
       tnxe = Tree_Create(sizeof(NXE), compareNXE);
-      create_NXE(TreeAllVert, TreeAllElg, tnxe);
+      create_NXE(Vertices, Simplexes, tnxe);
       for(int i = 0; i < CTX.mesh.nb_smoothing; i++)
         Tree_Action(tnxe, ActionLissSurf);
-      // MEMORY LEAK (JF)
       delete_NXE(tnxe);
     }
 
-    /* Destruction */
+    // Destruction
     Tree_Delete(RecEdges);
     Tree_Delete(RecSimplex);
     Tree_Delete(Triangles);
 
-    /* Si aucune recombinaison -> fin */
+    for(int i = 0; i < List_Nbr(SimplexesToRemove); i++){
+      Simplex *s;
+      List_Read(SimplexesToRemove, i, &s); 
+      Free_Simplex(&s, NULL);
+    }
+    List_Delete(SimplexesToRemove);
+
     ntot += RECNUM;
     if(!RECNUM)
       break;
   }
 
+  // remove the quads from the simplex tree
+  SimplexesToRemove = List_Create(100, 100, sizeof(Simplex*));
+  Tree_Action(Simplexes, removeQuads);
+  for(int i = 0; i < List_Nbr(SimplexesToRemove); i++){
+    Simplex *s;
+    List_Read(SimplexesToRemove, i, &s);
+    Quadrangle *q = Create_Quadrangle(s->V[0], s->V[1], s->V[2], s->V[3]);
+    q->iEnt = s->iEnt;
+    Tree_Add(Quadrangles, &q);
+    Tree_Suppress(Simplexes, &s);
+    Free_Simplex(&s, NULL);
+  }
+  List_Delete(SimplexesToRemove);
+
   Msg(STATUS2, "Recombined %d Quadrangles", ntot);
 
   return ntot;
-
 }
diff --git a/Mesh/2D_SMesh.cpp b/Mesh/2D_SMesh.cpp
index 5cdabaf60738560f2d58496846b11d33f59bbf58..f2983477c60c8a50c854b5352a5471c9d7fd1fcb 100644
--- a/Mesh/2D_SMesh.cpp
+++ b/Mesh/2D_SMesh.cpp
@@ -1,4 +1,4 @@
-// $Id: 2D_SMesh.cpp,v 1.17 2004-05-12 22:51:07 geuzaine Exp $
+// $Id: 2D_SMesh.cpp,v 1.18 2004-05-25 04:10:04 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -51,7 +51,7 @@ int index1d(int flag, int N, int n)
 {
   switch (flag) {
   case 0:
-    return (n);
+    return n;
   case 1:
     return (N - n - 1);
   default:
@@ -62,10 +62,10 @@ int index1d(int flag, int N, int n)
 int MeshTransfiniteSurface(Surface * sur)
 {
   int i, j, k, flag, nb, N1, N2, issphere;
-  int nbquad = 0, nbtri = 0;
   Curve *G[4], *GG[4];
   Vertex V, *c1, *c2, **list, *CP[2];
   Simplex *simp;
+  Quadrangle *quad;
   double u, v;
   int C_flag[4];
   Vertex *C[4], *S[4];
@@ -126,18 +126,18 @@ int MeshTransfiniteSurface(Surface * sur)
     for(i = 0; i < nb; i++)
       if(G[i] == NULL) {
         Msg(WARNING, "Wrong definition of Transfinite Surface %d", sur->Num);
-        return (0);
+        return 0;
       }
 
     if(nb == 4) {
       if((N1 = List_Nbr(G[0]->Vertices)) != List_Nbr(G[2]->Vertices))
-        return (0);
+        return 0;
       if((N2 = List_Nbr(G[1]->Vertices)) != List_Nbr(G[3]->Vertices))
-        return (0);
+        return 0;
     }
     else {
       if((N1 = List_Nbr(G[0]->Vertices)) != List_Nbr(G[2]->Vertices))
-        return (0);
+        return 0;
       N2 = List_Nbr(G[1]->Vertices);
     }
 
@@ -227,34 +227,25 @@ int MeshTransfiniteSurface(Surface * sur)
       for(i = 0; i < N1 - 1; i++) {
         for(j = 0; j < N2 - 1; j++) {
           if(sur->Recombine) {
-            simp =
-              Create_Quadrangle(list[(i) + N1 * (j)],
-                                list[(i + 1) + N1 * (j)],
-                                list[(i + 1) + N1 * (j + 1)],
-                                list[(i) + N1 * (j + 1)]);
-            simp->iEnt = sur->Num;
-            Tree_Add(sur->Simplexes, &simp);
-            List_Add(sur->TrsfSimplexes, &simp);
-
-            nbquad++;
+            quad = Create_Quadrangle(list[(i) + N1 * (j)],
+				     list[(i + 1) + N1 * (j)],
+				     list[(i + 1) + N1 * (j + 1)],
+				     list[(i) + N1 * (j + 1)]);
+            quad->iEnt = sur->Num;
+            Tree_Add(sur->Quadrangles, &quad);
           }
           else {
-            simp =
-              Create_Simplex(list[(i) + N1 * (j)], list[(i + 1) + N1 * (j)],
-                             list[(i) + N1 * (j + 1)], NULL);
+            simp = Create_Simplex(list[(i) + N1 * (j)], 
+				  list[(i + 1) + N1 * (j)],
+				  list[(i) + N1 * (j + 1)], NULL);
             simp->iEnt = sur->Num;
             Tree_Add(sur->Simplexes, &simp);
-            List_Add(sur->TrsfSimplexes, &simp);
 
-            simp =
-              Create_Simplex(list[(i + 1) + N1 * (j + 1)],
-                             list[(i) + N1 * (j + 1)],
-                             list[(i + 1) + N1 * (j)], NULL);
+            simp = Create_Simplex(list[(i + 1) + N1 * (j + 1)],
+				  list[(i) + N1 * (j + 1)],
+				  list[(i + 1) + N1 * (j)], NULL);
             simp->iEnt = sur->Num;
             Tree_Add(sur->Simplexes, &simp);
-            List_Add(sur->TrsfSimplexes, &simp);
-
-            nbtri += 2;
           }
         }
       }
@@ -267,62 +258,45 @@ int MeshTransfiniteSurface(Surface * sur)
         }
       }
       for(j = 0; j < N2 - 1; j++) {
-        simp =
-          Create_Simplex(list[1 + N1 * (j + 1)], list[N1 * (j + 1)],
-                         list[1 + N1 * (j)], NULL);
+        simp = Create_Simplex(list[1 + N1 * (j + 1)], 
+			      list[N1 * (j + 1)],
+			      list[1 + N1 * (j)], NULL);
         simp->iEnt = sur->Num;
         Tree_Add(sur->Simplexes, &simp);
-        List_Add(sur->TrsfSimplexes, &simp);
-
-        nbtri++;
       }
       for(i = 1; i < N1 - 1; i++) {
         for(j = 0; j < N2 - 1; j++) {
           if(sur->Recombine) {
-            simp =
-              Create_Quadrangle(list[(i) + N1 * (j)],
-                                list[(i + 1) + N1 * (j)],
-                                list[(i + 1) + N1 * (j + 1)],
-                                list[i + N1 * (j + 1)]);
-            simp->iEnt = sur->Num;
-            Tree_Add(sur->Simplexes, &simp);
-            List_Add(sur->TrsfSimplexes, &simp);
-
-            nbquad++;
+            quad = Create_Quadrangle(list[(i) + N1 * (j)],
+				     list[(i + 1) + N1 * (j)],
+				     list[(i + 1) + N1 * (j + 1)],
+				     list[i + N1 * (j + 1)]);
+            quad->iEnt = sur->Num;
+            Tree_Add(sur->Quadrangles, &quad);
           }
           else {
-            simp =
-              Create_Simplex(list[(i) + N1 * (j)], list[(i + 1) + N1 * (j)],
-                             list[(i) + N1 * (j + 1)], NULL);
+            simp = Create_Simplex(list[(i) + N1 * (j)], 
+				  list[(i + 1) + N1 * (j)],
+				  list[(i) + N1 * (j + 1)], NULL);
             simp->iEnt = sur->Num;
             Tree_Add(sur->Simplexes, &simp);
-            List_Add(sur->TrsfSimplexes, &simp);
 
-            simp =
-              Create_Simplex(list[(i + 1) + N1 * (j + 1)],
-                             list[(i) + N1 * (j + 1)],
-                             list[(i + 1) + N1 * (j)], NULL);
+            simp = Create_Simplex(list[(i + 1) + N1 * (j + 1)],
+				  list[(i) + N1 * (j + 1)],
+				  list[(i + 1) + N1 * (j)], NULL);
             simp->iEnt = sur->Num;
             Tree_Add(sur->Simplexes, &simp);
-            List_Add(sur->TrsfSimplexes, &simp);
-
-            nbtri += 2;
           }
         }
       }
 
     }
+    Free(list);
     break;
 
   default:
-    return (0);
+    return 0;
   }
 
-  Free(list);
-
-  // We count this here, to be able to distinguish very quickly
-  // between triangles and quadrangles later
-  THEM->Statistics[8] += nbquad;
-
-  return (1);
+  return 1;
 }
diff --git a/Mesh/3D_BGMesh.cpp b/Mesh/3D_BGMesh.cpp
index 5467960cbcec931a23e8cd116eb48667c515e6c2..51dac4a90585d44baeb2f78cef7f03904cd43b2e 100644
--- a/Mesh/3D_BGMesh.cpp
+++ b/Mesh/3D_BGMesh.cpp
@@ -1,4 +1,4 @@
-// $Id: 3D_BGMesh.cpp,v 1.30 2004-05-13 00:50:40 geuzaine Exp $
+// $Id: 3D_BGMesh.cpp,v 1.31 2004-05-25 04:10:04 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -48,7 +48,7 @@ void ExportLcFieldOnVolume(Mesh * M, char *filename)
     List_T *ll = Tree2List(vol->Simplexes);
     for(int j = 0; j < List_Nbr(ll); j++) {
       List_Read(ll, j, &simp);
-      simp->ExportLcField(f, 3);
+      simp->ExportLcField(f);
     }
     List_Delete(ll);
   }
@@ -75,7 +75,7 @@ void ExportLcFieldOnSurfaces(Mesh * M, char *filename)
     List_T *ll = Tree2List(surf->Simplexes);
     for(int j = 0; j < List_Nbr(ll); j++) {
       List_Read(ll, j, &simp);
-      simp->ExportLcField(f, 2);
+      simp->ExportLcField(f);
     }
     List_Delete(ll);
   }
diff --git a/Mesh/3D_Extrude.cpp b/Mesh/3D_Extrude.cpp
index ca992621b5d14cd396e5e6360e2ea274b50a2add..e3bda71aa8ed68813ce1fb4293d2235ed09d9e04 100644
--- a/Mesh/3D_Extrude.cpp
+++ b/Mesh/3D_Extrude.cpp
@@ -1,4 +1,4 @@
-// $Id: 3D_Extrude.cpp,v 1.76 2004-05-22 01:24:17 geuzaine Exp $
+// $Id: 3D_Extrude.cpp,v 1.77 2004-05-25 04:10:04 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -245,23 +245,19 @@ void are_del(Vertex * v1, Vertex * v2, Tree_T * t)
 
 void Extrude_Simplex_Phase1(void *data, void *dum)
 {
-  Simplex **pS, *s;
-  int i, j, k;
   Vertex *v1, *v2, *v3, *v4, *v5, *v6;
-  List_T *L0, *L1, *L2;
 
-  pS = (Simplex **) data;
-  s = *pS;
+  Simplex *s = *(Simplex **) data;
 
-  L0 = getnxl(s->V[0], DIM);
-  L1 = getnxl(s->V[1], DIM);
-  L2 = getnxl(s->V[2], DIM);
+  List_T *L0 = getnxl(s->V[0], DIM);
+  List_T *L1 = getnxl(s->V[1], DIM);
+  List_T *L2 = getnxl(s->V[2], DIM);
 
   if(!L0 || !L1 || !L2) return;
 
-  k = 0;
-  for(i = 0; i < ep->mesh.NbLayer; i++) {
-    for(j = 0; j < ep->mesh.NbElmLayer[i]; j++) {
+  int k = 0;
+  for(int i = 0; i < ep->mesh.NbLayer; i++) {
+    for(int j = 0; j < ep->mesh.NbElmLayer[i]; j++) {
       List_Read(L0, k, &v1);
       List_Read(L1, k, &v2);
       List_Read(L2, k, &v3);
@@ -281,23 +277,19 @@ void Extrude_Simplex_Phase1(void *data, void *dum)
 
 void Extrude_Simplex_Phase2(void *data, void *dum)
 {
-  Simplex **pS, *s;
-  int i, j, k;
   Vertex *v1, *v2, *v3, *v4, *v5, *v6;
-  List_T *L0, *L1, *L2;
 
-  pS = (Simplex **) data;
-  s = *pS;
+  Simplex *s = *(Simplex **) data;
 
-  L0 = getnxl(s->V[0], DIM);
-  L1 = getnxl(s->V[1], DIM);
-  L2 = getnxl(s->V[2], DIM);
+  List_T *L0 = getnxl(s->V[0], DIM);
+  List_T *L1 = getnxl(s->V[1], DIM);
+  List_T *L2 = getnxl(s->V[2], DIM);
 
   if(!L0 || !L1 || !L2) return;
 
-  k = 0;
-  for(i = 0; i < ep->mesh.NbLayer; i++) {
-    for(j = 0; j < ep->mesh.NbElmLayer[i]; j++) {
+  int k = 0;
+  for(int i = 0; i < ep->mesh.NbLayer; i++) {
+    for(int j = 0; j < ep->mesh.NbElmLayer[i]; j++) {
       List_Read(L0, k, &v1);
       List_Read(L1, k, &v2);
       List_Read(L2, k, &v3);
@@ -462,69 +454,33 @@ void Create_Sim(int iEnt, Vertex * v1, Vertex * v2, Vertex * v3, Vertex * v4)
 
 void Extrude_Simplex_Phase3(void *data, void *dum)
 {
-  Simplex **pS, *s;
   int i, j, k;
   Vertex *v[8];
-  List_T *L0, *L1, *L2, *L3 = NULL;
-
-  pS = (Simplex **) data;
-  s = *pS;
 
-  if(s->V[3] && !ep->mesh.Recombine) {
-    Msg(GERROR, "You have to use 'Recombine' to extrude quadrangular meshes");
-    return;
-  }
+  Simplex *s = *(Simplex **) data;
 
-  L0 = getnxl(s->V[0], DIM);
-  L1 = getnxl(s->V[1], DIM);
-  L2 = getnxl(s->V[2], DIM);
+  List_T *L0 = getnxl(s->V[0], DIM);
+  List_T *L1 = getnxl(s->V[1], DIM);
+  List_T *L2 = getnxl(s->V[2], DIM);
 
   if(!L0 || !L1 || !L2) return;
 
-  if(s->V[3]){
-    L3 = getnxl(s->V[3], DIM);
-    if(!L3) return;
-  }
-
-  //printf("orig: %d %d %d %d\n",s->V[0]->Num,s->V[1]->Num,s->V[2]->Num,s->V[3]->Num);
-
   k = 0;
   for(i = 0; i < ep->mesh.NbLayer; i++) {
     for(j = 0; j < ep->mesh.NbElmLayer[i]; j++) {
 
-      if(s->V[3]) {
-        List_Read(L0, k, &v[0]);
-        List_Read(L1, k, &v[1]);
-        List_Read(L2, k, &v[2]);
-        List_Read(L3, k, &v[3]);
-
-        //printf("   1: %d %d %d %d\n",v[0]->Num,v[1]->Num,v[2]->Num,v[3]->Num);
-
-        List_Read(L0, k + 1, &v[4]);
-        List_Read(L1, k + 1, &v[5]);
-        List_Read(L2, k + 1, &v[6]);
-        List_Read(L3, k + 1, &v[7]);
-
-        //printf("   2: %d %d %d %d\n",v[4]->Num,v[5]->Num,v[6]->Num,v[7]->Num);
-
-      }
-      else {
-        List_Read(L0, k, &v[0]);
-        List_Read(L1, k, &v[1]);
-        List_Read(L2, k, &v[2]);
-        List_Read(L0, k + 1, &v[3]);
-        List_Read(L1, k + 1, &v[4]);
-        List_Read(L2, k + 1, &v[5]);
-      }
+      List_Read(L0, k, &v[0]);
+      List_Read(L1, k, &v[1]);
+      List_Read(L2, k, &v[2]);
+      List_Read(L0, k + 1, &v[3]);
+      List_Read(L1, k + 1, &v[4]);
+      List_Read(L2, k + 1, &v[5]);
 
       k++;
       if(ep->mesh.ZonLayer[i]) {
 
         if(ep->mesh.Recombine) {
-          if(s->V[3])
-            Create_HexPri(ep->mesh.ZonLayer[i], v);
-          else
-            Create_PriPyrTet(ep->mesh.ZonLayer[i], v);
+	  Create_PriPyrTet(ep->mesh.ZonLayer[i], v);
         }
         else {
           if(are_exist(v[3], v[1], Tree_Ares) &&
@@ -575,6 +531,45 @@ void Extrude_Simplex_Phase3(void *data, void *dum)
   }
 }
 
+void Extrude_Quadrangle_Phase3(void *data, void *dum)
+{
+  int i, j, k;
+  Vertex *v[8];
+
+  Quadrangle *q = *(Quadrangle **) data;
+
+  if(!ep->mesh.Recombine) {
+    Msg(GERROR, "You have to use 'Recombine' to extrude quadrangular meshes");
+    return;
+  }
+
+  List_T *L0 = getnxl(q->V[0], DIM);
+  List_T *L1 = getnxl(q->V[1], DIM);
+  List_T *L2 = getnxl(q->V[2], DIM);
+  List_T *L3 = getnxl(q->V[3], DIM);
+
+  if(!L0 || !L1 || !L2 || !L3) return;
+
+  k = 0;
+  for(i = 0; i < ep->mesh.NbLayer; i++) {
+    for(j = 0; j < ep->mesh.NbElmLayer[i]; j++) {
+      List_Read(L0, k, &v[0]);
+      List_Read(L1, k, &v[1]);
+      List_Read(L2, k, &v[2]);
+      List_Read(L3, k, &v[3]);
+
+      List_Read(L0, k + 1, &v[4]);
+      List_Read(L1, k + 1, &v[5]);
+      List_Read(L2, k + 1, &v[6]);
+      List_Read(L3, k + 1, &v[7]);
+
+      k++;
+      if(ep->mesh.ZonLayer[i])
+	Create_HexPri(ep->mesh.ZonLayer[i], v);
+    }
+  }
+}
+
 void Extrude_Vertex(void *data, void *dum)
 {
   Vertex **vexist, *v, *newv;
@@ -638,19 +633,16 @@ void Extrude_Surface3(Surface * s)
 {
   THES = s;
   Tree_Action(s->Simplexes, Extrude_Simplex_Phase3);
+  Tree_Action(s->Quadrangles, Extrude_Quadrangle_Phase3);
 }
 
 
 void Create_Tri(int iEnt, Vertex * v1, Vertex * v2, Vertex * v3)
 {
-  Simplex *s;
   if(CTX.mesh.allow_degenerated_extrude ||
      (v1->Num != v2->Num && v1->Num != v3->Num && v2->Num != v3->Num)) {
-    s = Create_Simplex(v1, v2, v3, NULL);
-    if(!ep->useZonLayer())
-      s->iEnt = THES->Num;
-    else
-      s->iEnt = iEnt;
+    Simplex *s = Create_Simplex(v1, v2, v3, NULL);
+    s->iEnt = ep->useZonLayer() ? iEnt : THES->Num;
     s->Num = -s->Num;   //Tag triangles to re-extrude
     Tree_Add(THES->Simplexes, &s);
   }
@@ -658,46 +650,50 @@ void Create_Tri(int iEnt, Vertex * v1, Vertex * v2, Vertex * v3)
 
 void Extrude_Seg(Vertex * V1, Vertex * V2)
 {
-  int i, j, k;
   Vertex *v1, *v2, *v3, *v4;
-  Simplex *s;
-  List_T *L1, *L2;
 
-  L1 = getnxl(V1, DIM);
-  L2 = getnxl(V2, DIM);
+  List_T *L1 = getnxl(V1, DIM);
+  List_T *L2 = getnxl(V2, DIM);
 
   if(!L1 || !L2) return;
 
-  k = 0;
-  for(i = 0; i < ep->mesh.NbLayer; i++) {
-    for(j = 0; j < ep->mesh.NbElmLayer[i]; j++) {
+  int k = 0;
+  for(int i = 0; i < ep->mesh.NbLayer; i++) {
+    for(int j = 0; j < ep->mesh.NbElmLayer[i]; j++) {
       List_Read(L1, k, &v1);
       List_Read(L2, k, &v2);
       List_Read(L1, k + 1, &v3);
       List_Read(L2, k + 1, &v4);
       if(ep->mesh.Recombine) {
-        if(CTX.mesh.allow_degenerated_extrude)
-          s = Create_Quadrangle(v1, v2, v4, v3);
-        else if(v1->Num == v2->Num || v2->Num == v4->Num)
-          s = Create_Simplex(v1, v4, v3, NULL);
-        else if(v1->Num == v3->Num || v3->Num == v4->Num)
-          s = Create_Simplex(v1, v2, v4, NULL);
+        if(CTX.mesh.allow_degenerated_extrude){
+          Quadrangle *q = Create_Quadrangle(v1, v2, v4, v3);
+	  q->iEnt = ep->useZonLayer() ? ep->mesh.ZonLayer[i] : THES->Num;
+	  q->Num = -q->Num; // Tag elt to re-extrude
+	  Tree_Add(THES->Quadrangles, &q);
+	}
+        else if(v1->Num == v2->Num || v2->Num == v4->Num){
+          Simplex *s = Create_Simplex(v1, v4, v3, NULL);
+	  s->iEnt = ep->useZonLayer() ? ep->mesh.ZonLayer[i] : THES->Num;
+	  s->Num = -s->Num; // Tag elt to re-extrude
+	  Tree_Add(THES->Simplexes, &s);
+	}
+        else if(v1->Num == v3->Num || v3->Num == v4->Num){
+          Simplex *s = Create_Simplex(v1, v2, v4, NULL);
+	  s->iEnt = ep->useZonLayer() ? ep->mesh.ZonLayer[i] : THES->Num;
+	  s->Num = -s->Num; // Tag elt to re-extrude
+	  Tree_Add(THES->Simplexes, &s);
+	}
         else if(v1->Num == v4->Num || v2->Num == v3->Num) {
           Msg(GERROR, "Uncoherent quadrangle  (nodes %d %d %d %d)",
               v1->Num, v2->Num, v3->Num, v4->Num);
           return;
         }
-        else
-          s = Create_Quadrangle(v1, v2, v4, v3);
-        if(!ep->useZonLayer())
-	  s->iEnt = THES->Num;
-	else
-	  s->iEnt = ep->mesh.ZonLayer[i];
-        s->Num = -s->Num;       //Tag quadrangles to re-extrude
-        Tree_Add(THES->Simplexes, &s);
-
-        // This is horrible
-        THEM->Statistics[8] += 1;
+        else{
+          Quadrangle *q = Create_Quadrangle(v1, v2, v4, v3);
+	  q->iEnt = ep->useZonLayer() ? ep->mesh.ZonLayer[i] : THES->Num;
+	  q->Num = -q->Num; // Tag elt to re-extrude
+	  Tree_Add(THES->Quadrangles, &q);
+	}
       }
       else {
         if(are_exist(v3, v2, Tree_Ares)) {
@@ -717,15 +713,12 @@ void Extrude_Seg(Vertex * V1, Vertex * V2)
 
 void Extrude_Curve(void *data, void *dum)
 {
-  Curve **pC, *c;
   Vertex *v1, *v2;
-  int i;
-  pC = (Curve **) data;
-  c = *pC;
+  Curve *c = *(Curve **) data;
 
   //if (c->Num < 0) return;
 
-  for(i = 0; i < List_Nbr(c->Vertices) - 1; i++) {
+  for(int i = 0; i < List_Nbr(c->Vertices) - 1; i++) {
     List_Read(c->Vertices, i, &v1);
     List_Read(c->Vertices, i + 1, &v2);
     Extrude_Seg(v1, v2);
@@ -817,7 +810,6 @@ void copy_mesh(Curve * from, Curve * to, int direction)
     Simplex *s = Create_Simplex(v1, v2, NULL, NULL);
     s->iEnt = to->Num;
     Tree_Add(to->Simplexes, &s);
-    List_Add(to->TrsfSimplexes, &s);
   }
 
 }
@@ -901,7 +893,6 @@ int Extrude_Mesh(Curve * c)
 	else
 	  s->iEnt = ep->mesh.ZonLayer[i];
 	Tree_Add(c->Simplexes, &s);
-	List_Add(c->TrsfSimplexes, &s);
 
 	// fill-in the data we didn't have above:
 	v1->u = ep->u(i, j);
@@ -922,66 +913,94 @@ int Extrude_Mesh(Curve * c)
 
 void copy_mesh(Surface * from, Surface * to)
 {
-  List_T *list = Tree2List(from->Simplexes);
-  Simplex *s, *news;
-  Vertex **vexist, *v, *newv[4];
-
-  int nb = Tree_Nbr(to->Simplexes);
-  if(nb) {
-    if(nb != Tree_Nbr(from->Simplexes))
-      Msg(GERROR, "Incompatible extrusion of surface %d into surface %d",
-          from->Num, to->Num);
+  List_T *list;
+  Simplex *s;
+  Quadrangle *q;
+  Vertex **vexist, *newv[4];
+
+  int nbs = Tree_Nbr(to->Simplexes);
+  int nbq = Tree_Nbr(to->Quadrangles);
+  if((nbs && nbs != Tree_Nbr(from->Simplexes)) ||
+     (nbq && nbq != Tree_Nbr(from->Quadrangles))){
+    Msg(GERROR, "Incompatible extrusion of surface %d into surface %d",
+	from->Num, to->Num);
     return;
   }
 
+  // triangles
+  list = Tree2List(from->Simplexes);
   for(int i = 0; i < List_Nbr(list); i++) {
     List_Read(list, i, &s);
-    for(int j = 0; j < 4; j++) {
-      if(s->V[j]) {
-        v = s->V[j];
-        newv[j] = Create_Vertex(++THEM->MaxPointNum, v->Pos.X,
-				v->Pos.Y, v->Pos.Z, v->lc, v->u);
-        ep->Extrude(ep->mesh.NbLayer - 1, ep->mesh.NbElmLayer[ep->mesh.NbLayer - 1], 
-		    newv[j]->Pos.X, newv[j]->Pos.Y, newv[j]->Pos.Z);
-        if(Vertex_Bound && (vexist = (Vertex **) Tree_PQuery(Vertex_Bound, &newv[j]))) {
-          Free_Vertex(&newv[j], 0);
-          newv[j] = *vexist;
-        }
-        else {
-	  if(Point_Bound && (vexist = (Vertex **) Tree_PQuery(Point_Bound, &newv[j]))) {
-	    // keep the new one: we cannot have points and vertices
-	    // pointing to the same memory location
-	    newv[j]->Num = (*vexist)->Num;
-	  }
-          Tree_Add(THEM->Vertices, &newv[j]);
-          Tree_Insert(Vertex_Bound, &newv[j]);
-        }
+    for(int j = 0; j < 3; j++) {
+      newv[j] = Create_Vertex(++THEM->MaxPointNum, s->V[j]->Pos.X, s->V[j]->Pos.Y, 
+			      s->V[j]->Pos.Z, s->V[j]->lc, s->V[j]->u);
+      ep->Extrude(ep->mesh.NbLayer - 1, ep->mesh.NbElmLayer[ep->mesh.NbLayer - 1], 
+		  newv[j]->Pos.X, newv[j]->Pos.Y, newv[j]->Pos.Z);
+      if(Vertex_Bound && (vexist = (Vertex **) Tree_PQuery(Vertex_Bound, &newv[j]))) {
+	Free_Vertex(&newv[j], 0);
+	newv[j] = *vexist;
       }
       else {
-        newv[j] = NULL;
+	if(Point_Bound && (vexist = (Vertex **) Tree_PQuery(Point_Bound, &newv[j]))) {
+	  // keep the new one: we cannot have points and vertices
+	  // pointing to the same memory location
+	  newv[j]->Num = (*vexist)->Num;
+	}
+	Tree_Add(THEM->Vertices, &newv[j]);
+	Tree_Insert(Vertex_Bound, &newv[j]);
       }
     }
-    if(newv[3]) {
-      news = Create_Quadrangle(newv[0], newv[1], newv[2], newv[3]);
-      // This is horrible
-      THEM->Statistics[8] += 1;
-    }
-    else
-      news = Create_Simplex(newv[0], newv[1], newv[2], NULL);
+    Simplex *news = Create_Simplex(newv[0], newv[1], newv[2], NULL);
     news->iEnt = to->Num;
     Tree_Add(to->Simplexes, &news);
   }
   List_Delete(list);
+  
+  // quadrangles
+  list = Tree2List(from->Quadrangles);
+  for(int i = 0; i < List_Nbr(list); i++) {
+    List_Read(list, i, &q);
+    for(int j = 0; j < 4; j++) {
+      newv[j] = Create_Vertex(++THEM->MaxPointNum, q->V[j]->Pos.X, q->V[j]->Pos.Y, 
+			      q->V[j]->Pos.Z, q->V[j]->lc, q->V[j]->u);
+      ep->Extrude(ep->mesh.NbLayer - 1, ep->mesh.NbElmLayer[ep->mesh.NbLayer - 1], 
+		  newv[j]->Pos.X, newv[j]->Pos.Y, newv[j]->Pos.Z);
+      if(Vertex_Bound && (vexist = (Vertex **) Tree_PQuery(Vertex_Bound, &newv[j]))) {
+	Free_Vertex(&newv[j], 0);
+	newv[j] = *vexist;
+      }
+      else {
+	if(Point_Bound && (vexist = (Vertex **) Tree_PQuery(Point_Bound, &newv[j]))) {
+	  // keep the new one: we cannot have points and vertices
+	  // pointing to the same memory location
+	  newv[j]->Num = (*vexist)->Num;
+	}
+	Tree_Add(THEM->Vertices, &newv[j]);
+	Tree_Insert(Vertex_Bound, &newv[j]);
+      }
+    }
+    Quadrangle *newq = Create_Quadrangle(newv[0], newv[1], newv[2], newv[3]);
+    newq->iEnt = to->Num;
+    Tree_Add(to->Quadrangles, &newq);
+  }
+  List_Delete(list);
 }
 
-void AddVertsInSurf(void *a, void *b)
+void AddSimVertsInSurf(void *a, void *b)
 {
   Simplex *s = *(Simplex **) a;
-  for(int i = 0; i < 4; i++)
+  for(int i = 0; i < 3; i++)
     if(s->V[i])
       Tree_Insert(THES->Vertices, &s->V[i]);
 }
 
+void AddQuadVertsInSurf(void *a, void *b)
+{
+  Quadrangle *q = *(Quadrangle **) a;
+  for(int i = 0; i < 4; i++)
+    Tree_Insert(THES->Vertices, &q->V[i]);
+}
+
 int Extrude_Mesh(Surface * s)
 {
   int i;
@@ -1016,7 +1035,8 @@ int Extrude_Mesh(Surface * s)
     copy_mesh(ss, s);
   }
 
-  Tree_Action(s->Simplexes, AddVertsInSurf);
+  Tree_Action(s->Simplexes, AddSimVertsInSurf);
+  Tree_Action(s->Quadrangles, AddQuadVertsInSurf);
 
   return true;
 }
@@ -1145,5 +1165,4 @@ int Extrude_Mesh(Tree_T * Volumes)
   List_Delete(vol);
 
   return true;
-
 }
diff --git a/Mesh/3D_Extrude_Old.cpp b/Mesh/3D_Extrude_Old.cpp
index 1713068960404a83c0065f233b387170fbcbea4e..91bbce8c423e59a832623b9e0b94618187775a94 100644
--- a/Mesh/3D_Extrude_Old.cpp
+++ b/Mesh/3D_Extrude_Old.cpp
@@ -1,4 +1,4 @@
-// $Id: 3D_Extrude_Old.cpp,v 1.26 2004-05-22 01:24:18 geuzaine Exp $
+// $Id: 3D_Extrude_Old.cpp,v 1.27 2004-05-25 04:10:04 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -159,12 +159,10 @@ static void are_del(Vertex * v1, Vertex * v2, Tree_T * t)
 
 static void Extrude_Simplex_Phase1(void *data, void *dum)
 {
-  Simplex **pS, *s;
   int i, j, k;
   Vertex *v1, *v2, *v3, *v4, *v5, *v6;
 
-  pS = (Simplex **) data;
-  s = *pS;
+  Simplex *s = *(Simplex **) data;
 
   k = 0;
   for(i = 0; i < NbLayer; i++) {
@@ -188,19 +186,12 @@ static void Extrude_Simplex_Phase1(void *data, void *dum)
 
 static void Extrude_Simplex_Phase3(void *data, void *dum)
 {
-  Simplex **pS, *s, *news;
+  Simplex  *news;
   Prism *newp;
-  Hexahedron *newh;
   int i, j, k;
-  Vertex *v1, *v2, *v3, *v4, *v5, *v6, *v7, *v8;
-
-  pS = (Simplex **) data;
-  s = *pS;
+  Vertex *v1, *v2, *v3, *v4, *v5, *v6;
 
-  if(s->V[3] && !CTX.mesh.oldxtrude_recombine) {
-    Msg(GERROR,
-        "Non recombined extrusion impossible with quadrangles (use -recombine)");
-  }
+  Simplex *s = *(Simplex **) data;
 
   k = 0;
   for(i = 0; i <= NbLayer; i++) {
@@ -209,10 +200,6 @@ static void Extrude_Simplex_Phase3(void *data, void *dum)
       List_Read(s->V[1]->Extruded_Points, k, &v2);
       List_Read(s->V[2]->Extruded_Points, k, &v3);
       news = Create_Simplex(v1, v2, v3, NULL);
-      if(s->V[3]) {
-        List_Read(s->V[3]->Extruded_Points, k, &v4);
-        news->V[3] = v4;
-      }
       news->iEnt = SurfLayer[i];
       Tree_Add(THEV->Simp_Surf, &news);
     }
@@ -224,39 +211,19 @@ static void Extrude_Simplex_Phase3(void *data, void *dum)
   k = 0;
   for(i = 0; i < NbLayer; i++) {
     for(j = 0; j < NbElmLayer[i]; j++) {
-
-      if(s->V[3]) {
-        List_Read(s->V[0]->Extruded_Points, k, &v1);
-        List_Read(s->V[1]->Extruded_Points, k, &v2);
-        List_Read(s->V[2]->Extruded_Points, k, &v3);
-        List_Read(s->V[3]->Extruded_Points, k, &v4);
-        List_Read(s->V[0]->Extruded_Points, k + 1, &v5);
-        List_Read(s->V[1]->Extruded_Points, k + 1, &v6);
-        List_Read(s->V[2]->Extruded_Points, k + 1, &v7);
-        List_Read(s->V[3]->Extruded_Points, k + 1, &v8);
-      }
-      else {
-        List_Read(s->V[0]->Extruded_Points, k, &v1);
-        List_Read(s->V[1]->Extruded_Points, k, &v2);
-        List_Read(s->V[2]->Extruded_Points, k, &v3);
-        List_Read(s->V[0]->Extruded_Points, k + 1, &v4);
-        List_Read(s->V[1]->Extruded_Points, k + 1, &v5);
-        List_Read(s->V[2]->Extruded_Points, k + 1, &v6);
-      }
+      List_Read(s->V[0]->Extruded_Points, k, &v1);
+      List_Read(s->V[1]->Extruded_Points, k, &v2);
+      List_Read(s->V[2]->Extruded_Points, k, &v3);
+      List_Read(s->V[0]->Extruded_Points, k + 1, &v4);
+      List_Read(s->V[1]->Extruded_Points, k + 1, &v5);
+      List_Read(s->V[2]->Extruded_Points, k + 1, &v6);
 
       k++;
       if(ZonLayer[i]) {
         if(CTX.mesh.oldxtrude_recombine) {
-          if(s->V[3]) {
-            newh = Create_Hexahedron(v1, v2, v3, v4, v5, v6, v7, v8);
-            newh->iEnt = ZonLayer[i];
-            Tree_Add(THEV->Hexahedra, &newh);
-          }
-          else {
-            newp = Create_Prism(v1, v2, v3, v4, v5, v6);
-            newp->iEnt = ZonLayer[i];
-            Tree_Add(THEV->Prisms, &newp);
-          }
+	  newp = Create_Prism(v1, v2, v3, v4, v5, v6);
+	  newp->iEnt = ZonLayer[i];
+	  Tree_Add(THEV->Prisms, &newp);
         }
         else {
           if(are_exist(v4, v2, Tree_Ares) &&
@@ -337,14 +304,62 @@ static void Extrude_Simplex_Phase3(void *data, void *dum)
   }
 }
 
+static void Extrude_Quadrangle_Phase3(void *data, void *dum)
+{
+  int i, j, k;
+  Vertex *v1, *v2, *v3, *v4, *v5, *v6, *v7, *v8;
+
+  Quadrangle *q = *(Quadrangle **) data;
+
+  if(!CTX.mesh.oldxtrude_recombine){
+    Msg(GERROR, "Non recombined extrusion impossible with quadrangles (use -recombine)");
+    return;
+  }
+
+  k = 0;
+  for(i = 0; i <= NbLayer; i++) {
+    if(SurfLayer[i]) {
+      List_Read(q->V[0]->Extruded_Points, k, &v1);
+      List_Read(q->V[1]->Extruded_Points, k, &v2);
+      List_Read(q->V[2]->Extruded_Points, k, &v3);
+      List_Read(q->V[3]->Extruded_Points, k, &v4);
+      Quadrangle *newq = Create_Quadrangle(v1, v2, v3, v4);
+      newq->iEnt = SurfLayer[i];
+      Tree_Add(THEV->Quad_Surf, &newq);
+    }
+    for(j = 0; j < NbElmLayer[i]; j++) {
+      k++;
+    }
+  }
+
+  k = 0;
+  for(i = 0; i < NbLayer; i++) {
+    for(j = 0; j < NbElmLayer[i]; j++) {
+      List_Read(q->V[0]->Extruded_Points, k, &v1);
+      List_Read(q->V[1]->Extruded_Points, k, &v2);
+      List_Read(q->V[2]->Extruded_Points, k, &v3);
+      List_Read(q->V[3]->Extruded_Points, k, &v4);
+      List_Read(q->V[0]->Extruded_Points, k + 1, &v5);
+      List_Read(q->V[1]->Extruded_Points, k + 1, &v6);
+      List_Read(q->V[2]->Extruded_Points, k + 1, &v7);
+      List_Read(q->V[3]->Extruded_Points, k + 1, &v8);
+
+      k++;
+      if(ZonLayer[i]) {
+	Hexahedron *newh = Create_Hexahedron(v1, v2, v3, v4, v5, v6, v7, v8);
+	newh->iEnt = ZonLayer[i];
+	Tree_Add(THEV->Hexahedra, &newh);
+      }
+    }
+  }
+}
+
 static void Extrude_Simplex_Phase2(void *data, void *dum)
 {
-  Simplex **pS, *s;
   int i, j, k;
   Vertex *v1, *v2, *v3, *v4, *v5, *v6;
 
-  pS = (Simplex **) data;
-  s = *pS;
+  Simplex *s = *(Simplex **) data;
 
   k = 0;
   for(i = 0; i < NbLayer; i++) {
@@ -450,11 +465,10 @@ static void Extrude_Vertex(void *data, void *dum)
 
 static void Extrude_Surface1(void *data, void *dum)
 {
-  Surface **pS, *s;
   if(!NbLayer)
     return;
-  pS = (Surface **) data;
-  s = THES = *pS;
+  Surface *s = *(Surface **) data;
+  THES = s;
 
   Tree_Action(s->Vertices, Extrude_Vertex);
   if(!CTX.mesh.oldxtrude_recombine)
@@ -463,11 +477,10 @@ static void Extrude_Surface1(void *data, void *dum)
 
 static void Extrude_Surface2(void *data, void *dum)
 {
-  Surface **pS, *s;
   if(!NbLayer)
     return;
-  pS = (Surface **) data;
-  s = THES = *pS;
+  Surface *s = *(Surface **) data;
+  THES = s;
 
   Tree_Action(s->Simplexes, Extrude_Simplex_Phase2);
 }
@@ -475,12 +488,12 @@ static void Extrude_Surface2(void *data, void *dum)
 
 static void Extrude_Surface3(void *data, void *dum)
 {
-  Surface **pS, *s;
   int i;
   if(!NbLayer)
     return;
-  pS = (Surface **) data;
-  s = THES = *pS;
+
+  Surface *s = *(Surface **) data;
+  THES = s;
 
   /* Numerotation automatique des entites physiques */
   Msg(INFO, "Extruding Surface %d", s->Num);
@@ -493,6 +506,7 @@ static void Extrude_Surface3(void *data, void *dum)
   }
 
   Tree_Action(s->Simplexes, Extrude_Simplex_Phase3);
+  Tree_Action(s->Quadrangles, Extrude_Quadrangle_Phase3);
 }
 
 
@@ -501,6 +515,7 @@ static void Extrude_Seg(Vertex * V1, Vertex * V2)
   int i, j, k;
   Vertex *v1, *v2, *v3, *v4;
   Simplex *s;
+  Quadrangle *q;
 
   //printf("-curve vertex %d %p   %d %p\n", V1->Num, V1, V2->Num, V2);
 
@@ -527,10 +542,9 @@ static void Extrude_Seg(Vertex * V1, Vertex * V2)
       List_Read(V2->Extruded_Points, k + 1, &v4);
       if(SurfLayer[i]) {
         if(CTX.mesh.oldxtrude_recombine) {
-          s = Create_Simplex(v1, v2, v4, NULL);
-          s->V[3] = v3;
-          s->iEnt = SurfLayer[i];
-          Tree_Add(THEV->Simp_Surf, &s);
+          q = Create_Quadrangle(v1, v2, v4, v3);
+          q->iEnt = SurfLayer[i];
+          Tree_Add(THEV->Quad_Surf, &q);
         }
         else {
           if(are_exist(v3, v2, Tree_Ares)) {
diff --git a/Mesh/3D_Mesh.cpp b/Mesh/3D_Mesh.cpp
index d7e7bcd9d99ec4128bdc15a0959d85014d81bac9..651258930ad9d618b57582e0dfc5370135de251f 100644
--- a/Mesh/3D_Mesh.cpp
+++ b/Mesh/3D_Mesh.cpp
@@ -1,4 +1,4 @@
-// $Id: 3D_Mesh.cpp,v 1.58 2004-04-18 03:36:07 geuzaine Exp $
+// $Id: 3D_Mesh.cpp,v 1.59 2004-05-25 04:10:04 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -1049,9 +1049,4 @@ void Maillage_Volume(void *data, void *dum)
     List_Delete(Simplexes_Destroyed);
   }
 
-  THEM->Statistics[6] += Tree_Nbr(v->Vertices);
-  THEM->Statistics[9] += Tree_Nbr(v->Simplexes);
-  THEM->Statistics[10] += Tree_Nbr(v->Hexahedra);
-  THEM->Statistics[11] += Tree_Nbr(v->Prisms);
-  THEM->Statistics[12] += Tree_Nbr(v->Pyramids);
 }
diff --git a/Mesh/3D_Mesh_Old.cpp b/Mesh/3D_Mesh_Old.cpp
index 1121664954acdc5fb132d8f79abb347272841cf9..6df782ed05db7940f4090b704ad2f1114c3ff6dc 100644
--- a/Mesh/3D_Mesh_Old.cpp
+++ b/Mesh/3D_Mesh_Old.cpp
@@ -1,4 +1,4 @@
-// $Id: 3D_Mesh_Old.cpp,v 1.11 2004-04-18 03:36:07 geuzaine Exp $
+// $Id: 3D_Mesh_Old.cpp,v 1.12 2004-05-25 04:10:04 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -910,18 +910,4 @@ void Maillage_Volume(void *data, void *dum)
     List_Delete(Simplexes_Destroyed);
   }
 
-  THEM->Statistics[6] += Tree_Nbr(v->Vertices);
-  THEM->Statistics[9] += Tree_Nbr(v->Simplexes);
-  THEM->Statistics[10] += Tree_Nbr(v->Hexahedra);
-  THEM->Statistics[11] += Tree_Nbr(v->Prisms);
-
-  if(v->Typ == 99999) {
-    Gamma_Maillage(THEM, &THEM->Statistics[17], &THEM->Statistics[18],
-                   &THEM->Statistics[19]);
-    Eta_Maillage(THEM, &THEM->Statistics[20], &THEM->Statistics[21],
-                 &THEM->Statistics[22]);
-    R_Maillage(THEM, &THEM->Statistics[23], &THEM->Statistics[24],
-               &THEM->Statistics[25]);
-  }
-
 }
diff --git a/Mesh/Create.cpp b/Mesh/Create.cpp
index f5504391f2ab64ee5b1225e6c5410b736532af36..8f0390b74501ab953411093b044eb3a2473cce95 100644
--- a/Mesh/Create.cpp
+++ b/Mesh/Create.cpp
@@ -1,4 +1,4 @@
-// $Id: Create.cpp,v 1.54 2004-05-22 01:29:46 geuzaine Exp $
+// $Id: Create.cpp,v 1.55 2004-05-25 04:10:04 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -71,33 +71,6 @@ int compareEdgeLoop(const void *a, const void *b)
   return ((*q)->Num - (*w)->Num);
 }
 
-int compareHexahedron(const void *a, const void *b)
-{
-  Hexahedron **q, **w;
-
-  q = (Hexahedron **) a;
-  w = (Hexahedron **) b;
-  return ((*q)->Num - (*w)->Num);
-}
-
-int comparePrism(const void *a, const void *b)
-{
-  Prism **q, **w;
-
-  q = (Prism **) a;
-  w = (Prism **) b;
-  return ((*q)->Num - (*w)->Num);
-}
-
-int comparePyramid(const void *a, const void *b)
-{
-  Pyramid **q, **w;
-
-  q = (Pyramid **) a;
-  w = (Pyramid **) b;
-  return ((*q)->Num - (*w)->Num);
-}
-
 int compareQuality(const void *a, const void *b)
 {
   double d;
@@ -561,7 +534,6 @@ Curve *Create_Curve(int Num, int Typ, int Order, List_T * Liste,
   pC->Num = Num;
   THEM->MaxLineNum = IMAX(THEM->MaxLineNum, Num);
   pC->Simplexes = Tree_Create(sizeof(Simplex *), compareSimplex);
-  pC->TrsfSimplexes = List_Create(1, 10, sizeof(Simplex *));
   pC->Method = LIBRE;
   pC->degre = Order;
   pC->Circle.n[0] = 0.0;
@@ -658,7 +630,6 @@ void Free_Curve(void *a, void *b)
     List_Delete(pC->Vertices);
     Tree_Action(pC->Simplexes, Free_Simplex);
     Tree_Delete(pC->Simplexes);
-    List_Delete(pC->TrsfSimplexes);
     Free(pC->k);
     List_Delete(pC->Control_Points);
     Free(pC->cp);
@@ -684,10 +655,10 @@ Surface *Create_Surface(int Num, int Typ)
   for(i = 0; i < 5; i++)
     pS->ipar[i] = 0;
   pS->Recombine = 0;
-  pS->RecombineAngle = 30;
+  pS->RecombineAngle = 90;
   pS->TrsfPoints = List_Create(4, 4, sizeof(Vertex *));
   pS->Simplexes = Tree_Create(sizeof(Simplex *), compareQuality);
-  pS->TrsfSimplexes = List_Create(1, 10, sizeof(Simplex *));
+  pS->Quadrangles = Tree_Create(sizeof(Quadrangle *), compareQuadrangle);
   pS->Vertices = Tree_Create(sizeof(Vertex *), compareVertex);
   pS->TrsfVertices = List_Create(1, 10, sizeof(Vertex *));
   pS->Contours = List_Create(1, 1, sizeof(List_T *));
@@ -708,7 +679,8 @@ void Free_Surface(void *a, void *b)
     List_Delete(pS->TrsfPoints);
     Tree_Action(pS->Simplexes, Free_Simplex);
     Tree_Delete(pS->Simplexes);
-    List_Delete(pS->TrsfSimplexes);
+    Tree_Action(pS->Quadrangles, Free_Quadrangle);
+    Tree_Delete(pS->Quadrangles);
     Tree_Delete(pS->Vertices);
     List_Delete(pS->TrsfVertices);
     List_Delete(pS->Contours);
@@ -746,10 +718,12 @@ Volume *Create_Volume(int Num, int Typ)
   pV->Hexahedra = Tree_Create(sizeof(Hexahedron *), compareHexahedron);
   pV->Prisms = Tree_Create(sizeof(Prism *), comparePrism);
   pV->Pyramids = Tree_Create(sizeof(Pyramid *), comparePyramid);
-  pV->Simp_Surf = Tree_Create(sizeof(Simplex *), compareSimplex);       // for old extrusion mesh generator
   pV->Extrude = NULL;
   pV->Edges = NULL;
   pV->Faces = NULL;
+  // for old extrusion mesh generator
+  pV->Simp_Surf = Tree_Create(sizeof(Simplex *), compareSimplex);
+  pV->Quad_Surf = Tree_Create(sizeof(Simplex *), compareQuadrangle);
   return pV;
 }
 
@@ -758,11 +732,12 @@ void Free_Volume(void *a, void *b)
   Volume *pV = *(Volume **) a;
   if(pV) {
     List_Delete(pV->TrsfPoints);
-    List_Delete(pV->Surfaces);  //surfaces freed elsewhere
+    List_Delete(pV->Surfaces);  // surfaces freed elsewhere
     Tree_Action(pV->Simplexes, Free_Simplex);
     Tree_Delete(pV->Simplexes);
     Tree_Delete(pV->Simp_Surf); // for old extrusion mesh generator
-    Tree_Delete(pV->Vertices);  //vertices freed elsewhere
+    Tree_Delete(pV->Quad_Surf); // for old extrusion mesh generator
+    Tree_Delete(pV->Vertices);  // vertices freed elsewhere
     Tree_Action(pV->Hexahedra, Free_Hexahedron);
     Tree_Delete(pV->Hexahedra);
     Tree_Action(pV->Prisms, Free_Prism);
@@ -777,94 +752,3 @@ void Free_Volume(void *a, void *b)
   }
 }
 
-Hexahedron *Create_Hexahedron(Vertex * v1, Vertex * v2, Vertex * v3,
-                              Vertex * v4, Vertex * v5, Vertex * v6,
-                              Vertex * v7, Vertex * v8)
-{
-  Hexahedron *h;
-
-  h = (Hexahedron *) Malloc(sizeof(Hexahedron));
-  h->iEnt = -1;
-  h->iPart = -1;
-  h->Num = ++THEM->MaxSimplexNum;
-  h->Visible = VIS_MESH;
-  h->V[0] = v1;
-  h->V[1] = v2;
-  h->V[2] = v3;
-  h->V[3] = v4;
-  h->V[4] = v5;
-  h->V[5] = v6;
-  h->V[6] = v7;
-  h->V[7] = v8;
-  h->VSUP = NULL;
-
-  return (h);
-}
-
-void Free_Hexahedron(void *a, void *b)
-{
-  Hexahedron *pH = *(Hexahedron **) a;
-  if(pH) {
-    Free(pH);
-    pH = NULL;
-  }
-}
-
-Prism *Create_Prism(Vertex * v1, Vertex * v2, Vertex * v3,
-                    Vertex * v4, Vertex * v5, Vertex * v6)
-{
-  Prism *p;
-
-  p = (Prism *) Malloc(sizeof(Prism));
-  p->iEnt = -1;
-  p->iPart = -1;
-  p->Num = ++THEM->MaxSimplexNum;
-  p->Visible = VIS_MESH;
-  p->V[0] = v1;
-  p->V[1] = v2;
-  p->V[2] = v3;
-  p->V[3] = v4;
-  p->V[4] = v5;
-  p->V[5] = v6;
-  p->VSUP = NULL;
-
-  return (p);
-}
-
-void Free_Prism(void *a, void *b)
-{
-  Prism *pP = *(Prism **) a;
-  if(pP) {
-    Free(pP);
-    pP = NULL;
-  }
-}
-
-Pyramid *Create_Pyramid(Vertex * v1, Vertex * v2, Vertex * v3,
-                        Vertex * v4, Vertex * v5)
-{
-  Pyramid *p;
-
-  p = (Pyramid *) Malloc(sizeof(Pyramid));
-  p->iEnt = -1;
-  p->iPart = -1;
-  p->Num = ++THEM->MaxSimplexNum;
-  p->Visible = VIS_MESH;
-  p->V[0] = v1;
-  p->V[1] = v2;
-  p->V[2] = v3;
-  p->V[3] = v4;
-  p->V[4] = v5;
-  p->VSUP = NULL;
-
-  return (p);
-}
-
-void Free_Pyramid(void *a, void *b)
-{
-  Pyramid *p = *(Pyramid **) a;
-  if(p) {
-    Free(p);
-    p = NULL;
-  }
-}
diff --git a/Mesh/Create.h b/Mesh/Create.h
index f0f95c7167e5d7a7051eea78753b14ec186ffd2b..b1c4f6146825326f2ace1b9aebbd79b1f5b66a2f 100644
--- a/Mesh/Create.h
+++ b/Mesh/Create.h
@@ -28,9 +28,6 @@ int compareNXE(const void *a, const void *b);
 int compareFxE(const void *a, const void *b);
 int compareSurfaceLoop(const void *a, const void *b);
 int compareEdgeLoop(const void *a, const void *b);
-int compareHexahedron(const void *a, const void *b);
-int comparePrism(const void *a, const void *b);
-int comparePyramid(const void *a, const void *b);
 int compareQuality(const void *a, const void *b);
 int compareCurve(const void *a, const void *b);
 int compareAttractor(const void *a, const void *b);
@@ -48,12 +45,6 @@ Curve         *Create_Curve(int Num, int Typ, int Order, List_T * Liste,
 			    List_T * Knots, int p1, int p2, double u1, double u2);
 Surface       *Create_Surface(int Num, int Typ);
 Volume        *Create_Volume(int Num, int Typ);
-Hexahedron    *Create_Hexahedron(Vertex * v1, Vertex * v2, Vertex * v3, Vertex * v4,
-				 Vertex * v5, Vertex * v6, Vertex * v7, Vertex * v8);
-Prism         *Create_Prism(Vertex * v1, Vertex * v2, Vertex * v3,
-			    Vertex * v4, Vertex * v5, Vertex * v6);
-Pyramid       *Create_Pyramid(Vertex * v1, Vertex * v2, Vertex * v3,
-			      Vertex * v4, Vertex * v5);
 EdgeLoop      *Create_EdgeLoop(int Num, List_T * intlist);
 SurfaceLoop   *Create_SurfaceLoop(int Num, List_T * intlist);
 
@@ -61,9 +52,6 @@ void Free_PhysicalGroup(void *a, void *b);
 void Free_MeshPartition(void *a, void *b);
 void Free_Surface(void *a, void *b);
 void Free_Volume(void *a, void *b);
-void Free_Hexahedron(void *a, void *b);
-void Free_Prism(void *a, void *b);
-void Free_Pyramid(void *a, void *b);
 void Free_Curve(void *a, void *b);
 void Free_EdgeLoop(void *a, void *b);
 void Free_SurfaceLoop(void *a, void *b);
diff --git a/Mesh/Edge.cpp b/Mesh/Edge.cpp
index 4eaa3d932ef47df643b071ded4e6401e1c49a1d1..2c8d22d27058c40c8ef249871d9e7c8f544f8837 100644
--- a/Mesh/Edge.cpp
+++ b/Mesh/Edge.cpp
@@ -1,4 +1,4 @@
-// $Id: Edge.cpp,v 1.15 2004-04-19 00:18:07 geuzaine Exp $
+// $Id: Edge.cpp,v 1.16 2004-05-25 04:10:05 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -41,6 +41,44 @@ int edges_quad[4][2] = {
   {3, 0}
 };
 
+int edges_hexa[12][2] = {
+  {0, 1},
+  {0, 3},
+  {0, 4},
+  {1, 2},
+  {1, 5},
+  {2, 3},
+  {2, 6},
+  {3, 7},
+  {4, 5},
+  {4, 7},
+  {5, 6},
+  {6, 7}
+};
+
+int edges_prism[9][2] = {
+  {0, 1},
+  {0, 2},
+  {0, 3},
+  {1, 2},
+  {1, 4},
+  {2, 5},
+  {3, 4},
+  {3, 5},
+  {4, 5}
+};
+
+int edges_pyramid[8][2] = {
+  {0, 1},
+  {0, 3},
+  {0, 4},
+  {1, 2},
+  {1, 4},
+  {2, 3},
+  {2, 4},
+  {3, 4}
+};
+
 int edges_non[3] = { 2, 0, 1 };
 
 int compareedge(const void *a, const void *b)
@@ -77,62 +115,129 @@ int compareedge_angle(const void *a, const void *b)
   return (-1);
 }
 
-void EdgesContainer::AddEdges(Simplex * s, bool EdgesInVolume)
+void EdgesContainer::AddEdges(Simplex * s)
 {
-  int N, i, j;
+  int N, i;
   Edge E, *pE;
-  int edges[6][2];
 
-  if(s->V[3] && EdgesInVolume) {
+  if(s->V[3])
     N = 6;
-    for(i = 0; i < N; i++)
-      for(j = 0; j < 2; j++)
-        edges[i][j] = edges_tetra[i][j];
-  }
-  else if(s->V[3]) {
-    N = 4;
-    for(i = 0; i < N; i++)
-      for(j = 0; j < 2; j++)
-        edges[i][j] = edges_quad[i][j];
-  }
-  else if(s->V[2]) {
+  else if(s->V[2])
     N = 3;
-    for(i = 0; i < N; i++)
-      for(j = 0; j < 2; j++)
-        edges[i][j] = edges_tetra[i][j];
-  }
-  else {
+  else
     N = 1;
-    for(i = 0; i < N; i++)
-      for(j = 0; j < 2; j++)
-        edges[i][j] = edges_tetra[i][j];
-  }
 
   for(i = 0; i < N; i++) {
-    E.V[0] = s->V[edges[i][0]];
-    E.V[1] = s->V[edges[i][1]];
+    E.V[0] = s->V[edges_tetra[i][0]];
+    E.V[1] = s->V[edges_tetra[i][1]];
     if((pE = (Edge *) Tree_PQuery(AllEdges, &E))) {
+      if(!pE->Simplexes) // the edge could belong to a non-simplex
+	pE->Simplexes = List_Create(2, 1, sizeof(Simplex *));
       List_Add(pE->Simplexes, &s);
       if(N == 3)
         pE->O[1] = s->V[edges_non[i]];
     }
     else {
       E.Simplexes = List_Create(2, 1, sizeof(Simplex *));
-      if(N == 3)
+      if(N == 3){
         E.O[0] = s->V[edges_non[i]];
-      if(N == 3)
         E.O[1] = NULL;
+      }
       List_Add(E.Simplexes, &s);
       E.newv = NULL;
-      Tree_Replace(AllEdges, &E);
+      Tree_Add(AllEdges, &E);
+    }
+  }
+}
+
+void EdgesContainer::AddEdges(Quadrangle * q)
+{
+  Edge E, *pE;
+
+  for(int i = 0; i < 4; i++) {
+    E.V[0] = q->V[edges_quad[i][0]];
+    E.V[1] = q->V[edges_quad[i][1]];
+    if((pE = (Edge *) Tree_PQuery(AllEdges, &E))) {
+      if(!pE->Quadrangles) // the edge could belong to a non-quad
+	pE->Quadrangles = List_Create(2, 1, sizeof(Quadrangle *));
+      List_Add(pE->Quadrangles, &q);
+    }
+    else {
+      E.Quadrangles = List_Create(2, 1, sizeof(Quadrangle *));
+      List_Add(E.Quadrangles, &q);
+      E.newv = NULL;
+      Tree_Add(AllEdges, &E);
+    }
+  }
+}
+
+void EdgesContainer::AddEdges(Hexahedron * h)
+{
+  Edge E, *pE;
+
+  for(int i = 0; i < 12; i++) {
+    E.V[0] = h->V[edges_hexa[i][0]];
+    E.V[1] = h->V[edges_hexa[i][1]];
+    if((pE = (Edge *) Tree_PQuery(AllEdges, &E))) {
+      if(!pE->Hexahedra) // the edge could belong to a non-hexa
+	pE->Hexahedra = List_Create(2, 1, sizeof(Hexahedron *));
+      List_Add(pE->Hexahedra, &h);
+    }
+    else {
+      E.Hexahedra = List_Create(2, 1, sizeof(Hexahedron *));
+      List_Add(E.Hexahedra, &h);
+      E.newv = NULL;
+      Tree_Add(AllEdges, &E);
     }
   }
 }
 
-EdgesContainer::EdgesContainer(Tree_T * Simplexes, bool EdgesInVolume)
+void EdgesContainer::AddEdges(Prism * p)
+{
+  Edge E, *pE;
+
+  for(int i = 0; i < 9; i++) {
+    E.V[0] = p->V[edges_prism[i][0]];
+    E.V[1] = p->V[edges_prism[i][1]];
+    if((pE = (Edge *) Tree_PQuery(AllEdges, &E))) {
+      if(!pE->Prisms) // the edge could belong to a non-prism
+	pE->Prisms = List_Create(2, 1, sizeof(Prism *));
+      List_Add(pE->Prisms, &p);
+    }
+    else {
+      E.Prisms = List_Create(2, 1, sizeof(Prism *));
+      List_Add(E.Prisms, &p);
+      E.newv = NULL;
+      Tree_Add(AllEdges, &E);
+    }
+  }
+}
+
+void EdgesContainer::AddEdges(Pyramid * p)
+{
+  Edge E, *pE;
+
+  for(int i = 0; i < 8; i++) {
+    E.V[0] = p->V[edges_pyramid[i][0]];
+    E.V[1] = p->V[edges_pyramid[i][1]];
+    if((pE = (Edge *) Tree_PQuery(AllEdges, &E))) {
+      if(!pE->Pyramids) // the edge could belong to a non-pyramid
+	pE->Pyramids = List_Create(2, 1, sizeof(Pyramid *));
+      List_Add(pE->Pyramids, &p);
+    }
+    else {
+      E.Pyramids = List_Create(2, 1, sizeof(Pyramid *));
+      List_Add(E.Pyramids, &p);
+      E.newv = NULL;
+      Tree_Add(AllEdges, &E);
+    }
+  }
+}
+
+EdgesContainer::EdgesContainer(Tree_T * Simplexes)
 {
   AllEdges = Tree_Create(sizeof(Edge), compareedge);
-  AddTree(Simplexes, EdgesInVolume);
+  AddSimplexTree(Simplexes);
 }
 
 EdgesContainer::EdgesContainer(List_T * Surfaces)
@@ -141,7 +246,7 @@ EdgesContainer::EdgesContainer(List_T * Surfaces)
   Surface *s;
   for(int i = 0; i < List_Nbr(Surfaces); i++) {
     List_Read(Surfaces, i, &s);
-    AddTree(s->Simplexes, false);
+    AddSimplexTree(s->Simplexes);
   }
 }
 
@@ -150,13 +255,57 @@ EdgesContainer::EdgesContainer()
   AllEdges = Tree_Create(sizeof(Edge), compareedge);
 }
 
-void EdgesContainer::AddTree(Tree_T * Simplexes, bool EdgesInVolume)
+void EdgesContainer::AddSimplexTree(Tree_T * Simplexes)
 {
   Simplex *s;
   List_T *temp = Tree2List(Simplexes);
   for(int i = 0; i < List_Nbr(temp); i++) {
     List_Read(temp, i, &s);
-    AddEdges(s, EdgesInVolume);
+    AddEdges(s);
+  }
+  List_Delete(temp);
+}
+
+void EdgesContainer::AddQuadrangleTree(Tree_T * Quadrangles)
+{
+  Quadrangle *q;
+  List_T *temp = Tree2List(Quadrangles);
+  for(int i = 0; i < List_Nbr(temp); i++) {
+    List_Read(temp, i, &q);
+    AddEdges(q);
+  }
+  List_Delete(temp);
+}
+
+void EdgesContainer::AddHexahedronTree(Tree_T * Hexahedra)
+{
+  Hexahedron *h;
+  List_T *temp = Tree2List(Hexahedra);
+  for(int i = 0; i < List_Nbr(temp); i++) {
+    List_Read(temp, i, &h);
+    AddEdges(h);
+  }
+  List_Delete(temp);
+}
+
+void EdgesContainer::AddPrismTree(Tree_T * Prisms)
+{
+  Prism *p;
+  List_T *temp = Tree2List(Prisms);
+  for(int i = 0; i < List_Nbr(temp); i++) {
+    List_Read(temp, i, &p);
+    AddEdges(p);
+  }
+  List_Delete(temp);
+}
+
+void EdgesContainer::AddPyramidTree(Tree_T * Pyramids)
+{
+  Pyramid *p;
+  List_T *temp = Tree2List(Pyramids);
+  for(int i = 0; i < List_Nbr(temp); i++) {
+    List_Read(temp, i, &p);
+    AddEdges(p);
   }
   List_Delete(temp);
 }
@@ -164,12 +313,13 @@ void EdgesContainer::AddTree(Tree_T * Simplexes, bool EdgesInVolume)
 void Free_Edge(void *a, void *b)
 {
   Edge *e = (Edge *) a;
-  if(e->Liste)
-    List_Delete(e->Liste);
-  if(e->Simplexes)
-    List_Delete(e->Simplexes);
-  if(e->Points)
-    List_Delete(e->Points);
+  List_Delete(e->Liste);
+  List_Delete(e->Simplexes);
+  List_Delete(e->Quadrangles);
+  List_Delete(e->Hexahedra);
+  List_Delete(e->Prisms);
+  List_Delete(e->Pyramids);
+  List_Delete(e->Points);
 }
 
 EdgesContainer::~EdgesContainer()
@@ -188,6 +338,54 @@ bool EdgesContainer::Search(Vertex * v1, Vertex * v2)
   return true;
 }
 
+void EdgesContainer::Print()
+{
+  List_T *temp = Tree2List(AllEdges);
+  printf("Print Edges START\n");
+  for(int i = 0; i < List_Nbr(temp); i++) {
+    Edge *e = (Edge*)List_Pointer(temp, i);
+    printf("edge %d -> %d", e->V[0]->Num, e->V[1]->Num);
+    if(List_Nbr(e->Simplexes)){
+      printf(", in simplex");
+      for(int j = 0; j < List_Nbr(e->Simplexes); j++){
+	Simplex *s = *(Simplex**)List_Pointer(e->Simplexes, j);
+	printf(" %d", s->Num);
+      }
+    }
+    if(List_Nbr(e->Quadrangles)){
+      printf(", in quad");
+      for(int j = 0; j < List_Nbr(e->Quadrangles); j++){
+	Quadrangle *q = *(Quadrangle**)List_Pointer(e->Quadrangles, j);
+	printf(" %d", q->Num);
+      }
+    }
+    if(List_Nbr(e->Hexahedra)){
+      printf(", in hexa");
+      for(int j = 0; j < List_Nbr(e->Hexahedra); j++){
+	Hexahedron *h = *(Hexahedron**)List_Pointer(e->Hexahedra, j);
+	printf(" %d", h->Num);
+      }
+    }
+    if(List_Nbr(e->Prisms)){
+      printf(", in prism");
+      for(int j = 0; j < List_Nbr(e->Prisms); j++){
+	Prism *p = *(Prism**)List_Pointer(e->Prisms, j);
+	printf(" %d", p->Num);
+      }
+    }
+    if(List_Nbr(e->Pyramids)){
+      printf(", in pyramid");
+      for(int j = 0; j < List_Nbr(e->Pyramids); j++){
+	Pyramid *p = *(Pyramid**)List_Pointer(e->Pyramids, j);
+	printf(" %d", p->Num);
+      }
+    }
+    printf("\n");
+  }
+  printf("Print Edges STOP\n");
+  List_Delete(temp);
+}
+
 void EdgesContainer::SwapEdge(Vertex * V[2])
 {
   Edge *e, E;
@@ -201,6 +399,8 @@ void EdgesContainer::SwapEdge(Vertex * V[2])
   E = *e;
   if(!e)
     return;
+  if(!e->Simplexes)
+    return;
   List_Read(e->Simplexes, 0, &s1);
   List_Read(e->Simplexes, 1, &s2);
 
diff --git a/Mesh/Edge.h b/Mesh/Edge.h
index c3e4f3aadafdf8e3e9ffa204a10c5d81e9175772..a71167ce8d3881010a0348386ff6820451dda305 100644
--- a/Mesh/Edge.h
+++ b/Mesh/Edge.h
@@ -30,45 +30,54 @@ public :
   int Num;
   Vertex *V[2];
   List_T *Simplexes;
+  List_T *Quadrangles;
+  List_T *Hexahedra;
+  List_T *Prisms;
+  List_T *Pyramids;
   Vertex *newv;
   Vertex *O[2];
   double a;
   List_T *Liste;
   List_T *Points;
-  Edge()
-    {
-      Num = 0;
-      Liste = NULL;
-      Simplexes = NULL;
-      Points = NULL;
-    }
-  // MEMORY LEAK (JF)
-  ~Edge()
-    {
-      //if(Liste)List_Delete(Liste);
-      //if(Simplexes)List_Delete(Simplexes);
-      //if(Points)List_Delete(Points);
-    }
+  Edge(){
+    Num = 0;
+    Simplexes = NULL;
+    Quadrangles = NULL;
+    Hexahedra = NULL;
+    Prisms = NULL;
+    Pyramids = NULL;
+    Liste = NULL;
+    Points = NULL;
+  }
+  ~Edge(){ ; }
 };
 
 class EdgesContainer
 {
   public :
     Tree_T * AllEdges;
-    EdgesContainer (Tree_T *Simplexes, bool i = false);
-    EdgesContainer (List_T *Surfaces);
-    EdgesContainer ();
+    EdgesContainer(Tree_T *Simplexes);
+    EdgesContainer(List_T *Surfaces);
+    EdgesContainer();
     ~EdgesContainer();
-    void AddTree (Tree_T *Simplexes, bool EdgesInVolume);
-    void AddEdges(Simplex *s, bool i);
-    void GetEdges(Simplex *s, bool i, Edge *ed[4],int *ori);
+    void AddSimplexTree(Tree_T *Simplexes);
+    void AddQuadrangleTree(Tree_T *Quadrangles);
+    void AddHexahedronTree(Tree_T *Hexahedra);
+    void AddPrismTree(Tree_T *Prisms);    
+    void AddPyramidTree(Tree_T *Pyramids);
+    void AddEdges(Simplex *s);
+    void AddEdges(Quadrangle *q);
+    void AddEdges(Hexahedron *h);
+    void AddEdges(Prism *p);
+    void AddEdges(Pyramid *p);
     void RemoveEdge(Edge *e);
-    void SwapEdge (Vertex *v[2]);
+    void SwapEdge(Vertex *v[2]);
     bool Search(Vertex *v1, Vertex *v2);
+    void Print();
 };
 
-int compareedge (const void *a, const void *b);
-int compareedge_angle (const void *a, const void *b);
+int compareedge(const void *a, const void *b);
+int compareedge_angle(const void *a, const void *b);
 void Free_Edge(void *a, void *b);
 
 #endif
diff --git a/Mesh/Element.cpp b/Mesh/Element.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0fde9f97dc8eadaf979e6ce1ae16a5260b60e0a3
--- /dev/null
+++ b/Mesh/Element.cpp
@@ -0,0 +1,239 @@
+// $Id: Element.cpp,v 1.1 2004-05-25 04:10:05 geuzaine Exp $
+//
+// Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+// USA.
+// 
+// Please report all bugs and problems to <gmsh@geuz.org>.
+
+#include "Gmsh.h"
+#include "Mesh.h"
+#include "Element.h"
+
+int Element::TotalNumber = 0;
+
+Element::Element()
+  : Num(0), iEnt(-1), iPart(-1), Visible(VIS_MESH), VSUP(NULL)
+{
+}
+
+Element::~Element()
+{
+}
+
+// Quads
+
+Quadrangle::Quadrangle()
+{
+  iEnt = -1;
+  iPart = -1;
+  Num = ++TotalNumber;
+  Visible = VIS_MESH;
+  for(int i = 0; i < 4; i++) V[i] = NULL;
+  VSUP = NULL;
+}
+
+Quadrangle::Quadrangle(Vertex *v1, Vertex *v2, Vertex *v3, Vertex *v4)
+{
+  iEnt = -1;
+  iPart = -1;
+  Num = ++TotalNumber;
+  Visible = VIS_MESH;
+  V[0] = v1; V[1] = v2; V[2] = v3; V[3] = v4;
+  VSUP = NULL;
+}
+
+Quadrangle::~Quadrangle()
+{
+  if(VSUP) Free(VSUP);
+}
+
+Quadrangle *Create_Quadrangle(Vertex *v1, Vertex *v2, Vertex *v3, Vertex *v4)
+{
+  Quadrangle *q = new Quadrangle(v1, v2, v3, v4);
+  return q;
+}
+
+void Free_Quadrangle(void *a, void *b)
+{
+  Quadrangle *q = *(Quadrangle **) a;
+  if(q) {
+    delete q;
+    q = NULL;
+  }
+}
+
+int compareQuadrangle(const void *a, const void *b)
+{
+  Quadrangle *q = *(Quadrangle **) a;
+  Quadrangle *w = *(Quadrangle **) b;
+  return (q->Num - w->Num);
+}
+
+// Hexas
+
+Hexahedron::Hexahedron()
+{
+  iEnt = -1;
+  iPart = -1;
+  Num = ++TotalNumber;
+  Visible = VIS_MESH;
+  for(int i = 0; i < 8; i++) V[i] = NULL;
+  VSUP = NULL;
+}
+
+Hexahedron::Hexahedron(Vertex *v1, Vertex *v2, Vertex *v3, Vertex *v4,
+		       Vertex *v5, Vertex *v6, Vertex *v7, Vertex *v8)
+{
+  iEnt = -1;
+  iPart = -1;
+  Num = ++TotalNumber;
+  Visible = VIS_MESH;
+  V[0] = v1; V[1] = v2; V[2] = v3; V[3] = v4;
+  V[4] = v5; V[5] = v6; V[6] = v7; V[7] = v8;
+  VSUP = NULL;
+}
+
+Hexahedron::~Hexahedron()
+{
+  if(VSUP) Free(VSUP);
+}
+
+Hexahedron *Create_Hexahedron(Vertex * v1, Vertex * v2, Vertex * v3,
+                              Vertex * v4, Vertex * v5, Vertex * v6,
+                              Vertex * v7, Vertex * v8)
+{
+  Hexahedron *h = new Hexahedron(v1, v2, v3, v4, v5, v6, v7, v8);
+  return h;
+}
+
+void Free_Hexahedron(void *a, void *b)
+{
+  Hexahedron *h = *(Hexahedron **) a;
+  if(h) {
+    delete h;
+    h = NULL;
+  }
+}
+
+int compareHexahedron(const void *a, const void *b)
+{
+  Hexahedron *q = *(Hexahedron **) a;
+  Hexahedron *w = *(Hexahedron **) b;
+  return (q->Num - w->Num);
+}
+
+// Prisms
+
+Prism::Prism()
+{
+  iEnt = -1;
+  iPart = -1;
+  Num = 0;
+  Visible = VIS_MESH;
+  for(int i = 0; i < 6; i++) V[i] = NULL;
+  VSUP = NULL;
+}
+
+Prism::Prism(Vertex *v1, Vertex *v2, Vertex *v3, 
+	     Vertex *v4, Vertex *v5, Vertex *v6)
+{
+  iEnt = -1;
+  iPart = -1;
+  Num = ++TotalNumber;
+  Visible = VIS_MESH;
+  V[0] = v1; V[1] = v2; V[2] = v3; 
+  V[3] = v4; V[4] = v5; V[5] = v6;
+  VSUP = NULL;
+}
+
+Prism::~Prism()
+{
+  if(VSUP) Free(VSUP);
+}
+
+Prism *Create_Prism(Vertex * v1, Vertex * v2, Vertex * v3,
+                    Vertex * v4, Vertex * v5, Vertex * v6)
+{
+  Prism *p = new Prism(v1, v2, v3, v4, v5, v6);
+  return p;
+}
+
+void Free_Prism(void *a, void *b)
+{
+  Prism *p = *(Prism **) a;
+  if(p) {
+    delete p;
+    p = NULL;
+  }
+}
+
+int comparePrism(const void *a, const void *b)
+{
+  Prism *q = *(Prism **) a;
+  Prism *w = *(Prism **) b;
+  return (q->Num - w->Num);
+}
+
+// Pyramids
+
+Pyramid::Pyramid()
+{
+  iEnt = -1;
+  iPart = -1;
+  Num = 0;
+  Visible = VIS_MESH;
+  for(int i = 0; i < 5; i++) V[i] = NULL;
+  VSUP = NULL;
+}
+
+Pyramid::Pyramid(Vertex *v1, Vertex *v2, Vertex *v3, Vertex *v4, Vertex *v5)
+{
+  iEnt = -1;
+  iPart = -1;
+  Num = ++TotalNumber;
+  Visible = VIS_MESH;
+  V[0] = v1; V[1] = v2; V[2] = v3; V[3] = v4; V[4] = v5; 
+  VSUP = NULL;
+}
+
+Pyramid::~Pyramid()
+{
+  if(VSUP) Free(VSUP);
+}
+
+Pyramid *Create_Pyramid(Vertex * v1, Vertex * v2, Vertex * v3,
+                        Vertex * v4, Vertex * v5)
+{
+  Pyramid *p = new Pyramid(v1, v2, v3, v4, v5);
+  return p;
+}
+
+void Free_Pyramid(void *a, void *b)
+{
+  Pyramid *p = *(Pyramid **) a;
+  if(p) {
+    delete p;
+    p = NULL;
+  }
+}
+
+int comparePyramid(const void *a, const void *b)
+{
+  Pyramid *q = *(Pyramid **) a;
+  Pyramid *w = *(Pyramid **) b;
+  return (q->Num - w->Num);
+}
diff --git a/Mesh/Element.h b/Mesh/Element.h
index 8ceb1e951986e46cdb3de8eb28901fafba1c79fb..d50ccdaaf219b44429ad72d86fb9c7c025decb69 100644
--- a/Mesh/Element.h
+++ b/Mesh/Element.h
@@ -20,7 +20,7 @@
 // 
 // Please report all bugs and problems to <gmsh@geuz.org>.
 
-#include "List.h"
+#include "Vertex.h"
 
 class Element {
  public:
@@ -29,7 +29,63 @@ class Element {
   int     iPart;         // Mesh partition index
   char    Visible;       // Visualization flag
   Vertex  **VSUP;        // suppl. nodes for higher order elts
-  virtual ~Element(){;}
+  static  int TotalNumber;
+  Element();
+  virtual ~Element();
 };
 
+class Quadrangle : public Element{
+ public:
+  Vertex *V[4];
+  Quadrangle();
+  Quadrangle(Vertex *v1, Vertex *v2, Vertex *v3, Vertex *v4);
+  ~Quadrangle();
+};
+
+class Hexahedron : public Element{
+ public:
+  Vertex *V[8];
+  Hexahedron();
+  Hexahedron(Vertex *v1, Vertex *v2, Vertex *v3, Vertex *v4,
+	     Vertex *v5, Vertex *v6, Vertex *v7, Vertex *v8);
+  ~Hexahedron();
+};
+
+class Prism : public Element{
+ public:
+  Vertex *V[6];
+  Prism();
+  Prism(Vertex *v1, Vertex *v2, Vertex *v3, 
+	Vertex *v4, Vertex *v5, Vertex *v6);
+  ~Prism();
+};
+
+class Pyramid : public Element{
+ public:
+  Vertex *V[5];
+  Pyramid();
+  Pyramid(Vertex *v1, Vertex *v2, Vertex *v3, Vertex *v4, Vertex *v5);
+  ~Pyramid();
+};
+
+// C interface
+
+Quadrangle *Create_Quadrangle (Vertex *v1, Vertex *v2, Vertex *v3, Vertex *v4);
+Hexahedron *Create_Hexahedron(Vertex * v1, Vertex * v2, Vertex * v3, Vertex * v4,
+			      Vertex * v5, Vertex * v6, Vertex * v7, Vertex * v8);
+Prism *Create_Prism(Vertex * v1, Vertex * v2, Vertex * v3,
+		    Vertex * v4, Vertex * v5, Vertex * v6);
+Pyramid *Create_Pyramid(Vertex * v1, Vertex * v2, Vertex * v3,
+			Vertex * v4, Vertex * v5);
+
+void Free_Quadrangle(void *a, void *b);
+void Free_Hexahedron(void *a, void *b);
+void Free_Prism(void *a, void *b);
+void Free_Pyramid(void *a, void *b);
+
+int compareQuadrangle(const void *a, const void *b);
+int compareHexahedron(const void *a, const void *b);
+int comparePrism(const void *a, const void *b);
+int comparePyramid(const void *a, const void *b);
+
 #endif
diff --git a/Mesh/Generator.cpp b/Mesh/Generator.cpp
index 7872a9d55ee44e7cc8e974b7e98ccbf9a2cc18bc..ed242cecfd600c423af01d5e7063b2dfd467914c 100644
--- a/Mesh/Generator.cpp
+++ b/Mesh/Generator.cpp
@@ -1,4 +1,4 @@
-// $Id: Generator.cpp,v 1.52 2004-05-07 18:42:48 geuzaine Exp $
+// $Id: Generator.cpp,v 1.53 2004-05-25 04:10:05 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -25,26 +25,151 @@
 #include "Create.h"
 #include "Context.h"
 #include "OpenFile.h"
+#include "Views.h"
 
 extern Mesh *THEM;
 extern Context_T CTX;
 
-void GetStatistics(double s[50])
+static int nbOrder2 = 0;
+
+void countOrder2(void *a, void *b)
 {
-  int i;
-  if(!THEM) {
-    for(i = 0; i < 50; i++)
-      s[i] = 0.;
+  Vertex *v = *(Vertex**)a;
+  if(v->Degree == 2) nbOrder2++;
+}
+
+void GetStatistics(double stat[50])
+{
+  for(int i = 0; i < 50; i++)
+    stat[i] = 0.;
+
+  if(!THEM)
+    return;
+
+  stat[0] = Tree_Nbr(THEM->Points);
+  stat[1] = Tree_Nbr(THEM->Curves);
+  stat[2] = Tree_Nbr(THEM->Surfaces);
+  stat[3] = Tree_Nbr(THEM->Volumes);
+  
+  stat[4] = 0.;
+  if(Tree_Nbr(THEM->Curves)) {
+    List_T *curves = Tree2List(THEM->Curves);
+    for(int i = 0; i < List_Nbr(curves); i++){
+      Curve *c;
+      List_Read(curves, i, &c);
+      stat[4] += List_Nbr(c->Vertices);
+    }
+    List_Delete(curves);
   }
-  else {
-    THEM->Statistics[0] = Tree_Nbr(THEM->Points);
-    THEM->Statistics[1] = Tree_Nbr(THEM->Curves);
-    THEM->Statistics[2] = Tree_Nbr(THEM->Surfaces);
-    THEM->Statistics[3] = Tree_Nbr(THEM->Volumes);
-    Mesh_Quality(THEM);
-    for(i = 0; i < 50; i++)
-      s[i] = THEM->Statistics[i];
+
+  stat[5] = stat[7] = stat[8] = 0.;
+  if(Tree_Nbr(THEM->Surfaces)) {
+    List_T *surfaces = Tree2List(THEM->Surfaces);
+    for(int i = 0; i < List_Nbr(surfaces); i++){
+      Surface *s;
+      List_Read(surfaces, i, &s);
+      stat[5] += Tree_Nbr(s->Vertices);
+      stat[7] += Tree_Nbr(s->Simplexes);
+      stat[8] += Tree_Nbr(s->Quadrangles);
+    }
+    List_Delete(surfaces);
+  }
+
+  stat[6] = stat[9] = stat[10] = stat[11] = stat[12] = 0.;
+  if(Tree_Nbr(THEM->Volumes)) {
+    List_T *volumes = Tree2List(THEM->Volumes);
+    for(int i = 0; i < List_Nbr(volumes); i++){
+      Volume *v;
+      List_Read(volumes, i, &v);
+      stat[6] += Tree_Nbr(v->Vertices);
+      stat[9] += Tree_Nbr(v->Simplexes);
+      stat[10] += Tree_Nbr(v->Hexahedra);
+      stat[11] += Tree_Nbr(v->Prisms);
+      stat[12] += Tree_Nbr(v->Pyramids);
+    }
+    List_Delete(volumes);
   }
+
+  // hack... (Read_Mesh does not fill-in the vertices)
+  int nbnod = Tree_Nbr(THEM->Vertices);
+  if(nbnod && !stat[4] && !stat[5] && !stat[6]){
+    if(stat[9] || stat[10] || stat[11] || stat[12])
+      stat[6] = nbnod;
+    else if(stat[7] || stat[8])
+      stat[5] = nbnod;
+    else
+      stat[4] = nbnod;
+  }
+
+  stat[13] = THEM->timing[0];
+  stat[14] = THEM->timing[1];
+  stat[15] = THEM->timing[2];
+
+  nbOrder2 = 0;
+  Tree_Action(THEM->Vertices, countOrder2);
+  stat[16] = nbOrder2;
+
+  Mesh_Quality(THEM);
+  stat[17] = THEM->quality_gamma[0];
+  stat[18] = THEM->quality_gamma[1];
+  stat[19] = THEM->quality_gamma[2];
+  stat[20] = THEM->quality_eta[0];
+  stat[21] = THEM->quality_eta[1];
+  stat[22] = THEM->quality_eta[2];
+  stat[23] = THEM->quality_rho[0];
+  stat[24] = THEM->quality_rho[1];
+  stat[25] = THEM->quality_rho[2];
+
+  stat[26] = List_Nbr(CTX.post.list);
+  for(int i = 0; i < List_Nbr(CTX.post.list); i++) {
+    Post_View *v = (Post_View *) List_Pointer(CTX.post.list, i);
+    stat[27] += v->NbSP + v->NbVP + v->NbTP;
+    stat[28] += v->NbSL + v->NbVL + v->NbTL;
+    stat[29] += v->NbST + v->NbVT + v->NbTT;
+    stat[30] += v->NbSQ + v->NbVQ + v->NbTQ;
+    stat[31] += v->NbSS + v->NbVS + v->NbTS;
+    stat[32] += v->NbSH + v->NbVH + v->NbTH;
+    stat[33] += v->NbSI + v->NbVI + v->NbTI;
+    stat[34] += v->NbSY + v->NbVY + v->NbTY;
+    stat[35] += v->NbT2 + v->NbT3;
+    if(v->Visible) {
+      if(v->DrawPoints)
+        stat[36] += 
+	  (v->DrawScalars ? v->NbSP : 0) + (v->DrawVectors ? v->NbVP : 0) + 
+	  (v->DrawTensors ? v->NbTP : 0);
+      if(v->DrawLines)
+        stat[37] += 
+	  (v->DrawScalars ? v->NbSL : 0) + (v->DrawVectors ? v->NbVL : 0) + 
+	  (v->DrawTensors ? v->NbTL : 0);
+      if(v->DrawTriangles)
+        stat[38] += 
+	  (v->DrawScalars ? v->NbST : 0) + (v->DrawVectors ? v->NbVT : 0) + 
+	  (v->DrawTensors ? v->NbTT : 0);
+      if(v->DrawQuadrangles)
+        stat[39] +=
+	  (v->DrawScalars ? v->NbSQ : 0) + (v->DrawVectors ? v->NbVQ : 0) + 
+	  (v->DrawTensors ? v->NbTQ : 0);
+      if(v->DrawTetrahedra)
+        stat[40] += 
+	  (v->DrawScalars ? v->NbSS : 0) + (v->DrawVectors ? v->NbVS : 0) + 
+	  (v->DrawTensors ? v->NbTS : 0);
+      if(v->DrawHexahedra)
+        stat[41] +=
+	  (v->DrawScalars ? v->NbSH : 0) + (v->DrawVectors ? v->NbVH : 0) +
+	  (v->DrawTensors ? v->NbTH : 0);
+      if(v->DrawPrisms)
+        stat[42] += 
+	  (v->DrawScalars ? v->NbSI : 0) + (v->DrawVectors ? v->NbVI : 0) +
+	  (v->DrawTensors ? v->NbTI : 0);
+      if(v->DrawPyramids)
+        stat[43] += 
+	  (v->DrawScalars ? v->NbSY : 0) + (v->DrawVectors ? v->NbVY : 0) + 
+	  (v->DrawTensors ? v->NbTY : 0);
+      if(v->DrawStrings)
+        stat[44] += v->NbT2 + v->NbT3;
+    }
+  }
+
 }
 
 void ApplyLcFactor_Point(void *a, void *b)
@@ -72,20 +197,6 @@ void ApplyLcFactor(Mesh * M)
   List_Action(M->Metric->Attractors, ApplyLcFactor_Attractor);
 }
 
-void Maillage_Dimension_0(Mesh * M)
-{
-  for(int i = 0; i < 50; i++)
-    M->Statistics[i] = 0.0;
-  for(int i = 0; i < NB_HISTOGRAM; i++)
-    M->Histogram[0][i] = M->Histogram[1][i] = M->Histogram[2][i] = 0;
-  // This is the default type of BGM (lc associated with 
-  // points of the geometry). It can be changed to
-  // - ONFILE by loading a view containing a bgmesh
-  // - CONSTANT
-  // - FUNCTION
-  Create_BgMesh(WITHPOINTS, .2, M);
-}
-
 void Maillage_Dimension_1(Mesh * M)
 {
   double t1, t2;
@@ -93,7 +204,7 @@ void Maillage_Dimension_1(Mesh * M)
   t1 = Cpu();
   Tree_Action(M->Curves, Maillage_Curve);
   t2 = Cpu();
-  M->Statistics[13] = t2 - t1;
+  M->timing[0] = t2 - t1;
 }
 
 void Maillage_Dimension_2(Mesh * M)
@@ -130,7 +241,7 @@ void Maillage_Dimension_2(Mesh * M)
 
   t2 = Cpu();
 
-  M->Statistics[14] = t2 - t1;
+  M->timing[1] = t2 - t1;
 }
 
 void Maillage_Dimension_3(Mesh * M)
@@ -167,7 +278,7 @@ void Maillage_Dimension_3(Mesh * M)
 
   t2 = Cpu();
 
-  M->Statistics[15] = t2 - t1;
+  M->timing[2] = t2 - t1;
 }
 
 
@@ -182,7 +293,8 @@ void Init_Mesh(Mesh * M)
   M->MaxSurfaceLoopNum = 0;
   M->MaxVolumeNum = 0;
   M->MaxPhysicalNum = 0;
-  M->MaxSimplexNum = 0;
+
+  Element::TotalNumber = 0;
 
   ExitExtrude();
 
@@ -242,6 +354,14 @@ void Init_Mesh(Mesh * M)
 
   M->status = 0;
 
+  Create_BgMesh(WITHPOINTS, .2, M);
+
+  for(int i = 0; i < 3; i++){
+    M->timing[i] = 0.0;
+    M->quality_gamma[i] = 0.0;
+    M->quality_eta[i] = 0.0;
+    M->quality_rho[i] = 0.0;
+  }
   CTX.mesh.changed = 1;
 }
 
diff --git a/Mesh/Makefile b/Mesh/Makefile
index 1ab0b555df8b87d582cc8773a0fa32246ae8e3bc..431832baefe7da29b89f7f8531bf3e6300f6a70f 100644
--- a/Mesh/Makefile
+++ b/Mesh/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.61 2004-04-24 03:51:59 geuzaine Exp $
+# $Id: Makefile,v 1.62 2004-05-25 04:10:05 geuzaine Exp $
 #
 # Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 #
@@ -57,7 +57,6 @@ SRC = 1D_Mesh.cpp \
       Print_Mesh.cpp \
       Read_Mesh.cpp \
       STL.cpp \
-      SMS.cpp \
       SwapEdge.cpp \
       Utils.cpp \
       Metric.cpp \
@@ -68,6 +67,7 @@ SRC = 1D_Mesh.cpp \
       CrossData.cpp \
       Vertex.cpp \
       Edge.cpp \
+      Element.cpp \
       Simplex.cpp 
 
 OBJ = ${SRC:.cpp=.o}
@@ -246,7 +246,8 @@ Generator.o: Generator.cpp ../Common/Gmsh.h ../Common/Message.h \
   ../DataStr/Malloc.h ../DataStr/List.h ../DataStr/Tree.h \
   ../DataStr/avl.h ../DataStr/Tools.h ../Numeric/Numeric.h Mesh.h \
   Vertex.h Element.h Simplex.h Edge.h ../Geo/ExtrudeParams.h STL.h \
-  Metric.h Matrix.h Create.h ../Common/Context.h ../Parser/OpenFile.h
+  Metric.h Matrix.h Create.h ../Common/Context.h ../Parser/OpenFile.h \
+  ../Common/Views.h ../Common/ColorTable.h
 Print_Mesh.o: Print_Mesh.cpp ../Common/Gmsh.h ../Common/Message.h \
   ../DataStr/Malloc.h ../DataStr/List.h ../DataStr/Tree.h \
   ../DataStr/avl.h ../DataStr/Tools.h ../Numeric/Numeric.h ../Geo/Geo.h \
@@ -264,11 +265,6 @@ STL.o: STL.cpp ../Common/Gmsh.h ../Common/Message.h ../DataStr/Malloc.h \
   ../Numeric/Numeric.h Mesh.h Vertex.h Element.h Simplex.h Edge.h \
   ../Geo/ExtrudeParams.h STL.h Metric.h Matrix.h ../Geo/CAD.h \
   ../Geo/Geo.h Create.h Interpolation.h ../Common/Context.h
-SMS.o: SMS.cpp ../Common/Gmsh.h ../Common/Message.h ../DataStr/Malloc.h \
-  ../DataStr/List.h ../DataStr/Tree.h ../DataStr/avl.h ../DataStr/Tools.h \
-  ../Geo/Geo.h Mesh.h Vertex.h Element.h Simplex.h Edge.h \
-  ../Geo/ExtrudeParams.h STL.h Metric.h Matrix.h Create.h ../Geo/MinMax.h \
-  ../Geo/CAD.h ../Common/Context.h
 SwapEdge.o: SwapEdge.cpp ../Common/Gmsh.h ../Common/Message.h \
   ../DataStr/Malloc.h ../DataStr/List.h ../DataStr/Tree.h \
   ../DataStr/avl.h ../DataStr/Tools.h ../Numeric/Numeric.h Mesh.h \
@@ -320,6 +316,10 @@ Edge.o: Edge.cpp ../Common/Gmsh.h ../Common/Message.h ../DataStr/Malloc.h \
   ../DataStr/List.h ../DataStr/Tree.h ../DataStr/avl.h ../DataStr/Tools.h \
   ../Numeric/Numeric.h Mesh.h Vertex.h Element.h Simplex.h Edge.h \
   ../Geo/ExtrudeParams.h STL.h Metric.h Matrix.h
+Element.o: Element.cpp ../Common/Gmsh.h ../Common/Message.h \
+  ../DataStr/Malloc.h ../DataStr/List.h ../DataStr/Tree.h \
+  ../DataStr/avl.h ../DataStr/Tools.h Mesh.h Vertex.h Element.h Simplex.h \
+  Edge.h ../Geo/ExtrudeParams.h STL.h Metric.h Matrix.h
 Simplex.o: Simplex.cpp ../Common/Gmsh.h ../Common/Message.h \
   ../DataStr/Malloc.h ../DataStr/List.h ../DataStr/Tree.h \
   ../DataStr/avl.h ../DataStr/Tools.h ../Numeric/Numeric.h ../Geo/Geo.h \
diff --git a/Mesh/Mesh.h b/Mesh/Mesh.h
index 86af1b186cb178d4cfdffa9939524151fe3acdf0..ca05d083ea74377ba6d0b1d67b806ef015bbeeb7 100644
--- a/Mesh/Mesh.h
+++ b/Mesh/Mesh.h
@@ -41,8 +41,10 @@
 #define FORMAT_AUTO          10
 #define FORMAT_PPM           11
 #define FORMAT_YUV           12
+#define FORMAT_DMG           13
 #define FORMAT_SMS           14
 #define FORMAT_OPT           15
+#define FORMAT_VTK           16
 #define FORMAT_JPEGTEX       17
 #define FORMAT_TEX           18
 #define FORMAT_VRML          19
@@ -195,21 +197,6 @@ class NXE{
   NXE();
 };
 
-class Hexahedron : public Element{
- public:
-  Vertex *V[8];
-};
-
-class Prism : public Element{
- public:
-  Vertex *V[6];
-};
-
-class Pyramid : public Element{
- public:
-  Vertex *V[5];
-};
-
 typedef struct{
   int N;
   List_T *pT;
@@ -254,7 +241,7 @@ struct _Surf{
   List_T *Orientations;
   List_T *Contours;
   Tree_T *Simplexes;
-  List_T *TrsfSimplexes;
+  Tree_T *Quadrangles;
   Tree_T *Vertices;
   List_T *TrsfVertices;
   Tree_T *Edges;
@@ -317,6 +304,7 @@ typedef struct {
   Tree_T *Faces;
   Tree_T *Simplexes;
   Tree_T *Simp_Surf; // for old extrusion mesh generator
+  Tree_T *Quad_Surf; // for old extrusion mesh generator
   Tree_T *Hexahedra;
   Tree_T *Prisms;
   Tree_T *Pyramids;
@@ -377,7 +365,6 @@ typedef struct{
   List_T *Control_Points;
   List_T *Vertices;
   Tree_T *Simplexes;
-  List_T *TrsfSimplexes;
   ExtrudeParams *Extrude;
   float *k, *cp;
   int degre;
@@ -414,7 +401,7 @@ class MeshParameters{
   int DelaunayInsertionMethod;
   int DelaunayQuality;
   bool InteractiveDelaunay;
-  MeshParameters ();
+  MeshParameters();
 };
 
 struct _Mesh{
@@ -432,13 +419,15 @@ struct _Mesh{
   List_T *Partitions;
   Grid_T Grid; // fast search grid
   LcField BGM; // background mesh
-  double Statistics[50]; // mesh statistics
+  double timing[3]; // timing for 1d, 2d and 3d mesh
+  double quality_gamma[3]; // mesh quality statistics
+  double quality_eta[3]; // mesh quality statistics
+  double quality_rho[3]; // mesh quality statistics
   int Histogram[3][NB_HISTOGRAM]; // quality histograms
   GMSHMetric *Metric;
   MeshParameters MeshParams;
   int MaxPointNum, MaxLineNum, MaxLineLoopNum, MaxSurfaceNum;
   int MaxSurfaceLoopNum, MaxVolumeNum, MaxPhysicalNum;
-  int MaxSimplexNum;
 };
 
 typedef struct {
@@ -455,65 +444,65 @@ struct Map{
 
 // public functions
 
-void mai3d (Mesh * M, int Asked);
+void mai3d(Mesh * M, int Asked);
 
-void Init_Mesh (Mesh * M);
-void Create_BgMesh (int i, double d, Mesh * m);
-void Print_Geo (Mesh * M, char *c);
-void Print_Mesh (Mesh * M, char *c, int Type);
-void Read_Mesh (Mesh * M, FILE *fp, char *filename, int Type);
-void GetStatistics (double s[50]);
+void Init_Mesh(Mesh * M);
+void Create_BgMesh(int i, double d, Mesh * m);
+void Print_Geo(Mesh * M, char *c);
+void Print_Mesh(Mesh * M, char *c, int Type);
+void Read_Mesh(Mesh * M, FILE *fp, char *filename, int Type);
+void GetStatistics(double s[50]);
 
-void Maillage_Dimension_0 (Mesh *M);
-void Maillage_Dimension_1 (Mesh *M);
-void Maillage_Dimension_2 (Mesh *M);
-void Maillage_Dimension_3 (Mesh *M);
+void Maillage_Dimension_1(Mesh *M);
+void Maillage_Dimension_2(Mesh *M);
+void Maillage_Dimension_3(Mesh *M);
 
-void Maillage_Curve (void *data, void *dummy);
-void Maillage_Surface (void *data, void *dum);
-void Maillage_Volume (void *data, void *dum);
+void Maillage_Curve(void *data, void *dummy);
+void Maillage_Surface(void *data, void *dum);
+void Maillage_Volume(void *data, void *dum);
 
-int Extrude_Mesh (Curve * c);
-int Extrude_Mesh (Surface * s);
-int Extrude_Mesh (Volume * v);
-int Extrude_Mesh (Tree_T * Volumes);
+int Extrude_Mesh(Curve * c);
+int Extrude_Mesh(Surface * s);
+int Extrude_Mesh(Volume * v);
+int Extrude_Mesh(Tree_T * Volumes);
 void ExitExtrude();
 void Extrude_Mesh_Old(Mesh *M);
 
-int MeshTransfiniteSurface (Surface *sur);
-int MeshTransfiniteVolume (Volume *vol);
-int MeshCylindricalSurface (Surface * s);
-int MeshParametricSurface (Surface * s);
-int MeshEllipticSurface (Surface * sur);
+int MeshTransfiniteSurface(Surface *sur);
+int MeshTransfiniteVolume(Volume *vol);
+int MeshCylindricalSurface(Surface * s);
+int MeshParametricSurface(Surface * s);
+int MeshEllipticSurface(Surface * sur);
 
-int  AlgorithmeMaillage2DAnisotropeModeJF (Surface * s);
-void Maillage_Automatique_VieuxCode (Surface * pS, Mesh * m, int ori);
+int  AlgorithmeMaillage2DAnisotropeModeJF(Surface * s);
+void Maillage_Automatique_VieuxCode(Surface * pS, Mesh * m, int ori);
 int  Mesh_Shewchuk(Surface *s);
 
-int  Calcule_Contours (Surface * s);
-void Link_Simplexes (List_T * Sim, Tree_T * Tim);
-void Calcule_Z (void *data, void *dum);
-void Calcule_Z_Plan (void *data, void *dum);
-void Projette_Plan_Moyen (void *a, void *b);
-void Projette_Inverse (void *a, void *b);
-void Freeze_Vertex (void *a, void *b);
-void deFreeze_Vertex (void *a, void *b);
+int  Calcule_Contours(Surface * s);
+void Link_Simplexes(List_T * Sim, Tree_T * Tim);
+void Calcule_Z(void *data, void *dum);
+void Calcule_Z_Plan(void *data, void *dum);
+void Projette_Plan_Moyen(void *a, void *b);
+void Projette_Inverse(void *a, void *b);
+void Freeze_Vertex(void *a, void *b);
+void deFreeze_Vertex(void *a, void *b);
 
-double Lc_XYZ (double X, double Y, double Z, Mesh * m);
+double Lc_XYZ(double X, double Y, double Z, Mesh * m);
 void Degre1();
 void Degre2(int dim);
 void Degre2_Curve(void *a, void *b);
 void Degre2_Surface(void *a, void *b);
-void ActionLiss (void *data, void *dummy);
-void ActionLissSurf (void *data, void *dummy);
-int  Recombine (Tree_T *TreeAllVert, Tree_T *TreeAllElg, double a);
+void ActionLiss(void *data, void *dummy);
+void ActionLissSurf(void *data, void *dummy);
+int  Recombine(Tree_T *TreeAllVert, Tree_T *TreeAllSimp, Tree_T *TreeAllQuad,
+		double a);
 void ApplyLcFactor(Mesh *M);
 void ExportLcFieldOnVolume(Mesh * M, char *filename);
 void ExportLcFieldOnSurfaces(Mesh * M, char *filename);
 
-void Gamma_Maillage (Mesh * m, double *gamma, double *gammamax, double *gammamin);
-void Eta_Maillage (Mesh * m, double *gamma, double *gammamax, double *gammamin);
-void R_Maillage (Mesh * m, double *gamma, double *gammamax, double *gammamin);
+void Gamma_Maillage(Mesh * m, double *gamma, double *gammamax, double *gammamin);
+void Eta_Maillage(Mesh * m, double *gamma, double *gammamax, double *gammamin);
+void R_Maillage(Mesh * m, double *gamma, double *gammamax, double *gammamin);
 void Mesh_Quality(Mesh *m);
 void Print_Histogram(int *h);
 
diff --git a/Mesh/MeshQuality.cpp b/Mesh/MeshQuality.cpp
index 4215446b5bd960dd164eef27046c58de2fa317c5..1025d88d75fba1b17257d5597624c84a9ab5039e 100644
--- a/Mesh/MeshQuality.cpp
+++ b/Mesh/MeshQuality.cpp
@@ -1,4 +1,4 @@
-// $Id: MeshQuality.cpp,v 1.13 2004-02-07 01:40:22 geuzaine Exp $
+// $Id: MeshQuality.cpp,v 1.14 2004-05-25 04:10:05 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -135,7 +135,7 @@ static void r(void *a, void *b)
   Msg(DEBUG, "Rho computed in volume %d (%d values)", v->Num, NbCalcGamma);
 }
 
-void R_Maillage(Mesh * m, double *gamma, double *gammamax, double *gammamin)
+void R_Maillage(Mesh *m, double *gamma, double *gammamax, double *gammamin)
 {
   GAMMA = 0.0;
   GAMMAMAX = 0.0;
@@ -152,12 +152,11 @@ void R_Maillage(Mesh * m, double *gamma, double *gammamax, double *gammamin)
   *gammamin = GAMMAMIN;
 }
 
-void Mesh_Quality(Mesh * m)
+void Mesh_Quality(Mesh *m)
 {
-  Gamma_Maillage(m, &m->Statistics[17], &m->Statistics[18],
-                 &m->Statistics[19]);
-  Eta_Maillage(m, &m->Statistics[20], &m->Statistics[21], &m->Statistics[22]);
-  R_Maillage(m, &m->Statistics[23], &m->Statistics[24], &m->Statistics[25]);
+  Gamma_Maillage(m, &m->quality_gamma[0], &m->quality_gamma[2], &m->quality_gamma[1]);
+  Eta_Maillage(m, &m->quality_eta[0], &m->quality_eta[2], &m->quality_eta[1]);
+  R_Maillage(m, &m->quality_rho[0], &m->quality_rho[2], &m->quality_rho[1]);
 }
 
 void Print_Histogram(int *h)
diff --git a/Mesh/Print_Mesh.cpp b/Mesh/Print_Mesh.cpp
index 86bfff1bdd8d51f6a94bb5eddf082dff0e761324..6e67ef23d1f16476d02c510c95073b72c0fd1727 100644
--- a/Mesh/Print_Mesh.cpp
+++ b/Mesh/Print_Mesh.cpp
@@ -1,4 +1,4 @@
-// $Id: Print_Mesh.cpp,v 1.50 2004-05-01 13:55:36 geuzaine Exp $
+// $Id: Print_Mesh.cpp,v 1.51 2004-05-25 04:10:05 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -29,9 +29,7 @@
 
 extern Context_T CTX;
 
-static FILE *meshfile;
-
-// M S H   F O R M A T
+// Write mesh in native MSH format
 
 #define LINE            1
 #define TRIANGLE        2
@@ -50,23 +48,22 @@ static FILE *meshfile;
 #define POINT          15
 
 static int MSH_VOL_NUM, MSH_SUR_NUM, MSH_LIN_NUM;
-static int MSH_NODE_NUM, MSH_ELEMENT_NUM, MSH_3D, MSH_ADD;
+static int MSH_NODE_NUM, MSH_ELEMENT_NUM, MSH_ADD;
 static int MSH_PHYSICAL_NUM, MSH_PHYSICAL_ORI;
+static FILE *MSHFILE;
 
-void print_msh_node(void *a, void *b)
+static void _msh_print_node(void *a, void *b)
 {
-  Vertex **V;
-
-  V = (Vertex **) a;
+  Vertex *V = *(Vertex **) a;
 
-  fprintf(meshfile, "%d %.16g %.16g %.16g\n",
-          (*V)->Num,
-          (*V)->Pos.X * CTX.mesh.scaling_factor,
-          (*V)->Pos.Y * CTX.mesh.scaling_factor,
-          (*V)->Pos.Z * CTX.mesh.scaling_factor);
+  fprintf(MSHFILE, "%d %.16g %.16g %.16g\n",
+          V->Num,
+          V->Pos.X * CTX.mesh.scaling_factor,
+          V->Pos.Y * CTX.mesh.scaling_factor,
+          V->Pos.Z * CTX.mesh.scaling_factor);
 }
 
-void process_msh_nodes(Mesh * M)
+static void _msh_process_nodes(Mesh *M)
 {
   int i, j, Num;
   PhysicalGroup *p;
@@ -90,31 +87,30 @@ void process_msh_nodes(Mesh * M)
   MSH_NODE_NUM = Tree_Nbr(M->Vertices);
 
   if(CTX.mesh.msh_file_version == 2.0)
-    fprintf(meshfile, "$Nodes\n");
+    fprintf(MSHFILE, "$Nodes\n");
   else
-    fprintf(meshfile, "$NOD\n");
-  fprintf(meshfile, "%d\n", MSH_NODE_NUM);
-  Tree_Action(M->Vertices, print_msh_node);
+    fprintf(MSHFILE, "$NOD\n");
+  fprintf(MSHFILE, "%d\n", MSH_NODE_NUM);
+  Tree_Action(M->Vertices, _msh_print_node);
   if(CTX.mesh.msh_file_version == 2.0)
-    fprintf(meshfile, "$EndNodes\n");
+    fprintf(MSHFILE, "$EndNodes\n");
   else
-    fprintf(meshfile, "$ENDNOD\n");
+    fprintf(MSHFILE, "$ENDNOD\n");
 }
 
-void print_msh_simplex(void *a, void *b)
+static void _msh_print_simplex(void *a, void *b)
 {
-  Simplex **S;
   int i, type, nbn, nbs = 0;
 
-  S = (Simplex **) a;
+  Simplex *s = *(Simplex **) a;
 
-  if(MSH_VOL_NUM && (MSH_VOL_NUM != (*S)->iEnt))
+  if(MSH_VOL_NUM && (MSH_VOL_NUM != s->iEnt))
     return;
 
-  if(MSH_SUR_NUM && (MSH_SUR_NUM != (*S)->iEnt))
+  if(MSH_SUR_NUM && (MSH_SUR_NUM != s->iEnt))
     return;
 
-  if(MSH_LIN_NUM && (MSH_LIN_NUM != (*S)->iEnt))
+  if(MSH_LIN_NUM && (MSH_LIN_NUM != s->iEnt))
     return;
 
   if(!MSH_ADD) {
@@ -122,18 +118,18 @@ void print_msh_simplex(void *a, void *b)
     return;
   }
 
-  if(!(*S)->V[2]) {
+  if(!s->V[2]) {
     nbn = 2;
-    if((*S)->VSUP) {
+    if(s->VSUP) {
       type = LINE_2;
       nbs = 1;
     }
     else
       type = LINE;
   }
-  else if(!(*S)->V[3]) {
+  else if(!s->V[3]) {
     nbn = 3;
-    if((*S)->VSUP) {
+    if(s->VSUP) {
       type = TRIANGLE_2;
       nbs = 3;
     }
@@ -142,79 +138,108 @@ void print_msh_simplex(void *a, void *b)
   }
   else {
     nbn = 4;
-    if(!MSH_3D) {
-      if((*S)->VSUP) {
-        type = QUADRANGLE_2;
-        nbs = 4;
-      }
-      else
-        type = QUADRANGLE;
-    }
-    else if((*S)->VSUP) {
+    if(s->VSUP) {
       type = TETRAHEDRON_2;
       nbs = 6;
+      if(s->Volume_Simplexe() < 0) {
+	Vertex *temp;
+	temp = s->V[0];	s->V[0] = s->V[1]; s->V[1] = temp;
+	temp = s->VSUP[1]; s->VSUP[1] = s->VSUP[2]; s->VSUP[2] = temp;
+	temp = s->VSUP[5]; s->VSUP[5] = s->VSUP[3]; s->VSUP[3] = temp;
+      }
     }
-    else
+    else{
       type = TETRAHEDRON;
+      if(s->Volume_Simplexe() < 0) {
+	Vertex *temp;
+	temp = s->V[0];
+	s->V[0] = s->V[1];
+	s->V[1] = temp;
+      }
+    }
   }
 
-  if(type == TETRAHEDRON) {
-    if((*S)->Volume_Simplexe() < 0) {
-      Vertex *temp;
-      temp = (*S)->V[0];
-      (*S)->V[0] = (*S)->V[1];
-      (*S)->V[1] = temp;
-    }
+  if(CTX.mesh.msh_file_version == 2.0)
+    fprintf(MSHFILE, "%d %d 2 %d %d",
+	    MSH_ELEMENT_NUM++, type, MSH_PHYSICAL_NUM ? MSH_PHYSICAL_NUM : s->iEnt, 
+	    s->iEnt);
+  else
+    fprintf(MSHFILE, "%d %d %d %d %d",
+	    MSH_ELEMENT_NUM++, type,
+	    MSH_PHYSICAL_NUM ? MSH_PHYSICAL_NUM : s->iEnt, s->iEnt,
+	    nbn + nbs);
+
+  if(MSH_PHYSICAL_ORI > 0) {
+    for(i = 0; i < nbn; i++)
+      fprintf(MSHFILE, " %d", s->V[i]->Num);
+    for(i = 0; i < nbs; i++)
+      fprintf(MSHFILE, " %d", s->VSUP[i]->Num);
   }
-  else if(type == TETRAHEDRON_2) {
-    if((*S)->Volume_Simplexe() < 0) {
-      Vertex *temp;
-      temp = (*S)->V[0];
-      (*S)->V[0] = (*S)->V[1];
-      (*S)->V[1] = temp;
-      temp = (*S)->VSUP[1];
-      (*S)->VSUP[1] = (*S)->VSUP[2];
-      (*S)->VSUP[2] = temp;
-      temp = (*S)->VSUP[5];
-      (*S)->VSUP[5] = (*S)->VSUP[3];
-      (*S)->VSUP[3] = temp;
-    }
+  else {
+    for(i = 0; i < nbn; i++)
+      fprintf(MSHFILE, " %d", s->V[nbn - i - 1]->Num);
+    for(i = 0; i < nbs; i++)
+      fprintf(MSHFILE, " %d", s->VSUP[nbs - i - 1]->Num);
+  }
+
+  fprintf(MSHFILE, "\n");
+}
+
+static void _msh_print_quadrangle(void *a, void *b)
+{
+  int i, type, nbn, nbs = 0;
+
+  Quadrangle *q = *(Quadrangle **) a;
+
+  if(MSH_SUR_NUM && (MSH_SUR_NUM != q->iEnt))
+    return;
+
+  if(!MSH_ADD) {
+    MSH_ELEMENT_NUM++;
+    return;
+  }
+
+  nbn = 4;
+  if(q->VSUP) {
+    type = QUADRANGLE_2;
+    nbs = 4;
   }
+  else
+    type = QUADRANGLE;
 
   if(CTX.mesh.msh_file_version == 2.0)
-    fprintf(meshfile, "%d %d 2 %d %d",
-	    MSH_ELEMENT_NUM++, type, MSH_PHYSICAL_NUM ? MSH_PHYSICAL_NUM : (*S)->iEnt, 
-	    (*S)->iEnt);
+    fprintf(MSHFILE, "%d %d 2 %d %d",
+	    MSH_ELEMENT_NUM++, type, MSH_PHYSICAL_NUM ? MSH_PHYSICAL_NUM : q->iEnt, 
+	    q->iEnt);
   else
-    fprintf(meshfile, "%d %d %d %d %d",
+    fprintf(MSHFILE, "%d %d %d %d %d",
 	    MSH_ELEMENT_NUM++, type,
-	    MSH_PHYSICAL_NUM ? MSH_PHYSICAL_NUM : (*S)->iEnt, (*S)->iEnt,
+	    MSH_PHYSICAL_NUM ? MSH_PHYSICAL_NUM : q->iEnt, q->iEnt,
 	    nbn + nbs);
 
   if(MSH_PHYSICAL_ORI > 0) {
     for(i = 0; i < nbn; i++)
-      fprintf(meshfile, " %d", (*S)->V[i]->Num);
+      fprintf(MSHFILE, " %d", q->V[i]->Num);
     for(i = 0; i < nbs; i++)
-      fprintf(meshfile, " %d", (*S)->VSUP[i]->Num);
+      fprintf(MSHFILE, " %d", q->VSUP[i]->Num);
   }
   else {
     for(i = 0; i < nbn; i++)
-      fprintf(meshfile, " %d", (*S)->V[nbn - i - 1]->Num);
+      fprintf(MSHFILE, " %d", q->V[nbn - i - 1]->Num);
     for(i = 0; i < nbs; i++)
-      fprintf(meshfile, " %d", (*S)->VSUP[nbs - i - 1]->Num);
+      fprintf(MSHFILE, " %d", q->VSUP[nbs - i - 1]->Num);
   }
 
-  fprintf(meshfile, "\n");
+  fprintf(MSHFILE, "\n");
 }
 
-void print_msh_hexahedron(void *a, void *b)
+static void _msh_print_hexahedron(void *a, void *b)
 {
-  Hexahedron **H;
   int i, type, nbn, nbs = 0;
 
-  H = (Hexahedron **) a;
+  Hexahedron *h = *(Hexahedron **) a;
 
-  if(MSH_VOL_NUM && (MSH_VOL_NUM != (*H)->iEnt))
+  if(MSH_VOL_NUM && (MSH_VOL_NUM != h->iEnt))
     return;
 
   if(!MSH_ADD) {
@@ -223,7 +248,7 @@ void print_msh_hexahedron(void *a, void *b)
   }
 
   nbn = 8;
-  if((*H)->VSUP) {
+  if(h->VSUP) {
     type = HEXAHEDRON_2;
     nbs = 12;
   }
@@ -231,31 +256,30 @@ void print_msh_hexahedron(void *a, void *b)
     type = HEXAHEDRON;
 
   if(CTX.mesh.msh_file_version == 2.0)
-    fprintf(meshfile, "%d %d 2 %d %d",
-	    MSH_ELEMENT_NUM++, type, MSH_PHYSICAL_NUM ? MSH_PHYSICAL_NUM : (*H)->iEnt,
-	    (*H)->iEnt);
+    fprintf(MSHFILE, "%d %d 2 %d %d",
+	    MSH_ELEMENT_NUM++, type, MSH_PHYSICAL_NUM ? MSH_PHYSICAL_NUM : h->iEnt,
+	    h->iEnt);
   else
-    fprintf(meshfile, "%d %d %d %d %d",
+    fprintf(MSHFILE, "%d %d %d %d %d",
 	    MSH_ELEMENT_NUM++, type,
-	    MSH_PHYSICAL_NUM ? MSH_PHYSICAL_NUM : (*H)->iEnt, (*H)->iEnt,
+	    MSH_PHYSICAL_NUM ? MSH_PHYSICAL_NUM : h->iEnt, h->iEnt,
 	    nbn + nbs);
 
   for(i = 0; i < nbn; i++)
-    fprintf(meshfile, " %d", (*H)->V[i]->Num);
+    fprintf(MSHFILE, " %d", h->V[i]->Num);
   for(i = 0; i < nbs; i++)
-    fprintf(meshfile, " %d", (*H)->VSUP[i]->Num);
+    fprintf(MSHFILE, " %d", h->VSUP[i]->Num);
 
-  fprintf(meshfile, "\n");
+  fprintf(MSHFILE, "\n");
 }
 
-void print_msh_prism(void *a, void *b)
+static void _msh_print_prism(void *a, void *b)
 {
-  Prism **P;
   int i, type, nbn, nbs = 0;
 
-  P = (Prism **) a;
+  Prism *p = *(Prism **) a;
 
-  if(MSH_VOL_NUM && (MSH_VOL_NUM != (*P)->iEnt))
+  if(MSH_VOL_NUM && (MSH_VOL_NUM != p->iEnt))
     return;
 
   if(!MSH_ADD) {
@@ -264,7 +288,7 @@ void print_msh_prism(void *a, void *b)
   }
 
   nbn = 6;
-  if((*P)->VSUP) {
+  if(p->VSUP) {
     type = PRISM_2;
     nbs = 9;
   }
@@ -273,31 +297,30 @@ void print_msh_prism(void *a, void *b)
   }
 
   if(CTX.mesh.msh_file_version == 2.0)
-    fprintf(meshfile, "%d %d 2 %d %d",
-	    MSH_ELEMENT_NUM++, type, MSH_PHYSICAL_NUM ? MSH_PHYSICAL_NUM : (*P)->iEnt,
-	    (*P)->iEnt);
+    fprintf(MSHFILE, "%d %d 2 %d %d",
+	    MSH_ELEMENT_NUM++, type, MSH_PHYSICAL_NUM ? MSH_PHYSICAL_NUM : p->iEnt,
+	    p->iEnt);
   else
-    fprintf(meshfile, "%d %d %d %d %d",
+    fprintf(MSHFILE, "%d %d %d %d %d",
 	    MSH_ELEMENT_NUM++, type,
-	    MSH_PHYSICAL_NUM ? MSH_PHYSICAL_NUM : (*P)->iEnt, (*P)->iEnt,
+	    MSH_PHYSICAL_NUM ? MSH_PHYSICAL_NUM : p->iEnt, p->iEnt,
 	    nbn + nbs);
 
   for(i = 0; i < nbn; i++)
-    fprintf(meshfile, " %d", (*P)->V[i]->Num);
+    fprintf(MSHFILE, " %d", p->V[i]->Num);
   for(i = 0; i < nbs; i++)
-    fprintf(meshfile, " %d", (*P)->VSUP[i]->Num);
+    fprintf(MSHFILE, " %d", p->VSUP[i]->Num);
 
-  fprintf(meshfile, "\n");
+  fprintf(MSHFILE, "\n");
 }
 
-void print_msh_pyramid(void *a, void *b)
+static void _msh_print_pyramid(void *a, void *b)
 {
-  Pyramid **P;
   int i, type, nbn, nbs = 0;
 
-  P = (Pyramid **) a;
+  Pyramid *p = *(Pyramid **) a;
 
-  if(MSH_VOL_NUM && (MSH_VOL_NUM != (*P)->iEnt))
+  if(MSH_VOL_NUM && (MSH_VOL_NUM != p->iEnt))
     return;
 
   if(!MSH_ADD) {
@@ -306,7 +329,7 @@ void print_msh_pyramid(void *a, void *b)
   }
 
   nbn = 5;
-  if((*P)->VSUP) {
+  if(p->VSUP) {
     type = PYRAMID_2;
     nbs = 8;
   }
@@ -315,24 +338,24 @@ void print_msh_pyramid(void *a, void *b)
   }
 
   if(CTX.mesh.msh_file_version == 2.0)
-    fprintf(meshfile, "%d %d 2 %d %d",
-	    MSH_ELEMENT_NUM++, type, MSH_PHYSICAL_NUM ? MSH_PHYSICAL_NUM : (*P)->iEnt,
-	    (*P)->iEnt);
+    fprintf(MSHFILE, "%d %d 2 %d %d",
+	    MSH_ELEMENT_NUM++, type, MSH_PHYSICAL_NUM ? MSH_PHYSICAL_NUM : p->iEnt,
+	    p->iEnt);
   else
-    fprintf(meshfile, "%d %d %d %d %d",
+    fprintf(MSHFILE, "%d %d %d %d %d",
 	    MSH_ELEMENT_NUM++, type,
-	    MSH_PHYSICAL_NUM ? MSH_PHYSICAL_NUM : (*P)->iEnt, (*P)->iEnt,
+	    MSH_PHYSICAL_NUM ? MSH_PHYSICAL_NUM : p->iEnt, p->iEnt,
 	    nbn + nbs);
 
   for(i = 0; i < nbn; i++)
-    fprintf(meshfile, " %d", (*P)->V[i]->Num);
+    fprintf(MSHFILE, " %d", p->V[i]->Num);
   for(i = 0; i < nbs; i++)
-    fprintf(meshfile, " %d", (*P)->VSUP[i]->Num);
+    fprintf(MSHFILE, " %d", p->VSUP[i]->Num);
 
-  fprintf(meshfile, "\n");
+  fprintf(MSHFILE, "\n");
 }
 
-void print_msh_point(Vertex * V)
+static void _msh_print_point(Vertex *V)
 {
   if(!MSH_ADD) {
     MSH_ELEMENT_NUM++;
@@ -340,16 +363,16 @@ void print_msh_point(Vertex * V)
   }
 
   if(CTX.mesh.msh_file_version == 2.0)
-    fprintf(meshfile, "%d %d 2 %d %d %d\n",
+    fprintf(MSHFILE, "%d %d 2 %d %d %d\n",
 	    MSH_ELEMENT_NUM++, POINT, MSH_PHYSICAL_NUM ? MSH_PHYSICAL_NUM : V->Num, V->Num,
 	    V->Num);
   else
-    fprintf(meshfile, "%d %d %d %d 1 %d\n",
+    fprintf(MSHFILE, "%d %d %d %d 1 %d\n",
 	    MSH_ELEMENT_NUM++, POINT,
 	    MSH_PHYSICAL_NUM ? MSH_PHYSICAL_NUM : V->Num, V->Num, V->Num);
 }
 
-void print_msh_elements(Mesh * M)
+static void _msh_print_elements(Mesh *M)
 {
   int i, j, k, Num;
 
@@ -364,7 +387,6 @@ void print_msh_elements(Mesh * M)
   for(i = 0; i < List_Nbr(M->PhysicalGroups); i++) {
     List_Read(M->PhysicalGroups, i, &p);
     MSH_PHYSICAL_NUM = p->Num;
-    MSH_3D = 0;
     MSH_VOL_NUM = MSH_SUR_NUM = MSH_LIN_NUM = 0;
 
     switch (p->Typ) {
@@ -376,7 +398,7 @@ void print_msh_elements(Mesh * M)
         pv->Num = abs(Num);
         MSH_PHYSICAL_ORI = sign(Num);
         if(Tree_Query(M->Vertices, &pv))
-          print_msh_point(pv);
+          _msh_print_point(pv);
       }
       break;
 
@@ -388,7 +410,8 @@ void print_msh_elements(Mesh * M)
             List_Read(p->Entities, j, &Num);
             MSH_LIN_NUM = abs(Num);
             MSH_PHYSICAL_ORI = sign(Num);
-            Tree_Action(pV->Simp_Surf, print_msh_simplex);
+            Tree_Action(pV->Simp_Surf, _msh_print_simplex);
+            Tree_Action(pV->Quad_Surf, _msh_print_quadrangle);
           }
         }
         break;  //done
@@ -400,7 +423,7 @@ void print_msh_elements(Mesh * M)
         pc->Num = abs(Num);
         MSH_PHYSICAL_ORI = sign(Num);
         if(Tree_Query(M->Curves, &pc))
-          Tree_Action(pc->Simplexes, print_msh_simplex);
+          Tree_Action(pc->Simplexes, _msh_print_simplex);
       }
       break;
 
@@ -412,7 +435,8 @@ void print_msh_elements(Mesh * M)
             List_Read(p->Entities, j, &Num);
             MSH_SUR_NUM = abs(Num);
             MSH_PHYSICAL_ORI = sign(Num);
-            Tree_Action(pV->Simp_Surf, print_msh_simplex);
+            Tree_Action(pV->Simp_Surf, _msh_print_simplex);
+            Tree_Action(pV->Quad_Surf, _msh_print_quadrangle);
           }
         }
         break;  //done
@@ -423,8 +447,10 @@ void print_msh_elements(Mesh * M)
         List_Read(p->Entities, j, &Num);
         ps->Num = abs(Num);
         MSH_PHYSICAL_ORI = sign(Num);
-        if(Tree_Query(M->Surfaces, &ps))
-          Tree_Action(ps->Simplexes, print_msh_simplex);
+        if(Tree_Query(M->Surfaces, &ps)){
+          Tree_Action(ps->Simplexes, _msh_print_simplex);
+          Tree_Action(ps->Quadrangles, _msh_print_quadrangle);
+	}
       }
       break;
 
@@ -433,13 +459,12 @@ void print_msh_elements(Mesh * M)
         List_Read(ListVolumes, k, &pV);
         for(j = 0; j < List_Nbr(p->Entities); j++) {
           List_Read(p->Entities, j, &Num);
-          MSH_3D = 1;
           MSH_VOL_NUM = abs(Num);
           MSH_PHYSICAL_ORI = sign(Num);
-          Tree_Action(pV->Simplexes, print_msh_simplex);
-          Tree_Action(pV->Hexahedra, print_msh_hexahedron);
-          Tree_Action(pV->Prisms, print_msh_prism);
-          Tree_Action(pV->Pyramids, print_msh_pyramid);
+          Tree_Action(pV->Simplexes, _msh_print_simplex);
+          Tree_Action(pV->Hexahedra, _msh_print_hexahedron);
+          Tree_Action(pV->Prisms, _msh_print_prism);
+          Tree_Action(pV->Pyramids, _msh_print_pyramid);
         }
       }
       break;
@@ -453,70 +478,70 @@ void print_msh_elements(Mesh * M)
 
 }
 
-void print_all_msh_curves(void *a, void *b)
+static void _msh_print_all_curves(void *a, void *b)
 {
   Curve *c = *(Curve **) a;
-  Tree_Action(c->Simplexes, print_msh_simplex);
+  Tree_Action(c->Simplexes, _msh_print_simplex);
 }
 
-void print_all_msh_surfaces(void *a, void *b)
+static void _msh_print_all_surfaces(void *a, void *b)
 {
   Surface *s = *(Surface **) a;
-  Tree_Action(s->Simplexes, print_msh_simplex);
+  Tree_Action(s->Simplexes, _msh_print_simplex);
+  Tree_Action(s->Quadrangles, _msh_print_quadrangle);
 }
 
-void print_all_msh_simpsurf(void *a, void *b)
+static void _msh_print_all_simpsurf(void *a, void *b)
 {
   Volume *v = *(Volume **) a;
-  Tree_Action(v->Simp_Surf, print_msh_simplex);
+  Tree_Action(v->Simp_Surf, _msh_print_simplex);
+  Tree_Action(v->Quad_Surf, _msh_print_quadrangle);
 }
 
-void print_all_msh_volumes(void *a, void *b)
+static void _msh_print_all_volumes(void *a, void *b)
 {
   Volume *v = *(Volume **) a;
-  Tree_Action(v->Simplexes, print_msh_simplex);
-  Tree_Action(v->Hexahedra, print_msh_hexahedron);
-  Tree_Action(v->Prisms, print_msh_prism);
-  Tree_Action(v->Pyramids, print_msh_pyramid);
+  Tree_Action(v->Simplexes, _msh_print_simplex);
+  Tree_Action(v->Hexahedra, _msh_print_hexahedron);
+  Tree_Action(v->Prisms, _msh_print_prism);
+  Tree_Action(v->Pyramids, _msh_print_pyramid);
 }
 
-void print_all_msh_elements(Mesh * M)
+static void _msh_print_all_elements(Mesh *M)
 {
   MSH_PHYSICAL_NUM = 0;
   MSH_PHYSICAL_ORI = 1;
   MSH_LIN_NUM = MSH_SUR_NUM = MSH_VOL_NUM = 0;
 
-  MSH_3D = 0;
   if(CTX.mesh.oldxtrude) {
-    Tree_Action(M->Volumes, print_all_msh_simpsurf);
+    Tree_Action(M->Volumes, _msh_print_all_simpsurf);
   }
   else {
-    Tree_Action(M->Curves, print_all_msh_curves);
-    Tree_Action(M->Surfaces, print_all_msh_surfaces);
+    Tree_Action(M->Curves, _msh_print_all_curves);
+    Tree_Action(M->Surfaces, _msh_print_all_surfaces);
   }
 
-  MSH_3D = 1;
-  Tree_Action(M->Volumes, print_all_msh_volumes);
+  Tree_Action(M->Volumes, _msh_print_all_volumes);
 }
 
-void process_msh_elements(Mesh * M)
+static void _msh_process_elements(Mesh *M)
 {
   MSH_ADD = 0;
   MSH_ELEMENT_NUM = 1;
 
   if(!List_Nbr(M->PhysicalGroups) || CTX.mesh.save_all) {
     Msg(INFO, "Saving all elements (discarding physical groups)");
-    print_all_msh_elements(M);
+    _msh_print_all_elements(M);
   }
   else
-    print_msh_elements(M);
+    _msh_print_elements(M);
 
   if(CTX.mesh.msh_file_version == 2.0)
-    fprintf(meshfile, "$Elements\n");
+    fprintf(MSHFILE, "$Elements\n");
   else
-    fprintf(meshfile, "$ELM\n");
+    fprintf(MSHFILE, "$ELM\n");
 
-  fprintf(meshfile, "%d\n", MSH_ELEMENT_NUM - 1);
+  fprintf(MSHFILE, "%d\n", MSH_ELEMENT_NUM - 1);
 
   if(MSH_ELEMENT_NUM == 1)
     Msg(WARNING, "No elements to save");
@@ -524,20 +549,42 @@ void process_msh_elements(Mesh * M)
   MSH_ADD = 1;
   MSH_ELEMENT_NUM = 1;
   if(!List_Nbr(M->PhysicalGroups) || CTX.mesh.save_all)
-    print_all_msh_elements(M);
+    _msh_print_all_elements(M);
   else
-    print_msh_elements(M);
+    _msh_print_elements(M);
 
   if(CTX.mesh.msh_file_version == 2.0)
-    fprintf(meshfile, "$EndElements\n");
+    fprintf(MSHFILE, "$EndElements\n");
   else
-    fprintf(meshfile, "$ENDELM\n");
+    fprintf(MSHFILE, "$ENDELM\n");
 }
 
+void Print_Mesh_MSH(Mesh *M, FILE *fp)
+{
+  MSHFILE = fp;
+  if(CTX.mesh.msh_file_version == 1.0){
+    // OK, no header
+  }
+  else if(CTX.mesh.msh_file_version == 2.0){
+    fprintf(MSHFILE, "$MeshFormat\n");
+    fprintf(MSHFILE, "%g %d %d\n", CTX.mesh.msh_file_version,
+	    LIST_FORMAT_ASCII, sizeof(double));
+    fprintf(MSHFILE, "$EndMeshFormat\n");
+  }
+  else{
+    Msg(GERROR, "Unknown MSH file version to generate (%g)", 
+	CTX.mesh.msh_file_version);
+    return;
+  }
+  _msh_process_nodes(M);
+  _msh_process_elements(M);
+  Msg(INFO, "%d nodes", MSH_NODE_NUM);
+  Msg(INFO, "%d elements", MSH_ELEMENT_NUM - 1);
+}
 
-//  U N V   F O R M A T
+// Write mesh in UNV format
 
-// Numeros des enregistrements IDEAS
+// IDEAS records
 #define HEADER       151
 #define UNITS        164
 #define NODES        2411
@@ -547,7 +594,7 @@ void process_msh_elements(Mesh * M)
 #define RESVECT      57
 #define GROUPOFNODES 790
 
-// Numeros des elements IDEAS
+// IDEAS elements
 #define BEAM         21
 #define BEAM2        24
 #define THINSHLL     91
@@ -562,8 +609,9 @@ void process_msh_elements(Mesh * M)
 static int ELEMENT_ID;
 static Tree_T *tree;
 static int UNV_VOL_NUM;
+static FILE *UNVFILE;
 
-void process_unv_nodes(Mesh * M)
+static void _unv_process_nodes(Mesh *M)
 {
   int nbnod;
   double x, y, z;
@@ -572,8 +620,8 @@ void process_unv_nodes(Mesh * M)
 
   List_T *Nodes = Tree2List(M->Vertices);
 
-  fprintf(meshfile, "%6d\n", -1);
-  fprintf(meshfile, "%6d\n", NODES);
+  fprintf(UNVFILE, "%6d\n", -1);
+  fprintf(UNVFILE, "%6d\n", NODES);
   nbnod = List_Nbr(Nodes);
 
   for(i = 0; i < nbnod; i++) {
@@ -582,95 +630,38 @@ void process_unv_nodes(Mesh * M)
     x = v->Pos.X * CTX.mesh.scaling_factor;
     y = v->Pos.Y * CTX.mesh.scaling_factor;
     z = v->Pos.Z * CTX.mesh.scaling_factor;
-    fprintf(meshfile, "%10d%10d%10d%10d\n", idnod, 1, 1, 11);
-    fprintf(meshfile, "%21.16fD+00 %21.16fD+00 %21.16fD+00\n", x, y, z);
+    fprintf(UNVFILE, "%10d%10d%10d%10d\n", idnod, 1, 1, 11);
+    fprintf(UNVFILE, "%21.16fD+00 %21.16fD+00 %21.16fD+00\n", x, y, z);
   }
 
   List_Delete(Nodes);
-  fprintf(meshfile, "%6d\n", -1);
+  fprintf(UNVFILE, "%6d\n", -1);
 }
 
-int process_unv_2D_elements(Mesh * m)
+static void _unv_print_record(int num, int fetyp, int geo, int n, int nsup, 
+			      Vertex **v, Vertex **vsup)
 {
-  List_T *ListSurfaces = Tree2List(m->Surfaces);
-  List_T *ListVolumes = Tree2List(m->Volumes);
-  List_T *Elements;
-  Volume *vol;
-  List_T *AllSurfaces = List_Create(2, 2, sizeof(Surface *));
-  Simplex *sx;
-  Surface *s;
-  int i, j, nsup, n, ntot, k, geo, fetyp;
-
-  for(i = 0; i < List_Nbr(ListVolumes); i++) {
-    List_Read(ListVolumes, i, &vol);
-    for(j = 0; j < List_Nbr(vol->Surfaces); j++) {
-      List_Read(vol->Surfaces, j, &s);
-      if(Tree_Nbr(s->Simplexes))
-        List_Add(AllSurfaces, &s);
-    }
+  fprintf(UNVFILE, "%10d%10d%10d%10d%10d%10d\n",
+	  num, fetyp, geo, geo, 7, n + nsup);
+  int ntot = 0;
+  fprintf(UNVFILE, "%10d%10d%10d\n", 0, 0, 0);
+  for(int k = 0; k < n; k++) {
+    fprintf(UNVFILE, "%10d", v[k]->Num);
+    if(ntot % 8 == 7)
+      fprintf(UNVFILE, "\n");
+    ntot++;
   }
-
-  for(i = 0; i < List_Nbr(ListSurfaces); i++) {
-    List_Read(ListSurfaces, i, &s);
-    if(!List_Search(AllSurfaces, &s, compareSurface)) {
-      Elements = Tree2List(s->Simplexes);
-      for(j = 0; j < List_Nbr(Elements); j++) {
-        List_Read(Elements, j, &sx);
-        if(sx->V[3]) {
-          if(sx->VSUP) {
-            fetyp = QUAD;
-            n = 4;
-            nsup = 4;
-          }
-          else {
-            fetyp = QUAD;
-            n = 4;
-            nsup = 0;
-          }
-        }
-        else {
-          if(sx->VSUP) {
-            fetyp = THINSHLL;
-            n = 3;
-            nsup = 3;
-          }
-          else {
-            fetyp = THINSHLL;
-            nsup = 0;
-            n = 3;
-          }
-        }
-        geo = s->Num;
-        fprintf(meshfile, "%10d%10d%10d%10d%10d%10d\n",
-                /*ELEMENT_ID++ */ abs(sx->Num), fetyp, geo, geo, 7, n + nsup);
-        //'abs' since extrusion can tag triangles
-        // with a negative number
-        ntot = 0;
-        for(k = 0; k < n; k++) {
-          fprintf(meshfile, "%10d", sx->V[k]->Num);
-          if(ntot % 8 == 7)
-            fprintf(meshfile, "\n");
-          ntot++;
-        }
-        for(k = 0; k < nsup; k++) {
-          fprintf(meshfile, "%10d", sx->VSUP[k]->Num);
-          if(ntot % 8 == 7)
-            fprintf(meshfile, "\n");
-          ntot++;
-        }
-        if(ntot - 1 % 8 != 7)
-          fprintf(meshfile, "\n");
-      }
-      List_Delete(Elements);
-    }
+  for(int k = 0; k < nsup; k++) {
+    fprintf(UNVFILE, "%10d", vsup[k]->Num);
+    if(ntot % 8 == 7)
+      fprintf(UNVFILE, "\n");
+    ntot++;
   }
-  List_Delete(ListSurfaces);
-  List_Delete(ListVolumes);
-  List_Delete(AllSurfaces);
-  return 0;
+  if(ntot - 1 % 8 != 7)
+    fprintf(UNVFILE, "\n");
 }
 
-int process_unv_1D_elements(Mesh * m)
+static void _unv_process_1D_elements(Mesh *m)
 {
   List_T *ListCurves = Tree2List(m->Curves);
   List_T *AllCurves = List_Create(2, 2, sizeof(Surface *));
@@ -679,11 +670,10 @@ int process_unv_1D_elements(Mesh * m)
   Simplex *sx;
   Curve *c;
   Surface *surf;
-  int k, ntot, i, j, geo, fetyp, n, nsup;
 
-  for(i = 0; i < List_Nbr(ListSurfaces); i++) {
+  for(int i = 0; i < List_Nbr(ListSurfaces); i++) {
     List_Read(ListSurfaces, i, &surf);
-    for(j = 0; j < List_Nbr(surf->Generatrices); j++) {
+    for(int j = 0; j < List_Nbr(surf->Generatrices); j++) {
       List_Read(surf->Generatrices, j, &c);
       if(Tree_Nbr(c->Simplexes))
         List_Add(AllCurves, &c);
@@ -693,53 +683,79 @@ int process_unv_1D_elements(Mesh * m)
     }
   }
 
-  for(i = 0; i < List_Nbr(ListCurves); i++) {
+  for(int i = 0; i < List_Nbr(ListCurves); i++) {
     List_Read(ListCurves, i, &c);
     if(!List_Search(AllCurves, &c, compareCurve)) {
       Elements = Tree2List(c->Simplexes);
-      for(j = 0; j < List_Nbr(Elements); j++) {
+      for(int j = 0; j < List_Nbr(Elements); j++) {
         List_Read(Elements, j, &sx);
-        if(sx->VSUP) {
-          fetyp = BEAM2;
-          n = 2;
-          nsup = 2;
-        }
-        else {
-          fetyp = BEAM;
-          n = 2;
-          nsup = 0;
-        }
-        geo = c->Num;
-        fprintf(meshfile, "%10d%10d%10d%10d%10d%10d\n",
-                /*ELEMENT_ID++ */ sx->Num, fetyp, geo, geo, 7, n + nsup);
-        ntot = 0;
-        fprintf(meshfile, "%10d%10d%10d\n", 0, 0, 0);
-        for(k = 0; k < n; k++) {
-          fprintf(meshfile, "%10d", sx->V[k]->Num);
-          if(ntot % 8 == 7)
-            fprintf(meshfile, "\n");
-          ntot++;
-        }
-        for(k = 0; k < nsup; k++) {
-          fprintf(meshfile, "%10d", sx->VSUP[k]->Num);
-          if(ntot % 8 == 7)
-            fprintf(meshfile, "\n");
-          ntot++;
-        }
-        if(ntot - 1 % 8 != 7)
-          fprintf(meshfile, "\n");
+        if(sx->VSUP)
+	  _unv_print_record(sx->Num, BEAM2, c->Num, 2, 2, &sx->V[0], sx->VSUP);
+	else 
+	  _unv_print_record(sx->Num, BEAM, c->Num, 2, 0, &sx->V[0], NULL);
       }
-
       List_Delete(Elements);
     }
   }
+
   List_Delete(AllCurves);
   List_Delete(ListSurfaces);
   List_Delete(ListCurves);
-  return 0;
 }
 
-int process_unv_3D_elements(Mesh * m)
+static void _unv_process_2D_elements(Mesh *m)
+{
+  List_T *ListSurfaces = Tree2List(m->Surfaces);
+  List_T *AllSurfaces = List_Create(2, 2, sizeof(Surface *));
+  List_T *ListVolumes = Tree2List(m->Volumes);
+  List_T *Elements;
+  Volume *vol;
+  Surface *s;
+  Simplex *sx;
+  Quadrangle *qx;
+
+  for(int i = 0; i < List_Nbr(ListVolumes); i++) {
+    List_Read(ListVolumes, i, &vol);
+    for(int j = 0; j < List_Nbr(vol->Surfaces); j++) {
+      List_Read(vol->Surfaces, j, &s);
+      if(Tree_Nbr(s->Simplexes) || Tree_Nbr(s->Quadrangles))
+        List_Add(AllSurfaces, &s);
+    }
+  }
+
+  for(int i = 0; i < List_Nbr(ListSurfaces); i++) {
+    List_Read(ListSurfaces, i, &s);
+    if(!List_Search(AllSurfaces, &s, compareSurface)) {
+      
+      // triangles
+      Elements = Tree2List(s->Simplexes);
+      for(int j = 0; j < List_Nbr(Elements); j++) {
+        List_Read(Elements, j, &sx);
+	if(sx->VSUP)
+	  _unv_print_record(abs(sx->Num), THINSHLL, s->Num, 3, 3, &sx->V[0], sx->VSUP);
+	else
+	  _unv_print_record(abs(sx->Num), THINSHLL, s->Num, 3, 0, &sx->V[0], NULL);
+      }
+      List_Delete(Elements);
+      
+      // quadrangles
+      Elements = Tree2List(s->Quadrangles);
+      for(int j = 0; j < List_Nbr(Elements); j++) {
+        List_Read(Elements, j, &qx);
+	if(qx->VSUP)
+	  _unv_print_record(abs(qx->Num), QUAD, s->Num, 4, 4, &qx->V[0], qx->VSUP);
+	else
+	  _unv_print_record(abs(qx->Num), QUAD2, s->Num, 4, 0, &qx->V[0], NULL);
+      }
+      List_Delete(Elements);
+    }
+  }
+  List_Delete(ListSurfaces);
+  List_Delete(ListVolumes);
+  List_Delete(AllSurfaces);
+}
+
+static void _unv_process_3D_elements(Mesh *m)
 {
   List_T *ListVolumes = Tree2List(m->Volumes);
   List_T *Elements;
@@ -747,24 +763,14 @@ int process_unv_3D_elements(Mesh * m)
   Hexahedron *hx;
   Prism *px;
   Volume *v;
-  int nb = 0, i, j, nsup, n, ntot, k, geo, fetyp;
 
-  for(i = 0; i < List_Nbr(ListVolumes); i++) {
+  for(int i = 0; i < List_Nbr(ListVolumes); i++) {
     List_Read(ListVolumes, i, &v);
-    // TETRAEDRON
+
+    // Tets
     Elements = Tree2List(v->Simplexes);
-    for(j = 0; j < List_Nbr(Elements); j++) {
+    for(int j = 0; j < List_Nbr(Elements); j++) {
       List_Read(Elements, j, &sx);
-      if(sx->VSUP) {
-        fetyp = SOLIDFEM;
-        n = 4;
-        nsup = 6;
-      }
-      else {
-        fetyp = SOLIDFEM;
-        nsup = 0;
-        n = 4;
-      }
       if(sx->Volume_Simplexe() < 0) {
         Vertex *temp;
         temp = sx->V[0];
@@ -779,159 +785,88 @@ int process_unv_3D_elements(Mesh * m)
 	  sx->VSUP[3] = temp;
 	}
       }
-      geo = v->Num;
-      fprintf(meshfile, "%10d%10d%10d%10d%10d%10d\n",
-              ELEMENT_ID++, fetyp, geo, geo, 7, n + nsup);
-      ntot = 0;
-      for(k = 0; k < n; k++) {
-        fprintf(meshfile, "%10d", sx->V[k]->Num);
-        if(ntot % 8 == 7)
-          fprintf(meshfile, "\n");
-        ntot++;
-      }
-      for(k = 0; k < nsup; k++) {
-        fprintf(meshfile, "%10d", sx->VSUP[k]->Num);
-        if(ntot % 8 == 7)
-          fprintf(meshfile, "\n");
-        ntot++;
-      }
-      if(ntot - 1 % 8 != 7)
-        fprintf(meshfile, "\n");
+      if(sx->VSUP)
+	_unv_print_record(ELEMENT_ID++, SOLIDFEM, v->Num, 4, 6, &sx->V[0], sx->VSUP);
+      else
+	_unv_print_record(ELEMENT_ID++, SOLIDFEM, v->Num, 4, 0, &sx->V[0], NULL);
     }
     List_Delete(Elements);
-    nb += Tree_Nbr(v->Simplexes);
 
-    // PRISMS
+    // Prisms
     Elements = Tree2List(v->Prisms);
-    for(j = 0; j < List_Nbr(Elements); j++) {
+    for(int j = 0; j < List_Nbr(Elements); j++) {
       List_Read(Elements, j, &px);
-      if(px->VSUP) {
-        fetyp = WEDGE;
-        n = 6;
-        nsup = 9;
-      }
-      else {
-        fetyp = WEDGE;
-        nsup = 0;
-        n = 6;
-      }
-
-      geo = v->Num;
-      fprintf(meshfile, "%10d%10d%10d%10d%10d%10d\n",
-              ELEMENT_ID++, fetyp, geo, geo, 7, n + nsup);
-      ntot = 0;
-      for(k = 0; k < n; k++) {
-        fprintf(meshfile, "%10d", px->V[k]->Num);
-        if(ntot % 8 == 7)
-          fprintf(meshfile, "\n");
-        ntot++;
-      }
-      for(k = 0; k < nsup; k++) {
-        fprintf(meshfile, "%10d", px->VSUP[k]->Num);
-        if(ntot % 8 == 7)
-          fprintf(meshfile, "\n");
-        ntot++;
-      }
-      if(ntot - 1 % 8 != 7)
-        fprintf(meshfile, "\n");
+      if(px->VSUP)
+	_unv_print_record(ELEMENT_ID++, WEDGE, v->Num, 6, 9, &px->V[0], px->VSUP);
+      else
+	_unv_print_record(ELEMENT_ID++, WEDGE, v->Num, 6, 0, &px->V[0], NULL);
     }
     List_Delete(Elements);
-    nb += Tree_Nbr(v->Prisms);
 
-    // HEXAHEDRA
+    // Hexas
     Elements = Tree2List(v->Hexahedra);
-    for(j = 0; j < List_Nbr(Elements); j++) {
+    for(int j = 0; j < List_Nbr(Elements); j++) {
       List_Read(Elements, j, &hx);
-      if(hx->VSUP) {
-        fetyp = BRICK;
-        n = 8;
-        nsup = 12;
-      }
-      else {
-        fetyp = BRICK;
-        nsup = 0;
-        n = 8;
-      }
-
-      geo = v->Num;
-      fprintf(meshfile, "%10d%10d%10d%10d%10d%10d\n",
-              ELEMENT_ID++, fetyp, geo, geo, 7, n + nsup);
-      ntot = 0;
-      for(k = 0; k < n; k++) {
-        fprintf(meshfile, "%10d", hx->V[k]->Num);
-        if(ntot % 8 == 7)
-          fprintf(meshfile, "\n");
-        ntot++;
-      }
-      for(k = 0; k < nsup; k++) {
-        fprintf(meshfile, "%10d", hx->VSUP[k]->Num);
-        if(ntot % 8 == 7)
-          fprintf(meshfile, "\n");
-        ntot++;
-      }
-      if(ntot - 1 % 8 != 7)
-        fprintf(meshfile, "\n");
+      if(hx->VSUP)
+	_unv_print_record(ELEMENT_ID++, BRICK, v->Num, 8, 12, &hx->V[0], hx->VSUP);
+      else
+	_unv_print_record(ELEMENT_ID++, BRICK, v->Num, 8, 0, &hx->V[0], NULL);
     }
     List_Delete(Elements);
-    nb += Tree_Nbr(v->Hexahedra);
   }
   List_Delete(ListVolumes);
-  return nb;
 }
 
-void add_unv_vertex(void *a, void *b)
+static void _unv_add_vertex(void *a, void *b)
 {
-  Vertex *v;
-  v = *(Vertex **) a;
+  Vertex *v = *(Vertex **) a;
   if(Tree_Search(tree, &v->Num))
     return;
   Tree_Add(tree, &v->Num);
-  fprintf(meshfile, "%10d%10d%2d%2d%2d%2d%2d%2d\n", v->Num, 1, 0, 1, 0, 0, 0,
-          0);
-  fprintf(meshfile, "%21.16fD+00 %21.16fD+00 %21.16fD+00\n", 0., 1., 0.);
-  fprintf(meshfile, "%21.16fD+00 %21.16fD+00 %21.16fD+00\n", 0., 0., 0.);
-  fprintf(meshfile, "%10d%10d%10d%10d%10d%10d\n", 0, 0, 0, 0, 0, 0);
+  fprintf(UNVFILE, "%10d%10d%2d%2d%2d%2d%2d%2d\n", v->Num, 1, 0, 1, 0, 0, 0, 0);
+  fprintf(UNVFILE, "%21.16fD+00 %21.16fD+00 %21.16fD+00\n", 0., 1., 0.);
+  fprintf(UNVFILE, "%21.16fD+00 %21.16fD+00 %21.16fD+00\n", 0., 0., 0.);
+  fprintf(UNVFILE, "%10d%10d%10d%10d%10d%10d\n", 0, 0, 0, 0, 0, 0);
 }
 
-void add_unv_simplex_vertices(void *a, void *b)
+static void _unv_add_simplex_vertices(void *a, void *b)
 {
   Simplex *s = *(Simplex **) a;
   if(s->iEnt != UNV_VOL_NUM)
     return;
   for(int i = 0; i < 4; i++)
-    add_unv_vertex(&s->V[i], NULL);
+    _unv_add_vertex(&s->V[i], NULL);
 }
 
-void add_unv_hexahedron_vertices(void *a, void *b)
+static void _unv_add_hexahedron_vertices(void *a, void *b)
 {
   Hexahedron *h = *(Hexahedron **) a;
   if(h->iEnt != UNV_VOL_NUM)
     return;
   for(int i = 0; i < 8; i++)
-    add_unv_vertex(&h->V[i], NULL);
+    _unv_add_vertex(&h->V[i], NULL);
 }
 
-void add_unv_prism_vertices(void *a, void *b)
+static void _unv_add_prism_vertices(void *a, void *b)
 {
   Prism *p = *(Prism **) a;
   if(p->iEnt != UNV_VOL_NUM)
     return;
   for(int i = 0; i < 6; i++)
-    add_unv_vertex(&p->V[i], NULL);
+    _unv_add_vertex(&p->V[i], NULL);
 }
 
-void add_unv_pyramid_vertices(void *a, void *b)
+static void _unv_add_pyramid_vertices(void *a, void *b)
 {
   Pyramid *p = *(Pyramid **) a;
   if(p->iEnt != UNV_VOL_NUM)
     return;
   for(int i = 0; i < 5; i++)
-    add_unv_vertex(&p->V[i], NULL);
+    _unv_add_vertex(&p->V[i], NULL);
 }
 
-void process_unv_groups(Mesh * m)
+static void _unv_process_groups(Mesh *m)
 {
-  int j, i, k;
   Volume *pV;
   Surface *ps, s;
   Curve *pc, c;
@@ -939,71 +874,187 @@ void process_unv_groups(Mesh * m)
   PhysicalGroup *p;
   List_T *ListVolumes;
 
-  for(i = 0; i < List_Nbr(m->PhysicalGroups); i++) {
+  for(int i = 0; i < List_Nbr(m->PhysicalGroups); i++) {
 
     List_Read(m->PhysicalGroups, i, &p);
 
-    fprintf(meshfile, "%6d\n", -1);
-    fprintf(meshfile, "%6d\n", GROUPOFNODES);
-    fprintf(meshfile, "%10d%10d\n", p->Num, 1);
-    fprintf(meshfile, "LOAD SET %2d\n", 1);
+    fprintf(UNVFILE, "%6d\n", -1);
+    fprintf(UNVFILE, "%6d\n", GROUPOFNODES);
+    fprintf(UNVFILE, "%10d%10d\n", p->Num, 1);
+    fprintf(UNVFILE, "LOAD SET %2d\n", 1);
 
     tree = Tree_Create(sizeof(int), fcmp_absint);
 
     switch (p->Typ) {
     case MSH_PHYSICAL_VOLUME:
       ListVolumes = Tree2List(m->Volumes);
-      for(k = 0; k < List_Nbr(ListVolumes); k++) {
+      for(int k = 0; k < List_Nbr(ListVolumes); k++) {
         List_Read(ListVolumes, k, &pV);
-        for(j = 0; j < List_Nbr(p->Entities); j++) {
+        for(int j = 0; j < List_Nbr(p->Entities); j++) {
           List_Read(p->Entities, j, &UNV_VOL_NUM);
-          Tree_Action(pV->Simplexes, add_unv_simplex_vertices);
-          Tree_Action(pV->Hexahedra, add_unv_hexahedron_vertices);
-          Tree_Action(pV->Prisms, add_unv_prism_vertices);
-          Tree_Action(pV->Pyramids, add_unv_pyramid_vertices);
+          Tree_Action(pV->Simplexes, _unv_add_simplex_vertices);
+          Tree_Action(pV->Hexahedra, _unv_add_hexahedron_vertices);
+          Tree_Action(pV->Prisms, _unv_add_prism_vertices);
+          Tree_Action(pV->Pyramids, _unv_add_pyramid_vertices);
         }
       }
       List_Delete(ListVolumes);
       break;
     case MSH_PHYSICAL_SURFACE:
-      for(j = 0; j < List_Nbr(p->Entities); j++) {
+      for(int j = 0; j < List_Nbr(p->Entities); j++) {
         ps = &s;
         List_Read(p->Entities, j, &ps->Num);
         if(Tree_Query(m->Surfaces, &ps))
-          Tree_Action(ps->Vertices, add_unv_vertex);
+          Tree_Action(ps->Vertices, _unv_add_vertex);
       }
       break;
     case MSH_PHYSICAL_LINE:
-      for(j = 0; j < List_Nbr(p->Entities); j++) {
+      for(int j = 0; j < List_Nbr(p->Entities); j++) {
         pc = &c;
         List_Read(p->Entities, j, &pc->Num);
         if(Tree_Query(m->Curves, &pc))
-          for(k = 0; k < List_Nbr(pc->Vertices); k++)
-            add_unv_vertex(List_Pointer(pc->Vertices, k), NULL);
+          for(int k = 0; k < List_Nbr(pc->Vertices); k++)
+            _unv_add_vertex(List_Pointer(pc->Vertices, k), NULL);
       }
       break;
     case MSH_PHYSICAL_POINT:
-      for(j = 0; j < List_Nbr(p->Entities); j++) {
+      for(int j = 0; j < List_Nbr(p->Entities); j++) {
         pv = &v;
         List_Read(p->Entities, j, &pv->Num);
         if(Tree_Query(m->Vertices, &pv))
-          add_unv_vertex(&pv, NULL);
+          _unv_add_vertex(&pv, NULL);
       }
       break;
     }
 
     Tree_Delete(tree);
 
-    fprintf(meshfile, "%6d\n", -1);
+    fprintf(UNVFILE, "%6d\n", -1);
   }
 }
 
-//  G R E F   F O R M A T
+void Print_Mesh_UNV(Mesh *M, FILE *fp)
+{
+  UNVFILE = fp;
+  _unv_process_nodes(M);
+  fprintf(UNVFILE, "%6d\n", -1);
+  fprintf(UNVFILE, "%6d\n", ELEMENTS);
+  ELEMENT_ID = 1;
+  _unv_process_3D_elements(M);
+  _unv_process_2D_elements(M);
+  if(0) _unv_process_1D_elements(M);
+  fprintf(UNVFILE, "%6d\n", -1);
+  _unv_process_groups(M);
+}
+
+// Write mesh in Gref format
 
-void ConsecutiveNodes(Mesh * M, Tree_T * ConstecutiveNTree,
-                      Tree_T * ConsecutiveETree);
+static FILE *GREFFILE;
 
-static int compareFrozen(const void *a, const void *b)
+static void _gref_consecutive_nodes(Mesh *M, Tree_T *ConsecutiveNTree,
+				    Tree_T *ConsecutiveETree)
+{
+  Simplex *sx;
+  Quadrangle *qx;
+  Surface *s;
+  int nbnod, nbedges, nbdof;
+
+  int newnum = 0;
+
+  List_T *ListSurfaces = Tree2List(M->Surfaces);
+  for(int i = 0; i < List_Nbr(ListSurfaces); i++) {
+    List_Read(ListSurfaces, i, &s);
+    List_T *Triangles = Tree2List(s->Simplexes);
+    for(int j = 0; j < List_Nbr(Triangles); j++) {
+      List_Read(Triangles, j, &sx);
+      for(int k = 0; k < 3; k++) {
+        if(sx->V[k]->Frozen >= 0) {
+          sx->V[k]->Frozen = --newnum;
+          Tree_Insert(ConsecutiveNTree, &(sx->V[k]));
+        }
+      }
+    }
+    List_Delete(Triangles);
+    List_T *Quadrangles = Tree2List(s->Quadrangles);
+    for(int j = 0; j < List_Nbr(Quadrangles); j++) {
+      List_Read(Quadrangles, j, &qx);
+      for(int k = 0; k < 4; k++) {
+        if(qx->V[k]->Frozen >= 0) {
+          qx->V[k]->Frozen = --newnum;
+          Tree_Insert(ConsecutiveNTree, &(qx->V[k]));
+        }
+      }
+    }
+    List_Delete(Quadrangles);
+  }
+
+  nbnod = -newnum;
+
+  for(int i = 0; i < List_Nbr(ListSurfaces); i++) {
+    List_Read(ListSurfaces, i, &s);
+    List_T *Triangles = Tree2List(s->Simplexes);
+    for(int j = 0; j < List_Nbr(Triangles); j++) {
+      List_Read(Triangles, j, &sx);
+      for(int k = 0; k < 3; k++) {
+	if(sx->VSUP[k]->Frozen >= 0) {
+	  sx->VSUP[k]->Frozen = --newnum;
+	  Tree_Insert(ConsecutiveETree, &(sx->VSUP[k]));
+	}
+      }
+    }
+    List_Delete(Triangles);
+    List_T *Quadrangles = Tree2List(s->Quadrangles);
+    for(int j = 0; j < List_Nbr(Quadrangles); j++) {
+      List_Read(Quadrangles, j, &qx);
+      for(int k = 0; k < 4; k++) {
+	if(qx->VSUP[k]->Frozen >= 0) {
+	  qx->VSUP[k]->Frozen = --newnum;
+	  Tree_Insert(ConsecutiveETree, &(qx->VSUP[k]));
+	}
+      }
+    }
+    List_Delete(Quadrangles);
+  }
+
+  List_Delete(ListSurfaces);
+
+  nbedges = -newnum - nbnod;
+  nbdof = nbnod + nbedges;
+  Msg(INFO, "%d Dofs", nbdof);
+}
+
+static void _gref_end_consecutive_nodes(Mesh *M)
+{
+  Simplex *sx;
+  Quadrangle *qx;
+  Surface *s;
+
+  List_T *ListSurfaces = Tree2List(M->Surfaces);
+  for(int i = 0; i < List_Nbr(ListSurfaces); i++) {
+    List_Read(ListSurfaces, i, &s);
+    List_T *Triangles = Tree2List(s->Simplexes);
+    for(int j = 0; j < List_Nbr(Triangles); j++) {
+      List_Read(Triangles, j, &sx);
+      for(int k = 0; k < 3; k++)
+        sx->V[k]->Frozen = 0;
+      for(int k = 0; k < 3; k++)
+	sx->VSUP[k]->Frozen = 0;
+    }
+    List_Delete(Triangles);
+    List_T *Quadrangles = Tree2List(s->Quadrangles);
+    for(int j = 0; j < List_Nbr(Quadrangles); j++) {
+      List_Read(Quadrangles, j, &qx);
+      for(int k = 0; k < 4; k++)
+        qx->V[k]->Frozen = 0;
+      for(int k = 0; k < 4; k++)
+	qx->VSUP[k]->Frozen = 0;
+    }
+    List_Delete(Quadrangles);
+  }
+  List_Delete(ListSurfaces);
+}
+
+static int _gref_compare_frozen(const void *a, const void *b)
 {
   Vertex *q, *w;
   q = *(Vertex **) a;
@@ -1011,10 +1062,10 @@ static int compareFrozen(const void *a, const void *b)
   return w->Frozen - q->Frozen;
 }
 
-int process_Gref_nodes(FILE * fGref, Mesh * M,
-                       Tree_T * ConsecutiveNTree, Tree_T * ConsecutiveETree)
+static int _gref_process_nodes(Mesh *M, Tree_T *ConsecutiveNTree, 
+			       Tree_T *ConsecutiveETree)
 {
-  int i, nbtri;
+  int i, nbtriqua;
   Vertex *v;
   Surface *s;
   List_T *Nodes;
@@ -1023,41 +1074,42 @@ int process_Gref_nodes(FILE * fGref, Mesh * M,
   Tree_Action(M->Surfaces, Degre2_Surface);
  
   List_T *ListSurfaces = Tree2List(M->Surfaces);
-  nbtri = 0;
+  nbtriqua = 0;
   for(i = 0; i < List_Nbr(ListSurfaces); i++) {
     List_Read(ListSurfaces, i, &s);
-    nbtri += Tree_Nbr(s->Simplexes);
+    nbtriqua += Tree_Nbr(s->Simplexes);
+    nbtriqua += Tree_Nbr(s->Quadrangles);
   }
   List_Delete(ListSurfaces);
 
-  ConsecutiveNodes(M, ConsecutiveNTree, ConsecutiveETree);
+  _gref_consecutive_nodes(M, ConsecutiveNTree, ConsecutiveETree);
 
-  fprintf(fGref, "%d %d %d\n", nbtri, Tree_Nbr(ConsecutiveNTree),
+  fprintf(GREFFILE, "%d %d %d\n", nbtriqua, Tree_Nbr(ConsecutiveNTree),
           Tree_Nbr(ConsecutiveNTree) + Tree_Nbr(ConsecutiveETree));
 
   Nodes = Tree2List(ConsecutiveNTree);
   for(i = 0; i < List_Nbr(Nodes); i++) {
     List_Read(Nodes, i, &v);
-    fprintf(fGref, "%21.16e ", v->Pos.X * CTX.mesh.scaling_factor);
+    fprintf(GREFFILE, "%21.16e ", v->Pos.X * CTX.mesh.scaling_factor);
     if(i % 3 == 2)
-      fprintf(fGref, "\n");
+      fprintf(GREFFILE, "\n");
   }
   if((List_Nbr(Nodes) - 1) % 3 != 2)
-    fprintf(fGref, "\n");
+    fprintf(GREFFILE, "\n");
   for(i = 0; i < List_Nbr(Nodes); i++) {
     List_Read(Nodes, i, &v);
-    fprintf(fGref, "%21.16e ", v->Pos.Y * CTX.mesh.scaling_factor);
+    fprintf(GREFFILE, "%21.16e ", v->Pos.Y * CTX.mesh.scaling_factor);
     if(i % 3 == 2)
-      fprintf(fGref, "\n");
+      fprintf(GREFFILE, "\n");
   }
   if((List_Nbr(Nodes) - 1) % 3 != 2)
-    fprintf(fGref, "\n");
+    fprintf(GREFFILE, "\n");
   i = Tree_Nbr(ConsecutiveNTree);
   List_Delete(Nodes);
   return i;
 }
 
-int find_physicalentity(Vertex * v, Mesh * m)
+static int _gref_find_physical(Vertex *v, Mesh *m)
 {
   PhysicalGroup *p;
   Curve *c;
@@ -1087,8 +1139,7 @@ int find_physicalentity(Vertex * v, Mesh * m)
   return 0;
 }
 
-void process_Gref_poundarybonditions(FILE * fGref, Mesh * M,
-                                     Tree_T * TRN, Tree_T * TRE)
+static void _gref_process_boundary_conditions(Mesh *M, Tree_T *TRN, Tree_T *TRE)
 {
   int i, ent;
   Vertex *v;
@@ -1096,275 +1147,354 @@ void process_Gref_poundarybonditions(FILE * fGref, Mesh * M,
   List_T *Nodes = Tree2List(TRN);
   for(i = 0; i < List_Nbr(Nodes); i++) {
     List_Read(Nodes, i, &v);
-    ent = find_physicalentity(v, M);
-    fprintf(fGref, "%d %d ", ent, ent);
+    ent = _gref_find_physical(v, M);
+    fprintf(GREFFILE, "%d %d ", ent, ent);
     if(i % 3 == 2)
-      fprintf(fGref, "\n");
+      fprintf(GREFFILE, "\n");
   }
   if((List_Nbr(Nodes) - 1) % 3 != 2)
-    fprintf(fGref, "\n");
+    fprintf(GREFFILE, "\n");
   List_Delete(Nodes);
 
   Nodes = Tree2List(TRE);
   for(i = 0; i < List_Nbr(Nodes); i++) {
     List_Read(Nodes, i, &v);
-    ent = find_physicalentity(v, M);
-    fprintf(fGref, "%d %d ", ent, ent);
+    ent = _gref_find_physical(v, M);
+    fprintf(GREFFILE, "%d %d ", ent, ent);
     if(i % 3 == 2)
-      fprintf(fGref, "\n");
+      fprintf(GREFFILE, "\n");
   }
   if((List_Nbr(Nodes) - 1) % 3 != 2)
-    fprintf(fGref, "\n");
+    fprintf(GREFFILE, "\n");
   List_Delete(Nodes);
 }
 
-void process_Gref_elements(FILE * fGref, Mesh * M, int nn)
+static void _gref_process_elements(Mesh *M, int nn)
 {
-  int i, j;
   Simplex *sx;
+  Quadrangle *qx;
   Surface *s;
-  List_T *Triangles;
-  List_T *ListSurfaces;
 
-  ListSurfaces = Tree2List(M->Surfaces);
-  for(i = 0; i < List_Nbr(ListSurfaces); i++) {
-    List_Read(ListSurfaces, i, &s);
-    Triangles = Tree2List(s->Simplexes);
-    for(j = 0; j < List_Nbr(Triangles); j++) {
-      List_Read(Triangles, j, &sx);
-      if(!sx->V[3])
-        fprintf(fGref, "%d %d %d\n", -sx->V[0]->Frozen,
-                -sx->V[1]->Frozen, -sx->V[2]->Frozen);
-      else
-        fprintf(fGref, "%d %d %d %d\n", -sx->V[0]->Frozen,
-                -sx->V[1]->Frozen, -sx->V[2]->Frozen, -sx->V[3]->Frozen);
-
-    }
-    List_Delete(Triangles);
-  }
+  List_T *ListSurfaces = Tree2List(M->Surfaces);
 
-  for(i = 0; i < List_Nbr(ListSurfaces); i++) {
+  for(int i = 0; i < List_Nbr(ListSurfaces); i++) {
     List_Read(ListSurfaces, i, &s);
-    Triangles = Tree2List(s->Simplexes);
-    for(j = 0; j < List_Nbr(Triangles); j++) {
+    List_T *Triangles = Tree2List(s->Simplexes);
+    for(int j = 0; j < List_Nbr(Triangles); j++) {
       List_Read(Triangles, j, &sx);
-      if(!sx->V[3])
-        fprintf(fGref, "%d %d %d\n", -sx->VSUP[0]->Frozen - nn,
-                -sx->VSUP[1]->Frozen - nn, -sx->VSUP[2]->Frozen - nn);
-      else
-        fprintf(fGref, "%d %d %d %d\n", -sx->VSUP[0]->Frozen - nn,
-                -sx->VSUP[1]->Frozen - nn,
-                -sx->VSUP[2]->Frozen - nn, -sx->VSUP[3]->Frozen - nn);
+      fprintf(GREFFILE, "%d %d %d\n", -sx->V[0]->Frozen,
+	      -sx->V[1]->Frozen, -sx->V[2]->Frozen);
     }
     List_Delete(Triangles);
-  }
-  // Degres de Liberte
-  for(i = 0; i < List_Nbr(ListSurfaces); i++) {
-    List_Read(ListSurfaces, i, &s);
-    Triangles = Tree2List(s->Simplexes);
-    for(j = 0; j < List_Nbr(Triangles); j++) {
-      List_Read(Triangles, j, &sx);
-      if(!sx->V[3])
-        fprintf(fGref, "%d %d %d %d %d %d %d %d %d %d %d %d\n",
-                -2 * sx->V[0]->Frozen - 1,
-                -2 * sx->V[0]->Frozen,
-                -2 * sx->VSUP[0]->Frozen - 1,
-                -2 * sx->VSUP[0]->Frozen,
-                -2 * sx->V[1]->Frozen - 1,
-                -2 * sx->V[1]->Frozen,
-                -2 * sx->VSUP[1]->Frozen - 1,
-                -2 * sx->VSUP[1]->Frozen,
-                -2 * sx->V[2]->Frozen - 1,
-                -2 * sx->V[2]->Frozen,
-                -2 * sx->VSUP[2]->Frozen - 1, -2 * sx->VSUP[2]->Frozen);
-      else
-        fprintf(fGref, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
-                -2 * sx->V[0]->Frozen - 1,
-                -2 * sx->V[0]->Frozen,
-                -2 * sx->VSUP[0]->Frozen - 1,
-                -2 * sx->VSUP[0]->Frozen,
-                -2 * sx->V[1]->Frozen - 1,
-                -2 * sx->V[1]->Frozen,
-                -2 * sx->VSUP[1]->Frozen - 1,
-                -2 * sx->VSUP[1]->Frozen,
-                -2 * sx->V[2]->Frozen - 1,
-                -2 * sx->V[2]->Frozen,
-                -2 * sx->VSUP[2]->Frozen - 1,
-                -2 * sx->VSUP[2]->Frozen,
-                -2 * sx->V[3]->Frozen - 1,
-                -2 * sx->V[3]->Frozen,
-                -2 * sx->VSUP[3]->Frozen - 1, -2 * sx->VSUP[3]->Frozen);
+    List_T *Quadrangles = Tree2List(s->Quadrangles);
+    for(int j = 0; j < List_Nbr(Quadrangles); j++) {
+      List_Read(Quadrangles, j, &qx);
+      fprintf(GREFFILE, "%d %d %d %d\n", -qx->V[0]->Frozen,
+	      -qx->V[1]->Frozen, -qx->V[2]->Frozen, -qx->V[3]->Frozen);
     }
-    List_Delete(Triangles);
+    List_Delete(Quadrangles);
   }
-  List_Delete(ListSurfaces);
-}
-
-void ConsecutiveNodes(Mesh * M, Tree_T * ConsecutiveNTree,
-                      Tree_T * ConsecutiveETree)
-{
-  int i, j, k;
-  Simplex *sx;
-  Surface *s;
-  List_T *Triangles;
-  int nbnod, nbedges, nbdof;
-  List_T *ListSurfaces;
-
-  int newnum = 0, N;
 
-  ListSurfaces = Tree2List(M->Surfaces);
-  for(i = 0; i < List_Nbr(ListSurfaces); i++) {
+  // Degres de Liberte
+  for(int i = 0; i < List_Nbr(ListSurfaces); i++) {
     List_Read(ListSurfaces, i, &s);
-    Triangles = Tree2List(s->Simplexes);
-    for(j = 0; j < List_Nbr(Triangles); j++) {
+    List_T *Triangles = Tree2List(s->Simplexes);
+    for(int j = 0; j < List_Nbr(Triangles); j++) {
       List_Read(Triangles, j, &sx);
-      if(!sx->V[3])
-        N = 3;
-      else
-        N = 4;
-      for(k = 0; k < N; k++) {
-        if(sx->V[k]->Frozen >= 0) {
-          sx->V[k]->Frozen = --newnum;
-          Tree_Insert(ConsecutiveNTree, &(sx->V[k]));
-        }
-      }
+      fprintf(GREFFILE, "%d %d %d %d %d %d %d %d %d %d %d %d\n",
+	      -2 * sx->V[0]->Frozen - 1,
+	      -2 * sx->V[0]->Frozen,
+	      -2 * sx->VSUP[0]->Frozen - 1,
+	      -2 * sx->VSUP[0]->Frozen,
+	      -2 * sx->V[1]->Frozen - 1,
+	      -2 * sx->V[1]->Frozen,
+	      -2 * sx->VSUP[1]->Frozen - 1,
+	      -2 * sx->VSUP[1]->Frozen,
+	      -2 * sx->V[2]->Frozen - 1,
+	      -2 * sx->V[2]->Frozen,
+	      -2 * sx->VSUP[2]->Frozen - 1, -2 * sx->VSUP[2]->Frozen);
     }
     List_Delete(Triangles);
-  }
-  nbnod = -newnum;
-  ListSurfaces = Tree2List(M->Surfaces);
-  for(i = 0; i < List_Nbr(ListSurfaces); i++) {
-    List_Read(ListSurfaces, i, &s);
-    Triangles = Tree2List(s->Simplexes);
-    for(j = 0; j < List_Nbr(Triangles); j++) {
-      List_Read(Triangles, j, &sx);
-      if(!sx->V[3])
-        N = 3;
-      else
-        N = 4;
-      for(k = 0; k < N; k++) {
-        if(sx->VSUP[k]->Frozen >= 0) {
-          sx->VSUP[k]->Frozen = --newnum;
-          Tree_Insert(ConsecutiveETree, &(sx->VSUP[k]));
-        }
-      }
+    List_T *Quadrangles = Tree2List(s->Quadrangles);
+    for(int j = 0; j < List_Nbr(Quadrangles); j++) {
+      List_Read(Quadrangles, j, &qx);
+      fprintf(GREFFILE, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
+	      -2 * qx->V[0]->Frozen - 1,
+	      -2 * qx->V[0]->Frozen,
+	      -2 * qx->VSUP[0]->Frozen - 1,
+	      -2 * qx->VSUP[0]->Frozen,
+	      -2 * qx->V[1]->Frozen - 1,
+	      -2 * qx->V[1]->Frozen,
+	      -2 * qx->VSUP[1]->Frozen - 1,
+	      -2 * qx->VSUP[1]->Frozen,
+	      -2 * qx->V[2]->Frozen - 1,
+	      -2 * qx->V[2]->Frozen,
+	      -2 * qx->VSUP[2]->Frozen - 1,
+	      -2 * qx->VSUP[2]->Frozen,
+	      -2 * qx->V[3]->Frozen - 1,
+	      -2 * qx->V[3]->Frozen,
+	      -2 * qx->VSUP[3]->Frozen - 1, -2 * qx->VSUP[3]->Frozen);
     }
-    List_Delete(Triangles);
+    List_Delete(Quadrangles);
   }
-  nbedges = -newnum - nbnod;
-  nbdof = nbnod + nbedges;
-  Msg(INFO, "%d Dofs", nbdof);
+  List_Delete(ListSurfaces);
 }
 
-void EndConsecutiveNodes(Mesh * M)
+void Print_Mesh_GREF(Mesh *M, FILE *fp)
 {
-  int i, j, k;
-  Simplex *sx;
-  Surface *s;
-  List_T *Triangles;
-  List_T *ListSurfaces;
-  int N;
-
-  ListSurfaces = Tree2List(M->Surfaces);
-  for(i = 0; i < List_Nbr(ListSurfaces); i++) {
-    List_Read(ListSurfaces, i, &s);
-    Triangles = Tree2List(s->Simplexes);
-    for(j = 0; j < List_Nbr(Triangles); j++) {
-      List_Read(Triangles, j, &sx);
-      if(!sx->V[3])
-        N = 3;
-      else
-        N = 4;
-      for(k = 0; k < N; k++)
-        sx->V[k]->Frozen = 0;
-      for(k = 0; k < N; k++)
-        sx->VSUP[k]->Frozen = 0;
-    }
-    List_Delete(Triangles);
-  }
-  List_Delete(ListSurfaces);
+  GREFFILE = fp;
+  Tree_T *TRN = Tree_Create(sizeof(Vertex *), _gref_compare_frozen);
+  Tree_T *TRE = Tree_Create(sizeof(Vertex *), _gref_compare_frozen);
+  _gref_process_nodes(M, TRN, TRE);
+  _gref_process_elements(M, Tree_Nbr(TRN));
+  _gref_process_boundary_conditions(M, TRN, TRE);
+  Tree_Delete(TRN);
+  Tree_Delete(TRE);
+  _gref_end_consecutive_nodes(M);
 }
 
-//  V R M L 1   F O R M A T
+// Write mesh in VRML 1 format
 
 static List_T *wrlnodes = NULL;
+static FILE *WRLFILE;
 
-void print_wrl_node(void *a, void *b)
+static void _wrl_print_node(void *a, void *b)
 {
   Vertex *V = *(Vertex **) a;
-  fprintf(meshfile, "%.16g %.16g %.16g,\n",
+  fprintf(WRLFILE, "%.16g %.16g %.16g,\n",
           V->Pos.X * CTX.mesh.scaling_factor,
           V->Pos.Y * CTX.mesh.scaling_factor,
           V->Pos.Z * CTX.mesh.scaling_factor);
   List_Add(wrlnodes, &V->Num);
 }
 
-void process_wrl_nodes(Mesh * M)
+static void _wrl_process_nodes(Mesh *M)
 {
   if(!wrlnodes)
     wrlnodes = List_Create(Tree_Size(M->Vertices), 100, sizeof(int));
   else
     List_Reset(wrlnodes);
-  fprintf(meshfile, "#VRML V1.0 ascii\n");
-  fprintf(meshfile, "#created by Gmsh\n");
-  fprintf(meshfile, "Coordinate3 {\n");
-  fprintf(meshfile, "  point [\n");
-  Tree_Action(M->Vertices, print_wrl_node);
-  fprintf(meshfile, "  ]\n");
-  fprintf(meshfile, "}\n");
+  fprintf(WRLFILE, "#VRML V1.0 ascii\n");
+  fprintf(WRLFILE, "#created by Gmsh\n");
+  fprintf(WRLFILE, "Coordinate3 {\n");
+  fprintf(WRLFILE, "  point [\n");
+  Tree_Action(M->Vertices, _wrl_print_node);
+  fprintf(WRLFILE, "  ]\n");
+  fprintf(WRLFILE, "}\n");
 }
 
-void print_wrl_simplex(void *a, void *b)
+static void _wrl_print_line(void *a, void *b)
 {
-  Simplex *S = *(Simplex **) a;
-  int i = 0, j;
-  while(S->V[i]) {
-    j = List_ISearch(wrlnodes, &S->V[i]->Num, fcmp_int);
-    if(j < 0)
-      Msg(GERROR, "Unknown node %d in simplex %d", S->V[i]->Num, S->Num);
-    else
-      fprintf(meshfile, "%d,", j);
-    i++;
+  Simplex *s = *(Simplex **) a;
+  for(int i = 0; i < 2; i++){
+    if(s->V[i]){
+      int j = List_ISearch(wrlnodes, &s->V[i]->Num, fcmp_int);
+      if(j < 0)
+	Msg(GERROR, "Unknown node %d in line %d", s->V[i]->Num, s->Num);
+      else
+	fprintf(WRLFILE, "%d,", j);
+    }
   }
-  fprintf(meshfile, "-1,\n");
+  fprintf(WRLFILE, "-1,\n");
 }
 
-void print_all_wrl_curves(void *a, void *b)
+static void _wrl_print_triangle(void *a, void *b)
+{
+  Simplex *s = *(Simplex **) a;
+  for(int i = 0; i < 3; i++){
+    if(s->V[i]){
+      int j = List_ISearch(wrlnodes, &s->V[i]->Num, fcmp_int);
+      if(j < 0)
+	Msg(GERROR, "Unknown node %d in triangle %d", s->V[i]->Num, s->Num);
+      else
+	fprintf(WRLFILE, "%d,", j);
+    }
+  }
+  fprintf(WRLFILE, "-1,\n");
+}
+
+static void _wrl_print_quadrangle(void *a, void *b)
+{
+  Quadrangle *q = *(Quadrangle **) a;
+  for(int i = 0; i < 4; i++){
+    if(q->V[i]){
+      int j = List_ISearch(wrlnodes, &q->V[i]->Num, fcmp_int);
+      if(j < 0)
+	Msg(GERROR, "Unknown node %d in quadrangle %d", q->V[i]->Num, q->Num);
+      else
+	fprintf(WRLFILE, "%d,", j);
+    }
+  }
+  fprintf(WRLFILE, "-1,\n");
+}
+
+static void _wrl_print_all_curves(void *a, void *b)
 {
   Curve *c = *(Curve **) a;
   if(c->Num < 0)
     return;
-  fprintf(meshfile, "DEF Curve%d IndexedLineSet {\n", c->Num);
-  fprintf(meshfile, "  coordIndex [\n");
-  Tree_Action(c->Simplexes, print_wrl_simplex);
-  fprintf(meshfile, "  ]\n");
-  fprintf(meshfile, "}\n");
+  fprintf(WRLFILE, "DEF Curve%d IndexedLineSet {\n", c->Num);
+  fprintf(WRLFILE, "  coordIndex [\n");
+  Tree_Action(c->Simplexes, _wrl_print_line);
+  fprintf(WRLFILE, "  ]\n");
+  fprintf(WRLFILE, "}\n");
 }
 
-void print_all_wrl_surfaces(void *a, void *b)
+static void _wrl_print_all_surfaces(void *a, void *b)
 {
   Surface *s = *(Surface **) a;
-  fprintf(meshfile, "DEF Surface%d IndexedFaceSet {\n", s->Num);
-  fprintf(meshfile, "  coordIndex [\n");
-  Tree_Action(s->Simplexes, print_wrl_simplex);
-  fprintf(meshfile, "  ]\n");
-  fprintf(meshfile, "}\n");
+  fprintf(WRLFILE, "DEF Surface%d IndexedFaceSet {\n", s->Num);
+  fprintf(WRLFILE, "  coordIndex [\n");
+  Tree_Action(s->Simplexes, _wrl_print_triangle);
+  Tree_Action(s->Quadrangles, _wrl_print_quadrangle);
+  fprintf(WRLFILE, "  ]\n");
+  fprintf(WRLFILE, "}\n");
 }
 
-void process_wrl_elements(Mesh * M)
+static void _wrl_process_elements(Mesh *M)
 {
   if(!wrlnodes)
     Msg(GERROR, "VRML node list does not exist");
   else {
-    Tree_Action(M->Curves, print_all_wrl_curves);
-    Tree_Action(M->Surfaces, print_all_wrl_surfaces);
+    Tree_Action(M->Curves, _wrl_print_all_curves);
+    Tree_Action(M->Surfaces, _wrl_print_all_surfaces);
   }
 }
 
+void Print_Mesh_WRL(Mesh *M, FILE *fp)
+{
+  WRLFILE = fp;
+  _wrl_process_nodes(M);
+  _wrl_process_elements(M);
+}
+
+// Write mesh in DMG format
+
+static int _dmg_is_topologic(Vertex *v, List_T *curves)
+{
+  Curve *c;
+  for(int i = 0; i < List_Nbr(curves); i++) {
+    List_Read(curves, i, &c);
+    if(!compareVertex(&v, &c->beg))
+      return 1;
+  }
+  return 0;
+}
+
+void Print_Mesh_DMG(Mesh *m, FILE *fp)
+{
+  int i, j;
+  List_T *ll, *l;
+  Vertex *v;
+  Curve *c;
+  Surface *s;
+  int k;
+
+  l = Tree2List(m->Points);
+  ll = Tree2List(m->Curves);
+
+  k = 0;
+  for(i = 0; i < List_Nbr(l); i++) {
+    List_Read(l, i, &v);
+    if(_dmg_is_topologic(v, ll)) {
+      k++;
+    }
+  }
+
+  // write first the global infos 
+
+  fprintf(fp, "%d %d %d %d \n", Tree_Nbr(m->Volumes),
+          Tree_Nbr(m->Surfaces),
+          Tree_Nbr(m->Curves) / 2,     // the 2 is for the reverse curves
+          k);
+
+  // then write the bounding box
+
+  m->Grid.min.X = CTX.min[0];
+  m->Grid.min.Y = CTX.min[1];
+  m->Grid.min.Z = CTX.min[2];
+  m->Grid.max.X = CTX.max[0];
+  m->Grid.max.Y = CTX.max[1];
+  m->Grid.max.Z = CTX.max[2];
+
+  fprintf(fp, "%12.5E %12.5E %12.5E \n", 
+	  m->Grid.min.X, m->Grid.min.Y, m->Grid.min.Z);
+  fprintf(fp, "%12.5E %12.5E %12.5E \n", 
+	  m->Grid.max.X, m->Grid.max.Y, m->Grid.max.Z);
+
+  // write the points
+  k = 0;
+  for(i = 0; i < List_Nbr(l); i++) {
+    List_Read(l, i, &v);
+    if(_dmg_is_topologic(v, ll)) {
+      v->Frozen = k++;
+      fprintf(fp, "%d %12.5E %12.5E %12.5E \n", 
+	      v->Frozen, v->Pos.X, v->Pos.Y, v->Pos.Z);
+    }
+  }
+  List_Delete(l);
+
+  // write the curves
+  l = ll;
+  k = 0;
+  for(i = 0; i < List_Nbr(l); i++) {
+    List_Read(l, i, &c);
+    if(c->Num > 0) {
+      c->ipar[3] = k;
+      Curve *cinv = FindCurve(-c->Num, m);
+      cinv->ipar[3] = k++;
+      fprintf(fp, "%d %d %d \n", 
+	      c->ipar[3], c->beg->Frozen, c->end->Frozen);
+    }
+  }
+
+  List_Delete(l);
+
+  // write the surfaces
+  l = Tree2List(m->Surfaces);
+
+  for(i = 0; i < List_Nbr(l); i++) {
+    List_Read(l, i, &s);
+
+    int numEdgeLoop[2000], iLoop = 0;
+    Vertex *beg = NULL;
+    numEdgeLoop[iLoop] = 0;
+    int deb = 1;
+    for(j = 0; j < List_Nbr(s->Generatrices); j++) {
+      List_Read(s->Generatrices, j, &c);
+      if(deb) {
+        beg = c->beg;
+        deb = 0;
+      }
+      Msg(INFO, "beg->%d end->%d", c->beg->Num, c->end->Num);
+      (numEdgeLoop[iLoop])++;
+      if(c->end == beg) {
+        iLoop++;
+        numEdgeLoop[iLoop] = 0;
+        deb = 1;
+      }
+    }
+    s->ipar[3] = i;
+    fprintf(fp, "%d %d\n", i, iLoop);
+    int iEdge = 0;
+    for(k = 0; k < iLoop; k++) {
+      fprintf(fp, "%d ", numEdgeLoop[k]);
+      for(j = 0; j < numEdgeLoop[k]; j++) {
+        List_Read(s->Generatrices, iEdge++, &c);
+        fprintf(fp, "%d %d ", abs(c->ipar[3]), (c->Num > 0) ? 1 : -1);
+      }
+      fprintf(fp, "\n");
+    }
+  }
+  List_Delete(l);
+
+  // write the volumes (2 b continued...)
+}
+
 
 // Public Print_Mesh routine
 
-void Print_Mesh(Mesh * M, char *c, int Type)
+void Print_Mesh(Mesh *M, char *c, int Type)
 {
   char name[256], ext[10]="";
 
@@ -1378,18 +1508,11 @@ void Print_Mesh(Mesh * M, char *c, int Type)
   strcpy(name, M->name);
 
   switch(Type){
-  case FORMAT_MSH:
-    strcpy(ext, ".msh"); 
-    break;
-  case FORMAT_VRML:
-    strcpy(ext, ".wrl"); 
-    break;
-  case FORMAT_UNV:
-    strcpy(ext, ".unv");
-    break;
-  case FORMAT_GREF: 
-    strcpy(ext, ".Gref");
-    break;
+  case FORMAT_MSH:  strcpy(ext, ".msh"); break;
+  case FORMAT_VRML: strcpy(ext, ".wrl"); break;
+  case FORMAT_UNV:  strcpy(ext, ".unv"); break;
+  case FORMAT_GREF: strcpy(ext, ".Gref"); break;
+  case FORMAT_DMG:  strcpy(ext, ".dmg"); break;
   default:
     Msg(GERROR, "Unknown mesh file format %d", Type);
     return;
@@ -1399,62 +1522,24 @@ void Print_Mesh(Mesh * M, char *c, int Type)
 
   Msg(INFO, "Writing mesh file '%s'", name);
 
-  meshfile = fopen(name, "w");
-  if(!meshfile) {
+  FILE *fp = fopen(name, "w");
+  if(!fp) {
     Msg(GERROR, "Unable to open file '%s'", name);
     CTX.threads_lock = 0;
     return;
   }
 
   switch(Type){
-  case FORMAT_MSH:
-    if(CTX.mesh.msh_file_version == 1.0){
-      // OK, no header
-    }
-    else if(CTX.mesh.msh_file_version == 2.0){
-      fprintf(meshfile, "$MeshFormat\n");
-      fprintf(meshfile, "%g %d %d\n", CTX.mesh.msh_file_version,
-	      LIST_FORMAT_ASCII, sizeof(double));
-      fprintf(meshfile, "$EndMeshFormat\n");
-    }
-    else{
-      Msg(GERROR, "Unknown MSH file version to generate (%g)", 
-	  CTX.mesh.msh_file_version);
-      return;
-    }
-    process_msh_nodes(M);
-    process_msh_elements(M);
-    Msg(INFO, "%d nodes", MSH_NODE_NUM);
-    Msg(INFO, "%d elements", MSH_ELEMENT_NUM - 1);
-    break;
-  case FORMAT_VRML:
-    process_wrl_nodes(M);
-    process_wrl_elements(M);
-    break;
-  case FORMAT_UNV:
-    process_unv_nodes(M);
-    fprintf(meshfile, "%6d\n", -1);
-    fprintf(meshfile, "%6d\n", ELEMENTS);
-    ELEMENT_ID = 1;
-    process_unv_3D_elements(M);
-    process_unv_2D_elements(M);
-    // process_1D_elements (M);
-    fprintf(meshfile, "%6d\n", -1);
-    process_unv_groups(M);
-    break;
-  case FORMAT_GREF:
-    Tree_T *TRN = Tree_Create(sizeof(Vertex *), compareFrozen);
-    Tree_T *TRE = Tree_Create(sizeof(Vertex *), compareFrozen);
-    process_Gref_nodes(meshfile, M, TRN, TRE);
-    process_Gref_elements(meshfile, M, Tree_Nbr(TRN));
-    process_Gref_poundarybonditions(meshfile, M, TRN, TRE);
-    Tree_Delete(TRN);
-    Tree_Delete(TRE);
-    EndConsecutiveNodes(M);
+  case FORMAT_MSH:  Print_Mesh_MSH(M, fp); break;
+  case FORMAT_VRML: Print_Mesh_WRL(M, fp); break;
+  case FORMAT_UNV:  Print_Mesh_UNV(M, fp); break;
+  case FORMAT_GREF: Print_Mesh_GREF(M, fp); break;
+  case FORMAT_DMG:  Print_Mesh_DMG(M, fp); break;
+  default:
     break;
   }
 
-  fclose(meshfile);
+  fclose(fp);
   Msg(INFO, "Wrote mesh file '%s'", name);
   Msg(STATUS2N, "Wrote '%s'", name);
 
diff --git a/Mesh/Read_Mesh.cpp b/Mesh/Read_Mesh.cpp
index 92c014c01f788d7d219ae09b281cb8d226d7f3bd..a53d0439d46aaab16668765f875ecb4c809171cb 100644
--- a/Mesh/Read_Mesh.cpp
+++ b/Mesh/Read_Mesh.cpp
@@ -1,4 +1,4 @@
-// $Id: Read_Mesh.cpp,v 1.71 2004-04-18 03:36:07 geuzaine Exp $
+// $Id: Read_Mesh.cpp,v 1.72 2004-05-25 04:10:05 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -30,7 +30,7 @@
 
 extern Context_T CTX;
 
-// Read mesh in the native MSH format
+// Read mesh in native MSH format
 
 #define LGN1 1
 #define TRI1 2
@@ -113,6 +113,7 @@ void Read_Mesh_MSH(Mesh * M, FILE * fp)
   double x, y, z, lc1, lc2;
   Vertex *vert, verts[NB_NOD_MAX_ELM], *vertsp[NB_NOD_MAX_ELM], **vertspp;
   Simplex *simp;
+  Quadrangle *quad;
   Hexahedron *hex;
   Prism *pri;
   Pyramid *pyr;
@@ -299,7 +300,6 @@ void Read_Mesh_MSH(Mesh * M, FILE * fp)
 	    Msg(GERROR, "Line element %d already exists", simp->Num);
 	    Free_Simplex(&simp, 0);
 	  }
-          //NO!!! Tree_Insert(M->Simplexes, &simp) ; 
           break;
         case TRI1:
         case TRI2:
@@ -316,10 +316,7 @@ void Read_Mesh_MSH(Mesh * M, FILE * fp)
 	      simp->VSUP[i]->Degree = 2;
 	    }
 	  }
-          if(Tree_Insert(s->Simplexes, &simp) && Tree_Insert(M->Simplexes, &simp)){
-            M->Statistics[7]++;
-	  }
-          else{
+          if(!Tree_Insert(s->Simplexes, &simp)){
 	    Msg(GERROR, "Triangle %d already exists", simp->Num);
 	    Free_Simplex(&simp, 0);
 	  }
@@ -328,22 +325,18 @@ void Read_Mesh_MSH(Mesh * M, FILE * fp)
         case QUA2:
 	  s = addElementarySurface(M, Elementary);
 	  addPhysicalGroup(M, MSH_PHYSICAL_SURFACE, Physical, Elementary);
-          simp = Create_Quadrangle(vertsp[0], vertsp[1], vertsp[2], vertsp[3]);
-          simp->Num = Num;
-          simp->iEnt = Elementary;
-          simp->iPart = Add_MeshPartition(Partition, M);
+          quad = Create_Quadrangle(vertsp[0], vertsp[1], vertsp[2], vertsp[3]);
+          quad->Num = Num;
+          quad->iEnt = Elementary;
+          quad->iPart = Add_MeshPartition(Partition, M);
 	  if(Type == QUA2){
-	    simp->VSUP = (Vertex **) Malloc(4 * sizeof(Vertex *));
+	    quad->VSUP = (Vertex **) Malloc(4 * sizeof(Vertex *));
 	    for(i = 0; i < 4; i++){
-	      simp->VSUP[i] = vertsp[i+4];
-	      simp->VSUP[i]->Degree = 2;
+	      quad->VSUP[i] = vertsp[i+4];
+	      quad->VSUP[i]->Degree = 2;
 	    }
 	  }
-          if(Tree_Insert(s->Simplexes, &simp) && Tree_Insert(M->Simplexes, &simp)){
-            M->Statistics[7]++; //since s->Simplexes holds quads, too :-(
-            M->Statistics[8]++;
-          }
-	  else{
+          if(!Tree_Insert(s->Quadrangles, &quad)){
 	    Msg(GERROR, "Quadrangle %d already exists", simp->Num);
 	    Free_Simplex(&simp, 0);
 	  }
@@ -363,10 +356,7 @@ void Read_Mesh_MSH(Mesh * M, FILE * fp)
 	      simp->VSUP[i]->Degree = 2;
 	    }
 	  }
-          if(Tree_Insert(v->Simplexes, &simp) && Tree_Insert(M->Simplexes, &simp)){
-            M->Statistics[9]++;
-	  }
-	  else{
+          if(!Tree_Insert(v->Simplexes, &simp)){
 	    Msg(GERROR, "Tetrahedron %d already exists", simp->Num);
 	    Free_Simplex(&simp, 0);
 	  }
@@ -387,10 +377,7 @@ void Read_Mesh_MSH(Mesh * M, FILE * fp)
 	      hex->VSUP[i]->Degree = 2;
 	    }
 	  }
-          if(Tree_Insert(v->Hexahedra, &hex)){
-            M->Statistics[10]++;
-	  }
-	  else{
+          if(!Tree_Insert(v->Hexahedra, &hex)){
 	    Msg(GERROR, "Hexahedron %d already exists", hex->Num);
 	    Free_Hexahedron(&hex, 0);
 	  }
@@ -411,10 +398,7 @@ void Read_Mesh_MSH(Mesh * M, FILE * fp)
 	      pri->VSUP[i]->Degree = 2;
 	    }
 	  }
-          if(Tree_Insert(v->Prisms, &pri)){
-            M->Statistics[11]++;
-	  }
-	  else{
+          if(!Tree_Insert(v->Prisms, &pri)){
 	    Msg(GERROR, "Prism %d already exists", pri->Num);
 	    Free_Prism(&pri, 0);
 	  }
@@ -435,10 +419,7 @@ void Read_Mesh_MSH(Mesh * M, FILE * fp)
 	      pyr->VSUP[i]->Degree = 2;
 	    }
 	  }
-          if(Tree_Insert(v->Pyramids, &pyr)){
-            M->Statistics[12]++;
-	  }
-	  else{
+          if(!Tree_Insert(v->Pyramids, &pyr)){
 	    Msg(GERROR, "Pyramid %d already exists", pri->Num);
 	    Free_Pyramid(&pyr, 0);
 	  }
@@ -475,18 +456,12 @@ void Read_Mesh_MSH(Mesh * M, FILE * fp)
 
   }
 
-  if(Tree_Nbr(M->Volumes)) {
+  if(Tree_Nbr(M->Volumes))
     M->status = 3;
-    M->Statistics[6] = Tree_Nbr(M->Vertices);   // wrong, but...
-  }
-  else if(Tree_Nbr(M->Surfaces)) {
+  else if(Tree_Nbr(M->Surfaces))
     M->status = 2;
-    M->Statistics[5] = Tree_Nbr(M->Vertices);   // wrong, but...
-  }
-  else if(Tree_Nbr(M->Curves)) {
+  else if(Tree_Nbr(M->Curves))
     M->status = 1;
-    M->Statistics[4] = Tree_Nbr(M->Vertices);   // wrong, but...
-  }
   else if(Tree_Nbr(M->Points))
     M->status = 0;
   else
@@ -499,10 +474,336 @@ void Read_Mesh_MSH(Mesh * M, FILE * fp)
   List_Sort(M->Partitions, compareMeshPartitionIndex);
 }
 
+// Read mesh in VTK format
 
-// Public Read_Mesh routine
+void Read_Mesh_VTK(Mesh * m, FILE *fp)
+{
+  char line[256], dumline1[256], dumline2[256];
+  int i;
+  int NbFaces, NbVertices, Vertex1, Vertex2, Vertex3, NbVerticesOnFace;
+  double x, y, z;
+  Vertex *v1, *v2, *v3;
+
+  fgets(line, 255, fp);
+  fgets(line, 255, fp);
+  fgets(line, 255, fp);
+  fgets(line, 255, fp);
+  fgets(line, 255, fp);
+
+  sscanf(line, "%s %d %s", dumline1, &NbVertices, dumline2);
+  Surface *surf = Create_Surface(1, MSH_SURF_DISCRETE);
+  surf->Dirty = 1;
+  Tree_Add(m->Surfaces, &surf);
+  for(i = 0; i < NbVertices; i++) {
+    fscanf(fp, "%le %le %le", &x, &y, &z);
+    Vertex *v = Create_Vertex(i, x, y, z, 1.0, 1.0);
+    Tree_Add(m->Vertices, &v);
+    Tree_Add(surf->Vertices, &v);
+    v->ListSurf = List_Create(1, 1, sizeof(Surface *));
+    List_Add(v->ListSurf, &surf);
+  }
+
+  fscanf(fp, "%s %d %d", dumline1, &NbFaces, &i);
+  for(int i = 0; i < NbFaces; i++) {
+    fscanf(fp, "%d", &NbVerticesOnFace);
+    Simplex *s;
+    if(NbVerticesOnFace == 3) {
+      fscanf(fp, "%d %d %d", &Vertex1, &Vertex2, &Vertex3);
+      v1 = FindVertex(Vertex1, m);
+      v2 = FindVertex(Vertex2, m);
+      v3 = FindVertex(Vertex3, m);
+      if(!v1 || !v2 || !v3){
+	Msg(GERROR, "Bad vertex reference in VTK file: aborting");
+	return;
+      }
+      else{
+	s = Create_Simplex(v1, v2, v3, NULL);
+	s->Num = i;
+	s->iEnt = 1;
+      }
+    }
+    if(!(surf = FindSurface(1, m))) {
+      surf = Create_Surface(1, MSH_SURF_DISCRETE);
+      surf->Dirty = 1;
+      Tree_Add(m->Surfaces, &surf);
+    }
+    Tree_Add(surf->Simplexes, &s);
+  }
+
+  if(NbFaces)
+    m->status = 2;
+
+  Volume *vol = Create_Volume(1, MSH_VOLUME);
+  vol->Dirty = 1;
+  vol->Surfaces = List_Create(1, 1, sizeof(Surface *));
+  List_Add(vol->Surfaces, &surf);
+  Tree_Add(m->Volumes, &vol);
+}
+
+// Read mesh in SMS format
+
+#define ENTITY_VERTEX 0
+#define ENTITY_EDGE   1
+#define ENTITY_FACE   2
+#define ENTITY_REGION 3
+#define ENTITY_NONE   4
+
+void Read_Mesh_SMS(Mesh * m, FILE * in)
+{
+  char line[1023];
+  int i, patch, nbPts;
+  int NbRegions, NbFaces, NbEdges, NbVertices, NbPoints,
+    GEntityType, GEntityId, EntityNbConnections, Dummy,
+    Edge1, Edge2, Edge3, Edge4, Face1, Face2, Face3, Face4;
+  int VertexId1, VertexId2, NbEdgesOnFace, NbFacesOnRegion;
+  double x, y, z, u, v;
+  List_T *AllEdges, *AllFaces;
+  Vertex *v1 = NULL, *v2 = NULL, *v3 = NULL, *v4 = NULL;
+
+  fscanf(in, "%s %d", line, &Dummy);
+  fscanf(in, "%d %d %d %d %d", &NbRegions, &NbFaces, &NbEdges, &NbVertices,
+         &NbPoints);
+
+  Msg(INFO, "Reading a mesh in scorec format");
+  Msg(INFO, "%d Vertices", NbVertices);
+
+  for(i = 0; i < NbVertices; i++) {
+    fscanf(in, "%d", &GEntityId);
+    if(GEntityId) {
+      fscanf(in, "%d %d %lf %lf %lf", &GEntityType, &EntityNbConnections, &x,
+             &y, &z);
+      Vertex *vert = Create_Vertex(i, x, y, z, 1.0, 1.0);
+      Tree_Add(m->Vertices, &vert);
+      switch (GEntityType) {
+      case 0:
+	{
+	  // we need to make a new one: vertices in m->Vertices and
+	  // m->Points should never point to the same memory location
+	  Vertex *pnt = Create_Vertex(i, x, y, z, 1.0, 1.0);
+	  Tree_Add(m->Points, &pnt);
+	}
+        break;
+      case 1:
+        fscanf(in, "%le", &u);
+        break;
+      case 2:
+        fscanf(in, "%le %le %d", &u, &v, &patch);
+        break;
+      case 3:
+        break;
+      }
+    }
+  }
+
+  Msg(INFO, "%d edges", NbEdges);
+  AllEdges = List_Create(NbEdges, 1, sizeof(Edge));
+  Edge e;
+
+  for(int i = 0; i < NbEdges; i++) {
+    fscanf(in, "%d", &GEntityId);
+
+    if(GEntityId) {
+      fscanf(in, "%d %d %d %d %d", &GEntityType, &VertexId1, &VertexId2,
+             &EntityNbConnections, &nbPts);
+      for(int j = 0; j < nbPts; j++) {
+        switch (GEntityType) {
+        case 0:
+          break;
+        case 1:
+          fscanf(in, "%le", &u);
+          break;
+        case 2:
+          fscanf(in, "%le %le %d", &u, &v, &patch);
+          break;
+        case 3:
+          break;
+        }
+      }
+      e.Points = NULL;
+      Vertex *v1 = FindVertex(VertexId1 - 1, m);
+      Vertex *v2 = FindVertex(VertexId2 - 1, m);
+      e.V[0] = v1;
+      e.V[1] = v2;
+      List_Add(AllEdges, &e);
+      switch (GEntityType) {
+      case ENTITY_EDGE:
+        Simplex * s = Create_Simplex(v1, v2, NULL, NULL);
+        Curve *c;
+        if(!(c = FindCurve(GEntityId, m))) {
+          c = Create_Curve(GEntityId, MSH_SEGM_DISCRETE, 1, NULL, NULL, -1, -1, 0, 1);
+	  c->Dirty = 1;
+          Tree_Add(m->Curves, &c);
+        }
+        s->iEnt = GEntityId;
+        s->Num = i;
+        Tree_Add(c->Simplexes, &s);
+      }
+    }
+  }
+
+  AllFaces = List_Create(NbFaces, 1, sizeof(Simplex *));
+
+  Volume *vol = Create_Volume(1, MSH_VOLUME);
+  vol->Dirty = 1;
+  vol->Surfaces = List_Create(1, 1, sizeof(Surface *));
+  Tree_Add(m->Volumes, &vol);
+
+  Msg(INFO, "%d faces", NbFaces);
+  for(int i = 0; i < NbFaces; i++) {
+    fscanf(in, "%d", &GEntityId);
+    if(GEntityId) {
+      fscanf(in, "%d %d", &GEntityType, &NbEdgesOnFace);
+
+      List_T *Lists[4] = { 0, 0, 0, 0 };
+
+      if(NbEdgesOnFace == 3) {
+        fscanf(in, "%d %d %d %d", &Edge1, &Edge2, &Edge3, &nbPts);
+        List_Read(AllEdges, abs(Edge1) - 1, &e);
+        Lists[0] = e.Points;
+        if(Edge1 > 0)
+          v1 = e.V[0];
+        else
+          v1 = e.V[1];
+        List_Read(AllEdges, abs(Edge2) - 1, &e);
+        Lists[1] = e.Points;
+        if(Edge2 > 0)
+          v2 = e.V[0];
+        else
+          v2 = e.V[1];
+        List_Read(AllEdges, abs(Edge3) - 1, &e);
+        Lists[2] = e.Points;
+        if(Edge3 > 0)
+          v3 = e.V[0];
+        else
+          v3 = e.V[1];
+        v4 = NULL;
+      }
+      else if(NbEdgesOnFace == 4) {
+        fscanf(in, "%d %d %d %d %d", &Edge1, &Edge2, &Edge3, &Edge4, &nbPts);
+        List_Read(AllEdges, abs(Edge1) - 1, &e);
+        if(Edge1 > 0)
+          v1 = e.V[0];
+        else
+          v1 = e.V[1];
+        List_Read(AllEdges, abs(Edge2) - 1, &e);
+        if(Edge2 > 0)
+          v2 = e.V[0];
+        else
+          v2 = e.V[1];
+        List_Read(AllEdges, abs(Edge3) - 1, &e);
+        if(Edge3 > 0)
+          v3 = e.V[0];
+        else
+          v3 = e.V[1];
+        List_Read(AllEdges, abs(Edge4) - 1, &e);
+        if(Edge4 > 0)
+          v4 = e.V[0];
+        else
+          v4 = e.V[1];
+      }
+      else {
+        Msg(GERROR, "Wrong number pf edges on face (%d)", NbEdgesOnFace);
+      }
+      for(int j = 0; j < nbPts; j++) {
+        switch (GEntityType) {
+        case 0:
+          break;
+        case 1:
+          fscanf(in, "%le", &u);
+          break;
+        case 2:
+          fscanf(in, "%le %le %d", &u, &v, &patch);
+          break;
+        case 3:
+          break;
+        }
+      }
+
+      Simplex *s = Create_Simplex(v1, v2, v3, v4);
+      s->Num = i + 1;
+      s->iEnt = GEntityId + 10000;
+
+      Surface *surf;
+      List_Add(AllFaces, &s);
 
-void Read_Mesh_SMS(Mesh * m, FILE * fp);
+      switch (GEntityType) {
+      case ENTITY_REGION:
+        break;
+      case ENTITY_FACE:
+        if(!(surf = FindSurface(GEntityId + 10000, m))) {
+          surf = Create_Surface(GEntityId + 10000, MSH_SURF_DISCRETE);
+          surf->Dirty = 1;
+          if(!NbRegions)
+            List_Add(vol->Surfaces, &surf);
+          Tree_Add(m->Surfaces, &surf);
+        }
+        Tree_Add(surf->Vertices, &s->V[0]);
+        Tree_Add(surf->Vertices, &s->V[1]);
+        Tree_Add(surf->Vertices, &s->V[2]);
+        Tree_Add(surf->Simplexes, &s);
+      }
+    }
+  }
+
+  Msg(INFO, "%d region", NbRegions);
+
+  for(int i = 0; i < NbRegions; i++) {
+    fscanf(in, "%d", &GEntityId);
+    if(GEntityId) {
+      fscanf(in, "%d", &NbFacesOnRegion);
+      Simplex *myS1, *myS2;
+      if(NbFacesOnRegion == 4) {
+        fscanf(in, "%d %d %d %d %d", &Face1, &Face2, &Face3, &Face4, &Dummy);
+        List_Read(AllFaces, abs(Face1) - 1, &myS1);
+        List_Read(AllFaces, abs(Face2) - 1, &myS2);
+        v1 = myS1->V[0];
+        v2 = myS1->V[1];
+        v3 = myS1->V[2];
+        for(int hh = 0; hh < 3; hh++)
+          if(compareVertex(&v1, &myS2->V[hh]) &&
+             compareVertex(&v2, &myS2->V[hh]) &&
+             compareVertex(&v3, &myS2->V[hh]))
+            v4 = myS2->V[hh];
+      }
+      if(!v1 || !v2 || !v3 || !v4) {
+        Msg(GERROR, "%d\n", NbFacesOnRegion);
+        Msg(GERROR, "%p %p %p %p\n", v1, v2, v3, v4);
+	Msg(GERROR, "%p %p %p \n", myS1->V[0], myS1->V[1], myS1->V[2]);
+        Msg(GERROR, "%p %p %p \n", myS2->V[0], myS2->V[1], myS2->V[2]);
+        return;
+      }
+      Simplex *s = Create_Simplex(v1, v2, v3, v4);
+
+      if(!(vol = FindVolume(GEntityId, m))) {
+        vol = Create_Volume(GEntityId, MSH_VOLUME);
+	vol->Dirty = 1;
+        Tree_Add(m->Volumes, &vol);
+      }
+      s->iEnt = GEntityId;
+      Tree_Insert(vol->Simplexes, &s);
+      Tree_Insert(m->Simplexes, &s);
+    }
+  }
+
+  List_Delete(AllEdges);
+  List_Delete(AllFaces);
+
+  if(Tree_Nbr(m->Volumes)) {
+    m->status = 3;
+  }
+  else if(Tree_Nbr(m->Surfaces)) {
+    m->status = 2;
+  }
+  else if(Tree_Nbr(m->Curves)) {
+    m->status = 1;
+  }
+  else if(Tree_Nbr(m->Points))
+    m->status = 0;
+  else
+    m->status = -1;
+}
+
+// Public Read_Mesh routine
 
 void Read_Mesh(Mesh * M, FILE * fp, char *filename, int type)
 {
@@ -510,12 +811,9 @@ void Read_Mesh(Mesh * M, FILE * fp, char *filename, int type)
     Msg(INFO, "Reading mesh file '%s'", filename);
 
   switch (type) {
-  case FORMAT_MSH:
-    Read_Mesh_MSH(M, fp);
-    break;
-  case FORMAT_SMS:
-    Read_Mesh_SMS(M, fp);
-    break;
+  case FORMAT_MSH: Read_Mesh_MSH(M, fp); break;
+  case FORMAT_SMS: Read_Mesh_SMS(M, fp); break;
+  case FORMAT_VTK: Read_Mesh_VTK(M, fp); break;
   default:
     Msg(GERROR, "Unkown mesh file format");
     return;
diff --git a/Mesh/SMS.cpp b/Mesh/SMS.cpp
deleted file mode 100644
index f0fd3218545e47fbfc418fe961df9c5512d508a5..0000000000000000000000000000000000000000
--- a/Mesh/SMS.cpp
+++ /dev/null
@@ -1,680 +0,0 @@
-// $Id: SMS.cpp,v 1.17 2004-02-07 01:40:22 geuzaine Exp $
-//
-// Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-// USA.
-// 
-// Please report all bugs and problems to <gmsh@geuz.org>.
-
-#include <assert.h>
-#include "Gmsh.h"
-#include "Geo.h"
-#include "Mesh.h"
-#include "Create.h"
-#include "MinMax.h"
-#include "Vertex.h"
-#include "CAD.h"
-#include "Context.h"
-#include "Message.h"
-
-extern Context_T CTX;
-
-#define ENTITY_VERTEX 0
-#define ENTITY_EDGE   1
-#define ENTITY_FACE   2
-#define ENTITY_REGION 3
-#define ENTITY_NONE   4
-
-extern int FACE_DIMENSION;
-
-void TRIE_MON_GARS2(void *a, void *b)
-{
-  Simplex *s = *(Simplex **) a;
-  s->Fourre_Simplexe(s->V[0], s->V[1], s->V[2], s->V[3]);
-}
-
-void Read_VTK_File(char *file, Mesh * m)
-{
-  FILE *in = fopen(file, "r");
-  if(!in)
-    return;
-  char line[256], dumline1[256], dumline2[256];
-  int i;
-  int NbFaces, NbVertices, Vertex1, Vertex2, Vertex3, NbVerticesOnFace;
-  double x, y, z;
-  Vertex *v1, *v2, *v3, *v4;
-
-  fgets(line, 255, in);
-  fgets(line, 255, in);
-  fgets(line, 255, in);
-  fgets(line, 255, in);
-  fgets(line, 255, in);
-  sscanf(line, "%s %d %s", dumline1, &NbVertices, dumline2);
-
-  Surface *surf = Create_Surface(1, MSH_SURF_DISCRETE);
-  surf->Dirty = 1;
-  Tree_Add(m->Surfaces, &surf);
-
-  for(i = 0; i < NbVertices; i++) {
-    fscanf(in, "%le %le %le", &x, &y, &z);
-    Vertex *v = Create_Vertex(i, x, y, z, 1.0, 1.0);
-    Tree_Add(m->Vertices, &v);
-    Tree_Add(surf->Vertices, &v);
-    v->ListSurf = List_Create(1, 1, sizeof(Surface *));
-    List_Add(v->ListSurf, &surf);
-  }
-  fscanf(in, "%s %d %d", dumline1, &NbFaces, &i);
-  for(int i = 0; i < NbFaces; i++) {
-    fscanf(in, "%d", &NbVerticesOnFace);
-    if(NbVerticesOnFace == 3) {
-      fscanf(in, "%d %d %d", &Vertex1, &Vertex2, &Vertex3);
-      v1 = FindVertex(Vertex1, m);
-      v2 = FindVertex(Vertex2, m);
-      v3 = FindVertex(Vertex3, m);
-      v4 = NULL;
-    }
-    else {
-      Msg(GERROR, "No quads in VTK file, man!");
-      return;
-    }
-    Simplex *s = Create_Simplex(v1, v2, v3, v4);
-    s->V[0] = v1;
-    s->V[1] = v2;
-    s->V[2] = v3;
-    s->Num = i;
-    s->iEnt = 1;
-    if((surf = FindSurface(1, m))) {
-    }
-    else {
-      surf = Create_Surface(1, MSH_SURF_DISCRETE);
-      surf->Dirty = 1;
-      Tree_Add(m->Surfaces, &surf);
-    }
-    Tree_Add(surf->Simplexes, &s);
-  }
-  FACE_DIMENSION = 2;
-  Tree_Action(surf->Simplexes, TRIE_MON_GARS2);
-  if(NbFaces)
-    m->status = 2;
-
-  Volume *vol = Create_Volume(1, MSH_VOLUME);
-  vol->Dirty = 1;
-  vol->Surfaces = List_Create(1, 1, sizeof(Surface *));
-  List_Add(vol->Surfaces, &surf);
-  Tree_Add(m->Volumes, &vol);
-
-  fclose(in);
-}
-
-void Read_Mesh_SMS(Mesh * m, FILE * in)
-{
-  char line[1023];
-  int i, patch, nbPts;
-  int NbRegions, NbFaces, NbEdges, NbVertices, NbPoints,
-    GEntityType, GEntityId, EntityNbConnections, Dummy,
-    Edge1, Edge2, Edge3, Edge4, Face1, Face2, Face3, Face4;
-  int VertexId1, VertexId2, NbEdgesOnFace, NbFacesOnRegion;
-  double x, y, z, u, v;
-  List_T *AllEdges, *AllFaces;
-  Vertex *v1 = NULL, *v2 = NULL, *v3 = NULL, *v4 = NULL;
-
-  fscanf(in, "%s %d", line, &Dummy);
-  fscanf(in, "%d %d %d %d %d", &NbRegions, &NbFaces, &NbEdges, &NbVertices,
-         &NbPoints);
-
-  Msg(INFO, "Reading a mesh in scorec format");
-  Msg(INFO, "%d Vertices", NbVertices);
-
-  for(i = 0; i < NbVertices; i++) {
-    fscanf(in, "%d", &GEntityId);
-    if(GEntityId) {
-      fscanf(in, "%d %d %lf %lf %lf", &GEntityType, &EntityNbConnections, &x,
-             &y, &z);
-      Vertex *vert = Create_Vertex(i, x, y, z, 1.0, 1.0);
-      Tree_Add(m->Vertices, &vert);
-      switch (GEntityType) {
-      case 0:
-	{
-	  // we need to make a new one: vertices in m->Vertices and
-	  // m->Points should never point to the same memory location
-	  Vertex *pnt = Create_Vertex(i, x, y, z, 1.0, 1.0);
-	  Tree_Add(m->Points, &pnt);
-	}
-        break;
-      case 1:
-        fscanf(in, "%le", &u);
-        break;
-      case 2:
-        fscanf(in, "%le %le %d", &u, &v, &patch);
-        break;
-      case 3:
-        break;
-      }
-    }
-  }
-
-  Msg(INFO, "%d edges", NbEdges);
-  AllEdges = List_Create(NbEdges, 1, sizeof(Edge));
-  Edge e;
-
-  for(int i = 0; i < NbEdges; i++) {
-    fscanf(in, "%d", &GEntityId);
-
-    if(GEntityId) {
-      fscanf(in, "%d %d %d %d %d", &GEntityType, &VertexId1, &VertexId2,
-             &EntityNbConnections, &nbPts);
-      for(int j = 0; j < nbPts; j++) {
-        switch (GEntityType) {
-        case 0:
-          break;
-        case 1:
-          fscanf(in, "%le", &u);
-          break;
-        case 2:
-          fscanf(in, "%le %le %d", &u, &v, &patch);
-          break;
-        case 3:
-          break;
-        }
-      }
-      e.Points = NULL;
-      Vertex *v1 = FindVertex(VertexId1 - 1, m);
-      Vertex *v2 = FindVertex(VertexId2 - 1, m);
-      e.V[0] = v1;
-      e.V[1] = v2;
-      List_Add(AllEdges, &e);
-      switch (GEntityType) {
-      case ENTITY_EDGE:
-        Simplex * s = Create_Simplex(v1, v2, NULL, NULL);
-        Curve *c;
-        if((c = FindCurve(GEntityId, m))) {
-        }
-        else {
-          c = Create_Curve(GEntityId, MSH_SEGM_DISCRETE, 1, NULL, NULL, -1, -1, 0, 1);
-	  c->Dirty = 1;
-          Tree_Add(m->Curves, &c);
-        }
-        s->iEnt = GEntityId;
-        s->Num = i;
-        Tree_Add(c->Simplexes, &s);
-      }
-    }
-  }
-
-  AllFaces = List_Create(NbFaces, 1, sizeof(Simplex *));
-
-  Volume *vol = Create_Volume(1, MSH_VOLUME);
-  vol->Dirty = 1;
-  vol->Surfaces = List_Create(1, 1, sizeof(Surface *));
-  Tree_Add(m->Volumes, &vol);
-  FACE_DIMENSION = 2;
-
-  Msg(INFO, "%d faces", NbFaces);
-  for(int i = 0; i < NbFaces; i++) {
-    fscanf(in, "%d", &GEntityId);
-    if(GEntityId) {
-      fscanf(in, "%d %d", &GEntityType, &NbEdgesOnFace);
-
-      List_T *Lists[4] = { 0, 0, 0, 0 };
-
-      if(NbEdgesOnFace == 3) {
-        fscanf(in, "%d %d %d %d", &Edge1, &Edge2, &Edge3, &nbPts);
-        List_Read(AllEdges, abs(Edge1) - 1, &e);
-        Lists[0] = e.Points;
-        if(Edge1 > 0)
-          v1 = e.V[0];
-        else
-          v1 = e.V[1];
-        List_Read(AllEdges, abs(Edge2) - 1, &e);
-        Lists[1] = e.Points;
-        if(Edge2 > 0)
-          v2 = e.V[0];
-        else
-          v2 = e.V[1];
-        List_Read(AllEdges, abs(Edge3) - 1, &e);
-        Lists[2] = e.Points;
-        if(Edge3 > 0)
-          v3 = e.V[0];
-        else
-          v3 = e.V[1];
-        v4 = NULL;
-      }
-      else if(NbEdgesOnFace == 4) {
-        fscanf(in, "%d %d %d %d %d", &Edge1, &Edge2, &Edge3, &Edge4, &nbPts);
-        List_Read(AllEdges, abs(Edge1) - 1, &e);
-        if(Edge1 > 0)
-          v1 = e.V[0];
-        else
-          v1 = e.V[1];
-        List_Read(AllEdges, abs(Edge2) - 1, &e);
-        if(Edge2 > 0)
-          v2 = e.V[0];
-        else
-          v2 = e.V[1];
-        List_Read(AllEdges, abs(Edge3) - 1, &e);
-        if(Edge3 > 0)
-          v3 = e.V[0];
-        else
-          v3 = e.V[1];
-        List_Read(AllEdges, abs(Edge4) - 1, &e);
-        if(Edge4 > 0)
-          v4 = e.V[0];
-        else
-          v4 = e.V[1];
-      }
-      else {
-        Msg(GERROR, "Wrong number pf edges on face (%d)", NbEdgesOnFace);
-      }
-      for(int j = 0; j < nbPts; j++) {
-        switch (GEntityType) {
-        case 0:
-          break;
-        case 1:
-          fscanf(in, "%le", &u);
-          break;
-        case 2:
-          fscanf(in, "%le %le %d", &u, &v, &patch);
-          break;
-        case 3:
-          break;
-        }
-      }
-
-      Simplex *s = Create_Simplex(v1, v2, v3, v4);
-      s->Num = i + 1;
-      s->iEnt = GEntityId + 10000;
-      Surface *surf;
-      List_Add(AllFaces, &s);
-
-      switch (GEntityType) {
-      case ENTITY_REGION:
-        break;
-      case ENTITY_FACE:
-        if((surf = FindSurface(GEntityId + 10000, m))) {
-        }
-        else {
-          surf = Create_Surface(GEntityId + 10000, MSH_SURF_DISCRETE);
-          surf->Dirty = 1;
-          if(!NbRegions)
-            List_Add(vol->Surfaces, &surf);
-          Tree_Add(m->Surfaces, &surf);
-        }
-        Tree_Add(surf->Vertices, &s->V[0]);
-        Tree_Add(surf->Vertices, &s->V[1]);
-        Tree_Add(surf->Vertices, &s->V[2]);
-        Tree_Add(surf->Simplexes, &s);
-      }
-    }
-  }
-
-
-  Msg(INFO, "%d region", NbRegions);
-
-  for(int i = 0; i < NbRegions; i++) {
-    fscanf(in, "%d", &GEntityId);
-    if(GEntityId) {
-      fscanf(in, "%d", &NbFacesOnRegion);
-      Simplex *myS1, *myS2;
-      if(NbFacesOnRegion == 4) {
-        fscanf(in, "%d %d %d %d %d", &Face1, &Face2, &Face3, &Face4, &Dummy);
-        List_Read(AllFaces, abs(Face1) - 1, &myS1);
-        List_Read(AllFaces, abs(Face2) - 1, &myS2);
-        v1 = myS1->V[0];
-        v2 = myS1->V[1];
-        v3 = myS1->V[2];
-        for(int hh = 0; hh < 3; hh++)
-          if(compareVertex(&v1, &myS2->V[hh]) &&
-             compareVertex(&v2, &myS2->V[hh]) &&
-             compareVertex(&v3, &myS2->V[hh]))
-            v4 = myS2->V[hh];
-      }
-      if(!v1 || !v2 || !v3 || !v4) {
-        Msg(GERROR, "%d\n", NbFacesOnRegion);
-        Msg(GERROR, "%p %p %p %p\n", v1, v2, v3, v4);
-	Msg(GERROR, "%p %p %p \n", myS1->V[0], myS1->V[1], myS1->V[2]);
-        Msg(GERROR, "%p %p %p \n", myS2->V[0], myS2->V[1], myS2->V[2]);
-        return;
-      }
-      Simplex *s = Create_Simplex(v1, v2, v3, v4);
-
-      if((vol = FindVolume(GEntityId, m))) {
-      }
-      else {
-        vol = Create_Volume(GEntityId, MSH_VOLUME);
-	vol->Dirty = 1;
-        Tree_Add(m->Volumes, &vol);
-      }
-      s->iEnt = GEntityId;
-      Tree_Insert(vol->Simplexes, &s);
-      Tree_Insert(m->Simplexes, &s);
-    }
-  }
-
-  List_Delete(AllEdges);
-  List_Delete(AllFaces);
-
-  if(Tree_Nbr(m->Volumes)) {
-    m->status = 3;
-  }
-  else if(Tree_Nbr(m->Surfaces)) {
-    m->status = 2;
-  }
-  else if(Tree_Nbr(m->Curves)) {
-    m->status = 1;
-  }
-  else if(Tree_Nbr(m->Points))
-    m->status = 0;
-  else
-    m->status = -1;
-}
-
-#if 0
-
-void Write_SMS_FILE(Mesh * m, char *filename)
-{
-  FILE *f = fopen(filename, "w");
-  // write first the global infos 
-  int i, j;
-  // Edge e;
-
-  List_T *l;
-  List_T *AllFaces = List_Create(100, 100, sizeof(Simplex *));
-  Surface *surf;
-  Simplex *s;
-  Vertex *v;
-  Curve *c;
-
-  l = Tree2List(m->Surfaces);
-  EdgesContainer AllEdges(l);
-
-  for(i = 0; i < List_Nbr(l); i++) {
-    List_Read(l, i, &surf);
-    List_T *all = Tree2List(surf->Simplexes);
-    for(j = 0; j < List_Nbr(all); j++)
-      List_Add(AllFaces, List_Pointer(all, j));
-    List_Delete(all);
-  }
-  List_Delete(l);
-
-  fprintf(f, "gmsh 2\n");
-  fprintf(f, "0 %d %d %d %d\n", List_Nbr(AllFaces)
-          , Tree_Nbr(AllEdges.AllEdges)
-          , Tree_Nbr(m->Vertices)
-          , Tree_Nbr(m->Vertices));
-
-
-
-  l = Tree2List(m->Vertices);
-  int MaxFrozen;
-  for(i = 0; i < List_Nbr(l); i++) {
-    List_Read(l, i, &v);
-    MaxFrozen = (MaxFrozen >= v->Frozen) ? MaxFrozen : v->Frozen;
-  }
-
-  for(i = 0; i < List_Nbr(l); i++) {
-    List_Read(l, i, &v);
-    int mtype =
-      ((v->
-        ListCurves) ? ((List_Nbr(v->ListCurves) ==
-                        1) ? ENTITY_EDGE : ENTITY_VERTEX) : ENTITY_FACE);
-    int gent;
-    switch (mtype) {
-    case ENTITY_VERTEX:
-      gent = i + 1;
-      break;
-    case ENTITY_EDGE:
-      List_Read(v->ListCurves, 0, &c);
-      gent = c->ipar[3] + 1;
-      break;
-    case ENTITY_FACE:
-      List_Read(v->ListSurf, 0, &surf);
-      gent = surf->ipar[3] + 1;
-      break;
-    }
-    v->Frozen = i + 1;
-    int nn = 7;                 // arbitrary 
-    fprintf(f, "%d %d %d\n", gent, mtype, nn);
-    switch (mtype) {
-    case ENTITY_VERTEX:
-      fprintf(f, "%12.5E %12.5E %12.5E\n", v->Pos.X, v->Pos.Y, v->Pos.Z);
-      break;
-    case ENTITY_EDGE:
-      fprintf(f, "%12.5E %12.5E %12.5E 0 \n", v->Pos.X, v->Pos.Y, v->Pos.Z);
-      break;
-    case ENTITY_FACE:
-      fprintf(f, "%12.5E %12.5E %12.5E 0 0 1\n", v->Pos.X, v->Pos.Y,
-              v->Pos.Z);
-      break;
-    }
-  }
-
-  printf("%d edges\n", Tree_Nbr(AllEdges.AllEdges));
-  l = Tree2List(m->Curves);
-  for(i = 0; i < List_Nbr(l); i++) {
-    List_Read(l, i, &c);
-    AllEdges.AddTree(c->Simplexes, false);
-    // if(c->Num > 0 && c->Typ != MSH_SEGM_LINE) AllEdges.AddPoints(c,DEGRE2-1);
-  }
-  List_Delete(l);
-  printf("%d edges\n", Tree_Nbr(AllEdges.AllEdges));
-
-
-  l = Tree2List(AllEdges.AllEdges);
-  int compareEdgeNum(const void *a, const void *b);
-
-  List_Sort(l, compareEdgeNum);
-
-  for(i = 0; i < List_Nbr(l); i++) {
-    int mtype = ENTITY_FACE;
-    Edge *pe = (Edge *) List_Pointer(l, i);
-    int nn = 0, gent;
-    for(j = 0; j < List_Nbr(pe->Simplexes); j++) {
-      List_Read(pe->Simplexes, j, &s);
-      if(!s->V[2]) {
-        mtype = ENTITY_EDGE;
-        gent = s->iEnt;
-      }
-      if(mtype == ENTITY_FACE) {
-        nn++;
-        gent = s->iEnt;
-      }
-    }
-    if(!pe->Points)
-      fprintf(f, "%d %d %d %d %d 0\n", gent, mtype, pe->V[0]->Frozen,
-              pe->V[1]->Frozen, nn);
-    else {
-      fprintf(f, "%d %d %d %d %d %d\n", gent, mtype, pe->V[0]->Frozen,
-              pe->V[1]->Frozen, nn, List_Nbr(pe->Points));
-      for(int k = 0; k < List_Nbr(pe->Points); k++) {
-        Coord cr;
-        List_Read(pe->Points, k, &cr);
-        fprintf(f, "%12.5E %12.5E %12.5E %12.5E ", cr.X, cr.Y, cr.Z, 0.0);
-      }
-      fprintf(f, "\n");
-    }
-  }
-
-  Edge *ed[4];
-  int ori[4];
-  int *edids = new int[List_Nbr(l) + 1];
-  for(i = 0; i < List_Nbr(l) + 1; i++)
-    edids[i] = 0;
-  List_Delete(l);
-  for(i = 0; i < List_Nbr(AllFaces); i++) {
-    List_Read(AllFaces, i, &s);
-    AllEdges.GetEdges(s, false, ed, ori);
-    if(!ed[3]) {
-      for(int k = 0; k < 3; k++) {
-        if(edids[ed[k]->Num] == ori[k]) {
-          Simplex *s1, *s2;
-          List_Read(ed[k]->Simplexes, 0, &s1);
-          List_Read(ed[k]->Simplexes, 1, &s2);
-          printf("Edge %d %d\n", ed[k]->V[0]->Num, ed[k]->V[1]->Num);
-          printf("s1 = %d %d %d\n", s1->V[0]->Num, s1->V[1]->Num,
-                 s1->V[2]->Num);
-          printf("s2 = %d %d %d\n", s2->V[0]->Num, s2->V[1]->Num,
-                 s2->V[2]->Num);
-        }
-        else {
-          edids[ed[k]->Num] = ori[k];
-        }
-      }
-
-      fprintf(f, "%d %d 3 %d %d %d 0\n", s->iEnt, ENTITY_FACE,
-              ori[0] * ed[0]->Num, ori[1] * ed[1]->Num, ori[2] * ed[2]->Num);
-    }
-    else
-      fprintf(f, "%d %d 4 %d %d %d %d 0\n", s->iEnt, ENTITY_FACE,
-              ori[0] * ed[0]->Num, ori[1] * ed[1]->Num, ori[2] * ed[2]->Num,
-              ori[3] * ed[3]->Num);
-  }
-  delete edids;
-  List_Delete(AllFaces);
-  fclose(f);
-
-}
-
-#endif
-
-int isTopologic(Vertex * v, List_T * curves)
-{
-  Curve *c;
-  for(int i = 0; i < List_Nbr(curves); i++) {
-    List_Read(curves, i, &c);
-    if(!compareVertex(&v, &c->beg))
-      return 1;
-  }
-  return 0;
-}
-
-void Write_DMG_FILE(Mesh * m, char *filename)
-{
-  FILE *f = fopen(filename, "w");
-  int i, j;
-  List_T *ll, *l;
-  Vertex *v;
-  Curve *c;
-  Surface *s;
-  //Volume *vol;
-  int k;
-
-  l = Tree2List(m->Points);
-  ll = Tree2List(m->Curves);
-
-  k = 0;
-  for(i = 0; i < List_Nbr(l); i++) {
-    List_Read(l, i, &v);
-    if(isTopologic(v, ll)) {
-      k++;
-    }
-  }
-
-  // write first the global infos 
-
-  fprintf(f, "%d %d %d %d \n", Tree_Nbr(m->Volumes)
-          , Tree_Nbr(m->Surfaces)
-          , Tree_Nbr(m->Curves) / 2     // the 2 is for the reverse curves
-          , k);
-
-  // then write the bounding box
-
-  m->Grid.min.X = CTX.min[0];
-  m->Grid.min.Y = CTX.min[1];
-  m->Grid.min.Z = CTX.min[2];
-  m->Grid.max.X = CTX.max[0];
-  m->Grid.max.Y = CTX.max[1];
-  m->Grid.max.Z = CTX.max[2];
-
-  fprintf(f, "%12.5E %12.5E %12.5E \n", m->Grid.min.X, m->Grid.min.Y,
-          m->Grid.min.Z);
-  fprintf(f, "%12.5E %12.5E %12.5E \n", m->Grid.max.X, m->Grid.max.Y,
-          m->Grid.max.Z);
-
-  // write the points
-  k = 0;
-  for(i = 0; i < List_Nbr(l); i++) {
-    List_Read(l, i, &v);
-    if(isTopologic(v, ll)) {
-      v->Frozen = k++;
-      fprintf(f, "%d %12.5E %12.5E %12.5E \n", v->Frozen, v->Pos.X, v->Pos.Y,
-              v->Pos.Z);
-    }
-  }
-  List_Delete(l);
-  // write the curves
-  l = ll;
-  k = 0;
-  for(i = 0; i < List_Nbr(l); i++) {
-    List_Read(l, i, &c);
-    if(c->Num > 0) {
-      c->ipar[3] = k;
-      Curve *cinv = FindCurve(-c->Num, m);
-      cinv->ipar[3] = k++;
-      fprintf(f, "%d %d %d \n", c->ipar[3], c->beg->Frozen, c->end->Frozen);
-    }
-  }
-
-  List_Delete(l);
-
-  // write the surfaces
-  l = Tree2List(m->Surfaces);
-
-  for(i = 0; i < List_Nbr(l); i++) {
-    List_Read(l, i, &s);
-
-    int numEdgeLoop[2000], iLoop = 0;
-    Vertex *beg = NULL;
-    numEdgeLoop[iLoop] = 0;
-    int deb = 1;
-    for(j = 0; j < List_Nbr(s->Generatrices); j++) {
-      List_Read(s->Generatrices, j, &c);
-      if(deb) {
-        beg = c->beg;
-        deb = 0;
-      }
-      Msg(INFO, "beg->%d end->%d", c->beg->Num, c->end->Num);
-      (numEdgeLoop[iLoop])++;
-      if(c->end == beg) {
-        iLoop++;
-        numEdgeLoop[iLoop] = 0;
-        deb = 1;
-      }
-    }
-    s->ipar[3] = i;
-    fprintf(f, "%d %d\n", i, iLoop);
-    fprintf(stdout, "%d %d\n", i, iLoop);
-    int iEdge = 0;
-    for(k = 0; k < iLoop; k++) {
-      fprintf(f, "%d ", numEdgeLoop[k]);
-      fprintf(stdout, "%d ", numEdgeLoop[k]);
-      for(j = 0; j < numEdgeLoop[k]; j++) {
-        List_Read(s->Generatrices, iEdge++, &c);
-        fprintf(f, "%d %d ", abs(c->ipar[3]), (c->Num > 0) ? 1 : -1);
-        fprintf(stdout, "%d %d ", abs(c->ipar[3]), (c->Num > 0) ? 1 : -1);
-      }
-      fprintf(f, "\n");
-      fprintf(stdout, "\n");
-    }
-  }
-  List_Delete(l);
-
-  // write the volumes (2 b continued)
-
-  // close the file
-
-  fclose(f);
-
-}
diff --git a/Mesh/SecondOrder.cpp b/Mesh/SecondOrder.cpp
index 2f88c1336768857f671bc29fc295ab86f89408cf..496d8eb23142a92ad8702a949cf287a6ad133f3b 100644
--- a/Mesh/SecondOrder.cpp
+++ b/Mesh/SecondOrder.cpp
@@ -1,4 +1,4 @@
-// $Id: SecondOrder.cpp,v 1.22 2004-04-19 00:18:07 geuzaine Exp $
+// $Id: SecondOrder.cpp,v 1.23 2004-05-25 04:10:05 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -26,18 +26,15 @@
 #include "Interpolation.h"
 #include "Numeric.h"
 
-// FIXME: still todo
-// - middle edge nodes for hexas, prisms and pyramids
-// - middle face nodes for quads, hexas, prisms and pyramids
-
-// we really need to remove the quads from the simplex tree: it's a
-// real mess right now -> add a Quad tree in Surface (like the
-// Hax/Prism/Pyramid tree in Volume); generalize Edge in terms of
-// Element, and dynamic cast to Simplex, Quandrangle, Hexahdra, etc.
+// FIXME: still to add middle face nodes for quads, hexas, prisms and
+// pyramids
 
 extern Mesh *THEM;
 extern int edges_tetra[6][2];
 extern int edges_quad[4][2];
+extern int edges_hexa[12][2];
+extern int edges_prism[9][2];
+extern int edges_pyramid[8][2];
 
 static Surface *THES = NULL;
 static Curve *THEC = NULL;
@@ -125,10 +122,8 @@ Vertex *onsurface(Vertex * v1, Vertex * v2)
 void PutMiddlePoint(void *a, void *b)
 {
   Edge *ed;
-  Simplex *s;
   Vertex *v;
-  int i, j, k, N;
-  int edges[6][2];
+  int i, j, N;
 
   ed = (Edge *) a;
 
@@ -151,51 +146,88 @@ void PutMiddlePoint(void *a, void *b)
 
   ed->newv = v;
   Tree_Insert(THEM->Vertices, &v);
-
+      
   for(i = 0; i < List_Nbr(ed->Simplexes); i++) {
+    Simplex *s;
     List_Read(ed->Simplexes, i, &s);
-    if(s->V[3] && !THES) { // tetrahedron
-      if(!s->VSUP)
-        s->VSUP = (Vertex **) Malloc(6 * sizeof(Vertex *));
+    if(s->V[3]) // tetrahedron
       N = 6;
-      for(k = 0; k < N; k++)
-        for(j = 0; j < 2; j++)
-          edges[k][j] = edges_tetra[k][j];
+    else if(s->V[2]) // triangle
+      N = 3;
+    else // line
+      N = 1;
+    if(!s->VSUP)
+      s->VSUP = (Vertex **) Malloc(N * sizeof(Vertex *));
+    for(j = 0; j < N; j++) {
+      if((!compareVertex(&s->V[edges_tetra[j][0]], &ed->V[0]) &&
+	  !compareVertex(&s->V[edges_tetra[j][1]], &ed->V[1])) ||
+	 (!compareVertex(&s->V[edges_tetra[j][0]], &ed->V[1]) &&
+	  !compareVertex(&s->V[edges_tetra[j][1]], &ed->V[0]))) {
+	s->VSUP[j] = v;
+      }
     }
-    else if(s->V[3]) { // quadrangle
-      if(!s->VSUP)
-        s->VSUP = (Vertex **) Malloc(4 * sizeof(Vertex *));
-      N = 4;
-      for(k = 0; k < N; k++)
-        for(j = 0; j < 2; j++)
-          edges[k][j] = edges_quad[k][j];
+  }
+
+  for(i = 0; i < List_Nbr(ed->Quadrangles); i++) {
+    Quadrangle *q;
+    List_Read(ed->Quadrangles, i, &q);
+    if(!q->VSUP)
+      q->VSUP = (Vertex **) Malloc(4 * sizeof(Vertex *));
+    for(j = 0; j < 4; j++) {
+      if((!compareVertex(&q->V[edges_quad[j][0]], &ed->V[0]) &&
+          !compareVertex(&q->V[edges_quad[j][1]], &ed->V[1])) ||
+         (!compareVertex(&q->V[edges_quad[j][0]], &ed->V[1]) &&
+          !compareVertex(&q->V[edges_quad[j][1]], &ed->V[0]))) {
+        q->VSUP[j] = v;
+      }
     }
-    else if(s->V[2]) { // triangle
-      if(!s->VSUP)
-        s->VSUP = (Vertex **) Malloc(3 * sizeof(Vertex *));
-      N = 3;
-      for(k = 0; k < N; k++)
-        for(j = 0; j < 2; j++)
-          edges[k][j] = edges_tetra[k][j];
+  }
+
+  for(i = 0; i < List_Nbr(ed->Hexahedra); i++) {
+    Hexahedron *h;
+    List_Read(ed->Hexahedra, i, &h);
+    if(!h->VSUP)
+      h->VSUP = (Vertex **) Malloc(12 * sizeof(Vertex *));
+    for(j = 0; j < 12; j++) {
+      if((!compareVertex(&h->V[edges_hexa[j][0]], &ed->V[0]) &&
+          !compareVertex(&h->V[edges_hexa[j][1]], &ed->V[1])) ||
+         (!compareVertex(&h->V[edges_hexa[j][0]], &ed->V[1]) &&
+          !compareVertex(&h->V[edges_hexa[j][1]], &ed->V[0]))) {
+        h->VSUP[j] = v;
+      }
     }
-    else { // line
-      if(!s->VSUP)
-        s->VSUP = (Vertex **) Malloc(sizeof(Vertex *));
-      N = 1;
-      for(k = 0; k < N; k++)
-        for(j = 0; j < 2; j++)
-          edges[k][j] = edges_tetra[k][j];
+  }
+
+  for(i = 0; i < List_Nbr(ed->Prisms); i++) {
+    Prism *p;
+    List_Read(ed->Prisms, i, &p);
+    if(!p->VSUP)
+      p->VSUP = (Vertex **) Malloc(9 * sizeof(Vertex *));
+    for(j = 0; j < 9; j++) {
+      if((!compareVertex(&p->V[edges_prism[j][0]], &ed->V[0]) &&
+          !compareVertex(&p->V[edges_prism[j][1]], &ed->V[1])) ||
+         (!compareVertex(&p->V[edges_prism[j][0]], &ed->V[1]) &&
+          !compareVertex(&p->V[edges_prism[j][1]], &ed->V[0]))) {
+        p->VSUP[j] = v;
+      }
     }
+  }
 
-    for(j = 0; j < N; j++) {
-      if((!compareVertex(&s->V[edges[j][0]], &ed->V[0]) &&
-          !compareVertex(&s->V[edges[j][1]], &ed->V[1])) ||
-         (!compareVertex(&s->V[edges[j][0]], &ed->V[1]) &&
-          !compareVertex(&s->V[edges[j][1]], &ed->V[0]))) {
-        s->VSUP[j] = v;
+  for(i = 0; i < List_Nbr(ed->Pyramids); i++) {
+    Pyramid *p;
+    List_Read(ed->Pyramids, i, &p);
+    if(!p->VSUP)
+      p->VSUP = (Vertex **) Malloc(8 * sizeof(Vertex *));
+    for(j = 0; j < 8; j++) {
+      if((!compareVertex(&p->V[edges_pyramid[j][0]], &ed->V[0]) &&
+          !compareVertex(&p->V[edges_pyramid[j][1]], &ed->V[1])) ||
+         (!compareVertex(&p->V[edges_pyramid[j][0]], &ed->V[1]) &&
+          !compareVertex(&p->V[edges_pyramid[j][1]], &ed->V[0]))) {
+        p->VSUP[j] = v;
       }
     }
   }
+
 }
 
 void ResetDegre2_Vertex(void *a, void *b)
@@ -212,6 +244,34 @@ void ResetDegre2_Simplex(void *a, void *b)
   s->VSUP = NULL;
 }
 
+void ResetDegre2_Quadrangle(void *a, void *b)
+{
+  Quadrangle *q = *(Quadrangle**)a;
+  Free(q->VSUP);  
+  q->VSUP = NULL;
+}
+
+void ResetDegre2_Hexahedron(void *a, void *b)
+{
+  Hexahedron *h = *(Hexahedron**)a;
+  Free(h->VSUP);  
+  h->VSUP = NULL;
+}
+
+void ResetDegre2_Prism(void *a, void *b)
+{
+  Prism *p = *(Prism**)a;
+  Free(p->VSUP);  
+  p->VSUP = NULL;
+}
+
+void ResetDegre2_Pyramid(void *a, void *b)
+{
+  Pyramid *p = *(Pyramid**)a;
+  Free(p->VSUP);  
+  p->VSUP = NULL;
+}
+
 void ResetDegre2_Curve(void *a, void *b)
 {
   Curve *c = *(Curve**)a;
@@ -224,6 +284,7 @@ void ResetDegre2_Surface(void *a, void *b)
   Surface *s = *(Surface**)a;
   if(s->Dirty) return;
   Tree_Action(s->Simplexes, ResetDegre2_Simplex);
+  Tree_Action(s->Quadrangles, ResetDegre2_Quadrangle);
 }
 
 void ResetDegre2_Volume(void *a, void *b)
@@ -231,6 +292,9 @@ void ResetDegre2_Volume(void *a, void *b)
   Volume *v = *(Volume**)a;
   if(v->Dirty) return;
   Tree_Action(v->Simplexes, ResetDegre2_Simplex);
+  Tree_Action(v->Hexahedra, ResetDegre2_Hexahedron);
+  Tree_Action(v->Prisms, ResetDegre2_Prism);
+  Tree_Action(v->Pyramids, ResetDegre2_Pyramid);
 }
 
 void Degre1()
@@ -255,15 +319,13 @@ void Degre1()
     Tree_Suppress(THEM->Vertices, v);
     Free_Vertex(v, NULL);
   }
-
-  THEM->Statistics[16] = 0;
 }
 
 void Degre2_Curve(void *a, void *b)
 {
   Curve *c = *(Curve**)a;
   if(c->Dirty) return;
-  edges->AddTree(c->Simplexes, false);
+  edges->AddSimplexTree(c->Simplexes);
   THEC = c;
   THES = NULL;
   Tree_Action(edges->AllEdges, PutMiddlePoint);
@@ -273,7 +335,8 @@ void Degre2_Surface(void *a, void *b)
 {
   Surface *s = *(Surface**)a;
   if(s->Dirty) return;
-  edges->AddTree(s->Simplexes, false);
+  edges->AddSimplexTree(s->Simplexes);
+  edges->AddQuadrangleTree(s->Quadrangles);
   THEC = NULL;
   THES = s;
   Tree_Action(edges->AllEdges, PutMiddlePoint);
@@ -284,14 +347,10 @@ void Degre2_Volume(void *a, void *b)
   Volume *v = *(Volume**)a;
   if(v->Dirty) return;
 
-  // FIXME: warn if we have unhandled elements
-  if(Tree_Nbr(v->Hexahedra) || Tree_Nbr(v->Prisms) || Tree_Nbr(v->Pyramids) ||
-     THEM->Statistics[8]){
-    Msg(GERROR, "Second order hexahedra, prisms and pyramids not supported yet");
-    return;
-  }
-
-  edges->AddTree(v->Simplexes, true);
+  edges->AddSimplexTree(v->Simplexes);
+  edges->AddHexahedronTree(v->Hexahedra);
+  edges->AddPrismTree(v->Prisms);
+  edges->AddPyramidTree(v->Pyramids);
   THEC = NULL;
   THES = NULL;
   Tree_Action(edges->AllEdges, PutMiddlePoint);
@@ -303,7 +362,6 @@ void Degre2(int dim)
   double t1 = Cpu();
 
   Degre1();
-  int nb1 = Tree_Nbr(THEM->Vertices);
 
   if(dim >= 1)
     Tree_Action(THEM->Curves, Degre2_Curve);
@@ -312,9 +370,6 @@ void Degre2(int dim)
   if(dim >= 3)
     Tree_Action(THEM->Volumes, Degre2_Volume);
 
-  int nb2 = Tree_Nbr(THEM->Vertices);
-  THEM->Statistics[16] = nb2 - nb1;
-
   double t2 = Cpu();
   Msg(STATUS2, "Mesh second order complete (%g s)", t2 - t1);
 }
diff --git a/Mesh/Simplex.cpp b/Mesh/Simplex.cpp
index 2e9e9567d0a30d8746eae37634bf71cff9abc7cf..f31ce24382d516ed2cca6ef29048903d31ec4af5 100644
--- a/Mesh/Simplex.cpp
+++ b/Mesh/Simplex.cpp
@@ -1,4 +1,4 @@
-// $Id: Simplex.cpp,v 1.31 2004-05-13 00:50:40 geuzaine Exp $
+// $Id: Simplex.cpp,v 1.32 2004-05-25 04:10:05 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -29,37 +29,29 @@
 extern Context_T CTX;
 extern Mesh *THEM, *LOCAL;
 
-int Simplex::TotalAllocated = 0;
-int Simplex::TotalNumber = 0;
-
 extern Simplex MyNewBoundary;
 
 int FACE_DIMENSION = 2;
 
 Simplex::Simplex()
 {
-  TotalAllocated++;
-  TotalNumber++;
   VSUP = NULL;
   V[0] = V[1] = V[2] = V[3] = NULL;
   S[0] = S[1] = S[2] = S[3] = NULL;
   iEnt = -1;
   iPart = -1;
   Quality = 0.;
-  Num = TotalNumber;
+  Num = ++TotalNumber;
   Visible = VIS_MESH;
 }
 
 Simplex::Simplex(Vertex * v1, Vertex * v2, Vertex * v3, Vertex * v4)
 {
-  TotalAllocated++;
-  TotalNumber++;
   VSUP = NULL;
   S[0] = S[1] = S[2] = S[3] = NULL;
   Quality = 0.;
   Fourre_Simplexe(v1, v2, v3, v4);
-  Num = TotalNumber;
-  THEM->MaxSimplexNum = IMAX(THEM->MaxSimplexNum, Num);
+  Num = ++TotalNumber;
   iEnt = -1;
   iPart = -1;
   Visible = VIS_MESH;
@@ -67,7 +59,7 @@ Simplex::Simplex(Vertex * v1, Vertex * v2, Vertex * v3, Vertex * v4)
 
 Simplex::~Simplex()
 {
-  TotalAllocated--;
+  if(VSUP) Free(VSUP);
 }
 
 int Simplex::CircumCircle(double x1, double y1,
@@ -162,7 +154,8 @@ double Simplex::Volume_Simplexe2D()
 {
   return ((V[1]->Pos.X - V[0]->Pos.X) *
           (V[2]->Pos.Y - V[1]->Pos.Y) -
-          (V[2]->Pos.X - V[1]->Pos.X) * (V[1]->Pos.Y - V[0]->Pos.Y));
+          (V[2]->Pos.X - V[1]->Pos.X) * 
+	  (V[1]->Pos.Y - V[0]->Pos.Y));
 }
 
 void Simplex::center_tet(double X[4], double Y[4], double Z[4], double res[3])
@@ -256,8 +249,7 @@ double Simplex::EtaShapeMeasure()
       lij2 += DSQR(lij(i, j));
     }
   }
-  return 12. * pow(9. / 10. * DSQR(fabs(Volume_Simplexe())),
-                   1. / 3.) / (lij2);
+  return 12. * pow(9. / 10. * DSQR(fabs(Volume_Simplexe())), 1./3.) / (lij2);
 }
 
 double Simplex::RhoShapeMeasure()
@@ -382,29 +374,11 @@ void Free_Simplex(void *a, void *b)
   }
 }
 
-// to avoid the renumbering of the nodes and all the 'Fourre_Simplex' stuff
-Simplex *Create_Quadrangle(Vertex * v1, Vertex * v2, Vertex * v3, Vertex * v4)
-{
-  Simplex *s;
-  s = new Simplex();
-  s->V[0] = v1;
-  s->V[1] = v2;
-  s->V[2] = v3;
-  s->V[3] = v4;
-  return s;
-}
-
 int compareSimplex(const void *a, const void *b)
 {
-  Simplex **q, **w;
-
-  /* Les simplexes sont definis une seule fois :
-     1 pointeur par entite -> on compare les pointeurs */
-
-  q = (Simplex **) a;
-  w = (Simplex **) b;
-  //if((*q)->iEnt != (*w)->iEnt) return (*q)->iEnt - (*w)->iEnt;
-  return ((*q)->Num - (*w)->Num);
+  Simplex *q = *(Simplex **) a;
+  Simplex *w = *(Simplex **) b;
+  return (q->Num - w->Num);
 }
 
 int Simplex::Pt_In_Simplexe(Vertex * v, double uvw[3], double tol)
@@ -589,7 +563,7 @@ int Simplex::Pt_In_Simplex_2D(Vertex * v)
   return 1;
 }
 
-void Simplex::ExportLcField(FILE * f, int dim)
+void Simplex::ExportLcField(FILE * f)
 {
   if(!V[2])
     fprintf(f, "SL(%f,%f,%f,%f,%f,%f){%12.5E,%12.5E};\n",
@@ -601,9 +575,7 @@ void Simplex::ExportLcField(FILE * f, int dim)
             V[1]->Pos.Z, V[2]->Pos.X, V[2]->Pos.Y, V[2]->Pos.Z, V[0]->lc,
             V[1]->lc, V[2]->lc);
   else
-    fprintf(f,
-	    "%s(%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f){%12.5E,%12.5E,%12.5E,%12.5E};\n",
-	    (dim == 3) ? "SS" : "SQ",
+    fprintf(f, "SS(%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f){%12.5E,%12.5E,%12.5E,%12.5E};\n",
 	    V[0]->Pos.X, V[0]->Pos.Y, V[0]->Pos.Z, V[1]->Pos.X, V[1]->Pos.Y,
 	    V[1]->Pos.Z, V[2]->Pos.X, V[2]->Pos.Y, V[2]->Pos.Z, V[3]->Pos.X,
 	    V[3]->Pos.Y, V[3]->Pos.Z, V[0]->lc, V[1]->lc, V[2]->lc, V[3]->lc);
@@ -791,8 +763,7 @@ bool Simplex::SwapFace(int iFac, List_T * newsimp, List_T * delsimp)
   s3 = Create_Simplex(s->F[iFac].V[2], s->F[iFac].V[0], o[0], o[1]);
 
   double vol1 = s->Volume_Simplexe() + Volume_Simplexe();
-  double vol2 =
-    s1->Volume_Simplexe() + s2->Volume_Simplexe() + s3->Volume_Simplexe();
+  double vol2 = s1->Volume_Simplexe() + s2->Volume_Simplexe() + s3->Volume_Simplexe();
 
   if(fabs(fabs(vol1) - fabs(vol2)) > 1.e-5 * (fabs(vol1) + fabs(vol2))) {
     delete s1;
@@ -804,7 +775,8 @@ bool Simplex::SwapFace(int iFac, List_T * newsimp, List_T * delsimp)
   double gamma1 = GammaShapeMeasure();
 
   if(s1->GammaShapeMeasure() < gamma1 ||
-     s2->GammaShapeMeasure() < gamma1 || s3->GammaShapeMeasure() < gamma1)
+     s2->GammaShapeMeasure() < gamma1 || 
+     s3->GammaShapeMeasure() < gamma1)
     return false;
 
   return true;
@@ -812,14 +784,11 @@ bool Simplex::SwapFace(int iFac, List_T * newsimp, List_T * delsimp)
 
 int compareFace(const void *a, const void *b)
 {
-  Face *q, *w;
-
-  q = (Face *) a;
-  w = (Face *) b;
+  Face *q = (Face *) a;
+  Face *w = (Face *) b;
 
   if(!q->V[0] || !w->V[0])
-    Msg(FATAL,
-        "Bad face (are you trying to generate hexahedra with a Delaunay?!)");
+    Msg(FATAL, "Bad face (are you trying to generate hexahedra with a Delaunay?!)");
 
   if(q->V[0]->Num > w->V[0]->Num)
     return (1);
diff --git a/Mesh/Simplex.h b/Mesh/Simplex.h
index d4b67fa3476c51c287b90ae23337df6b036ea7c1..451c039e0688a7ee19c1bb4b0dbb35ad4d1b5af3 100644
--- a/Mesh/Simplex.h
+++ b/Mesh/Simplex.h
@@ -36,8 +36,6 @@ class Simplex : public Element {
   Coord   Center;        // CC center
   double  Radius;        // CC radius
   Simplex *S[4];         // 4 neighbours
-  static  int TotalNumber;
-  static  int TotalAllocated;
   Simplex();
   ~Simplex();
   Simplex(Vertex *v1, Vertex *v2, Vertex *v3, Vertex *v4);
@@ -60,7 +58,7 @@ class Simplex : public Element {
   bool SwapEdge (int iFac);
   bool SwapFace (int iFac, List_T *newsimp, List_T *delsimp);
   bool ExtractOppositeEdges ( int iFac, Vertex *p[2], Vertex *q[2]);
-  void ExportLcField (FILE *f, int dim=3);
+  void ExportLcField (FILE *f);
   void Center_Ellipsum_3D (double m[3][3]);
   double GammaShapeMeasure ();
   double RhoShapeMeasure ();
@@ -74,7 +72,6 @@ int compareFace (const void *a, const void *b);
 
 Simplex *Create_Simplex (Vertex *v1, Vertex *v2, Vertex *v3, Vertex *v4);
 void Free_Simplex (void *a, void *b);
-Simplex *Create_Quadrangle (Vertex *v1, Vertex *v2, Vertex *v3, Vertex *v4);
 
 
 #endif
diff --git a/Mesh/Smoothing.cpp b/Mesh/Smoothing.cpp
index d693171a4a2b6bdb290ed423505391f8bb44452c..f0a329d5a14d92ad16b3c045967037c6e431fe07 100644
--- a/Mesh/Smoothing.cpp
+++ b/Mesh/Smoothing.cpp
@@ -1,4 +1,4 @@
-// $Id: Smoothing.cpp,v 1.12 2004-02-07 01:40:22 geuzaine Exp $
+// $Id: Smoothing.cpp,v 1.13 2004-05-25 04:10:05 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -81,7 +81,7 @@ void ActionLiss(void *data, void *dummy)
 
   pnxe = (NXE *) data;
 
-  /* On Ne Lisse Point Les Points sur les courbes (quelle horreur) */
+  // On Ne Lisse Point Les Points sur les courbes (quelle horreur)
   if(pnxe->v->ListCurves)
     return;
   nodes = List_Create(2, 2, sizeof(Vertex *));
@@ -93,7 +93,8 @@ void ActionLiss(void *data, void *dummy)
     List_Read(pnxe->Liste, i, &s);
     min_quality_old = DMIN(min_quality_old, s->GammaShapeMeasure());
     volume_before += s->Volume_Simplexe();
-    /* On Ne Lisse Point Les Points sur les surfaces quand les volumes sont mailles */
+    // On Ne Lisse Point Les Points sur les surfaces quand les volumes
+    // sont mailles
     if(s->V[3] && pnxe->v->ListSurf)
       return;
     for(j = 0; j < 4; j++) {
@@ -128,9 +129,9 @@ void ActionLiss(void *data, void *dummy)
     List_Read(pnxe->Liste, i, &s);
     volume_after += s->Volume_Simplexe();
   }
-  if(fabs(volume_after - volume_before) >
-     1.e-8 * fabs(volume_after + volume_before)
-     || min_quality_old > min_quality_new) {
+  if(fabs(volume_after - volume_before) > 1.e-8 * 
+     fabs(volume_after + volume_before) || 
+     min_quality_old > min_quality_new) {
     pnxe->v->Pos.X = xold;
     pnxe->v->Pos.Y = yold;
     pnxe->v->Pos.Z = zold;
@@ -148,19 +149,15 @@ void ActionLissSurf(void *data, void *dummy)
 
   pnxe = (NXE *) data;
 
-  /*
-     On Ne Lisse Point Les Points sur les courbes
-   */
+  // On Ne Lisse Point Les Points sur les courbes
   if(pnxe->v->ListCurves)
     return;
 
   X = Y = Z = Sum = 0.0;
   for(i = 0; i < List_Nbr(pnxe->Liste); i++) {
     List_Read(pnxe->Liste, i, &s);
-    /*
-       On Ne Lisse Point Les Points sur les surfaces quand les
-       volumes sont mailles
-     */
+    // On Ne Lisse Point Les Points sur les surfaces quand les volumes
+    // sont mailles
     for(j = 0; j < 4; j++) {
       if(s->V[j] && compareVertex(&pnxe->v, &s->V[j])) {
         Sum += 0.5;
diff --git a/Parser/Gmsh.tab.cpp b/Parser/Gmsh.tab.cpp
index 5c82549b3d7f229389e2f8cf45a89e09a6368c3a..017b1a8688eef14c7033e2f4dbe6a7203611869f 100644
--- a/Parser/Gmsh.tab.cpp
+++ b/Parser/Gmsh.tab.cpp
@@ -191,7 +191,7 @@
 
 #line 1 "Gmsh.y"
 
-// $Id: Gmsh.tab.cpp,v 1.190 2004-05-22 01:34:57 geuzaine Exp $
+// $Id: Gmsh.tab.cpp,v 1.191 2004-05-25 04:10:05 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -249,6 +249,7 @@ extern Mesh *THEM;
 static Surface *STL_Surf;
 static ExtrudeParams extr;
 static Post_View *View;
+static int ntmp;
 
 #define MAX_RECUR_LOOPS 100
 static int ImbricatedLoop = 0;
@@ -257,7 +258,6 @@ static int yylinenoImbricatedLoopsTab[MAX_RECUR_LOOPS];
 static double LoopControlVariablesTab[MAX_RECUR_LOOPS][3];
 static char *LoopControlVariablesNameTab[MAX_RECUR_LOOPS];
 
-char *strsave (char *ptr);
 void yyerror (char *s);
 void yymsg (int type, char *fmt, ...);
 void skip_until (char *skip, char *until);
@@ -734,44 +734,44 @@ static const short yyrline[] = { 0,
    412,   417,   433,   438,   444,   449,   450,   451,   452,   453,
    454,   455,   456,   457,   458,   459,   460,   461,   462,   463,
    464,   465,   466,   467,   468,   469,   470,   471,   472,   473,
-   474,   477,   480,   484,   490,   496,   499,   503,   509,   515,
-   518,   522,   528,   534,   537,   541,   549,   555,   558,   562,
-   570,   576,   579,   583,   591,   597,   600,   604,   616,   622,
-   625,   629,   641,   647,   650,   654,   666,   672,   675,   679,
-   692,   698,   701,   705,   718,   724,   727,   731,   744,   750,
-   753,   757,   770,   776,   779,   783,   796,   802,   805,   809,
-   822,   828,   831,   835,   858,   864,   867,   871,   894,   900,
-   903,   907,   930,   936,   939,   943,   961,   967,   970,   974,
-   992,   998,  1001,  1005,  1023,  1029,  1032,  1036,  1053,  1059,
-  1062,  1066,  1083,  1089,  1092,  1096,  1113,  1119,  1125,  1132,
-  1140,  1146,  1152,  1159,  1167,  1176,  1178,  1179,  1180,  1181,
-  1184,  1186,  1189,  1221,  1257,  1306,  1322,  1332,  1350,  1363,
-  1379,  1404,  1430,  1443,  1459,  1472,  1488,  1507,  1529,  1538,
-  1552,  1572,  1588,  1607,  1626,  1644,  1662,  1680,  1706,  1724,
-  1743,  1767,  1791,  1817,  1834,  1852,  1871,  1890,  1929,  1954,
-  1976,  1992,  2011,  2030,  2046,  2065,  2082,  2099,  2119,  2125,
-  2130,  2135,  2142,  2144,  2145,  2148,  2153,  2157,  2173,  2189,
-  2205,  2225,  2239,  2249,  2259,  2263,  2272,  2286,  2294,  2299,
-  2310,  2323,  2364,  2378,  2393,  2402,  2411,  2415,  2426,  2442,
-  2456,  2481,  2506,  2533,  2539,  2544,  2549,  2553,  2561,  2575,
-  2586,  2597,  2602,  2613,  2618,  2629,  2634,  2647,  2665,  2683,
-  2701,  2706,  2724,  2729,  2747,  2752,  2773,  2790,  2807,  2824,
-  2829,  2846,  2852,  2869,  2875,  2894,  2898,  2903,  2930,  2954,
-  2962,  2981,  2999,  3017,  3044,  3070,  3096,  3110,  3129,  3134,
-  3143,  3145,  3146,  3147,  3148,  3151,  3153,  3154,  3155,  3156,
-  3157,  3158,  3159,  3160,  3167,  3168,  3169,  3170,  3171,  3172,
-  3173,  3174,  3175,  3176,  3177,  3178,  3179,  3180,  3181,  3182,
-  3183,  3184,  3185,  3186,  3187,  3188,  3189,  3190,  3191,  3192,
-  3193,  3194,  3195,  3196,  3197,  3198,  3200,  3201,  3202,  3203,
-  3204,  3205,  3206,  3207,  3208,  3209,  3210,  3211,  3212,  3213,
-  3214,  3215,  3216,  3217,  3218,  3219,  3220,  3225,  3230,  3231,
-  3232,  3236,  3248,  3267,  3280,  3292,  3314,  3331,  3348,  3365,
-  3384,  3389,  3393,  3397,  3401,  3407,  3412,  3416,  3420,  3426,
-  3430,  3435,  3439,  3444,  3448,  3452,  3458,  3464,  3471,  3477,
-  3481,  3485,  3496,  3503,  3514,  3534,  3544,  3554,  3566,  3582,
-  3600,  3623,  3650,  3656,  3660,  3664,  3676,  3681,  3693,  3699,
-  3719,  3724,  3737,  3743,  3749,  3754,  3762,  3776,  3780,  3799,
-  3815
+   474,   477,   480,   484,   490,   496,   499,   503,   510,   519,
+   522,   526,   533,   542,   545,   549,   558,   567,   570,   574,
+   583,   592,   595,   599,   608,   617,   620,   624,   637,   646,
+   649,   653,   666,   675,   678,   682,   695,   704,   707,   711,
+   725,   734,   737,   741,   755,   764,   767,   771,   785,   794,
+   797,   801,   815,   824,   827,   831,   845,   854,   857,   861,
+   875,   884,   887,   891,   915,   924,   927,   931,   955,   964,
+   967,   971,   995,  1004,  1007,  1011,  1030,  1039,  1042,  1046,
+  1065,  1074,  1077,  1081,  1100,  1109,  1112,  1116,  1134,  1143,
+  1146,  1150,  1168,  1177,  1180,  1184,  1202,  1211,  1217,  1224,
+  1232,  1238,  1244,  1251,  1259,  1268,  1270,  1271,  1272,  1273,
+  1276,  1278,  1281,  1313,  1349,  1398,  1414,  1424,  1442,  1455,
+  1471,  1496,  1522,  1535,  1551,  1564,  1580,  1599,  1621,  1630,
+  1644,  1664,  1680,  1699,  1718,  1736,  1754,  1772,  1798,  1816,
+  1835,  1859,  1883,  1909,  1926,  1944,  1963,  1982,  2021,  2046,
+  2068,  2084,  2103,  2122,  2138,  2157,  2174,  2191,  2211,  2217,
+  2222,  2227,  2234,  2236,  2237,  2240,  2245,  2249,  2265,  2281,
+  2297,  2317,  2331,  2341,  2351,  2355,  2364,  2378,  2386,  2391,
+  2402,  2415,  2456,  2470,  2485,  2494,  2503,  2507,  2518,  2534,
+  2548,  2573,  2598,  2625,  2631,  2636,  2641,  2645,  2653,  2667,
+  2678,  2689,  2694,  2705,  2710,  2721,  2726,  2739,  2757,  2775,
+  2793,  2798,  2816,  2821,  2839,  2844,  2865,  2882,  2899,  2916,
+  2921,  2938,  2944,  2961,  2967,  2986,  2990,  2995,  3022,  3046,
+  3054,  3073,  3091,  3109,  3136,  3162,  3188,  3202,  3221,  3226,
+  3235,  3237,  3238,  3239,  3240,  3243,  3245,  3246,  3247,  3248,
+  3249,  3250,  3251,  3252,  3259,  3260,  3261,  3262,  3263,  3264,
+  3265,  3266,  3267,  3268,  3269,  3270,  3271,  3272,  3273,  3274,
+  3275,  3276,  3277,  3278,  3279,  3280,  3281,  3282,  3283,  3284,
+  3285,  3286,  3287,  3288,  3289,  3290,  3292,  3293,  3294,  3295,
+  3296,  3297,  3298,  3299,  3300,  3301,  3302,  3303,  3304,  3305,
+  3306,  3307,  3308,  3309,  3310,  3311,  3312,  3317,  3322,  3323,
+  3324,  3328,  3340,  3359,  3372,  3384,  3406,  3423,  3440,  3457,
+  3476,  3481,  3485,  3489,  3493,  3499,  3504,  3508,  3512,  3518,
+  3522,  3527,  3531,  3536,  3540,  3544,  3550,  3556,  3563,  3569,
+  3573,  3577,  3588,  3595,  3606,  3626,  3636,  3646,  3658,  3674,
+  3692,  3715,  3742,  3748,  3752,  3756,  3768,  3773,  3785,  3791,
+  3811,  3816,  3829,  3835,  3841,  3846,  3854,  3868,  3872,  3891,
+  3907
 };
 #endif
 
@@ -4994,7 +4994,7 @@ case 104:
 #line 486 "Gmsh.y"
 { 
       List_Add(View->SP, &yyvsp[-5].d); List_Add(View->SP, &yyvsp[-3].d);
-      List_Add(View->SP, &yyvsp[-1].d);
+      List_Add(View->SP, &yyvsp[-1].d);      
     ;
     break;}
 case 105:
@@ -5016,111 +5016,131 @@ case 108:
 { 
       List_Add(View->VP, &yyvsp[-5].d); List_Add(View->VP, &yyvsp[-3].d);
       List_Add(View->VP, &yyvsp[-1].d); 
+      ntmp = List_Nbr(View->VP);
     ;
     break;}
 case 109:
-#line 510 "Gmsh.y"
+#line 511 "Gmsh.y"
 {
+      if((List_Nbr(View->VP) - ntmp) % 3)
+	yymsg(GERROR, "Wrong number of values for vector point "
+	      "(%d is not a multiple of 3)", List_Nbr(View->VP) - ntmp);
       View->NbVP++;
     ;
     break;}
 case 110:
-#line 517 "Gmsh.y"
+#line 521 "Gmsh.y"
 { List_Add(View->TP, &yyvsp[0].d); ;
     break;}
 case 111:
-#line 519 "Gmsh.y"
+#line 523 "Gmsh.y"
 { List_Add(View->TP, &yyvsp[0].d); ;
     break;}
 case 112:
-#line 524 "Gmsh.y"
+#line 528 "Gmsh.y"
 { 
       List_Add(View->TP, &yyvsp[-5].d); List_Add(View->TP, &yyvsp[-3].d);
       List_Add(View->TP, &yyvsp[-1].d);
+      ntmp = List_Nbr(View->TP);
     ;
     break;}
 case 113:
-#line 529 "Gmsh.y"
+#line 534 "Gmsh.y"
 {
+      if((List_Nbr(View->TP) - ntmp) % 9)
+	yymsg(GERROR, "Wrong number of values for tensor point "
+	      "(%d is not a multiple of 9)", List_Nbr(View->TP) - ntmp);
       View->NbTP++;
     ;
     break;}
 case 114:
-#line 536 "Gmsh.y"
+#line 544 "Gmsh.y"
 { List_Add(View->SL, &yyvsp[0].d); ;
     break;}
 case 115:
-#line 538 "Gmsh.y"
+#line 546 "Gmsh.y"
 { List_Add(View->SL, &yyvsp[0].d); ;
     break;}
 case 116:
-#line 544 "Gmsh.y"
+#line 552 "Gmsh.y"
 { 
       List_Add(View->SL, &yyvsp[-11].d); List_Add(View->SL, &yyvsp[-5].d);
       List_Add(View->SL, &yyvsp[-9].d); List_Add(View->SL, &yyvsp[-3].d);
       List_Add(View->SL, &yyvsp[-7].d); List_Add(View->SL, &yyvsp[-1].d);
+      ntmp = List_Nbr(View->SL);
     ;
     break;}
 case 117:
-#line 550 "Gmsh.y"
+#line 559 "Gmsh.y"
 {
+      if((List_Nbr(View->SL) - ntmp) % 2)
+	yymsg(GERROR, "Wrong number of values for scalar line "
+	      "(%d is not a multiple of 2)", List_Nbr(View->SL) - ntmp);
       View->NbSL++;
     ;
     break;}
 case 118:
-#line 557 "Gmsh.y"
+#line 569 "Gmsh.y"
 { List_Add(View->VL, &yyvsp[0].d); ;
     break;}
 case 119:
-#line 559 "Gmsh.y"
+#line 571 "Gmsh.y"
 { List_Add(View->VL, &yyvsp[0].d); ;
     break;}
 case 120:
-#line 565 "Gmsh.y"
+#line 577 "Gmsh.y"
 { 
       List_Add(View->VL, &yyvsp[-11].d); List_Add(View->VL, &yyvsp[-5].d);
       List_Add(View->VL, &yyvsp[-9].d); List_Add(View->VL, &yyvsp[-3].d);
       List_Add(View->VL, &yyvsp[-7].d); List_Add(View->VL, &yyvsp[-1].d);
+      ntmp = List_Nbr(View->VL);
     ;
     break;}
 case 121:
-#line 571 "Gmsh.y"
+#line 584 "Gmsh.y"
 {
+      if((List_Nbr(View->VL) - ntmp) % 6)
+	yymsg(GERROR, "Wrong number of values for vector line "
+	      "(%d is not a multiple of 6)", List_Nbr(View->VL) - ntmp);
       View->NbVL++;
     ;
     break;}
 case 122:
-#line 578 "Gmsh.y"
+#line 594 "Gmsh.y"
 { List_Add(View->TL, &yyvsp[0].d); ;
     break;}
 case 123:
-#line 580 "Gmsh.y"
+#line 596 "Gmsh.y"
 { List_Add(View->TL, &yyvsp[0].d); ;
     break;}
 case 124:
-#line 586 "Gmsh.y"
+#line 602 "Gmsh.y"
 { 
       List_Add(View->TL, &yyvsp[-11].d); List_Add(View->TL, &yyvsp[-5].d);
       List_Add(View->TL, &yyvsp[-9].d); List_Add(View->TL, &yyvsp[-3].d);
       List_Add(View->TL, &yyvsp[-7].d); List_Add(View->TL, &yyvsp[-1].d);
+      ntmp = List_Nbr(View->TL);
     ;
     break;}
 case 125:
-#line 592 "Gmsh.y"
+#line 609 "Gmsh.y"
 {
+      if((List_Nbr(View->TL) - ntmp) % 18)
+	yymsg(GERROR, "Wrong number of values for tensor line "
+	      "(%d is not a multiple of 18)", List_Nbr(View->TL) - ntmp);
       View->NbTL++;
     ;
     break;}
 case 126:
-#line 599 "Gmsh.y"
+#line 619 "Gmsh.y"
 { List_Add(View->ST, &yyvsp[0].d); ;
     break;}
 case 127:
-#line 601 "Gmsh.y"
+#line 621 "Gmsh.y"
 { List_Add(View->ST, &yyvsp[0].d); ;
     break;}
 case 128:
-#line 608 "Gmsh.y"
+#line 628 "Gmsh.y"
 { 
       List_Add(View->ST, &yyvsp[-17].d); List_Add(View->ST, &yyvsp[-11].d);
       List_Add(View->ST, &yyvsp[-5].d);
@@ -5128,24 +5148,28 @@ case 128:
       List_Add(View->ST, &yyvsp[-3].d);
       List_Add(View->ST, &yyvsp[-13].d); List_Add(View->ST, &yyvsp[-7].d);
       List_Add(View->ST, &yyvsp[-1].d);
+      ntmp = List_Nbr(View->ST);
     ;
     break;}
 case 129:
-#line 617 "Gmsh.y"
+#line 638 "Gmsh.y"
 {
+      if((List_Nbr(View->ST) - ntmp) % 3)
+	yymsg(GERROR, "Wrong number of values for scalar triangle "
+	      "(%d is not a multiple of 3)", List_Nbr(View->ST) - ntmp);
       View->NbST++;
     ;
     break;}
 case 130:
-#line 624 "Gmsh.y"
+#line 648 "Gmsh.y"
 { List_Add(View->VT, &yyvsp[0].d); ;
     break;}
 case 131:
-#line 626 "Gmsh.y"
+#line 650 "Gmsh.y"
 { List_Add(View->VT, &yyvsp[0].d); ;
     break;}
 case 132:
-#line 633 "Gmsh.y"
+#line 657 "Gmsh.y"
 { 
       List_Add(View->VT, &yyvsp[-17].d); List_Add(View->VT, &yyvsp[-11].d);
       List_Add(View->VT, &yyvsp[-5].d);
@@ -5153,24 +5177,28 @@ case 132:
       List_Add(View->VT, &yyvsp[-3].d);
       List_Add(View->VT, &yyvsp[-13].d); List_Add(View->VT, &yyvsp[-7].d);
       List_Add(View->VT, &yyvsp[-1].d);
+      ntmp = List_Nbr(View->VT);
     ;
     break;}
 case 133:
-#line 642 "Gmsh.y"
+#line 667 "Gmsh.y"
 {
+      if((List_Nbr(View->VT) - ntmp) % 9)
+	yymsg(GERROR, "Wrong number of values for vector triangle "
+	      "(%d is not a multiple of 9)", List_Nbr(View->VT) - ntmp);
       View->NbVT++;
     ;
     break;}
 case 134:
-#line 649 "Gmsh.y"
+#line 677 "Gmsh.y"
 { List_Add(View->TT, &yyvsp[0].d); ;
     break;}
 case 135:
-#line 651 "Gmsh.y"
+#line 679 "Gmsh.y"
 { List_Add(View->TT, &yyvsp[0].d); ;
     break;}
 case 136:
-#line 658 "Gmsh.y"
+#line 686 "Gmsh.y"
 { 
       List_Add(View->TT, &yyvsp[-17].d); List_Add(View->TT, &yyvsp[-11].d);
       List_Add(View->TT, &yyvsp[-5].d);
@@ -5178,24 +5206,28 @@ case 136:
       List_Add(View->TT, &yyvsp[-3].d);
       List_Add(View->TT, &yyvsp[-13].d); List_Add(View->TT, &yyvsp[-7].d);
       List_Add(View->TT, &yyvsp[-1].d);
+      ntmp = List_Nbr(View->TT);
     ;
     break;}
 case 137:
-#line 667 "Gmsh.y"
+#line 696 "Gmsh.y"
 {
+      if((List_Nbr(View->TT) - ntmp) % 27)
+	yymsg(GERROR, "Wrong number of values for tensor triangle "
+	      "(%d is not a multiple of 27)", List_Nbr(View->TT) - ntmp);
       View->NbTT++;
     ;
     break;}
 case 138:
-#line 674 "Gmsh.y"
+#line 706 "Gmsh.y"
 { List_Add(View->SQ, &yyvsp[0].d); ;
     break;}
 case 139:
-#line 676 "Gmsh.y"
+#line 708 "Gmsh.y"
 { List_Add(View->SQ, &yyvsp[0].d); ;
     break;}
 case 140:
-#line 684 "Gmsh.y"
+#line 716 "Gmsh.y"
 { 
       List_Add(View->SQ, &yyvsp[-23].d);  List_Add(View->SQ, &yyvsp[-17].d);
       List_Add(View->SQ, &yyvsp[-11].d); List_Add(View->SQ, &yyvsp[-5].d);
@@ -5203,24 +5235,28 @@ case 140:
       List_Add(View->SQ, &yyvsp[-9].d); List_Add(View->SQ, &yyvsp[-3].d);
       List_Add(View->SQ, &yyvsp[-19].d);  List_Add(View->SQ, &yyvsp[-13].d);
       List_Add(View->SQ, &yyvsp[-7].d); List_Add(View->SQ, &yyvsp[-1].d);
+      ntmp = List_Nbr(View->SQ);
     ;
     break;}
 case 141:
-#line 693 "Gmsh.y"
+#line 726 "Gmsh.y"
 {
+      if((List_Nbr(View->SQ) - ntmp) % 4)
+	yymsg(GERROR, "Wrong number of values for scalar quadrangle "
+	      "(%d is not a multiple of 4)", List_Nbr(View->SQ) - ntmp);
       View->NbSQ++;
     ;
     break;}
 case 142:
-#line 700 "Gmsh.y"
+#line 736 "Gmsh.y"
 { List_Add(View->VQ, &yyvsp[0].d); ;
     break;}
 case 143:
-#line 702 "Gmsh.y"
+#line 738 "Gmsh.y"
 { List_Add(View->VQ, &yyvsp[0].d); ;
     break;}
 case 144:
-#line 710 "Gmsh.y"
+#line 746 "Gmsh.y"
 { 
       List_Add(View->VQ, &yyvsp[-23].d);  List_Add(View->VQ, &yyvsp[-17].d);
       List_Add(View->VQ, &yyvsp[-11].d); List_Add(View->VQ, &yyvsp[-5].d);
@@ -5228,24 +5264,28 @@ case 144:
       List_Add(View->VQ, &yyvsp[-9].d); List_Add(View->VQ, &yyvsp[-3].d);
       List_Add(View->VQ, &yyvsp[-19].d);  List_Add(View->VQ, &yyvsp[-13].d);
       List_Add(View->VQ, &yyvsp[-7].d); List_Add(View->VQ, &yyvsp[-1].d);
+      ntmp = List_Nbr(View->VQ);
     ;
     break;}
 case 145:
-#line 719 "Gmsh.y"
+#line 756 "Gmsh.y"
 {
+      if((List_Nbr(View->VQ) - ntmp) % 12)
+	yymsg(GERROR, "Wrong number of values for vector quadrangle "
+	      "(%d is not a multiple of 12)", List_Nbr(View->VQ) - ntmp);
       View->NbVQ++;
     ;
     break;}
 case 146:
-#line 726 "Gmsh.y"
+#line 766 "Gmsh.y"
 { List_Add(View->TQ, &yyvsp[0].d); ;
     break;}
 case 147:
-#line 728 "Gmsh.y"
+#line 768 "Gmsh.y"
 { List_Add(View->TQ, &yyvsp[0].d); ;
     break;}
 case 148:
-#line 736 "Gmsh.y"
+#line 776 "Gmsh.y"
 { 
       List_Add(View->TQ, &yyvsp[-23].d);  List_Add(View->TQ, &yyvsp[-17].d);
       List_Add(View->TQ, &yyvsp[-11].d); List_Add(View->TQ, &yyvsp[-5].d);
@@ -5253,24 +5293,28 @@ case 148:
       List_Add(View->TQ, &yyvsp[-9].d); List_Add(View->TQ, &yyvsp[-3].d);
       List_Add(View->TQ, &yyvsp[-19].d);  List_Add(View->TQ, &yyvsp[-13].d);
       List_Add(View->TQ, &yyvsp[-7].d); List_Add(View->TQ, &yyvsp[-1].d);
+      ntmp = List_Nbr(View->TQ);
     ;
     break;}
 case 149:
-#line 745 "Gmsh.y"
+#line 786 "Gmsh.y"
 {
+      if((List_Nbr(View->TQ) - ntmp) % 36)
+	yymsg(GERROR, "Wrong number of values for tensor quadrangle "
+	      "(%d is not a multiple of 36)", List_Nbr(View->TQ) - ntmp);
       View->NbTQ++;
     ;
     break;}
 case 150:
-#line 752 "Gmsh.y"
+#line 796 "Gmsh.y"
 { List_Add(View->SS, &yyvsp[0].d); ;
     break;}
 case 151:
-#line 754 "Gmsh.y"
+#line 798 "Gmsh.y"
 { List_Add(View->SS, &yyvsp[0].d); ;
     break;}
 case 152:
-#line 762 "Gmsh.y"
+#line 806 "Gmsh.y"
 { 
       List_Add(View->SS, &yyvsp[-23].d);  List_Add(View->SS, &yyvsp[-17].d);
       List_Add(View->SS, &yyvsp[-11].d); List_Add(View->SS, &yyvsp[-5].d);
@@ -5278,24 +5322,28 @@ case 152:
       List_Add(View->SS, &yyvsp[-9].d); List_Add(View->SS, &yyvsp[-3].d);
       List_Add(View->SS, &yyvsp[-19].d);  List_Add(View->SS, &yyvsp[-13].d);
       List_Add(View->SS, &yyvsp[-7].d); List_Add(View->SS, &yyvsp[-1].d);
+      ntmp = List_Nbr(View->SS);
     ;
     break;}
 case 153:
-#line 771 "Gmsh.y"
+#line 816 "Gmsh.y"
 {
+      if((List_Nbr(View->SS) - ntmp) % 4)
+	yymsg(GERROR, "Wrong number of values for scalar tetrahedron "
+	      "(%d is not a multiple of 4)", List_Nbr(View->SS) - ntmp);
       View->NbSS++;
     ;
     break;}
 case 154:
-#line 778 "Gmsh.y"
+#line 826 "Gmsh.y"
 { List_Add(View->VS, &yyvsp[0].d); ;
     break;}
 case 155:
-#line 780 "Gmsh.y"
+#line 828 "Gmsh.y"
 { List_Add(View->VS, &yyvsp[0].d); ;
     break;}
 case 156:
-#line 788 "Gmsh.y"
+#line 836 "Gmsh.y"
 { 
       List_Add(View->VS, &yyvsp[-23].d);  List_Add(View->VS, &yyvsp[-17].d);
       List_Add(View->VS, &yyvsp[-11].d); List_Add(View->VS, &yyvsp[-5].d);
@@ -5303,24 +5351,28 @@ case 156:
       List_Add(View->VS, &yyvsp[-9].d); List_Add(View->VS, &yyvsp[-3].d);
       List_Add(View->VS, &yyvsp[-19].d);  List_Add(View->VS, &yyvsp[-13].d);
       List_Add(View->VS, &yyvsp[-7].d); List_Add(View->VS, &yyvsp[-1].d);
+      ntmp = List_Nbr(View->VS);
     ;
     break;}
 case 157:
-#line 797 "Gmsh.y"
+#line 846 "Gmsh.y"
 {
+      if((List_Nbr(View->VS) - ntmp) % 12)
+	yymsg(GERROR, "Wrong number of values for vector tetrahedron "
+	      "(%d is not a multiple of 12)", List_Nbr(View->VS) - ntmp);
       View->NbVS++;
     ;
     break;}
 case 158:
-#line 804 "Gmsh.y"
+#line 856 "Gmsh.y"
 { List_Add(View->TS, &yyvsp[0].d); ;
     break;}
 case 159:
-#line 806 "Gmsh.y"
+#line 858 "Gmsh.y"
 { List_Add(View->TS, &yyvsp[0].d); ;
     break;}
 case 160:
-#line 814 "Gmsh.y"
+#line 866 "Gmsh.y"
 { 
       List_Add(View->TS, &yyvsp[-23].d);  List_Add(View->TS, &yyvsp[-17].d);
       List_Add(View->TS, &yyvsp[-11].d); List_Add(View->TS, &yyvsp[-5].d);
@@ -5328,24 +5380,28 @@ case 160:
       List_Add(View->TS, &yyvsp[-9].d); List_Add(View->TS, &yyvsp[-3].d);
       List_Add(View->TS, &yyvsp[-19].d);  List_Add(View->TS, &yyvsp[-13].d);
       List_Add(View->TS, &yyvsp[-7].d); List_Add(View->TS, &yyvsp[-1].d);
+      ntmp = List_Nbr(View->TS);
     ;
     break;}
 case 161:
-#line 823 "Gmsh.y"
+#line 876 "Gmsh.y"
 {
+      if((List_Nbr(View->TS) - ntmp) % 36)
+	yymsg(GERROR, "Wrong number of values for tensor tetrahedron "
+	      "(%d is not a multiple of 36)", List_Nbr(View->TS) - ntmp);
       View->NbTS++;
     ;
     break;}
 case 162:
-#line 830 "Gmsh.y"
+#line 886 "Gmsh.y"
 { List_Add(View->SH, &yyvsp[0].d); ;
     break;}
 case 163:
-#line 832 "Gmsh.y"
+#line 888 "Gmsh.y"
 { List_Add(View->SH, &yyvsp[0].d); ;
     break;}
 case 164:
-#line 844 "Gmsh.y"
+#line 900 "Gmsh.y"
 { 
       List_Add(View->SH, &yyvsp[-47].d);  List_Add(View->SH, &yyvsp[-41].d);
       List_Add(View->SH, &yyvsp[-35].d); List_Add(View->SH, &yyvsp[-29].d);
@@ -5359,24 +5415,28 @@ case 164:
       List_Add(View->SH, &yyvsp[-31].d); List_Add(View->SH, &yyvsp[-25].d);
       List_Add(View->SH, &yyvsp[-19].d); List_Add(View->SH, &yyvsp[-13].d);
       List_Add(View->SH, &yyvsp[-7].d); List_Add(View->SH, &yyvsp[-1].d);
+      ntmp = List_Nbr(View->SH);
     ;
     break;}
 case 165:
-#line 859 "Gmsh.y"
+#line 916 "Gmsh.y"
 {
+      if((List_Nbr(View->SH) - ntmp) % 8)
+	yymsg(GERROR, "Wrong number of values for scalar hexahedron "
+	      "(%d is not a multiple of 8)", List_Nbr(View->SH) - ntmp);
       View->NbSH++;
     ;
     break;}
 case 166:
-#line 866 "Gmsh.y"
+#line 926 "Gmsh.y"
 { List_Add(View->VH, &yyvsp[0].d); ;
     break;}
 case 167:
-#line 868 "Gmsh.y"
+#line 928 "Gmsh.y"
 { List_Add(View->VH, &yyvsp[0].d); ;
     break;}
 case 168:
-#line 880 "Gmsh.y"
+#line 940 "Gmsh.y"
 { 
       List_Add(View->VH, &yyvsp[-47].d);  List_Add(View->VH, &yyvsp[-41].d);
       List_Add(View->VH, &yyvsp[-35].d); List_Add(View->VH, &yyvsp[-29].d);
@@ -5390,24 +5450,28 @@ case 168:
       List_Add(View->VH, &yyvsp[-31].d); List_Add(View->VH, &yyvsp[-25].d);
       List_Add(View->VH, &yyvsp[-19].d); List_Add(View->VH, &yyvsp[-13].d);
       List_Add(View->VH, &yyvsp[-7].d); List_Add(View->VH, &yyvsp[-1].d);
+      ntmp = List_Nbr(View->VH);
     ;
     break;}
 case 169:
-#line 895 "Gmsh.y"
+#line 956 "Gmsh.y"
 {
+      if((List_Nbr(View->VH) - ntmp) % 24)
+	yymsg(GERROR, "Wrong number of values for vector hexahedron "
+	      "(%d is not a multiple of 24)", List_Nbr(View->VH) - ntmp);
       View->NbVH++;
     ;
     break;}
 case 170:
-#line 902 "Gmsh.y"
+#line 966 "Gmsh.y"
 { List_Add(View->TH, &yyvsp[0].d); ;
     break;}
 case 171:
-#line 904 "Gmsh.y"
+#line 968 "Gmsh.y"
 { List_Add(View->TH, &yyvsp[0].d); ;
     break;}
 case 172:
-#line 916 "Gmsh.y"
+#line 980 "Gmsh.y"
 { 
       List_Add(View->TH, &yyvsp[-47].d);  List_Add(View->TH, &yyvsp[-41].d);
       List_Add(View->TH, &yyvsp[-35].d); List_Add(View->TH, &yyvsp[-29].d);
@@ -5421,24 +5485,28 @@ case 172:
       List_Add(View->TH, &yyvsp[-31].d); List_Add(View->TH, &yyvsp[-25].d);
       List_Add(View->TH, &yyvsp[-19].d); List_Add(View->TH, &yyvsp[-13].d);
       List_Add(View->TH, &yyvsp[-7].d); List_Add(View->TH, &yyvsp[-1].d);
+      ntmp = List_Nbr(View->TH);
     ;
     break;}
 case 173:
-#line 931 "Gmsh.y"
+#line 996 "Gmsh.y"
 {
+      if((List_Nbr(View->TH) - ntmp) % 72)
+	yymsg(GERROR, "Wrong number of values for tensor hexahedron "
+	      "(%d is not a multiple of 72)", List_Nbr(View->TH) - ntmp);
       View->NbTH++;
     ;
     break;}
 case 174:
-#line 938 "Gmsh.y"
+#line 1006 "Gmsh.y"
 { List_Add(View->SI, &yyvsp[0].d); ;
     break;}
 case 175:
-#line 940 "Gmsh.y"
+#line 1008 "Gmsh.y"
 { List_Add(View->SI, &yyvsp[0].d); ;
     break;}
 case 176:
-#line 950 "Gmsh.y"
+#line 1018 "Gmsh.y"
 { 
       List_Add(View->SI, &yyvsp[-35].d);  List_Add(View->SI, &yyvsp[-29].d);
       List_Add(View->SI, &yyvsp[-23].d); List_Add(View->SI, &yyvsp[-17].d);
@@ -5449,24 +5517,28 @@ case 176:
       List_Add(View->SI, &yyvsp[-31].d);  List_Add(View->SI, &yyvsp[-25].d);
       List_Add(View->SI, &yyvsp[-19].d); List_Add(View->SI, &yyvsp[-13].d);
       List_Add(View->SI, &yyvsp[-7].d); List_Add(View->SI, &yyvsp[-1].d);
+      ntmp = List_Nbr(View->SI);
     ;
     break;}
 case 177:
-#line 962 "Gmsh.y"
+#line 1031 "Gmsh.y"
 {
+      if((List_Nbr(View->SI) - ntmp) % 6)
+	yymsg(GERROR, "Wrong number of values for scalar prism "
+	      "(%d is not a multiple of 6)", List_Nbr(View->SI) - ntmp);
       View->NbSI++;
     ;
     break;}
 case 178:
-#line 969 "Gmsh.y"
+#line 1041 "Gmsh.y"
 { List_Add(View->VI, &yyvsp[0].d); ;
     break;}
 case 179:
-#line 971 "Gmsh.y"
+#line 1043 "Gmsh.y"
 { List_Add(View->VI, &yyvsp[0].d); ;
     break;}
 case 180:
-#line 981 "Gmsh.y"
+#line 1053 "Gmsh.y"
 { 
       List_Add(View->VI, &yyvsp[-35].d);  List_Add(View->VI, &yyvsp[-29].d);
       List_Add(View->VI, &yyvsp[-23].d); List_Add(View->VI, &yyvsp[-17].d);
@@ -5477,24 +5549,28 @@ case 180:
       List_Add(View->VI, &yyvsp[-31].d);  List_Add(View->VI, &yyvsp[-25].d);
       List_Add(View->VI, &yyvsp[-19].d); List_Add(View->VI, &yyvsp[-13].d);
       List_Add(View->VI, &yyvsp[-7].d); List_Add(View->VI, &yyvsp[-1].d);
+      ntmp = List_Nbr(View->VI);
     ;
     break;}
 case 181:
-#line 993 "Gmsh.y"
+#line 1066 "Gmsh.y"
 {
+      if((List_Nbr(View->VI) - ntmp) % 18)
+	yymsg(GERROR, "Wrong number of values for vector prism "
+	      "(%d is not a multiple of 18)", List_Nbr(View->VI) - ntmp);
       View->NbVI++;
     ;
     break;}
 case 182:
-#line 1000 "Gmsh.y"
+#line 1076 "Gmsh.y"
 { List_Add(View->TI, &yyvsp[0].d); ;
     break;}
 case 183:
-#line 1002 "Gmsh.y"
+#line 1078 "Gmsh.y"
 { List_Add(View->TI, &yyvsp[0].d); ;
     break;}
 case 184:
-#line 1012 "Gmsh.y"
+#line 1088 "Gmsh.y"
 { 
       List_Add(View->TI, &yyvsp[-35].d);  List_Add(View->TI, &yyvsp[-29].d);
       List_Add(View->TI, &yyvsp[-23].d); List_Add(View->TI, &yyvsp[-17].d);
@@ -5505,24 +5581,28 @@ case 184:
       List_Add(View->TI, &yyvsp[-31].d);  List_Add(View->TI, &yyvsp[-25].d);
       List_Add(View->TI, &yyvsp[-19].d); List_Add(View->TI, &yyvsp[-13].d);
       List_Add(View->TI, &yyvsp[-7].d); List_Add(View->TI, &yyvsp[-1].d);
+      ntmp = List_Nbr(View->TI);
     ;
     break;}
 case 185:
-#line 1024 "Gmsh.y"
+#line 1101 "Gmsh.y"
 {
+      if((List_Nbr(View->TI) - ntmp) % 54)
+	yymsg(GERROR, "Wrong number of values for tensor prism "
+	      "(%d is not a multiple of 54)", List_Nbr(View->TI) - ntmp);
       View->NbTI++;
     ;
     break;}
 case 186:
-#line 1031 "Gmsh.y"
+#line 1111 "Gmsh.y"
 { List_Add(View->SY, &yyvsp[0].d); ;
     break;}
 case 187:
-#line 1033 "Gmsh.y"
+#line 1113 "Gmsh.y"
 { List_Add(View->SY, &yyvsp[0].d); ;
     break;}
 case 188:
-#line 1042 "Gmsh.y"
+#line 1122 "Gmsh.y"
 { 
       List_Add(View->SY, &yyvsp[-29].d);  List_Add(View->SY, &yyvsp[-23].d);
       List_Add(View->SY, &yyvsp[-17].d); List_Add(View->SY, &yyvsp[-11].d);
@@ -5533,24 +5613,28 @@ case 188:
       List_Add(View->SY, &yyvsp[-25].d);  List_Add(View->SY, &yyvsp[-19].d);
       List_Add(View->SY, &yyvsp[-13].d); List_Add(View->SY, &yyvsp[-7].d);
       List_Add(View->SY, &yyvsp[-1].d);
+      ntmp = List_Nbr(View->SY);
     ;
     break;}
 case 189:
-#line 1054 "Gmsh.y"
+#line 1135 "Gmsh.y"
 {
+      if((List_Nbr(View->SY) - ntmp) % 5)
+	yymsg(GERROR, "Wrong number of values for scalar pyramid "
+	      "(%d is not a multiple of 5)", List_Nbr(View->SY) - ntmp);
       View->NbSY++;
     ;
     break;}
 case 190:
-#line 1061 "Gmsh.y"
+#line 1145 "Gmsh.y"
 { List_Add(View->VY, &yyvsp[0].d); ;
     break;}
 case 191:
-#line 1063 "Gmsh.y"
+#line 1147 "Gmsh.y"
 { List_Add(View->VY, &yyvsp[0].d); ;
     break;}
 case 192:
-#line 1072 "Gmsh.y"
+#line 1156 "Gmsh.y"
 { 
       List_Add(View->VY, &yyvsp[-29].d);  List_Add(View->VY, &yyvsp[-23].d);
       List_Add(View->VY, &yyvsp[-17].d); List_Add(View->VY, &yyvsp[-11].d);
@@ -5561,24 +5645,28 @@ case 192:
       List_Add(View->VY, &yyvsp[-25].d);  List_Add(View->VY, &yyvsp[-19].d);
       List_Add(View->VY, &yyvsp[-13].d); List_Add(View->VY, &yyvsp[-7].d);
       List_Add(View->VY, &yyvsp[-1].d);
+      ntmp = List_Nbr(View->VY);
     ;
     break;}
 case 193:
-#line 1084 "Gmsh.y"
+#line 1169 "Gmsh.y"
 {
+      if((List_Nbr(View->VY) - ntmp) % 15)
+	yymsg(GERROR, "Wrong number of values for vector pyramid "
+	      "(%d is not a multiple of 15)", List_Nbr(View->VY) - ntmp);
       View->NbVY++;
     ;
     break;}
 case 194:
-#line 1091 "Gmsh.y"
+#line 1179 "Gmsh.y"
 { List_Add(View->TY, &yyvsp[0].d); ;
     break;}
 case 195:
-#line 1093 "Gmsh.y"
+#line 1181 "Gmsh.y"
 { List_Add(View->TY, &yyvsp[0].d); ;
     break;}
 case 196:
-#line 1102 "Gmsh.y"
+#line 1190 "Gmsh.y"
 { 
       List_Add(View->TY, &yyvsp[-29].d);  List_Add(View->TY, &yyvsp[-23].d);
       List_Add(View->TY, &yyvsp[-17].d); List_Add(View->TY, &yyvsp[-11].d);
@@ -5589,30 +5677,34 @@ case 196:
       List_Add(View->TY, &yyvsp[-25].d);  List_Add(View->TY, &yyvsp[-19].d);
       List_Add(View->TY, &yyvsp[-13].d); List_Add(View->TY, &yyvsp[-7].d);
       List_Add(View->TY, &yyvsp[-1].d);
+      ntmp = List_Nbr(View->TY);
     ;
     break;}
 case 197:
-#line 1114 "Gmsh.y"
+#line 1203 "Gmsh.y"
 {
+      if((List_Nbr(View->TY) - ntmp) % 45)
+	yymsg(GERROR, "Wrong number of values for tensor pyramid "
+	      "(%d is not a multiple of 45)", List_Nbr(View->TY) - ntmp);
       View->NbTY++;
     ;
     break;}
 case 198:
-#line 1121 "Gmsh.y"
+#line 1213 "Gmsh.y"
 { 
       for(int i = 0; i < (int)strlen(yyvsp[0].c)+1; i++) List_Add(View->T2C, &yyvsp[0].c[i]); 
       Free(yyvsp[0].c);
     ;
     break;}
 case 199:
-#line 1126 "Gmsh.y"
+#line 1218 "Gmsh.y"
 { 
       for(int i = 0; i < (int)strlen(yyvsp[0].c)+1; i++) List_Add(View->T2C, &yyvsp[0].c[i]); 
       Free(yyvsp[0].c);
     ;
     break;}
 case 200:
-#line 1134 "Gmsh.y"
+#line 1226 "Gmsh.y"
 { 
       List_Add(View->T2D, &yyvsp[-5].d); List_Add(View->T2D, &yyvsp[-3].d);
       List_Add(View->T2D, &yyvsp[-1].d); 
@@ -5621,27 +5713,27 @@ case 200:
     ;
     break;}
 case 201:
-#line 1141 "Gmsh.y"
+#line 1233 "Gmsh.y"
 {
       View->NbT2++;
     ;
     break;}
 case 202:
-#line 1148 "Gmsh.y"
+#line 1240 "Gmsh.y"
 { 
       for(int i = 0; i < (int)strlen(yyvsp[0].c)+1; i++) List_Add(View->T3C, &yyvsp[0].c[i]); 
       Free(yyvsp[0].c);
     ;
     break;}
 case 203:
-#line 1153 "Gmsh.y"
+#line 1245 "Gmsh.y"
 { 
       for(int i = 0; i < (int)strlen(yyvsp[0].c)+1; i++) List_Add(View->T3C, &yyvsp[0].c[i]); 
       Free(yyvsp[0].c);
     ;
     break;}
 case 204:
-#line 1161 "Gmsh.y"
+#line 1253 "Gmsh.y"
 { 
       List_Add(View->T3D, &yyvsp[-7].d); List_Add(View->T3D, &yyvsp[-5].d);
       List_Add(View->T3D, &yyvsp[-3].d); List_Add(View->T3D, &yyvsp[-1].d); 
@@ -5650,41 +5742,41 @@ case 204:
     ;
     break;}
 case 205:
-#line 1168 "Gmsh.y"
+#line 1260 "Gmsh.y"
 {
       View->NbT3++;
     ;
     break;}
 case 206:
-#line 1177 "Gmsh.y"
+#line 1269 "Gmsh.y"
 { yyval.i = 0; ;
     break;}
 case 207:
-#line 1178 "Gmsh.y"
+#line 1270 "Gmsh.y"
 { yyval.i = 1; ;
     break;}
 case 208:
-#line 1179 "Gmsh.y"
+#line 1271 "Gmsh.y"
 { yyval.i = 2; ;
     break;}
 case 209:
-#line 1180 "Gmsh.y"
+#line 1272 "Gmsh.y"
 { yyval.i = 3; ;
     break;}
 case 210:
-#line 1181 "Gmsh.y"
+#line 1273 "Gmsh.y"
 { yyval.i = 4; ;
     break;}
 case 211:
-#line 1185 "Gmsh.y"
+#line 1277 "Gmsh.y"
 { yyval.i = 1; ;
     break;}
 case 212:
-#line 1186 "Gmsh.y"
+#line 1278 "Gmsh.y"
 { yyval.i = -1; ;
     break;}
 case 213:
-#line 1194 "Gmsh.y"
+#line 1286 "Gmsh.y"
 {
       Symbol TheSymbol;
       TheSymbol.Name = yyvsp[-3].c;
@@ -5714,7 +5806,7 @@ case 213:
     ;
     break;}
 case 214:
-#line 1222 "Gmsh.y"
+#line 1314 "Gmsh.y"
 {
       Symbol TheSymbol;
       TheSymbol.Name = yyvsp[-6].c;
@@ -5752,7 +5844,7 @@ case 214:
     ;
     break;}
 case 215:
-#line 1258 "Gmsh.y"
+#line 1350 "Gmsh.y"
 {
       if(List_Nbr(yyvsp[-5].l) != List_Nbr(yyvsp[-1].l))
 	yymsg(GERROR, "Incompatible array dimensions in affectation");
@@ -5803,7 +5895,7 @@ case 215:
     ;
     break;}
 case 216:
-#line 1307 "Gmsh.y"
+#line 1399 "Gmsh.y"
 {
       Symbol TheSymbol;
       TheSymbol.Name = yyvsp[-5].c;
@@ -5821,7 +5913,7 @@ case 216:
     ;
     break;}
 case 217:
-#line 1323 "Gmsh.y"
+#line 1415 "Gmsh.y"
 {
       Symbol TheSymbol;
       TheSymbol.Name = yyvsp[-2].c;
@@ -5833,7 +5925,7 @@ case 217:
     ;
     break;}
 case 218:
-#line 1333 "Gmsh.y"
+#line 1425 "Gmsh.y"
 {
       Symbol TheSymbol;
       TheSymbol.Name = yyvsp[-5].c;
@@ -5850,7 +5942,7 @@ case 218:
     ;
     break;}
 case 219:
-#line 1351 "Gmsh.y"
+#line 1443 "Gmsh.y"
 { 
       char* (*pStrOpt)(int num, int action, char *value);
       StringXString *pStrCat;
@@ -5865,7 +5957,7 @@ case 219:
     ;
     break;}
 case 220:
-#line 1364 "Gmsh.y"
+#line 1456 "Gmsh.y"
 { 
       char* (*pStrOpt)(int num, int action, char *value);
       StringXString *pStrCat;
@@ -5880,7 +5972,7 @@ case 220:
     ;
     break;}
 case 221:
-#line 1380 "Gmsh.y"
+#line 1472 "Gmsh.y"
 {
       double (*pNumOpt)(int num, int action, double value);
       StringXNumber *pNumCat;
@@ -5907,7 +5999,7 @@ case 221:
     ;
     break;}
 case 222:
-#line 1405 "Gmsh.y"
+#line 1497 "Gmsh.y"
 {
       double (*pNumOpt)(int num, int action, double value);
       StringXNumber *pNumCat;
@@ -5935,7 +6027,7 @@ case 222:
     ;
     break;}
 case 223:
-#line 1431 "Gmsh.y"
+#line 1523 "Gmsh.y"
 {
       double (*pNumOpt)(int num, int action, double value);
       StringXNumber *pNumCat;
@@ -5950,7 +6042,7 @@ case 223:
     ;
     break;}
 case 224:
-#line 1444 "Gmsh.y"
+#line 1536 "Gmsh.y"
 {
       double (*pNumOpt)(int num, int action, double value);
       StringXNumber *pNumCat;
@@ -5965,7 +6057,7 @@ case 224:
     ;
     break;}
 case 225:
-#line 1460 "Gmsh.y"
+#line 1552 "Gmsh.y"
 {
       unsigned int (*pColOpt)(int num, int action, unsigned int value);
       StringXColor *pColCat;
@@ -5980,7 +6072,7 @@ case 225:
     ;
     break;}
 case 226:
-#line 1473 "Gmsh.y"
+#line 1565 "Gmsh.y"
 {
       unsigned int (*pColOpt)(int num, int action, unsigned int value);
       StringXColor *pColCat;
@@ -5995,7 +6087,7 @@ case 226:
     ;
     break;}
 case 227:
-#line 1489 "Gmsh.y"
+#line 1581 "Gmsh.y"
 {
       GmshColorTable *ct = Get_ColorTable(0);
       if(!ct)
@@ -6016,7 +6108,7 @@ case 227:
     ;
     break;}
 case 228:
-#line 1508 "Gmsh.y"
+#line 1600 "Gmsh.y"
 {
       GmshColorTable *ct = Get_ColorTable((int)yyvsp[-6].d);
       if(!ct)
@@ -6037,7 +6129,7 @@ case 228:
     ;
     break;}
 case 229:
-#line 1530 "Gmsh.y"
+#line 1622 "Gmsh.y"
 {
       try {
 	GMSH_PluginManager::instance()->setPluginOption(yyvsp[-6].c, yyvsp[-3].c, yyvsp[-1].d); 
@@ -6048,7 +6140,7 @@ case 229:
     ;
     break;}
 case 230:
-#line 1539 "Gmsh.y"
+#line 1631 "Gmsh.y"
 {
       try {
 	GMSH_PluginManager::instance()->setPluginOption(yyvsp[-6].c, yyvsp[-3].c, yyvsp[-1].c); 
@@ -6059,7 +6151,7 @@ case 230:
     ;
     break;}
 case 231:
-#line 1557 "Gmsh.y"
+#line 1649 "Gmsh.y"
 {
       int num = (int)yyvsp[-4].d;
       if(FindPoint(num, THEM)){
@@ -6077,7 +6169,7 @@ case 231:
     ;
     break;}
 case 232:
-#line 1573 "Gmsh.y"
+#line 1665 "Gmsh.y"
 {
       int num = (int)yyvsp[-4].d;
       if(FindPhysicalGroup(num, MSH_PHYSICAL_POINT, THEM)){
@@ -6095,7 +6187,7 @@ case 232:
     ;
     break;}
 case 233:
-#line 1589 "Gmsh.y"
+#line 1681 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[-9].l); i++){
 	double p;
@@ -6116,7 +6208,7 @@ case 233:
     ;
     break;}
 case 234:
-#line 1608 "Gmsh.y"
+#line 1700 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[-3].l); i++){
 	double d;
@@ -6134,7 +6226,7 @@ case 234:
     ;
     break;}
 case 235:
-#line 1627 "Gmsh.y"
+#line 1719 "Gmsh.y"
 {
       int num = (int)yyvsp[-4].d;
       if(FindCurve(num, THEM)){
@@ -6154,7 +6246,7 @@ case 235:
     ;
     break;}
 case 236:
-#line 1645 "Gmsh.y"
+#line 1737 "Gmsh.y"
 {
       int num = (int)yyvsp[-4].d;
       if(FindCurve(num, THEM)){
@@ -6174,7 +6266,7 @@ case 236:
     ;
     break;}
 case 237:
-#line 1663 "Gmsh.y"
+#line 1755 "Gmsh.y"
 {
       int num = (int)yyvsp[-4].d;
       if(FindCurve(num, THEM)){
@@ -6194,7 +6286,7 @@ case 237:
     ;
     break;}
 case 238:
-#line 1681 "Gmsh.y"
+#line 1773 "Gmsh.y"
 {
       int num = (int)yyvsp[-6].d;
       if(FindCurve(num, THEM)){
@@ -6222,7 +6314,7 @@ case 238:
     ;
     break;}
 case 239:
-#line 1707 "Gmsh.y"
+#line 1799 "Gmsh.y"
 {
       int num = (int)yyvsp[-4].d;
       if(FindCurve(num, THEM)){
@@ -6242,7 +6334,7 @@ case 239:
     ;
     break;}
 case 240:
-#line 1726 "Gmsh.y"
+#line 1818 "Gmsh.y"
 {
       int num = (int)yyvsp[-14].d;
       if(FindCurve(num, THEM)){
@@ -6262,7 +6354,7 @@ case 240:
     ;
     break;}
 case 241:
-#line 1744 "Gmsh.y"
+#line 1836 "Gmsh.y"
 {
       int num = (int)yyvsp[-4].d;
       if(List_Nbr(yyvsp[-1].l) < 4){
@@ -6288,7 +6380,7 @@ case 241:
     ;
     break;}
 case 242:
-#line 1768 "Gmsh.y"
+#line 1860 "Gmsh.y"
 {
       int num = (int)yyvsp[-4].d;
       if(List_Nbr(yyvsp[-1].l) < 4){
@@ -6314,7 +6406,7 @@ case 242:
     ;
     break;}
 case 243:
-#line 1792 "Gmsh.y"
+#line 1884 "Gmsh.y"
 {
       int num = (int)yyvsp[-8].d;
       if(List_Nbr(yyvsp[-5].l) + (int)yyvsp[-1].d + 1 != List_Nbr(yyvsp[-3].l)){
@@ -6342,7 +6434,7 @@ case 243:
     ;
     break;}
 case 244:
-#line 1818 "Gmsh.y"
+#line 1910 "Gmsh.y"
 {
       int num = (int)yyvsp[-4].d;
       if(FindEdgeLoop(num, THEM)){
@@ -6361,7 +6453,7 @@ case 244:
     ;
     break;}
 case 245:
-#line 1835 "Gmsh.y"
+#line 1927 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[-9].l); i++){
 	double p;
@@ -6381,7 +6473,7 @@ case 245:
     ;
     break;}
 case 246:
-#line 1853 "Gmsh.y"
+#line 1945 "Gmsh.y"
 {
       int num = (int)yyvsp[-4].d;
       if(FindPhysicalGroup(num, MSH_PHYSICAL_LINE, THEM)){
@@ -6399,7 +6491,7 @@ case 246:
     ;
     break;}
 case 247:
-#line 1872 "Gmsh.y"
+#line 1964 "Gmsh.y"
 {
       int num = (int)yyvsp[-4].d;
       if(FindSurface(num, THEM)){
@@ -6420,7 +6512,7 @@ case 247:
     ;
     break;}
 case 248:
-#line 1891 "Gmsh.y"
+#line 1983 "Gmsh.y"
 {
       int num = (int)yyvsp[-4].d, type = 0;
       if(FindSurface(num, THEM)){
@@ -6461,7 +6553,7 @@ case 248:
     ;
     break;}
 case 249:
-#line 1930 "Gmsh.y"
+#line 2022 "Gmsh.y"
 {
       int num = (int)yyvsp[-8].d;
       Surface *support = FindSurface((int)yyvsp[-4].d, THEM);
@@ -6488,7 +6580,7 @@ case 249:
     ;
     break;}
 case 250:
-#line 1956 "Gmsh.y"
+#line 2048 "Gmsh.y"
 {
       int num = (int)yyvsp[-10].d, type = 0;
       Surface *s = FindSurface(num, THEM);
@@ -6509,7 +6601,7 @@ case 250:
     ;
     break;}
 case 251:
-#line 1978 "Gmsh.y"
+#line 2070 "Gmsh.y"
 {
       int num = (int)yyvsp[-10].d, type = 0;
       Surface *s = FindSurface(num, THEM);
@@ -6526,7 +6618,7 @@ case 251:
     ;
     break;}
 case 252:
-#line 1995 "Gmsh.y"
+#line 2087 "Gmsh.y"
 {
       int num = (int)yyvsp[-16].d;
       if(FindSurface(num, THEM)){
@@ -6545,7 +6637,7 @@ case 252:
     ;
     break;}
 case 253:
-#line 2014 "Gmsh.y"
+#line 2106 "Gmsh.y"
 {
       int num = (int)yyvsp[-16].d;
       if(FindSurface(num, THEM)){
@@ -6564,7 +6656,7 @@ case 253:
     ;
     break;}
 case 254:
-#line 2031 "Gmsh.y"
+#line 2123 "Gmsh.y"
 {
       int num = (int)yyvsp[-4].d;
       if(FindSurfaceLoop(num, THEM)){
@@ -6582,7 +6674,7 @@ case 254:
     ;
     break;}
 case 255:
-#line 2047 "Gmsh.y"
+#line 2139 "Gmsh.y"
 {
       int num = (int)yyvsp[-4].d;
       if(FindPhysicalGroup(num, MSH_PHYSICAL_SURFACE, THEM)){
@@ -6600,7 +6692,7 @@ case 255:
     ;
     break;}
 case 256:
-#line 2066 "Gmsh.y"
+#line 2158 "Gmsh.y"
 {
       int num = (int)yyvsp[-4].d;
       if(FindVolume(num, THEM)){
@@ -6619,7 +6711,7 @@ case 256:
     ;
     break;}
 case 257:
-#line 2083 "Gmsh.y"
+#line 2175 "Gmsh.y"
 {
       int num = (int)yyvsp[-4].d;
       if(FindVolume(num, THEM)){
@@ -6638,7 +6730,7 @@ case 257:
     ;
     break;}
 case 258:
-#line 2100 "Gmsh.y"
+#line 2192 "Gmsh.y"
 {
       int num = (int)yyvsp[-4].d;
       if(FindPhysicalGroup(num, MSH_PHYSICAL_VOLUME, THEM)){
@@ -6656,59 +6748,59 @@ case 258:
     ;
     break;}
 case 259:
-#line 2121 "Gmsh.y"
+#line 2213 "Gmsh.y"
 {
       TranslateShapes(yyvsp[-3].v[0], yyvsp[-3].v[1], yyvsp[-3].v[2], yyvsp[-1].l, 1);
       yyval.l = yyvsp[-1].l;
     ;
     break;}
 case 260:
-#line 2126 "Gmsh.y"
+#line 2218 "Gmsh.y"
 {
       RotateShapes(yyvsp[-8].v[0], yyvsp[-8].v[1], yyvsp[-8].v[2], yyvsp[-6].v[0], yyvsp[-6].v[1], yyvsp[-6].v[2], yyvsp[-4].d, yyvsp[-1].l, 1);
       yyval.l = yyvsp[-1].l;
     ;
     break;}
 case 261:
-#line 2131 "Gmsh.y"
+#line 2223 "Gmsh.y"
 {
       SymmetryShapes(yyvsp[-3].v[0], yyvsp[-3].v[1], yyvsp[-3].v[2], yyvsp[-3].v[3], yyvsp[-1].l, 1);
       yyval.l = yyvsp[-1].l;
     ;
     break;}
 case 262:
-#line 2136 "Gmsh.y"
+#line 2228 "Gmsh.y"
 {
       DilatShapes(yyvsp[-6].v[0], yyvsp[-6].v[1], yyvsp[-6].v[2], yyvsp[-4].d, yyvsp[-1].l, 1);
       yyval.l = yyvsp[-1].l;
     ;
     break;}
 case 263:
-#line 2143 "Gmsh.y"
+#line 2235 "Gmsh.y"
 { yyval.l = yyvsp[0].l; ;
     break;}
 case 264:
-#line 2144 "Gmsh.y"
+#line 2236 "Gmsh.y"
 { yyval.l = yyvsp[0].l; ;
     break;}
 case 265:
-#line 2145 "Gmsh.y"
+#line 2237 "Gmsh.y"
 { yyval.l = yyvsp[0].l; ;
     break;}
 case 266:
-#line 2150 "Gmsh.y"
+#line 2242 "Gmsh.y"
 {
       yyval.l = List_Create(3, 3, sizeof(Shape));
     ;
     break;}
 case 267:
-#line 2154 "Gmsh.y"
+#line 2246 "Gmsh.y"
 {
       List_Add(yyval.l, &yyvsp[0].s);
     ;
     break;}
 case 268:
-#line 2158 "Gmsh.y"
+#line 2250 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[-2].l); i++){
 	double d;
@@ -6726,7 +6818,7 @@ case 268:
     ;
     break;}
 case 269:
-#line 2174 "Gmsh.y"
+#line 2266 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[-2].l); i++){
 	double d;
@@ -6744,7 +6836,7 @@ case 269:
     ;
     break;}
 case 270:
-#line 2190 "Gmsh.y"
+#line 2282 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[-2].l); i++){
 	double d;
@@ -6762,7 +6854,7 @@ case 270:
     ;
     break;}
 case 271:
-#line 2206 "Gmsh.y"
+#line 2298 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[-2].l); i++){
 	double d;
@@ -6780,7 +6872,7 @@ case 271:
     ;
     break;}
 case 272:
-#line 2227 "Gmsh.y"
+#line 2319 "Gmsh.y"
 {
       yyval.l = List_Create(3, 3, sizeof(Shape));
       for(int i = 0; i < List_Nbr(yyvsp[-1].l); i++){
@@ -6795,14 +6887,14 @@ case 272:
     ;
     break;}
 case 273:
-#line 2240 "Gmsh.y"
+#line 2332 "Gmsh.y"
 {
       if(!strcmp(yyvsp[-4].c, "View")) DuplicateView((int)yyvsp[-2].d, 0);
       yyval.l = NULL;
     ;
     break;}
 case 274:
-#line 2251 "Gmsh.y"
+#line 2343 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[-1].l); i++){
 	Shape TheShape;
@@ -6813,20 +6905,20 @@ case 274:
     ;
     break;}
 case 275:
-#line 2260 "Gmsh.y"
+#line 2352 "Gmsh.y"
 {
       if(!strcmp(yyvsp[-4].c, "View")) RemoveViewByIndex((int)yyvsp[-2].d);
     ;
     break;}
 case 276:
-#line 2264 "Gmsh.y"
+#line 2356 "Gmsh.y"
 {
       if(!strcmp(yyvsp[-1].c, "Meshes") || !strcmp(yyvsp[-1].c, "All"))
 	Init_Mesh(THEM);
     ;
     break;}
 case 277:
-#line 2274 "Gmsh.y"
+#line 2366 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[-1].l); i++){
 	Shape TheShape;
@@ -6837,7 +6929,7 @@ case 277:
     ;
     break;}
 case 278:
-#line 2288 "Gmsh.y"
+#line 2380 "Gmsh.y"
 {
       int m = (CTX.visibility_mode == 2) ? VIS_MESH : 
 	((CTX.visibility_mode == 1) ? VIS_GEOM : VIS_GEOM|VIS_MESH);
@@ -6846,14 +6938,14 @@ case 278:
     ;
     break;}
 case 279:
-#line 2295 "Gmsh.y"
+#line 2387 "Gmsh.y"
 {
       for(int i = 2; i < 6; i++)
 	SetVisibilityByNumber(yyvsp[-1].c, i, 0);
     ;
     break;}
 case 280:
-#line 2300 "Gmsh.y"
+#line 2392 "Gmsh.y"
 {
       int m = (CTX.visibility_mode == 2) ? VIS_MESH :
 	((CTX.visibility_mode == 1) ? VIS_GEOM : VIS_GEOM|VIS_MESH);
@@ -6866,7 +6958,7 @@ case 280:
     ;
     break;}
 case 281:
-#line 2311 "Gmsh.y"
+#line 2403 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[-1].l); i++){
 	Shape TheShape;
@@ -6877,7 +6969,7 @@ case 281:
     ;
     break;}
 case 282:
-#line 2325 "Gmsh.y"
+#line 2417 "Gmsh.y"
 {
       if(!strcmp(yyvsp[-2].c, "Include")){
 	char tmpstring[1024];
@@ -6919,7 +7011,7 @@ case 282:
     ;
     break;}
 case 283:
-#line 2365 "Gmsh.y"
+#line 2457 "Gmsh.y"
 {
       if(!strcmp(yyvsp[-6].c, "Save") && !strcmp(yyvsp[-5].c, "View")){
 	Post_View *v = (Post_View *)List_Pointer_Test(CTX.post.list, (int)yyvsp[-3].d);
@@ -6935,7 +7027,7 @@ case 283:
     ;
     break;}
 case 284:
-#line 2379 "Gmsh.y"
+#line 2471 "Gmsh.y"
 {
       if(!strcmp(yyvsp[-2].c, "Sleep")){
 	long sleep_time = GetTime();
@@ -6952,7 +7044,7 @@ case 284:
     ;
     break;}
 case 285:
-#line 2394 "Gmsh.y"
+#line 2486 "Gmsh.y"
 {
       try {
 	GMSH_PluginManager::instance()->action(yyvsp[-4].c, yyvsp[-1].c, 0);
@@ -6963,7 +7055,7 @@ case 285:
    ;
     break;}
 case 286:
-#line 2403 "Gmsh.y"
+#line 2495 "Gmsh.y"
 {
       if(!strcmp(yyvsp[-1].c, "Views"))
 	CombineViews(1, 0);
@@ -6974,13 +7066,13 @@ case 286:
     ;
     break;}
 case 287:
-#line 2412 "Gmsh.y"
+#line 2504 "Gmsh.y"
 {
       exit(0);
     ;
     break;}
 case 288:
-#line 2416 "Gmsh.y"
+#line 2508 "Gmsh.y"
 {
 #if defined(HAVE_FLTK)
       if(!CTX.batch) // we're in interactive mode
@@ -6989,7 +7081,7 @@ case 288:
     ;
     break;}
 case 289:
-#line 2429 "Gmsh.y"
+#line 2521 "Gmsh.y"
 {
       LoopControlVariablesTab[ImbricatedLoop][0] = yyvsp[-3].d;
       LoopControlVariablesTab[ImbricatedLoop][1] = yyvsp[-1].d;
@@ -7005,7 +7097,7 @@ case 289:
     ;
     break;}
 case 290:
-#line 2443 "Gmsh.y"
+#line 2535 "Gmsh.y"
 {
       LoopControlVariablesTab[ImbricatedLoop][0] = yyvsp[-5].d;
       LoopControlVariablesTab[ImbricatedLoop][1] = yyvsp[-3].d;
@@ -7021,7 +7113,7 @@ case 290:
     ;
     break;}
 case 291:
-#line 2457 "Gmsh.y"
+#line 2549 "Gmsh.y"
 {
       LoopControlVariablesTab[ImbricatedLoop][0] = yyvsp[-3].d;
       LoopControlVariablesTab[ImbricatedLoop][1] = yyvsp[-1].d;
@@ -7048,7 +7140,7 @@ case 291:
     ;
     break;}
 case 292:
-#line 2482 "Gmsh.y"
+#line 2574 "Gmsh.y"
 {
       LoopControlVariablesTab[ImbricatedLoop][0] = yyvsp[-5].d;
       LoopControlVariablesTab[ImbricatedLoop][1] = yyvsp[-3].d;
@@ -7075,7 +7167,7 @@ case 292:
     ;
     break;}
 case 293:
-#line 2507 "Gmsh.y"
+#line 2599 "Gmsh.y"
 {
       if(LoopControlVariablesTab[ImbricatedLoop-1][1] >  
 	 LoopControlVariablesTab[ImbricatedLoop-1][0]){
@@ -7104,7 +7196,7 @@ case 293:
     ;
     break;}
 case 294:
-#line 2534 "Gmsh.y"
+#line 2626 "Gmsh.y"
 {
       if(!FunctionManager::Instance()->createFunction(yyvsp[0].c, yyin, yyname, yylineno))
 	yymsg(GERROR, "Redefinition of function %s", yyvsp[0].c);
@@ -7112,32 +7204,32 @@ case 294:
     ;
     break;}
 case 295:
-#line 2540 "Gmsh.y"
+#line 2632 "Gmsh.y"
 {
       if(!FunctionManager::Instance()->leaveFunction(&yyin, yyname, yylineno))
 	yymsg(GERROR, "Error while exiting function");
     ;
     break;}
 case 296:
-#line 2545 "Gmsh.y"
+#line 2637 "Gmsh.y"
 {
       if(!FunctionManager::Instance()->enterFunction(yyvsp[-1].c, &yyin, yyname, yylineno))
 	yymsg(GERROR, "Unknown function %s", yyvsp[-1].c);
     ;
     break;}
 case 297:
-#line 2550 "Gmsh.y"
+#line 2642 "Gmsh.y"
 {
       if(!yyvsp[-1].d) skip_until("If", "EndIf");
     ;
     break;}
 case 298:
-#line 2554 "Gmsh.y"
+#line 2646 "Gmsh.y"
 {
     ;
     break;}
 case 299:
-#line 2565 "Gmsh.y"
+#line 2657 "Gmsh.y"
 {
       Curve *pc, *prc;
       Shape TheShape;
@@ -7150,7 +7242,7 @@ case 299:
     ;
     break;}
 case 300:
-#line 2576 "Gmsh.y"
+#line 2668 "Gmsh.y"
 {
       Curve *pc, *prc;
       Shape TheShape;
@@ -7163,7 +7255,7 @@ case 300:
     ;
     break;}
 case 301:
-#line 2587 "Gmsh.y"
+#line 2679 "Gmsh.y"
 {
       Curve *pc, *prc;
       Shape TheShape;
@@ -7176,14 +7268,14 @@ case 301:
     ;
     break;}
 case 302:
-#line 2598 "Gmsh.y"
+#line 2690 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 303:
-#line 2603 "Gmsh.y"
+#line 2695 "Gmsh.y"
 {
       Curve *pc, *prc;
       Shape TheShape;
@@ -7196,14 +7288,14 @@ case 303:
     ;
     break;}
 case 304:
-#line 2614 "Gmsh.y"
+#line 2706 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 305:
-#line 2619 "Gmsh.y"
+#line 2711 "Gmsh.y"
 {
       Curve *pc, *prc;
       Shape TheShape;
@@ -7216,14 +7308,14 @@ case 305:
     ;
     break;}
 case 306:
-#line 2630 "Gmsh.y"
+#line 2722 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 307:
-#line 2635 "Gmsh.y"
+#line 2727 "Gmsh.y"
 {
       Curve *pc, *prc;
       Shape TheShape;
@@ -7236,7 +7328,7 @@ case 307:
     ;
     break;}
 case 308:
-#line 2648 "Gmsh.y"
+#line 2740 "Gmsh.y"
 {
       Surface *ps;
       Shape TheShape;
@@ -7256,7 +7348,7 @@ case 308:
     ;
     break;}
 case 309:
-#line 2666 "Gmsh.y"
+#line 2758 "Gmsh.y"
 {
       Surface *ps;
       Shape TheShape;
@@ -7276,7 +7368,7 @@ case 309:
     ;
     break;}
 case 310:
-#line 2684 "Gmsh.y"
+#line 2776 "Gmsh.y"
 {
       Surface *ps;
       Shape TheShape;
@@ -7296,14 +7388,14 @@ case 310:
     ;
     break;}
 case 311:
-#line 2702 "Gmsh.y"
+#line 2794 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 312:
-#line 2707 "Gmsh.y"
+#line 2799 "Gmsh.y"
 {
       Surface *ps;
       Shape TheShape;
@@ -7323,14 +7415,14 @@ case 312:
     ;
     break;}
 case 313:
-#line 2725 "Gmsh.y"
+#line 2817 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 314:
-#line 2730 "Gmsh.y"
+#line 2822 "Gmsh.y"
 {
       Surface *ps;
       Shape TheShape;
@@ -7350,14 +7442,14 @@ case 314:
     ;
     break;}
 case 315:
-#line 2748 "Gmsh.y"
+#line 2840 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 316:
-#line 2753 "Gmsh.y"
+#line 2845 "Gmsh.y"
 {
       Surface *ps;
       Shape TheShape;
@@ -7377,7 +7469,7 @@ case 316:
     ;
     break;}
 case 317:
-#line 2774 "Gmsh.y"
+#line 2866 "Gmsh.y"
 {
       Shape TheShape;
       TheShape.Num = Extrude_ProtudeSurface(TRANSLATE, (int)yyvsp[-4].d, yyvsp[-2].v[0], yyvsp[-2].v[1], yyvsp[-2].v[2],
@@ -7396,7 +7488,7 @@ case 317:
     ;
     break;}
 case 318:
-#line 2791 "Gmsh.y"
+#line 2883 "Gmsh.y"
 {
       Shape TheShape;
       TheShape.Num = Extrude_ProtudeSurface(ROTATE, (int)yyvsp[-8].d, 0., 0., 0.,
@@ -7415,7 +7507,7 @@ case 318:
     ;
     break;}
 case 319:
-#line 2808 "Gmsh.y"
+#line 2900 "Gmsh.y"
 {
       Shape TheShape;
       TheShape.Num = Extrude_ProtudeSurface(TRANSLATE_ROTATE, (int)yyvsp[-10].d, yyvsp[-8].v[0], yyvsp[-8].v[1], yyvsp[-8].v[2],
@@ -7434,14 +7526,14 @@ case 319:
     ;
     break;}
 case 320:
-#line 2825 "Gmsh.y"
+#line 2917 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 321:
-#line 2830 "Gmsh.y"
+#line 2922 "Gmsh.y"
 {
       Shape TheShape;
       TheShape.Num = Extrude_ProtudeSurface(TRANSLATE, (int)yyvsp[-8].d, yyvsp[-6].v[0], yyvsp[-6].v[1], yyvsp[-6].v[2],
@@ -7460,14 +7552,14 @@ case 321:
     ;
     break;}
 case 322:
-#line 2847 "Gmsh.y"
+#line 2939 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 323:
-#line 2853 "Gmsh.y"
+#line 2945 "Gmsh.y"
 {
       Shape TheShape;
       TheShape.Num = Extrude_ProtudeSurface(ROTATE, (int)yyvsp[-12].d, 0., 0., 0.,
@@ -7486,14 +7578,14 @@ case 323:
     ;
     break;}
 case 324:
-#line 2870 "Gmsh.y"
+#line 2962 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 325:
-#line 2876 "Gmsh.y"
+#line 2968 "Gmsh.y"
 {
       Shape TheShape;
       TheShape.Num = Extrude_ProtudeSurface(TRANSLATE_ROTATE, (int)yyvsp[-14].d, yyvsp[-12].v[0], yyvsp[-12].v[1], yyvsp[-12].v[2],
@@ -7512,17 +7604,17 @@ case 325:
     ;
     break;}
 case 326:
-#line 2896 "Gmsh.y"
+#line 2988 "Gmsh.y"
 {
     ;
     break;}
 case 327:
-#line 2899 "Gmsh.y"
+#line 2991 "Gmsh.y"
 {
     ;
     break;}
 case 328:
-#line 2905 "Gmsh.y"
+#line 2997 "Gmsh.y"
 {
       double d;
       extr.mesh.ExtrudeMesh = true;
@@ -7550,7 +7642,7 @@ case 328:
     ;
     break;}
 case 329:
-#line 2931 "Gmsh.y"
+#line 3023 "Gmsh.y"
 {
       double d;
       extr.mesh.ExtrudeMesh = true;
@@ -7576,13 +7668,13 @@ case 329:
     ;
     break;}
 case 330:
-#line 2955 "Gmsh.y"
+#line 3047 "Gmsh.y"
 {
       extr.mesh.Recombine = true;
     ;
     break;}
 case 331:
-#line 2964 "Gmsh.y"
+#line 3056 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[-3].l); i++){
 	double d;
@@ -7602,7 +7694,7 @@ case 331:
     ;
     break;}
 case 332:
-#line 2982 "Gmsh.y"
+#line 3074 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[-6].l); i++){
 	double d;
@@ -7622,7 +7714,7 @@ case 332:
     ;
     break;}
 case 333:
-#line 3000 "Gmsh.y"
+#line 3092 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[-6].l); i++){
 	double d;
@@ -7642,7 +7734,7 @@ case 333:
     ;
     break;}
 case 334:
-#line 3018 "Gmsh.y"
+#line 3110 "Gmsh.y"
 {
       Surface *s = FindSurface((int)yyvsp[-4].d, THEM);
       if(!s)
@@ -7671,7 +7763,7 @@ case 334:
     ;
     break;}
 case 335:
-#line 3045 "Gmsh.y"
+#line 3137 "Gmsh.y"
 {
       Surface *s = FindSurface((int)yyvsp[-4].d, THEM);
       if(!s)
@@ -7699,7 +7791,7 @@ case 335:
     ;
     break;}
 case 336:
-#line 3071 "Gmsh.y"
+#line 3163 "Gmsh.y"
 {
       Volume *v = FindVolume((int)yyvsp[-4].d, THEM);
       if(!v)
@@ -7727,7 +7819,7 @@ case 336:
     ;
     break;}
 case 337:
-#line 3097 "Gmsh.y"
+#line 3189 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[-3].l); i++){
 	double d;
@@ -7743,7 +7835,7 @@ case 337:
     ;
     break;}
 case 338:
-#line 3111 "Gmsh.y"
+#line 3203 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[-1].l); i++){
 	double d;
@@ -7759,71 +7851,71 @@ case 338:
     ;
     break;}
 case 339:
-#line 3131 "Gmsh.y"
+#line 3223 "Gmsh.y"
 { 
       ReplaceAllDuplicates(THEM);
     ;
     break;}
 case 340:
-#line 3135 "Gmsh.y"
+#line 3227 "Gmsh.y"
 { 
       IntersectAllSegmentsTogether();
     ;
     break;}
 case 341:
-#line 3144 "Gmsh.y"
+#line 3236 "Gmsh.y"
 {yyval.i = 1;;
     break;}
 case 342:
-#line 3145 "Gmsh.y"
+#line 3237 "Gmsh.y"
 {yyval.i = 0;;
     break;}
 case 343:
-#line 3146 "Gmsh.y"
+#line 3238 "Gmsh.y"
 {yyval.i = -1;;
     break;}
 case 344:
-#line 3147 "Gmsh.y"
+#line 3239 "Gmsh.y"
 {yyval.i = -1;;
     break;}
 case 345:
-#line 3148 "Gmsh.y"
+#line 3240 "Gmsh.y"
 {yyval.i = -1;;
     break;}
 case 346:
-#line 3152 "Gmsh.y"
+#line 3244 "Gmsh.y"
 { yyval.d = yyvsp[0].d;           ;
     break;}
 case 347:
-#line 3153 "Gmsh.y"
+#line 3245 "Gmsh.y"
 { yyval.d = yyvsp[-1].d;           ;
     break;}
 case 348:
-#line 3154 "Gmsh.y"
+#line 3246 "Gmsh.y"
 { yyval.d = -yyvsp[0].d;          ;
     break;}
 case 349:
-#line 3155 "Gmsh.y"
+#line 3247 "Gmsh.y"
 { yyval.d = yyvsp[0].d;           ;
     break;}
 case 350:
-#line 3156 "Gmsh.y"
+#line 3248 "Gmsh.y"
 { yyval.d = !yyvsp[0].d;          ;
     break;}
 case 351:
-#line 3157 "Gmsh.y"
+#line 3249 "Gmsh.y"
 { yyval.d = yyvsp[-2].d - yyvsp[0].d;      ;
     break;}
 case 352:
-#line 3158 "Gmsh.y"
+#line 3250 "Gmsh.y"
 { yyval.d = yyvsp[-2].d + yyvsp[0].d;      ;
     break;}
 case 353:
-#line 3159 "Gmsh.y"
+#line 3251 "Gmsh.y"
 { yyval.d = yyvsp[-2].d * yyvsp[0].d;      ;
     break;}
 case 354:
-#line 3161 "Gmsh.y"
+#line 3253 "Gmsh.y"
 { 
       if(!yyvsp[0].d)
 	yymsg(GERROR, "Division by zero in '%g / %g'", yyvsp[-2].d, yyvsp[0].d);
@@ -7832,235 +7924,235 @@ case 354:
     ;
     break;}
 case 355:
-#line 3167 "Gmsh.y"
+#line 3259 "Gmsh.y"
 { yyval.d = (int)yyvsp[-2].d % (int)yyvsp[0].d;  ;
     break;}
 case 356:
-#line 3168 "Gmsh.y"
+#line 3260 "Gmsh.y"
 { yyval.d = pow(yyvsp[-2].d, yyvsp[0].d);  ;
     break;}
 case 357:
-#line 3169 "Gmsh.y"
+#line 3261 "Gmsh.y"
 { yyval.d = yyvsp[-2].d < yyvsp[0].d;      ;
     break;}
 case 358:
-#line 3170 "Gmsh.y"
+#line 3262 "Gmsh.y"
 { yyval.d = yyvsp[-2].d > yyvsp[0].d;      ;
     break;}
 case 359:
-#line 3171 "Gmsh.y"
+#line 3263 "Gmsh.y"
 { yyval.d = yyvsp[-2].d <= yyvsp[0].d;     ;
     break;}
 case 360:
-#line 3172 "Gmsh.y"
+#line 3264 "Gmsh.y"
 { yyval.d = yyvsp[-2].d >= yyvsp[0].d;     ;
     break;}
 case 361:
-#line 3173 "Gmsh.y"
+#line 3265 "Gmsh.y"
 { yyval.d = yyvsp[-2].d == yyvsp[0].d;     ;
     break;}
 case 362:
-#line 3174 "Gmsh.y"
+#line 3266 "Gmsh.y"
 { yyval.d = yyvsp[-2].d != yyvsp[0].d;     ;
     break;}
 case 363:
-#line 3175 "Gmsh.y"
+#line 3267 "Gmsh.y"
 { yyval.d = yyvsp[-2].d && yyvsp[0].d;     ;
     break;}
 case 364:
-#line 3176 "Gmsh.y"
+#line 3268 "Gmsh.y"
 { yyval.d = yyvsp[-2].d || yyvsp[0].d;     ;
     break;}
 case 365:
-#line 3177 "Gmsh.y"
+#line 3269 "Gmsh.y"
 { yyval.d = yyvsp[-4].d? yyvsp[-2].d : yyvsp[0].d;  ;
     break;}
 case 366:
-#line 3178 "Gmsh.y"
+#line 3270 "Gmsh.y"
 { yyval.d = exp(yyvsp[-1].d);      ;
     break;}
 case 367:
-#line 3179 "Gmsh.y"
+#line 3271 "Gmsh.y"
 { yyval.d = log(yyvsp[-1].d);      ;
     break;}
 case 368:
-#line 3180 "Gmsh.y"
+#line 3272 "Gmsh.y"
 { yyval.d = log10(yyvsp[-1].d);    ;
     break;}
 case 369:
-#line 3181 "Gmsh.y"
+#line 3273 "Gmsh.y"
 { yyval.d = sqrt(yyvsp[-1].d);     ;
     break;}
 case 370:
-#line 3182 "Gmsh.y"
+#line 3274 "Gmsh.y"
 { yyval.d = sin(yyvsp[-1].d);      ;
     break;}
 case 371:
-#line 3183 "Gmsh.y"
+#line 3275 "Gmsh.y"
 { yyval.d = asin(yyvsp[-1].d);     ;
     break;}
 case 372:
-#line 3184 "Gmsh.y"
+#line 3276 "Gmsh.y"
 { yyval.d = cos(yyvsp[-1].d);      ;
     break;}
 case 373:
-#line 3185 "Gmsh.y"
+#line 3277 "Gmsh.y"
 { yyval.d = acos(yyvsp[-1].d);     ;
     break;}
 case 374:
-#line 3186 "Gmsh.y"
+#line 3278 "Gmsh.y"
 { yyval.d = tan(yyvsp[-1].d);      ;
     break;}
 case 375:
-#line 3187 "Gmsh.y"
+#line 3279 "Gmsh.y"
 { yyval.d = atan(yyvsp[-1].d);     ;
     break;}
 case 376:
-#line 3188 "Gmsh.y"
+#line 3280 "Gmsh.y"
 { yyval.d = atan2(yyvsp[-3].d, yyvsp[-1].d);;
     break;}
 case 377:
-#line 3189 "Gmsh.y"
+#line 3281 "Gmsh.y"
 { yyval.d = sinh(yyvsp[-1].d);     ;
     break;}
 case 378:
-#line 3190 "Gmsh.y"
+#line 3282 "Gmsh.y"
 { yyval.d = cosh(yyvsp[-1].d);     ;
     break;}
 case 379:
-#line 3191 "Gmsh.y"
+#line 3283 "Gmsh.y"
 { yyval.d = tanh(yyvsp[-1].d);     ;
     break;}
 case 380:
-#line 3192 "Gmsh.y"
+#line 3284 "Gmsh.y"
 { yyval.d = fabs(yyvsp[-1].d);     ;
     break;}
 case 381:
-#line 3193 "Gmsh.y"
+#line 3285 "Gmsh.y"
 { yyval.d = floor(yyvsp[-1].d);    ;
     break;}
 case 382:
-#line 3194 "Gmsh.y"
+#line 3286 "Gmsh.y"
 { yyval.d = ceil(yyvsp[-1].d);     ;
     break;}
 case 383:
-#line 3195 "Gmsh.y"
+#line 3287 "Gmsh.y"
 { yyval.d = fmod(yyvsp[-3].d, yyvsp[-1].d); ;
     break;}
 case 384:
-#line 3196 "Gmsh.y"
+#line 3288 "Gmsh.y"
 { yyval.d = fmod(yyvsp[-3].d, yyvsp[-1].d); ;
     break;}
 case 385:
-#line 3197 "Gmsh.y"
+#line 3289 "Gmsh.y"
 { yyval.d = sqrt(yyvsp[-3].d*yyvsp[-3].d+yyvsp[-1].d*yyvsp[-1].d); ;
     break;}
 case 386:
-#line 3198 "Gmsh.y"
+#line 3290 "Gmsh.y"
 { yyval.d = yyvsp[-1].d*(double)rand()/(double)RAND_MAX; ;
     break;}
 case 387:
-#line 3200 "Gmsh.y"
+#line 3292 "Gmsh.y"
 { yyval.d = exp(yyvsp[-1].d);      ;
     break;}
 case 388:
-#line 3201 "Gmsh.y"
+#line 3293 "Gmsh.y"
 { yyval.d = log(yyvsp[-1].d);      ;
     break;}
 case 389:
-#line 3202 "Gmsh.y"
+#line 3294 "Gmsh.y"
 { yyval.d = log10(yyvsp[-1].d);    ;
     break;}
 case 390:
-#line 3203 "Gmsh.y"
+#line 3295 "Gmsh.y"
 { yyval.d = sqrt(yyvsp[-1].d);     ;
     break;}
 case 391:
-#line 3204 "Gmsh.y"
+#line 3296 "Gmsh.y"
 { yyval.d = sin(yyvsp[-1].d);      ;
     break;}
 case 392:
-#line 3205 "Gmsh.y"
+#line 3297 "Gmsh.y"
 { yyval.d = asin(yyvsp[-1].d);     ;
     break;}
 case 393:
-#line 3206 "Gmsh.y"
+#line 3298 "Gmsh.y"
 { yyval.d = cos(yyvsp[-1].d);      ;
     break;}
 case 394:
-#line 3207 "Gmsh.y"
+#line 3299 "Gmsh.y"
 { yyval.d = acos(yyvsp[-1].d);     ;
     break;}
 case 395:
-#line 3208 "Gmsh.y"
+#line 3300 "Gmsh.y"
 { yyval.d = tan(yyvsp[-1].d);      ;
     break;}
 case 396:
-#line 3209 "Gmsh.y"
+#line 3301 "Gmsh.y"
 { yyval.d = atan(yyvsp[-1].d);     ;
     break;}
 case 397:
-#line 3210 "Gmsh.y"
+#line 3302 "Gmsh.y"
 { yyval.d = atan2(yyvsp[-3].d, yyvsp[-1].d);;
     break;}
 case 398:
-#line 3211 "Gmsh.y"
+#line 3303 "Gmsh.y"
 { yyval.d = sinh(yyvsp[-1].d);     ;
     break;}
 case 399:
-#line 3212 "Gmsh.y"
+#line 3304 "Gmsh.y"
 { yyval.d = cosh(yyvsp[-1].d);     ;
     break;}
 case 400:
-#line 3213 "Gmsh.y"
+#line 3305 "Gmsh.y"
 { yyval.d = tanh(yyvsp[-1].d);     ;
     break;}
 case 401:
-#line 3214 "Gmsh.y"
+#line 3306 "Gmsh.y"
 { yyval.d = fabs(yyvsp[-1].d);     ;
     break;}
 case 402:
-#line 3215 "Gmsh.y"
+#line 3307 "Gmsh.y"
 { yyval.d = floor(yyvsp[-1].d);    ;
     break;}
 case 403:
-#line 3216 "Gmsh.y"
+#line 3308 "Gmsh.y"
 { yyval.d = ceil(yyvsp[-1].d);     ;
     break;}
 case 404:
-#line 3217 "Gmsh.y"
+#line 3309 "Gmsh.y"
 { yyval.d = fmod(yyvsp[-3].d, yyvsp[-1].d); ;
     break;}
 case 405:
-#line 3218 "Gmsh.y"
+#line 3310 "Gmsh.y"
 { yyval.d = fmod(yyvsp[-3].d, yyvsp[-1].d); ;
     break;}
 case 406:
-#line 3219 "Gmsh.y"
+#line 3311 "Gmsh.y"
 { yyval.d = sqrt(yyvsp[-3].d*yyvsp[-3].d+yyvsp[-1].d*yyvsp[-1].d); ;
     break;}
 case 407:
-#line 3220 "Gmsh.y"
+#line 3312 "Gmsh.y"
 { yyval.d = yyvsp[-1].d*(double)rand()/(double)RAND_MAX; ;
     break;}
 case 408:
-#line 3229 "Gmsh.y"
+#line 3321 "Gmsh.y"
 { yyval.d = yyvsp[0].d; ;
     break;}
 case 409:
-#line 3230 "Gmsh.y"
+#line 3322 "Gmsh.y"
 { yyval.d = 3.141592653589793; ;
     break;}
 case 410:
-#line 3231 "Gmsh.y"
+#line 3323 "Gmsh.y"
 { yyval.d = ParUtil::Instance()->rank(); ;
     break;}
 case 411:
-#line 3232 "Gmsh.y"
+#line 3324 "Gmsh.y"
 { yyval.d = ParUtil::Instance()->size(); ;
     break;}
 case 412:
-#line 3237 "Gmsh.y"
+#line 3329 "Gmsh.y"
 {
       Symbol TheSymbol;
       TheSymbol.Name = yyvsp[0].c;
@@ -8074,7 +8166,7 @@ case 412:
     ;
     break;}
 case 413:
-#line 3249 "Gmsh.y"
+#line 3341 "Gmsh.y"
 {
       Symbol TheSymbol;
       TheSymbol.Name = yyvsp[-3].c;
@@ -8095,7 +8187,7 @@ case 413:
     ;
     break;}
 case 414:
-#line 3268 "Gmsh.y"
+#line 3360 "Gmsh.y"
 {
       Symbol TheSymbol;
       TheSymbol.Name = yyvsp[-2].c;
@@ -8110,7 +8202,7 @@ case 414:
     ;
     break;}
 case 415:
-#line 3281 "Gmsh.y"
+#line 3373 "Gmsh.y"
 {
       Symbol TheSymbol;
       TheSymbol.Name = yyvsp[-1].c;
@@ -8124,7 +8216,7 @@ case 415:
     ;
     break;}
 case 416:
-#line 3293 "Gmsh.y"
+#line 3385 "Gmsh.y"
 {
       Symbol TheSymbol;
       TheSymbol.Name = yyvsp[-4].c;
@@ -8145,7 +8237,7 @@ case 416:
     ;
     break;}
 case 417:
-#line 3315 "Gmsh.y"
+#line 3407 "Gmsh.y"
 {
       double (*pNumOpt)(int num, int action, double value);
       StringXNumber *pNumCat;
@@ -8164,7 +8256,7 @@ case 417:
     ;
     break;}
 case 418:
-#line 3332 "Gmsh.y"
+#line 3424 "Gmsh.y"
 {
       double (*pNumOpt)(int num, int action, double value);
       StringXNumber *pNumCat;
@@ -8183,7 +8275,7 @@ case 418:
     ;
     break;}
 case 419:
-#line 3349 "Gmsh.y"
+#line 3441 "Gmsh.y"
 {
       double (*pNumOpt)(int num, int action, double value);
       StringXNumber *pNumCat;
@@ -8202,7 +8294,7 @@ case 419:
     ;
     break;}
 case 420:
-#line 3366 "Gmsh.y"
+#line 3458 "Gmsh.y"
 {
       double (*pNumOpt)(int num, int action, double value);
       StringXNumber *pNumCat;
@@ -8221,130 +8313,130 @@ case 420:
     ;
     break;}
 case 421:
-#line 3386 "Gmsh.y"
+#line 3478 "Gmsh.y"
 {
       memcpy(yyval.v, yyvsp[0].v, 5*sizeof(double));
     ;
     break;}
 case 422:
-#line 3390 "Gmsh.y"
+#line 3482 "Gmsh.y"
 {
       for(int i = 0; i < 5; i++) yyval.v[i] = -yyvsp[0].v[i];
     ;
     break;}
 case 423:
-#line 3394 "Gmsh.y"
+#line 3486 "Gmsh.y"
 { 
       for(int i = 0; i < 5; i++) yyval.v[i] = yyvsp[0].v[i];
     ;
     break;}
 case 424:
-#line 3398 "Gmsh.y"
+#line 3490 "Gmsh.y"
 { 
       for(int i = 0; i < 5; i++) yyval.v[i] = yyvsp[-2].v[i] - yyvsp[0].v[i];
     ;
     break;}
 case 425:
-#line 3402 "Gmsh.y"
+#line 3494 "Gmsh.y"
 {
       for(int i = 0; i < 5; i++) yyval.v[i] = yyvsp[-2].v[i] + yyvsp[0].v[i];
     ;
     break;}
 case 426:
-#line 3409 "Gmsh.y"
+#line 3501 "Gmsh.y"
 { 
       yyval.v[0] = yyvsp[-9].d;  yyval.v[1] = yyvsp[-7].d;  yyval.v[2] = yyvsp[-5].d;  yyval.v[3] = yyvsp[-3].d; yyval.v[4] = yyvsp[-1].d;
     ;
     break;}
 case 427:
-#line 3413 "Gmsh.y"
+#line 3505 "Gmsh.y"
 { 
       yyval.v[0] = yyvsp[-7].d;  yyval.v[1] = yyvsp[-5].d;  yyval.v[2] = yyvsp[-3].d;  yyval.v[3] = yyvsp[-1].d; yyval.v[4] = 1.0;
     ;
     break;}
 case 428:
-#line 3417 "Gmsh.y"
+#line 3509 "Gmsh.y"
 {
       yyval.v[0] = yyvsp[-5].d;  yyval.v[1] = yyvsp[-3].d;  yyval.v[2] = yyvsp[-1].d;  yyval.v[3] = 0.0; yyval.v[4] = 1.0;
     ;
     break;}
 case 429:
-#line 3421 "Gmsh.y"
+#line 3513 "Gmsh.y"
 {
       yyval.v[0] = yyvsp[-5].d;  yyval.v[1] = yyvsp[-3].d;  yyval.v[2] = yyvsp[-1].d;  yyval.v[3] = 0.0; yyval.v[4] = 1.0;
     ;
     break;}
 case 430:
-#line 3428 "Gmsh.y"
+#line 3520 "Gmsh.y"
 {
     ;
     break;}
 case 431:
-#line 3431 "Gmsh.y"
+#line 3523 "Gmsh.y"
 {
     ;
     break;}
 case 432:
-#line 3437 "Gmsh.y"
+#line 3529 "Gmsh.y"
 {
     ;
     break;}
 case 433:
-#line 3440 "Gmsh.y"
+#line 3532 "Gmsh.y"
 {
     ;
     break;}
 case 434:
-#line 3446 "Gmsh.y"
+#line 3538 "Gmsh.y"
 {
     ;
     break;}
 case 435:
-#line 3449 "Gmsh.y"
+#line 3541 "Gmsh.y"
 {
        yyval.l = yyvsp[-1].l;
     ;
     break;}
 case 436:
-#line 3453 "Gmsh.y"
+#line 3545 "Gmsh.y"
 {
        yyval.l = yyvsp[-1].l;
     ;
     break;}
 case 437:
-#line 3460 "Gmsh.y"
+#line 3552 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(List_T*));
       List_Add(yyval.l, &(yyvsp[0].l));
     ;
     break;}
 case 438:
-#line 3465 "Gmsh.y"
+#line 3557 "Gmsh.y"
 {
       List_Add(yyval.l, &(yyvsp[0].l));
     ;
     break;}
 case 439:
-#line 3473 "Gmsh.y"
+#line 3565 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(double));
       List_Add(yyval.l, &(yyvsp[0].d));
     ;
     break;}
 case 440:
-#line 3478 "Gmsh.y"
+#line 3570 "Gmsh.y"
 {
       yyval.l = yyvsp[0].l;
     ;
     break;}
 case 441:
-#line 3482 "Gmsh.y"
+#line 3574 "Gmsh.y"
 {
       yyval.l = yyvsp[-1].l;
     ;
     break;}
 case 442:
-#line 3486 "Gmsh.y"
+#line 3578 "Gmsh.y"
 {
       yyval.l = yyvsp[-1].l;
       double *pd;
@@ -8355,7 +8447,7 @@ case 442:
     ;
     break;}
 case 443:
-#line 3498 "Gmsh.y"
+#line 3590 "Gmsh.y"
 { 
       yyval.l = List_Create(2, 1, sizeof(double)); 
       for(double d = yyvsp[-2].d; (yyvsp[-2].d < yyvsp[0].d) ? (d <= yyvsp[0].d) : (d >= yyvsp[0].d); (yyvsp[-2].d < yyvsp[0].d) ? (d += 1.) : (d -= 1.)) 
@@ -8363,7 +8455,7 @@ case 443:
     ;
     break;}
 case 444:
-#line 3504 "Gmsh.y"
+#line 3596 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(double)); 
       if(!yyvsp[0].d || (yyvsp[-4].d < yyvsp[-2].d && yyvsp[0].d < 0) || (yyvsp[-4].d > yyvsp[-2].d && yyvsp[0].d > 0)){
@@ -8376,7 +8468,7 @@ case 444:
    ;
     break;}
 case 445:
-#line 3515 "Gmsh.y"
+#line 3607 "Gmsh.y"
 {
       // Returns the coordinates of a point and fills a list with it.
       // This allows to ensure e.g. that relative point positions are
@@ -8398,7 +8490,7 @@ case 445:
     ;
     break;}
 case 446:
-#line 3535 "Gmsh.y"
+#line 3627 "Gmsh.y"
 {
       yyval.l = List_Create(List_Nbr(yyvsp[0].l), 1, sizeof(double));
       for(int i = 0; i < List_Nbr(yyvsp[0].l); i++){
@@ -8410,7 +8502,7 @@ case 446:
     ;
     break;}
 case 447:
-#line 3545 "Gmsh.y"
+#line 3637 "Gmsh.y"
 {
       yyval.l = List_Create(List_Nbr(yyvsp[0].l), 1, sizeof(double));
       for(int i = 0; i < List_Nbr(yyvsp[0].l); i++){
@@ -8422,7 +8514,7 @@ case 447:
     ;
     break;}
 case 448:
-#line 3555 "Gmsh.y"
+#line 3647 "Gmsh.y"
 {
       // FIXME: The syntax for this is ugly: we get double semi-colons
       // at the end of the line
@@ -8436,7 +8528,7 @@ case 448:
     ;
     break;}
 case 449:
-#line 3567 "Gmsh.y"
+#line 3659 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(double));
       Symbol TheSymbol;
@@ -8454,7 +8546,7 @@ case 449:
     ;
     break;}
 case 450:
-#line 3583 "Gmsh.y"
+#line 3675 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(double));
       Symbol TheSymbol;
@@ -8474,7 +8566,7 @@ case 450:
     ;
     break;}
 case 451:
-#line 3601 "Gmsh.y"
+#line 3693 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(double));
       Symbol TheSymbol;
@@ -8499,7 +8591,7 @@ case 451:
     ;
     break;}
 case 452:
-#line 3624 "Gmsh.y"
+#line 3716 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(double));
       Symbol TheSymbol;
@@ -8526,26 +8618,26 @@ case 452:
     ;
     break;}
 case 453:
-#line 3652 "Gmsh.y"
+#line 3744 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(double));
       List_Add(yyval.l, &(yyvsp[0].d));
     ;
     break;}
 case 454:
-#line 3657 "Gmsh.y"
+#line 3749 "Gmsh.y"
 {
       yyval.l = yyvsp[0].l;
     ;
     break;}
 case 455:
-#line 3661 "Gmsh.y"
+#line 3753 "Gmsh.y"
 {
       List_Add(yyval.l, &(yyvsp[0].d));
     ;
     break;}
 case 456:
-#line 3665 "Gmsh.y"
+#line 3757 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[0].l); i++){
 	double d;
@@ -8556,19 +8648,19 @@ case 456:
     ;
     break;}
 case 457:
-#line 3678 "Gmsh.y"
+#line 3770 "Gmsh.y"
 {
       yyval.u = PACK_COLOR((int)yyvsp[-7].d, (int)yyvsp[-5].d, (int)yyvsp[-3].d, (int)yyvsp[-1].d);
     ;
     break;}
 case 458:
-#line 3682 "Gmsh.y"
+#line 3774 "Gmsh.y"
 {
       yyval.u = PACK_COLOR((int)yyvsp[-5].d, (int)yyvsp[-3].d, (int)yyvsp[-1].d, 255);
     ;
     break;}
 case 459:
-#line 3694 "Gmsh.y"
+#line 3786 "Gmsh.y"
 {
       int flag;
       yyval.u = Get_ColorForString(ColorString, -1, yyvsp[0].c, &flag);
@@ -8576,7 +8668,7 @@ case 459:
     ;
     break;}
 case 460:
-#line 3700 "Gmsh.y"
+#line 3792 "Gmsh.y"
 {
       unsigned int (*pColOpt)(int num, int action, unsigned int value);
       StringXColor *pColCat;
@@ -8596,13 +8688,13 @@ case 460:
     ;
     break;}
 case 461:
-#line 3721 "Gmsh.y"
+#line 3813 "Gmsh.y"
 {
       yyval.l = yyvsp[-1].l;
     ;
     break;}
 case 462:
-#line 3725 "Gmsh.y"
+#line 3817 "Gmsh.y"
 {
       yyval.l = List_Create(256, 10, sizeof(unsigned int));
       GmshColorTable *ct = Get_ColorTable((int)yyvsp[-3].d);
@@ -8615,26 +8707,26 @@ case 462:
     ;
     break;}
 case 463:
-#line 3739 "Gmsh.y"
+#line 3831 "Gmsh.y"
 {
       yyval.l = List_Create(256, 10, sizeof(unsigned int));
       List_Add(yyval.l, &(yyvsp[0].u));
     ;
     break;}
 case 464:
-#line 3744 "Gmsh.y"
+#line 3836 "Gmsh.y"
 {
       List_Add(yyval.l, &(yyvsp[0].u));
     ;
     break;}
 case 465:
-#line 3751 "Gmsh.y"
+#line 3843 "Gmsh.y"
 {
       yyval.c = yyvsp[0].c;
     ;
     break;}
 case 466:
-#line 3755 "Gmsh.y"
+#line 3847 "Gmsh.y"
 {
       yyval.c = (char *)Malloc((strlen(yyvsp[-3].c)+strlen(yyvsp[-1].c)+1)*sizeof(char));
       strcpy(yyval.c, yyvsp[-3].c);  
@@ -8644,7 +8736,7 @@ case 466:
     ;
     break;}
 case 467:
-#line 3763 "Gmsh.y"
+#line 3855 "Gmsh.y"
 {
       yyval.c = (char *)Malloc((strlen(yyvsp[-1].c)+1)*sizeof(char));
       int i;
@@ -8660,13 +8752,13 @@ case 467:
     ;
     break;}
 case 468:
-#line 3777 "Gmsh.y"
+#line 3869 "Gmsh.y"
 {
       yyval.c = yyvsp[-1].c;
     ;
     break;}
 case 469:
-#line 3781 "Gmsh.y"
+#line 3873 "Gmsh.y"
 {
       char tmpstring[1024];
       int i = PrintListOfDouble(yyvsp[-3].c, yyvsp[-1].l, tmpstring);
@@ -8687,7 +8779,7 @@ case 469:
     ;
     break;}
 case 470:
-#line 3800 "Gmsh.y"
+#line 3892 "Gmsh.y"
 { 
       char* (*pStrOpt)(int num, int action, char *value);
       StringXString *pStrCat;
@@ -8705,7 +8797,7 @@ case 470:
     ;
     break;}
 case 471:
-#line 3816 "Gmsh.y"
+#line 3908 "Gmsh.y"
 { 
       char* (*pStrOpt)(int num, int action, char *value);
       StringXString *pStrCat;
@@ -8944,7 +9036,7 @@ yyerrhandle:
     }
   return 1;
 }
-#line 3833 "Gmsh.y"
+#line 3925 "Gmsh.y"
 
 
 void DeleteSymbol(void *a, void *b){
diff --git a/Parser/Gmsh.y b/Parser/Gmsh.y
index c4a80d76dc49984d1966cc37844ef125646a1776..8ee8aa4162487eae549981414ba88393f5c215f9 100644
--- a/Parser/Gmsh.y
+++ b/Parser/Gmsh.y
@@ -1,5 +1,5 @@
 %{
-// $Id: Gmsh.y,v 1.166 2004-05-22 01:29:46 geuzaine Exp $
+// $Id: Gmsh.y,v 1.167 2004-05-25 04:10:10 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -57,6 +57,7 @@ extern Mesh *THEM;
 static Surface *STL_Surf;
 static ExtrudeParams extr;
 static Post_View *View;
+static int ntmp;
 
 #define MAX_RECUR_LOOPS 100
 static int ImbricatedLoop = 0;
@@ -65,7 +66,6 @@ static int yylinenoImbricatedLoopsTab[MAX_RECUR_LOOPS];
 static double LoopControlVariablesTab[MAX_RECUR_LOOPS][3];
 static char *LoopControlVariablesNameTab[MAX_RECUR_LOOPS];
 
-char *strsave (char *ptr);
 void yyerror (char *s);
 void yymsg (int type, char *fmt, ...);
 void skip_until (char *skip, char *until);
@@ -485,7 +485,7 @@ ScalarPoint :
     tScalarPoint '(' FExpr ',' FExpr ',' FExpr ')'
     { 
       List_Add(View->SP, &$3); List_Add(View->SP, &$5);
-      List_Add(View->SP, &$7);
+      List_Add(View->SP, &$7);      
     }
     '{' ScalarPointValues '}' tEND
     {
@@ -505,9 +505,13 @@ VectorPoint :
     { 
       List_Add(View->VP, &$3); List_Add(View->VP, &$5);
       List_Add(View->VP, &$7); 
+      ntmp = List_Nbr(View->VP);
     }
     '{' VectorPointValues '}' tEND
     {
+      if((List_Nbr(View->VP) - ntmp) % 3)
+	yymsg(GERROR, "Wrong number of values for vector point "
+	      "(%d is not a multiple of 3)", List_Nbr(View->VP) - ntmp);
       View->NbVP++;
     }
 ;
@@ -524,9 +528,13 @@ TensorPoint :
     { 
       List_Add(View->TP, &$3); List_Add(View->TP, &$5);
       List_Add(View->TP, &$7);
+      ntmp = List_Nbr(View->TP);
     }
     '{' TensorPointValues '}' tEND
     {
+      if((List_Nbr(View->TP) - ntmp) % 9)
+	yymsg(GERROR, "Wrong number of values for tensor point "
+	      "(%d is not a multiple of 9)", List_Nbr(View->TP) - ntmp);
       View->NbTP++;
     }
 ;
@@ -545,9 +553,13 @@ ScalarLine :
       List_Add(View->SL, &$3); List_Add(View->SL, &$9);
       List_Add(View->SL, &$5); List_Add(View->SL, &$11);
       List_Add(View->SL, &$7); List_Add(View->SL, &$13);
+      ntmp = List_Nbr(View->SL);
     }
     '{' ScalarLineValues '}' tEND
     {
+      if((List_Nbr(View->SL) - ntmp) % 2)
+	yymsg(GERROR, "Wrong number of values for scalar line "
+	      "(%d is not a multiple of 2)", List_Nbr(View->SL) - ntmp);
       View->NbSL++;
     }
 ;
@@ -566,9 +578,13 @@ VectorLine :
       List_Add(View->VL, &$3); List_Add(View->VL, &$9);
       List_Add(View->VL, &$5); List_Add(View->VL, &$11);
       List_Add(View->VL, &$7); List_Add(View->VL, &$13);
+      ntmp = List_Nbr(View->VL);
     }
     '{' VectorLineValues '}' tEND
     {
+      if((List_Nbr(View->VL) - ntmp) % 6)
+	yymsg(GERROR, "Wrong number of values for vector line "
+	      "(%d is not a multiple of 6)", List_Nbr(View->VL) - ntmp);
       View->NbVL++;
     }
 ;
@@ -587,9 +603,13 @@ TensorLine :
       List_Add(View->TL, &$3); List_Add(View->TL, &$9);
       List_Add(View->TL, &$5); List_Add(View->TL, &$11);
       List_Add(View->TL, &$7); List_Add(View->TL, &$13);
+      ntmp = List_Nbr(View->TL);
     }
     '{' TensorLineValues '}' tEND
     {
+      if((List_Nbr(View->TL) - ntmp) % 18)
+	yymsg(GERROR, "Wrong number of values for tensor line "
+	      "(%d is not a multiple of 18)", List_Nbr(View->TL) - ntmp);
       View->NbTL++;
     }
 ;
@@ -612,9 +632,13 @@ ScalarTriangle :
       List_Add(View->ST, &$17);
       List_Add(View->ST, &$7); List_Add(View->ST, &$13);
       List_Add(View->ST, &$19);
+      ntmp = List_Nbr(View->ST);
     }
     '{' ScalarTriangleValues '}' tEND
     {
+      if((List_Nbr(View->ST) - ntmp) % 3)
+	yymsg(GERROR, "Wrong number of values for scalar triangle "
+	      "(%d is not a multiple of 3)", List_Nbr(View->ST) - ntmp);
       View->NbST++;
     }
 ;
@@ -637,9 +661,13 @@ VectorTriangle :
       List_Add(View->VT, &$17);
       List_Add(View->VT, &$7); List_Add(View->VT, &$13);
       List_Add(View->VT, &$19);
+      ntmp = List_Nbr(View->VT);
     }
     '{' VectorTriangleValues '}' tEND
     {
+      if((List_Nbr(View->VT) - ntmp) % 9)
+	yymsg(GERROR, "Wrong number of values for vector triangle "
+	      "(%d is not a multiple of 9)", List_Nbr(View->VT) - ntmp);
       View->NbVT++;
     }
 ;
@@ -662,9 +690,13 @@ TensorTriangle :
       List_Add(View->TT, &$17);
       List_Add(View->TT, &$7); List_Add(View->TT, &$13);
       List_Add(View->TT, &$19);
+      ntmp = List_Nbr(View->TT);
     }
     '{' TensorTriangleValues '}' tEND
     {
+      if((List_Nbr(View->TT) - ntmp) % 27)
+	yymsg(GERROR, "Wrong number of values for tensor triangle "
+	      "(%d is not a multiple of 27)", List_Nbr(View->TT) - ntmp);
       View->NbTT++;
     }
 ;
@@ -688,9 +720,13 @@ ScalarQuadrangle :
       List_Add(View->SQ, &$17); List_Add(View->SQ, &$23);
       List_Add(View->SQ, &$7);  List_Add(View->SQ, &$13);
       List_Add(View->SQ, &$19); List_Add(View->SQ, &$25);
+      ntmp = List_Nbr(View->SQ);
     }
     '{' ScalarQuadrangleValues '}' tEND
     {
+      if((List_Nbr(View->SQ) - ntmp) % 4)
+	yymsg(GERROR, "Wrong number of values for scalar quadrangle "
+	      "(%d is not a multiple of 4)", List_Nbr(View->SQ) - ntmp);
       View->NbSQ++;
     }
 ;
@@ -714,9 +750,13 @@ VectorQuadrangle :
       List_Add(View->VQ, &$17); List_Add(View->VQ, &$23);
       List_Add(View->VQ, &$7);  List_Add(View->VQ, &$13);
       List_Add(View->VQ, &$19); List_Add(View->VQ, &$25);
+      ntmp = List_Nbr(View->VQ);
     }
     '{' VectorQuadrangleValues '}' tEND
     {
+      if((List_Nbr(View->VQ) - ntmp) % 12)
+	yymsg(GERROR, "Wrong number of values for vector quadrangle "
+	      "(%d is not a multiple of 12)", List_Nbr(View->VQ) - ntmp);
       View->NbVQ++;
     }
 ;
@@ -740,9 +780,13 @@ TensorQuadrangle :
       List_Add(View->TQ, &$17); List_Add(View->TQ, &$23);
       List_Add(View->TQ, &$7);  List_Add(View->TQ, &$13);
       List_Add(View->TQ, &$19); List_Add(View->TQ, &$25);
+      ntmp = List_Nbr(View->TQ);
     }
     '{' TensorQuadrangleValues '}' tEND
     {
+      if((List_Nbr(View->TQ) - ntmp) % 36)
+	yymsg(GERROR, "Wrong number of values for tensor quadrangle "
+	      "(%d is not a multiple of 36)", List_Nbr(View->TQ) - ntmp);
       View->NbTQ++;
     }
 ;
@@ -766,9 +810,13 @@ ScalarTetrahedron :
       List_Add(View->SS, &$17); List_Add(View->SS, &$23);
       List_Add(View->SS, &$7);  List_Add(View->SS, &$13);
       List_Add(View->SS, &$19); List_Add(View->SS, &$25);
+      ntmp = List_Nbr(View->SS);
     }
     '{' ScalarTetrahedronValues '}' tEND
     {
+      if((List_Nbr(View->SS) - ntmp) % 4)
+	yymsg(GERROR, "Wrong number of values for scalar tetrahedron "
+	      "(%d is not a multiple of 4)", List_Nbr(View->SS) - ntmp);
       View->NbSS++;
     }
 ;
@@ -792,9 +840,13 @@ VectorTetrahedron :
       List_Add(View->VS, &$17); List_Add(View->VS, &$23);
       List_Add(View->VS, &$7);  List_Add(View->VS, &$13);
       List_Add(View->VS, &$19); List_Add(View->VS, &$25);
+      ntmp = List_Nbr(View->VS);
     }
     '{' VectorTetrahedronValues '}' tEND
     {
+      if((List_Nbr(View->VS) - ntmp) % 12)
+	yymsg(GERROR, "Wrong number of values for vector tetrahedron "
+	      "(%d is not a multiple of 12)", List_Nbr(View->VS) - ntmp);
       View->NbVS++;
     }
 ;
@@ -818,9 +870,13 @@ TensorTetrahedron :
       List_Add(View->TS, &$17); List_Add(View->TS, &$23);
       List_Add(View->TS, &$7);  List_Add(View->TS, &$13);
       List_Add(View->TS, &$19); List_Add(View->TS, &$25);
+      ntmp = List_Nbr(View->TS);
     }
     '{' TensorTetrahedronValues '}' tEND
     {
+      if((List_Nbr(View->TS) - ntmp) % 36)
+	yymsg(GERROR, "Wrong number of values for tensor tetrahedron "
+	      "(%d is not a multiple of 36)", List_Nbr(View->TS) - ntmp);
       View->NbTS++;
     }
 ;
@@ -854,9 +910,13 @@ ScalarHexahedron :
       List_Add(View->SH, &$19); List_Add(View->SH, &$25);
       List_Add(View->SH, &$31); List_Add(View->SH, &$37);
       List_Add(View->SH, &$43); List_Add(View->SH, &$49);
+      ntmp = List_Nbr(View->SH);
     }
     '{' ScalarHexahedronValues '}' tEND
     {
+      if((List_Nbr(View->SH) - ntmp) % 8)
+	yymsg(GERROR, "Wrong number of values for scalar hexahedron "
+	      "(%d is not a multiple of 8)", List_Nbr(View->SH) - ntmp);
       View->NbSH++;
     }
 ;
@@ -890,9 +950,13 @@ VectorHexahedron :
       List_Add(View->VH, &$19); List_Add(View->VH, &$25);
       List_Add(View->VH, &$31); List_Add(View->VH, &$37);
       List_Add(View->VH, &$43); List_Add(View->VH, &$49);
+      ntmp = List_Nbr(View->VH);
     }
     '{' VectorHexahedronValues '}' tEND
     {
+      if((List_Nbr(View->VH) - ntmp) % 24)
+	yymsg(GERROR, "Wrong number of values for vector hexahedron "
+	      "(%d is not a multiple of 24)", List_Nbr(View->VH) - ntmp);
       View->NbVH++;
     }
 ;
@@ -926,9 +990,13 @@ TensorHexahedron :
       List_Add(View->TH, &$19); List_Add(View->TH, &$25);
       List_Add(View->TH, &$31); List_Add(View->TH, &$37);
       List_Add(View->TH, &$43); List_Add(View->TH, &$49);
+      ntmp = List_Nbr(View->TH);
     }
     '{' TensorHexahedronValues '}' tEND
     {
+      if((List_Nbr(View->TH) - ntmp) % 72)
+	yymsg(GERROR, "Wrong number of values for tensor hexahedron "
+	      "(%d is not a multiple of 72)", List_Nbr(View->TH) - ntmp);
       View->NbTH++;
     }
 ;
@@ -957,9 +1025,13 @@ ScalarPrism :
       List_Add(View->SI, &$7);  List_Add(View->SI, &$13);
       List_Add(View->SI, &$19); List_Add(View->SI, &$25);
       List_Add(View->SI, &$31); List_Add(View->SI, &$37);
+      ntmp = List_Nbr(View->SI);
     }
     '{' ScalarPrismValues '}' tEND
     {
+      if((List_Nbr(View->SI) - ntmp) % 6)
+	yymsg(GERROR, "Wrong number of values for scalar prism "
+	      "(%d is not a multiple of 6)", List_Nbr(View->SI) - ntmp);
       View->NbSI++;
     }
 ;
@@ -988,9 +1060,13 @@ VectorPrism :
       List_Add(View->VI, &$7);  List_Add(View->VI, &$13);
       List_Add(View->VI, &$19); List_Add(View->VI, &$25);
       List_Add(View->VI, &$31); List_Add(View->VI, &$37);
+      ntmp = List_Nbr(View->VI);
     }
     '{' VectorPrismValues '}' tEND
     {
+      if((List_Nbr(View->VI) - ntmp) % 18)
+	yymsg(GERROR, "Wrong number of values for vector prism "
+	      "(%d is not a multiple of 18)", List_Nbr(View->VI) - ntmp);
       View->NbVI++;
     }
 ;
@@ -1019,9 +1095,13 @@ TensorPrism :
       List_Add(View->TI, &$7);  List_Add(View->TI, &$13);
       List_Add(View->TI, &$19); List_Add(View->TI, &$25);
       List_Add(View->TI, &$31); List_Add(View->TI, &$37);
+      ntmp = List_Nbr(View->TI);
     }
     '{' TensorPrismValues '}' tEND
     {
+      if((List_Nbr(View->TI) - ntmp) % 54)
+	yymsg(GERROR, "Wrong number of values for tensor prism "
+	      "(%d is not a multiple of 54)", List_Nbr(View->TI) - ntmp);
       View->NbTI++;
     }
 ;
@@ -1049,9 +1129,13 @@ ScalarPyramid :
       List_Add(View->SY, &$7);  List_Add(View->SY, &$13);
       List_Add(View->SY, &$19); List_Add(View->SY, &$25);
       List_Add(View->SY, &$31);
+      ntmp = List_Nbr(View->SY);
     }
     '{' ScalarPyramidValues '}' tEND
     {
+      if((List_Nbr(View->SY) - ntmp) % 5)
+	yymsg(GERROR, "Wrong number of values for scalar pyramid "
+	      "(%d is not a multiple of 5)", List_Nbr(View->SY) - ntmp);
       View->NbSY++;
     }
 ;
@@ -1079,9 +1163,13 @@ VectorPyramid :
       List_Add(View->VY, &$7);  List_Add(View->VY, &$13);
       List_Add(View->VY, &$19); List_Add(View->VY, &$25);
       List_Add(View->VY, &$31);
+      ntmp = List_Nbr(View->VY);
     }
     '{' VectorPyramidValues '}' tEND
     {
+      if((List_Nbr(View->VY) - ntmp) % 15)
+	yymsg(GERROR, "Wrong number of values for vector pyramid "
+	      "(%d is not a multiple of 15)", List_Nbr(View->VY) - ntmp);
       View->NbVY++;
     }
 ;
@@ -1109,9 +1197,13 @@ TensorPyramid :
       List_Add(View->TY, &$7);  List_Add(View->TY, &$13);
       List_Add(View->TY, &$19); List_Add(View->TY, &$25);
       List_Add(View->TY, &$31);
+      ntmp = List_Nbr(View->TY);
     }
     '{' TensorPyramidValues '}' tEND
     {
+      if((List_Nbr(View->TY) - ntmp) % 45)
+	yymsg(GERROR, "Wrong number of values for tensor pyramid "
+	      "(%d is not a multiple of 45)", List_Nbr(View->TY) - ntmp);
       View->NbTY++;
     }
 ;
diff --git a/Parser/Gmsh.yy.cpp b/Parser/Gmsh.yy.cpp
index d1a3b0ef6d36057bd43d013c0e0fa56e69272821..e3b220c889b760cc46ab54029d42f305bf42df12 100644
--- a/Parser/Gmsh.yy.cpp
+++ b/Parser/Gmsh.yy.cpp
@@ -2,7 +2,7 @@
 /* A lexical scanner generated by flex */
 
 /* Scanner skeleton version:
- * $Header: /cvsroot/gmsh/Parser/Gmsh.yy.cpp,v 1.189 2004-05-22 01:34:57 geuzaine Exp $
+ * $Header: /cvsroot/gmsh/Parser/Gmsh.yy.cpp,v 1.190 2004-05-25 04:10:10 geuzaine Exp $
  */
 
 #define FLEX_SCANNER
@@ -1014,7 +1014,7 @@ char *yytext;
 #line 1 "Gmsh.l"
 #define INITIAL 0
 #line 2 "Gmsh.l"
-// $Id: Gmsh.yy.cpp,v 1.189 2004-05-22 01:34:57 geuzaine Exp $
+// $Id: Gmsh.yy.cpp,v 1.190 2004-05-25 04:10:10 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
diff --git a/Parser/OpenFile.cpp b/Parser/OpenFile.cpp
index 5c3b27cf1f6427ccb518fa2542771d9456fcc1ed..95f1c9a1a7488c83cc04ae45df0f6216f385fdc1 100644
--- a/Parser/OpenFile.cpp
+++ b/Parser/OpenFile.cpp
@@ -1,4 +1,4 @@
-// $Id: OpenFile.cpp,v 1.56 2004-05-22 01:38:31 geuzaine Exp $
+// $Id: OpenFile.cpp,v 1.57 2004-05-25 04:10:10 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -274,10 +274,8 @@ void OpenProblem(char *name)
 
   CTX.threads_lock = 0;
 
-  if(!status) {
+  if(!status)
     mai3d(THEM, 0);
-    Maillage_Dimension_0(&M);
-  }
 
 #if defined(HAVE_FLTK)
   if(!CTX.batch)
diff --git a/doc/FAQ b/doc/FAQ
index 2c846d7729923b55bf6930248f558831b8bd1dc9..a3187a209ec81a1746743c262f795aab3c9fde31 100644
--- a/doc/FAQ
+++ b/doc/FAQ
@@ -1,4 +1,4 @@
-$Id: FAQ,v 1.35 2004-04-08 23:45:02 geuzaine Exp $
+$Id: FAQ,v 1.36 2004-05-25 04:10:10 geuzaine Exp $
 
 This is the Gmsh FAQ
 
@@ -11,7 +11,7 @@ Section 1: The basics
 Gmsh is an automatic three-dimensional finite element mesh generator,
 primarily Delaunay, with built-in pre- and post-processing
 facilities. Its primal design goal is to provide a simple meshing tool
-for academic test cases with parametric input and up to date
+for academic problems with parametric input and up to date
 visualization capabilities.  One of the strengths of Gmsh is its
 ability to respect a characteristic length field for the generation of
 adapted meshes on lines, surfaces and volumes.
diff --git a/doc/VERSIONS b/doc/VERSIONS
index b9089045a8f148597ccc591a0dba2ef8639f2108..d87247ad02f7349da9f5903f6eebf62fa1b344ce 100644
--- a/doc/VERSIONS
+++ b/doc/VERSIONS
@@ -1,6 +1,6 @@
-$Id: VERSIONS,v 1.209 2004-05-22 01:24:18 geuzaine Exp $
+$Id: VERSIONS,v 1.210 2004-05-25 04:10:10 geuzaine Exp $
 
-New since 1.52: various background mesh fixes and enhancements; new
+New in 1.53: various background mesh fixes and enhancements; new
 Plugin(Evaluate) to evaluate arbitrary expressions on post-processing
 views; generalized Plugin(Extract) to handle any combination of
 components; generalized "Coherence" to handle transfinite
@@ -8,7 +8,9 @@ surface/volume attributes; plugin options can now be set in the option
 file (like all other options); added "undo" capability during geometry
 creation; rewrote the contour guessing routines so that entities can
 be selected in an arbitrary order; Mac users can now double click on
-geo/msh/pos files in the Finder to launch Gmsh; many small cleanups;
+geo/msh/pos files in the Finder to launch Gmsh; removed support for
+fltk 1.0; rewrote most of the code related to quadrangles; many code
+cleanups;
 
 New in 1.52: new raster ("bitmap") PostScript/EPS/PDF output formats;
 new Plugin(Extract) to extract a given component from a
diff --git a/doc/gmsh.1 b/doc/gmsh.1
index e5ea908f0caecc08db35c60df74320675025ebd7..55abb91b51c8a893f59f5a4dd3496beefe3098b0 100644
--- a/doc/gmsh.1
+++ b/doc/gmsh.1
@@ -1,4 +1,4 @@
-.\" $Id: gmsh.1,v 1.51 2004-02-05 17:16:04 geuzaine Exp $
+.\" $Id: gmsh.1,v 1.52 2004-05-25 04:10:10 geuzaine Exp $
 .TH Gmsh 1 "14 June 2003" "Gmsh 1.45" "Gmsh Manual Pages"
 .UC 4
 .\" ********************************************************************
@@ -13,7 +13,7 @@ with built-in pre- and post-processing facilities
 \fIGmsh\fR is an automatic three-dimensional finite element mesh
 generator (primarily Delaunay) with build-in CAD and post-processing
 facilities. Its design goal is to provide a simple meshing tool for
-academic test cases with parametric input and up to date visualization
+academic problems with parametric input and up to date visualization
 capabilities. One of its strengths is the ability to respect a
 characteristic length field for the generation of adapted meshes on
 lines, surfaces and volumes, and to mix these meshes with simple
diff --git a/doc/gmsh.html b/doc/gmsh.html
index 92131635f8d5de6b2a52f0dfac3081fc661f38aa..ed136f1e175692a9bf91f9370503909dd3129835 100644
--- a/doc/gmsh.html
+++ b/doc/gmsh.html
@@ -24,7 +24,7 @@ generator with built-in pre- and post-processing facilities</h1>
 <p>
 <h3 align="center">Christophe Geuzaine and Jean-François Remacle</h3>
 <p>
-<h3 align=center>Version <a href="doc/VERSIONS">1.52</a>, 5 May 2004</h3>
+<h3 align=center>Version <a href="doc/VERSIONS">1.53</a>, xx May 2004</h3>
 <p>
 <center>
   <a href="#Description">Description</a> |
@@ -40,10 +40,9 @@ generator with built-in pre- and post-processing facilities</h1>
 <h2><a name="Description"></a>Description</h2>
 
 Gmsh is an automatic 3D finite element mesh generator (primarily
-Delaunay) with build-in CAD and post-processing facilities. Its
-design goal is to provide a simple meshing tool for academic test
-cases with parametric input and up to date visualization
-capabilities.
+Delaunay) with build-in CAD and post-processing facilities. Its design
+goal is to provide a simple meshing tool for academic problems with
+parametric input and up to date visualization capabilities.
 <p>
 Gmsh is built around four modules: geometry, mesh, solver and
 post-processing. The specification of any input to these modules is
@@ -109,11 +108,11 @@ available for Windows, Linux and Mac OS X. The tutorial and demo files
 are included in the archives.
 
 <ul>
-<li><a href="/gmsh/bin/Windows/gmsh-1.52.1-Windows.zip">Windows zip archive (95/98/NT/2000/XP)</a>
-<li><a href="/gmsh/bin/Linux/gmsh-1.52.1-1.i386.rpm">Linux RPM (i386, Red Hat >= 7.3)</a>
-<li><a href="/gmsh/bin/Linux/gmsh-1.52.1-Linux.tgz">Linux tarball (i386, glibc >= 2.2)</a> 
-<li><a href="/gmsh/bin/MacOSX/gmsh-1.52.1-MacOSX.tgz">Mac OS X tarball (Mac OS X >= 10.2)</a>
-<li><a href="/gmsh/src/gmsh-1.52.1-source.tgz">Source tarball (all platforms)</a>
+<li><a href="/gmsh/bin/Windows/gmsh-1.53.0-Windows.zip">Windows zip archive (95/98/NT/2000/XP)</a>
+<li><a href="/gmsh/bin/Linux/gmsh-1.53.0-1.i386.rpm">Linux RPM (i386, Red Hat >= 7.3)</a>
+<li><a href="/gmsh/bin/Linux/gmsh-1.53.0-Linux.tgz">Linux tarball (i386, glibc >= 2.2)</a> 
+<li><a href="/gmsh/bin/MacOSX/gmsh-1.53.0-MacOSX.tgz">Mac OS X tarball (Mac OS X >= 10.2)</a>
+<li><a href="/gmsh/src/gmsh-1.53.0-source.tgz">Source tarball (all platforms)</a>
     <a href="#build-footnote" name="build-footmark"><sup>2</sup></a>
 </ul>
 
diff --git a/doc/texinfo/gmsh.texi b/doc/texinfo/gmsh.texi
index e058640c1e955d9913cf3d75946aae6f3def31f3..e5bc8c4a28af030eae264c3e13800e1ffdefb8d7 100644
--- a/doc/texinfo/gmsh.texi
+++ b/doc/texinfo/gmsh.texi
@@ -1,5 +1,5 @@
 \input texinfo.tex @c -*-texinfo-*-
-@c $Id: gmsh.texi,v 1.109 2004-05-22 01:24:18 geuzaine Exp $
+@c $Id: gmsh.texi,v 1.110 2004-05-25 04:10:11 geuzaine Exp $
 @c
 @c Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 @c
@@ -37,8 +37,8 @@
 @c =========================================================================
 @c %**start of header
 @setfilename        gmsh.info
-@set EDITION        1.21
-@set GMSH-VERSION   1.52
+@set EDITION        1.22
+@set GMSH-VERSION   1.53
 @set GMSH-WEB       @uref{http://www.geuz.org/gmsh/}
 @set COPYRIGHT      @copyright{} 1997-2004 Christophe Geuzaine, Jean-Fran@,{c}ois Remacle
 @c
@@ -274,7 +274,7 @@ Bugs, versions and credits
 
 Gmsh is an automatic three-dimensional finite element mesh generator,
 primarily Delaunay, with built-in pre- and post-processing facilities. Its
-design goal is to provide a simple meshing tool for academic test cases with
+design goal is to provide a simple meshing tool for academic problems with
 parametric input and up to date visualization capabilities.  One of its
 strengths is the ability to respect a characteristic length field for the
 generation of adapted meshes on lines, surfaces and volumes, and to mix
@@ -518,7 +518,7 @@ and not very robust.  If these algorithms fail, try to change some
 characteristic lengths to generate meshes that better suit the geometrical
 details of the structures;
 @item
-Gmsh was designed to solve academic test-cases, not industrial-size
+Gmsh was designed to solve academic ``test cases'', not industrial-size
 problems. You may find that Gmsh is too slow for large problems (with
 thousands of geometric primitives, or millions of mesh/post-processing
 elements).