diff --git a/Common/CreateFile.cpp b/Common/CreateFile.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e23a30c2523842675b3a12680fbc5f97125fea61
--- /dev/null
+++ b/Common/CreateFile.cpp
@@ -0,0 +1,378 @@
+// $Id: CreateFile.cpp,v 1.1 2008-07-04 15:02:47 geuzaine Exp $
+//
+// Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+// USA.
+// 
+// Please report all bugs and problems to <gmsh@geuz.org>.
+
+#include <string.h>
+#include "Message.h"
+#include "GModel.h"
+#include "GmshDefines.h"
+#include "StringUtils.h"
+#include "Context.h"
+#include "Options.h"
+
+#if defined(HAVE_FLTK)
+#include "GmshUI.h"
+#include "gl2ps.h"
+#include "gl2gif.h"
+#include "gl2jpeg.h"
+#include "gl2png.h"
+#include "gl2ppm.h"
+#include "gl2yuv.h"
+#endif
+
+extern Context_T CTX;
+
+int GuessFileFormatFromFileName(const char *name)
+{
+  int len;
+  char ext[256];
+
+  for(len = strlen(name) - 1; len >= 0; len--) {
+    if(name[len] == '.') {
+      strcpy(ext, &name[len]);
+      break;
+    }
+  }
+  if(len <= 0)
+    strcpy(ext, "");
+  
+  if     (!strcmp(ext, ".geo"))  return FORMAT_GEO;
+  else if(!strcmp(ext, ".msh"))  return FORMAT_MSH;
+  else if(!strcmp(ext, ".pos"))  return FORMAT_POS;
+  else if(!strcmp(ext, ".opt"))  return FORMAT_OPT;
+  else if(!strcmp(ext, ".unv"))  return FORMAT_UNV;
+  else if(!strcmp(ext, ".vtk"))  return FORMAT_VTK;
+  else if(!strcmp(ext, ".stl"))  return FORMAT_STL;
+  else if(!strcmp(ext, ".cgns")) return FORMAT_CGNS;
+  else if(!strcmp(ext, ".med"))  return FORMAT_MED;
+  else if(!strcmp(ext, ".mesh")) return FORMAT_MESH;
+  else if(!strcmp(ext, ".bdf"))  return FORMAT_BDF;
+  else if(!strcmp(ext, ".nas"))  return FORMAT_BDF;
+  else if(!strcmp(ext, ".p3d"))  return FORMAT_P3D;
+  else if(!strcmp(ext, ".wrl"))  return FORMAT_VRML;
+  else if(!strcmp(ext, ".vrml")) return FORMAT_VRML;
+  else if(!strcmp(ext, ".gif"))  return FORMAT_GIF;
+  else if(!strcmp(ext, ".jpg"))  return FORMAT_JPEG;
+  else if(!strcmp(ext, ".jpeg")) return FORMAT_JPEG;
+  else if(!strcmp(ext, ".png"))  return FORMAT_PNG;
+  else if(!strcmp(ext, ".ps"))   return FORMAT_PS;
+  else if(!strcmp(ext, ".eps"))  return FORMAT_EPS;
+  else if(!strcmp(ext, ".pdf"))  return FORMAT_PDF;
+  else if(!strcmp(ext, ".tex"))  return FORMAT_TEX;
+  else if(!strcmp(ext, ".svg"))  return FORMAT_SVG;
+  else if(!strcmp(ext, ".ppm"))  return FORMAT_PPM;
+  else if(!strcmp(ext, ".yuv"))  return FORMAT_YUV;
+  else                           return -1;
+}
+
+void GetDefaultFileName(int format, char *name)
+{
+  char ext[32] = "";
+  strcpy(name, CTX.no_ext_filename);
+  switch(format){
+  case FORMAT_GEO:  strcpy(ext, ".geo_unrolled"); break;
+  case FORMAT_MSH:  strcpy(ext, ".msh"); break;
+  case FORMAT_POS:  strcpy(ext, ".pos"); break;
+  case FORMAT_OPT:  strcpy(ext, ".opt"); break;
+  case FORMAT_UNV:  strcpy(ext, ".unv"); break;
+  case FORMAT_VTK:  strcpy(ext, ".vtk"); break;
+  case FORMAT_STL:  strcpy(ext, ".stl"); break;
+  case FORMAT_CGNS: strcpy(ext, ".cgns"); break;
+  case FORMAT_MED:  strcpy(ext, ".med"); break;
+  case FORMAT_MESH: strcpy(ext, ".mesh"); break;
+  case FORMAT_BDF:  strcpy(ext, ".bdf"); break;
+  case FORMAT_P3D:  strcpy(ext, ".p3d"); break;
+  case FORMAT_VRML: strcpy(ext, ".wrl"); break;
+  case FORMAT_GIF:  strcpy(ext, ".gif"); break;
+  case FORMAT_JPEG: strcpy(ext, ".jpg"); break;
+  case FORMAT_PNG:  strcpy(ext, ".png"); break;
+  case FORMAT_PS:   strcpy(ext, ".ps"); break;
+  case FORMAT_EPS:  strcpy(ext, ".eps"); break;
+  case FORMAT_PDF:  strcpy(ext, ".pdf"); break;
+  case FORMAT_TEX:  strcpy(ext, ".tex"); break;
+  case FORMAT_SVG:  strcpy(ext, ".svg"); break;
+  case FORMAT_PPM:  strcpy(ext, ".ppm"); break;
+  case FORMAT_YUV:  strcpy(ext, ".yuv"); break;
+  default: break;
+  }
+  strcat(name, ext);
+}
+
+void CreateOutputFile(const char *filename, int format)
+{
+  char name[256], no_ext[256], ext[256], base[256];
+
+  if(!filename || !strlen(filename))
+    GetDefaultFileName(format, name);
+  else
+    strcpy(name, filename);
+
+  splitFileName(name, no_ext, ext, base);
+
+  int oldformat = CTX.print.format;
+  CTX.print.format = format;
+  CTX.printing = 1;
+
+#if defined(HAVE_FLTK)
+  GLint viewport[4];
+  for(int i = 0; i < 4; i++) viewport[i] = CTX.viewport[i];
+  GLint width = viewport[2] - viewport[0];
+  GLint height = viewport[3] - viewport[1];
+#endif
+
+  bool printEndMessage = true;
+  if(format != FORMAT_AUTO) Msg::StatusBar(2, true, "Writing '%s'", name);
+
+  switch (format) {
+
+  case FORMAT_AUTO:
+    CreateOutputFile(name, GuessFileFormatFromFileName(name));
+    printEndMessage = false;
+    break;
+    
+  case FORMAT_OPT:
+    Print_Options(0, GMSH_FULLRC, 1, 1, name);
+    break;
+
+  case FORMAT_MSH:
+    GModel::current()->writeMSH(name, CTX.mesh.msh_file_version, CTX.mesh.msh_binary, 
+                                CTX.mesh.save_all, CTX.mesh.scaling_factor);
+    break;
+
+  case FORMAT_STL:
+    GModel::current()->writeSTL(name, CTX.mesh.stl_binary,
+                                CTX.mesh.save_all, CTX.mesh.scaling_factor);
+    break;
+
+  case FORMAT_VRML:
+    GModel::current()->writeVRML(name, CTX.mesh.save_all, CTX.mesh.scaling_factor);
+    break;
+
+  case FORMAT_UNV:
+    GModel::current()->writeUNV(name, CTX.mesh.save_all, CTX.mesh.save_groups_of_nodes,
+                                CTX.mesh.scaling_factor);
+    break;
+
+  case FORMAT_VTK:
+    GModel::current()->writeVTK(name, CTX.mesh.msh_binary, CTX.mesh.save_all,
+                                CTX.mesh.scaling_factor);
+    break;
+
+  case FORMAT_MESH:
+    GModel::current()->writeMESH(name, CTX.mesh.save_all, CTX.mesh.scaling_factor);
+    break;
+
+  case FORMAT_BDF:
+    GModel::current()->writeBDF(name, CTX.mesh.bdf_field_format, 
+                     CTX.mesh.save_all, CTX.mesh.scaling_factor);
+    break;
+
+  case FORMAT_P3D:
+    GModel::current()->writeP3D(name, CTX.mesh.save_all, CTX.mesh.scaling_factor);
+    break;
+
+  case FORMAT_CGNS:
+    GModel::current()->writeCGNS(name, CTX.mesh.scaling_factor);
+    break;
+
+  case FORMAT_MED:
+    GModel::current()->writeMED(name, CTX.mesh.save_all, CTX.mesh.scaling_factor);
+    break;
+
+  case FORMAT_POS:
+    GModel::current()->writePOS(name, CTX.print.pos_elementary, CTX.print.pos_element, 
+                                CTX.print.pos_gamma, CTX.print.pos_eta, CTX.print.pos_rho, 
+                                CTX.mesh.save_all, CTX.mesh.scaling_factor);
+    break;
+
+  case FORMAT_GEO:
+    GModel::current()->writeGEO(name, CTX.print.geo_labels);
+    break;
+
+#if defined(HAVE_FLTK)
+  case FORMAT_PPM:
+  case FORMAT_YUV:
+  case FORMAT_GIF:  
+  case FORMAT_JPEG:
+  case FORMAT_PNG:
+    {
+      FILE *fp;
+      if(!(fp = fopen(name, "wb"))) {
+        Msg::Error("Unable to open file '%s'", name);
+        break;
+      }
+
+      PixelBuffer buffer(width, height, GL_RGB, GL_UNSIGNED_BYTE);
+
+      int old_bg_gradient = CTX.bg_gradient;
+      if(format == FORMAT_GIF && CTX.print.gif_transparent)
+        CTX.bg_gradient = 0;
+      buffer.Fill(CTX.batch);
+      CTX.bg_gradient = old_bg_gradient;
+
+      if(format == FORMAT_PPM){
+        create_ppm(fp, &buffer);
+      }
+      else if(format == FORMAT_YUV){
+        create_yuv(fp, &buffer);
+      }
+      else if(format == FORMAT_GIF){
+        create_gif(fp, &buffer,
+                   CTX.print.gif_dither,
+                   CTX.print.gif_sort,
+                   CTX.print.gif_interlace,
+                   CTX.print.gif_transparent,
+                   CTX.UNPACK_RED(CTX.color.bg),
+                   CTX.UNPACK_GREEN(CTX.color.bg), 
+                   CTX.UNPACK_BLUE(CTX.color.bg));
+      }
+      else if(format == FORMAT_JPEG){
+        create_jpeg(fp, &buffer, CTX.print.jpeg_quality, CTX.print.jpeg_smoothing);
+      }
+      else{
+        create_png(fp, &buffer, 100);
+      }
+      fclose(fp);
+    }
+    break;
+
+  case FORMAT_PS:
+  case FORMAT_EPS:
+  case FORMAT_PDF:
+  case FORMAT_SVG:
+    {
+      FILE *fp;
+      if(!(fp = fopen(name, "wb"))) {
+        Msg::Error("Unable to open file '%s'", name);
+        break;
+      }
+      
+      int psformat;
+      switch(format){
+      case FORMAT_PDF:
+        psformat = GL2PS_PDF;
+        break;
+      case FORMAT_PS:
+        psformat = GL2PS_PS;
+        break;
+      case FORMAT_SVG:
+        psformat = GL2PS_SVG;
+        break;
+      default:
+        psformat = GL2PS_EPS;
+        break;
+      }
+
+      int old_bg_gradient = CTX.bg_gradient;
+      if(!CTX.print.eps_background) CTX.bg_gradient = 0;
+      
+      PixelBuffer buffer(width, height, GL_RGB, GL_FLOAT);
+      
+      if(CTX.print.eps_quality == 0)
+        buffer.Fill(CTX.batch);
+      
+      int pssort = 
+        (CTX.print.eps_quality == 3) ? GL2PS_NO_SORT :
+        (CTX.print.eps_quality == 2) ? GL2PS_BSP_SORT : 
+        GL2PS_SIMPLE_SORT;
+      int psoptions =
+        GL2PS_SIMPLE_LINE_OFFSET | GL2PS_SILENT |
+        (CTX.print.eps_occlusion_culling ? GL2PS_OCCLUSION_CULL : 0) |
+        (CTX.print.eps_best_root ? GL2PS_BEST_ROOT : 0) |
+        (CTX.print.eps_background ? GL2PS_DRAW_BACKGROUND : 0) |
+        (CTX.print.eps_compress ? GL2PS_COMPRESS : 0) |
+        (CTX.print.eps_ps3shading ? 0 : GL2PS_NO_PS3_SHADING);
+
+      GLint buffsize = 0;
+      int res = GL2PS_OVERFLOW;
+      while(res == GL2PS_OVERFLOW) {
+        buffsize += 2048 * 2048;
+        gl2psBeginPage(CTX.base_filename, "Gmsh", viewport, 
+                       psformat, pssort, psoptions, GL_RGBA, 0, NULL, 
+                       15, 20, 10, buffsize, fp, base);
+        if(CTX.print.eps_quality == 0){
+          double modelview[16], projection[16];
+          glGetDoublev(GL_PROJECTION_MATRIX, projection);
+          glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
+          glMatrixMode(GL_PROJECTION);
+          glLoadIdentity();
+          glOrtho((double)CTX.viewport[0], (double)CTX.viewport[2],
+                  (double)CTX.viewport[1], (double)CTX.viewport[3], -1., 1.);
+          glMatrixMode(GL_MODELVIEW);
+          glLoadIdentity();
+          glRasterPos2d(0, 0);
+          gl2psDrawPixels(width, height, 0, 0, GL_RGB, GL_FLOAT, buffer.GetPixels());
+          glMatrixMode(GL_PROJECTION);
+          glLoadMatrixd(projection);
+          glMatrixMode(GL_MODELVIEW);
+          glLoadMatrixd(modelview);
+        }
+        else{
+          buffer.Fill(CTX.batch);
+        }
+        res = gl2psEndPage();
+      }
+
+      CTX.bg_gradient = old_bg_gradient;
+      fclose(fp);
+    }
+    break;
+
+  case FORMAT_TEX:
+    {
+      FILE *fp;
+      if(!(fp = fopen(name, "w"))) {
+        Msg::Error("Unable to open file '%s'", name);
+        break;
+      }
+      GLint buffsize = 0;
+      int res = GL2PS_OVERFLOW;
+      while(res == GL2PS_OVERFLOW) {
+        buffsize += 2048 * 2048;
+        gl2psBeginPage(CTX.base_filename, "Gmsh", viewport,
+                       GL2PS_TEX, GL2PS_NO_SORT, GL2PS_NONE, GL_RGBA, 0, NULL, 
+                       0, 0, 0, buffsize, fp, base);
+        PixelBuffer buffer(width, height, GL_RGB, GL_UNSIGNED_BYTE);
+        int oldtext = CTX.print.text;
+        CTX.print.text = 1;
+        buffer.Fill(CTX.batch);
+        CTX.print.text = oldtext;
+        res = gl2psEndPage();
+      }
+      fclose(fp);
+    }
+    break;
+#endif
+
+  default:
+    Msg::Error("Unknown output file format");
+    printEndMessage = false;
+    break;
+  }
+
+  if(printEndMessage) Msg::StatusBar(2, true, "Wrote '%s'", name);
+
+  CTX.print.format = oldformat;
+  CTX.printing = 0;
+
+#if defined(HAVE_FLTK)
+  Draw();
+#endif
+}
diff --git a/Common/CreateFile.h b/Common/CreateFile.h
new file mode 100644
index 0000000000000000000000000000000000000000..c7cc7f791aa3679d7c848a3c2c51dc9d340da7c8
--- /dev/null
+++ b/Common/CreateFile.h
@@ -0,0 +1,27 @@
+#ifndef _CREATE_FILE_H_
+#define _CREATE_FILE_H_
+
+// Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+// USA.
+// 
+// Please report all bugs and problems to <gmsh@geuz.org>.
+
+int GuessFileFormatFromFileName(const char *name);
+void GetDefaultFileName(int format, char *name);
+void CreateOutputFile(const char *name, int format);
+
+#endif
diff --git a/Common/OpenFile.cpp b/Common/OpenFile.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3f027395fb0735a23a4bb20bb64144a5b0da2cd1
--- /dev/null
+++ b/Common/OpenFile.cpp
@@ -0,0 +1,456 @@
+// $Id: OpenFile.cpp,v 1.1 2008-07-04 15:02:47 geuzaine Exp $
+//
+// Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+// USA.
+// 
+// Please report all bugs and problems to <gmsh@geuz.org>.
+
+#include <string.h>
+#include "Message.h"
+#include "Geo.h"
+#include "GModel.h"
+#include "Numeric.h"
+#include "Context.h"
+#include "OpenFile.h"
+#include "CommandLine.h"
+#include "ReadImg.h"
+#include "OS.h"
+#include "StringUtils.h"
+
+#if !defined(HAVE_NO_PARSER)
+#include "Parser.h"
+#endif
+
+#if !defined(HAVE_NO_POST)
+#include "PView.h"
+#include "PViewData.h"
+#endif
+
+#if defined(HAVE_FLTK)
+#include "GmshUI.h"
+#include "Draw.h"
+#include "SelectBuffer.h"
+#include "GUI.h"
+extern GUI *WID;
+#endif
+
+extern Context_T CTX;
+
+static void FinishUpBoundingBox()
+{
+  double range[3];
+
+  for(int i = 0; i < 3; i++){
+    CTX.cg[i] = 0.5 * (CTX.min[i] + CTX.max[i]);
+    range[i] = CTX.max[i] - CTX.min[i];
+  }
+
+  if(range[0] < CTX.geom.tolerance && 
+     range[1] < CTX.geom.tolerance && 
+     range[2] < CTX.geom.tolerance) {
+    CTX.min[0] -= 1.; CTX.min[1] -= 1.;
+    CTX.max[0] += 1.; CTX.max[1] += 1.;
+    CTX.lc = 1.;
+  }
+  else if(range[0] < CTX.geom.tolerance && 
+          range[1] < CTX.geom.tolerance) {
+    CTX.lc = range[2];
+    CTX.min[0] -= CTX.lc; CTX.min[1] -= CTX.lc;
+    CTX.max[0] += CTX.lc; CTX.max[1] += CTX.lc;
+  }
+  else if(range[0] < CTX.geom.tolerance && 
+          range[2] < CTX.geom.tolerance) {
+    CTX.lc = range[1];
+    CTX.min[0] -= CTX.lc; CTX.max[0] += CTX.lc;
+  }
+  else if(range[1] < CTX.geom.tolerance && 
+          range[2] < CTX.geom.tolerance) {
+    CTX.lc = range[0];
+    CTX.min[1] -= CTX.lc; CTX.max[1] += CTX.lc;
+  }
+  else if(range[0] < CTX.geom.tolerance) {
+    CTX.lc = sqrt(DSQR(range[1]) + DSQR(range[2]));
+    CTX.min[0] -= CTX.lc; CTX.max[0] += CTX.lc;
+  }
+  else if(range[1] < CTX.geom.tolerance) {
+    CTX.lc = sqrt(DSQR(range[0]) + DSQR(range[2]));
+    CTX.min[1] -= CTX.lc; CTX.max[1] += CTX.lc;
+  }
+  else if(range[2] < CTX.geom.tolerance) {
+    CTX.lc = sqrt(DSQR(range[0]) + DSQR(range[1]));
+  }
+  else {
+    CTX.lc = sqrt(DSQR(range[0]) + DSQR(range[1]) + DSQR(range[2]));
+  }
+}
+
+void SetBoundingBox(double xmin, double xmax,
+                    double ymin, double ymax, 
+                    double zmin, double zmax)
+{
+  CTX.min[0] = xmin; CTX.max[0] = xmax;
+  CTX.min[1] = ymin; CTX.max[1] = ymax;
+  CTX.min[2] = zmin; CTX.max[2] = zmax;
+  FinishUpBoundingBox();
+}
+
+void SetBoundingBox()
+{
+  if(CTX.forced_bbox) return;
+
+  SBoundingBox3d bb = GModel::current()->bounds();
+  
+#if !defined(HAVE_NO_POST)
+  if(bb.empty()) {
+    for(unsigned int i = 0; i < PView::list.size(); i++)
+      if(!PView::list[i]->getData()->getBoundingBox().empty())
+        bb += PView::list[i]->getData()->getBoundingBox();
+  }
+#endif
+  
+  if(bb.empty()){
+    bb += SPoint3(-1., -1., -1.);
+    bb += SPoint3(1., 1., 1.);
+  }
+  
+  CTX.min[0] = bb.min().x(); CTX.max[0] = bb.max().x();
+  CTX.min[1] = bb.min().y(); CTX.max[1] = bb.max().y();
+  CTX.min[2] = bb.min().z(); CTX.max[2] = bb.max().z();
+  FinishUpBoundingBox();
+}
+
+// FIXME: this is necessary for now to have an approximate CTX.lc
+// *while* parsing input files (it's important since some of the
+// geometrical operations use a tolerance that depends on
+// CTX.lc). This will be removed once the new database is filled
+// directly during the parsing step
+static SBoundingBox3d temp_bb;
+
+void ResetTemporaryBoundingBox()
+{
+  temp_bb.reset();
+}
+
+void AddToTemporaryBoundingBox(double x, double y, double z)
+{
+  temp_bb += SPoint3(x, y, z);
+  CTX.min[0] = temp_bb.min().x(); CTX.max[0] = temp_bb.max().x();
+  CTX.min[1] = temp_bb.min().y(); CTX.max[1] = temp_bb.max().y();
+  CTX.min[2] = temp_bb.min().z(); CTX.max[2] = temp_bb.max().z();
+  FinishUpBoundingBox();
+}
+
+int ParseFile(const char *f, int close, int warn_if_missing)
+{
+#if defined(HAVE_NO_PARSER)
+  Msg::Error("Gmsh parser is not compiled in this version");
+  return 0;
+#else
+  char yyname_old[256], tmp[256];
+  FILE *yyin_old, *fp;
+  int yylineno_old, yyerrorstate_old, yyviewindex_old;
+
+  // add 'b' for pure Windows programs: opening in text mode messes up
+  // fsetpos/fgetpos (used e.g. for user-defined functions)
+  if(!(fp = fopen(f, "rb"))){
+    if(warn_if_missing) Msg::Warning("Unable to open file '%s'", f);
+    return 0;
+  }
+
+#if !defined(HAVE_NO_POST)
+  int numViewsBefore = PView::list.size();
+#endif
+
+  strncpy(yyname_old, gmsh_yyname, 255);
+  yyin_old = gmsh_yyin;
+  yyerrorstate_old = gmsh_yyerrorstate;
+  yylineno_old = gmsh_yylineno;
+  yyviewindex_old = gmsh_yyviewindex;
+
+  strncpy(gmsh_yyname, f, 255);
+  gmsh_yyin = fp;
+  gmsh_yyerrorstate = 0;
+  gmsh_yylineno = 1;
+  gmsh_yyviewindex = 0;
+
+  fpos_t position;
+  fgetpos(gmsh_yyin, &position);
+  fgets(tmp, sizeof(tmp), gmsh_yyin);
+  fsetpos(gmsh_yyin, &position);
+
+  while(!feof(gmsh_yyin)){
+    gmsh_yyparse();
+    if(gmsh_yyerrorstate > 20){
+      Msg::Error("Too many errors: aborting...");
+      force_yyflush();
+      break;
+    }
+  }
+
+  if(close) fclose(gmsh_yyin);
+
+  strncpy(gmsh_yyname, yyname_old, 255);
+  gmsh_yyin = yyin_old;
+  gmsh_yyerrorstate = yyerrorstate_old;
+  gmsh_yylineno = yylineno_old;
+  gmsh_yyviewindex = yyviewindex_old;
+
+#if defined(HAVE_FLTK) && !defined(HAVE_NO_POST)
+  if(!CTX.batch && numViewsBefore != (int)PView::list.size())
+    WID->update_views();
+#endif
+
+  return 1;
+#endif
+}
+
+void ParseString(const char *str)
+{
+  if(!str) return;
+  FILE *fp;
+  if((fp = fopen(CTX.tmp_filename_fullpath, "w"))) {
+    fprintf(fp, str);
+    fprintf(fp, "\n");
+    fclose(fp);
+    ParseFile(CTX.tmp_filename_fullpath, 1);
+    GModel::current()->importGEOInternals();
+  }
+}
+
+void SetProjectName(const char *name)
+{
+  char no_ext[256], ext[256], base[256];
+  splitFileName(name, no_ext, ext, base);
+
+  if(CTX.filename != name) // yes, we mean to compare the pointers
+    strncpy(CTX.filename, name, 255);
+  strncpy(CTX.no_ext_filename, no_ext, 255);
+  strncpy(CTX.base_filename, base, 255);
+
+  GModel::current()->setName(base);
+    
+#if defined(HAVE_FLTK)
+  if(!CTX.batch) WID->set_title(CTX.filename);
+#endif
+}
+
+int MergeFile(const char *name, int warn_if_missing)
+{
+  // added 'b' for pure Windows programs, since some of these files
+  // contain binary data
+  FILE *fp = fopen(name, "rb");
+  if(!fp){
+    if(warn_if_missing) Msg::Warning("Unable to open file '%s'", name);
+    return 0;
+  }
+
+  char header[256];
+  fgets(header, sizeof(header), fp);
+  fclose(fp);
+
+  Msg::StatusBar(2, true, "Reading '%s'", name);
+
+  char no_ext[256], ext[256], base[256];
+  splitFileName(name, no_ext, ext, base);
+
+#if defined(HAVE_FLTK)
+  if(!CTX.batch) {
+    if(!strcmp(ext, ".gz")) {
+      // the real solution would be to rewrite all our I/O functions in
+      // terms of gzFile, but until then, this is better than nothing
+      if(fl_choice("File '%s' is in gzip format.\n\nDo you want to uncompress it?", 
+                   "Cancel", "Uncompress", NULL, name)){
+        char tmp[256];
+        sprintf(tmp, "gunzip -c %s > %s", name, no_ext);
+        if(SystemCall(tmp))
+          Msg::Error("Failed to uncompress `%s': check directory permissions", name);
+        if(!strcmp(CTX.filename, name)) // this is the project file
+          SetProjectName(no_ext);
+        return MergeFile(no_ext);
+      }
+    }
+  }
+#endif
+
+  CTX.geom.draw = 0; // don't try to draw the model while reading
+
+  GModel *m = GModel::current();
+
+  // FIXME: We need to decide what do do for CAD entities, meshes,
+  // etc.  For meshes we should definitely create one new model per
+  // merge (and reset current() to the previous value after the
+  // merge). This will make multi-step multi-meshes post-pro views
+  // work out of the box.
+  // GModel *m = new GModel;
+
+#if !defined(HAVE_NO_POST)
+  int numViewsBefore = PView::list.size();
+#endif
+
+  int status = 0;
+  if(!strcmp(ext, ".stl") || !strcmp(ext, ".STL")){
+    status = m->readSTL(name, CTX.geom.tolerance);
+  }
+  else if(!strcmp(ext, ".brep") || !strcmp(ext, ".rle") ||
+          !strcmp(ext, ".brp") || !strcmp(ext, ".BRP")){
+    status = m->readOCCBREP(std::string(name));
+  }
+  else if(!strcmp(ext, ".iges") || !strcmp(ext, ".IGES") ||
+          !strcmp(ext, ".igs") || !strcmp(ext, ".IGS")){
+    status = m->readOCCIGES(std::string(name));
+  }
+  else if(!strcmp(ext, ".step") || !strcmp(ext, ".STEP") ||
+          !strcmp(ext, ".stp") || !strcmp(ext, ".STP")){
+    status = m->readOCCSTEP(std::string(name));
+  }
+  else if(!strcmp(ext, ".unv") || !strcmp(ext, ".UNV")){
+    status = m->readUNV(name);
+  }
+  else if(!strcmp(ext, ".wrl") || !strcmp(ext, ".WRL") || 
+          !strcmp(ext, ".vrml") || !strcmp(ext, ".VRML") ||
+          !strcmp(ext, ".iv") || !strcmp(ext, ".IV")){
+    status = m->readVRML(name);
+  }
+  else if(!strcmp(ext, ".mesh") || !strcmp(ext, ".MESH")){
+    status = m->readMESH(name);
+  }
+#if !defined(HAVE_NO_POST)
+  else if(!strcmp(ext, ".med") || !strcmp(ext, ".MED") ||
+	  !strcmp(ext, ".mmed") || !strcmp(ext, ".MMED") ||
+	  !strcmp(ext, ".rmed") || !strcmp(ext, ".RMED")){
+    status = GModel::readMED(name);
+    if(status > 1) status = PView::readMED(name);
+  }
+#endif
+  else if(!strcmp(ext, ".bdf") || !strcmp(ext, ".BDF") ||
+          !strcmp(ext, ".nas") || !strcmp(ext, ".NAS")){
+    status = m->readBDF(name);
+  }
+  else if(!strcmp(ext, ".p3d") || !strcmp(ext, ".P3D")){
+    status = m->readP3D(name);
+  }
+  else if(!strcmp(ext, ".fm") || !strcmp(ext, ".FM")) {
+    status = m->readFourier(name);
+  }
+#if defined(HAVE_FLTK)
+  else if(!strcmp(ext, ".pnm") || !strcmp(ext, ".PNM") ||
+          !strcmp(ext, ".pbm") || !strcmp(ext, ".PBM") ||
+          !strcmp(ext, ".pgm") || !strcmp(ext, ".PGM") ||
+          !strcmp(ext, ".ppm") || !strcmp(ext, ".PPM")) {
+    status = read_pnm(name);
+  }
+  else if(!strcmp(ext, ".bmp") || !strcmp(ext, ".BMP")) {
+    status = read_bmp(name);
+  }
+#if defined(HAVE_LIBJPEG)
+  else if(!strcmp(ext, ".jpg") || !strcmp(ext, ".JPG") ||
+          !strcmp(ext, ".jpeg") || !strcmp(ext, ".JPEG")) {
+    status = read_jpeg(name);
+  }
+#endif
+#if defined(HAVE_LIBPNG)
+  else if(!strcmp(ext, ".png") || !strcmp(ext, ".PNG")) {
+    status = read_png(name);
+  }
+#endif
+#endif
+  else {
+    CTX.geom.draw = 1;
+    if(!strncmp(header, "$PTS", 4) || !strncmp(header, "$NO", 3) || 
+       !strncmp(header, "$PARA", 5) || !strncmp(header, "$ELM", 4) ||
+       !strncmp(header, "$MeshFormat", 11)) {
+      status = m->readMSH(name);
+#if !defined(HAVE_NO_POST)
+      if(status > 1) status = PView::readMSH(name);
+#endif
+    }
+#if !defined(HAVE_NO_POST)
+    else if(!strncmp(header, "$PostFormat", 11) || 
+            !strncmp(header, "$View", 5)) {
+      status = PView::readPOS(name);
+    }
+#endif
+    else {
+      status = m->readGEO(name);
+    }
+  }
+
+  SetBoundingBox();
+
+  CTX.geom.draw = 1;
+  CTX.mesh.changed = ENT_ALL;
+
+#if defined(HAVE_FLTK) && !defined(HAVE_NO_POST)
+  if(!CTX.batch && numViewsBefore != (int)PView::list.size())
+    WID->update_views();
+#endif
+
+  Msg::StatusBar(2, true, "Read '%s'", name);
+  return status;
+}
+
+void OpenProject(const char *name)
+{
+  if(CTX.threads_lock) {
+    Msg::Info("I'm busy! Ask me that later...");
+    return;
+  }
+  CTX.threads_lock = 1;
+
+  // FIXME: this will change once we clarify Open/Merge/Clear
+#if !defined(HAVE_NO_POST)
+  for(int i = PView::list.size() - 1; i >= 0; i--)
+    if(PView::list[i]->getData()->hasModel(GModel::current()))
+      delete PView::list[i];
+#endif
+  GModel::current()->destroy();
+  GModel::current()->getGEOInternals()->destroy();
+
+  // temporary hack until we fill the current GModel on the fly during
+  // parsing
+  ResetTemporaryBoundingBox();
+
+  SetProjectName(name);
+  MergeFile(name);
+
+  CTX.threads_lock = 0;
+
+#if defined(HAVE_FLTK)
+  if(!CTX.batch){
+    WID->reset_visibility();
+    WID->update_views();
+  }
+  ZeroHighlight();
+#endif
+}
+
+void OpenProjectMacFinder(const char *filename)
+{
+  static int first = 1;
+  if(first || CTX.batch){
+    // just copy the filename: it will be opened when the GUI is ready
+    // in main()
+    strncpy(CTX.filename, filename, 255);
+    first = 0;
+  }
+  else{
+    OpenProject(filename);
+#if defined(HAVE_FLTK)
+    Draw();
+#endif
+  }
+}
diff --git a/Common/OpenFile.h b/Common/OpenFile.h
new file mode 100644
index 0000000000000000000000000000000000000000..e2407e763c4aa58043fd6e2e3f78a6ce1dbf8361
--- /dev/null
+++ b/Common/OpenFile.h
@@ -0,0 +1,34 @@
+#ifndef _OPENFILE_H_
+#define _OPENFILE_H_
+
+// Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+// USA.
+// 
+// Please report all bugs and problems to <gmsh@geuz.org>.
+
+int ParseFile(const char *filename, int close, int warn_if_missing=0);
+void ParseString(const char *str);
+void OpenProject(const char *filename);
+void OpenProjectMacFinder(const char *filename);
+int MergeFile(const char *filename, int warn_if_missing=0);
+void SetBoundingBox(double xmin, double xmax,
+                    double ymin, double ymax, 
+                    double zmin, double zmax);
+void SetBoundingBox();
+void AddToTemporaryBoundingBox(double x, double y, double z);
+
+#endif