diff --git a/Common/Context.h b/Common/Context.h
index 957e52fca9409626e8cab8b6aedd3f1db046b03a..e3f9716bd6c25a20a35e118167b5a5e7c5d4699b 100644
--- a/Common/Context.h
+++ b/Common/Context.h
@@ -182,7 +182,7 @@ public :
       return val;
     }
     int oldxtrude, oldxtrude_recombine;
-    int allow_degenerated_extrude, save_all;
+    int allow_degenerated_extrude, save_all, stl_binary;
     char *triangle_options;
     int smooth_normals, reverse_all_normals;
     double angle_smooth_normals;
diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index c2c15e5050bea53a22275e74f132e65d7b4924c2..4e0b623307f6c55fbe41064cbf8837d268799ae6 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -993,6 +993,8 @@ StringXNumber MeshOptions_Number[] = {
     "Disable dubious point insertion tests" },
   { F|O, "StlDistanceTol" , opt_mesh_stl_distance_tol, 5.e-7 ,
     "Distance tolerance between two distinct vertices in STL meshes" },
+  { F|O, "StlBinary" , opt_mesh_stl_binary , 0. , 
+    "Save STL files in binary format?" },
   { F|O, "SurfaceEdges" , opt_mesh_surfaces_edges , 1. , 
     "Display edges of surface mesh?" },
   { F|O, "SurfaceFaces" , opt_mesh_surfaces_faces , 0. , 
diff --git a/Common/Options.cpp b/Common/Options.cpp
index 047b9a06f76e6f9ccb4a9e60dda10b6683bb7462..d327fdc2cca8734ec6c67fcb060ece184d989439 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -1,4 +1,4 @@
-// $Id: Options.cpp,v 1.299 2006-08-18 21:11:42 geuzaine Exp $
+// $Id: Options.cpp,v 1.300 2006-08-19 04:24:02 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -4626,6 +4626,13 @@ double opt_mesh_msh_file_version(OPT_ARGS_NUM)
   return CTX.mesh.msh_file_version;
 }
 
