From c29139f82a1f57a7e7f12d99d4ceb65742f51b33 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Wed, 5 Apr 2017 22:12:36 +0200
Subject: [PATCH] interactive display of shapes before they are added + many
 improvements to the interactive workflow

---
 Common/OpenFile.cpp        |   6 +-
 Fltk/contextWindow.cpp     | 427 ++++++++++++++++++++++++++++++-------
 Fltk/graphicWindow.cpp     |   3 +
 Geo/GModelIO_OCC.cpp       | 357 ++++++++++++++++++++++++++-----
 Geo/GModelIO_OCC.h         | 112 +++++++++-
 Geo/GeoStringInterface.cpp |  26 ++-
 Geo/OCCFace.cpp            |  75 ++-----
 Graphics/drawAxes.cpp      |   2 +-
 Graphics/drawContext.cpp   |   6 +
 Graphics/drawContext.h     |   3 +
 Graphics/drawGeom.cpp      |   3 +
 Parser/Gmsh.tab.cpp        | 190 ++++++++---------
 Parser/Gmsh.y              | 190 ++++++++---------
 Parser/Parser.h            |   3 +-
 14 files changed, 1020 insertions(+), 383 deletions(-)

diff --git a/Common/OpenFile.cpp b/Common/OpenFile.cpp
index ac69c8691e..16452e4e46 100644
--- a/Common/OpenFile.cpp
+++ b/Common/OpenFile.cpp
@@ -639,7 +639,8 @@ void ClearProject()
 #if defined(HAVE_PARSER)
   gmsh_yysymbols.clear();
   gmsh_yystringsymbols.clear();
-  nameSpaces.clear();
+  gmsh_yyfactory.clear();
+  gmsh_yynamespaces.clear();
 #endif
   for(int i = GModel::list.size() - 1; i >= 0; i--)
     delete GModel::list[i];
@@ -701,7 +702,8 @@ void OpenProject(const std::string &fileName)
   for(std::map<std::string, std::string>::iterator it = cls.begin();
       it != cls.end(); it++)
     gmsh_yystringsymbols[it->first] = std::vector<std::string>(1, it->second);
-  nameSpaces.clear();
+  gmsh_yyfactory.clear();
+  gmsh_yynamespaces.clear();
   FunctionManager::Instance()->clear();
 #endif
 
diff --git a/Fltk/contextWindow.cpp b/Fltk/contextWindow.cpp
index de7574897b..b59dacccdf 100644
--- a/Fltk/contextWindow.cpp
+++ b/Fltk/contextWindow.cpp
@@ -3,6 +3,7 @@
 // See the LICENSE.txt file for license information. Please report all
 // bugs and problems to the public mailing list <gmsh@onelab.info>.
 
+#include <stdlib.h>
 #include <FL/Fl_Tabs.H>
 #include <FL/Fl_Return_Button.H>
 #include "FlGui.h"
@@ -12,6 +13,7 @@
 #include "graphicWindow.h"
 #include "openglWindow.h"
 #include "GModel.h"
+#include "GModelIO_OCC.h"
 #include "Parser.h"
 #include "GeoStringInterface.h"
 #include "OpenFile.h"
@@ -19,6 +21,65 @@
 #include "Options.h"
 #include "MallocUtils.h"
 #include "Geo.h"
+#include "VertexArray.h"
+#include "mathEvaluator.h"
+
+static bool getval(const char *str, double &val)
+{
+  // TODO: we should parse using the .geo parser instead (would allow to
+  // correctly take into account previously defined parameters) - or we could
+  // add all parser parameters in the mathEvaluator vars...
+  std::vector<std::string> expr(1), var;
+  std::vector<double> res(1), valVar;
+  expr[0] = str;
+  mathEvaluator f(expr, var);
+  if(expr.empty()) return false;
+  if(!f.eval(valVar, res)) return false;
+  val = res[0];
+  return true;
+}
+
+static void draw_stl(std::vector<SPoint3> &vertices, std::vector<SVector3> &normals,
+                     std::vector<int> &triangles)
+{
+  GLint mode[2];
+  glGetIntegerv(GL_POLYGON_MODE, mode);
+  if(CTX::instance()->geom.surfaceType > 1)
+    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+  else
+    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+  glEnable(GL_LIGHTING);
+  glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
+  glColor4ubv((GLubyte *) & CTX::instance()->color.geom.highlight[0]);
+
+  VertexArray va(3, triangles.size());
+  for(unsigned int i = 0; i < triangles.size(); i+=3){
+    SPoint3 p1 = vertices[triangles[i]];
+    SPoint3 p2 = vertices[triangles[i + 1]];
+    SPoint3 p3 = vertices[triangles[i + 2]];
+    SVector3 n1 = normals[triangles[i]];
+    SVector3 n2 = normals[triangles[i + 1]];
+    SVector3 n3 = normals[triangles[i + 2]];
+    double x[3] = {p1.x(), p2.x(), p3.x()};
+    double y[3] = {p1.y(), p2.y(), p3.y()};
+    double z[3] = {p1.z(), p2.z(), p3.z()};
+    SVector3 nn[3] = {n1, n2, n3};
+    va.add(x, y, z, nn);
+  }
+  va.finalize();
+
+  glVertexPointer(3, GL_FLOAT, 0, va.getVertexArray());
+  glEnableClientState(GL_VERTEX_ARRAY);
+  glNormalPointer(GL_BYTE, 0, va.getNormalArray());
+  glEnableClientState(GL_NORMAL_ARRAY);
+  glDisableClientState(GL_COLOR_ARRAY);
+  glDrawArrays(GL_TRIANGLES, 0, va.getNumVertices());
+  glDisableClientState(GL_VERTEX_ARRAY);
+  glDisableClientState(GL_NORMAL_ARRAY);
+
+  glDisable(GL_LIGHTING);
+  glPolygonMode(GL_FRONT_AND_BACK, mode[1]);
+}
 
 static void elementary_add_parameter_cb(Fl_Widget *w, void *data)
 {
@@ -75,6 +136,29 @@ static void elementary_add_ellipse_cb(Fl_Widget *w, void *data)
   drawContext::global()->draw();
 }
 
+static void draw_disk(void *context)
+{
+  if(!GModel::current()->getOCCInternals()) GModel::current()->createOCCInternals();
+  double xc, yc, zc, rx, ry;
+  if(!getval(FlGui::instance()->elementaryContext->input[21]->value(), xc)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[22]->value(), yc)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[23]->value(), zc)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[24]->value(), rx)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[25]->value(), ry)) return;
+  std::vector<SPoint3> vertices;
+  std::vector<SVector3> normals;
+  std::vector<int> triangles;
+  if(!GModel::current()->getOCCInternals()->makeDiskSTL
+     (xc, yc, zc, rx, ry, vertices, normals, triangles))
+    return;
+  draw_stl(vertices, normals, triangles);
+}
+
+static void elementary_draw_disk_cb(Fl_Widget *w, void *data)
+{
+  drawContext::setDrawGeomTransientFunction(draw_disk);
+}
+
 static void elementary_add_disk_cb(Fl_Widget *w, void *data)
 {
   add_disk(GModel::current()->getFileName(),
@@ -89,6 +173,30 @@ static void elementary_add_disk_cb(Fl_Widget *w, void *data)
   drawContext::global()->draw();
 }
 
+static void draw_rectangle(void *context)
+{
+  if(!GModel::current()->getOCCInternals()) GModel::current()->createOCCInternals();
+  double x, y, z, dx, dy, r;
+  if(!getval(FlGui::instance()->elementaryContext->input[26]->value(), x)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[27]->value(), y)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[28]->value(), z)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[29]->value(), dx)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[30]->value(), dy)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[31]->value(), r)) return;
+  std::vector<SPoint3> vertices;
+  std::vector<SVector3> normals;
+  std::vector<int> triangles;
+  if(!GModel::current()->getOCCInternals()->makeRectangleSTL
+     (x, y, z, dx, dy, r, vertices, normals, triangles))
+    return;
+  draw_stl(vertices, normals, triangles);
+}
+
+static void elementary_draw_rectangle_cb(Fl_Widget *w, void *data)
+{
+  drawContext::setDrawGeomTransientFunction(draw_rectangle);
+}
+
 static void elementary_add_rectangle_cb(Fl_Widget *w, void *data)
 {
   add_rectangle(GModel::current()->getFileName(),
@@ -104,6 +212,31 @@ static void elementary_add_rectangle_cb(Fl_Widget *w, void *data)
   drawContext::global()->draw();
 }
 
+static void draw_sphere(void *context)
+{
+  if(!GModel::current()->getOCCInternals()) GModel::current()->createOCCInternals();
+  double xc, yc, zc, r, angle1, angle2, angle3;
+  if(!getval(FlGui::instance()->elementaryContext->input[32]->value(), xc)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[33]->value(), yc)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[34]->value(), zc)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[35]->value(), r)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[36]->value(), angle1)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[37]->value(), angle2)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[38]->value(), angle3)) return;
+  std::vector<SPoint3> vertices;
+  std::vector<SVector3> normals;
+  std::vector<int> triangles;
+  if(!GModel::current()->getOCCInternals()->makeSphereSTL
+     (xc, yc, zc, r, angle1, angle2, angle3, vertices, normals, triangles))
+    return;
+  draw_stl(vertices, normals, triangles);
+}
+
+static void elementary_draw_sphere_cb(Fl_Widget *w, void *data)
+{
+  drawContext::setDrawGeomTransientFunction(draw_sphere);
+}
+
 static void elementary_add_sphere_cb(Fl_Widget *w, void *data)
 {
   add_sphere(GModel::current()->getFileName(),
@@ -116,10 +249,37 @@ static void elementary_add_sphere_cb(Fl_Widget *w, void *data)
              FlGui::instance()->elementaryContext->input[38]->value());
   FlGui::instance()->resetVisibility();
   GModel::current()->setSelection(0);
+  drawContext::setDrawGeomTransientFunction(0);
   SetBoundingBox();
   drawContext::global()->draw();
 }
 
