diff --git a/Common/Gmsh.cpp b/Common/Gmsh.cpp
index a5b55c08adf20adc998a59003ab80cc66a587e3a..f7e0ef279f5b2e45e4c3aaeaf6ae4824f1ff4510 100644
--- a/Common/Gmsh.cpp
+++ b/Common/Gmsh.cpp
@@ -95,8 +95,10 @@ int GmshBatch()
   }
   else if(CTX.batch > 0) {
     GModel::current()->mesh(CTX.batch);
+#if defined(HAVE_CHACO) || defined(HAVE_METIS)
     if(CTX.batchAfterMesh == 1)
        PartitionMesh(GModel::current(), CTX.mesh.partition_options);
+#endif
     CreateOutputFile(CTX.output_filename, CTX.mesh.format);
   }
   else if(CTX.batch == -1)
diff --git a/Common/Message.cpp b/Common/Message.cpp
index 0e782aa01793c8952d981bb34b4ab2010701a03f..8eb23cda47782147eba57825c9fcbdb863248928 100644
--- a/Common/Message.cpp
+++ b/Common/Message.cpp
@@ -270,12 +270,36 @@ void Message::Direct(int level, const char *fmt, ...)
 #if defined(HAVE_FLTK)
   if(WID){
     WID->check();
-    std::string tmp;
+    const char *const last = str + std::max(0u, std::strlen(str) - 1);
+    char _buf[1029];
     if(level < 3)
-      tmp = std::string("@C1@.") + str;
+      std::strcpy(_buf, "@C1@.");
     else
-      tmp = std::string("@C4@.") + str;
-    WID->add_message(tmp.c_str());
+      std::strcpy(_buf, "@C4@.");
+    char *const buf = _buf + 5;
+    char *p = std::strtok(str, "\n");
+    if(p) {
+      // If more than 1 leading '\n', print a blank line
+      if(p - str > 1) {
+        buf[0] = ' ';
+        buf[1] = '\0';
+        WID->add_message(_buf);
+      }
+      std::strcpy(buf, p);
+      WID->add_message(_buf);
+      // New line for each interior '\n'
+      while(p = std::strtok(NULL, "\n")) {
+        std::strcpy(buf, p);
+        WID->add_message(_buf);
+      }
+    }
+    // If more than 1 trailing '\n', or only "\n" in the string, print a blank
+    // line.
+    if(*last == '\n') {
+      buf[0] = ' ';
+      buf[1] = '\0';
+      WID->add_message(_buf);
+    }
     if(level == 1)
       WID->create_message_window();
   }
diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp
index f05177d0ce5d7768f16a6015a3c181330a8117f3..b304efbe38d596557e94fc35159c9d68b96e0c9e 100644
--- a/Fltk/Callbacks.cpp
+++ b/Fltk/Callbacks.cpp
@@ -3743,7 +3743,9 @@ void mesh_optimize_netgen_cb(CALLBACK_ARGS)
 
 void mesh_partition_cb(CALLBACK_ARGS)
 {
+#if defined(HAVE_METIS) || defined(HAVE_CHACO)
   partition_dialog();
+#endif
 }
 
 void mesh_define_length_cb(CALLBACK_ARGS)
diff --git a/Fltk/GUI_Extras.cpp b/Fltk/GUI_Extras.cpp
index 80bc66e869dcaa850098acecbd9628dc18ae0f4d..c15940b85a5e1cba11e1997c5d25def1d8b14c57 100644
--- a/Fltk/GUI_Extras.cpp
+++ b/Fltk/GUI_Extras.cpp
@@ -1138,6 +1138,7 @@ int stl_dialog(const char *name)
 }
 
 // Partition dialog - widget pointers, callbacks and dialog routine
+#if defined(HAVE_CHACO) || defined(HAVE_METIS)
 
 // Forward declarations of some callbacks
 void partition_opt_chaco_globalalg_cb(Fl_Widget *widget, void *data);
@@ -1424,12 +1425,13 @@ void partition_partition_cb(Fl_Widget *widget, void *data)
   dlg->write_all_options();
 
   // Partition the mesh
-  PartitionMesh(GModel::current(), CTX.mesh.partition_options);
+  int ier = PartitionMesh(GModel::current(), CTX.mesh.partition_options);
 
   // Update the screen
