diff --git a/Geo/GeoUtils.cpp b/Geo/GeoUtils.cpp
index 671bd2ffe99d30266d613760279f9c0d7afa2bae..34ad2d10086d6922c00338e784c7aa860002490c 100644
--- a/Geo/GeoUtils.cpp
+++ b/Geo/GeoUtils.cpp
@@ -1,4 +1,4 @@
-// $Id: GeoUtils.cpp,v 1.12 2006-04-16 03:27:30 geuzaine Exp $
+// $Id: GeoUtils.cpp,v 1.13 2006-04-16 18:55:18 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -51,22 +51,7 @@ void sortEdgesInLoop(int num, List_T *edges)
 	    for(int k = List_Nbr(rc->Vertices) - 1; k >= 0; k--)
 	      List_Add(c->Vertices, List_Pointer(rc->Vertices, k));
 	}
-	// if the loop is composed of a single discrete curve we check
-	// if the first vertex and the last vertex are the same. If
-	// not, we assume that they should, and we add the missing end
-	// vertex. (This situation can arise due to a limitation in
-	// Read_Mesh, where we do a List_Insert() to add the vertices
-	// in discrete curves--so that we never get the last vertex
-	// for single, closed curves.)
-	if(nbEdges == 1 && List_Nbr(c->Vertices)){
-	  Vertex *first = *(Vertex**)List_Pointer(c->Vertices, 0);
-	  Vertex *last = *(Vertex**)List_Pointer(c->Vertices, List_Nbr(c->Vertices) - 1);
-	  if(first != last){
-	    Msg(INFO, "Adding last vertex in closed discrete curve %d", c->Num);
-	    List_Add(c->Vertices, &first);
-	  }
-	}
-	// setting end points for discrete curves
+	// set end points for discrete curves
 	if(!c->beg && !c->end && List_Nbr(c->Vertices)){
 	  Vertex *first = *(Vertex**)List_Pointer(c->Vertices, 0);
 	  Vertex *last = *(Vertex**)List_Pointer(c->Vertices, List_Nbr(c->Vertices) - 1);
@@ -80,7 +65,6 @@ void sortEdgesInLoop(int num, List_T *edges)
   }
   List_Reset(edges);
 
- 
   int j = 0, k = 0;
   c0 = c1 = *(Curve **) List_Pointer(temp, 0);
   List_Add(edges, &c1->Num);
diff --git a/Mesh/Read_Mesh.cpp b/Mesh/Read_Mesh.cpp
index 42adc7324352cffb4d38309d8365f31aa413fe28..1007662f2c170b105235049687ccb889daba020e 100644
--- a/Mesh/Read_Mesh.cpp
+++ b/Mesh/Read_Mesh.cpp
@@ -1,4 +1,4 @@
-// $Id: Read_Mesh.cpp,v 1.103 2006-04-04 04:32:31 geuzaine Exp $
+// $Id: Read_Mesh.cpp,v 1.104 2006-04-16 18:55:18 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -20,6 +20,7 @@
 // Please report all bugs and problems to <gmsh@geuz.org>.
 
 #include <map>
+#include <vector>
 #include "Gmsh.h"
 #include "Geo.h"
 #include "CAD.h"
@@ -66,6 +67,80 @@ Curve *addElementaryCurve(Mesh * M, int Num)
   return c;
 }
 
+class nodex{
+ public:
+  Vertex *v;
+  int left, right; // index left/right segment in simplex list
+  nodex(Vertex *vv) : v(vv), left(-1), right(-1) {}
+};
+
+void addVerticesInCurve(void *a, void *b)
+{
+  Curve *c = *(Curve**)a;
+
+  // check if already done or if nothing to do
+  if(List_Nbr(c->Vertices) || !Tree_Nbr(c->SimplexesBase)) 
+    return;
+
+  List_T *elm = Tree2List(c->SimplexesBase);
+
+  // construct node x segment connectivity
+  std::map<int, nodex*> nodes;
+  for(int i = 0; i < List_Nbr(elm); i++){
+    SimplexBase *s = *(SimplexBase**)List_Pointer(elm, i);
+    for(int j = 0; j < 2; j++){
+      if(!nodes.count(s->V[j]->Num))
+	nodes[s->V[j]->Num] = new nodex(s->V[j]);
+      if(!j)
+	nodes[s->V[j]->Num]->right = i;
+      else
+	nodes[s->V[j]->Num]->left = i;
+    }
+  }
+
+  // find starting element (or use the first one for closed curve)
+  std::map<int, nodex*>::const_iterator beg = nodes.begin();
+  std::map<int, nodex*>::const_iterator end = nodes.end();
+  int start = 0;
+  while(beg != end){
+    if((*beg).second->left < 0){ // no element to the left
+      start = (*beg).second->right;
+      break;
+    }
+    beg++;
+  }
+
+  // add nodes by following the line segments
+  if(start < 0){
+    Msg(GERROR, "Something is wrong in mesh of curve %d", c->Num);
+  }
+  else{
+    int N = List_Nbr(elm);
+    SimplexBase *s = *(SimplexBase**)List_Pointer(elm, start);
+    List_Add(c->Vertices, &s->V[0]);
+    while(N > 0){
+      if(s->VSUP) List_Add(c->Vertices, &s->VSUP[0]);
+      List_Add(c->Vertices, &s->V[1]);
+      nodex *n = nodes[s->V[1]->Num];
+      if(n->left != start){
+	Msg(GERROR, "Wrong orientation of element %d in curve %d", s->Num, c->Num);
+	break;
+      }
+      start = n->right;
+      if(start >= 0){
+	s = *(SimplexBase**)List_Pointer(elm, start);
+      }
+      else if(N != 1){
+	Msg(GERROR, "Something is wrong in mesh of curve %d", c->Num);
+	break;
+      }
+      N--;
+    }
+  }
+  
+  List_Delete(elm);
+}
+
 Surface *addElementarySurface(Mesh * M, int Num)
 {
   Surface *s;
@@ -430,11 +505,11 @@ void Read_Mesh_MSH(Mesh * M, FILE * fp)
 	    Msg(GERROR, "Line element %d already exists", simp->Num);
 	    Free_SimplexBase(&simp, 0);
 	  }
-	  else{
-	    // this can be quite slow if there are many nodes on the curve...
-	    for(i = 0; i < Nbr_Nodes; i++)
-	      List_Insert(c->Vertices, &vertsp[i], compareVertex);
-	  }
+	  // we don't insert the vertices in the list of vertices at
+	  // this point, since we need the list to ordered (and
+	  // consistent!), and simply doing a List_Insert and sorting
+	  // according to node numbers is not enough (in addition to
+	  // being slow): see addVerticesInCurve() below.
           break;
         case TRI1:
         case TRI2:
@@ -641,6 +716,9 @@ void Read_Mesh_MSH(Mesh * M, FILE * fp)
   else
     M->status = -1;
 
+  // add vertices in curves
+  Tree_Action(M->Curves, addVerticesInCurve);
+
   // For efficiency reasons, we store the partition index (and not the
   // partition number) in the various mesh elements. We need to
   // re-sort the list according to these indices to allow direct