+double opt_mesh_stl_binary(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET)
+    CTX.mesh.stl_binary = (int)val;
+  return CTX.mesh.stl_binary;
+}
+
 double opt_mesh_nb_smoothing(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
@@ -4641,10 +4648,6 @@ double opt_mesh_nb_partitions(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
     CTX.mesh.nbPartitions = (int)val;
-  //#if defined(HAVE_FLTK)
-  //  if(WID && (action & GMSH_GUI))
-  //    WID->mesh_value[0]->value(CTX.mesh.nb_smoothing);
-  //#endif
   return CTX.mesh.nbPartitions;
 }
 
diff --git a/Common/Options.h b/Common/Options.h
index 0ed6ff759259f18b33c8c9cb457c4fa02eabc1b0..0cad7a65065914a6bedb4a0ce88b1b4f93b55311 100644
--- a/Common/Options.h
+++ b/Common/Options.h
@@ -447,6 +447,7 @@ double opt_mesh_light_lines(OPT_ARGS_NUM);
 double opt_mesh_light_two_side(OPT_ARGS_NUM);
 double opt_mesh_format(OPT_ARGS_NUM);
 double opt_mesh_msh_file_version(OPT_ARGS_NUM);
+double opt_mesh_stl_binary(OPT_ARGS_NUM);
 double opt_mesh_nb_smoothing(OPT_ARGS_NUM);
 double opt_mesh_stl_distance_tol(OPT_ARGS_NUM);
 double opt_mesh_nb_elem_per_rc(OPT_ARGS_NUM);
diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp
index c586e98c157e974d6717ce25b6df93bfbd56efdb..61043149c6dd5c7915ec440c42293f095df5dc40 100644
--- a/Fltk/Callbacks.cpp
+++ b/Fltk/Callbacks.cpp
@@ -1,4 +1,4 @@
-// $Id: Callbacks.cpp,v 1.442 2006-08-19 01:12:38 geuzaine Exp $
+// $Id: Callbacks.cpp,v 1.443 2006-08-19 04:24:03 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -650,26 +650,25 @@ int _save_pos(char *name)
 
 int _save_unv(char *name)
 {
-  CreateOutputFile(name, CTX.mesh.format = FORMAT_UNV);
+  CreateOutputFile(name, FORMAT_UNV);
   return 1;
 }
 
 int _save_mesh(char *name)
 {
-  CreateOutputFile(name, CTX.mesh.format = FORMAT_MESH);
+  CreateOutputFile(name, FORMAT_MESH);
   return 1;
 }
 
 int _save_vrml(char *name)
 {
-  CreateOutputFile(name, CTX.mesh.format = FORMAT_VRML);
+  CreateOutputFile(name, FORMAT_VRML);
   return 1;
 }
 
 int _save_stl(char *name)
 {
-  CreateOutputFile(name, CTX.mesh.format = FORMAT_STL);
-  return 1;
+  return stl_dialog(name);
 }
 
 int _save_ps(char *name)
@@ -752,6 +751,7 @@ int _save_auto(char *name)
   switch(GuessFileFormatFromFileName(name)){
   case FORMAT_OPT     : return _save_options(name);
   case FORMAT_MSH     : return _save_msh(name);
+  case FORMAT_STL     : return _save_stl(name);
   case FORMAT_PS      : return _save_ps(name);
   case FORMAT_EPS     : return _save_eps(name);
   case FORMAT_EPSTEX  : return _save_epstex(name);
diff --git a/Fltk/GUI_Extras.cpp b/Fltk/GUI_Extras.cpp
index 3bda8024a3b54c45b48d1921a0639fbe41a248d6..ba4b10c38c4827fc22989beec573e5698732ae7d 100644
--- a/Fltk/GUI_Extras.cpp
+++ b/Fltk/GUI_Extras.cpp
@@ -1,4 +1,4 @@
-// $Id: GUI_Extras.cpp,v 1.18 2006-08-08 04:42:43 geuzaine Exp $
+// $Id: GUI_Extras.cpp,v 1.19 2006-08-19 04:24:03 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -582,3 +582,58 @@ int msh_dialog(char *name)
   return 0;
 }
 
+// save stl dialog
+
+int stl_dialog(char *name)
+{
+  struct _stl_dialog{
+    Fl_Window *window;
+    Fl_Choice *c;
+    Fl_Button *ok, *cancel;
+  };
+  static _stl_dialog *dialog = NULL;
+
+  static Fl_Menu_Item formatmenu[] = {
+    {"ASCII", 0, 0, 0},
+    {"Binary", 0, 0, 0},
+    {0}
+  };
+
+  if(!dialog){
+    dialog = new _stl_dialog;
+    int h = 3*10 + 25 + 1*25, y = 0;
+    // not a "Dialog_Window" since it is modal 
+    dialog->window = new Fl_Double_Window(200, h, "STL Options"); y = 10;
+    dialog->window->box(GMSH_WINDOW_BOX);
+    dialog->c = new Fl_Choice(10, y, 130, 25, "Format"); y+= 25;
+    dialog->c->menu(formatmenu);
+    dialog->c->align(FL_ALIGN_RIGHT);
+    dialog->ok = new Fl_Return_Button(10, y+10, 85, 25, "OK");
+    dialog->cancel = new Fl_Button(105, y+10, 85, 25, "Cancel");
+    dialog->window->set_modal();
+    dialog->window->end();
+    dialog->window->hotspot(dialog->window);
+  }
+  
+  dialog->c->value(CTX.mesh.stl_binary ? 1 : 0);
+  dialog->window->show();
+
+  while(dialog->window->shown()){
+    Fl::wait();
+    for (;;) {
+      Fl_Widget* o = Fl::readqueue();
+      if (!o) break;
+      if (o == dialog->ok) {
+	opt_mesh_stl_binary(0, GMSH_SET | GMSH_GUI, dialog->c->value());
+	CreateOutputFile(name, FORMAT_STL);
+	dialog->window->hide();
+	return 1;
+      }
+      if (o == dialog->window || o == dialog->cancel){
+	dialog->window->hide();
+	return 0;
+      }
+    }
+  }
+  return 0;
+}
diff --git a/Fltk/GUI_Extras.h b/Fltk/GUI_Extras.h
index 798ba31cfb735c38c84d34be416d9eb779cc5092..22ec826fc5e5dc103aaa4702d1466e7e36a4d23e 100644
--- a/Fltk/GUI_Extras.h
+++ b/Fltk/GUI_Extras.h
@@ -34,6 +34,7 @@ int gif_dialog(char *filename);
 int gl2ps_dialog(char *filename, char *title, int format, int TeX);
 int options_dialog(char *filename);
 int msh_dialog(char *filename);
+int stl_dialog(char *filename);
 
 #endif
 
diff --git a/Geo/GModel.h b/Geo/GModel.h
index 7af51784c1e3054c43b464b30460fcc855040f55..1eabb8aefd6199182fccd21ed180bec633515f0c 100644
--- a/Geo/GModel.h
+++ b/Geo/GModel.h
@@ -123,7 +123,7 @@ class GModel
 	       double scalingFactor=1.0);
   int writePOS(const std::string &name, double scalingFactor=1.0);
   int readSTL(const std::string &name, double tolerance=1.e-3);
