diff --git a/Common/onelab.h b/Common/onelab.h
index 5d95178f20b4e770f94dfc3a01d24f5c0573bd9b..9bee45d83d010f46c15b7471c1d0a64d9a28df91 100644
--- a/Common/onelab.h
+++ b/Common/onelab.h
@@ -70,6 +70,10 @@ namespace onelab{
     {
       _attributes[key] = value;
     }
+    void setAttributes(const std::map<std::string, std::string> &attributes)
+    {
+      _attributes = attributes; 
+    }
     void setClients(std::set<std::string> &clients){ _clients = clients; }
     void addClient(const std::string &client){ _clients.insert(client); }
     void addClients(std::set<std::string> &clients)
@@ -92,6 +96,10 @@ namespace onelab{
       if(it != _attributes.end()) return it->second;
       return "";
     }
+    const std::map<std::string, std::string> &getAttributes() const 
+    {
+      return _attributes; 
+    }
     const std::set<std::string> &getClients() const { return _clients; }
     static char charSep(){ return '|' /* '\0' */; }
     static double maxNumber(){ return 1e200; }
@@ -159,13 +167,13 @@ namespace onelab{
     void setMin(double min){ _min = min; }
     void setMax(double max){ _max = max; }
     void setStep(double step){ _step = step; }
-    void setChoices(std::vector<double> &choices){ _choices = choices; }
+    void setChoices(const std::vector<double> &choices){ _choices = choices; }
     std::string getType() const { return "number"; }
     double getValue() const { return _value; }
     double getMin() const { return _min; }
     double getMax() const { return _max; }
     double getStep() const { return _step; }
-    const std::vector<double> &getChoices(){ return _choices; }
+    const std::vector<double> &getChoices() const { return _choices; }
     void update(const number &p)
     {
       if(p.getValue() != getValue()){
@@ -176,8 +184,16 @@ namespace onelab{
         setMin(p.getMin());
       if(p.getMax() != maxNumber())
         setMax(p.getMax());
-      if(p.getStep() != getStep())
+      if(p.getStep())
         setStep(p.getStep());
+      if(p.getChoices().size())
+        setChoices(p.getChoices());
+      if(p.getShortHelp().size())
+        setShortHelp(p.getShortHelp());
+      if(p.getHelp().size())
+        setHelp(p.getHelp());
+      if(p.getAttributes().size())
+        setAttributes(p.getAttributes());
     }
     std::string toChar()
     {
@@ -250,6 +266,12 @@ namespace onelab{
       }
       if(p.getChoices().size())
         setChoices(p.getChoices());
+      if(p.getShortHelp().size())
+        setShortHelp(p.getShortHelp());
+      if(p.getHelp().size())
+        setHelp(p.getHelp());
+      if(p.getAttributes().size())
+        setAttributes(p.getAttributes());
     }
     std::string toChar()
     {
diff --git a/Fltk/inputRange.h b/Fltk/inputRange.h
new file mode 100644
index 0000000000000000000000000000000000000000..083c935772fbffc38ab8b69756359041840f78a7
--- /dev/null
+++ b/Fltk/inputRange.h
@@ -0,0 +1,137 @@
+// Gmsh - Copyright (C) 1997-2011 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#include <string>
+#include <sstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <FL/Fl.H>
+#include <FL/Fl_Window.H>
+#include <FL/Fl_Value_Input.H>
+#include <FL/Fl_Toggle_Button.H>
+
+class inputRange : public Fl_Group {
+ private:
+  Fl_Value_Input *_input;
+  Fl_Input *_range;
+  Fl_Toggle_Button *_range_butt, *_loop_butt;
+  double _min, _max, _step, _max_number;
+  void _values2string()
+  {
+    // construct range string from min/max/step
+    std::ostringstream tmp;
+    if(_min != -_max_number){
+      tmp << _min;
+      _input->minimum(_min);
+    }
+    tmp << ":";
+    if(_max != _max_number){
+      tmp << _max;
+      _input->maximum(_max);
+    }
+    if(_step){
+      tmp << ":" << _step;
+      _input->step(_step);
+    }
+    _range->value(tmp.str().c_str());
+  }
+  void _string2values()
+  {
+    // parse range string and affect min/max/step
+    std::string str(_range->value()), min, max, step;
+    std::string::size_type first = 0, last;
+    last = str.find_first_of(':', first);
+    min = str.substr(first, last - first);
+    if(last != std::string::npos){
+      first = last + 1;
+      last = str.find_first_of(':', first);
+      max = str.substr(first, last - first);
+      if(last != std::string::npos)
+        step = str.substr(last + 1, str.size());
+    }
+    if(min.size()){
+      _min = atof(min.c_str());
+      _input->minimum(_min);
+    }
+    if(max.size()){
+      _max = atof(max.c_str());
+      _input->maximum(_max);
+    }
+    if(step.size()){
+      _step = atof(step.c_str());
+      _input->step(_step);
+    }
+  }
+  void _show_range()
+  {
+    if(_range_butt->value()){
+      _input->size(_input->w() - _range->w(), _input->h());
+      _input->redraw();
+      _range->show();
+    }
+    else{
+      _input->size(_input->w() + _range->w(), _input->h());
+      _input->redraw();
+      _range->hide();
+    }
+  }
+  static void _input_cb(Fl_Widget *w, void *data)
+  {
+    ((inputRange*)data)->do_callback();
+  }
+  static void _range_cb(Fl_Widget *w, void *data)
+  {
+    ((inputRange*)data)->_string2values();
+    ((inputRange*)data)->do_callback();
+  }
+  static void _range_butt_cb(Fl_Widget *w, void *data)
+  {
+    ((inputRange*)data)->_show_range(); 
+  }
+  static void _loop_butt_cb(Fl_Widget *w, void *data)
+  {
+    ((inputRange*)data)->do_callback(); 
+  }
+ public:
+  inputRange(int x, int y, int w, int h, double max_number, const char *l=0) 
+    : Fl_Group(x,y,w,h,l), _min(-max_number), _max(max_number), _step(0),
+      _max_number(max_number)
+  {
+    int dot_w = FL_NORMAL_SIZE - 2, loop_w = FL_NORMAL_SIZE + 6;
+    int input_w = w - dot_w - loop_w;
+    int range_w = input_w / 2;
+
+    _input = new Fl_Value_Input(x, y, input_w, h);
+    _input->callback(_input_cb, this);
+    _input->when(FL_WHEN_ENTER_KEY|FL_WHEN_RELEASE);
+    
+    _range = new Fl_Input(x + input_w - range_w, y, range_w, h);
+    _range->callback(_range_cb, this);
+    _range->when(FL_WHEN_ENTER_KEY|FL_WHEN_RELEASE);
+    _range->hide();
+
+    _range_butt = new Fl_Toggle_Button(x + input_w, y, dot_w, h, ":");
+    _range_butt->callback(_range_butt_cb, this);
+
+    _loop_butt = new Fl_Toggle_Button(x + input_w + dot_w, y, loop_w, h);
+    _loop_butt->label("@-1gmsh_rotate");
+    _loop_butt->selection_color(FL_GREEN);
+    _loop_butt->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE);
+    _loop_butt->callback(_loop_butt_cb, this);
+
+    end(); // close the group
+    resizable(_input);
+  }
+  double value() { return _input->value(); }
+  void value(double val) { _input->value(val); }
+  void minimum(double val) { _min = val; _values2string(); }
+  double minimum() { return _min; }
+  void maximum(double val) { _max = val; _values2string(); }
+  double maximum() { return _max; }
+  void step(double val) { _step = val; _values2string(); }
+  double step() { return _step; }
+  void loop(int val) { _loop_butt->value(val); }
+  int loop() { return _loop_butt->value(); }
+};
diff --git a/Fltk/onelabWindow.cpp b/Fltk/onelabWindow.cpp
index 0142ec1f5fda94fdffc8d5baa5f118883f62f324..ef4b5fa1426b088a4de2c5d5b669328c7a1865f8 100644
--- a/Fltk/onelabWindow.cpp
+++ b/Fltk/onelabWindow.cpp
@@ -7,10 +7,10 @@
 #include "GmshMessage.h"
 #include "onelab.h"
 #if (FL_MAJOR_VERSION == 1) && (FL_MINOR_VERSION == 3)
-#include <FL/Fl_Value_Input.H>
 #include <FL/Fl_Input_Choice.H>
 #include <FL/Fl_Check_Button.H>
 #include <FL/Fl_Box.H>
+#include "inputRange.h"
 #include "Context.h"
 #include "GModel.h"
 #include "GmshDefines.h"
@@ -406,6 +406,9 @@ void onelab_cb(Fl_Widget *w, void *data)
       if(ps.size()) what += " " + ps[0].getValue();
       c->run(what);
     }
+    else if(action == "kill"){
+      c->kill();
+    }
   }
 
   FlGui::instance()->onelab->activate();
@@ -423,19 +426,25 @@ static void onelab_check_button_cb(Fl_Widget *w, void *data)
   std::vector<onelab::number> numbers;
   onelab::server::instance()->get(numbers, name);
   if(numbers.size()){
-    numbers[0].setValue(((Fl_Check_Button*)w)->value());
+    Fl_Check_Button *o = (Fl_Check_Button*)w;
+    numbers[0].setValue(o->value());
     onelab::server::instance()->set(numbers[0]);
   }
 }
 
-static void onelab_value_input_cb(Fl_Widget *w, void *data)
+static void onelab_input_range_cb(Fl_Widget *w, void *data)
 {
   if(!data) return;
   std::string name = FlGui::instance()->onelab->getPath((Fl_Tree_Item*)data);
   std::vector<onelab::number> numbers;
   onelab::server::instance()->get(numbers, name);
   if(numbers.size()){
-    numbers[0].setValue(((Fl_Value_Input*)w)->value());
+    inputRange *o = (inputRange*)w;
+    numbers[0].setValue(o->value());
+    numbers[0].setMin(o->minimum());
+    numbers[0].setMax(o->maximum());
+    numbers[0].setStep(o->step());
+    numbers[0].setAttribute("loop", o->loop() ? "true" : "false");
     onelab::server::instance()->set(numbers[0]);
   }
 }
@@ -447,7 +456,8 @@ static void onelab_input_choice_cb(Fl_Widget *w, void *data)
   std::vector<onelab::string> strings;
   onelab::server::instance()->get(strings, name);
   if(strings.size()){
-    strings[0].setValue(((Fl_Input_Choice*)w)->value());
+    Fl_Input_Choice *o = (Fl_Input_Choice*)w;
+    strings[0].setValue(o->value());
     onelab::server::instance()->set(strings[0]);
   }
 }
