diff --git a/Common/GmshMessage.cpp b/Common/GmshMessage.cpp
index f5f303a7063839ef61ce70df9898b3ce0b847890..cdfc6b8331e26d9665be82917894f1cdf160751d 100644
--- a/Common/GmshMessage.cpp
+++ b/Common/GmshMessage.cpp
@@ -160,9 +160,9 @@ void Msg::Fatal(const char *fmt, ...)
   if(FlGui::available()){
     FlGui::instance()->check();
     std::string tmp = std::string("@C1@.") + "Fatal   : " + str;
-    FlGui::instance()->messages->add(tmp.c_str());
-    FlGui::instance()->messages->show();
-    FlGui::instance()->messages->save
+    FlGui::instance()->addMessage(tmp.c_str());
+    FlGui::instance()->showMessages();
+    FlGui::instance()->saveMessages
       ((CTX::instance()->homeDir + CTX::instance()->errorFileName).c_str());
     fl_alert("A fatal error has occurred which will force Gmsh to abort.\n"
              "The error messages have been saved in the following file:\n\n%s",
@@ -201,8 +201,8 @@ void Msg::Error(const char *fmt, ...)
   if(FlGui::available()){
     FlGui::instance()->check();
     std::string tmp = std::string("@C1@.") + "Error   : " + str;
-    FlGui::instance()->messages->add(tmp.c_str());
-    FlGui::instance()->messages->show();
+    FlGui::instance()->addMessage(tmp.c_str());
+    FlGui::instance()->showMessages();
   }
 #endif
 
@@ -234,7 +234,7 @@ void Msg::Warning(const char *fmt, ...)
   if(FlGui::available()){
     FlGui::instance()->check();
     std::string tmp = std::string("@C1@.") + "Warning : " + str;
-    FlGui::instance()->messages->add(tmp.c_str());
+    FlGui::instance()->addMessage(tmp.c_str());
   }
 #endif
 
@@ -261,7 +261,7 @@ void Msg::Info(const char *fmt, ...)
   if(FlGui::available()){
     FlGui::instance()->check();
     std::string tmp = std::string("Info    : ") + str;
-    FlGui::instance()->messages->add(tmp.c_str());
+    FlGui::instance()->addMessage(tmp.c_str());
   }
 #endif
 
@@ -305,9 +305,9 @@ void Msg::Direct(int level, const char *fmt, ...)
       tmp = std::string("@C1@.") + str;
     else
       tmp = std::string("@C4@.") + str;
-    FlGui::instance()->messages->add(tmp.c_str());
+    FlGui::instance()->addMessage(tmp.c_str());
     if(level == 1)
-      FlGui::instance()->messages->show();
+      FlGui::instance()->showMessages();
   }
 #endif
 
@@ -338,7 +338,7 @@ void Msg::StatusBar(int num, bool log, const char *fmt, ...)
       FlGui::instance()->setStatus(str, num - 1);
     if(log){
       std::string tmp = std::string("Info    : ") + str;
-      FlGui::instance()->messages->add(tmp.c_str());
+      FlGui::instance()->addMessage(tmp.c_str());
     }
   }
 #endif
@@ -365,7 +365,7 @@ void Msg::Debug(const char *fmt, ...)
 #if defined(HAVE_FLTK)
   if(FlGui::available()){
     std::string tmp = std::string("Debug   : ") + str;
-    FlGui::instance()->messages->add(tmp.c_str());
+    FlGui::instance()->addMessage(tmp.c_str());
   }
 #endif
 
