diff --git a/Fltk/classificationEditor.cpp b/Fltk/classificationEditor.cpp
index 6e1c480d82117996e5f8b04199923b5ce207d1dc..4e130fd34acd8afc8e2f7b08fd6991c70a3c65d4 100644
--- a/Fltk/classificationEditor.cpp
+++ b/Fltk/classificationEditor.cpp
@@ -4,7 +4,7 @@
 // bugs and problems to <gmsh@geuz.org>.
 
 #include <FL/Fl_Tabs.H>
-#include <FL/Fl_Value_Input.H>
+#include <FL/Fl_Box.H>
 #include "FlGui.h"
 #include "classificationEditor.h"
 #include "paletteWindow.h"
@@ -19,184 +19,43 @@
 #include "discreteEdge.h"
 #include "discreteFace.h"
 
-static void NoElementsSelectedMode(classificationEditor *e)
-{
-  e->_buttons[CLASSBUTTON_DEL]->deactivate();
-  e->_buttons[CLASSBUTTON_ADD]->deactivate();
-  e->_buttons[CLASSBUTTON_CLEAR]->deactivate();
-  //  e->_buttons[CLASSBUTTON_OK]->deactivate();
-  e->_togbuttons[CLASSTOGBUTTON_CLOS]->deactivate();
-  e->_inputs[CLASSVALUE_ANGLE]->deactivate();
-
-  e->_buttons[CLASSBUTTON_SELECT]->activate(); 
-  e->_togbuttons[CLASSTOGBUTTON_HIDE]->activate(); 
-}
-
-static void ElementsSelectedMode(classificationEditor *e)
-{
-  e->_buttons[CLASSBUTTON_DEL]->activate();
-  e->_buttons[CLASSBUTTON_ADD]->activate();
-  e->_buttons[CLASSBUTTON_CLEAR]->activate();
-  e->_togbuttons[CLASSTOGBUTTON_CLOS]->activate();
-  e->_inputs[CLASSVALUE_ANGLE]->activate();
-  //  e->_buttons[CLASSBUTTON_OK]->activate();
-
-  e->_buttons[CLASSBUTTON_SELECT]->deactivate(); 
-  e->_togbuttons[CLASSTOGBUTTON_HIDE]->deactivate(); 
-}
-
-// we should 
-static void class_selectgface_cb(Fl_Widget *w, void *data)
-{
-  classificationEditor *e = (classificationEditor*)data;
-  std::vector<GFace*> temp;
-
-  opt_geometry_surfaces(0, GMSH_SET | GMSH_GUI, 1);
-
-  while(1) {
-    CTX::instance()->mesh.changed = ENT_ALL;
-    drawContext::global()->draw();
-
-    Msg::StatusBar(3, false, "Select Model Face\n"
-                   "[Press 'e' to end selection or 'q' to abort]");
-    
-    char ib = FlGui::instance()->selectEntity(ENT_SURFACE);
-    if(ib == 'l') {
-      for(unsigned int i = 0; i < FlGui::instance()->selectedFaces.size(); i++){
-        FlGui::instance()->selectedFaces[i]->setSelection(1);
-        temp.push_back(FlGui::instance()->selectedFaces[i]);
-      }
-    }
-    // ok store the list of gfaces !
-    if(ib == 'e') {
-      GModel::current()->setSelection(0);
-      for(unsigned int i = 0; i < temp.size(); i++){
-        e->_faces.insert(temp[i]);
-      }
-      break;
-    }
-    // do nothing
-    if(ib == 'q') {
-      GModel::current()->setSelection(0);
-      break;
-    }
-  } 
-  CTX::instance()->mesh.changed = ENT_ALL;
-  drawContext::global()->draw();  
-  Msg::StatusBar(3, false, "");
-}
-
-static void class_deleteedge_cb(Fl_Widget *w, void *data)
+edge_angle::edge_angle(MVertex *_v1, MVertex *_v2, MElement *t1, MElement *t2)
+  : v1(_v1), v2(_v2)
 {
-  classificationEditor *e = (classificationEditor*)data;
-  std::vector<MLine*> ele;
-  
-  CTX::instance()->pickElements = 1;
-  
-  while(1) {
-    CTX::instance()->mesh.changed = ENT_ALL;
-    drawContext::global()->draw();
-
-    Msg::StatusBar(3, false, "Select Elements\n"
-                   "[Press 'e' to end selection or 'q' to abort]");
-    
-    char ib = FlGui::instance()->selectEntity(ENT_ALL);
-    if(ib == 'l') {
-      if(CTX::instance()->pickElements){
-        for(unsigned int i = 0; i < FlGui::instance()->selectedElements.size(); i++){
-          MElement *me = FlGui::instance()->selectedElements[i];
-          if(me->getType() == TYPE_LIN && me->getVisibility() != 2){
-            me->setVisibility(2); ele.push_back((MLine*)me);
-          }
-        }
-      }
-    }
-    if(ib == 'r') {
-      for(unsigned int i = 0; i < FlGui::instance()->selectedElements.size(); i++)
-        FlGui::instance()->selectedElements[i]->setVisibility(1);
-    }
-    // ok, we compute edges !
-    if(ib == 'e') {
-      GModel::current()->setSelection(0);
-      break;
-    }
-    // do nothing
-    if(ib == 'q') {
-      GModel::current()->setSelection(0);
-      ele.clear();
-      break;
+  if(!t2) angle = 0;
+  else{
+    double c1[3];
+    double c2[3];
+    double c3[3];
+    {
+      MVertex *p1 = t1->getVertex(0);
+      MVertex *p2 = t1->getVertex(1);
+      MVertex *p3 = t1->getVertex(2);
+      double a[3] = {p1->x() - p2->x(), p1->y() - p2->y(), p1->z() - p2->z()};
+      double b[3] = {p1->x() - p3->x(), p1->y() - p3->y(), p1->z() - p3->z()};
+      c1[2] = a[0] * b[1] - a[1] * b[0];
+      c1[1] = -a[0] * b[2] + a[2] * b[0];
+      c1[0] = a[1] * b[2] - a[2] * b[1];
     }
-  }
-
-  std::sort(ele.begin(),ele.end());
-  //  look in all temporary edges if a deleted one is present and delete it !
-  std::vector<MLine*> temp = e->temporary->lines;
-  e->temporary->lines.clear();
-       
-  for(unsigned int i = 0; i < temp.size(); i++){      
-    std::vector<MLine*>::iterator it = std::find(ele.begin(), ele.end(), temp[i]);
-    if(it != ele.end()){
-      delete temp[i];
+    {
+      MVertex *p1 = t2->getVertex(0);
+      MVertex *p2 = t2->getVertex(1);
+      MVertex *p3 = t2->getVertex(2);
+      double a[3] = {p1->x() - p2->x(), p1->y() - p2->y(), p1->z() - p2->z()};
+      double b[3] = {p1->x() - p3->x(), p1->y() - p3->y(), p1->z() - p3->z()};
+      c2[2] = a[0] * b[1] - a[1] * b[0];
+      c2[1] = -a[0] * b[2] + a[2] * b[0];
+      c2[0] = a[1] * b[2] - a[2] * b[1];
     }
-    else e->temporary->lines.push_back(temp[i]);
-  }
-  
-  CTX::instance()->mesh.changed = ENT_ALL;
-  CTX::instance()->pickElements = 0;
-  drawContext::global()->draw();  
-  Msg::StatusBar(3, false, "");
-}
-
-static void class_save_cb(Fl_Widget *w, void *data)
-{
-  classificationEditor *e = (classificationEditor*)data;
-
-  e->saved->lines.insert(e->saved->lines.end(), e->temporary->lines.begin(),
-                         e->temporary->lines.end());
-  e->temporary->lines.clear();
-  e->_elements.clear();
-  e->edges_detected.clear();
-
-  CTX::instance()->mesh.changed = ENT_ALL;
-  CTX::instance()->pickElements = 0;
-  NoElementsSelectedMode(e);
-  drawContext::global()->draw();  
-  Msg::StatusBar(3, false, "");
-}
-
-static void class_clear_cb(Fl_Widget *w, void *data)
-{
-  classificationEditor *e = (classificationEditor*)data;
-
-  for(unsigned int i = 0; i < e->temporary->lines.size(); i++){      
-    delete e->temporary->lines[i];
+    norme(c1);
+    norme(c2);
+    prodve(c1, c2, c3);
+    double cosa; prosca(c1, c2, &cosa);
+    double sina = norme(c3);
+    angle = atan2(sina, cosa);
   }
-  e->temporary->lines.clear();
-
-  CTX::instance()->mesh.changed = ENT_ALL;
-  CTX::instance()->pickElements = 0;
-  NoElementsSelectedMode(e);
-  drawContext::global()->draw();  
-  Msg::StatusBar(3, false, "");
 }
 
-static void class_ok_cb(Fl_Widget *w, void *data)
-{
-  classificationEditor *e = (classificationEditor*)data;
-  e->edge_detec->deactivate();
-  e->edge_detec->hide();
-  e->face_color->activate();
-  e->face_color->show();
-  class_save_cb(w,data);
-  opt_mesh_lines(0, GMSH_SET | GMSH_GUI, e->op[0]);
-  opt_mesh_surfaces_edges(0, GMSH_SET | GMSH_GUI, e->op[1]);
-  opt_mesh_surfaces_faces(0, GMSH_SET | GMSH_GUI, e->op[2]);
-  opt_mesh_line_width(0, GMSH_SET | GMSH_GUI, e->op[3]);
-
-  Msg::StatusBar(3, false, "");
-}
-
-
 struct compareMLinePtr 
 {
   bool operator () (MLine *l1, MLine *l2) const
@@ -206,6 +65,23 @@ struct compareMLinePtr
   }
 };
 
+static void buildListOfEdgeAngle(e2t_cont adj, std::vector<edge_angle> &edges_detected,
+                                 std::vector<edge_angle> &edges_lonly)
+{
+  e2t_cont::iterator it = adj.begin();
+  for(; it != adj.end(); ++it){
+    if(it->second.second)
+      edges_detected.push_back(edge_angle(it->first.getVertex(0), 
+                                          it->first.getVertex(1), 
+                                          it->second.first, it->second.second));
+    else 
+      edges_lonly.push_back(edge_angle(it->first.getVertex(0),
+                                       it->first.getVertex(1), 
+                                       it->second.first, it->second.second));
+  }
+  std::sort(edges_detected.begin(), edges_detected.end());
+}
+
 static void recurClassify(MTri3 *t, GFace *gf,
                           std::map<MLine*, GEdge*, compareMLinePtr> &lines,
                           std::map<MTriangle*, GFace*> &reverse)
@@ -232,20 +108,19 @@ static GEdge *getNewModelEdge(GFace *gf1, GFace *gf2,
 {
   int t1 = gf1 ? gf1->tag() : -1;
   int t2 = gf2 ? gf2->tag() : -1;
-  int i1 = std::min(t1,t2);
-  int i2 = std::max(t1,t2);
+  int i1 = std::min(t1, t2);
+  int i2 = std::max(t1, t2);
 
   if(i1 == i2) return 0;
 
   std::map<std::pair<int, int>, GEdge*>::iterator it = 
     newEdges.find(std::make_pair<int, int>(i1, i2));
   if(it == newEdges.end()){
-    discreteEdge *temporary = new discreteEdge
+    discreteEdge *ge = new discreteEdge
       (GModel::current(), GModel::current()->maxEdgeNum() + 1, 0, 0);
-    //printf("add new edge gf1=%d gf2=%d \n", t1, t2);
-    GModel::current()->add(temporary);
-    newEdges[std::make_pair<int, int>(i1, i2)] = temporary;
-    return temporary;
+    GModel::current()->add(ge);
+    newEdges[std::make_pair<int, int>(i1, i2)] = ge;
+    return ge;
   }
   else
     return it->second;  
@@ -258,7 +133,6 @@ static void recurClassifyEdges(MTri3 *t,
                                std::map<std::pair<int, int>, GEdge*> &newEdges)
 {
   if(!t->isDeleted()){
-
     t->setDeleted(true);
     GFace *gf1 = reverse[t->tri()];
     for(int i = 0; i < 3; i++){
@@ -279,179 +153,62 @@ static void recurClassifyEdges(MTri3 *t,
       if(tn)
         recurClassifyEdges(tn, reverse, lines, touched, newEdges);
     }
-
   }
 }
 
-static void class_color_cb(Fl_Widget* w, void* data)
+static void NoElementsSelectedMode(classificationEditor *e)
 {
-  classificationEditor *e = (classificationEditor*)data;
-  std::map<MLine*, GEdge*, compareMLinePtr> lines;
-  {
-    GModel::eiter it =  GModel::current()->firstEdge();
-    GModel::eiter ite = GModel::current()->lastEdge();
-    for( ; it != ite; ++it){
-      for(unsigned int i = 0; i < (*it)->lines.size();i++) 
-        lines[(*it)->lines[i]] = *it;
-    }
-  }
-
-  std::list<MTri3*> tris;
-  {
-    std::set<GFace*>::iterator it = e->_faces.begin();
-    while(it != e->_faces.end()){
-      GFace *gf = *it;
-      for(unsigned int i = 0; i < gf->triangles.size(); i++){
-        tris.push_back(new MTri3(gf->triangles[i], 0));
-      }
-      gf->triangles.clear();
-      ++it;
-    }
-  }
+  e->buttons[CLASS_BUTTON_SELECT_ELEMENTS]->activate(); 
+  e->buttons[CLASS_BUTTON_SELECT_ALL_ELEMENTS]->activate(); 
 
-  if ( !tris.size() )return;
-
-
-  connectTriangles(tris);
-
-  {
-    std::map<MTriangle*,GFace*> reverse;
-
-    // color all triangles
-    std::list<MTri3*> ::iterator it = tris.begin();
-    while(it != tris.end()){
-      if(!(*it)->isDeleted()){
-        discreteFace *temporary = new discreteFace
-          (GModel::current(), GModel::current()->maxFaceNum() + 1);
-        recurClassify(*it, temporary, lines, reverse);
-        GModel::current()->add(temporary);
-      }
-      ++it;
-    }
-    
-    // color some lines
-    it = tris.begin();
-    while(it != tris.end()){
-      (*it)->setDeleted(false);
-      ++it;
-    }
-    
-    it = tris.begin();
-    
-    //classify edges that are bound by different GFaces
-    //--------------------------------------------------
-    std::map<std::pair<int, int>, GEdge*> newEdges;
-    std::set<MLine*> touched;
-    recurClassifyEdges(*it, reverse, lines, touched, newEdges);
-    GModel::current()->remove(e->saved);
-
-    //check if new edges should not be splitted 
-    //splitted if composed of several open or closed edges
-    //-----------------------------------------------------
-    for (std::map<std::pair<int, int>, GEdge*>::iterator it = newEdges.begin() ; it != newEdges.end() ; ++it){
-
-      GEdge *ge = it->second;
-      //printf("NEW edge with tag  = %d \n", ge->tag());
-
-      std::list<MLine*> segments;
-      for (unsigned int i = 0; i < ge->lines.size(); i++){
-        segments.push_back(ge->lines[i]);
-      }
+  e->buttons[CLASS_BUTTON_DELETE_FROM_SELECTION]->deactivate();
+  e->buttons[CLASS_BUTTON_RESET_SELECTION]->deactivate();
+  e->toggles[CLASS_TOGGLE_BOUNDARY]->deactivate();
+  e->inputs[CLASS_VALUE_ANGLE]->deactivate();
+  e->buttons[CLASS_BUTTON_CLASSIFY]->deactivate();
 
-      //for each actual GEdge
-      while (!segments.empty()) {
-        std::vector<MLine*> myLines;
-        std::list<MLine*>::iterator it = segments.begin();
-        MVertex *vB = (*it)->getVertex(0);
-        MVertex *vE = (*it)->getVertex(1);
-        myLines.push_back(*it);
-        segments.erase(it);
-        it++;
-        //printf("***candidate mline %d %d of size %d \n", vB->getNum(), vE->getNum(), segments.size());
-
-        for (int i=0; i<2; i++) {
-          for (std::list<MLine*>::iterator it = segments.begin() ; it != segments.end(); ++it){ 
-            MVertex *v1 = (*it)->getVertex(0);
-            MVertex *v2 = (*it)->getVertex(1);
-            //printf("mline %d %d \n", v1->getNum(), v2->getNum());
-            std::list<MLine*>::iterator itp;
-            if ( v1 == vE  ){
-              //printf("->push back this mline \n");
-              myLines.push_back(*it);
-              itp = it;
-              it++;
-              segments.erase(itp);
-              vE = v2;
-              i = -1;
-            }
-            else if ( v2 == vE){
-              //printf("->push back this mline \n");
-              myLines.push_back(*it);
-              itp = it;
-              it++;
-              segments.erase(itp);
-              vE = v1;
-              i=-1;
-            }
-            if (it == segments.end()) break;
-          }
-          if (vB == vE) break;
-          if (segments.empty()) break;
-          //printf("not found VB=%d vE=%d\n", vB->getNum(), vE->getNum());
-          MVertex *temp = vB;
-          vB = vE;
-          vE = temp;
-          //printf("not found VB=%d vE=%d\n", vB->getNum(), vE->getNum());
-        }
-        GEdge *newGe = new discreteEdge
-          (GModel::current(), GModel::current()->maxEdgeNum() + 1, 0, 0);
-        newGe->lines.insert(newGe->lines.end(), myLines.begin(), myLines.end());
-        GModel::current()->add(newGe);
-      }//end for each actual GEdge
-    }
-    //printf("end new edge with tag \n");
-
-    for (std::map<std::pair<int, int>, GEdge*>::iterator it = newEdges.begin();
-         it != newEdges.end(); ++it){
-      GEdge *ge = it->second;
-      GModel::current()->remove(ge);
-    }
-
-    while(it != tris.end()){
-      delete *it;
-      ++it;
-    }
-  }
-  
   CTX::instance()->mesh.changed = ENT_ALL;
+  CTX::instance()->pickElements = 0;
   drawContext::global()->draw();  
   Msg::StatusBar(3, false, "");
 }
 
-static void updateedges_cb(Fl_Widget* w, void* data)
+static void ElementsSelectedMode(classificationEditor *e)
+{
+  e->buttons[CLASS_BUTTON_DELETE_FROM_SELECTION]->activate();
+  e->buttons[CLASS_BUTTON_RESET_SELECTION]->activate();
+  e->toggles[CLASS_TOGGLE_BOUNDARY]->activate();
+  e->inputs[CLASS_VALUE_ANGLE]->activate();
+
+  e->buttons[CLASS_BUTTON_SELECT_ELEMENTS]->deactivate(); 
+  e->buttons[CLASS_BUTTON_SELECT_ALL_ELEMENTS]->deactivate(); 
+}
+
+static void update_edges_cb(Fl_Widget *w, void *data)
 {
   classificationEditor *e = (classificationEditor*)data;
  
+  if(!e->selected) return;
+
   printf("%d inside edges detected\n", (int)e->edges_detected.size());
 
-  for(unsigned int i = 0; i < e->temporary->lines.size(); i++){
-    delete e->temporary->lines[i];
-  }
-  e->temporary->lines.clear();
+  for(unsigned int i = 0; i < e->selected->lines.size(); i++)
+    delete e->selected->lines[i];
+  e->selected->lines.clear();
 
   for(unsigned int i = 0; i < e->edges_detected.size(); i++){
     edge_angle ea =  e->edges_detected[i];
     // printf("angle = %g\n",ea.angle);
-    if(ea.angle <= e->_inputs[CLASSVALUE_ANGLE]->value() / 180 * M_PI)
+    if(ea.angle <= e->inputs[CLASS_VALUE_ANGLE]->value() / 180 * M_PI)
       break;
-    e->temporary->lines.push_back(new MLine(ea.v1, ea.v2));
+    e->selected->lines.push_back(new MLine(ea.v1, ea.v2));
   } 
 
   printf("%d boundary edges detected\n", (int)e->edges_lonly.size());
-  if(e->_togbuttons[CLASSTOGBUTTON_CLOS]->value()){
+  if(e->toggles[CLASS_TOGGLE_BOUNDARY]->value()){
     for(unsigned int i = 0 ; i < e->edges_lonly.size(); i++){
       edge_angle ea = e->edges_lonly[i];
-      e->temporary->lines.push_back(new MLine(ea.v1, ea.v2));
+      e->selected->lines.push_back(new MLine(ea.v1, ea.v2));
       //check if closed loop
     } 
   }
@@ -460,6 +217,91 @@ static void updateedges_cb(Fl_Widget* w, void* data)
   drawContext::global()->draw();   
 }
 
+static void class_select_elements_cb(Fl_Widget *w, void *data)
+{
+  classificationEditor *e = (classificationEditor*)data;
+  std::vector<MTriangle*> &ele(e->elements);
+
+  // allocate discrete edge to hold the selected mesh segments
+  if(!e->selected){
+    e->selected = new discreteEdge
+      (GModel::current(), GModel::current()->maxEdgeNum() + 1, 0, 0);
+    GModel::current()->add(e->selected);
+  }
+
+  CTX::instance()->pickElements = 1;
+
+  while(1) {
+    CTX::instance()->mesh.changed = ENT_ALL;
+    drawContext::global()->draw();
+
+    Msg::StatusBar(3, false, "Select elements\n"
+                   "[Press 'e' to end selection or 'q' to abort]");
+    
+    char ib = FlGui::instance()->selectEntity(ENT_ALL);
+    if(ib == 'l') {
+      for(unsigned int i = 0; i < FlGui::instance()->selectedElements.size(); i++){
+        MElement *me = FlGui::instance()->selectedElements[i];
+        if(me->getType() == TYPE_TRI && me->getVisibility() != 2){
+          me->setVisibility(2); ele.push_back((MTriangle*)me);
+        }
+      }
+    }
+    if(ib == 'r') {
+      for(unsigned int i = 0; i < FlGui::instance()->selectedElements.size(); i++)
+        FlGui::instance()->selectedElements[i]->setVisibility(1);
+    }
+    if(ib == 'e') { // ok, compute the edges
+      GModel::current()->setSelection(0);
+      e2t_cont adj;
+      buildEdgeToTriangle(ele, adj);
+      buildListOfEdgeAngle(adj, e->edges_detected, e->edges_lonly);
+      ElementsSelectedMode(e);
+      break;
+    }
+    if(ib == 'q') { // do nothing
+      GModel::current()->setSelection(0);
+      ele.clear();
+      break;
+    }
+  }
+  
+  update_edges_cb(0, data);
+
+  CTX::instance()->mesh.changed = ENT_ALL;
+  CTX::instance()->pickElements = 0;
+  drawContext::global()->draw();  
+  Msg::StatusBar(3, false, "");
+}
+
+static void class_select_all_elements_cb(Fl_Widget *w, void *data)
+{
+  classificationEditor *e = (classificationEditor*)data;
+
+  // allocate discrete edge to hold the selected mesh segments
+  if(!e->selected){
+    e->selected = new discreteEdge
+      (GModel::current(), GModel::current()->maxEdgeNum() + 1, 0, 0);
+    GModel::current()->add(e->selected);
+  }
+
+  for(GModel::fiter it = GModel::current()->firstFace(); 
+      it != GModel::current()->lastFace(); ++it)
+    e->elements.insert(e->elements.end(), (*it)->triangles.begin(), 
+                       (*it)->triangles.end());
+
+  e2t_cont adj;
+  buildEdgeToTriangle(e->elements, adj);
+  buildListOfEdgeAngle(adj, e->edges_detected, e->edges_lonly);
+  ElementsSelectedMode(e);
+  update_edges_cb(0, data);
+
+  CTX::instance()->mesh.changed = ENT_ALL;
+  CTX::instance()->pickElements = 0;
+  drawContext::global()->draw();  
+  Msg::StatusBar(3, false, "");
+}
+
 static void class_hide_cb(Fl_Widget *w, void *data)
 {
   CTX::instance()->hideUnselected = !CTX::instance()->hideUnselected;
@@ -467,45 +309,45 @@ static void class_hide_cb(Fl_Widget *w, void *data)
   drawContext::global()->draw();
 }
 
-static void buildListOfEdgeAngle(e2t_cont adj, std::vector<edge_angle> &edges_detected,
-                                 std::vector<edge_angle> &edges_lonly)
+static void show_only_edges_cb(Fl_Widget *w, void *data)
 {
-  e2t_cont::iterator it = adj.begin();
-  for(; it != adj.end(); ++it){
-    if(it->second.second)
-      edges_detected.push_back(edge_angle(it->first.getVertex(0), 
-                                          it->first.getVertex(1), 
-                                          it->second.first, it->second.second));
-    else 
-      edges_lonly.push_back(edge_angle(it->first.getVertex(0),
-                                       it->first.getVertex(1), 
-                                       it->second.first, it->second.second));
+  classificationEditor *e = (classificationEditor*)data;
+  static int old_sf = opt_mesh_surfaces_faces(0, GMSH_GET, 0.);
+  static int old_se = opt_mesh_surfaces_edges(0, GMSH_GET, 0.);
+  if(e->toggles[CLASS_TOGGLE_SHOW_ONLY_EDGES]->value()){
+    opt_mesh_lines(0, GMSH_SET | GMSH_GUI, 1.);
+    opt_mesh_surfaces_faces(0, GMSH_SET | GMSH_GUI, 0.);
+    opt_mesh_surfaces_edges(0, GMSH_SET | GMSH_GUI, 0.);
   }
-  std::sort(edges_detected.begin(), edges_detected.end());
+  else{
+    opt_mesh_surfaces_faces(0, GMSH_SET | GMSH_GUI, old_sf);
+    opt_mesh_surfaces_edges(0, GMSH_SET | GMSH_GUI, old_se);
+  }
+  drawContext::global()->draw();
 }
 
-static void class_select_cb(Fl_Widget *w, void *data)
+static void class_delete_edge_cb(Fl_Widget *w, void *data)
 {
   classificationEditor *e = (classificationEditor*)data;
-  std::vector<MTriangle*> &ele(e->getElements());
 
-  CTX::instance()->pickElements = 1;
+  if(!e->selected) return;
 
+  CTX::instance()->pickElements = 1;
+  std::vector<MLine*> ele;
+  
   while(1) {
     CTX::instance()->mesh.changed = ENT_ALL;
     drawContext::global()->draw();
 
-    Msg::StatusBar(3, false, "Select Elements\n"
+    Msg::StatusBar(3, false, "Select elements\n"
                    "[Press 'e' to end selection or 'q' to abort]");
     
     char ib = FlGui::instance()->selectEntity(ENT_ALL);
     if(ib == 'l') {
-      if(CTX::instance()->pickElements){
-        for(unsigned int i = 0; i < FlGui::instance()->selectedElements.size(); i++){
-          MElement *me = FlGui::instance()->selectedElements[i];
-          if(me->getType() == TYPE_TRI && me->getVisibility() != 2){
-            me->setVisibility(2); ele.push_back((MTriangle*)me);
-          }
+      for(unsigned int i = 0; i < FlGui::instance()->selectedElements.size(); i++){
+        MElement *me = FlGui::instance()->selectedElements[i];
+        if(me->getType() == TYPE_LIN && me->getVisibility() != 2){
+          me->setVisibility(2); ele.push_back((MLine*)me);
         }
       }
     }
@@ -516,10 +358,6 @@ static void class_select_cb(Fl_Widget *w, void *data)
     // ok, we compute edges !
     if(ib == 'e') {
       GModel::current()->setSelection(0);
-      e2t_cont adj;
-      buildEdgeToTriangle(ele, adj);
-      buildListOfEdgeAngle(adj, e->edges_detected, e->edges_lonly);
-      ElementsSelectedMode(e);
       break;
     }
     // do nothing
@@ -529,164 +367,366 @@ static void class_select_cb(Fl_Widget *w, void *data)
       break;
     }
   }
-  
-  updateedges_cb(0, data);
 
+  std::sort(ele.begin(), ele.end());
+
+  //  look in all selected edges if a deleted one is present and delete it
+  std::vector<MLine*> temp = e->selected->lines;
+  e->selected->lines.clear();
+  for(unsigned int i = 0; i < temp.size(); i++){      
+    std::vector<MLine*>::iterator it = std::find(ele.begin(), ele.end(), temp[i]);
+    if(it != ele.end()) 
+      delete temp[i];
+    else
+      e->selected->lines.push_back(temp[i]);
+  }
+  
   CTX::instance()->mesh.changed = ENT_ALL;
   CTX::instance()->pickElements = 0;
   drawContext::global()->draw();  
   Msg::StatusBar(3, false, "");
+
+  e->elements.clear();
+  e->edges_detected.clear();
 }
 
-edge_angle::edge_angle(MVertex *_v1, MVertex *_v2, MElement *t1, MElement *t2)
-  : v1(_v1), v2(_v2)
+static void class_reset_selection_cb(Fl_Widget *w, void *data)
 {
-  if(!t2) angle = 0;
-  else{
-    double c1[3];
-    double c2[3];
-    double c3[3];
-    {
-      MVertex *p1 = t1->getVertex(0);
-      MVertex *p2 = t1->getVertex(1);
-      MVertex *p3 = t1->getVertex(2);
-      double a[3] = {p1->x() - p2->x(), p1->y() - p2->y(), p1->z() - p2->z()};
-      double b[3] = {p1->x() - p3->x(), p1->y() - p3->y(), p1->z() - p3->z()};
-      c1[2] = a[0] * b[1] - a[1] * b[0];
-      c1[1] = -a[0] * b[2] + a[2] * b[0];
-      c1[0] = a[1] * b[2] - a[2] * b[1];
+  classificationEditor *e = (classificationEditor*)data;
+  if(!e->selected) return;
+  for(unsigned int i = 0; i < e->selected->lines.size(); i++)
+    delete e->selected->lines[i];
+  e->selected->lines.clear();
+  e->selected->deleteVertexArrays();
+  e->elements.clear();
+  e->edges_detected.clear();
+  NoElementsSelectedMode(e);
+}
+
+static void class_select_surfaces_cb(Fl_Widget *w, void *data)
+{
+  classificationEditor *e = (classificationEditor*)data;
+  std::vector<GFace*> temp;
+
+  opt_geometry_surfaces(0, GMSH_SET | GMSH_GUI, 1);
+
+  while(1) {
+    CTX::instance()->mesh.changed = ENT_ALL;
+    drawContext::global()->draw();
+
+    Msg::StatusBar(3, false, "Select Surface\n"
+                   "[Press 'e' to end selection or 'q' to abort]");
+    
+    char ib = FlGui::instance()->selectEntity(ENT_SURFACE);
+    if(ib == 'l') {
+      for(unsigned int i = 0; i < FlGui::instance()->selectedFaces.size(); i++){
+        FlGui::instance()->selectedFaces[i]->setSelection(1);
+        temp.push_back(FlGui::instance()->selectedFaces[i]);
+      }
     }
-    {
-      MVertex *p1 = t2->getVertex(0);
-      MVertex *p2 = t2->getVertex(1);
-      MVertex *p3 = t2->getVertex(2);
-      double a[3] = {p1->x() - p2->x(), p1->y() - p2->y(), p1->z() - p2->z()};
-      double b[3] = {p1->x() - p3->x(), p1->y() - p3->y(), p1->z() - p3->z()};
-      c2[2] = a[0] * b[1] - a[1] * b[0];
-      c2[1] = -a[0] * b[2] + a[2] * b[0];
-      c2[0] = a[1] * b[2] - a[2] * b[1];
+    if(ib == 'e') { // store the list of gfaces
+      GModel::current()->setSelection(0);
+      for(unsigned int i = 0; i < temp.size(); i++){
+        e->faces.insert(temp[i]);
+      }
+      break;
     }
-    norme(c1);
-    norme(c2);
-    prodve(c1, c2, c3);
-    double cosa; prosca(c1, c2, &cosa);
-    double sina = norme(c3);
-    angle = atan2(sina, cosa);
+    if(ib == 'q') { // do nothing
+      GModel::current()->setSelection(0);
+      break;
+    }
+  } 
+
+  if(e->faces.size())
+    e->buttons[CLASS_BUTTON_CLASSIFY]->activate();
+
+  CTX::instance()->mesh.changed = ENT_ALL;
+  drawContext::global()->draw();  
+  Msg::StatusBar(3, false, "");
+}
+
+static void class_select_all_surfaces_cb(Fl_Widget *w, void *data)
+{
+  classificationEditor *e = (classificationEditor*)data;
+
+  for(GModel::fiter it = GModel::current()->firstFace(); 
+      it != GModel::current()->lastFace(); ++it)
+    e->faces.insert(*it);
+
+  if(e->faces.size())
+    e->buttons[CLASS_BUTTON_CLASSIFY]->activate();
+
+  CTX::instance()->mesh.changed = ENT_ALL;
+  drawContext::global()->draw();  
+  Msg::StatusBar(3, false, "");
+}
+
+static void class_classify_cb(Fl_Widget *w, void *data)
+{
+  classificationEditor *e = (classificationEditor*)data;
+  std::map<MLine*, GEdge*, compareMLinePtr> lines;
+  for(GModel::eiter it = GModel::current()->firstEdge(); 
+      it != GModel::current()->lastEdge(); ++it){
+    for(unsigned int i = 0; i < (*it)->lines.size();i++) 
+      lines[(*it)->lines[i]] = *it;
   }
+
+  std::list<MTri3*> tris;
+  {
+    std::set<GFace*>::iterator it = e->faces.begin();
+    while(it != e->faces.end()){
+      GFace *gf = *it;
+      for(unsigned int i = 0; i < gf->triangles.size(); i++)
+        tris.push_back(new MTri3(gf->triangles[i], 0));
+      gf->triangles.clear();
+      ++it;
+    }
+  }
+  if(tris.empty()) return;
+
+  connectTriangles(tris);
+
+  std::map<MTriangle*, GFace*> reverse;
+  // color all triangles
+  std::list<MTri3*> ::iterator it = tris.begin();
+  while(it != tris.end()){
+    if(!(*it)->isDeleted()){
+      discreteFace *gf = new discreteFace
+        (GModel::current(), GModel::current()->maxFaceNum() + 1);
+      recurClassify(*it, gf, lines, reverse);
+      GModel::current()->add(gf);
+    }
+    ++it;
+  }
+  
+  // color some lines
+  it = tris.begin();
+  while(it != tris.end()){
+    (*it)->setDeleted(false);
+    ++it;
+  }
+  
+  it = tris.begin();
+  
+  // classify edges that are bound by different GFaces
+  std::map<std::pair<int, int>, GEdge*> newEdges;
+  std::set<MLine*> touched;
+  recurClassifyEdges(*it, reverse, lines, touched, newEdges);
+  
+  // check if new edges should not be splitted 
+  // splitted if composed of several open or closed edges
+  for (std::map<std::pair<int, int>, GEdge*>::iterator it = newEdges.begin();
+       it != newEdges.end() ; ++it){
+    GEdge *ge = it->second;
+    std::list<MLine*> segments;
+    for (unsigned int i = 0; i < ge->lines.size(); i++){
+      segments.push_back(ge->lines[i]);
+    }
+    
+    // for each actual GEdge
+    while (!segments.empty()) {
+      std::vector<MLine*> myLines;
+      std::list<MLine*>::iterator it = segments.begin();
+      MVertex *vB = (*it)->getVertex(0);
+      MVertex *vE = (*it)->getVertex(1);
+      myLines.push_back(*it);
+      segments.erase(it);
+      it++;
+      // printf("***candidate mline %d %d of size %d \n", 
+      //        vB->getNum(), vE->getNum(), segments.size());
+      
+      for (int i=0; i<2; i++) {
+        for (std::list<MLine*>::iterator it = segments.begin();
+             it != segments.end(); ++it){ 
+          MVertex *v1 = (*it)->getVertex(0);
+          MVertex *v2 = (*it)->getVertex(1);
+          // printf("mline %d %d \n", v1->getNum(), v2->getNum());
+          std::list<MLine*>::iterator itp;
+          if (v1 == vE){
+            // printf("->push back this mline \n");
+            myLines.push_back(*it);
+            itp = it;
+            it++;
+            segments.erase(itp);
+            vE = v2;
+            i = -1;
+          }
+          else if ( v2 == vE){
+            //printf("->push back this mline \n");
+            myLines.push_back(*it);
+            itp = it;
+            it++;
+            segments.erase(itp);
+            vE = v1;
+            i = -1;
+          }
+          if (it == segments.end()) break;
+        }
+        if (vB == vE) break;
+        if (segments.empty()) break;
+        // printf("not found VB=%d vE=%d\n", vB->getNum(), vE->getNum());
+        MVertex *temp = vB;
+        vB = vE;
+        vE = temp;
+        // printf("not found VB=%d vE=%d\n", vB->getNum(), vE->getNum());
+      }
+      GEdge *newGe = new discreteEdge
+        (GModel::current(), GModel::current()->maxEdgeNum() + 1, 0, 0);
+      newGe->lines.insert(newGe->lines.end(), myLines.begin(), myLines.end());
+      GModel::current()->add(newGe);
+    } //end for each actual GEdge
+  }
+
+  //printf("end new edge with tag \n");
+  
+  for (std::map<std::pair<int, int>, GEdge*>::iterator it = newEdges.begin();
+       it != newEdges.end(); ++it){
+    GEdge *ge = it->second;
+    GModel::current()->remove(ge);
+  }
+  
+  while(it != tris.end()){
+    delete *it;
+    ++it;
+  }
+
+  // remove selected, but do not delete its elements
+  if(e->selected){
+    GModel::current()->remove(e->selected);
+    e->selected->lines.clear();
+    delete e->selected;
+    e->selected = 0;
+  }
+  e->elements.clear();
+  e->edges_detected.clear();
+  NoElementsSelectedMode(e);
 }
 
-classificationEditor::classificationEditor()
+classificationEditor::classificationEditor() : selected(0)
 {
-  op[0] = opt_mesh_lines(0, GMSH_GET, 0.);
-  op[1] = opt_mesh_surfaces_edges(0, GMSH_GET, 0.);
-  op[2] = opt_mesh_surfaces_faces(0, GMSH_GET, 0.);
-  op[3] = opt_mesh_line_width(0, GMSH_SET | GMSH_GET,0.);
-
-  opt_mesh_lines(0, GMSH_SET | GMSH_GUI, 1);
-  opt_mesh_surfaces_edges(0, GMSH_SET | GMSH_GUI, 0);
-  opt_mesh_surfaces_faces(0, GMSH_SET | GMSH_GUI, 1);
-  opt_mesh_line_width(0, GMSH_SET | GMSH_GUI, 1.5);
-
-  // construct GUI in terms of standard sizes
-  int BBB = (int)(1.4 * BB); // labels too long
-  const int width = (int)(3.5 * BBB), height = 10 * BH;
-
-  _window = new paletteWindow
-    (width, height, CTX::instance()->nonModalWindows ? true : false, "Classify");
+  opt_mesh_lines(0, GMSH_SET | GMSH_GUI, 1.);
+
+  drawContext::global()->draw();
+
+  int BBB = (int)(1.4 * BB);
+  const int width = (int)(3.15 * BBB), height = (int)(9.5 * BH);
+
+  window = new paletteWindow
+    (width, height, CTX::instance()->nonModalWindows ? true : false, "Reclassify");
+  window->box(GMSH_WINDOW_BOX);
   
-  new Fl_Tabs(WB, WB, width - 2 * WB, height - 2 * WB);
+  int x = WB, y = WB;
   {
-    Fl_Group *o = new Fl_Group
-      (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Edge Detection");
-    edge_detec = o;
+    Fl_Box *b = new Fl_Box
+      (x, y, width, BH, "1. Select mesh elements on which to perform edge detection");
+    b->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
     
-    _buttons[CLASSBUTTON_OK] = new Fl_Button 
-      (4*WB+2*BBB, 7*WB+6*BH, BBB, BH, "OK");
-    _buttons[CLASSBUTTON_OK]->callback(class_ok_cb, this);
+    x += WB;
+    y += BH;
+    buttons[CLASS_BUTTON_SELECT_ELEMENTS] = new Fl_Button
+      (x, y, BBB, BH, "Select elements");
+    buttons[CLASS_BUTTON_SELECT_ELEMENTS]->callback(class_select_elements_cb, this);
+
+    buttons[CLASS_BUTTON_SELECT_ALL_ELEMENTS] = new Fl_Button
+      (x + BBB + WB, y, (int)(0.5 * BBB) - WB, BH, "All");
+    buttons[CLASS_BUTTON_SELECT_ALL_ELEMENTS]->callback(class_select_all_elements_cb, this);
     
-    _buttons[CLASSBUTTON_SELECT] = new Fl_Button 
-      (2*WB, 2*WB+1*BH, BBB, BH, "Select Elements");
-    _buttons[CLASSBUTTON_SELECT]->callback(class_select_cb, this);
+    toggles[CLASS_TOGGLE_HIDE] = new Fl_Check_Button
+      (x + 1.5 * BBB + WB, y, width - 1.5 * BBB - x - 2 * WB, BH, "Hide unselected elements");
+    toggles[CLASS_TOGGLE_HIDE]->type(FL_TOGGLE_BUTTON);
+    toggles[CLASS_TOGGLE_HIDE]->callback(class_hide_cb, this);
     
-    _togbuttons[CLASSTOGBUTTON_HIDE] = new Fl_Toggle_Button
-      (3*WB+BBB, 2*WB+1*BH, BBB, BH, "Hide Unselected");
-    _togbuttons[CLASSTOGBUTTON_HIDE]->callback(class_hide_cb,this);
-
-    _togbuttons[CLASSTOGBUTTON_CLOS] = new Fl_Toggle_Button
-      (2*WB, 4*WB+3*BH, BBB, BH, "Include Closure");
-    _togbuttons[CLASSTOGBUTTON_CLOS]->callback(updateedges_cb,this);
+    x -= WB;
+  }
+  {
+    y += BH / 2;
+    Fl_Box* b = new Fl_Box(x, y + BH - WB, width - 2 * WB, 2);
+    b->box(FL_ENGRAVED_FRAME);
+    b->labeltype(FL_NO_LABEL);
+  }
+  {
+    y += BH;
+    Fl_Box *b = new Fl_Box
+      (x, y, width, BH, "2. Fine-tune edge selection");
+    b->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
     
-    _inputs[CLASSVALUE_ANGLE] = new Fl_Value_Input
-      (3*WB+BBB, 4*WB+3*BH, BBB, BH, "Treshold Angle");
-    _inputs[CLASSVALUE_ANGLE]->value(40);
-    _inputs [CLASSVALUE_ANGLE]->maximum(90);
-    _inputs[CLASSVALUE_ANGLE]->minimum(0);
-    _inputs[CLASSVALUE_ANGLE]->align(FL_ALIGN_RIGHT);
-    _inputs[CLASSVALUE_ANGLE]->step(1);
-    _inputs[CLASSVALUE_ANGLE]->when(FL_WHEN_RELEASE);  
-    _inputs[CLASSVALUE_ANGLE]->callback(updateedges_cb,this);
-
-    _buttons[CLASSBUTTON_DEL] = new Fl_Button 
-      (2*WB, 5*WB+4*BH, BBB, BH, "Delete Edge");
-    _buttons[CLASSBUTTON_DEL]->callback(class_deleteedge_cb, this);    
-    _buttons[CLASSBUTTON_DEL]->deactivate();
-
-    _buttons[CLASSBUTTON_ADD] = new Fl_Button
-      (2*WB, 6*WB+5*BH, BBB, BH, "Save Selection");
-    _buttons[CLASSBUTTON_ADD]->callback(class_save_cb, this);    
-    _buttons[CLASSBUTTON_ADD]->deactivate();
-
-    _buttons[CLASSBUTTON_CLEAR] = new Fl_Button 
-      (2*WB, 7*WB+6*BH, BBB, BH, "Clear Selection");
-    _buttons[CLASSBUTTON_CLEAR]->callback(class_clear_cb, this);    
-    _buttons[CLASSBUTTON_CLEAR]->deactivate();
-    o->end();
+    x += WB;
+    y += BH;
+    inputs[CLASS_VALUE_ANGLE] = new Fl_Value_Input
+      (x, y, 2 * BBB / 3, BH, "Threshold angle");
+    inputs[CLASS_VALUE_ANGLE]->value(40);
+    inputs[CLASS_VALUE_ANGLE]->maximum(180);
+    inputs[CLASS_VALUE_ANGLE]->minimum(0);
+    inputs[CLASS_VALUE_ANGLE]->align(FL_ALIGN_RIGHT);
+    inputs[CLASS_VALUE_ANGLE]->step(1);
+    inputs[CLASS_VALUE_ANGLE]->when(FL_WHEN_RELEASE);  
+    inputs[CLASS_VALUE_ANGLE]->callback(update_edges_cb, this);
+
+    toggles[CLASS_TOGGLE_SHOW_ONLY_EDGES] = new Fl_Check_Button
+      (x + 1.5 * BBB + WB, y, width - x - 1.5 * BBB - 2 * WB, BH, "Show only edges");
+    toggles[CLASS_TOGGLE_SHOW_ONLY_EDGES]->type(FL_TOGGLE_BUTTON);
+    toggles[CLASS_TOGGLE_SHOW_ONLY_EDGES]->callback(show_only_edges_cb, this);
+    
+    y += BH;
+    toggles[CLASS_TOGGLE_BOUNDARY] = new Fl_Check_Button
+      (x, y, width - x - 2 * WB, BH, "Include edges on boundary (closure)");
+    toggles[CLASS_TOGGLE_BOUNDARY]->type(FL_TOGGLE_BUTTON);
+    toggles[CLASS_TOGGLE_BOUNDARY]->callback(update_edges_cb, this);
+    
+    y += BH;
+    buttons[CLASS_BUTTON_DELETE_FROM_SELECTION] = new Fl_Button 
+      (x, y, 1.5 * BBB, BH, "Delete edges from selection");
+    buttons[CLASS_BUTTON_DELETE_FROM_SELECTION]->callback(class_delete_edge_cb, this);    
+    buttons[CLASS_BUTTON_DELETE_FROM_SELECTION]->deactivate();
+    
+    buttons[CLASS_BUTTON_RESET_SELECTION] = new Fl_Button 
+      (x + 1.5 * BBB + WB, y, BBB, BH, "Reset selection");
+    buttons[CLASS_BUTTON_RESET_SELECTION]->callback(class_reset_selection_cb, this);    
+    buttons[CLASS_BUTTON_RESET_SELECTION]->deactivate();
+    
+    x -= WB;
   }
   {
-    Fl_Group *o = new Fl_Group
-      (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Face Colouring");
-    face_color = o;
-    o->deactivate();
-    o->hide();
-    _buttons[CLASSBUTTON_SELFAC] = new Fl_Button
-      (2*WB, 2*WB+1*BH, BBB, BH, "Select Model Face");
-    _buttons[CLASSBUTTON_SELFAC]->callback(class_selectgface_cb, this);
-    _buttons[CLASSBUTTON_COLOR] = new Fl_Button 
-      (2*WB, 3*WB+2*BH, BBB, BH, "Classify Mesh Faces");
-    _buttons[CLASSBUTTON_COLOR]->callback(class_color_cb, this);
-    o->end();
+    y += BH / 2;
+    Fl_Box* b = new Fl_Box(x, y + BH - WB, width - 2 * WB, 2);
+    b->box(FL_ENGRAVED_FRAME);
+    b->labeltype(FL_NO_LABEL);
   }
   {
-    Fl_Group *o = new Fl_Group
-      (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Reparametrize Surfaces");
-    reverse_eng = o;
-    o->hide();
-    o->deactivate();
-    o->end();
+    y += BH;
+    Fl_Box *b = new Fl_Box
+      (x, y, width, BH, "3. Reclassify surfaces using selected edges");
+    b->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
+    
+    x += WB;
+    y += BH;
+
+    buttons[CLASS_BUTTON_SELECT_SURFACES] = new Fl_Button
+      (x, y, BBB, BH, "Select surfaces");
+    buttons[CLASS_BUTTON_SELECT_SURFACES]->callback(class_select_surfaces_cb, this);
+
+    buttons[CLASS_BUTTON_SELECT_ALL_SURFACES] = new Fl_Button
+      (x + BBB + WB, y, (int)(0.5 * BBB) - WB, BH, "All");
+    buttons[CLASS_BUTTON_SELECT_ALL_SURFACES]->callback(class_select_all_surfaces_cb, this);
+
+    buttons[CLASS_BUTTON_CLASSIFY] = new Fl_Button 
+      (x + 1.5 * BBB + WB, y, BBB, BH, "Reclassify");
+    buttons[CLASS_BUTTON_CLASSIFY]->callback(class_classify_cb, this);
+    buttons[CLASS_BUTTON_CLASSIFY]->deactivate();
+
+    x -= WB;
   }
-  NoElementsSelectedMode(this);
 
-  // allocate detected edges
-  // temporary for the selection
-  // saved for the ones that have been saved by the user
-  // and that will be used for next step
+  window->end();
+  window->hotspot(window);
 
-  temporary = new discreteEdge(GModel::current(), GModel::current()->maxEdgeNum() + 1, 0, 0);
-  GModel::current()->add(temporary);
-  saved = new discreteEdge(GModel::current(), GModel::current()->maxEdgeNum() + 1, 0, 0);
-  GModel::current()->add(saved);
-  
-  _window->end();
-  _window->hotspot(_window);
-  _window->size_range(width, (int)(0.85 * height));    
+  NoElementsSelectedMode(this);
 }
 
 void mesh_classify_cb(Fl_Widget* w, void* data)
 {
   // create the (static) editor
   static classificationEditor *editor = 0;
-  if(!editor){
-    editor = new classificationEditor();
-  }
+  if(!editor) editor = new classificationEditor();
   editor->show();
 }
diff --git a/Fltk/classificationEditor.h b/Fltk/classificationEditor.h
index 55ba72a2db05307b27a9b1c281c2edb1b406e8b8..4bd2b2711ba745fee3ce509a23e2198fd6c55847 100644
--- a/Fltk/classificationEditor.h
+++ b/Fltk/classificationEditor.h
@@ -7,24 +7,26 @@
 #define _CLASSIFICATION_EDITOR_H_
 
 #include <vector>
-#include <FL/Fl_Toggle_Button.H>
-#include <FL/Fl_Round_Button.H>
 #include <FL/Fl_Window.H>
+#include <FL/Fl_Check_Button.H>
 #include <FL/Fl_Value_Input.H>
 #include "GModel.h"
 #include "MElement.h"
 #include "ColorTable.h"
 
-#define CLASSBUTTON_SELECT   0
-#define CLASSBUTTON_DEL      1
-#define CLASSBUTTON_ADD      2
-#define CLASSBUTTON_CLEAR    3
-#define CLASSBUTTON_OK       4
-#define CLASSBUTTON_COLOR    5
-#define CLASSBUTTON_SELFAC   6
-#define CLASSTOGBUTTON_HIDE  0
-#define CLASSTOGBUTTON_CLOS  1
-#define CLASSVALUE_ANGLE     0
+#define CLASS_BUTTON_SELECT_ELEMENTS       0
+#define CLASS_BUTTON_SELECT_ALL_ELEMENTS   1
+#define CLASS_BUTTON_DELETE_FROM_SELECTION 2
+#define CLASS_BUTTON_RESET_SELECTION       3
+#define CLASS_BUTTON_SELECT_SURFACES       4
+#define CLASS_BUTTON_SELECT_ALL_SURFACES   5
+#define CLASS_BUTTON_CLASSIFY              6
+
+#define CLASS_TOGGLE_HIDE             0
+#define CLASS_TOGGLE_BOUNDARY         1
+#define CLASS_TOGGLE_SHOW_ONLY_EDGES  2
+
+#define CLASS_VALUE_ANGLE             0
 
 class edge_angle {
  public :
@@ -40,21 +42,16 @@ class edge_angle {
 class classificationEditor {
  public:
   double op[10];
-  std::vector<MTriangle*> _elements;
-  std::set<GFace*> _faces;
-  Fl_Window *_window;
-  Fl_Button *_buttons[10];
-  Fl_Toggle_Button *_togbuttons[10];
-  Fl_Value_Input *_inputs[10];
-  GEdge *temporary;
-  GEdge *saved;
-  std::list<GFace *> tempFaces;
-  std::vector<edge_angle> edges_detected;
-  std::vector<edge_angle> edges_lonly;
+  std::vector<MTriangle*> elements;
+  std::set<GFace*> faces;
+  Fl_Window *window;
+  Fl_Button *buttons[10];
+  Fl_Check_Button *toggles[10];
+  Fl_Value_Input *inputs[10];
+  GEdge *selected, *saved;
+  std::vector<edge_angle> edges_detected, edges_lonly;
   classificationEditor();
-  void show(){ _window->show(); }
-  std::vector<MTriangle*> &getElements() { return _elements; }
-  Fl_Group *edge_detec, *face_color, *reverse_eng;
+  void show(){ window->show(); }
 };
 
 void mesh_classify_cb(Fl_Widget* w, void* data);
diff --git a/benchmarks/extrude/sphere_boundary_layer.geo b/benchmarks/extrude/sphere_boundary_layer.geo
index dc79a3ccace52a9b98ca4c12fdf76d3c6259b446..e8498a641f4f0a6f417db830be0baf868fdb5bcb 100644
--- a/benchmarks/extrude/sphere_boundary_layer.geo
+++ b/benchmarks/extrude/sphere_boundary_layer.geo
@@ -1,4 +1,4 @@
-lc = .2;
+lc = 1;
 
 Point(1) = {0.0,0.0,0.0,lc};
 Point(2) = {1,0.0,0.0,lc};
@@ -37,9 +37,12 @@ Ruled Surface(26) = {25};
 Line Loop(27) = {-4,12,-6};
 Ruled Surface(28) = {27};
 
-Extrude {
-  Surface{14:28:2};  Layers{10, 0.2}; // Recombine; 
-}
+old = Geometry.ExtrudeReturnLateralEntities;
+Geometry.ExtrudeReturnLateralEntities = 0;
+tmp[] = Extrude {
+  Surface{14:28:2}; Layers{5, 0.2}; Recombine; // 14:28:2 means itterate from 14 to 28 by steps of 2
+};
+Geometry.ExtrudeReturnLateralEntities = old;
 
 Point(100) = {-1.5,-1.5,-1.5, lc};
 Point(101) = {-1.5,1.5,-1.5, lc};
@@ -74,10 +77,11 @@ Plane Surface(186) = {185};
 Line Loop(187) = {172, 173, 174, 167};
 Plane Surface(188) = {187};
 
-Surface Loop(1000) = {20, 22, 18, 14, 26, 16, 24, 28};
-Surface Loop(1001) = {45, 96, 113, 79, 62, 130, 147, 164};
-Surface Loop(1002) = {188, 186, 184, 180, 178, 182};
-Volume(1000) = {1000}; // inside
-Volume(1001) = {1002, 1001}; // outside
+Surface Loop(1000) = {14:28:2}; // the sphere (only need for internal mesh)
+Surface Loop(1001) = {tmp[{0:14:2}]};  // The outside of the BL
+Surface Loop(1002) = {188, 186, 184, 180, 178, 182}; // the box (entire farfield surface loop)
+
+//Volume(1000) = {1000}; /// inside the sphere
+Volume(1001) = {1002, 1001}; /// FarField
 
 Mesh.Algorithm3D = 4;
diff --git a/benchmarks/stl/coupe_geom.stl.gz b/benchmarks/stl/coupe_geom.stl.gz
index ae299fdde2d37645c8dce300fd4075242009c319..ec014157e439ba7cfe120432d23cb73a5be82e26 100644
Binary files a/benchmarks/stl/coupe_geom.stl.gz and b/benchmarks/stl/coupe_geom.stl.gz differ