---
 scribo/scribo/core/line_info.hh  |   18 +-
 scribo/scribo/core/stats.hh      |   16 +-
 scribo/scribo/text/merging.hh    |   16 +-
 scribo/scribo/text/paragraphs.hh |  462 ++++++++++++++++++++++++++++++-------
 4 files changed, 402 insertions(+), 110 deletions(-)
diff --git a/scribo/scribo/core/line_info.hh b/scribo/scribo/core/line_info.hh
index a798e9b..fa4051d 100644
--- a/scribo/scribo/core/line_info.hh
+++ b/scribo/scribo/core/line_info.hh
@@ -1006,21 +1006,22 @@ namespace scribo
       const int dy = bb1.pmax().row() - bb2.pmax().row();
 
       // The two characters must be distinct
-      if (space < 0)
-	return false;
+      // if (space < 0)
+      // 	return false;
 
       if (// Approximately the same width
-	((std::max(w1, w2) / std::min(w1, w2)) > 1.1f ||
+	((std::max(w1, w2) / std::min(w1, w2)) > 1.3 ||
 	 // One character must not be smaller than the space between
 	 // the two characters
 	   (w1 < space || w2 < space))
 	// If the two characters have a different width they must also
 	// have a different height
-	  && not (std::max(h1, h2) / std::min(h1, h2) <= 1.5f))
+	  && not (std::max(h1, h2) / std::min(h1, h2) <= 1.7f))
 	return false;
 
       // Approximately aligned on baseline
-      if (std::abs(dy) > 10)
+      if (std::abs(dy) > 10 &&
+	  not (std::max(h1, h2) / std::min(h1, h2) <= 1.7f))
 	return false;
 
       return true;
@@ -1055,6 +1056,10 @@ namespace scribo
     float min_base = 0.0f;
     const unsigned clusters_b_nelements = clusters_b.nelements();
 
+    if (clusters_b_nelements >= 3)
+      return data_->baseline_clusters_.mean();
+
+
     for (unsigned i = 0; i < clusters_b_nelements; ++i)
     {
       const unsigned clusters_b_i_nelements = clusters_b[i].nelements();
@@ -1092,6 +1097,9 @@ namespace scribo
     float max_mean = 0.0f;
     const unsigned clusters_m_nelements = clusters_m.nelements();
 
+    if (clusters_m_nelements >= 3)
+      return data_->meanline_clusters_.mean();
+
     for (unsigned i = 0; i < clusters_m_nelements; ++i)
     {
       const unsigned clusters_m_i_nelements = clusters_m[i].nelements();
diff --git a/scribo/scribo/core/stats.hh b/scribo/scribo/core/stats.hh
index 43cc3d6..3801545 100644
--- a/scribo/scribo/core/stats.hh
+++ b/scribo/scribo/core/stats.hh
@@ -250,7 +250,7 @@ private:
     std::vector< unsigned > clusters;
     unsigned cluster_index = 1;
 
-    clusters.reserve(data_.nelements());
+    clusters.resize(data_.nelements());
 
     if (not data_sorted_)
     {
@@ -261,7 +261,7 @@ private:
     unsigned i = 0;
     const unsigned nelements = data_.nelements();
 
-    clusters.push_back(cluster_index);
+    clusters[0] = cluster_index;
     const T std = data_.standard_deviation();
 
     for (i = 1; i < nelements - 1; ++i)
@@ -273,16 +273,14 @@ private:
 	       && left_distance <= std))
 	++cluster_index;
 
-      clusters.push_back(cluster_index);
+      clusters[i] = cluster_index;
     }
 
-    if (nelements > 1)
-    {
-      if (data_[i] - data_[i - 1] > std)
-	++cluster_index;
+    if (nelements > 1
+	&& data_[i] - data_[i - 1] > std)
+      ++cluster_index;
 
-      clusters.push_back(cluster_index);
-    }
+    clusters[i] = cluster_index;
 
     clusters_.clear();
     clusters_.reserve(cluster_index);