@@ -494,7 +504,7 @@ onelabWindow::onelabWindow(int deltaFontSize)
 {
   FL_NORMAL_SIZE -= deltaFontSize;
 
-  int width = 25 * FL_NORMAL_SIZE;
+  int width = 28 * FL_NORMAL_SIZE;
   int height = 15 * BH + 3 * WB;
   
   _win = new paletteWindow
@@ -541,6 +551,8 @@ static std::string getShortName(const std::string &name)
 
 void onelabWindow::rebuildTree()
 {
+  int width = (3*IW)/2;
+
   _tree->clear();
   _tree->sortorder(FL_TREE_SORT_ASCENDING);
   _tree->selectmode(FL_TREE_SELECT_NONE);
@@ -552,13 +564,13 @@ void onelabWindow::rebuildTree()
   onelab::server::instance()->get(numbers);
   for(unsigned int i = 0; i < numbers.size(); i++){
     Fl_Tree_Item *n = _tree->add(numbers[i].getName().c_str());
-    n->labelsize(FL_NORMAL_SIZE + 3);
+    n->labelsize(FL_NORMAL_SIZE + 5);
     std::string label = numbers[i].getShortHelp();
     if(label.empty()) label = getShortName(numbers[i].getName());
     _tree->begin();
     if(numbers[i].getChoices().size() == 2 &&
        numbers[i].getChoices()[0] == 0 && numbers[i].getChoices()[1] == 1){
-      Fl_Check_Button *but = new Fl_Check_Button(1,1,IW,1);
+      Fl_Check_Button *but = new Fl_Check_Button(1, 1, width, 1);
       _treeWidgets.push_back(but);
       but->copy_label(label.c_str());
       but->value(numbers[i].getValue());
@@ -566,18 +578,17 @@ void onelabWindow::rebuildTree()
       n->widget(but);
     }
     else{
-      Fl_Value_Input *but = new Fl_Value_Input(1,1,IW,1);
+      inputRange *but = new inputRange
+        (1, 1, width, 1, onelab::parameter::maxNumber());
       _treeWidgets.push_back(but);
       but->copy_label(label.c_str());
       but->value(numbers[i].getValue());
-      if(numbers[i].getMin() != -1.e200)
-        but->minimum(numbers[i].getMin());
-      if(numbers[i].getMax() != 1.e200)
-        but->maximum(numbers[i].getMax());
-      if(numbers[i].getStep())
-        but->step(numbers[i].getStep());
+      but->minimum(numbers[i].getMin());
+      but->maximum(numbers[i].getMax());
+      but->step(numbers[i].getStep());
+      but->loop(numbers[i].getAttribute("loop") == "true");
       but->align(FL_ALIGN_RIGHT);
-      but->callback(onelab_value_input_cb, (void*)n);
+      but->callback(onelab_input_range_cb, (void*)n);
       but->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY);
       n->widget(but);
     }
@@ -588,11 +599,11 @@ void onelabWindow::rebuildTree()
   onelab::server::instance()->get(strings);
   for(unsigned int i = 0; i < strings.size(); i++){
     Fl_Tree_Item *n = _tree->add(strings[i].getName().c_str());
-    n->labelsize(FL_NORMAL_SIZE + 3);
+    n->labelsize(FL_NORMAL_SIZE + 5);
     std::string label = strings[i].getShortHelp();
     if(label.empty()) label = getShortName(strings[i].getName());
     _tree->begin();
-    Fl_Input_Choice *but = new Fl_Input_Choice(1,1,IW,1);
+    Fl_Input_Choice *but = new Fl_Input_Choice(1, 1, width, 1);
     _treeWidgets.push_back(but);
     but->copy_label(label.c_str());
     for(unsigned int j = 0; j < strings[i].getChoices().size(); j++)
@@ -614,7 +625,7 @@ void onelabWindow::rebuildTree()
   for(Fl_Tree_Item *n = _tree->first(); n; n = n->next()){
     if(n->has_children()){
       _tree->begin();
-      Fl_Box *but = new Fl_Box(1,1,IW,1);
+      Fl_Box *but = new Fl_Box(1, 1, width, 1);
       but->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
       _treeWidgets.push_back(but);
       but->copy_label(getShortName(n->label()).c_str());
@@ -647,6 +658,20 @@ void onelabWindow::rebuildSolverList()
   _win->label(_title.c_str());
 }
 
+void onelabWindow::activate()
+{
+  _butt[0]->label("Compute");
+  _butt[0]->callback(onelab_cb, (void*)"compute");
+  _butt[1]->activate(); 
+}
+
+void onelabWindow::deactivate()
+{
+  _butt[0]->label("Kill");
+  _butt[0]->callback(onelab_cb, (void*)"kill");
+  _butt[1]->deactivate();
+}
+
 void onelabWindow::addSolver(const std::string &name, const std::string &commandLine,
                              int index)
 {
diff --git a/Fltk/onelabWindow.h b/Fltk/onelabWindow.h
index b8648707d4117c32d2940ae0a5a2067660f5efa1..d26fafbc472a871cc47174efbd7da7f1556e3b27 100644
--- a/Fltk/onelabWindow.h
+++ b/Fltk/onelabWindow.h
@@ -32,8 +32,8 @@ class onelabWindow{
   void rebuildSolverList();
   void rebuildTree();
   void redrawTree(){ _tree->redraw(); }
-  void activate(){ _butt[0]->activate(); _butt[1]->activate(); }
-  void deactivate(){ _butt[0]->deactivate(); _butt[1]->deactivate(); }
+  void activate();
+  void deactivate();
   void show(){ _win->show(); }
   int shown(){ return _win->shown(); }
   std::string getModelExtension(){ return _modelExtension; }