diff --git a/Geo/GEdge.cpp b/Geo/GEdge.cpp
index 635c06edcd1a8cd3cdc9ab870d4fe9e640611868..8c37aa8f9d6706cdc1bf5b0d3545415e94633705 100644
--- a/Geo/GEdge.cpp
+++ b/Geo/GEdge.cpp
@@ -218,7 +218,7 @@ double GEdge::length(const double &u0, const double &u1, const int nbQuadPoints)
 #endif
 }
 
-GPoint GEdge::closestPoint(const SPoint3 & q,double& t) const
+GPoint GEdge::closestPoint(const SPoint3 &q, double &t) const
 {
   double tolerance = 1.e-12;
   double dist = 1.;
@@ -243,10 +243,10 @@ GPoint GEdge::closestPoint(const SPoint3 & q,double& t) const
       dt0 = dt;
       SVector3 dp = q - position(t);
       SVector3 derP = firstDer(t);
-      double b = dot(derP,derP);
-      double c = dot(derP,dp);
+      double b = dot(derP, derP);
+      double c = dot(derP, dp);
       dt = c / b;
-      t = std::max(tMin,std::min(tMax,t0+relax * dt));
+      t = std::max(tMin, std::min(tMax, t0 + relax * dt));
       dt = fabs(t - t0);
     }
     if (i > nb)  relax *= 0.5;
diff --git a/Graphics/Makefile b/Graphics/Makefile
index 3e5c659c2315c148d9a456518c19512849fba54b..8a0dbdd61291e2c547af90bd3c43c996994b39c1 100644
--- a/Graphics/Makefile
+++ b/Graphics/Makefile
@@ -77,7 +77,7 @@ drawContext${OBJEXT}: drawContext.cpp ../Common/GmshMessage.h drawContext.h \
   ../Geo/GEdge.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
   ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
   ../Geo/SBoundingBox3d.h ../Post/PView.h ../Post/PViewOptions.h \
-  ../Post/ColorTable.h
+  ../Post/ColorTable.h gl2ps.h
 drawMesh${OBJEXT}: drawMesh.cpp drawContext.h ../Geo/SBoundingBox3d.h \
   ../Geo/SPoint3.h ../Common/GmshMessage.h ../Common/GmshDefines.h \
   ../Geo/GModel.h ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/Range.h \
diff --git a/Mesh/Makefile b/Mesh/Makefile
index 35b80dc2d471e01116913b0e3f324bc06add3ae6..3bc0c63136936cd990d7f3112353a4a1b21625b0 100644
--- a/Mesh/Makefile
+++ b/Mesh/Makefile
@@ -259,7 +259,8 @@ meshGFaceOptimize${OBJEXT}: meshGFaceOptimize.cpp meshGFaceOptimize.h \
   ../Geo/GEdgeLoop.h ../Geo/GEdge.h ../Geo/GEntity.h ../Geo/GVertex.h \
   ../Geo/GEntity.h ../Geo/GPoint.h ../Geo/SPoint2.h ../Geo/SVector3.h \
   ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/SPoint2.h ../Geo/SVector3.h \
-  ../Geo/Pair.h BackgroundMesh.h Generator.h
+  ../Geo/Pair.h BackgroundMesh.h ../Numeric/Numeric.h \
+  ../Numeric/GmshMatrix.h Generator.h
 meshGFaceQuadrilateralize${OBJEXT}: meshGFaceQuadrilateralize.cpp \
   meshGFaceQuadrilateralize.h ../Common/GmshMessage.h \
   ../Numeric/Numeric.h ../Numeric/GmshMatrix.h ../Common/GmshConfig.h \
