diff --git a/Common/VertexArray.cpp b/Common/VertexArray.cpp
index 570255712b005d107e047b8469a5b3aef64f428d..3a42d4ab1a83d17e33d983786cfde868cdbbe8c4 100644
--- a/Common/VertexArray.cpp
+++ b/Common/VertexArray.cpp
@@ -1,4 +1,4 @@
-// $Id: VertexArray.cpp,v 1.4 2005-01-01 19:35:27 geuzaine Exp $
+// $Id: VertexArray.cpp,v 1.5 2005-05-21 01:10:46 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -27,8 +27,8 @@
 VertexArray::VertexArray(int numNodesPerElement, int numElements) 
 {
   type = numNodesPerElement;
-  if(type != 3 && type != 4){
-    Msg(GERROR, "Vertex arrays should only contain triangles or quadrangles");
+  if(type != 2 && type != 3 && type != 4){
+    Msg(GERROR, "Vertex arrays should only contain lines, triangles or quadrangles");
     type = 3;
   }
   num = fill = 0;
@@ -66,6 +66,21 @@ void VertexArray::add(float x, float y, float z,
   List_Add(colors, &a);
 }
 
+void VertexArray::add(float x, float y, float z, unsigned int col)
+{
+  unsigned char r = UNPACK_RED(col);
+  unsigned char g = UNPACK_GREEN(col);
+  unsigned char b = UNPACK_BLUE(col);
+  unsigned char a = UNPACK_ALPHA(col);
+  List_Add(vertices, &x);
+  List_Add(vertices, &y);
+  List_Add(vertices, &z);
+  List_Add(colors, &r);
+  List_Add(colors, &g);
+  List_Add(colors, &b);
+  List_Add(colors, &a);
+}
+
 static double theeye[3];
 
 int compareTriEye(const void *a, const void *b)
diff --git a/Common/VertexArray.h b/Common/VertexArray.h
index c2509e84764868cee364b28a04a604a99bcaa10a..2d31f67ed3b4643caecbd96382c9bffd70f8e310 100644
--- a/Common/VertexArray.h
+++ b/Common/VertexArray.h
@@ -30,6 +30,7 @@ class VertexArray{
   ~VertexArray();
   void add(float x, float y, float z, 
 	   float n0, float n1, float n2, unsigned int col);
+  void add(float x, float y, float z, unsigned int col);
   void sort(double eye[3]);
 };
 
diff --git a/Graphics/Draw.h b/Graphics/Draw.h
index 5b6790c953a70716ff382ae75320219d99426d5e..b21a6f299225ce35f22fac0d5dfc2ca97765ad72 100644
--- a/Graphics/Draw.h
+++ b/Graphics/Draw.h
@@ -100,7 +100,7 @@ void Draw_Mesh_Tetrahedron(void *a, void *b);
 void Draw_Mesh_Hexahedron(void *a, void *b);
 void Draw_Mesh_Prism(void *a, void *b);
 void Draw_Mesh_Pyramid(void *a, void *b);
-void Draw_Mesh_Array(VertexArray *va, int faces, int edges);
+void Draw_Mesh_Array(VertexArray *va, int faces=0, int edges=0);
 
 #define ARGS Post_View *View, int preproNormals, \
              double ValMin, double ValMax, 	 \
diff --git a/Graphics/Mesh.cpp b/Graphics/Mesh.cpp
index 1cf9385bc886c520155d0208c499007428c266f8..abafe8d1c8d49025e1f3a571dcf1ff602da498f2 100644
--- a/Graphics/Mesh.cpp
+++ b/Graphics/Mesh.cpp
@@ -1,4 +1,4 @@
-// $Id: Mesh.cpp,v 1.125 2005-03-15 15:43:31 geuzaine Exp $
+// $Id: Mesh.cpp,v 1.126 2005-05-21 01:10:47 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -47,6 +47,7 @@ extern int quadfaces_pyramid[1][4];
 
 static DrawingColor theColor;
 static int thePhysical = 0;
+static Curve *theCurve = NULL;
 static Surface *theSurface = NULL;
 static Volume *theVolume = NULL;
 
@@ -427,11 +428,37 @@ void Draw_Mesh_Curve(void *a, void *b)
     return;
   if(!(c->Visible & VIS_MESH))
     return;
+
+  theCurve = c;
   theColor = c->Color;
   thePhysical = getFirstPhysical(MSH_PHYSICAL_LINE, c->Num);
 
-  Tree_Action(c->Simplexes, Draw_Mesh_Line);
-  Tree_Action(c->SimplexesBase, Draw_Mesh_Line);
+  if(CTX.mesh.vertex_arrays){
+    if(CTX.mesh.changed){
+      Msg(DEBUG, "regenerate curve mesh vertex array");
+      if(c->LinVertexArray) delete c->LinVertexArray;
+      c->LinVertexArray = new VertexArray(2, Tree_Nbr(c->Simplexes) + 
+					  Tree_Nbr(c->SimplexesBase));
+      c->LinVertexArray->fill = 1;
+      Tree_Action(c->Simplexes, Draw_Mesh_Line);
+      Tree_Action(c->SimplexesBase, Draw_Mesh_Line);
+      if(c->LinVertexArray){
+	Msg(DEBUG, "%d segments in curve vertex array", c->LinVertexArray->num);
+	c->LinVertexArray->fill = 0;
+      }
+    }
+    if(c->LinVertexArray)
+      Draw_Mesh_Array(c->LinVertexArray);
+  }
+    
+  if(!c->LinVertexArray || CTX.mesh.lines_num ||
+     CTX.mesh.points_per_element || CTX.mesh.tangents){
+    Msg(DEBUG, "classic line data path");
+    Tree_Action(c->Simplexes, Draw_Mesh_Line);
+    Tree_Action(c->SimplexesBase, Draw_Mesh_Line);
+  }
+
+  theCurve = NULL;
 }
 
 void Draw_Mesh_Point(int num, double x, double y, double z, int degree, int visible)
@@ -527,26 +554,41 @@ void Draw_Mesh_Line(void *a, void *b)
 		      s->VSUP[0]->Degree, s->VSUP[0]->Visible);
   }
 