-  int writeSTL(const std::string &name, double scalingFactor=1.0);
+  int writeSTL(const std::string &name, bool binary=false, double scalingFactor=1.0);
   int readVRML(const std::string &name);
   int writeVRML(const std::string &name, double scalingFactor=1.0);
   int writeUNV(const std::string &name, double scalingFactor=1.0);
diff --git a/Geo/GModelIO.cpp b/Geo/GModelIO.cpp
index 89e146b768061629b8e46cdc5f0ec798c39e65fe..2854347247b9d517d7a3b98c863373be5986288b 100644
--- a/Geo/GModelIO.cpp
+++ b/Geo/GModelIO.cpp
@@ -1,4 +1,4 @@
-// $Id: GModelIO.cpp,v 1.25 2006-08-18 17:21:39 geuzaine Exp $
+// $Id: GModelIO.cpp,v 1.26 2006-08-19 04:24:03 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -728,23 +728,36 @@ int GModel::readSTL(const std::string &name, double tolerance)
   return 1;
 }
 
-int GModel::writeSTL(const std::string &name, double scalingFactor)
+int GModel::writeSTL(const std::string &name, bool binary, double scalingFactor)
 {
-  FILE *fp = fopen(name.c_str(), "w");
+  FILE *fp = fopen(name.c_str(), binary ? "wb" : "w");
   if(!fp){
     Msg(GERROR, "Unable to open file '%s'", name.c_str());
     return 0;
   }
 
-  fprintf(fp, "solid Created by Gmsh\n");
+  if(!binary)
+    fprintf(fp, "solid Created by Gmsh\n");
+  else{
+    char header[80];
+    strncpy(header, "Created by Gmsh", 80);
+    fwrite(header, sizeof(char), 80, fp);
+    unsigned int nfacets = 0;
+    for(fiter it = firstFace(); it != lastFace(); ++it)
+      nfacets += (*it)->triangles.size() + 2 * (*it)->quadrangles.size();
+    fwrite(&nfacets, sizeof(unsigned int), 1, fp);
+  }
+    
   for(fiter it = firstFace(); it != lastFace(); ++it) {
     for(unsigned int i = 0; i < (*it)->triangles.size(); i++)
-      (*it)->triangles[i]->writeSTL(fp, scalingFactor);
+      (*it)->triangles[i]->writeSTL(fp, binary, scalingFactor);
     for(unsigned int i = 0; i < (*it)->quadrangles.size(); i++)
-      (*it)->quadrangles[i]->writeSTL(fp, scalingFactor);
+      (*it)->quadrangles[i]->writeSTL(fp, binary, scalingFactor);
   }
-  fprintf(fp, "endsolid Created by Gmsh\n");
 
+  if(!binary)
+    fprintf(fp, "endsolid Created by Gmsh\n");
+  
   fclose(fp);
   return 1;
 }
