diff --git a/Common/Views.cpp b/Common/Views.cpp
index e8602a8fdbb9728ef4df95597c0883a7f05bd810..0552f4cc6e5570f711d6373277d18c9451b0a634 100644
--- a/Common/Views.cpp
+++ b/Common/Views.cpp
@@ -1,4 +1,4 @@
-// $Id: Views.cpp,v 1.143 2004-10-26 00:43:22 geuzaine Exp $
+// $Id: Views.cpp,v 1.144 2004-10-30 15:23:44 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -1557,16 +1557,6 @@ void CombineViews(int time, int how, int remove)
 
 // generic access functions
 
-int Post_View::get_val(int list, int node, int timestep, double *value)
-{
-  return 0;
-}
-
-void Post_View::add_val(int list, int node, int timestep, double value)
-{
-  ;
-}
-
 int Post_View::empty(){
   if(NbSP || NbVP || NbTP ||
      NbSL || NbVL || NbTL ||
diff --git a/Common/Views.h b/Common/Views.h
index f1d95b408fd4e204946a35b01e3ee7611a2206f2..6eba5318b0290a785178ea4f0cadcd9b92b7d739 100644
--- a/Common/Views.h
+++ b/Common/Views.h
@@ -182,8 +182,6 @@ class Post_View{
   void transform(double mat[3][3]);
 
   // some generic access functions
-  int get_val(int list, int node, int timestep, double *value);
-  void add_val(int list, int node, int timestep, double value);
   int empty();
   void get_raw_data(int type, List_T **list, int **nbe, int *nbc, int *nbn);
 };
diff --git a/Plugin/Harmonic2Time.cpp b/Plugin/Harmonic2Time.cpp
deleted file mode 100644
index d44df315ad8901bb00321fc4682d284aab3c2dae..0000000000000000000000000000000000000000
--- a/Plugin/Harmonic2Time.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-// $Id: Harmonic2Time.cpp,v 1.14 2004-05-16 20:04:43 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 "Plugin.h"
-#include "Harmonic2Time.h"
-#include "List.h"
-#include "Views.h"
-#include "Context.h"
-#include "Numeric.h"
-
-extern Context_T CTX;
-
-StringXNumber Harmonic2TimeOptions_Number[] = {
-  {GMSH_FULLRC, "realPart", NULL, 0.},
-  {GMSH_FULLRC, "imaginaryPart", NULL, 1.},
-  {GMSH_FULLRC, "nbSteps", NULL, 20.},
-  {GMSH_FULLRC, "iView", NULL, -1.}
-};
-
-extern "C"
-{
-  GMSH_Plugin *GMSH_RegisterHarmonic2TimePlugin()
-  {
-    return new GMSH_Harmonic2TimePlugin();
-  }
-}
-
-
-GMSH_Harmonic2TimePlugin::GMSH_Harmonic2TimePlugin()
-{
-  ;
-}
-
-void GMSH_Harmonic2TimePlugin::getName(char *name) const
-{
-  strcpy(name, "Harmonic2Time");
-}
-
-void GMSH_Harmonic2TimePlugin::getInfos(char *author, char *copyright,
-                                        char *help_text) const
-{
-  strcpy(author, "C. Geuzaine (geuz@geuz.org)");
-  strcpy(copyright, "DGR (www.multiphysics.com)");
-  strcpy(help_text,
-         "Plugin(Harmonic2Time) takes the values in the\n"
-	 "time steps `realPart' and `imaginaryPart' of\n"
-         "the view `iView', and creates a new view\n"
-         "containing (`iView'[`realPart'] * cos(p) -\n"
-         "`iView'[`imaginaryPart'] * sin(p)), with\n"
-         "p = 2*Pi*k/`nbSteps', k = 0, ..., `nbSteps'-1.\n"
-	 "If `iView' < 0, the plugin is run on the\n"
-	 "current view.\n"
-	 "\n"
-	 "Plugin(Harmonic2Time) creates one new view.\n");
-}
-
-int GMSH_Harmonic2TimePlugin::getNbOptions() const
-{
-  return sizeof(Harmonic2TimeOptions_Number) / sizeof(StringXNumber);
-}
-
-StringXNumber *GMSH_Harmonic2TimePlugin::getOption(int iopt)
-{
-  return &Harmonic2TimeOptions_Number[iopt];
-}
-
-void GMSH_Harmonic2TimePlugin::catchErrorMessage(char *errorMessage) const
-{
-  strcpy(errorMessage, "Harmonic2Time failed...");
-}
-
-
-static void harmonic2time(Post_View * vv, Post_View * View,
-                          int rIndex, int iIndex, int nbSteps)
-{
-  int i, j, k;
-  double val, valr, vali, p;
-  for(i = 0; i < nbSteps; i++) {
-    p = Deux_Pi * i / (nbSteps - 1);
-    for(j = 0; j < VIEW_NB_ELEMENT_TYPES; j++) {
-      for(k = 0; k < VIEW_MAX_ELEMENT_NODES; k++) {
-        if(vv->get_val(j, k, rIndex, &valr) &&
-           vv->get_val(j, k, iIndex, &vali)) {
-          val = valr * cos(p) - vali * sin(p);
-          View->add_val(j, k, i, val);
-        }
-      }
-    }
-  }
-}
-
-Post_View *GMSH_Harmonic2TimePlugin::execute(Post_View * v)
-{
-  int rIndex, iIndex, nbSteps, iView;
-
-  rIndex = (int)Harmonic2TimeOptions_Number[0].def;
-  iIndex = (int)Harmonic2TimeOptions_Number[1].def;
-  nbSteps = (int)Harmonic2TimeOptions_Number[2].def;
-  iView = (int)Harmonic2TimeOptions_Number[3].def;
-
-  if(iView < 0)
-    iView = v ? v->Index : 0;
-
-  if(!List_Pointer_Test(CTX.post.list, iView)) {
-    Msg(GERROR, "View[%d] does not exist", iView);
-    return v;
-  }
-
-  Post_View *v1 = (Post_View*)List_Pointer(CTX.post.list, iView);
-
-  if(MIN(rIndex, iIndex) >= 0 && v1->NbTimeStep >= MAX(rIndex, iIndex)) {
-    // FIXME: this is not secure: if BeginView forces a post.list
-    // reallocation, v1 could be wrong
-    Post_View *v2 = BeginView(1);
-    harmonic2time(v1, v2, rIndex, iIndex, nbSteps);
-    // create time data
-    // FIXME: todo
-    // finalize
-    char name[1024], filename[1024];
-    sprintf(name, "%s_Harmonic2Time", v1->Name);
-    sprintf(filename, "%s_Harmonic2Time.pos", v1->Name);
-    EndView(v2, 1, filename, name);
-    return v2;
-  }
-
-  return v1;
-}
-
diff --git a/Plugin/HarmonicToTime.cpp b/Plugin/HarmonicToTime.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bfe7c18297a33564694f728a0607f5cd65711b22
--- /dev/null
+++ b/Plugin/HarmonicToTime.cpp
@@ -0,0 +1,187 @@
+// $Id: HarmonicToTime.cpp,v 1.1 2004-10-30 15:23:45 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 "Plugin.h"
+#include "HarmonicToTime.h"
+#include "List.h"
+#include "Views.h"
+#include "Context.h"
+#include "Numeric.h"
+
+extern Context_T CTX;
+
+StringXNumber HarmonicToTimeOptions_Number[] = {
+  {GMSH_FULLRC, "realPart", NULL, 0.},
+  {GMSH_FULLRC, "imaginaryPart", NULL, 1.},
+  {GMSH_FULLRC, "nSteps", NULL, 20.},
+  {GMSH_FULLRC, "iView", NULL, -1.}
+};
+
+extern "C"
+{
+  GMSH_Plugin *GMSH_RegisterHarmonicToTimePlugin()
+  {
+    return new GMSH_HarmonicToTimePlugin();
+  }
+}
+
+
+GMSH_HarmonicToTimePlugin::GMSH_HarmonicToTimePlugin()
+{
+  ;
+}
+
+void GMSH_HarmonicToTimePlugin::getName(char *name) const
+{
+  strcpy(name, "Harmonic to time");
+}
+
+void GMSH_HarmonicToTimePlugin::getInfos(char *author, char *copyright,
+                                        char *help_text) const
+{
+  strcpy(author, "C. Geuzaine (geuz@geuz.org)");
+  strcpy(copyright, "DGR (www.multiphysics.com)");
+  strcpy(help_text,
+         "Plugin(HarmonicToTime) takes the values in the\n"
+	 "time steps `realPart' and `imaginaryPart' of\n"
+         "the view `iView', and creates a new view\n"
+         "containing (`iView'[`realPart'] * cos(p) -\n"
+         "`iView'[`imaginaryPart'] * sin(p)), with\n"
+         "p = 2*Pi*k/`nSteps', k = 0, ..., `nSteps'-1.\n"
+	 "If `iView' < 0, the plugin is run on the\n"
+	 "current view.\n"
+	 "\n"
+	 "Plugin(HarmonicToTime) creates one new view.\n");
+}
+
+int GMSH_HarmonicToTimePlugin::getNbOptions() const
+{
+  return sizeof(HarmonicToTimeOptions_Number) / sizeof(StringXNumber);
+}
+
+StringXNumber *GMSH_HarmonicToTimePlugin::getOption(int iopt)
+{
+  return &HarmonicToTimeOptions_Number[iopt];
+}
+
+void GMSH_HarmonicToTimePlugin::catchErrorMessage(char *errorMessage) const
+{
+  strcpy(errorMessage, "HarmonicToTime failed...");
+}
+
+
+static void h2t(int nb1, List_T *list1, int *nb2, List_T *list2,
+		int nbNod, int nbComp, int rIndex, int iIndex, int nSteps)
+{
+  if(!nb1) return;
+
+  int nb = List_Nbr(list1) / nb1;
+  for(int i = 0; i < List_Nbr(list1); i += nb) {
+    for(int j = 0; j < 3 * nbNod; j++)
+      List_Add(list2, List_Pointer_Fast(list1, i + j));
+    double *valr = (double *)List_Pointer_Fast(list1, i + 3 * nbNod +
+					       nbNod * nbComp * rIndex);
+    double *vali = (double *)List_Pointer_Fast(list1, i + 3 * nbNod +
+					       nbNod * nbComp * iIndex);
+    for(int t = 0; t < nSteps; t++) {
+      double p = 2. * M_PI * t / nSteps;
+      for(int j = 0; j < nbNod; j++) {
+	for(int k = 0; k < nbComp; k++) {
+	  double val = valr[nbComp * j + k] * cos(p) - vali[nbComp * j + k] * sin(p);
+	  List_Add(list2, &val);	  
+	}
+      }
+    }
+  }
+  *nb2 = nb1;
+}
+
+Post_View *GMSH_HarmonicToTimePlugin::execute(Post_View * v)
+{
+  int rIndex, iIndex, nSteps, iView;
+
+  rIndex = (int)HarmonicToTimeOptions_Number[0].def;
+  iIndex = (int)HarmonicToTimeOptions_Number[1].def;
+  nSteps = (int)HarmonicToTimeOptions_Number[2].def;
+  iView = (int)HarmonicToTimeOptions_Number[3].def;
+
+  if(iView < 0)
+    iView = v ? v->Index : 0;
+
+  if(!List_Pointer_Test(CTX.post.list, iView)) {
+    Msg(GERROR, "View[%d] does not exist", iView);
+    return v;
+  }
+
+  if(nSteps <= 0){
+    Msg(GERROR, "nSteps should be > 0");
+    return v;
+  }
+
+  Post_View *v1 = (Post_View*)List_Pointer(CTX.post.list, iView);
+  if(rIndex < 0 || rIndex >= v1->NbTimeStep ||
+     iIndex < 0 || iIndex >= v1->NbTimeStep){
+    Msg(GERROR, "Wrong real or imaginary part index");
+    return v;
+  }
+
+  Post_View *v2 = BeginView(1);
+  // get v1 again, in case BeginView induced a realloc of the view list
+  v1 = (Post_View*)List_Pointer(CTX.post.list, iView);
+
+  h2t(v1->NbSP, v1->SP, &v2->NbSP, v2->SP, 1, 1, rIndex, iIndex, nSteps);
+  h2t(v1->NbVP, v1->VP, &v2->NbVP, v2->VP, 1, 3, rIndex, iIndex, nSteps);
+  h2t(v1->NbTP, v1->TP, &v2->NbTP, v2->TP, 1, 9, rIndex, iIndex, nSteps);
+  h2t(v1->NbSL, v1->SL, &v2->NbSL, v2->SL, 2, 1, rIndex, iIndex, nSteps);
+  h2t(v1->NbVL, v1->VL, &v2->NbVL, v2->VL, 2, 3, rIndex, iIndex, nSteps);
+  h2t(v1->NbTL, v1->TL, &v2->NbTL, v2->TL, 2, 9, rIndex, iIndex, nSteps);
+  h2t(v1->NbST, v1->ST, &v2->NbST, v2->ST, 3, 1, rIndex, iIndex, nSteps);
+  h2t(v1->NbVT, v1->VT, &v2->NbVT, v2->VT, 3, 3, rIndex, iIndex, nSteps);
+  h2t(v1->NbTT, v1->TT, &v2->NbTT, v2->TT, 3, 9, rIndex, iIndex, nSteps);
+  h2t(v1->NbSQ, v1->SQ, &v2->NbSQ, v2->SQ, 4, 1, rIndex, iIndex, nSteps);
+  h2t(v1->NbVQ, v1->VQ, &v2->NbVQ, v2->VQ, 4, 3, rIndex, iIndex, nSteps);
+  h2t(v1->NbTQ, v1->TQ, &v2->NbTQ, v2->TQ, 4, 9, rIndex, iIndex, nSteps);
+  h2t(v1->NbSS, v1->SS, &v2->NbSS, v2->SS, 4, 1, rIndex, iIndex, nSteps);
+  h2t(v1->NbVS, v1->VS, &v2->NbVS, v2->VS, 4, 3, rIndex, iIndex, nSteps);
+  h2t(v1->NbTS, v1->TS, &v2->NbTS, v2->TS, 4, 9, rIndex, iIndex, nSteps);
+  h2t(v1->NbSH, v1->SH, &v2->NbSH, v2->SH, 8, 1, rIndex, iIndex, nSteps);
+  h2t(v1->NbVH, v1->VH, &v2->NbVH, v2->VH, 8, 3, rIndex, iIndex, nSteps);
+  h2t(v1->NbTH, v1->TH, &v2->NbTH, v2->TH, 8, 9, rIndex, iIndex, nSteps);
+  h2t(v1->NbSI, v1->SI, &v2->NbSI, v2->SI, 6, 1, rIndex, iIndex, nSteps);
+  h2t(v1->NbVI, v1->VI, &v2->NbVI, v2->VI, 6, 3, rIndex, iIndex, nSteps);
+  h2t(v1->NbTI, v1->TI, &v2->NbTI, v2->TI, 6, 9, rIndex, iIndex, nSteps);
+  h2t(v1->NbSY, v1->SY, &v2->NbSY, v2->SY, 5, 1, rIndex, iIndex, nSteps);
+  h2t(v1->NbVY, v1->VY, &v2->NbVY, v2->VY, 5, 3, rIndex, iIndex, nSteps);
+  h2t(v1->NbTY, v1->TY, &v2->NbTY, v2->TY, 5, 9, rIndex, iIndex, nSteps);
+
+  // copy time data
+  for(int i = 0; i < nSteps; i++){
+    double p = 2.*M_PI*i/(double)nSteps;
+    List_Add(v2->Time, &p);
+  }
+  // finalize
+  char name[1024], filename[1024];
+  sprintf(name, "%s_Skin", v1->Name);
+  sprintf(filename, "%s_Skin.pos", v1->Name);
+  EndView(v2, 1, filename, name);
+
+  return v2;
+}
diff --git a/Plugin/Harmonic2Time.h b/Plugin/HarmonicToTime.h
similarity index 89%
rename from Plugin/Harmonic2Time.h
rename to Plugin/HarmonicToTime.h
index 327ec204ee4113e5a02f4cc03375dc0cafeb9fff..b5f1e87b9b539817c66f6550f535ac1bb978762f 100644
--- a/Plugin/Harmonic2Time.h
+++ b/Plugin/HarmonicToTime.h
@@ -24,13 +24,13 @@
 
 extern "C"
 {
-  GMSH_Plugin *GMSH_RegisterHarmonic2TimePlugin();
+  GMSH_Plugin *GMSH_RegisterHarmonicToTimePlugin();
 }
 
-class GMSH_Harmonic2TimePlugin : public GMSH_Post_Plugin
+class GMSH_HarmonicToTimePlugin : public GMSH_Post_Plugin
 {
 public:
-  GMSH_Harmonic2TimePlugin();
+  GMSH_HarmonicToTimePlugin();
   void getName(char *name) const;
   void getInfos(char *author, char *copyright, char *help_text) const;
   void catchErrorMessage(char *errorMessage) const;
diff --git a/Plugin/Makefile b/Plugin/Makefile
index 7dadbe3d34bc4176445332c0d18118634f5c68c5..e805d036393edb22e2018010851e2fc19f1b4bdd 100644
--- a/Plugin/Makefile
+++ b/Plugin/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.57 2004-10-28 08:13:09 geuzaine Exp $
+# $Id: Makefile,v 1.58 2004-10-30 15:23:45 geuzaine Exp $
 #
 # Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 #
@@ -41,7 +41,7 @@ SRC = Plugin.cpp\
         Extract.cpp\
         DecomposeInSimplex.cpp\
         Evaluate.cpp\
-        Harmonic2Time.cpp
+        HarmonicToTime.cpp
 
 OBJ = ${SRC:.cpp=.o}
 
@@ -71,7 +71,7 @@ Plugin.o: Plugin.cpp Plugin.h ../Common/Options.h ../Common/Message.h \
   ../Common/VertexArray.h ../Common/SmoothNormals.h \
   ../Common/GmshMatrix.h PluginManager.h CutMap.h Levelset.h CutGrid.h \
   StreamLines.h CutPlane.h CutParametric.h CutSphere.h Skin.h \
-  ../DataStr/Tree.h ../DataStr/avl.h Extract.h Harmonic2Time.h \
+  ../DataStr/Tree.h ../DataStr/avl.h Extract.h HarmonicToTime.h \
   DecomposeInSimplex.h Smooth.h Transform.h Triangulate.h \
   SphericalRaise.h DisplacementRaise.h StructuralSolver.h ../Geo/Geo.h \
   ../Mesh/Mesh.h ../Mesh/Vertex.h ../Mesh/Element.h ../Mesh/Simplex.h \
@@ -173,8 +173,8 @@ Evaluate.o: Evaluate.cpp Plugin.h ../Common/Options.h ../Common/Message.h \
   ../Common/VertexArray.h ../Common/SmoothNormals.h \
   ../Common/GmshMatrix.h Evaluate.h ../Common/Context.h \
   ../Numeric/Numeric.h
-Harmonic2Time.o: Harmonic2Time.cpp Plugin.h ../Common/Options.h \
+HarmonicToTime.o: HarmonicToTime.cpp Plugin.h ../Common/Options.h \
   ../Common/Message.h ../Common/Views.h ../Common/ColorTable.h \
   ../DataStr/List.h ../Common/VertexArray.h ../Common/SmoothNormals.h \
-  ../Common/GmshMatrix.h Harmonic2Time.h ../Common/Context.h \
+  ../Common/GmshMatrix.h HarmonicToTime.h ../Common/Context.h \
   ../Numeric/Numeric.h
diff --git a/Plugin/Plugin.cpp b/Plugin/Plugin.cpp
index 958f42301d1d73783c10326f89d246775b043df4..3629af39ae48771f907f7c0712bb463f49f87569 100644
--- a/Plugin/Plugin.cpp
+++ b/Plugin/Plugin.cpp
@@ -1,4 +1,4 @@
-// $Id: Plugin.cpp,v 1.61 2004-10-28 08:13:09 geuzaine Exp $
+// $Id: Plugin.cpp,v 1.62 2004-10-30 15:23:45 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -40,7 +40,7 @@
 #include "CutSphere.h"
 #include "Skin.h"
 #include "Extract.h"
-#include "Harmonic2Time.h"
+#include "HarmonicToTime.h"
 #include "DecomposeInSimplex.h"
 #include "Smooth.h"
 #include "Transform.h"
@@ -187,6 +187,8 @@ void GMSH_PluginManager::registerDefaultPlugins()
 		      ("SphericalRaise", GMSH_RegisterSphericalRaisePlugin()));
     allPlugins.insert(std::pair < char *, GMSH_Plugin * >
 		      ("DisplacementRaise", GMSH_RegisterDisplacementRaisePlugin()));
+    allPlugins.insert(std::pair < char *, GMSH_Plugin * >
+		      ("HarmonicToTime", GMSH_RegisterHarmonicToTimePlugin()));
 #if defined(HAVE_TRIANGLE)
     allPlugins.insert(std::pair < char *, GMSH_Plugin * >
 		      ("Triangulate", GMSH_RegisterTriangulatePlugin()));
diff --git a/doc/VERSIONS b/doc/VERSIONS
index e9c399672e4813008e1dc08baff6a7ff4861b238..9081f49a365186981981f6a954c2572d3bcc7ff8 100644
--- a/doc/VERSIONS
+++ b/doc/VERSIONS
@@ -1,4 +1,4 @@
-$Id: VERSIONS,v 1.263 2004-10-30 03:07:29 geuzaine Exp $
+$Id: VERSIONS,v 1.264 2004-10-30 15:23:45 geuzaine Exp $
 
 New since 1.56: generalized displacement maps to display arbitrary
 view types; the arrows representing a vector field can now also be
@@ -6,7 +6,8 @@ colored by the values from other scalar, vector or tensor fields; new
 adaptive high order visualization mode; new options for solvers
 (SocketCommand and NameCommand) and views (ArrowSizeProportional);
 fixed display of undesired solver plugin popups; enhanced interactive
-plugin behaviour; various small bug fixes and enhancements;
+plugin behaviour; new Plugin(HarmonicToTime); various small bug fixes
+and enhancements;
 
 New in 1.56: new post-processing option to draw a scalar view raised
 by a displacement view without using Plugin(DisplacementRaise) (makes