diff --git a/Common/GmshDaemon.cpp b/Common/GmshDaemon.cpp
index d5ef10b4c3f645a5bb4f479fa88edd01f44e2119..43aeb05178caf0c11db31c43ed2ce40926ab4453 100644
--- a/Common/GmshDaemon.cpp
+++ b/Common/GmshDaemon.cpp
@@ -17,6 +17,7 @@ int GmshDaemon(std::string socket)
     return 1;
   }
   client.Start();
+  client.Info("Server sucessfully started. Listening...");
 
   // read large data file,
   // initialize mpi job,
diff --git a/Common/GmshSocket.h b/Common/GmshSocket.h
index f9e95eb1c69a1f9b0fee07020bf856facb6bd0c7..5210367f0b538829446423cd563a3fa9b83a8b47 100644
--- a/Common/GmshSocket.h
+++ b/Common/GmshSocket.h
@@ -125,17 +125,18 @@ class GmshSocket{
   // seconds and microseconds == 0 we check for available data and
   // return immediately, i.e., we do polling). Returns 0 when data is
   // available.
-  int Select(int socket, int seconds, int microseconds)
+  int Select(int seconds, int microseconds, int socket=-1)
   {
+    int s = (socket < 0) ? _sock : socket;
     struct timeval tv;
     tv.tv_sec = seconds;
     tv.tv_usec = microseconds;
     fd_set rfds;
     FD_ZERO(&rfds);
-    FD_SET(socket, &rfds);
+    FD_SET(s, &rfds);
     // select checks all IO descriptors between 0 and its first arg,
     // minus 1... hence the +1 below
-    return select(socket + 1, &rfds, NULL, NULL, &tv);
+    return select(s + 1, &rfds, NULL, NULL, &tv);
   }
   void SendString(int type, const char *str)
   {
@@ -146,6 +147,19 @@ class GmshSocket{
     // send body
     _SendData(str, len);
   }
+  void Info(const char *str){ SendString(INFO, str); }
+  void Warning(const char *str){ SendString(WARNING, str); }
+  void Error(const char *str){ SendString(ERROR, str); }
+  void Progress(const char *str){ SendString(PROGRESS, str); }
+  void MergeFile(const char *str){ SendString(MERGE_FILE, str); }
+  void ParseString(const char *str){ SendString(PARSE_STRING, str); }
+  void SpeedTest(const char *str){ SendString(SPEED_TEST, str); }
+  void Option(int num, const char *str)
+  {
+    if(num < 1) num = 1;
+    if(num > 5) num = 5;
+    SendString(OPTION_1 + num - 1, str);
+  }
   int ReceiveHeader(int *type, int *len)
   {
     bool swap = false;
@@ -201,8 +215,7 @@ class GmshClient : public GmshSocket {
 #if !defined(WIN32) || defined(__CYGWIN__)
       // UNIX socket (testing ":" is not enough with Windows paths)
       _sock = socket(PF_UNIX, SOCK_STREAM, 0);
-      if(_sock < 0)
-        return -1;  // Error: Couldn't create socket
+      if(_sock < 0) return -1;
       // try to connect socket to given name
       struct sockaddr_un addr_un;
       memset((char *) &addr_un, 0, sizeof(addr_un));
@@ -220,8 +233,7 @@ class GmshClient : public GmshSocket {
     else{
       // TCP/IP socket
       _sock = socket(AF_INET, SOCK_STREAM, 0);
-      if(_sock < 0)
-        return -1; // Error: Couldn't create socket
+      if(_sock < 0) return -1;
       // try to connect socket to host:port
       const char *port = strstr(sockname, ":");
       int portno = atoi(port + 1);
@@ -233,7 +245,7 @@ class GmshClient : public GmshSocket {
       struct hostent *server;
       if(!(server = gethostbyname(remote))){
         CloseSocket(_sock);
-        return -3; // Error: No such host
+        return -3; // no such host
       }
       struct sockaddr_in addr_in;
       memset((char *) &addr_in, 0, sizeof(addr_in));
@@ -247,11 +259,7 @@ class GmshClient : public GmshSocket {
       }
     }
     CloseSocket(_sock);
-    return -2; // Error: Couldn't connect
-  }
-  int Select(int seconds, int microseconds)
-  {
-    return GmshSocket::Select(_sock, seconds, microseconds);
+    return -2; // couldn't connect
   }
   void Start()
   {
@@ -264,19 +272,6 @@ class GmshClient : public GmshSocket {
     SendString(START, tmp);
   }
   void Stop(){ SendString(STOP, "Goodbye!"); }
-  void Info(const char *str){ SendString(INFO, str); }
-  void Warning(const char *str){ SendString(WARNING, str); }
-  void Error(const char *str){ SendString(ERROR, str); }
-  void Progress(const char *str){ SendString(PROGRESS, str); }
-  void MergeFile(const char *str){ SendString(MERGE_FILE, str); }
-  void ParseString(const char *str){ SendString(PARSE_STRING, str); }
-  void SpeedTest(const char *str){ SendString(SPEED_TEST, str); }
-  void Option(int num, const char *str)
-  {
-    if(num < 1) num = 1;
-    if(num > 5) num = 5;
-    SendString(OPTION_1 + num - 1, str);
-  }
   void Disconnect(){ CloseSocket(_sock); }
 };
 
@@ -287,10 +282,9 @@ class GmshServer : public GmshSocket{
   GmshServer() : GmshSocket(), _portno(-1) {}
   virtual ~GmshServer(){}
   virtual int SystemCall(const char *str) = 0;
-  virtual int NonBlockingWait(int socket, int num, double waitint) = 0;
-  int StartClient(const char *command, const char *sockname=0, int timeout=5)
+  virtual int NonBlockingWait(int socket, int num, double waitint, double timeout) = 0;
+  int Start(int num, const char *command, const char *sockname, double timeout)
   {
-    bool justwait = (!command || !strlen(command));
     _sockname = sockname;
 
     // no socket? launch the command directly
@@ -308,8 +302,7 @@ class GmshServer : public GmshSocket{
       unlink(_sockname);
       // create a socket
       tmpsock = socket(PF_UNIX, SOCK_STREAM, 0);
-      if(tmpsock < 0)
-        return -1;  // Error: Couldn't create socket
+      if(tmpsock < 0) throw "Couldn't create socket";
       // bind the socket to its name
       struct sockaddr_un addr_un;
       memset((char *) &addr_un, 0, sizeof(addr_un));
@@ -317,12 +310,12 @@ class GmshServer : public GmshSocket{
       addr_un.sun_family = AF_UNIX;
       if(bind(tmpsock, (struct sockaddr *)&addr_un, sizeof(addr_un)) < 0){
         CloseSocket(tmpsock);
-        return -2;  // Error: Couldn't bind socket to name
+        throw "Couldn't bind socket to name";
       }
       // change permissions on the socket name in case it has to be rm'd later
       chmod(_sockname, 0666);
 #else
-      return -7; // Unix sockets not available on Windows
+      throw "Unix sockets not available on Windows";
 #endif
     }
     else{
@@ -336,7 +329,7 @@ class GmshServer : public GmshSocket{
 #else
       if(tmpsock == INVALID_SOCKET)
 #endif
-        return -1;  // Error: Couldn't create socket
+        throw "Couldn't create socket";
       // bind the socket to its name
       struct sockaddr_in addr_in;
       memset((char *) &addr_in, 0, sizeof(addr_in));
@@ -345,33 +338,33 @@ class GmshServer : public GmshSocket{
       addr_in.sin_port = htons(_portno);
       if(bind(tmpsock, (struct sockaddr *)&addr_in, sizeof(addr_in)) < 0){
         CloseSocket(tmpsock);
-        return -2;  // Error: Couldn't bind socket to name
+        throw "Couldn't bind socket to name";
       }
     }
 
-    if(!justwait)
+    if(command && strlen(command)){
       SystemCall(command); // Start the solver
-    
+    }
+    else{
+      timeout = 0.; // no command launched: don't set a timeout
+    }
+
     // listen on socket (queue up to 20 connections before having
     // them automatically rejected)
     if(listen(tmpsock, 20)){
       CloseSocket(tmpsock);
-      return -3;  // Error: Socket listen failed
+      throw "Socket listen failed";
     }
     
-    if(justwait){
-      // wait indefinitely until we get data
-      if(NonBlockingWait(tmpsock, -1, 0.5)){
-        CloseSocket(tmpsock);
-        return -6; // not an actual error: we just stopped listening
+    // wait until we get data
+    int ret = NonBlockingWait(tmpsock, num, 0.5, timeout);
+    if(ret){
+      CloseSocket(tmpsock);
+      if(ret == 2){
+        throw "Socket listening timeout";
       }
-    }
-    else{
-      // Wait at most timeout seconds for data, issue error if no
-      // connection in that amount of time
-      if(!Select(tmpsock, timeout, 0)){
-        CloseSocket(tmpsock);
-        return -4;  // Error: Socket listening timeout
+      else{
+        return -1; // stopped listening
       }
     }
 
@@ -381,8 +374,6 @@ class GmshServer : public GmshSocket{
       struct sockaddr_un from_un;
       socklen_t len = sizeof(from_un);
       _sock = accept(tmpsock, (struct sockaddr *)&from_un, &len);
-#else
-      _sock = -7; // Unix sockets not available on Windows
 #endif
     }
     else{
@@ -393,7 +384,7 @@ class GmshServer : public GmshSocket{
     CloseSocket(tmpsock);
 
     if(_sock < 0)
-      return -5;  // Error: Socket accept failed
+      throw "Socket accept failed";
     return _sock;
   }
   int Shutdown()
diff --git a/Common/StringUtils.cpp b/Common/StringUtils.cpp
index fa9483fcb62773815f12aba022d3db8c2f908991..ba7f28b3452ca8931491077d89eb1c935848c624 100644
--- a/Common/StringUtils.cpp
+++ b/Common/StringUtils.cpp
@@ -62,14 +62,14 @@ std::string SanitizeTeXString(const char *in, int equation)
   return out;
 }
 
-std::string FixWindowsPath(const char *in)
+std::string FixWindowsPath(std::string in)
 {
 #if defined(__CYGWIN__)
   char tmp[1024];
-  cygwin_conv_to_win32_path(in, tmp);
+  cygwin_conv_to_win32_path(in.c_str(), tmp);
   return std::string(tmp);
 #else
-  return std::string(in);
+  return in;
 #endif
 }
 
@@ -115,6 +115,21 @@ std::vector<std::string> SplitWhiteSpace(std::string in, unsigned int len)
   return out;
 }
 
+std::string ReplacePercentS(std::string in, std::string val)
+{
+  std::string out;
+  for(unsigned int i = 0; i < in.size(); i++){
+    if(in[i] == '%' && i + 1 < in.size() && in[i + 1] == 's'){
+      out += val;
+      i++;
+    }
+    else{
+      out += in[i];
+    }
+  }
+  return out;
+}
+
 void ReplaceMultiFormat(const char *in, const char *val, char *out)
 {
   unsigned int i = 0, j = 0;
diff --git a/Common/StringUtils.h b/Common/StringUtils.h
index ce4111b2ee4e15efb94ea8fae1d2b363b41db23e..c0f34a6e1ee5bfbdc5deeb2e73a63f281311f5f5 100644
--- a/Common/StringUtils.h
+++ b/Common/StringUtils.h
@@ -13,10 +13,11 @@
 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);
+std::string FixWindowsPath(std::string in);
 std::string FixRelativePath(std::string reference, std::string in);
 std::vector<std::string> SplitFileName(std::string fileName);
 std::vector<std::string> SplitWhiteSpace(std::string in, unsigned int len);
+std::string ReplacePercentS(std::string in, std::string val);
 void ReplaceMultiFormat(const char *in, const char *val, char *out);
 
 #endif
diff --git a/Fltk/Solvers.cpp b/Fltk/Solvers.cpp
index 8769423c32880ca8465aa79e156e085ecfd7d155..fa94528ec3dd0235be20ba1452b00da8c6e772d3 100644
--- a/Fltk/Solvers.cpp
+++ b/Fltk/Solvers.cpp
@@ -26,23 +26,30 @@ class myGmshServer : public GmshServer{
   myGmshServer() : GmshServer() {}
   ~myGmshServer() {}
   int SystemCall(const char *str){ return ::SystemCall(str); }
-  int NonBlockingWait(int socket, int num, double waitint)
+  int NonBlockingWait(int socket, int num, double waitint, double timeout)
   { 
-    // This routine polls the socket at least every 'waitint' seconds and
-    // returns 0 if data is available or 1 if there was en error or if the
-    // process was killed. Otherwise it just tends to current GUI events
-    // (this is easier to manage than non-blocking IO, and simpler than
-    // using the "real" solution, i.e., threads. Another possibility would
+    // This routine polls the socket at least every 'waitint' seconds,
+    // and for at most timout seconds (or indefinitely if
+    // timeout==0). The routine returns 0 as soon as data is available
+    // and 1 if there was en error or if the process was
+    // killed. Otherwise it just tends to current GUI events (this is
+    // easier to manage than non-blocking IO, and simpler than using
+    // the "real" solution, i.e., threads. Another possibility would
     // be to use Fl::add_fd())
+    double start = GetTimeInSeconds();
     while(1){
-      if((num >= 0 && SINFO[num].pid < 0) || (num < 0 && !CTX::instance()->solver.listen)){
-        // process has been killed or we stopped listening
-        return 1;
+      if(timeout > 0 && GetTimeInSeconds() - start > timeout) {
+        return 2; // timout
+      }
+
+      if((num >= 0 && SINFO[num].pid < 0) ||
+         (num < 0 && !CTX::instance()->solver.listen)){
+        return 1; // process has been killed or we stopped listening
       }
 
       // check if there is data (call select with a zero timeout to
       // return immediately, i.e., do polling)
-      int ret = Select(socket, 0, 0);
+      int ret = Select(0, 0, socket);
 
       if(ret == 0){ 
         // nothing available: wait at most waitint seconds, and in the
@@ -50,8 +57,7 @@ class myGmshServer : public GmshServer{
         FlGui::instance()->wait(waitint);
       }
       else if(ret > 0){ 
-        // data is there
-        return 0;
+        return 0; // data is there!
       }
       else{ 
         // an error happened
@@ -73,7 +79,7 @@ std::string GetSocketName(int num)
     std::ostringstream tmp;
     tmp << CTX::instance()->homeDir << CTX::instance()->solver.socketName;
     if(num >= 0) tmp << "-" << num;
-    sockname = FixWindowsPath(tmp.str().c_str());
+    sockname = FixWindowsPath(tmp.str());
   }
   else{
     // TCP/IP socket
@@ -97,19 +103,21 @@ int Solver(int num, const char *args)
   GmshServer *server = new myGmshServer;
 
   if(num >= 0){
-    prog = FixWindowsPath(SINFO[num].executable_name.c_str());
+    prog = FixWindowsPath(SINFO[num].executable_name);
     if(!SINFO[num].client_server) {
       command = prog + " " + args;
 #if !defined(WIN32)
       command += " &";
 #endif
-      server->StartClient(command.c_str());
+      server->Start(num, command.c_str(), 0, 0.);
+      delete server;
       return 1;
     }
   }
   else{
     if(!CTX::instance()->solver.listen){
       Msg::Info("Stopped listening for solver connections");
+      delete server;
       return 0;
     }
     // we don't know who will (maybe) contact us
@@ -128,51 +136,31 @@ int Solver(int num, const char *args)
 #endif
   }
 
-  int sock = server->StartClient(command.c_str(), sockname.c_str());
+  if(num >= 0){
+    SINFO[num].pid = 0;
+    SINFO[num].server = 0;
+  }
+  bool initOption[5] = {true, true, true, true, true};
 
-  if(sock < 0) {
-    switch (sock) {
-    case -1:
-      Msg::Error("Couldn't create socket '%s'", sockname.c_str());
-      break;
-    case -2:
-      Msg::Error("Couldn't bind socket to name '%s'", sockname.c_str());
-      break;
-    case -3:
-      Msg::Error("Socket listen failed on '%s'", sockname.c_str());
-      break;
-    case -4:
-      Msg::Error("Socket listen timeout on '%s'", sockname.c_str());
-      Msg::Error("Is '%s' correctly installed?", prog.c_str());
-      break;
-    case -5:
-      Msg::Error("Socket accept failed on '%s'", sockname.c_str());
-      break;
-    case -6:
-      Msg::Info("Stopped listening for solver connections");
-      server->Shutdown();
-      break;
-    case -7:
-      Msg::Error("Unix sockets not available on Windows without Cygwin");
-      Msg::Error("Use TCP/IP sockets instead");
-      break;
-    case -8:
-      Msg::Error("Could not initialize Windows sockets");
-      break;
-    }
+  int sock;
+  try{
+    sock = server->Start(num, command.c_str(), sockname.c_str(), 5.);
+  }
+  catch(const char *err){
+    Msg::Error("%s (on socket '%s')", err, sockname.c_str());
+    sock = -1;
+  }
+
+  if(sock < 0){
     if(num >= 0){
       for(int i = 0; i < SINFO[num].nboptions; i++)
         FlGui::instance()->solver[num]->choice[i]->clear();
     }
+    server->Shutdown();
+    delete server;
     return 0;
   }
 
-  if(num >= 0){
-    SINFO[num].pid = 0;
-    SINFO[num].server = 0;
-  }
-  bool initOption[5] = {true, true, true, true, true};
-
   Msg::StatusBar(2, false, "Running '%s'", prog.c_str());
 
   while(1) {
@@ -182,7 +170,7 @@ int Solver(int num, const char *args)
     if(stop || (num >= 0 && SINFO[num].pid < 0))
       break;
 
-    stop = server->NonBlockingWait(sock, num, 0.1);
+    stop = server->NonBlockingWait(sock, num, 0.1, 0.);
 
     if(stop || (num >= 0 && SINFO[num].pid < 0))
       break;
@@ -312,16 +300,19 @@ int Solver(int num, const char *args)
         FlGui::instance()->solver[num]->choice[i]->value(0);
       }
     }
+
+    // only necessary in case of error
+    SINFO[num].server = 0;
   }
-  
+
   server->Shutdown();
+  delete server;
 
   if(num >= 0){
     Msg::StatusBar(2, false, "");
   }
   else{
     Msg::Info("Client disconnected: starting new connection");
-    delete server;
     goto new_connection;
   }
 
diff --git a/Fltk/aboutWindow.cpp b/Fltk/aboutWindow.cpp
index 52910198f44254193967edad3f6d218640de7340..d6cd3d37425ffb5220a824f7eb96b8299759c3af 100644
--- a/Fltk/aboutWindow.cpp
+++ b/Fltk/aboutWindow.cpp
@@ -17,7 +17,7 @@
 
 static void help_license_cb(Fl_Widget *w, void *data)
 {
-  std::string prog = FixWindowsPath(CTX::instance()->webBrowser.c_str());
+  std::string prog = FixWindowsPath(CTX::instance()->webBrowser);
   char cmd[1024];
   ReplaceMultiFormat(prog.c_str(), "http://geuz.org/gmsh/doc/LICENSE.txt", cmd);
   SystemCall(cmd);
@@ -25,7 +25,7 @@ static void help_license_cb(Fl_Widget *w, void *data)
 
 static void help_credits_cb(Fl_Widget *w, void *data)
 {
-  std::string prog = FixWindowsPath(CTX::instance()->webBrowser.c_str());
+  std::string prog = FixWindowsPath(CTX::instance()->webBrowser);
   char cmd[1024];
   ReplaceMultiFormat(prog.c_str(), "http://geuz.org/gmsh/doc/CREDITS.txt", cmd);
   SystemCall(cmd);
diff --git a/Fltk/menuWindow.cpp b/Fltk/menuWindow.cpp
index 33926dedd9268aff75520615da6d0e48168b128b..e5aedf0f07074b9788354c26db269710ef67b6e3 100644
--- a/Fltk/menuWindow.cpp
+++ b/Fltk/menuWindow.cpp
@@ -150,37 +150,38 @@ static void file_remote_cb(Fl_Widget *w, void *data)
 {
   std::string str((const char*)data);
 
-  if(str == "connect"){
-    Msg::Info("Starting remote Gmsh");
+  if(str == "start"){
+    Msg::Info("Starting remote Gmsh server");
     if(SINFO[MAX_NUM_SOLVERS].server){
-      Msg::Info("A server is already running, trying to stop it first");
-      SINFO[MAX_NUM_SOLVERS].server->SendString(GmshSocket::STOP, "DISCONNECTING!");
+      Msg::Error("A server is already running");
+    }
+    else{
+      SINFO[MAX_NUM_SOLVERS].name = "Gmsh Server";
+      SINFO[MAX_NUM_SOLVERS].executable_name = "./gmsh";
+      SINFO[MAX_NUM_SOLVERS].socket_command = "-socket %s";
+      SINFO[MAX_NUM_SOLVERS].nboptions = 0;
+      SINFO[MAX_NUM_SOLVERS].client_server = 1;
+      SINFO[MAX_NUM_SOLVERS].popup_messages = 1;
+      SINFO[MAX_NUM_SOLVERS].merge_views = 1;
+      Solver(MAX_NUM_SOLVERS, "");
     }
-    SINFO[MAX_NUM_SOLVERS].name = "Gmsh Daemon";
-    SINFO[MAX_NUM_SOLVERS].executable_name = "./gmsh";
-    SINFO[MAX_NUM_SOLVERS].socket_command = "-socket %s";
-    SINFO[MAX_NUM_SOLVERS].nboptions = 0;
-    SINFO[MAX_NUM_SOLVERS].client_server = 1;
-    SINFO[MAX_NUM_SOLVERS].popup_messages = 1;
-    SINFO[MAX_NUM_SOLVERS].merge_views = 1;
-    Solver(MAX_NUM_SOLVERS, "");
   }
-  else if(str == "disconnect"){
+  else if(str == "stop"){
     if(SINFO[MAX_NUM_SOLVERS].server){
-      Msg::Info("Stopping remote Gmsh");
+      Msg::Info("Stopping remote Gmsh server");
       SINFO[MAX_NUM_SOLVERS].server->SendString(GmshSocket::STOP, "DISCONNECTING!");
     }
     else{
-      Msg::Warning("Cannot disconnect remote Gmsh: server not running");
+      Msg::Error("Cannot stop remote Gmsh: server not running");
     }
   }
   else if(str == "test"){
     if(SINFO[MAX_NUM_SOLVERS].server){
-      Msg::Info("Testing remote Gmsh daemon");
+      Msg::Info("Testing remote Gmsh server");
       SINFO[MAX_NUM_SOLVERS].server->SendString(9999, "GENERATE A VIEW!");
     }
     else{
-      Msg::Warning("Cannot test remote Gmsh: must be connected first!");
+      Msg::Error("Cannot test remote Gmsh: server not running");
     }
   }
 }
@@ -520,7 +521,7 @@ static void help_command_line_cb(Fl_Widget *w, void *data)
 
 static void help_online_cb(Fl_Widget *w, void *data)
 {
-  std::string prog = FixWindowsPath(CTX::instance()->webBrowser.c_str());
+  std::string prog = FixWindowsPath(CTX::instance()->webBrowser);
   char cmd[1024];
   ReplaceMultiFormat(prog.c_str(), "http://geuz.org/gmsh/doc/texinfo/", cmd);
   SystemCall(cmd);
@@ -573,8 +574,8 @@ static void geometry_physical_cb(Fl_Widget *w, void *data)
 
 static void geometry_edit_cb(Fl_Widget *w, void *data)
 {
-  std::string prog = FixWindowsPath(CTX::instance()->editor.c_str());
-  std::string file = FixWindowsPath(GModel::current()->getFileName().c_str());
+  std::string prog = FixWindowsPath(CTX::instance()->editor);
+  std::string file = FixWindowsPath(GModel::current()->getFileName());
   char cmd[1024];
   ReplaceMultiFormat(prog.c_str(), file.c_str(), cmd);
   SystemCall(cmd);
@@ -2237,10 +2238,10 @@ static Fl_Menu_Item sysbar_table[] = {
       {"Vertically",   0, (Fl_Callback *)file_window_cb, (void*)"split_v"},
       {"Clear",        0, (Fl_Callback *)file_window_cb, (void*)"split_u"},
       {0},
-#if 0 // test remote gmsh daemon
-    {"Connect...",  0, (Fl_Callback *)file_remote_cb, (void*)"connect"},
-    {"Test remote!",  0, (Fl_Callback *)file_remote_cb, (void*)"test"},
-    {"Disconnect",  0, (Fl_Callback *)file_remote_cb, (void*)"disconnect", FL_MENU_DIVIDER},
+#if 1 // test remote Gmsh server
+    {"Start server...",  0, (Fl_Callback *)file_remote_cb, (void*)"start"},
+    {"Test server!",  0, (Fl_Callback *)file_remote_cb, (void*)"test"},
+    {"Stop server",  0, (Fl_Callback *)file_remote_cb, (void*)"stop", FL_MENU_DIVIDER},
 #endif
     {"Rename...",  FL_META+'r', (Fl_Callback *)file_rename_cb, 0},
     {"Save As...", FL_META+'s', (Fl_Callback *)file_save_as_cb, 0},
diff --git a/Fltk/solverWindow.cpp b/Fltk/solverWindow.cpp
index 733cebba7e3e0b7b6360309a35ee72ea22f5a993..3d8400f93a3cd8e5b6fe7382fae6ffee483d221a 100644
--- a/Fltk/solverWindow.cpp
+++ b/Fltk/solverWindow.cpp
@@ -50,7 +50,7 @@ void solver_cb(Fl_Widget *w, void *data)
 
   std::string inputFile(FlGui::instance()->solver[num]->input[0]->value());
   if(SINFO[num].nboptions && inputFile.size()) {
-    std::string file = FixWindowsPath(inputFile.c_str());
+    std::string file = FixWindowsPath(inputFile);
     char tmp[256], tmp2[256];
     sprintf(tmp, "\"%s\"", file.c_str());
     sprintf(tmp2, SINFO[num].name_command.c_str(), tmp);
@@ -70,7 +70,7 @@ static void solver_file_open_cb(Fl_Widget *w, void *data)
   if(file_chooser(0, 0, "Choose", tmp)) {
     FlGui::instance()->solver[num]->input[0]->value(file_chooser_get_name(1).c_str());
     if(SINFO[num].nboptions) {
-      std::string file = FixWindowsPath(file_chooser_get_name(1).c_str());
+      std::string file = FixWindowsPath(file_chooser_get_name(1));
       sprintf(tmp, "\"%s\"", file.c_str());
       sprintf(tmp2, SINFO[num].name_command.c_str(), tmp);
       sprintf(tmp, "%s %s", SINFO[num].option_command.c_str(), tmp2);
@@ -82,7 +82,7 @@ static void solver_file_open_cb(Fl_Widget *w, void *data)
 static void solver_file_edit_cb(Fl_Widget *w, void *data)
 {
   int num = (int)(long)data;
-  std::string prog = FixWindowsPath(CTX::instance()->editor.c_str());
+  std::string prog = FixWindowsPath(CTX::instance()->editor);
   std::string file = FixWindowsPath(FlGui::instance()->solver[num]->input[0]->value());
   char cmd[1024];
   ReplaceMultiFormat(prog.c_str(), file.c_str(), cmd);
@@ -139,7 +139,6 @@ static void solver_command_cb(Fl_Widget *w, void *data)
       sprintf(command, SINFO[num].button_command[idx].c_str(), 
               SINFO[num].option[usedopts][val].c_str());
     else{
-      Msg::Warning("Invalid choice (%d) for option %d", val, usedopts);
       strcpy(command, "");
     }
   }
diff --git a/README.txt b/README.txt
index 79fbe0d55209009bcc67243666689855b792a439..ead75106026273d236e18fc4d8808932940e2e1b 100644
--- a/README.txt
+++ b/README.txt
@@ -19,8 +19,8 @@ Build Gmsh using CMake's graphical user interface
 -------------------------------------------------
 
 * Launch CMake and fill-in the two top input fields (telling where the
-  Gmsh source is located and where you want the Gmsh binary to be
-  created).
+  Gmsh source directory is located and where you want the Gmsh binary
+  to be created).
 
 * Click on "Add entry" and define the variable CMAKE_PREFIX_PATH, of
   type "PATH", pointing to the location(s) of any external package(s)