-  CTX.mesh.changed |= (ENT_LINE | ENT_SURFACE | ENT_VOLUME);
-  Draw();
-  Msg::StatusBar(2, false, " ");
+  if(!ier) {
+    opt_mesh_color_carousel(0, GMSH_SET | GMSH_GUI, 3.);
+    Draw();
+  }
 
   Fl::delete_widget(widget->window());
 }
@@ -1889,3 +1891,5 @@ int partition_dialog()
   partition_select_groups_cb(window->child(0), &dlg);
   window->show();
 }
+
+#endif  // compiling partition dialog
diff --git a/Geo/MZone.cpp b/Geo/MZone.cpp
index e56ed75b296ccf63ef415273a7024472d95c18f5..76f22e6901436d00bdc4f0c23b24b6eb3a7ff250 100644
--- a/Geo/MZone.cpp
+++ b/Geo/MZone.cpp
@@ -53,12 +53,6 @@ void MZone<DIM>::add_elements_in_entities
 (EntIter begin, EntIter end, const int partition)
 {
 
-  // Check the Ent and EntIter types
-  // NOTE:  If the compiler sent you here, you're using an invalid entity as a
-  // template parameter and/or and invalid iterator.  See struct
-  // 'ValidEntityIterator' in 'MZone.h' for valid types
-//   typedef typename ValidEntityIterator<Ent, typename EntIter::value_type>
-//     ::Type Check;
   typedef typename DimTr<DIM>::EntityT Ent;
 
   // Find the neighbours of each vertex, edge, and face
@@ -102,10 +96,6 @@ void MZone<DIM>::add_elements_in_entity
 (EntPtr entity, const int partition)
 {
 
-//   // Check the type of EntPtr (it must not be GEntity*)
-//   // NOTE:  If the compiler sent you here, you're using an invalid entity as a
-//   // pointer.  See struct ValidEntityIterator in 'MZone.h' for valid types.
-//   typedef typename ValidEntityIterator<Ent, EntPtr>::Type Check;
   typedef typename DimTr<DIM>::EntityT Ent;
 
   // Find the neighbours of each vertex, edge, and face
diff --git a/Geo/MZoneBoundary.h b/Geo/MZoneBoundary.h
index 6d6e47913b970a4db556af54c914731240e2c437..9dd67d70e2c3f040d887ea781b2b4000818abf42 100644
--- a/Geo/MZoneBoundary.h
+++ b/Geo/MZoneBoundary.h
@@ -79,15 +79,12 @@ struct ZoneConnectivity
       : vertex(0), vertexIndex1(0), vertexIndex2(0)
     { }
     VertexPair(MVertex *const _vertex,
-               const unsigned zone1, const unsigned zone2,
-               const unsigned _vertexIndex1, const unsigned _vertexIndex2)
-      : vertex(_vertex)
+               const int zone1, const int zone2,
+               const int _vertexIndex1, const int _vertexIndex2)
+      : vertex(_vertex),
+        vertexIndex1(_vertexIndex1), vertexIndex2(_vertexIndex2)
     {
-      if(zone1 < zone2) {
-        vertexIndex1 = _vertexIndex1;
-        vertexIndex2 = _vertexIndex2;
-      }
-      else {
+      if(zone2 < zone1) {
         vertexIndex1 = _vertexIndex2;
         vertexIndex2 = _vertexIndex1;
       }
@@ -98,7 +95,38 @@ struct ZoneConnectivity
   // Constructor
   ZoneConnectivity()
   {
-    vertexPairVec.reserve(32);  // Avoid small reallocations
+    vertexPairVec.reserve(32);  // Avoid small reallocations by push_back()
+  }
+};
+
+struct ZoneConnectivityByElem
+{
+  // Internal structures
+  struct ElementPair                    // Pairs of elements.  Ordered based on
+                                        // zone indices
+  {
+    int elemIndex1;
+    int elemIndex2;
+    // Constructors
+    ElementPair()
+      : elemIndex1(0), elemIndex2(0)
+    { }
+    ElementPair(const int zone1, const int zone2,
+                const int _elemIndex1, const int _elemIndex2)
+      : elemIndex1(_elemIndex1), elemIndex2(_elemIndex2)
+    {
+      if(zone2 < zone1) {
+        elemIndex1 = _elemIndex2;
+        elemIndex2 = _elemIndex1;
+      }
+    }
+  };
+  // Data
+  std::vector<ElementPair> elemPairVec;
+  // Constructor
+  ZoneConnectivityByElem()
+  {
+    elemPairVec.reserve(32);  // Avoid small reallocations by push_back()
   }
 };
 
@@ -125,7 +153,7 @@ struct VertexBoundary
                  const SVector3 &_normal, MVertex *const _vertex,
                  const int _vertexIndex)
     : zoneIndex(_zoneIndex), bcPatchIndex(_bcPatchIndex), normal(_normal),
-    vertex(_vertex), vertexIndex(_vertexIndex)
+      vertex(_vertex), vertexIndex(_vertexIndex)
   { }
 };
 
