From 5e3944eefe9410f184d54c44644d590bffe9963b Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Mon, 10 Mar 2008 16:01:17 +0000
Subject: [PATCH] - simple IO for new node data - notion of partitions and
 interpolationScheme - move string utils in separate file

---
 Common/Makefile            |   4 +-
 Common/StringUtils.cpp     |  74 +++++++++++++++++++++
 Common/StringUtils.h       |  30 +++++++++
 Fltk/Makefile              |   9 +--
 Fltk/Opengl.cpp            |  37 ++---------
 Geo/GModelIO_Mesh.cpp      |  27 +-------
 Geo/Makefile               |   4 +-
 Makefile                   |   6 +-
 Parser/OpenFile.cpp        |   8 ++-
 Post/Makefile              |  10 +--
 Post/PView.cpp             |  27 ++++----
 Post/PView.h               |   6 +-
 Post/PViewData.h           |   4 +-
 Post/PViewDataGModel.cpp   |  14 +++-
 Post/PViewDataGModel.h     |  17 ++++-
 Post/PViewDataGModelIO.cpp | 130 +++++++++++++++++++++++++++++--------
 Post/PViewDataList.cpp     |   3 +-
 Post/PViewDataList.h       |   2 +-
 Post/PViewDataListIO.cpp   |   8 ++-
 19 files changed, 293 insertions(+), 127 deletions(-)
 create mode 100644 Common/StringUtils.cpp
 create mode 100644 Common/StringUtils.h

diff --git a/Common/Makefile b/Common/Makefile
index 37ee59fe3a..5b76aa2fb2 100644
--- a/Common/Makefile
+++ b/Common/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.159 2008-02-24 19:59:02 geuzaine Exp $
+# $Id: Makefile,v 1.160 2008-03-10 16:01:15 geuzaine Exp $
 #
 # Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 #
@@ -39,6 +39,7 @@ SRC = Context.cpp\
       Trackball.cpp\
       VertexArray.cpp\
       SmoothData.cpp\
+      StringUtils.cpp\
       License.cpp
 
 OBJ = ${SRC:.cpp=${OBJEXT}}
@@ -113,4 +114,5 @@ VertexArray.o: VertexArray.cpp VertexArray.h ../Geo/SVector3.h \
   ../Numeric/NumericEmbedded.h
 SmoothData.o: SmoothData.cpp SmoothData.h ../Numeric/Numeric.h \
   ../Numeric/NumericEmbedded.h
+StringUtils.o: StringUtils.cpp StringUtils.h
 License.o: License.cpp Message.h
diff --git a/Common/StringUtils.cpp b/Common/StringUtils.cpp
new file mode 100644
index 0000000000..2e9f590836
--- /dev/null
+++ b/Common/StringUtils.cpp
@@ -0,0 +1,74 @@
+// $Id: StringUtils.cpp,v 1.1 2008-03-10 16:01:15 geuzaine Exp $
+//
+// Copyright (C) 1997-2008 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 "StringUtils.h"
+
+void swapBytes(char *array, int size, int n)
+{
+  char *x = new char[size];
+  for(int i = 0; i < n; i++) {
+    char *a = &array[i * size];
+    memcpy(x, a, size);
+    for(int c = 0; c < size; c++)
+      a[size - 1 - c] = x[c];
+  }
+  delete [] x;
+}
+
+std::string extractDoubleQuotedString(const char *str, int len)
+{
+  char *c = strstr(str, "\"");
+  if(!c) return "";
+  std::string ret;
+  for(int i = 1; i < len; i++) {
+    if(c[i] == '"' || c[i] == EOF || c[i] == '\n' || c[i] == '\r') break;
+    ret.push_back(c[i]);
+  }
+  return ret;
+}
+
+
+std::string sanitizeTeXString(const char *in, int equation)
+{
+  // if there is a '$' or a '\' in the string, assume the author knows
+  // what he's doing:
+  if(strstr(in, "$") || strstr(in, "\\"))
+    return std::string(in);
+
+  std::string out;
+
+  if(equation) out.push_back('$');
+
+  // otherwise, escape the following special characters:
+  char bad[8] = { '%', '^', '#', '%', '&', '_', '{', '}' };
+  while(*in){
+    for(unsigned int i = 0; i < sizeof(bad); i++){
+      if(*in == bad[i]){
+	out.push_back('\\');
+	break;
+      }
+    }
+    out.push_back(*in++);
+  }
+
+  if(equation) out.push_back('$');
+  return out;
+}
diff --git a/Common/StringUtils.h b/Common/StringUtils.h
new file mode 100644
index 0000000000..74f6cdded2
--- /dev/null
+++ b/Common/StringUtils.h
@@ -0,0 +1,30 @@
+#ifndef _STRING_UTIL_H_
+#define _STRING_UTIL_H_
+
+// Copyright (C) 1997-2008 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 <string.h>
+#include <string>
+
+void swapBytes(char *array, int size, int n);
+std::string extractDoubleQuotedString(const char *str, int len);
+std::string sanitizeTeXString(const char *in, int equation);
+
+#endif
diff --git a/Fltk/Makefile b/Fltk/Makefile
index 29f4857e39..5e08713106 100644
--- a/Fltk/Makefile
+++ b/Fltk/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.171 2008-02-24 19:59:02 geuzaine Exp $
+# $Id: Makefile,v 1.172 2008-03-10 16:01:15 geuzaine Exp $
 #
 # Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 #