@@ -468,14 +468,14 @@ void Msg::PrintErrorCounter(const char *title)
 #if defined(HAVE_FLTK)
   if(FlGui::available()){
     std::string red("@C1@.");
-    FlGui::instance()->messages->add((red + prefix + line).c_str());
-    FlGui::instance()->messages->add((red + prefix + title).c_str());
-    FlGui::instance()->messages->add((red + prefix + warn).c_str());
-    FlGui::instance()->messages->add((red + prefix + err).c_str());
-    FlGui::instance()->messages->add((red + prefix + help).c_str());
-    FlGui::instance()->messages->add((red + prefix + line).c_str());
+    FlGui::instance()->addMessage((red + prefix + line).c_str());
+    FlGui::instance()->addMessage((red + prefix + title).c_str());
+    FlGui::instance()->addMessage((red + prefix + warn).c_str());
+    FlGui::instance()->addMessage((red + prefix + err).c_str());
+    FlGui::instance()->addMessage((red + prefix + help).c_str());
+    FlGui::instance()->addMessage((red + prefix + line).c_str());
     if(_errorCount){
-      FlGui::instance()->messages->show();
+      FlGui::instance()->showMessages();
       fl_beep();
     }
   }
diff --git a/Fltk/FlGui.cpp b/Fltk/FlGui.cpp
index 23892ba73935d19e2bef5d7533f4fa92ba28809f..a844d19fa6cb37a430a095a150f335da6b063588 100644
--- a/Fltk/FlGui.cpp
+++ b/Fltk/FlGui.cpp
@@ -907,3 +907,19 @@ void window_cb(Fl_Widget *w, void *data)
   }
 }
 
+void FlGui::addMessage(const char *msg)
+{
+  for(unsigned int i = 0; i < FlGui::instance()->graph.size(); i++)
+    FlGui::instance()->graph[i]->addMessage(msg);
+}
+
+void FlGui::showMessages(int numLines)
+{
+  for(unsigned int i = 0; i < FlGui::instance()->graph.size(); i++)
+    FlGui::instance()->graph[i]->showMessages(numLines);
+}
+
+void FlGui::saveMessages(const char *fileName)
+{
+  FlGui::instance()->graph[0]->saveMessages(fileName);
+}
diff --git a/Fltk/FlGui.h b/Fltk/FlGui.h
index bc3b6563544a50be7bf2ae7bb8f08dd0775bad00..997eb331fcc5dfdbab6ff0c3b6ffe69589d01426 100644
--- a/Fltk/FlGui.h
+++ b/Fltk/FlGui.h
@@ -106,6 +106,12 @@ class FlGui{
   void setStatus(const char *msg, int num);
   // create the window for physical context dependant definitions
   void callForSolverPlugin(int dim);
+  // add line in message console(s)
+  void addMessage(const char *msg);
+  // show (or hide, if numLines=0) the message console
+  void showMessages(int numLines=-1);
+  // add line in message console(s)
+  void saveMessages(const char *fileName);
 };
 
 void redraw_cb(Fl_Widget *w, void *data);
diff --git a/Fltk/graphicWindow.cpp b/Fltk/graphicWindow.cpp
index 5406800492121c05522aea2888beb0a139e8efc6..11c43098870b1c92650cbe490f8167d6b058f493 100644
--- a/Fltk/graphicWindow.cpp
+++ b/Fltk/graphicWindow.cpp
@@ -417,6 +417,24 @@ static void remove_graphic_window_cb(Fl_Widget *w, void *data)
   }
 }
 
+static void message_copy_cb(Fl_Widget *w, void *data)
+{
+  std::string buff;
+  for(int i = 1; i <= FlGui::instance()->graph[0]->browser->size(); i++) {
+    if(FlGui::instance()->graph[0]->browser->selected(i)) {
+      const char *c = FlGui::instance()->graph[0]->browser->text(i);
+      if(strlen(c) > 5 && c[0] == '@')
+        buff += std::string(&c[5]);
+      else
+        buff += std::string(c);
+      buff += "\n";
+    }
+  }
+  // bof bof bof
+  Fl::copy(buff.c_str(), buff.size(), 0);
+  Fl::copy(buff.c_str(), buff.size(), 1);
+}
+
 // This dummy box class permits to define a box widget that will not
 // eat the FL_ENTER/FL_LEAVE events (the new Box widget in fltk > 1.1
 // does that, so that gl->handle() was not called when the mouse