diff --git a/scribo/scribo/text/merging.hh b/scribo/scribo/text/merging.hh
index c94f9f5..9b4db56 100644
--- a/scribo/scribo/text/merging.hh
+++ b/scribo/scribo/text/merging.hh
@@ -460,8 +460,8 @@ namespace scribo
 	if (l_cur_height < l_ted_x_height
 	    && l_cur_height > 0.05f * l_ted_x_height
 	    && float(l_cur_width) / float(l_cur.card()) < l_ted.char_width()
-	    && dx < l_ted_cw
-	    && l_cur_pmin.row() < l_ted_pmax.row())
+	    && dx < 2 * l_ted_cw
+	    && l_cur_pmin.row() < l_ted.baseline())
 	{
 	  l_cur.update_type(line::Punctuation);
 	  return true;
@@ -740,11 +740,12 @@ namespace scribo
 		  // vertically aligned
 		  // Obviously no separators between the two lines
 		  if ((l_info.card() <= 5 ||
-		       (std::abs(l_info.baseline() - mc_info.baseline()) < 5
-			&& std::abs(l_info.meanline() - mc_info.meanline()) < 5))
-		      && dx < l_ted_cw && dy < 0
-		      && not (l_info.holder().components().has_separators()
-			      && between_separators(l_info, mc_info)))
+		       (std::abs(l_info.baseline() - mc_info.baseline())
+			< 5 && std::abs(l_info.meanline() -
+					mc_info.meanline()) < 5))
+		    && dx < l_ted_cw && dy < 0
+		    && 	not (l_info.holder().components().has_separators()
+		  	     && between_separators(l_info, mc_info)))
 		    l = do_union(lines, l, mc,  parent);
 		  // }
 
@@ -1046,7 +1047,6 @@ namespace scribo
 // 	ts = t.stop();
 // 	std::cout << "time " << ts << std::endl;
 
-
 	lines.force_stats_update();
 
 	return lines;
diff --git a/scribo/scribo/text/paragraphs.hh b/scribo/scribo/text/paragraphs.hh
index 5cb253e..beaea0c 100644
--- a/scribo/scribo/text/paragraphs.hh
+++ b/scribo/scribo/text/paragraphs.hh
@@ -47,11 +47,123 @@ namespace scribo
 
 	return x;
       }
