From 0afe968685ee4904ebbac2a08aee22a08d5a2d22 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Tue, 2 Dec 2008 21:45:13 +0000
Subject: [PATCH] cleanup SelectEntity & co (now works per gl window)

---
 Common/Makefile               |   2 +-
 Common/OpenFile.cpp           |   3 +-
 Fltk/GUI.cpp                  |  54 +++--
 Fltk/GUI.h                    |  14 +-
 Fltk/Makefile                 |  88 ++++----
 Fltk/classificationEditor.cpp | 122 +++++------
 Fltk/contextWindow.cpp        |   4 +-
 Fltk/fieldWindow.cpp          |   4 +-
 Fltk/menuWindow.cpp           | 255 +++++++++++++---------
 Fltk/openglWindow.cpp         | 384 +++++++++++++++++++++++++---------
 Fltk/openglWindow.h           |  21 ++
 Fltk/optionWindow.cpp         |   6 +-
 Fltk/projectionEditor.cpp     |  14 +-
 Fltk/visibilityWindow.cpp     |   4 +-
 Geo/GModel.cpp                |  17 ++
 Geo/GModel.h                  |   3 +
 Graphics/Makefile             |  16 --
 Graphics/SelectBuffer.cpp     | 322 ----------------------------
 Graphics/SelectBuffer.h       |  38 ----
 19 files changed, 651 insertions(+), 720 deletions(-)
 delete mode 100644 Graphics/SelectBuffer.cpp
 delete mode 100644 Graphics/SelectBuffer.h

diff --git a/Common/Makefile b/Common/Makefile
index fc4082844c..9cf694d18c 100644
--- a/Common/Makefile
+++ b/Common/Makefile
@@ -128,7 +128,7 @@ OpenFile${OBJEXT}: OpenFile.cpp GmshMessage.h ../Geo/Geo.h \
   ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h OpenFile.h \
   CommandLine.h ../Graphics/ReadImg.h OS.h StringUtils.h \
   ../Parser/Parser.h ../Post/PView.h ../Post/PViewData.h ../Fltk/GUI.h \
-  ../Fltk/Draw.h ../Graphics/SelectBuffer.h ../Graphics/drawContext.h
+  ../Fltk/Draw.h
 CreateFile${OBJEXT}: CreateFile.cpp GmshMessage.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 \
diff --git a/Common/OpenFile.cpp b/Common/OpenFile.cpp
index dc951666a3..55a2179100 100644
--- a/Common/OpenFile.cpp
+++ b/Common/OpenFile.cpp
@@ -28,7 +28,6 @@
 #include <FL/fl_ask.H>
 #include "GUI.h"
 #include "Draw.h"
-#include "SelectBuffer.h"
 #endif
 
 extern Context_T CTX;
@@ -429,7 +428,7 @@ void OpenProject(const char *name)
     GUI::instance()->resetVisibility();
     GUI::instance()->updateViews();
     GUI::instance()->updateFields();
-    ZeroHighlight();
+    GModel::current()->setSelection(0);
   }
 #endif
 }
diff --git a/Fltk/GUI.cpp b/Fltk/GUI.cpp
index 8a3980fa75..3da1908588 100644
--- a/Fltk/GUI.cpp
+++ b/Fltk/GUI.cpp
@@ -28,6 +28,7 @@
 #include "GmshDefines.h"
 #include "GmshMessage.h"
 #include "GModel.h"
+#include "MElement.h"
 #include "PView.h"
 #include "Solvers.h"
 #include "Field.h"
@@ -52,12 +53,6 @@ GUI::GUI(int argc, char **argv)
   onscreen_buffer[0][0] = '\0';
   onscreen_buffer[1][0] = '\0';
 
-  // initialize selection bits
-  selection = ENT_NONE;
-  try_selection = quit_selection = end_selection = 0;
-  undo_selection = invert_selection = 0;
-  for(int i = 0; i < 4; i++) try_selection_xywh[i] = 0;
-
   // set X display
   if(strlen(CTX.display))
     Fl::display(CTX.display);
@@ -134,10 +129,10 @@ GUI::GUI(int argc, char **argv)
   graph[0]->gl->take_focus();
 
   // test: create another graphic window
-  //double mat[3][3]={{3,0,0}, {0,1,0}, {0,0,1}};
-  //drawContext *ctx = new drawContext(new drawTransformScaled(mat));
-  //graph.push_back(new graphicWindow(_fontsize, ctx));
-  //graph.back()->win->show();
+  double mat[3][3]={{3,0,0}, {0,1,0}, {0,0,1}};
+  drawContext *ctx = new drawContext(new drawTransformScaled(mat));
+  graph.push_back(new graphicWindow(_fontsize, ctx));
+  graph.back()->win->show();
 
   options = new optionWindow(_fontsize);
   fields = new fieldWindow(_fontsize);