@@ -149,6 +177,23 @@ struct ZoneBoVecSort
   const ZoneBoVec &zoneBoVec;
 };
 
+struct ElementBoundary
+{
+  int zoneIndex;
+  int bcPatchIndex;
+  SVector3 normal;
+  int elemIndex;
+  // Constructors
+  ElementBoundary()
+    : elemIndex(0)
+  { }
+  ElementBoundary(const int _zoneIndex, const int _bcPatchIndex,
+                  const SVector3 &_normal, const int _elemIndex)
+    : zoneIndex(_zoneIndex), bcPatchIndex(_bcPatchIndex), normal(_normal),
+      elemIndex(_elemIndex)
+  { }
+};
+
 
 /*******************************************************************************
  *
@@ -298,5 +343,4 @@ private:
 
 };
 
-
 #endif
diff --git a/Mesh/Partition.cpp b/Mesh/Partition.cpp
index f6491d62855744d442daa484b78d952f293d31d7..c88ad991e462f80b15ccfe675e530338879c0843 100644
--- a/Mesh/Partition.cpp
+++ b/Mesh/Partition.cpp
@@ -5,6 +5,8 @@
 //
 // Partition.cpp - Copyright (C) 2008 S. Guzik, C. Geuzaine, J.-F. Remacle
 
+#if defined(HAVE_CHACO) || defined(HAVE_METIS)
+
 #include "ElementTraits.h"
 #include "GModel.h"
 #include "Partition.h"
@@ -87,8 +89,15 @@ int PartitionMesh(GModel *const model, PartitionOptions &options)
 
   Graph graph;
   BoElemGrVec boElemGrVec;
-  if(MakeGraph(model, graph, &boElemGrVec)) return 1;
-  if(PartitionGraph(graph, options)) return 1;
+  int ier;
+  Msg::StatusBar(1, true, "Building graph...");
+  ier = MakeGraph(model, graph, &boElemGrVec);
+  Msg::StatusBar(1, true, "Partitioning graph...");
+  if(!ier) ier = PartitionGraph(graph, options);
+  if(ier) {
+    Msg::StatusBar(1, true, "Mesh");
+    return 1;
+  }
 
   // Assign partitions to internal elements
   const int n = graph.getNumVertex();
@@ -103,6 +112,8 @@ int PartitionMesh(GModel *const model, PartitionOptions &options)
   }
 
   model->recomputeMeshPartitions();
+  Msg::Info("Partitioning complete");
+  Msg::StatusBar(1, true, "Mesh");
   return 0;
 
 }
@@ -128,7 +139,7 @@ int PartitionGraph(Graph &graph, PartitionOptions &options)
   case 1:  // Chacho
 #ifdef HAVE_CHACO
     {
-      Msg::Info("Running Chaco graph partitioner");
+      Msg::Info("Launching Chaco graph partitioner");
       // Some setup (similar to that of Chaco/input/input.c)
       if(options.global_method != 2) options.rqi_flag = 0;
       if(options.global_method == 1 || options.rqi_flag) {
@@ -162,7 +173,7 @@ int PartitionGraph(Graph &graph, PartitionOptions &options)
   case 2:  // Metis
 #ifdef HAVE_METIS
     {
-      Msg::Info("Running METIS graph partitioner");
+      Msg::Info("Launching METIS graph partitioner");
       // "C" numbering for Metis
       {
         int *p = &graph.adjncy[0];  //**Sections
@@ -741,3 +752,5 @@ template void MakeGraphDIM<3, GModel::riter, GModel::fiter>
 (const GModel::riter begin, const GModel::riter end,
  const GModel::fiter beginBE, const GModel::fiter endBE,
  Graph &graph, BoElemGrVec *const boElemGrVec);
+
+#endif