@@ -448,7 +466,8 @@ graphicWindow::graphicWindow(bool main, int numTiles)
   int sw = FL_NORMAL_SIZE + 3; // status button width
   int width = CTX::instance()->glSize[0];
   int glheight = CTX::instance()->glSize[1];
-  int height = glheight + sh;
+  int mheight = glheight / 4;
+  int height = glheight + mheight + sh;
   
   // the graphic window should be a "normal" window (neither modal nor
   // non-modal)
@@ -462,69 +481,69 @@ graphicWindow::graphicWindow(bool main, int numTiles)
   }
 
   // bottom button bar
-  bottom = new Fl_Box(0, glheight, width, sh);
+  bottom = new Fl_Box(0, glheight + mheight, width, sh);
   bottom->box(FL_FLAT_BOX);
   
   int x = 2;
   int sht = sh - 4; // leave a 2 pixel border at the bottom
   
-  butt[5] = new Fl_Button(x, glheight + 2, sw, sht, "@-1gmsh_models");
+  butt[5] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "@-1gmsh_models");
   butt[5]->callback(status_options_cb, (void *)"model");
   butt[5]->tooltip("Select active model");
   x += sw;
-  butt[0] = new Fl_Button(x, glheight + 2, sw, sht, "X");
+  butt[0] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "X");
   butt[0]->callback(status_xyz1p_cb, (void *)"x");
   butt[0]->tooltip("Set +X or -X view (Alt+x or Alt+Shift+x)");
   x += sw;  
-  butt[1] = new Fl_Button(x, glheight + 2, sw, sht, "Y");
+  butt[1] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "Y");
   butt[1]->callback(status_xyz1p_cb, (void *)"y");
   butt[1]->tooltip("Set +Y or -Y view (Alt+y or Alt+Shift+y)");
   x += sw;  
-  butt[2] = new Fl_Button(x, glheight + 2, sw, sht, "Z");
+  butt[2] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "Z");
   butt[2]->callback(status_xyz1p_cb, (void *)"z");
   butt[2]->tooltip("Set +Z or -Z view (Alt+z or Alt+Shift+z)");
   x += sw;  
-  butt[4] = new Fl_Button(x, glheight + 2, sw, sht, "@-1gmsh_rotate");
+  butt[4] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "@-1gmsh_rotate");
   butt[4]->callback(status_xyz1p_cb, (void *)"r");
   butt[4]->tooltip("Rotate +90 or -90 (Shift) degrees, or sync rotations (Alt)");
   x += sw;  
-  butt[3] = new Fl_Button(x, glheight + 2, 2 * FL_NORMAL_SIZE, sht, "1:1");
+  butt[3] = new Fl_Button(x, glheight + mheight + 2, 2 * FL_NORMAL_SIZE, sht, "1:1");
   butt[3]->callback(status_xyz1p_cb, (void *)"1:1");
   butt[3]->tooltip("Set unit scale, sync scale between viewports (Alt), "
                    "or reset bounding box around visible entities (Shift)");
   x += 2 * FL_NORMAL_SIZE;  
-  butt[8] = new Fl_Button(x, glheight + 2, sw, sht, "@-1gmsh_ortho");
+  butt[8] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "@-1gmsh_ortho");
   butt[8]->callback(status_options_cb, (void *)"p");
   butt[8]->tooltip("Toggle projection mode (Alt+o or Alt+Shift+o)");
   x += sw;  
-  butt[12] = new Fl_Button(x, glheight + 2, sw, sht, "M");
+  butt[12] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "M");
   butt[12]->callback(status_options_cb, (void *)"M");
   butt[12]->tooltip("Toggle mesh visibility (Alt+m)");
   x += sw;  
-  butt[13] = new Fl_Button(x, glheight + 2, sw, sht, "@-1gmsh_clscale");
+  butt[13] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "@-1gmsh_clscale");
   butt[13]->callback(status_options_cb, (void *)"clscale");
   butt[13]->tooltip("Change mesh element size factor");
   x += sw;  
