diff --git a/Graphics/Graph2D.cpp b/Graphics/Graph2D.cpp
index 4fd524d51b3cf3aec64f422185697e1b9d9a7209..c4e8b2114b8bb50de83e2e5dce4c11bfd1f67d91 100644
--- a/Graphics/Graph2D.cpp
+++ b/Graphics/Graph2D.cpp
@@ -1,4 +1,4 @@
-// $Id: Graph2D.cpp,v 1.63 2007-09-01 09:20:00 geuzaine Exp $
+// $Id: Graph2D.cpp,v 1.64 2007-09-02 21:05:20 geuzaine Exp $
 //
 // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 //
@@ -149,16 +149,16 @@ static void drawGraphAxes(PView *p, double xleft, double ytop, double width,
     if((opt->ShowTime == 1 && nt > 1) || opt->ShowTime == 2){
       char tmp[256];
       sprintf(tmp, opt->Format, data->getTime(opt->TimeStep));
-      sprintf(label, "%s (%s)", p->getName().c_str(), tmp);
+      sprintf(label, "%s (%s)", data->getName().c_str(), tmp);
     }
     else if((opt->ShowTime == 3 && nt > 1) || opt->ShowTime == 4){
-      sprintf(label, "%s (%d)", p->getName().c_str(), opt->TimeStep);
+      sprintf(label, "%s (%d)", data->getName().c_str(), opt->TimeStep);
     }
     else
-      sprintf(label, "%s", p->getName().c_str());
+      sprintf(label, "%s", data->getName().c_str());
   }
   else
-    sprintf(label, "%s", p->getName().c_str());
+    sprintf(label, "%s", data->getName().c_str());
   glRasterPos2d(xleft, ytop + font_h + tic);
   Draw_String_Center(label);
   
diff --git a/Graphics/Iso.cpp b/Graphics/Iso.cpp
index 55fb20b46606bbe944ff08f849063c57f8047d57..0a35036faee76fdf005fe0b2228bcc28cd43f6b4 100644
--- a/Graphics/Iso.cpp
+++ b/Graphics/Iso.cpp
@@ -1,4 +1,4 @@
-// $Id: Iso.cpp,v 1.40 2007-08-27 13:46:21 geuzaine Exp $
+// $Id: Iso.cpp,v 1.41 2007-09-02 21:05:20 geuzaine Exp $
 //
 // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 //
@@ -36,7 +36,7 @@ static void affect(double *xi, double *yi, double *zi, int i,
   zi[i] = zp[j];
 }
 
-// Draw an iso-point in a line
+// Compute an iso-point in a line
 
 int IsoLine(double *X, double *Y, double *Z, double *Val, double V,
 	    double *Xp, double *Yp, double *Zp)
@@ -76,6 +76,8 @@ int IsoTriangle(double *X, double *Y, double *Z, double *Val, double V,
   return 0;
 }
 