+  unsigned int col;
   if(theColor.type)
-    glColor4ubv((GLubyte *) & theColor.mesh);
+    col = theColor.mesh;
   else if(CTX.mesh.color_carousel == 1)
-    glColor4ubv((GLubyte *) & CTX.color.mesh.carousel[abs(s->iEnt % 10)]);
+    col = CTX.color.mesh.carousel[abs(s->iEnt % 10)];
   else if(CTX.mesh.color_carousel == 2)
-    glColor4ubv((GLubyte *) & CTX.color.mesh.carousel[abs(thePhysical % 10)]);
+    col = CTX.color.mesh.carousel[abs(thePhysical % 10)];
   else if(CTX.mesh.color_carousel == 3)
-    glColor4ubv((GLubyte *) & CTX.color.mesh.carousel[abs(s->iPart % 10)]);
+    col = CTX.color.mesh.carousel[abs(s->iPart % 10)];
   else
-    glColor4ubv((GLubyte *) & CTX.color.mesh.line);
-
-  if(CTX.mesh.lines) {
-    glBegin(GL_LINE_STRIP);
-    for(int i = 0; i < N; i++){
-      glVertex3d(X[i], Y[i], Z[i]);
+    col = CTX.color.mesh.line;
+
+  if(theCurve && theCurve->LinVertexArray && theCurve->LinVertexArray->fill){
+    theCurve->LinVertexArray->add(X[0], Y[0], Z[0], col);
+    theCurve->LinVertexArray->add(X[1], Y[1], Z[1], col);
+    theCurve->LinVertexArray->num++;
+    if(N == 3){
+      theCurve->LinVertexArray->add(X[1], Y[1], Z[1], col);
+      theCurve->LinVertexArray->add(X[2], Y[2], Z[2], col);
+      theCurve->LinVertexArray->num++;
+    }
+  }
+  else{
+    if(CTX.mesh.lines) {
+      glColor4ubv((GLubyte *) & col);
+      glBegin(GL_LINE_STRIP);
+      for(int i = 0; i < N; i++){
+	glVertex3d(X[i], Y[i], Z[i]);
+      }
+      glEnd();
     }
-    glEnd();
   }
 
   if(CTX.mesh.lines_num) {
+    glColor4ubv((GLubyte *) & col);
     sprintf(Num, "%d", s->Num);
     double offset = 0.3 * (CTX.mesh.line_width + CTX.gl_fontsize) * CTX.pixel_equiv_x;
     glRasterPos3d(Xc + offset / CTX.s[0],
@@ -696,33 +738,38 @@ void Draw_Mesh_Array(VertexArray *va, int faces, int edges)
     return;
 
   glVertexPointer(3, GL_FLOAT, 0, va->vertices->array);
-  glNormalPointer(GL_FLOAT, 0, va->normals->array);
   glColorPointer(4, GL_UNSIGNED_BYTE, 0, va->colors->array);
+  glNormalPointer(GL_FLOAT, 0, va->normals->array);
 
   glEnableClientState(GL_VERTEX_ARRAY);
   glEnableClientState(GL_COLOR_ARRAY);
   glEnableClientState(GL_NORMAL_ARRAY);
 
-  if(faces){
-    if(CTX.mesh.light)
-      glEnable(GL_LIGHTING);
-    else
-      glDisableClientState(GL_NORMAL_ARRAY);
-    if(CTX.polygon_offset) glEnable(GL_POLYGON_OFFSET_FILL);
-    glDrawArrays((va->type == 3) ? GL_TRIANGLES : GL_QUADS, 0, va->type * va->num);
-    glDisable(GL_POLYGON_OFFSET_FILL);
-    glDisable(GL_LIGHTING);
+  if(va->type == 2){
+    glDisableClientState(GL_NORMAL_ARRAY);
+    glDrawArrays(GL_LINES, 0, va->type * va->num);
   }
-      
-  if(edges){
+  else{
     if(faces){
-      glDisableClientState(GL_COLOR_ARRAY);
-      glColor4ubv((GLubyte *) & CTX.color.mesh.line);
+      if(CTX.mesh.light)
+	glEnable(GL_LIGHTING);
+      else
+	glDisableClientState(GL_NORMAL_ARRAY);
+      if(CTX.polygon_offset) glEnable(GL_POLYGON_OFFSET_FILL);
+      glDrawArrays((va->type == 3) ? GL_TRIANGLES : GL_QUADS, 0, va->type * va->num);
+      glDisable(GL_POLYGON_OFFSET_FILL);
+      glDisable(GL_LIGHTING);
+    }
+    if(edges){
+      if(faces){
+	glDisableClientState(GL_COLOR_ARRAY);
+	glColor4ubv((GLubyte *) & CTX.color.mesh.line);
+      }
+      glDisableClientState(GL_NORMAL_ARRAY);
+      glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+      glDrawArrays((va->type == 3) ? GL_TRIANGLES : GL_QUADS, 0, va->type * va->num);
+      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
     }
-    glDisableClientState(GL_NORMAL_ARRAY);
-    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-    glDrawArrays((va->type == 3) ? GL_TRIANGLES : GL_QUADS, 0, va->type * va->num);
-    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
   }
 
   glDisableClientState(GL_VERTEX_ARRAY);
diff --git a/Mesh/Create.cpp b/Mesh/Create.cpp
index e30bce3e7f0b0c51e6b85958ef3ad4b9071d53e7..cf017ea875602031047d8173f0e8554f5d6f960b 100644
--- a/Mesh/Create.cpp
+++ b/Mesh/Create.cpp
@@ -1,4 +1,4 @@
-// $Id: Create.cpp,v 1.73 2005-05-15 01:44:26 geuzaine Exp $
+// $Id: Create.cpp,v 1.74 2005-05-21 01:10:47 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -510,10 +510,6 @@ void End_Surface(Surface * s, int reset_orientations)
 Curve *Create_Curve(int Num, int Typ, int Order, List_T * Liste,
                     List_T * Knots, int p1, int p2, double u1, double u2)
 {
-  Curve *pC;
-  Vertex *v;
-  int i, j, iPnt;
-  double d;
   double matcr[4][4] = { {-0.5, 1.5, -1.5, 0.5},
 			 {1.0, -2.5, 2.0, -0.5},
 			 {-0.5, 0.0, 0.5, 0.0},
@@ -527,12 +523,14 @@ Curve *Create_Curve(int Num, int Typ, int Order, List_T * Liste,
 			  {-3, 3.0, 0, 0.0},
 			  {1, 0, 0, 0.0} };
 
-  pC = (Curve *) Malloc(sizeof(Curve));
+  Curve *pC = (Curve *) Malloc(sizeof(Curve));
   pC->bds = 0;
+  pC->LinVertexArray = NULL;
   pC->Color.type = 0;
   pC->Visible = VIS_GEOM | VIS_MESH;
   pC->cp = NULL;
   pC->Vertices = List_Create(2, 20, sizeof(Vertex *));
+  pC->VerticesTemp = NULL;
   pC->Extrude = NULL;
   pC->Typ = Typ;
   pC->Num = Num;
@@ -544,24 +542,24 @@ Curve *Create_Curve(int Num, int Typ, int Order, List_T * Liste,
   pC->Circle.n[0] = 0.0;
   pC->Circle.n[1] = 0.0;
   pC->Circle.n[2] = 1.0;
-  for(i = 0; i < 4; i++) {
+  for(int i = 0; i < 4; i++) {
     pC->ipar[i] = 0;
     pC->dpar[i] = 0.0;
   }
 
   if(Typ == MSH_SEGM_SPLN) {
-    for(i = 0; i < 4; i++)
-      for(j = 0; j < 4; j++)
+    for(int i = 0; i < 4; i++)
+      for(int j = 0; j < 4; j++)
         pC->mat[i][j] = matcr[i][j];
   }
   else if(Typ == MSH_SEGM_BSPLN) {
-    for(i = 0; i < 4; i++)
-      for(j = 0; j < 4; j++)
+    for(int i = 0; i < 4; i++)
+      for(int j = 0; j < 4; j++)
         pC->mat[i][j] = matbs[i][j] / 6.0;
   }
   else if(Typ == MSH_SEGM_BEZIER) {
-    for(i = 0; i < 4; i++)
-      for(j = 0; j < 4; j++)
+    for(int i = 0; i < 4; i++)
+      for(int j = 0; j < 4; j++)
         pC->mat[i][j] = matbez[i][j];
   }
 
@@ -575,7 +573,8 @@ Curve *Create_Curve(int Num, int Typ, int Order, List_T * Liste,
     List_Read(Knots, List_Nbr(Knots) - 1, &kmax);
     pC->ubeg = kmin;
     pC->uend = kmax;
-    for(i = 0; i < List_Nbr(Knots); i++) {
+    for(int i = 0; i < List_Nbr(Knots); i++) {
+      double d;
       List_Read(Knots, i, &d);
       pC->k[i] = (float)d;
     }
@@ -585,8 +584,10 @@ Curve *Create_Curve(int Num, int Typ, int Order, List_T * Liste,
 
   if(Liste) {
     pC->Control_Points = List_Create(List_Nbr(Liste), 1, sizeof(Vertex *));
-    for(j = 0; j < List_Nbr(Liste); j++) {
+    for(int j = 0; j < List_Nbr(Liste); j++) {
+      int iPnt;
       List_Read(Liste, j, &iPnt);
+      Vertex *v;
       if((v = FindPoint(iPnt, THEM)))
         List_Add(pC->Control_Points, &v);
       else{
@@ -606,6 +607,7 @@ Curve *Create_Curve(int Num, int Typ, int Order, List_T * Liste,
     List_Read(pC->Control_Points, List_Nbr(pC->Control_Points) - 1, &pC->end);
   }
   else {
+    Vertex *v;
     if((v = FindPoint(p1, THEM))) {
       Msg(INFO, "Curve %d first control point %d ", pC->Num, v->Num);
       pC->beg = v;
@@ -631,6 +633,8 @@ void Free_Curve(void *a, void *b)
 {
   Curve *pC = *(Curve **) a;
   if(pC) {
+    if(pC->LinVertexArray)
+      delete pC->LinVertexArray;
     List_Delete(pC->Vertices);
     Tree_Action(pC->Simplexes, Free_Simplex);
     Tree_Delete(pC->Simplexes);
@@ -646,10 +650,7 @@ void Free_Curve(void *a, void *b)
 
 Surface *Create_Surface(int Num, int Typ)
 {
-  Surface *pS;
-  int i;  
-
-  pS = (Surface *) Malloc(sizeof(Surface));
+  Surface *pS = (Surface *) Malloc(sizeof(Surface));
   pS->bds = 0;
   pS->Color.type = 0;
   pS->Visible = VIS_GEOM | VIS_MESH;
@@ -657,7 +658,7 @@ Surface *Create_Surface(int Num, int Typ)
   THEM->MaxSurfaceNum = IMAX(THEM->MaxSurfaceNum, Num);
   pS->Typ = Typ;
   pS->Method = LIBRE;
-  for(i = 0; i < 5; i++)
+  for(int i = 0; i < 5; i++)
     pS->ipar[i] = 0;
   pS->Recombine = 0;
   pS->RecombineAngle = 75;
@@ -714,17 +715,14 @@ void Free_Surface(void *a, void *b)
 
 Volume *Create_Volume(int Num, int Typ)
 {
-  Volume *pV;
-  int i;
-
-  pV = (Volume *) Malloc(sizeof(Volume));
+  Volume *pV = (Volume *) Malloc(sizeof(Volume));
   pV->Color.type = 0;
   pV->Visible = VIS_GEOM | VIS_MESH;
   pV->Num = Num;
   THEM->MaxVolumeNum = IMAX(THEM->MaxVolumeNum, Num);
   pV->Typ = Typ;
   pV->Method = LIBRE;
-  for(i = 0; i < 8; i++)
+  for(int i = 0; i < 8; i++)
     pV->ipar[i] = 0;
   pV->TrsfPoints = List_Create(6, 6, sizeof(Vertex *));
   pV->Surfaces = List_Create(1, 2, sizeof(Surface *));
diff --git a/Mesh/Mesh.h b/Mesh/Mesh.h
index 54cbe81d3e313cc6fff0737f00cb8fa28e8ab2f2..027816b18a2d5517c6237a6e9b4f1ba9cefb5fe2 100644
--- a/Mesh/Mesh.h
+++ b/Mesh/Mesh.h
@@ -354,26 +354,28 @@ typedef struct{
 }CircParam;
 
 typedef struct{
-    int Num;
-    int Typ;
-    char Visible;
-    int Method;
-    int ipar[4];
-    double dpar[4];
-    double l;
-    double mat[4][4];
-    Vertex *beg, *end;
-    double ubeg, uend;
-    List_T *Control_Points;
-    List_T *Vertices;
-    Tree_T *Simplexes, *SimplexesBase;
-    ExtrudeParams *Extrude;
-    float *k, *cp;
-    int degre;
-    CircParam Circle;
-    char functu[256], functv[256], functw[256];
-    DrawingColor Color;
-    BDS_Mesh *bds;
+  int Num;
+  int Typ;
+  char Visible;
+  int Method;
+  int ipar[4];
+  double dpar[4];
+  double l;
+  double mat[4][4];
+  Vertex *beg, *end;
+  double ubeg, uend;
+  List_T *Control_Points;
+  List_T *Vertices;
+  Tree_T *VerticesTemp; // a temp tree for fast vertex insertion
+  Tree_T *Simplexes, *SimplexesBase;
+  ExtrudeParams *Extrude;
+  float *k, *cp;
+  int degre;
+  CircParam Circle;
+  char functu[256], functv[256], functw[256];
+  DrawingColor Color;
+  BDS_Mesh *bds;
+  VertexArray *LinVertexArray;
 }Curve;
 
 typedef struct{
diff --git a/Mesh/Read_Mesh.cpp b/Mesh/Read_Mesh.cpp
index 2a07ac1b8f2539052bde4c6c1b3881304697b57e..ed16b303c2199af0c6f4126437694fff1183bacd 100644
--- a/Mesh/Read_Mesh.cpp
+++ b/Mesh/Read_Mesh.cpp
@@ -1,4 +1,4 @@
-// $Id: Read_Mesh.cpp,v 1.87 2005-05-15 01:44:26 geuzaine Exp $
+// $Id: Read_Mesh.cpp,v 1.88 2005-05-21 01:10:47 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -120,6 +120,21 @@ int getNbrNodes(int Type)
   }
 }
 
+static Curve *theCurve = NULL;
+
+static void TransferVertex(void *a, void *b)
+{
+  List_Add(theCurve->Vertices, a);
+}
+
+static void Transfer_VertexTree2List(void *a, void *b)
+{
+  theCurve = *(Curve**)a;
+  Tree_Action(theCurve->VerticesTemp, TransferVertex);
+  Tree_Delete(theCurve->VerticesTemp);
+  theCurve->VerticesTemp = NULL;
+}
+
 void Read_Mesh_MSH(Mesh * M, FILE * fp)
 {
   char String[256];
@@ -325,8 +340,16 @@ void Read_Mesh_MSH(Mesh * M, FILE * fp)
 	    Free_SimplexBase(&simp, 0);
 	  }
 	  else{
+	    // This is dog slow when there is a large num of verts per curve:
+	    //
+	    // for(i = 0; i < Nbr_Nodes; i++)
+	    //    List_Insert(c->Vertices, &vertsp[i], fcmp_int);
+	    //
+	    // So we use a temp tree instead:
+	    if(!c->VerticesTemp)
+	      c->VerticesTemp = Tree_Create(sizeof(Vertex *), compareVertex);
 	    for(i = 0; i < Nbr_Nodes; i++)
-	      List_Insert(c->Vertices, &vertsp[i], fcmp_int);
+	      Tree_Insert(c->VerticesTemp, &vertsp[i]);
 	  }
           break;
         case TRI1:
@@ -536,6 +559,9 @@ void Read_Mesh_MSH(Mesh * M, FILE * fp)
   // re-sort the list according to these indices to allow direct
   // access through List_Pointer & co.
   List_Sort(M->Partitions, compareMeshPartitionIndex);
+
+  // Transfer the vertices from temp trees into lists
+  Tree_Action(M->Curves, Transfer_VertexTree2List);
 }
 
 // Read mesh in VTK format
diff --git a/doc/VERSIONS b/doc/VERSIONS
index 7aa1b734513ddce0dc74697c65b9513e3e142b20..2801646f1f59584ae1057e094bdec4c2f58a3a75 100644
--- a/doc/VERSIONS
+++ b/doc/VERSIONS
@@ -1,11 +1,12 @@
-$Id: VERSIONS,v 1.326 2005-04-06 21:40:15 geuzaine Exp $
+$Id: VERSIONS,v 1.327 2005-05-21 01:10:48 geuzaine Exp $
 
 New since 1.60: added support for second order (curved) elements in
 post-processor; new version (1.4) of post-processing file formats; new
 stippling options for 2D plots; removed limit on allowed number of
 files on command line; all "Combine" operations are now available in
 the parser; changed View.ArrowLocation into View.GlyphLocation;
-optimized memory usage when loading many (>1000) views;
+optimized memory usage when loading many (>1000) views; optimzed
+loading and drawing of line meshes; 
 
 New in 1.60: added support for discrete curves; new Window menu on Mac
 OS X; generalized all octree-based plugins (CutGrid, StreamLines,