@@ -197,9 +197,10 @@ Opengl.o: Opengl.cpp ../Common/GmshUI.h ../Common/GmshDefines.h \
   ../Geo/GEntity.h ../Geo/GVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h \
   ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/GFace.h ../Geo/GEntity.h \
   ../Geo/GPoint.h ../Geo/GEdgeLoop.h ../Geo/GEdge.h ../Geo/SPoint2.h \
-  ../Geo/SVector3.h ../Geo/Pair.h ../Geo/GRegion.h ../Geo/GEntity.h GUI.h \
-  Opengl_Window.h Colorbar_Window.h ../Post/ColorTable.h Popup_Button.h \
-  SpherePosition_Widget.h ../Graphics/gl2ps.h
+  ../Geo/SVector3.h ../Geo/Pair.h ../Geo/GRegion.h ../Geo/GEntity.h \
+  ../Common/StringUtils.h GUI.h Opengl_Window.h Colorbar_Window.h \
+  ../Post/ColorTable.h Popup_Button.h SpherePosition_Widget.h \
+  ../Graphics/gl2ps.h
 Opengl_Window.o: Opengl_Window.cpp ../Common/GmshUI.h \
   ../Common/GmshDefines.h ../Common/Message.h ../Numeric/Numeric.h \
   ../Numeric/NumericEmbedded.h ../Common/Context.h ../DataStr/List.h \
diff --git a/Fltk/Opengl.cpp b/Fltk/Opengl.cpp
index 6fb1a55ef9..9b63d20546 100644
--- a/Fltk/Opengl.cpp
+++ b/Fltk/Opengl.cpp
@@ -1,4 +1,4 @@
-// $Id: Opengl.cpp,v 1.78 2008-02-23 15:30:07 geuzaine Exp $
+// $Id: Opengl.cpp,v 1.79 2008-03-10 16:01:15 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -19,13 +19,13 @@
 // 
 // Please report all bugs and problems to <gmsh@geuz.org>.
 
-#include <string.h>
 #include "GmshUI.h"
 #include "GmshDefines.h"
 #include "Numeric.h"
 #include "Context.h"
 #include "Draw.h"
 #include "SelectBuffer.h"
+#include "StringUtils.h"
 #include "GUI.h"
 #include "gl2ps.h"
 
@@ -46,34 +46,6 @@ void Draw(void)
   WID->redraw_opengl();
 }
 