+// Compute an iso-polygon inside a tetrahedron
+
 int IsoSimplex(double *X, double *Y, double *Z, double *Val, double V,
 	       double *Xp, double *Yp, double *Zp, double n[3])
 {
diff --git a/Graphics/Scale.cpp b/Graphics/Scale.cpp
index 639fc06afc45432f6c596b08389ff8cf9b755d8d..23a2d1efa1d545dac3f189f4d4dfad637883fb13 100644
--- a/Graphics/Scale.cpp
+++ b/Graphics/Scale.cpp
@@ -1,4 +1,4 @@
-// $Id: Scale.cpp,v 1.66 2007-09-01 09:20:00 geuzaine Exp $
+// $Id: Scale.cpp,v 1.67 2007-09-02 21:05:20 geuzaine Exp $
 //
 // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 //
@@ -180,13 +180,13 @@ static void drawScaleLabel(PView *p, double xmin, double ymin, double width,
   if((opt->ShowTime == 1 && nt > 1) || opt->ShowTime == 2){
     char tmp[256];
     sprintf(tmp, opt->Format, data->getTime(opt->TimeStep));
-    sprintf(label, "%s (%s)", p->getName().c_str(), tmp);
+    sprintf(label, "%s (%s)", data->getName().c_str(), tmp);
   }
   else if((opt->ShowTime == 3 && nt > 1) || opt->ShowTime == 4){
-    sprintf(label, "%s (%d)", p->getName().c_str(), opt->TimeStep);
+    sprintf(label, "%s (%d)", data->getName().c_str(), opt->TimeStep);
   }
   else
-    sprintf(label, "%s", p->getName().c_str());
+    sprintf(label, "%s", data->getName().c_str());
  
   if(horizontal){
     glRasterPos2d(xmin + width / 2., ymin + height + tic + 1.4 * font_h);
@@ -306,10 +306,10 @@ void Draw_Scales()
       if(opt->ShowTime){
 	char tmp[256];
 	sprintf(tmp, opt->Format, data->getTime(opt->TimeStep));
-	sprintf(label, "%s (%s)", p->getName().c_str(), tmp);
+	sprintf(label, "%s (%s)", data->getName().c_str(), tmp);
       }
       else
-	sprintf(label, "%s", p->getName().c_str());
+	sprintf(label, "%s", data->getName().c_str());
       width = std::max(width, gl_width(label));
       if(i % 2) width_total += std::max(bar_size + width, bar_size + width_prev);
     }
diff --git a/Post/Makefile b/Post/Makefile
index 8d5ad98739d205d933fd53271a7cd1ef1de0963d..1085213fb49a068c9ebf76779b70883d25a93448 100644
--- a/Post/Makefile
+++ b/Post/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.8 2007-09-01 16:05:43 geuzaine Exp $
+# $Id: Makefile,v 1.9 2007-09-02 21:05:20 geuzaine Exp $
 #
 # Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 #
@@ -73,7 +73,7 @@ PViewDataList.o: PViewDataList.cpp PViewDataList.h PViewData.h \
   ../Numeric/Numeric.h ../Common/SmoothData.h ../Common/Context.h
 PViewDataListIO.o: PViewDataListIO.cpp PViewDataList.h PViewData.h \
   ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../DataStr/List.h \
-  ../Common/Message.h
+  ../Numeric/Numeric.h ../Common/Message.h ../Common/Context.h
 PViewDataGModel.o: PViewDataGModel.cpp PViewDataGModel.h PViewData.h \
   ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h PViewDataList.h \
   ../DataStr/List.h ../Geo/GModel.h ../Geo/GVertex.h ../Geo/GEntity.h \
diff --git a/Post/PView.h b/Post/PView.h
index 663685055028a1716311ab924223b482b1d4be39..b3e8ed825ecdfbf085ccb869378ae039f3573463 100644
--- a/Post/PView.h
+++ b/Post/PView.h
@@ -42,8 +42,6 @@ class PView{
   int _aliasOf;
   // reference counter mark that some other views link to this one
   int _links;
-  // name of the view
-  std::string _name;
   // eye position
   SPoint3 _eye;
   // the options
@@ -62,8 +60,6 @@ class PView{
   static PView *current();
   PViewOptions *getOptions(){ return _options; }  
   PViewData *getData(){ return _data; }
-  std::string getName(){ return _name; }
-  void setName(std::string val){ _name = val; }
   int getNum(){ return _num; }
   int getIndex(){ return _index; }
   void setIndex(int val){ _index = val; }
diff --git a/Post/PViewData.h b/Post/PViewData.h
index ecb692b52ef7bdd0948930ec35d94a3fc37c2455..0617aba8f954b00677a5eb71616df6cb8a326a3d 100644
--- a/Post/PViewData.h
+++ b/Post/PViewData.h
@@ -28,6 +28,8 @@ class PViewData {
  private:
   // flag to mark that the data is 'dirty' and should not be displayed
   bool _dirty;
+  // name of the view
+  std::string _name;
   // name of the file the data was loaded from
   std::string _filename;
  public:
@@ -35,8 +37,12 @@ class PViewData {
   virtual ~PViewData(){}
   virtual bool getDirty(){ return _dirty; }
   virtual void setDirty(bool val){ _dirty = val; }
-  virtual void finalize(){}
+  virtual void finalize(){ _dirty = false; }
   virtual int getNumTimeSteps() = 0;
+  virtual std::string getName(){ return _name; }
+  virtual void setName(std::string val){ _name = val; }
+  virtual std::string getFileName(){ return _filename; }
+  virtual void setFileName(std::string val){ _filename = val; }
   virtual double getTime(int step){ return 0.; }
   virtual double getMin(int step=-1) = 0;
   virtual double getMax(int step=-1) = 0;
@@ -66,7 +72,13 @@ class PViewData {
 			   double &x, double &y, double &style){}
   virtual void getString3D(int i, int step, std::string &str, 
 			   double &x, double &y, double &z, double &style){}
-  virtual bool read(std::string filename){}
+  virtual bool read(std::string name){ return false; }
+  virtual bool writePOS(std::string name, bool binary=false, bool parsed=true,
+			bool append=false){ return false; }
+  virtual bool writeSTL(std::string name){ return false; }
+  virtual bool writeTXT(std::string name){ return false; }
+  virtual bool writeMSH(std::string name){ return false; }
+
 };
 
 #endif
diff --git a/Post/PViewDataGModel.cpp b/Post/PViewDataGModel.cpp
index 4deea8560ddc080676d21a8d7078c412e3140ee8..3fc2cf502948007773562dcf11ca876dce32ce6e 100644
--- a/Post/PViewDataGModel.cpp
+++ b/Post/PViewDataGModel.cpp
@@ -1,4 +1,4 @@
-// $Id: PViewDataGModel.cpp,v 1.1 2007-09-01 16:06:24 geuzaine Exp $
+// $Id: PViewDataGModel.cpp,v 1.2 2007-09-02 21:05:20 geuzaine Exp $
 //
 // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 //
@@ -23,3 +23,30 @@
 // 
 
 #include "PViewDataGModel.h"
+
+bool PViewDataGModel::read(std::string name)
+{
+  // model->read();
+}
+
+bool PViewDataGModel::writePOS(std::string name, bool binary, bool parsed,
+			       bool append)
+{
+  // model->writePOS()
+}
+
+bool PViewDataGModel::writeSTL(std::string name)
+{
+  // model->writeSTL()
+}
+
+bool PViewDataGModel::writeTXT(std::string name)
+{
+  // model->writeTXT()
+}
+
+bool PViewDataGModel::writeMSH(std::string name)
+{
+  // model->writeMSH()
+}
+
diff --git a/Post/PViewDataGModel.h b/Post/PViewDataGModel.h
index f37e1da570b0a133d96933fc8c321c8ca87e08e1..f2864fc7b882adff432fb5411166fa7ac91d4b84 100644
--- a/Post/PViewDataGModel.h
+++ b/Post/PViewDataGModel.h
@@ -44,6 +44,12 @@ class PViewDataGModel : public PViewData {
   int getNumComponents(int ele){ return 1; }
   void getValue(int ele, int node, int comp, int step, double &val){}
   int getNumEdges(int ele){ return 0; }
+  bool read(std::string name);
+  bool writePOS(std::string name, bool binary=false, bool parsed=true,
+		bool append=false);
+  bool writeSTL(std::string name);
+  bool writeTXT(std::string name);
+  bool writeMSH(std::string name);
 };
 
 #endif
diff --git a/Post/PViewDataList.cpp b/Post/PViewDataList.cpp
index a9520a4bba0c1de348698154080bec6a169d8c50..63ed65053378c866b11bcb9d1a8019e57b6bca39 100644
--- a/Post/PViewDataList.cpp
+++ b/Post/PViewDataList.cpp
@@ -1,4 +1,4 @@
-// $Id: PViewDataList.cpp,v 1.1 2007-09-01 16:06:24 geuzaine Exp $
+// $Id: PViewDataList.cpp,v 1.2 2007-09-02 21:05:20 geuzaine Exp $
 //
 // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 //
@@ -101,9 +101,10 @@ void PViewDataList::finalize()
   _stat(T2D, T2C, 4); _stat(T3D, T3C, 5);
 
   // convert all "old-style" (non adaptive) 2nd order elements into
-  // linear elements *and* free all the data associated with the
-  // 2nd order elements
-  //FIXME:   _splitCurvedElements();
+  // linear elements *and* free all the data associated with the 2nd
+  // order elements (this is a temporary solution, until we use
+  // Adaptive_Views on all curved elements)
+  _splitCurvedElements();
 
   // compute min/max and other statistics for all element lists
   _stat(SP, 1, NbSP, 1); _stat(VP, 3, NbVP, 1); _stat(TP, 9, NbTP, 1);
@@ -402,6 +403,107 @@ void PViewDataList::getString3D(int i, int step, std::string &str,
   _getString(3, i, step, str, x, y, z, style);
 }
 
+static void splitCurvedElement(List_T **in, int *nbin, List_T *out, int *nbout, 
+			       int nodin, int nodout, int nbcomp, int nbsplit,
+			       int split[][8], int remove=1)
+{
+  if(*nbin){
+    int nb = List_Nbr(*in) / *nbin;
+    int nbstep = (nb - 3 * nodin) / (nodin * nbcomp); // we don't know this yet for the view
+    for(int i = 0; i < List_Nbr(*in); i += nb) {
+      double *coord = (double *)List_Pointer_Fast(*in, i);
+      double *val = (double *)List_Pointer_Fast(*in, i + 3 * nodin);
+      for(int j = 0; j < nbsplit; j++){
+	for(int k = 0; k < nodout; k++)
+	  List_Add(out, &coord[split[j][k]]);
+	for(int k = 0; k < nodout; k++)
+	  List_Add(out, &coord[nodin + split[j][k]]);
+	for(int k = 0; k < nodout; k++)
+	  List_Add(out, &coord[2 * nodin + split[j][k]]);
+	for(int ts = 0; ts < nbstep; ts++){
+	  for(int k = 0; k < nodout; k++){
+	    for(int l = 0; l < nbcomp; l++){
+	      List_Add(out, &val[nodin * nbcomp * ts + nbcomp * split[j][k] + l]);
+	    }
+	  }
+	}
+	(*nbout)++;
+      }
+    }
+  }
+
+  if(remove){
+    *nbin = 0;
+    List_Delete(*in);
+    *in = NULL;
+  }
+}
+
+void PViewDataList::_splitCurvedElements()
+{
+  int lin[2][8] = { // 2-split
+    {0,2}, {2,1}
+  };
+  splitCurvedElement(&SL2, &NbSL2, SL, &NbSL, 3,2, 1, 2, lin);
+  splitCurvedElement(&VL2, &NbVL2, VL, &NbVL, 3,2, 3, 2, lin);
+  splitCurvedElement(&TL2, &NbTL2, TL, &NbTL, 3,2, 9, 2, lin);
+
+  int tri[4][8] = { // 4-split
+    {0,3,5}, {1,4,3}, {2,5,4}, {3,4,5}
+  };
+  splitCurvedElement(&ST2, &NbST2, ST, &NbST, 6,3, 1, 4, tri);
+  splitCurvedElement(&VT2, &NbVT2, VT, &NbVT, 6,3, 3, 4, tri);
+  splitCurvedElement(&TT2, &NbTT2, TT, &NbTT, 6,3, 9, 4, tri);
+
+  int qua[4][8] = { // 4-split
+    {0,4,8,7}, {1,5,8,4}, {2,6,8,5}, {3,7,8,6}
+  };
+  splitCurvedElement(&SQ2, &NbSQ2, SQ, &NbSQ, 9,4, 1, 4, qua);
+  splitCurvedElement(&VQ2, &NbVQ2, VQ, &NbVQ, 9,4, 3, 4, qua);
+  splitCurvedElement(&TQ2, &NbTQ2, TQ, &NbTQ, 9,4, 9, 4, qua);
+
+  int tet[8][8] = { // 8-split
+    {0,4,6,7}, {1,5,4,9}, {2,6,5,8}, {3,9,7,8},
+    {4,6,7,8}, {4,6,5,8}, {4,5,9,8}, {4,7,9,8}
+  };
+  splitCurvedElement(&SS2, &NbSS2, SS, &NbSS, 10,4, 1, 8, tet);
+  splitCurvedElement(&VS2, &NbVS2, VS, &NbVS, 10,4, 3, 8, tet);
+  splitCurvedElement(&TS2, &NbTS2, TS, &NbTS, 10,4, 9, 8, tet);
+
+  int hex[8][8] = { // 8-split
+    {0,8,20,9, 10,21,26,22}, {8,1,11,20, 21,12,23,26},
+    {9,20,13,3, 22,26,24,15}, {20,11,2,13, 26,23,14,24},
+    {10,21,26,22, 4,16,25,17}, {21,12,23,26, 16,5,18,25},
+    {22,26,24,15, 17,25,19,7}, {26,23,14,24, 25,18,6,19}
+  };
+  splitCurvedElement(&SH2, &NbSH2, SH, &NbSH, 27,8, 1, 8, hex);
+  splitCurvedElement(&VH2, &NbVH2, VH, &NbVH, 27,8, 3, 8, hex);
+  splitCurvedElement(&TH2, &NbTH2, TH, &NbTH, 27,8, 9, 8, hex);
+
+  int pri[8][8] = { // 8-split
+    {0,6,7, 8,15,16}, {1,9,6, 10,17,15}, {2,7,9, 11,16,17}, {6,9,7, 15,17,16},
+    {8,15,16, 3,12,13}, {10,17,15, 4,14,12}, {11,16,17, 5,13,14}, {15,17,16, 12,14,13}
+  };
+  splitCurvedElement(&SI2, &NbSI2, SI, &NbSI, 18,6, 1, 8, pri);
+  splitCurvedElement(&VI2, &NbVI2, VI, &NbVI, 18,6, 3, 8, pri);
+  splitCurvedElement(&TI2, &NbTI2, TI, &NbTI, 18,6, 9, 8, pri);
+
+  int pyr[6][8] = { // 6 pyramids
+    {0,5,13,6, 7}, {5,1,8,13, 9}, {6,13,10,3, 12}, {13,8,2,10, 11},
+    {7,9,11,12, 4}, {7,12,11,9, 13}
+  };
+  splitCurvedElement(&SY2, &NbSY2, SY, &NbSY, 14,5, 1, 6, pyr, 0); // don't remove yet
+  splitCurvedElement(&VY2, &NbVY2, VY, &NbVY, 14,5, 3, 6, pyr, 0);
+  splitCurvedElement(&TY2, &NbTY2, TY, &NbTY, 14,5, 9, 6, pyr, 0);
+
+  int pyr2[4][8] = { // + 4 tets to fill the holes
+    {6,12,7,13}, {7,9,5,13}, {9,11,8,13}, {12,10,11,13}
+  };
+  splitCurvedElement(&SY2, &NbSY2, SS, &NbSS, 14,4, 1, 4, pyr2);
+  splitCurvedElement(&VY2, &NbVY2, VS, &NbVS, 14,4, 3, 4, pyr2);
+  splitCurvedElement(&TY2, &NbTY2, TS, &NbTS, 14,4, 9, 4, pyr2);
+}
+
 static void generateConnectivities(List_T *list, int nbList, 
 				   int nbTimeStep, int nbVert, 
 				   smooth_data &data)
diff --git a/Post/PViewDataList.h b/Post/PViewDataList.h
index 145cadffbb54f8dd9fb30f3db340fdabecb9ce85..eab7173e098cf92eefd3b352f0e571bb18158b2f 100644
--- a/Post/PViewDataList.h
+++ b/Post/PViewDataList.h
@@ -72,6 +72,7 @@ class PViewDataList : public PViewData {
 		List_T *list, int nblist);
   void _getString(int dim, int i, int timestep, std::string &str, 
 		  double &x, double &y, double &z, double &style);
+  void _splitCurvedElements();
  public:
   PViewDataList(bool allocate=true);
   ~PViewDataList();
@@ -111,7 +112,12 @@ class PViewDataList : public PViewData {
   void getString3D(int i, int step, std::string &str, 
 		   double &x, double &y, double &z, double &style);
   void smooth();
-  bool read(std::string filename);
+  bool read(std::string name);
+  bool writePOS(std::string name, bool binary=false, bool parsed=true,
+		bool append=false);
+  bool writeSTL(std::string name);
+  bool writeTXT(std::string name);
+  bool writeMSH(std::string name);
 };
 
 #endif
diff --git a/Post/PViewDataListIO.cpp b/Post/PViewDataListIO.cpp
index 9aa8d845bca029f44ca36287da5d2198a12df181..82be6bdb9bd5d2a54fb8a45dfce067d54b6b543f 100644
--- a/Post/PViewDataListIO.cpp
+++ b/Post/PViewDataListIO.cpp
@@ -1,4 +1,4 @@
-// $Id: PViewDataListIO.cpp,v 1.1 2007-09-01 16:06:24 geuzaine Exp $
+// $Id: PViewDataListIO.cpp,v 1.2 2007-09-02 21:05:20 geuzaine Exp $
 //
 // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 //
@@ -22,8 +22,13 @@
 // Contributor(s):
 // 
 
+#include <set>
 #include "PViewDataList.h"
+#include "Numeric.h"
 #include "Message.h"
+#include "Context.h"
+
+extern Context_T CTX;
 
 bool PViewDataList::read(std::string filename)
 {
@@ -297,5 +302,479 @@ bool PViewDataList::read(std::string filename)
     
   }
 
+  fclose(fp);
+  setFileName(filename);
+  return true;
+}
+
+
+static void writeTimePOS(FILE *fp, List_T *list)
+{
+  if(List_Nbr(list) > 1){
+    fprintf(fp, "TIME{");
+    for(int i = 0; i < List_Nbr(list); i ++){
+      if(i) fprintf(fp, ",");
+      fprintf(fp, "%.16g", *(double *)List_Pointer(list, i));
+    }
+    fprintf(fp, "};\n");
+  }
+}
+
+static void writeElementPOS(FILE *fp, const char *str, int nbnod, int nb,
+			    List_T *list)
+{
+  if(nb){
+    int n = List_Nbr(list) / nb;
+    for(int i = 0; i < List_Nbr(list); i += n) {
+      double *x = (double *)List_Pointer(list, i);
+      double *y = (double *)List_Pointer(list, i + nbnod);
+      double *z = (double *)List_Pointer(list, i + 2 * nbnod);
+      fprintf(fp, "%s(", str);
+      for(int j = 0; j < nbnod; j++) {
+	if(j) fprintf(fp, ",");
+	fprintf(fp, "%.16g,%.16g,%.16g", x[j], y[j], z[j]);
+      }
+      fprintf(fp, "){");
+      for(int j = 3 * nbnod; j < n; j++) {
+	if(j - 3 * nbnod) fprintf(fp, ",");
+	fprintf(fp, "%.16g", *(double *)List_Pointer(list, i + j));
+      }
+      fprintf(fp, "};\n");
+    }
+  }
+}
+
+static void writeTextPOS(FILE *fp, int nbc, int nb, List_T *TD, List_T *TC)
+{
+  if(!nb || (nbc != 4 && nbc != 5)) return;
+  for(int j = 0; j < List_Nbr(TD); j += nbc){
+    double x, y, z, style, start, end;
+    List_Read(TD, j, &x);
+    List_Read(TD, j+1, &y);
+    if(nbc == 5)
+      List_Read(TD, j+2, &z);
+    List_Read(TD, j+nbc-2, &style);
+    if(nbc == 4)
+      fprintf(fp, "T2(%g,%g,%g){", x, y, style);
+    else
+      fprintf(fp, "T3(%g,%g,%g,%g){", x, y, z, style);
+    List_Read(TD, j+nbc-1, &start);
+    if(j+nbc*2-1 < List_Nbr(TD))
+      List_Read(TD, j+nbc*2-1, &end);
+    else
+      end = List_Nbr(TC);
+    int l = 0;
+    while(l < end-start){
+      char *str = (char*)List_Pointer(TC, (int)start + l);
+      if(l) fprintf(fp, ",");
+      fprintf(fp, "\"%s\"", str);
+      l += strlen(str)+1;
+    }
+    fprintf(fp, "};\n");
+  }
+}
+
+bool PViewDataList::writePOS(std::string name, bool binary, bool parsed, bool append)
+{
+  FILE *fp = fopen(name.c_str(), 
+		   append ? (binary ? "ab" : "a") : (binary ? "wb" : "w"));
+  if(!fp){
+    Msg(GERROR, "Unable to open file '%s'", name.c_str());
+    return false;
+  }
+
+  if(!parsed && !append){
+    fprintf(fp, "$PostFormat /* Gmsh 1.3, %s */\n", binary ? "binary" : "ascii");
+    fprintf(fp, "1.3 %d %d\n", binary, (int)sizeof(double));
+    fprintf(fp, "$EndPostFormat\n");
+  }
+
+  char str[256];
+  strcpy(str, getName().c_str());
+  for(int i = 0; i < (int)strlen(str); i++)
+    if(str[i] == ' ') str[i] = '^';
+
+  if(!parsed){
+    fprintf(fp, "$View /* %s */\n", getName().c_str());
+    fprintf(fp, "%s ", str);
+    fprintf(fp, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d "
+	    "%d %d %d %d %d %d %d %d %d %d %d %d\n",
+	    List_Nbr(Time),
+	    NbSP, NbVP, NbTP, NbSL, NbVL, NbTL,
+	    NbST, NbVT, NbTT, NbSQ, NbVQ, NbTQ,
+	    NbSS, NbVS, NbTS, NbSH, NbVH, NbTH,
+	    NbSI, NbVI, NbTI, NbSY, NbVY, NbTY,
+	    NbT2, List_Nbr(T2C), NbT3, List_Nbr(T3C));
+    int f = binary ? LIST_FORMAT_BINARY : LIST_FORMAT_ASCII;
+    if(binary) {
+      int one = 1;
+      if(!fwrite(&one, sizeof(int), 1, fp)){
+	Msg(GERROR, "Write error");
+	return false;
+      }
+    }
+    List_WriteToFile(Time, fp, f);
+    List_WriteToFile(SP, fp, f); List_WriteToFile(VP, fp, f); 
+    List_WriteToFile(TP, fp, f); List_WriteToFile(SL, fp, f);
+    List_WriteToFile(VL, fp, f); List_WriteToFile(TL, fp, f);
+    List_WriteToFile(ST, fp, f); List_WriteToFile(VT, fp, f);
+    List_WriteToFile(TT, fp, f); List_WriteToFile(SQ, fp, f);
+    List_WriteToFile(VQ, fp, f); List_WriteToFile(TQ, fp, f);
+    List_WriteToFile(SS, fp, f); List_WriteToFile(VS, fp, f);
+    List_WriteToFile(TS, fp, f); List_WriteToFile(SH, fp, f);
+    List_WriteToFile(VH, fp, f); List_WriteToFile(TH, fp, f);
+    List_WriteToFile(SI, fp, f); List_WriteToFile(VI, fp, f);
+    List_WriteToFile(TI, fp, f); List_WriteToFile(SY, fp, f);
+    List_WriteToFile(VY, fp, f); List_WriteToFile(TY, fp, f);
+    List_WriteToFile(T2D, fp, f); List_WriteToFile(T2C, fp, f);
+    List_WriteToFile(T3D, fp, f); List_WriteToFile(T3C, fp, f);
+    fprintf(fp, "\n");
+    fprintf(fp, "$EndView\n");
+  }
+  else{
+    fprintf(fp, "View \"%s\" {\n", getName().c_str());
+    writeTimePOS(fp, Time);
+    writeElementPOS(fp, "SP", 1, NbSP, SP); writeElementPOS(fp, "VP", 1, NbVP, VP);
+    writeElementPOS(fp, "TP", 1, NbTP, TP); writeElementPOS(fp, "SL", 2, NbSL, SL);
+    writeElementPOS(fp, "VL", 2, NbVL, VL); writeElementPOS(fp, "TL", 2, NbTL, TL);
+    writeElementPOS(fp, "ST", 3, NbST, ST); writeElementPOS(fp, "VT", 3, NbVT, VT);
+    writeElementPOS(fp, "TT", 3, NbTT, TT); writeElementPOS(fp, "SQ", 4, NbSQ, SQ);
+    writeElementPOS(fp, "VQ", 4, NbVQ, VQ); writeElementPOS(fp, "TQ", 4, NbTQ, TQ);
+    writeElementPOS(fp, "SS", 4, NbSS, SS); writeElementPOS(fp, "VS", 4, NbVS, VS);
+    writeElementPOS(fp, "TS", 4, NbTS, TS); writeElementPOS(fp, "SH", 8, NbSH, SH);
+    writeElementPOS(fp, "VH", 8, NbVH, VH); writeElementPOS(fp, "TH", 8, NbTH, TH);
+    writeElementPOS(fp, "SI", 6, NbSI, SI); writeElementPOS(fp, "VI", 6, NbVI, VI);
+    writeElementPOS(fp, "TI", 6, NbTI, TI); writeElementPOS(fp, "SY", 5, NbSY, SY);
+    writeElementPOS(fp, "VY", 5, NbVY, VY); writeElementPOS(fp, "TY", 5, NbTY, TY);
+    writeTextPOS(fp, 4, NbT2, T2D, T2C); writeTextPOS(fp, 5, NbT3, T3D, T3C);
+    fprintf(fp, "};\n");
+  }
+
+  fclose(fp);
+  return true;
+}
+
+static void writeElementSTL(FILE *fp, int nbelm, List_T *list, int nbnod)
+{
+  if(!nbelm) return;
+  int nb = List_Nbr(list) / nbelm;
+  for(int i = 0; i < List_Nbr(list); i+=nb){
+    double *x = (double*)List_Pointer(list, i);
+    double n[3];
+    normal3points(x[0], x[3], x[6],
+		  x[1], x[4], x[7],
+		  x[2], x[5], x[8], n);
+    if(nbnod == 3){
+      fprintf(fp, "facet normal %g %g %g\n", n[0], n[1], n[2]);
+      fprintf(fp, "  outer loop\n");
+      fprintf(fp, "    vertex %g %g %g\n", x[0], x[3], x[6]);
+      fprintf(fp, "    vertex %g %g %g\n", x[1], x[4], x[7]);
+      fprintf(fp, "    vertex %g %g %g\n", x[2], x[5], x[8]);
+      fprintf(fp, "  endloop\n");
+      fprintf(fp, "endfacet\n");
+    }
+    else{
+      fprintf(fp, "facet normal %g %g %g\n", n[0], n[1], n[2]);
+      fprintf(fp, "  outer loop\n");
+      fprintf(fp, "    vertex %g %g %g\n", x[0], x[4], x[8]);
+      fprintf(fp, "    vertex %g %g %g\n", x[1], x[5], x[9]);
+      fprintf(fp, "    vertex %g %g %g\n", x[2], x[6], x[10]);
+      fprintf(fp, "  endloop\n");
+      fprintf(fp, "endfacet\n");
+      fprintf(fp, "facet normal %g %g %g\n", n[0], n[1], n[2]);
+      fprintf(fp, "  outer loop\n");
+      fprintf(fp, "    vertex %g %g %g\n", x[0], x[4], x[8]);
+      fprintf(fp, "    vertex %g %g %g\n", x[2], x[6], x[10]);
+      fprintf(fp, "    vertex %g %g %g\n", x[3], x[7], x[11]);
+      fprintf(fp, "  endloop\n");
+      fprintf(fp, "endfacet\n");
+    }
+  }
+}
+
+bool PViewDataList::writeSTL(std::string name)
+{
+  FILE *fp = fopen(name.c_str(), "w");
+  if(!fp){
+    Msg(GERROR, "Unable to open file '%s'", name.c_str());
+    return false;
+  }
+
+  if(!NbST && !NbVT && !NbTT && !NbSQ && !NbVQ && !NbTQ){
+    Msg(GERROR, "No surface elements to save");
+    return false;
+  }
+
+  fprintf(fp, "solid Created by Gmsh\n");
+  writeElementSTL(fp, NbST, ST, 3);
+  writeElementSTL(fp, NbVT, VT, 3);
+  writeElementSTL(fp, NbTT, TT, 3);
+  writeElementSTL(fp, NbSQ, SQ, 4);
+  writeElementSTL(fp, NbVQ, VQ, 4);
+  writeElementSTL(fp, NbTQ, TQ, 4);
+  fprintf(fp, "endsolid Created by Gmsh\n");
+
+  fclose(fp);
+  return true;
+}
+
+static void writeElementTXT(FILE *file, int nbelm, List_T *list,
+			    int nbnod, int nbcomp, int nbtime)
+{
+  if(!nbelm) return;
+  int nb = List_Nbr(list) / nbelm;
+  for(int i = 0; i < List_Nbr(list); i += nb){
+    double *x = (double*)List_Pointer(list, i);
+    for(int j = 0; j < nbnod * (3 + nbcomp * nbtime); j++)
+      fprintf(file, "%.16g ", x[j]);
+    fprintf(file, "\n");
+  }
+  fprintf(file, "\n");
+}
+
+bool PViewDataList::writeTXT(std::string name)
+{
+  FILE *fp = fopen(name.c_str(), "w");
+  if(!fp){
+    Msg(GERROR, "Unable to open file '%s'", name.c_str());
+    return false;
+  }
+
+  writeElementTXT(fp, NbSP, SP, 1, 1, NbTimeStep);
+  writeElementTXT(fp, NbVP, VP, 1, 3, NbTimeStep);
+  writeElementTXT(fp, NbTP, TP, 1, 9, NbTimeStep);
+  writeElementTXT(fp, NbSL, SL, 2, 1, NbTimeStep);
+  writeElementTXT(fp, NbVL, VL, 2, 3, NbTimeStep);
+  writeElementTXT(fp, NbTL, TL, 2, 9, NbTimeStep);
+  writeElementTXT(fp, NbST, ST, 3, 1, NbTimeStep);
+  writeElementTXT(fp, NbVT, VT, 3, 3, NbTimeStep);
+  writeElementTXT(fp, NbTT, TT, 3, 9, NbTimeStep);
+  writeElementTXT(fp, NbSQ, SQ, 4, 1, NbTimeStep);
+  writeElementTXT(fp, NbVQ, VQ, 4, 3, NbTimeStep);
+  writeElementTXT(fp, NbTQ, TQ, 4, 9, NbTimeStep);
+  writeElementTXT(fp, NbSS, SS, 4, 1, NbTimeStep);
+  writeElementTXT(fp, NbVS, VS, 4, 3, NbTimeStep);
+  writeElementTXT(fp, NbTS, TS, 4, 9, NbTimeStep);
+  writeElementTXT(fp, NbSH, SH, 8, 1, NbTimeStep);
+  writeElementTXT(fp, NbVH, VH, 8, 3, NbTimeStep);
+  writeElementTXT(fp, NbTH, TH, 8, 9, NbTimeStep);
+  writeElementTXT(fp, NbSI, SI, 6, 1, NbTimeStep);
+  writeElementTXT(fp, NbVI, VI, 6, 3, NbTimeStep);
+  writeElementTXT(fp, NbTI, TI, 6, 9, NbTimeStep);
+  writeElementTXT(fp, NbSY, SY, 5, 1, NbTimeStep);
+  writeElementTXT(fp, NbVY, VY, 5, 3, NbTimeStep);
+  writeElementTXT(fp, NbTY, TY, 5, 9, NbTimeStep);
+
+  fclose(fp);
   return true;
 }
+
+class pVertex{
+ public:
+  int Num;
+  double X, Y, Z;
+  pVertex() : Num(0), X(0.), Y(0.), Z(0.) {}
+  pVertex(double x, double y, double z) : Num(0), X(x), Y(y), Z(z) {}
+};
+
+class pVertexLessThan{
+ public:
+  bool operator()(const pVertex ent1, const pVertex ent2) const
+  {
+    double tol = CTX.lc * 1.e-10 ;
+    if(ent1.X - ent2.X  >  tol) return true;
+    if(ent1.X - ent2.X  < -tol) return false;
+    if(ent1.Y - ent2.Y  >  tol) return true;
+    if(ent1.Y - ent2.Y  < -tol) return false;
+    if(ent1.Z - ent2.Z  >  tol) return true;
+    return false;
+  }
+};
+
+static void getNodeMSH(int nbelm, List_T *list, int nbnod, int nbcomp, 
+		       std::set<pVertex, pVertexLessThan> *nodes,
+		       int *numelm)
+{
+  if(!nbelm) return;
+  int nb = List_Nbr(list) / nbelm;
+  for(int i = 0; i < List_Nbr(list); i+=nb){
+    double *x = (double *)List_Pointer_Fast(list, i);
+    double *y = (double *)List_Pointer_Fast(list, i + nbnod);
+    double *z = (double *)List_Pointer_Fast(list, i + 2 * nbnod);
+    for(int j = 0; j < nbnod; j++) {
+      pVertex n(x[j], y[j], z[j]);
+      std::set<pVertex, pVertexLessThan>::iterator it = nodes->find(n);
+      if(it == nodes->end()){
+	n.Num = nodes->size() + 1;
+	nodes->insert(n);
+      }
+    }
+    (*numelm)++;
+  }
+}
+
+static void writeElementMSH(FILE *fp, int num, int nbnod, pVertex nod[8], 
+			    int nbcomp, double *vals, int dim)
+{
+  // compute average value in elm
+  double d = 0.;
+  for(int k = 0; k < nbnod; k++) {
+    double *v = &vals[nbcomp * k];
+    switch(nbcomp) {
+    case 1: // scalar
+      d += v[0];
+      break;
+    case 3 : // vector
+      d += sqrt(DSQR(v[0]) + DSQR(v[1]) + DSQR(v[2]));
+      break;
+    case 9 : // tensor
+      d += ComputeVonMises(v);
+      break;
+    }
+  }
+  d /= (double)nbnod;
+
+  // assign val as elementary region number
+  int ele = (int)fabs(d), phys = 1;
+  
+  switch(dim){
+  case 0:
+    fprintf(fp, "%d 15 %d %d 1 %d\n", num, phys, ele, nod[0].Num);
+    break;
+  case 1:
+    fprintf(fp, "%d 1 %d %d 2 %d %d\n", num, phys, ele, nod[0].Num, nod[1].Num);
+    break;
+  case 2:
+    if(nbnod == 3)
+      fprintf(fp, "%d 2 %d %d 3 %d %d %d\n", num, phys, ele, 
+	      nod[0].Num, nod[1].Num, nod[2].Num);
+    else
+      fprintf(fp, "%d 3 %d %d 4 %d %d %d %d\n", num, phys, ele, 
+	      nod[0].Num, nod[1].Num, nod[2].Num, nod[3].Num);
+    break;
+  case 3:
+  default:
+    if(nbnod == 4)
+      fprintf(fp, "%d 4 %d %d 4 %d %d %d %d\n", num, phys, ele, 
+	      nod[0].Num, nod[1].Num, nod[2].Num, nod[3].Num);
+    else if(nbnod == 5)
+      fprintf(fp, "%d 7 %d %d 5 %d %d %d %d %d\n", num, phys, ele, 
+	      nod[0].Num, nod[1].Num, nod[2].Num, nod[3].Num, nod[4].Num);
+    else if(nbnod == 6)
+      fprintf(fp, "%d 6 %d %d 6 %d %d %d %d %d %d\n", num, phys, ele, 
+	      nod[0].Num, nod[1].Num, nod[2].Num, nod[3].Num, nod[4].Num, 
+	      nod[5].Num);
+    else
+      fprintf(fp, "%d 5 %d %d 8 %d %d %d %d %d %d %d %d\n", num, phys, ele, 
+	      nod[0].Num, nod[1].Num, nod[2].Num, nod[3].Num, nod[4].Num, 
+	      nod[5].Num, nod[6].Num, nod[7].Num);
+    break;
+  }
+}
+
+static void writeElementsMSH(FILE *fp, int nbelm, List_T *list,
+			     int nbnod, int nbcomp, int dim, 
+			     std::set<pVertex, pVertexLessThan> *nodes,
+			     int *numelm)
+{
+  if(!nbelm) return;
+  pVertex nod[8];
+  int nb = List_Nbr(list) / nbelm;
+  for(int i = 0; i < List_Nbr(list); i+=nb){
+    double *x = (double *)List_Pointer_Fast(list, i);
+    double *y = (double *)List_Pointer_Fast(list, i + nbnod);
+    double *z = (double *)List_Pointer_Fast(list, i + 2 * nbnod);
+    double *v = (double *)List_Pointer_Fast(list, i + 3 * nbnod);
+    for(int j = 0; j < nbnod; j++) {
+      pVertex n(x[j], y[j], z[j]);
+      std::set<pVertex, pVertexLessThan>::iterator it = nodes->find(n);
+      if(it == nodes->end()){
+	Msg(GERROR, "Unknown node in element");
+	return;
+      }
+      else{
+	nod[j] = (pVertex)(*it);
+      }
+    }
+    (*numelm)++;
+    writeElementMSH(fp, *numelm, nbnod, nod, nbcomp, v, dim);
+  }
+}
+
+bool PViewDataList::writeMSH(std::string name)
+{
+  FILE *fp = fopen(name.c_str(), "w");
+  if(!fp){
+    Msg(GERROR, "Unable to open file '%s'", name.c_str());
+    return false;
+  }
+
+  std::set<pVertex, pVertexLessThan> nodes;
+  int numelm = 0;
+  getNodeMSH(NbSP, SP, 1, 1, &nodes, &numelm);
+  getNodeMSH(NbVP, VP, 1, 3, &nodes, &numelm);
+  getNodeMSH(NbTP, TP, 1, 9, &nodes, &numelm);
+  getNodeMSH(NbSL, SL, 2, 1, &nodes, &numelm);
+  getNodeMSH(NbVL, VL, 2, 3, &nodes, &numelm);
+  getNodeMSH(NbTL, TL, 2, 9, &nodes, &numelm);
+  getNodeMSH(NbST, ST, 3, 1, &nodes, &numelm);
+  getNodeMSH(NbVT, VT, 3, 3, &nodes, &numelm);
+  getNodeMSH(NbTT, TT, 3, 9, &nodes, &numelm);
+  getNodeMSH(NbSQ, SQ, 4, 1, &nodes, &numelm);
+  getNodeMSH(NbVQ, VQ, 4, 3, &nodes, &numelm);
+  getNodeMSH(NbTQ, TQ, 4, 9, &nodes, &numelm);
+  getNodeMSH(NbSS, SS, 4, 1, &nodes, &numelm);
+  getNodeMSH(NbVS, VS, 4, 3, &nodes, &numelm);
+  getNodeMSH(NbTS, TS, 4, 9, &nodes, &numelm);
+  getNodeMSH(NbSH, SH, 8, 1, &nodes, &numelm);
+  getNodeMSH(NbVH, VH, 8, 3, &nodes, &numelm);
+  getNodeMSH(NbTH, TH, 8, 9, &nodes, &numelm);
+  getNodeMSH(NbSI, SI, 6, 1, &nodes, &numelm);
+  getNodeMSH(NbVI, VI, 6, 3, &nodes, &numelm);
+  getNodeMSH(NbTI, TI, 6, 9, &nodes, &numelm);
+  getNodeMSH(NbSY, SY, 5, 1, &nodes, &numelm);
+  getNodeMSH(NbVY, VY, 5, 3, &nodes, &numelm);
+  getNodeMSH(NbTY, TY, 5, 9, &nodes, &numelm);
+
+  fprintf(fp, "$NOD\n");
+  fprintf(fp, "%d\n", (int)nodes.size());
+  std::set<pVertex, pVertexLessThan>::iterator it = nodes.begin();
+  for(; it != nodes.end(); ++it){
+    pVertex n = (pVertex)(*it);
+    fprintf(fp, "%d %.16g %.16g %.16g\n", n.Num, n.X, n.Y, n.Z);
+  }
+  fprintf(fp, "$ENDNOD\n");
+
+  fprintf(fp, "$ELM\n");
+  fprintf(fp, "%d\n", numelm);
+  numelm = 0;
+  writeElementsMSH(fp, NbSP, SP, 1, 1, 0, &nodes, &numelm);
+  writeElementsMSH(fp, NbVP, VP, 1, 3, 0, &nodes, &numelm);
+  writeElementsMSH(fp, NbTP, TP, 1, 9, 0, &nodes, &numelm);
+  writeElementsMSH(fp, NbSL, SL, 2, 1, 1, &nodes, &numelm);
+  writeElementsMSH(fp, NbVL, VL, 2, 3, 1, &nodes, &numelm);
+  writeElementsMSH(fp, NbTL, TL, 2, 9, 1, &nodes, &numelm);
+  writeElementsMSH(fp, NbST, ST, 3, 1, 2, &nodes, &numelm);
+  writeElementsMSH(fp, NbVT, VT, 3, 3, 2, &nodes, &numelm);
+  writeElementsMSH(fp, NbTT, TT, 3, 9, 2, &nodes, &numelm);
+  writeElementsMSH(fp, NbSQ, SQ, 4, 1, 2, &nodes, &numelm);
+  writeElementsMSH(fp, NbVQ, VQ, 4, 3, 2, &nodes, &numelm);
+  writeElementsMSH(fp, NbTQ, TQ, 4, 9, 2, &nodes, &numelm);
+  writeElementsMSH(fp, NbSS, SS, 4, 1, 3, &nodes, &numelm);
+  writeElementsMSH(fp, NbVS, VS, 4, 3, 3, &nodes, &numelm);
+  writeElementsMSH(fp, NbTS, TS, 4, 9, 3, &nodes, &numelm);
+  writeElementsMSH(fp, NbSH, SH, 8, 1, 3, &nodes, &numelm);
+  writeElementsMSH(fp, NbVH, VH, 8, 3, 3, &nodes, &numelm);
+  writeElementsMSH(fp, NbTH, TH, 8, 9, 3, &nodes, &numelm);
+  writeElementsMSH(fp, NbSI, SI, 6, 1, 3, &nodes, &numelm);
+  writeElementsMSH(fp, NbVI, VI, 6, 3, 3, &nodes, &numelm);
+  writeElementsMSH(fp, NbTI, TI, 6, 9, 3, &nodes, &numelm);
+  writeElementsMSH(fp, NbSY, SY, 5, 1, 3, &nodes, &numelm);
+  writeElementsMSH(fp, NbVY, VY, 5, 3, 3, &nodes, &numelm);
+  writeElementsMSH(fp, NbTY, TY, 5, 9, 3, &nodes, &numelm);
+  fprintf(fp, "$ENDELM\n");
+
+  fclose(fp);
+  return true;
+}
+