-  butt[9] = new Fl_Button(x, glheight + 2, sw, sht, "S");
+  butt[9] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "S");
   butt[9]->callback(status_options_cb, (void *)"S");
   butt[9]->tooltip("Toggle mouse selection ON/OFF (Escape)");
   x += sw;  
-  butt[6] = new Fl_Button(x, glheight + 2, sw, sht, "@-1gmsh_rewind");
+  butt[6] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "@-1gmsh_rewind");
   butt[6]->callback(status_rewind_cb);
   butt[6]->tooltip("Rewind animation");
   butt[6]->deactivate();
   x += sw;  
-  butt[10] = new Fl_Button(x, glheight + 2, sw, sht, "@-1gmsh_back");
+  butt[10] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "@-1gmsh_back");
   butt[10]->callback(status_stepbackward_cb);
   butt[10]->tooltip("Step backward");
   butt[10]->deactivate();
   x += sw;  
-  butt[7] = new Fl_Button(x, glheight + 2, sw, sht, "@-1gmsh_play");
+  butt[7] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "@-1gmsh_play");
   butt[7]->callback(status_play_cb);
   butt[7]->tooltip("Play/pause animation");
   butt[7]->deactivate();
   x += sw;  
-  butt[11] = new Fl_Button(x, glheight + 2, sw, sht, "@-1gmsh_forward");
+  butt[11] = new Fl_Button(x, glheight + mheight + 2, sw, sht, "@-1gmsh_forward");
   butt[11]->callback(status_stepforward_cb);
   butt[11]->tooltip("Step forward");
   butt[11]->deactivate();
@@ -540,8 +559,8 @@ graphicWindow::graphicWindow(bool main, int numTiles)
   int wleft = (width - x) / 3 - 1;
   int wright = (width - x) - (width - x) / 3 - 1;
   
-  label[0] = new Fl_Box(x, glheight + 2, wleft, sht);
-  label[1] = new Fl_Box(x + (width - x) / 3, glheight + 2, wright, sht);
+  label[0] = new Fl_Box(x, glheight + mheight + 2, wleft, sht);
+  label[1] = new Fl_Box(x + (width - x) / 3, glheight + mheight + 2, wright, sht);
   for(int i = 0; i < 2; i++) {
     label[i]->box(FL_THIN_DOWN_BOX);
     label[i]->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE | FL_ALIGN_CLIP);
@@ -557,7 +576,7 @@ graphicWindow::graphicWindow(bool main, int numTiles)
   win->size_range(minWidth, minHeight);
 
   // tiled opengl windows
-  tile = new Fl_Tile(0, 0, width, glheight);
+  tile = new Fl_Tile(0, 0, width, glheight + mheight);
 
   int w2 = width / 2, h2 = glheight / 2;
   if(numTiles == 2){
@@ -597,8 +616,16 @@ graphicWindow::graphicWindow(bool main, int numTiles)
   }
   for(unsigned int i = 0; i < gl.size(); i++) gl[i]->mode(mode);
 
-  tile->end();
+  browser = new Fl_Browser(0, glheight, width, mheight);
+  browser->box(FL_THIN_DOWN_BOX);
+  browser->textfont(FL_COURIER);
+  browser->textsize(FL_NORMAL_SIZE - 1);
+  browser->type(FL_MULTI_BROWSER);
+  browser->callback(message_copy_cb);
+  browser->has_scrollbar(Fl_Browser_::VERTICAL);
 
+  tile->end();
+  
   win->position(CTX::instance()->glPosition[0], CTX::instance()->glPosition[1]);
   win->end();
 }
@@ -698,3 +725,43 @@ void graphicWindow::checkAnimButtons()
     butt[11]->deactivate();
   }
 }