diff --git a/Geo/MElement.cpp b/Geo/MElement.cpp
index a38fd8916814916fba442a436e816ab414cbd120..23e1130251a39bb5682b19fdcd913a358ab67ddb 100644
--- a/Geo/MElement.cpp
+++ b/Geo/MElement.cpp
@@ -1,4 +1,4 @@
-// $Id: MElement.cpp,v 1.8 2006-08-15 06:26:52 geuzaine Exp $
+// $Id: MElement.cpp,v 1.9 2006-08-19 04:24:03 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -176,40 +176,53 @@ void MElement::writePOS(FILE *fp, double scalingFactor, int elementary)
   fprintf(fp, "};\n");
 }
 
-void MElement::writeSTL(FILE *fp, double scalingFactor)
+void MElement::writeSTL(FILE *fp, bool binary, double scalingFactor)
 {
-  int n = getNumVertices();
-  if(n < 3 || n > 4) return;
-
-  MVertex *v0 = getVertex(0);
-  MVertex *v1 = getVertex(1);
-  MVertex *v2 = getVertex(2);
-  double N[3];
-  normal3points(v0->x(), v0->y(), v0->z(), 
-		v1->x(), v1->y(), v1->z(), 
-		v2->x(), v2->y(), v2->z(), N);
-  fprintf(fp, "facet normal %g %g %g\n", N[0], N[1], N[2]);
-  fprintf(fp, "  outer loop\n");
-  fprintf(fp, "    vertex %g %g %g\n", v0->x() * scalingFactor, 
-	  v0->y() * scalingFactor, v0->z() * scalingFactor);
-  fprintf(fp, "    vertex %g %g %g\n", v1->x() * scalingFactor, 
-	  v1->y() * scalingFactor, v1->z() * scalingFactor);
-  fprintf(fp, "    vertex %g %g %g\n", v2->x() * scalingFactor, 
-	  v2->y() * scalingFactor, v2->z() * scalingFactor);
-  fprintf(fp, "  endloop\n");
-  fprintf(fp, "endfacet\n");
-  if(n == 4){
-    MVertex *v3 = getVertex(3);
-    fprintf(fp, "facet normal %g %g %g\n", N[0], N[1], N[2]);
+  if(getNumEdges() != 3 && getNumEdges() != 4) return;
+  int qid[3] = {0, 2, 3};
+  SVector3 n = getFace(0).normal();
+  if(!binary){
+    fprintf(fp, "facet normal %g %g %g\n", n[0], n[1], n[2]);
     fprintf(fp, "  outer loop\n");
-    fprintf(fp, "    vertex %g %g %g\n", v0->x() * scalingFactor, 
-	    v0->y() * scalingFactor, v0->z() * scalingFactor);
-    fprintf(fp, "    vertex %g %g %g\n", v2->x() * scalingFactor, 
-	    v2->y() * scalingFactor, v2->z() * scalingFactor);
-    fprintf(fp, "    vertex %g %g %g\n", v3->x() * scalingFactor, 
-	    v3->y() * scalingFactor, v3->z() * scalingFactor);
+    for(int j = 0; j < 3; j++)
+      fprintf(fp, "    vertex %g %g %g\n", 
+	      getVertex(j)->x() * scalingFactor, 
+	      getVertex(j)->y() * scalingFactor, 
+	      getVertex(j)->z() * scalingFactor);
     fprintf(fp, "  endloop\n");
     fprintf(fp, "endfacet\n");
+    if(getNumVertices() == 4){
+      fprintf(fp, "facet normal %g %g %g\n", n[0], n[1], n[2]);
+      fprintf(fp, "  outer loop\n");
+      for(int j = 0; j < 3; j++)
+	fprintf(fp, "    vertex %g %g %g\n", 
+		getVertex(qid[j])->x() * scalingFactor, 
+		getVertex(qid[j])->y() * scalingFactor, 
+		getVertex(qid[j])->z() * scalingFactor);
+      fprintf(fp, "  endloop\n");
+      fprintf(fp, "endfacet\n");
+    }
+  }
+  else{
+    char data[50];
+    float *coords = (float*)data;
+    coords[0] = n[0];
+    coords[1] = n[1];
+    coords[2] = n[2];
+    for(int j = 0; j < 3; j++){
+      coords[3 + 3 * j] = getVertex(j)->x() * scalingFactor;
+      coords[3 + 3 * j + 1] = getVertex(j)->y() * scalingFactor;
+      coords[3 + 3 * j + 2] = getVertex(j)->z() * scalingFactor;
+    }
+    fwrite(data, sizeof(char), 50, fp);
+    if(getNumVertices() == 4){
+      for(int j = 0; j < 3; j++){
+	coords[3 + 3 * j] = getVertex(qid[j])->x() * scalingFactor;
+	coords[3 + 3 * j + 1] = getVertex(qid[j])->y() * scalingFactor;
+	coords[3 + 3 * j + 2] = getVertex(qid[j])->z() * scalingFactor;
+      }
+      fwrite(data, sizeof(char), 50, fp);
+    }
   }
 }
 
diff --git a/Geo/MElement.h b/Geo/MElement.h
index c7d21f6278434a7679ade77c340cf8b0d293627d..004784d7cac0c20c404b4af48eddb5c704d3d411 100644
--- a/Geo/MElement.h
+++ b/Geo/MElement.h
@@ -131,7 +131,7 @@ class MElement
 			int elementary=1, int physical=1);
   virtual void writePOS(FILE *fp, double scalingFactor=1.0,
 			int elementary=1);