+
+      template <typename T>
+      inline
+      void
+      set_root(util::array<T>& parent, unsigned x, const unsigned root)
+      {
+	while (parent(x) != x && parent(x) != root)
+	{
+	  const unsigned tmp = parent(x);
+	  x = parent(x);
+	  parent(tmp) = root;
+	}
+
+	parent(x) = root;
+      }
   }
 
   namespace filter
   {
 
+    template <typename L>
+    inline
+    bool
+    between_horizontal_separator(const scribo::line_info<L>& l1,
+				 const scribo::line_info<L>& l2)
+    {
+      // No separators found in image.
+      mln_precondition(l1.holder().components().has_separators());
+
+      const box2d& l1_bbox = l1.bbox();
+      const box2d& l2_bbox = l2.bbox();
+
+      unsigned
+	row1 = l1_bbox.pcenter().row(),
+	row2 = l2_bbox.pcenter().row();
+      const mln_ch_value(L, bool)&
+	separators = l1.holder().components().separators();
+
+      unsigned row;
+      unsigned col_ptr;
+      unsigned left_col_ptr;
+      unsigned right_col_ptr;
+      unsigned end;
+
+      if (row1 < row2)
+      {
+	row1 = l1_bbox.pmax().row();
+	row2 = l2_bbox.pmin().row();
+
+	const unsigned quarter =
+	  ((l1_bbox.pcenter().col() - l1_bbox.pmin().col()) >> 2);
+
+	row = l1_bbox.pcenter().row();
+	col_ptr = l1_bbox.pcenter().col();
+	left_col_ptr = l1_bbox.pmin().col() + quarter;
+	right_col_ptr = l1_bbox.pmax().col() - quarter;
+	end = row2;
+      }
+      else
+      {
+	row2 = l2_bbox.pmax().row();
+	row1 = l1_bbox.pmin().row();
+
+	const unsigned quarter =
+	  ((l2_bbox.pcenter().col() - l2_bbox.pmin().col()) >> 2);
+
+	row = l2_bbox.pcenter().row();
+	col_ptr = l2_bbox.pcenter().col();
+	left_col_ptr = l2_bbox.pmin().col() + quarter;
+	right_col_ptr = l2_bbox.pmax().col() - quarter;
+	end = row1;
+      }
+
+     // If sep_ptr is true, then a separator is reached.
+      while (row < end)
+      {
+	++row;
+	if (separators.at_(row, col_ptr)
+	    || separators.at_(row, left_col_ptr)
+	    || separators.at_(row, right_col_ptr))
+	  return true;
+      }
+
+      return false;
+    }
+
+
+    template <typename L>
+    inline
+    bool may_have_another_left_link(const util::array<value::int_u16>& right,
+				    const value::int_u16 index,
+				    const value::int_u16 current_line,
+				    const util::array< line_info<L> >& lines)
+    {
+      const line_info<L>& l = lines(current_line);
+      const point2d& pmin = l.bbox().pmin();
+      const unsigned x1 = l.x_height();
+
+      for (unsigned i = 0; i < right.nelements(); ++i)
+      {
+	if (i != index && right(i) == index)
+	{
+	  const line_info<L>& l_info = lines(i);
+	  const unsigned x2 = l_info.x_height();
+
+	  const float delta_max = 0.5f * std::min(x1, x2);
+
+	  if (l_info.bbox().pmin().col() < pmin.col()
+	      && std::abs(l.baseline() - l_info.baseline()) < delta_max
+	    )
+	    return true;
+	}
+      }
+
+      return false;
+    }
+
 //---------------------------------------------------------------------
 // This method aims to cut the links between lines that do not fit the
 // different criteria
@@ -60,7 +172,7 @@ namespace scribo
     template <typename L>
     inline
     void paragraph_links(const util::array<value::int_u16>& left,
-			 const util::array<value::int_u16>& right,
+			 util::array<value::int_u16>& right,
 			 util::array<value::int_u16>& output,
 			 const util::array< line_info<L> >& lines,
 			 const image2d<bool>& input)
@@ -81,9 +193,28 @@ namespace scribo
       {
 	// Neighbors
 
-	const value::int_u16 left_nbh = output(l);
-	const value::int_u16 right_nbh = right(l);
-	const value::int_u16 lol_nbh = output(left_nbh);
+	value::int_u16 left_nbh = output(l);
+	value::int_u16 right_nbh = right(l);
+	value::int_u16 lol_nbh = output(left_nbh);
+
+	const line_info<L>& left_line = lines(left_nbh);
+	const line_info<L>& current_line = lines(l);
+	const line_info<L>& right_line = lines(right_nbh);
+
+	if (right_line.holder().components().has_separators() &&
+	    between_horizontal_separator(right_line, current_line))
+	{
+	  output(right_nbh) = right_nbh;
+	  right_nbh = l;
+	}
+	if (current_line.holder().components().has_separators() &&
+	    between_horizontal_separator(current_line, left_line))
+	{
+	  output(l) = l;
+	  left_nbh = l;
+	  lol_nbh = l;
+	}
+
 
 	// Line features
 	const float x_height = lines(l).x_height();
@@ -110,6 +241,7 @@ namespace scribo
 	// Maximal x variation to consider two lines vertically aligned
 	const int delta_alignment = cline_cw;
 
+
 	// Checks the baseline distances of the two neighbors
 	{
 	  // Current line baseline
@@ -149,7 +281,7 @@ namespace scribo
 	      // and its right neighbor
 	      if (right_distance > 1.4f * ror_distance
 		  && std::max(ror_x_height, right_x_height) <
-		  1.2f * std::min(ror_x_height, right_x_height)
+		  1.4f * std::min(ror_x_height, right_x_height)
 		  && output(right_nbh) == l)
 	      {
 		  output(right_nbh) = right_nbh;
@@ -182,7 +314,7 @@ namespace scribo
 
 	    // Condition to cut the link between the current line and
 	    // its right neighbor
-	    if ((max_x_height > min_x_height * 1.2f) &&
+	    if ((max_x_height > min_x_height * 1.4f) &&
 		!(max_char_width <= 1.2f * min_char_width))
 	    {
 	      if (output(right_nbh) == l)
@@ -218,7 +350,7 @@ namespace scribo
 	      // and its left neighbor
 	      if (left_distance > 1.4f * lol_distance
 		  && std::max(lol_x_height, left_x_height) <
-		  1.2f * std::min(lol_x_height, left_x_height))
+		  1.4f * std::min(lol_x_height, left_x_height))
 	      {
 		  output(l) = l;
 		  continue;
@@ -250,7 +382,7 @@ namespace scribo
 
 	    // Condition to cut the link between the current line and
 	    // its left neighbor
-	    if ((max_x_height > min_x_height * 1.2f) &&
+	    if ((max_x_height > min_x_height * 1.4f) &&
 		!(max_char_width <= 1.2f * min_char_width))
 	    {
 	      output(l) = l;
@@ -262,27 +394,28 @@ namespace scribo
 	      continue;
 	  }
 	  // The current line has at least one left and one right neighbor
-	  else // if (delta_baseline_max >= delta_baseline_min)
+	  else // if (delta_baseline_max >= 1.1f * delta_baseline_min)
 	  {
 	    // Distance between the left and the current line
 	    const float left_distance =
-	      lines(left_nbh).meanline() - lines(l).baseline();
+	      left_line_bbox.pcenter().row() - current_line_bbox.pcenter().row();
 	    // Distance between the right and the current line
 	    const float right_distance =
-	      lines(l).meanline() - lines(right_nbh).baseline();
+	      current_line_bbox.pcenter().row() - right_line_bbox.pcenter().row();
 
 	    // If the left line is too far compared to the right one
 	    // we cut the link with it
-	    if (left_distance > 1.2f * right_distance
-	      && std::max(x_height, left_x_height) > 1.2f * std::min(x_height, left_x_height))
+	    if (left_distance > 1.5f * right_distance
+	      && std::max(x_height, left_x_height) > 1.2f * std::min(x_height, left_x_height)
+	      )
 	    {
 	      output(l) = l;
 	      continue;
 	    }
 	    // If the right line is too far compared to the left one
 	    // we cut the link with it
-	    else if (right_distance > 1.2f * left_distance
-		     && std::max(x_height, right_x_height) > 1.2f * std::min(x_height, right_x_height)
+	    else if (right_distance > 1.5f * left_distance
+	    	     && std::max(x_height, right_x_height) >= 1.2f * std::min(x_height, right_x_height)
 	    	     && output(right_nbh) == l)
 	    {
 	      output(right_nbh) = right_nbh;
@@ -301,7 +434,7 @@ namespace scribo
 	      const float min_x_height = std::min(x_height, left_x_height);
 	      const float max_x_height = std::max(x_height, left_x_height);
 
-	      if ((max_x_height > min_x_height * 1.2f) &&
+	      if ((max_x_height > min_x_height * 1.4f) &&
 		  !(cw_max <= 1.2f * cw_min))
 	      {
 		output(l) = l;
@@ -314,7 +447,7 @@ namespace scribo
 		const float cw_max = std::max(rline_cw, cline_cw);
 		const float cw_min = std::min(rline_cw, cline_cw);
 
-		if ((max_x_height > min_x_height * 1.2f)
+		if ((max_x_height > min_x_height * 1.4f)
 		    && !(cw_max <= 1.2f * cw_min)
 		    && output(right_nbh) == l)
 		{
@@ -330,7 +463,7 @@ namespace scribo
 	      const float min_x_height = std::min(x_height, right_x_height);
 	      const float max_x_height = std::max(x_height, right_x_height);
 
-	      if ((max_x_height > min_x_height * 1.2f)
+	      if ((max_x_height > min_x_height * 1.4f)
 		  && !(cw_max <= 1.2f * cw_min)
 		  && output(right_nbh) == l)
 	      {
@@ -344,7 +477,7 @@ namespace scribo
 		const float cw_max = std::max(lline_cw, cline_cw);
 		const float cw_min = std::min(lline_cw, cline_cw);
 
-		if ((max_x_height > min_x_height * 1.2f)
+		if ((max_x_height > min_x_height * 1.4f)
 		    && !(cw_max <= 1.2f * cw_min))
 		{
 		  output(l) = l;
@@ -363,51 +496,6 @@ namespace scribo
 //-----------------------------------------------------------------------------
 //   ___________________________
 //  |___________________________|
-//      ________________________
-//     |________________________|
-//   ___________________________
-//  |___________________________|
-//   ___________________________
-//  |___________________________|
-//
-//  Simple case : paragraphs are justified on the left. We try to find any
-//  indentation like above.
-//
-//-----------------------------------------------------------------------------
-
-	{
-	  // Check if the current line neighbors are aligned
-	  bool left_right_aligned = false;
-	  bool left_lol_aligned = false;
-	  const int dx_lr = std::abs(lline_col_min - rline_col_min);
-	  const int dx_llol = std::abs(lline_col_min - lolline_col_min);
-
-	  if (dx_lr < delta_alignment)
-	    left_right_aligned = true;
-
-	  if (dx_llol < delta_alignment)
-	    left_lol_aligned = true;
-
-	  if (left_right_aligned && left_lol_aligned)
-	  {
-	    const int left_right_col_min = std::min(lline_col_min, rline_col_min);
-	    const int dx_lrc = std::abs(left_right_col_min - cline_col_min);
-	    const float l_char_width = 1.5f * lines(l).char_width();
-
-	    if (dx_lrc > l_char_width &&
-		dx_lrc < 3.0f * l_char_width &&
-		cline_col_min > rline_col_min &&
-		cline_col_min > lline_col_min)
-	    {
-	      output(right_nbh) = right_nbh;
-	      continue;
-	    }
-	  }
-	}
-
-//-----------------------------------------------------------------------------
-//   ___________________________
-//  |___________________________|
 //   ___________________
 //  |___________________|           End of the paragraph - Current line
 //      ________________________
@@ -443,8 +531,11 @@ namespace scribo
 	  {
 	    const int dx_lrc = std::abs(lline_col_max - cline_col_max);
 	    const int l_char_width = lines(l).char_width();
+	    const int dx_indent = std::abs(std::max(lline_col_min,
+						    rline_col_min) - cline_col_min);
 
 	    if (dx_lrc > l_char_width &&
+		dx_indent < 4 * delta_alignment &&
 		cline_col_max < lline_col_max &&
 		cline_col_min < lline_col_min &&
 		(lline_col_min > lolline_col_min || lol_is_left))
@@ -456,48 +547,216 @@ namespace scribo
 	}
 
 
+
 //-----------------------------------------------------------------------------
 //   ___________________________
 //  |___________________________|
-//   ___________________________
-//  |___________________________|
 //      ________________________
 //     |________________________|
+//   ___________________________
+//  |___________________________|
+//   ___________________________
+//  |___________________________|
 //
 //  Simple case : paragraphs are justified on the left. We try to find any
-//  indentation like above at the end of a column.
+//  indentation like above.
 //
 //-----------------------------------------------------------------------------
 
-	if (left_nbh == l)
 	{
-	  const value::int_u16 ror_nbh = right(right_nbh);
-	  const box2d& ror_line_bbox = lines(ror_nbh).bbox();
-	  const int rorline_col_min  = ror_line_bbox.pmin().col();
+	  // Check if the current line neighbors are aligned
+	  bool left_right_aligned = false;
+	  bool left_lol_aligned = false;
+	  const int dx_lr = std::abs(lline_col_min - rline_col_min);
+	  const int dx_llol = std::abs(lline_col_min - lolline_col_min);
 
-	  bool right_ror_min_aligned = false;
-	  const int dx_rror_min = std::abs(rline_col_min - rorline_col_min);
+	  if (dx_lr < delta_alignment)
+	    left_right_aligned = true;
 
-	  if (dx_rror_min < delta_alignment)
-	    right_ror_min_aligned = true;
+	  if (dx_llol < delta_alignment)
+	    left_lol_aligned = true;
 
-	  if (right_ror_min_aligned)
+	  if (left_right_aligned && left_lol_aligned)
 	  {
-	    const int right_ror_col_min = std::min(rline_col_min, rorline_col_min);
-	    const int dx_rrorc = std::abs(right_ror_col_min - cline_col_min);
+	    const int left_right_col_min = std::min(lline_col_min, rline_col_min);
+	    const int dx_lrc = std::abs(left_right_col_min - cline_col_min);
 	    const float l_char_width = 1.5f * lines(l).char_width();
 
-	    if (dx_rrorc > l_char_width &&
-		dx_rrorc < 3.0f * l_char_width &&
+	    if (dx_lrc > l_char_width &&
+		!may_have_another_left_link(right, right_nbh, l, lines) &&
+		dx_lrc < 10.0f * l_char_width &&
 		cline_col_min > rline_col_min &&
-		cline_col_max >= rline_col_max)
+		cline_col_min > lline_col_min)
 	    {
-	      output(right_nbh) = right_nbh;
+	      const value::int_u16 out_right_nbh = output(right_nbh);
+
+	      if (out_right_nbh != l)
+		right(l) = l;
+	      else
+		output(right_nbh) = right_nbh;
 	      continue;
 	    }
 	  }
 	}
-      }
+
+//-----------------------------------------------------------------------------
+//   ___________________________
+//  |___________________________|
+//   ___________________________
+//  |___________________________|
+//      ________________________
+//     |________________________|
+//   ___________________________
+//  |___________________________|
+//
+//  Simple case : paragraphs are justified on the left. We try to find any
+//  indentation like above.
+//
+//-----------------------------------------------------------------------------
+
+     	{
+     	  const value::int_u16 ror_nbh = right(right_nbh);
+     	  const box2d& ror_line_bbox = lines(ror_nbh).bbox();
+     	  const int rorline_col_min  = ror_line_bbox.pmin().col();
+
+     	  bool right_ror_min_aligned = false;
+	  bool left_right_aligned = false;
+	  const int dx_lr = std::abs(lline_col_min - rline_col_min);
+     	  const int dx_rror_min = std::abs(rline_col_min - rorline_col_min);
+
+     	  if (dx_rror_min < delta_alignment)
+     	    right_ror_min_aligned = true;
+
+	  if (dx_lr < delta_alignment)
+	    left_right_aligned = true;
+
+     	  if (right_ror_min_aligned && left_right_aligned &&
+	      ror_nbh != right_nbh)
+     	  {
+ 	    const int left_right_col_min = std::min(lline_col_min, rline_col_min);
+	    const int dx_lrc = std::abs(left_right_col_min - cline_col_min);
+    	    const float l_char_width = 1.5f * lines(l).char_width();
+
+     	    if (dx_lrc > l_char_width &&
+		!may_have_another_left_link(right, right_nbh, l, lines) &&
+     		dx_lrc < 10.0f * l_char_width &&
+     		cline_col_min > rline_col_min &&
+     		cline_col_min > lline_col_min)
+     	    {
+	      const value::int_u16 out_right_nbh = output(right_nbh);
+
+	      if (out_right_nbh != l)
+		right(l) = l;
+	      else
+		output(right_nbh) = right_nbh;
+     	      continue;
+     	    }
+     	  }
+     	}
+
+//-----------------------------------------------------------------------------
+//   ___________________________
+//  |___________________________|
+//           ___________
+//          |___________|
+//      ________________________
+//     |________________________|
+//   ___________________________
+//  |___________________________|
+//
+//  Simple case : paragraphs are justified on the left. We try to find any
+//  indentation like above.
+//
+//-----------------------------------------------------------------------------
+
+     	{
+     	  const value::int_u16 ror_nbh = right(right_nbh);
+     	  const box2d& ror_line_bbox = lines(ror_nbh).bbox();
+     	  const int rorline_col_min  = ror_line_bbox.pmin().col();
+
+	  bool left_ror_aligned = false;
+	  const int dx_lror = std::abs(lline_col_min - rorline_col_min);
+
+	  if (dx_lror < delta_alignment)
+	    left_ror_aligned = true;
+
+     	  if (left_ror_aligned)
+     	  {
+ 	    const int left_ror_col_min = std::min(lline_col_min, rorline_col_min);
+	    const int dx_lrorc = std::abs(left_ror_col_min - cline_col_min);
+    	    const float l_char_width = 1.5f * lines(l).char_width();
+	    const int dx_lrorr = std::abs(left_ror_col_min - rline_col_min);
+	    const int dx_crmax = std::abs(rline_col_max - cline_col_max);
+
+     	    if (dx_lrorc > l_char_width &&
+		dx_lrorr > 5 * l_char_width &&
+		dx_lrorr > dx_lrorc &&
+		dx_crmax > 5 * l_char_width &&
+		!may_have_another_left_link(right, right_nbh, l, lines) &&
+     		dx_lrorc < 10.0f * l_char_width &&
+     		cline_col_min > rorline_col_min &&
+     		cline_col_min > lline_col_min)
+     	    {
+     	      right(right_nbh) = right_nbh;
+     	      continue;
+     	    }
+     	  }
+     	}
+
+
+// Strange case
+	{
+	  if (rline_col_min > current_line_bbox.pcenter().col()
+	      && !may_have_another_left_link(right, right_nbh, l, lines)
+	      && cline_col_max < rline_col_max
+	      && output(right_nbh) == l)
+	  {
+	    output(right_nbh) = right_nbh;
+	  }
+	}
+
+//-----------------------------------------------------------------------------
+//   ___________________________
+//  |___________________________|
+//   ___________________________
+//  |___________________________|
+//      ________________________
+//     |________________________|
+//
+//  Simple case : paragraphs are justified on the left. We try to find any
+//  indentation like above at the end of a column.
+//
+//-----------------------------------------------------------------------------
+
+     	if (left_nbh == l)
+     	{
+     	  const value::int_u16 ror_nbh = right(right_nbh);
+     	  const box2d& ror_line_bbox = lines(ror_nbh).bbox();
+     	  const int rorline_col_min  = ror_line_bbox.pmin().col();
+
+     	  bool right_ror_min_aligned = false;
+     	  const int dx_rror_min = std::abs(rline_col_min - rorline_col_min);
+
+     	  if (dx_rror_min < delta_alignment)
+     	    right_ror_min_aligned = true;
+
+     	  if (right_ror_min_aligned)
+     	  {
+     	    const int right_ror_col_min = std::min(rline_col_min, rorline_col_min);
+     	    const int dx_rrorc = std::abs(right_ror_col_min - cline_col_min);
+     	    const float l_char_width = 1.5f * lines(l).char_width();
+
+     	    if (dx_rrorc > l_char_width &&
+     		dx_rrorc < 10.0f * l_char_width &&
+     		cline_col_min > rline_col_min &&
+     		cline_col_max >= rline_col_max)
+     	    {
+     	      output(right_nbh) = right_nbh;
+     	      continue;
+     	    }
+     	  }
+     	}
+     }
 
 
       // Only debug
@@ -505,8 +764,21 @@ namespace scribo
       {
 	image2d<value::rgb8> debug = data::convert(value::rgb8(), input);
 
+	const util::array<value::int_u16> backup = output;
 	for (unsigned i = 0; i < output.nelements(); ++i)
-	  output(i) = internal::find_root(output, i);
+	{
+	    const value::int_u16 current_neighbor = backup(i);
+	    output(i) = internal::find_root(output, i);
+	    const value::int_u16 root_index = output(i);
+
+	    for (unsigned j = 0; j < right.nelements(); ++j)
+	    {
+	      if (i != j &&
+	      	  current_neighbor != i &&
+	      	  right(j) == i)
+	      	internal::set_root(output, j, root_index);
+	  }
+	}
 
 	mln::util::array<accu::shape::bbox<point2d> > nbbox(output.nelements());
 	for (unsigned i = 0; i < nlines; ++i)
@@ -690,7 +962,7 @@ namespace scribo
       int dmax = 1.5f * lines(i).x_height();
 
       // Starting points in the current line box
-      point2d c = rbbox(i).pcenter();
+      point2d c(rbbox(i).pcenter());
       point2d q(rbbox(i).pmin().row() + ((c.row() - rbbox(i).pmin().row()) / 4), c.col());
 
       int
@@ -830,7 +1102,7 @@ namespace scribo
       int dmax = 1.5f * lines(i).x_height();
 
       // Starting points in the current line box
-      point2d c = rbbox(i).pcenter();
+      point2d c(rbbox(i).pcenter());
       point2d q(rbbox(i).pmax().row() - ((rbbox(i).pmax().row() - c.row()) / 4), c.col());
 
       int
@@ -952,7 +1224,9 @@ namespace scribo
   inline
   void finalize_links(util::array<value::int_u16>& left,
 		      util::array<value::int_u16>& right,
-		      const util::array< line_info<L> >& lines)
+		      const util::array< line_info<L> >& lines// ,
+		      // const image2d<bool>& input
+    )
   {
     const unsigned nlines = lines.nelements();
 
@@ -979,6 +1253,17 @@ namespace scribo
 	  v = i;
       }
     }
+
+    // image2d<value::rgb8> left_links = data::convert(value::rgb8(), input);
+    // image2d<value::rgb8> right_links = data::convert(value::rgb8(), input);
+
+    // for (unsigned l = 0; l < nlines; ++l)
+    // {
+    //   mln::draw::line(left_links, lines(l).bbox().pcenter(), lines(left(l)).bbox().pcenter(), literal::red);
+    //   mln::draw::line(right_links, lines(l).bbox().pcenter(), lines(right(l)).bbox().pcenter(), literal::red);
+    // }
+    // mln::io::ppm::save(left_links, "out_left_links.ppm");
+    // mln::io::ppm::save(right_links, "out_right_links.ppm");
   }
 
   template <typename L>
@@ -1016,7 +1301,8 @@ namespace scribo
     std::cout << "Linking right" << std::endl;
     process_right_link(blocks, rbbox, lines_info, right);
     std::cout << "Finalizing links" << std::endl;
-    finalize_links(left, right, lines_info);
+    finalize_links(left, right, lines_info// , input
+      );
     // std::cout << "Finalizing merging" << std::endl;
     // finalize_line_merging(left, right, lines);
     std::cout << "Extracting paragraphs" << std::endl;
-- 
1.5.6.5