diff --git a/utils/solvers/c++/GmshSocket.h b/utils/solvers/c++/GmshSocket.h
index 8afb52ed8047e9be897a429a7511e9b84eaab3cf..db40391fa393454256a31e52de67eb365bfe5987 100644
--- a/utils/solvers/c++/GmshSocket.h
+++ b/utils/solvers/c++/GmshSocket.h
@@ -28,6 +28,8 @@
 #ifndef _GMSH_SOCKET_H_
 #define _GMSH_SOCKET_H_
 
+//#include "GmshConfig.h"
+
 #include <string>
 #include <stdio.h>
 #include <stdlib.h>
@@ -84,6 +86,8 @@ class GmshSocket{
     GMSH_PARAMETER_UPDATE    = 32,
     GMSH_OPEN_PROJECT        = 33,
     GMSH_CLIENT_CHANGED      = 34,
+    GMSH_PARAMETER_WITHOUT_CHOICES = 35,
+    GMSH_PARAMETER_QUERY_WITHOUT_CHOICES = 36,
     GMSH_OPTION_1            = 100,
     GMSH_OPTION_2            = 101,
     GMSH_OPTION_3            = 102,
@@ -94,6 +98,8 @@ class GmshSocket{
   int _sock;
   // the socket name
   std::string _sockname;
+  // statistics
+  unsigned long int _sent, _received;
   // send some data over the socket
   int _SendData(const void *buffer, int bytes)
   {
@@ -106,6 +112,7 @@ class GmshSocket{
       sofar += len;
       remaining -= len;
     } while(remaining > 0);
+    _sent += bytes;
     return bytes;
   }
   // receive some data over the socket
@@ -121,6 +128,7 @@ class GmshSocket{
       sofar += len;
       remaining -= len;
     } while(remaining > 0);
+    _received += bytes;
     return bytes;
   }
   // utility function to swap bytes in an array
@@ -145,7 +153,7 @@ class GmshSocket{
 #endif
   }
  public:
-  GmshSocket() : _sock(0)
+  GmshSocket() : _sock(0), _sent(0), _received(0)
   {
 #if defined(WIN32) && !defined(__CYGWIN__)
     WSADATA wsaData;
@@ -246,6 +254,8 @@ class GmshSocket{
     shutdown(s, SHUT_RDWR);
 #endif
   }
+  unsigned long int SentBytes(){ return _sent; }
+  unsigned long int ReceivedBytes(){ return _received; }
 };
 
 class GmshClient : public GmshSocket {
diff --git a/utils/solvers/c++/onelab.h b/utils/solvers/c++/onelab.h
index f71601773699991585f1c2a681464c085989fa43..338ec47606225a4522908d05c128c47978250140 100644
--- a/utils/solvers/c++/onelab.h
+++ b/utils/solvers/c++/onelab.h
@@ -137,7 +137,13 @@ namespace onelab{
     }
     std::string getShortName() const
     {
-      if(_label.size()) return _label;
+      std::string units = getAttribute("Units");
+      if(_label.size()){
+        if(units.empty())
+          return _label;
+        else
+          return _label + " [" + units + "]";
+      }
       std::string s = _name;
       // remove path
       std::string::size_type last = _name.find_last_of('/');
@@ -154,7 +160,10 @@ namespace onelab{
       // start'
       while(s.size() && s[0] >= '0' && s[0] <= '9')
         s = s.substr(1);
-      return s;
+      if(units.empty())
+        return s;
+      else
+        return s + " [" + units + "]";
     }
     int getChanged(const std::string &client="") const
     {
@@ -189,7 +198,7 @@ namespace onelab{
     const std::map<std::string, int> &getClients() const { return _clients; }
     static char charSep() { return '\0'; }
     static double maxNumber() { return 1e200; }
-    static std::string version() { return "1.2"; }
+    static std::string version() { return "1.3"; }
     static int defaultChangedValue() { return 31; }
     static std::string getNextToken(const std::string &msg,
                                     std::string::size_type &first,
@@ -353,8 +362,7 @@ namespace onelab{
   };
 
   // The number class. Numbers are stored internally as double precision real
-  // numbers. All more complicated types (complex numbers, vectors, expressions,
-  // functions, etc.) are supposed to be exchanged as strings.
+  // numbers.
   class number : public parameter{
   private:
     std::vector<double> _values, _choices;
@@ -382,6 +390,7 @@ namespace onelab{
     void setChoiceLabels(const std::vector<std::string> &labels)
     {
       if(labels.size() != _choices.size()) return;
+      if(_valueLabels.size()) _valueLabels.clear();
       for(unsigned int i = 0; i < _choices.size(); i++)
         _valueLabels[_choices[i]] = labels[i];
     }
@@ -720,14 +729,24 @@ namespace onelab{
         if(!done) done = _clear(name, client, _strings);
       }
     }
-    bool set(const number &p,
-             const std::string &client=""){ return _set(p, client, _numbers); }
-    bool set(const string &p,
-             const std::string &client=""){ return _set(p, client, _strings); }
+    bool set(const number &p, const std::string &client="")
+    {
+      return _set(p, client, _numbers);
+    }
+    bool set(const string &p, const std::string &client="")
+    {
+      return _set(p, client, _strings);
+    }
     bool get(std::vector<number> &ps, const std::string &name="",
-             const std::string &client=""){ return _get(ps, name, client, _numbers); }
-    bool get(std::vector<onelab::string> &ps, const std::string &name="",
-             const std::string &client=""){ return _get(ps, name, client, _strings); }
+             const std::string &client="")
+    {
+      return _get(ps, name, client, _numbers);
+    }
+    bool get(std::vector<string> &ps, const std::string &name="",
+             const std::string &client="")
+    {
+      return _get(ps, name, client, _strings);
+    }
     void getPtr(number **ptr, const std::string name, const std::string client="")
     {
       *ptr = _getPtr(name, client, _numbers);
@@ -812,10 +831,10 @@ namespace onelab{
         onelab::parameter::getInfoFromChar(msg[i], version, type, name);
         if(onelab::parameter::version() != version) return false;
         if(type == "number"){
-          onelab::number p; p.fromChar(msg[i]); set(p, client);
+          number p; p.fromChar(msg[i]); set(p, client);
         }
         else if(type == "string"){
-          onelab::string p; p.fromChar(msg[i]); set(p, client);
+          string p; p.fromChar(msg[i]); set(p, client);
         }
         else
           return false;
@@ -881,7 +900,11 @@ namespace onelab{
     virtual bool set(const number &p) = 0;
     virtual bool set(const string &p) = 0;
     virtual bool get(std::vector<number> &ps, const std::string &name="") = 0;
-    virtual bool get(std::vector<onelab::string> &ps, const std::string &name="") = 0;
+    virtual bool get(std::vector<string> &ps, const std::string &name="") = 0;
+    virtual bool setAndAppendChoices(const number &p) = 0;
+    virtual bool setAndAppendChoices(const string &p) = 0;
+    virtual bool getWithoutChoices(std::vector<number> &ps, const std::string &name="") = 0;
+    virtual bool getWithoutChoices(std::vector<string> &ps, const std::string &name="") = 0;
     std::vector<std::string> toChar()
     {
       std::vector<std::string> out;
@@ -898,10 +921,10 @@ namespace onelab{
         onelab::parameter::getInfoFromChar(msg[i], version, type, name);
         if(onelab::parameter::version() != version) return false;
         if(type == "number"){
-          onelab::number p; p.fromChar(msg[i]); set(p);
+          number p; p.fromChar(msg[i]); set(p);
         }
         else if(type == "string"){
-          onelab::string p; p.fromChar(msg[i]); set(p);
+          string p; p.fromChar(msg[i]); set(p);
         }
         else
           return false;
@@ -919,6 +942,7 @@ namespace onelab{
       return false;
     }
   };
+
   // The onelab server: a singleton that stores the parameter space and
   // interacts with onelab clients.
   class server{
@@ -1038,8 +1062,46 @@ namespace onelab{
     virtual bool set(const string &p){ return _set(p); }
     virtual bool get(std::vector<number> &ps,
                      const std::string &name=""){ return _get(ps, name); }
-    virtual bool get(std::vector<onelab::string> &ps,
+    virtual bool get(std::vector<string> &ps,
                      const std::string &name=""){ return _get(ps, name); }
+    virtual bool setAndAppendChoices(const number &p)
+    {
+      std::vector<number> ps;
+      _get(ps, _name);
+      std::vector<double> choices;
+      if(ps.size()) choices = ps[0].getChoices();
+      choices.insert(choices.end(), p.getChoices().begin(), p.getChoices().end());
+      number p2(p);
+      p2.setChoices(choices);
+      return _set(p2);
+    }
+    virtual bool setAndAppendChoices(const string &p)
+    {
+      std::vector<string> ps;
+      _get(ps, _name);
+      std::vector<std::string> choices;
+      if(ps.size()) choices = ps[0].getChoices();
+      choices.insert(choices.end(), p.getChoices().begin(), p.getChoices().end());
+      string p2(p);
+      p2.setChoices(choices);
+      return _set(p2);
+    }
+    virtual bool getWithoutChoices(std::vector<number> &ps,
+                                   const std::string &name="")
+    {
+      bool ret = _get(ps, name);
+      for(unsigned int i = 0; i < ps.size(); i++)
+        ps[i].setChoices(std::vector<double>());
+      return ret;
+    }
+    virtual bool getWithoutChoices(std::vector<string> &ps,
+                                   const std::string &name="")
+    {
+      bool ret = _get(ps, name);
+      for(unsigned int i = 0; i < ps.size(); i++)
+        ps[i].setChoices(std::vector<std::string>());
+      return ret;
+    }
   };
 
   // The local part of a network client.
@@ -1096,21 +1158,26 @@ namespace onelab{
     GmshClient *_gmshClient;
     // number of subclients
     int _numSubClients;
-    template <class T> bool _set(const T &p)
+    template <class T> bool _set(const T &p, bool withChoices=true)
     {
       if(!_gmshClient) return false;
       std::string msg = p.toChar();
-      _gmshClient->SendMessage(GmshSocket::GMSH_PARAMETER, msg.size(), &msg[0]);
+      _gmshClient->SendMessage(withChoices ? GmshSocket::GMSH_PARAMETER :
+                               GmshSocket::GMSH_PARAMETER_WITHOUT_CHOICES,
+                               msg.size(), &msg[0]);
       return true;
     }
-    template <class T> bool _get(std::vector<T> &ps, const std::string &name="")
+    template <class T> bool _get(std::vector<T> &ps, const std::string &name="",
+                                 bool withChoices=true)
     {
       ps.clear();
       if(!_gmshClient) return false;
       T p(name);
       std::string msg = p.toChar();
-      if (name.size())
-	_gmshClient->SendMessage(GmshSocket::GMSH_PARAMETER_QUERY, msg.size(), &msg[0]);
+      if(name.size())
+	_gmshClient->SendMessage(withChoices ? GmshSocket::GMSH_PARAMETER_QUERY :
+                                 GmshSocket::GMSH_PARAMETER_QUERY_WITHOUT_CHOICES,
+                                 msg.size(), &msg[0]);
       else // get all parameters
 	_gmshClient->SendMessage(GmshSocket::GMSH_PARAMETER_QUERY_ALL, msg.size(), &msg[0]);
 
@@ -1228,10 +1295,24 @@ namespace onelab{
     }
     virtual bool set(const number &p){ return _set(p); }
     virtual bool set(const string &p){ return _set(p); }
-    virtual bool get(std::vector<number> &ps,
-                     const std::string &name=""){ return _get(ps, name); }
-    virtual bool get(std::vector<onelab::string> &ps,
-                     const std::string &name=""){ return _get(ps, name); }
+    virtual bool get(std::vector<number> &ps, const std::string &name="")
+    {
+      return _get(ps, name);
+    }
+    virtual bool get(std::vector<string> &ps, const std::string &name="")
+    {
+      return _get(ps, name);
+    }
+    virtual bool setAndAppendChoices(const number &p){ return _set(p, false); }
+    virtual bool setAndAppendChoices(const string &p){ return _set(p, false); }
+    virtual bool getWithoutChoices(std::vector<number> &ps, const std::string &name="")
+    {
+      return _get(ps, name, false);
+    }
+    virtual bool getWithoutChoices(std::vector<string> &ps, const std::string &name="")
+    {
+      return _get(ps, name, false);
+    }
     void sendInfo(const std::string &msg)
     {
       if(_gmshClient) _gmshClient->Info(msg.c_str());
@@ -1263,7 +1344,10 @@ namespace onelab{
     void runNonBlockingSubClient(const std::string &name, const std::string &command)
     {
       if(!_gmshClient){
-        system(command.c_str());
+        int res = system(command.c_str());
+        if(res){
+          // report error
+        }
         return;
       }
       std::string msg = name + parameter::charSep() + command;