-  virtual void writeSTL(FILE *fp, double scalingFactor=1.0);
+  virtual void writeSTL(FILE *fp, bool binary=false, double scalingFactor=1.0);
   virtual void writeVRML(FILE *fp);
   virtual void writeUNV(FILE *fp, int elementary);
   virtual void writeMESH(FILE *fp, int elementary);
diff --git a/Parser/CreateFile.cpp b/Parser/CreateFile.cpp
index d8462fc28028551a112b65d25a547db21fcee0e9..20e18f3b229eae9b419a8dbdcd3ee3f6d4ba6c89 100644
--- a/Parser/CreateFile.cpp
+++ b/Parser/CreateFile.cpp
@@ -1,4 +1,4 @@
-// $Id: CreateFile.cpp,v 1.1 2006-08-12 19:34:16 geuzaine Exp $
+// $Id: CreateFile.cpp,v 1.2 2006-08-19 04:24:03 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -150,7 +150,7 @@ void CreateOutputFile(char *filename, int format)
     break;
 
   case FORMAT_STL:
-    GMODEL->writeSTL(name, CTX.mesh.scaling_factor);
+    GMODEL->writeSTL(name, CTX.mesh.stl_binary, CTX.mesh.scaling_factor);
     break;
 
   case FORMAT_VRML:
diff --git a/doc/texinfo/opt_general.texi b/doc/texinfo/opt_general.texi
index 8ec47fe0365411aefba4fff360c7f9254a9a2926..d9e39e8ce25823aabedd6022948d71ff8c139f82 100644
--- a/doc/texinfo/opt_general.texi
+++ b/doc/texinfo/opt_general.texi
@@ -615,8 +615,8 @@ Default value: @code{450}@*
 Saved in: @code{General.SessionFileName}
 
 @item General.MouseSelection
-Mouse selection mode (0=none, 1=no hover, 2=full)@*
-Default value: @code{2}@*
+Mouse hover and selection mode (0=none, 1=hover and select geometry but only select mesh, 2=hover and select geometry and mesh)@*
+Default value: @code{1}@*
 Saved in: @code{General.OptionsFileName}
 
 @item General.NoPopup
diff --git a/doc/texinfo/opt_mesh.texi b/doc/texinfo/opt_mesh.texi
index c5345a6bd3479bbf4f90d5a3bd278cae0554e10f..c67276ce96bb0c68e6f41a07fc6a57c499d2efd3 100644
--- a/doc/texinfo/opt_mesh.texi
+++ b/doc/texinfo/opt_mesh.texi
@@ -359,6 +359,11 @@ Distance tolerance between two distinct vertices in STL meshes@*
 Default value: @code{5e-07}@*
 Saved in: @code{General.OptionsFileName}
 
+@item Mesh.StlBinary
+Save STL files in binary format?@*
+Default value: @code{0}@*
+Saved in: @code{General.OptionsFileName}
+
 @item Mesh.SurfaceEdges
 Display edges of surface mesh?@*
 Default value: @code{1}@*