diff --git a/Mesh/meshGFaceOptimize.cpp b/Mesh/meshGFaceOptimize.cpp
index 7bd6005778bebc20019ca5caf0a55774a8884e55..40077361c063c944e7bd3ac6d6b5218151e3c44a 100644
--- a/Mesh/meshGFaceOptimize.cpp
+++ b/Mesh/meshGFaceOptimize.cpp
@@ -84,9 +84,9 @@ void buildMeshGenerationDataStructures(GFace *gf,
     Vs.push_back(param[1]);
   }
   for(unsigned int i = 0; i < gf->triangles.size(); i++){
-    double lc = 0.3333333333 * (vSizes [gf->triangles[i]->getVertex(0)->getNum()] +
-                                vSizes [gf->triangles[i]->getVertex(1)->getNum()] +
-                                vSizes [gf->triangles[i]->getVertex(2)->getNum()]);
+    double lc = 0.3333333333 * (vSizes[gf->triangles[i]->getVertex(0)->getNum()] +
+                                vSizes[gf->triangles[i]->getVertex(1)->getNum()] +
+                                vSizes[gf->triangles[i]->getVertex(2)->getNum()]);
     AllTris.insert(new MTri3(gf->triangles[i], lc));
   }
   gf->triangles.clear();
@@ -244,8 +244,6 @@ void laplaceSmoothing(GFace *gf)
   }
 }
 
-extern void fourthPoint(double *p1, double *p2, double *p3, double *p4);
-
 double surfaceTriangleUV(MVertex *v1, MVertex *v2, MVertex *v3,           
                          const std::vector<double> &Us,
                          const std::vector<double> &Vs)
diff --git a/Numeric/Makefile b/Numeric/Makefile
index 5fb873468a0913221046ca5aa36bf6547978873a..dcb5059fb766fd6e553eaae7221be9d6031e1739 100644
--- a/Numeric/Makefile
+++ b/Numeric/Makefile
@@ -14,16 +14,17 @@ CFLAGS = ${OPTIM} ${FLAGS} ${INC} ${SYSINCLUDE}
 SRC = Numeric.cpp\
       GmshMatrix.cpp\
       gmshLaplace.cpp\
-      gmshHelmholtz.cpp\
-      gmshElasticity.cpp\
+        gmshHelmholtz.cpp\
+        gmshElasticity.cpp\
+        gmshProjection.cpp\
       EigSolve.cpp\
       FunctionSpace.cpp\
       GaussQuadratureLin.cpp\
-      GaussQuadratureTri.cpp\
-      GaussQuadratureQuad.cpp\
-      GaussQuadratureTet.cpp\
-      GaussQuadratureHex.cpp\
-      GaussLegendreSimplex.cpp\
+        GaussQuadratureTri.cpp\
+        GaussQuadratureQuad.cpp\
+        GaussQuadratureTet.cpp\
+        GaussQuadratureHex.cpp\
+        GaussLegendreSimplex.cpp\
       GmshPredicates.cpp\
 
 OBJ = ${SRC:.cpp=${OBJEXT}}
@@ -103,6 +104,22 @@ gmshElasticity${OBJEXT}: gmshElasticity.cpp gmshElasticity.h \
   ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
   ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h ../Numeric/Gauss.h \
   ../Common/Gmsh.h ../Common/GmshMessage.h Numeric.h
+gmshProjection${OBJEXT}: gmshProjection.cpp gmshProjection.h \
+  gmshTermOfFormulation.h GmshMatrix.h ../Common/GmshConfig.h \
+  ../Common/GmshMessage.h gmshFunction.h gmshAssembler.h \
+  gmshLinearSystem.h ../Geo/GModel.h ../Geo/GVertex.h ../Geo/GEntity.h \
+  ../Geo/Range.h ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h \
+  ../Geo/SPoint3.h ../Geo/GPoint.h ../Geo/SPoint2.h ../Geo/GEdge.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 \
+  ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h ../Geo/MElement.h \
+  ../Common/GmshDefines.h ../Geo/MVertex.h ../Geo/SPoint2.h \
+  ../Geo/SPoint3.h ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h ../Numeric/Gauss.h \
+  ../Common/Gmsh.h ../Common/GmshMessage.h Numeric.h
 EigSolve${OBJEXT}: EigSolve.cpp
 FunctionSpace${OBJEXT}: FunctionSpace.cpp FunctionSpace.h GmshMatrix.h \
   ../Common/GmshConfig.h ../Common/GmshMessage.h ../Common/GmshDefines.h