-void SanitizeTeXString(const char *in, char *out)
-{
-  // if there is a '$' or a '\' in the string, assume the author knows
-  // what he's doing:
-  if(strstr(in, "$") || strstr(in, "\\")){
-    strcpy(out, in);
-    return;
-  }
-
-  if(CTX.print.tex_as_equation) *out++ = '$';
-
-  // otherwise, escape the following special characters:
-  char bad[8] = { '%', '^', '#', '%', '&', '_', '{', '}' };
-  while(*in){
-    for(unsigned int i = 0; i < sizeof(bad); i++){
-      if(*in == bad[i]){
-	*out++ = '\\';
-	break;
-      }
-    }
-    *out++ = *in++;
-  }
-
-  if(CTX.print.tex_as_equation) *out++ = '$';
-
-  *out = '\0';
-}
-
 void Draw_String(const char *s, const char *font_name, int font_enum, int font_size, int align)
 {
   if(CTX.printing && !CTX.print.text) return;
@@ -111,8 +83,7 @@ void Draw_String(const char *s, const char *font_name, int font_enum, int font_s
   }
   else{
     if(CTX.print.format == FORMAT_TEX){
-      char tmp[1024];
-      SanitizeTeXString(s, tmp);
+      std::string tmp = sanitizeTeXString(s, CTX.print.tex_as_equation);
       int opt;
       switch(align){
       case 1: opt = GL2PS_TEXT_B;   break; // bottom center
@@ -125,7 +96,7 @@ void Draw_String(const char *s, const char *font_name, int font_enum, int font_s
       case 8: opt = GL2PS_TEXT_CR;  break; // center right
       default: opt = GL2PS_TEXT_BL; break; // bottom left
       }
-      gl2psTextOpt(tmp, font_name, font_size, opt, 0.);
+      gl2psTextOpt(tmp.c_str(), font_name, font_size, opt, 0.);
     }
     else if(CTX.print.eps_quality && (CTX.print.format == FORMAT_PS ||
 				      CTX.print.format == FORMAT_EPS ||
diff --git a/Geo/GModelIO_Mesh.cpp b/Geo/GModelIO_Mesh.cpp
index 8538698231..0916eb09b9 100644
--- a/Geo/GModelIO_Mesh.cpp
+++ b/Geo/GModelIO_Mesh.cpp
@@ -1,4 +1,4 @@
-// $Id: GModelIO_Mesh.cpp,v 1.40 2008-03-08 22:03:12 geuzaine Exp $
+// $Id: GModelIO_Mesh.cpp,v 1.41 2008-03-10 16:01:15 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -30,6 +30,7 @@
 #include "discreteFace.h"
 #include "discreteEdge.h"
 #include "discreteVertex.h"
+#include "StringUtils.h"
 
 #if defined(HAVE_GMSH_EMBEDDED)
 #  include "GmshEmbedded.h"
@@ -37,18 +38,6 @@
 #  include "Message.h"
 #endif
 
-static void swapBytes(char *array, int size, int n)
-{
-  char *x = new char[size];
-  for(int i = 0; i < n; i++) {
-    char *a = &array[i * size];
-    memcpy(x, a, size);
-    for(int c = 0; c < size; c++)
-      a[size - 1 - c] = x[c];
-  }
-  delete [] x;
-}
-
 template<class T>
 static void addElements(std::vector<T*> &dst, const std::vector<MElement*> &src)
 {
@@ -262,18 +251,6 @@ static void createElementMSH(GModel *m, int num, int type, int physical,
   if(part) m->getMeshPartitions().insert(part);
 }
 
-std::string extractDoubleQuotedString(char *str, int len)
-{
-  char *c = strstr(str, "\"");
-  if(!c) return "";
-  std::string ret;
-  for(int i = 1; i < len; i++) {
-    if(c[i] == '"' || c[i] == EOF || c[i] == '\n' || c[i] == '\r') break;
-    ret.push_back(c[i]);
-  }
-  return ret;
-}
-
 int GModel::readMSH(const std::string &name)
 {
   FILE *fp = fopen(name.c_str(), "rb");
diff --git a/Geo/Makefile b/Geo/Makefile
index b2d856f1ae..bc2301739b 100644
--- a/Geo/Makefile
+++ b/Geo/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.190 2008-02-24 19:59:02 geuzaine Exp $
+# $Id: Makefile,v 1.191 2008-03-10 16:01:15 geuzaine Exp $
 #
 # Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 #
@@ -185,7 +185,7 @@ GModelIO_Mesh.o: GModelIO_Mesh.cpp GModel.h GVertex.h GEntity.h Range.h \
   ../Numeric/Numeric.h ../Numeric/NumericEmbedded.h ../DataStr/List.h \
   ../DataStr/Tree.h ../DataStr/avl.h ExtrudeParams.h \
   ../Common/SmoothData.h discreteFace.h discreteEdge.h discreteVertex.h \
-  ../Common/Message.h
+  ../Common/StringUtils.h ../Common/Message.h
 GModelIO_OCC.o: GModelIO_OCC.cpp GModelIO_OCC.h GModel.h GVertex.h \
   GEntity.h Range.h SPoint3.h SBoundingBox3d.h GPoint.h SPoint2.h GEdge.h \
   SVector3.h GFace.h GEdgeLoop.h Pair.h GRegion.h OCCIncludes.h \
diff --git a/Makefile b/Makefile
index f5da856ed5..961ace2828 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.472 2008-03-03 22:23:05 geuzaine Exp $
+# $Id: Makefile,v 1.473 2008-03-10 16:01:15 geuzaine Exp $
 #
 # Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 #
@@ -41,12 +41,12 @@ GMSH_API = Geo/GModel.h\
            Geo/Pair.h Geo/Range.h\
            Common/GmshDefines.h Common/GmshVersion.h
 
-GMSH_EMBEDDED = ${GMSH_API} Geo/discrete*.h Numeric/NumericEmbedded.h\
+GMSH_EMBEDDED = ${GMSH_API} Geo/discrete*.h\
                 Geo/GModel.cpp Geo/GModelIO_Mesh.cpp\
                 Geo/GEntity.cpp Geo/GVertex.cpp Geo/GEdge.cpp\
                 Geo/GEdgeLoop.cpp Geo/GFace.cpp Geo/GRegion.cpp\
                 Geo/MElement.cpp Geo/MFace.cpp Geo/MVertex.cpp\
-                Numeric/NumericEmbedded.cpp\
+                Common/StringUtils.{cpp,h} Numeric/NumericEmbedded.{cpp,h}\
                 utils/embed/GmshEmbedded.{cpp,h} utils/embed/Makefile
 
 all: link
diff --git a/Parser/OpenFile.cpp b/Parser/OpenFile.cpp
index 0f165ba0bf..68e8782921 100644
--- a/Parser/OpenFile.cpp
+++ b/Parser/OpenFile.cpp
@@ -1,4 +1,4 @@
-// $Id: OpenFile.cpp,v 1.177 2008-02-23 15:30:10 geuzaine Exp $
+// $Id: OpenFile.cpp,v 1.178 2008-03-10 16:01:16 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -47,7 +47,8 @@ extern GUI *WID;
 
 extern Context_T CTX;
 
-void FixRelativePath(const char *in, char *out){
+void FixRelativePath(const char *in, char *out)
+{
   if(in[0] == '/' || in[0] == '\\' || (strlen(in)>2 && in[1] == ':')){
     // do nothing: 'in' is an absolute path
     strcpy(out, in);
@@ -62,7 +63,8 @@ void FixRelativePath(const char *in, char *out){
   }
 }
 
-void FixWindowsPath(const char *in, char *out){
+void FixWindowsPath(const char *in, char *out)
+{
 #if defined(__CYGWIN__)
   cygwin_conv_to_win32_path(in, out);
 #else
diff --git a/Post/Makefile b/Post/Makefile
index 63a667e357..2a9ab093cd 100644
--- a/Post/Makefile
+++ b/Post/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.31 2008-02-24 19:59:03 geuzaine Exp $
+# $Id: Makefile,v 1.32 2008-03-10 16:01:16 geuzaine Exp $
 #
 # Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 #
@@ -73,7 +73,7 @@ PView.o: PView.cpp PView.h PViewData.h ../Geo/SBoundingBox3d.h \
   ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
   ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SBoundingBox3d.h \
   ../Common/VertexArray.h ../Common/Context.h ../Common/SmoothData.h \
-  ../Common/Message.h
+  ../Common/StringUtils.h ../Common/Message.h
 PViewData.o: PViewData.cpp PViewData.h ../Geo/SBoundingBox3d.h \
   ../Geo/SPoint3.h
 PViewDataIO.o: PViewDataIO.cpp ../Common/Message.h ../Numeric/Numeric.h \
@@ -100,7 +100,7 @@ PViewDataGModel.o: PViewDataGModel.cpp PViewDataGModel.h PViewData.h \
   ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SBoundingBox3d.h \
   ../Geo/MElement.h ../Common/GmshDefines.h ../Geo/MVertex.h \
   ../Geo/SPoint3.h ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h \
-  ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h ../Common/Message.h
+  ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h
 PViewDataGModelIO.o: PViewDataGModelIO.cpp ../Common/Message.h \
   PViewDataGModel.h PViewData.h ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h \
   PViewDataList.h AdaptiveViews.h ../DataStr/List.h \
@@ -111,7 +111,9 @@ PViewDataGModelIO.o: PViewDataGModelIO.cpp ../Common/Message.h \
   ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/GFace.h ../Geo/GEntity.h \
   ../Geo/GPoint.h ../Geo/GEdgeLoop.h ../Geo/GEdge.h ../Geo/SPoint2.h \
   ../Geo/SVector3.h ../Geo/Pair.h ../Geo/GRegion.h ../Geo/GEntity.h \
-  ../Geo/SBoundingBox3d.h
+  ../Geo/SBoundingBox3d.h ../Geo/MVertex.h ../Geo/SPoint3.h \
+  ../Numeric/Numeric.h ../Numeric/NumericEmbedded.h \
+  ../Common/StringUtils.h
 PViewOptions.o: PViewOptions.cpp PViewOptions.h ColorTable.h \
   ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Common/Message.h
 AdaptiveViews.o: AdaptiveViews.cpp AdaptiveViews.h ../DataStr/List.h \
diff --git a/Post/PView.cpp b/Post/PView.cpp
index 1207219a5e..7ebc06cfa3 100644
--- a/Post/PView.cpp
+++ b/Post/PView.cpp
@@ -1,4 +1,4 @@
-// $Id: PView.cpp,v 1.20 2008-03-08 22:03:12 geuzaine Exp $
+// $Id: PView.cpp,v 1.21 2008-03-10 16:01:16 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -29,6 +29,7 @@
 #include "PViewDataGModel.h"
 #include "VertexArray.h"
 #include "SmoothData.h"
+#include "StringUtils.h"
 #include "Message.h"
 
 int PView::_globalNum = 0;
@@ -211,11 +212,12 @@ void PView::combine(bool time, int how, bool remove)
       delete *it;
 }
 
-PView *PView::getViewByName(std::string name, int noTimeStep)
+PView *PView::getViewByName(std::string name, int timeStep, int partition)
 {
   for(unsigned int i = 0; i < list.size(); i++){
     if(list[i]->getData()->getName() == name &&
-       (noTimeStep < 0 || noTimeStep >= list[i]->getData()->getNumTimeSteps()))
+       ((timeStep < 0 || !list[i]->getData()->hasTimeStep(timeStep)) ||
+	(partition < 0 || !list[i]->getData()->hasPartition(partition))))
       return list[i];
   }
   return 0;
@@ -302,8 +304,6 @@ bool PView::readPOS(std::string filename, int fileIndex)
   return true;
 }
 
-extern std::string extractDoubleQuotedString(char *str, int len);
-
 bool PView::readMSH(std::string filename, int fileIndex)
 {
   FILE *fp = fopen(filename.c_str(), "rb");
@@ -328,8 +328,9 @@ bool PView::readMSH(std::string filename, int fileIndex)
 
     if(!strncmp(&str[1], "MeshFormat", 10)) {
       double version;
+      if(!fgets(str, sizeof(str), fp)) return false;
       int format, size;
-      if(fscanf(fp, "%lf %d %d", &version, &format, &size) != 3) return 0;
+      if(sscanf(str, "%lf %d %d", &version, &format, &size) != 3) return false;
       if(format){
 	binary = true;
 	Msg(INFO, "Mesh is in binary format");
@@ -345,19 +346,21 @@ bool PView::readMSH(std::string filename, int fileIndex)
       index++;
       if(fileIndex < 0 || fileIndex == index){
 	// read data info
-	if(!fgets(str, sizeof(str), fp)) return 0;
+	if(!fgets(str, sizeof(str), fp)) return false;
 	std::string name = extractDoubleQuotedString(str, 256);
-	int timeStep, numComp, numNodes;
+	int timeStep, partition, interpolationScheme, numComp, numNodes;
 	double time;
-	if(fscanf(fp, "%d %lf %d %d", &timeStep, &time, &numComp, &numNodes) != 4)
-	  return 0;
+	if(!fgets(str, sizeof(str), fp)) return false;
+	if(sscanf(str, "%d %lf %d %d %d %d", &timeStep, &time, &partition,
+		  &interpolationScheme, &numComp, &numNodes) != 6) return false;
 	// either get existing viewData, or create new one
-	PView *p = getViewByName(name, timeStep);
+	PView *p = getViewByName(name, timeStep, partition);
 	PViewDataGModel *d = 0;
 	if(p) d = dynamic_cast<PViewDataGModel*>(p->getData());
 	bool create = d ? false : true;
 	if(create) d = new PViewDataGModel(GModel::current());
-	if(!d->readMSH(fp, binary, swap, timeStep, time, numComp, numNodes)){
+	if(!d->readMSH(fp, binary, swap, timeStep, time, partition, 
+		       numComp, numNodes)){
 	  Msg(GERROR, "Could not read data in msh file");
 	  if(create) delete d;
 	  return false;
diff --git a/Post/PView.h b/Post/PView.h
index b1d52300f3..6a48bc18e8 100644
--- a/Post/PView.h
+++ b/Post/PView.h
@@ -81,8 +81,10 @@ class PView{
   static void combine(bool time, int how, bool remove);
 
   // find view by name (if noTimeStep >= 0, return view only if it
-  // does *not* contain that timestep)
-  static PView *getViewByName(std::string name, int noTimeStep=-1);
+  // does *not* contain that timestep; if partition >=0, return view
+  // only if it does *not* contain that partition)
+  static PView *getViewByName(std::string name, int timeStep=-1, 
+			      int partition=-1);
 
   // read view(s) in list format from a file
   static bool readPOS(std::string filename, int fileIndex=-1);
diff --git a/Post/PViewData.h b/Post/PViewData.h
index b4da85e1e9..02ece472d6 100644
--- a/Post/PViewData.h
+++ b/Post/PViewData.h
@@ -104,13 +104,15 @@ class PViewData {
   virtual bool isAdaptive(){ return false; }
   virtual bool skipEntity(int ent){ return false; }
   virtual bool skipElement(int ent, int ele, int step){ return false; }
+  virtual bool hasTimeStep(int step){ return step < getNumTimeSteps(); }
+  virtual bool hasPartition(int part){ return false; }
 
   // I/O routines
   virtual bool writeSTL(std::string name);
   virtual bool writeTXT(std::string name);
   virtual bool writePOS(std::string name, bool binary=false, bool parsed=true,
 			bool append=false){ return false; }
-  virtual bool writeMSH(std::string name){ return false; }
+  virtual bool writeMSH(std::string name, bool binary=false){ return false; }
 };
 
 class nameData{
diff --git a/Post/PViewDataGModel.cpp b/Post/PViewDataGModel.cpp
index 6afa0ebb21..a0736bf6ce 100644
--- a/Post/PViewDataGModel.cpp
+++ b/Post/PViewDataGModel.cpp
@@ -1,4 +1,4 @@
-// $Id: PViewDataGModel.cpp,v 1.23 2008-03-09 14:47:32 geuzaine Exp $
+// $Id: PViewDataGModel.cpp,v 1.24 2008-03-10 16:01:16 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -152,3 +152,15 @@ bool PViewDataGModel::skipElement(int ent, int ele, int step)
   }
   return false;
 }
+
+bool PViewDataGModel::hasTimeStep(int step)
+{
+  if(step < _nodeData.size() && _nodeData[step]) return true;
+  if(step < _elementData.size() && _elementData[step]) return true;
+  return false;
+}
+
+bool PViewDataGModel::hasPartition(int part)
+{
+  return _partitions.find(part) != _partitions.end();
+}
diff --git a/Post/PViewDataGModel.h b/Post/PViewDataGModel.h
index 2f64cb5e0b..fe2ec9f0f8 100644
--- a/Post/PViewDataGModel.h
+++ b/Post/PViewDataGModel.h
@@ -40,12 +40,20 @@ class stepData{
 // data container using elements from a GModel
 class PViewDataGModel : public PViewData {
  private:
+  // a pointer to the underlying model
   GModel *_model;
+  // the unrolled list of all geometrical entities in the model
   std::vector<GEntity*> _entities;
+  // the node- and element-based data
   std::vector<stepData<double>*> _nodeData, _elementData;
-  PViewDataList *_cloneToList(); // create old-style data from this
+  // the global min/max of the view
   double _min, _max;
+  // the bounding box of the view (= model bbox for now)
   SBoundingBox3d _bbox;
+  // a set of all "partitions" encountered in the input data
+  std::set<int> _partitions;
+  // create old-style list-based dataset from this one
+  PViewDataList *_cloneToList();
  public:
   PViewDataGModel(GModel *model);
   ~PViewDataGModel();
@@ -65,10 +73,13 @@ class PViewDataGModel : public PViewData {
   int getNumEdges(int ent, int ele);
   bool skipEntity(int ent);
   bool skipElement(int ent, int ele, int step);
+  bool hasTimeStep(int step);
+  bool hasPartition(int part);
 
   // I/O routines
-  bool readMSH(FILE *fp, bool binary, bool swap, int timeStep, double time, 
-	       int numComp, int numNodes);
+  bool readMSH(FILE *fp, bool binary, bool swap, int timeStep, double time,
+	       int partition, int numComp, int numNodes);
+  bool writeMSH(std::string name, bool binary=false);
 };
 
 #endif
diff --git a/Post/PViewDataGModelIO.cpp b/Post/PViewDataGModelIO.cpp
index 01f0192a54..2813284574 100644
--- a/Post/PViewDataGModelIO.cpp
+++ b/Post/PViewDataGModelIO.cpp
@@ -1,4 +1,4 @@
-// $Id: PViewDataGModelIO.cpp,v 1.4 2008-03-09 14:47:32 geuzaine Exp $
+// $Id: PViewDataGModelIO.cpp,v 1.5 2008-03-10 16:01:16 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -27,11 +27,13 @@
 #include "PViewDataGModel.h"
 #include "MVertex.h"
 #include "Numeric.h"
+#include "StringUtils.h"
 
-bool PViewDataGModel::readMSH(FILE *fp, bool binary, bool swap, int timeStep, double time, 
-			      int numComp, int numNodes)
+bool PViewDataGModel::readMSH(FILE *fp, bool binary, bool swap, int timeStep, 
+			      double time, int partition, int numComp, int numNodes)
 {
-  Msg(INFO, "Reading step %d (time %g): %d nodes", timeStep, time, numNodes);
+  Msg(INFO, "Reading step %d (time %g) partition %d: %d nodes", 
+      timeStep, time, partition, numNodes);
 
   while(timeStep >= _nodeData.size()) _nodeData.push_back(0);
 
@@ -40,34 +42,106 @@ bool PViewDataGModel::readMSH(FILE *fp, bool binary, bool swap, int timeStep, do
   _nodeData[timeStep]->time = time;
   _nodeData[timeStep]->values.resize(numNodes);
 
-  if(0 &&binary){
-    Msg(GERROR, "not ready yet for binary");
-    return 0;
+  std::vector<double> tmp(numComp, 0.);
+
+  for(int i = 0; i < numNodes; i++){
+    int num;
+    if(binary){
+      if(fread(&num, sizeof(int), 1, fp) != 1) return false;
+      if(swap) swapBytes((char*)&num, sizeof(int), 1);
+    }
+    else{
+      if(fscanf(fp, "%d", &num) != 1) return false;
+    }
+    MVertex *v = _model->getMeshVertexByTag(num);
+    if(!v){
+      Msg(GERROR, "Unknown vertex %d in data", num);
+      return false;
+    }
+    if(v->getDataIndex() < 0){
+      int max = _model->getMaxVertexDataIndex();
+      _model->setMaxVertexDataIndex(max + 1);
+      v->setDataIndex(max + 1);
+    }
+    int index = v->getDataIndex();
+    if(index >= _nodeData[timeStep]->values.size())
+      _nodeData[timeStep]->values.resize(index + 100); // optimize this
+    if(binary){
+      if(fread(&tmp[0], sizeof(double), numComp, fp) != numComp) return false;
+      if(swap) swapBytes((char*)&tmp[0], sizeof(double), numComp);
+    }
+    else{
+      for(int j = 0; j < numComp; j++)
+	if(fscanf(fp, "%lf", &tmp[j]) != 1) return false;
+    }
+    for(int j = 0; j < numComp; j++)
+      _nodeData[timeStep]->values[index].push_back(tmp[j]);
+    double s = ComputeScalarRep(numComp, &_nodeData[timeStep]->values[index][0]);
+    _nodeData[timeStep]->min = std::min(_nodeData[timeStep]->min, s);
+    _nodeData[timeStep]->max = std::max(_nodeData[timeStep]->max, s);
   }
-  else{
-    for(int i = 0; i < numNodes; i++){
-      int num;
-      if(fscanf(fp, "%d", &num) != 1) return 0;
-      MVertex *v = _model->getMeshVertexByTag(num);
-      if(!v) return 0;
-      if(v->getDataIndex() < 0){
-	int max = _model->getMaxVertexDataIndex();
-	_model->setMaxVertexDataIndex(max + 1);
-	v->setDataIndex(max + 1);
+
+  _partitions.insert(partition);
+
+  finalize();
+  return true;
+}
+
+bool PViewDataGModel::writeMSH(std::string name, bool binary)
+{
+  binary = true;
+
+  bool saveAll = true;
+  if(!_model->writeMSH(name, 2.0, binary, saveAll)) return false;
+
+  // append data
+  FILE *fp = fopen(name.c_str(), binary ? "ab" : "a");
+  if(!fp){
+    Msg(GERROR, "Unable to open file '%s'", name.c_str());
+    return false;
+  }
+
+  // map data index to vertex tags
+  std::vector<int> tags(_model->getMaxVertexDataIndex() + 1, 0);
+  for(unsigned int i = 0; i < _entities.size(); i++){
+    for(unsigned int j = 0; j < _entities[i]->mesh_vertices.size(); j++){
+      MVertex *v = _entities[i]->mesh_vertices[j];
+      if(v->getDataIndex() >= 0) tags[v->getDataIndex()] = v->getNum();
+    }
+  }
+
+  for(unsigned int ts = 0; ts < _nodeData.size(); ts++){
+    if(!_nodeData[ts]) continue;
+    int numNodes = 0, numComp = 100;
+    for(unsigned int i = 0; i < _nodeData[ts]->values.size(); i++){
+      if(_nodeData[ts]->values[i].size()){
+	numComp = std::min(numComp, (int)_nodeData[ts]->values[i].size());
+	numNodes++;
       }
-      int index = v->getDataIndex();
-      if(index >= _nodeData[timeStep]->values.size())
-	_nodeData[timeStep]->values.resize(index + 1);
-      for(int j = 0; j < numComp; j++){
-	double val;
-	if(fscanf(fp, "%lf", &val) != 1) return 0;
-	_nodeData[timeStep]->values[index].push_back(val);
+    }
+    if(numNodes && numComp){
+      fprintf(fp, "$NodeData\n");
+      fprintf(fp, "\"%s\"\n", getName().c_str());
+      fprintf(fp, "%d %.16g 0 0 %d %d\n", ts, _nodeData[ts]->time, numComp, numNodes);
+      for(unsigned int i = 0; i < _nodeData[ts]->values.size(); i++){
+	if(_nodeData[ts]->values[i].size() >= numComp){
+	  if(binary){
+	    fwrite(&tags[i], sizeof(int), 1, fp);
+	    fwrite(&_nodeData[ts]->values[i][0], sizeof(double), numComp, fp);
+	  }
+	  else{
+	    fprintf(fp, "%d", tags[i]);
+	    for(int k = 0; k < numComp; k++)
+	      fprintf(fp, " %.16g", _nodeData[ts]->values[i][k]);
+	    fprintf(fp, "\n");
+	  }
+	}
       }
-      double s = ComputeScalarRep(numComp, &_nodeData[timeStep]->values[index][0]);
-      _nodeData[timeStep]->min = std::min(_nodeData[timeStep]->min, s);
-      _nodeData[timeStep]->max = std::max(_nodeData[timeStep]->max, s);
+      if(binary) fprintf(fp, "\n");
+      fprintf(fp, "$EndNodeData\n");
     }
   }
-  finalize();
+    
+  fclose(fp);
   return true;
 }
diff --git a/Post/PViewDataList.cpp b/Post/PViewDataList.cpp
index 9b76dc5282..eedc7560a3 100644
--- a/Post/PViewDataList.cpp
+++ b/Post/PViewDataList.cpp
@@ -1,4 +1,4 @@
-// $Id: PViewDataList.cpp,v 1.15 2008-03-08 22:03:13 geuzaine Exp $
+// $Id: PViewDataList.cpp,v 1.16 2008-03-10 16:01:16 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -844,3 +844,4 @@ bool PViewDataList::combineTime(nameData &nd)
   setFileName(std::string(name) + ".pos");
   return finalize();
 }
+
diff --git a/Post/PViewDataList.h b/Post/PViewDataList.h
index b2f86b9747..57505452ea 100644
--- a/Post/PViewDataList.h
+++ b/Post/PViewDataList.h
@@ -116,7 +116,7 @@ class PViewDataList : public PViewData {
   bool readPOS(FILE *fp, double version, int format, int size);
   bool writePOS(std::string name, bool binary=false, bool parsed=true,
 		bool append=false);
-  bool writeMSH(std::string name);
+  bool writeMSH(std::string name, bool binary=false);
 };
 
 #endif
diff --git a/Post/PViewDataListIO.cpp b/Post/PViewDataListIO.cpp
index f14b402035..0425b64d57 100644
--- a/Post/PViewDataListIO.cpp
+++ b/Post/PViewDataListIO.cpp
@@ -1,4 +1,4 @@
-// $Id: PViewDataListIO.cpp,v 1.14 2008-03-09 21:36:16 geuzaine Exp $
+// $Id: PViewDataListIO.cpp,v 1.15 2008-03-10 16:01:17 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -509,7 +509,7 @@ static void writeElementsMSH(FILE *fp, int nbelm, List_T *list,
   }
 }
 
-bool PViewDataList::writeMSH(std::string name)
+bool PViewDataList::writeMSH(std::string name, bool binary)
 {
   FILE *fp = fopen(name.c_str(), "w");
   if(!fp){
@@ -517,6 +517,8 @@ bool PViewDataList::writeMSH(std::string name)
     return false;
   }
 
+  if(binary) Msg(WARNING, "Binary write not implemented yet");
+
   std::set<pVertex, pVertexLessThan> nodes;
   int numelm = 0;
   getNodeMSH(NbSP, SP, 1, 1, NbTimeStep, &nodes, &numelm);
@@ -590,7 +592,7 @@ bool PViewDataList::writeMSH(std::string name)
       double time = getTime(ts);
       fprintf(fp, "$NodeData\n");
       fprintf(fp, "\"%s\"\n", getName().c_str());
-      fprintf(fp, "%d %.16g %d %d\n", ts, time, numComp, numNodes);
+      fprintf(fp, "%d %.16g 0 0 %d %d\n", ts, time, numComp, numNodes);
       for(std::set<pVertex, pVertexLessThan>::iterator it = nodes.begin();
 	  it != nodes.end(); ++it){
 	fprintf(fp, "%d", it->Num);
-- 
GitLab