+static void draw_cylinder(void *context)
+{
+  if(!GModel::current()->getOCCInternals()) GModel::current()->createOCCInternals();
+  double xc, yc, zc, dx, dy, dz, r, angle;
+  if(!getval(FlGui::instance()->elementaryContext->input[39]->value(), xc)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[40]->value(), yc)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[41]->value(), zc)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[42]->value(), dx)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[43]->value(), dy)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[44]->value(), dz)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[45]->value(), r)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[46]->value(), angle)) return;
+  std::vector<SPoint3> vertices;
+  std::vector<SVector3> normals;
+  std::vector<int> triangles;
+  if(!GModel::current()->getOCCInternals()->makeCylinderSTL
+     (xc, yc, zc, dx, dy, dz, r, angle, vertices, normals, triangles))
+    return;
+  draw_stl(vertices, normals, triangles);
+}
+
+static void elementary_draw_cylinder_cb(Fl_Widget *w, void *data)
+{
+  drawContext::setDrawGeomTransientFunction(draw_cylinder);
+}
+
 static void elementary_add_cylinder_cb(Fl_Widget *w, void *data)
 {
   add_cylinder(GModel::current()->getFileName(),
@@ -137,6 +297,30 @@ static void elementary_add_cylinder_cb(Fl_Widget *w, void *data)
   drawContext::global()->draw();
 }
 
+static void draw_block(void *context)
+{
+  if(!GModel::current()->getOCCInternals()) GModel::current()->createOCCInternals();
+  double x, y, z, dx, dy, dz;
+  if(!getval(FlGui::instance()->elementaryContext->input[47]->value(), x)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[48]->value(), y)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[49]->value(), z)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[50]->value(), dx)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[51]->value(), dy)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[52]->value(), dz)) return;
+  std::vector<SPoint3> vertices;
+  std::vector<SVector3> normals;
+  std::vector<int> triangles;
+  if(!GModel::current()->getOCCInternals()->makeBlockSTL
+     (x, y, z, dx, dy, dz, vertices, normals, triangles))
+    return;
+  draw_stl(vertices, normals, triangles);
+}
+
+static void elementary_draw_block_cb(Fl_Widget *w, void *data)
+{
+  drawContext::setDrawGeomTransientFunction(draw_block);
+}
+
 static void elementary_add_block_cb(Fl_Widget *w, void *data)
 {
   add_block(GModel::current()->getFileName(),
@@ -152,6 +336,30 @@ static void elementary_add_block_cb(Fl_Widget *w, void *data)
   drawContext::global()->draw();
 }
 
+static void draw_torus(void *context)
+{
+  if(!GModel::current()->getOCCInternals()) GModel::current()->createOCCInternals();
+  double xc, yc, zc, r1, r2, angle;
+  if(!getval(FlGui::instance()->elementaryContext->input[53]->value(), xc)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[54]->value(), yc)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[55]->value(), zc)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[56]->value(), r1)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[57]->value(), r2)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[58]->value(), angle)) return;
+  std::vector<SPoint3> vertices;
+  std::vector<SVector3> normals;
+  std::vector<int> triangles;
+  if(!GModel::current()->getOCCInternals()->makeTorusSTL
+     (xc, yc, zc, r1, r2, angle, vertices, normals, triangles))
+    return;
+  draw_stl(vertices, normals, triangles);
+}
+
+static void elementary_draw_torus_cb(Fl_Widget *w, void *data)
+{
+  drawContext::setDrawGeomTransientFunction(draw_torus);
+}
+
 static void elementary_add_torus_cb(Fl_Widget *w, void *data)
 {
   add_torus(GModel::current()->getFileName(),
@@ -167,6 +375,33 @@ static void elementary_add_torus_cb(Fl_Widget *w, void *data)
   drawContext::global()->draw();
 }
 
+static void draw_cone(void *context)
+{
+  if(!GModel::current()->getOCCInternals()) GModel::current()->createOCCInternals();
+  double xc, yc, zc, dx, dy, dz, r1, r2, angle;
+  if(!getval(FlGui::instance()->elementaryContext->input[59]->value(), xc)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[60]->value(), yc)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[61]->value(), zc)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[62]->value(), dx)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[63]->value(), dy)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[64]->value(), dz)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[65]->value(), r1)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[66]->value(), r2)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[67]->value(), angle)) return;
+  std::vector<SPoint3> vertices;
+  std::vector<SVector3> normals;
+  std::vector<int> triangles;
+  if(!GModel::current()->getOCCInternals()->makeConeSTL
+     (xc, yc, zc, dx, dy, dz, r1, r2, angle, vertices, normals, triangles))
+    return;
+  draw_stl(vertices, normals, triangles);
+}
+
+static void elementary_draw_cone_cb(Fl_Widget *w, void *data)
+{
+  drawContext::setDrawGeomTransientFunction(draw_cone);
+}
+
 static void elementary_add_cone_cb(Fl_Widget *w, void *data)
 {
   add_cone(GModel::current()->getFileName(),
@@ -185,6 +420,31 @@ static void elementary_add_cone_cb(Fl_Widget *w, void *data)
   drawContext::global()->draw();
 }
 
+static void draw_wedge(void *context)
+{
+  if(!GModel::current()->getOCCInternals()) GModel::current()->createOCCInternals();
+  double x, y, z, dx, dy, dz, ltx;
+  if(!getval(FlGui::instance()->elementaryContext->input[68]->value(), x)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[69]->value(), y)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[70]->value(), z)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[71]->value(), dx)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[72]->value(), dy)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[73]->value(), dz)) return;
+  if(!getval(FlGui::instance()->elementaryContext->input[74]->value(), ltx)) return;
+  std::vector<SPoint3> vertices;
+  std::vector<SVector3> normals;
+  std::vector<int> triangles;
+  if(!GModel::current()->getOCCInternals()->makeWedgeSTL
+     (x, y, z, dx, dy, dz, ltx, vertices, normals, triangles))
+    return;
+  draw_stl(vertices, normals, triangles);
+}
+
+static void elementary_draw_wedge_cb(Fl_Widget *w, void *data)
+{
+  drawContext::setDrawGeomTransientFunction(draw_wedge);
+}
+
 static void elementary_add_wedge_cb(Fl_Widget *w, void *data)
 {
   add_wedge(GModel::current()->getFileName(),
@@ -224,18 +484,18 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
 {
   FL_NORMAL_SIZE -= deltaFontSize;
 
-  int width = 31 * FL_NORMAL_SIZE;
-  int height = 4 * WB + 10 * BH;
+  int width = 33 * FL_NORMAL_SIZE;
+  int height = 5 * WB + 10 * BH;
 
   win = new paletteWindow(width, height, CTX::instance()->nonModalWindows ? true : false,
                           "Elementary Entity Context");
   win->box(GMSH_WINDOW_BOX);
   {
-    tab1 = new Fl_Tabs(WB, WB, width - 2 * WB, height - 2 * WB);
+    tab1 = new Fl_Tabs(WB, WB, width - 2 * WB, height - 3 * WB - BH);
     // 0: Parameter
     {
       group[0] = new Fl_Group
-        (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Parameter");
+        (WB, WB + BH, width - 2 * WB, height - 3 * WB - 2 * BH, "Parameter");
       input[0] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "Name");
       input[0]->value("lc");
       input[1] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Value");
@@ -247,7 +507,7 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
       for(int i = 0; i < 4; i++)   input[i]->align(FL_ALIGN_RIGHT);
       {
         Fl_Return_Button *o = new Fl_Return_Button
-          (width - BB - 2 * WB, height - 2 * WB - BH, BB, BH, "Add");
+          (width - BB - 2 * WB, height - 3 * WB - 2 * BH, BB, BH, "Add");
         o->callback(elementary_add_parameter_cb);
       }
       group[0]->end();
@@ -255,7 +515,7 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
     // 1: Point
     {
       group[1] = new Fl_Group
-        (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Point");
+        (WB, WB + BH, width - 2 * WB, height - 3 * WB - 2 * BH, "Point");
       input[4] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "X");
       input[4]->value("0");
       input[5] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Y");
@@ -267,22 +527,9 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
       input[7]->value("1.0");
       for(int i = 4; i < 8; i++)
         input[i]->align(FL_ALIGN_RIGHT);
-
-      for(int i = 0; i < 3; i++)
-        butt[i] = new Fl_Check_Button
-          (width - 2 * WB - IW, 2 * WB + (i+1) * BH, IW, BH, "Freeze");
-
-      value[0] = new Fl_Value_Input(2 * WB, 2 * WB + 5 * BH, IW/3, BH);
-      value[1] = new Fl_Value_Input(2 * WB + IW/3, 2 * WB + 5 * BH, IW/3, BH);
-      value[2] = new Fl_Value_Input(2 * WB + 2*IW/3, 2 * WB + 5 * BH, IW/3, BH,
-                                    "Snapping grid spacing");
-      for(int i = 0; i < 3; i++) {
-        value[i]->align(FL_ALIGN_RIGHT);
-        value[i]->callback(elementary_snap_cb);
-      }
       {
         Fl_Return_Button *o = new Fl_Return_Button
-          (width - BB - 2 * WB, height - 2 * WB - BH, BB, BH, "Add");
+          (width - BB - 2 * WB, height - 3 * WB - 2 * BH, BB, BH, "Add");
         o->callback(elementary_add_point_cb);
       }
       group[1]->end();
@@ -290,7 +537,7 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
     // 2: Circle
     {
       group[2] = new Fl_Group
-        (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Circle");
+        (WB, WB + BH, width - 2 * WB, height - 3 * WB - 2 * BH, "Circle");
       input[8] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "Center X");
       input[8]->value("0");
       input[9] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Center Y");
@@ -300,14 +547,14 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
       input[11] = new Fl_Input(2 * WB, 2 * WB + 4 * BH, IW, BH, "Radius");
       input[11]->value("1");
       input[12] = new Fl_Input(2 * WB, 2 * WB + 5 * BH, IW, BH, "Angle 1");
-      input[12]->value("");
+      input[12]->value("0");
       input[13] = new Fl_Input(2 * WB, 2 * WB + 6 * BH, IW, BH, "Angle 2");
-      input[13]->value("");
+      input[13]->value("2*Pi");
       for(int i = 8; i < 14; i++)
         input[i]->align(FL_ALIGN_RIGHT);
       {
         Fl_Return_Button *o = new Fl_Return_Button
-          (width - BB - 2 * WB, height - 2 * WB - BH, BB, BH, "Add");
+          (width - BB - 2 * WB, height - 3 * WB - 2 * BH, BB, BH, "Add");
         o->callback(elementary_add_circle_cb);
       }
       group[2]->end();
@@ -315,7 +562,7 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
     // 3: Ellipse
     {
       group[3] = new Fl_Group
-        (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Ellipse");
+        (WB, WB + BH, width - 2 * WB, height - 3 * WB - 2 * BH, "Ellipse");
       input[14] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "Center X");
       input[14]->value("0");
       input[15] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Center Y");
@@ -327,14 +574,14 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
       input[18] = new Fl_Input(2 * WB, 2 * WB + 4 * BH, IW, BH, "Radius Y");
       input[18]->value("0.5");
       input[19] = new Fl_Input(2 * WB, 2 * WB + 5 * BH, IW, BH, "Angle 1");
-      input[19]->value("");
+      input[19]->value("0");
       input[20] = new Fl_Input(2 * WB, 2 * WB + 6 * BH, IW, BH, "Angle 2");
-      input[20]->value("");
+      input[20]->value("2*Pi");
       for(int i = 14; i < 21; i++)
         input[i]->align(FL_ALIGN_RIGHT);
       {
         Fl_Return_Button *o = new Fl_Return_Button
-          (width - BB - 2 * WB, height - 2 * WB - BH, BB, BH, "Add");
+          (width - BB - 2 * WB, height - 3 * WB - 2 * BH, BB, BH, "Add");
         o->callback(elementary_add_ellipse_cb);
       }
       group[3]->end();
@@ -342,7 +589,7 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
     // 4: Disk
     {
       group[4] = new Fl_Group
-        (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Disk");
+        (WB, WB + BH, width - 2 * WB, height - 3 * WB - 2 * BH, "Disk");
       input[21] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "Center X");
       input[21]->value("0");
       input[22] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Center Y");
@@ -353,11 +600,14 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
       input[24]->value("1");
       input[25] = new Fl_Input(2 * WB, 2 * WB + 5 * BH, IW, BH, "Radius Y");
       input[25]->value("0.5");
-      for(int i = 21; i < 26; i++)
+      for(int i = 21; i < 26; i++){
         input[i]->align(FL_ALIGN_RIGHT);
+        input[i]->callback(elementary_draw_disk_cb);
+        input[i]->when(FL_WHEN_CHANGED);
+      }
       {
         Fl_Return_Button *o = new Fl_Return_Button
-          (width - BB - 2 * WB, height - 2 * WB - BH, BB, BH, "Add");
+          (width - BB - 2 * WB, height - 3 * WB - 2 * BH, BB, BH, "Add");
         o->callback(elementary_add_disk_cb);
       }
       group[4]->end();
@@ -365,7 +615,7 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
     // 5: Rectangle
     {
       group[5] = new Fl_Group
-        (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Rectangle");
+        (WB, WB + BH, width - 2 * WB, height - 3 * WB - 2 * BH, "Rectangle");
       input[26] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "X");
       input[26]->value("0");
       input[27] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Y");
@@ -377,12 +627,15 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
       input[30] = new Fl_Input(2 * WB, 2 * WB + 5 * BH, IW, BH, "DY");
       input[30]->value("0.5");
       input[31] = new Fl_Input(2 * WB, 2 * WB + 6 * BH, IW, BH, "Rounded radius");
-      input[31]->value("");
-      for(int i = 26; i < 32; i++)
+      input[31]->value("0");
+      for(int i = 26; i < 32; i++){
         input[i]->align(FL_ALIGN_RIGHT);
+        input[i]->callback(elementary_draw_rectangle_cb);
+        input[i]->when(FL_WHEN_CHANGED);
+      }
       {
         Fl_Return_Button *o = new Fl_Return_Button
-          (width - BB - 2 * WB, height - 2 * WB - BH, BB, BH, "Add");
+          (width - BB - 2 * WB, height - 3 * WB - 2 * BH, BB, BH, "Add");
         o->callback(elementary_add_rectangle_cb);
       }
       group[5]->end();
@@ -390,11 +643,11 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
     tab1->end();
   }
   {
-    tab2 = new Fl_Tabs(WB, WB, width - 2 * WB, height - 2 * WB);
+    tab2 = new Fl_Tabs(WB, WB, width - 2 * WB, height - 3 * WB - BH);
     // 6: Sphere
     {
       group[6] = new Fl_Group
-        (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Sphere");
+        (WB, WB + BH, width - 2 * WB, height - 3 * WB - 2 * BH, "Sphere");
       input[32] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "Center X");
       input[32]->value("0");
       input[33] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Center Y");
@@ -404,16 +657,19 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
       input[35] = new Fl_Input(2 * WB, 2 * WB + 4 * BH, IW, BH, "Radius");
       input[35]->value("1");
       input[36] = new Fl_Input(2 * WB, 2 * WB + 5 * BH, IW, BH, "Angle 1");
-      input[36]->value("");
+      input[36]->value("-Pi/2");
       input[37] = new Fl_Input(2 * WB, 2 * WB + 6 * BH, IW, BH, "Angle 2");
-      input[37]->value("");
+      input[37]->value("Pi/2");
       input[38] = new Fl_Input(2 * WB, 2 * WB + 7 * BH, IW, BH, "Angle 3");
-      input[38]->value("");
-      for(int i = 32; i < 39; i++)
+      input[38]->value("2*Pi");
+      for(int i = 32; i < 39; i++){
         input[i]->align(FL_ALIGN_RIGHT);
+        input[i]->callback(elementary_draw_sphere_cb);
+        input[i]->when(FL_WHEN_CHANGED);
+      }
       {
         Fl_Return_Button *o = new Fl_Return_Button
-          (width - BB - 2 * WB, height - 2 * WB - BH, BB, BH, "Add");
+          (width - BB - 2 * WB, height - 3 * WB - 2 * BH, BB, BH, "Add");
         o->callback(elementary_add_sphere_cb);
       }
       group[6]->end();
@@ -421,7 +677,7 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
     // 7: Cylinder
     {
       group[7] = new Fl_Group
-        (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Cylinder");
+        (WB, WB + BH, width - 2 * WB, height - 3 * WB - 2 * BH, "Cylinder");
       input[39] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "Center base X");
       input[39]->value("0");
       input[40] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Center base Y");
@@ -437,12 +693,15 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
       input[45] = new Fl_Input(2 * WB, 2 * WB + 7 * BH, IW, BH, "Radius");
       input[45]->value("1");
       input[46] = new Fl_Input(2 * WB, 2 * WB + 8 * BH, IW, BH, "Angle");
-      input[46]->value("");
-      for(int i = 39; i < 47; i++)
+      input[46]->value("2*Pi");
+      for(int i = 39; i < 47; i++){
         input[i]->align(FL_ALIGN_RIGHT);
+        input[i]->callback(elementary_draw_cylinder_cb);
+        input[i]->when(FL_WHEN_CHANGED);
+      }
       {
         Fl_Return_Button *o = new Fl_Return_Button
-          (width - BB - 2 * WB, height - 2 * WB - BH, BB, BH, "Add");
+          (width - BB - 2 * WB, height - 3 * WB - 2 * BH, BB, BH, "Add");
         o->callback(elementary_add_cylinder_cb);
       }
       group[7]->end();
@@ -450,7 +709,7 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
     // 8: Block
     {
       group[8] = new Fl_Group
-        (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Block");
+        (WB, WB + BH, width - 2 * WB, height - 3 * WB - 2 * BH, "Block");
       input[47] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "X");
       input[47]->value("0");
       input[48] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Y");
@@ -463,11 +722,14 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
       input[51]->value("1");
       input[52] = new Fl_Input(2 * WB, 2 * WB + 6 * BH, IW, BH, "DZ");
       input[52]->value("1");
-      for(int i = 47; i < 53; i++)
+      for(int i = 47; i < 53; i++){
         input[i]->align(FL_ALIGN_RIGHT);
+        input[i]->callback(elementary_draw_block_cb);
+        input[i]->when(FL_WHEN_CHANGED);
+      }
       {
         Fl_Return_Button *o = new Fl_Return_Button
-          (width - BB - 2 * WB, height - 2 * WB - BH, BB, BH, "Add");
+          (width - BB - 2 * WB, height - 3 * WB - 2 * BH, BB, BH, "Add");
         o->callback(elementary_add_block_cb);
       }
       group[8]->end();
@@ -476,7 +738,7 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
     // 9: Torus
     {
       group[9] = new Fl_Group
-        (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Torus");
+        (WB, WB + BH, width - 2 * WB, height - 3 * WB - 2 * BH, "Torus");
       input[53] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "Center X");
       input[53]->value("0");
       input[54] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Center Y");
@@ -488,12 +750,15 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
       input[57] = new Fl_Input(2 * WB, 2 * WB + 5 * BH, IW, BH, "Radius 2");
       input[57]->value("0.3");
       input[58] = new Fl_Input(2 * WB, 2 * WB + 6 * BH, IW, BH, "Angle");
-      input[58]->value("");
-      for(int i = 53; i < 59; i++)
+      input[58]->value("2*Pi");
+      for(int i = 53; i < 59; i++){
         input[i]->align(FL_ALIGN_RIGHT);
+        input[i]->callback(elementary_draw_torus_cb);
+        input[i]->when(FL_WHEN_CHANGED);
+      }
       {
         Fl_Return_Button *o = new Fl_Return_Button
-          (width - BB - 2 * WB, height - 2 * WB - BH, BB, BH, "Add");
+          (width - BB - 2 * WB, height - 3 * WB - 2 * BH, BB, BH, "Add");
         o->callback(elementary_add_torus_cb);
       }
       group[9]->end();
@@ -502,7 +767,7 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
     // 10: Cone
     {
       group[10] = new Fl_Group
-        (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Cone");
+        (WB, WB + BH, width - 2 * WB, height - 3 * WB - 2 * BH, "Cone");
       input[59] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "Center base X");
       input[59]->value("0");
       input[60] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Center base Y");
@@ -515,17 +780,20 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
       input[63]->value("0");
       input[64] = new Fl_Input(2 * WB, 2 * WB + 6 * BH, IW, BH, "Axis DZ");
       input[64]->value("0");
-      input[65] = new Fl_Input(2 * WB, 2 * WB + 7 * BH, IW, BH, "Radius 1");
+      input[65] = new Fl_Input(2 * WB + (width - 2 * WB)/2, 2 * WB + 4 * BH, IW, BH, "Radius 1");
       input[65]->value("0.5");
-      input[66] = new Fl_Input(2 * WB, 2 * WB + 8 * BH, IW, BH, "Radius 2");
+      input[66] = new Fl_Input(2 * WB + (width - 2 * WB)/2, 2 * WB + 5 * BH, IW, BH, "Radius 2");
       input[66]->value("0.1");
-      input[67] = new Fl_Input(2 * WB, 2 * WB + 9 * BH, IW, BH, "Angle");
-      input[67]->value("");
-      for(int i = 59; i < 68; i++)
+      input[67] = new Fl_Input(2 * WB + (width - 2 * WB)/2, 2 * WB + 6 * BH, IW, BH, "Angle");
+      input[67]->value("2*Pi");
+      for(int i = 59; i < 68; i++){
         input[i]->align(FL_ALIGN_RIGHT);
+        input[i]->callback(elementary_draw_cone_cb);
+        input[i]->when(FL_WHEN_CHANGED);
+      }
       {
         Fl_Return_Button *o = new Fl_Return_Button
-          (width - BB - 2 * WB, height - 2 * WB - BH, BB, BH, "Add");
+          (width - BB - 2 * WB, height - 3 * WB - 2 * BH, BB, BH, "Add");
         o->callback(elementary_add_cone_cb);
       }
       group[10]->end();
@@ -533,7 +801,7 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
     // 11: Wedge
     {
       group[11] = new Fl_Group
-        (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Wedge");
+        (WB, WB + BH, width - 2 * WB, height - 3 * WB - 2 * BH, "Wedge");
       input[68] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "X");
       input[68]->value("0");
       input[69] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Y");
@@ -548,11 +816,14 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
       input[73]->value("0.5");
       input[74] = new Fl_Input(2 * WB, 2 * WB + 7 * BH, IW, BH, "Top DX");
       input[74]->value("0");
-      for(int i = 68; i < 75; i++)
+      for(int i = 68; i < 75; i++){
         input[i]->align(FL_ALIGN_RIGHT);
+        input[i]->callback(elementary_draw_wedge_cb);
+        input[i]->when(FL_WHEN_CHANGED);
+      }
       {
         Fl_Return_Button *o = new Fl_Return_Button
-          (width - BB - 2 * WB, height - 2 * WB - BH, BB, BH, "Add");
+          (width - BB - 2 * WB, height - 3 * WB - 2 * BH, BB, BH, "Add");
         o->callback(elementary_add_wedge_cb);
       }
       group[11]->end();
@@ -564,6 +835,18 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize)
     Fl_Button *o = new Fl_Button(width - 4 * WB, WB, 3*WB, 3*WB, "...");
     o->callback(elementary_switch_tabs_cb);
   }
+  {
+    value[0] = new Fl_Value_Input(WB, height - WB - BH, IW/3, BH, "X");
+    value[1] = new Fl_Value_Input(WB + IW/2, height - WB - BH, IW/3, BH, "Y");
+    value[2] = new Fl_Value_Input(WB + IW, height - WB - BH, IW/3, BH, "Z snap");
+    for(int i = 0; i < 3; i++) {
+      value[i]->align(FL_ALIGN_RIGHT);
+      value[i]->callback(elementary_snap_cb);
+    }
+    butt[0] = new Fl_Check_Button(width - 6 * BH, height - WB - BH, 1.2 * BH, BH, "X");
+    butt[1] = new Fl_Check_Button(width - 6 * BH + 1.2 * BH, height - WB - BH, 1.2*BH, BH, "Y");
+    butt[2] = new Fl_Check_Button(width - 6 * BH + 2.4 * BH, height - WB - BH, (6 - 2*1.2) * BH - WB, BH, "Z freeze");
+  }
 
   tab1->show();
   tab2->hide();
@@ -587,17 +870,13 @@ void elementaryContextWindow::updatePoint(double pt[3], int which)
       char str[32];
       sprintf(str, "%g", pt[i]);
       if(which == 1){
-        input[4 + i]->value(str);
-        input[8 + i]->value(str);
-        input[14 + i]->value(str);
-        input[21 + i]->value(str);
-        input[26 + i]->value(str);
-        input[32 + i]->value(str);
-        input[39 + i]->value(str);
-        input[47 + i]->value(str);
-        input[53 + i]->value(str);
-        input[59 + i]->value(str);
-        input[68 + i]->value(str);
+        int start[11] = {4, 8, 14, 21, 26, 32, 39, 47, 53, 59, 68};
+        for(int k = 0; k < 11; k++){
+          input[start[k] + i]->value(str);
+          if(input[start[k] + i]->parent()->active()){
+            input[start[k] + i]->do_callback();
+          }
+        }
       }
     }
   }
diff --git a/Fltk/graphicWindow.cpp b/Fltk/graphicWindow.cpp
index ca4cd31b74..cdcffc4f87 100644
--- a/Fltk/graphicWindow.cpp
+++ b/Fltk/graphicWindow.cpp
@@ -631,6 +631,7 @@ void geometry_reload_cb(Fl_Widget *w, void *data)
 void geometry_remove_last_command_cb(Fl_Widget *w, void *data)
 {
   std::string fileName = GModel::current()->getFileName();
+  if(StatFile(fileName)) return;
   // FIXME: make this work with compressed files
   std::ifstream t;
   t.open(fileName.c_str(), std::ifstream::in);
@@ -659,6 +660,7 @@ void geometry_remove_last_command_cb(Fl_Widget *w, void *data)
 
 static void add_new_point_based_entity(const std::string &what, int pane)
 {
+  opt_general_axes(0, GMSH_SET | GMSH_GUI, 3);
   opt_geometry_points(0, GMSH_SET | GMSH_GUI, 1);
   drawContext::global()->draw();
 
@@ -793,6 +795,7 @@ static void add_new_point_based_entity(const std::string &what, int pane)
   }
 
   FlGui::instance()->elementaryContext->hide();
+  drawContext::setDrawGeomTransientFunction(0);
 
   // at the end, not during creation to avoid having things jumping around
   SetBoundingBox();
diff --git a/Geo/GModelIO_OCC.cpp b/Geo/GModelIO_OCC.cpp
index 03b5232928..d419d8a7ed 100644
--- a/Geo/GModelIO_OCC.cpp
+++ b/Geo/GModelIO_OCC.cpp
@@ -23,6 +23,7 @@
 #include <BRepAlgoAPI_Cut.hxx>
 #include <BRepAlgoAPI_Fuse.hxx>
 #include <BRepAlgoAPI_Section.hxx>
+#include <BRepBndLib.hxx>
 #include <BRepBuilderAPI_Copy.hxx>
 #include <BRepBuilderAPI_MakeEdge.hxx>
 #include <BRepBuilderAPI_MakeFace.hxx>
@@ -37,6 +38,7 @@
 #include <BRepFilletAPI_MakeFillet.hxx>
 #include <BRepGProp.hxx>
 #include <BRepLib.hxx>
+#include <BRepMesh_FastDiscret.hxx>
 #include <BRepOffsetAPI_MakeFilling.hxx>
 #include <BRepOffsetAPI_MakePipe.hxx>
 #include <BRepOffsetAPI_MakeThickSolid.hxx>
@@ -893,14 +895,9 @@ bool OCC_Internals::addLineLoop(int &tag, const std::vector<int> &edgeTags)
   return addWire(tag, edgeTags, true);
 }
 
-bool OCC_Internals::addRectangle(int &tag, double x, double y, double z,
-                                 double dx, double dy,  double roundedRadius)
+bool OCC_Internals::_makeRectangle(TopoDS_Face &result, double x, double y, double z,
+                                   double dx, double dy, double roundedRadius)
 {
-  if(tag >= 0 && _tagFace.IsBound(tag)){
-    Msg::Error("OpenCASCADE face with tag %d already exists", tag);
-    return false;
-  }
-  TopoDS_Face result;
   try{
     TopoDS_Wire wire;
     double x1 = x, y1 = y, z1 = z, x2 = x1 + dx, y2 = y1 + dy;
@@ -961,20 +958,31 @@ bool OCC_Internals::addRectangle(int &tag, double x, double y, double z,
     Msg::Error("OpenCASCADE exception %s", err.GetMessageString());
     return false;
   }
-  if(tag < 0) tag = getMaxTag(2) + 1;
-  bind(result, tag, true);
   return true;
 }
 
-bool OCC_Internals::addDisk(int &tag, double xc, double yc, double zc,
-                            double rx, double ry)
+bool OCC_Internals::addRectangle(int &tag, double x, double y, double z,
+                                 double dx, double dy, double roundedRadius)
 {
   if(tag >= 0 && _tagFace.IsBound(tag)){
     Msg::Error("OpenCASCADE face with tag %d already exists", tag);
     return false;
   }
-
   TopoDS_Face result;
+  if(!_makeRectangle(result, x, y, z, dx, dy, roundedRadius))
+    return false;
+  if(tag < 0) tag = getMaxTag(2) + 1;
+  bind(result, tag, true);
+  return true;
+}
+
+bool OCC_Internals::_makeDisk(TopoDS_Face &result, double xc, double yc, double zc,
+                              double rx, double ry)
+{
+  if(ry > rx){
+    Msg::Error("Major radius rx should be larger than minor radius ry");
+    return false;
+  }
   try{
     gp_Dir N_dir(0., 0., 1.);
     gp_Dir x_dir(1., 0., 0.);
@@ -989,6 +997,19 @@ bool OCC_Internals::addDisk(int &tag, double xc, double yc, double zc,
     Msg::Error("OpenCASCADE exception %s", err.GetMessageString());
     return false;
   }
+  return true;
+}
+
+bool OCC_Internals::addDisk(int &tag, double xc, double yc, double zc,
+                            double rx, double ry)
+{
+  if(tag >= 0 && _tagFace.IsBound(tag)){
+    Msg::Error("OpenCASCADE face with tag %d already exists", tag);
+    return false;
+  }
+  TopoDS_Face result;
+  if(!_makeDisk(result, xc, yc, zc, rx, ry))
+    return false;
   if(tag < 0) tag = getMaxTag(2) + 1;
   bind(result, tag, true);
   return true;
@@ -1197,16 +1218,10 @@ bool OCC_Internals::addVolume(int &tag, const std::vector<int> &shellTags)
   return true;
 }
 
-bool OCC_Internals::addSphere(int &tag, double xc, double yc, double zc,
-                              double radius, double angle1, double angle2,
-                              double angle3)
+bool OCC_Internals::_makeSphere(TopoDS_Solid &result, double xc, double yc, double zc,
+                                double radius, double angle1, double angle2,
+                                double angle3)
 {
-  if(tag >= 0 && _tagSolid.IsBound(tag)){
-    Msg::Error("OpenCASCADE region with tag %d already exists", tag);
-    return false;
-  }
-
-  TopoDS_Solid result;
   try{
     gp_Pnt p(xc, yc, zc);
     BRepPrimAPI_MakeSphere s(p, radius, angle1, angle2, angle3);
@@ -1221,20 +1236,28 @@ bool OCC_Internals::addSphere(int &tag, double xc, double yc, double zc,
     Msg::Error("OpenCASCADE exception %s", err.GetMessageString());
     return false;
   }
-  if(tag < 0) tag = getMaxTag(3) + 1;
-  bind(result, tag, true);
   return true;
 }
 
-bool OCC_Internals::addBlock(int &tag, double x, double y, double z,
-                             double dx, double dy, double dz)
+bool OCC_Internals::addSphere(int &tag, double xc, double yc, double zc,
+                              double radius, double angle1, double angle2,
+                              double angle3)
 {
   if(tag >= 0 && _tagSolid.IsBound(tag)){
     Msg::Error("OpenCASCADE region with tag %d already exists", tag);
     return false;
   }
-
   TopoDS_Solid result;
+  if(!_makeSphere(result, xc, yc, zc, radius, angle1, angle2, angle3))
+    return false;
+  if(tag < 0) tag = getMaxTag(3) + 1;
+  bind(result, tag, true);
+  return true;
+}
+
+bool OCC_Internals::_makeBlock(TopoDS_Solid &result, double x, double y, double z,
+                               double dx, double dy, double dz)
+{
   try{
     gp_Pnt P1(x, y, z);
     gp_Pnt P2(x + dx, y + dy, z + dz);
@@ -1250,25 +1273,32 @@ bool OCC_Internals::addBlock(int &tag, double x, double y, double z,
     Msg::Error("OpenCASCADE exception %s", err.GetMessageString());
     return false;
   }
-  if(tag < 0) tag = getMaxTag(3) + 1;
-  bind(result, tag, true);
   return true;
 }
 
-bool OCC_Internals::addCylinder(int &tag, double x, double y, double z,
-                                double dx, double dy, double dz, double r,
-                                double angle)
+bool OCC_Internals::addBlock(int &tag, double x, double y, double z,
+                             double dx, double dy, double dz)
 {
   if(tag >= 0 && _tagSolid.IsBound(tag)){
     Msg::Error("OpenCASCADE region with tag %d already exists", tag);
     return false;
   }
+  TopoDS_Solid result;
+  if(!_makeBlock(result, x, y, z, dx, dy, dz))
+    return false;
+  if(tag < 0) tag = getMaxTag(3) + 1;
+  bind(result, tag, true);
+  return true;
+}
+
+bool OCC_Internals::_makeCylinder(TopoDS_Solid &result, double x, double y, double z,
+                                  double dx, double dy, double dz, double r, double angle)
+{
   const double H = sqrt(dx * dx + dy * dy + dz * dz);
   if(!H){
     Msg::Error("Cannot build cylinder of zero height");
     return false;
   }
-  TopoDS_Solid result;
   try{
     gp_Pnt aP(x, y, z);
     gp_Vec aV(dx / H, dy / H, dz / H);
@@ -1285,19 +1315,28 @@ bool OCC_Internals::addCylinder(int &tag, double x, double y, double z,
     Msg::Error("OpenCASCADE exception %s", err.GetMessageString());
     return false;
   }
-  if(tag < 0) tag = getMaxTag(3) + 1;
-  bind(result, tag, true);
   return true;
 }
 
-bool OCC_Internals::addTorus(int &tag, double x, double y, double z,
-                             double r1, double r2, double angle)
+bool OCC_Internals::addCylinder(int &tag, double x, double y, double z,
+                                double dx, double dy, double dz, double r,
+                                double angle)
 {
   if(tag >= 0 && _tagSolid.IsBound(tag)){
     Msg::Error("OpenCASCADE region with tag %d already exists", tag);
     return false;
   }
   TopoDS_Solid result;
+  if(!_makeCylinder(result, x, y, z, dx, dy, dz, r, angle))
+    return false;
+  if(tag < 0) tag = getMaxTag(3) + 1;
+  bind(result, tag, true);
+  return true;
+}
+
+bool OCC_Internals::_makeTorus(TopoDS_Solid &result, double x, double y, double z,
+                               double r1, double r2, double angle)
+{
   try{
     gp_Pnt aP(x, y, z);
     gp_Vec aV(0, 0, 1);
@@ -1314,26 +1353,33 @@ bool OCC_Internals::addTorus(int &tag, double x, double y, double z,
     Msg::Error("OpenCASCADE exception %s", err.GetMessageString());
     return false;
   }
-  if(tag < 0) tag = getMaxTag(3) + 1;
-  bind(result, tag, true);
   return true;
 }
 
-bool OCC_Internals::addCone(int &tag, double x, double y, double z,
-                            double dx, double dy, double dz, double r1,
-                            double r2, double angle)
+bool OCC_Internals::addTorus(int &tag, double x, double y, double z,
+                             double r1, double r2, double angle)
 {
   if(tag >= 0 && _tagSolid.IsBound(tag)){
     Msg::Error("OpenCASCADE region with tag %d already exists", tag);
     return false;
   }
+  TopoDS_Solid result;
+  if(!_makeTorus(result, x, y, z, r1, r2, angle))
+    return false;
+  if(tag < 0) tag = getMaxTag(3) + 1;
+  bind(result, tag, true);
+  return true;
+}
 
+bool OCC_Internals::_makeCone(TopoDS_Solid &result, double x, double y, double z,
+                              double dx, double dy, double dz, double r1, double r2,
+                              double angle)
+{
   const double H = sqrt(dx * dx + dy * dy + dz * dz);
   if(!H){
     Msg::Error("Cannot build cone of zero height");
     return false;
   }
-  TopoDS_Solid result;
   try{
     gp_Pnt aP(x, y, z);
     gp_Vec aV(dx / H, dy / H, dz / H);
@@ -1350,20 +1396,28 @@ bool OCC_Internals::addCone(int &tag, double x, double y, double z,
     Msg::Error("OpenCASCADE exception %s", err.GetMessageString());
     return false;
   }
-  if(tag < 0) tag = getMaxTag(3) + 1;
-  bind(result, tag, true);
   return true;
 }
 
-bool OCC_Internals::addWedge(int &tag, double x, double y, double z,
-                             double dx, double dy, double dz, double ltx)
+bool OCC_Internals::addCone(int &tag, double x, double y, double z,
+                            double dx, double dy, double dz, double r1,
+                            double r2, double angle)
 {
   if(tag >= 0 && _tagSolid.IsBound(tag)){
     Msg::Error("OpenCASCADE region with tag %d already exists", tag);
     return false;
   }
-
   TopoDS_Solid result;
+  if(!_makeCone(result, x, y, z, dx, dy, dz, r1, r2, angle))
+    return false;
+  if(tag < 0) tag = getMaxTag(3) + 1;
+  bind(result, tag, true);
+  return true;
+}
+
+bool OCC_Internals::_makeWedge(TopoDS_Solid &result, double x, double y, double z,
+                               double dx, double dy, double dz, double ltx)
+{
   try{
     gp_Pnt aP(x, y, z);
     gp_Vec aV(0, 0, 1);
@@ -1380,6 +1434,19 @@ bool OCC_Internals::addWedge(int &tag, double x, double y, double z,
     Msg::Error("OpenCASCADE exception %s", err.GetMessageString());
     return false;
   }
+  return true;
+}
+
+bool OCC_Internals::addWedge(int &tag, double x, double y, double z,
+                             double dx, double dy, double dz, double ltx)
+{
+  if(tag >= 0 && _tagSolid.IsBound(tag)){
+    Msg::Error("OpenCASCADE region with tag %d already exists", tag);
+    return false;
+  }
+  TopoDS_Solid result;
+  if(!_makeWedge(result, x, y, z, dx, dy, dz, ltx))
+    return false;
   if(tag < 0) tag = getMaxTag(3) + 1;
   bind(result, tag, true);
   return true;
@@ -1399,7 +1466,6 @@ bool OCC_Internals::addThruSections(int tag, const std::vector<int> &wireTags,
     Msg::Error("ThruSections require at least 2 wires");
     return false;
   }
-
   TopoDS_Shape result;
   try{
     BRepOffsetAPI_ThruSections ts(makeSolid, makeRuled);
@@ -1427,7 +1493,6 @@ bool OCC_Internals::addThruSections(int tag, const std::vector<int> &wireTags,
     Msg::Error("OpenCASCADE exception %s", err.GetMessageString());
     return false;
   }
-
   bind(result, tag, outDimTags, true, true);
   return true;
 }
@@ -1441,7 +1506,6 @@ bool OCC_Internals::addThickSolid(int tag, int solidTag,
     Msg::Error("OpenCASCADE region with tag %d already exists", tag);
     return false;
   }
-
   if(!isBound(3, solidTag)){
     Msg::Error("Unknown OpenCASCADE region with tag %d", solidTag);
     return false;
@@ -1470,7 +1534,6 @@ bool OCC_Internals::addThickSolid(int tag, int solidTag,
     Msg::Error("OpenCASCADE exception %s", err.GetMessageString());
     return false;
   }
-
   bind(result, tag, outDimTags, true, true);
   return true;
 }
@@ -2916,6 +2979,198 @@ void OCC_Internals::_healShape(TopoDS_Shape &myshape, double tolerance,
   Msg::Info("-----------------------------------");
 }
 
+bool OCC_Internals::_makeFaceSTL(TopoDS_Face s,
+                                 std::vector<SPoint2> *verticesUV,
+                                 std::vector<SPoint3> *verticesXYZ,
+                                 std::vector<SVector3> *normals,
+                                 std::vector<int> &triangles)
+{
+  Bnd_Box aBox;
+  BRepBndLib::Add(s, aBox);
+
+#if (OCC_VERSION_MAJOR >= 7)
+  BRepMesh_FastDiscret::Parameters parameters;
+  parameters.Deflection = 0.1;
+  parameters.Angle = 0.35;
+  parameters.Relative = Standard_True;
+  BRepMesh_FastDiscret aMesher(aBox, parameters);
+#else
+  BRepMesh_FastDiscret aMesher(0.1, 0.35, aBox, Standard_False, Standard_False,
+                               Standard_True, Standard_False);
+#endif
+#if (OCC_VERSION_MAJOR == 6) && (OCC_VERSION_MINOR < 5)
+  aMesher.Add(s);
+#else
+  aMesher.Perform(s);
+#endif
+
+  TopLoc_Location loc;
+  Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation(s, loc);
+
+  if(triangulation.IsNull())
+    return false;
+
+  if(verticesUV && !triangulation->HasUVNodes())
+    return false;
+
+  int start = 0;
+  if(verticesUV) start = verticesUV->size();
+  if(verticesXYZ) start = verticesXYZ->size();
+  for(int i = 1; i <= triangulation->NbNodes(); i++){
+    gp_Pnt2d p = (triangulation->UVNodes())(i);
+    if(verticesUV){
+      verticesUV->push_back(SPoint2(p.X(), p.Y()));
+    }
+    if(verticesXYZ){
+      gp_Pnt pp = (triangulation->Nodes())(i);
+      verticesXYZ->push_back(SPoint3(pp.X(), pp.Y(), pp.Z()));
+    }
+    if(normals){
+      Handle(Geom_Surface) sur = BRep_Tool::Surface(s);
+      gp_Pnt pnt;
+      gp_Vec du, dv;
+      sur->D1(p.X(), p.Y(), pnt, du, dv);
+      SVector3 t1(du.X(), du.Y(), du.Z());
+      SVector3 t2(dv.X(), dv.Y(), dv.Z());
+      SVector3 n(crossprod(t1, t2));
+      n.normalize();
+      if(s.Orientation() == TopAbs_REVERSED) return n * (-1.);
+      normals->push_back(n);
+    }
+  }
+  for(int i = 1; i <= triangulation->NbTriangles(); i++){
+    Poly_Triangle triangle = (triangulation->Triangles())(i);
+    int p1, p2, p3;
+    triangle.Get(p1, p2, p3);
+    triangles.push_back(start + p1 - 1);
+    triangles.push_back(start + p2 - 1);
+    triangles.push_back(start + p3 - 1);
+  }
+  return true;
+}
+
+bool OCC_Internals::makeFaceSTL(TopoDS_Face s, std::vector<SPoint2> &vertices,
+                                std::vector<int> &triangles)
+{
+  return _makeFaceSTL(s, &vertices, 0, 0, triangles);
+}
+
+bool OCC_Internals::makeFaceSTL(TopoDS_Face s, std::vector<SPoint3> &vertices,
+                                std::vector<SVector3> &normals, std::vector<int> &triangles)
+{
+  return _makeFaceSTL(s, 0, &vertices, &normals, triangles);
+}
+
+bool OCC_Internals::makeSolidSTL(TopoDS_Solid s, std::vector<SPoint3> &vertices,
+                                 std::vector<SVector3> &normals, std::vector<int> &triangles)
+{
+  bool ret = true;
+  TopExp_Explorer exp0;
+  for(exp0.Init(s, TopAbs_FACE); exp0.More(); exp0.Next()){
+    TopoDS_Face face = TopoDS::Face(exp0.Current());
+    bool tmp = _makeFaceSTL(TopoDS::Face(face.Oriented(TopAbs_FORWARD)),
+                            0, &vertices, &normals, triangles);
+    if(!tmp) ret = false;
+  }
+  return ret;
+}
+
+bool OCC_Internals::makeRectangleSTL(double x, double y, double z, double dx, double dy,
+                                     double roundedRadius, std::vector<SPoint3> &vertices,
+                                     std::vector<SVector3> &normals, std::vector<int> &triangles)
+{
+  TopoDS_Face result;
+  if(!_makeRectangle(result, x, y, z, dx, dy, roundedRadius))
+    return false;
+  if(!makeFaceSTL(result, vertices, normals, triangles))
+    return false;
+  return true;
+}
+
+bool OCC_Internals::makeDiskSTL(double xc, double yc, double zc, double rx, double ry,
+                                std::vector<SPoint3> &vertices, std::vector<SVector3> &normals,
+                                std::vector<int> &triangles)
+{
+  TopoDS_Face result;
+  if(!_makeDisk(result, xc, yc, zc, rx, ry))
+    return false;
+  if(!makeFaceSTL(result, vertices, normals, triangles))
+    return false;
+  return true;
+}
+
+bool OCC_Internals::makeSphereSTL(double xc, double yc, double zc, double radius, double angle1,
+                                  double angle2, double angle3, std::vector<SPoint3> &vertices,
+                                  std::vector<SVector3> &normals, std::vector<int> &triangles)
+{
+  TopoDS_Solid result;
+  if(!_makeSphere(result, xc, yc, zc, radius, angle1, angle2, angle3))
+    return false;
+  if(!makeSolidSTL(result, vertices, normals, triangles))
+    return false;
+  return true;
+}
+
+bool OCC_Internals::makeBlockSTL(double x, double y, double z, double dx, double dy, double dz,
+                                 std::vector<SPoint3> &vertices, std::vector<SVector3> &normals,
+                                 std::vector<int> &triangles)
+{
+  TopoDS_Solid result;
+  if(!_makeBlock(result, x, y, z, dx, dy, dz))
+    return false;
+  if(!makeSolidSTL(result, vertices, normals, triangles))
+    return false;
+  return true;
+}
+
+bool OCC_Internals::makeCylinderSTL(double x, double y, double z, double dx, double dy, double dz,
+                                    double r, double angle, std::vector<SPoint3> &vertices,
+                                    std::vector<SVector3> &normals, std::vector<int> &triangles)
+{
+  TopoDS_Solid result;
+  if(!_makeCylinder(result, x, y, z, dx, dy, dz, r, angle))
+    return false;
+  if(!makeSolidSTL(result, vertices, normals, triangles))
+    return false;
+  return true;
+}
+
+bool OCC_Internals::makeConeSTL(double x, double y, double z, double dx, double dy, double dz,
+                                double r1, double r2, double angle, std::vector<SPoint3> &vertices,
+                                std::vector<SVector3> &normals, std::vector<int> &triangles)
+{
+  TopoDS_Solid result;
+  if(!_makeCone(result, x, y, z, dx, dy, dz, r1, r2, angle))
+    return false;
+  if(!makeSolidSTL(result, vertices, normals, triangles))
+    return false;
+  return true;
+}
+
+bool OCC_Internals::makeWedgeSTL(double x, double y, double z, double dx, double dy, double dz,
+                                 double ltx, std::vector<SPoint3> &vertices,
+                                 std::vector<SVector3> &normals, std::vector<int> &triangles)
+{
+  TopoDS_Solid result;
+  if(!_makeWedge(result, x, y, z, dx, dy, dz, ltx))
+    return false;
+  if(!makeSolidSTL(result, vertices, normals, triangles))
+    return false;
+  return true;
+}
+
+bool OCC_Internals::makeTorusSTL(double x, double y, double z, double r1, double r2, double angle,
+                                 std::vector<SPoint3> &vertices, std::vector<SVector3> &normals,
+                                 std::vector<int> &triangles)
+{
+  TopoDS_Solid result;
+  if(!_makeTorus(result, x, y, z, r1, r2, angle))
+    return false;
+  if(!makeSolidSTL(result, vertices, normals, triangles))
+    return false;
+  return true;
+}
+
 // FIXME ***************** BEGIN WILL BE REMOVED ************************
 
 void addSimpleShapes(TopoDS_Shape theShape, TopTools_ListOfShape &theList)
diff --git a/Geo/GModelIO_OCC.h b/Geo/GModelIO_OCC.h
index d36c389399..ed81c70e93 100644
--- a/Geo/GModelIO_OCC.h
+++ b/Geo/GModelIO_OCC.h
@@ -74,6 +74,32 @@ class OCC_Internals {
   // iterate on all bound entities and recompute the maximum tag
   void _recomputeMaxTag(int dim);
 
+  // make shapes
+  bool _makeRectangle(TopoDS_Face &result, double x, double y, double z,
+                    double dx, double dy, double roundedRadius=0.);
+  bool _makeDisk(TopoDS_Face &result, double xc, double yc, double zc,
+                 double rx, double ry);
+  bool _makeSphere(TopoDS_Solid &result, double xc, double yc, double zc,
+                   double radius, double angle1, double angle2, double angle3);
+  bool _makeBlock(TopoDS_Solid &result, double x, double y, double z,
+                  double dx, double dy, double dz);
+  bool _makeCylinder(TopoDS_Solid &result, double x, double y, double z,
+                   double dx, double dy, double dz, double r, double angle);
+  bool _makeCone(TopoDS_Solid &result, double x, double y, double z,
+                 double dx, double dy, double dz, double r1, double r2,
+                 double angle);
+  bool _makeWedge(TopoDS_Solid &result, double x, double y, double z,
+                  double dx, double dy, double dz, double ltx);
+  bool _makeTorus(TopoDS_Solid &result, double x, double y, double z,
+                  double r1, double r2, double angle);
+
+  // make STL triangulation of a face
+  bool _makeFaceSTL(TopoDS_Face s,
+                    std::vector<SPoint2> *verticesUV,
+                    std::vector<SPoint3> *verticesXYZ,
+                    std::vector<SVector3> *normalsXYZ,
+                    std::vector<int> &triangles);
+
   // add a shape and all its subshapes to _vmap, _emap, ..., _somap
   void _addShapeToMaps(TopoDS_Shape shape);
 
@@ -250,16 +276,48 @@ class OCC_Internals {
   // set meshing constraints
   void setMeshSize(int dim, int tag, double size);
 
-  // queries
-  bool getVertex(int tag, double &x, double &y, double &z);
-
   // synchronize internal CAD data with the given GModel
   void synchronize(GModel *model);
+
+  // queries
+  bool getVertex(int tag, double &x, double &y, double &z);
   GVertex *getVertexForOCCShape(GModel *model, TopoDS_Vertex toFind);
   GEdge *getEdgeForOCCShape(GModel *model, TopoDS_Edge toFind);
   GFace *getFaceForOCCShape(GModel *model, TopoDS_Face toFind);
   GRegion *getRegionForOCCShape(GModel *model, TopoDS_Solid toFind);
 
+  // STL utilities
+  bool makeFaceSTL(TopoDS_Face s, std::vector<SPoint2> &vertices,
+                   std::vector<int> &triangles);
+  bool makeFaceSTL(TopoDS_Face s, std::vector<SPoint3> &vertices,
+                   std::vector<SVector3> &normals, std::vector<int> &triangles);
+  bool makeSolidSTL(TopoDS_Solid s, std::vector<SPoint3> &vertices,
+                    std::vector<SVector3> &normals, std::vector<int> &triangles);
+  bool makeRectangleSTL(double x, double y, double z, double dx, double dy,
+                        double roundedRadius, std::vector<SPoint3> &vertices,
+                        std::vector<SVector3> &normals, std::vector<int> &triangles);
+  bool makeDiskSTL(double xc, double yc, double zc, double rx, double ry,
+                   std::vector<SPoint3> &vertices, std::vector<SVector3> &normals,
+                   std::vector<int> &triangles);
+  bool makeSphereSTL(double xc, double yc, double zc, double radius, double angle1,
+                     double angle2, double angle3, std::vector<SPoint3> &vertices,
+                     std::vector<SVector3> &normals, std::vector<int> &triangles);
+  bool makeBlockSTL(double x, double y, double z, double dx, double dy, double dz,
+                    std::vector<SPoint3> &vertices, std::vector<SVector3> &normals,
+                    std::vector<int> &triangles);
+  bool makeCylinderSTL(double x, double y, double z, double dx, double dy, double dz,
+                       double r, double angle, std::vector<SPoint3> &vertices,
+                       std::vector<SVector3> &normals, std::vector<int> &triangles);
+  bool makeConeSTL(double x, double y, double z, double dx, double dy, double dz,
+                   double r1, double r2, double angle, std::vector<SPoint3> &vertices,
+                   std::vector<SVector3> &normals, std::vector<int> &triangles);
+  bool makeWedgeSTL(double x, double y, double z, double dx, double dy, double dz,
+                    double ltx, std::vector<SPoint3> &vertices,
+                    std::vector<SVector3> &normals, std::vector<int> &triangles);
+  bool makeTorusSTL(double x, double y, double z, double r1, double r2, double angle,
+                    std::vector<SPoint3> &vertices, std::vector<SVector3> &normals,
+                    std::vector<int> &triangles);
+
   // *** FIXME what follows will be removed ***
  private:
   TopoDS_Shape _shape;
@@ -499,6 +557,54 @@ public:
   void setMeshSize(int dim, int tag, double size){}
   void synchronize(GModel *model){}
   bool getVertex(int tag, double &x, double &y, double &z){ return false; }
+  bool makeRectangleSTL(double x, double y, double z, double dx, double dy,
+                        double roundedRadius, std::vector<SPoint3> &vertices,
+                        std::vector<SVector3> &normals, std::vector<int> &triangles)
+  {
+    return false;
+  }
+  bool makeDiskSTL(double xc, double yc, double zc, double rx, double ry,
+                   std::vector<SPoint3> &vertices, std::vector<SVector3> &normals,
+                   std::vector<int> &triangles)
+  {
+    return false;
+  }
+  bool makeSphereSTL(double xc, double yc, double zc, double radius, double angle1,
+                     double angle2, double angle3, std::vector<SPoint3> &vertices,
+                     std::vector<SVector3> &normals, std::vector<int> &triangles)
+  {
+    return false;
+  }
+  bool makeBlockSTL(double x, double y, double z, double dx, double dy, double dz,
+                    std::vector<SPoint3> &vertices, std::vector<SVector3> &normals,
+                    std::vector<int> &triangles)
+  {
+    return false;
+  }
+  bool makeCylinderSTL(double x, double y, double z, double dx, double dy, double dz,
+                       double r, double angle, std::vector<SPoint3> &vertices,
+                       std::vector<SVector3> &normals, std::vector<int> &triangles)
+  {
+    return false;
+  }
+  bool makeConeSTL(double x, double y, double z, double dx, double dy, double dz,
+                   double r1, double r2, double angle, std::vector<SPoint3> &vertices,
+                   std::vector<SVector3> &normals, std::vector<int> &triangles)
+  {
+    return false;
+  }
+  bool makeWedgeSTL(double x, double y, double z, double dx, double dy, double dz,
+                    double ltx, std::vector<SPoint3> &vertices,
+                    std::vector<SVector3> &normals, std::vector<int> &triangles)
+  {
+    return false;
+  }
+  bool makeTorusSTL(double x, double y, double z, double r1, double r2, double angle,
+                    std::vector<SPoint3> &vertices, std::vector<SVector3> &normals,
+                    std::vector<int> &triangles)
+  {
+    return false;
+  }
 };
 
 #endif
diff --git a/Geo/GeoStringInterface.cpp b/Geo/GeoStringInterface.cpp
index 967cf8b713..0f95a53ba8 100644
--- a/Geo/GeoStringInterface.cpp
+++ b/Geo/GeoStringInterface.cpp
@@ -23,8 +23,15 @@
 #include "onelab.h"
 #endif
 
-void add_infile(const std::string &text, const std::string &fileName)
+void add_infile(const std::string &text, const std::string &fileNameOrEmpty)
 {
+  std::string fileName = fileNameOrEmpty;
+  if(fileName.empty()){
+    fileName = CTX::instance()->defaultFileName;
+    GModel::current()->setFileName(fileName);
+    GModel::current()->setName("");
+  }
+
   Msg::Debug("Adding `%s' to file `%s'", text.c_str(), fileName.c_str());
   std::vector<std::string> split = SplitFileName(fileName);
   std::string noExt = split[0] + split[1], ext = split[2];
@@ -187,6 +194,11 @@ static std::string dimTags2String(const std::vector<std::pair<int, int> > &l)
   return sstream.str();
 }
 
+static void check_occ(std::ostringstream &sstream)
+{
+  if(gmsh_yyfactory != "OpenCASCADE") sstream << "SetFactory(\"OpenCASCADE\");\n";
+}
+
 void add_charlength(const std::string &fileName, const std::vector<int> &l,
                     const std::string &lc)
 {
@@ -443,6 +455,7 @@ void add_circle(const std::string &fileName, const std::string &x, const std::st
                 const std::string &alpha2)
 {
   std::ostringstream sstream;
+  check_occ(sstream);
   sstream << "Circle(" << GModel::current()->getMaxElementaryNumber(1) + 1
           << ") = {" << x << ", " << y << ", " << z << ", " << r;
   if(alpha1.size())
@@ -458,6 +471,7 @@ void add_ellipse(const std::string &fileName, const std::string &x, const std::s
                  const std::string &alpha1, const std::string &alpha2)
 {
   std::ostringstream sstream;
+  check_occ(sstream);
   sstream << "Ellipse(" << GModel::current()->getMaxElementaryNumber(1) + 1
           << ") = {" << x << ", " << y << ", " << z << ", " << rx << ", " << ry;
   if(alpha1.size())
@@ -472,6 +486,7 @@ void add_disk(const std::string &fileName, const std::string &x, const std::stri
                 const std::string &z, const std::string &rx, const std::string &ry)
 {
   std::ostringstream sstream;
+  check_occ(sstream);
   sstream << "Disk(" << GModel::current()->getMaxElementaryNumber(2) + 1
           << ") = {" << x << ", " << y << ", " << z << ", " << rx << ", " << ry << "};";
   add_infile(sstream.str(), fileName);
@@ -482,6 +497,7 @@ void add_rectangle(const std::string &fileName, const std::string &x, const std:
                    const std::string &roundedRadius)
 {
   std::ostringstream sstream;
+  check_occ(sstream);
   sstream << "Rectangle(" << GModel::current()->getMaxElementaryNumber(2) + 1
           << ") = {" << x << ", " << y << ", " << z << ", " << dx << ", " << dy;
   if(roundedRadius.size())
@@ -495,6 +511,7 @@ void add_sphere(const std::string &fileName, const std::string &x, const std::st
                 const std::string &alpha2, const std::string &alpha3)
 {
   std::ostringstream sstream;
+  check_occ(sstream);
   sstream << "Sphere(" << GModel::current()->getMaxElementaryNumber(3) + 1
           << ") = {" << x << ", " << y << ", " << z << ", " << r;
   if(alpha1.size())
@@ -512,6 +529,7 @@ void add_cylinder(const std::string &fileName, const std::string &x, const std::
                   const std::string &dz, const std::string &r, const std::string &alpha)
 {
   std::ostringstream sstream;
+  check_occ(sstream);
   sstream << "Cylinder(" << GModel::current()->getMaxElementaryNumber(3) + 1
           << ") = {" << x << ", " << y << ", " << z << ", " << dx << ", " << dy
           << ", " << dz << ", " << r;
@@ -526,6 +544,7 @@ void add_block(const std::string &fileName, const std::string &x, const std::str
                const std::string &dz)
 {
   std::ostringstream sstream;
+  check_occ(sstream);
   sstream << "Block(" << GModel::current()->getMaxElementaryNumber(3) + 1
           << ") = {" << x << ", " << y << ", " << z << ", " << dx << ", "
           << dy << ", " << dz << "};";
@@ -537,6 +556,7 @@ void add_torus(const std::string &fileName, const std::string &x, const std::str
                const std::string &alpha)
 {
   std::ostringstream sstream;
+  check_occ(sstream);
   sstream << "Torus(" << GModel::current()->getMaxElementaryNumber(3) + 1
           << ") = {" << x << ", " << y << ", " << z << ", " << r1 << ", " << r2;
   if(alpha.size())
@@ -551,6 +571,7 @@ void add_cone(const std::string &fileName, const std::string &x, const std::stri
               const std::string &alpha)
 {
   std::ostringstream sstream;
+  check_occ(sstream);
   sstream << "Cone(" << GModel::current()->getMaxElementaryNumber(3) + 1
           << ") = {" << x << ", " << y << ", " << z << ", " << dx << ", "
           << dy << ", " << dz << ", " << r1 << ", " << r2;
@@ -565,6 +586,7 @@ void add_wedge(const std::string &fileName, const std::string &x, const std::str
                const std::string &dz, const std::string &ltx)
 {
   std::ostringstream sstream;
+  check_occ(sstream);
   sstream << "Wedge(" << GModel::current()->getMaxElementaryNumber(3) + 1
           << ") = {" << x << ", " << y << ", " << z << ", " << dx << ", " << dy
           << ", " << dz << ", " << ltx << "};";
@@ -659,6 +681,7 @@ void apply_boolean(const std::string &fileName, const std::string &op,
                    int deleteObject, int deleteTool)
 {
   std::ostringstream sstream;
+  check_occ(sstream);
   sstream << op << "{ " << dimTags2String(object);
   if(deleteObject) sstream << "Delete; ";
   sstream << "}{ " << dimTags2String(tool);
@@ -671,6 +694,7 @@ void apply_fillet(const std::string &fileName, const std::vector<int> &regions,
                   const std::vector<int> &edges, const std::string &radius)
 {
   std::ostringstream sstream;
+  check_occ(sstream);
   sstream << "Fillet{" << vector2String(regions) << "}{"
           << vector2String(edges) << "}{" << radius << "}";
   add_infile(sstream.str(), fileName);
diff --git a/Geo/OCCFace.cpp b/Geo/OCCFace.cpp
index afaf02b406..421c04eb49 100644
--- a/Geo/OCCFace.cpp
+++ b/Geo/OCCFace.cpp
@@ -18,7 +18,6 @@
 
 #include <BRepBndLib.hxx>
 #include <BRepLProp_SLProps.hxx>
-#include <BRepMesh_FastDiscret.hxx>
 #include <BRep_Builder.hxx>
 #include <Bnd_Box.hxx>
 #include <GeomAPI_ProjectPointOnSurf.hxx>
@@ -424,34 +423,8 @@ bool OCCFace::buildSTLTriangulation(bool force)
     else
       return true;
   }
-
-  Bnd_Box aBox;
-  BRepBndLib::Add(s, aBox);
-
-#if (OCC_VERSION_MAJOR >= 7)
-  BRepMesh_FastDiscret::Parameters parameters;
-  parameters.Deflection = 0.1;
-  parameters.Angle = 0.5;
-  parameters.Relative = Standard_True;
-  BRepMesh_FastDiscret aMesher(aBox, parameters);
-#else
-  BRepMesh_FastDiscret aMesher(0.1, 0.5, aBox, Standard_False, Standard_False,
-                               Standard_True, Standard_False);
-#endif
-#if (OCC_VERSION_MAJOR == 6) && (OCC_VERSION_MINOR < 5)
-  aMesher.Add(s);
-#else
-  aMesher.Perform(s);
-#endif
-
-  TopLoc_Location loc;
-  Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation(s, loc);
-
-  if(triangulation.IsNull() || !triangulation->HasUVNodes()){
-    if(triangulation.IsNull())
-      Msg::Warning("OCC STL triangulation of surface %d failed", tag());
-    else
-      Msg::Warning("OCC STL triangulation of surface %d has no u,v coordinates", tag());
+  if(!model()->getOCCInternals()->makeFaceSTL(s, stl_vertices, stl_triangles)){
+    Msg::Warning("OpenCASCADE triangulation of surface %d failed", tag());
     // add a dummy triangle so that we won't try again
     stl_vertices.push_back(SPoint2(0., 0.));
     stl_triangles.push_back(0);
@@ -460,29 +433,18 @@ bool OCCFace::buildSTLTriangulation(bool force)
     return false;
   }
 
-  for(int i = 1; i <= triangulation->NbNodes(); i++){
-    gp_Pnt2d p = (triangulation->UVNodes())(i);
-    stl_vertices.push_back(SPoint2(p.X(), p.Y()));
-  }
-
   bool reverse = false;
-  for(int i = 1; i <= triangulation->NbTriangles(); i++){
-    Poly_Triangle triangle = (triangulation->Triangles())(i);
-    int p1, p2, p3;
-    triangle.Get(p1, p2, p3);
-
-    // orient STL mesh to get normal right
-    if(i == 1){
-      gp_Pnt2d gp1 = (triangulation->UVNodes())(p1);
-      gp_Pnt2d gp2 = (triangulation->UVNodes())(p2);
-      gp_Pnt2d gp3 = (triangulation->UVNodes())(p3);
-      SPoint2 b = SPoint2(gp1.X(), gp1.Y()) + SPoint2(gp2.X(), gp2.Y()) +
-        SPoint2(gp3.X(), gp3.Y());
+  for(unsigned int i = 0; i < stl_triangles.size(); i += 3){
+    if(i == 0){
+      SPoint2 gp1 = stl_vertices[stl_triangles[i]];
+      SPoint2 gp2 = stl_vertices[stl_triangles[i + 1]];
+      SPoint2 gp3 = stl_vertices[stl_triangles[i + 2]];
+      SPoint2 b = gp1 + gp2 + gp2;
       b *= 1. / 3.;
       SVector3 nf = normal(b);
-      GPoint sp1 = point(gp1.X(), gp1.Y());
-      GPoint sp2 = point(gp2.X(), gp2.Y());
-      GPoint sp3 = point(gp3.X(), gp3.Y());
+      GPoint sp1 = point(gp1.x(), gp1.y());
+      GPoint sp2 = point(gp2.x(), gp2.y());
+      GPoint sp3 = point(gp3.x(), gp3.y());
       double n[3];
       normal3points(sp1.x(), sp1.y(), sp1.z(),
                     sp2.x(), sp2.y(), sp2.z(),
@@ -493,19 +455,12 @@ bool OCCFace::buildSTLTriangulation(bool force)
         reverse = true;
       }
     }
-
-    if(!reverse){
-      stl_triangles.push_back(p1 - 1);
-      stl_triangles.push_back(p2 - 1);
-      stl_triangles.push_back(p3 - 1);
-    }
-    else{
-      stl_triangles.push_back(p1 - 1);
-      stl_triangles.push_back(p3 - 1);
-      stl_triangles.push_back(p2 - 1);
+    if(reverse){
+      int tmp = stl_triangles[i + 1];
+      stl_triangles[i + 1] = stl_triangles[i + 2];
+      stl_triangles[i + 2] = tmp;
     }
   }
-
   return true;
 }
 
diff --git a/Graphics/drawAxes.cpp b/Graphics/drawAxes.cpp
index 9dbc3308bb..28f8e13fd3 100644
--- a/Graphics/drawAxes.cpp
+++ b/Graphics/drawAxes.cpp
@@ -326,7 +326,7 @@ void drawContext::drawAxes()
                CTX::instance()->axesForceValue ? CTX::instance()->axesValue :
                CTX::instance()->axesPosition);
     }
-    else if(geometryExists){
+    else{
       double bb[6] =
         {CTX::instance()->min[0], CTX::instance()->max[0], CTX::instance()->min[1],
          CTX::instance()->max[1], CTX::instance()->min[2], CTX::instance()->max[2]};
diff --git a/Graphics/drawContext.cpp b/Graphics/drawContext.cpp
index 22c4b6ba6c..9bc6e0e41d 100644
--- a/Graphics/drawContext.cpp
+++ b/Graphics/drawContext.cpp
@@ -33,6 +33,12 @@
 #endif
 
 drawContextGlobal *drawContext::_global = 0;
+void (*drawContext::drawGeomTransient)(void*) = 0;
+
+void drawContext::setDrawGeomTransientFunction(void (*fct)(void *))
+{
+  drawGeomTransient = fct;
+}
 
 extern SPoint2 getGraph2dDataPointForTag(unsigned int);
 
diff --git a/Graphics/drawContext.h b/Graphics/drawContext.h
index 8556be92a5..122caf2f61 100644
--- a/Graphics/drawContext.h
+++ b/Graphics/drawContext.h
@@ -255,6 +255,9 @@ class drawContext {
                               double xmax, double ymax, double zmax,
                               double a, double b, double c, double d,
                               int shade=0);
+  // dynamic pointer to a transient geometry drawing function
+  static void setDrawGeomTransientFunction(void (*fct)(void *));
+  static void (*drawGeomTransient)(void*);
 };
 
 class mousePosition {
diff --git a/Graphics/drawGeom.cpp b/Graphics/drawGeom.cpp
index a908118c7d..67cf4f25f1 100644
--- a/Graphics/drawGeom.cpp
+++ b/Graphics/drawGeom.cpp
@@ -533,6 +533,9 @@ void drawContext::drawGeom()
 {
   if(!CTX::instance()->geom.draw) return;
 
+  // draw any transient geometry stuff
+  if(drawGeomTransient) (*drawGeomTransient)(this);
+
   for(int i = 0; i < 6; i++)
     if(CTX::instance()->geom.clip & (1 << i))
       glEnable((GLenum)(GL_CLIP_PLANE0 + i));
diff --git a/Parser/Gmsh.tab.cpp b/Parser/Gmsh.tab.cpp
index a596bd6c64..05ae28cf93 100644
--- a/Parser/Gmsh.tab.cpp
+++ b/Parser/Gmsh.tab.cpp
@@ -599,7 +599,8 @@ int gmsh_yyerrorstate = 0;
 int gmsh_yyviewindex = 0;
 std::map<std::string, gmsh_yysymbol> gmsh_yysymbols;
 std::map<std::string, std::vector<std::string> > gmsh_yystringsymbols;
-NameSpaces nameSpaces;
+std::string gmsh_yyfactory;
+NameSpaces gmsh_yynamespaces;
 
 // static parser variables (accessible only in this file)
 #if defined(HAVE_POST)
@@ -616,7 +617,6 @@ static gmshfpos_t yyposImbricatedLoopsTab[MAX_RECUR_LOOPS];
 static int yylinenoImbricatedLoopsTab[MAX_RECUR_LOOPS];
 static double LoopControlVariablesTab[MAX_RECUR_LOOPS][3];
 static std::string LoopControlVariablesNameTab[MAX_RECUR_LOOPS];
-static std::string factory;
 static std::string struct_name, struct_namespace;
 static int flag_tSTRING_alloc = 0;
 
@@ -6522,8 +6522,8 @@ yyreduce:
   case 9:
 #line 281 "Gmsh.y"
     {
-      factory = (yyvsp[(3) - (5)].c);
-      if(factory == "OpenCASCADE"){
+      gmsh_yyfactory = (yyvsp[(3) - (5)].c);
+      if(gmsh_yyfactory == "OpenCASCADE"){
         if(!GModel::current()->getOCCInternals())
           GModel::current()->createOCCInternals();
         for(int dim = -2; dim <= 3; dim++)
@@ -8108,7 +8108,7 @@ yyreduce:
       double lc = CTX::instance()->geom.scalingFactor * (yyvsp[(6) - (7)].v)[3];
       if(lc == 0.) lc = MAX_LC; // no mesh size given at the point
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->addVertex(num, x, y, z, lc);
       }
       else{
@@ -8131,7 +8131,7 @@ yyreduce:
       int num = (int)(yyvsp[(3) - (7)].d);
       std::vector<int> tags; ListOfDouble2Vector((yyvsp[(6) - (7)].l), tags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->addLine(num, tags);
       }
       else{
@@ -8150,7 +8150,7 @@ yyreduce:
       int num = (int)(yyvsp[(3) - (7)].d);
       std::vector<int> tags; ListOfDouble2Vector((yyvsp[(6) - (7)].l), tags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->addSpline(num, tags);
       }
       else{
@@ -8170,7 +8170,7 @@ yyreduce:
       std::vector<int> tags; ListOfDouble2Vector((yyvsp[(6) - (8)].l), tags);
       std::vector<double> param; ListOfDouble2Vector((yyvsp[(6) - (8)].l), param);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         if(tags.size() == 3){
           r = GModel::current()->getOCCInternals()->addCircleArc
             (num, tags[0], tags[1], tags[2]);
@@ -8210,7 +8210,7 @@ yyreduce:
       std::vector<int> tags; ListOfDouble2Vector((yyvsp[(6) - (8)].l), tags);
       std::vector<double> param; ListOfDouble2Vector((yyvsp[(6) - (8)].l), param);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         if(tags.size() == 3){
           r = GModel::current()->getOCCInternals()->addEllipseArc
             (num, tags[0], tags[1], tags[2]);
@@ -8252,8 +8252,8 @@ yyreduce:
       int num = (int)(yyvsp[(3) - (7)].d);
       std::vector<int> tags; ListOfDouble2Vector((yyvsp[(6) - (7)].l), tags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
-        yymsg(0, "BSpline not yet available with OpenCASCADE factory");
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+        yymsg(0, "BSpline not yet available with OpenCASCADE geometry kernel");
       }
       else{
         r = GModel::current()->getGEOInternals()->addBSpline(num, tags);
@@ -8271,7 +8271,7 @@ yyreduce:
       int num = (int)(yyvsp[(3) - (7)].d);
       std::vector<int> tags; ListOfDouble2Vector((yyvsp[(6) - (7)].l), tags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->addBezier(num, tags);
       }
       else{
@@ -8291,8 +8291,8 @@ yyreduce:
       std::vector<int> tags; ListOfDouble2Vector((yyvsp[(6) - (11)].l), tags);
       std::vector<double> knots; ListOfDouble2Vector((yyvsp[(8) - (11)].l), knots);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
-        yymsg(0, "Nurbs not available yet with OpenCASCADE factory");
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+        yymsg(0, "Nurbs not available yet with OpenCASCADE geometry kernel");
       }
       else{
         int order = knots.size() - tags.size() - 1;
@@ -8327,11 +8327,11 @@ yyreduce:
       int num = (int)(yyvsp[(3) - (7)].d);
       std::vector<int> tags; ListOfDouble2Vector((yyvsp[(6) - (7)].l), tags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->addWire(num, tags, false);
       }
       else{
-        yymsg(0, "Wire only available using OpenCASCADE factory");
+        yymsg(0, "Wire only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add wire");
       List_Delete((yyvsp[(6) - (7)].l));
@@ -8346,7 +8346,7 @@ yyreduce:
       int num = (int)(yyvsp[(4) - (8)].d);
       std::vector<int> tags; ListOfDouble2Vector((yyvsp[(7) - (8)].l), tags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         for(unsigned int i = 0; i < tags.size(); i++)
           tags[i] = std::abs(tags[i]); // all edge tags > 0 for OCC
         r = GModel::current()->getOCCInternals()->addLineLoop(num, tags);
@@ -8368,7 +8368,7 @@ yyreduce:
       int num = (int)(yyvsp[(4) - (8)].d);
       std::vector<int> tags; ListOfDouble2Vector((yyvsp[(7) - (8)].l), tags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->addPlaneSurface(num, tags);
       }
       else{
@@ -8387,7 +8387,7 @@ yyreduce:
       int num = (int)(yyvsp[(3) - (8)].d);
       std::vector<int> wires; ListOfDouble2Vector((yyvsp[(6) - (8)].l), wires);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         if(wires.size() != 1){
           yymsg(0, "OpenCASCADE face filling requires a single line loop");
         }
@@ -8456,7 +8456,7 @@ yyreduce:
       (yyval.s).Type = 0;
       bool r = true;
       if(param.size() >= 4 && param.size() <= 7){
-        if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+        if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
           double a1 = (param.size() >= 5) ? param[4] : -M_PI/2;
           double a2 = (param.size() >= 6) ? param[5] : M_PI/2;
           double a3 = (param.size() >= 7) ? param[6] : 2.*M_PI;
@@ -8464,7 +8464,7 @@ yyreduce:
             (num, param[0], param[1], param[2], param[3], a1, a2, a3);
         }
         else{
-          yymsg(0, "Sphere only available with OpenCASCADE factory");
+          yymsg(0, "Sphere only available with OpenCASCADE geometry kernel");
         }
         (yyval.s).Type = MSH_VOLUME;
       }
@@ -8505,7 +8505,7 @@ yyreduce:
       int num = (int)(yyvsp[(3) - (7)].d);
       std::vector<double> param; ListOfDouble2Vector((yyvsp[(6) - (7)].l), param);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         if(param.size() == 6){
           r = GModel::current()->getOCCInternals()->addBlock
             (num, param[0], param[1], param[2], param[3], param[4], param[5]);
@@ -8515,7 +8515,7 @@ yyreduce:
         }
       }
       else{
-        yymsg(0, "Block only available with OpenCASCADE factory");
+        yymsg(0, "Block only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add block");
       List_Delete((yyvsp[(6) - (7)].l));
@@ -8530,7 +8530,7 @@ yyreduce:
       int num = (int)(yyvsp[(3) - (7)].d);
       std::vector<double> param; ListOfDouble2Vector((yyvsp[(6) - (7)].l), param);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         if(param.size() == 5 || param.size() == 6){
           double alpha = (param.size() == 6) ? param[5] : 2*M_PI;
           r = GModel::current()->getOCCInternals()->addTorus
@@ -8541,7 +8541,7 @@ yyreduce:
         }
       }
       else{
-        yymsg(0, "Torus only available with OpenCASCADE factory");
+        yymsg(0, "Torus only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add torus");
       List_Delete((yyvsp[(6) - (7)].l));
@@ -8556,7 +8556,7 @@ yyreduce:
       int num = (int)(yyvsp[(3) - (7)].d);
       std::vector<double> param; ListOfDouble2Vector((yyvsp[(6) - (7)].l), param);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         if(param.size() == 5 || param.size() == 6){
           double r = (param.size() == 6) ? param[5] : 0.;
           r = GModel::current()->getOCCInternals()->addRectangle
@@ -8567,7 +8567,7 @@ yyreduce:
         }
       }
       else{
-        yymsg(0, "Rectangle only available with OpenCASCADE factory");
+        yymsg(0, "Rectangle only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add rectangle");
       List_Delete((yyvsp[(6) - (7)].l));
@@ -8582,7 +8582,7 @@ yyreduce:
       int num = (int)(yyvsp[(3) - (7)].d);
       std::vector<double> param; ListOfDouble2Vector((yyvsp[(6) - (7)].l), param);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         if(param.size() == 4 || param.size() == 5){
           double ry = (param.size() == 5) ? param[4] : param[3];
           r = GModel::current()->getOCCInternals()->addDisk
@@ -8593,7 +8593,7 @@ yyreduce:
         }
       }
       else{
-        yymsg(0, "Disk only available with OpenCASCADE factory");
+        yymsg(0, "Disk only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add disk");
       List_Delete((yyvsp[(6) - (7)].l));
@@ -8608,7 +8608,7 @@ yyreduce:
       int num = (int)(yyvsp[(3) - (7)].d);
       std::vector<double> param; ListOfDouble2Vector((yyvsp[(6) - (7)].l), param);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         if(param.size() == 7 || param.size() == 8){
           double angle = (param.size() == 8) ? param[7] : 2*M_PI;
           r = GModel::current()->getOCCInternals()->addCylinder
@@ -8620,7 +8620,7 @@ yyreduce:
         }
       }
       else{
-        yymsg(0, "Cylinder only available with OpenCASCADE factory");
+        yymsg(0, "Cylinder only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add cylinder");
       List_Delete((yyvsp[(6) - (7)].l));
@@ -8635,7 +8635,7 @@ yyreduce:
       int num = (int)(yyvsp[(3) - (7)].d);
       std::vector<double> param; ListOfDouble2Vector((yyvsp[(6) - (7)].l), param);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         if(param.size() == 8 || param.size() == 9){
           double alpha = (param.size() == 9) ? param[8] : 2*M_PI;
           r = GModel::current()->getOCCInternals()->addCone
@@ -8647,7 +8647,7 @@ yyreduce:
         }
       }
       else{
-        yymsg(0, "Cone only available with OpenCASCADE factory");
+        yymsg(0, "Cone only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add cone");
       List_Delete((yyvsp[(6) - (7)].l));
@@ -8662,7 +8662,7 @@ yyreduce:
       int num = (int)(yyvsp[(3) - (7)].d);
       std::vector<double> param; ListOfDouble2Vector((yyvsp[(6) - (7)].l), param);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         if(param.size() == 6 || param.size() == 7){
           double ltx = (param.size() == 7) ? param[6] : 0.;
           r = GModel::current()->getOCCInternals()->addWedge
@@ -8674,7 +8674,7 @@ yyreduce:
         }
       }
       else{
-        yymsg(0, "Wedge only available with OpenCASCADE factory");
+        yymsg(0, "Wedge only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add wedge");
       List_Delete((yyvsp[(6) - (7)].l));
@@ -8689,7 +8689,7 @@ yyreduce:
       int num = (int)(yyvsp[(3) - (7)].d);
       std::vector<double> param; ListOfDouble2Vector((yyvsp[(6) - (7)].l), param);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         if(param.size() >= 2){
           int in = (int)param[0];
           double offset = param[1];
@@ -8705,7 +8705,7 @@ yyreduce:
         }
       }
       else{
-        yymsg(0, "ThickSolid only available with OpenCASCADE factory");
+        yymsg(0, "ThickSolid only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add thick solid");
       List_Delete((yyvsp[(6) - (7)].l));
@@ -8756,7 +8756,7 @@ yyreduce:
       int num = (int)(yyvsp[(4) - (8)].d);
       std::vector<int> tags; ListOfDouble2Vector((yyvsp[(7) - (8)].l), tags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->addSurfaceLoop(num, tags);
       }
       else{
@@ -8776,7 +8776,7 @@ yyreduce:
       int num = (int)(yyvsp[(3) - (7)].d);
       std::vector<int> tags; ListOfDouble2Vector((yyvsp[(6) - (7)].l), tags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->addVolume(num, tags);
       }
       else{
@@ -8795,13 +8795,13 @@ yyreduce:
       int num = (int)(yyvsp[(3) - (7)].d);
       std::vector<int> wires; ListOfDouble2Vector((yyvsp[(6) - (7)].l), wires);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         std::vector<std::pair<int, int> > outDimTags;
         r = GModel::current()->getOCCInternals()->addThruSections
           (num, wires, true, false, outDimTags);
       }
       else{
-        yymsg(0, "ThruSections only available with OpenCASCADE factory");
+        yymsg(0, "ThruSections only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add thrusections");
       List_Delete((yyvsp[(6) - (7)].l));
@@ -8816,13 +8816,13 @@ yyreduce:
       int num = (int)(yyvsp[(4) - (8)].d);
       std::vector<int> wires; ListOfDouble2Vector((yyvsp[(7) - (8)].l), wires);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         std::vector<std::pair<int, int> > outDimTags;
         r = GModel::current()->getOCCInternals()->addThruSections
           (num, wires, true, true, outDimTags);
       }
       else{
-        yymsg(0, "ThruSections only available with OpenCASCADE factory");
+        yymsg(0, "ThruSections only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add ruled thrusections");
       List_Delete((yyvsp[(7) - (8)].l));
@@ -8910,7 +8910,7 @@ yyreduce:
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(4) - (5)].l), dimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->translate
           (dimTags, (yyvsp[(2) - (5)].v)[0], (yyvsp[(2) - (5)].v)[1], (yyvsp[(2) - (5)].v)[2]);
       }
@@ -8929,7 +8929,7 @@ yyreduce:
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(10) - (11)].l), dimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->rotate
           (dimTags, (yyvsp[(5) - (11)].v)[0], (yyvsp[(5) - (11)].v)[1], (yyvsp[(5) - (11)].v)[2], (yyvsp[(3) - (11)].v)[0], (yyvsp[(3) - (11)].v)[1], (yyvsp[(3) - (11)].v)[2], (yyvsp[(7) - (11)].d));
       }
@@ -8948,8 +8948,8 @@ yyreduce:
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(4) - (5)].l), dimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
-        Msg::Error("Symmetry not implemented yet with OpenCASCADE factory");
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+        Msg::Error("Symmetry not implemented yet with OpenCASCADE geometry kernel");
       }
       else{
         r = GModel::current()->getGEOInternals()->symmetry
@@ -8966,7 +8966,7 @@ yyreduce:
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(8) - (9)].l), dimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         yymsg(1, "Warning Dilate OCC: Dilatation (second argument) + Translation (first argument) ");
         r = GModel::current()->getOCCInternals()->dilate
           (dimTags, (yyvsp[(3) - (9)].v)[0], (yyvsp[(3) - (9)].v)[1], (yyvsp[(3) - (9)].v)[2], (yyvsp[(5) - (9)].d), (yyvsp[(5) - (9)].d), (yyvsp[(5) - (9)].d));
@@ -8986,7 +8986,7 @@ yyreduce:
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(8) - (9)].l), dimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         yymsg(1, "Warning Dilate OCC: Dilatation (second argument) + Translation (first argument) ");
         r = GModel::current()->getOCCInternals()->dilate
           (dimTags, (yyvsp[(3) - (9)].v)[0], (yyvsp[(3) - (9)].v)[1], (yyvsp[(3) - (9)].v)[2], (yyvsp[(5) - (9)].v)[0], (yyvsp[(5) - (9)].v)[1], (yyvsp[(5) - (9)].v)[2]);
@@ -9010,7 +9010,7 @@ yyreduce:
       std::string action((yyvsp[(1) - (4)].c));
       bool r = true;
       if(action == "Duplicata"){
-        if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+        if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
           r = GModel::current()->getOCCInternals()->copy(inDimTags, outDimTags);
         }
         else{
@@ -9043,7 +9043,7 @@ yyreduce:
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         yymsg(0, "Intersect line not available with OpenCASCADE");
       }
       else{
@@ -9067,7 +9067,7 @@ yyreduce:
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         yymsg(0, "Split Line not available with OpenCASCADE");
       }
       else{
@@ -9558,7 +9558,7 @@ yyreduce:
     {
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(3) - (4)].l), dimTags);
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         GModel::current()->getOCCInternals()->remove(dimTags);
       }
       GModel::current()->getGEOInternals()->remove(dimTags);
@@ -9572,7 +9572,7 @@ yyreduce:
     {
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(4) - (5)].l), dimTags);
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         GModel::current()->getOCCInternals()->remove(dimTags, true);
       }
       GModel::current()->getGEOInternals()->remove(dimTags, true);
@@ -9657,7 +9657,7 @@ yyreduce:
   case 234:
 #line 2979 "Gmsh.y"
     {
-      nameSpaces.clear();
+      gmsh_yynamespaces.clear();
     ;}
     break;
 
@@ -10406,7 +10406,7 @@ yyreduce:
       std::vector<std::pair<int, int> > inDimTags, outDimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(4) - (5)].l), inDimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->extrude
           (inDimTags, (yyvsp[(2) - (5)].v)[0], (yyvsp[(2) - (5)].v)[1], (yyvsp[(2) - (5)].v)[2], outDimTags);
       }
@@ -10427,7 +10427,7 @@ yyreduce:
       std::vector<std::pair<int, int> > inDimTags, outDimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(10) - (11)].l), inDimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->revolve
           (inDimTags, (yyvsp[(5) - (11)].v)[0], (yyvsp[(5) - (11)].v)[1], (yyvsp[(5) - (11)].v)[2], (yyvsp[(3) - (11)].v)[0], (yyvsp[(3) - (11)].v)[1], (yyvsp[(3) - (11)].v)[2], (yyvsp[(7) - (11)].d), outDimTags);
       }
@@ -10448,8 +10448,8 @@ yyreduce:
       std::vector<std::pair<int, int> > inDimTags, outDimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(12) - (13)].l), inDimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
-        yymsg(0, "Twisting extrude not available with OpenCASCADE factory");
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+        yymsg(0, "Twisting extrude not available with OpenCASCADE geometry kernel");
       }
       else{
         r = GModel::current()->getGEOInternals()->twist
@@ -10478,7 +10478,7 @@ yyreduce:
       std::vector<std::pair<int, int> > inDimTags, outDimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(4) - (7)].l), inDimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->extrude
           (inDimTags, (yyvsp[(2) - (7)].v)[0], (yyvsp[(2) - (7)].v)[1], (yyvsp[(2) - (7)].v)[2], outDimTags, &extr);
       }
@@ -10508,7 +10508,7 @@ yyreduce:
       std::vector<std::pair<int, int> > inDimTags, outDimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(10) - (13)].l), inDimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->revolve
           (inDimTags, (yyvsp[(5) - (13)].v)[0], (yyvsp[(5) - (13)].v)[1], (yyvsp[(5) - (13)].v)[2], (yyvsp[(3) - (13)].v)[0], (yyvsp[(3) - (13)].v)[1], (yyvsp[(3) - (13)].v)[2], (yyvsp[(7) - (13)].d), outDimTags,
            &extr);
@@ -10540,8 +10540,8 @@ yyreduce:
       std::vector<std::pair<int, int> > inDimTags, outDimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(12) - (15)].l), inDimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
-        yymsg(0, "Twisting extrude not available with OpenCASCADE factory");
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+        yymsg(0, "Twisting extrude not available with OpenCASCADE geometry kernel");
       }
       else{
         r = GModel::current()->getGEOInternals()->twist
@@ -10570,8 +10570,8 @@ yyreduce:
       std::vector<std::pair<int, int> > inDimTags, outDimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(3) - (6)].l), inDimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
-        yymsg(0, "Boundary layer extrusion not available with OpenCASCADE factory");
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+        yymsg(0, "Boundary layer extrusion not available with OpenCASCADE geometry kernel");
       }
       else{
         r = GModel::current()->getGEOInternals()->boundaryLayer
@@ -10590,11 +10590,11 @@ yyreduce:
       std::vector<std::pair<int, int> > inDimTags, outDimTags;
       ListOfShapes2VectorOfPairs((yyvsp[(3) - (9)].l), inDimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->addPipe(inDimTags, (int)(yyvsp[(8) - (9)].d), outDimTags);
       }
       else{
-        yymsg(0, "Pipe only available with OpenCASCADE factory");
+        yymsg(0, "Pipe only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not extrude shapes");
       (yyval.l) = (yyvsp[(3) - (9)].l);
@@ -10608,7 +10608,7 @@ yyreduce:
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         std::vector<int> wires; ListOfDouble2Vector((yyvsp[(2) - (2)].l), wires);
         std::vector<std::pair<int, int> > outDimTags;
         r = GModel::current()->getOCCInternals()->addThruSections
@@ -10616,7 +10616,7 @@ yyreduce:
         VectorOfPairs2ListOfShapes(outDimTags, (yyval.l));
       }
       else{
-        yymsg(0, "ThruSections only available with OpenCASCADE factory");
+        yymsg(0, "ThruSections only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add thrusections");
       List_Delete((yyvsp[(2) - (2)].l));
@@ -10628,7 +10628,7 @@ yyreduce:
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         std::vector<int> wires; ListOfDouble2Vector((yyvsp[(3) - (3)].l), wires);
         std::vector<std::pair<int, int> > outDimTags;
         r = GModel::current()->getOCCInternals()->addThruSections
@@ -10636,7 +10636,7 @@ yyreduce:
         VectorOfPairs2ListOfShapes(outDimTags, (yyval.l));
       }
       else{
-        yymsg(0, "ThruSections only available with OpenCASCADE factory");
+        yymsg(0, "ThruSections only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add ruled thrusections");
       List_Delete((yyvsp[(3) - (3)].l));
@@ -10648,7 +10648,7 @@ yyreduce:
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         double radius = (yyvsp[(9) - (10)].d);
         std::vector<int> regions, edges;
         ListOfDouble2Vector((yyvsp[(3) - (10)].l), regions); ListOfDouble2Vector((yyvsp[(6) - (10)].l), edges);
@@ -10658,7 +10658,7 @@ yyreduce:
         VectorOfPairs2ListOfShapes(outDimTags, (yyval.l));
       }
       else{
-        yymsg(0, "Fillet only available with OpenCASCADE factory");
+        yymsg(0, "Fillet only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not fillet shapes");
       List_Delete((yyvsp[(3) - (10)].l));
@@ -10843,7 +10843,7 @@ yyreduce:
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         std::vector<std::pair<int, int > > object, tool, out;
         ListOfShapes2VectorOfPairs((yyvsp[(3) - (9)].l), object);
         ListOfShapes2VectorOfPairs((yyvsp[(7) - (9)].l), tool);
@@ -10855,7 +10855,7 @@ yyreduce:
         VectorOfPairs2ListOfShapes(out, (yyval.l));
       }
       else{
-        yymsg(0, "Boolean operators only available with OpenCASCADE factory");
+        yymsg(0, "Boolean operators only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not apply boolean operator");
       List_Delete((yyvsp[(3) - (9)].l));
@@ -10868,14 +10868,14 @@ yyreduce:
     {
       (yyval.l) = List_Create(2, 1, sizeof(Shape));
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         std::vector<std::pair<int, int> > out;
         std::string tmp = FixRelativePath(gmsh_yyname, (yyvsp[(3) - (4)].c));
         GModel::current()->getOCCInternals()->importShapes(tmp, true, out);
         VectorOfPairs2ListOfShapes(out, (yyval.l));
       }
       else{
-        yymsg(0, "ShapeFromFile only available with OpenCASCADE factory");
+        yymsg(0, "ShapeFromFile only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could import shape");
       Free((yyvsp[(3) - (4)].c));
@@ -10886,7 +10886,7 @@ yyreduce:
 #line 4002 "Gmsh.y"
     {
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         std::vector<std::pair<int, int> > object, tool, out;
         ListOfShapes2VectorOfPairs((yyvsp[(7) - (14)].l), object);
         ListOfShapes2VectorOfPairs((yyvsp[(11) - (14)].l), tool);
@@ -12211,7 +12211,7 @@ yyreduce:
 #line 4949 "Gmsh.y"
     {
       std::string struct_namespace((yyvsp[(3) - (4)].c));
-      (yyval.d) = (double)nameSpaces[struct_namespace].size();
+      (yyval.d) = (double)gmsh_yynamespaces[struct_namespace].size();
       Free((yyvsp[(3) - (4)].c));
     ;}
     break;
@@ -12220,7 +12220,7 @@ yyreduce:
 #line 4955 "Gmsh.y"
     {
       std::string struct_namespace(std::string(""));
-      (yyval.d) = (double)nameSpaces[struct_namespace].size();
+      (yyval.d) = (double)gmsh_yynamespaces[struct_namespace].size();
     ;}
     break;
 
@@ -12471,7 +12471,7 @@ yyreduce:
       std::string struct_namespace((yyvsp[(2) - (3)].c2).char1? (yyvsp[(2) - (3)].c2).char1 : std::string("")),
         struct_name((yyvsp[(2) - (3)].c2).char2);
       init_options
-        (nameSpaces.getMember_ValMax(struct_namespace, struct_name));
+        (gmsh_yynamespaces.getMember_ValMax(struct_namespace, struct_name));
     ;}
     break;
 
@@ -12482,9 +12482,9 @@ yyreduce:
         struct_name((yyvsp[(2) - (7)].c2).char2);
       Free((yyvsp[(2) - (7)].c2).char1); Free((yyvsp[(2) - (7)].c2).char2);
       int tag_out;
-      if (nameSpaces.defStruct(struct_namespace, struct_name,
-                               floatOptions, charOptions,
-                               tag_out, member_ValMax, (yyvsp[(3) - (7)].i)))
+      if (gmsh_yynamespaces.defStruct(struct_namespace, struct_name,
+                                      floatOptions, charOptions,
+                                      tag_out, member_ValMax, (yyvsp[(3) - (7)].i)))
         yymsg(0, "Redefinition of Struct '%s::%s'",
               struct_namespace.c_str(), struct_name.c_str());
       (yyval.d) = (double)tag_out;
@@ -13686,8 +13686,8 @@ yyreduce:
     {
       std::string out;
       const std::string * key_struct = NULL;
-      switch (nameSpaces.get_key_struct_from_tag(struct_namespace,
-                                                 (int)(yyvsp[(3) - (4)].d), key_struct)) {
+      switch (gmsh_yynamespaces.get_key_struct_from_tag(struct_namespace,
+                                                        (int)(yyvsp[(3) - (4)].d), key_struct)) {
       case 0:
         out = *key_struct;
         break;
@@ -14254,14 +14254,14 @@ void PrintParserSymbols(bool help, std::vector<std::string> &vec)
       vec.push_back(s);
     }
   }
-  if (nameSpaces.size()){
+  if (gmsh_yynamespaces.size()){
     if(help){
       vec.push_back("//");
       vec.push_back("// Structures");
       vec.push_back("//");
     }
     std::vector<std::string> strs;
-    nameSpaces.sprint(strs);
+    gmsh_yynamespaces.sprint(strs);
     vec.insert(vec.end(), strs.begin(), strs.end());
   }
 }
@@ -14681,7 +14681,7 @@ double treat_Struct_FullName_Float
   else{
     if (type_var == 1) {
       std::string struct_namespace(c1? c1 : std::string("")), struct_name(c2);
-      if(nameSpaces.getTag(struct_namespace, struct_name, out)) {
+      if(gmsh_yynamespaces.getTag(struct_namespace, struct_name, out)) {
         out = val_default;
         if (type_treat == 0) yymsg(0, "Unknown variable '%s'", struct_name.c_str());
       }
@@ -14701,7 +14701,7 @@ double treat_Struct_FullName_dot_tSTRING_Float
   double out;
   std::string struct_namespace(c1? c1 : std::string("")), struct_name(c2);
   std::string key_member(c3);
-  switch (nameSpaces.getMember
+  switch (gmsh_yynamespaces.getMember
           (struct_namespace, struct_name, key_member, out, index)) {
   case 0:
     if (type_treat == 1) out = 1.; // Exists (type_treat == 1)
@@ -14713,7 +14713,7 @@ double treat_Struct_FullName_dot_tSTRING_Float
   case 2:
     if (type_treat != 0) {
       const std::string * out_dummy = NULL;
-      out = (nameSpaces.getMember
+      out = (gmsh_yynamespaces.getMember
              (struct_namespace, struct_name, key_member, out_dummy))?
         val_default : 1.;
     }
@@ -14741,7 +14741,7 @@ List_T * treat_Struct_FullName_dot_tSTRING_ListOfFloat
   const std::vector<double> * out_vector; double val_;
   std::string struct_namespace(c1? c1 : std::string("")), struct_name(c2);
   std::string key_member(c3);
-  switch (nameSpaces.getMember_Vector
+  switch (gmsh_yynamespaces.getMember_Vector
           (struct_namespace, struct_name, key_member, out_vector)) {
   case 0:
     out = List_Create(out_vector->size(), 1, sizeof(double));
@@ -14770,7 +14770,7 @@ int treat_Struct_FullName_dot_tSTRING_Float_getDim
   int out;
   std::string struct_namespace(c1? c1 : std::string("")), struct_name(c2);
   std::string key_member(c3);
-  switch (nameSpaces.getMember_Dim
+  switch (gmsh_yynamespaces.getMember_Dim
           (struct_namespace, struct_name, key_member, out)) {
   case 0:
     break;
@@ -14823,7 +14823,7 @@ char* treat_Struct_FullName_dot_tSTRING_String
   std::string out_tmp; // PD: we should avoid that -> StringOption() to be changed
   std::string struct_namespace(c1? c1 : std::string("")), struct_name(c2);
   std::string key_member(c3);
-  switch (nameSpaces.getMember
+  switch (gmsh_yynamespaces.getMember
           (struct_namespace, struct_name, key_member, out, index)) {
   case 0:
     break;
@@ -14858,7 +14858,7 @@ List_T * treat_Struct_FullName_dot_tSTRING_ListOfString
   const std::vector<std::string> * out_vector; char * val_;
   std::string struct_namespace(c1? c1 : std::string("")), struct_name(c2);
   std::string key_member(c3);
-  switch (nameSpaces.getMember_Vector
+  switch (gmsh_yynamespaces.getMember_Vector
           (struct_namespace, struct_name, key_member, out_vector)) {
   case 0:
     out = List_Create(out_vector->size(), 1, sizeof(char *));
diff --git a/Parser/Gmsh.y b/Parser/Gmsh.y
index 52ea9a0e14..024d3cf5ec 100644
--- a/Parser/Gmsh.y
+++ b/Parser/Gmsh.y
@@ -68,7 +68,8 @@ int gmsh_yyerrorstate = 0;
 int gmsh_yyviewindex = 0;
 std::map<std::string, gmsh_yysymbol> gmsh_yysymbols;
 std::map<std::string, std::vector<std::string> > gmsh_yystringsymbols;
-NameSpaces nameSpaces;
+std::string gmsh_yyfactory;
+NameSpaces gmsh_yynamespaces;
 
 // static parser variables (accessible only in this file)
 #if defined(HAVE_POST)
@@ -85,7 +86,6 @@ static gmshfpos_t yyposImbricatedLoopsTab[MAX_RECUR_LOOPS];
 static int yylinenoImbricatedLoopsTab[MAX_RECUR_LOOPS];
 static double LoopControlVariablesTab[MAX_RECUR_LOOPS][3];
 static std::string LoopControlVariablesNameTab[MAX_RECUR_LOOPS];
-static std::string factory;
 static std::string struct_name, struct_namespace;
 static int flag_tSTRING_alloc = 0;
 
@@ -279,8 +279,8 @@ GeoFormatItem :
   | Affectation { return 1; }
   | tSetFactory '(' StringExprVar ')' tEND
     {
-      factory = $3;
-      if(factory == "OpenCASCADE"){
+      gmsh_yyfactory = $3;
+      if(gmsh_yyfactory == "OpenCASCADE"){
         if(!GModel::current()->getOCCInternals())
           GModel::current()->createOCCInternals();
         for(int dim = -2; dim <= 3; dim++)
@@ -1616,7 +1616,7 @@ Shape :
       double lc = CTX::instance()->geom.scalingFactor * $6[3];
       if(lc == 0.) lc = MAX_LC; // no mesh size given at the point
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->addVertex(num, x, y, z, lc);
       }
       else{
@@ -1636,7 +1636,7 @@ Shape :
       int num = (int)$3;
       std::vector<int> tags; ListOfDouble2Vector($6, tags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->addLine(num, tags);
       }
       else{
@@ -1652,7 +1652,7 @@ Shape :
       int num = (int)$3;
       std::vector<int> tags; ListOfDouble2Vector($6, tags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->addSpline(num, tags);
       }
       else{
@@ -1669,7 +1669,7 @@ Shape :
       std::vector<int> tags; ListOfDouble2Vector($6, tags);
       std::vector<double> param; ListOfDouble2Vector($6, param);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         if(tags.size() == 3){
           r = GModel::current()->getOCCInternals()->addCircleArc
             (num, tags[0], tags[1], tags[2]);
@@ -1706,7 +1706,7 @@ Shape :
       std::vector<int> tags; ListOfDouble2Vector($6, tags);
       std::vector<double> param; ListOfDouble2Vector($6, param);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         if(tags.size() == 3){
           r = GModel::current()->getOCCInternals()->addEllipseArc
             (num, tags[0], tags[1], tags[2]);
@@ -1745,8 +1745,8 @@ Shape :
       int num = (int)$3;
       std::vector<int> tags; ListOfDouble2Vector($6, tags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
-        yymsg(0, "BSpline not yet available with OpenCASCADE factory");
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+        yymsg(0, "BSpline not yet available with OpenCASCADE geometry kernel");
       }
       else{
         r = GModel::current()->getGEOInternals()->addBSpline(num, tags);
@@ -1761,7 +1761,7 @@ Shape :
       int num = (int)$3;
       std::vector<int> tags; ListOfDouble2Vector($6, tags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->addBezier(num, tags);
       }
       else{
@@ -1779,8 +1779,8 @@ Shape :
       std::vector<int> tags; ListOfDouble2Vector($6, tags);
       std::vector<double> knots; ListOfDouble2Vector($8, knots);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
-        yymsg(0, "Nurbs not available yet with OpenCASCADE factory");
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+        yymsg(0, "Nurbs not available yet with OpenCASCADE geometry kernel");
       }
       else{
         int order = knots.size() - tags.size() - 1;
@@ -1809,11 +1809,11 @@ Shape :
       int num = (int)$3;
       std::vector<int> tags; ListOfDouble2Vector($6, tags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->addWire(num, tags, false);
       }
       else{
-        yymsg(0, "Wire only available using OpenCASCADE factory");
+        yymsg(0, "Wire only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add wire");
       List_Delete($6);
@@ -1825,7 +1825,7 @@ Shape :
       int num = (int)$4;
       std::vector<int> tags; ListOfDouble2Vector($7, tags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         for(unsigned int i = 0; i < tags.size(); i++)
           tags[i] = std::abs(tags[i]); // all edge tags > 0 for OCC
         r = GModel::current()->getOCCInternals()->addLineLoop(num, tags);
@@ -1844,7 +1844,7 @@ Shape :
       int num = (int)$4;
       std::vector<int> tags; ListOfDouble2Vector($7, tags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->addPlaneSurface(num, tags);
       }
       else{
@@ -1860,7 +1860,7 @@ Shape :
       int num = (int)$3;
       std::vector<int> wires; ListOfDouble2Vector($6, wires);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         if(wires.size() != 1){
           yymsg(0, "OpenCASCADE face filling requires a single line loop");
         }
@@ -1914,7 +1914,7 @@ Shape :
       $$.Type = 0;
       bool r = true;
       if(param.size() >= 4 && param.size() <= 7){
-        if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+        if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
           double a1 = (param.size() >= 5) ? param[4] : -M_PI/2;
           double a2 = (param.size() >= 6) ? param[5] : M_PI/2;
           double a3 = (param.size() >= 7) ? param[6] : 2.*M_PI;
@@ -1922,7 +1922,7 @@ Shape :
             (num, param[0], param[1], param[2], param[3], a1, a2, a3);
         }
         else{
-          yymsg(0, "Sphere only available with OpenCASCADE factory");
+          yymsg(0, "Sphere only available with OpenCASCADE geometry kernel");
         }
         $$.Type = MSH_VOLUME;
       }
@@ -1957,7 +1957,7 @@ Shape :
       int num = (int)$3;
       std::vector<double> param; ListOfDouble2Vector($6, param);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         if(param.size() == 6){
           r = GModel::current()->getOCCInternals()->addBlock
             (num, param[0], param[1], param[2], param[3], param[4], param[5]);
@@ -1967,7 +1967,7 @@ Shape :
         }
       }
       else{
-        yymsg(0, "Block only available with OpenCASCADE factory");
+        yymsg(0, "Block only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add block");
       List_Delete($6);
@@ -1979,7 +1979,7 @@ Shape :
       int num = (int)$3;
       std::vector<double> param; ListOfDouble2Vector($6, param);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         if(param.size() == 5 || param.size() == 6){
           double alpha = (param.size() == 6) ? param[5] : 2*M_PI;
           r = GModel::current()->getOCCInternals()->addTorus
@@ -1990,7 +1990,7 @@ Shape :
         }
       }
       else{
-        yymsg(0, "Torus only available with OpenCASCADE factory");
+        yymsg(0, "Torus only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add torus");
       List_Delete($6);
@@ -2002,7 +2002,7 @@ Shape :
       int num = (int)$3;
       std::vector<double> param; ListOfDouble2Vector($6, param);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         if(param.size() == 5 || param.size() == 6){
           double r = (param.size() == 6) ? param[5] : 0.;
           r = GModel::current()->getOCCInternals()->addRectangle
@@ -2013,7 +2013,7 @@ Shape :
         }
       }
       else{
-        yymsg(0, "Rectangle only available with OpenCASCADE factory");
+        yymsg(0, "Rectangle only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add rectangle");
       List_Delete($6);
@@ -2025,7 +2025,7 @@ Shape :
       int num = (int)$3;
       std::vector<double> param; ListOfDouble2Vector($6, param);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         if(param.size() == 4 || param.size() == 5){
           double ry = (param.size() == 5) ? param[4] : param[3];
           r = GModel::current()->getOCCInternals()->addDisk
@@ -2036,7 +2036,7 @@ Shape :
         }
       }
       else{
-        yymsg(0, "Disk only available with OpenCASCADE factory");
+        yymsg(0, "Disk only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add disk");
       List_Delete($6);
@@ -2048,7 +2048,7 @@ Shape :
       int num = (int)$3;
       std::vector<double> param; ListOfDouble2Vector($6, param);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         if(param.size() == 7 || param.size() == 8){
           double angle = (param.size() == 8) ? param[7] : 2*M_PI;
           r = GModel::current()->getOCCInternals()->addCylinder
@@ -2060,7 +2060,7 @@ Shape :
         }
       }
       else{
-        yymsg(0, "Cylinder only available with OpenCASCADE factory");
+        yymsg(0, "Cylinder only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add cylinder");
       List_Delete($6);
@@ -2072,7 +2072,7 @@ Shape :
       int num = (int)$3;
       std::vector<double> param; ListOfDouble2Vector($6, param);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         if(param.size() == 8 || param.size() == 9){
           double alpha = (param.size() == 9) ? param[8] : 2*M_PI;
           r = GModel::current()->getOCCInternals()->addCone
@@ -2084,7 +2084,7 @@ Shape :
         }
       }
       else{
-        yymsg(0, "Cone only available with OpenCASCADE factory");
+        yymsg(0, "Cone only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add cone");
       List_Delete($6);
@@ -2096,7 +2096,7 @@ Shape :
       int num = (int)$3;
       std::vector<double> param; ListOfDouble2Vector($6, param);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         if(param.size() == 6 || param.size() == 7){
           double ltx = (param.size() == 7) ? param[6] : 0.;
           r = GModel::current()->getOCCInternals()->addWedge
@@ -2108,7 +2108,7 @@ Shape :
         }
       }
       else{
-        yymsg(0, "Wedge only available with OpenCASCADE factory");
+        yymsg(0, "Wedge only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add wedge");
       List_Delete($6);
@@ -2120,7 +2120,7 @@ Shape :
       int num = (int)$3;
       std::vector<double> param; ListOfDouble2Vector($6, param);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         if(param.size() >= 2){
           int in = (int)param[0];
           double offset = param[1];
@@ -2136,7 +2136,7 @@ Shape :
         }
       }
       else{
-        yymsg(0, "ThickSolid only available with OpenCASCADE factory");
+        yymsg(0, "ThickSolid only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add thick solid");
       List_Delete($6);
@@ -2179,7 +2179,7 @@ Shape :
       int num = (int)$4;
       std::vector<int> tags; ListOfDouble2Vector($7, tags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->addSurfaceLoop(num, tags);
       }
       else{
@@ -2196,7 +2196,7 @@ Shape :
       int num = (int)$3;
       std::vector<int> tags; ListOfDouble2Vector($6, tags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->addVolume(num, tags);
       }
       else{
@@ -2212,13 +2212,13 @@ Shape :
       int num = (int)$3;
       std::vector<int> wires; ListOfDouble2Vector($6, wires);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         std::vector<std::pair<int, int> > outDimTags;
         r = GModel::current()->getOCCInternals()->addThruSections
           (num, wires, true, false, outDimTags);
       }
       else{
-        yymsg(0, "ThruSections only available with OpenCASCADE factory");
+        yymsg(0, "ThruSections only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add thrusections");
       List_Delete($6);
@@ -2230,13 +2230,13 @@ Shape :
       int num = (int)$4;
       std::vector<int> wires; ListOfDouble2Vector($7, wires);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         std::vector<std::pair<int, int> > outDimTags;
         r = GModel::current()->getOCCInternals()->addThruSections
           (num, wires, true, true, outDimTags);
       }
       else{
-        yymsg(0, "ThruSections only available with OpenCASCADE factory");
+        yymsg(0, "ThruSections only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add ruled thrusections");
       List_Delete($7);
@@ -2311,7 +2311,7 @@ Transform :
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs($4, dimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->translate
           (dimTags, $2[0], $2[1], $2[2]);
       }
@@ -2327,7 +2327,7 @@ Transform :
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs($10, dimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->rotate
           (dimTags, $5[0], $5[1], $5[2], $3[0], $3[1], $3[2], $7);
       }
@@ -2343,8 +2343,8 @@ Transform :
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs($4, dimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
-        Msg::Error("Symmetry not implemented yet with OpenCASCADE factory");
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+        Msg::Error("Symmetry not implemented yet with OpenCASCADE geometry kernel");
       }
       else{
         r = GModel::current()->getGEOInternals()->symmetry
@@ -2358,7 +2358,7 @@ Transform :
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs($8, dimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         yymsg(1, "Warning Dilate OCC: Dilatation (second argument) + Translation (first argument) ");
         r = GModel::current()->getOCCInternals()->dilate
           (dimTags, $3[0], $3[1], $3[2], $5, $5, $5);
@@ -2375,7 +2375,7 @@ Transform :
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs($8, dimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         yymsg(1, "Warning Dilate OCC: Dilatation (second argument) + Translation (first argument) ");
         r = GModel::current()->getOCCInternals()->dilate
           (dimTags, $3[0], $3[1], $3[2], $5[0], $5[1], $5[2]);
@@ -2396,7 +2396,7 @@ Transform :
       std::string action($1);
       bool r = true;
       if(action == "Duplicata"){
-        if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+        if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
           r = GModel::current()->getOCCInternals()->copy(inDimTags, outDimTags);
         }
         else{
@@ -2426,7 +2426,7 @@ Transform :
     {
       $$ = List_Create(2, 1, sizeof(Shape));
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         yymsg(0, "Intersect line not available with OpenCASCADE");
       }
       else{
@@ -2448,7 +2448,7 @@ Transform :
     {
       $$ = List_Create(2, 1, sizeof(Shape));
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         yymsg(0, "Split Line not available with OpenCASCADE");
       }
       else{
@@ -2896,7 +2896,7 @@ Delete :
     {
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs($3, dimTags);
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         GModel::current()->getOCCInternals()->remove(dimTags);
       }
       GModel::current()->getGEOInternals()->remove(dimTags);
@@ -2907,7 +2907,7 @@ Delete :
     {
       std::vector<std::pair<int, int> > dimTags;
       ListOfShapes2VectorOfPairs($4, dimTags);
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         GModel::current()->getOCCInternals()->remove(dimTags, true);
       }
       GModel::current()->getGEOInternals()->remove(dimTags, true);
@@ -2977,7 +2977,7 @@ Delete :
     }
   | tDelete tDefineStruct tEND
     {
-      nameSpaces.clear();
+      gmsh_yynamespaces.clear();
     }
 ;
 
@@ -3630,7 +3630,7 @@ Extrude :
       std::vector<std::pair<int, int> > inDimTags, outDimTags;
       ListOfShapes2VectorOfPairs($4, inDimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->extrude
           (inDimTags, $2[0], $2[1], $2[2], outDimTags);
       }
@@ -3648,7 +3648,7 @@ Extrude :
       std::vector<std::pair<int, int> > inDimTags, outDimTags;
       ListOfShapes2VectorOfPairs($10, inDimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->revolve
           (inDimTags, $5[0], $5[1], $5[2], $3[0], $3[1], $3[2], $7, outDimTags);
       }
@@ -3666,8 +3666,8 @@ Extrude :
       std::vector<std::pair<int, int> > inDimTags, outDimTags;
       ListOfShapes2VectorOfPairs($12, inDimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
-        yymsg(0, "Twisting extrude not available with OpenCASCADE factory");
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+        yymsg(0, "Twisting extrude not available with OpenCASCADE geometry kernel");
       }
       else{
         r = GModel::current()->getGEOInternals()->twist
@@ -3690,7 +3690,7 @@ Extrude :
       std::vector<std::pair<int, int> > inDimTags, outDimTags;
       ListOfShapes2VectorOfPairs($4, inDimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->extrude
           (inDimTags, $2[0], $2[1], $2[2], outDimTags, &extr);
       }
@@ -3714,7 +3714,7 @@ Extrude :
       std::vector<std::pair<int, int> > inDimTags, outDimTags;
       ListOfShapes2VectorOfPairs($10, inDimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->revolve
           (inDimTags, $5[0], $5[1], $5[2], $3[0], $3[1], $3[2], $7, outDimTags,
            &extr);
@@ -3740,8 +3740,8 @@ Extrude :
       std::vector<std::pair<int, int> > inDimTags, outDimTags;
       ListOfShapes2VectorOfPairs($12, inDimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
-        yymsg(0, "Twisting extrude not available with OpenCASCADE factory");
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+        yymsg(0, "Twisting extrude not available with OpenCASCADE geometry kernel");
       }
       else{
         r = GModel::current()->getGEOInternals()->twist
@@ -3764,8 +3764,8 @@ Extrude :
       std::vector<std::pair<int, int> > inDimTags, outDimTags;
       ListOfShapes2VectorOfPairs($3, inDimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
-        yymsg(0, "Boundary layer extrusion not available with OpenCASCADE factory");
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+        yymsg(0, "Boundary layer extrusion not available with OpenCASCADE geometry kernel");
       }
       else{
         r = GModel::current()->getGEOInternals()->boundaryLayer
@@ -3781,11 +3781,11 @@ Extrude :
       std::vector<std::pair<int, int> > inDimTags, outDimTags;
       ListOfShapes2VectorOfPairs($3, inDimTags);
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         r = GModel::current()->getOCCInternals()->addPipe(inDimTags, (int)$8, outDimTags);
       }
       else{
-        yymsg(0, "Pipe only available with OpenCASCADE factory");
+        yymsg(0, "Pipe only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not extrude shapes");
       $$ = $3;
@@ -3796,7 +3796,7 @@ Extrude :
     {
       $$ = List_Create(2, 1, sizeof(Shape));
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         std::vector<int> wires; ListOfDouble2Vector($2, wires);
         std::vector<std::pair<int, int> > outDimTags;
         r = GModel::current()->getOCCInternals()->addThruSections
@@ -3804,7 +3804,7 @@ Extrude :
         VectorOfPairs2ListOfShapes(outDimTags, $$);
       }
       else{
-        yymsg(0, "ThruSections only available with OpenCASCADE factory");
+        yymsg(0, "ThruSections only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add thrusections");
       List_Delete($2);
@@ -3813,7 +3813,7 @@ Extrude :
     {
       $$ = List_Create(2, 1, sizeof(Shape));
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         std::vector<int> wires; ListOfDouble2Vector($3, wires);
         std::vector<std::pair<int, int> > outDimTags;
         r = GModel::current()->getOCCInternals()->addThruSections
@@ -3821,7 +3821,7 @@ Extrude :
         VectorOfPairs2ListOfShapes(outDimTags, $$);
       }
       else{
-        yymsg(0, "ThruSections only available with OpenCASCADE factory");
+        yymsg(0, "ThruSections only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not add ruled thrusections");
       List_Delete($3);
@@ -3830,7 +3830,7 @@ Extrude :
     {
       $$ = List_Create(2, 1, sizeof(Shape));
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         double radius = $9;
         std::vector<int> regions, edges;
         ListOfDouble2Vector($3, regions); ListOfDouble2Vector($6, edges);
@@ -3840,7 +3840,7 @@ Extrude :
         VectorOfPairs2ListOfShapes(outDimTags, $$);
       }
       else{
-        yymsg(0, "Fillet only available with OpenCASCADE factory");
+        yymsg(0, "Fillet only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not fillet shapes");
       List_Delete($3);
@@ -3960,7 +3960,7 @@ Boolean :
     {
       $$ = List_Create(2, 1, sizeof(Shape));
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         std::vector<std::pair<int, int > > object, tool, out;
         ListOfShapes2VectorOfPairs($3, object);
         ListOfShapes2VectorOfPairs($7, tool);
@@ -3972,7 +3972,7 @@ Boolean :
         VectorOfPairs2ListOfShapes(out, $$);
       }
       else{
-        yymsg(0, "Boolean operators only available with OpenCASCADE factory");
+        yymsg(0, "Boolean operators only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could not apply boolean operator");
       List_Delete($3);
@@ -3982,14 +3982,14 @@ Boolean :
     {
       $$ = List_Create(2, 1, sizeof(Shape));
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         std::vector<std::pair<int, int> > out;
         std::string tmp = FixRelativePath(gmsh_yyname, $3);
         GModel::current()->getOCCInternals()->importShapes(tmp, true, out);
         VectorOfPairs2ListOfShapes(out, $$);
       }
       else{
-        yymsg(0, "ShapeFromFile only available with OpenCASCADE factory");
+        yymsg(0, "ShapeFromFile only available with OpenCASCADE geometry kernel");
       }
       if(!r) yymsg(0, "Could import shape");
       Free($3);
@@ -4001,7 +4001,7 @@ BooleanShape :
                                           '{' ListOfShapes BooleanOption '}' tEND
     {
       bool r = true;
-      if(factory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
+      if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){
         std::vector<std::pair<int, int> > object, tool, out;
         ListOfShapes2VectorOfPairs($7, object);
         ListOfShapes2VectorOfPairs($11, tool);
@@ -4948,13 +4948,13 @@ FExpr_Single :
   | tDimNameSpace LP String__Index RP
     {
       std::string struct_namespace($3);
-      $$ = (double)nameSpaces[struct_namespace].size();
+      $$ = (double)gmsh_yynamespaces[struct_namespace].size();
       Free($3);
     }
   | tDimNameSpace LP RP
     {
       std::string struct_namespace(std::string(""));
-      $$ = (double)nameSpaces[struct_namespace].size();
+      $$ = (double)gmsh_yynamespaces[struct_namespace].size();
     }
 
   | String__Index NumericIncrement
@@ -5162,7 +5162,7 @@ DefineStruct :
       std::string struct_namespace($2.char1? $2.char1 : std::string("")),
         struct_name($2.char2);
       init_options
-        (nameSpaces.getMember_ValMax(struct_namespace, struct_name));
+        (gmsh_yynamespaces.getMember_ValMax(struct_namespace, struct_name));
     }
     '[' FloatParameterOptionsOrNone_NoComma ']'
     {
@@ -5170,9 +5170,9 @@ DefineStruct :
         struct_name($2.char2);
       Free($2.char1); Free($2.char2);
       int tag_out;
-      if (nameSpaces.defStruct(struct_namespace, struct_name,
-                               floatOptions, charOptions,
-                               tag_out, member_ValMax, $3))
+      if (gmsh_yynamespaces.defStruct(struct_namespace, struct_name,
+                                      floatOptions, charOptions,
+                                      tag_out, member_ValMax, $3))
         yymsg(0, "Redefinition of Struct '%s::%s'",
               struct_namespace.c_str(), struct_name.c_str());
       $$ = (double)tag_out;
@@ -6100,8 +6100,8 @@ StringExpr :
     {
       std::string out;
       const std::string * key_struct = NULL;
-      switch (nameSpaces.get_key_struct_from_tag(struct_namespace,
-                                                 (int)$3, key_struct)) {
+      switch (gmsh_yynamespaces.get_key_struct_from_tag(struct_namespace,
+                                                        (int)$3, key_struct)) {
       case 0:
         out = *key_struct;
         break;
@@ -6429,14 +6429,14 @@ void PrintParserSymbols(bool help, std::vector<std::string> &vec)
       vec.push_back(s);
     }
   }
-  if (nameSpaces.size()){
+  if (gmsh_yynamespaces.size()){
     if(help){
       vec.push_back("//");
       vec.push_back("// Structures");
       vec.push_back("//");
     }
     std::vector<std::string> strs;
-    nameSpaces.sprint(strs);
+    gmsh_yynamespaces.sprint(strs);
     vec.insert(vec.end(), strs.begin(), strs.end());
   }
 }
@@ -6856,7 +6856,7 @@ double treat_Struct_FullName_Float
   else{
     if (type_var == 1) {
       std::string struct_namespace(c1? c1 : std::string("")), struct_name(c2);
-      if(nameSpaces.getTag(struct_namespace, struct_name, out)) {
+      if(gmsh_yynamespaces.getTag(struct_namespace, struct_name, out)) {
         out = val_default;
         if (type_treat == 0) yymsg(0, "Unknown variable '%s'", struct_name.c_str());
       }
@@ -6876,7 +6876,7 @@ double treat_Struct_FullName_dot_tSTRING_Float
   double out;
   std::string struct_namespace(c1? c1 : std::string("")), struct_name(c2);
   std::string key_member(c3);
-  switch (nameSpaces.getMember
+  switch (gmsh_yynamespaces.getMember
           (struct_namespace, struct_name, key_member, out, index)) {
   case 0:
     if (type_treat == 1) out = 1.; // Exists (type_treat == 1)
@@ -6888,7 +6888,7 @@ double treat_Struct_FullName_dot_tSTRING_Float
   case 2:
     if (type_treat != 0) {
       const std::string * out_dummy = NULL;
-      out = (nameSpaces.getMember
+      out = (gmsh_yynamespaces.getMember
              (struct_namespace, struct_name, key_member, out_dummy))?
         val_default : 1.;
     }
@@ -6916,7 +6916,7 @@ List_T * treat_Struct_FullName_dot_tSTRING_ListOfFloat
   const std::vector<double> * out_vector; double val_;
   std::string struct_namespace(c1? c1 : std::string("")), struct_name(c2);
   std::string key_member(c3);
-  switch (nameSpaces.getMember_Vector
+  switch (gmsh_yynamespaces.getMember_Vector
           (struct_namespace, struct_name, key_member, out_vector)) {
   case 0:
     out = List_Create(out_vector->size(), 1, sizeof(double));
@@ -6945,7 +6945,7 @@ int treat_Struct_FullName_dot_tSTRING_Float_getDim
   int out;
   std::string struct_namespace(c1? c1 : std::string("")), struct_name(c2);
   std::string key_member(c3);
-  switch (nameSpaces.getMember_Dim
+  switch (gmsh_yynamespaces.getMember_Dim
           (struct_namespace, struct_name, key_member, out)) {
   case 0:
     break;
@@ -6998,7 +6998,7 @@ char* treat_Struct_FullName_dot_tSTRING_String
   std::string out_tmp; // PD: we should avoid that -> StringOption() to be changed
   std::string struct_namespace(c1? c1 : std::string("")), struct_name(c2);
   std::string key_member(c3);
-  switch (nameSpaces.getMember
+  switch (gmsh_yynamespaces.getMember
           (struct_namespace, struct_name, key_member, out, index)) {
   case 0:
     break;
@@ -7033,7 +7033,7 @@ List_T * treat_Struct_FullName_dot_tSTRING_ListOfString
   const std::vector<std::string> * out_vector; char * val_;
   std::string struct_namespace(c1? c1 : std::string("")), struct_name(c2);
   std::string key_member(c3);
-  switch (nameSpaces.getMember_Vector
+  switch (gmsh_yynamespaces.getMember_Vector
           (struct_namespace, struct_name, key_member, out_vector)) {
   case 0:
     out = List_Create(out_vector->size(), 1, sizeof(char *));
diff --git a/Parser/Parser.h b/Parser/Parser.h
index 54b8bb0bb3..9aed6b7ec2 100644
--- a/Parser/Parser.h
+++ b/Parser/Parser.h
@@ -449,7 +449,8 @@ extern std::string gmsh_yyname;
 extern int gmsh_yyerrorstate;
 extern std::map<std::string, gmsh_yysymbol> gmsh_yysymbols;
 extern std::map<std::string, std::vector<std::string> > gmsh_yystringsymbols;
-extern NameSpaces nameSpaces;
+extern std::string gmsh_yyfactory;
+extern NameSpaces gmsh_yynamespaces;
 
 void PrintParserSymbols(bool help, std::vector<std::string> &vec);
 
-- 
GitLab