diff --git a/Numeric/gmshHelmholtz.cpp b/Numeric/gmshHelmholtz.cpp
index 132fa0648c70488f78385beb936b744370ed7bc4..eaf52c7ef211c8835c5bfa5ecdce2d3449dcfafa 100644
--- a/Numeric/gmshHelmholtz.cpp
+++ b/Numeric/gmshHelmholtz.cpp
@@ -10,7 +10,7 @@ void gmshHelmholtzTerm::elementMatrix(MElement *e,
                                       gmshMatrix<std::complex<double> > &m) const
 {
   int nbNodes = e->getNumVertices();
-  int integrationOrder = 2 * e->getPolynomialOrder() - 0;
+  int integrationOrder = 2 * e->getPolynomialOrder();
   int npts;
   IntPt *GP;
   double jac[3][3];
@@ -44,7 +44,7 @@ void gmshHelmholtzTerm::elementMatrix(MElement *e,
 	m(j, k) += ((Grads[j][0] * Grads[k][0] +
                      Grads[j][1] * Grads[k][1] +
                      Grads[j][2] * Grads[k][2]) 
-                    - kk * kk * sf[j] * sf[k]) * weight * detJ * 0.5;
+                    - kk * kk * sf[j] * sf[k]) * weight * detJ;
       }
     }
   }