+
+void graphicWindow::showMessages(int numLines)
+{
+  // change tile "live" by changing the position of a tile intersection
+  if(browser->h() == 0)
+    tile->position(0, win->h() - bottom->h(),
+                   0, win->h() - bottom->h() - 300);
+  if(numLines && CTX::instance()->msgAutoScroll)
+    browser->bottomline(browser->size());
+  //tile->show();
+  //printf("msg height = %d\n", msg->h());
+}
+
+void graphicWindow::addMessage(const char *msg)
+{
+  browser->add(msg, 0);
+  if(win->shown() && browser->h() > 10 && CTX::instance()->msgAutoScroll)
+    browser->bottomline(browser->size());
+}
+
+void graphicWindow::saveMessages(const char *filename)
+{
+  FILE *fp = fopen(filename, "w");
+
+  if(!fp) {
+    Msg::Error("Unable to open file '%s'", filename);
+    return;
+  }
+
+  Msg::StatusBar(2, true, "Writing '%s'...", filename);
+  for(int i = 1; i <= browser->size(); i++) {
+    const char *c = browser->text(i);
+    if(c[0] == '@')
+      fprintf(fp, "%s\n", &c[5]);
+    else
+      fprintf(fp, "%s\n", c);
+  }
+  Msg::StatusBar(2, true, "Done writing '%s'", filename);
+  fclose(fp);
+}
diff --git a/Fltk/graphicWindow.h b/Fltk/graphicWindow.h
index ab53da0d1c7459f41e9a886d3e6011e2b64aec1b..74ba102ec2a2f6990d441eb5348fd34b0deb8e0d 100644
--- a/Fltk/graphicWindow.h
+++ b/Fltk/graphicWindow.h
@@ -13,6 +13,7 @@
 #include <FL/Fl_Button.H>
 #include <FL/Fl_Box.H>
 #include <FL/Fl_Tile.H>
+#include <FL/Fl_Browser.H>
 #include "openglWindow.h"
 
 class graphicWindow{
@@ -22,6 +23,7 @@ class graphicWindow{
   Fl_Window *win;
   Fl_Tile *tile;
   std::vector<openglWindow*> gl;
+  Fl_Browser *browser;
   Fl_Box *bottom;
   Fl_Button *butt[14];
   Fl_Box *label[2];
@@ -33,6 +35,9 @@ class graphicWindow{
   void split(openglWindow *g, char how);
   void setAnimButtons(int mode);
   void checkAnimButtons();
+  void showMessages(int numLines);
+  void addMessage(const char *msg);
+  void saveMessages(const char *filename);
 };
 
 void status_xyz1p_cb(Fl_Widget *w, void *data);
diff --git a/Fltk/messageWindow.cpp b/Fltk/messageWindow.cpp
index baab79180f16d9f5aed02a5a563fd6709caf6175..5c53f92382fb599d7b46d5ef6ad3793c012ea479 100644
--- a/Fltk/messageWindow.cpp
+++ b/Fltk/messageWindow.cpp
@@ -11,6 +11,7 @@
 #include "FlGui.h"
 #include "messageWindow.h"
 #include "paletteWindow.h"
+#include "graphicWindow.h"
 #include "fileDialogs.h"
 #include "GmshMessage.h"
 #include "OS.h"
@@ -18,7 +19,8 @@
 
 void message_cb(Fl_Widget *w, void *data)
 {
-  FlGui::instance()->messages->show();
+  FlGui::instance()->graph[0]->showMessages(10);
+  FlGui::check();
 }
 
 static void message_auto_scroll_cb(Fl_Widget *w, void *data)
diff --git a/Mesh/meshGEdge.cpp b/Mesh/meshGEdge.cpp
index ae1c95c165f24cd96c9d4f11dd0a3256dca23184..adb99fec89ac752a3313cb4b183b024bba1788b1 100644
--- a/Mesh/meshGEdge.cpp
+++ b/Mesh/meshGEdge.cpp
@@ -320,7 +320,8 @@ void meshGEdge::operator() (GEdge *ge)
 
   // force odd number of points for if blossom is used for
   // recombination
-  if(CTX::instance()->mesh.algoRecombine == 1 && N % 2 == 0) N++;
+  if(ge->meshAttributes.Method != MESH_TRANSFINITE && 
+     CTX::instance()->mesh.algoRecombine == 1 && N % 2 == 0) N++;
 
   // printFandPrimitive(ge->tag(),Points);