@@ -227,23 +222,28 @@ int GUI::testGlobalShortcuts(int event)
     status = 1;
   }
   else if(Fl::test_shortcut('e')) {
-    end_selection = 1;
+    for(unsigned int i = 0; i < graph.size(); i++)
+      graph[i]->gl->endSelection = 1;
     status = 0; // trick: do as if we didn't use it
   }
   else if(Fl::test_shortcut('u')) {
-    undo_selection = 1;
+    for(unsigned int i = 0; i < graph.size(); i++)
+      graph[i]->gl->undoSelection = 1;
     status = 0; // trick: do as if we didn't use it
   }
   else if(Fl::test_shortcut('i')) {
-    invert_selection = 1;
+    for(unsigned int i = 0; i < graph.size(); i++)
+      graph[i]->gl->invertSelection = 1;
     status = 0; // trick: do as if we didn't use it
   }
   else if(Fl::test_shortcut('q')) {
-    quit_selection = 1;
+    for(unsigned int i = 0; i < graph.size(); i++)
+      graph[i]->gl->quitSelection = 1;
     status = 0; // trick: do as if we didn't use it
   }
   else if(Fl::test_shortcut('-')) {
-    invert_selection = 1;
+    for(unsigned int i = 0; i < graph.size(); i++)
+      graph[i]->gl->invertSelection = 1;
     status = 0; // trick: do as if we didn't use it
   }
   else if(Fl::test_shortcut(FL_Escape) ||
@@ -251,8 +251,12 @@ int GUI::testGlobalShortcuts(int event)
           Fl::test_shortcut(FL_SHIFT + FL_Escape) ||
           Fl::test_shortcut(FL_CTRL + FL_Escape) ||
           Fl::test_shortcut(FL_ALT + FL_Escape)) {
-    if(graph[0]->gl->lassoMode){
-      graph[0]->gl->lassoMode = false;
+    bool lasso = false;
+    for(unsigned int i = 0; i < graph.size(); i++)
+      if(graph[i]->gl->lassoMode) lasso = true;
+    if(lasso){
+      for(unsigned int i = 0; i < graph.size(); i++)
+        graph[i]->gl->lassoMode = false;
       status = 2;
     }
     else{
@@ -617,6 +621,22 @@ void GUI::callForSolverPlugin(int dim)
   if(sp) sp->popupPropertiesForPhysicalEntity(dim);
 }
 
+char GUI::selectEntity(int type, 
+                       std::vector<GVertex*> &vertices, std::vector<GEdge*> &edges,
+                       std::vector<GFace*> &faces, std::vector<GRegion*> &regions,
+                       std::vector<MElement*> &elements)
+{
+  unsigned int index = 0;
+  if(graph.size() > 1)
+    for(Fl_Window *w = Fl::first_window(); w; w = Fl::next_window(w))
+      for(index = 0; index < GUI::instance()->graph.size(); index++)
+        if(w == graph[index]->win || w == graph[index]->gl)
+          goto done;
+ done:
+  return graph[index]->gl->selectEntity
+    (type, vertices, edges, faces, regions, elements);
+}
+
 // Callbacks
 
 void hide_cb(Fl_Widget *w, void *data)
diff --git a/Fltk/GUI.h b/Fltk/GUI.h
index 5abcdd34d3..3ddde31bb2 100644
--- a/Fltk/GUI.h
+++ b/Fltk/GUI.h
@@ -32,15 +32,18 @@ class meshContextWindow;
 class aboutWindow;
 class solverWindow;
 
+class GVertex;
+class GEdge;
+class GFace;
+class GRegion;
+class MElement;
+
 class GUI{
  private:
   int _fontsize;
   static GUI *_instance;
  public:
   char onscreen_buffer[2][256];
-  int selection, try_selection, quit_selection, end_selection;
-  int undo_selection, invert_selection;
-  int try_selection_xywh[4];
  public:
   std::vector<graphicWindow*> graph;
   menuWindow *menu;
@@ -93,6 +96,11 @@ class GUI{
   void setStatus(const char *msg, int num);
   // create the window for physical context dependant definitions
   void callForSolverPlugin(int dim);
+  // select an entity in the most recent graphic window
+  char selectEntity(int type, 
+                    std::vector<GVertex*> &vertices, std::vector<GEdge*> &edges,
+                    std::vector<GFace*> &faces, std::vector<GRegion*> &regions, 
+                    std::vector<MElement*> &elements);
 };
 
 // callbacks
diff --git a/Fltk/Makefile b/Fltk/Makefile
index a0bb89684d..24d0d5d735 100644
--- a/Fltk/Makefile
+++ b/Fltk/Makefile
@@ -96,11 +96,14 @@ GUI${OBJEXT}: GUI.cpp GUI.h graphicWindow.h openglWindow.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 ../Post/PView.h Solvers.h ../Mesh/Field.h \
-  ../Plugin/Plugin.h ../Common/Options.h ../Post/PViewDataList.h \
-  ../Post/PViewData.h ../Common/ListUtils.h ../Numeric/GmshMatrix.h \
-  ../Plugin/PluginManager.h ../Common/OpenFile.h ../Common/Context.h \
-  ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h
+  ../Geo/SBoundingBox3d.h ../Geo/MElement.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 ../Post/PView.h \
+  Solvers.h ../Mesh/Field.h ../Plugin/Plugin.h ../Common/Options.h \
+  ../Post/PViewDataList.h ../Post/PViewData.h ../Common/ListUtils.h \
+  ../Plugin/PluginManager.h ../Common/OpenFile.h Win32Icon.h \
+  ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h
 graphicWindow${OBJEXT}: graphicWindow.cpp GUI.h graphicWindow.h openglWindow.h \
   ../Graphics/drawContext.h ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h \
   shortcutWindow.h menuWindow.h popupButton.h messageWindow.h \
@@ -109,20 +112,21 @@ graphicWindow${OBJEXT}: graphicWindow.cpp GUI.h graphicWindow.h openglWindow.h \
   ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h
 openglWindow${OBJEXT}: openglWindow.cpp openglWindow.h ../Graphics/drawContext.h \
   ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h graphicWindow.h manipWindow.h \
-  contextWindow.h ../Common/GmshDefines.h ../Common/GmshMessage.h Draw.h \
-  ../Numeric/Numeric.h ../Numeric/NumericEmbedded.h ../Common/Context.h \
-  ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h \
-  ../Graphics/SelectBuffer.h ../Graphics/drawContext.h ../Geo/GVertex.h \
-  ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.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 GUI.h \
-  ../Geo/MElement.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
+  contextWindow.h ../Common/GmshDefines.h ../Common/GmshMessage.h \
+  ../Geo/GModel.h ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/Range.h \
+  ../Geo/SPoint3.h ../Geo/SBoundingBox3d.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 ../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 Draw.h \
+  ../Numeric/Numeric.h ../Numeric/NumericEmbedded.h GUI.h \
+  ../Common/VertexArray.h ../Common/Context.h ../Geo/CGNSOptions.h \
+  ../Mesh/PartitionOptions.h
 menuWindow${OBJEXT}: menuWindow.cpp GUI.h Draw.h menuWindow.h popupButton.h \
   shortcutWindow.h graphicWindow.h openglWindow.h \
   ../Graphics/drawContext.h ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h \
@@ -147,31 +151,27 @@ menuWindow${OBJEXT}: menuWindow.cpp GUI.h Draw.h menuWindow.h popupButton.h \
   ../Common/CommandLine.h ../Mesh/Generator.h ../Mesh/HighOrder.h \
   ../Post/PView.h ../Post/PViewData.h ../Post/PViewOptions.h \
   ../Post/ColorTable.h ../Mesh/Field.h ../Common/OS.h \
-  ../Common/StringUtils.h ../Graphics/SelectBuffer.h \
-  ../Graphics/drawContext.h ../Common/OpenFile.h ../Common/CreateFile.h \
+  ../Common/StringUtils.h ../Common/OpenFile.h ../Common/CreateFile.h \
   ../Geo/findLinks.h ../Common/ListUtils.h ../Geo/GeoStringInterface.h \
   ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h
 optionWindow${OBJEXT}: optionWindow.cpp GUI.h optionWindow.h \
   spherePositionWidget.h colorbarWindow.h ../Post/ColorTable.h \
   shortcutWindow.h menuWindow.h popupButton.h extraDialogs.h Draw.h \
-  ../Graphics/SelectBuffer.h ../Graphics/drawContext.h \
-  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Geo/GVertex.h \
-  ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.h ../Geo/GPoint.h ../Geo/SPoint2.h ../Geo/GEdge.h \
+  ../Common/GmshDefines.h ../Common/GmshMessage.h ../Common/Options.h \
+  Solvers.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 \
-  ../Common/GmshDefines.h ../Common/GmshMessage.h ../Common/Options.h \
-  Solvers.h ../Geo/GModel.h ../Geo/GVertex.h ../Geo/GEdge.h \
-  ../Geo/GFace.h ../Geo/GRegion.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.h ../Geo/MElement.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 ../Post/PView.h \
-  ../Post/PViewData.h ../Post/PViewOptions.h ../Post/ColorTable.h \
-  ../Common/OS.h ../Common/Context.h ../Geo/CGNSOptions.h \
-  ../Mesh/PartitionOptions.h
+  ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h ../Geo/MElement.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 \
+  ../Post/PView.h ../Post/PViewData.h ../Post/PViewOptions.h \
+  ../Post/ColorTable.h ../Common/OS.h ../Common/Context.h \
+  ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h
 colorbarWindow${OBJEXT}: colorbarWindow.cpp colorbarWindow.h \
   ../Post/ColorTable.h GUI.h ../Common/Context.h ../Geo/CGNSOptions.h \
   ../Mesh/PartitionOptions.h
@@ -186,7 +186,6 @@ fieldWindow${OBJEXT}: fieldWindow.cpp GUI.h Draw.h fieldWindow.h \
   ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/SPoint3.h \
   ../Geo/SBoundingBox3d.h ../Post/PView.h ../Common/GmshMessage.h \
   ../Mesh/Field.h ../Geo/GeoStringInterface.h ../Common/ListUtils.h \
-  ../Graphics/SelectBuffer.h ../Graphics/drawContext.h \
   ../Common/Options.h ../Post/ColorTable.h ../Common/Context.h \
   ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h
 pluginWindow${OBJEXT}: pluginWindow.cpp GUI.h Draw.h pluginWindow.h \
@@ -226,7 +225,6 @@ visibilityWindow${OBJEXT}: visibilityWindow.cpp GUI.h Draw.h visibilityWindow.h
   ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
   ../Numeric/FunctionSpace.h ../Numeric/GmshMatrix.h \
   ../Common/Visibility.h ../Common/GmshDefines.h \
-  ../Graphics/SelectBuffer.h ../Graphics/drawContext.h \
   ../Geo/GeoStringInterface.h ../Common/ListUtils.h ../Common/Options.h \
   ../Post/ColorTable.h ../Common/Context.h ../Geo/CGNSOptions.h \
   ../Mesh/PartitionOptions.h
@@ -244,16 +242,16 @@ manipWindow${OBJEXT}: manipWindow.cpp GUI.h Draw.h manipWindow.h \
   ../Common/Options.h ../Post/ColorTable.h ../Common/Context.h \
   ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h
 contextWindow${OBJEXT}: contextWindow.cpp GUI.h Draw.h contextWindow.h \
-  shortcutWindow.h ../Geo/GeoStringInterface.h ../Common/ListUtils.h \
-  ../Common/OpenFile.h ../Graphics/SelectBuffer.h \
-  ../Graphics/drawContext.h ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h \
-  ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.h ../Geo/GPoint.h ../Geo/SPoint2.h ../Geo/GEdge.h \
+  shortcutWindow.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 \
-  ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h
+  ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h ../Geo/GeoStringInterface.h \
+  ../Common/ListUtils.h ../Common/OpenFile.h ../Common/Context.h \
+  ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h
 solverWindow${OBJEXT}: solverWindow.cpp GUI.h solverWindow.h shortcutWindow.h \
   optionWindow.h spherePositionWidget.h colorbarWindow.h \
   ../Post/ColorTable.h messageWindow.h fileDialogs.h \
@@ -303,8 +301,7 @@ projectionEditor${OBJEXT}: projectionEditor.cpp GUI.h projectionEditor.h \
   ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
   ../Common/GmshMessage.h ../Numeric/FunctionSpace.h \
   ../Numeric/GmshMatrix.h Draw.h ../Common/Options.h \
-  ../Common/StringUtils.h ../Graphics/SelectBuffer.h \
-  ../Graphics/drawContext.h ../Geo/fourierFace.h ../Geo/GFace.h \
+  ../Common/StringUtils.h ../Geo/fourierFace.h ../Geo/GFace.h \
   ../Geo/GModel.h ../Geo/Range.h ../Geo/fourierEdge.h ../Geo/GEdge.h \
   ../Geo/GModel.h ../Geo/fourierVertex.h ../Geo/GModel.h ../Geo/GVertex.h \
   ../Geo/MVertex.h ../Common/Context.h ../Geo/CGNSOptions.h \
@@ -325,7 +322,6 @@ classificationEditor${OBJEXT}: classificationEditor.cpp GUI.h \
   ../Numeric/GmshMatrix.h ../Post/ColorTable.h ../Numeric/Numeric.h \
   ../Numeric/NumericEmbedded.h Draw.h ../Common/Options.h \
   ../Common/Context.h ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h \
-  ../Graphics/SelectBuffer.h ../Graphics/drawContext.h \
   ../Mesh/meshGFaceDelaunayInsertion.h ../Mesh/meshGFaceOptimize.h \
   ../Mesh/meshGFaceDelaunayInsertion.h ../Geo/discreteEdge.h \
   ../Geo/GModel.h ../Geo/GEdge.h ../Geo/discreteFace.h ../Geo/GModel.h \
diff --git a/Fltk/classificationEditor.cpp b/Fltk/classificationEditor.cpp
index 1b84e89bbd..89cdc32458 100644
--- a/Fltk/classificationEditor.cpp
+++ b/Fltk/classificationEditor.cpp
@@ -11,7 +11,6 @@
 #include "Draw.h"
 #include "Options.h"
 #include "Context.h"
-#include "SelectBuffer.h"
 #include "GmshMessage.h"
 #include "meshGFaceDelaunayInsertion.h"
 #include "meshGFaceOptimize.h"
@@ -20,7 +19,7 @@
 
 extern Context_T CTX;
 
-static void NoElementsSelectedMode (classificationEditor *e)
+static void NoElementsSelectedMode(classificationEditor *e)
 {
   e->_buttons[CLASSBUTTON_DEL]->deactivate();
   e->_buttons[CLASSBUTTON_ADD]->deactivate();
@@ -65,24 +64,25 @@ static void class_selectgface_cb(Fl_Widget *w, void *data)
     Msg::StatusBar(3, false, "Select Model Face\n"
         "[Press 'e' to end selection or 'q' to abort]");
     
-    char ib = SelectEntity(ENT_SURFACE, vertices, edges, faces, regions, elements);
+    char ib = GUI::instance()->selectEntity
+      (ENT_SURFACE, vertices, edges, faces, regions, elements);
     if(ib == 'l') {
       for(unsigned int i = 0; i < faces.size(); i++){
-        HighlightEntity(faces[i]);      
+        faces[i]->setSelection(1);
         temp.push_back(faces[i]);
       }
     }
     // ok store the list of gfaces !
     if(ib == 'e') {
-      ZeroHighlight();
+      GModel::current()->setSelection(0);
       for(unsigned int i = 0; i < temp.size(); i++){
-        e->_faces.insert (temp[i]);
+        e->_faces.insert(temp[i]);
       }
       break;
     }
     // do nothing
     if(ib == 'q') {
-      ZeroHighlight();
+      GModel::current()->setSelection(0);
       break;
     }
   } 
@@ -110,7 +110,8 @@ static void class_deleteedge_cb(Fl_Widget *w, void *data)
     Msg::StatusBar(3, false, "Select Elements\n"
         "[Press 'e' to end selection or 'q' to abort]");
     
-    char ib = SelectEntity(ENT_ALL, vertices, edges, faces, regions, elements);
+    char ib = GUI::instance()->selectEntity
+      (ENT_ALL, vertices, edges, faces, regions, elements);
     if(ib == 'l') {
       if(CTX.pick_elements){
         for(unsigned int i = 0; i < elements.size(); i++){
@@ -126,26 +127,26 @@ static void class_deleteedge_cb(Fl_Widget *w, void *data)
     }
     // ok, we compute edges !
     if(ib == 'e') {
-      ZeroHighlight();      
+      GModel::current()->setSelection(0);
       break;
     }
     // do nothing
     if(ib == 'q') {
-      ZeroHighlight();
+      GModel::current()->setSelection(0);
       ele.clear();
       break;
     }
   }
 
-  std::sort (ele.begin(),ele.end());
+  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())
+      std::vector<MLine*>::iterator it = std::find(ele.begin(),ele.end(),temp[i]);
+      if(it != ele.end())
         {
           delete temp[i];
         }
@@ -170,7 +171,7 @@ static void class_save_cb(Fl_Widget *w, void *data)
 
   CTX.mesh.changed = ENT_ALL;
   CTX.pick_elements = 0;
-  NoElementsSelectedMode (e);
+  NoElementsSelectedMode(e);
   Draw();  
   Msg::StatusBar(3, false, "");
 }
@@ -186,7 +187,7 @@ static void class_clear_cb(Fl_Widget *w, void *data)
 
   CTX.mesh.changed = ENT_ALL;
   CTX.pick_elements = 0;
-  NoElementsSelectedMode (e);
+  NoElementsSelectedMode(e);
   Draw();  
   Msg::StatusBar(3, false, "");
 }
@@ -220,14 +221,13 @@ static void class_okcolor_cb(Fl_Widget *w, void *data)
 
 static int maxEdgeNum()
 {
-  GModel::eiter it =  GModel::current()->firstEdge();
+  GModel::eiter it = GModel::current()->firstEdge();
   GModel::eiter ite = GModel::current()->lastEdge();
   int MAXX = 0;
-  while (it != ite)
-    {
-      MAXX = std::max (MAXX, (*it)->tag());
-      ++it;
-    }
+  while(it != ite){
+    MAXX = std::max(MAXX, (*it)->tag());
+    ++it;
+  }
   return MAXX;
 }
 
@@ -236,20 +236,19 @@ static int maxFaceNum()
   GModel::fiter it =  GModel::current()->firstFace();
   GModel::fiter ite = GModel::current()->lastFace();
   int MAXX = 0;
-  while (it != ite)
-    {
-      MAXX = std::max (MAXX, (*it)->tag());
-      ++it;
-    }
+  while(it != ite){
+    MAXX = std::max(MAXX, (*it)->tag());
+    ++it;
+  }
   return MAXX;
 }
 
 struct compareMLinePtr 
 {
-  bool operator () ( MLine *l1 , MLine *l2) const
+  bool operator () (MLine *l1, MLine *l2) const
   {
     static Less_Edge le;
-    return le(l1->getEdge(0),l2->getEdge(0)); 
+    return le(l1->getEdge(0), l2->getEdge(0)); 
   }
 };
 