diff --git a/Numeric/gmshProjection.cpp b/Numeric/gmshProjection.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c3fdf746e0552aae938a4226afb82f7c9624f864
--- /dev/null
+++ b/Numeric/gmshProjection.cpp
@@ -0,0 +1,33 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#include "gmshProjection.h"
+#include "Numeric.h"
+
+void gmshProjectionTerm::elementMatrix(MElement *e, gmshMatrix<double> &m) const
+{
+  int nbNodes = e->getNumVertices();
+  int integrationOrder = 2 * e->getPolynomialOrder();
+  int npts;
+  IntPt *GP;
+  double jac[3][3];
+  double sf[256];
+  e->getIntegrationPoints(integrationOrder, &npts, &GP);
+  m.set_all(0.);
+  for (int i = 0; i < npts; i++){
+    const double u = GP[i].pt[0];
+    const double v = GP[i].pt[1];
+    const double w = GP[i].pt[2];
+    const double weight = GP[i].weight;
+    const double detJ = e->getJacobian(u, v, w, jac);   
+    SPoint3 p; e->pnt(u, v, w, p);
+    e->getShapeFunctions(u, v, w, sf);
+    for (int j = 0; j < nbNodes; j++){
+      for (int k = 0; k < nbNodes; k++){
+	m(j, k) += sf[j] * sf[k] * weight * detJ;
+      }
+    }
+  }
+} 
diff --git a/Numeric/gmshProjection.h b/Numeric/gmshProjection.h
new file mode 100644
index 0000000000000000000000000000000000000000..9df8cbb408e3054c3ef36d23f2a00a7e327463be
--- /dev/null
+++ b/Numeric/gmshProjection.h
@@ -0,0 +1,34 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#ifndef _GMSH_PROJECTION_H_
+#define _GMSH_PROJECTION_H_
+
+#include "gmshTermOfFormulation.h"
+#include "gmshFunction.h"
+#include "Gmsh.h"
+#include "GModel.h"
+#include "MElement.h"
+#include "GmshMatrix.h"
+
+class gmshProjectionTerm : public gmshNodalFemTerm<double> {
+ private:
+  const int _iField ;
+ protected:
+  virtual int sizeOfR(MElement *e) const { return e->getNumVertices(); }
+  virtual int sizeOfC(MElement *e) const { return e->getNumVertices(); }
+  void getLocalDofR(MElement *e, int iRow, MVertex **vR, int *iCompR, int *iFieldR) const
+  {
+    *vR = e->getVertex(iRow);
+    *iCompR = 0;
+    *iFieldR = _iField;
+  }
+ public:
+  gmshProjectionTerm(GModel *gm, int iField = 0) : 
+    gmshNodalFemTerm<double>(gm), _iField(iField){}
+  virtual void elementMatrix(MElement *e, gmshMatrix<double> &m) const;
+};
+
+#endif
diff --git a/Numeric/gmshTermOfFormulation.h b/Numeric/gmshTermOfFormulation.h
index cd5e35ee953a7d886316eb2fb2fc45836d20b8eb..fd264ef7bcf2f6cd68d937a5768a1e9a07b24a9a 100644
--- a/Numeric/gmshTermOfFormulation.h
+++ b/Numeric/gmshTermOfFormulation.h
@@ -124,6 +124,7 @@ class gmshNodalFemTerm : public gmshTermOfFormulation<scalar> {
     std::map<int, std::vector<GEntity*> >::iterator it = groups[dim].find(physical);  
     if (it == groups[dim].end()) return;
     double jac[3][3];
+    double sf[256];
 
     for (unsigned int i = 0; i < it->second.size(); ++i){
       GEntity *ge = it->second[i];
@@ -135,23 +136,15 @@ class gmshNodalFemTerm : public gmshTermOfFormulation<scalar> {
         IntPt *GP;
         e->getIntegrationPoints(integrationOrder, &npts, &GP);  
         for (int ip = 0; ip < npts; ip++){
-	  const double u      = GP[ip].pt[0];
-	  const double v      = GP[ip].pt[1];
-	  const double w      = GP[ip].pt[2];
+	  const double u = GP[ip].pt[0];
+	  const double v = GP[ip].pt[1];
+	  const double w = GP[ip].pt[2];
 	  const double weight = GP[ip].weight;
-	  const double detJ = e->getJacobian(u,v,w,jac);   
-	  double x = 0;
-	  double y = 0;
-	  double z = 0;
-          double sf[nbNodes];
-          e->getShapeFunctions(u,v,w,sf);
-	  for (int k = 0; k < nbNodes; k++){  
-	    x += e->getVertex(k)->x() * sf[k];
-	    y += e->getVertex(k)->y() * sf[k];
-	    z += e->getVertex(k)->z() * sf[k];
-	  }
-	  const scalar FCT = fct (x,y,z);
-	  for (int k = 0; k < nbNodes; k++){  
+	  const double detJ = e->getJacobian(u, v, w, jac);
+          SPoint3 p; e->pnt(u, v, w, p);
+          e->getShapeFunctions(u, v, w, sf);
+	  const scalar FCT = fct(p.x(), p.y(), p.z());
+	  for (int k = 0; k < nbNodes; k++){
 	    lsys.assemble(e->getVertex(k), comp, field, detJ * weight * sf[k] * FCT);
 	  }
         }
diff --git a/Plugin/FiniteElement.cpp b/Plugin/FiniteElement.cpp
index b2fa3601bbfe522faef66f00d5086b7136f96dee..b35428a4297b0c164a45fdc78e6cd91feebe427f 100644
--- a/Plugin/FiniteElement.cpp
+++ b/Plugin/FiniteElement.cpp
@@ -3,27 +3,33 @@
 // See the LICENSE.txt file for license information. Please report all
 // bugs and problems to <gmsh@geuz.org>.
 
+#include <stdlib.h>
 #include "GmshConfig.h"
 #include "GModel.h"
 #include "FiniteElement.h"
 #include "gmshAssembler.h"
+#include "gmshProjection.h"
 #include "gmshLaplace.h"
 #include "gmshHelmholtz.h"
 #include "gmshLinearSystemGmm.h"
 
+#if defined(HAVE_MATH_EVAL)
+#include "matheval.h"
+#endif
+
 StringXNumber FiniteElementOptions_Number[] = {
-  {GMSH_FULLRC, "Parameter", NULL, 1.},
-  {GMSH_FULLRC, "Volume", NULL, 1.},
-  {GMSH_FULLRC, "Surface1", NULL, 2.},
-  {GMSH_FULLRC, "Value1", NULL, 0.},
-  {GMSH_FULLRC, "Surface2", NULL, 3.},
-  {GMSH_FULLRC, "Value2", NULL, 1.}
+  {GMSH_FULLRC, "Omega", NULL, 1.},
+  {GMSH_FULLRC, "Gamma1", NULL, 0.},
+  {GMSH_FULLRC, "Gamma1Value", NULL, 0.},
+  {GMSH_FULLRC, "Gamma2", NULL, 0.},
+  {GMSH_FULLRC, "Gamma2Value", NULL, 0.}
 };
 
 StringXString FiniteElementOptions_String[] = {
-  {GMSH_FULLRC, "Equation", NULL, "Laplace"},
-  {GMSH_FULLRC, "BC1", NULL, "Dirichlet"},
-  {GMSH_FULLRC, "BC2", NULL, "Dirichlet"},
+  {GMSH_FULLRC, "Equation", NULL, "Projection"},
+  {GMSH_FULLRC, "Parameter", NULL, "Sin(x*y)"},
+  {GMSH_FULLRC, "Gamma1BC", NULL, ""},
+  {GMSH_FULLRC, "Gamma2BC", NULL, ""},
 };
 
 extern "C"
@@ -78,6 +84,40 @@ void GMSH_FiniteElementPlugin::catchErrorMessage(char *errorMessage) const
   strcpy(errorMessage, "FiniteElement failed...");
 }
 
+template<class scalar>
+class gmshMathEvalFunction : public gmshFunction<scalar> {
+ private:
+  std::string _str;
+  void *_f;
+ public:
+  gmshMathEvalFunction(std::string str) : _str(str)
+  {
+#if defined(HAVE_MATH_EVAL)
+    _f = evaluator_create((char*)_str.c_str());
+    if(!_f) Msg::Error("Invalid expression '%s'", _str.c_str());
+#endif
+  }
+  virtual ~gmshMathEvalFunction()
+  {
+#if defined(HAVE_MATH_EVAL)
+    if(_f) evaluator_destroy(_f);
+#endif
+  }
+  virtual scalar operator () (double x, double y, double z) const 
+  { 
+#if defined(HAVE_MATH_EVAL)
+    if(_f){
+      char *names[] = {"x", "y", "z"};
+      double values[] = {x, y, z};
+      return evaluator_evaluate(_f, sizeof(names)/sizeof(names[0]), names, values);
+    }
+    return atof(_str.c_str());
+#else
+    return atof(_str.c_str());
+#endif
+  }
+};
+
 #if defined(HAVE_GMM)
 template<class scalar>
 class solver{
@@ -86,13 +126,13 @@ class solver{
   gmshAssembler<scalar> *myAssembler;
   solver()
   {
-    int volume = (int)FiniteElementOptions_Number[1].def;
-    int surface1 = (int)FiniteElementOptions_Number[2].def;
-    double value1 = FiniteElementOptions_Number[3].def;
-    int surface2 = (int)FiniteElementOptions_Number[4].def;
-    double value2 = FiniteElementOptions_Number[5].def;
-    std::string bc1 = FiniteElementOptions_String[1].def;
-    std::string bc2 = FiniteElementOptions_String[2].def;
+    int volume = (int)FiniteElementOptions_Number[0].def;
+    int surface1 = (int)FiniteElementOptions_Number[1].def;
+    double value1 = FiniteElementOptions_Number[2].def;
+    int surface2 = (int)FiniteElementOptions_Number[3].def;
+    double value2 = FiniteElementOptions_Number[4].def;
+    std::string bc1 = FiniteElementOptions_String[2].def;
+    std::string bc2 = FiniteElementOptions_String[3].def;
 
     lsys = new gmshLinearSystemGmm<scalar>;
     lsys->setPrec(1.e-10);
@@ -127,8 +167,8 @@ class solver{
 PView *GMSH_FiniteElementPlugin::execute(PView *v)
 {
   std::string equation = FiniteElementOptions_String[0].def;
-  double parameter = FiniteElementOptions_Number[0].def;
-  int volume = (int)FiniteElementOptions_Number[1].def;
+  std::string parameter = FiniteElementOptions_String[1].def;
+  int volume = (int)FiniteElementOptions_Number[0].def;
 
 #if defined(HAVE_GMM)
   GModel *m = GModel::current();
@@ -140,11 +180,25 @@ PView *GMSH_FiniteElementPlugin::execute(PView *v)
   m->getMeshVertices(volume, dim, vertices);
   std::map<int, std::vector<double> > data;
 
-  if(equation == "Laplace"){
+  if(equation == "Projection"){
+    solver<double> s;
+    if(!s.myAssembler->sizeOfR()) return 0;
+    gmshMathEvalFunction<double> par(parameter);
+    gmshProjectionTerm projection(m, 1);
+    for(unsigned int i = 0; i < groups[dim][volume].size(); i++)
+      projection.addToMatrix(*s.myAssembler, groups[dim][volume][i]);
+    projection.addNeumann(volume, dim, 0, 1, par, *s.myAssembler);
+    s.lsys->systemSolve();
+    for (unsigned int i = 0; i < vertices.size(); i++)
+      data[vertices[i]->getNum()].push_back
+        (s.myAssembler->getDofValue(vertices[i], 0, 1));
+    PView *pv = new PView("projection", "NodeData", m, data, 0.);
+  }
+  else if(equation == "Laplace"){
     solver<double> s;
     if(!s.myAssembler->sizeOfR()) return 0;
-    gmshFunction<double> diffusivity(parameter);
-    gmshLaplaceTerm laplace(m, &diffusivity, 1);
+    gmshMathEvalFunction<double> par(parameter);
+    gmshLaplaceTerm laplace(m, &par, 1);
     for(unsigned int i = 0; i < groups[dim][volume].size(); i++)
       laplace.addToMatrix(*s.myAssembler, groups[dim][volume][i]);
     s.lsys->systemSolve();
@@ -156,8 +210,8 @@ PView *GMSH_FiniteElementPlugin::execute(PView *v)
   else if(equation == "Helmholtz"){
     solver<std::complex<double> > s;
     if(!s.myAssembler->sizeOfR()) return 0;
-    gmshFunction<std::complex<double> > waveNumber(parameter);
-    gmshHelmholtzTerm helmholtz(m, &waveNumber, 1);
+    gmshMathEvalFunction<std::complex<double> > par(parameter);
+    gmshHelmholtzTerm helmholtz(m, &par, 1);
     for(unsigned int i = 0; i < groups[dim][volume].size(); i++)
       helmholtz.addToMatrix(*s.myAssembler, groups[dim][volume][i]);
     s.lsys->setGmres(1);
diff --git a/Plugin/Makefile b/Plugin/Makefile
index f6a28415efc974b5bfdb6363760349dd29d1333f..e822f87ef1f93b24b7ea84cb7fe232d786edc63b 100644
--- a/Plugin/Makefile
+++ b/Plugin/Makefile
@@ -320,7 +320,7 @@ FiniteElement${OBJEXT}: FiniteElement.cpp ../Common/GmshConfig.h ../Geo/GModel.h
   ../Post/ColorTable.h ../Common/GmshMessage.h ../Post/PView.h \
   ../Post/PViewDataList.h ../Post/PViewData.h ../Numeric/GmshMatrix.h \
   ../Common/ListUtils.h ../Numeric/gmshAssembler.h \
-  ../Numeric/gmshLinearSystem.h ../Numeric/gmshLaplace.h \
+  ../Numeric/gmshLinearSystem.h ../Numeric/gmshProjection.h \
   ../Numeric/gmshTermOfFormulation.h ../Numeric/GmshMatrix.h \
   ../Numeric/gmshFunction.h ../Numeric/gmshAssembler.h ../Geo/MElement.h \
   ../Common/GmshDefines.h ../Geo/MVertex.h ../Geo/SPoint2.h \
@@ -328,6 +328,8 @@ FiniteElement${OBJEXT}: FiniteElement.cpp ../Common/GmshConfig.h ../Geo/GModel.h
   ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
   ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h ../Numeric/Gauss.h \
   ../Numeric/gmshFunction.h ../Common/Gmsh.h ../Common/GmshMessage.h \
+  ../Numeric/GmshMatrix.h ../Numeric/gmshLaplace.h \
+  ../Numeric/gmshTermOfFormulation.h ../Numeric/gmshFunction.h \
   ../Numeric/GmshMatrix.h ../Numeric/gmshHelmholtz.h \
   ../Numeric/gmshTermOfFormulation.h ../Numeric/gmshFunction.h \
   ../Numeric/GmshMatrix.h ../Numeric/gmshLinearSystemGmm.h \
diff --git a/doc/TODO.txt b/doc/TODO.txt
index 0e59153b3b99ee38fbaf5689bc9218999c15c3b4..1099b6123973e695722b7a74e47ffef9aae407f5 100644
--- a/doc/TODO.txt
+++ b/doc/TODO.txt
@@ -1,4 +1,10 @@
-$Id: TODO.txt,v 1.20 2009-03-10 12:06:14 geuzaine Exp $
+$Id: TODO.txt,v 1.21 2009-03-17 07:36:33 geuzaine Exp $
+
+********************************************************************
+
+extrude along a given curve (use curve->closestPoint for each xyz in
+ExtrudeParams and extrude along the tangent? not that simple: this
+could lead to self-intersection if curvature >>)
 
 ********************************************************************
 
@@ -129,10 +135,6 @@ implement better algo to determine which axes to draw
 
 ********************************************************************
 
-extrude along a given function or along a parametric curve
-
-********************************************************************
-
 Custom range on "filled iso" 3D views produces ugly plots, where one
 sees inside the cut elements. (In the meantime, one can use
 Plugin(CutMap) with "ExtractVolume" set to 1 (or -1): this will
diff --git a/doc/VERSIONS.txt b/doc/VERSIONS.txt
index ea83933b2742a501e992c967cffaaebc95e0a643..21d72f34c0153c19c226b616a1fe2beac210b301 100644
--- a/doc/VERSIONS.txt
+++ b/doc/VERSIONS.txt
@@ -1,10 +1,10 @@
-$Id: VERSIONS.txt,v 1.40 2009-03-16 07:23:48 geuzaine Exp $
+$Id: VERSIONS.txt,v 1.41 2009-03-17 07:36:33 geuzaine Exp $
 
-(?): removed GSL dependency (Gmsh now simply requires Blas and
+2.3.1 (?): removed GSL dependency (Gmsh now simply uses Blas and
 Lapack); new per-window visibility; added support for composite window
-printing and background images; fixes for string options in parser;
-fixed surface mesh orientation for Open Cascade models; fixed triangle
-orientations in Delaunay and Frontal algorithms.
+printing and background images; fixed string option affectation in
+parser; fixed surface mesh orientation for Open Cascade models; fixed
+random triangle orientations in Delaunay and Frontal algorithms.
 
 2.3.0 (Jan 23, 2009): major graphics and GUI code refactoring; new
 full-quad/hexa subdivision algorithm (removed Mesh.RecombineAlgo);