diff --git a/Common/CreateFile.cpp b/Common/CreateFile.cpp
index c4321ec5ead11f038957e75095903a5f96b96970..55bca74e0258e41a4ce32627a2f9e5d25960e978 100644
--- a/Common/CreateFile.cpp
+++ b/Common/CreateFile.cpp
@@ -3,7 +3,6 @@
 // See the LICENSE.txt file for license information. Please report all
 // bugs and problems to <gmsh@geuz.org>.
 
-#include <string.h>
 #include "GmshConfig.h"
 #include "GmshMessage.h"
 #include "GModel.h"
@@ -26,53 +25,41 @@
 
 int GuessFileFormatFromFileName(std::string fileName)
 {
-  int len;
-  char ext[256];
-  const char *name = fileName.c_str();
-  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, ".diff")) return FORMAT_DIFF;
-  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;
+  std::string ext = SplitFileName(fileName)[2];
+  if     (ext == ".geo")  return FORMAT_GEO;
+  else if(ext == ".msh")  return FORMAT_MSH;
+  else if(ext == ".pos")  return FORMAT_POS;
+  else if(ext == ".opt")  return FORMAT_OPT;
+  else if(ext == ".unv")  return FORMAT_UNV;
+  else if(ext == ".vtk")  return FORMAT_VTK;
+  else if(ext == ".stl")  return FORMAT_STL;
+  else if(ext == ".cgns") return FORMAT_CGNS;
+  else if(ext == ".med")  return FORMAT_MED;
+  else if(ext == ".mesh") return FORMAT_MESH;
+  else if(ext == ".bdf")  return FORMAT_BDF;
+  else if(ext == ".diff") return FORMAT_DIFF;
+  else if(ext == ".nas")  return FORMAT_BDF;
+  else if(ext == ".p3d")  return FORMAT_P3D;
+  else if(ext == ".wrl")  return FORMAT_VRML;
+  else if(ext == ".vrml") return FORMAT_VRML;
+  else if(ext == ".gif")  return FORMAT_GIF;
+  else if(ext == ".jpg")  return FORMAT_JPEG;
+  else if(ext == ".jpeg") return FORMAT_JPEG;
+  else if(ext == ".png")  return FORMAT_PNG;
+  else if(ext == ".ps")   return FORMAT_PS;
+  else if(ext == ".eps")  return FORMAT_EPS;
+  else if(ext == ".pdf")  return FORMAT_PDF;
+  else if(ext == ".tex")  return FORMAT_TEX;
+  else if(ext == ".svg")  return FORMAT_SVG;
+  else if(ext == ".ppm")  return FORMAT_PPM;
+  else if(ext == ".yuv")  return FORMAT_YUV;
   else                           return -1;
 }
 
 std::string GetDefaultFileName(int format)
 {
-  char no_ext[256], ext[256], base[256];
-  SplitFileName(GModel::current()->getFileName().c_str(), no_ext, ext, base);
-  std::string name(no_ext);
+  std::vector<std::string> split = SplitFileName(GModel::current()->getFileName());
+  std::string name = split[0] + split[1];
   switch(format){
   case FORMAT_GEO:  name += ".geo_unrolled"; break;
   case FORMAT_MSH:  name += ".msh"; break;
@@ -150,9 +137,6 @@ void CreateOutputFile(std::string fileName, int format)
   if(fileName.empty())
     fileName = GetDefaultFileName(format);
 
-  char no_ext[256], ext[256], base[256];
-  SplitFileName(fileName.c_str(), no_ext, ext, base);
-
   int oldformat = CTX::instance()->print.format;
   CTX::instance()->print.format = format;
   CTX::instance()->printing = 1;
@@ -308,7 +292,7 @@ void CreateOutputFile(std::string fileName, int format)
         Msg::Error("Unable to open file '%s'", fileName.c_str());
         break;
       }
-
+      std::string base = SplitFileName(fileName)[1];
       GLint width = GUI::instance()->getCurrentOpenglWindow()->w();
       GLint height = GUI::instance()->getCurrentOpenglWindow()->h();
       GLint viewport[4] = {0, 0, width, height};
@@ -342,9 +326,9 @@ void CreateOutputFile(std::string fileName, int format)
       int res = GL2PS_OVERFLOW;
       while(res == GL2PS_OVERFLOW) {
         buffsize += 2048 * 2048;
-        gl2psBeginPage(base, "Gmsh", viewport, 
+        gl2psBeginPage(base.c_str(), "Gmsh", viewport, 
                        psformat, pssort, psoptions, GL_RGBA, 0, NULL, 
-                       15, 20, 10, buffsize, fp, base);
+                       15, 20, 10, buffsize, fp, base.c_str());
         if(CTX::instance()->print.epsQuality == 0){
           double modelview[16], projection[16];
           glGetDoublev(GL_PROJECTION_MATRIX, projection);
@@ -382,6 +366,7 @@ void CreateOutputFile(std::string fileName, int format)
         Msg::Error("Unable to open file '%s'", fileName.c_str());
         break;
       }
+      std::string base = SplitFileName(fileName)[1];
       GLint width = GUI::instance()->getCurrentOpenglWindow()->w();
       GLint height = GUI::instance()->getCurrentOpenglWindow()->h();
       GLint viewport[4] = {0, 0, width, height};
@@ -389,9 +374,9 @@ void CreateOutputFile(std::string fileName, int format)
       int res = GL2PS_OVERFLOW;
       while(res == GL2PS_OVERFLOW) {
         buffsize += 2048 * 2048;
-        gl2psBeginPage(base, "Gmsh", viewport,
+        gl2psBeginPage(base.c_str(), "Gmsh", viewport,
                        GL2PS_TEX, GL2PS_NO_SORT, GL2PS_NONE, GL_RGBA, 0, NULL, 
-                       0, 0, 0, buffsize, fp, base);
+                       0, 0, 0, buffsize, fp, base.c_str());
         PixelBuffer buffer(width, height, GL_RGB, GL_UNSIGNED_BYTE);
         int oldtext = CTX::instance()->print.text;
         CTX::instance()->print.text = 1;
diff --git a/Common/OpenFile.cpp b/Common/OpenFile.cpp
index 9d51557af4a5715d3c6142bf654bdb50be661063..bc5a3d4ebfed7cf524978ca2c983789878fe07f9 100644
--- a/Common/OpenFile.cpp
+++ b/Common/OpenFile.cpp
@@ -211,10 +211,8 @@ void ParseString(std::string str)
 
 static void SetProjectName(std::string fileName)
 {
-  char no_ext[256], ext[256], base[256];
-  SplitFileName(fileName.c_str(), no_ext, ext, base);
   GModel::current()->setFileName(fileName);
-  GModel::current()->setName(base);
+  GModel::current()->setName(SplitFileName(fileName)[1]);
 }
 
 int MergeFile(std::string fileName, bool warnIfMissing)
@@ -242,21 +240,21 @@ int MergeFile(std::string fileName, bool warnIfMissing)
 
   Msg::StatusBar(2, true, "Reading '%s'", fileName.c_str());
 
-  char no_ext[256], ext[256], base[256];
-  SplitFileName(fileName.c_str(), no_ext, ext, base);
+  std::vector<std::string> split = SplitFileName(fileName);
+  std::string noExt = split[0] + split[1], ext = split[2];
 
 #if defined(HAVE_FLTK)
   if(GUI::available()) {
-    if(!strcmp(ext, ".gz")) {
+    if(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, fileName.c_str())){
-        if(SystemCall(std::string("gunzip -c ") + fileName + " > " + no_ext))
+        if(SystemCall(std::string("gunzip -c ") + fileName + " > " + noExt))
           Msg::Error("Failed to uncompress `%s': check directory permissions", 
                      fileName.c_str());
-        SetProjectName(no_ext);
-        return MergeFile(no_ext);
+        SetProjectName(noExt);
+        return MergeFile(noExt);
       }
     }
   }
@@ -269,71 +267,62 @@ int MergeFile(std::string fileName, bool warnIfMissing)
 #endif
 
   int status = 0;
-  if(!strcmp(ext, ".stl") || !strcmp(ext, ".STL")){
+  if(ext == ".stl" || ext == ".STL"){
     status = GModel::current()->readSTL(fileName, CTX::instance()->geom.tolerance);
   }
-  else if(!strcmp(ext, ".brep") || !strcmp(ext, ".rle") ||
-          !strcmp(ext, ".brp") || !strcmp(ext, ".BRP")){
+  else if(ext == ".brep" || ext == ".rle" || ext == ".brp" || ext == ".BRP"){
     status = GModel::current()->readOCCBREP(fileName);
   }
-  else if(!strcmp(ext, ".iges") || !strcmp(ext, ".IGES") ||
-          !strcmp(ext, ".igs") || !strcmp(ext, ".IGS")){
+  else if(ext == ".iges" || ext == ".IGES" || ext == ".igs" || ext == ".IGS"){
     status = GModel::current()->readOCCIGES(fileName);
   }
-  else if(!strcmp(ext, ".step") || !strcmp(ext, ".STEP") ||
-          !strcmp(ext, ".stp") || !strcmp(ext, ".STP")){
+  else if(ext == ".step" || ext == ".STEP" || ext == ".stp" || ext == ".STP"){
     status = GModel::current()->readOCCSTEP(fileName);
   }
-  else if(!strcmp(ext, ".unv") || !strcmp(ext, ".UNV")){
+  else if(ext == ".unv" || ext == ".UNV"){
     status = GModel::current()->readUNV(fileName);
   }
-  else if(!strcmp(ext, ".vtk") || !strcmp(ext, ".VTK")){
+  else if(ext == ".vtk" || ext == ".VTK"){
     status = GModel::current()->readVTK(fileName, CTX::instance()->bigEndian);
   }
-  else if(!strcmp(ext, ".wrl") || !strcmp(ext, ".WRL") || 
-          !strcmp(ext, ".vrml") || !strcmp(ext, ".VRML") ||
-          !strcmp(ext, ".iv") || !strcmp(ext, ".IV")){
+  else if(ext == ".wrl" || ext == ".WRL" || ext == ".vrml" || ext == ".VRML" ||
+          ext == ".iv" || ext == ".IV"){
     status = GModel::current()->readVRML(fileName);
   }
-  else if(!strcmp(ext, ".mesh") || !strcmp(ext, ".MESH")){
+  else if(ext == ".mesh" || ext == ".MESH"){
     status = GModel::current()->readMESH(fileName);
   }
-  else if(!strcmp(ext, ".med") || !strcmp(ext, ".MED") ||
-	  !strcmp(ext, ".mmed") || !strcmp(ext, ".MMED") ||
-	  !strcmp(ext, ".rmed") || !strcmp(ext, ".RMED")){
+  else if(ext == ".med" || ext == ".MED" || ext == ".mmed" || ext == ".MMED" ||
+	  ext == ".rmed" || ext == ".RMED"){
     status = GModel::readMED(fileName);
 #if !defined(HAVE_NO_POST)
     if(status > 1) status = PView::readMED(fileName);
 #endif
   }
-  else if(!strcmp(ext, ".bdf") || !strcmp(ext, ".BDF") ||
-          !strcmp(ext, ".nas") || !strcmp(ext, ".NAS")){
+  else if(ext == ".bdf" || ext == ".BDF" || ext == ".nas" || ext == ".NAS"){
     status = GModel::current()->readBDF(fileName);
   }
-  else if(!strcmp(ext, ".p3d") || !strcmp(ext, ".P3D")){
+  else if(ext == ".p3d" || ext == ".P3D"){
     status = GModel::current()->readP3D(fileName);
   }
-  else if(!strcmp(ext, ".fm") || !strcmp(ext, ".FM")) {
+  else if(ext == ".fm" || ext == ".FM") {
     status = GModel::current()->readFourier(fileName);
   }
 #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")) {
+  else if(ext == ".pnm" || ext == ".PNM" || ext == ".pbm" || ext == ".PBM" ||
+          ext == ".pgm" || ext == ".PGM" || ext == ".ppm" || ext == ".PPM") {
     status = read_pnm(fileName);
   }
-  else if(!strcmp(ext, ".bmp") || !strcmp(ext, ".BMP")) {
+  else if(ext == ".bmp" || ext == ".BMP") {
     status = read_bmp(fileName);
   }
 #if defined(HAVE_LIBJPEG)
-  else if(!strcmp(ext, ".jpg") || !strcmp(ext, ".JPG") ||
-          !strcmp(ext, ".jpeg") || !strcmp(ext, ".JPEG")) {
+  else if(ext == ".jpg" || ext == ".JPG" || ext == ".jpeg" || ext == ".JPEG") {
     status = read_jpeg(fileName);
   }
 #endif
 #if defined(HAVE_LIBPNG)
-  else if(!strcmp(ext, ".png") || !strcmp(ext, ".PNG")) {
+  else if(ext == ".png" || ext == ".PNG") {
     status = read_png(fileName);
   }
 #endif
diff --git a/Common/StringUtils.cpp b/Common/StringUtils.cpp
index 2a975fa649fa40020c5e582ebcdf68864b7b7d1c..b266c3228e7d68d10c1add744a453c4b6d80371c 100644
--- a/Common/StringUtils.cpp
+++ b/Common/StringUtils.cpp
@@ -72,24 +72,20 @@ std::string FixWindowsPath(const char *in)
 #endif
 }
 
-void SplitFileName(const char *name, char *no_ext, char *ext, char *base)
+std::vector<std::string> SplitFileName(std::string fileName)
 {
-  strcpy(no_ext, name);
-  strcpy(ext, "");
-  for(int i = strlen(name) - 1; i >= 0; i--){
-    if(name[i] == '.'){
-      strcpy(ext, &name[i]);
-      no_ext[i] = '\0';
-      break;
-    }
-  }
-  strcpy(base, no_ext);
-  for(int i = strlen(no_ext) - 1; i >= 0; i--){
-    if(no_ext[i] == '/' || no_ext[i] == '\\'){
-      strcpy(base, &no_ext[i + 1]);
-      break;
-    }
-  }
+  // returns [path, baseName, extension]
+  int idot = fileName.find_last_of('.');
+  int islash = fileName.find_last_of("/\\");
+  if(idot == std::string::npos) idot = -1;
+  if(islash == std::string::npos) islash = -1;
+  std::vector<std::string> s(3);
+  if(idot > 0)
+    s[2] = fileName.substr(idot);
+  if(islash > 0)
+    s[0] = fileName.substr(0, islash + 1);
+  s[1] = fileName.substr(s[0].size(), fileName.size() - s[0].size() - s[2].size());
+  return s;
 }
 
 std::vector<std::string> SplitWhiteSpace(std::string in, unsigned int len)
diff --git a/Common/StringUtils.h b/Common/StringUtils.h
index 0d029fd085fc1056f4e500047afa0c2971f98abb..f6cb6990ef974620941bd87995f2fa538b8756b3 100644
--- a/Common/StringUtils.h
+++ b/Common/StringUtils.h
@@ -14,7 +14,7 @@ void SwapBytes(char *array, int size, int n);
 std::string ExtractDoubleQuotedString(const char *str, int len);
 std::string SanitizeTeXString(const char *in, int equation);
 std::string FixWindowsPath(const char *in);
-void SplitFileName(const char *name, char *no_ext, char *ext, char *base);
+std::vector<std::string> SplitFileName(std::string fileName);
 std::vector<std::string> SplitWhiteSpace(std::string in, unsigned int len);
 void ReplaceMultiFormat(const char *in, const char *val, char *out);
 
diff --git a/Fltk/projectionEditor.cpp b/Fltk/projectionEditor.cpp
index 1057172454b5835412957041f6d23cb5528fe667..9e3129a0d95b8a37077ede1534c26223dedaa185 100644
--- a/Fltk/projectionEditor.cpp
+++ b/Fltk/projectionEditor.cpp
@@ -508,9 +508,7 @@ static void save_projection_cb(Fl_Widget *w, void *data)
         Msg::Error("Unable to open file `%s'", name.c_str());
         return;
       }
-      char no_ext[256], ext[256], base[256];
-      SplitFileName(name.c_str(), no_ext, ext, base);
-      fprintf(fp, "1\n%s\n%s\n", base, ps->GetName().c_str());
+      fprintf(fp, "1\n%s\n%s\n", SplitFileName(name)[1].c_str(), ps->GetName().c_str());
       for(unsigned int i = 0; i < p->parameters.size(); i++)
         fprintf(fp, "%.16g\n", p->parameters[i]->value());
       fclose(fp);
diff --git a/Fltk/solverWindow.cpp b/Fltk/solverWindow.cpp
index 117e4271b0d18ea6d7703328a511bb32d6dc0112..2348d9d46162b03daab6e0f0da5bafff5f2ee576 100644
--- a/Fltk/solverWindow.cpp
+++ b/Fltk/solverWindow.cpp
@@ -34,11 +34,9 @@ void solver_cb(Fl_Widget *w, void *data)
   }
   if(first[num]) {
     first[num] = 0;
-    char file[256], no_ext[256], ext[256], base[256];
-    SplitFileName(GModel::current()->getFileName().c_str(), no_ext, ext, base);
-    strcpy(file, no_ext);
-    strcat(file, SINFO[num].extension.c_str());
-    GUI::instance()->solver[num]->input[0]->value(file);
+    std::vector<std::string> split = SplitFileName(GModel::current()->getFileName());
+    std::string file = split[0] + split[1] + SINFO[num].extension;
+    GUI::instance()->solver[num]->input[0]->value(file.c_str());
   }
   // show the window before calling Solver() to avoid race condition on
   // Windows (if the message window pops up die to an error, the window
@@ -46,8 +44,7 @@ void solver_cb(Fl_Widget *w, void *data)
   GUI::instance()->solver[num]->win->show();
 
   if(SINFO[num].nboptions) {
-    std::string file = FixWindowsPath
-      (GUI::instance()->solver[num]->input[0]->value());
+    std::string file = FixWindowsPath(GUI::instance()->solver[num]->input[0]->value());
     char tmp[256], tmp2[256];
     sprintf(tmp, "\"%s\"", file.c_str());
     sprintf(tmp2, SINFO[num].name_command.c_str(), tmp);
diff --git a/Geo/GeoStringInterface.cpp b/Geo/GeoStringInterface.cpp
index fc7c434c97d1905bf6b5ac3b05a4b525fb9108c9..96820dfc9138436750bf5932790cf0f874b96903 100644
--- a/Geo/GeoStringInterface.cpp
+++ b/Geo/GeoStringInterface.cpp
@@ -86,9 +86,8 @@ void add_infile(std::string text, std::string fileName, bool deleted_something)
   }
   
   if(!CTX::instance()->expertMode) {
-    char no_ext[256], ext[256], base[256];
-    SplitFileName(fileName.c_str(), no_ext, ext, base);
-    if(strlen(ext) && strcmp(ext, ".geo") && strcmp(ext, ".GEO")){
+    std::string ext = SplitFileName(fileName)[2];
+    if(ext.size() && ext != ".geo" && ext != ".GEO"){
       char question[1024];
       sprintf(question, 
               "A scripting command is going to be appended to a non-`.geo' file.\n\n"
diff --git a/Graphics/drawContext.cpp b/Graphics/drawContext.cpp
index 6872a6b7f1cbca2be5e54cf8e9984c232187e2ae..e48e8f09eb21f806d574bb50fbbc2bcb2c6565d4 100644
--- a/Graphics/drawContext.cpp
+++ b/Graphics/drawContext.cpp
@@ -168,7 +168,7 @@ void drawContext::setEulerAnglesFromRotationMatrix()
 {
   r[1] = asin(rot[8]); // Calculate Y-axis angle
   double C =  cos(r[1]);
-  r[1] *=  180. / M_PI;
+  r[1] *= 180. / M_PI;
   if(fabs(C) > 0.005){ // Gimball lock?
     double tmpx =  rot[10] / C; // No, so get X-axis angle
     double tmpy = -rot[9] / C;
@@ -440,7 +440,6 @@ void drawContext::initProjection(int xpick, int ypick, int wpick, int hpick)
     glEnable(GL_DEPTH_TEST);
   }
 
-
   if(CTX::instance()->ortho) {
     glOrtho(vxmin, vxmax, vymin, vymax, clip_near, clip_far);
     glMatrixMode(GL_MODELVIEW);