@@ -257,7 +256,7 @@ static void recurClassify(MTri3 *t, GFace *gf,
                           std::map<MLine*, GEdge*, compareMLinePtr> &lines,
                           std::map<MTriangle*, GFace*> &reverse)
 {
-  if (!t->isDeleted()){
+  if(!t->isDeleted()){
     gf->triangles.push_back(t->tri());
     reverse[t->tri()] = gf;
     t->setDeleted(true);
@@ -267,7 +266,7 @@ static void recurClassify(MTri3 *t, GFace *gf,
         edgeXface exf(t, i);
         MLine ml(exf.v[0], exf.v[1]);       
         std::map<MLine*, GEdge*, compareMLinePtr>::iterator it = lines.find(&ml);
-        if (it == lines.end())
+        if(it == lines.end())
           recurClassify(tn, gf, lines, reverse);
       }
     }  
@@ -282,13 +281,13 @@ static GEdge *getNewModelEdge(GFace *gf1, GFace *gf2,
   int i1 = std::min(t1,t2);
   int i2 = std::max(t1,t2);
 
-  if (i1 == i2) return 0;
+  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(GModel::current(), maxEdgeNum() + 1);
-    GModel::current()->add (temporary);
+    GModel::current()->add(temporary);
     newEdges[std::make_pair<int, int>(i1, i2)] = temporary;
     return temporary;
   }
@@ -296,31 +295,31 @@ static GEdge *getNewModelEdge(GFace *gf1, GFace *gf2,
     return it->second;  
 }
 
-static void recurClassifyEdges(MTri3 *t , 
+static void recurClassifyEdges(MTri3 *t, 
                                std::map<MTriangle*, GFace*> &reverse,
                                std::map<MLine*, GEdge*, compareMLinePtr> &lines,
                                std::set<MLine*> &touched,
                                std::map<std::pair<int, int>, GEdge*> &newEdges)
 {
-  if (!t->isDeleted()){
+  if(!t->isDeleted()){
     t->setDeleted(true);
     GFace *gf1 = reverse[t->tri()];
-    for (int i = 0; i < 3; i++){
+    for(int i = 0; i < 3; i++){
       GFace *gf2 = 0;
       MTri3 *tn = t->getNeigh(i);
-      if (tn)
+      if(tn)
         gf2 = reverse[tn->tri()];
       edgeXface exf(t, i);
       MLine ml(exf.v[0], exf.v[1]);
       std::map<MLine*, GEdge*, compareMLinePtr>::iterator it = lines.find(&ml);
-      if (it != lines.end()){
-        if (touched.find(it->first) == touched.end()){
-          GEdge *ge =  getNewModelEdge (gf1, gf2, newEdges);
-          if (ge) ge->lines.push_back(it->first);
+      if(it != lines.end()){
+        if(touched.find(it->first) == touched.end()){
+          GEdge *ge =  getNewModelEdge(gf1, gf2, newEdges);
+          if(ge) ge->lines.push_back(it->first);
           touched.insert(it->first);
         }
       }
-      if (tn)
+      if(tn)
         recurClassifyEdges(tn, reverse, lines, touched, newEdges);
     }
   }
@@ -333,8 +332,8 @@ static void class_color_cb(Fl_Widget* w, void* data)
   {
     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++) 
+    for( ; it != ite; ++it){
+      for(unsigned int i = 0; i < (*it)->lines.size();i++) 
         lines[(*it)->lines[i]] = *it;
     }
   }
@@ -342,9 +341,9 @@ static void class_color_cb(Fl_Widget* w, void* data)
   std::list<MTri3*> tris;
   {
     std::set<GFace*>::iterator it = e->_faces.begin();
-    while (it != e->_faces.end()){
+    while(it != e->_faces.end()){
       GFace *gf = *it;
-      for (unsigned int i = 0; i < gf->triangles.size(); i++){
+      for(unsigned int i = 0; i < gf->triangles.size(); i++){
             tris.push_back(new MTri3(gf->triangles [i], 0));
       }
       gf->triangles.clear();
@@ -359,8 +358,8 @@ static void class_color_cb(Fl_Widget* w, void* data)
 
     // color all triangles
     std::list<MTri3*> ::iterator it = tris.begin();
-    while (it != tris.end()){
-      if (!(*it)->isDeleted()){
+    while(it != tris.end()){
+      if(!(*it)->isDeleted()){
         discreteFace *temporary = new discreteFace(GModel::current(), maxFaceNum() + 1);
         recurClassify(*it, temporary, lines, reverse);
         GModel::current()->add(temporary);
@@ -370,7 +369,7 @@ static void class_color_cb(Fl_Widget* w, void* data)
     
     // color some lines
     it = tris.begin();
-    while (it != tris.end()){
+    while(it != tris.end()){
       (*it)->setDeleted(false);
       ++it;
     }
@@ -382,7 +381,7 @@ static void class_color_cb(Fl_Widget* w, void* data)
     recurClassifyEdges(*it, reverse, lines, touched, newEdges);
     GModel::current()->remove(e->saved);
 
-    while (it != tris.end()){
+    while(it != tris.end()){
       delete *it;
       ++it;
     }
@@ -404,7 +403,7 @@ static void updateedges_cb(Fl_Widget* w, void* data)
   }
   e->temporary->lines.clear();
 
-  for (unsigned int i = 0; i < e->edges_detected.size(); i++){
+  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)
@@ -412,8 +411,8 @@ static void updateedges_cb(Fl_Widget* w, void* data)
     e->temporary->lines.push_back(new MLine(ea.v1, ea.v2));
   } 
 
-  if (e->_togbuttons[CLASSTOGBUTTON_CLOS]->value()){
-    for (unsigned int i = 0 ; i < e->edges_lonly.size(); i++){
+  if(e->_togbuttons[CLASSTOGBUTTON_CLOS]->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));
     } 
@@ -434,7 +433,7 @@ static void buildListOfEdgeAngle(e2t_cont adj, std::vector<edge_angle> &edges_de
                                  std::vector<edge_angle> &edges_lonly)
 {
   e2t_cont::iterator it = adj.begin();
-  for( ; it != adj.end(); ++it){
+  for(; it != adj.end(); ++it){
     if(it->second.second)
       edges_detected.push_back(edge_angle(it->first.getVertex(0), 
                                           it->first.getVertex(1), 
@@ -466,7 +465,8 @@ static void class_select_cb(Fl_Widget *w, void *data)
     Msg::StatusBar(3, false, "Select Elements\n"
         "[Press 'e' to end selection or 'q' to abort]");
     
-    char ib = SelectEntity(ENT_ALL, vertices, edges, faces, regions, elements);
+    char ib = GUI::instance()->selectEntity
+      (ENT_ALL, vertices, edges, faces, regions, elements);
     if(ib == 'l') {
       if(CTX.pick_elements){
         for(unsigned int i = 0; i < elements.size(); i++){
@@ -482,16 +482,16 @@ static void class_select_cb(Fl_Widget *w, void *data)
     }
     // ok, we compute edges !
     if(ib == 'e') {
-      ZeroHighlight();
+      GModel::current()->setSelection(0);
       e2t_cont adj;
-      buildEdgeToTriangle (ele , adj );      
-      buildListOfEdgeAngle ( adj,e->edges_detected,e->edges_lonly);
-      ElementsSelectedMode (e);
+      buildEdgeToTriangle(ele, adj);
+      buildListOfEdgeAngle(adj, e->edges_detected, e->edges_lonly);
+      ElementsSelectedMode(e);
       break;
     }
     // do nothing
     if(ib == 'q') {
-      ZeroHighlight();
+      GModel::current()->setSelection(0);
       ele.clear();
       break;
     }
@@ -508,7 +508,7 @@ static void class_select_cb(Fl_Widget *w, void *data)
 edge_angle::edge_angle(MVertex *_v1, MVertex *_v2, MElement *t1, MElement *t2)
   : v1(_v1), v2(_v2)
 {
-  if (!t2) angle = 0;
+  if(!t2) angle = 0;
   else{
     double c1[3];
     double c2[3];
@@ -630,7 +630,7 @@ classificationEditor::classificationEditor()
     o->deactivate();
     o->end();
   }
-  NoElementsSelectedMode (this);
+  NoElementsSelectedMode(this);
 
   // allocate detected edges
   // temporary for the selection
diff --git a/Fltk/contextWindow.cpp b/Fltk/contextWindow.cpp
index dece09ba31..0c12a9bdf4 100644
--- a/Fltk/contextWindow.cpp
+++ b/Fltk/contextWindow.cpp
@@ -9,9 +9,9 @@
 #include "Draw.h"
 #include "contextWindow.h"
 #include "shortcutWindow.h"
+#include "GModel.h"
 #include "GeoStringInterface.h"
 #include "OpenFile.h"
-#include "SelectBuffer.h"
 #include "Context.h"
 
 extern Context_T CTX;
@@ -31,7 +31,7 @@ static void con_geometry_define_point_cb(Fl_Widget *w, void *data)
             GUI::instance()->geoContext->input[4]->value(),
             GUI::instance()->geoContext->input[5]->value());
   GUI::instance()->resetVisibility();
-  ZeroHighlight();
+  GModel::current()->setSelection(0);
   SetBoundingBox();
   Draw();
 }
diff --git a/Fltk/fieldWindow.cpp b/Fltk/fieldWindow.cpp
index f9472332f5..d6a4e32680 100644
--- a/Fltk/fieldWindow.cpp
+++ b/Fltk/fieldWindow.cpp
@@ -19,7 +19,6 @@
 #include "GmshMessage.h"
 #include "Field.h"
 #include "GeoStringInterface.h"
-#include "SelectBuffer.h"
 #include "Options.h"
 #include "Context.h"
 
@@ -110,7 +109,8 @@ static void field_select_node_cb(Fl_Widget *w, void *data)
     Msg::StatusBar(3, false, "Select %s\n[Press %s'q' to abort]", 
         help, mode ? "" : "'u' to undo or ");
     
-    char ib = SelectEntity(ENT_POINT, vertices, edges, faces, regions, elements);
+    char ib = GUI::instance()->selectEntity
+      (ENT_POINT, vertices, edges, faces, regions, elements);
     printf("char = %c\n", ib);
     if(ib == 'q'){
       for(std::vector<GVertex*>::iterator it = vertices.begin(); it != vertices.end(); it++){
diff --git a/Fltk/menuWindow.cpp b/Fltk/menuWindow.cpp
index 13b59f15cd..9721ed01a2 100644
--- a/Fltk/menuWindow.cpp
+++ b/Fltk/menuWindow.cpp
@@ -41,7 +41,6 @@
 #include "Field.h"
 #include "OS.h"
 #include "StringUtils.h"
-#include "SelectBuffer.h"
 #include "OpenFile.h"
 #include "CreateFile.h"
 #include "findLinks.h"
@@ -531,15 +530,18 @@ static void add_new_point()
   GUI::instance()->geoContext->show(1);
 
   while(1) {
-    GUI::instance()->graph[0]->gl->addPointMode = true;
+    for(unsigned int i = 0; i < GUI::instance()->graph.size(); i++)
+      GUI::instance()->graph[i]->gl->addPointMode = true;
     Msg::StatusBar(3, false, "Move mouse and/or enter coordinates\n"
-        "[Press 'Shift' to hold position, 'e' to add point or 'q' to abort]");
+                   "[Press 'Shift' to hold position, 'e' to add point "
+                   "or 'q' to abort]");
     std::vector<GVertex*> vertices;
     std::vector<GEdge*> edges;
     std::vector<GFace*> faces;
     std::vector<GRegion*> regions;
     std::vector<MElement*> elements;
-    char ib = SelectEntity(ENT_NONE, vertices, edges, faces, regions, elements);
+    char ib = GUI::instance()->selectEntity
+      (ENT_NONE, vertices, edges, faces, regions, elements);
     if(ib == 'e'){
       add_point(CTX.filename,
                 GUI::instance()->geoContext->input[2]->value(),
@@ -550,7 +552,8 @@ static void add_new_point()
       Draw();
     }
     if(ib == 'q'){
-      GUI::instance()->graph[0]->gl->addPointMode = false;
+      for(unsigned int i = 0; i < GUI::instance()->graph.size(); i++)
+        GUI::instance()->graph[i]->gl->addPointMode = false;
       break;
     }
   }
@@ -574,14 +577,16 @@ static void add_new_multiline(std::string type)
   while(1) {
     if(p.empty())
       Msg::StatusBar(3, false, "Select control points\n"
-          "[Press 'e' to end selection or 'q' to abort]");
+                     "[Press 'e' to end selection or 'q' to abort]");
     else
       Msg::StatusBar(3, false, "Select control points\n"
-          "[Press 'e' to end selection, 'u' to undo last selection or 'q' to abort]");
-    char ib = SelectEntity(ENT_POINT, vertices, edges, faces, regions, elements);
+                     "[Press 'e' to end selection, 'u' to undo last selection "
+                     "or 'q' to abort]");
+    char ib = GUI::instance()->selectEntity
+      (ENT_POINT, vertices, edges, faces, regions, elements);
     if(ib == 'l') {
       for(unsigned int i = 0; i < vertices.size(); i++){
-        HighlightEntity(vertices[i]);
+        vertices[i]->setSelection(1);
         p.push_back(vertices[i]->tag());
       }
       Draw();
@@ -593,19 +598,20 @@ static void add_new_multiline(std::string type)
       if(p.size() >= 2)
 	add_multline(type, p, CTX.filename);
       GUI::instance()->resetVisibility();
-      ZeroHighlight();
+      GModel::current()->setSelection(0);
       Draw();
       p.clear();
     }
     if(ib == 'u') {
       if(p.size()){
-        ZeroHighlightEntityNum(p.back(), 0, 0, 0);
+        GVertex *gv = GModel::current()->getVertexByTag(p.back());
+        if(gv) gv->setSelection(0);
         Draw();
         p.pop_back();
       }
     }
     if(ib == 'q') {
-      ZeroHighlight();
+      GModel::current()->setSelection(0);
       Draw();
       break;
     }
@@ -630,13 +636,14 @@ static void add_new_line()
   while(1) {
     if(p.empty())
       Msg::StatusBar(3, false, "Select start point\n"
-          "[Press 'q' to abort]");
+                     "[Press 'q' to abort]");
     if(p.size() == 1)
       Msg::StatusBar(3, false, "Select end point\n"
-          "[Press 'u' to undo last selection or 'q' to abort]");
-    char ib = SelectEntity(ENT_POINT, vertices, edges, faces, regions, elements);
+                     "[Press 'u' to undo last selection or 'q' to abort]");
+    char ib = GUI::instance()->selectEntity
+      (ENT_POINT, vertices, edges, faces, regions, elements);
     if(ib == 'l') {
-      HighlightEntity(vertices[0]);
+      vertices[0]->setSelection(1);
       Draw();
       p.push_back(vertices[0]->tag());
     }
@@ -645,20 +652,21 @@ static void add_new_line()
     }
     if(ib == 'u') {
       if(p.size()){
-        ZeroHighlightEntityNum(p.back(), 0, 0, 0);
+        GVertex *gv = GModel::current()->getVertexByTag(p.back());
+        if(gv) gv->setSelection(0);
         Draw();
         p.pop_back();
       }
     }
     if(ib == 'q') {
-      ZeroHighlight();
+      GModel::current()->setSelection(0);
       Draw();
       break;
     }
     if(p.size() == 2) {
       add_multline("Line", p, CTX.filename);
       GUI::instance()->resetVisibility();
-      ZeroHighlight();
+      GModel::current()->setSelection(0);
       Draw();
       p.clear();
     }
@@ -683,16 +691,17 @@ static void add_new_circle()
   while(1) {
     if(p.empty())
       Msg::StatusBar(3, false, "Select start point\n"
-          "[Press 'q' to abort]");
+                     "[Press 'q' to abort]");
     if(p.size() == 1)
       Msg::StatusBar(3, false, "Select center point\n"
-          "[Press 'u' to undo last selection or 'q' to abort]");
+                     "[Press 'u' to undo last selection or 'q' to abort]");
     if(p.size() == 2)
       Msg::StatusBar(3, false, "Select end point\n"
-          "[Press 'u' to undo last selection or 'q' to abort]");
-    char ib = SelectEntity(ENT_POINT, vertices, edges, faces, regions, elements);
+                     "[Press 'u' to undo last selection or 'q' to abort]");
+    char ib = GUI::instance()->selectEntity
+      (ENT_POINT, vertices, edges, faces, regions, elements);
     if(ib == 'l') {
-      HighlightEntity(vertices[0]);
+      vertices[0]->setSelection(1);
       Draw();
       p.push_back(vertices[0]->tag());
     }
@@ -701,20 +710,21 @@ static void add_new_circle()
     }
     if(ib == 'u') {
       if(p.size()){
-        ZeroHighlightEntityNum(p.back(), 0, 0, 0);
+        GVertex *gv = GModel::current()->getVertexByTag(p.back());
+        if(gv) gv->setSelection(0);
         Draw();
         p.pop_back();
       }
     }
     if(ib == 'q') {
-      ZeroHighlight();
+      GModel::current()->setSelection(0);
       Draw();
       break;
     }
     if(p.size() == 3) {
       add_circ(p[0], p[1], p[2], CTX.filename); // begin, center, end
       GUI::instance()->resetVisibility();
-      ZeroHighlight();
+      GModel::current()->setSelection(0);
       Draw();
       p.clear();
     }
@@ -739,19 +749,20 @@ static void add_new_ellipse()
   while(1) {
     if(p.empty())
       Msg::StatusBar(3, false, "Select start point\n"
-          "[Press 'q' to abort]");
+                     "[Press 'q' to abort]");
     if(p.size() == 1)
       Msg::StatusBar(3, false, "Select center point\n"
-          "[Press 'u' to undo last selection or 'q' to abort]");
+                     "[Press 'u' to undo last selection or 'q' to abort]");
     if(p.size() == 2)
       Msg::StatusBar(3, false, "Select major axis point\n"
-          "[Press 'u' to undo last selection or 'q' to abort]");
+                     "[Press 'u' to undo last selection or 'q' to abort]");
     if(p.size() == 3)
       Msg::StatusBar(3, false, "Select end point\n"
-          "[Press 'u' to undo last selection or 'q' to abort]");
-    char ib = SelectEntity(ENT_POINT, vertices, edges, faces, regions, elements);
+                     "[Press 'u' to undo last selection or 'q' to abort]");
+    char ib = GUI::instance()->selectEntity
+      (ENT_POINT, vertices, edges, faces, regions, elements);
     if(ib == 'l') {
-      HighlightEntity(vertices[0]);
+      vertices[0]->setSelection(1);
       Draw();
       p.push_back(vertices[0]->tag());
     }
@@ -760,20 +771,21 @@ static void add_new_ellipse()
     }
     if(ib == 'u') {
       if(p.size()){
-        ZeroHighlightEntityNum(p.back(), 0, 0, 0);
+        GVertex *gv = GModel::current()->getVertexByTag(p.back());
+        if(gv) gv->setSelection(0);
         Draw();
         p.pop_back();
       }
     }
     if(ib == 'q') {
-      ZeroHighlight();
+      GModel::current()->setSelection(0);
       Draw();
       break;
     }
     if(p.size() == 4) {
       add_ell(p[0], p[1], p[2], p[3], CTX.filename);
       GUI::instance()->resetVisibility();
-      ZeroHighlight();
+      GModel::current()->setSelection(0);
       Draw();
       p.clear();
     }
@@ -791,14 +803,16 @@ static int select_contour(int type, int num, List_T * List)
     k = allEdgesLinked(num, List);
     for(int i = 0; i < List_Nbr(List); i++) {
       List_Read(List, i, &ip);
-      HighlightEntityNum(0, abs(ip), 0, 0);
+      GEdge *ge = GModel::current()->getEdgeByTag(abs(ip));
+      if(ge) ge->setSelection(1);
     }
     break;
   case ENT_SURFACE:
     k = allFacesLinked(num, List);
     for(int i = 0; i < List_Nbr(List); i++) {
       List_Read(List, i, &ip);
-      HighlightEntityNum(0, 0, abs(ip), 0);
+      GFace *gf = GModel::current()->getFaceByTag(abs(ip));
+      if(gf) gf->setSelection(1);
     }
     break;
   }
@@ -839,33 +853,38 @@ static void add_new_surface_volume(int mode)
       if(type == ENT_LINE){
         if(!List_Nbr(List1))
           Msg::StatusBar(3, false, "Select surface boundary\n"
-              "[Press 'q' to abort]");
+                         "[Press 'q' to abort]");
         else
           Msg::StatusBar(3, false, "Select surface boundary\n"
-              "[Press 'u' to undo last selection or 'q' to abort]");
+                         "[Press 'u' to undo last selection or 'q' to abort]");
       }
       else{
         if(!List_Nbr(List1))
           Msg::StatusBar(3, false, "Select volume boundary\n"
-              "[Press 'q' to abort]");
+                         "[Press 'q' to abort]");
         else
           Msg::StatusBar(3, false, "Select volume boundary\n"
-              "[Press 'u' to undo last selection or 'q' to abort]");
+                         "[Press 'u' to undo last selection or 'q' to abort]");
       }
-
-      char ib = SelectEntity(type, vertices, edges, faces, regions, elements);
+      
+      char ib = GUI::instance()->selectEntity
+        (type, vertices, edges, faces, regions, elements);
       if(ib == 'q') {
-        ZeroHighlight();
+        GModel::current()->setSelection(0);
         Draw();
         goto stopall;
       }
       if(ib == 'u') {
         if(List_Nbr(List1) > 0){
           List_Read(List1, List_Nbr(List1)-1, &num);
-          ZeroHighlightEntityNum(0,
-                                 (type == ENT_LINE) ? abs(num) : 0, 
-                                 (type != ENT_LINE) ? abs(num) : 0,
-                                 0);
+          if(type == ENT_LINE){
+            GEdge *ge = GModel::current()->getEdgeByTag(abs(num));
+            if(ge) ge->setSelection(0);
+          }
+          else{
+            GFace *gf = GModel::current()->getFaceByTag(abs(num));
+            if(gf) gf->setSelection(0);
+          }
           List_Pop(List1);
           Draw();
         }
@@ -893,14 +912,15 @@ static void add_new_surface_volume(int mode)
                 (3, false, "Select hole boundaries\n"
                  "[Press 'e' to end selection, 'u' to undo last selection "
                  "or 'q' to abort]");
-            ib = SelectEntity(type, vertices, edges, faces, regions, elements);
+            ib = GUI::instance()->selectEntity
+              (type, vertices, edges, faces, regions, elements);
             if(ib == 'q') {
-              ZeroHighlight();
+              GModel::current()->setSelection(0);
               Draw();
               goto stopall;
             }
             if(ib == 'e') {
-              ZeroHighlight();
+              GModel::current()->setSelection(0);
               Draw();
               List_Reset(List1);
               break;
@@ -908,10 +928,14 @@ static void add_new_surface_volume(int mode)
             if(ib == 'u') {
               if(List_Nbr(List1) > 0){
                 List_Read(List1, List_Nbr(List1)-1, &num);
-                ZeroHighlightEntityNum(0,
-                                       (type == ENT_LINE) ? abs(num) : 0, 
-                                       (type != ENT_LINE) ? abs(num) : 0,
-                                       0);
+                if(type == ENT_LINE){
+                  GEdge *ge = GModel::current()->getEdgeByTag(abs(num));
+                  if(ge) ge->setSelection(0);
+                }
+                else{
+                  GFace *gf = GModel::current()->getFaceByTag(abs(num));
+                  if(gf) gf->setSelection(0);
+                }
                 List_Pop(List1);
                 Draw();
               }
@@ -939,7 +963,7 @@ static void add_new_surface_volume(int mode)
             case 2: add_vol(List2, CTX.filename); break;
             }
             GUI::instance()->resetVisibility();
-            ZeroHighlight();
+            GModel::current()->setSelection(0);
             Draw();
             break;
           }
@@ -992,7 +1016,7 @@ static void split_selection()
   opt_geometry_lines(0, GMSH_SET | GMSH_GUI, 1);
   Draw();
   Msg::StatusBar(3, false, "Select a line to split\n"
-          "[Press 'q' to abort]");
+                 "[Press 'q' to abort]");
   std::vector<GVertex*> vertices;
   std::vector<GEdge*> edges;
   std::vector<GFace*> faces;
@@ -1000,12 +1024,13 @@ static void split_selection()
   std::vector<MElement*> elements;
   GEdge* edge_to_split = NULL;
   while(1){
-    char ib = SelectEntity(2, vertices, edges, faces, regions, elements);
+    char ib = GUI::instance()->selectEntity
+      (ENT_LINE, vertices, edges, faces, regions, elements);
     if(ib == 'q')
       break;
     if(!edges.empty()){
       edge_to_split = edges[0];
-      HighlightEntity(edges[0]);
+      edges[0]->setSelection(1);
       break;
     }
   }
@@ -1018,7 +1043,8 @@ static void split_selection()
   opt_geometry_points(0, GMSH_SET | GMSH_GUI, 1);
   Draw();
   while(1){
-    char ib = SelectEntity(1, vertices, edges, faces, regions, elements);
+    char ib = GUI::instance()->selectEntity
+      (ENT_POINT, vertices, edges, faces, regions, elements);
     if(ib == 'q')
       break;
     if(ib == 'e'){
@@ -1030,13 +1056,13 @@ static void split_selection()
         int tag = vertices[i]->tag();
         int index = List_ISearchSeq(List1, &tag, fcmp_int); 
         if(index < 0) List_Add(List1, &tag);
-        HighlightEntity(vertices[i]);
+        vertices[i]->setSelection(1);
       }
     }
   }
   Msg::StatusBar(3, false, "");
   GUI::instance()->resetVisibility();
-  ZeroHighlight();
+  GModel::current()->setSelection(0);
   Draw();
 }
 
@@ -1085,12 +1111,14 @@ static void action_point_line_surface_volume(int action, int mode, const char *w
   while(1) {
     if(!List_Nbr(List1))
       Msg::StatusBar(3, false, "Select %s\n"
-          "[Press 'e' to end selection or 'q' to abort]", str);
+                     "[Press 'e' to end selection or 'q' to abort]", str);
     else
       Msg::StatusBar(3, false, "Select %s\n"
-          "[Press 'e' to end selection, 'u' to undo last selection or 'q' to abort]", str);
-
-    char ib = SelectEntity(type, vertices, edges, faces, regions, elements);
+                     "[Press 'e' to end selection, 'u' to undo last selection "
+                     "or 'q' to abort]", str);
+    
+    char ib = GUI::instance()->selectEntity
+      (type, vertices, edges, faces, regions, elements);
     if(ib == 'l') {
       // we don't use List_Insert in order to keep the original
       // ordering (this is slower, but this way undo works as
@@ -1099,7 +1127,7 @@ static void action_point_line_surface_volume(int action, int mode, const char *w
       switch (type) {
       case ENT_POINT: 
         for(unsigned int i = 0; i < vertices.size(); i++){
-          HighlightEntity(vertices[i]);
+          vertices[i]->setSelection(1);
           tag = vertices[i]->tag();
           if(List_ISearchSeq(List1, &tag, fcmp_int) < 0)
             List_Add(List1, &tag);
@@ -1107,7 +1135,7 @@ static void action_point_line_surface_volume(int action, int mode, const char *w
         break;
       case ENT_LINE:
         for(unsigned int i = 0; i < edges.size(); i++){
-          HighlightEntity(edges[i]);
+          edges[i]->setSelection(1);
           tag = edges[i]->tag();
           if(List_ISearchSeq(List1, &tag, fcmp_int) < 0)
             List_Add(List1, &tag);
@@ -1115,7 +1143,7 @@ static void action_point_line_surface_volume(int action, int mode, const char *w
         break;
       case ENT_SURFACE:
         for(unsigned int i = 0; i < faces.size(); i++){
-          HighlightEntity(faces[i]);
+          faces[i]->setSelection(1);
           tag = faces[i]->tag();
           if(List_ISearchSeq(List1, &tag, fcmp_int) < 0)
             List_Add(List1, &tag);
@@ -1123,7 +1151,7 @@ static void action_point_line_surface_volume(int action, int mode, const char *w
         break;
       case ENT_VOLUME:
         for(unsigned int i = 0; i < regions.size(); i++){
-          HighlightEntity(regions[i]);
+          regions[i]->setSelection(1);
           tag = regions[i]->tag();
           if(List_ISearchSeq(List1, &tag, fcmp_int) < 0)
             List_Add(List1, &tag);
@@ -1143,7 +1171,7 @@ static void action_point_line_surface_volume(int action, int mode, const char *w
           tag = vertices[i]->tag();
           index = List_ISearchSeq(List1, &tag, fcmp_int); 
           if(index >= 0) List_PSuppress(List1, index);
-          ZeroHighlightEntityNum(tag, 0, 0, 0);
+          vertices[i]->setSelection(0);
         }
         break;
       case ENT_LINE:
@@ -1151,7 +1179,7 @@ static void action_point_line_surface_volume(int action, int mode, const char *w
           tag = edges[i]->tag();
           index = List_ISearchSeq(List1, &tag, fcmp_int); 
           if(index >= 0) List_PSuppress(List1, index);
-          ZeroHighlightEntityNum(0, tag, 0, 0);
+          edges[i]->setSelection(0);
         }
         break;
       case ENT_SURFACE:
@@ -1159,7 +1187,7 @@ static void action_point_line_surface_volume(int action, int mode, const char *w
           tag = faces[i]->tag();
           index = List_ISearchSeq(List1, &tag, fcmp_int); 
           if(index >= 0) List_PSuppress(List1, index);
-          ZeroHighlightEntityNum(0, 0, tag, 0);
+          faces[i]->setSelection(0);
         }
         break;
       case ENT_VOLUME:
@@ -1167,7 +1195,7 @@ static void action_point_line_surface_volume(int action, int mode, const char *w
           tag = regions[i]->tag();
           index = List_ISearchSeq(List1, &tag, fcmp_int); 
           if(index >= 0) List_PSuppress(List1, index);
-          ZeroHighlightEntityNum(0, 0, 0, tag);
+          regions[i]->setSelection(0);
         }
         break;
       }
@@ -1177,10 +1205,22 @@ static void action_point_line_surface_volume(int action, int mode, const char *w
       if(List_Nbr(List1)) {
         int num;
         List_Read(List1, List_Nbr(List1) - 1, &num);
-        ZeroHighlightEntityNum((type == ENT_POINT) ? num : 0,
-                               (type == ENT_LINE) ? num : 0,
-                               (type == ENT_SURFACE) ? num : 0,
-                               (type == ENT_VOLUME) ? num : 0);
+        if(type == ENT_POINT){
+          GVertex *gv = GModel::current()->getVertexByTag(num);
+          if(gv) gv->setSelection(0);
+        }
+        else if(type == ENT_LINE){
+          GEdge *ge = GModel::current()->getEdgeByTag(num);
+          if(ge) ge->setSelection(0);
+        }
+        else if(type == ENT_SURFACE){
+          GFace *gf = GModel::current()->getFaceByTag(num);
+          if(gf) gf->setSelection(0);
+        }
+        else if(type == ENT_VOLUME){
+          GRegion *gr = GModel::current()->getRegionByTag(num);
+          if(gr) gr->setSelection(0);
+        }
         Draw();
         List_Pop(List1);
       }
@@ -1256,13 +1296,13 @@ static void action_point_line_surface_volume(int action, int mode, const char *w
         }
         List_Reset(List1);
         GUI::instance()->resetVisibility();
-        ZeroHighlight();
+        GModel::current()->setSelection(0);
         if(action <= 6) SetBoundingBox();
         Draw();
       }
     }
     if(ib == 'q') {
-      ZeroHighlight();
+      GModel::current()->setSelection(0);
       Draw();
       break;
     }
@@ -1505,9 +1545,10 @@ static void mesh_delete_parts_cb(Fl_Widget *w, void *data)
                      "'q' to abort]", str);
     else
       Msg::StatusBar(3, false, "Select %s\n"
-          "[Press 'e' to end selection or 'q' to abort]", str);
+                     "[Press 'e' to end selection or 'q' to abort]", str);
 
-    char ib = SelectEntity(what, vertices, edges, faces, regions, elements);
+    char ib = GUI::instance()->selectEntity
+      (what, vertices, edges, faces, regions, elements);
     if(ib == 'l') {
       if(CTX.pick_elements){
         for(unsigned int i = 0; i < elements.size(); i++){
@@ -1576,7 +1617,7 @@ static void mesh_delete_parts_cb(Fl_Widget *w, void *data)
       ent.clear();
     }
     if(ib == 'q') {
-      ZeroHighlight();
+      GModel::current()->setSelection(0);
       break;
     }
   }
@@ -1611,10 +1652,11 @@ static void mesh_inspect_cb(Fl_Widget *w, void *data)
 
   while(1) {
     Msg::StatusBar(3, false, "Select element\n[Press 'q' to abort]");
-    char ib = SelectEntity(ENT_ALL, vertices, edges, faces, regions, elements);
+    char ib = GUI::instance()->selectEntity
+      (ENT_ALL, vertices, edges, faces, regions, elements);
     if(ib == 'l') {
       if(elements.size()){
-        ZeroHighlight();
+        GModel::current()->setSelection(0);
         elements[0]->setVisibility(2);
         Msg::Direct("Element %d:", elements[0]->getNum());
 	int type = elements[0]->getTypeForMSH();
@@ -1643,7 +1685,7 @@ static void mesh_inspect_cb(Fl_Widget *w, void *data)
       }
     }
     if(ib == 'q') {
-      ZeroHighlight();
+      GModel::current()->setSelection(0);
       break;
     }
   }
@@ -1745,19 +1787,23 @@ static void add_transfinite(int dim)
     case 1:
       if(p.empty())
         Msg::StatusBar(3, false, "Select lines\n"
-            "[Press 'e' to end selection or 'q' to abort]");
+                       "[Press 'e' to end selection or 'q' to abort]");
       else
         Msg::StatusBar(3, false, "Select lines\n"
-            "[Press 'e' to end selection, 'u' to undo last selection or 'q' to abort]");
-      ib = SelectEntity(ENT_LINE, vertices, edges, faces, regions, elements);
+                       "[Press 'e' to end selection, 'u' to undo last selection "
+                       "or 'q' to abort]");
+      ib = GUI::instance()->selectEntity
+        (ENT_LINE, vertices, edges, faces, regions, elements);
       break;
     case 2:
       Msg::StatusBar(3, false, "Select surface\n[Press 'q' to abort]");
-      ib = SelectEntity(ENT_SURFACE, vertices, edges, faces, regions, elements);
+      ib = GUI::instance()->selectEntity
+        (ENT_SURFACE, vertices, edges, faces, regions, elements);
       break;
     case 3:
       Msg::StatusBar(3, false, "Select volume\n[Press 'q' to abort]");
-      ib = SelectEntity(ENT_VOLUME, vertices, edges, faces, regions, elements);
+      ib = GUI::instance()->selectEntity
+        (ENT_VOLUME, vertices, edges, faces, regions, elements);
       break;
     default:
       ib = 'l';
@@ -1772,21 +1818,22 @@ static void add_transfinite(int dim)
                        GUI::instance()->meshContext->input[2]->value(),
                        GUI::instance()->meshContext->input[1]->value());
       }
-      ZeroHighlight();
+      GModel::current()->setSelection(0);
       Draw();
       p.clear();
     }
     if(ib == 'u') {
       if(dim == 1) {
         if(p.size()){
-          ZeroHighlightEntityNum(0, p.back(), 0, 0);
+          GEdge *ge = GModel::current()->getEdgeByTag(p.back());
+          if(ge) ge->setSelection(0);
           Draw();
           p.pop_back();
         }
       }
     }
     if(ib == 'q') {
-      ZeroHighlight();
+      GModel::current()->setSelection(0);
       Draw();
       break;
     }
@@ -1798,7 +1845,7 @@ static void add_transfinite(int dim)
       switch (dim) {
       case 1:
         for(unsigned int i = 0; i < edges.size(); i++){
-          HighlightEntity(edges[i]);
+          edges[i]->setSelection(1);
           p.push_back(edges[i]->tag());
         }
         Draw();
@@ -1806,12 +1853,12 @@ static void add_transfinite(int dim)
       case 2:
       case 3:
         if(dim == 2){
-          HighlightEntity(faces[0]);
+          faces[0]->setSelection(1);
           Draw();
           p.push_back(faces[0]->tag());
         }
         else{
-          HighlightEntity(regions[0]);
+          regions[0]->setSelection(1);
           Draw();
           p.push_back(regions[0]->tag());
         }
@@ -1823,15 +1870,17 @@ static void add_transfinite(int dim)
             Msg::StatusBar(3, false, "Select (ordered) boundary points\n"
                            "[Press 'e' to end selection, 'u' to undo last selection "
                            "or 'q' to abort]");
-          ib = SelectEntity(ENT_POINT, vertices, edges, faces, regions, elements);
+          ib = GUI::instance()->selectEntity
+            (ENT_POINT, vertices, edges, faces, regions, elements);
           if(ib == 'l') {
-            HighlightEntity(vertices[0]);
+            vertices[0]->setSelection(1);
             Draw();
             p.push_back(vertices[0]->tag());
           }
           if(ib == 'u') {
             if(p.size() > 1){
-              ZeroHighlightEntityNum(p.back(), 0, 0, 0);
+              GVertex *gv = GModel::current()->getVertexByTag(p.back());
+              if(gv) gv->setSelection(0);
               Draw();
               p.pop_back();
             }
@@ -1856,13 +1905,13 @@ static void add_transfinite(int dim)
                 Msg::Error("Wrong number of points for transfinite volume");
               break;
             }
-            ZeroHighlight();
+            GModel::current()->setSelection(0);
             Draw();
             p.clear();
             break;
           }
           if(ib == 'q') {
-            ZeroHighlight();
+            GModel::current()->setSelection(0);
             Draw();
             goto stopall;
           }
diff --git a/Fltk/openglWindow.cpp b/Fltk/openglWindow.cpp
index 7ddd2ac4d4..e37653d2c4 100644
--- a/Fltk/openglWindow.cpp
+++ b/Fltk/openglWindow.cpp
@@ -10,12 +10,13 @@
 #include "contextWindow.h"
 #include "GmshDefines.h"
 #include "GmshMessage.h"
+#include "GModel.h"
+#include "MElement.h"
 #include "Draw.h"
 #include "Numeric.h"
-#include "Context.h"
-#include "SelectBuffer.h"
 #include "GUI.h"
-#include "MElement.h"
+#include "VertexArray.h"
+#include "Context.h"
 
 extern Context_T CTX;
 
@@ -72,7 +73,12 @@ openglWindow::openglWindow(int x, int y, int w, int h, const char *l,
   : _ctx(ctx), Fl_Gl_Window(x, y, w, h, l)
 {
   addPointMode = lassoMode = selectionMode = false;
+  selection = ENT_NONE;
+  trySelection = quitSelection = endSelection = 0;
+  undoSelection = invertSelection = 0;
+  for(int i = 0; i < 4; i++) trySelectionXYWH[i] = 0;
   _point[0] = _point[1] = _point[2] = 0.;
+  // create default draw context if none given
   if(!_ctx) _ctx = new drawContext();
 }
 
@@ -205,15 +211,11 @@ int openglWindow::handle(int event)
         lassoMode = false;
         if(selectionMode && CTX.mouse_selection){
           // will try to select multiple entities
-          GUI::instance()->try_selection = 2;
-          GUI::instance()->try_selection_xywh[0] = 
-            (int)(_click.win[0] + _curr.win[0]) / 2;
-          GUI::instance()->try_selection_xywh[1] = 
-            (int)(_click.win[1] + _curr.win[1]) / 2;
-          GUI::instance()->try_selection_xywh[2] = 
-            (int)fabs(_click.win[0] - _curr.win[0]);
-          GUI::instance()->try_selection_xywh[3] = 
-            (int)fabs(_click.win[1] - _curr.win[1]);
+          trySelection = 2;
+          trySelectionXYWH[0] = (int)(_click.win[0] + _curr.win[0]) / 2;
+          trySelectionXYWH[1] = (int)(_click.win[1] + _curr.win[1]) / 2;
+          trySelectionXYWH[2] = (int)fabs(_click.win[0] - _curr.win[0]);
+          trySelectionXYWH[3] = (int)fabs(_click.win[1] - _curr.win[1]);
         }
         else{
           lassoZoom(_ctx, _click, _curr);
@@ -221,11 +223,11 @@ int openglWindow::handle(int event)
       }
       else if(CTX.mouse_selection){
         // will try to select clicked entity
-        GUI::instance()->try_selection = 1;
-        GUI::instance()->try_selection_xywh[0] = (int)_curr.win[0];
-        GUI::instance()->try_selection_xywh[1] = (int)_curr.win[1];
-        GUI::instance()->try_selection_xywh[2] = 5;
-        GUI::instance()->try_selection_xywh[3] = 5;
+        trySelection = 1;
+        trySelectionXYWH[0] = (int)_curr.win[0];
+        trySelectionXYWH[1] = (int)_curr.win[1];
+        trySelectionXYWH[2] = 5;
+        trySelectionXYWH[3] = 5;
       }
     }
     else if(Fl::event_button() == 2 || 
@@ -240,15 +242,11 @@ int openglWindow::handle(int event)
         lassoMode = false;
         if(selectionMode && CTX.mouse_selection){
           // will try to unselect multiple entities
-          GUI::instance()->try_selection = -2;
-          GUI::instance()->try_selection_xywh[0] = 
-            (int)(_click.win[0] + _curr.win[0]) / 2;
-          GUI::instance()->try_selection_xywh[1] =
-            (int)(_click.win[1] + _curr.win[1]) / 2;
-          GUI::instance()->try_selection_xywh[2] =
-            (int)fabs(_click.win[0] - _curr.win[0]);
-          GUI::instance()->try_selection_xywh[3] =
-            (int)fabs(_click.win[1] - _curr.win[1]);
+          trySelection = -2;
+          trySelectionXYWH[0] = (int)(_click.win[0] + _curr.win[0]) / 2;
+          trySelectionXYWH[1] = (int)(_click.win[1] + _curr.win[1]) / 2;
+          trySelectionXYWH[2] = (int)fabs(_click.win[0] - _curr.win[0]);
+          trySelectionXYWH[3] = (int)fabs(_click.win[1] - _curr.win[1]);
         }
         else{
           lassoZoom(_ctx, _click, _curr);
@@ -256,11 +254,11 @@ int openglWindow::handle(int event)
       }
       else if(CTX.mouse_selection){
         // will try to unselect clicked entity
-        GUI::instance()->try_selection = -1;
-        GUI::instance()->try_selection_xywh[0] = (int)_curr.win[0];
-        GUI::instance()->try_selection_xywh[1] = (int)_curr.win[1];
-        GUI::instance()->try_selection_xywh[2] = 5;
-        GUI::instance()->try_selection_xywh[3] = 5;
+        trySelection = -1;
+        trySelectionXYWH[0] = (int)_curr.win[0];
+        trySelectionXYWH[1] = (int)_curr.win[1];
+        trySelectionXYWH[2] = 5;
+        trySelectionXYWH[3] = 5;
       }
     }
     else {
@@ -317,19 +315,19 @@ int openglWindow::handle(int event)
       else {
         if(Fl::event_state(FL_META)) {
           // will try to select or unselect entities on the fly
-          GUI::instance()->try_selection = Fl::event_state(FL_SHIFT) ? -1 : 1; 
-          GUI::instance()->try_selection_xywh[0] = (int)_curr.win[0];
-          GUI::instance()->try_selection_xywh[1] = (int)_curr.win[1];
-          GUI::instance()->try_selection_xywh[2] = 5;
-          GUI::instance()->try_selection_xywh[3] = 5;
+          trySelection = Fl::event_state(FL_SHIFT) ? -1 : 1; 
+          trySelectionXYWH[0] = (int)_curr.win[0];
+          trySelectionXYWH[1] = (int)_curr.win[1];
+          trySelectionXYWH[2] = 5;
+          trySelectionXYWH[3] = 5;
         }
         else if(Fl::event_button() == 1 && 
                 !Fl::event_state(FL_SHIFT) && !Fl::event_state(FL_ALT)) {
           if(CTX.useTrackball)
             _ctx->addQuaternion((2. * _prev.win[0] - w()) / w(),
-                              (h() - 2. * _prev.win[1]) / h(),
-                              (2. * _curr.win[0] - w()) / w(),
-                              (h() - 2. * _curr.win[1]) / h());
+                                (h() - 2. * _prev.win[1]) / h(),
+                                (2. * _curr.win[0] - w()) / w(),
+                                (h() - 2. * _curr.win[1]) / h());
           else {
             _ctx->r[1] += ((fabs(dx) > fabs(dy)) ? 180. * dx / (double)w() : 0.);
             _ctx->r[0] += ((fabs(dx) > fabs(dy)) ? 0. : 180. * dy / (double)h());
@@ -398,21 +396,19 @@ int openglWindow::handle(int event)
     }
     else{ // hover mode
       if(_curr.win[0] != _prev.win[0] || _curr.win[1] != _prev.win[1]){
-        make_current();
         std::vector<GVertex*> vertices;
         std::vector<GEdge*> edges;
         std::vector<GFace*> faces;
         std::vector<GRegion*> regions;
         std::vector<MElement*> elements;
-        bool res = ProcessSelectionBuffer
-          (_ctx, GUI::instance()->selection, false, CTX.mouse_hover_meshes, 
-           (int)_curr.win[0], (int)_curr.win[1], 5, 5, vertices, edges, 
-           faces, regions, elements);
-        if((GUI::instance()->selection == ENT_ALL && res) ||
-           (GUI::instance()->selection == ENT_POINT && vertices.size()) ||
-           (GUI::instance()->selection == ENT_LINE && edges.size()) || 
-           (GUI::instance()->selection == ENT_SURFACE && faces.size()) ||
-           (GUI::instance()->selection == ENT_VOLUME && regions.size()))
+        bool res = processSelectionBuffer(selection, false, CTX.mouse_hover_meshes, 
+                                          (int)_curr.win[0], (int)_curr.win[1], 5, 5,
+                                          vertices, edges, faces, regions, elements);
+        if((selection == ENT_ALL && res) ||
+           (selection == ENT_POINT && vertices.size()) ||
+           (selection == ENT_LINE && edges.size()) || 
+           (selection == ENT_SURFACE && faces.size()) ||
+           (selection == ENT_VOLUME && regions.size()))
           cursor(FL_CURSOR_CROSS, FL_BLACK, FL_WHITE);
         else
           cursor(FL_CURSOR_DEFAULT, FL_BLACK, FL_WHITE);
@@ -423,8 +419,8 @@ int openglWindow::handle(int event)
         else if(regions.size()) ge = regions[0];
         MElement *me = elements.size() ? elements[0] : 0;
         Msg::StatusBar(2, false, "%s %s",
-		    ge ? ge->getInfoString().c_str() : "", 
-		    me ? me->getInfoString().c_str() : "");
+                       ge ? ge->getInfoString().c_str() : "", 
+                       me ? me->getInfoString().c_str() : "");
       }
     }
     _prev.set(_ctx);
@@ -435,26 +431,226 @@ int openglWindow::handle(int event)
   }
 }
 
-char SelectEntity(int type, 
-                  std::vector<GVertex*> &vertices,
-                  std::vector<GEdge*> &edges,
-                  std::vector<GFace*> &faces,
-                  std::vector<GRegion*> &regions,
-                  std::vector<MElement*> &elements)
+class hit{
+ public:
+  GLuint type, ient, depth, type2, ient2;
+  hit(GLuint t, GLuint i, GLuint d, GLuint t2=0, GLuint i2=0) 
+    : type(t), ient(i), depth(d), type2(t2), ient2(i2) {}
+};
+
+class hitDepthLessThan{
+ public:
+  bool operator()(const hit &h1, const hit &h2) const
+  {
+    return h1.depth < h2.depth;
+  }
+};
+
+// returns the element at a given position in a vertex array (element
+// pointers are not always stored: returning 0 is not an error)
+static MElement *getElement(GEntity *e, int va_type, int index)
+{
+  switch(va_type){
+  case 2: 
+    if(e->va_lines && index < e->va_lines->getNumElementPointers())
+      return *e->va_lines->getElementPointerArray(index);
+    break;
+  case 3:
+    if(e->va_triangles && index < e->va_triangles->getNumElementPointers())
+      return *e->va_triangles->getElementPointerArray(index);
+    break;
+  }
+  return 0;
+}
+
+bool openglWindow::processSelectionBuffer(int type, bool multipleSelection,
+                                          bool meshSelection, int x, int y, int w, int h,
+                                          std::vector<GVertex*> &vertices,
+                                          std::vector<GEdge*> &edges,
+                                          std::vector<GFace*> &faces,
+                                          std::vector<GRegion*> &regions,
+                                          std::vector<MElement*> &elements)
 {
-  if(!GUI::instance()) return 'q';
+  vertices.clear();
+  edges.clear();
+  faces.clear();
+  regions.clear();
+  elements.clear();
+
+  // In our case the selection buffer size is equal to between 5 and 7
+  // times the maximum number of possible hits
+  GModel *m = GModel::current();
+  int eles = (meshSelection && CTX.pick_elements) ? 4 * m->getNumMeshElements() : 0;
+  int size = 7 * (m->getNumVertices() + m->getNumEdges() + m->getNumFaces() + 
+                  m->getNumRegions() + eles) + 1000 ;
+
+  make_current();
+  GLuint *selectionBuffer = new GLuint[size];
+  glSelectBuffer(size, selectionBuffer);
+
+  glRenderMode(GL_SELECT);
+  _ctx->render_mode = drawContext::GMSH_SELECT;
+
+  glInitNames();
+  glPushMatrix();
+  _ctx->initProjection(x, y, w, h);
+  _ctx->initPosition();
+  _ctx->drawGeom();
+  if(meshSelection) _ctx->drawMesh();
+  glPopMatrix();
+
+  GLint numhits = glRenderMode(GL_RENDER);
+  _ctx->render_mode = drawContext::GMSH_RENDER;
+
+  if(!numhits){ // no hits
+    delete [] selectionBuffer;
+    return false;
+  }
+  else if(numhits < 0){ // overflow
+    delete [] selectionBuffer;
+    Msg::Warning("Too many entities selected");
+    return false;
+  }
+
+  std::vector<hit> hits;
+  GLuint *ptr = selectionBuffer;
+  for(int i = 0; i < numhits; i++) {
+    // in Gmsh 'names' should always be 0, 2 or 4:
+    // * names == 0 means that there is nothing on the stack
+    // * if names == 2, the first name is the type of the entity 
+    //   (0 for point, 1 for edge, 2 for face or 3 for volume) and
+    //   the second is the entity number;
+    // * if names == 4, the first name is the type of the entity,
+    //   the second is the entity number, the third is the type
+    //   of vertex array (2 for line, 3 for triangle, 4 for quad)
+    //   and the fourth is the index of the element in the vertex
+    //   array
+    GLuint names = *ptr++; 
+    *ptr++; // mindepth
+    GLuint maxdepth = *ptr++;
+    if(names == 2){
+      GLuint depth = maxdepth;
+      GLuint type = *ptr++; 
+      GLuint ient = *ptr++;
+      hits.push_back(hit(type, ient, depth));
+    }
+    else if(names == 4){
+      GLuint depth = maxdepth;
+      GLuint type = *ptr++; 
+      GLuint ient = *ptr++;
+      GLuint type2 = *ptr++; 
+      GLuint ient2 = *ptr++;
+      hits.push_back(hit(type, ient, depth, type2, ient2));
+    }
+  }
 
+  delete [] selectionBuffer;
+  
+  if(!hits.size()){ // no entities
+    return false;
+  }
+
+  // sort hits to get closest entities first
+  std::sort(hits.begin(), hits.end(), hitDepthLessThan());
+
+  // filter result: if type == ENT_NONE, return the closest entity of
+  // "lowest dimension" (point < line < surface < volume). Otherwise,
+  // return the closest entity of type "type"
+  GLuint typmin = 10;
+  for(unsigned int i = 0; i < hits.size(); i++)
+    typmin = std::min(typmin, hits[i].type);
+
+  for(unsigned int i = 0; i < hits.size(); i++) {
+    if((type == ENT_ALL) ||
+       (type == ENT_NONE && hits[i].type == typmin) ||
+       (type == ENT_POINT && hits[i].type == 0) ||
+       (type == ENT_LINE && hits[i].type == 1) ||
+       (type == ENT_SURFACE && hits[i].type == 2) ||
+       (type == ENT_VOLUME && hits[i].type == 3)){
+      switch (hits[i].type) {
+      case 0:
+        {
+          GVertex *v = m->getVertexByTag(hits[i].ient);
+          if(!v){
+            Msg::Error("Problem in point selection processing");
+            return false;
+          }
+          vertices.push_back(v);
+          if(!multipleSelection) return true;
+        }
+        break;
+      case 1:
+        {
+          GEdge *e = m->getEdgeByTag(hits[i].ient);
+          if(!e){
+            Msg::Error("Problem in line selection processing");
+            return false;
+          }
+          if(hits[i].type2){
+            MElement *ele = getElement(e, hits[i].type2, hits[i].ient2);
+            if(ele) elements.push_back(ele);
+          }
+          edges.push_back(e);
+          if(!multipleSelection) return true;
+        }
+        break;
+      case 2:
+        {
+          GFace *f = m->getFaceByTag(hits[i].ient);
+          if(!f){
+            Msg::Error("Problem in surface selection processing");
+            return false;
+          }
+          if(hits[i].type2){
+            MElement *ele = getElement(f, hits[i].type2, hits[i].ient2);
+            if(ele) elements.push_back(ele);
+          }
+          faces.push_back(f);
+          if(!multipleSelection) return true;
+        }
+        break;
+      case 3:
+        {
+          GRegion *r = m->getRegionByTag(hits[i].ient);
+          if(!r){
+            Msg::Error("Problem in volume selection processing");
+            return false;
+          }
+          if(hits[i].type2){
+            MElement *ele = getElement(r, hits[i].type2, hits[i].ient2);
+            if(ele) elements.push_back(ele);
+          }
+          regions.push_back(r);
+          if(!multipleSelection) return true;
+        }
+        break;
+      }
+    }
+  }
+
+  if(vertices.size() || edges.size() || faces.size() || 
+     regions.size() || elements.size()) 
+    return true;
+  return false;
+}
+
+char openglWindow::selectEntity(int type, 
+                                std::vector<GVertex*> &vertices,
+                                std::vector<GEdge*> &edges,
+                                std::vector<GFace*> &faces,
+                                std::vector<GRegion*> &regions,
+                                std::vector<MElement*> &elements)
+{
   // force keyboard focus in GL window 
-  GUI::instance()->graph[0]->gl->take_focus();
-  // enable lasso selection
-  GUI::instance()->graph[0]->gl->selectionMode = true;
+  take_focus();
 
-  GUI::instance()->selection = type;
-  GUI::instance()->try_selection = 0;
-  GUI::instance()->quit_selection = 0;
-  GUI::instance()->end_selection = 0;
-  GUI::instance()->undo_selection = 0;
-  GUI::instance()->invert_selection = 0;
+  selectionMode = true;
+  selection = type;
+  trySelection = 0;
+  quitSelection = 0;
+  endSelection = 0;
+  undoSelection = 0;
+  invertSelection = 0;
 
   while(1) {
     vertices.clear();
@@ -463,45 +659,41 @@ char SelectEntity(int type,
     regions.clear();
     elements.clear();
     GUI::instance()->wait();
-    if(GUI::instance()->quit_selection) {
-      GUI::instance()->selection = ENT_NONE;
-      GUI::instance()->graph[0]->gl->selectionMode = false;
-      GUI::instance()->graph[0]->gl->lassoMode = false;
-      GUI::instance()->graph[0]->gl->addPointMode = false;
-      GUI::instance()->graph[0]->gl->cursor(FL_CURSOR_DEFAULT, FL_BLACK, FL_WHITE);
+    if(quitSelection) {
+      selection = ENT_NONE;
+      selectionMode = false;
+      lassoMode = false;
+      addPointMode = false;
+      cursor(FL_CURSOR_DEFAULT, FL_BLACK, FL_WHITE);
       return 'q';
     }
-    if(GUI::instance()->end_selection) {
-      GUI::instance()->end_selection = 0;
-      GUI::instance()->selection = ENT_NONE;
+    if(endSelection) {
+      selection = ENT_NONE;
+      endSelection = 0;
       return 'e';
     }
-    if(GUI::instance()->undo_selection) {
-      GUI::instance()->undo_selection = 0;
+    if(undoSelection) {
+      undoSelection = 0;
       return 'u';
     }
-    if(GUI::instance()->invert_selection) {
-      GUI::instance()->invert_selection = 0;
+    if(invertSelection) {
+      invertSelection = 0;
       return 'i';
     }
-    if(GUI::instance()->try_selection) {
-      bool add = (GUI::instance()->try_selection > 0) ? true : false;
-      bool multi = (abs(GUI::instance()->try_selection) > 1) ? true : false;
-      GUI::instance()->try_selection = 0;
-      if(GUI::instance()->selection == ENT_NONE){ // just report the mouse click
-        GUI::instance()->graph[0]->gl->selectionMode = false;
+    if(trySelection) {
+      bool add = (trySelection > 0) ? true : false;
+      bool multi = (abs(trySelection) > 1) ? true : false;
+      trySelection = 0;
+      if(selection == ENT_NONE){ // just report the mouse click
+        selectionMode = false;
         return 'c';
       }
-      else if(ProcessSelectionBuffer
-              (GUI::instance()->graph[0]->gl->getDrawContext(),
-               GUI::instance()->selection, multi, true,
-               GUI::instance()->try_selection_xywh[0],
-               GUI::instance()->try_selection_xywh[1], 
-               GUI::instance()->try_selection_xywh[2],
-               GUI::instance()->try_selection_xywh[3], 
-               vertices, edges, faces, regions, elements)){
-        GUI::instance()->selection = ENT_NONE;
-        GUI::instance()->graph[0]->gl->selectionMode = false;
+      else if(processSelectionBuffer(selection, multi, true, trySelectionXYWH[0],
+                                     trySelectionXYWH[1], trySelectionXYWH[2],
+                                     trySelectionXYWH[3], vertices, edges, faces, 
+                                     regions, elements)){
+        selection = ENT_NONE;
+        selectionMode = false;
         if(add)
           return 'l';
         else
diff --git a/Fltk/openglWindow.h b/Fltk/openglWindow.h
index be0b060eb1..67f5d8599f 100644
--- a/Fltk/openglWindow.h
+++ b/Fltk/openglWindow.h
@@ -6,10 +6,17 @@
 #ifndef _OPENGL_WINDOW_H_
 #define _OPENGL_WINDOW_H_
 
+#include <vector>
 #include <FL/Fl_Gl_Window.H>
 #include <FL/Fl_Box.H>
 #include "drawContext.h"
 
+class GVertex;
+class GEdge;
+class GFace;
+class GRegion;
+class MElement;
+
 class mousePosition {
  public:
   double win[3]; // window coordinates
@@ -39,14 +46,28 @@ class openglWindow : public Fl_Gl_Window {
   mousePosition _click, _curr, _prev, _lasso;
   drawContext *_ctx;
   double _point[3];
+  int selection, trySelection, trySelectionXYWH[4];
   void draw();
   int handle(int);
+  bool processSelectionBuffer(int type, 
+                              bool multipleSelection, bool meshSelection,
+                              int x, int y, int w, int h,
+                              std::vector<GVertex*> &vertices,
+                              std::vector<GEdge*> &edges,
+                              std::vector<GFace*> &faces,
+                              std::vector<GRegion*> &regions,
+                              std::vector<MElement*> &elements);
  public:
   bool addPointMode, lassoMode, selectionMode;
+  int endSelection, undoSelection, invertSelection, quitSelection;
   openglWindow(int x, int y, int w, int h, const char *l=0,
                drawContext *ctx=0);
   ~openglWindow();
   drawContext *getDrawContext(){ return _ctx; }
+  char selectEntity(int type, 
+                    std::vector<GVertex*> &vertices, std::vector<GEdge*> &edges,
+                    std::vector<GFace*> &faces, std::vector<GRegion*> &regions,
+                    std::vector<MElement*> &elements);
 };
 
 #endif
diff --git a/Fltk/optionWindow.cpp b/Fltk/optionWindow.cpp
index fd3b470223..03040508fc 100644
--- a/Fltk/optionWindow.cpp
+++ b/Fltk/optionWindow.cpp
@@ -14,7 +14,6 @@
 #include "menuWindow.h"
 #include "extraDialogs.h"
 #include "Draw.h"
-#include "SelectBuffer.h"
 #include "GmshDefines.h"
 #include "GmshMessage.h"
 #include "Options.h"
@@ -174,7 +173,8 @@ static void general_options_rotation_center_select_cb(Fl_Widget *w, void *data)
   std::vector<MElement*> elements;
 
   Msg::StatusBar(3, false, "Select entity\n[Press 'q' to abort]");
-  char ib = SelectEntity(ENT_ALL, vertices, edges, faces, regions, elements);
+  char ib = GUI::instance()->selectEntity
+    (ENT_ALL, vertices, edges, faces, regions, elements);
   if(ib == 'l') {
     SPoint3 pc(0., 0., 0.);
     if(vertices.size())
@@ -193,7 +193,7 @@ static void general_options_rotation_center_select_cb(Fl_Widget *w, void *data)
     opt_general_rotation_center1(0, GMSH_SET|GMSH_GUI, pc.y());
     opt_general_rotation_center2(0, GMSH_SET|GMSH_GUI, pc.z());
   }
-  ZeroHighlight();
+  GModel::current()->setSelection(0);
   Draw();
   Msg::StatusBar(3, false, "");
 }
diff --git a/Fltk/projectionEditor.cpp b/Fltk/projectionEditor.cpp
index 5067b8e204..2a48880ab6 100644
--- a/Fltk/projectionEditor.cpp
+++ b/Fltk/projectionEditor.cpp
@@ -15,7 +15,6 @@
 #include "Draw.h"
 #include "Options.h"
 #include "StringUtils.h"
-#include "SelectBuffer.h"
 #include "fourierFace.h"
 #include "GmshMessage.h"
 #include "Context.h"
@@ -239,7 +238,8 @@ static void set_position_cb(Fl_Widget *w, void *data)
     std::vector<GFace*> faces;
     std::vector<GRegion*> regions;
     std::vector<MElement*> elements;
-    char ib = SelectEntity(ENT_ALL, vertices, edges, faces, regions, elements);
+    char ib = GUI::instance()->selectEntity
+      (ENT_ALL, vertices, edges, faces, regions, elements);
     if(ib == 'l'){
       if(vertices.size()){
         p->parameters[0]->value(vertices[0]->x());
@@ -299,7 +299,8 @@ static void select_cb(Fl_Widget *w, void *data)
       Msg::StatusBar(3, false, "Select %s\n"
 		  "[Press 'e' to end selection or 'q' to abort]", str);
 
-    char ib = SelectEntity(what, vertices, edges, faces, regions, elements);
+    char ib = GUI::instance()->selectEntity
+      (what, vertices, edges, faces, regions, elements);
     if(ib == 'l') {
       if(CTX.pick_elements){
         for(unsigned int i = 0; i < elements.size(); i++){
@@ -346,12 +347,12 @@ static void select_cb(Fl_Widget *w, void *data)
       }
     }
     if(ib == 'e') {
-      ZeroHighlight();
+      GModel::current()->setSelection(0);
       ele.clear();
       ent.clear();
     }
     if(ib == 'q') {
-      ZeroHighlight();
+      GModel::current()->setSelection(0);
       ele.clear();
       ent.clear();
       break;
@@ -696,7 +697,8 @@ static void action_cb(Fl_Widget *w, void *data)
     std::vector<GFace*> faces;
     std::vector<GRegion*> regions;
     std::vector<MElement*> elements;
-    char ib = SelectEntity(ENT_SURFACE, vertices, edges, faces, regions, elements);
+    char ib = GUI::instance()->selectEntity
+      (ENT_SURFACE, vertices, edges, faces, regions, elements);
     if(ib == 'l') faces.insert(faces.end(), faces.begin(), faces.end());
     Msg::StatusBar(3, false, "");
   }
diff --git a/Fltk/visibilityWindow.cpp b/Fltk/visibilityWindow.cpp
index 3abfd9b4e1..4d1a2ebf8f 100644
--- a/Fltk/visibilityWindow.cpp
+++ b/Fltk/visibilityWindow.cpp
@@ -17,7 +17,6 @@
 #include "GModel.h"
 #include "MElement.h"
 #include "Visibility.h"
-#include "SelectBuffer.h"
 #include "GeoStringInterface.h"
 #include "Options.h"
 #include "Context.h"
@@ -377,7 +376,8 @@ static void visibility_interactive_cb(Fl_Widget *w, void *data)
     Msg::StatusBar(3, false, "Select %s\n[Press %s'q' to abort]", 
                    help, mode ? "" : "'u' to undo or ");
 
-    char ib = SelectEntity(what, vertices, edges, faces, regions, elements);
+    char ib = GUI::instance()->selectEntity
+      (what, vertices, edges, faces, regions, elements);
     if(ib == 'l') {
       apply_visibility(mode, vertices, edges, faces, regions, elements);
       // store for possible undo later
diff --git a/Geo/GModel.cpp b/Geo/GModel.cpp
index 4b8cdcce5d..46c89b857e 100644
--- a/Geo/GModel.cpp
+++ b/Geo/GModel.cpp
@@ -899,3 +899,20 @@ int GModel::removeDuplicateMeshVertices(double tolerance)
     
   return diff;
 }
+
+void GModel::setSelection(int val)
+{
+  std::vector<GEntity*> entities;
+  getEntities(entities);
+
+  for(unsigned int i = 0; i < entities.size(); i++){
+    entities[i]->setSelection(val);
+    // reset selection in elements (stored in the visibility flag to
+    // save space)
+    if(val == 0){
+      for(int j = 0; j < entities[i]->getNumMeshElements(); j++)
+        if(entities[i]->getMeshElement(j)->getVisibility() == 2)
+          entities[i]->getMeshElement(j)->setVisibility(1);
+    }
+  }  
+}
diff --git a/Geo/GModel.h b/Geo/GModel.h
index d4379a1117..58e37304a9 100644
--- a/Geo/GModel.h
+++ b/Geo/GModel.h
@@ -192,6 +192,9 @@ class GModel
   // get the name (if any) of a given physical group
   std::string getPhysicalName(int number);
 
+  // set the selection flag on all entities
+  void setSelection(int val);
+
   // the bounding box
   SBoundingBox3d bounds();
 
diff --git a/Graphics/Makefile b/Graphics/Makefile
index ff0d12a9b5..218c2026d2 100644
--- a/Graphics/Makefile
+++ b/Graphics/Makefile
@@ -15,7 +15,6 @@ INC = ${DASH}I../Common ${DASH}I../Geo ${DASH}I../Mesh\
 CFLAGS = ${OPTIM} ${FLAGS} ${INC} ${SYSINCLUDE}
 
 SRC = Trackball.cpp \
-      SelectBuffer.cpp \
       Iso.cpp \
       ReadImg.cpp \
       drawContext.cpp \
@@ -60,21 +59,6 @@ depend:
 
 # DO NOT DELETE THIS LINE
 Trackball${OBJEXT}: Trackball.cpp Trackball.h
-SelectBuffer${OBJEXT}: SelectBuffer.cpp ../Common/GmshDefines.h \
-  ../Common/GmshMessage.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 ../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 ../Common/Context.h \
-  ../Geo/CGNSOptions.h ../Mesh/PartitionOptions.h SelectBuffer.h \
-  drawContext.h ../Common/VertexArray.h
 Iso${OBJEXT}: Iso.cpp ../Numeric/Numeric.h ../Numeric/NumericEmbedded.h
 ReadImg${OBJEXT}: ReadImg.cpp ReadImg.h ../Common/GmshMessage.h ../Post/PView.h \
   ../Geo/SPoint3.h ../Post/PViewDataList.h ../Post/PViewData.h \
diff --git a/Graphics/SelectBuffer.cpp b/Graphics/SelectBuffer.cpp
deleted file mode 100644
index 2d9b06e021..0000000000
--- a/Graphics/SelectBuffer.cpp
+++ /dev/null
@@ -1,322 +0,0 @@
-// Gmsh - Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
-//
-// See the LICENSE.txt file for license information. Please report all
-// bugs and problems to <gmsh@geuz.org>.
-
-#include <FL/gl.h>
-#include "GmshDefines.h"
-#include "GmshMessage.h"
-#include "GModel.h"
-#include "MElement.h"
-#include "Context.h"
-#include "SelectBuffer.h"
-#include "VertexArray.h"
-
-extern Context_T CTX;
-
-class hit{
- public:
-  GLuint type, ient, depth, type2, ient2;
-  hit(GLuint t, GLuint i, GLuint d, GLuint t2=0, GLuint i2=0) 
-    : type(t), ient(i), depth(d), type2(t2), ient2(i2) {}
-};
-
-class hitDepthLessThan{
- public:
-  bool operator()(const hit &h1, const hit &h2) const
-  {
-    return h1.depth < h2.depth;
-  }
-};
-
-// returns the element at a given position in a vertex array (element
-// pointers are not always stored: returning 0 is not an error)
-static MElement *getElement(GEntity *e, int va_type, int index)
-{
-  switch(va_type){
-  case 2: 
-    if(e->va_lines && index < e->va_lines->getNumElementPointers())
-      return *e->va_lines->getElementPointerArray(index);
-    break;
-  case 3:
-    if(e->va_triangles && index < e->va_triangles->getNumElementPointers())
-      return *e->va_triangles->getElementPointerArray(index);
-    break;
-  }
-  return 0;
-}
-
-bool ProcessSelectionBuffer(drawContext *ctx, int entityType,
-                            bool multipleSelection, bool meshSelection,
-                            int x, int y, int w, int h,
-                            std::vector<GVertex*> &vertices,
-                            std::vector<GEdge*> &edges,
-                            std::vector<GFace*> &faces,
-                            std::vector<GRegion*> &regions,
-                            std::vector<MElement*> &elements)
-{
-  vertices.clear();
-  edges.clear();
-  faces.clear();
-  regions.clear();
-  elements.clear();
-
-  // In our case the selection buffer size is equal to between 5 and 7
-  // times the maximum number of possible hits
-  GModel *m = GModel::current();
-  int eles = (meshSelection && CTX.pick_elements) ? 4 * m->getNumMeshElements() : 0;
-  int size = 7 * (m->getNumVertices() + m->getNumEdges() + m->getNumFaces() + 
-                  m->getNumRegions() + eles) + 1000 ;
-
-  GLuint *selectionBuffer = new GLuint[size];
-  glSelectBuffer(size, selectionBuffer);
-
-  glRenderMode(GL_SELECT);
-  ctx->render_mode = drawContext::GMSH_SELECT;
-
-  glInitNames();
-  glPushMatrix();
-  ctx->initProjection(x, y, w, h);
-  ctx->initPosition();
-  ctx->drawGeom();
-  if(meshSelection) ctx->drawMesh();
-  glPopMatrix();
-
-  GLint numhits = glRenderMode(GL_RENDER);
-  ctx->render_mode = drawContext::GMSH_RENDER;
-
-  if(!numhits){ // no hits
-    delete [] selectionBuffer;
-    return false;
-  }
-  else if(numhits < 0){ // overflow
-    delete [] selectionBuffer;
-    Msg::Warning("Too many entities selected");
-    return false;
-  }
-
-  std::vector<hit> hits;
-  GLuint *ptr = selectionBuffer;
-  for(int i = 0; i < numhits; i++) {
-    // in Gmsh 'names' should always be 0, 2 or 4:
-    // * names == 0 means that there is nothing on the stack
-    // * if names == 2, the first name is the type of the entity 
-    //   (0 for point, 1 for edge, 2 for face or 3 for volume) and
-    //   the second is the entity number;
-    // * if names == 4, the first name is the type of the entity,
-    //   the second is the entity number, the third is the type
-    //   of vertex array (2 for line, 3 for triangle, 4 for quad)
-    //   and the fourth is the index of the element in the vertex
-    //   array
-    GLuint names = *ptr++; 
-    *ptr++; // mindepth
-    GLuint maxdepth = *ptr++;
-    if(names == 2){
-      GLuint depth = maxdepth;
-      GLuint type = *ptr++; 
-      GLuint ient = *ptr++;
-      hits.push_back(hit(type, ient, depth));
-    }
-    else if(names == 4){
-      GLuint depth = maxdepth;
-      GLuint type = *ptr++; 
-      GLuint ient = *ptr++;
-      GLuint type2 = *ptr++; 
-      GLuint ient2 = *ptr++;
-      hits.push_back(hit(type, ient, depth, type2, ient2));
-    }
-  }
-
-  delete [] selectionBuffer;
-  
-  if(!hits.size()){ // no entities
-    return false;
-  }
-
-  // sort hits to get closest entities first
-  std::sort(hits.begin(), hits.end(), hitDepthLessThan());
-
-  // filter result: if entityType == ENT_NONE, return the closest
-  // entity of "lowest dimension" (point < line < surface <
-  // volume). Otherwise, return the closest entity of type
-  // "entityType"
-  GLuint typmin = 10;
-  for(unsigned int i = 0; i < hits.size(); i++)
-    typmin = std::min(typmin, hits[i].type);
-
-  for(unsigned int i = 0; i < hits.size(); i++) {
-    if((entityType == ENT_ALL) ||
-       (entityType == ENT_NONE && hits[i].type == typmin) ||
-       (entityType == ENT_POINT && hits[i].type == 0) ||
-       (entityType == ENT_LINE && hits[i].type == 1) ||
-       (entityType == ENT_SURFACE && hits[i].type == 2) ||
-       (entityType == ENT_VOLUME && hits[i].type == 3)){
-      switch (hits[i].type) {
-      case 0:
-        {
-          GVertex *v = m->getVertexByTag(hits[i].ient);
-          if(!v){
-            Msg::Error("Problem in point selection processing");
-            return false;
-          }
-          vertices.push_back(v);
-          if(!multipleSelection) return true;
-        }
-        break;
-      case 1:
-        {
-          GEdge *e = m->getEdgeByTag(hits[i].ient);
-          if(!e){
-            Msg::Error("Problem in line selection processing");
-            return false;
-          }
-          if(hits[i].type2){
-            MElement *ele = getElement(e, hits[i].type2, hits[i].ient2);
-            if(ele) elements.push_back(ele);
-          }
-          edges.push_back(e);
-          if(!multipleSelection) return true;
-        }
-        break;
-      case 2:
-        {
-          GFace *f = m->getFaceByTag(hits[i].ient);
-          if(!f){
-            Msg::Error("Problem in surface selection processing");
-            return false;
-          }
-          if(hits[i].type2){
-            MElement *ele = getElement(f, hits[i].type2, hits[i].ient2);
-            if(ele) elements.push_back(ele);
-          }
-          faces.push_back(f);
-          if(!multipleSelection) return true;
-        }
-        break;
-      case 3:
-        {
-          GRegion *r = m->getRegionByTag(hits[i].ient);
-          if(!r){
-            Msg::Error("Problem in volume selection processing");
-            return false;
-          }
-          if(hits[i].type2){
-            MElement *ele = getElement(r, hits[i].type2, hits[i].ient2);
-            if(ele) elements.push_back(ele);
-          }
-          regions.push_back(r);
-          if(!multipleSelection) return true;
-        }
-        break;
-      }
-    }
-  }
-
-  if(vertices.size() || edges.size() || faces.size() || 
-     regions.size() || elements.size()) 
-    return true;
-  return false;
-}
-
-void HighlightEntity(GEntity *e)
-{
-  e->setSelection(1);
-}
-
-void HighlightEntityNum(int v, int c, int s, int r)
-{
-  GModel *m = GModel::current();
-  if(v) {
-    GVertex *pv = m->getVertexByTag(v);
-    if(pv) HighlightEntity(pv);
-  }
-  if(c) {
-    GEdge *pc = m->getEdgeByTag(c);
-    if(pc) HighlightEntity(pc);
-  }
-  if(s) {
-    GFace *ps = m->getFaceByTag(s);
-    if(ps) HighlightEntity(ps);
-  }
-  if(r) {
-    GRegion *pr = m->getRegionByTag(r);
-    if(pr) HighlightEntity(pr);
-  }
-}
-
-void ZeroHighlightEntity(GEntity *e)
-{
-  e->setSelection(0);
-}
-
-void ZeroHighlightEntity(GVertex *v, GEdge *c, GFace *s, GRegion *r)
-{
-  if(v) ZeroHighlightEntity(v);
-  if(c) ZeroHighlightEntity(c);
-  if(s) ZeroHighlightEntity(s);
-  if(r) ZeroHighlightEntity(r);
-}
-
-void ZeroHighlightEntityNum(int v, int c, int s, int r)
-{
-  GModel *m = GModel::current();
-  if(v) {
-    GVertex *pv = m->getVertexByTag(v);
-    if(pv) ZeroHighlightEntity(pv);
-  }
-  if(c) {
-    GEdge *pc = m->getEdgeByTag(c);
-    if(pc) ZeroHighlightEntity(pc);
-  }
-  if(s) {
-    GFace *ps = m->getFaceByTag(s);
-    if(ps) ZeroHighlightEntity(ps);
-  }
-  if(r) {
-    GRegion *pr = m->getRegionByTag(r);
-    if(pr) ZeroHighlightEntity(pr);
-  }
-}
-
-void ZeroHighlight()
-{
-  GModel *m = GModel::current();
-
-  for(GModel::viter it = m->firstVertex(); it != m->lastVertex(); it++)
-    ZeroHighlightEntity(*it);
-  for(GModel::eiter it = m->firstEdge(); it != m->lastEdge(); it++)
-    ZeroHighlightEntity(*it);
-  for(GModel::fiter it = m->firstFace(); it != m->lastFace(); it++)
-    ZeroHighlightEntity(*it);
-  for(GModel::riter it = m->firstRegion(); it != m->lastRegion(); it++)
-    ZeroHighlightEntity(*it);
-
-  for(GModel::eiter it = m->firstEdge(); it != m->lastEdge(); it++){
-    for(unsigned int i = 0; i < (*it)->lines.size(); i++)
-      if((*it)->lines[i]->getVisibility() == 2)
-        (*it)->lines[i]->setVisibility(1);
-  }
-  for(GModel::fiter it = m->firstFace(); it != m->lastFace(); it++){
-    for(unsigned int i = 0; i < (*it)->triangles.size(); i++)
-      if((*it)->triangles[i]->getVisibility() == 2)
-        (*it)->triangles[i]->setVisibility(1);
-    for(unsigned int i = 0; i < (*it)->quadrangles.size(); i++)
-      if((*it)->quadrangles[i]->getVisibility() == 2) 
-        (*it)->quadrangles[i]->setVisibility(1);
-  }
-  for(GModel::riter it = m->firstRegion(); it != m->lastRegion(); it++){
-    for(unsigned int i = 0; i < (*it)->tetrahedra.size(); i++)
-      if((*it)->tetrahedra[i]->getVisibility() == 2)
-        (*it)->tetrahedra[i]->setVisibility(1);
-    for(unsigned int i = 0; i < (*it)->hexahedra.size(); i++)
-      if((*it)->hexahedra[i]->getVisibility() == 2)
-        (*it)->hexahedra[i]->setVisibility(1);
-    for(unsigned int i = 0; i < (*it)->prisms.size(); i++)
-      if((*it)->prisms[i]->getVisibility() == 2)
-        (*it)->prisms[i]->setVisibility(1);
-    for(unsigned int i = 0; i < (*it)->pyramids.size(); i++)
-      if((*it)->pyramids[i]->getVisibility() == 2)
-        (*it)->pyramids[i]->setVisibility(1);
-  }
-  
-}
diff --git a/Graphics/SelectBuffer.h b/Graphics/SelectBuffer.h
deleted file mode 100644
index 65068b1545..0000000000
--- a/Graphics/SelectBuffer.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Gmsh - Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
-//
-// See the LICENSE.txt file for license information. Please report all
-// bugs and problems to <gmsh@geuz.org>.
-
-#ifndef _SELECT_BUFFER_H_
-#define _SELECT_BUFFER_H_
-
-#include <vector>
-#include "drawContext.h"
-#include "GVertex.h"
-#include "GEdge.h"
-#include "GFace.h"
-#include "GRegion.h"
-
-class MElement;
-
-bool ProcessSelectionBuffer(drawContext *ctx, int entityType, 
-                            bool multipleSelection, bool meshSelection,
-                            int x, int y, int w, int h, 
-                            std::vector<GVertex*> &vertices,
-                            std::vector<GEdge*> &edges,
-                            std::vector<GFace*> &faces,
-                            std::vector<GRegion*> &regions,
-                            std::vector<MElement*> &elements);
-char SelectEntity(int entityType,
-                  std::vector<GVertex*> &vertices,
-                  std::vector<GEdge*> &edges,
-                  std::vector<GFace*> &faces,
-                  std::vector<GRegion*> &regions,
-                  std::vector<MElement*> &elements);
-void HighlightEntity(GEntity *e);
-void HighlightEntityNum(int v, int c, int s, int r);
-void ZeroHighlightEntity(GEntity *e);
-void ZeroHighlightEntityNum(int v, int c, int s, int r);
-void ZeroHighlight();
-
-#endif
-- 
GitLab